package cview
import (
"math"
"sync"
"github.com/gdamore/tcell/v2"
)
type Slider struct {
*ProgressBar
label []byte
labelWidth int
labelColor tcell .Color
labelColorFocused tcell .Color
fieldBackgroundColor tcell .Color
fieldBackgroundColorFocused tcell .Color
fieldTextColor tcell .Color
fieldTextColorFocused tcell .Color
increment int
dragging bool
changed func (value int )
done func (tcell .Key )
finished func (tcell .Key )
sync .RWMutex
}
func NewSlider () *Slider {
s := &Slider {
ProgressBar : NewProgressBar (),
increment : 10 ,
labelColor : Styles .SecondaryTextColor ,
fieldBackgroundColor : Styles .MoreContrastBackgroundColor ,
fieldBackgroundColorFocused : Styles .ContrastBackgroundColor ,
fieldTextColor : Styles .PrimaryTextColor ,
labelColorFocused : ColorUnset ,
fieldTextColorFocused : ColorUnset ,
}
return s
}
func (s *Slider ) SetLabel (label string ) {
s .Lock ()
defer s .Unlock ()
s .label = []byte (label )
}
func (s *Slider ) GetLabel () string {
s .RLock ()
defer s .RUnlock ()
return string (s .label )
}
func (s *Slider ) SetLabelWidth (width int ) {
s .Lock ()
defer s .Unlock ()
s .labelWidth = width
}
func (s *Slider ) SetLabelColor (color tcell .Color ) {
s .Lock ()
defer s .Unlock ()
s .labelColor = color
}
func (s *Slider ) SetLabelColorFocused (color tcell .Color ) {
s .Lock ()
defer s .Unlock ()
s .labelColorFocused = color
}
func (s *Slider ) SetFieldBackgroundColor (color tcell .Color ) {
s .Lock ()
defer s .Unlock ()
s .fieldBackgroundColor = color
}
func (s *Slider ) SetFieldBackgroundColorFocused (color tcell .Color ) {
s .Lock ()
defer s .Unlock ()
s .fieldBackgroundColorFocused = color
}
func (s *Slider ) SetFieldTextColor (color tcell .Color ) {
s .Lock ()
defer s .Unlock ()
s .fieldTextColor = color
}
func (s *Slider ) SetFieldTextColorFocused (color tcell .Color ) {
s .Lock ()
defer s .Unlock ()
s .fieldTextColorFocused = color
}
func (s *Slider ) GetFieldHeight () int {
return 1
}
func (s *Slider ) GetFieldWidth () int {
return 0
}
func (s *Slider ) SetIncrement (increment int ) {
s .Lock ()
defer s .Unlock ()
s .increment = increment
}
func (s *Slider ) SetChangedFunc (handler func (value int )) {
s .Lock ()
defer s .Unlock ()
s .changed = handler
}
func (s *Slider ) SetDoneFunc (handler func (key tcell .Key )) {
s .Lock ()
defer s .Unlock ()
s .done = handler
}
func (s *Slider ) SetFinishedFunc (handler func (key tcell .Key )) {
s .Lock ()
defer s .Unlock ()
s .finished = handler
}
func (s *Slider ) Draw (screen tcell .Screen ) {
if !s .GetVisible () {
return
}
s .Box .Draw (screen )
hasFocus := s .GetFocusable ().HasFocus ()
s .Lock ()
labelColor := s .labelColor
fieldBackgroundColor := s .fieldBackgroundColor
fieldTextColor := s .fieldTextColor
if hasFocus {
if s .labelColorFocused != ColorUnset {
labelColor = s .labelColorFocused
}
if s .fieldBackgroundColorFocused != ColorUnset {
fieldBackgroundColor = s .fieldBackgroundColorFocused
}
if s .fieldTextColorFocused != ColorUnset {
fieldTextColor = s .fieldTextColorFocused
}
}
x , y , width , height := s .GetInnerRect ()
rightLimit := x + width
if height < 1 || rightLimit <= x {
s .Unlock ()
return
}
if len (s .label ) > 0 {
if s .vertical {
height --
} else {
if s .labelWidth > 0 {
labelWidth := s .labelWidth
if labelWidth > rightLimit -x {
labelWidth = rightLimit - x
}
Print (screen , []byte (s .label ), x , y , labelWidth , AlignLeft , labelColor )
x += labelWidth + 1
width -= labelWidth + 1
} else {
_ , drawnWidth := Print (screen , []byte (s .label ), x , y , rightLimit -x , AlignLeft , labelColor )
x += drawnWidth + 1
width -= drawnWidth + 1
}
}
}
s .Unlock ()
s .ProgressBar .SetRect (x , y , width , height )
s .ProgressBar .SetEmptyColor (fieldBackgroundColor )
s .ProgressBar .SetFilledColor (fieldTextColor )
s .ProgressBar .Draw (screen )
}
func (s *Slider ) InputHandler () func (event *tcell .EventKey , setFocus func (p Primitive )) {
return s .WrapInputHandler (func (event *tcell .EventKey , setFocus func (p Primitive )) {
if HitShortcut (event , Keys .Cancel , Keys .MovePreviousField , Keys .MoveNextField ) {
if s .done != nil {
s .done (event .Key ())
}
if s .finished != nil {
s .finished (event .Key ())
}
return
}
previous := s .progress
if HitShortcut (event , Keys .MoveFirst , Keys .MoveFirst2 ) {
s .SetProgress (0 )
} else if HitShortcut (event , Keys .MoveLast , Keys .MoveLast2 ) {
s .SetProgress (s .max )
} else if HitShortcut (event , Keys .MoveUp , Keys .MoveUp2 , Keys .MoveRight , Keys .MoveRight2 , Keys .MovePreviousField ) {
s .AddProgress (s .increment )
} else if HitShortcut (event , Keys .MoveDown , Keys .MoveDown2 , Keys .MoveLeft , Keys .MoveLeft2 , Keys .MoveNextField ) {
s .AddProgress (s .increment * -1 )
}
if s .progress != previous && s .changed != nil {
s .changed (s .progress )
}
})
}
func (s *Slider ) MouseHandler () func (action MouseAction , event *tcell .EventMouse , setFocus func (p Primitive )) (consumed bool , capture Primitive ) {
return s .WrapMouseHandler (func (action MouseAction , event *tcell .EventMouse , setFocus func (p Primitive )) (consumed bool , capture Primitive ) {
x , y := event .Position ()
if !s .InRect (x , y ) {
s .dragging = false
return false , nil
}
if action == MouseLeftClick {
setFocus (s )
consumed = true
}
handleMouse := func () {
if !s .ProgressBar .InRect (x , y ) {
s .dragging = false
return
}
bx , by , bw , bh := s .GetInnerRect ()
var clickPos , clickRange int
if s .ProgressBar .vertical {
clickPos = (bh - 1 ) - (y - by )
clickRange = bh - 1
} else {
clickPos = x - bx
clickRange = bw - 1
}
setValue := int (math .Floor (float64 (s .max ) * (float64 (clickPos ) / float64 (clickRange ))))
if setValue != s .progress {
s .SetProgress (setValue )
if s .changed != nil {
s .changed (s .progress )
}
}
}
switch action {
case MouseLeftDown :
setFocus (s )
consumed = true
capture = s
s .dragging = true
handleMouse ()
case MouseMove :
if s .dragging {
consumed = true
capture = s
handleMouse ()
}
case MouseLeftUp :
if s .dragging {
consumed = true
s .dragging = false
handleMouse ()
}
}
return
})
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .