173 lines
4.1 KiB
Go
173 lines
4.1 KiB
Go
package clui
|
|
|
|
import (
|
|
xs "github.com/huandu/xstrings"
|
|
)
|
|
|
|
/*
|
|
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 {
|
|
BaseControl
|
|
direction Direction
|
|
multiline bool
|
|
textDisplay Align
|
|
}
|
|
|
|
/*
|
|
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 CreateLabel(parent Control, w, h int, title string, scale int) *Label {
|
|
c := new(Label)
|
|
c.BaseControl = NewBaseControl()
|
|
|
|
if w == AutoSize {
|
|
w = xs.Len(title)
|
|
}
|
|
if h == AutoSize {
|
|
h = 1
|
|
}
|
|
|
|
c.parent = parent
|
|
|
|
c.SetTitle(title)
|
|
c.SetSize(w, h)
|
|
c.SetConstraints(w, h)
|
|
c.SetScale(scale)
|
|
c.tabSkip = true
|
|
c.textDisplay = AlignLeft
|
|
|
|
if parent != nil {
|
|
parent.AddChild(c)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (l *Label) Draw() {
|
|
if l.hidden {
|
|
return
|
|
}
|
|
|
|
PushAttributes()
|
|
defer PopAttributes()
|
|
|
|
fg, bg := RealColor(l.fg, l.Style(), ColorText), RealColor(l.bg, l.Style(), ColorBack)
|
|
if !l.Enabled() {
|
|
fg = RealColor(l.fg, l.Style(), ColorDisabledText)
|
|
}
|
|
|
|
SetTextColor(fg)
|
|
SetBackColor(bg)
|
|
FillRect(l.x, l.y, l.width, l.height, ' ')
|
|
|
|
if l.title == "" {
|
|
return
|
|
}
|
|
|
|
if l.multiline {
|
|
parser := NewColorParser(l.title, fg, bg)
|
|
elem := parser.NextElement()
|
|
xx, yy := l.x, l.y
|
|
for elem.Type != ElemEndOfText {
|
|
if xx >= l.x+l.width || yy >= l.y+l.height {
|
|
break
|
|
}
|
|
|
|
if elem.Type == ElemLineBreak {
|
|
xx = l.x
|
|
yy += 1
|
|
} else if elem.Type == ElemPrintable {
|
|
SetTextColor(elem.Fg)
|
|
SetBackColor(elem.Bg)
|
|
putCharUnsafe(xx, yy, elem.Ch)
|
|
|
|
if l.direction == Horizontal {
|
|
xx += 1
|
|
if xx >= l.x+l.width {
|
|
xx = l.x
|
|
yy += 1
|
|
}
|
|
} else {
|
|
yy += 1
|
|
if yy >= l.y+l.height {
|
|
yy = l.y
|
|
xx += 1
|
|
}
|
|
}
|
|
}
|
|
|
|
elem = parser.NextElement()
|
|
}
|
|
} else {
|
|
if l.direction == Horizontal {
|
|
shift, str := AlignColorizedText(l.title, l.width, l.align)
|
|
if str != l.title && l.align != l.textDisplay {
|
|
shift, str = AlignColorizedText(l.title, l.width, l.textDisplay)
|
|
}
|
|
DrawText(l.x+shift, l.y, str)
|
|
} else {
|
|
shift, str := AlignColorizedText(l.title, l.height, l.align)
|
|
if str != l.title && l.align != l.textDisplay {
|
|
shift, str = AlignColorizedText(l.title, l.width, l.textDisplay)
|
|
}
|
|
DrawTextVertical(l.x, l.y+shift, str)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// TextDisplay returns which part of the lable title is displayed in case of
|
|
// title is longer than the label:
|
|
// - AlignLeft - the head of the title is shown
|
|
// - AlignRight - the tail of the title is shown
|
|
// The property is used only by single line Label
|
|
func (l *Label) TextDisplay() Align {
|
|
return l.textDisplay
|
|
}
|
|
|
|
// SetTextDisplay sets which part of the title is displayed in case of the title
|
|
// is longer than the lable. Only AlignLeft and AlignRigth are valid values
|
|
// for the property. Any other value does is skipped and does not affect
|
|
// displaying the title
|
|
func (l *Label) SetTextDisplay(align Align) {
|
|
if align != AlignLeft && align != AlignRight {
|
|
return
|
|
}
|
|
|
|
l.textDisplay = align
|
|
}
|