예제 #1
0
func (e *EditField) insertRune(ch rune) {
	if e.readonly {
		return
	}

	if e.maxWidth > 0 && xs.Len(e.title) >= e.maxWidth {
		return
	}

	idx := e.cursorPos

	if idx == 0 {
		e.SetTitle(string(ch) + e.title)
	} else if idx >= xs.Len(e.title) {
		e.SetTitle(e.title + string(ch))
	} else {
		e.SetTitle(xs.Slice(e.title, 0, idx) + string(ch) + xs.Slice(e.title, idx, -1))
	}

	e.cursorPos++

	if e.cursorPos >= e.width {
		if e.offset == 0 {
			e.offset = 2
		} else {
			e.offset++
		}
	}
}
예제 #2
0
// Ellipsize truncates text to maxWidth by replacing a
// substring in the middle with ellipsis and keeping
// the beginning and ending of the string untouched.
// If maxWidth is less than 5 then no ellipsis is
// added, the text is just truncated from the right.
func Ellipsize(str string, maxWidth int) string {
	ln := xs.Len(str)
	if ln <= maxWidth {
		return str
	}

	if maxWidth < 5 {
		return xs.Slice(str, 0, maxWidth)
	}

	left := int((maxWidth - 3) / 2)
	right := maxWidth - left - 3
	return xs.Slice(str, 0, left) + "..." + xs.Slice(str, ln-right, -1)
}
예제 #3
0
// Repaint draws the control on its View surface
func (e *EditField) Draw() {
	PushAttributes()
	defer PopAttributes()

	x, y := e.Pos()
	w, _ := e.Size()

	parts := []rune(SysObject(ObjEdit))
	chLeft, chRight := string(parts[0]), string(parts[1])

	var textOut string
	curOff := 0
	if e.offset == 0 && xs.Len(e.title) < e.width {
		textOut = e.title
	} else {
		fromIdx := 0
		toIdx := 0
		if e.offset == 0 {
			toIdx = e.width - 1
			textOut = xs.Slice(e.title, 0, toIdx) + chRight
			curOff = -e.offset
		} else {
			curOff = 1 - e.offset
			fromIdx = e.offset
			if e.width-1 <= xs.Len(e.title)-e.offset {
				toIdx = e.offset + e.width - 2
				textOut = chLeft + xs.Slice(e.title, fromIdx, toIdx) + chRight
			} else {
				textOut = chLeft + xs.Slice(e.title, fromIdx, -1)
			}
		}
	}

	fg, bg := RealColor(e.fg, ColorEditText), RealColor(e.bg, ColorEditBack)
	if !e.Enabled() {
		fg, bg = RealColor(e.fg, ColorDisabledText), RealColor(e.fg, ColorDisabledBack)
	} else if e.Active() {
		fg, bg = RealColor(e.fg, ColorEditActiveText), RealColor(e.bg, ColorEditActiveBack)
	}

	SetTextColor(fg)
	SetBackColor(bg)
	FillRect(x, y, w, 1, ' ')
	DrawRawText(x, y, textOut)
	if e.Active() {
		SetCursorPos(e.cursorPos+e.x+curOff, e.y)
	}
}
예제 #4
0
// SetMaxWidth sets the maximum lenght of the EditField text. If the current text is longer it is truncated
func (e *EditField) SetMaxWidth(w int) {
	e.maxWidth = w
	if w > 0 && xs.Len(e.title) > w {
		e.title = xs.Slice(e.title, 0, w)
		e.end()
	}
}
예제 #5
0
// CutText makes a text no longer than maxWidth
func CutText(str string, maxWidth int) string {
	ln := xs.Len(str)
	if ln <= maxWidth {
		return str
	}

	return xs.Slice(str, 0, maxWidth)
}
예제 #6
0
func (e *EditField) del() {
	length := xs.Len(e.title)

	if e.title == "" || e.cursorPos == length || e.readonly {
		return
	}

	if e.cursorPos == length-1 {
		e.SetTitle(xs.Slice(e.title, 0, length-1))
	} else {
		e.SetTitle(xs.Slice(e.title, 0, e.cursorPos) + xs.Slice(e.title, e.cursorPos+1, -1))
	}

	if length-1 < e.width {
		e.offset = 0
	}
}
예제 #7
0
func (e *EditField) backspace() {
	if e.title == "" || e.cursorPos == 0 || e.readonly {
		return
	}

	length := xs.Len(e.title)
	if e.cursorPos >= length {
		e.cursorPos--
		e.SetTitle(xs.Slice(e.title, 0, length-1))
	} else if e.cursorPos == 1 {
		e.cursorPos = 0
		e.SetTitle(xs.Slice(e.title, 1, -1))
		e.offset = 0
	} else {
		e.cursorPos--
		e.SetTitle(xs.Slice(e.title, 0, e.cursorPos) + xs.Slice(e.title, e.cursorPos+1, -1))
	}

	if length-1 < e.width {
		e.offset = 0
	}
}
예제 #8
0
// DrawRawTextVertical draws the part of text that is inside the current clipping
// rectangle. DrawRawTextVertical always paints string as is - no color changes.
// If you want to draw string with color changing commands included then
// use DrawTextVertical function
func DrawRawTextVertical(x, y int, text string) {
	cx, cy, cw, ch := ClipRect()
	if y >= cy+ch || x < cx || x >= cx+cw {
		return
	}

	length := xs.Len(text)
	if y+length < cy {
		return
	}

	if y < cy {
		text = xs.Slice(text, cy-y, -1)
		length = length - (cy - y)
		y = cy
	}
	text = CutText(text, ch)

	dy := 0
	for _, ch := range text {
		putCharUnsafe(x, y+dy, ch)
		dy++
	}
}
예제 #9
0
// DrawRawText draws the part of text that is inside the current clipping
// rectangle. DrawRawText always paints string as is - no color changes.
// If you want to draw string with color changing commands included then
// use DrawText function
func DrawRawText(x, y int, text string) {
	cx, cy, cw, ch := ClipRect()
	if x >= cx+cw || y < cy || y >= cy+ch {
		return
	}

	length := xs.Len(text)
	if x+length < cx {
		return
	}

	if x < cx {
		text = xs.Slice(text, cx-x, -1)
		length = length - (cx - x)
		x = cx
	}
	text = CutText(text, cw)

	dx := 0
	for _, ch := range text {
		putCharUnsafe(x+dx, y, ch)
		dx++
	}
}
예제 #10
0
// Repaint draws the control on its View surface.
// Horizontal ProgressBar supports custom title over the bar.
// One can set title using method SetTitle. There are a few
// predefined variables that can be used inside title to
// show value or total progress. Variable must be enclosed
// with double curly brackets. Available variables:
// percent - the current percentage rounded to closest integer
// value - raw ProgressBar value
// min - lower ProgressBar limit
// max - upper ProgressBar limit
// Examples:
//      pb.SetTitle("{{value}} of {{max}}")
//      pb.SetTitle("{{percent}}%")
func (b *ProgressBar) Draw() {
	if b.max <= b.min {
		return
	}

	PushAttributes()
	defer PopAttributes()

	fgOff, fgOn := RealColor(b.fg, ColorProgressText), RealColor(b.fgActive, ColorProgressActiveText)
	bgOff, bgOn := RealColor(b.bg, ColorProgressBack), RealColor(b.bgActive, ColorProgressActiveBack)

	parts := []rune(SysObject(ObjProgressBar))
	cFilled, cEmpty := parts[0], parts[1]

	prc := 0
	if b.value >= b.max {
		prc = 100
	} else if b.value < b.max && b.value > b.min {
		prc = (100 * (b.value - b.min)) / (b.max - b.min)
	}

	var title string
	if b.direction == Horizontal && b.Title() != "" {
		title = b.Title()
		title = strings.Replace(title, "{{percent}}", strconv.Itoa(prc), -1)
		title = strings.Replace(title, "{{value}}", strconv.Itoa(b.value), -1)
		title = strings.Replace(title, "{{min}}", strconv.Itoa(b.min), -1)
		title = strings.Replace(title, "{{max}}", strconv.Itoa(b.max), -1)
	}

	x, y := b.Pos()
	w, h := b.Size()

	if b.direction == Horizontal {
		filled := prc * w / 100
		sFilled := strings.Repeat(string(cFilled), filled)
		sEmpty := strings.Repeat(string(cEmpty), w-filled)

		for yy := y; yy < y+h; yy++ {
			SetTextColor(fgOn)
			SetBackColor(bgOn)
			DrawRawText(x, yy, sFilled)
			SetTextColor(fgOff)
			SetBackColor(bgOff)
			DrawRawText(x+filled, yy, sEmpty)
		}

		if title != "" {
			shift, str := AlignText(title, w, b.align)
			titleClr := RealColor(b.titleFg, ColorProgressTitleText)
			var sOn, sOff string
			if filled == 0 || shift >= filled {
				sOff = str
			} else if w == filled || shift+xs.Len(str) < filled {
				sOn = str
			} else {
				r := filled - shift
				sOn = xs.Slice(str, 0, r)
				sOff = xs.Slice(str, r, -1)
			}
			SetTextColor(titleClr)
			if sOn != "" {
				SetBackColor(bgOn)
				DrawRawText(x+shift, y, sOn)
			}
			if sOff != "" {
				SetBackColor(bgOff)
				DrawRawText(x+shift+xs.Len(sOn), y, sOff)
			}
		}
	} else {
		filled := prc * h / 100
		sFilled := strings.Repeat(string(cFilled), w)
		sEmpty := strings.Repeat(string(cEmpty), w)
		for yy := y; yy < y+h-filled; yy++ {
			SetTextColor(fgOff)
			SetBackColor(bgOff)
			DrawRawText(x, yy, sEmpty)
		}
		for yy := y + h - filled; yy < y+h; yy++ {
			SetTextColor(fgOff)
			SetBackColor(bgOff)
			DrawRawText(x, yy, sFilled)
		}
	}
}