closes #40 - alignment for multicolored single lined string

This commit is contained in:
Vladimir Markelov 2015-11-05 11:36:51 -08:00
parent 377892432f
commit d184b3b829
5 changed files with 98 additions and 13 deletions

View File

@ -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
}

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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 {