123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- package door
- import (
- "fmt"
- "strings"
- )
- // TODO: Break out the progress bar characters into stuctures.
- // Write tests to verify that CP437 matches Unicode.
- // See box_test. ;)
- type BarStyle int8
- const (
- SOLID BarStyle = iota
- HALF_STEP
- GRADIENT
- )
- type Percent_Style int8
- const (
- PERCENT_NONE Percent_Style = iota
- PERCENT
- PERCENT_SPACE
- )
- type BarRange struct {
- Percent int64
- Color string
- }
- type BarLine struct {
- Width int
- Style BarStyle
- Percent int64 // percentage * 100
- PercentStyle Percent_Style
- ColorRange []BarRange
- UpdateP func() int64
- Line
- }
- type BarCharacters struct {
- Solid string
- Half [2]string
- Gradient [4]string
- }
- var BARS BarCharacters
- var BARS_CP437 = BarCharacters{
- "\xdb",
- [2]string{"\xdb", "\xdd"},
- [4]string{"\xdb", "\xb0", "\xb1", "\xb2"},
- }
- var BARS_UNICODE = BarCharacters{
- "\u2588",
- [2]string{"\u2588", "\u258c"},
- [4]string{"\u2588", "\u2591", "\u2592", "\u2593"},
- }
- func (bl *BarLine) CheckRange() {
- if len(bl.ColorRange) != 0 {
- // Ok, there is a color range. Get checking
- for _, br := range bl.ColorRange {
- if bl.Percent <= br.Percent {
- bl.DefaultColor = br.Color
- break
- }
- }
- }
- }
- func (bl *BarLine) Output() string {
- var output string
- var step_width int64
- if bl.UpdateP != nil {
- bl.Percent = bl.UpdateP()
- }
- bl.CheckRange()
- switch bl.Style {
- case SOLID:
- step_width = int64(100 * 100 / bl.Width)
- var steps int = int(bl.Percent / step_width)
- output += strings.Repeat(BARS.Solid, steps)
- // This will work, because we aren't trying to len(output) with unicode.
- output += strings.Repeat(" ", int(bl.Width-steps))
- case HALF_STEP:
- step_width = int64(100 * 100 / bl.Width)
- var steps int = int(bl.Percent * 2 / step_width)
- output += strings.Repeat(BARS.Half[0], steps/2)
- if steps%2 == 1 {
- output += BARS.Half[1]
- steps++
- }
- output += strings.Repeat(" ", bl.Width-(steps/2))
- case GRADIENT:
- step_width = int64(100 * 100 / bl.Width)
- var steps int = int(bl.Percent * 4 / step_width)
- output += strings.Repeat(BARS.Gradient[0], steps/4)
- if steps%4 != 0 {
- switch steps % 4 {
- case 1, 2, 3:
- output += BARS.Gradient[steps%4]
- }
- for steps%4 != 0 {
- steps++
- }
- }
- output += strings.Repeat(" ", bl.Width-(steps/4))
- }
- if bl.PercentStyle != PERCENT_NONE {
- percent := fmt.Sprintf("%d", bl.Percent/100)
- var pos int = bl.Width/2 - 1
- if percent != "100" {
- percent += "%"
- if len(percent) < 3 {
- percent = " " + percent
- }
- }
- if bl.PercentStyle == PERCENT_SPACE {
- percent = " " + percent + " "
- pos--
- }
- // to process/slice the string (with unicode) do this:
- // convert to []rune, slice that, convert back to string
- //
- // sliceable := []rune(output)
- // newString := string(sliceable[:5]) + " new content " + (sliceable[10:])
- // fmt.Printf("%d %d [%s] %d [%s]\n", bl.Width, pos, percent, len(output), output)
- if Unicode {
- runes := []rune(output)
- output = string(runes[:pos]) + percent + string(runes[pos+len(percent):])
- } else {
- output = output[:pos] + percent + output[pos+len(percent):]
- }
- }
- return bl.DefaultColor + output
- }
|