forked from tslocum/cview
Remove return values from methods which return their primitive (breaks chaining)
This commit is contained in:
parent
2763609e05
commit
ed5e6d94dd
|
@ -4,6 +4,7 @@ v1.5.1 (WIP)
|
|||
- Add TableCell.SetBytes, TableCell.GetBytes and TableCell.GetText
|
||||
- Allow modification of scroll bar render text
|
||||
- Optimize TextView (writing is 90% faster, drawing is 50% faster)
|
||||
- Remove return values from methods which return their primitive (breaks chaining)
|
||||
|
||||
v1.5.0 (2020-10-03)
|
||||
- Add scroll bar to TextView
|
||||
|
|
18
FORK.md
18
FORK.md
|
@ -26,6 +26,14 @@ maintainers and allowing code changes which may be outside of tview's scope.
|
|||
|
||||
# Differences
|
||||
|
||||
## Primitive methods do not return the primitive they belong to
|
||||
|
||||
When chaining multiple method calls on a primitive together, application
|
||||
developers might accidentally end the chain with a different return type than
|
||||
the first method call. This could result in unexpected return types. For
|
||||
example, ending a chain with `SetTitle` would result in a `Box` rather than the
|
||||
original primitive.
|
||||
|
||||
## cview is [thread-safe](https://docs.rocketnine.space/gitlab.com/tslocum/cview/#hdr-Concurrency)
|
||||
|
||||
tview [is not thread-safe](https://godoc.org/github.com/rivo/tview#hdr-Concurrency).
|
||||
|
@ -38,11 +46,6 @@ tview [blocks until the queued function returns](https://github.com/rivo/tview/b
|
|||
|
||||
All clicks are handled as single clicks until an interval is set with [Application.SetDoubleClickInterval](https://docs.rocketnine.space/gitlab.com/tslocum/cview/#Application.SetDoubleClickInterval).
|
||||
|
||||
## Setting a primitive's background color to `tcell.ColorDefault` does not result in transparency
|
||||
|
||||
Call [Box.SetBackgroundTransparent](https://docs.rocketnine.space/gitlab.com/tslocum/cview/#Box.SetBackgroundTransparent)
|
||||
to enable background transparency.
|
||||
|
||||
## Tables are sorted when a fixed row is clicked by default
|
||||
|
||||
Call [Table.SetSortClicked](https://docs.rocketnine.space/gitlab.com/tslocum/cview/#Table.SetSortClicked)
|
||||
|
@ -53,6 +56,11 @@ to disable this behavior.
|
|||
Call [List.SetWrapAround](https://docs.rocketnine.space/gitlab.com/tslocum/cview/#List.SetWrapAround)
|
||||
to wrap around when navigating.
|
||||
|
||||
## Setting a primitive's background color to `tcell.ColorDefault` does not result in transparency
|
||||
|
||||
Call [Box.SetBackgroundTransparent](https://docs.rocketnine.space/gitlab.com/tslocum/cview/#Box.SetBackgroundTransparent)
|
||||
to enable background transparency.
|
||||
|
||||
## TextViews store their text as []byte instead of string
|
||||
|
||||
This greatly improves buffer efficiency. [TextView.Write](https://docs.rocketnine.space/gitlab.com/tslocum/cview/#TextView.Write)
|
||||
|
|
|
@ -127,12 +127,12 @@ func NewApplication() *Application {
|
|||
// Note that this also affects the default event handling of the application
|
||||
// itself: Such a handler can intercept the Ctrl-C event which closes the
|
||||
// application.
|
||||
func (a *Application) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Application {
|
||||
func (a *Application) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
a.inputCapture = capture
|
||||
return a
|
||||
|
||||
}
|
||||
|
||||
// GetInputCapture returns the function installed with SetInputCapture() or nil
|
||||
|
@ -149,9 +149,9 @@ func (a *Application) GetInputCapture() func(event *tcell.EventKey) *tcell.Event
|
|||
// forwarded to the appropriate mouse event handler. This function can then
|
||||
// choose to forward that event (or a different one) by returning it or stop
|
||||
// the event processing by returning a nil mouse event.
|
||||
func (a *Application) SetMouseCapture(capture func(event *tcell.EventMouse, action MouseAction) (*tcell.EventMouse, MouseAction)) *Application {
|
||||
func (a *Application) SetMouseCapture(capture func(event *tcell.EventMouse, action MouseAction) (*tcell.EventMouse, MouseAction)) {
|
||||
a.mouseCapture = capture
|
||||
return a
|
||||
|
||||
}
|
||||
|
||||
// GetMouseCapture returns the function installed with SetMouseCapture() or nil
|
||||
|
@ -173,9 +173,9 @@ func (a *Application) SetDoubleClickInterval(interval time.Duration) {
|
|||
//
|
||||
// This function is typically called before the first call to Run(). Init() need
|
||||
// not be called on the screen.
|
||||
func (a *Application) SetScreen(screen tcell.Screen) *Application {
|
||||
func (a *Application) SetScreen(screen tcell.Screen) {
|
||||
if screen == nil {
|
||||
return a // Invalid input. Do nothing.
|
||||
return // Invalid input. Do nothing.
|
||||
}
|
||||
|
||||
a.Lock()
|
||||
|
@ -183,7 +183,7 @@ func (a *Application) SetScreen(screen tcell.Screen) *Application {
|
|||
// Run() has not been called yet.
|
||||
a.screen = screen
|
||||
a.Unlock()
|
||||
return a
|
||||
return
|
||||
}
|
||||
|
||||
// Run() is already in progress. Exchange screen.
|
||||
|
@ -191,12 +191,10 @@ func (a *Application) SetScreen(screen tcell.Screen) *Application {
|
|||
a.Unlock()
|
||||
oldScreen.Fini()
|
||||
a.screenReplacement <- screen
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// EnableMouse enables mouse events.
|
||||
func (a *Application) EnableMouse(enable bool) *Application {
|
||||
func (a *Application) EnableMouse(enable bool) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
if enable != a.enableMouse && a.screen != nil {
|
||||
|
@ -207,7 +205,7 @@ func (a *Application) EnableMouse(enable bool) *Application {
|
|||
}
|
||||
}
|
||||
a.enableMouse = enable
|
||||
return a
|
||||
|
||||
}
|
||||
|
||||
// Run starts the application and thus the event loop. This function returns
|
||||
|
@ -545,11 +543,11 @@ func (a *Application) Suspend(f func()) bool {
|
|||
// Draw refreshes the screen (during the next update cycle). It calls the Draw()
|
||||
// function of the application's root primitive and then syncs the screen
|
||||
// buffer.
|
||||
func (a *Application) Draw() *Application {
|
||||
func (a *Application) Draw() {
|
||||
a.QueueUpdate(func() {
|
||||
a.draw()
|
||||
})
|
||||
return a
|
||||
|
||||
}
|
||||
|
||||
// ForceDraw refreshes the screen immediately. Use this function with caution as
|
||||
|
@ -559,12 +557,12 @@ func (a *Application) Draw() *Application {
|
|||
//
|
||||
// It is safe to call this function during queued updates and direct event
|
||||
// handling.
|
||||
func (a *Application) ForceDraw() *Application {
|
||||
return a.draw()
|
||||
func (a *Application) ForceDraw() {
|
||||
a.draw()
|
||||
}
|
||||
|
||||
// draw actually does what Draw() promises to do.
|
||||
func (a *Application) draw() *Application {
|
||||
func (a *Application) draw() {
|
||||
a.Lock()
|
||||
|
||||
screen := a.screen
|
||||
|
@ -576,7 +574,7 @@ func (a *Application) draw() *Application {
|
|||
// Maybe we're not ready yet or not anymore.
|
||||
if screen == nil || root == nil {
|
||||
a.Unlock()
|
||||
return a
|
||||
return
|
||||
}
|
||||
|
||||
// Resize if requested.
|
||||
|
@ -590,7 +588,7 @@ func (a *Application) draw() *Application {
|
|||
a.Unlock()
|
||||
if before(screen) {
|
||||
screen.Show()
|
||||
return a
|
||||
return
|
||||
}
|
||||
} else {
|
||||
a.Unlock()
|
||||
|
@ -606,8 +604,6 @@ func (a *Application) draw() *Application {
|
|||
|
||||
// Sync screen.
|
||||
screen.Show()
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// SetBeforeDrawFunc installs a callback function which is invoked just before
|
||||
|
@ -619,12 +615,11 @@ func (a *Application) draw() *Application {
|
|||
// you may call screen.Clear().
|
||||
//
|
||||
// Provide nil to uninstall the callback function.
|
||||
func (a *Application) SetBeforeDrawFunc(handler func(screen tcell.Screen) bool) *Application {
|
||||
func (a *Application) SetBeforeDrawFunc(handler func(screen tcell.Screen) bool) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
a.beforeDraw = handler
|
||||
return a
|
||||
}
|
||||
|
||||
// GetBeforeDrawFunc returns the callback function installed with
|
||||
|
@ -640,12 +635,11 @@ func (a *Application) GetBeforeDrawFunc() func(screen tcell.Screen) bool {
|
|||
// primitive was drawn during screen updates.
|
||||
//
|
||||
// Provide nil to uninstall the callback function.
|
||||
func (a *Application) SetAfterDrawFunc(handler func(screen tcell.Screen)) *Application {
|
||||
func (a *Application) SetAfterDrawFunc(handler func(screen tcell.Screen)) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
a.afterDraw = handler
|
||||
return a
|
||||
}
|
||||
|
||||
// GetAfterDrawFunc returns the callback function installed with
|
||||
|
@ -664,7 +658,7 @@ func (a *Application) GetAfterDrawFunc() func(screen tcell.Screen) {
|
|||
// the application starts.
|
||||
//
|
||||
// It also calls SetFocus() on the primitive.
|
||||
func (a *Application) SetRoot(root Primitive, fullscreen bool) *Application {
|
||||
func (a *Application) SetRoot(root Primitive, fullscreen bool) {
|
||||
a.Lock()
|
||||
a.root = root
|
||||
a.rootFullscreen = fullscreen
|
||||
|
@ -674,18 +668,15 @@ func (a *Application) SetRoot(root Primitive, fullscreen bool) *Application {
|
|||
a.Unlock()
|
||||
|
||||
a.SetFocus(root)
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// ResizeToFullScreen resizes the given primitive such that it fills the entire
|
||||
// screen.
|
||||
func (a *Application) ResizeToFullScreen(p Primitive) *Application {
|
||||
func (a *Application) ResizeToFullScreen(p Primitive) {
|
||||
a.RLock()
|
||||
width, height := a.screen.Size()
|
||||
a.RUnlock()
|
||||
p.SetRect(0, 0, width, height)
|
||||
return a
|
||||
}
|
||||
|
||||
// SetAfterResizeFunc installs a callback function which is invoked when the
|
||||
|
@ -694,12 +685,11 @@ func (a *Application) ResizeToFullScreen(p Primitive) *Application {
|
|||
// application is drawn.
|
||||
//
|
||||
// Provide nil to uninstall the callback function.
|
||||
func (a *Application) SetAfterResizeFunc(handler func(width int, height int)) *Application {
|
||||
func (a *Application) SetAfterResizeFunc(handler func(width int, height int)) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
a.afterResize = handler
|
||||
return a
|
||||
}
|
||||
|
||||
// GetAfterResizeFunc returns the callback function installed with
|
||||
|
@ -717,14 +707,14 @@ func (a *Application) GetAfterResizeFunc() func(width int, height int) {
|
|||
//
|
||||
// Blur() will be called on the previously focused primitive. Focus() will be
|
||||
// called on the new primitive.
|
||||
func (a *Application) SetFocus(p Primitive) *Application {
|
||||
func (a *Application) SetFocus(p Primitive) {
|
||||
a.Lock()
|
||||
|
||||
if a.beforeFocus != nil {
|
||||
a.Unlock()
|
||||
ok := a.beforeFocus(p)
|
||||
if !ok {
|
||||
return a
|
||||
return
|
||||
}
|
||||
a.Lock()
|
||||
}
|
||||
|
@ -752,8 +742,6 @@ func (a *Application) SetFocus(p Primitive) *Application {
|
|||
a.SetFocus(p)
|
||||
})
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// GetFocus returns the primitive which has the current focus. If none has it,
|
||||
|
@ -769,24 +757,22 @@ func (a *Application) GetFocus() Primitive {
|
|||
// application's focus changes. Return false to maintain the current focus.
|
||||
//
|
||||
// Provide nil to uninstall the callback function.
|
||||
func (a *Application) SetBeforeFocusFunc(handler func(p Primitive) bool) *Application {
|
||||
func (a *Application) SetBeforeFocusFunc(handler func(p Primitive) bool) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
a.beforeFocus = handler
|
||||
return a
|
||||
}
|
||||
|
||||
// SetAfterFocusFunc installs a callback function which is invoked after the
|
||||
// application's focus changes.
|
||||
//
|
||||
// Provide nil to uninstall the callback function.
|
||||
func (a *Application) SetAfterFocusFunc(handler func(p Primitive)) *Application {
|
||||
func (a *Application) SetAfterFocusFunc(handler func(p Primitive)) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
a.afterFocus = handler
|
||||
return a
|
||||
}
|
||||
|
||||
// QueueUpdate queues a function to be executed as part of the event loop.
|
||||
|
@ -795,27 +781,24 @@ func (a *Application) SetAfterFocusFunc(handler func(p Primitive)) *Application
|
|||
// may not be desirable. You can call Draw() from f if the screen should be
|
||||
// refreshed after each update. Alternatively, use QueueUpdateDraw() to follow
|
||||
// up with an immediate refresh of the screen.
|
||||
func (a *Application) QueueUpdate(f func()) *Application {
|
||||
func (a *Application) QueueUpdate(f func()) {
|
||||
a.updates <- f
|
||||
return a
|
||||
}
|
||||
|
||||
// QueueUpdateDraw works like QueueUpdate() except it refreshes the screen
|
||||
// immediately after executing f.
|
||||
func (a *Application) QueueUpdateDraw(f func()) *Application {
|
||||
func (a *Application) QueueUpdateDraw(f func()) {
|
||||
a.QueueUpdate(func() {
|
||||
f()
|
||||
a.draw()
|
||||
})
|
||||
return a
|
||||
}
|
||||
|
||||
// QueueEvent sends an event to the Application event loop.
|
||||
//
|
||||
// It is not recommended for event to be nil.
|
||||
func (a *Application) QueueEvent(event tcell.Event) *Application {
|
||||
func (a *Application) QueueEvent(event tcell.Event) {
|
||||
a.events <- event
|
||||
return a
|
||||
}
|
||||
|
||||
// RingBell sends a bell code to the terminal.
|
||||
|
|
43
box.go
43
box.go
|
@ -98,12 +98,11 @@ func (b *Box) GetBorderPadding() (top, bottom, left, right int) {
|
|||
}
|
||||
|
||||
// SetBorderPadding sets the size of the borders around the box content.
|
||||
func (b *Box) SetBorderPadding(top, bottom, left, right int) *Box {
|
||||
func (b *Box) SetBorderPadding(top, bottom, left, right int) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.paddingTop, b.paddingBottom, b.paddingLeft, b.paddingRight = top, bottom, left, right
|
||||
return b
|
||||
}
|
||||
|
||||
// GetRect returns the current position of the rectangle, x, y, width, and
|
||||
|
@ -172,12 +171,11 @@ func (b *Box) SetRect(x, y, width, height int) {
|
|||
// must return the box's inner dimensions (x, y, width, height) which will be
|
||||
// returned by GetInnerRect(), used by descendent primitives to draw their own
|
||||
// content.
|
||||
func (b *Box) SetDrawFunc(handler func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)) *Box {
|
||||
func (b *Box) SetDrawFunc(handler func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.draw = handler
|
||||
return b
|
||||
}
|
||||
|
||||
// GetDrawFunc returns the callback function which was installed with
|
||||
|
@ -227,12 +225,11 @@ func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func(p Primiti
|
|||
// can have focus at a time. Composing primitives such as Form pass the focus on
|
||||
// to their contained primitives and thus never receive any key events
|
||||
// themselves. Therefore, they cannot intercept key events.
|
||||
func (b *Box) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) *Box {
|
||||
func (b *Box) SetInputCapture(capture func(event *tcell.EventKey) *tcell.EventKey) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.inputCapture = capture
|
||||
return b
|
||||
}
|
||||
|
||||
// GetInputCapture returns the function installed with SetInputCapture() or nil
|
||||
|
@ -280,9 +277,8 @@ func (b *Box) MouseHandler() func(action MouseAction, event *tcell.EventMouse, s
|
|||
// called.
|
||||
//
|
||||
// Providing a nil handler will remove a previously existing handler.
|
||||
func (b *Box) SetMouseCapture(capture func(action MouseAction, event *tcell.EventMouse) (MouseAction, *tcell.EventMouse)) *Box {
|
||||
func (b *Box) SetMouseCapture(capture func(action MouseAction, event *tcell.EventMouse) (MouseAction, *tcell.EventMouse)) {
|
||||
b.mouseCapture = capture
|
||||
return b
|
||||
}
|
||||
|
||||
// InRect returns true if the given coordinate is within the bounds of the box's
|
||||
|
@ -299,12 +295,11 @@ func (b *Box) GetMouseCapture() func(action MouseAction, event *tcell.EventMouse
|
|||
}
|
||||
|
||||
// SetBackgroundColor sets the box's background color.
|
||||
func (b *Box) SetBackgroundColor(color tcell.Color) *Box {
|
||||
func (b *Box) SetBackgroundColor(color tcell.Color) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.backgroundColor = color
|
||||
return b
|
||||
}
|
||||
|
||||
// GetBackgroundColor returns the box's background color.
|
||||
|
@ -316,12 +311,11 @@ func (b *Box) GetBackgroundColor() tcell.Color {
|
|||
|
||||
// SetBackgroundTransparent sets the flag indicating whether or not the box's
|
||||
// background is transparent.
|
||||
func (b *Box) SetBackgroundTransparent(transparent bool) *Box {
|
||||
func (b *Box) SetBackgroundTransparent(transparent bool) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.backgroundTransparent = transparent
|
||||
return b
|
||||
}
|
||||
|
||||
// GetBorder returns a value indicating whether the box have a border
|
||||
|
@ -334,50 +328,45 @@ func (b *Box) GetBorder() bool {
|
|||
|
||||
// SetBorder sets the flag indicating whether or not the box should have a
|
||||
// border.
|
||||
func (b *Box) SetBorder(show bool) *Box {
|
||||
func (b *Box) SetBorder(show bool) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.border = show
|
||||
return b
|
||||
}
|
||||
|
||||
// SetBorderColor sets the box's border color.
|
||||
func (b *Box) SetBorderColor(color tcell.Color) *Box {
|
||||
func (b *Box) SetBorderColor(color tcell.Color) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.borderColor = color
|
||||
return b
|
||||
}
|
||||
|
||||
// SetBorderColorFocused sets the box's border color when the box is focused.
|
||||
func (b *Box) SetBorderColorFocused(color tcell.Color) *Box {
|
||||
func (b *Box) SetBorderColorFocused(color tcell.Color) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
b.borderColorFocused = color
|
||||
return b
|
||||
}
|
||||
|
||||
// SetBorderAttributes sets the border's style attributes. You can combine
|
||||
// different attributes using bitmask operations:
|
||||
//
|
||||
// box.SetBorderAttributes(tcell.AttrUnderline | tcell.AttrBold)
|
||||
func (b *Box) SetBorderAttributes(attr tcell.AttrMask) *Box {
|
||||
func (b *Box) SetBorderAttributes(attr tcell.AttrMask) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.borderAttributes = attr
|
||||
return b
|
||||
}
|
||||
|
||||
// SetTitle sets the box's title.
|
||||
func (b *Box) SetTitle(title string) *Box {
|
||||
func (b *Box) SetTitle(title string) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.title = []byte(title)
|
||||
return b
|
||||
}
|
||||
|
||||
// GetTitle returns the box's current title.
|
||||
|
@ -389,22 +378,21 @@ func (b *Box) GetTitle() string {
|
|||
}
|
||||
|
||||
// SetTitleColor sets the box's title color.
|
||||
func (b *Box) SetTitleColor(color tcell.Color) *Box {
|
||||
func (b *Box) SetTitleColor(color tcell.Color) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.titleColor = color
|
||||
return b
|
||||
}
|
||||
|
||||
// SetTitleAlign sets the alignment of the title, one of AlignLeft, AlignCenter,
|
||||
// or AlignRight.
|
||||
func (b *Box) SetTitleAlign(align int) *Box {
|
||||
func (b *Box) SetTitleAlign(align int) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.titleAlign = align
|
||||
return b
|
||||
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
|
@ -527,12 +515,11 @@ func (b *Box) Draw(screen tcell.Screen) {
|
|||
|
||||
// ShowFocus sets the flag indicating whether or not the borders of this
|
||||
// primitive should change thickness when focused.
|
||||
func (b *Box) ShowFocus(showFocus bool) *Box {
|
||||
func (b *Box) ShowFocus(showFocus bool) {
|
||||
b.l.Lock()
|
||||
defer b.l.Unlock()
|
||||
|
||||
b.showFocus = showFocus
|
||||
return b
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
|
|
21
button.go
21
button.go
|
@ -34,7 +34,8 @@ type Button struct {
|
|||
|
||||
// NewButton returns a new input field.
|
||||
func NewButton(label string) *Button {
|
||||
box := NewBox().SetBackgroundColor(Styles.ContrastBackgroundColor)
|
||||
box := NewBox()
|
||||
box.SetBackgroundColor(Styles.ContrastBackgroundColor)
|
||||
box.SetRect(0, 0, TaggedStringWidth(label)+4, 1)
|
||||
return &Button{
|
||||
Box: box,
|
||||
|
@ -46,12 +47,11 @@ func NewButton(label string) *Button {
|
|||
}
|
||||
|
||||
// SetLabel sets the button text.
|
||||
func (b *Button) SetLabel(label string) *Button {
|
||||
func (b *Button) SetLabel(label string) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.label = []byte(label)
|
||||
return b
|
||||
}
|
||||
|
||||
// GetLabel returns the button text.
|
||||
|
@ -63,41 +63,37 @@ func (b *Button) GetLabel() string {
|
|||
}
|
||||
|
||||
// SetLabelColor sets the color of the button text.
|
||||
func (b *Button) SetLabelColor(color tcell.Color) *Button {
|
||||
func (b *Button) SetLabelColor(color tcell.Color) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.labelColor = color
|
||||
return b
|
||||
}
|
||||
|
||||
// SetLabelColorFocused sets the color of the button text when the button is
|
||||
// in focus.
|
||||
func (b *Button) SetLabelColorFocused(color tcell.Color) *Button {
|
||||
func (b *Button) SetLabelColorFocused(color tcell.Color) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.labelColorFocused = color
|
||||
return b
|
||||
}
|
||||
|
||||
// SetBackgroundColorFocused sets the background color of the button text when
|
||||
// the button is in focus.
|
||||
func (b *Button) SetBackgroundColorFocused(color tcell.Color) *Button {
|
||||
func (b *Button) SetBackgroundColorFocused(color tcell.Color) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.backgroundColorFocused = color
|
||||
return b
|
||||
}
|
||||
|
||||
// SetSelectedFunc sets a handler which is called when the button was selected.
|
||||
func (b *Button) SetSelectedFunc(handler func()) *Button {
|
||||
func (b *Button) SetSelectedFunc(handler func()) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.selected = handler
|
||||
return b
|
||||
}
|
||||
|
||||
// SetBlurFunc sets a handler which is called when the user leaves the button.
|
||||
|
@ -107,12 +103,11 @@ func (b *Button) SetSelectedFunc(handler func()) *Button {
|
|||
// - KeyEscape: Leaving the button with no specific direction.
|
||||
// - KeyTab: Move to the next field.
|
||||
// - KeyBacktab: Move to the previous field.
|
||||
func (b *Button) SetBlurFunc(handler func(key tcell.Key)) *Button {
|
||||
func (b *Button) SetBlurFunc(handler func(key tcell.Key)) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.blur = handler
|
||||
return b
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
|
|
42
checkbox.go
42
checkbox.go
|
@ -76,21 +76,19 @@ func NewCheckBox() *CheckBox {
|
|||
}
|
||||
|
||||
// SetChecked sets the state of the checkbox.
|
||||
func (c *CheckBox) SetChecked(checked bool) *CheckBox {
|
||||
func (c *CheckBox) SetChecked(checked bool) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.checked = checked
|
||||
return c
|
||||
}
|
||||
|
||||
// SetCheckedRune sets the rune to show when the checkbox is checked.
|
||||
func (c *CheckBox) SetCheckedRune(rune rune) *CheckBox {
|
||||
func (c *CheckBox) SetCheckedRune(rune rune) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.checkedRune = rune
|
||||
return c
|
||||
}
|
||||
|
||||
// IsChecked returns whether or not the box is checked.
|
||||
|
@ -102,12 +100,11 @@ func (c *CheckBox) IsChecked() bool {
|
|||
}
|
||||
|
||||
// SetLabel sets the text to be displayed before the input area.
|
||||
func (c *CheckBox) SetLabel(label string) *CheckBox {
|
||||
func (c *CheckBox) SetLabel(label string) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.label = []byte(label)
|
||||
return c
|
||||
}
|
||||
|
||||
// GetLabel returns the text to be displayed before the input area.
|
||||
|
@ -119,12 +116,11 @@ func (c *CheckBox) GetLabel() string {
|
|||
}
|
||||
|
||||
// SetMessage sets the text to be displayed after the checkbox
|
||||
func (c *CheckBox) SetMessage(message string) *CheckBox {
|
||||
func (c *CheckBox) SetMessage(message string) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.message = []byte(message)
|
||||
return c
|
||||
}
|
||||
|
||||
// GetMessage returns the text to be displayed after the checkbox
|
||||
|
@ -137,66 +133,59 @@ func (c *CheckBox) GetMessage() string {
|
|||
|
||||
// SetLabelWidth sets the screen width of the label. A value of 0 will cause the
|
||||
// primitive to use the width of the label string.
|
||||
func (c *CheckBox) SetLabelWidth(width int) *CheckBox {
|
||||
func (c *CheckBox) SetLabelWidth(width int) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.labelWidth = width
|
||||
return c
|
||||
}
|
||||
|
||||
// SetLabelColor sets the color of the label.
|
||||
func (c *CheckBox) SetLabelColor(color tcell.Color) *CheckBox {
|
||||
func (c *CheckBox) SetLabelColor(color tcell.Color) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.labelColor = color
|
||||
return c
|
||||
}
|
||||
|
||||
// SetLabelColorFocused sets the color of the label when focused.
|
||||
func (c *CheckBox) SetLabelColorFocused(color tcell.Color) *CheckBox {
|
||||
func (c *CheckBox) SetLabelColorFocused(color tcell.Color) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.labelColorFocused = color
|
||||
return c
|
||||
}
|
||||
|
||||
// SetFieldBackgroundColor sets the background color of the input area.
|
||||
func (c *CheckBox) SetFieldBackgroundColor(color tcell.Color) *CheckBox {
|
||||
func (c *CheckBox) SetFieldBackgroundColor(color tcell.Color) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.fieldBackgroundColor = color
|
||||
return c
|
||||
}
|
||||
|
||||
// SetFieldBackgroundColorFocused sets the background color of the input area when focused.
|
||||
func (c *CheckBox) SetFieldBackgroundColorFocused(color tcell.Color) *CheckBox {
|
||||
func (c *CheckBox) SetFieldBackgroundColorFocused(color tcell.Color) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.fieldBackgroundColorFocused = color
|
||||
return c
|
||||
}
|
||||
|
||||
// SetFieldTextColor sets the text color of the input area.
|
||||
func (c *CheckBox) SetFieldTextColor(color tcell.Color) *CheckBox {
|
||||
func (c *CheckBox) SetFieldTextColor(color tcell.Color) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.fieldTextColor = color
|
||||
return c
|
||||
}
|
||||
|
||||
// SetFieldTextColorFocused sets the text color of the input area when focused.
|
||||
func (c *CheckBox) SetFieldTextColorFocused(color tcell.Color) *CheckBox {
|
||||
func (c *CheckBox) SetFieldTextColorFocused(color tcell.Color) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.fieldTextColorFocused = color
|
||||
return c
|
||||
}
|
||||
|
||||
// GetFieldHeight returns the height of the field.
|
||||
|
@ -219,12 +208,11 @@ func (c *CheckBox) GetFieldWidth() int {
|
|||
// SetChangedFunc sets a handler which is called when the checked state of this
|
||||
// checkbox was changed by the user. The handler function receives the new
|
||||
// state.
|
||||
func (c *CheckBox) SetChangedFunc(handler func(checked bool)) *CheckBox {
|
||||
func (c *CheckBox) SetChangedFunc(handler func(checked bool)) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.changed = handler
|
||||
return c
|
||||
}
|
||||
|
||||
// SetDoneFunc sets a handler which is called when the user is done using the
|
||||
|
@ -234,21 +222,19 @@ func (c *CheckBox) SetChangedFunc(handler func(checked bool)) *CheckBox {
|
|||
// - KeyEscape: Abort text input.
|
||||
// - KeyTab: Move to the next field.
|
||||
// - KeyBacktab: Move to the previous field.
|
||||
func (c *CheckBox) SetDoneFunc(handler func(key tcell.Key)) *CheckBox {
|
||||
func (c *CheckBox) SetDoneFunc(handler func(key tcell.Key)) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.done = handler
|
||||
return c
|
||||
}
|
||||
|
||||
// SetFinishedFunc sets a callback invoked when the user leaves this form item.
|
||||
func (c *CheckBox) SetFinishedFunc(handler func(key tcell.Key)) *CheckBox {
|
||||
func (c *CheckBox) SetFinishedFunc(handler func(key tcell.Key)) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.finished = handler
|
||||
return c
|
||||
}
|
||||
|
||||
// SetAttributes applies attribute settings to a form item.
|
||||
|
|
|
@ -28,18 +28,17 @@ func (c *ContextMenu) initializeList() {
|
|||
return
|
||||
}
|
||||
|
||||
c.list = NewList().
|
||||
ShowSecondaryText(false).
|
||||
SetHover(true).
|
||||
SetWrapAround(true)
|
||||
c.list.
|
||||
ShowFocus(false).
|
||||
SetBorder(true).
|
||||
SetBorderPadding(
|
||||
Styles.ContextMenuPaddingTop,
|
||||
Styles.ContextMenuPaddingBottom,
|
||||
Styles.ContextMenuPaddingLeft,
|
||||
Styles.ContextMenuPaddingRight)
|
||||
c.list = NewList()
|
||||
c.list.ShowSecondaryText(false)
|
||||
c.list.SetHover(true)
|
||||
c.list.SetWrapAround(true)
|
||||
c.list.ShowFocus(false)
|
||||
c.list.SetBorder(true)
|
||||
c.list.SetBorderPadding(
|
||||
Styles.ContextMenuPaddingTop,
|
||||
Styles.ContextMenuPaddingBottom,
|
||||
Styles.ContextMenuPaddingLeft,
|
||||
Styles.ContextMenuPaddingRight)
|
||||
}
|
||||
|
||||
// ContextMenuList returns the underlying List of the context menu.
|
||||
|
@ -54,21 +53,23 @@ func (c *ContextMenu) ContextMenuList() *List {
|
|||
|
||||
// AddContextItem adds an item to the context menu. Adding an item with no text
|
||||
// or shortcut will add a divider.
|
||||
func (c *ContextMenu) AddContextItem(text string, shortcut rune, selected func(index int)) *ContextMenu {
|
||||
func (c *ContextMenu) AddContextItem(text string, shortcut rune, selected func(index int)) {
|
||||
c.l.Lock()
|
||||
defer c.l.Unlock()
|
||||
|
||||
c.initializeList()
|
||||
|
||||
c.list.AddItem(NewListItem(text).SetShortcut(shortcut).SetSelectedFunc(c.wrap(selected)))
|
||||
item := NewListItem(text)
|
||||
item.SetShortcut(shortcut)
|
||||
item.SetSelectedFunc(c.wrap(selected))
|
||||
|
||||
c.list.AddItem(item)
|
||||
if text == "" && shortcut == 0 {
|
||||
c.list.Lock()
|
||||
index := len(c.list.items) - 1
|
||||
c.list.items[index].enabled = false
|
||||
c.list.Unlock()
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ContextMenu) wrap(f func(index int)) func() {
|
||||
|
@ -78,27 +79,24 @@ func (c *ContextMenu) wrap(f func(index int)) func() {
|
|||
}
|
||||
|
||||
// ClearContextMenu removes all items from the context menu.
|
||||
func (c *ContextMenu) ClearContextMenu() *ContextMenu {
|
||||
func (c *ContextMenu) ClearContextMenu() {
|
||||
c.l.Lock()
|
||||
defer c.l.Unlock()
|
||||
|
||||
c.initializeList()
|
||||
|
||||
c.list.Clear()
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// SetContextSelectedFunc sets the function which is called when the user
|
||||
// selects a context menu item. The function receives the item's index in the
|
||||
// menu (starting with 0), its text and its shortcut rune. SetSelectedFunc must
|
||||
// be called before the context menu is shown.
|
||||
func (c *ContextMenu) SetContextSelectedFunc(handler func(index int, text string, shortcut rune)) *ContextMenu {
|
||||
func (c *ContextMenu) SetContextSelectedFunc(handler func(index int, text string, shortcut rune)) {
|
||||
c.l.Lock()
|
||||
defer c.l.Unlock()
|
||||
|
||||
c.selected = handler
|
||||
return c
|
||||
}
|
||||
|
||||
// ShowContextMenu shows the context menu. Provide -1 for both to position on
|
||||
|
@ -158,7 +156,8 @@ func (c *ContextMenu) show(item int, x int, y int, setFocus func(Primitive)) {
|
|||
} else {
|
||||
c.l.Unlock()
|
||||
}
|
||||
}).SetDoneFunc(func() {
|
||||
})
|
||||
c.list.SetDoneFunc(func() {
|
||||
c.l.Lock()
|
||||
defer c.l.Unlock()
|
||||
|
||||
|
|
|
@ -7,11 +7,15 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
box := cview.NewBox().
|
||||
SetBorder(true).
|
||||
SetBorderAttributes(tcell.AttrBold).
|
||||
SetTitle("A [red]c[yellow]o[green]l[darkcyan]o[blue]r[darkmagenta]f[red]u[yellow]l[white] [black:red]c[:yellow]o[:green]l[:darkcyan]o[:blue]r[:darkmagenta]f[:red]u[:yellow]l[white:] [::bu]title")
|
||||
if err := cview.NewApplication().SetRoot(box, true).Run(); err != nil {
|
||||
app := cview.NewApplication()
|
||||
|
||||
box := cview.NewBox()
|
||||
box.SetBorder(true)
|
||||
box.SetBorderAttributes(tcell.AttrBold)
|
||||
box.SetTitle("A [red]c[yellow]o[green]l[darkcyan]o[blue]r[darkmagenta]f[red]u[yellow]l[white] [black:red]c[:yellow]o[:green]l[:darkcyan]o[:blue]r[:darkmagenta]f[:red]u[:yellow]l[white:] [::bu]title")
|
||||
|
||||
app.SetRoot(box, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,17 @@ import "gitlab.com/tslocum/cview"
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
button := cview.NewButton("Hit Enter to close").SetSelectedFunc(func() {
|
||||
app.EnableMouse(true)
|
||||
|
||||
button := cview.NewButton("Hit Enter to close")
|
||||
button.SetBorder(true)
|
||||
button.SetRect(0, 0, 22, 3)
|
||||
button.SetSelectedFunc(func() {
|
||||
app.Stop()
|
||||
})
|
||||
button.SetBorder(true).SetRect(0, 0, 22, 3)
|
||||
if err := app.SetRoot(button, false).EnableMouse(true).Run(); err != nil {
|
||||
|
||||
app.SetRoot(button, false)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,13 @@ import (
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
checkbox := cview.NewCheckBox().SetLabel("Hit Enter to check box: ")
|
||||
if err := app.SetRoot(checkbox, true).EnableMouse(true).Run(); err != nil {
|
||||
app.EnableMouse(true)
|
||||
|
||||
checkbox := cview.NewCheckBox()
|
||||
checkbox.SetLabel("Hit Enter to check box: ")
|
||||
|
||||
app.SetRoot(checkbox, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,19 @@ import "gitlab.com/tslocum/cview"
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
dropdown := cview.NewDropDown().
|
||||
SetLabel("Select an option (hit Enter): ").
|
||||
SetOptions(nil,
|
||||
cview.NewDropDownOption("First"),
|
||||
cview.NewDropDownOption("Second"),
|
||||
cview.NewDropDownOption("Third"),
|
||||
cview.NewDropDownOption("Fourth"),
|
||||
cview.NewDropDownOption("Fifth"))
|
||||
if err := app.SetRoot(dropdown, true).EnableMouse(true).Run(); err != nil {
|
||||
app.EnableMouse(true)
|
||||
|
||||
dropdown := cview.NewDropDown()
|
||||
dropdown.SetLabel("Select an option (hit Enter): ")
|
||||
dropdown.SetOptions(nil,
|
||||
cview.NewDropDownOption("First"),
|
||||
cview.NewDropDownOption("Second"),
|
||||
cview.NewDropDownOption("Third"),
|
||||
cview.NewDropDownOption("Fourth"),
|
||||
cview.NewDropDownOption("Fifth"))
|
||||
|
||||
app.SetRoot(dropdown, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,16 +5,30 @@ import (
|
|||
"gitlab.com/tslocum/cview"
|
||||
)
|
||||
|
||||
func demoBox(title string) *cview.Box {
|
||||
b := cview.NewBox()
|
||||
b.SetBorder(true)
|
||||
b.SetTitle(title)
|
||||
return b
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
flex := cview.NewFlex().
|
||||
AddItem(cview.NewBox().SetBorder(true).SetTitle("Left (1/2 x width of Top)"), 0, 1, false).
|
||||
AddItem(cview.NewFlex().SetDirection(cview.FlexRow).
|
||||
AddItem(cview.NewBox().SetBorder(true).SetTitle("Top"), 0, 1, false).
|
||||
AddItem(cview.NewBox().SetBorder(true).SetTitle("Middle (3 x height of Top)"), 0, 3, false).
|
||||
AddItem(cview.NewBox().SetBorder(true).SetTitle("Bottom (5 rows)"), 5, 1, false), 0, 2, false).
|
||||
AddItem(cview.NewBox().SetBorder(true).SetTitle("Right (20 cols)"), 20, 1, false)
|
||||
if err := app.SetRoot(flex, true).EnableMouse(true).Run(); err != nil {
|
||||
app.EnableMouse(true)
|
||||
|
||||
subFlex := cview.NewFlex()
|
||||
subFlex.SetDirection(cview.FlexRow)
|
||||
subFlex.AddItem(demoBox("Top"), 0, 1, false)
|
||||
subFlex.AddItem(demoBox("Middle (3 x height of Top)"), 0, 3, false)
|
||||
subFlex.AddItem(demoBox("Bottom (5 rows)"), 5, 1, false)
|
||||
|
||||
flex := cview.NewFlex()
|
||||
flex.AddItem(demoBox("Left (1/2 x width of Top)"), 0, 1, false)
|
||||
flex.AddItem(subFlex, 0, 2, false)
|
||||
flex.AddItem(demoBox("Right (20 cols)"), 20, 1, false)
|
||||
|
||||
app.SetRoot(flex, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,22 +7,29 @@ import (
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
form := cview.NewForm().
|
||||
AddDropDownSimple("Title", 0, nil, "Mr.", "Ms.", "Mrs.", "Dr.", "Prof.").
|
||||
AddInputField("First name", "", 20, nil, nil).
|
||||
AddInputField("Last name", "", 20, nil, nil).
|
||||
AddFormItem(cview.NewInputField().
|
||||
SetLabel("Address").
|
||||
SetFieldWidth(30).
|
||||
SetFieldNote("Your complete address")).
|
||||
AddPasswordField("Password", "", 10, '*', nil).
|
||||
AddCheckBox("", "Age 18+", false, nil).
|
||||
AddButton("Save", nil).
|
||||
AddButton("Quit", func() {
|
||||
app.Stop()
|
||||
})
|
||||
form.SetBorder(true).SetTitle("Enter some data").SetTitleAlign(cview.AlignLeft)
|
||||
if err := app.SetRoot(form, true).EnableMouse(true).Run(); err != nil {
|
||||
app.EnableMouse(true)
|
||||
|
||||
form := cview.NewForm()
|
||||
form.AddDropDownSimple("Title", 0, nil, "Mr.", "Ms.", "Mrs.", "Dr.", "Prof.")
|
||||
form.AddInputField("First name", "", 20, nil, nil)
|
||||
form.AddInputField("Last name", "", 20, nil, nil)
|
||||
addressField := cview.NewInputField()
|
||||
addressField.SetLabel("Address")
|
||||
addressField.SetFieldWidth(30)
|
||||
addressField.SetFieldNote("Your complete address")
|
||||
form.AddFormItem(addressField)
|
||||
form.AddPasswordField("Password", "", 10, '*', nil)
|
||||
form.AddCheckBox("", "Age 18+", false, nil)
|
||||
form.AddButton("Save", nil)
|
||||
form.AddButton("Quit", func() {
|
||||
app.Stop()
|
||||
})
|
||||
form.SetBorder(true)
|
||||
form.SetTitle("Enter some data")
|
||||
form.SetTitleAlign(cview.AlignLeft)
|
||||
|
||||
app.SetRoot(form, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,15 +8,22 @@ import (
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
frame := cview.NewFrame(cview.NewBox().SetBackgroundColor(tcell.ColorBlue.TrueColor())).
|
||||
SetBorders(2, 2, 2, 2, 4, 4).
|
||||
AddText("Header left", true, cview.AlignLeft, tcell.ColorWhite.TrueColor()).
|
||||
AddText("Header middle", true, cview.AlignCenter, tcell.ColorWhite.TrueColor()).
|
||||
AddText("Header right", true, cview.AlignRight, tcell.ColorWhite.TrueColor()).
|
||||
AddText("Header second middle", true, cview.AlignCenter, tcell.ColorRed.TrueColor()).
|
||||
AddText("Footer middle", false, cview.AlignCenter, tcell.ColorGreen.TrueColor()).
|
||||
AddText("Footer second middle", false, cview.AlignCenter, tcell.ColorGreen.TrueColor())
|
||||
if err := app.SetRoot(frame, true).EnableMouse(true).Run(); err != nil {
|
||||
app.EnableMouse(true)
|
||||
|
||||
box := cview.NewBox()
|
||||
box.SetBackgroundColor(tcell.ColorBlue.TrueColor())
|
||||
|
||||
frame := cview.NewFrame(box)
|
||||
frame.SetBorders(2, 2, 2, 2, 4, 4)
|
||||
frame.AddText("Header left", true, cview.AlignLeft, tcell.ColorWhite.TrueColor())
|
||||
frame.AddText("Header middle", true, cview.AlignCenter, tcell.ColorWhite.TrueColor())
|
||||
frame.AddText("Header right", true, cview.AlignRight, tcell.ColorWhite.TrueColor())
|
||||
frame.AddText("Header second middle", true, cview.AlignCenter, tcell.ColorRed.TrueColor())
|
||||
frame.AddText("Footer middle", false, cview.AlignCenter, tcell.ColorGreen.TrueColor())
|
||||
frame.AddText("Footer second middle", false, cview.AlignCenter, tcell.ColorGreen.TrueColor())
|
||||
|
||||
app.SetRoot(frame, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,33 +6,38 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
app.EnableMouse(true)
|
||||
|
||||
newPrimitive := func(text string) cview.Primitive {
|
||||
return cview.NewTextView().
|
||||
SetTextAlign(cview.AlignCenter).
|
||||
SetText(text)
|
||||
tv := cview.NewTextView()
|
||||
tv.SetTextAlign(cview.AlignCenter)
|
||||
tv.SetText(text)
|
||||
return tv
|
||||
}
|
||||
menu := newPrimitive("Menu")
|
||||
main := newPrimitive("Main content")
|
||||
sideBar := newPrimitive("Side Bar")
|
||||
|
||||
grid := cview.NewGrid().
|
||||
SetRows(3, 0, 3).
|
||||
SetColumns(30, 0, 30).
|
||||
SetBorders(true).
|
||||
AddItem(newPrimitive("Header"), 0, 0, 1, 3, 0, 0, false).
|
||||
AddItem(newPrimitive("Footer"), 2, 0, 1, 3, 0, 0, false)
|
||||
grid := cview.NewGrid()
|
||||
grid.SetRows(3, 0, 3)
|
||||
grid.SetColumns(30, 0, 30)
|
||||
grid.SetBorders(true)
|
||||
grid.AddItem(newPrimitive("Header"), 0, 0, 1, 3, 0, 0, false)
|
||||
grid.AddItem(newPrimitive("Footer"), 2, 0, 1, 3, 0, 0, false)
|
||||
|
||||
// Layout for screens narrower than 100 cells (menu and side bar are hidden).
|
||||
grid.AddItem(menu, 0, 0, 0, 0, 0, 0, false).
|
||||
AddItem(main, 1, 0, 1, 3, 0, 0, false).
|
||||
AddItem(sideBar, 0, 0, 0, 0, 0, 0, false)
|
||||
grid.AddItem(menu, 0, 0, 0, 0, 0, 0, false)
|
||||
grid.AddItem(main, 1, 0, 1, 3, 0, 0, false)
|
||||
grid.AddItem(sideBar, 0, 0, 0, 0, 0, 0, false)
|
||||
|
||||
// Layout for screens wider than 100 cells.
|
||||
grid.AddItem(menu, 1, 0, 1, 1, 0, 100, false).
|
||||
AddItem(main, 1, 1, 1, 1, 0, 100, false).
|
||||
AddItem(sideBar, 1, 2, 1, 1, 0, 100, false)
|
||||
grid.AddItem(menu, 1, 0, 1, 1, 0, 100, false)
|
||||
grid.AddItem(main, 1, 1, 1, 1, 0, 100, false)
|
||||
grid.AddItem(sideBar, 1, 2, 1, 1, 0, 100, false)
|
||||
|
||||
if err := cview.NewApplication().SetRoot(grid, true).EnableMouse(true).Run(); err != nil {
|
||||
app.SetRoot(grid, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -17,12 +17,12 @@ type company struct {
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
inputField := cview.NewInputField().
|
||||
SetLabel("Enter a company name: ").
|
||||
SetFieldWidth(30).
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
app.Stop()
|
||||
})
|
||||
inputField := cview.NewInputField()
|
||||
inputField.SetLabel("Enter a company name: ")
|
||||
inputField.SetFieldWidth(30)
|
||||
inputField.SetDoneFunc(func(key tcell.Key) {
|
||||
app.Stop()
|
||||
})
|
||||
|
||||
// Set up autocomplete function.
|
||||
var mutex sync.RWMutex
|
||||
|
@ -75,7 +75,8 @@ func main() {
|
|||
return nil
|
||||
})
|
||||
|
||||
if err := app.SetRoot(inputField, true).Run(); err != nil {
|
||||
app.SetRoot(inputField, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,15 +8,19 @@ import (
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
inputField := cview.NewInputField().
|
||||
SetLabel("Enter a number: ").
|
||||
SetPlaceholder("E.g. 1234").
|
||||
SetFieldWidth(10).
|
||||
SetAcceptanceFunc(cview.InputFieldInteger).
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
app.Stop()
|
||||
})
|
||||
if err := app.SetRoot(inputField, true).EnableMouse(true).Run(); err != nil {
|
||||
app.EnableMouse(true)
|
||||
|
||||
inputField := cview.NewInputField()
|
||||
inputField.SetLabel("Enter a number: ")
|
||||
inputField.SetPlaceholder("E.g. 1234")
|
||||
inputField.SetFieldWidth(10)
|
||||
inputField.SetAcceptanceFunc(cview.InputFieldInteger)
|
||||
inputField.SetDoneFunc(func(key tcell.Key) {
|
||||
app.Stop()
|
||||
})
|
||||
|
||||
app.SetRoot(inputField, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,23 +2,32 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitlab.com/tslocum/cview"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
app.EnableMouse(true)
|
||||
|
||||
list := cview.NewList()
|
||||
|
||||
reset := func() {
|
||||
list.
|
||||
Clear().
|
||||
AddItem(cview.NewListItem("List item 1").SetSecondaryText("Some explanatory text").SetShortcut('a')).
|
||||
AddItem(cview.NewListItem("List item 2").SetSecondaryText("Some explanatory text").SetShortcut('b')).
|
||||
AddItem(cview.NewListItem("List item 3").SetSecondaryText("Some explanatory text").SetShortcut('c')).
|
||||
AddItem(cview.NewListItem("List item 4").SetSecondaryText("Some explanatory text").SetShortcut('d')).
|
||||
AddItem(cview.NewListItem("Quit").SetSecondaryText("Press to exit").SetShortcut('q').SetSelectedFunc(func() {
|
||||
app.Stop()
|
||||
}))
|
||||
list.Clear()
|
||||
for i := 0; i < 4; i++ {
|
||||
item := cview.NewListItem(fmt.Sprintf("List item %d", i+1))
|
||||
item.SetSecondaryText("Some explanatory text")
|
||||
item.SetShortcut(rune('a' + i))
|
||||
list.AddItem(item)
|
||||
}
|
||||
quitItem := cview.NewListItem("Quit")
|
||||
quitItem.SetSecondaryText("Press to exit")
|
||||
quitItem.SetShortcut('q')
|
||||
quitItem.SetSelectedFunc(func() {
|
||||
app.Stop()
|
||||
})
|
||||
list.AddItem(quitItem)
|
||||
|
||||
list.ContextMenuList().SetItemEnabled(3, false)
|
||||
}
|
||||
|
@ -52,7 +61,8 @@ func main() {
|
|||
})
|
||||
|
||||
reset()
|
||||
if err := app.SetRoot(list, true).EnableMouse(true).Run(); err != nil {
|
||||
app.SetRoot(list, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,15 +7,19 @@ import (
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
modal := cview.NewModal().
|
||||
SetText("Do you want to quit the application?").
|
||||
AddButtons([]string{"Quit", "Cancel"}).
|
||||
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
if buttonLabel == "Quit" {
|
||||
app.Stop()
|
||||
}
|
||||
})
|
||||
if err := app.SetRoot(modal, false).EnableMouse(true).Run(); err != nil {
|
||||
app.EnableMouse(true)
|
||||
|
||||
modal := cview.NewModal()
|
||||
modal.SetText("Do you want to quit the application?")
|
||||
modal.AddButtons([]string{"Quit", "Cancel"})
|
||||
modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
if buttonLabel == "Quit" {
|
||||
app.Stop()
|
||||
}
|
||||
})
|
||||
|
||||
app.SetRoot(modal, false)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,25 +11,28 @@ const pageCount = 5
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
app.EnableMouse(true)
|
||||
|
||||
pages := cview.NewPages()
|
||||
for page := 0; page < pageCount; page++ {
|
||||
func(page int) {
|
||||
pages.AddPage(fmt.Sprintf("page-%d", page),
|
||||
cview.NewModal().
|
||||
SetText(fmt.Sprintf("This is page %d. Choose where to go next.", page+1)).
|
||||
AddButtons([]string{"Next", "Quit"}).
|
||||
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
if buttonIndex == 0 {
|
||||
pages.SwitchToPage(fmt.Sprintf("page-%d", (page+1)%pageCount))
|
||||
} else {
|
||||
app.Stop()
|
||||
}
|
||||
}),
|
||||
false,
|
||||
page == 0)
|
||||
modal := cview.NewModal()
|
||||
modal.SetText(fmt.Sprintf("This is page %d. Choose where to go next.", page+1))
|
||||
modal.AddButtons([]string{"Next", "Quit"})
|
||||
modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
if buttonIndex == 0 {
|
||||
pages.SwitchToPage(fmt.Sprintf("page-%d", (page+1)%pageCount))
|
||||
} else {
|
||||
app.Stop()
|
||||
}
|
||||
})
|
||||
|
||||
pages.AddPage(fmt.Sprintf("page-%d", page), modal, false, page == 0)
|
||||
}(page)
|
||||
}
|
||||
if err := app.SetRoot(pages, true).EnableMouse(true).Run(); err != nil {
|
||||
|
||||
app.SetRoot(pages, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,16 @@ import "gitlab.com/tslocum/cview"
|
|||
// Center returns a new primitive which shows the provided primitive in its
|
||||
// center, given the provided primitive's size.
|
||||
func Center(width, height int, p cview.Primitive) cview.Primitive {
|
||||
return cview.NewFlex().
|
||||
AddItem(cview.NewBox(), 0, 1, false).
|
||||
AddItem(cview.NewFlex().
|
||||
SetDirection(cview.FlexRow).
|
||||
AddItem(cview.NewBox(), 0, 1, false).
|
||||
AddItem(p, height, 1, true).
|
||||
AddItem(cview.NewBox(), 0, 1, false), width, 1, true).
|
||||
AddItem(cview.NewBox(), 0, 1, false)
|
||||
subFlex := cview.NewFlex()
|
||||
subFlex.SetDirection(cview.FlexRow)
|
||||
subFlex.AddItem(cview.NewBox(), 0, 1, false)
|
||||
subFlex.AddItem(p, height, 1, true)
|
||||
subFlex.AddItem(cview.NewBox(), 0, 1, false)
|
||||
|
||||
flex := cview.NewFlex()
|
||||
flex.AddItem(cview.NewBox(), 0, 1, false)
|
||||
flex.AddItem(subFlex, width, 1, true)
|
||||
flex.AddItem(cview.NewBox(), 0, 1, false)
|
||||
|
||||
return flex
|
||||
}
|
||||
|
|
|
@ -13,13 +13,14 @@ const codeWidth = 56
|
|||
// size) on the left side and its source code on the right side.
|
||||
func Code(p cview.Primitive, width, height int, code string) cview.Primitive {
|
||||
// Set up code view.
|
||||
codeView := cview.NewTextView().
|
||||
SetWrap(false).
|
||||
SetDynamicColors(true)
|
||||
codeView := cview.NewTextView()
|
||||
codeView.SetWrap(false)
|
||||
codeView.SetDynamicColors(true)
|
||||
codeView.SetBorderPadding(1, 1, 2, 0)
|
||||
fmt.Fprint(codeView, code)
|
||||
|
||||
return cview.NewFlex().
|
||||
AddItem(Center(width, height, p), 0, 1, true).
|
||||
AddItem(codeView, codeWidth, 1, false)
|
||||
f := cview.NewFlex()
|
||||
f.AddItem(Center(width, height, p), 0, 1, true)
|
||||
f.AddItem(codeView, codeWidth, 1, false)
|
||||
return f
|
||||
}
|
||||
|
|
|
@ -19,15 +19,15 @@ The [black:red]tags [black:green]look [black:yellow]like [::u]this:
|
|||
|
||||
// Colors demonstrates how to use colors.
|
||||
func Colors(nextSlide func()) (title string, content cview.Primitive) {
|
||||
tv := cview.NewTextView().
|
||||
SetWordWrap(true).
|
||||
SetDynamicColors(true).
|
||||
SetText(colorsText).
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
nextSlide()
|
||||
})
|
||||
tv.
|
||||
SetBorder(true).
|
||||
SetTitle("A [red]c[yellow]o[green]l[darkcyan]o[blue]r[darkmagenta]f[red]u[yellow]l[white] [black:red]c[:yellow]o[:green]l[:darkcyan]o[:blue]r[:darkmagenta]f[:red]u[:yellow]l[white:] [::bu]title")
|
||||
tv := cview.NewTextView()
|
||||
tv.SetBorder(true)
|
||||
tv.SetTitle("A [red]c[yellow]o[green]l[darkcyan]o[blue]r[darkmagenta]f[red]u[yellow]l[white] [black:red]c[:yellow]o[:green]l[:darkcyan]o[:blue]r[:darkmagenta]f[:red]u[:yellow]l[white:] [::bu]title")
|
||||
tv.SetDynamicColors(true)
|
||||
tv.SetWordWrap(true)
|
||||
tv.SetText(colorsText)
|
||||
tv.SetDoneFunc(func(key tcell.Key) {
|
||||
nextSlide()
|
||||
})
|
||||
|
||||
return "Colors", Center(44, 16, tv)
|
||||
}
|
||||
|
|
|
@ -33,30 +33,32 @@ func Cover(nextSlide func()) (title string, content cview.Primitive) {
|
|||
logoWidth = len(line)
|
||||
}
|
||||
}
|
||||
logoBox := cview.NewTextView().
|
||||
SetTextColor(tcell.ColorGreen.TrueColor()).
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
nextSlide()
|
||||
})
|
||||
logoBox := cview.NewTextView()
|
||||
logoBox.SetTextColor(tcell.ColorGreen.TrueColor())
|
||||
logoBox.SetDoneFunc(func(key tcell.Key) {
|
||||
nextSlide()
|
||||
})
|
||||
fmt.Fprint(logoBox, logo)
|
||||
|
||||
// Create a frame for the subtitle and navigation infos.
|
||||
frame := cview.NewFrame(cview.NewBox()).
|
||||
SetBorders(0, 0, 0, 0, 0, 0).
|
||||
AddText(subtitle, true, cview.AlignCenter, tcell.ColorWhite.TrueColor()).
|
||||
AddText("", true, cview.AlignCenter, tcell.ColorWhite.TrueColor()).
|
||||
AddText(mouse, true, cview.AlignCenter, tcell.ColorDarkMagenta.TrueColor()).
|
||||
AddText(navigation, true, cview.AlignCenter, tcell.ColorDarkMagenta.TrueColor())
|
||||
frame := cview.NewFrame(cview.NewBox())
|
||||
frame.SetBorders(0, 0, 0, 0, 0, 0)
|
||||
frame.AddText(subtitle, true, cview.AlignCenter, tcell.ColorWhite.TrueColor())
|
||||
frame.AddText("", true, cview.AlignCenter, tcell.ColorWhite.TrueColor())
|
||||
frame.AddText(mouse, true, cview.AlignCenter, tcell.ColorDarkMagenta.TrueColor())
|
||||
frame.AddText(navigation, true, cview.AlignCenter, tcell.ColorDarkMagenta.TrueColor())
|
||||
|
||||
// Create a Flex layout that centers the logo and subtitle.
|
||||
flex := cview.NewFlex().
|
||||
SetDirection(cview.FlexRow).
|
||||
AddItem(cview.NewBox(), 0, 7, false).
|
||||
AddItem(cview.NewFlex().
|
||||
AddItem(cview.NewBox(), 0, 1, false).
|
||||
AddItem(logoBox, logoWidth, 1, true).
|
||||
AddItem(cview.NewBox(), 0, 1, false), logoHeight, 1, true).
|
||||
AddItem(frame, 0, 10, false)
|
||||
subFlex := cview.NewFlex()
|
||||
subFlex.AddItem(cview.NewBox(), 0, 1, false)
|
||||
subFlex.AddItem(logoBox, logoWidth, 1, true)
|
||||
subFlex.AddItem(cview.NewBox(), 0, 1, false)
|
||||
|
||||
flex := cview.NewFlex()
|
||||
flex.SetDirection(cview.FlexRow)
|
||||
flex.AddItem(cview.NewBox(), 0, 7, false)
|
||||
flex.AddItem(subFlex, logoHeight, 1, true)
|
||||
flex.AddItem(frame, 0, 10, false)
|
||||
|
||||
return "Start", flex
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@ import (
|
|||
|
||||
// End shows the final slide.
|
||||
func End(nextSlide func()) (title string, content cview.Primitive) {
|
||||
textView := cview.NewTextView().SetDoneFunc(func(key tcell.Key) {
|
||||
textView := cview.NewTextView()
|
||||
textView.SetDoneFunc(func(key tcell.Key) {
|
||||
nextSlide()
|
||||
})
|
||||
url := "https://gitlab.com/tslocum/cview"
|
||||
|
|
|
@ -5,35 +5,50 @@ import (
|
|||
"gitlab.com/tslocum/cview"
|
||||
)
|
||||
|
||||
func demoBox(title string) *cview.Box {
|
||||
b := cview.NewBox()
|
||||
b.SetBorder(true)
|
||||
b.SetTitle(title)
|
||||
return b
|
||||
}
|
||||
|
||||
// Flex demonstrates flexbox layout.
|
||||
func Flex(nextSlide func()) (title string, content cview.Primitive) {
|
||||
modalShown := false
|
||||
pages := cview.NewPages()
|
||||
textView := cview.NewTextView().
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
if modalShown {
|
||||
nextSlide()
|
||||
modalShown = false
|
||||
} else {
|
||||
pages.ShowPage("modal")
|
||||
modalShown = true
|
||||
}
|
||||
})
|
||||
textView.SetBorder(true).SetTitle("Flexible width, twice of middle column")
|
||||
flex := cview.NewFlex().
|
||||
AddItem(textView, 0, 2, true).
|
||||
AddItem(cview.NewFlex().
|
||||
SetDirection(cview.FlexRow).
|
||||
AddItem(cview.NewBox().SetBorder(true).SetTitle("Flexible width"), 0, 1, false).
|
||||
AddItem(cview.NewBox().SetBorder(true).SetTitle("Fixed height"), 15, 1, false).
|
||||
AddItem(cview.NewBox().SetBorder(true).SetTitle("Flexible height"), 0, 1, false), 0, 1, false).
|
||||
AddItem(cview.NewBox().SetBorder(true).SetTitle("Fixed width"), 30, 1, false)
|
||||
modal := cview.NewModal().
|
||||
SetText("Resize the window to see the effect of the flexbox parameters").
|
||||
AddButtons([]string{"Ok"}).SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
|
||||
textView := cview.NewTextView()
|
||||
textView.SetBorder(true)
|
||||
textView.SetTitle("Flexible width, twice of middle column")
|
||||
textView.SetDoneFunc(func(key tcell.Key) {
|
||||
if modalShown {
|
||||
nextSlide()
|
||||
modalShown = false
|
||||
} else {
|
||||
pages.ShowPage("modal")
|
||||
modalShown = true
|
||||
}
|
||||
})
|
||||
|
||||
subFlex := cview.NewFlex()
|
||||
subFlex.SetDirection(cview.FlexRow)
|
||||
subFlex.AddItem(demoBox("Flexible width"), 0, 1, false)
|
||||
subFlex.AddItem(demoBox("Fixed height"), 15, 1, false)
|
||||
subFlex.AddItem(demoBox("Flexible height"), 0, 1, false)
|
||||
|
||||
flex := cview.NewFlex()
|
||||
flex.AddItem(textView, 0, 2, true)
|
||||
flex.AddItem(subFlex, 0, 1, false)
|
||||
flex.AddItem(demoBox("Fixed width"), 30, 1, false)
|
||||
|
||||
modal := cview.NewModal()
|
||||
modal.SetText("Resize the window to see the effect of the flexbox parameters")
|
||||
modal.AddButtons([]string{"Ok"})
|
||||
modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
pages.HidePage("modal")
|
||||
})
|
||||
pages.AddPage("flex", flex, true, true).
|
||||
AddPage("modal", modal, false, false)
|
||||
|
||||
pages.AddPage("flex", flex, true, true)
|
||||
pages.AddPage("modal", modal, false, false)
|
||||
return "Flex", pages
|
||||
}
|
||||
|
|
|
@ -30,14 +30,15 @@ const form = `[green]package[white] main
|
|||
|
||||
// Form demonstrates forms.
|
||||
func Form(nextSlide func()) (title string, content cview.Primitive) {
|
||||
f := cview.NewForm().
|
||||
AddInputField("First name:", "", 20, nil, nil).
|
||||
AddInputField("Last name:", "", 20, nil, nil).
|
||||
AddDropDownSimple("Role:", 0, nil, "Engineer", "Manager", "Administration").
|
||||
AddPasswordField("Password:", "", 10, '*', nil).
|
||||
AddCheckBox("", "On vacation", false, nil).
|
||||
AddButton("Save", nextSlide).
|
||||
AddButton("Cancel", nextSlide)
|
||||
f.SetBorder(true).SetTitle("Employee Information")
|
||||
f := cview.NewForm()
|
||||
f.AddInputField("First name:", "", 20, nil, nil)
|
||||
f.AddInputField("Last name:", "", 20, nil, nil)
|
||||
f.AddDropDownSimple("Role:", 0, nil, "Engineer", "Manager", "Administration")
|
||||
f.AddPasswordField("Password:", "", 10, '*', nil)
|
||||
f.AddCheckBox("", "On vacation", false, nil)
|
||||
f.AddButton("Save", nextSlide)
|
||||
f.AddButton("Cancel", nextSlide)
|
||||
f.SetBorder(true)
|
||||
f.SetTitle("Employee Information")
|
||||
return "Forms", Code(f, 36, 15, form)
|
||||
}
|
||||
|
|
|
@ -11,49 +11,51 @@ func Grid(nextSlide func()) (title string, content cview.Primitive) {
|
|||
pages := cview.NewPages()
|
||||
|
||||
newPrimitive := func(text string) cview.Primitive {
|
||||
return cview.NewTextView().
|
||||
SetTextAlign(cview.AlignCenter).
|
||||
SetText(text).
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
if modalShown {
|
||||
nextSlide()
|
||||
modalShown = false
|
||||
} else {
|
||||
pages.ShowPage("modal")
|
||||
modalShown = true
|
||||
}
|
||||
})
|
||||
tv := cview.NewTextView()
|
||||
tv.SetTextAlign(cview.AlignCenter)
|
||||
tv.SetText(text)
|
||||
tv.SetDoneFunc(func(key tcell.Key) {
|
||||
if modalShown {
|
||||
nextSlide()
|
||||
modalShown = false
|
||||
} else {
|
||||
pages.ShowPage("modal")
|
||||
modalShown = true
|
||||
}
|
||||
})
|
||||
return tv
|
||||
}
|
||||
|
||||
menu := newPrimitive("Menu")
|
||||
main := newPrimitive("Main content")
|
||||
sideBar := newPrimitive("Side Bar")
|
||||
|
||||
grid := cview.NewGrid().
|
||||
SetRows(3, 0, 3).
|
||||
SetColumns(0, -4, 0).
|
||||
SetBorders(true).
|
||||
AddItem(newPrimitive("Header"), 0, 0, 1, 3, 0, 0, true).
|
||||
AddItem(newPrimitive("Footer"), 2, 0, 1, 3, 0, 0, false)
|
||||
grid := cview.NewGrid()
|
||||
grid.SetRows(3, 0, 3)
|
||||
grid.SetColumns(0, -4, 0)
|
||||
grid.SetBorders(true)
|
||||
grid.AddItem(newPrimitive("Header"), 0, 0, 1, 3, 0, 0, true)
|
||||
grid.AddItem(newPrimitive("Footer"), 2, 0, 1, 3, 0, 0, false)
|
||||
|
||||
// Layout for screens narrower than 100 cells (menu and side bar are hidden).
|
||||
grid.AddItem(menu, 0, 0, 0, 0, 0, 0, false).
|
||||
AddItem(main, 1, 0, 1, 3, 0, 0, false).
|
||||
AddItem(sideBar, 0, 0, 0, 0, 0, 0, false)
|
||||
grid.AddItem(menu, 0, 0, 0, 0, 0, 0, false)
|
||||
grid.AddItem(main, 1, 0, 1, 3, 0, 0, false)
|
||||
grid.AddItem(sideBar, 0, 0, 0, 0, 0, 0, false)
|
||||
|
||||
// Layout for screens wider than 100 cells.
|
||||
grid.AddItem(menu, 1, 0, 1, 1, 0, 100, false).
|
||||
AddItem(main, 1, 1, 1, 1, 0, 100, false).
|
||||
AddItem(sideBar, 1, 2, 1, 1, 0, 100, false)
|
||||
grid.AddItem(menu, 1, 0, 1, 1, 0, 100, false)
|
||||
grid.AddItem(main, 1, 1, 1, 1, 0, 100, false)
|
||||
grid.AddItem(sideBar, 1, 2, 1, 1, 0, 100, false)
|
||||
|
||||
modal := cview.NewModal().
|
||||
SetText("Resize the window to see how the grid layout adapts").
|
||||
AddButtons([]string{"Ok"}).SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
modal := cview.NewModal()
|
||||
modal.SetText("Resize the window to see how the grid layout adapts")
|
||||
modal.AddButtons([]string{"Ok"})
|
||||
modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
pages.HidePage("modal")
|
||||
})
|
||||
|
||||
pages.AddPage("grid", grid, true, true).
|
||||
AddPage("modal", modal, false, false)
|
||||
pages.AddPage("grid", grid, true, true)
|
||||
pages.AddPage("modal", modal, false, false)
|
||||
|
||||
return "Grid", pages
|
||||
}
|
||||
|
|
|
@ -31,9 +31,10 @@ const inputField = `[green]package[white] main
|
|||
|
||||
// InputField demonstrates the InputField.
|
||||
func InputField(nextSlide func()) (title string, content cview.Primitive) {
|
||||
input := cview.NewInputField().
|
||||
SetLabel("Enter a number: ").
|
||||
SetAcceptanceFunc(cview.InputFieldInteger).SetDoneFunc(func(key tcell.Key) {
|
||||
input := cview.NewInputField()
|
||||
input.SetLabel("Enter a number: ")
|
||||
input.SetAcceptanceFunc(cview.InputFieldInteger)
|
||||
input.SetDoneFunc(func(key tcell.Key) {
|
||||
nextSlide()
|
||||
})
|
||||
return "Input", Code(input, 30, 1, inputField)
|
||||
|
|
|
@ -6,15 +6,25 @@ import "gitlab.com/tslocum/cview"
|
|||
func Introduction(nextSlide func()) (title string, content cview.Primitive) {
|
||||
list := cview.NewList()
|
||||
|
||||
listText := [][]string{
|
||||
{"A Go package for terminal based UIs", "with a special focus on rich interactive widgets"},
|
||||
{"Based on github.com/gdamore/tcell", "Like termbox but better (see tcell docs)"},
|
||||
{"Designed to be simple", `"Hello world" is 5 lines of code`},
|
||||
{"Good for data entry", `For charts, use "termui" - for low-level views, use "gocui" - ...`},
|
||||
{"Supports context menus", "Right click on one of these items or press Alt+Enter"},
|
||||
{"Extensive documentation", "Demo code is available for each widget"},
|
||||
}
|
||||
|
||||
reset := func() {
|
||||
list.
|
||||
Clear().
|
||||
AddItem(cview.NewListItem("A Go package for terminal based UIs").SetSecondaryText("with a special focus on rich interactive widgets").SetShortcut('1').SetSelectedFunc(nextSlide)).
|
||||
AddItem(cview.NewListItem("Based on github.com/gdamore/tcell").SetSecondaryText("Like termbox but better (see tcell docs)").SetShortcut('2').SetSelectedFunc(nextSlide)).
|
||||
AddItem(cview.NewListItem("Designed to be simple").SetSecondaryText(`"Hello world" is 5 lines of code`).SetShortcut('3').SetSelectedFunc(nextSlide)).
|
||||
AddItem(cview.NewListItem("Good for data entry").SetSecondaryText(`For charts, use "termui" - for low-level views, use "gocui" - ...`).SetShortcut('4').SetSelectedFunc(nextSlide)).
|
||||
AddItem(cview.NewListItem("Supports context menus").SetSecondaryText("Right click on one of these items or press Alt+Enter").SetShortcut('5').SetSelectedFunc(nextSlide)).
|
||||
AddItem(cview.NewListItem("Extensive documentation").SetSecondaryText("Demo code is available for each widget").SetShortcut('6').SetSelectedFunc(nextSlide))
|
||||
list.Clear()
|
||||
|
||||
for i, itemText := range listText {
|
||||
item := cview.NewListItem(itemText[0])
|
||||
item.SetSecondaryText(itemText[1])
|
||||
item.SetShortcut(rune('1' + i))
|
||||
item.SetSelectedFunc(nextSlide)
|
||||
list.AddItem(item)
|
||||
}
|
||||
|
||||
list.ContextMenuList().SetItemEnabled(3, false)
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ func main() {
|
|||
}()
|
||||
}
|
||||
|
||||
app.EnableMouse(true)
|
||||
|
||||
// The presentation slides.
|
||||
slides := []Slide{
|
||||
Cover,
|
||||
|
@ -66,25 +68,25 @@ func main() {
|
|||
// The bottom row has some info on where we are.
|
||||
info := cview.NewTextView()
|
||||
info.
|
||||
SetDynamicColors(true).
|
||||
SetRegions(true).
|
||||
SetWrap(false).
|
||||
SetHighlightedFunc(func(added, removed, remaining []string) {
|
||||
pages.SwitchToPage(added[0])
|
||||
})
|
||||
SetDynamicColors(true)
|
||||
info.SetRegions(true)
|
||||
info.SetWrap(false)
|
||||
info.SetHighlightedFunc(func(added, removed, remaining []string) {
|
||||
pages.SwitchToPage(added[0])
|
||||
})
|
||||
|
||||
// Create the pages for all slides.
|
||||
previousSlide := func() {
|
||||
slide, _ := strconv.Atoi(info.GetHighlights()[0])
|
||||
slide = (slide - 1 + len(slides)) % len(slides)
|
||||
info.Highlight(strconv.Itoa(slide)).
|
||||
ScrollToHighlight()
|
||||
info.Highlight(strconv.Itoa(slide))
|
||||
info.ScrollToHighlight()
|
||||
}
|
||||
nextSlide := func() {
|
||||
slide, _ := strconv.Atoi(info.GetHighlights()[0])
|
||||
slide = (slide + 1) % len(slides)
|
||||
info.Highlight(strconv.Itoa(slide)).
|
||||
ScrollToHighlight()
|
||||
info.Highlight(strconv.Itoa(slide))
|
||||
info.ScrollToHighlight()
|
||||
}
|
||||
|
||||
cursor := 0
|
||||
|
@ -101,10 +103,10 @@ func main() {
|
|||
info.Highlight("0")
|
||||
|
||||
// Create the main layout.
|
||||
layout := cview.NewFlex().
|
||||
SetDirection(cview.FlexRow).
|
||||
AddItem(pages, 0, 1, true).
|
||||
AddItem(info, 1, 1, false)
|
||||
layout := cview.NewFlex()
|
||||
layout.SetDirection(cview.FlexRow)
|
||||
layout.AddItem(pages, 0, 1, true)
|
||||
layout.AddItem(info, 1, 1, false)
|
||||
|
||||
// Shortcuts to navigate the slides.
|
||||
app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
|
@ -117,7 +119,8 @@ func main() {
|
|||
})
|
||||
|
||||
// Start the application.
|
||||
if err := app.SetRoot(layout, true).EnableMouse(true).Run(); err != nil {
|
||||
app.SetRoot(layout, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,8 +249,8 @@ const tableSelectCell = `[green]func[white] [yellow]main[white]() {
|
|||
|
||||
// Table demonstrates the Table.
|
||||
func Table(nextSlide func()) (title string, content cview.Primitive) {
|
||||
table := cview.NewTable().
|
||||
SetFixed(1, 1)
|
||||
table := cview.NewTable()
|
||||
table.SetFixed(1, 1)
|
||||
for row, line := range strings.Split(tableData, "\n") {
|
||||
for column, cell := range strings.Split(line, "|") {
|
||||
color := tcell.ColorWhite.TrueColor()
|
||||
|
@ -265,68 +265,69 @@ func Table(nextSlide func()) (title string, content cview.Primitive) {
|
|||
} else if column == 0 || column >= 4 {
|
||||
align = cview.AlignRight
|
||||
}
|
||||
tableCell := cview.NewTableCell(cell).
|
||||
SetTextColor(color).
|
||||
SetAlign(align).
|
||||
SetSelectable(row != 0 && column != 0)
|
||||
tableCell := cview.NewTableCell(cell)
|
||||
tableCell.SetTextColor(color)
|
||||
tableCell.SetAlign(align)
|
||||
tableCell.SetSelectable(row != 0 && column != 0)
|
||||
if column >= 1 && column <= 3 {
|
||||
tableCell.SetExpansion(1)
|
||||
}
|
||||
table.SetCell(row, column, tableCell)
|
||||
}
|
||||
}
|
||||
table.SetBorder(true).SetTitle("Table")
|
||||
table.SetBorder(true)
|
||||
table.SetTitle("Table")
|
||||
|
||||
code := cview.NewTextView().
|
||||
SetWrap(false).
|
||||
SetDynamicColors(true)
|
||||
code := cview.NewTextView()
|
||||
code.SetWrap(false)
|
||||
code.SetDynamicColors(true)
|
||||
code.SetBorderPadding(1, 1, 2, 0)
|
||||
|
||||
list := cview.NewList()
|
||||
|
||||
basic := func() {
|
||||
table.SetBorders(false).
|
||||
SetSelectable(false, false).
|
||||
SetSeparator(' ')
|
||||
table.SetBorders(false)
|
||||
table.SetSelectable(false, false)
|
||||
table.SetSeparator(' ')
|
||||
code.Clear()
|
||||
fmt.Fprint(code, tableBasic)
|
||||
}
|
||||
|
||||
separator := func() {
|
||||
table.SetBorders(false).
|
||||
SetSelectable(false, false).
|
||||
SetSeparator(cview.Borders.Vertical)
|
||||
table.SetBorders(false)
|
||||
table.SetSelectable(false, false)
|
||||
table.SetSeparator(cview.Borders.Vertical)
|
||||
code.Clear()
|
||||
fmt.Fprint(code, tableSeparator)
|
||||
}
|
||||
|
||||
borders := func() {
|
||||
table.SetBorders(true).
|
||||
SetSelectable(false, false)
|
||||
table.SetBorders(true)
|
||||
table.SetSelectable(false, false)
|
||||
code.Clear()
|
||||
fmt.Fprint(code, tableBorders)
|
||||
}
|
||||
|
||||
selectRow := func() {
|
||||
table.SetBorders(false).
|
||||
SetSelectable(true, false).
|
||||
SetSeparator(' ')
|
||||
table.SetBorders(false)
|
||||
table.SetSelectable(true, false)
|
||||
table.SetSeparator(' ')
|
||||
code.Clear()
|
||||
fmt.Fprint(code, tableSelectRow)
|
||||
}
|
||||
|
||||
selectColumn := func() {
|
||||
table.SetBorders(false).
|
||||
SetSelectable(false, true).
|
||||
SetSeparator(' ')
|
||||
table.SetBorders(false)
|
||||
table.SetSelectable(false, true)
|
||||
table.SetSeparator(' ')
|
||||
code.Clear()
|
||||
fmt.Fprint(code, tableSelectColumn)
|
||||
}
|
||||
|
||||
selectCell := func() {
|
||||
table.SetBorders(false).
|
||||
SetSelectable(true, true).
|
||||
SetSeparator(' ')
|
||||
table.SetBorders(false)
|
||||
table.SetSelectable(true, true)
|
||||
table.SetSeparator(' ')
|
||||
code.Clear()
|
||||
fmt.Fprint(code, tableSelectCell)
|
||||
}
|
||||
|
@ -335,28 +336,47 @@ func Table(nextSlide func()) (title string, content cview.Primitive) {
|
|||
app.SetFocus(table)
|
||||
table.SetDoneFunc(func(key tcell.Key) {
|
||||
app.SetFocus(list)
|
||||
}).SetSelectedFunc(func(row int, column int) {
|
||||
})
|
||||
table.SetSelectedFunc(func(row int, column int) {
|
||||
app.SetFocus(list)
|
||||
})
|
||||
}
|
||||
|
||||
list.ShowSecondaryText(false).
|
||||
AddItem(cview.NewListItem("Basic table").SetShortcut('b').SetSelectedFunc(basic)).
|
||||
AddItem(cview.NewListItem("Table with separator").SetShortcut('s').SetSelectedFunc(separator)).
|
||||
AddItem(cview.NewListItem("Table with borders").SetShortcut('o').SetSelectedFunc(borders)).
|
||||
AddItem(cview.NewListItem("Selectable rows").SetShortcut('r').SetSelectedFunc(selectRow)).
|
||||
AddItem(cview.NewListItem("Selectable columns").SetShortcut('c').SetSelectedFunc(selectColumn)).
|
||||
AddItem(cview.NewListItem("Selectable cells").SetShortcut('l').SetSelectedFunc(selectCell)).
|
||||
AddItem(cview.NewListItem("Navigate").SetShortcut('n').SetSelectedFunc(navigate)).
|
||||
AddItem(cview.NewListItem("Next slide").SetShortcut('x').SetSelectedFunc(nextSlide))
|
||||
list.ShowSecondaryText(false)
|
||||
list.SetBorderPadding(1, 1, 2, 2)
|
||||
|
||||
var demoTableText = []struct {
|
||||
text string
|
||||
shortcut rune
|
||||
selected func()
|
||||
}{
|
||||
{"Basic table", 'b', basic},
|
||||
{"Table with separator", 's', separator},
|
||||
{"Table with borders", 'o', borders},
|
||||
{"Selectable rows", 'r', selectRow},
|
||||
{"Selectable columns", 'c', selectColumn},
|
||||
{"Selectable cells", 'l', selectCell},
|
||||
{"Navigate", 'n', navigate},
|
||||
{"Next slide", 'x', nextSlide},
|
||||
}
|
||||
|
||||
for _, tableText := range demoTableText {
|
||||
item := cview.NewListItem(tableText.text)
|
||||
item.SetShortcut(tableText.shortcut)
|
||||
item.SetSelectedFunc(tableText.selected)
|
||||
list.AddItem(item)
|
||||
}
|
||||
|
||||
basic()
|
||||
|
||||
return "Table", cview.NewFlex().
|
||||
AddItem(cview.NewFlex().
|
||||
SetDirection(cview.FlexRow).
|
||||
AddItem(list, 10, 1, true).
|
||||
AddItem(table, 0, 1, false), 0, 1, true).
|
||||
AddItem(code, codeWidth, 1, false)
|
||||
subFlex := cview.NewFlex()
|
||||
subFlex.SetDirection(cview.FlexRow)
|
||||
subFlex.AddItem(list, 10, 1, true)
|
||||
subFlex.AddItem(table, 0, 1, false)
|
||||
|
||||
flex := cview.NewFlex()
|
||||
flex.AddItem(subFlex, 0, 1, true)
|
||||
flex.AddItem(code, codeWidth, 1, false)
|
||||
|
||||
return "Table", flex
|
||||
}
|
||||
|
|
|
@ -31,12 +31,12 @@ const textView1 = `[green]func[white] [yellow]main[white]() {
|
|||
|
||||
// TextView1 demonstrates the basic text view.
|
||||
func TextView1(nextSlide func()) (title string, content cview.Primitive) {
|
||||
textView := cview.NewTextView().
|
||||
SetTextColor(tcell.ColorYellow.TrueColor()).
|
||||
SetScrollable(false).
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
nextSlide()
|
||||
})
|
||||
textView := cview.NewTextView()
|
||||
textView.SetTextColor(tcell.ColorYellow.TrueColor())
|
||||
textView.SetScrollable(false)
|
||||
textView.SetDoneFunc(func(key tcell.Key) {
|
||||
nextSlide()
|
||||
})
|
||||
textView.SetChangedFunc(func() {
|
||||
if textView.HasFocus() {
|
||||
app.Draw()
|
||||
|
@ -55,7 +55,8 @@ func TextView1(nextSlide func()) (title string, content cview.Primitive) {
|
|||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
}()
|
||||
textView.SetBorder(true).SetTitle("TextView implements io.Writer")
|
||||
textView.SetBorder(true)
|
||||
textView.SetTitle("TextView implements io.Writer")
|
||||
return "Text 1", Code(textView, 36, 13, textView1)
|
||||
}
|
||||
|
||||
|
@ -108,49 +109,54 @@ const textView2 = `[green]package[white] main
|
|||
|
||||
// TextView2 demonstrates the extended text view.
|
||||
func TextView2(nextSlide func()) (title string, content cview.Primitive) {
|
||||
codeView := cview.NewTextView().
|
||||
SetWrap(false)
|
||||
codeView := cview.NewTextView()
|
||||
codeView.SetWrap(false)
|
||||
fmt.Fprint(codeView, textView2)
|
||||
codeView.SetBorder(true).SetTitle("Buffer content")
|
||||
codeView.SetBorder(true)
|
||||
codeView.SetTitle("Buffer content")
|
||||
|
||||
textView := cview.NewTextView()
|
||||
textView.SetDynamicColors(true).
|
||||
SetWrap(false).
|
||||
SetRegions(true).
|
||||
SetDoneFunc(func(key tcell.Key) {
|
||||
if key == tcell.KeyEscape {
|
||||
nextSlide()
|
||||
return
|
||||
textView.SetDynamicColors(true)
|
||||
textView.SetWrap(false)
|
||||
textView.SetRegions(true)
|
||||
textView.SetDoneFunc(func(key tcell.Key) {
|
||||
if key == tcell.KeyEscape {
|
||||
nextSlide()
|
||||
return
|
||||
}
|
||||
highlights := textView.GetHighlights()
|
||||
hasHighlights := len(highlights) > 0
|
||||
switch key {
|
||||
case tcell.KeyEnter:
|
||||
if hasHighlights {
|
||||
textView.Highlight()
|
||||
} else {
|
||||
textView.Highlight("0")
|
||||
textView.ScrollToHighlight()
|
||||
}
|
||||
highlights := textView.GetHighlights()
|
||||
hasHighlights := len(highlights) > 0
|
||||
switch key {
|
||||
case tcell.KeyEnter:
|
||||
if hasHighlights {
|
||||
textView.Highlight()
|
||||
} else {
|
||||
textView.Highlight("0").
|
||||
ScrollToHighlight()
|
||||
}
|
||||
case tcell.KeyTab:
|
||||
if hasHighlights {
|
||||
current, _ := strconv.Atoi(highlights[0])
|
||||
next := (current + 1) % 9
|
||||
textView.Highlight(strconv.Itoa(next)).
|
||||
ScrollToHighlight()
|
||||
}
|
||||
case tcell.KeyBacktab:
|
||||
if hasHighlights {
|
||||
current, _ := strconv.Atoi(highlights[0])
|
||||
next := (current - 1 + 9) % 9
|
||||
textView.Highlight(strconv.Itoa(next)).
|
||||
ScrollToHighlight()
|
||||
}
|
||||
case tcell.KeyTab:
|
||||
if hasHighlights {
|
||||
current, _ := strconv.Atoi(highlights[0])
|
||||
next := (current + 1) % 9
|
||||
textView.Highlight(strconv.Itoa(next))
|
||||
textView.ScrollToHighlight()
|
||||
}
|
||||
})
|
||||
case tcell.KeyBacktab:
|
||||
if hasHighlights {
|
||||
current, _ := strconv.Atoi(highlights[0])
|
||||
next := (current - 1 + 9) % 9
|
||||
textView.Highlight(strconv.Itoa(next))
|
||||
textView.ScrollToHighlight()
|
||||
}
|
||||
}
|
||||
})
|
||||
fmt.Fprint(textView, textView2)
|
||||
textView.SetBorder(true).SetTitle("TextView output")
|
||||
return "Text 2", cview.NewFlex().
|
||||
AddItem(textView, 0, 1, true).
|
||||
AddItem(codeView, 0, 1, false)
|
||||
textView.SetBorder(true)
|
||||
textView.SetTitle("TextView output")
|
||||
|
||||
flex := cview.NewFlex()
|
||||
flex.AddItem(textView, 0, 1, true)
|
||||
flex.AddItem(codeView, 0, 1, false)
|
||||
|
||||
return "Text 2", flex
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ type node struct {
|
|||
var (
|
||||
tree = cview.NewTreeView()
|
||||
treeNextSlide func()
|
||||
treeCode = cview.NewTextView().SetWrap(false).SetDynamicColors(true)
|
||||
treeCode = cview.NewTextView()
|
||||
)
|
||||
|
||||
var rootNode = &node{
|
||||
|
@ -74,7 +74,10 @@ var rootNode = &node{
|
|||
{text: "Tree list starts one level down"},
|
||||
{text: "Works better for lists where no top node is needed"},
|
||||
{text: "Switch to this layout", selected: func() {
|
||||
tree.SetAlign(false).SetTopLevel(1).SetGraphics(true).SetPrefixes(nil)
|
||||
tree.SetAlign(false)
|
||||
tree.SetTopLevel(1)
|
||||
tree.SetGraphics(true)
|
||||
tree.SetPrefixes(nil)
|
||||
treeCode.SetText(strings.Replace(treeAllCode, "$$$", treeTopLevelCode, -1))
|
||||
}},
|
||||
}},
|
||||
|
@ -82,7 +85,10 @@ var rootNode = &node{
|
|||
{text: "For trees that are similar to lists"},
|
||||
{text: "Hierarchy shown only in line drawings"},
|
||||
{text: "Switch to this layout", selected: func() {
|
||||
tree.SetAlign(true).SetTopLevel(0).SetGraphics(true).SetPrefixes(nil)
|
||||
tree.SetAlign(true)
|
||||
tree.SetTopLevel(0)
|
||||
tree.SetGraphics(true)
|
||||
tree.SetPrefixes(nil)
|
||||
treeCode.SetText(strings.Replace(treeAllCode, "$$$", treeAlignCode, -1))
|
||||
}},
|
||||
}},
|
||||
|
@ -90,7 +96,10 @@ var rootNode = &node{
|
|||
{text: "Best for hierarchical bullet point lists"},
|
||||
{text: "You can define your own prefixes per level"},
|
||||
{text: "Switch to this layout", selected: func() {
|
||||
tree.SetAlign(false).SetTopLevel(1).SetGraphics(false).SetPrefixes([]string{"[red]* ", "[darkcyan]- ", "[darkmagenta]- "})
|
||||
tree.SetAlign(false)
|
||||
tree.SetTopLevel(1)
|
||||
tree.SetGraphics(false)
|
||||
tree.SetPrefixes([]string{"[red]* ", "[darkcyan]- ", "[darkmagenta]- "})
|
||||
treeCode.SetText(strings.Replace(treeAllCode, "$$$", treePrefixCode, -1))
|
||||
}},
|
||||
}},
|
||||
|
@ -98,7 +107,10 @@ var rootNode = &node{
|
|||
{text: "Lines illustrate hierarchy"},
|
||||
{text: "Basic indentation"},
|
||||
{text: "Switch to this layout", selected: func() {
|
||||
tree.SetAlign(false).SetTopLevel(0).SetGraphics(true).SetPrefixes(nil)
|
||||
tree.SetAlign(false)
|
||||
tree.SetTopLevel(0)
|
||||
tree.SetGraphics(true)
|
||||
tree.SetPrefixes(nil)
|
||||
treeCode.SetText(strings.Replace(treeAllCode, "$$$", treeBasicCode, -1))
|
||||
}},
|
||||
}},
|
||||
|
@ -108,16 +120,16 @@ var rootNode = &node{
|
|||
// TreeView demonstrates the tree view.
|
||||
func TreeView(nextSlide func()) (title string, content cview.Primitive) {
|
||||
treeNextSlide = nextSlide
|
||||
tree.SetBorder(true).
|
||||
SetTitle("TreeView")
|
||||
tree.SetBorder(true)
|
||||
tree.SetTitle("TreeView")
|
||||
|
||||
// Add nodes.
|
||||
var add func(target *node) *cview.TreeNode
|
||||
add = func(target *node) *cview.TreeNode {
|
||||
node := cview.NewTreeNode(target.text).
|
||||
SetSelectable(target.expand || target.selected != nil).
|
||||
SetExpanded(target == rootNode).
|
||||
SetReference(target)
|
||||
node := cview.NewTreeNode(target.text)
|
||||
node.SetSelectable(target.expand || target.selected != nil)
|
||||
node.SetExpanded(target == rootNode)
|
||||
node.SetReference(target)
|
||||
if target.expand {
|
||||
node.SetColor(tcell.ColorGreen.TrueColor())
|
||||
} else if target.selected != nil {
|
||||
|
@ -129,21 +141,25 @@ func TreeView(nextSlide func()) (title string, content cview.Primitive) {
|
|||
return node
|
||||
}
|
||||
root := add(rootNode)
|
||||
tree.SetRoot(root).
|
||||
SetCurrentNode(root).
|
||||
SetSelectedFunc(func(n *cview.TreeNode) {
|
||||
original := n.GetReference().(*node)
|
||||
if original.expand {
|
||||
n.SetExpanded(!n.IsExpanded())
|
||||
} else if original.selected != nil {
|
||||
original.selected()
|
||||
}
|
||||
})
|
||||
tree.SetRoot(root)
|
||||
tree.SetCurrentNode(root)
|
||||
tree.SetSelectedFunc(func(n *cview.TreeNode) {
|
||||
original := n.GetReference().(*node)
|
||||
if original.expand {
|
||||
n.SetExpanded(!n.IsExpanded())
|
||||
} else if original.selected != nil {
|
||||
original.selected()
|
||||
}
|
||||
})
|
||||
|
||||
treeCode.SetText(strings.Replace(treeAllCode, "$$$", treeBasicCode, -1)).
|
||||
SetBorderPadding(1, 1, 2, 0)
|
||||
treeCode.SetWrap(false)
|
||||
treeCode.SetDynamicColors(true)
|
||||
treeCode.SetText(strings.Replace(treeAllCode, "$$$", treeBasicCode, -1))
|
||||
treeCode.SetBorderPadding(1, 1, 2, 0)
|
||||
|
||||
return "Tree", cview.NewFlex().
|
||||
AddItem(tree, 0, 1, true).
|
||||
AddItem(treeCode, codeWidth, 1, false)
|
||||
flex := cview.NewFlex()
|
||||
flex.AddItem(tree, 0, 1, true)
|
||||
flex.AddItem(treeCode, codeWidth, 1, false)
|
||||
|
||||
return "Tree", flex
|
||||
}
|
||||
|
|
|
@ -10,25 +10,26 @@ const loremIpsumText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit,
|
|||
func Window(nextSlide func()) (title string, content cview.Primitive) {
|
||||
wm := cview.NewWindowManager()
|
||||
|
||||
list := cview.NewList().
|
||||
AddItem(cview.NewListItem("Item #1")).
|
||||
AddItem(cview.NewListItem("Item #2")).
|
||||
AddItem(cview.NewListItem("Item #3")).
|
||||
AddItem(cview.NewListItem("Item #4")).
|
||||
AddItem(cview.NewListItem("Item #5")).
|
||||
AddItem(cview.NewListItem("Item #6")).
|
||||
AddItem(cview.NewListItem("Item #7")).
|
||||
ShowSecondaryText(false)
|
||||
list := cview.NewList()
|
||||
list.ShowSecondaryText(false)
|
||||
list.AddItem(cview.NewListItem("Item #1"))
|
||||
list.AddItem(cview.NewListItem("Item #2"))
|
||||
list.AddItem(cview.NewListItem("Item #3"))
|
||||
list.AddItem(cview.NewListItem("Item #4"))
|
||||
list.AddItem(cview.NewListItem("Item #5"))
|
||||
list.AddItem(cview.NewListItem("Item #6"))
|
||||
list.AddItem(cview.NewListItem("Item #7"))
|
||||
|
||||
loremIpsum := cview.NewTextView().SetText(loremIpsumText)
|
||||
loremIpsum := cview.NewTextView()
|
||||
loremIpsum.SetText(loremIpsumText)
|
||||
|
||||
w1 := cview.NewWindow(list).
|
||||
SetPosition(2, 2).
|
||||
SetSize(10, 7)
|
||||
w1 := cview.NewWindow(list)
|
||||
w1.SetPosition(2, 2)
|
||||
w1.SetSize(10, 7)
|
||||
|
||||
w2 := cview.NewWindow(loremIpsum).
|
||||
SetPosition(7, 4).
|
||||
SetSize(12, 12)
|
||||
w2 := cview.NewWindow(loremIpsum)
|
||||
w2.SetPosition(7, 4)
|
||||
w2.SetSize(12, 12)
|
||||
|
||||
w1.SetTitle("List")
|
||||
w2.SetTitle("Lorem Ipsum")
|
||||
|
|
|
@ -60,11 +60,15 @@ func (r *RadioButtons) InputHandler() func(event *tcell.EventKey, setFocus func(
|
|||
}
|
||||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
|
||||
radioButtons := NewRadioButtons([]string{"Lions", "Elephants", "Giraffes"})
|
||||
radioButtons.SetBorder(true).
|
||||
SetTitle("Radio Button Demo").
|
||||
SetRect(0, 0, 30, 5)
|
||||
if err := cview.NewApplication().SetRoot(radioButtons, false).Run(); err != nil {
|
||||
radioButtons.SetBorder(true)
|
||||
radioButtons.SetTitle("Radio Button Demo")
|
||||
radioButtons.SetRect(0, 0, 30, 5)
|
||||
|
||||
app.SetRoot(radioButtons, false)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@ import (
|
|||
func main() {
|
||||
app := cview.NewApplication()
|
||||
|
||||
grid := cview.NewGrid().SetColumns(-1, 6, 4, 30, -1).SetRows(-1, 12, 4, 4, -1)
|
||||
grid := cview.NewGrid()
|
||||
grid.SetColumns(-1, 6, 4, 30, -1)
|
||||
grid.SetRows(-1, 12, 4, 4, -1)
|
||||
grid.SetBackgroundColor(cview.Styles.PrimitiveBackgroundColor)
|
||||
|
||||
verticalProgressBar := cview.NewProgressBar()
|
||||
|
@ -51,7 +53,8 @@ func main() {
|
|||
}
|
||||
}()
|
||||
|
||||
if err := app.SetRoot(grid, true).Run(); err != nil {
|
||||
app.SetRoot(grid, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,10 @@ const loremIpsumText = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
table := cview.NewTable().
|
||||
SetBorders(true)
|
||||
app.EnableMouse(true)
|
||||
|
||||
table := cview.NewTable()
|
||||
table.SetBorders(true)
|
||||
lorem := strings.Split(loremIpsumText, " ")
|
||||
cols, rows := 10, 40
|
||||
word := 0
|
||||
|
@ -23,25 +25,30 @@ func main() {
|
|||
if c < 1 || r < 1 {
|
||||
color = tcell.ColorYellow.TrueColor()
|
||||
}
|
||||
table.SetCell(r, c,
|
||||
cview.NewTableCell(lorem[word]).
|
||||
SetTextColor(color).
|
||||
SetAlign(cview.AlignCenter))
|
||||
cell := cview.NewTableCell(lorem[word])
|
||||
cell.SetTextColor(color)
|
||||
cell.SetAlign(cview.AlignCenter)
|
||||
table.SetCell(r, c, cell)
|
||||
word = (word + 1) % len(lorem)
|
||||
}
|
||||
}
|
||||
table.Select(0, 0).SetFixed(1, 1).SetDoneFunc(func(key tcell.Key) {
|
||||
table.Select(0, 0)
|
||||
table.SetFixed(1, 1)
|
||||
table.SetDoneFunc(func(key tcell.Key) {
|
||||
if key == tcell.KeyEscape {
|
||||
app.Stop()
|
||||
}
|
||||
if key == tcell.KeyEnter {
|
||||
table.SetSelectable(true, true)
|
||||
}
|
||||
}).SetSelectedFunc(func(row int, column int) {
|
||||
})
|
||||
table.SetSelectedFunc(func(row int, column int) {
|
||||
table.GetCell(row, column).SetTextColor(tcell.ColorRed.TrueColor())
|
||||
table.SetSelectable(false, false)
|
||||
})
|
||||
if err := app.SetRoot(table, true).EnableMouse(true).Run(); err != nil {
|
||||
|
||||
app.SetRoot(table, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,13 +21,15 @@ Capitalize on low hanging fruit to identify a ballpark value added activity to b
|
|||
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
textView := cview.NewTextView().
|
||||
SetDynamicColors(true).
|
||||
SetRegions(true).
|
||||
SetWordWrap(true).
|
||||
SetChangedFunc(func() {
|
||||
app.Draw()
|
||||
})
|
||||
app.EnableMouse(true)
|
||||
|
||||
textView := cview.NewTextView()
|
||||
textView.SetDynamicColors(true)
|
||||
textView.SetRegions(true)
|
||||
textView.SetWordWrap(true)
|
||||
textView.SetChangedFunc(func() {
|
||||
app.Draw()
|
||||
})
|
||||
numSelections := 0
|
||||
go func() {
|
||||
for _, word := range strings.Split(corporate, " ") {
|
||||
|
@ -48,7 +50,8 @@ func main() {
|
|||
if len(currentSelection) > 0 {
|
||||
textView.Highlight()
|
||||
} else {
|
||||
textView.Highlight("0").ScrollToHighlight()
|
||||
textView.Highlight("0")
|
||||
textView.ScrollToHighlight()
|
||||
}
|
||||
} else if len(currentSelection) > 0 {
|
||||
index, _ := strconv.Atoi(currentSelection[0])
|
||||
|
@ -59,11 +62,14 @@ func main() {
|
|||
} else {
|
||||
return
|
||||
}
|
||||
textView.Highlight(strconv.Itoa(index)).ScrollToHighlight()
|
||||
textView.Highlight(strconv.Itoa(index))
|
||||
textView.ScrollToHighlight()
|
||||
}
|
||||
})
|
||||
textView.SetBorder(true)
|
||||
if err := app.SetRoot(textView, true).EnableMouse(true).Run(); err != nil {
|
||||
|
||||
app.SetRoot(textView, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,15 @@ import (
|
|||
|
||||
// Show a navigable tree view of the current directory.
|
||||
func main() {
|
||||
app := cview.NewApplication()
|
||||
app.EnableMouse(true)
|
||||
|
||||
rootDir := "."
|
||||
root := cview.NewTreeNode(rootDir).
|
||||
SetColor(tcell.ColorRed.TrueColor())
|
||||
tree := cview.NewTreeView().
|
||||
SetRoot(root).
|
||||
SetCurrentNode(root)
|
||||
root := cview.NewTreeNode(rootDir)
|
||||
root.SetColor(tcell.ColorRed.TrueColor())
|
||||
tree := cview.NewTreeView()
|
||||
tree.SetRoot(root)
|
||||
tree.SetCurrentNode(root)
|
||||
|
||||
// A helper function which adds the files and directories of the given path
|
||||
// to the given target node.
|
||||
|
@ -26,9 +29,9 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
for _, file := range files {
|
||||
node := cview.NewTreeNode(file.Name()).
|
||||
SetReference(filepath.Join(path, file.Name())).
|
||||
SetSelectable(file.IsDir())
|
||||
node := cview.NewTreeNode(file.Name())
|
||||
node.SetReference(filepath.Join(path, file.Name()))
|
||||
node.SetSelectable(file.IsDir())
|
||||
if file.IsDir() {
|
||||
node.SetColor(tcell.ColorGreen.TrueColor())
|
||||
}
|
||||
|
@ -56,7 +59,8 @@ func main() {
|
|||
}
|
||||
})
|
||||
|
||||
if err := cview.NewApplication().SetRoot(tree, true).EnableMouse(true).Run(); err != nil {
|
||||
app.SetRoot(tree, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,38 +12,39 @@ func main() {
|
|||
pages := cview.NewPages()
|
||||
|
||||
form := cview.NewForm()
|
||||
form.AddDropDownSimple("称谓", 0, nil, "先生", "女士", "博士", "老师", "师傅").
|
||||
AddInputField("姓名", "", 20, nil, nil).
|
||||
AddPasswordField("密码", "", 10, '*', nil).
|
||||
AddCheckBox("", "年龄 18+", false, nil).
|
||||
AddButton("保存", func() {
|
||||
_, option := form.GetFormItem(0).(*cview.DropDown).GetCurrentOption()
|
||||
userName := form.GetFormItem(1).(*cview.InputField).GetText()
|
||||
form.AddDropDownSimple("称谓", 0, nil, "先生", "女士", "博士", "老师", "师傅")
|
||||
form.AddInputField("姓名", "", 20, nil, nil)
|
||||
form.AddPasswordField("密码", "", 10, '*', nil)
|
||||
form.AddCheckBox("", "年龄 18+", false, nil)
|
||||
form.AddButton("保存", func() {
|
||||
_, option := form.GetFormItem(0).(*cview.DropDown).GetCurrentOption()
|
||||
userName := form.GetFormItem(1).(*cview.InputField).GetText()
|
||||
|
||||
alert(pages, "alert-dialog", fmt.Sprintf("保存成功,%s %s!", userName, option.GetText()))
|
||||
}).
|
||||
AddButton("退出", func() {
|
||||
app.Stop()
|
||||
})
|
||||
form.SetBorder(true).SetTitle("输入一些内容").SetTitleAlign(cview.AlignLeft)
|
||||
alert(pages, "alert-dialog", fmt.Sprintf("保存成功,%s %s!", userName, option.GetText()))
|
||||
})
|
||||
form.AddButton("退出", func() {
|
||||
app.Stop()
|
||||
})
|
||||
form.SetBorder(true)
|
||||
form.SetTitle("输入一些内容")
|
||||
form.SetTitleAlign(cview.AlignLeft)
|
||||
pages.AddPage("base", form, true, true)
|
||||
|
||||
if err := app.SetRoot(pages, true).Run(); err != nil {
|
||||
app.SetRoot(pages, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// alert shows a confirmation dialog.
|
||||
func alert(pages *cview.Pages, id string, message string) *cview.Pages {
|
||||
return pages.AddPage(
|
||||
id,
|
||||
cview.NewModal().
|
||||
SetText(message).
|
||||
AddButtons([]string{"确定"}).
|
||||
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
pages.HidePage(id).RemovePage(id)
|
||||
}),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
func alert(pages *cview.Pages, id string, message string) {
|
||||
modal := cview.NewModal()
|
||||
modal.SetText(message)
|
||||
modal.AddButtons([]string{"确定"})
|
||||
modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
pages.HidePage(id)
|
||||
pages.RemovePage(id)
|
||||
})
|
||||
|
||||
pages.AddPage(id, modal, false, true)
|
||||
}
|
||||
|
|
23
doc_test.go
23
doc_test.go
|
@ -12,16 +12,24 @@ func ExampleNewApplication() {
|
|||
app := NewApplication()
|
||||
|
||||
// Create shared TextView.
|
||||
sharedTextView := NewTextView().SetText("Widgets may be re-used between multiple layouts.").SetTextAlign(AlignCenter)
|
||||
sharedTextView := NewTextView()
|
||||
sharedTextView.SetTextAlign(AlignCenter)
|
||||
sharedTextView.SetText("Widgets may be re-used between multiple layouts.")
|
||||
|
||||
// Create main layout using Grid.
|
||||
mainTextView := NewTextView().SetText("This is mainLayout.\n\nPress <Tab> to view aboutLayout.").SetTextAlign(AlignCenter)
|
||||
mainTextView := NewTextView()
|
||||
mainTextView.SetTextAlign(AlignCenter)
|
||||
mainTextView.SetText("This is mainLayout.\n\nPress <Tab> to view aboutLayout.")
|
||||
|
||||
mainLayout := NewGrid()
|
||||
mainLayout.AddItem(mainTextView, 0, 0, 1, 1, 0, 0, false)
|
||||
mainLayout.AddItem(sharedTextView, 1, 0, 1, 1, 0, 0, false)
|
||||
|
||||
// Create about layout using Grid.
|
||||
aboutTextView := NewTextView().SetText("cview muti-layout application example\n\nhttps://gitlab.com/tslocum/cview").SetTextAlign(AlignCenter)
|
||||
aboutTextView := NewTextView()
|
||||
aboutTextView.SetTextAlign(AlignCenter)
|
||||
aboutTextView.SetText("cview muti-layout application example\n\nhttps://gitlab.com/tslocum/cview")
|
||||
|
||||
aboutLayout := NewGrid()
|
||||
aboutLayout.AddItem(aboutTextView, 0, 0, 1, 1, 0, 0, false)
|
||||
aboutLayout.AddItem(sharedTextView, 1, 0, 1, 1, 0, 0, false)
|
||||
|
@ -53,7 +61,8 @@ func ExampleNewApplication() {
|
|||
})
|
||||
|
||||
// Run the application.
|
||||
if err := app.SetRoot(mainLayout, true).Run(); err != nil {
|
||||
app.SetRoot(mainLayout, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +79,8 @@ func ExampleApplication_EnableMouse() {
|
|||
app.SetDoubleClickInterval(StandardDoubleClick)
|
||||
|
||||
// Create a textview.
|
||||
tv := NewTextView().SetText("Click somewhere!")
|
||||
tv := NewTextView()
|
||||
tv.SetText("Click somewhere!")
|
||||
|
||||
// Set a mouse capture function which prints where the mouse was clicked.
|
||||
app.SetMouseCapture(func(event *tcell.EventMouse, action MouseAction) (*tcell.EventMouse, MouseAction) {
|
||||
|
@ -93,7 +103,8 @@ func ExampleApplication_EnableMouse() {
|
|||
})
|
||||
|
||||
// Run the application.
|
||||
if err := app.SetRoot(tv, true).Run(); err != nil {
|
||||
app.SetRoot(tv, true)
|
||||
if err := app.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
103
dropdown.go
103
dropdown.go
|
@ -31,15 +31,13 @@ func (d *DropDownOption) GetText() string {
|
|||
}
|
||||
|
||||
// SetText returns the text of this dropdown option.
|
||||
func (d *DropDownOption) SetText(text string) *DropDownOption {
|
||||
func (d *DropDownOption) SetText(text string) {
|
||||
d.text = text
|
||||
return d
|
||||
}
|
||||
|
||||
// SetSelectedFunc sets the handler to be called when this option is selected.
|
||||
func (d *DropDownOption) SetSelectedFunc(handler func(index int, option *DropDownOption)) *DropDownOption {
|
||||
func (d *DropDownOption) SetSelectedFunc(handler func(index int, option *DropDownOption)) {
|
||||
d.selected = handler
|
||||
return d
|
||||
}
|
||||
|
||||
// GetReference returns the reference object of this dropdown option.
|
||||
|
@ -51,9 +49,8 @@ func (d *DropDownOption) GetReference() interface{} {
|
|||
}
|
||||
|
||||
// SetReference allows you to store a reference of any type in this option.
|
||||
func (d *DropDownOption) SetReference(reference interface{}) *DropDownOption {
|
||||
func (d *DropDownOption) SetReference(reference interface{}) {
|
||||
d.reference = reference
|
||||
return d
|
||||
}
|
||||
|
||||
// DropDown implements a selection widget whose options become visible in a
|
||||
|
@ -146,12 +143,12 @@ type DropDown struct {
|
|||
// NewDropDown returns a new drop-down.
|
||||
func NewDropDown() *DropDown {
|
||||
list := NewList()
|
||||
list.ShowSecondaryText(false).
|
||||
SetMainTextColor(Styles.PrimitiveBackgroundColor).
|
||||
SetSelectedTextColor(Styles.PrimitiveBackgroundColor).
|
||||
SetSelectedBackgroundColor(Styles.PrimaryTextColor).
|
||||
SetHighlightFullLine(true).
|
||||
SetBackgroundColor(Styles.MoreContrastBackgroundColor)
|
||||
list.ShowSecondaryText(false)
|
||||
list.SetMainTextColor(Styles.PrimitiveBackgroundColor)
|
||||
list.SetSelectedTextColor(Styles.PrimitiveBackgroundColor)
|
||||
list.SetSelectedBackgroundColor(Styles.PrimaryTextColor)
|
||||
list.SetHighlightFullLine(true)
|
||||
list.SetBackgroundColor(Styles.MoreContrastBackgroundColor)
|
||||
|
||||
d := &DropDown{
|
||||
Box: NewBox(),
|
||||
|
@ -175,17 +172,16 @@ func NewDropDown() *DropDown {
|
|||
|
||||
// SetDropDownSymbolRune sets the rune to be drawn at the end of the dropdown field
|
||||
// to indicate that this field is a dropdown.
|
||||
func (d *DropDown) SetDropDownSymbolRune(symbol rune) *DropDown {
|
||||
func (d *DropDown) SetDropDownSymbolRune(symbol rune) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
d.dropDownSymbol = symbol
|
||||
return d
|
||||
}
|
||||
|
||||
// SetCurrentOption sets the index of the currently selected option. This may
|
||||
// be a negative value to indicate that no option is currently selected. Calling
|
||||
// this function will also trigger the "selected" callback (if there is one).
|
||||
func (d *DropDown) SetCurrentOption(index int) *DropDown {
|
||||
func (d *DropDown) SetCurrentOption(index int) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
|
@ -211,7 +207,6 @@ func (d *DropDown) SetCurrentOption(index int) *DropDown {
|
|||
d.Lock()
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// GetCurrentOption returns the index of the currently selected option as well
|
||||
|
@ -232,7 +227,7 @@ func (d *DropDown) GetCurrentOption() (int, *DropDownOption) {
|
|||
// selected option (currentPrefix/currentSuffix) as well as the text to be
|
||||
// displayed when no option is currently selected. Per default, all of these
|
||||
// strings are empty.
|
||||
func (d *DropDown) SetTextOptions(prefix, suffix, currentPrefix, currentSuffix, noSelection string) *DropDown {
|
||||
func (d *DropDown) SetTextOptions(prefix, suffix, currentPrefix, currentSuffix, noSelection string) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
|
@ -244,16 +239,14 @@ func (d *DropDown) SetTextOptions(prefix, suffix, currentPrefix, currentSuffix,
|
|||
for index := 0; index < d.list.GetItemCount(); index++ {
|
||||
d.list.SetItemText(index, prefix+d.options[index].text+suffix, "")
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// SetLabel sets the text to be displayed before the input area.
|
||||
func (d *DropDown) SetLabel(label string) *DropDown {
|
||||
func (d *DropDown) SetLabel(label string) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.label = label
|
||||
return d
|
||||
}
|
||||
|
||||
// GetLabel returns the text to be displayed before the input area.
|
||||
|
@ -266,125 +259,112 @@ func (d *DropDown) GetLabel() string {
|
|||
|
||||
// SetLabelWidth sets the screen width of the label. A value of 0 will cause the
|
||||
// primitive to use the width of the label string.
|
||||
func (d *DropDown) SetLabelWidth(width int) *DropDown {
|
||||
func (d *DropDown) SetLabelWidth(width int) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.labelWidth = width
|
||||
return d
|
||||
}
|
||||
|
||||
// SetLabelColor sets the color of the label.
|
||||
func (d *DropDown) SetLabelColor(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetLabelColor(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.labelColor = color
|
||||
return d
|
||||
}
|
||||
|
||||
// SetLabelColorFocused sets the color of the label when focused.
|
||||
func (d *DropDown) SetLabelColorFocused(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetLabelColorFocused(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.labelColorFocused = color
|
||||
return d
|
||||
}
|
||||
|
||||
// SetFieldBackgroundColor sets the background color of the options area.
|
||||
func (d *DropDown) SetFieldBackgroundColor(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetFieldBackgroundColor(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.fieldBackgroundColor = color
|
||||
return d
|
||||
}
|
||||
|
||||
// SetFieldBackgroundColorFocused sets the background color of the options area when focused.
|
||||
func (d *DropDown) SetFieldBackgroundColorFocused(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetFieldBackgroundColorFocused(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.fieldBackgroundColorFocused = color
|
||||
return d
|
||||
}
|
||||
|
||||
// SetFieldTextColor sets the text color of the options area.
|
||||
func (d *DropDown) SetFieldTextColor(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetFieldTextColor(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.fieldTextColor = color
|
||||
return d
|
||||
}
|
||||
|
||||
// SetFieldTextColorFocused sets the text color of the options area when focused.
|
||||
func (d *DropDown) SetFieldTextColorFocused(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetFieldTextColorFocused(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.fieldTextColorFocused = color
|
||||
return d
|
||||
}
|
||||
|
||||
// SetDropDownTextColor sets text color of the drop-down list.
|
||||
func (d *DropDown) SetDropDownTextColor(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetDropDownTextColor(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.list.SetMainTextColor(color)
|
||||
return d
|
||||
}
|
||||
|
||||
// SetDropDownBackgroundColor sets the background color of the drop-down list.
|
||||
func (d *DropDown) SetDropDownBackgroundColor(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetDropDownBackgroundColor(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.list.SetBackgroundColor(color)
|
||||
return d
|
||||
}
|
||||
|
||||
// SetDropDownSelectedTextColor sets the text color of the selected option in
|
||||
// the drop-down list.
|
||||
func (d *DropDown) SetDropDownSelectedTextColor(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetDropDownSelectedTextColor(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.list.SetSelectedTextColor(color)
|
||||
return d
|
||||
}
|
||||
|
||||
// SetDropDownSelectedBackgroundColor sets the background color of the selected
|
||||
// option in the drop-down list.
|
||||
func (d *DropDown) SetDropDownSelectedBackgroundColor(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetDropDownSelectedBackgroundColor(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.list.SetSelectedBackgroundColor(color)
|
||||
return d
|
||||
}
|
||||
|
||||
// SetPrefixTextColor sets the color of the prefix string. The prefix string is
|
||||
// shown when the user starts typing text, which directly selects the first
|
||||
// option that starts with the typed string.
|
||||
func (d *DropDown) SetPrefixTextColor(color tcell.Color) *DropDown {
|
||||
func (d *DropDown) SetPrefixTextColor(color tcell.Color) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.prefixTextColor = color
|
||||
return d
|
||||
}
|
||||
|
||||
// SetFieldWidth sets the screen width of the options area. A value of 0 means
|
||||
// extend to as long as the longest option text.
|
||||
func (d *DropDown) SetFieldWidth(width int) *DropDown {
|
||||
func (d *DropDown) SetFieldWidth(width int) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.fieldWidth = width
|
||||
return d
|
||||
}
|
||||
|
||||
// GetFieldHeight returns the height of the field.
|
||||
|
@ -417,48 +397,45 @@ func (d *DropDown) getFieldWidth() int {
|
|||
}
|
||||
|
||||
// AddOptionsSimple adds new selectable options to this drop-down.
|
||||
func (d *DropDown) AddOptionsSimple(options ...string) *DropDown {
|
||||
func (d *DropDown) AddOptionsSimple(options ...string) {
|
||||
optionsToAdd := make([]*DropDownOption, len(options))
|
||||
for i, option := range options {
|
||||
optionsToAdd[i] = NewDropDownOption(option)
|
||||
}
|
||||
d.AddOptions(optionsToAdd...)
|
||||
return d
|
||||
}
|
||||
|
||||
// AddOptions adds new selectable options to this drop-down.
|
||||
func (d *DropDown) AddOptions(options ...*DropDownOption) *DropDown {
|
||||
func (d *DropDown) AddOptions(options ...*DropDownOption) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
return d.addOptions(options...)
|
||||
d.addOptions(options...)
|
||||
}
|
||||
|
||||
func (d *DropDown) addOptions(options ...*DropDownOption) *DropDown {
|
||||
func (d *DropDown) addOptions(options ...*DropDownOption) {
|
||||
d.options = append(d.options, options...)
|
||||
for _, option := range options {
|
||||
d.list.AddItem(NewListItem(d.optionPrefix + option.text + d.optionSuffix))
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// SetOptionsSimple replaces all current options with the ones provided and installs
|
||||
// one callback function which is called when one of the options is selected.
|
||||
// It will be called with the option's index and the option itself
|
||||
// The "selected" parameter may be nil.
|
||||
func (d *DropDown) SetOptionsSimple(selected func(index int, option *DropDownOption), options ...string) *DropDown {
|
||||
func (d *DropDown) SetOptionsSimple(selected func(index int, option *DropDownOption), options ...string) {
|
||||
optionsToSet := make([]*DropDownOption, len(options))
|
||||
for i, option := range options {
|
||||
optionsToSet[i] = NewDropDownOption(option)
|
||||
}
|
||||
d.SetOptions(selected, optionsToSet...)
|
||||
return d
|
||||
}
|
||||
|
||||
// SetOptions replaces all current options with the ones provided and installs
|
||||
// one callback function which is called when one of the options is selected.
|
||||
// It will be called with the option's index and the option itself.
|
||||
// The "selected" parameter may be nil.
|
||||
func (d *DropDown) SetOptions(selected func(index int, option *DropDownOption), options ...*DropDownOption) *DropDown {
|
||||
func (d *DropDown) SetOptions(selected func(index int, option *DropDownOption), options ...*DropDownOption) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
|
@ -466,18 +443,16 @@ func (d *DropDown) SetOptions(selected func(index int, option *DropDownOption),
|
|||
d.options = nil
|
||||
d.addOptions(options...)
|
||||
d.selected = selected
|
||||
return d
|
||||
}
|
||||
|
||||
// SetChangedFunc sets a handler which is called when the user changes the
|
||||
// focused drop-down option. The handler is provided with the selected option's
|
||||
// index and the option itself. If "no option" was selected, these values are
|
||||
// -1 and nil.
|
||||
func (d *DropDown) SetChangedFunc(handler func(index int, option *DropDownOption)) *DropDown {
|
||||
func (d *DropDown) SetChangedFunc(handler func(index int, option *DropDownOption)) {
|
||||
d.list.SetChangedFunc(func(index int, item *ListItem) {
|
||||
handler(index, d.options[index])
|
||||
})
|
||||
return d
|
||||
}
|
||||
|
||||
// SetSelectedFunc sets a handler which is called when the user selects a
|
||||
|
@ -485,12 +460,11 @@ func (d *DropDown) SetChangedFunc(handler func(index int, option *DropDownOption
|
|||
// an option's optional individual handler. The handler is provided with the
|
||||
// selected option's index and the option itself. If "no option" was selected, these values
|
||||
// are -1 and nil.
|
||||
func (d *DropDown) SetSelectedFunc(handler func(index int, option *DropDownOption)) *DropDown {
|
||||
func (d *DropDown) SetSelectedFunc(handler func(index int, option *DropDownOption)) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.selected = handler
|
||||
return d
|
||||
}
|
||||
|
||||
// SetDoneFunc sets a handler which is called when the user is done selecting
|
||||
|
@ -500,21 +474,19 @@ func (d *DropDown) SetSelectedFunc(handler func(index int, option *DropDownOptio
|
|||
// - KeyEscape: Abort selection.
|
||||
// - KeyTab: Move to the next field.
|
||||
// - KeyBacktab: Move to the previous field.
|
||||
func (d *DropDown) SetDoneFunc(handler func(key tcell.Key)) *DropDown {
|
||||
func (d *DropDown) SetDoneFunc(handler func(key tcell.Key)) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.done = handler
|
||||
return d
|
||||
}
|
||||
|
||||
// SetFinishedFunc sets a callback invoked when the user leaves this form item.
|
||||
func (d *DropDown) SetFinishedFunc(handler func(key tcell.Key)) *DropDown {
|
||||
func (d *DropDown) SetFinishedFunc(handler func(key tcell.Key)) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
d.finished = handler
|
||||
return d
|
||||
}
|
||||
|
||||
// SetAttributes applies attribute settings to a form item.
|
||||
|
@ -734,7 +706,8 @@ func (d *DropDown) openList(setFocus func(Primitive)) {
|
|||
if d.options[d.currentOption].selected != nil {
|
||||
d.options[d.currentOption].selected(d.currentOption, d.options[d.currentOption])
|
||||
}
|
||||
}).SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
})
|
||||
d.list.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if event.Key() == tcell.KeyRune {
|
||||
d.prefix += string(event.Rune())
|
||||
d.evalPrefix()
|
||||
|
|
21
flex.go
21
flex.go
|
@ -51,9 +51,10 @@ type Flex struct {
|
|||
// flex.SetBackgroundTransparent(false)
|
||||
func NewFlex() *Flex {
|
||||
f := &Flex{
|
||||
Box: NewBox().SetBackgroundTransparent(true),
|
||||
Box: NewBox(),
|
||||
direction: FlexColumn,
|
||||
}
|
||||
f.SetBackgroundTransparent(true)
|
||||
f.focus = f
|
||||
return f
|
||||
}
|
||||
|
@ -68,22 +69,20 @@ func (f *Flex) GetDirection() int {
|
|||
|
||||
// SetDirection sets the direction in which the contained primitives are
|
||||
// distributed. This can be either FlexColumn (default) or FlexRow.
|
||||
func (f *Flex) SetDirection(direction int) *Flex {
|
||||
func (f *Flex) SetDirection(direction int) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.direction = direction
|
||||
return f
|
||||
}
|
||||
|
||||
// SetFullScreen sets the flag which, when true, causes the flex layout to use
|
||||
// the entire screen space instead of whatever size it is currently assigned to.
|
||||
func (f *Flex) SetFullScreen(fullScreen bool) *Flex {
|
||||
func (f *Flex) SetFullScreen(fullScreen bool) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.fullScreen = fullScreen
|
||||
return f
|
||||
}
|
||||
|
||||
// AddItem adds a new item to the container. The "fixedSize" argument is a width
|
||||
|
@ -101,7 +100,7 @@ func (f *Flex) SetFullScreen(fullScreen bool) *Flex {
|
|||
// You can provide a nil value for the primitive. This will fill the empty
|
||||
// screen space with the default background color. To show content behind the
|
||||
// space, add a Box with a transparent background instead.
|
||||
func (f *Flex) AddItem(item Primitive, fixedSize, proportion int, focus bool) *Flex {
|
||||
func (f *Flex) AddItem(item Primitive, fixedSize, proportion int, focus bool) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
|
@ -110,12 +109,11 @@ func (f *Flex) AddItem(item Primitive, fixedSize, proportion int, focus bool) *F
|
|||
}
|
||||
|
||||
f.items = append(f.items, &flexItem{Item: item, FixedSize: fixedSize, Proportion: proportion, Focus: focus})
|
||||
return f
|
||||
}
|
||||
|
||||
// AddItemAtIndex adds an item to the flex at a given index.
|
||||
// For more information see AddItem.
|
||||
func (f *Flex) AddItemAtIndex(index int, item Primitive, fixedSize, proportion int, focus bool) *Flex {
|
||||
func (f *Flex) AddItemAtIndex(index int, item Primitive, fixedSize, proportion int, focus bool) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
newItem := &flexItem{Item: item, FixedSize: fixedSize, Proportion: proportion, Focus: focus}
|
||||
|
@ -125,12 +123,11 @@ func (f *Flex) AddItemAtIndex(index int, item Primitive, fixedSize, proportion i
|
|||
} else {
|
||||
f.items = append(f.items[:index], append([]*flexItem{newItem}, f.items[index:]...)...)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// RemoveItem removes all items for the given primitive from the container,
|
||||
// keeping the order of the remaining items intact.
|
||||
func (f *Flex) RemoveItem(p Primitive) *Flex {
|
||||
func (f *Flex) RemoveItem(p Primitive) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
|
@ -139,13 +136,12 @@ func (f *Flex) RemoveItem(p Primitive) *Flex {
|
|||
f.items = append(f.items[:index], f.items[index+1:]...)
|
||||
}
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// ResizeItem sets a new size for the item(s) with the given primitive. If there
|
||||
// are multiple Flex items with the same primitive, they will all receive the
|
||||
// same size. For details regarding the size parameters, see AddItem().
|
||||
func (f *Flex) ResizeItem(p Primitive, fixedSize, proportion int) *Flex {
|
||||
func (f *Flex) ResizeItem(p Primitive, fixedSize, proportion int) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
|
@ -155,7 +151,6 @@ func (f *Flex) ResizeItem(p Primitive, fixedSize, proportion int) *Flex {
|
|||
item.Proportion = proportion
|
||||
}
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
|
|
157
form.go
157
form.go
|
@ -119,7 +119,8 @@ type Form struct {
|
|||
|
||||
// NewForm returns a new form.
|
||||
func NewForm() *Form {
|
||||
box := NewBox().SetBorderPadding(1, 1, 1, 1)
|
||||
box := NewBox()
|
||||
box.SetBorderPadding(1, 1, 1, 1)
|
||||
|
||||
f := &Form{
|
||||
Box: box,
|
||||
|
@ -143,130 +144,117 @@ func NewForm() *Form {
|
|||
// SetItemPadding sets the number of empty rows between form items for vertical
|
||||
// layouts and the number of empty cells between form items for horizontal
|
||||
// layouts.
|
||||
func (f *Form) SetItemPadding(padding int) *Form {
|
||||
func (f *Form) SetItemPadding(padding int) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.itemPadding = padding
|
||||
return f
|
||||
}
|
||||
|
||||
// SetHorizontal sets the direction the form elements are laid out. If set to
|
||||
// true, instead of positioning them from top to bottom (the default), they are
|
||||
// positioned from left to right, moving into the next row if there is not
|
||||
// enough space.
|
||||
func (f *Form) SetHorizontal(horizontal bool) *Form {
|
||||
func (f *Form) SetHorizontal(horizontal bool) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.horizontal = horizontal
|
||||
return f
|
||||
}
|
||||
|
||||
// SetLabelColor sets the color of the labels.
|
||||
func (f *Form) SetLabelColor(color tcell.Color) *Form {
|
||||
func (f *Form) SetLabelColor(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.labelColor = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetLabelColorFocused sets the color of the labels when focused.
|
||||
func (f *Form) SetLabelColorFocused(color tcell.Color) *Form {
|
||||
func (f *Form) SetLabelColorFocused(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.labelColorFocused = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetFieldBackgroundColor sets the background color of the input areas.
|
||||
func (f *Form) SetFieldBackgroundColor(color tcell.Color) *Form {
|
||||
func (f *Form) SetFieldBackgroundColor(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.fieldBackgroundColor = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetFieldBackgroundColorFocused sets the background color of the input areas when focused.
|
||||
func (f *Form) SetFieldBackgroundColorFocused(color tcell.Color) *Form {
|
||||
func (f *Form) SetFieldBackgroundColorFocused(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.fieldBackgroundColorFocused = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetFieldTextColor sets the text color of the input areas.
|
||||
func (f *Form) SetFieldTextColor(color tcell.Color) *Form {
|
||||
func (f *Form) SetFieldTextColor(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.fieldTextColor = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetFieldTextColorFocused sets the text color of the input areas when focused.
|
||||
func (f *Form) SetFieldTextColorFocused(color tcell.Color) *Form {
|
||||
func (f *Form) SetFieldTextColorFocused(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.fieldTextColorFocused = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetButtonsAlign sets how the buttons align horizontally, one of AlignLeft
|
||||
// (the default), AlignCenter, and AlignRight. This is only
|
||||
func (f *Form) SetButtonsAlign(align int) *Form {
|
||||
func (f *Form) SetButtonsAlign(align int) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.buttonsAlign = align
|
||||
return f
|
||||
}
|
||||
|
||||
// SetButtonBackgroundColor sets the background color of the buttons.
|
||||
func (f *Form) SetButtonBackgroundColor(color tcell.Color) *Form {
|
||||
func (f *Form) SetButtonBackgroundColor(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.buttonBackgroundColor = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetButtonBackgroundColorFocused sets the background color of the buttons when focused.
|
||||
func (f *Form) SetButtonBackgroundColorFocused(color tcell.Color) *Form {
|
||||
func (f *Form) SetButtonBackgroundColorFocused(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.buttonBackgroundColorFocused = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetButtonTextColor sets the color of the button texts.
|
||||
func (f *Form) SetButtonTextColor(color tcell.Color) *Form {
|
||||
func (f *Form) SetButtonTextColor(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.buttonTextColor = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetButtonTextColorFocused sets the color of the button texts when focused.
|
||||
func (f *Form) SetButtonTextColorFocused(color tcell.Color) *Form {
|
||||
func (f *Form) SetButtonTextColorFocused(color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.buttonTextColorFocused = color
|
||||
return f
|
||||
}
|
||||
|
||||
// SetFocus shifts the focus to the form element with the given index, counting
|
||||
// non-button items first and buttons last. Note that this index is only used
|
||||
// when the form itself receives focus.
|
||||
func (f *Form) SetFocus(index int) *Form {
|
||||
func (f *Form) SetFocus(index int) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
|
@ -277,7 +265,6 @@ func (f *Form) SetFocus(index int) *Form {
|
|||
} else {
|
||||
f.focusedElement = index
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// AddInputField adds an input field to the form. It has a label, an optional
|
||||
|
@ -285,17 +272,18 @@ func (f *Form) SetFocus(index int) *Form {
|
|||
// an optional accept function to validate the item's value (set to nil to
|
||||
// accept any text), and an (optional) callback function which is invoked when
|
||||
// the input field's text has changed.
|
||||
func (f *Form) AddInputField(label, value string, fieldWidth int, accept func(textToCheck string, lastChar rune) bool, changed func(text string)) *Form {
|
||||
func (f *Form) AddInputField(label, value string, fieldWidth int, accept func(textToCheck string, lastChar rune) bool, changed func(text string)) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.items = append(f.items, NewInputField().
|
||||
SetLabel(label).
|
||||
SetText(value).
|
||||
SetFieldWidth(fieldWidth).
|
||||
SetAcceptanceFunc(accept).
|
||||
SetChangedFunc(changed))
|
||||
return f
|
||||
inputField := NewInputField()
|
||||
inputField.SetLabel(label)
|
||||
inputField.SetText(value)
|
||||
inputField.SetFieldWidth(fieldWidth)
|
||||
inputField.SetAcceptanceFunc(accept)
|
||||
inputField.SetChangedFunc(changed)
|
||||
|
||||
f.items = append(f.items, inputField)
|
||||
}
|
||||
|
||||
// AddPasswordField adds a password field to the form. This is similar to an
|
||||
|
@ -304,75 +292,81 @@ func (f *Form) AddInputField(label, value string, fieldWidth int, accept func(te
|
|||
// value, a field width (a value of 0 extends it as far as possible), and an
|
||||
// (optional) callback function which is invoked when the input field's text has
|
||||
// changed.
|
||||
func (f *Form) AddPasswordField(label, value string, fieldWidth int, mask rune, changed func(text string)) *Form {
|
||||
func (f *Form) AddPasswordField(label, value string, fieldWidth int, mask rune, changed func(text string)) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
if mask == 0 {
|
||||
mask = '*'
|
||||
}
|
||||
f.items = append(f.items, NewInputField().
|
||||
SetLabel(label).
|
||||
SetText(value).
|
||||
SetFieldWidth(fieldWidth).
|
||||
SetMaskCharacter(mask).
|
||||
SetChangedFunc(changed))
|
||||
return f
|
||||
|
||||
passwordField := NewInputField()
|
||||
passwordField.SetLabel(label)
|
||||
passwordField.SetText(value)
|
||||
passwordField.SetFieldWidth(fieldWidth)
|
||||
passwordField.SetMaskCharacter(mask)
|
||||
passwordField.SetChangedFunc(changed)
|
||||
|
||||
f.items = append(f.items, passwordField)
|
||||
}
|
||||
|
||||
// AddDropDownSimple adds a drop-down element to the form. It has a label, options,
|
||||
// and an (optional) callback function which is invoked when an option was
|
||||
// selected. The initial option may be a negative value to indicate that no
|
||||
// option is currently selected.
|
||||
func (f *Form) AddDropDownSimple(label string, initialOption int, selected func(index int, option *DropDownOption), options ...string) *Form {
|
||||
func (f *Form) AddDropDownSimple(label string, initialOption int, selected func(index int, option *DropDownOption), options ...string) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.items = append(f.items, NewDropDown().
|
||||
SetLabel(label).
|
||||
SetOptionsSimple(selected, options...).
|
||||
SetCurrentOption(initialOption))
|
||||
return f
|
||||
dd := NewDropDown()
|
||||
dd.SetLabel(label)
|
||||
dd.SetOptionsSimple(selected, options...)
|
||||
dd.SetCurrentOption(initialOption)
|
||||
|
||||
f.items = append(f.items, dd)
|
||||
}
|
||||
|
||||
// AddDropDown adds a drop-down element to the form. It has a label, options,
|
||||
// and an (optional) callback function which is invoked when an option was
|
||||
// selected. The initial option may be a negative value to indicate that no
|
||||
// option is currently selected.
|
||||
func (f *Form) AddDropDown(label string, initialOption int, selected func(index int, option *DropDownOption), options []*DropDownOption) *Form {
|
||||
func (f *Form) AddDropDown(label string, initialOption int, selected func(index int, option *DropDownOption), options []*DropDownOption) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.items = append(f.items, NewDropDown().
|
||||
SetLabel(label).
|
||||
SetOptions(selected, options...).
|
||||
SetCurrentOption(initialOption))
|
||||
return f
|
||||
dd := NewDropDown()
|
||||
dd.SetLabel(label)
|
||||
dd.SetOptions(selected, options...)
|
||||
dd.SetCurrentOption(initialOption)
|
||||
|
||||
f.items = append(f.items, dd)
|
||||
}
|
||||
|
||||
// AddCheckBox adds a checkbox to the form. It has a label, a message, an
|
||||
// initial state, and an (optional) callback function which is invoked when the
|
||||
// state of the checkbox was changed by the user.
|
||||
func (f *Form) AddCheckBox(label string, message string, checked bool, changed func(checked bool)) *Form {
|
||||
func (f *Form) AddCheckBox(label string, message string, checked bool, changed func(checked bool)) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.items = append(f.items, NewCheckBox().
|
||||
SetLabel(label).
|
||||
SetMessage(message).
|
||||
SetChecked(checked).
|
||||
SetChangedFunc(changed))
|
||||
return f
|
||||
c := NewCheckBox()
|
||||
c.SetLabel(label)
|
||||
c.SetMessage(message)
|
||||
c.SetChecked(checked)
|
||||
c.SetChangedFunc(changed)
|
||||
|
||||
f.items = append(f.items, c)
|
||||
}
|
||||
|
||||
// AddButton adds a new button to the form. The "selected" function is called
|
||||
// when the user selects this button. It may be nil.
|
||||
func (f *Form) AddButton(label string, selected func()) *Form {
|
||||
func (f *Form) AddButton(label string, selected func()) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.buttons = append(f.buttons, NewButton(label).SetSelectedFunc(selected))
|
||||
return f
|
||||
button := NewButton(label)
|
||||
button.SetSelectedFunc(selected)
|
||||
f.buttons = append(f.buttons, button)
|
||||
}
|
||||
|
||||
// GetButton returns the button at the specified 0-based index. Note that
|
||||
|
@ -387,12 +381,11 @@ func (f *Form) GetButton(index int) *Button {
|
|||
|
||||
// RemoveButton removes the button at the specified position, starting with 0
|
||||
// for the button that was added first.
|
||||
func (f *Form) RemoveButton(index int) *Form {
|
||||
func (f *Form) RemoveButton(index int) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.buttons = append(f.buttons[:index], f.buttons[index+1:]...)
|
||||
return f
|
||||
}
|
||||
|
||||
// GetButtonCount returns the number of buttons in this form.
|
||||
|
@ -420,7 +413,7 @@ func (f *Form) GetButtonIndex(label string) int {
|
|||
|
||||
// Clear removes all input elements from the form, including the buttons if
|
||||
// specified.
|
||||
func (f *Form) Clear(includeButtons bool) *Form {
|
||||
func (f *Form) Clear(includeButtons bool) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
|
@ -429,16 +422,14 @@ func (f *Form) Clear(includeButtons bool) *Form {
|
|||
f.buttons = nil
|
||||
}
|
||||
f.focusedElement = 0
|
||||
return f
|
||||
}
|
||||
|
||||
// ClearButtons removes all buttons from the form.
|
||||
func (f *Form) ClearButtons() *Form {
|
||||
func (f *Form) ClearButtons() {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.buttons = nil
|
||||
return f
|
||||
}
|
||||
|
||||
// AddFormItem adds a new item to the form. This can be used to add your own
|
||||
|
@ -451,7 +442,7 @@ func (f *Form) ClearButtons() *Form {
|
|||
// - The background color
|
||||
// - The field text color
|
||||
// - The field background color
|
||||
func (f *Form) AddFormItem(item FormItem) *Form {
|
||||
func (f *Form) AddFormItem(item FormItem) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
|
@ -460,7 +451,6 @@ func (f *Form) AddFormItem(item FormItem) *Form {
|
|||
}
|
||||
|
||||
f.items = append(f.items, item)
|
||||
return f
|
||||
}
|
||||
|
||||
// GetFormItemCount returns the number of items in the form (not including the
|
||||
|
@ -499,12 +489,11 @@ func (f *Form) GetFormItem(index int) FormItem {
|
|||
// RemoveFormItem removes the form element at the given position, starting with
|
||||
// index 0. Elements are referenced in the order they were added. Buttons are
|
||||
// not included.
|
||||
func (f *Form) RemoveFormItem(index int) *Form {
|
||||
func (f *Form) RemoveFormItem(index int) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.items = append(f.items[:index], f.items[index+1:]...)
|
||||
return f
|
||||
}
|
||||
|
||||
// GetFormItemByLabel returns the first form element with the given label. If
|
||||
|
@ -558,22 +547,20 @@ func (f *Form) GetFocusedItemIndex() (formItem, button int) {
|
|||
// selection to the first item (similarly in the other direction). If set to
|
||||
// false, the selection won't change when navigating downwards on the last item
|
||||
// or navigating upwards on the first item.
|
||||
func (f *Form) SetWrapAround(wrapAround bool) *Form {
|
||||
func (f *Form) SetWrapAround(wrapAround bool) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.wrapAround = wrapAround
|
||||
return f
|
||||
}
|
||||
|
||||
// SetCancelFunc sets a handler which is called when the user hits the Escape
|
||||
// key.
|
||||
func (f *Form) SetCancelFunc(callback func()) *Form {
|
||||
func (f *Form) SetCancelFunc(callback func()) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.cancel = callback
|
||||
return f
|
||||
}
|
||||
|
||||
// GetAttributes returns the current attribute settings of a form.
|
||||
|
@ -732,10 +719,10 @@ func (f *Form) Draw(screen tcell.Screen) {
|
|||
if buttonWidth > space {
|
||||
buttonWidth = space
|
||||
}
|
||||
button.SetLabelColor(f.buttonTextColor).
|
||||
SetLabelColorFocused(f.buttonTextColorFocused).
|
||||
SetBackgroundColorFocused(f.buttonBackgroundColorFocused).
|
||||
SetBackgroundColor(f.buttonBackgroundColor)
|
||||
button.SetLabelColor(f.buttonTextColor)
|
||||
button.SetLabelColorFocused(f.buttonTextColorFocused)
|
||||
button.SetBackgroundColorFocused(f.buttonBackgroundColorFocused)
|
||||
button.SetBackgroundColor(f.buttonBackgroundColor)
|
||||
|
||||
buttonIndex := index + len(f.items)
|
||||
positions[buttonIndex].x = x
|
||||
|
|
9
frame.go
9
frame.go
|
@ -58,7 +58,7 @@ func NewFrame(primitive Primitive) *Frame {
|
|||
// the Align constants. Rows in the header are printed top to bottom, rows in
|
||||
// the footer are printed bottom to top. Note that long text can overlap as
|
||||
// different alignments will be placed on the same row.
|
||||
func (f *Frame) AddText(text string, header bool, align int, color tcell.Color) *Frame {
|
||||
func (f *Frame) AddText(text string, header bool, align int, color tcell.Color) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
|
@ -68,27 +68,24 @@ func (f *Frame) AddText(text string, header bool, align int, color tcell.Color)
|
|||
Align: align,
|
||||
Color: color,
|
||||
})
|
||||
return f
|
||||
}
|
||||
|
||||
// Clear removes all text from the frame.
|
||||
func (f *Frame) Clear() *Frame {
|
||||
func (f *Frame) Clear() {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.text = nil
|
||||
return f
|
||||
}
|
||||
|
||||
// SetBorders sets the width of the frame borders as well as "header" and
|
||||
// "footer", the vertical space between the header and footer text and the
|
||||
// contained primitive (does not apply if there is no text).
|
||||
func (f *Frame) SetBorders(top, bottom, header, footer, left, right int) *Frame {
|
||||
func (f *Frame) SetBorders(top, bottom, header, footer, left, right int) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.top, f.bottom, f.header, f.footer, f.left, f.right = top, bottom, header, footer, left, right
|
||||
return f
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
|
|
36
grid.go
36
grid.go
|
@ -68,9 +68,10 @@ type Grid struct {
|
|||
// grid.SetBackgroundTransparent(false)
|
||||
func NewGrid() *Grid {
|
||||
g := &Grid{
|
||||
Box: NewBox().SetBackgroundTransparent(true),
|
||||
Box: NewBox(),
|
||||
bordersColor: Styles.GraphicsColor,
|
||||
}
|
||||
g.SetBackgroundTransparent(true)
|
||||
g.focus = g
|
||||
return g
|
||||
}
|
||||
|
@ -104,12 +105,11 @@ func NewGrid() *Grid {
|
|||
//
|
||||
// The resulting widths would be: 30, 15, 15, 15, 20, 15, and 15 cells, a total
|
||||
// of 125 cells, 25 cells wider than the available grid width.
|
||||
func (g *Grid) SetColumns(columns ...int) *Grid {
|
||||
func (g *Grid) SetColumns(columns ...int) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
g.columns = columns
|
||||
return g
|
||||
}
|
||||
|
||||
// SetRows defines how the rows of the grid are distributed. These values behave
|
||||
|
@ -118,17 +118,16 @@ func (g *Grid) SetColumns(columns ...int) *Grid {
|
|||
//
|
||||
// The provided values correspond to row heights, the first value defining
|
||||
// the height of the topmost row.
|
||||
func (g *Grid) SetRows(rows ...int) *Grid {
|
||||
func (g *Grid) SetRows(rows ...int) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
g.rows = rows
|
||||
return g
|
||||
}
|
||||
|
||||
// SetSize is a shortcut for SetRows() and SetColumns() where all row and column
|
||||
// values are set to the given size values. See SetColumns() for details on sizes.
|
||||
func (g *Grid) SetSize(numRows, numColumns, rowSize, columnSize int) *Grid {
|
||||
func (g *Grid) SetSize(numRows, numColumns, rowSize, columnSize int) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
|
@ -140,12 +139,11 @@ func (g *Grid) SetSize(numRows, numColumns, rowSize, columnSize int) *Grid {
|
|||
for index := range g.columns {
|
||||
g.columns[index] = columnSize
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
// SetMinSize sets an absolute minimum width for rows and an absolute minimum
|
||||
// height for columns. Panics if negative values are provided.
|
||||
func (g *Grid) SetMinSize(row, column int) *Grid {
|
||||
func (g *Grid) SetMinSize(row, column int) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
|
@ -153,13 +151,12 @@ func (g *Grid) SetMinSize(row, column int) *Grid {
|
|||
panic("Invalid minimum row/column size")
|
||||
}
|
||||
g.minHeight, g.minWidth = row, column
|
||||
return g
|
||||
}
|
||||
|
||||
// SetGap sets the size of the gaps between neighboring primitives on the grid.
|
||||
// If borders are drawn (see SetBorders()), these values are ignored and a gap
|
||||
// of 1 is assumed. Panics if negative values are provided.
|
||||
func (g *Grid) SetGap(row, column int) *Grid {
|
||||
func (g *Grid) SetGap(row, column int) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
|
@ -167,27 +164,24 @@ func (g *Grid) SetGap(row, column int) *Grid {
|
|||
panic("Invalid gap size")
|
||||
}
|
||||
g.gapRows, g.gapColumns = row, column
|
||||
return g
|
||||
}
|
||||
|
||||
// SetBorders sets whether or not borders are drawn around grid items. Setting
|
||||
// this value to true will cause the gap values (see SetGap()) to be ignored and
|
||||
// automatically assumed to be 1 where the border graphics are drawn.
|
||||
func (g *Grid) SetBorders(borders bool) *Grid {
|
||||
func (g *Grid) SetBorders(borders bool) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
g.borders = borders
|
||||
return g
|
||||
}
|
||||
|
||||
// SetBordersColor sets the color of the item borders.
|
||||
func (g *Grid) SetBordersColor(color tcell.Color) *Grid {
|
||||
func (g *Grid) SetBordersColor(color tcell.Color) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
g.bordersColor = color
|
||||
return g
|
||||
}
|
||||
|
||||
// AddItem adds a primitive and its position to the grid. The top-left corner
|
||||
|
@ -216,7 +210,7 @@ func (g *Grid) SetBordersColor(color tcell.Color) *Grid {
|
|||
// If the item's focus is set to true, it will receive focus when the grid
|
||||
// receives focus. If there are multiple items with a true focus flag, the last
|
||||
// visible one that was added will receive focus.
|
||||
func (g *Grid) AddItem(p Primitive, row, column, rowSpan, colSpan, minGridHeight, minGridWidth int, focus bool) *Grid {
|
||||
func (g *Grid) AddItem(p Primitive, row, column, rowSpan, colSpan, minGridHeight, minGridWidth int, focus bool) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
|
@ -230,12 +224,11 @@ func (g *Grid) AddItem(p Primitive, row, column, rowSpan, colSpan, minGridHeight
|
|||
MinGridWidth: minGridWidth,
|
||||
Focus: focus,
|
||||
})
|
||||
return g
|
||||
}
|
||||
|
||||
// RemoveItem removes all items for the given primitive from the grid, keeping
|
||||
// the order of the remaining items intact.
|
||||
func (g *Grid) RemoveItem(p Primitive) *Grid {
|
||||
func (g *Grid) RemoveItem(p Primitive) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
|
@ -244,16 +237,14 @@ func (g *Grid) RemoveItem(p Primitive) *Grid {
|
|||
g.items = append(g.items[:index], g.items[index+1:]...)
|
||||
}
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
// Clear removes all items from the grid.
|
||||
func (g *Grid) Clear() *Grid {
|
||||
func (g *Grid) Clear() {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
g.items = nil
|
||||
return g
|
||||
}
|
||||
|
||||
// SetOffset sets the number of rows and columns which are skipped before
|
||||
|
@ -261,12 +252,11 @@ func (g *Grid) Clear() *Grid {
|
|||
// completely move off the screen, these values may be adjusted the next time
|
||||
// the grid is drawn. The actual position of the grid may also be adjusted such
|
||||
// that contained primitives that have focus remain visible.
|
||||
func (g *Grid) SetOffset(rows, columns int) *Grid {
|
||||
func (g *Grid) SetOffset(rows, columns int) {
|
||||
g.Lock()
|
||||
defer g.Unlock()
|
||||
|
||||
g.rowOffset, g.columnOffset = rows, columns
|
||||
return g
|
||||
}
|
||||
|
||||
// GetOffset returns the current row and column offset (see SetOffset() for
|
||||
|
|
108
inputfield.go
108
inputfield.go
|
@ -161,7 +161,7 @@ func NewInputField() *InputField {
|
|||
}
|
||||
|
||||
// SetText sets the current text of the input field.
|
||||
func (i *InputField) SetText(text string) *InputField {
|
||||
func (i *InputField) SetText(text string) {
|
||||
i.Lock()
|
||||
|
||||
i.text = []byte(text)
|
||||
|
@ -172,8 +172,6 @@ func (i *InputField) SetText(text string) *InputField {
|
|||
} else {
|
||||
i.Unlock()
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
// GetText returns the current text of the input field.
|
||||
|
@ -185,12 +183,11 @@ func (i *InputField) GetText() string {
|
|||
}
|
||||
|
||||
// SetLabel sets the text to be displayed before the input area.
|
||||
func (i *InputField) SetLabel(label string) *InputField {
|
||||
func (i *InputField) SetLabel(label string) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.label = []byte(label)
|
||||
return i
|
||||
}
|
||||
|
||||
// GetLabel returns the text to be displayed before the input area.
|
||||
|
@ -203,182 +200,163 @@ func (i *InputField) GetLabel() string {
|
|||
|
||||
// SetLabelWidth sets the screen width of the label. A value of 0 will cause the
|
||||
// primitive to use the width of the label string.
|
||||
func (i *InputField) SetLabelWidth(width int) *InputField {
|
||||
func (i *InputField) SetLabelWidth(width int) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.labelWidth = width
|
||||
return i
|
||||
}
|
||||
|
||||
// SetPlaceholder sets the text to be displayed when the input text is empty.
|
||||
func (i *InputField) SetPlaceholder(text string) *InputField {
|
||||
func (i *InputField) SetPlaceholder(text string) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.placeholder = []byte(text)
|
||||
return i
|
||||
}
|
||||
|
||||
// SetLabelColor sets the color of the label.
|
||||
func (i *InputField) SetLabelColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetLabelColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.labelColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetLabelColorFocused sets the color of the label when focused.
|
||||
func (i *InputField) SetLabelColorFocused(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetLabelColorFocused(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.labelColorFocused = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFieldBackgroundColor sets the background color of the input area.
|
||||
func (i *InputField) SetFieldBackgroundColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetFieldBackgroundColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.fieldBackgroundColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFieldBackgroundColorFocused sets the background color of the input area
|
||||
// when focused.
|
||||
func (i *InputField) SetFieldBackgroundColorFocused(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetFieldBackgroundColorFocused(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.fieldBackgroundColorFocused = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFieldTextColor sets the text color of the input area.
|
||||
func (i *InputField) SetFieldTextColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetFieldTextColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.fieldTextColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFieldTextColorFocused sets the text color of the input area when focused.
|
||||
func (i *InputField) SetFieldTextColorFocused(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetFieldTextColorFocused(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.fieldTextColorFocused = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetPlaceholderTextColor sets the text color of placeholder text.
|
||||
func (i *InputField) SetPlaceholderTextColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetPlaceholderTextColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.placeholderTextColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetPlaceholderTextColorFocused sets the text color of placeholder text when
|
||||
// focused.
|
||||
func (i *InputField) SetPlaceholderTextColorFocused(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetPlaceholderTextColorFocused(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.placeholderTextColorFocused = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetAutocompleteListTextColor sets the text color of the ListItems.
|
||||
func (i *InputField) SetAutocompleteListTextColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetAutocompleteListTextColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.autocompleteListTextColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetAutocompleteListBackgroundColor sets the background color of the
|
||||
// autocomplete list.
|
||||
func (i *InputField) SetAutocompleteListBackgroundColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetAutocompleteListBackgroundColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.autocompleteListBackgroundColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetAutocompleteListSelectedTextColor sets the text color of the selected
|
||||
// ListItem.
|
||||
func (i *InputField) SetAutocompleteListSelectedTextColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetAutocompleteListSelectedTextColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.autocompleteListSelectedTextColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetAutocompleteListSelectedBackgroundColor sets the background of the
|
||||
// selected ListItem.
|
||||
func (i *InputField) SetAutocompleteListSelectedBackgroundColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetAutocompleteListSelectedBackgroundColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.autocompleteListSelectedBackgroundColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetAutocompleteSuggestionTextColor sets the text color of the autocomplete
|
||||
// suggestion in the input field.
|
||||
func (i *InputField) SetAutocompleteSuggestionTextColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetAutocompleteSuggestionTextColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.autocompleteSuggestionTextColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFieldNoteTextColor sets the text color of the note.
|
||||
func (i *InputField) SetFieldNoteTextColor(color tcell.Color) *InputField {
|
||||
func (i *InputField) SetFieldNoteTextColor(color tcell.Color) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.fieldNoteTextColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFieldNote sets the text to show below the input field, e.g. when the
|
||||
// input is invalid.
|
||||
func (i *InputField) SetFieldNote(note string) *InputField {
|
||||
func (i *InputField) SetFieldNote(note string) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.fieldNote = []byte(note)
|
||||
return i
|
||||
}
|
||||
|
||||
// ResetFieldNote sets the note to an empty string.
|
||||
func (i *InputField) ResetFieldNote() *InputField {
|
||||
func (i *InputField) ResetFieldNote() {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.fieldNote = nil
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFieldWidth sets the screen width of the input area. A value of 0 means
|
||||
// extend as much as possible.
|
||||
func (i *InputField) SetFieldWidth(width int) *InputField {
|
||||
func (i *InputField) SetFieldWidth(width int) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.fieldWidth = width
|
||||
return i
|
||||
}
|
||||
|
||||
// GetFieldWidth returns this primitive's field width.
|
||||
|
@ -417,12 +395,11 @@ func (i *InputField) SetCursorPosition(cursorPos int) {
|
|||
|
||||
// SetMaskCharacter sets a character that masks user input on a screen. A value
|
||||
// of 0 disables masking.
|
||||
func (i *InputField) SetMaskCharacter(mask rune) *InputField {
|
||||
func (i *InputField) SetMaskCharacter(mask rune) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.maskCharacter = mask
|
||||
return i
|
||||
}
|
||||
|
||||
// SetAutocompleteFunc sets an autocomplete callback function which may return
|
||||
|
@ -431,13 +408,12 @@ func (i *InputField) SetMaskCharacter(mask rune) *InputField {
|
|||
// invoked in this function and whenever the current text changes or when
|
||||
// Autocomplete() is called. Entries are cleared when the user selects an entry
|
||||
// or presses Escape.
|
||||
func (i *InputField) SetAutocompleteFunc(callback func(currentText string) (entries []*ListItem)) *InputField {
|
||||
func (i *InputField) SetAutocompleteFunc(callback func(currentText string) (entries []*ListItem)) {
|
||||
i.Lock()
|
||||
i.autocomplete = callback
|
||||
i.Unlock()
|
||||
|
||||
i.Autocomplete()
|
||||
return i
|
||||
}
|
||||
|
||||
// Autocomplete invokes the autocomplete callback (if there is one). If the
|
||||
|
@ -448,11 +424,11 @@ func (i *InputField) SetAutocompleteFunc(callback func(currentText string) (entr
|
|||
// It is safe to call this function from any goroutine. Note that the input
|
||||
// field is not redrawn automatically unless called from the main goroutine
|
||||
// (e.g. in response to events).
|
||||
func (i *InputField) Autocomplete() *InputField {
|
||||
func (i *InputField) Autocomplete() {
|
||||
i.Lock()
|
||||
if i.autocomplete == nil {
|
||||
i.Unlock()
|
||||
return i
|
||||
return
|
||||
}
|
||||
i.Unlock()
|
||||
|
||||
|
@ -464,22 +440,23 @@ func (i *InputField) Autocomplete() *InputField {
|
|||
i.autocompleteList = nil
|
||||
i.autocompleteListSuggestion = nil
|
||||
i.Unlock()
|
||||
return i
|
||||
return
|
||||
}
|
||||
|
||||
i.Lock()
|
||||
|
||||
// Make a list if we have none.
|
||||
if i.autocompleteList == nil {
|
||||
i.autocompleteList = NewList()
|
||||
i.autocompleteList.
|
||||
SetChangedFunc(i.autocompleteChanged).
|
||||
ShowSecondaryText(false).
|
||||
SetMainTextColor(i.autocompleteListTextColor).
|
||||
SetSelectedTextColor(i.autocompleteListSelectedTextColor).
|
||||
SetSelectedBackgroundColor(i.autocompleteListSelectedBackgroundColor).
|
||||
SetHighlightFullLine(true).
|
||||
SetBackgroundColor(i.autocompleteListBackgroundColor)
|
||||
l := NewList()
|
||||
l.SetChangedFunc(i.autocompleteChanged)
|
||||
l.ShowSecondaryText(false)
|
||||
l.SetMainTextColor(i.autocompleteListTextColor)
|
||||
l.SetSelectedTextColor(i.autocompleteListSelectedTextColor)
|
||||
l.SetSelectedBackgroundColor(i.autocompleteListSelectedBackgroundColor)
|
||||
l.SetHighlightFullLine(true)
|
||||
l.SetBackgroundColor(i.autocompleteListBackgroundColor)
|
||||
|
||||
i.autocompleteList = l
|
||||
}
|
||||
|
||||
// Fill it with the entries.
|
||||
|
@ -499,7 +476,6 @@ func (i *InputField) Autocomplete() *InputField {
|
|||
}
|
||||
|
||||
i.Unlock()
|
||||
return i
|
||||
}
|
||||
|
||||
// autocompleteChanged gets called when another item in the
|
||||
|
@ -521,22 +497,20 @@ func (i *InputField) autocompleteChanged(_ int, item *ListItem) {
|
|||
//
|
||||
// This package defines a number of variables prefixed with InputField which may
|
||||
// be used for common input (e.g. numbers, maximum text length).
|
||||
func (i *InputField) SetAcceptanceFunc(handler func(textToCheck string, lastChar rune) bool) *InputField {
|
||||
func (i *InputField) SetAcceptanceFunc(handler func(textToCheck string, lastChar rune) bool) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.accept = handler
|
||||
return i
|
||||
}
|
||||
|
||||
// SetChangedFunc sets a handler which is called whenever the text of the input
|
||||
// field has changed. It receives the current text (after the change).
|
||||
func (i *InputField) SetChangedFunc(handler func(text string)) *InputField {
|
||||
func (i *InputField) SetChangedFunc(handler func(text string)) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.changed = handler
|
||||
return i
|
||||
}
|
||||
|
||||
// SetDoneFunc sets a handler which is called when the user is done entering
|
||||
|
@ -547,21 +521,19 @@ func (i *InputField) SetChangedFunc(handler func(text string)) *InputField {
|
|||
// - KeyEscape: Abort text input.
|
||||
// - KeyTab: Move to the next field.
|
||||
// - KeyBacktab: Move to the previous field.
|
||||
func (i *InputField) SetDoneFunc(handler func(key tcell.Key)) *InputField {
|
||||
func (i *InputField) SetDoneFunc(handler func(key tcell.Key)) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.done = handler
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFinishedFunc sets a callback invoked when the user leaves this form item.
|
||||
func (i *InputField) SetFinishedFunc(handler func(key tcell.Key)) *InputField {
|
||||
func (i *InputField) SetFinishedFunc(handler func(key tcell.Key)) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.finished = handler
|
||||
return i
|
||||
}
|
||||
|
||||
// SetAttributes applies attribute settings to a form item.
|
||||
|
|
108
list.go
108
list.go
|
@ -30,17 +30,16 @@ func NewListItem(mainText string) *ListItem {
|
|||
}
|
||||
|
||||
// SetMainBytes sets the main text of the list item.
|
||||
func (l *ListItem) SetMainBytes(val []byte) *ListItem {
|
||||
func (l *ListItem) SetMainBytes(val []byte) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.mainText = val
|
||||
return l
|
||||
}
|
||||
|
||||
// SetMainText sets the main text of the list item.
|
||||
func (l *ListItem) SetMainText(val string) *ListItem {
|
||||
return l.SetMainBytes([]byte(val))
|
||||
func (l *ListItem) SetMainText(val string) {
|
||||
l.SetMainBytes([]byte(val))
|
||||
}
|
||||
|
||||
// GetMainBytes returns the item's main text.
|
||||
|
@ -57,17 +56,16 @@ func (l *ListItem) GetMainText() string {
|
|||
}
|
||||
|
||||
// SetSecondaryBytes sets a secondary text to be shown underneath the main text.
|
||||
func (l *ListItem) SetSecondaryBytes(val []byte) *ListItem {
|
||||
func (l *ListItem) SetSecondaryBytes(val []byte) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.secondaryText = val
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSecondaryText sets a secondary text to be shown underneath the main text.
|
||||
func (l *ListItem) SetSecondaryText(val string) *ListItem {
|
||||
return l.SetSecondaryBytes([]byte(val))
|
||||
func (l *ListItem) SetSecondaryText(val string) {
|
||||
l.SetSecondaryBytes([]byte(val))
|
||||
}
|
||||
|
||||
// GetSecondaryBytes returns the item's secondary text.
|
||||
|
@ -84,12 +82,11 @@ func (l *ListItem) GetSecondaryText() string {
|
|||
}
|
||||
|
||||
// SetShortcut sets the key to select the ListItem directly, 0 if there is no shortcut.
|
||||
func (l *ListItem) SetShortcut(val rune) *ListItem {
|
||||
func (l *ListItem) SetShortcut(val rune) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.shortcut = val
|
||||
return l
|
||||
}
|
||||
|
||||
// GetShortcut returns the ListItem's shortcut.
|
||||
|
@ -101,21 +98,19 @@ func (l *ListItem) GetShortcut() rune {
|
|||
}
|
||||
|
||||
// SetSelectedFunc sets a function which is called when the ListItem is selected.
|
||||
func (l *ListItem) SetSelectedFunc(handler func()) *ListItem {
|
||||
func (l *ListItem) SetSelectedFunc(handler func()) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.selected = handler
|
||||
return l
|
||||
}
|
||||
|
||||
// SetReference allows you to store a reference of any type in the item
|
||||
func (l *ListItem) SetReference(val interface{}) *ListItem {
|
||||
func (l *ListItem) SetReference(val interface{}) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.reference = val
|
||||
return l
|
||||
}
|
||||
|
||||
// GetReference returns the item's reference object.
|
||||
|
@ -228,7 +223,7 @@ func NewList() *List {
|
|||
// range indices are clamped to the beginning/end.
|
||||
//
|
||||
// Calling this function triggers a "changed" event if the selection changes.
|
||||
func (l *List) SetCurrentItem(index int) *List {
|
||||
func (l *List) SetCurrentItem(index int) {
|
||||
l.Lock()
|
||||
|
||||
if index < 0 {
|
||||
|
@ -254,7 +249,6 @@ func (l *List) SetCurrentItem(index int) *List {
|
|||
}
|
||||
|
||||
l.Unlock()
|
||||
return l
|
||||
}
|
||||
|
||||
// GetCurrentItem returns the currently selected list item,
|
||||
|
@ -292,12 +286,12 @@ func (l *List) GetItems() []*ListItem {
|
|||
//
|
||||
// The currently selected item is shifted accordingly. If it is the one that is
|
||||
// removed, a "changed" event is fired.
|
||||
func (l *List) RemoveItem(index int) *List {
|
||||
func (l *List) RemoveItem(index int) {
|
||||
l.Lock()
|
||||
|
||||
if len(l.items) == 0 {
|
||||
l.Unlock()
|
||||
return l
|
||||
return
|
||||
}
|
||||
|
||||
// Adjust index.
|
||||
|
@ -317,7 +311,7 @@ func (l *List) RemoveItem(index int) *List {
|
|||
// If there is nothing left, we're done.
|
||||
if len(l.items) == 0 {
|
||||
l.Unlock()
|
||||
return l
|
||||
return
|
||||
}
|
||||
|
||||
// Shift current item.
|
||||
|
@ -334,13 +328,11 @@ func (l *List) RemoveItem(index int) *List {
|
|||
} else {
|
||||
l.Unlock()
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// SetOffset sets the number of list items skipped at the top before the first
|
||||
// item is drawn.
|
||||
func (l *List) SetOffset(offset int) *List {
|
||||
func (l *List) SetOffset(offset int) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
|
@ -349,7 +341,6 @@ func (l *List) SetOffset(offset int) *List {
|
|||
}
|
||||
|
||||
l.offset = offset
|
||||
return l
|
||||
}
|
||||
|
||||
// GetOffset returns the number of list items skipped at the top before the
|
||||
|
@ -362,137 +353,124 @@ func (l *List) GetOffset() int {
|
|||
}
|
||||
|
||||
// SetMainTextColor sets the color of the items' main text.
|
||||
func (l *List) SetMainTextColor(color tcell.Color) *List {
|
||||
func (l *List) SetMainTextColor(color tcell.Color) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.mainTextColor = color
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSecondaryTextColor sets the color of the items' secondary text.
|
||||
func (l *List) SetSecondaryTextColor(color tcell.Color) *List {
|
||||
func (l *List) SetSecondaryTextColor(color tcell.Color) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.secondaryTextColor = color
|
||||
return l
|
||||
}
|
||||
|
||||
// SetShortcutColor sets the color of the items' shortcut.
|
||||
func (l *List) SetShortcutColor(color tcell.Color) *List {
|
||||
func (l *List) SetShortcutColor(color tcell.Color) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.shortcutColor = color
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSelectedTextColor sets the text color of selected items.
|
||||
func (l *List) SetSelectedTextColor(color tcell.Color) *List {
|
||||
func (l *List) SetSelectedTextColor(color tcell.Color) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.selectedTextColor = color
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSelectedTextAttributes sets the style attributes of selected items.
|
||||
func (l *List) SetSelectedTextAttributes(attr tcell.AttrMask) *List {
|
||||
func (l *List) SetSelectedTextAttributes(attr tcell.AttrMask) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.selectedTextAttributes = attr
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSelectedBackgroundColor sets the background color of selected items.
|
||||
func (l *List) SetSelectedBackgroundColor(color tcell.Color) *List {
|
||||
func (l *List) SetSelectedBackgroundColor(color tcell.Color) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.selectedBackgroundColor = color
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSelectedFocusOnly sets a flag which determines when the currently selected
|
||||
// list item is highlighted. If set to true, selected items are only highlighted
|
||||
// when the list has focus. If set to false, they are always highlighted.
|
||||
func (l *List) SetSelectedFocusOnly(focusOnly bool) *List {
|
||||
func (l *List) SetSelectedFocusOnly(focusOnly bool) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.selectedFocusOnly = focusOnly
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSelectedAlwaysVisible sets a flag which determines whether the currently
|
||||
// selected list item must remain visible when scrolling.
|
||||
func (l *List) SetSelectedAlwaysVisible(alwaysVisible bool) *List {
|
||||
func (l *List) SetSelectedAlwaysVisible(alwaysVisible bool) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.selectedAlwaysVisible = alwaysVisible
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSelectedAlwaysCentered sets a flag which determines whether the currently
|
||||
// selected list item must remain centered when scrolling.
|
||||
func (l *List) SetSelectedAlwaysCentered(alwaysCentered bool) *List {
|
||||
func (l *List) SetSelectedAlwaysCentered(alwaysCentered bool) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.selectedAlwaysCentered = alwaysCentered
|
||||
return l
|
||||
}
|
||||
|
||||
// SetHighlightFullLine sets a flag which determines whether the colored
|
||||
// background of selected items spans the entire width of the view. If set to
|
||||
// true, the highlight spans the entire view. If set to false, only the text of
|
||||
// the selected item from beginning to end is highlighted.
|
||||
func (l *List) SetHighlightFullLine(highlight bool) *List {
|
||||
func (l *List) SetHighlightFullLine(highlight bool) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.highlightFullLine = highlight
|
||||
return l
|
||||
}
|
||||
|
||||
// ShowSecondaryText determines whether or not to show secondary item texts.
|
||||
func (l *List) ShowSecondaryText(show bool) *List {
|
||||
func (l *List) ShowSecondaryText(show bool) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.showSecondaryText = show
|
||||
return l
|
||||
return
|
||||
}
|
||||
|
||||
// SetScrollBarVisibility specifies the display of the scroll bar.
|
||||
func (l *List) SetScrollBarVisibility(visibility ScrollBarVisibility) *List {
|
||||
func (l *List) SetScrollBarVisibility(visibility ScrollBarVisibility) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.scrollBarVisibility = visibility
|
||||
return l
|
||||
}
|
||||
|
||||
// SetScrollBarColor sets the color of the scroll bar.
|
||||
func (l *List) SetScrollBarColor(color tcell.Color) *List {
|
||||
func (l *List) SetScrollBarColor(color tcell.Color) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.scrollBarColor = color
|
||||
return l
|
||||
}
|
||||
|
||||
// SetHover sets the flag that determines whether hovering over an item will
|
||||
// highlight it (without triggering callbacks set with SetSelectedFunc).
|
||||
func (l *List) SetHover(hover bool) *List {
|
||||
func (l *List) SetHover(hover bool) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.hover = hover
|
||||
return l
|
||||
}
|
||||
|
||||
// SetWrapAround sets the flag that determines whether navigating the list will
|
||||
|
@ -500,12 +478,11 @@ func (l *List) SetHover(hover bool) *List {
|
|||
// selection to the first item (similarly in the other direction). If set to
|
||||
// false, the selection won't change when navigating downwards on the last item
|
||||
// or navigating upwards on the first item.
|
||||
func (l *List) SetWrapAround(wrapAround bool) *List {
|
||||
func (l *List) SetWrapAround(wrapAround bool) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.wrapAround = wrapAround
|
||||
return l
|
||||
}
|
||||
|
||||
// SetChangedFunc sets the function which is called when the user navigates to
|
||||
|
@ -514,39 +491,35 @@ func (l *List) SetWrapAround(wrapAround bool) *List {
|
|||
//
|
||||
// This function is also called when the first item is added or when
|
||||
// SetCurrentItem() is called.
|
||||
func (l *List) SetChangedFunc(handler func(index int, item *ListItem)) *List {
|
||||
func (l *List) SetChangedFunc(handler func(index int, item *ListItem)) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.changed = handler
|
||||
return l
|
||||
}
|
||||
|
||||
// SetSelectedFunc sets the function which is called when the user selects a
|
||||
// list item by pressing Enter on the current selection. The function receives
|
||||
// the item's index in the list of items (starting with 0) and its struct.
|
||||
func (l *List) SetSelectedFunc(handler func(int, *ListItem)) *List {
|
||||
func (l *List) SetSelectedFunc(handler func(int, *ListItem)) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.selected = handler
|
||||
return l
|
||||
}
|
||||
|
||||
// SetDoneFunc sets a function which is called when the user presses the Escape
|
||||
// key.
|
||||
func (l *List) SetDoneFunc(handler func()) *List {
|
||||
func (l *List) SetDoneFunc(handler func()) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.done = handler
|
||||
return l
|
||||
}
|
||||
|
||||
// AddItem calls InsertItem() with an index of -1.
|
||||
func (l *List) AddItem(item *ListItem) *List {
|
||||
func (l *List) AddItem(item *ListItem) {
|
||||
l.InsertItem(-1, item)
|
||||
return l
|
||||
}
|
||||
|
||||
// InsertItem adds a new item to the list at the specified index. An index of 0
|
||||
|
@ -571,7 +544,7 @@ func (l *List) AddItem(item *ListItem) *List {
|
|||
// The currently selected item will shift its position accordingly. If the list
|
||||
// was previously empty, a "changed" event is fired because the new item becomes
|
||||
// selected.
|
||||
func (l *List) InsertItem(index int, item *ListItem) *List {
|
||||
func (l *List) InsertItem(index int, item *ListItem) {
|
||||
l.Lock()
|
||||
|
||||
item.enabled = true
|
||||
|
@ -606,8 +579,6 @@ func (l *List) InsertItem(index int, item *ListItem) *List {
|
|||
} else {
|
||||
l.Unlock()
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// GetItem returns the ListItem at the given index.
|
||||
|
@ -637,25 +608,23 @@ func (l *List) GetItemText(index int) (main, secondary string) {
|
|||
|
||||
// SetItemText sets an item's main and secondary text. Panics if the index is
|
||||
// out of range.
|
||||
func (l *List) SetItemText(index int, main, secondary string) *List {
|
||||
func (l *List) SetItemText(index int, main, secondary string) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
item := l.items[index]
|
||||
item.mainText = []byte(main)
|
||||
item.secondaryText = []byte(secondary)
|
||||
return l
|
||||
}
|
||||
|
||||
// SetItemEnabled sets whether an item is selectable. Panics if the index is
|
||||
// out of range.
|
||||
func (l *List) SetItemEnabled(index int, enabled bool) *List {
|
||||
func (l *List) SetItemEnabled(index int, enabled bool) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
item := l.items[index]
|
||||
item.enabled = enabled
|
||||
return l
|
||||
}
|
||||
|
||||
// FindItems searches the main and secondary texts for the given strings and
|
||||
|
@ -705,14 +674,13 @@ func (l *List) FindItems(mainSearch, secondarySearch string, mustContainBoth, ig
|
|||
}
|
||||
|
||||
// Clear removes all items from the list.
|
||||
func (l *List) Clear() *List {
|
||||
func (l *List) Clear() {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
l.items = nil
|
||||
l.currentItem = 0
|
||||
l.offset = 0
|
||||
return l
|
||||
}
|
||||
|
||||
// Focus is called by the application when the primitive receives focus.
|
||||
|
|
10
list_test.go
10
list_test.go
|
@ -24,7 +24,10 @@ func TestList(t *testing.T) {
|
|||
|
||||
// Add item 0
|
||||
|
||||
l.AddItem(NewListItem(listTextA).SetSecondaryText(listTextB).SetShortcut('a'))
|
||||
itemA := NewListItem(listTextA)
|
||||
itemA.SetSecondaryText(listTextB)
|
||||
itemA.SetShortcut('a')
|
||||
l.AddItem(itemA)
|
||||
if l.GetItemCount() != 1 {
|
||||
t.Errorf("failed to update List: expected item count 1, got %d", l.GetItemCount())
|
||||
} else if l.GetCurrentItemIndex() != 0 {
|
||||
|
@ -42,7 +45,10 @@ func TestList(t *testing.T) {
|
|||
|
||||
// Add item 1
|
||||
|
||||
l.AddItem(NewListItem(listTextB).SetSecondaryText(listTextC).SetShortcut('a'))
|
||||
itemB := NewListItem(listTextB)
|
||||
itemB.SetSecondaryText(listTextC)
|
||||
itemB.SetShortcut('a')
|
||||
l.AddItem(itemB)
|
||||
if l.GetItemCount() != 2 {
|
||||
t.Errorf("failed to update List: expected item count 1, got %v", l.GetItemCount())
|
||||
} else if l.GetCurrentItemIndex() != 0 {
|
||||
|
|
50
modal.go
50
modal.go
|
@ -40,82 +40,81 @@ func NewModal() *Modal {
|
|||
Box: NewBox(),
|
||||
textColor: Styles.PrimaryTextColor,
|
||||
}
|
||||
m.form = NewForm().
|
||||
SetButtonsAlign(AlignCenter).
|
||||
SetButtonBackgroundColor(Styles.PrimitiveBackgroundColor).
|
||||
SetButtonTextColor(Styles.PrimaryTextColor)
|
||||
m.form.SetBackgroundColor(Styles.ContrastBackgroundColor).SetBorderPadding(0, 0, 0, 0)
|
||||
|
||||
m.form = NewForm()
|
||||
m.form.SetButtonsAlign(AlignCenter)
|
||||
m.form.SetButtonBackgroundColor(Styles.PrimitiveBackgroundColor)
|
||||
m.form.SetButtonTextColor(Styles.PrimaryTextColor)
|
||||
m.form.SetBackgroundColor(Styles.ContrastBackgroundColor)
|
||||
m.form.SetBorderPadding(0, 0, 0, 0)
|
||||
m.form.SetCancelFunc(func() {
|
||||
if m.done != nil {
|
||||
m.done(-1, "")
|
||||
}
|
||||
})
|
||||
m.frame = NewFrame(m.form).SetBorders(0, 0, 1, 0, 0, 0)
|
||||
m.frame.SetBorder(true).
|
||||
SetBackgroundColor(Styles.ContrastBackgroundColor).
|
||||
SetBorderPadding(1, 1, 1, 1)
|
||||
|
||||
m.frame = NewFrame(m.form)
|
||||
m.frame.SetBorder(true)
|
||||
m.frame.SetBorders(0, 0, 1, 0, 0, 0)
|
||||
m.frame.SetBackgroundColor(Styles.ContrastBackgroundColor)
|
||||
m.frame.SetBorderPadding(1, 1, 1, 1)
|
||||
|
||||
m.focus = m
|
||||
return m
|
||||
}
|
||||
|
||||
// SetBackgroundColor sets the color of the Modal Frame background.
|
||||
func (m *Modal) SetBackgroundColor(color tcell.Color) *Modal {
|
||||
func (m *Modal) SetBackgroundColor(color tcell.Color) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.form.SetBackgroundColor(color)
|
||||
m.frame.SetBackgroundColor(color)
|
||||
return m
|
||||
}
|
||||
|
||||
// SetTextColor sets the color of the message text.
|
||||
func (m *Modal) SetTextColor(color tcell.Color) *Modal {
|
||||
func (m *Modal) SetTextColor(color tcell.Color) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.textColor = color
|
||||
return m
|
||||
}
|
||||
|
||||
// SetButtonBackgroundColor sets the background color of the buttons.
|
||||
func (m *Modal) SetButtonBackgroundColor(color tcell.Color) *Modal {
|
||||
func (m *Modal) SetButtonBackgroundColor(color tcell.Color) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.form.SetButtonBackgroundColor(color)
|
||||
return m
|
||||
}
|
||||
|
||||
// SetButtonTextColor sets the color of the button texts.
|
||||
func (m *Modal) SetButtonTextColor(color tcell.Color) *Modal {
|
||||
func (m *Modal) SetButtonTextColor(color tcell.Color) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.form.SetButtonTextColor(color)
|
||||
return m
|
||||
}
|
||||
|
||||
// SetDoneFunc sets a handler which is called when one of the buttons was
|
||||
// pressed. It receives the index of the button as well as its label text. The
|
||||
// handler is also called when the user presses the Escape key. The index will
|
||||
// then be negative and the label text an empty string.
|
||||
func (m *Modal) SetDoneFunc(handler func(buttonIndex int, buttonLabel string)) *Modal {
|
||||
func (m *Modal) SetDoneFunc(handler func(buttonIndex int, buttonLabel string)) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.done = handler
|
||||
return m
|
||||
}
|
||||
|
||||
// SetText sets the message text of the window. The text may contain line
|
||||
// breaks. Note that words are wrapped, too, based on the final size of the
|
||||
// window.
|
||||
func (m *Modal) SetText(text string) *Modal {
|
||||
func (m *Modal) SetText(text string) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.text = text
|
||||
return m
|
||||
}
|
||||
|
||||
// GetForm returns the Form embedded in the window. The returned Form may be
|
||||
|
@ -137,7 +136,7 @@ func (m *Modal) GetFrame() *Frame {
|
|||
|
||||
// AddButtons adds buttons to the window. There must be at least one button and
|
||||
// a "done" handler so the window can be closed again.
|
||||
func (m *Modal) AddButtons(labels []string) *Modal {
|
||||
func (m *Modal) AddButtons(labels []string) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
|
@ -160,25 +159,22 @@ func (m *Modal) AddButtons(labels []string) *Modal {
|
|||
})
|
||||
}(index, label)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// ClearButtons removes all buttons from the window.
|
||||
func (m *Modal) ClearButtons() *Modal {
|
||||
func (m *Modal) ClearButtons() {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.form.ClearButtons()
|
||||
return m
|
||||
}
|
||||
|
||||
// SetFocus shifts the focus to the button with the given index.
|
||||
func (m *Modal) SetFocus(index int) *Modal {
|
||||
func (m *Modal) SetFocus(index int) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.form.SetFocus(index)
|
||||
return m
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
|
|
27
pages.go
27
pages.go
|
@ -45,12 +45,11 @@ func NewPages() *Pages {
|
|||
|
||||
// SetChangedFunc sets a handler which is called whenever the visibility or the
|
||||
// order of any visible pages changes. This can be used to redraw the pages.
|
||||
func (p *Pages) SetChangedFunc(handler func()) *Pages {
|
||||
func (p *Pages) SetChangedFunc(handler func()) {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
||||
p.changed = handler
|
||||
return p
|
||||
}
|
||||
|
||||
// GetPageCount returns the number of pages currently stored in this object.
|
||||
|
@ -70,7 +69,7 @@ func (p *Pages) GetPageCount() int {
|
|||
// was changed in one of the other functions). If "resize" is set to true, the
|
||||
// primitive will be set to the size available to the Pages primitive whenever
|
||||
// the pages are drawn.
|
||||
func (p *Pages) AddPage(name string, item Primitive, resize, visible bool) *Pages {
|
||||
func (p *Pages) AddPage(name string, item Primitive, resize, visible bool) {
|
||||
hasFocus := p.HasFocus()
|
||||
|
||||
p.Lock()
|
||||
|
@ -93,20 +92,18 @@ func (p *Pages) AddPage(name string, item Primitive, resize, visible bool) *Page
|
|||
p.Focus(p.setFocus)
|
||||
p.Lock()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// AddAndSwitchToPage calls AddPage(), then SwitchToPage() on that newly added
|
||||
// page.
|
||||
func (p *Pages) AddAndSwitchToPage(name string, item Primitive, resize bool) *Pages {
|
||||
func (p *Pages) AddAndSwitchToPage(name string, item Primitive, resize bool) {
|
||||
p.AddPage(name, item, resize, true)
|
||||
p.SwitchToPage(name)
|
||||
return p
|
||||
}
|
||||
|
||||
// RemovePage removes the page with the given name. If that page was the only
|
||||
// visible page, visibility is assigned to the last page.
|
||||
func (p *Pages) RemovePage(name string) *Pages {
|
||||
func (p *Pages) RemovePage(name string) {
|
||||
hasFocus := p.HasFocus()
|
||||
|
||||
p.Lock()
|
||||
|
@ -141,7 +138,6 @@ func (p *Pages) RemovePage(name string) *Pages {
|
|||
p.Focus(p.setFocus)
|
||||
p.Lock()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// HasPage returns true if a page with the given name exists in this object.
|
||||
|
@ -159,7 +155,7 @@ func (p *Pages) HasPage(name string) bool {
|
|||
|
||||
// ShowPage sets a page's visibility to "true" (in addition to any other pages
|
||||
// which are already visible).
|
||||
func (p *Pages) ShowPage(name string) *Pages {
|
||||
func (p *Pages) ShowPage(name string) {
|
||||
hasFocus := p.HasFocus()
|
||||
|
||||
p.Lock()
|
||||
|
@ -181,11 +177,10 @@ func (p *Pages) ShowPage(name string) *Pages {
|
|||
p.Focus(p.setFocus)
|
||||
p.Lock()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// HidePage sets a page's visibility to "false".
|
||||
func (p *Pages) HidePage(name string) *Pages {
|
||||
func (p *Pages) HidePage(name string) {
|
||||
hasFocus := p.HasFocus()
|
||||
|
||||
p.Lock()
|
||||
|
@ -207,12 +202,11 @@ func (p *Pages) HidePage(name string) *Pages {
|
|||
p.Focus(p.setFocus)
|
||||
p.Lock()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// SwitchToPage sets a page's visibility to "true" and all other pages'
|
||||
// visibility to "false".
|
||||
func (p *Pages) SwitchToPage(name string) *Pages {
|
||||
func (p *Pages) SwitchToPage(name string) {
|
||||
hasFocus := p.HasFocus()
|
||||
|
||||
p.Lock()
|
||||
|
@ -235,13 +229,12 @@ func (p *Pages) SwitchToPage(name string) *Pages {
|
|||
p.Focus(p.setFocus)
|
||||
p.Lock()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// SendToFront changes the order of the pages such that the page with the given
|
||||
// name comes last, causing it to be drawn last with the next update (if
|
||||
// visible).
|
||||
func (p *Pages) SendToFront(name string) *Pages {
|
||||
func (p *Pages) SendToFront(name string) {
|
||||
hasFocus := p.HasFocus()
|
||||
|
||||
p.Lock()
|
||||
|
@ -265,13 +258,12 @@ func (p *Pages) SendToFront(name string) *Pages {
|
|||
p.Focus(p.setFocus)
|
||||
p.Lock()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// SendToBack changes the order of the pages such that the page with the given
|
||||
// name comes first, causing it to be drawn first with the next update (if
|
||||
// visible).
|
||||
func (p *Pages) SendToBack(name string) *Pages {
|
||||
func (p *Pages) SendToBack(name string) {
|
||||
hasFocus := p.HasFocus()
|
||||
|
||||
p.Lock()
|
||||
|
@ -295,7 +287,6 @@ func (p *Pages) SendToBack(name string) *Pages {
|
|||
p.Focus(p.setFocus)
|
||||
p.Lock()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// GetFrontPage returns the front-most visible page. If there are no visible
|
||||
|
|
|
@ -38,14 +38,16 @@ type ProgressBar struct {
|
|||
|
||||
// NewProgressBar returns a new progress bar.
|
||||
func NewProgressBar() *ProgressBar {
|
||||
return &ProgressBar{
|
||||
Box: NewBox().SetBackgroundColor(Styles.PrimitiveBackgroundColor),
|
||||
p := &ProgressBar{
|
||||
Box: NewBox(),
|
||||
emptyRune: ' ',
|
||||
emptyColor: Styles.PrimitiveBackgroundColor,
|
||||
filledRune: tcell.RuneBlock,
|
||||
filledColor: Styles.PrimaryTextColor,
|
||||
max: 100,
|
||||
}
|
||||
p.SetBackgroundColor(Styles.PrimitiveBackgroundColor)
|
||||
return p
|
||||
}
|
||||
|
||||
// SetEmptyRune sets the rune used for the empty area of the progress bar.
|
||||
|
|
122
table.go
122
table.go
|
@ -63,17 +63,16 @@ func NewTableCell(text string) *TableCell {
|
|||
}
|
||||
|
||||
// SetBytes sets the cell's text.
|
||||
func (c *TableCell) SetBytes(text []byte) *TableCell {
|
||||
func (c *TableCell) SetBytes(text []byte) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.Text = text
|
||||
return c
|
||||
}
|
||||
|
||||
// SetText sets the cell's text.
|
||||
func (c *TableCell) SetText(text string) *TableCell {
|
||||
return c.SetBytes([]byte(text))
|
||||
func (c *TableCell) SetText(text string) {
|
||||
c.SetBytes([]byte(text))
|
||||
}
|
||||
|
||||
// GetBytes returns the cell's text.
|
||||
|
@ -91,23 +90,21 @@ func (c *TableCell) GetText() string {
|
|||
|
||||
// SetAlign sets the cell's text alignment, one of AlignLeft, AlignCenter, or
|
||||
// AlignRight.
|
||||
func (c *TableCell) SetAlign(align int) *TableCell {
|
||||
func (c *TableCell) SetAlign(align int) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.Align = align
|
||||
return c
|
||||
}
|
||||
|
||||
// SetMaxWidth sets maximum width of the cell in screen space. This is used to
|
||||
// give a column a maximum width. Any cell text whose screen width exceeds this
|
||||
// width is cut off. Set to 0 if there is no maximum width.
|
||||
func (c *TableCell) SetMaxWidth(maxWidth int) *TableCell {
|
||||
func (c *TableCell) SetMaxWidth(maxWidth int) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.MaxWidth = maxWidth
|
||||
return c
|
||||
}
|
||||
|
||||
// SetExpansion sets the value by which the column of this cell expands if the
|
||||
|
@ -123,7 +120,7 @@ func (c *TableCell) SetMaxWidth(maxWidth int) *TableCell {
|
|||
// in that column is used.
|
||||
//
|
||||
// This function panics if a negative value is provided.
|
||||
func (c *TableCell) SetExpansion(expansion int) *TableCell {
|
||||
func (c *TableCell) SetExpansion(expansion int) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
|
@ -131,68 +128,61 @@ func (c *TableCell) SetExpansion(expansion int) *TableCell {
|
|||
panic("Table cell expansion values may not be negative")
|
||||
}
|
||||
c.Expansion = expansion
|
||||
return c
|
||||
}
|
||||
|
||||
// SetTextColor sets the cell's text color.
|
||||
func (c *TableCell) SetTextColor(color tcell.Color) *TableCell {
|
||||
func (c *TableCell) SetTextColor(color tcell.Color) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.Color = color
|
||||
return c
|
||||
}
|
||||
|
||||
// SetBackgroundColor sets the cell's background color. Set to
|
||||
// tcell.ColorDefault to use the table's background color.
|
||||
func (c *TableCell) SetBackgroundColor(color tcell.Color) *TableCell {
|
||||
func (c *TableCell) SetBackgroundColor(color tcell.Color) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.BackgroundColor = color
|
||||
return c
|
||||
}
|
||||
|
||||
// SetAttributes sets the cell's text attributes. You can combine different
|
||||
// attributes using bitmask operations:
|
||||
//
|
||||
// cell.SetAttributes(tcell.AttrUnderline | tcell.AttrBold)
|
||||
func (c *TableCell) SetAttributes(attr tcell.AttrMask) *TableCell {
|
||||
func (c *TableCell) SetAttributes(attr tcell.AttrMask) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.Attributes = attr
|
||||
return c
|
||||
}
|
||||
|
||||
// SetStyle sets the cell's style (foreground color, background color, and
|
||||
// attributes) all at once.
|
||||
func (c *TableCell) SetStyle(style tcell.Style) *TableCell {
|
||||
func (c *TableCell) SetStyle(style tcell.Style) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.Color, c.BackgroundColor, c.Attributes = style.Decompose()
|
||||
return c
|
||||
}
|
||||
|
||||
// SetSelectable sets whether or not this cell can be selected by the user.
|
||||
func (c *TableCell) SetSelectable(selectable bool) *TableCell {
|
||||
func (c *TableCell) SetSelectable(selectable bool) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.NotSelectable = !selectable
|
||||
return c
|
||||
}
|
||||
|
||||
// SetReference allows you to store a reference of any type in this cell. This
|
||||
// will allow you to establish a mapping between the cell and your
|
||||
// actual data.
|
||||
func (c *TableCell) SetReference(reference interface{}) *TableCell {
|
||||
func (c *TableCell) SetReference(reference interface{}) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.Reference = reference
|
||||
return c
|
||||
}
|
||||
|
||||
// GetReference returns this cell's reference object.
|
||||
|
@ -367,50 +357,45 @@ func NewTable() *Table {
|
|||
}
|
||||
|
||||
// Clear removes all table data.
|
||||
func (t *Table) Clear() *Table {
|
||||
func (t *Table) Clear() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.cells = nil
|
||||
t.lastColumn = -1
|
||||
return t
|
||||
}
|
||||
|
||||
// SetBorders sets whether or not each cell in the table is surrounded by a
|
||||
// border.
|
||||
func (t *Table) SetBorders(show bool) *Table {
|
||||
func (t *Table) SetBorders(show bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.borders = show
|
||||
return t
|
||||
}
|
||||
|
||||
// SetBordersColor sets the color of the cell borders.
|
||||
func (t *Table) SetBordersColor(color tcell.Color) *Table {
|
||||
func (t *Table) SetBordersColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.bordersColor = color
|
||||
return t
|
||||
}
|
||||
|
||||
// SetScrollBarVisibility specifies the display of the scroll bar.
|
||||
func (t *Table) SetScrollBarVisibility(visibility ScrollBarVisibility) *Table {
|
||||
func (t *Table) SetScrollBarVisibility(visibility ScrollBarVisibility) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.scrollBarVisibility = visibility
|
||||
return t
|
||||
}
|
||||
|
||||
// SetScrollBarColor sets the color of the scroll bar.
|
||||
func (t *Table) SetScrollBarColor(color tcell.Color) *Table {
|
||||
func (t *Table) SetScrollBarColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.scrollBarColor = color
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSelectedStyle sets a specific style for selected cells. If no such style
|
||||
|
@ -420,12 +405,11 @@ func (t *Table) SetScrollBarColor(color tcell.Color) *Table {
|
|||
// To reset a previous setting to its default, make the following call:
|
||||
//
|
||||
// table.SetSelectedStyle(tcell.ColorDefault, tcell.ColorDefault, 0)
|
||||
func (t *Table) SetSelectedStyle(foregroundColor, backgroundColor tcell.Color, attributes tcell.AttrMask) *Table {
|
||||
func (t *Table) SetSelectedStyle(foregroundColor, backgroundColor tcell.Color, attributes tcell.AttrMask) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.selectedStyle = SetAttributes(tcell.StyleDefault.Foreground(foregroundColor).Background(backgroundColor), attributes)
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSeparator sets the character used to fill the space between two
|
||||
|
@ -435,23 +419,21 @@ func (t *Table) SetSelectedStyle(foregroundColor, backgroundColor tcell.Color, a
|
|||
// ignored.
|
||||
//
|
||||
// Separators have the same color as borders.
|
||||
func (t *Table) SetSeparator(separator rune) *Table {
|
||||
func (t *Table) SetSeparator(separator rune) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.separator = separator
|
||||
return t
|
||||
}
|
||||
|
||||
// SetFixed sets the number of fixed rows and columns which are always visible
|
||||
// even when the rest of the cells are scrolled out of view. Rows are always the
|
||||
// top-most ones. Columns are always the left-most ones.
|
||||
func (t *Table) SetFixed(rows, columns int) *Table {
|
||||
func (t *Table) SetFixed(rows, columns int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.fixedRows, t.fixedColumns = rows, columns
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSelectable sets the flags which determine what can be selected in a table.
|
||||
|
@ -461,12 +443,11 @@ func (t *Table) SetFixed(rows, columns int) *Table {
|
|||
// - rows = true, columns = false: Rows can be selected.
|
||||
// - rows = false, columns = true: Columns can be selected.
|
||||
// - rows = true, columns = true: Individual cells can be selected.
|
||||
func (t *Table) SetSelectable(rows, columns bool) *Table {
|
||||
func (t *Table) SetSelectable(rows, columns bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.rowsSelectable, t.columnsSelectable = rows, columns
|
||||
return t
|
||||
}
|
||||
|
||||
// GetSelectable returns what can be selected in a table. Refer to
|
||||
|
@ -493,7 +474,7 @@ func (t *Table) GetSelection() (row, column int) {
|
|||
// ignored completely. The "selection changed" event is fired if such a callback
|
||||
// is available (even if the selection ends up being the same as before and even
|
||||
// if cells are not selectable).
|
||||
func (t *Table) Select(row, column int) *Table {
|
||||
func (t *Table) Select(row, column int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -503,7 +484,6 @@ func (t *Table) Select(row, column int) *Table {
|
|||
t.selectionChanged(row, column)
|
||||
t.Lock()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// SetOffset sets how many rows and columns should be skipped when drawing the
|
||||
|
@ -511,13 +491,12 @@ func (t *Table) Select(row, column int) *Table {
|
|||
// Navigating a selection can change these values.
|
||||
//
|
||||
// Fixed rows and columns are never skipped.
|
||||
func (t *Table) SetOffset(row, column int) *Table {
|
||||
func (t *Table) SetOffset(row, column int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.rowOffset, t.columnOffset = row, column
|
||||
t.trackEnd = false
|
||||
return t
|
||||
}
|
||||
|
||||
// GetOffset returns the current row and column offset. This indicates how many
|
||||
|
@ -535,48 +514,44 @@ func (t *Table) GetOffset() (row, column int) {
|
|||
//
|
||||
// Set this flag to true to avoid shifting column widths when the table is
|
||||
// scrolled. (May be slower for large tables.)
|
||||
func (t *Table) SetEvaluateAllRows(all bool) *Table {
|
||||
func (t *Table) SetEvaluateAllRows(all bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.evaluateAllRows = all
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSelectedFunc sets a handler which is called whenever the user presses the
|
||||
// Enter key on a selected cell/row/column. The handler receives the position of
|
||||
// the selection and its cell contents. If entire rows are selected, the column
|
||||
// index is undefined. Likewise for entire columns.
|
||||
func (t *Table) SetSelectedFunc(handler func(row, column int)) *Table {
|
||||
func (t *Table) SetSelectedFunc(handler func(row, column int)) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.selected = handler
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSelectionChangedFunc sets a handler which is called whenever the current
|
||||
// selection changes. The handler receives the position of the new selection.
|
||||
// If entire rows are selected, the column index is undefined. Likewise for
|
||||
// entire columns.
|
||||
func (t *Table) SetSelectionChangedFunc(handler func(row, column int)) *Table {
|
||||
func (t *Table) SetSelectionChangedFunc(handler func(row, column int)) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.selectionChanged = handler
|
||||
return t
|
||||
}
|
||||
|
||||
// SetDoneFunc sets a handler which is called whenever the user presses the
|
||||
// Escape, Tab, or Backtab key. If nothing is selected, it is also called when
|
||||
// user presses the Enter key (because pressing Enter on a selection triggers
|
||||
// the "selected" handler set via SetSelectedFunc()).
|
||||
func (t *Table) SetDoneFunc(handler func(key tcell.Key)) *Table {
|
||||
func (t *Table) SetDoneFunc(handler func(key tcell.Key)) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.done = handler
|
||||
return t
|
||||
}
|
||||
|
||||
// SetCell sets the content of a cell the specified position. It is ok to
|
||||
|
@ -588,7 +563,7 @@ func (t *Table) SetDoneFunc(handler func(key tcell.Key)) *Table {
|
|||
// a row of 100,000 will immediately create 100,000 empty rows.
|
||||
//
|
||||
// To avoid unnecessary garbage collection, fill columns from left to right.
|
||||
func (t *Table) SetCell(row, column int, cell *TableCell) *Table {
|
||||
func (t *Table) SetCell(row, column int, cell *TableCell) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -606,12 +581,11 @@ func (t *Table) SetCell(row, column int, cell *TableCell) *Table {
|
|||
if column > t.lastColumn {
|
||||
t.lastColumn = column
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// SetCellSimple calls SetCell() with the given text, left-aligned, in white.
|
||||
func (t *Table) SetCellSimple(row, column int, text string) *Table {
|
||||
return t.SetCell(row, column, NewTableCell(text))
|
||||
func (t *Table) SetCellSimple(row, column int, text string) {
|
||||
t.SetCell(row, column, NewTableCell(text))
|
||||
}
|
||||
|
||||
// GetCell returns the contents of the cell at the specified position. A valid
|
||||
|
@ -631,22 +605,20 @@ func (t *Table) GetCell(row, column int) *TableCell {
|
|||
|
||||
// RemoveRow removes the row at the given position from the table. If there is
|
||||
// no such row, this has no effect.
|
||||
func (t *Table) RemoveRow(row int) *Table {
|
||||
func (t *Table) RemoveRow(row int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
if row < 0 || row >= len(t.cells) {
|
||||
return t
|
||||
return
|
||||
}
|
||||
|
||||
t.cells = append(t.cells[:row], t.cells[row+1:]...)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// RemoveColumn removes the column at the given position from the table. If
|
||||
// there is no such column, this has no effect.
|
||||
func (t *Table) RemoveColumn(column int) *Table {
|
||||
func (t *Table) RemoveColumn(column int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -656,31 +628,28 @@ func (t *Table) RemoveColumn(column int) *Table {
|
|||
}
|
||||
t.cells[row] = append(t.cells[row][:column], t.cells[row][column+1:]...)
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// InsertRow inserts a row before the row with the given index. Cells on the
|
||||
// given row and below will be shifted to the bottom by one row. If "row" is
|
||||
// equal or larger than the current number of rows, this function has no effect.
|
||||
func (t *Table) InsertRow(row int) *Table {
|
||||
func (t *Table) InsertRow(row int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
if row >= len(t.cells) {
|
||||
return t
|
||||
return
|
||||
}
|
||||
t.cells = append(t.cells, nil) // Extend by one.
|
||||
copy(t.cells[row+1:], t.cells[row:]) // Shift down.
|
||||
t.cells[row] = nil // New row is uninitialized.
|
||||
return t
|
||||
}
|
||||
|
||||
// InsertColumn inserts a column before the column with the given index. Cells
|
||||
// in the given column and to its right will be shifted to the right by one
|
||||
// column. Rows that have fewer initialized cells than "column" will remain
|
||||
// unchanged.
|
||||
func (t *Table) InsertColumn(column int) *Table {
|
||||
func (t *Table) InsertColumn(column int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -692,7 +661,6 @@ func (t *Table) InsertColumn(column int) *Table {
|
|||
copy(t.cells[row][column+1:], t.cells[row][column:]) // Shift to the right.
|
||||
t.cells[row][column] = &TableCell{} // New element is an uninitialized table cell.
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// GetRowCount returns the number of rows in the table.
|
||||
|
@ -760,58 +728,54 @@ func (t *Table) cellAt(x, y int) (row, column int) {
|
|||
// ScrollToBeginning scrolls the table to the beginning to that the top left
|
||||
// corner of the table is shown. Note that this position may be corrected if
|
||||
// there is a selection.
|
||||
func (t *Table) ScrollToBeginning() *Table {
|
||||
func (t *Table) ScrollToBeginning() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.trackEnd = false
|
||||
t.columnOffset = 0
|
||||
t.rowOffset = 0
|
||||
return t
|
||||
}
|
||||
|
||||
// ScrollToEnd scrolls the table to the beginning to that the bottom left corner
|
||||
// of the table is shown. Adding more rows to the table will cause it to
|
||||
// automatically scroll with the new data. Note that this position may be
|
||||
// corrected if there is a selection.
|
||||
func (t *Table) ScrollToEnd() *Table {
|
||||
func (t *Table) ScrollToEnd() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.trackEnd = true
|
||||
t.columnOffset = 0
|
||||
t.rowOffset = len(t.cells)
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSortClicked sets a flag which determines whether the table is sorted when
|
||||
// a fixed row is clicked. This flag is enabled by default.
|
||||
func (t *Table) SetSortClicked(sortClicked bool) *Table {
|
||||
func (t *Table) SetSortClicked(sortClicked bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.sortClicked = sortClicked
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSortFunc sets the sorting function used for the table. When unset, a
|
||||
// case-sensitive string comparison is used.
|
||||
func (t *Table) SetSortFunc(sortFunc func(column, i, j int) bool) *Table {
|
||||
func (t *Table) SetSortFunc(sortFunc func(column, i, j int) bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.sortFunc = sortFunc
|
||||
return t
|
||||
}
|
||||
|
||||
// Sort sorts the table by the column at the given index. You may set a custom
|
||||
// sorting function with SetSortFunc.
|
||||
func (t *Table) Sort(column int, descending bool) *Table {
|
||||
func (t *Table) Sort(column int, descending bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
if len(t.cells) == 0 || column < 0 || column >= len(t.cells[0]) {
|
||||
return t
|
||||
return
|
||||
}
|
||||
|
||||
if t.sortFunc == nil {
|
||||
|
@ -832,8 +796,6 @@ func (t *Table) Sort(column int, descending bool) *Table {
|
|||
}
|
||||
return t.sortFunc(column, j, i)
|
||||
})
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
|
|
84
textview.go
84
textview.go
|
@ -221,7 +221,7 @@ func NewTextView() *TextView {
|
|||
// SetScrollable sets the flag that decides whether or not the text view is
|
||||
// scrollable. If true, text is kept in a buffer and can be navigated. If false,
|
||||
// the last line will always be visible.
|
||||
func (t *TextView) SetScrollable(scrollable bool) *TextView {
|
||||
func (t *TextView) SetScrollable(scrollable bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -229,31 +229,28 @@ func (t *TextView) SetScrollable(scrollable bool) *TextView {
|
|||
if !scrollable {
|
||||
t.trackEnd = true
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// SetScrollBarVisibility specifies the display of the scroll bar.
|
||||
func (t *TextView) SetScrollBarVisibility(visibility ScrollBarVisibility) *TextView {
|
||||
func (t *TextView) SetScrollBarVisibility(visibility ScrollBarVisibility) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.scrollBarVisibility = visibility
|
||||
return t
|
||||
}
|
||||
|
||||
// SetScrollBarColor sets the color of the scroll bar.
|
||||
func (t *TextView) SetScrollBarColor(color tcell.Color) *TextView {
|
||||
func (t *TextView) SetScrollBarColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.scrollBarColor = color
|
||||
return t
|
||||
}
|
||||
|
||||
// SetWrap sets the flag that, if true, leads to lines that are longer than the
|
||||
// available width being wrapped onto the next line. If false, any characters
|
||||
// beyond the available width are not displayed.
|
||||
func (t *TextView) SetWrap(wrap bool) *TextView {
|
||||
func (t *TextView) SetWrap(wrap bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -261,7 +258,6 @@ func (t *TextView) SetWrap(wrap bool) *TextView {
|
|||
t.index = nil
|
||||
}
|
||||
t.wrap = wrap
|
||||
return t
|
||||
}
|
||||
|
||||
// SetWordWrap sets the flag that, if true and if the "wrap" flag is also true
|
||||
|
@ -269,7 +265,7 @@ func (t *TextView) SetWrap(wrap bool) *TextView {
|
|||
// that trailing spaces will not be printed.
|
||||
//
|
||||
// This flag is ignored if the "wrap" flag is false.
|
||||
func (t *TextView) SetWordWrap(wrapOnWords bool) *TextView {
|
||||
func (t *TextView) SetWordWrap(wrapOnWords bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -277,12 +273,11 @@ func (t *TextView) SetWordWrap(wrapOnWords bool) *TextView {
|
|||
t.index = nil
|
||||
}
|
||||
t.wordWrap = wrapOnWords
|
||||
return t
|
||||
}
|
||||
|
||||
// SetTextAlign sets the text alignment within the text view. This must be
|
||||
// either AlignLeft, AlignCenter, or AlignRight.
|
||||
func (t *TextView) SetTextAlign(align int) *TextView {
|
||||
func (t *TextView) SetTextAlign(align int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -290,35 +285,32 @@ func (t *TextView) SetTextAlign(align int) *TextView {
|
|||
t.index = nil
|
||||
}
|
||||
t.align = align
|
||||
return t
|
||||
}
|
||||
|
||||
// SetTextColor sets the initial color of the text (which can be changed
|
||||
// dynamically by sending color strings in square brackets to the text view if
|
||||
// dynamic colors are enabled).
|
||||
func (t *TextView) SetTextColor(color tcell.Color) *TextView {
|
||||
func (t *TextView) SetTextColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.textColor = color
|
||||
return t
|
||||
}
|
||||
|
||||
// SetBytes sets the text of this text view to the provided byte slice.
|
||||
// Previously contained text will be removed.
|
||||
func (t *TextView) SetBytes(text []byte) *TextView {
|
||||
func (t *TextView) SetBytes(text []byte) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.clear()
|
||||
t.write(text)
|
||||
return t
|
||||
}
|
||||
|
||||
// SetText sets the text of this text view to the provided string. Previously
|
||||
// contained text will be removed.
|
||||
func (t *TextView) SetText(text string) *TextView {
|
||||
return t.SetBytes([]byte(text))
|
||||
func (t *TextView) SetText(text string) {
|
||||
t.SetBytes([]byte(text))
|
||||
}
|
||||
|
||||
// GetBytes returns the current text of this text view. If "stripTags" is set
|
||||
|
@ -360,7 +352,7 @@ func (t *TextView) GetText(stripTags bool) string {
|
|||
|
||||
// SetDynamicColors sets the flag that allows the text color to be changed
|
||||
// dynamically. See class description for details.
|
||||
func (t *TextView) SetDynamicColors(dynamic bool) *TextView {
|
||||
func (t *TextView) SetDynamicColors(dynamic bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -368,12 +360,11 @@ func (t *TextView) SetDynamicColors(dynamic bool) *TextView {
|
|||
t.index = nil
|
||||
}
|
||||
t.dynamicColors = dynamic
|
||||
return t
|
||||
}
|
||||
|
||||
// SetRegions sets the flag that allows to define regions in the text. See class
|
||||
// description for details.
|
||||
func (t *TextView) SetRegions(regions bool) *TextView {
|
||||
func (t *TextView) SetRegions(regions bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -381,7 +372,6 @@ func (t *TextView) SetRegions(regions bool) *TextView {
|
|||
t.index = nil
|
||||
}
|
||||
t.regions = regions
|
||||
return t
|
||||
}
|
||||
|
||||
// SetChangedFunc sets a handler function which is called when the text of the
|
||||
|
@ -400,23 +390,21 @@ func (t *TextView) SetRegions(regions bool) *TextView {
|
|||
// Application.QueueUpdate().
|
||||
//
|
||||
// See package description for details on dealing with concurrency.
|
||||
func (t *TextView) SetChangedFunc(handler func()) *TextView {
|
||||
func (t *TextView) SetChangedFunc(handler func()) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.changed = handler
|
||||
return t
|
||||
}
|
||||
|
||||
// SetDoneFunc sets a handler which is called when the user presses on the
|
||||
// following keys: Escape, Enter, Tab, Backtab. The key is passed to the
|
||||
// handler.
|
||||
func (t *TextView) SetDoneFunc(handler func(key tcell.Key)) *TextView {
|
||||
func (t *TextView) SetDoneFunc(handler func(key tcell.Key)) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.done = handler
|
||||
return t
|
||||
}
|
||||
|
||||
// SetHighlightedFunc sets a handler which is called when the list of currently
|
||||
|
@ -426,9 +414,8 @@ func (t *TextView) SetDoneFunc(handler func(key tcell.Key)) *TextView {
|
|||
//
|
||||
// Note that because regions are only determined during drawing, this function
|
||||
// can only fire for regions that have existed during the last call to Draw().
|
||||
func (t *TextView) SetHighlightedFunc(handler func(added, removed, remaining []string)) *TextView {
|
||||
func (t *TextView) SetHighlightedFunc(handler func(added, removed, remaining []string)) {
|
||||
t.highlighted = handler
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *TextView) clipBuffer() {
|
||||
|
@ -444,54 +431,50 @@ func (t *TextView) clipBuffer() {
|
|||
|
||||
// SetMaxLines sets the maximum number of newlines the text view will hold
|
||||
// before discarding older data from the buffer.
|
||||
func (t *TextView) SetMaxLines(maxLines int) *TextView {
|
||||
func (t *TextView) SetMaxLines(maxLines int) {
|
||||
t.maxLines = maxLines
|
||||
t.clipBuffer()
|
||||
return t
|
||||
}
|
||||
|
||||
// ScrollTo scrolls to the specified row and column (both starting with 0).
|
||||
func (t *TextView) ScrollTo(row, column int) *TextView {
|
||||
func (t *TextView) ScrollTo(row, column int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
if !t.scrollable {
|
||||
return t
|
||||
return
|
||||
}
|
||||
t.lineOffset = row
|
||||
t.columnOffset = column
|
||||
t.trackEnd = false
|
||||
return t
|
||||
}
|
||||
|
||||
// ScrollToBeginning scrolls to the top left corner of the text if the text view
|
||||
// is scrollable.
|
||||
func (t *TextView) ScrollToBeginning() *TextView {
|
||||
func (t *TextView) ScrollToBeginning() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
if !t.scrollable {
|
||||
return t
|
||||
return
|
||||
}
|
||||
t.trackEnd = false
|
||||
t.lineOffset = 0
|
||||
t.columnOffset = 0
|
||||
return t
|
||||
}
|
||||
|
||||
// ScrollToEnd scrolls to the bottom left corner of the text if the text view
|
||||
// is scrollable. Adding new rows to the end of the text view will cause it to
|
||||
// scroll with the new data.
|
||||
func (t *TextView) ScrollToEnd() *TextView {
|
||||
func (t *TextView) ScrollToEnd() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
if !t.scrollable {
|
||||
return t
|
||||
return
|
||||
}
|
||||
t.trackEnd = true
|
||||
t.columnOffset = 0
|
||||
return t
|
||||
}
|
||||
|
||||
// GetScrollOffset returns the number of rows and columns that are skipped at
|
||||
|
@ -504,20 +487,19 @@ func (t *TextView) GetScrollOffset() (row, column int) {
|
|||
}
|
||||
|
||||
// Clear removes all text from the buffer.
|
||||
func (t *TextView) Clear() *TextView {
|
||||
func (t *TextView) Clear() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
return t.clear()
|
||||
t.clear()
|
||||
}
|
||||
|
||||
func (t *TextView) clear() *TextView {
|
||||
func (t *TextView) clear() {
|
||||
t.buffer = nil
|
||||
t.recentBytes = nil
|
||||
if t.reindex {
|
||||
t.index = nil
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// Highlight specifies which regions should be highlighted. If highlight
|
||||
|
@ -532,7 +514,7 @@ func (t *TextView) clear() *TextView {
|
|||
//
|
||||
// Text in highlighted regions will be drawn inverted, i.e. with their
|
||||
// background and foreground colors swapped.
|
||||
func (t *TextView) Highlight(regionIDs ...string) *TextView {
|
||||
func (t *TextView) Highlight(regionIDs ...string) {
|
||||
t.Lock()
|
||||
|
||||
// Toggle highlights.
|
||||
|
@ -588,8 +570,6 @@ func (t *TextView) Highlight(regionIDs ...string) *TextView {
|
|||
} else {
|
||||
t.Unlock()
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// GetHighlights returns the IDs of all currently highlighted regions.
|
||||
|
@ -607,9 +587,8 @@ func (t *TextView) GetHighlights() (regionIDs []string) {
|
|||
// When set to true, the Highlight() function (or a mouse click) will toggle the
|
||||
// provided/selected regions. When set to false, Highlight() (or a mouse click)
|
||||
// will simply highlight the provided regions.
|
||||
func (t *TextView) SetToggleHighlights(toggle bool) *TextView {
|
||||
func (t *TextView) SetToggleHighlights(toggle bool) {
|
||||
t.toggleHighlights = toggle
|
||||
return t
|
||||
}
|
||||
|
||||
// ScrollToHighlight will cause the visible area to be scrolled so that the
|
||||
|
@ -620,17 +599,16 @@ func (t *TextView) SetToggleHighlights(toggle bool) *TextView {
|
|||
//
|
||||
// Nothing happens if there are no highlighted regions or if the text view is
|
||||
// not scrollable.
|
||||
func (t *TextView) ScrollToHighlight() *TextView {
|
||||
func (t *TextView) ScrollToHighlight() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
if len(t.highlights) == 0 || !t.scrollable || !t.regions {
|
||||
return t
|
||||
return
|
||||
}
|
||||
t.index = nil
|
||||
t.scrollToHighlights = true
|
||||
t.trackEnd = false
|
||||
return t
|
||||
}
|
||||
|
||||
// GetRegionText returns the text of the region with the given ID. If dynamic
|
||||
|
@ -801,7 +779,7 @@ func (t *TextView) write(p []byte) (n int, err error) {
|
|||
// it is modified. This improves the performance of TextViews whose contents
|
||||
// always have line-breaks in the same location. This must be called after the
|
||||
// buffer has been indexed.
|
||||
func (t *TextView) SetReindexBuffer(reindex bool) *TextView {
|
||||
func (t *TextView) SetReindexBuffer(reindex bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -810,8 +788,6 @@ func (t *TextView) SetReindexBuffer(reindex bool) *TextView {
|
|||
if reindex {
|
||||
t.index = nil
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// reindexBuffer re-indexes the buffer such that we can use it to easily draw
|
||||
|
|
|
@ -42,7 +42,7 @@ func TestTextViewWrite(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
var (
|
||||
tv = tvc(NewTextView(), c)
|
||||
tv = tvc(c)
|
||||
expectedData []byte
|
||||
n int
|
||||
err error
|
||||
|
@ -84,7 +84,7 @@ func BenchmarkTextViewWrite(b *testing.B) {
|
|||
|
||||
b.Run(c.String(), func(b *testing.B) {
|
||||
var (
|
||||
tv = tvc(NewTextView(), c)
|
||||
tv = tvc(c)
|
||||
n int
|
||||
err error
|
||||
)
|
||||
|
@ -123,7 +123,7 @@ func BenchmarkTextViewIndex(b *testing.B) {
|
|||
|
||||
b.Run(c.String(), func(b *testing.B) {
|
||||
var (
|
||||
tv = tvc(NewTextView(), c)
|
||||
tv = tvc(c)
|
||||
n int
|
||||
err error
|
||||
)
|
||||
|
@ -195,7 +195,7 @@ func BenchmarkTextViewGetText(b *testing.B) {
|
|||
|
||||
b.Run(c.String(), func(b *testing.B) {
|
||||
var (
|
||||
tv = tvc(NewTextView(), c)
|
||||
tv = tvc(c)
|
||||
n int
|
||||
err error
|
||||
v []byte
|
||||
|
@ -236,7 +236,7 @@ func TestTextViewDraw(t *testing.T) {
|
|||
t.Run(c.String(), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tv := tvc(NewTextView(), c)
|
||||
tv := tvc(c)
|
||||
|
||||
app, err := newTestApp(tv)
|
||||
if err != nil {
|
||||
|
@ -269,7 +269,7 @@ func BenchmarkTextViewDraw(b *testing.B) {
|
|||
c := c // Capture
|
||||
|
||||
b.Run(c.String(), func(b *testing.B) {
|
||||
tv := tvc(NewTextView(), c)
|
||||
tv := tvc(c)
|
||||
|
||||
app, err := newTestApp(tv)
|
||||
if err != nil {
|
||||
|
@ -404,8 +404,14 @@ func generateRandomData() []byte {
|
|||
return b.Bytes()
|
||||
}
|
||||
|
||||
func tvc(tv *TextView, c *textViewTestCase) *TextView {
|
||||
return tv.SetDynamicColors(c.color).SetRegions(c.region).SetScrollable(c.scroll).SetWrap(c.wrap).SetWordWrap(c.wordwrap)
|
||||
func tvc(c *textViewTestCase) *TextView {
|
||||
tv := NewTextView()
|
||||
tv.SetDynamicColors(c.color)
|
||||
tv.SetRegions(c.region)
|
||||
tv.SetScrollable(c.scroll)
|
||||
tv.SetWrap(c.wrap)
|
||||
tv.SetWordWrap(c.wordwrap)
|
||||
return tv
|
||||
}
|
||||
|
||||
func cl(v bool) rune {
|
||||
|
|
95
treeview.go
95
treeview.go
|
@ -71,14 +71,14 @@ func NewTreeNode(text string) *TreeNode {
|
|||
// this node) with the traversed node and its parent node (nil for this node).
|
||||
// The callback returns whether traversal should continue with the traversed
|
||||
// node's child nodes (true) or not recurse any deeper (false).
|
||||
func (n *TreeNode) Walk(callback func(node, parent *TreeNode) bool) *TreeNode {
|
||||
func (n *TreeNode) Walk(callback func(node, parent *TreeNode) bool) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
return n.walk(callback)
|
||||
n.walk(callback)
|
||||
}
|
||||
|
||||
func (n *TreeNode) walk(callback func(node, parent *TreeNode) bool) *TreeNode {
|
||||
func (n *TreeNode) walk(callback func(node, parent *TreeNode) bool) {
|
||||
n.parent = nil
|
||||
nodes := []*TreeNode{n}
|
||||
for len(nodes) > 0 {
|
||||
|
@ -96,19 +96,16 @@ func (n *TreeNode) walk(callback func(node, parent *TreeNode) bool) *TreeNode {
|
|||
nodes = append(nodes, node.children[index])
|
||||
}
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
// SetReference allows you to store a reference of any type in this node. This
|
||||
// will allow you to establish a mapping between the TreeView hierarchy and your
|
||||
// internal tree structure.
|
||||
func (n *TreeNode) SetReference(reference interface{}) *TreeNode {
|
||||
func (n *TreeNode) SetReference(reference interface{}) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.reference = reference
|
||||
return n
|
||||
}
|
||||
|
||||
// GetReference returns this node's reference object.
|
||||
|
@ -120,12 +117,11 @@ func (n *TreeNode) GetReference() interface{} {
|
|||
}
|
||||
|
||||
// SetChildren sets this node's child nodes.
|
||||
func (n *TreeNode) SetChildren(childNodes []*TreeNode) *TreeNode {
|
||||
func (n *TreeNode) SetChildren(childNodes []*TreeNode) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.children = childNodes
|
||||
return n
|
||||
}
|
||||
|
||||
// GetText returns this node's text.
|
||||
|
@ -145,98 +141,88 @@ func (n *TreeNode) GetChildren() []*TreeNode {
|
|||
}
|
||||
|
||||
// ClearChildren removes all child nodes from this node.
|
||||
func (n *TreeNode) ClearChildren() *TreeNode {
|
||||
func (n *TreeNode) ClearChildren() {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.children = nil
|
||||
return n
|
||||
}
|
||||
|
||||
// AddChild adds a new child node to this node.
|
||||
func (n *TreeNode) AddChild(node *TreeNode) *TreeNode {
|
||||
func (n *TreeNode) AddChild(node *TreeNode) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.children = append(n.children, node)
|
||||
return n
|
||||
}
|
||||
|
||||
// SetSelectable sets a flag indicating whether this node can be focused and
|
||||
// selected by the user.
|
||||
func (n *TreeNode) SetSelectable(selectable bool) *TreeNode {
|
||||
func (n *TreeNode) SetSelectable(selectable bool) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.selectable = selectable
|
||||
return n
|
||||
}
|
||||
|
||||
// SetFocusedFunc sets the function which is called when the user navigates to
|
||||
// this node.
|
||||
//
|
||||
// This function is also called when the user selects this node.
|
||||
func (n *TreeNode) SetFocusedFunc(handler func()) *TreeNode {
|
||||
func (n *TreeNode) SetFocusedFunc(handler func()) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.focused = handler
|
||||
return n
|
||||
}
|
||||
|
||||
// SetSelectedFunc sets a function which is called when the user selects this
|
||||
// node by hitting Enter when it is focused.
|
||||
func (n *TreeNode) SetSelectedFunc(handler func()) *TreeNode {
|
||||
func (n *TreeNode) SetSelectedFunc(handler func()) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.selected = handler
|
||||
return n
|
||||
}
|
||||
|
||||
// SetExpanded sets whether or not this node's child nodes should be displayed.
|
||||
func (n *TreeNode) SetExpanded(expanded bool) *TreeNode {
|
||||
func (n *TreeNode) SetExpanded(expanded bool) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.expanded = expanded
|
||||
return n
|
||||
}
|
||||
|
||||
// Expand makes the child nodes of this node appear.
|
||||
func (n *TreeNode) Expand() *TreeNode {
|
||||
func (n *TreeNode) Expand() {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.expanded = true
|
||||
return n
|
||||
}
|
||||
|
||||
// Collapse makes the child nodes of this node disappear.
|
||||
func (n *TreeNode) Collapse() *TreeNode {
|
||||
func (n *TreeNode) Collapse() {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.expanded = false
|
||||
return n
|
||||
}
|
||||
|
||||
// ExpandAll expands this node and all descendent nodes.
|
||||
func (n *TreeNode) ExpandAll() *TreeNode {
|
||||
func (n *TreeNode) ExpandAll() {
|
||||
n.Walk(func(node, parent *TreeNode) bool {
|
||||
node.expanded = true
|
||||
return true
|
||||
})
|
||||
return n
|
||||
}
|
||||
|
||||
// CollapseAll collapses this node and all descendent nodes.
|
||||
func (n *TreeNode) CollapseAll() *TreeNode {
|
||||
func (n *TreeNode) CollapseAll() {
|
||||
n.Walk(func(node, parent *TreeNode) bool {
|
||||
n.expanded = false
|
||||
return true
|
||||
})
|
||||
return n
|
||||
}
|
||||
|
||||
// IsExpanded returns whether the child nodes of this node are visible.
|
||||
|
@ -248,12 +234,11 @@ func (n *TreeNode) IsExpanded() bool {
|
|||
}
|
||||
|
||||
// SetText sets the node's text which is displayed.
|
||||
func (n *TreeNode) SetText(text string) *TreeNode {
|
||||
func (n *TreeNode) SetText(text string) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.text = text
|
||||
return n
|
||||
}
|
||||
|
||||
// GetColor returns the node's color.
|
||||
|
@ -265,23 +250,21 @@ func (n *TreeNode) GetColor() tcell.Color {
|
|||
}
|
||||
|
||||
// SetColor sets the node's text color.
|
||||
func (n *TreeNode) SetColor(color tcell.Color) *TreeNode {
|
||||
func (n *TreeNode) SetColor(color tcell.Color) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.color = color
|
||||
return n
|
||||
}
|
||||
|
||||
// SetIndent sets an additional indentation for this node's text. A value of 0
|
||||
// keeps the text as far left as possible with a minimum of line graphics. Any
|
||||
// value greater than that moves the text to the right.
|
||||
func (n *TreeNode) SetIndent(indent int) *TreeNode {
|
||||
func (n *TreeNode) SetIndent(indent int) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
n.indent = indent
|
||||
return n
|
||||
}
|
||||
|
||||
// TreeView displays tree structures. A tree consists of nodes (TreeNode
|
||||
|
@ -384,12 +367,11 @@ func NewTreeView() *TreeView {
|
|||
}
|
||||
|
||||
// SetRoot sets the root node of the tree.
|
||||
func (t *TreeView) SetRoot(root *TreeNode) *TreeView {
|
||||
func (t *TreeView) SetRoot(root *TreeNode) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.root = root
|
||||
return t
|
||||
}
|
||||
|
||||
// GetRoot returns the root node of the tree. If no such node was previously
|
||||
|
@ -406,7 +388,7 @@ func (t *TreeView) GetRoot() *TreeNode {
|
|||
// changed to the top-most selectable and visible node.
|
||||
//
|
||||
// This function does NOT trigger the "changed" callback.
|
||||
func (t *TreeView) SetCurrentNode(node *TreeNode) *TreeView {
|
||||
func (t *TreeView) SetCurrentNode(node *TreeNode) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -416,7 +398,6 @@ func (t *TreeView) SetCurrentNode(node *TreeNode) *TreeView {
|
|||
t.currentNode.focused()
|
||||
t.Lock()
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// GetCurrentNode returns the currently selected node or nil of no node is
|
||||
|
@ -431,12 +412,11 @@ func (t *TreeView) GetCurrentNode() *TreeNode {
|
|||
// SetTopLevel sets the first tree level that is visible with 0 referring to the
|
||||
// root, 1 to the root's child nodes, and so on. Nodes above the top level are
|
||||
// not displayed.
|
||||
func (t *TreeView) SetTopLevel(topLevel int) *TreeView {
|
||||
func (t *TreeView) SetTopLevel(topLevel int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.topLevel = topLevel
|
||||
return t
|
||||
}
|
||||
|
||||
// SetPrefixes defines the strings drawn before the nodes' texts. This is a
|
||||
|
@ -448,7 +428,7 @@ func (t *TreeView) SetTopLevel(topLevel int) *TreeView {
|
|||
//
|
||||
// treeView.SetGraphics(false).
|
||||
// SetPrefixes([]string{"* ", "- ", "x "})
|
||||
func (t *TreeView) SetPrefixes(prefixes []string) *TreeView {
|
||||
func (t *TreeView) SetPrefixes(prefixes []string) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
|
@ -456,101 +436,90 @@ func (t *TreeView) SetPrefixes(prefixes []string) *TreeView {
|
|||
for i := range prefixes {
|
||||
t.prefixes[i] = []byte(prefixes[i])
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// SetAlign controls the horizontal alignment of the node texts. If set to true,
|
||||
// all texts except that of top-level nodes will be placed in the same column.
|
||||
// If set to false, they will indent with the hierarchy.
|
||||
func (t *TreeView) SetAlign(align bool) *TreeView {
|
||||
func (t *TreeView) SetAlign(align bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.align = align
|
||||
return t
|
||||
}
|
||||
|
||||
// SetGraphics sets a flag which determines whether or not line graphics are
|
||||
// drawn to illustrate the tree's hierarchy.
|
||||
func (t *TreeView) SetGraphics(showGraphics bool) *TreeView {
|
||||
func (t *TreeView) SetGraphics(showGraphics bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.graphics = showGraphics
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSelectedTextColor sets the text color of selected items.
|
||||
func (t *TreeView) SetSelectedTextColor(color tcell.Color) *TreeView {
|
||||
func (t *TreeView) SetSelectedTextColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.selectedTextColor = &color
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSelectedBackgroundColor sets the background color of selected items.
|
||||
func (t *TreeView) SetSelectedBackgroundColor(color tcell.Color) *TreeView {
|
||||
func (t *TreeView) SetSelectedBackgroundColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.selectedBackgroundColor = &color
|
||||
return t
|
||||
}
|
||||
|
||||
// SetGraphicsColor sets the colors of the lines used to draw the tree structure.
|
||||
func (t *TreeView) SetGraphicsColor(color tcell.Color) *TreeView {
|
||||
func (t *TreeView) SetGraphicsColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.graphicsColor = color
|
||||
return t
|
||||
}
|
||||
|
||||
// SetScrollBarVisibility specifies the display of the scroll bar.
|
||||
func (t *TreeView) SetScrollBarVisibility(visibility ScrollBarVisibility) *TreeView {
|
||||
func (t *TreeView) SetScrollBarVisibility(visibility ScrollBarVisibility) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.scrollBarVisibility = visibility
|
||||
return t
|
||||
}
|
||||
|
||||
// SetScrollBarColor sets the color of the scroll bar.
|
||||
func (t *TreeView) SetScrollBarColor(color tcell.Color) *TreeView {
|
||||
func (t *TreeView) SetScrollBarColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.scrollBarColor = color
|
||||
return t
|
||||
}
|
||||
|
||||
// SetChangedFunc sets the function which is called when the user navigates to
|
||||
// a new tree node.
|
||||
func (t *TreeView) SetChangedFunc(handler func(node *TreeNode)) *TreeView {
|
||||
func (t *TreeView) SetChangedFunc(handler func(node *TreeNode)) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.changed = handler
|
||||
return t
|
||||
}
|
||||
|
||||
// SetSelectedFunc sets the function which is called when the user selects a
|
||||
// node by pressing Enter on the current selection.
|
||||
func (t *TreeView) SetSelectedFunc(handler func(node *TreeNode)) *TreeView {
|
||||
func (t *TreeView) SetSelectedFunc(handler func(node *TreeNode)) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.selected = handler
|
||||
return t
|
||||
}
|
||||
|
||||
// SetDoneFunc sets a handler which is called whenever the user presses the
|
||||
// Escape, Tab, or Backtab key.
|
||||
func (t *TreeView) SetDoneFunc(handler func(key tcell.Key)) *TreeView {
|
||||
func (t *TreeView) SetDoneFunc(handler func(key tcell.Key)) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.done = handler
|
||||
return t
|
||||
}
|
||||
|
||||
// GetScrollOffset returns the number of node rows that were skipped at the top
|
||||
|
|
|
@ -11,8 +11,9 @@ func newTestApp(root Primitive) (*Application, error) {
|
|||
sc.SetSize(80, 24)
|
||||
|
||||
// Initialize application
|
||||
app := NewApplication().
|
||||
SetScreen(sc).
|
||||
SetRoot(root, true)
|
||||
app := NewApplication()
|
||||
app.SetScreen(sc)
|
||||
app.SetRoot(root, true)
|
||||
|
||||
return app, nil
|
||||
}
|
||||
|
|
|
@ -36,31 +36,28 @@ func NewWindow(primitive Primitive) *Window {
|
|||
}
|
||||
|
||||
// SetPosition sets the position of the window.
|
||||
func (w *Window) SetPosition(x, y int) *Window {
|
||||
func (w *Window) SetPosition(x, y int) {
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
|
||||
w.x, w.y = x, y
|
||||
return w
|
||||
}
|
||||
|
||||
// SetSize sets the size of the window.
|
||||
func (w *Window) SetSize(width, height int) *Window {
|
||||
func (w *Window) SetSize(width, height int) {
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
|
||||
w.width, w.height = width, height
|
||||
return w
|
||||
}
|
||||
|
||||
// SetFullscreen sets the flag indicating whether or not the the window should
|
||||
// be drawn fullscreen.
|
||||
func (w *Window) SetFullscreen(fullscreen bool) *Window {
|
||||
func (w *Window) SetFullscreen(fullscreen bool) {
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
|
||||
w.fullscreen = fullscreen
|
||||
return w
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
|
|
Loading…
Reference in New Issue