...

Source file src/code.rocketnine.space/tslocum/cview/progressbar.go

Documentation: code.rocketnine.space/tslocum/cview

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

View as plain text