1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
package cview
import (
"math"
"sync"
"github.com/gdamore/tcell/v2"
)
// ProgressBar indicates the progress of an operation.
type ProgressBar struct {
*Box
// Rune to use when rendering the empty area of the progress bar.
emptyRune rune
// Color of the empty area of the progress bar.
emptyColor tcell.Color
// Rune to use when rendering the filled area of the progress bar.
filledRune rune
// Color of the filled area of the progress bar.
filledColor tcell.Color
// If set to true, instead of filling from left to right, the bar is filled
// from bottom to top.
vertical bool
// Current progress.
progress int
// Progress required to fill the bar.
max int
sync.RWMutex
}
// NewProgressBar returns a new progress bar.
func NewProgressBar() *ProgressBar {
p := &ProgressBar{
Box: NewBox(),
emptyRune: tcell.RuneBlock,
emptyColor: Styles.PrimitiveBackgroundColor,
filledRune: tcell.RuneBlock,
filledColor: Styles.PrimaryTextColor,
max: 100,
}
p.SetBackgroundColor(Styles.PrimitiveBackgroundColor)
return p
}
// SetEmptyRune sets the rune used for the empty area of the progress bar.
func (p *ProgressBar) SetEmptyRune(empty rune) {
p.Lock()
defer p.Unlock()
p.emptyRune = empty
}
// SetEmptyColor sets the color of the empty area of the progress bar.
func (p *ProgressBar) SetEmptyColor(empty tcell.Color) {
p.Lock()
defer p.Unlock()
p.emptyColor = empty
}
// SetFilledRune sets the rune used for the filled area of the progress bar.
func (p *ProgressBar) SetFilledRune(filled rune) {
p.Lock()
defer p.Unlock()
p.filledRune = filled
}
// SetFilledColor sets the color of the filled area of the progress bar.
func (p *ProgressBar) SetFilledColor(filled tcell.Color) {
p.Lock()
defer p.Unlock()
p.filledColor = filled
}
// SetVertical sets the direction of the progress bar.
func (p *ProgressBar) SetVertical(vertical bool) {
p.Lock()
defer p.Unlock()
p.vertical = vertical
}
// SetMax sets the progress required to fill the bar.
func (p *ProgressBar) SetMax(max int) {
p.Lock()
defer p.Unlock()
p.max = max
}
// GetMax returns the progress required to fill the bar.
func (p *ProgressBar) GetMax() int {
p.RLock()
defer p.RUnlock()
return p.max
}
// AddProgress adds to the current progress.
func (p *ProgressBar) AddProgress(progress int) {
p.Lock()
defer p.Unlock()
p.progress += progress
if p.progress < 0 {
p.progress = 0
} else if p.progress > p.max {
p.progress = p.max
}
}
// SetProgress sets the current progress.
func (p *ProgressBar) SetProgress(progress int) {
p.Lock()
defer p.Unlock()
p.progress = progress
if p.progress < 0 {
p.progress = 0
} else if p.progress > p.max {
p.progress = p.max
}
}
// GetProgress gets the current progress.
func (p *ProgressBar) GetProgress() int {
p.RLock()
defer p.RUnlock()
return p.progress
}
// Complete returns whether the progress bar has been filled.
func (p *ProgressBar) Complete() bool {
p.RLock()
defer p.RUnlock()
return p.progress >= p.max
}
// Draw draws this primitive onto the screen.
func (p *ProgressBar) Draw(screen tcell.Screen) {
if !p.GetVisible() {
return
}
p.Box.Draw(screen)
p.Lock()
defer p.Unlock()
x, y, width, height := p.GetInnerRect()
barSize := height
maxLength := width
if p.vertical {
barSize = width
maxLength = height
}
barLength := int(math.RoundToEven(float64(maxLength) * (float64(p.progress) / float64(p.max))))
if barLength > maxLength {
barLength = maxLength
}
for i := 0; i < barSize; i++ {
for j := 0; j < barLength; j++ {
if p.vertical {
screen.SetContent(x+i, y+(height-1-j), p.filledRune, nil, tcell.StyleDefault.Foreground(p.filledColor).Background(p.backgroundColor))
} else {
screen.SetContent(x+j, y+i, p.filledRune, nil, tcell.StyleDefault.Foreground(p.filledColor).Background(p.backgroundColor))
}
}
for j := barLength; j < maxLength; j++ {
if p.vertical {
screen.SetContent(x+i, y+(height-1-j), p.emptyRune, nil, tcell.StyleDefault.Foreground(p.emptyColor).Background(p.backgroundColor))
} else {
screen.SetContent(x+j, y+i, p.emptyRune, nil, tcell.StyleDefault.Foreground(p.emptyColor).Background(p.backgroundColor))
}
}
}
}
|