Browse Source

Add relevant info to pages of the presentation demo

Also, only draw DropDown symbols when focused by default.

Resolves #61.
textarea
Trevor Slocum 1 year ago
parent
commit
71e3cc57f7
  1. 2
      CHANGELOG
  2. 18
      button.go
  3. 4
      demos/presentation/colors.go
  4. 15
      demos/presentation/cover.go
  5. 4
      demos/presentation/end.go
  6. 4
      demos/presentation/flex.go
  7. 4
      demos/presentation/form.go
  8. 4
      demos/presentation/grid.go
  9. 4
      demos/presentation/inputfield.go
  10. 4
      demos/presentation/introduction.go
  11. 34
      demos/presentation/main.go
  12. 4
      demos/presentation/slider.go
  13. 4
      demos/presentation/table.go
  14. 8
      demos/presentation/textview.go
  15. 4
      demos/presentation/treeview.go
  16. 4
      demos/presentation/window.go
  17. 39
      dropdown.go
  18. 16
      form.go
  19. 8
      inputfield.go
  20. 2
      slider.go
  21. 10
      styles.go

2
CHANGELOG

@ -1,6 +1,8 @@
v1.5.6 (WIP)
- Add TrueColorTags option and do not use TrueColor tag values by default
- Add TextView.SetHighlightForegroundColor and TextView.SetHighlightBackgroundColor
- Add DropDown.SetDropDownOpenSymbolRune
- Add DropDown.SetAlwaysDrawDropDownSymbol (DropDown symbols are now only drawn when focused by default)
- Draw additional accents when rendering a list divider
- Update List, Table and TreeView to not handle Tab or Backtab
- Allow specifying TabbedPanels switcher height

18
button.go

@ -4,7 +4,6 @@ import (
"sync"
"github.com/gdamore/tcell/v2"
"github.com/lucasb-eyer/go-colorful"
)
// Button is labeled box that triggers an action when selected.
@ -37,24 +36,13 @@ type Button struct {
func NewButton(label string) *Button {
box := NewBox()
box.SetRect(0, 0, TaggedStringWidth(label)+4, 1)
bg := Styles.PrimaryTextColor
if bg == tcell.ColorDefault {
r, g, b := Styles.InverseTextColor.RGB()
c := colorful.Color{R: float64(r) / 255, G: float64(g) / 255, B: float64(b) / 255}
_, _, li := c.Hcl()
if li < .5 {
bg = tcell.ColorWhite.TrueColor()
} else {
bg = tcell.ColorBlack.TrueColor()
}
}
box.SetBackgroundColor(bg)
box.SetBackgroundColor(Styles.ContrastBackgroundColor)
return &Button{
Box: box,
label: []byte(label),
labelColor: Styles.InverseTextColor,
labelColor: Styles.PrimaryTextColor,
labelColorFocused: Styles.PrimaryTextColor,
backgroundColorFocused: Styles.ContrastBackgroundColor,
backgroundColorFocused: Styles.MoreContrastBackgroundColor,
}
}

4
demos/presentation/colors.go

@ -18,7 +18,7 @@ The [black:red]tags [black:green]look [black:yellow]like [::u]this:
[#00ff00[]`
// Colors demonstrates how to use colors.
func Colors(nextSlide func()) (title string, content cview.Primitive) {
func Colors(nextSlide func()) (title string, info string, content cview.Primitive) {
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")
@ -29,5 +29,5 @@ func Colors(nextSlide func()) (title string, content cview.Primitive) {
nextSlide()
})
return "Colors", Center(44, 16, tv)
return "Colors", "", Center(44, 16, tv)
}

15
demos/presentation/cover.go

@ -16,14 +16,10 @@ const logo = `
======= == === ======== ==== ====
`
const (
subtitle = `Terminal-based user interface toolkit`
mouse = `Navigate with your keyboard or mouse.`
navigation = `Next slide: Ctrl-N Previous: Ctrl-P Exit: Ctrl-C`
)
const subtitle = "Terminal-based user interface toolkit"
// Cover returns the cover page.
func Cover(nextSlide func()) (title string, content cview.Primitive) {
func Cover(nextSlide func()) (title string, info string, content cview.Primitive) {
// What's the size of the logo?
lines := strings.Split(logo, "\n")
logoWidth := 0
@ -43,10 +39,7 @@ func Cover(nextSlide func()) (title string, content cview.Primitive) {
// Create a frame for the subtitle and navigation infos.
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())
frame.AddText(subtitle, true, cview.AlignCenter, tcell.ColorDarkMagenta.TrueColor())
// Create a Flex layout that centers the logo and subtitle.
subFlex := cview.NewFlex()
@ -60,5 +53,5 @@ func Cover(nextSlide func()) (title string, content cview.Primitive) {
flex.AddItem(subFlex, logoHeight, 1, true)
flex.AddItem(frame, 0, 10, false)
return "Start", flex
return "Start", appInfo, flex
}

4
demos/presentation/end.go

@ -8,12 +8,12 @@ import (
)
// End shows the final slide.
func End(nextSlide func()) (title string, content cview.Primitive) {
func End(nextSlide func()) (title string, info string, content cview.Primitive) {
textView := cview.NewTextView()
textView.SetDoneFunc(func(key tcell.Key) {
nextSlide()
})
url := "https://code.rocketnine.space/tslocum/cview"
fmt.Fprint(textView, url)
return "End", Center(len(url), 1, textView)
return "End", "", Center(len(url), 1, textView)
}

4
demos/presentation/flex.go

@ -13,7 +13,7 @@ func demoBox(title string) *cview.Box {
}
// Flex demonstrates flexbox layout.
func Flex(nextSlide func()) (title string, content cview.Primitive) {
func Flex(nextSlide func()) (title string, info string, content cview.Primitive) {
modalShown := false
panels := cview.NewPanels()
@ -50,5 +50,5 @@ func Flex(nextSlide func()) (title string, content cview.Primitive) {
panels.AddPanel("flex", flex, true, true)
panels.AddPanel("modal", modal, false, false)
return "Flex", panels
return "Flex", "", panels
}

4
demos/presentation/form.go

@ -29,7 +29,7 @@ const form = `[green]package[white] main
}`
// Form demonstrates forms.
func Form(nextSlide func()) (title string, content cview.Primitive) {
func Form(nextSlide func()) (title string, info string, content cview.Primitive) {
f := cview.NewForm()
f.AddInputField("First name:", "", 20, nil, nil)
f.AddInputField("Last name:", "", 20, nil, nil)
@ -40,5 +40,5 @@ func Form(nextSlide func()) (title string, content cview.Primitive) {
f.AddButton("Cancel", nextSlide)
f.SetBorder(true)
f.SetTitle("Employee Information")
return "Form", Code(f, 36, 15, form)
return "Form", formInfo, Code(f, 36, 15, form)
}

4
demos/presentation/grid.go

@ -6,7 +6,7 @@ import (
)
// Grid demonstrates the grid layout.
func Grid(nextSlide func()) (title string, content cview.Primitive) {
func Grid(nextSlide func()) (title string, info string, content cview.Primitive) {
modalShown := false
panels := cview.NewPanels()
@ -57,5 +57,5 @@ func Grid(nextSlide func()) (title string, content cview.Primitive) {
panels.AddPanel("grid", grid, true, true)
panels.AddPanel("modal", modal, false, false)
return "Grid", panels
return "Grid", "", panels
}

4
demos/presentation/inputfield.go

@ -30,12 +30,12 @@ const inputField = `[green]package[white] main
}`
// InputField demonstrates the InputField.
func InputField(nextSlide func()) (title string, content cview.Primitive) {
func InputField(nextSlide func()) (title string, info string, content cview.Primitive) {
input := cview.NewInputField()
input.SetLabel("Enter a number: ")
input.SetAcceptanceFunc(cview.InputFieldInteger)
input.SetDoneFunc(func(key tcell.Key) {
nextSlide()
})
return "InputField", Code(input, 30, 1, inputField)
return "InputField", "", Code(input, 30, 1, inputField)
}

4
demos/presentation/introduction.go

@ -3,7 +3,7 @@ package main
import "code.rocketnine.space/tslocum/cview"
// Introduction returns a cview.List with the highlights of the cview package.
func Introduction(nextSlide func()) (title string, content cview.Primitive) {
func Introduction(nextSlide func()) (title string, info string, content cview.Primitive) {
list := cview.NewList()
listText := [][]string{
@ -58,5 +58,5 @@ func Introduction(nextSlide func()) (title string, content cview.Primitive) {
})
reset()
return "Introduction", Center(80, 12, list)
return "Introduction", listInfo, Center(80, 12, list)
}

34
demos/presentation/main.go

@ -24,10 +24,19 @@ import (
"github.com/gdamore/tcell/v2"
)
// Slide is a function which returns the slide's main primitive and its title.
// It receives a "nextSlide" function which can be called to advance the
// presentation to the next slide.
type Slide func(nextSlide func()) (title string, content cview.Primitive)
const (
appInfo = "Next slide: Ctrl-N Previous: Ctrl-P Exit: Ctrl-C (Navigate with your keyboard or mouse)"
listInfo = "Next item: J, Down Previous item: K, Up Open context menu: Alt+Enter"
textViewInfo = "Scroll down: J, Down, PageDown Scroll up: K, Up, PageUp"
sliderInfo = "Decrease: H, J, Left, Down Increase: K, L, Right, Up"
formInfo = "Next field: Tab Previous field: Shift+Tab Select: Enter"
windowInfo = "Windows may be dragged an resized using the mouse."
)
// Slide is a function which returns the slide's title, any applicable
// information and its main primitive, its. It receives a "nextSlide" function
// which can be called to advance the presentation to the next slide.
type Slide func(nextSlide func()) (title string, info string, content cview.Primitive)
// The application.
var app = cview.NewApplication()
@ -83,8 +92,21 @@ func main() {
for index, slide := range slides {
slideRegions = append(slideRegions, cursor)
title, primitive := slide(nextSlide)
panels.AddTab(strconv.Itoa(index), title, primitive)
title, info, primitive := slide(nextSlide)
h := cview.NewTextView()
if info != "" {
h.SetDynamicColors(true)
h.SetText(" [" + cview.ColorHex(cview.Styles.SecondaryTextColor) + "]Info:[-] " + info)
}
// Create a Flex layout that centers the logo and subtitle.
f := cview.NewFlex()
f.SetDirection(cview.FlexRow)
f.AddItem(h, 1, 1, false)
f.AddItem(primitive, 0, 1, true)
panels.AddTab(strconv.Itoa(index), title, f)
cursor += len(title) + 4
}

4
demos/presentation/slider.go

@ -32,7 +32,7 @@ const sliderCode = `[green]package[white] main
}`
// Slider demonstrates the Slider.
func Slider(nextSlide func()) (title string, content cview.Primitive) {
func Slider(nextSlide func()) (title string, info string, content cview.Primitive) {
slider := cview.NewSlider()
slider.SetLabel("Volume: 0%")
slider.SetChangedFunc(func(value int) {
@ -41,5 +41,5 @@ func Slider(nextSlide func()) (title string, content cview.Primitive) {
slider.SetDoneFunc(func(key tcell.Key) {
nextSlide()
})
return "Slider", Code(slider, 30, 1, sliderCode)
return "Slider", sliderInfo, Code(slider, 30, 1, sliderCode)
}

4
demos/presentation/table.go

@ -248,7 +248,7 @@ const tableSelectCell = `[green]func[white] [yellow]main[white]() {
}`
// Table demonstrates the Table.
func Table(nextSlide func()) (title string, content cview.Primitive) {
func Table(nextSlide func()) (title string, info string, content cview.Primitive) {
table := cview.NewTable()
table.SetFixed(1, 1)
for row, line := range strings.Split(tableData, "\n") {
@ -378,5 +378,5 @@ func Table(nextSlide func()) (title string, content cview.Primitive) {
flex.AddItem(subFlex, 0, 1, true)
flex.AddItem(code, codeWidth, 1, false)
return "Table", flex
return "Table", "", flex
}

8
demos/presentation/textview.go

@ -30,7 +30,7 @@ const textView1 = `[green]func[white] [yellow]main[white]() {
}`
// TextView1 demonstrates the basic text view.
func TextView1(nextSlide func()) (title string, content cview.Primitive) {
func TextView1(nextSlide func()) (title string, info string, content cview.Primitive) {
textView := cview.NewTextView()
textView.SetTextColor(tcell.ColorYellow.TrueColor())
textView.SetDoneFunc(func(key tcell.Key) {
@ -57,7 +57,7 @@ func TextView1(nextSlide func()) (title string, content cview.Primitive) {
textView.SetBorder(true)
textView.SetTitle("TextView implements io.Writer")
textView.ScrollToEnd()
return "TextView 1", Code(textView, 36, 13, textView1)
return "TextView 1", textViewInfo, Code(textView, 36, 13, textView1)
}
const textView2 = `[green]package[white] main
@ -108,7 +108,7 @@ const textView2 = `[green]package[white] main
}`
// TextView2 demonstrates the extended text view.
func TextView2(nextSlide func()) (title string, content cview.Primitive) {
func TextView2(nextSlide func()) (title string, info string, content cview.Primitive) {
codeView := cview.NewTextView()
codeView.SetWrap(false)
fmt.Fprint(codeView, textView2)
@ -159,5 +159,5 @@ func TextView2(nextSlide func()) (title string, content cview.Primitive) {
flex.AddItem(textView, 0, 1, true)
flex.AddItem(codeView, 0, 1, false)
return "TextView 2", flex
return "TextView 2", textViewInfo, flex
}

4
demos/presentation/treeview.go

@ -118,7 +118,7 @@ var rootNode = &node{
}}
// TreeView demonstrates the tree view.
func TreeView(nextSlide func()) (title string, content cview.Primitive) {
func TreeView(nextSlide func()) (title string, info string, content cview.Primitive) {
treeNextSlide = nextSlide
tree.SetBorder(true)
tree.SetTitle("TreeView")
@ -161,5 +161,5 @@ func TreeView(nextSlide func()) (title string, content cview.Primitive) {
flex.AddItem(tree, 0, 1, true)
flex.AddItem(treeCode, codeWidth, 1, false)
return "TreeView", flex
return "TreeView", "", flex
}

4
demos/presentation/window.go

@ -7,7 +7,7 @@ import (
const loremIpsumText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
// Window returns the window page.
func Window(nextSlide func()) (title string, content cview.Primitive) {
func Window(nextSlide func()) (title string, info string, content cview.Primitive) {
wm := cview.NewWindowManager()
list := cview.NewList()
@ -34,5 +34,5 @@ func Window(nextSlide func()) (title string, content cview.Primitive) {
wm.Add(w1, w2)
return "Window", wm
return "Window", windowInfo, wm
}

39
dropdown.go

@ -134,9 +134,15 @@ type DropDown struct {
// The chars to show when the option's text gets shortened.
abbreviationChars string
// The symbol to draw at the end of the field.
// The symbol to draw at the end of the field when closed.
dropDownSymbol rune
// The symbol to draw at the end of the field when opened.
dropDownOpenSymbol rune
// A flag that determines whether the drop down symbol is always drawn.
alwaysDrawDropDownSymbol bool
sync.RWMutex
}
@ -144,7 +150,7 @@ type DropDown struct {
func NewDropDown() *DropDown {
list := NewList()
list.ShowSecondaryText(false)
list.SetMainTextColor(Styles.PrimitiveBackgroundColor)
list.SetMainTextColor(Styles.SecondaryTextColor)
list.SetSelectedTextColor(Styles.PrimitiveBackgroundColor)
list.SetSelectedBackgroundColor(Styles.PrimaryTextColor)
list.SetHighlightFullLine(true)
@ -159,6 +165,7 @@ func NewDropDown() *DropDown {
fieldTextColor: Styles.PrimaryTextColor,
prefixTextColor: Styles.ContrastSecondaryTextColor,
dropDownSymbol: Styles.DropDownSymbol,
dropDownOpenSymbol: Styles.DropDownOpenSymbol,
abbreviationChars: Styles.DropDownAbbreviationChars,
labelColorFocused: ColorUnset,
fieldBackgroundColorFocused: ColorUnset,
@ -178,6 +185,22 @@ func (d *DropDown) SetDropDownSymbolRune(symbol rune) {
d.dropDownSymbol = symbol
}
// SetDropDownOpenSymbolRune sets the rune to be drawn at the end of the
// dropdown field to indicate that the a dropdown is open.
func (d *DropDown) SetDropDownOpenSymbolRune(symbol rune) {
d.Lock()
defer d.Unlock()
d.dropDownOpenSymbol = symbol
}
// SetAlwaysDrawDropDownSymbol sets a flad that determines whether the drop
// down symbol is always drawn. The symbol is normally only drawn when focused.
func (d *DropDown) SetAlwaysDrawDropDownSymbol(alwaysDraw bool) {
d.Lock()
defer d.Unlock()
d.alwaysDrawDropDownSymbol = alwaysDraw
}
// 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).
@ -594,7 +617,13 @@ func (d *DropDown) Draw(screen tcell.Screen) {
}
// Draw drop-down symbol
screen.SetContent(x+fieldWidth-2, y, d.dropDownSymbol, nil, new(tcell.Style).Foreground(fieldTextColor).Background(fieldBackgroundColor))
if d.alwaysDrawDropDownSymbol || d._hasFocus() {
symbol := d.dropDownSymbol
if d.open {
symbol = d.dropDownOpenSymbol
}
screen.SetContent(x+fieldWidth-2, y, symbol, nil, new(tcell.Style).Foreground(fieldTextColor).Background(fieldBackgroundColor))
}
// Draw options list.
if hasFocus && d.open {
@ -742,6 +771,10 @@ func (d *DropDown) HasFocus() bool {
d.RLock()
defer d.RUnlock()
return d._hasFocus()
}
func (d *DropDown) _hasFocus() bool {
if d.open {
return d.list.HasFocus()
}

16
form.go

@ -151,14 +151,14 @@ func NewForm() *Form {
Box: box,
itemPadding: 1,
labelColor: Styles.SecondaryTextColor,
fieldBackgroundColor: Styles.MoreContrastBackgroundColor,
fieldBackgroundColorFocused: Styles.ContrastBackgroundColor,
fieldTextColor: Styles.InverseTextColor,
fieldTextColorFocused: Styles.InverseTextColor,
buttonBackgroundColor: Styles.MoreContrastBackgroundColor,
buttonBackgroundColorFocused: Styles.ContrastBackgroundColor,
buttonTextColor: Styles.InverseTextColor,
buttonTextColorFocused: Styles.InverseTextColor,
fieldBackgroundColor: Styles.ContrastBackgroundColor,
fieldBackgroundColorFocused: Styles.MoreContrastBackgroundColor,
fieldTextColor: Styles.PrimaryTextColor,
fieldTextColorFocused: Styles.PrimaryTextColor,
buttonBackgroundColor: Styles.ContrastBackgroundColor,
buttonBackgroundColorFocused: Styles.MoreContrastBackgroundColor,
buttonTextColor: Styles.PrimaryTextColor,
buttonTextColorFocused: Styles.PrimaryTextColor,
labelColorFocused: ColorUnset,
}

8
inputfield.go

@ -144,10 +144,10 @@ func NewInputField() *InputField {
return &InputField{
Box: NewBox(),
labelColor: Styles.SecondaryTextColor,
fieldBackgroundColor: Styles.PrimaryTextColor,
fieldBackgroundColorFocused: Styles.ContrastBackgroundColor,
fieldTextColor: Styles.ContrastPrimaryTextColor,
fieldTextColorFocused: Styles.ContrastPrimaryTextColor,
fieldBackgroundColor: Styles.ContrastBackgroundColor,
fieldBackgroundColorFocused: Styles.MoreContrastBackgroundColor,
fieldTextColor: Styles.PrimaryTextColor,
fieldTextColorFocused: Styles.PrimaryTextColor,
placeholderTextColor: Styles.ContrastSecondaryTextColor,
autocompleteListTextColor: Styles.PrimitiveBackgroundColor,
autocompleteListBackgroundColor: Styles.MoreContrastBackgroundColor,

2
slider.go

@ -65,9 +65,9 @@ func NewSlider() *Slider {
increment: 10,
labelColor: Styles.SecondaryTextColor,
fieldBackgroundColor: Styles.ContrastBackgroundColor,
fieldBackgroundColorFocused: Styles.MoreContrastBackgroundColor,
fieldTextColor: Styles.PrimaryTextColor,
labelColorFocused: ColorUnset,
fieldBackgroundColorFocused: ColorUnset,
fieldTextColorFocused: ColorUnset,
}
return s

10
styles.go

@ -33,7 +33,8 @@ type Theme struct {
// Drop down
DropDownAbbreviationChars string // The chars to show when the option's text gets shortened.
DropDownSymbol rune // The symbol to draw at the end of the field.
DropDownSymbol rune // The symbol to draw at the end of the field when closed.
DropDownOpenSymbol rune // The symbol to draw at the end of the field when opened.
// Scroll bar
ScrollBarColor tcell.Color
@ -59,8 +60,8 @@ var Styles = Theme{
ContrastSecondaryTextColor: tcell.ColorLightSlateGray.TrueColor(),
PrimitiveBackgroundColor: tcell.ColorBlack.TrueColor(),
ContrastBackgroundColor: tcell.ColorLimeGreen.TrueColor(),
MoreContrastBackgroundColor: tcell.ColorGreen.TrueColor(),
ContrastBackgroundColor: tcell.ColorGreen.TrueColor(),
MoreContrastBackgroundColor: tcell.ColorDarkGreen.TrueColor(),
CheckBoxCheckedRune: 'X',
@ -70,7 +71,8 @@ var Styles = Theme{
ContextMenuPaddingRight: 1,
DropDownAbbreviationChars: "...",
DropDownSymbol: '▼',
DropDownSymbol: '◀',
DropDownOpenSymbol: '▼',
ScrollBarColor: tcell.ColorWhite.TrueColor(),

Loading…
Cancel
Save