160 lines
4.1 KiB
Go
160 lines
4.1 KiB
Go
package clui
|
|
|
|
import (
|
|
xs "github.com/huandu/xstrings"
|
|
term "github.com/nsf/termbox-go"
|
|
"strings"
|
|
)
|
|
|
|
/*
|
|
Label is a decorative control that can display text in horizontal
|
|
or vertical direction. Other available text features are alignment
|
|
and multi-line ability. Text can be single- or multi-colored with
|
|
tags inside the text. Multi-colored strings have limited support
|
|
of alignment feature: if text is longer than Label width the text
|
|
is always left aligned
|
|
*/
|
|
type Label struct {
|
|
ControlBase
|
|
direction Direction
|
|
multiline bool
|
|
multicolor bool
|
|
}
|
|
|
|
/*
|
|
NewLabel creates a new label.
|
|
view - is a View that manages the control
|
|
parent - is container that keeps the control. The same View can be a view and a parent at the same time.
|
|
w and h - are minimal size of the control.
|
|
title - is Label title.
|
|
scale - the way of scaling the control when the parent is resized. Use DoNotScale constant if the
|
|
control should keep its original size.
|
|
*/
|
|
func NewLabel(view View, parent Control, w, h int, title string, scale int) *Label {
|
|
c := new(Label)
|
|
|
|
if w == AutoSize {
|
|
w = xs.Len(title)
|
|
}
|
|
if h == AutoSize {
|
|
h = 1
|
|
}
|
|
|
|
c.view = view
|
|
c.parent = parent
|
|
|
|
c.SetTitle(title)
|
|
c.SetSize(w, h)
|
|
c.SetConstraints(w, h)
|
|
c.tabSkip = true
|
|
|
|
if parent != nil {
|
|
parent.AddChild(c, scale)
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
// Direction returns direction of text output: vertical or horizontal
|
|
func (l *Label) Direction() Direction {
|
|
return l.direction
|
|
}
|
|
|
|
// SetDirection sets the text output direction
|
|
func (l *Label) SetDirection(dir Direction) {
|
|
l.direction = dir
|
|
}
|
|
|
|
// Repaint draws the control on its View surface
|
|
func (l *Label) Repaint() {
|
|
canvas := l.view.Canvas()
|
|
tm := l.view.Screen().Theme()
|
|
|
|
fg, bg := RealColor(tm, l.fg, ColorText), RealColor(tm, l.bg, ColorBack)
|
|
if !l.Enabled() {
|
|
fg = RealColor(tm, l.fg, ColorDisabledText)
|
|
}
|
|
|
|
canvas.FillRect(l.x, l.y, l.width, l.height, term.Cell{Ch: ' ', Fg: fg, Bg: bg})
|
|
|
|
if l.multiline {
|
|
lineCnt, lineLen := l.height, l.width
|
|
if l.direction == Vertical {
|
|
lineCnt, lineLen = l.width, l.height
|
|
}
|
|
|
|
lines := strings.Split(l.title, "\n")
|
|
|
|
var realLines []string
|
|
for _, s := range lines {
|
|
curr := s
|
|
for xs.Len(curr) > lineLen {
|
|
realLines = append(realLines, xs.Slice(curr, 0, lineLen))
|
|
curr = xs.Slice(curr, lineLen, -1)
|
|
}
|
|
realLines = append(realLines, curr)
|
|
}
|
|
|
|
idx := 0
|
|
for idx < lineCnt && idx < len(realLines) {
|
|
if l.direction == Horizontal {
|
|
shift, text := AlignText(realLines[idx], l.width, l.align)
|
|
canvas.PutText(l.x+shift, l.y+idx, text, fg, bg)
|
|
} else {
|
|
shift, text := AlignText(realLines[idx], l.height, l.align)
|
|
canvas.PutVerticalText(l.x+idx, l.y+shift, text, fg, bg)
|
|
}
|
|
idx++
|
|
}
|
|
} else {
|
|
if l.multicolor {
|
|
max := l.width
|
|
if l.direction == Vertical {
|
|
max = l.height
|
|
}
|
|
|
|
shift, text := AlignColorizedText(l.title, max, l.align)
|
|
if l.direction == Vertical {
|
|
canvas.PutColorizedText(l.x, l.y+shift, max, text, fg, bg, l.direction)
|
|
} else {
|
|
canvas.PutColorizedText(l.x+shift, l.y, max, text, fg, bg, l.direction)
|
|
}
|
|
} else {
|
|
if l.direction == Horizontal {
|
|
shift, text := AlignText(l.title, l.width, l.align)
|
|
canvas.PutText(l.x+shift, l.y, text, fg, bg)
|
|
} else {
|
|
shift, text := AlignText(l.title, l.height, l.align)
|
|
canvas.PutVerticalText(l.x, l.y+shift, text, fg, bg)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Multiline returns if text is displayed on several lines if the
|
|
// label title is longer than label width or title contains
|
|
// line breaks
|
|
func (l *Label) Multiline() bool {
|
|
return l.multiline
|
|
}
|
|
|
|
// SetMultiline sets if the label should output text as one line
|
|
// or automatically display it in several lines
|
|
func (l *Label) SetMultiline(multi bool) {
|
|
l.multiline = multi
|
|
}
|
|
|
|
// MultiColored returns if the label checks and applies any
|
|
// color related tags inside its title. If MultiColores is
|
|
// false then title is displayed as is.
|
|
// To read about available color tags, please see ColorParser
|
|
func (l *Label) MultiColored() bool {
|
|
return l.multicolor
|
|
}
|
|
|
|
// SetMultiColored changes how the label output its title: as is
|
|
// or parse and apply all internal color tags
|
|
func (l *Label) SetMultiColored(multi bool) {
|
|
l.multicolor = multi
|
|
}
|