From 5b78b896c9c81a3ff9f7233ff62aafabed441f20 Mon Sep 17 00:00:00 2001 From: Caleb Bassi Date: Sat, 26 Jan 2019 02:47:47 -0800 Subject: [PATCH] Add WrapText option to Paragraph --- symbols.go | 4 +- utils.go | 125 +++++++++++++++++++++++++++---------------- widgets/list.go | 2 +- widgets/paragraph.go | 23 +++++--- widgets/table.go | 2 +- 5 files changed, 97 insertions(+), 59 deletions(-) diff --git a/symbols.go b/symbols.go index 8f2a74c..b7bda5f 100644 --- a/symbols.go +++ b/symbols.go @@ -1,8 +1,8 @@ package termui const ( - DOT = '•' - DOTS = '…' + DOT = '•' + ELLIPSES = '…' ) var ( diff --git a/utils.go b/utils.go index 00c389a..b0e6cde 100644 --- a/utils.go +++ b/utils.go @@ -30,31 +30,43 @@ func InterfaceSlice(slice interface{}) []interface{} { return ret } -func MaxInt(x, y int) int { - if x > y { - return x - } - return y -} - -func MinInt(x, y int) int { - if x < y { - return x - } - return y -} - // TrimString trims a string to a max length and adds '…' to the end if it was trimmed. func TrimString(s string, w int) string { if w <= 0 { return "" } if rw.StringWidth(s) > w { - return rw.Truncate(s, w, string(DOTS)) + return rw.Truncate(s, w, string(ELLIPSES)) } return s } +func SelectColor(colors []Color, index int) Color { + return colors[index%len(colors)] +} + +func SelectStyle(styles []Style, index int) Style { + return styles[index%len(styles)] +} + +// Math ------------------------------------------------------------------------ + +func SumIntSlice(slice []int) int { + sum := 0 + for _, val := range slice { + sum += val + } + return sum +} + +func SumFloat64Slice(data []float64) float64 { + sum := 0.0 + for _, v := range data { + sum += v + } + return sum +} + func GetMaxIntFromSlice(slice []int) (int, error) { if len(slice) == 0 { return 0, fmt.Errorf("cannot get max value from empty slice") @@ -96,42 +108,10 @@ func GetMaxFloat64From2dSlice(slices [][]float64) (float64, error) { return max, nil } -func SelectColor(colors []Color, index int) Color { - return colors[index%len(colors)] -} - -func SelectStyle(styles []Style, index int) Style { - return styles[index%len(styles)] -} - -func CellsToString(cells []Cell) string { - runes := make([]rune, len(cells)) - for i, cell := range cells { - runes[i] = cell.Rune - } - return string(runes) -} - func RoundFloat64(x float64) float64 { return math.Floor(x + 0.5) } -func SumIntSlice(slice []int) int { - sum := 0 - for _, val := range slice { - sum += val - } - return sum -} - -func SumFloat64Slice(data []float64) float64 { - sum := 0.0 - for _, v := range data { - sum += v - } - return sum -} - func AbsInt(x int) int { if x >= 0 { return x @@ -153,6 +133,22 @@ func MaxFloat64(x, y float64) float64 { return y } +func MaxInt(x, y int) int { + if x > y { + return x + } + return y +} + +func MinInt(x, y int) int { + if x < y { + return x + } + return y +} + +// []Cell ---------------------------------------------------------------------- + // WrapCells takes []Cell and inserts Cells containing '\n' wherever a linebreak should go. func WrapCells(cells []Cell, width uint) []Cell { str := CellsToString(cells) @@ -177,3 +173,38 @@ func RunesToStyledCells(runes []rune, style Style) []Cell { } return cells } + +func CellsToString(cells []Cell) string { + runes := make([]rune, len(cells)) + for i, cell := range cells { + runes[i] = cell.Rune + } + return string(runes) +} + +func TrimCells(cells []Cell, w int) []Cell { + s := CellsToString(cells) + s = TrimString(s, w) + newCells := []Cell{} + for i, r := range s { + newCells = append(newCells, Cell{r, cells[i].Style}) + } + return newCells +} + +func SplitCells(cells []Cell, r rune) [][]Cell { + splitCells := [][]Cell{} + temp := []Cell{} + for _, cell := range cells { + if cell.Rune == r { + splitCells = append(splitCells, temp) + temp = []Cell{} + } else { + temp = append(temp, cell) + } + } + if len(splitCells) > 0 { + splitCells = append(splitCells, temp) + } + return splitCells +} diff --git a/widgets/list.go b/widgets/list.go index 46b24f7..b6497bd 100644 --- a/widgets/list.go +++ b/widgets/list.go @@ -39,7 +39,7 @@ func (self *List) Draw(buf *Buffer) { point = image.Pt(self.Inner.Min.X, point.Y+1) } else { if point.X+1 == self.Inner.Max.X+1 && len(cells) > self.Inner.Dx() { - buf.SetCell(NewCell(DOTS, cells[j].Style), point.Add(image.Pt(-1, 0))) + buf.SetCell(NewCell(ELLIPSES, cells[j].Style), point.Add(image.Pt(-1, 0))) break } else { buf.SetCell(cells[j], point) diff --git a/widgets/paragraph.go b/widgets/paragraph.go index 51dbcda..9498f16 100644 --- a/widgets/paragraph.go +++ b/widgets/paragraph.go @@ -14,27 +14,34 @@ type Paragraph struct { Block Text string TextStyle Style + WrapText bool } func NewParagraph() *Paragraph { return &Paragraph{ Block: *NewBlock(), TextStyle: Theme.Paragraph.Text, + WrapText: true, } } func (self *Paragraph) Draw(buf *Buffer) { self.Block.Draw(buf) - point := self.Inner.Min - cells := WrapCells(ParseText(self.Text, self.TextStyle), uint(self.Inner.Dx())) + cells := ParseText(self.Text, self.TextStyle) + if self.WrapText { + cells = WrapCells(cells, uint(self.Inner.Dx())) + } - for i := 0; i < len(cells) && point.Y < self.Inner.Max.Y; i++ { - if cells[i].Rune == '\n' { - point = image.Pt(self.Inner.Min.X, point.Y+1) - } else { - buf.SetCell(cells[i], point) - point = point.Add(image.Pt(1, 0)) + rows := SplitCells(cells, '\n') + + for y, row := range rows { + if y+self.Inner.Min.Y >= self.Inner.Max.Y { + break + } + row = TrimCells(row, self.Inner.Dx()) + for x, cell := range row { + buf.SetCell(cell, image.Pt(x, y).Add(self.Inner.Min)) } } } diff --git a/widgets/table.go b/widgets/table.go index f8d5f5c..c7f3761 100644 --- a/widgets/table.go +++ b/widgets/table.go @@ -61,7 +61,7 @@ func (self *Table) Draw(buf *Buffer) { if len(col) > columnWidths[j] || self.TextAlign == AlignLeft { for k, cell := range col { if k == columnWidths[j] || colXCoordinate+k == self.Inner.Max.X { - cell.Rune = DOTS + cell.Rune = ELLIPSES buf.SetCell(cell, image.Pt(colXCoordinate+k-1, yCoordinate)) break } else {