fzf/src/tui/tcell.go

722 lines
16 KiB
Go
Raw Normal View History

2016-10-24 03:45:45 +00:00
// +build tcell windows
package tui
import (
"os"
2016-10-24 03:45:45 +00:00
"time"
"runtime"
2017-06-01 23:27:17 +00:00
"github.com/gdamore/tcell"
"github.com/gdamore/tcell/encoding"
2017-06-01 23:27:17 +00:00
"github.com/mattn/go-runewidth"
"github.com/rivo/uniseg"
2016-10-24 03:45:45 +00:00
)
func HasFullscreenRenderer() bool {
return true
}
2017-01-07 16:30:31 +00:00
func (p ColorPair) style() tcell.Style {
style := tcell.StyleDefault
return style.Foreground(tcell.Color(p.Fg())).Background(tcell.Color(p.Bg()))
}
2016-10-24 03:45:45 +00:00
2017-01-07 16:30:31 +00:00
type Attr tcell.Style
type TcellWindow struct {
color bool
preview bool
top int
left int
width int
height int
normal ColorPair
lastX int
lastY int
moveCursor bool
borderStyle BorderStyle
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) Top() int {
return w.top
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) Left() int {
return w.left
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) Width() int {
return w.width
}
func (w *TcellWindow) Height() int {
return w.height
}
func (w *TcellWindow) Refresh() {
if w.moveCursor {
_screen.ShowCursor(w.left+w.lastX, w.top+w.lastY)
w.moveCursor = false
}
w.lastX = 0
w.lastY = 0
w.drawBorder()
2017-01-07 16:30:31 +00:00
}
2016-10-24 03:45:45 +00:00
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) FinishFill() {
// NO-OP
2016-10-24 03:45:45 +00:00
}
const (
2016-11-15 14:57:32 +00:00
Bold Attr = Attr(tcell.AttrBold)
Dim = Attr(tcell.AttrDim)
Blink = Attr(tcell.AttrBlink)
Reverse = Attr(tcell.AttrReverse)
Underline = Attr(tcell.AttrUnderline)
Italic = Attr(tcell.AttrItalic)
2016-10-24 03:45:45 +00:00
)
const (
AttrUndefined = Attr(0)
AttrRegular = Attr(1 << 7)
AttrClear = Attr(1 << 8)
2016-10-24 03:45:45 +00:00
)
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) defaultTheme() *ColorTheme {
2016-10-24 03:45:45 +00:00
if _screen.Colors() >= 256 {
return Dark256
}
return Default16
}
var (
_colorToAttribute = []tcell.Color{
tcell.ColorBlack,
tcell.ColorRed,
tcell.ColorGreen,
tcell.ColorYellow,
tcell.ColorBlue,
tcell.ColorDarkMagenta,
tcell.ColorLightCyan,
tcell.ColorWhite,
}
)
func (c Color) Style() tcell.Color {
if c <= colDefault {
return tcell.ColorDefault
} else if c >= colBlack && c <= colWhite {
return _colorToAttribute[int(c)]
} else {
return tcell.Color(c)
}
}
func (a Attr) Merge(b Attr) Attr {
return a | b
}
// handle the following as private members of FullscreenRenderer instance
// they are declared here to prevent introducing tcell library in non-windows builds
2016-10-24 03:45:45 +00:00
var (
_screen tcell.Screen
_prevMouseButton tcell.ButtonMask
2016-10-24 03:45:45 +00:00
)
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) initScreen() {
2016-10-24 03:45:45 +00:00
s, e := tcell.NewScreen()
if e != nil {
errorExit(e.Error())
2016-10-24 03:45:45 +00:00
}
if e = s.Init(); e != nil {
errorExit(e.Error())
}
2017-01-07 16:30:31 +00:00
if r.mouse {
s.EnableMouse()
} else {
s.DisableMouse()
2016-10-24 03:45:45 +00:00
}
_screen = s
}
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) Init() {
if os.Getenv("TERM") == "cygwin" {
os.Setenv("TERM", "")
}
encoding.Register()
2017-01-07 16:30:31 +00:00
r.initScreen()
initTheme(r.theme, r.defaultTheme(), r.forceBlack)
}
2016-10-24 03:45:45 +00:00
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) MaxX() int {
2016-10-24 03:45:45 +00:00
ncols, _ := _screen.Size()
return int(ncols)
}
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) MaxY() int {
2016-10-24 03:45:45 +00:00
_, nlines := _screen.Size()
return int(nlines)
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) X() int {
return w.lastX
}
func (w *TcellWindow) Y() int {
return w.lastY
}
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) Clear() {
_screen.Sync()
2016-10-24 03:45:45 +00:00
_screen.Clear()
}
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) Refresh() {
2016-10-24 03:45:45 +00:00
// noop
}
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) GetChar() Event {
2016-10-24 03:45:45 +00:00
ev := _screen.PollEvent()
switch ev := ev.(type) {
case *tcell.EventResize:
return Event{Resize, 0, nil}
2016-10-24 03:45:45 +00:00
// process mouse events:
case *tcell.EventMouse:
// mouse down events have zeroed buttons, so we can't use them
// mouse up event consists of two events, 1. (main) event with modifier and other metadata, 2. event with zeroed buttons
// so mouse click is three consecutive events, but the first and last are indistinguishable from movement events (with released buttons)
// dragging has same structure, it only repeats the middle (main) event appropriately
2016-10-24 03:45:45 +00:00
x, y := ev.Position()
mod := ev.Modifiers() != 0
// since we dont have mouse down events (unlike LightRenderer), we need to track state in prevButton
prevButton, button := _prevMouseButton, ev.Buttons()
_prevMouseButton = button
drag := prevButton == button
switch {
case button&tcell.WheelDown != 0:
return Event{Mouse, 0, &MouseEvent{y, x, -1, false, false, false, mod}}
case button&tcell.WheelUp != 0:
return Event{Mouse, 0, &MouseEvent{y, x, +1, false, false, false, mod}}
case button&tcell.Button1 != 0 && !drag:
// all potential double click events put their 'line' coordinate in the clickY array
// double click event has two conditions, temporal and spatial, the first is checked here
now := time.Now()
if now.Sub(r.prevDownTime) < doubleClickDuration {
r.clickY = append(r.clickY, y)
} else {
r.clickY = []int{y}
}
r.prevDownTime = now
// detect double clicks (also check for spatial condition)
n := len(r.clickY)
double := n > 1 && r.clickY[n-2] == r.clickY[n-1]
if double {
// make sure two consecutive double clicks require four clicks
r.clickY = []int{}
}
// fire single or double click event
return Event{Mouse, 0, &MouseEvent{y, x, 0, true, !double, double, mod}}
case button&tcell.Button2 != 0 && !drag:
return Event{Mouse, 0, &MouseEvent{y, x, 0, false, true, false, mod}}
case runtime.GOOS != "windows":
2016-10-24 03:45:45 +00:00
// double and single taps on Windows don't quite work due to
// the console acting on the events and not allowing us
// to consume them.
left := button&tcell.Button1 != 0
down := left || button&tcell.Button3 != 0
2016-10-24 03:45:45 +00:00
double := false
if down {
now := time.Now()
if !left {
r.clickY = []int{}
} else if now.Sub(r.prevDownTime) < doubleClickDuration {
2017-01-07 16:30:31 +00:00
r.clickY = append(r.clickY, x)
2016-10-24 03:45:45 +00:00
} else {
2017-01-07 16:30:31 +00:00
r.clickY = []int{x}
r.prevDownTime = now
2016-10-24 03:45:45 +00:00
}
} else {
2017-01-07 16:30:31 +00:00
if len(r.clickY) > 1 && r.clickY[0] == r.clickY[1] &&
time.Now().Sub(r.prevDownTime) < doubleClickDuration {
2016-10-24 03:45:45 +00:00
double = true
}
}
return Event{Mouse, 0, &MouseEvent{y, x, 0, left, down, double, mod}}
2016-10-24 03:45:45 +00:00
}
// process keyboard:
case *tcell.EventKey:
mods := ev.Modifiers()
none := mods == tcell.ModNone
alt := (mods & tcell.ModAlt) > 0
ctrl := (mods & tcell.ModCtrl) > 0
shift := (mods & tcell.ModShift) > 0
ctrlAlt := ctrl && alt
altShift := alt && shift
keyfn := func(r rune) Event {
if alt {
return CtrlAltKey(r)
}
return EventType(CtrlA.Int() - 'a' + int(r)).AsEvent()
}
2016-10-24 03:45:45 +00:00
switch ev.Key() {
// section 1: Ctrl+(Alt)+[a-z]
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlA:
return keyfn('a')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlB:
return keyfn('b')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlC:
return keyfn('c')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlD:
return keyfn('d')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlE:
return keyfn('e')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlF:
return keyfn('f')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlG:
return keyfn('g')
case tcell.KeyCtrlH:
switch ev.Rune() {
case 0:
if ctrl {
return Event{BSpace, 0, nil}
}
case rune(tcell.KeyCtrlH):
switch {
case ctrl:
return keyfn('h')
case alt:
return Event{AltBS, 0, nil}
case none, shift:
return Event{BSpace, 0, nil}
}
}
case tcell.KeyCtrlI:
return keyfn('i')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlJ:
return keyfn('j')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlK:
return keyfn('k')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlL:
return keyfn('l')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlM:
return keyfn('m')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlN:
return keyfn('n')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlO:
return keyfn('o')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlP:
return keyfn('p')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlQ:
return keyfn('q')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlR:
return keyfn('r')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlS:
return keyfn('s')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlT:
return keyfn('t')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlU:
return keyfn('u')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlV:
return keyfn('v')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlW:
return keyfn('w')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlX:
return keyfn('x')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlY:
return keyfn('y')
2016-10-24 03:45:45 +00:00
case tcell.KeyCtrlZ:
return keyfn('z')
// section 2: Ctrl+[ \]_]
case tcell.KeyCtrlSpace:
return Event{CtrlSpace, 0, nil}
2019-11-14 13:39:25 +00:00
case tcell.KeyCtrlBackslash:
return Event{CtrlBackSlash, 0, nil}
case tcell.KeyCtrlRightSq:
return Event{CtrlRightBracket, 0, nil}
case tcell.KeyCtrlCarat:
return Event{CtrlCaret, 0, nil}
2019-11-14 13:39:25 +00:00
case tcell.KeyCtrlUnderscore:
return Event{CtrlSlash, 0, nil}
// section 3: (Alt)+Backspace2
2017-04-28 13:58:08 +00:00
case tcell.KeyBackspace2:
if alt {
return Event{AltBS, 0, nil}
}
2016-10-24 03:45:45 +00:00
return Event{BSpace, 0, nil}
// section 4: (Alt+Shift)+Key(Up|Down|Left|Right)
2016-10-24 03:45:45 +00:00
case tcell.KeyUp:
if altShift {
return Event{AltSUp, 0, nil}
}
if shift {
return Event{SUp, 0, nil}
}
if alt {
return Event{AltUp, 0, nil}
}
2016-10-24 03:45:45 +00:00
return Event{Up, 0, nil}
case tcell.KeyDown:
if altShift {
return Event{AltSDown, 0, nil}
}
if shift {
return Event{SDown, 0, nil}
}
if alt {
return Event{AltDown, 0, nil}
}
2016-10-24 03:45:45 +00:00
return Event{Down, 0, nil}
case tcell.KeyLeft:
if altShift {
return Event{AltSLeft, 0, nil}
}
if shift {
return Event{SLeft, 0, nil}
}
if alt {
return Event{AltLeft, 0, nil}
}
2016-10-24 03:45:45 +00:00
return Event{Left, 0, nil}
case tcell.KeyRight:
if altShift {
return Event{AltSRight, 0, nil}
}
if shift {
return Event{SRight, 0, nil}
}
if alt {
return Event{AltRight, 0, nil}
}
2016-10-24 03:45:45 +00:00
return Event{Right, 0, nil}
// section 5: (Insert|Home|Delete|End|PgUp|PgDn|BackTab|F1-F12)
case tcell.KeyInsert:
return Event{Insert, 0, nil}
2016-10-24 03:45:45 +00:00
case tcell.KeyHome:
return Event{Home, 0, nil}
case tcell.KeyDelete:
return Event{Del, 0, nil}
case tcell.KeyEnd:
return Event{End, 0, nil}
case tcell.KeyPgUp:
2016-10-24 03:45:45 +00:00
return Event{PgUp, 0, nil}
case tcell.KeyPgDn:
return Event{PgDn, 0, nil}
case tcell.KeyBacktab:
return Event{BTab, 0, nil}
2016-10-24 03:45:45 +00:00
case tcell.KeyF1:
return Event{F1, 0, nil}
case tcell.KeyF2:
return Event{F2, 0, nil}
case tcell.KeyF3:
return Event{F3, 0, nil}
case tcell.KeyF4:
return Event{F4, 0, nil}
case tcell.KeyF5:
return Event{F5, 0, nil}
case tcell.KeyF6:
return Event{F6, 0, nil}
case tcell.KeyF7:
return Event{F7, 0, nil}
case tcell.KeyF8:
return Event{F8, 0, nil}
case tcell.KeyF9:
return Event{F9, 0, nil}
case tcell.KeyF10:
return Event{F10, 0, nil}
case tcell.KeyF11:
return Event{F11, 0, nil}
2016-10-24 03:45:45 +00:00
case tcell.KeyF12:
return Event{F12, 0, nil}
2016-10-24 03:45:45 +00:00
// section 6: (Ctrl+Alt)+'rune'
2016-10-24 03:45:45 +00:00
case tcell.KeyRune:
r := ev.Rune()
switch {
// translate native key events to ascii control characters
case r == ' ' && ctrl:
return Event{CtrlSpace, 0, nil}
// handle AltGr characters
case ctrlAlt:
return Event{Rune, r, nil} // dropping modifiers
// simple characters (possibly with modifier)
case alt:
return AltKey(r)
default:
return Event{Rune, r, nil}
}
2016-10-24 03:45:45 +00:00
// section 7: Esc
2016-10-24 03:45:45 +00:00
case tcell.KeyEsc:
return Event{ESC, 0, nil}
}
}
// section 8: Invalid
2016-10-24 03:45:45 +00:00
return Event{Invalid, 0, nil}
}
func (r *FullscreenRenderer) Pause(clear bool) {
if clear {
_screen.Fini()
}
}
func (r *FullscreenRenderer) Resume(clear bool, sigcont bool) {
if clear {
r.initScreen()
}
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) Close() {
2016-10-24 03:45:45 +00:00
_screen.Fini()
}
2017-01-07 16:30:31 +00:00
func (r *FullscreenRenderer) RefreshWindows(windows []Window) {
2016-10-24 03:45:45 +00:00
// TODO
for _, w := range windows {
2017-01-07 16:30:31 +00:00
w.Refresh()
2016-10-24 03:45:45 +00:00
}
_screen.Show()
}
func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window {
normal := ColNormal
if preview {
normal = ColPreview
}
2017-01-07 16:30:31 +00:00
return &TcellWindow{
color: r.theme.Colored,
preview: preview,
top: top,
left: left,
width: width,
height: height,
normal: normal,
borderStyle: borderStyle}
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) Close() {
2016-10-24 03:45:45 +00:00
// TODO
}
func fill(x, y, w, h int, n ColorPair, r rune) {
2016-10-24 03:45:45 +00:00
for ly := 0; ly <= h; ly++ {
for lx := 0; lx <= w; lx++ {
_screen.SetContent(x+lx, y+ly, r, nil, n.style())
2016-10-24 03:45:45 +00:00
}
}
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) Erase() {
fill(w.left-1, w.top, w.width+1, w.height, w.normal, ' ')
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) Enclose(y int, x int) bool {
return x >= w.left && x < (w.left+w.width) &&
y >= w.top && y < (w.top+w.height)
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) Move(y int, x int) {
w.lastX = x
w.lastY = y
w.moveCursor = true
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) MoveAndClear(y int, x int) {
2016-10-24 03:45:45 +00:00
w.Move(y, x)
2017-01-07 16:30:31 +00:00
for i := w.lastX; i < w.width; i++ {
_screen.SetContent(i+w.left, w.lastY+w.top, rune(' '), nil, w.normal.style())
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
w.lastX = x
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
func (w *TcellWindow) Print(text string) {
w.printString(text, w.normal)
2016-10-24 03:45:45 +00:00
}
func (w *TcellWindow) printString(text string, pair ColorPair) {
2016-10-24 03:45:45 +00:00
lx := 0
a := pair.Attr()
2016-10-24 03:45:45 +00:00
style := pair.style()
if a&AttrClear == 0 {
style = style.
2016-11-08 16:45:06 +00:00
Reverse(a&Attr(tcell.AttrReverse) != 0).
Underline(a&Attr(tcell.AttrUnderline) != 0).
Italic(a&Attr(tcell.AttrItalic) != 0).
Blink(a&Attr(tcell.AttrBlink) != 0).
Dim(a&Attr(tcell.AttrDim) != 0)
2016-11-08 16:45:06 +00:00
}
2016-10-24 03:45:45 +00:00
gr := uniseg.NewGraphemes(text)
for gr.Next() {
rs := gr.Runes()
2016-10-24 03:45:45 +00:00
if len(rs) == 1 {
r := rs[0]
if r < rune(' ') { // ignore control characters
continue
} else if r == '\n' {
w.lastY++
lx = 0
continue
} else if r == '\u000D' { // skip carriage return
2016-10-24 03:45:45 +00:00
continue
}
}
var xPos = w.left + w.lastX + lx
var yPos = w.top + w.lastY
if xPos < (w.left+w.width) && yPos < (w.top+w.height) {
_screen.SetContent(xPos, yPos, rs[0], rs[1:], style)
}
lx += runewidth.StringWidth(string(rs))
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
w.lastX += lx
2016-10-24 03:45:45 +00:00
}
func (w *TcellWindow) CPrint(pair ColorPair, text string) {
w.printString(text, pair)
2016-10-24 03:45:45 +00:00
}
2020-10-25 12:43:53 +00:00
func (w *TcellWindow) fillString(text string, pair ColorPair) FillReturn {
2016-10-24 03:45:45 +00:00
lx := 0
2020-10-25 12:43:53 +00:00
a := pair.Attr()
2016-10-24 03:45:45 +00:00
2016-11-08 16:45:06 +00:00
var style tcell.Style
2017-01-07 16:30:31 +00:00
if w.color {
2016-11-08 16:45:06 +00:00
style = pair.style()
} else {
style = w.normal.style()
2016-11-08 16:45:06 +00:00
}
style = style.
2016-10-24 03:45:45 +00:00
Blink(a&Attr(tcell.AttrBlink) != 0).
Bold(a&Attr(tcell.AttrBold) != 0).
Dim(a&Attr(tcell.AttrDim) != 0).
Reverse(a&Attr(tcell.AttrReverse) != 0).
Underline(a&Attr(tcell.AttrUnderline) != 0).
Italic(a&Attr(tcell.AttrItalic) != 0)
2016-10-24 03:45:45 +00:00
gr := uniseg.NewGraphemes(text)
for gr.Next() {
rs := gr.Runes()
if len(rs) == 1 && rs[0] == '\n' {
2017-01-07 16:30:31 +00:00
w.lastY++
w.lastX = 0
2016-10-24 03:45:45 +00:00
lx = 0
continue
}
2016-10-24 03:45:45 +00:00
// word wrap:
xPos := w.left + w.lastX + lx
if xPos >= (w.left + w.width) {
w.lastY++
w.lastX = 0
lx = 0
xPos = w.left
}
2016-10-24 03:45:45 +00:00
yPos := w.top + w.lastY
if yPos >= (w.top + w.height) {
return FillSuspend
2016-10-24 03:45:45 +00:00
}
_screen.SetContent(xPos, yPos, rs[0], rs[1:], style)
lx += runewidth.StringWidth(string(rs))
2016-10-24 03:45:45 +00:00
}
2017-01-07 16:30:31 +00:00
w.lastX += lx
2020-10-25 12:43:53 +00:00
if w.lastX == w.width {
w.lastY++
w.lastX = 0
return FillNextLine
}
2016-10-24 03:45:45 +00:00
return FillContinue
2016-10-24 03:45:45 +00:00
}
func (w *TcellWindow) Fill(str string) FillReturn {
2020-10-25 12:43:53 +00:00
return w.fillString(str, w.normal)
2016-10-24 03:45:45 +00:00
}
func (w *TcellWindow) CFill(fg Color, bg Color, a Attr, str string) FillReturn {
if fg == colDefault {
fg = w.normal.Fg()
}
if bg == colDefault {
bg = w.normal.Bg()
}
2020-10-25 12:43:53 +00:00
return w.fillString(str, NewColorPair(fg, bg, a))
2016-10-24 03:45:45 +00:00
}
func (w *TcellWindow) drawBorder() {
shape := w.borderStyle.shape
if shape == BorderNone {
return
}
2017-01-07 16:30:31 +00:00
left := w.left
right := left + w.width
top := w.top
bot := top + w.height
2016-10-24 03:45:45 +00:00
2016-11-08 16:45:06 +00:00
var style tcell.Style
2017-01-07 16:30:31 +00:00
if w.color {
if w.preview {
style = ColPreviewBorder.style()
} else {
style = ColBorder.style()
}
2016-11-08 16:45:06 +00:00
} else {
style = w.normal.style()
2016-11-08 16:45:06 +00:00
}
2016-10-24 03:45:45 +00:00
switch shape {
case BorderRounded, BorderSharp, BorderHorizontal, BorderTop:
for x := left; x < right; x++ {
_screen.SetContent(x, top, w.borderStyle.horizontal, nil, style)
}
2016-10-24 03:45:45 +00:00
}
switch shape {
case BorderRounded, BorderSharp, BorderHorizontal, BorderBottom:
for x := left; x < right; x++ {
_screen.SetContent(x, bot-1, w.borderStyle.horizontal, nil, style)
}
}
switch shape {
case BorderRounded, BorderSharp, BorderVertical, BorderLeft:
for y := top; y < bot; y++ {
_screen.SetContent(left, y, w.borderStyle.vertical, nil, style)
}
}
switch shape {
case BorderRounded, BorderSharp, BorderVertical, BorderRight:
for y := top; y < bot; y++ {
_screen.SetContent(right-1, y, w.borderStyle.vertical, nil, style)
}
}
switch shape {
case BorderRounded, BorderSharp:
_screen.SetContent(left, top, w.borderStyle.topLeft, nil, style)
_screen.SetContent(right-1, top, w.borderStyle.topRight, nil, style)
_screen.SetContent(left, bot-1, w.borderStyle.bottomLeft, nil, style)
_screen.SetContent(right-1, bot-1, w.borderStyle.bottomRight, nil, style)
}
2016-10-24 03:45:45 +00:00
}