mirror of
https://github.com/VladimirMarkelov/clui.git
synced 2025-05-01 22:18:35 +08:00
closes #40 - alignment for multicolored single lined string
This commit is contained in:
parent
377892432f
commit
d184b3b829
12
canvas.go
12
canvas.go
@ -169,8 +169,7 @@ func (fb *FrameBuffer) PutVerticalText(x, y int, text string, fg, bg term.Attrib
|
||||
|
||||
/*
|
||||
PutColorizedText draws multicolor string on Canvas clipping by Canvas boundaries.
|
||||
Multiline is not supported. Align feature is limited: the text is aligned only if it is
|
||||
shorter than maximum width, and displayed left aligned otherwise.
|
||||
Multiline is not supported.
|
||||
Various parts of text can be colorized with html-like tags. Every tag must start with '<'
|
||||
followed by tag type and colon(without space between them), atrribute in human redable form,
|
||||
and closing '>'.
|
||||
@ -184,21 +183,16 @@ empty string - reset the color to default value (that is passed as argument)
|
||||
'reversed' - reversed text and background
|
||||
other available attributes are color names: black, red, green, yellow, blue, magenta, cyan, white.
|
||||
|
||||
Example: PutColorizedText(0, 0, 10, "<t:red bold><b:yellow>E<t:>xample, ColorBlack, ColorWhite, Horizontal, AlignLeft)
|
||||
Example: PutColorizedText(0, 0, 10, "<t:red bold><b:yellow>E<t:>xample, ColorBlack, ColorWhite, Horizontal)
|
||||
It displays red letter 'C' on a yellow background, then switch text color to default one and draws
|
||||
other letters in black text and yellow background colors. Default background color is not used, so
|
||||
it can be set as ColroDefault in a method call
|
||||
*/
|
||||
func (fb *FrameBuffer) PutColorizedText(x, y, max int, text string, fg, bg term.Attribute, dir Direction, align Align) {
|
||||
sReal := UnColorizeText(text)
|
||||
func (fb *FrameBuffer) PutColorizedText(x, y, max int, text string, fg, bg term.Attribute, dir Direction) {
|
||||
var dx, dy int
|
||||
if dir == Horizontal {
|
||||
delta, _ := AlignText(sReal, max, align)
|
||||
x += delta
|
||||
dx = 1
|
||||
} else {
|
||||
delta, _ := AlignText(sReal, max, align)
|
||||
y += delta
|
||||
dy = 1
|
||||
}
|
||||
|
||||
|
25
ctrlutil.go
25
ctrlutil.go
@ -229,6 +229,31 @@ func StringToColor(str string) term.Attribute {
|
||||
return clr
|
||||
}
|
||||
|
||||
// ColorToString returns string representation of the attribute
|
||||
func ColorToString(attr term.Attribute) string {
|
||||
var out string
|
||||
colors := []string{
|
||||
"", "black", "red", "green", "yellow",
|
||||
"blue", "magenta", "cyan", "white"}
|
||||
|
||||
rawClr := attr & 15
|
||||
if rawClr < 8 {
|
||||
out += colors[rawClr] + " "
|
||||
}
|
||||
|
||||
if attr&term.AttrBold != 0 {
|
||||
out += "bold "
|
||||
}
|
||||
if attr&term.AttrUnderline != 0 {
|
||||
out += "underline "
|
||||
}
|
||||
if attr&term.AttrReverse != 0 {
|
||||
out += "reverse "
|
||||
}
|
||||
|
||||
return strings.TrimSpace(out)
|
||||
}
|
||||
|
||||
// ThumbPosition returns a scrollbar thumb position depending
|
||||
// on currently active item(itemNo), total number of items
|
||||
// (itemCount), and length/height of the scrollbar(length)
|
||||
|
@ -37,10 +37,9 @@ type Canvas interface {
|
||||
PutVerticalText(x int, y int, text string, fg term.Attribute, bg term.Attribute)
|
||||
/*
|
||||
PutColorizedText draws multicolor string on Canvas clipping by Canvas boundaries.
|
||||
Multiline is not supported. Align feature is limited: the text is aligned only if it is
|
||||
shorter than maximum width, and displayed left aligned otherwise
|
||||
Multiline is not supported.
|
||||
*/
|
||||
PutColorizedText(x int, y int, maxWidth int, text string, fg term.Attribute, bg term.Attribute, dir Direction, align Align)
|
||||
PutColorizedText(x int, y int, maxWidth int, text string, fg term.Attribute, bg term.Attribute, dir Direction)
|
||||
// Symbol returns current Canvas cell value at given coordinates. If coordinates are outside Canvas ok is false
|
||||
Symbol(x int, y int) (symbol term.Cell, ok bool)
|
||||
// Clear fills Canvas with given background color
|
||||
|
7
label.go
7
label.go
@ -112,7 +112,12 @@ func (l *Label) Repaint() {
|
||||
if l.direction == Vertical {
|
||||
max = l.height
|
||||
}
|
||||
canvas.PutColorizedText(l.x, l.y, max, l.title, fg, bg, l.direction, l.align)
|
||||
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)
|
||||
|
62
textutil.go
62
textutil.go
@ -2,6 +2,7 @@ package clui
|
||||
|
||||
import (
|
||||
xs "github.com/huandu/xstrings"
|
||||
term "github.com/nsf/termbox-go"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
@ -60,6 +61,67 @@ func AlignText(str string, width int, align Align) (shift int, out string) {
|
||||
return 0, str
|
||||
}
|
||||
|
||||
// AlignColorizedText does the same as AlignText does but
|
||||
// it preserves the color of the letters byt adding correct
|
||||
// colro tags to the line beginning.
|
||||
// Note: function is ineffective and a bit slow - do not use
|
||||
// it everywhere
|
||||
func AlignColorizedText(str string, width int, align Align) (int, string) {
|
||||
rawText := UnColorizeText(str)
|
||||
length := xs.Len(rawText)
|
||||
|
||||
if length <= width {
|
||||
shift, _ := AlignText(rawText, width, align)
|
||||
return shift, str
|
||||
}
|
||||
|
||||
skip := 0
|
||||
if align == AlignRight {
|
||||
skip = length - width
|
||||
} else if align == AlignCenter {
|
||||
skip = (length - width) / 2
|
||||
}
|
||||
|
||||
fgChanged, bgChanged := false, false
|
||||
curr := 0
|
||||
parser := NewColorParser(str, term.ColorBlack, term.ColorBlack)
|
||||
out := ""
|
||||
for curr <= skip+width {
|
||||
elem := parser.NextElement()
|
||||
|
||||
if elem.Type == ElemEndOfText {
|
||||
break
|
||||
}
|
||||
|
||||
if elem.Type == ElemPrintable {
|
||||
curr++
|
||||
if curr == skip+1 {
|
||||
if fgChanged {
|
||||
out += "<t:" + ColorToString(elem.Fg) + ">"
|
||||
}
|
||||
if bgChanged {
|
||||
out += "<b:" + ColorToString(elem.Bg) + ">"
|
||||
}
|
||||
out += string(elem.Ch)
|
||||
} else if curr > skip+1 {
|
||||
out += string(elem.Ch)
|
||||
}
|
||||
} else if elem.Type == ElemTextColor {
|
||||
fgChanged = true
|
||||
if curr > skip+1 {
|
||||
out += "<t:" + ColorToString(elem.Fg) + ">"
|
||||
}
|
||||
} else if elem.Type == ElemBackColor {
|
||||
bgChanged = true
|
||||
if curr > skip+1 {
|
||||
out += "<b:" + ColorToString(elem.Bg) + ">"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0, out
|
||||
}
|
||||
|
||||
// UnColorizeText removes all color-related tags from the
|
||||
// string. Tags to remove: <(f|t|b):.*>
|
||||
func UnColorizeText(str string) string {
|
||||
|
Loading…
x
Reference in New Issue
Block a user