Lists are a thing now

Looks like child bounds arent clipped properly though, ugh
This commit is contained in:
Sasha Koshka 2023-04-18 02:59:44 -04:00
parent 6b13e772a9
commit 0bf5c3b86c
7 changed files with 420 additions and 95 deletions

View File

@ -102,10 +102,10 @@ func (entity *entity) scrollTargetChildAt (point image.Point) *entity {
return nil return nil
} }
func (entity *entity) forMouseTargetContainers (callback func (tomo.MouseTargetContainer)) { func (entity *entity) forMouseTargetContainers (callback func (tomo.MouseTargetContainer, tomo.Element)) {
if entity.parent == nil { return } if entity.parent == nil { return }
if parent, ok := entity.parent.element.(tomo.MouseTargetContainer); ok { if parent, ok := entity.parent.element.(tomo.MouseTargetContainer); ok {
callback(parent) callback(parent, entity.element)
} }
entity.parent.forMouseTargetContainers(callback) entity.parent.forMouseTargetContainers(callback)
} }
@ -211,7 +211,8 @@ func (entity *entity) PlaceChild (index int, bounds image.Rectangle) {
func (entity *entity) SelectChild (index int, selected bool) { func (entity *entity) SelectChild (index int, selected bool) {
child := entity.children[index] child := entity.children[index]
if element, ok := entity.element.(tomo.Selectable); ok { if element, ok := child.element.(tomo.Selectable); ok {
if child.selected == selected { return }
child.selected = selected child.selected = selected
element.HandleSelectionChange() element.HandleSelectionChange()
} }

View File

@ -212,11 +212,11 @@ func (window *window) handleButtonPress (
point.X, point.Y, point.X, point.Y,
input.Button(buttonEvent.Detail)) input.Button(buttonEvent.Detail))
} }
callback := func (container tomo.MouseTargetContainer) { callback := func (container tomo.MouseTargetContainer, child tomo.Element) {
container.HandleChildMouseDown ( container.HandleChildMouseDown (
point.X, point.Y, point.X, point.Y,
input.Button(buttonEvent.Detail), input.Button(buttonEvent.Detail),
underneath.element) child)
} }
underneath.forMouseTargetContainers(callback) underneath.forMouseTargetContainers(callback)
} }
@ -238,12 +238,12 @@ func (window *window) handleButtonRelease (
int(buttonEvent.EventY), int(buttonEvent.EventY),
input.Button(buttonEvent.Detail)) input.Button(buttonEvent.Detail))
} }
callback := func (container tomo.MouseTargetContainer) { callback := func (container tomo.MouseTargetContainer, child tomo.Element) {
container.HandleChildMouseUp ( container.HandleChildMouseUp (
int(buttonEvent.EventX), int(buttonEvent.EventX),
int(buttonEvent.EventY), int(buttonEvent.EventY),
input.Button(buttonEvent.Detail), input.Button(buttonEvent.Detail),
dragging.element) child)
} }
dragging.forMouseTargetContainers(callback) dragging.forMouseTargetContainers(callback)
} }

View File

@ -212,14 +212,9 @@ func (Default) Pattern (id tomo.Pattern, state tomo.State, c tomo.Case) artist.P
switch id { switch id {
case tomo.PatternBackground: return patterns.Uhex(0xaaaaaaFF) case tomo.PatternBackground: return patterns.Uhex(0xaaaaaaFF)
case tomo.PatternDead: return defaultTextures[0][offset] case tomo.PatternDead: return defaultTextures[0][offset]
case tomo.PatternRaised: case tomo.PatternRaised: return defaultTextures[1][offset]
if c.Match("tomo", "listEntry", "") { case tomo.PatternSunken: return defaultTextures[2][offset]
return defaultTextures[10][offset] case tomo.PatternPinboard: return defaultTextures[3][offset]
} else {
return defaultTextures[1][offset]
}
case tomo.PatternSunken: return defaultTextures[2][offset]
case tomo.PatternPinboard: return defaultTextures[3][offset]
case tomo.PatternButton: case tomo.PatternButton:
switch { switch {
case c.Match("tomo", "checkbox", ""): case c.Match("tomo", "checkbox", ""):
@ -272,16 +267,8 @@ func (Default) Color (id tomo.Color, state tomo.State, c tomo.Case) color.RGBA {
// Padding returns the default padding value for the given pattern. // Padding returns the default padding value for the given pattern.
func (Default) Padding (id tomo.Pattern, c tomo.Case) artist.Inset { func (Default) Padding (id tomo.Pattern, c tomo.Case) artist.Inset {
switch id { switch id {
case tomo.PatternRaised:
if c.Match("tomo", "listEntry", "") {
return artist.I(4, 8)
} else {
return artist.I(8)
}
case tomo.PatternSunken: case tomo.PatternSunken:
if c.Match("tomo", "list", "") { if c.Match("tomo", "progressBar", "") {
return artist.I(4, 0, 3)
} else if c.Match("tomo", "progressBar", "") {
return artist.I(2, 1, 1, 2) return artist.I(2, 1, 1, 2)
} else { } else {
return artist.I(8) return artist.I(8)

View File

@ -13,18 +13,19 @@ type cellEntity interface {
// Cell is a single-element container that satisfies tomo.Selectable. It // Cell is a single-element container that satisfies tomo.Selectable. It
// provides styling based on whether or not it is selected. // provides styling based on whether or not it is selected.
type Cell struct { type Cell struct {
entity cellEntity entity cellEntity
child tomo.Element child tomo.Element
enabled bool enabled bool
padding bool theme theme.Wrapped
theme theme.Wrapped
onSelectionChange func ()
} }
// NewCell creates a new cell element. If padding is true, the cell will have // NewCell creates a new cell element. If padding is true, the cell will have
// padding on all sides. Child can be nil and added later with the Adopt() // padding on all sides. Child can be nil and added later with the Adopt()
// method. // method.
func NewCell (child tomo.Element, padding bool) (element *Cell) { func NewCell (child tomo.Element) (element *Cell) {
element = &Cell { padding: padding } element = &Cell { enabled: true }
element.theme.Case = tomo.C("tomo", "cell") element.theme.Case = tomo.C("tomo", "cell")
element.entity = tomo.NewEntity(element).(cellEntity) element.entity = tomo.NewEntity(element).(cellEntity)
element.Adopt(child) element.Adopt(child)
@ -42,7 +43,7 @@ func (element *Cell) Draw (destination canvas.Canvas) {
pattern := element.theme.Pattern(tomo.PatternTableCell, element.state()) pattern := element.theme.Pattern(tomo.PatternTableCell, element.state())
if element.child == nil { if element.child == nil {
pattern.Draw(destination, bounds) pattern.Draw(destination, bounds)
} else if element.padding { } else {
artist.DrawShatter ( artist.DrawShatter (
destination, pattern, bounds, destination, pattern, bounds,
element.child.Entity().Bounds()) element.child.Entity().Bounds())
@ -54,9 +55,7 @@ func (element *Cell) Layout () {
if element.child == nil { return } if element.child == nil { return }
bounds := element.entity.Bounds() bounds := element.entity.Bounds()
if element.padding { bounds = element.theme.Padding(tomo.PatternTableCell).Apply(bounds)
bounds = element.theme.Padding(tomo.PatternTableCell).Apply(bounds)
}
element.entity.PlaceChild(0, bounds) element.entity.PlaceChild(0, bounds)
} }
@ -80,6 +79,7 @@ func (element *Cell) Adopt (child tomo.Element) {
element.updateMinimumSize() element.updateMinimumSize()
element.entity.Invalidate() element.entity.Invalidate()
element.invalidateChild()
element.entity.InvalidateLayout() element.entity.InvalidateLayout()
} }
@ -93,9 +93,7 @@ func (element *Cell) SetEnabled (enabled bool) {
if element.enabled == enabled { return } if element.enabled == enabled { return }
element.enabled = enabled element.enabled = enabled
element.entity.Invalidate() element.entity.Invalidate()
if child, ok := element.child.(tomo.Enableable); ok { element.invalidateChild()
child.SetEnabled(enabled)
}
} }
// SetTheme sets this element's theme. // SetTheme sets this element's theme.
@ -104,11 +102,26 @@ func (element *Cell) SetTheme (theme tomo.Theme) {
element.theme.Theme = theme element.theme.Theme = theme
element.updateMinimumSize() element.updateMinimumSize()
element.entity.Invalidate() element.entity.Invalidate()
element.invalidateChild()
element.entity.InvalidateLayout() element.entity.InvalidateLayout()
} }
// OnSelectionChange sets a function to be called when this element is selected
// or unselected.
func (element *Cell) OnSelectionChange (callback func ()) {
element.onSelectionChange = callback
}
func (element *Cell) Selected () bool {
return element.entity.Selected()
}
func (element *Cell) HandleSelectionChange () { func (element *Cell) HandleSelectionChange () {
element.entity.Invalidate() element.entity.Invalidate()
element.invalidateChild()
if element.onSelectionChange != nil {
element.onSelectionChange()
}
} }
func (element *Cell) HandleChildMinimumSizeChange (tomo.Element) { func (element *Cell) HandleChildMinimumSizeChange (tomo.Element) {
@ -132,11 +145,15 @@ func (element *Cell) updateMinimumSize () {
width += childWidth width += childWidth
height += childHeight height += childHeight
} }
if element.padding { padding := element.theme.Padding(tomo.PatternTableCell)
padding := element.theme.Padding(tomo.PatternTableCell) width += padding.Horizontal()
width += padding.Horizontal() height += padding.Vertical()
height += padding.Vertical()
}
element.entity.SetMinimumSize(width, height) element.entity.SetMinimumSize(width, height)
} }
func (element *Cell) invalidateChild () {
if element.child != nil {
element.child.Entity().Invalidate()
}
}

315
elements/list.go Normal file
View File

@ -0,0 +1,315 @@
package elements
import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
type listEntity interface {
tomo.ContainerEntity
tomo.ScrollableEntity
}
type List struct {
entity listEntity
scratch map[tomo.Element] scratchEntry
scroll image.Point
contentBounds image.Rectangle
columnSizes []int
selected int
forcedMinimumWidth int
forcedMinimumHeight int
theme theme.Wrapped
onScrollBoundsChange func ()
}
func NewList (columns int, children ...tomo.Selectable) (element *List) {
if columns < 1 { columns = 1 }
element = &List { selected: -1 }
element.scratch = make(map[tomo.Element] scratchEntry)
element.columnSizes = make([]int, columns)
element.theme.Case = tomo.C("tomo", "list")
element.entity = tomo.NewEntity(element).(listEntity)
for _, child := range children {
element.Adopt(child)
}
return
}
func (element *List) Entity () tomo.Entity {
return element.entity
}
func (element *List) Draw (destination canvas.Canvas) {
rocks := make([]image.Rectangle, element.entity.CountChildren())
for index := 0; index < element.entity.CountChildren(); index ++ {
rocks[index] = element.entity.Child(index).Entity().Bounds()
}
pattern := element.theme.Pattern(tomo.PatternSunken, tomo.State { })
artist.DrawShatter(destination, pattern, element.entity.Bounds(), rocks...)
}
func (element *List) Layout () {
margin := element.theme.Margin(tomo.PatternSunken)
padding := element.theme.Padding(tomo.PatternSunken)
bounds := padding.Apply(element.entity.Bounds())
element.contentBounds = image.Rectangle { }
dot := bounds.Min.Sub(element.scroll)
xStart := dot.X
rowHeight := 0
columnIndex := 0
nextLine := func () {
dot.X = xStart
dot.Y += margin.Y
dot.Y += rowHeight
rowHeight = 0
columnIndex = 0
}
for index := 0; index < element.entity.CountChildren(); index ++ {
child := element.entity.Child(index)
entry := element.scratch[child]
if columnIndex >= len(element.columnSizes) {
nextLine()
}
width := element.columnSizes[columnIndex]
height := int(entry.minSize)
if len(element.columnSizes) == 1 && width < bounds.Dx() {
width = bounds.Dx()
}
if rowHeight < height {
rowHeight = height
}
childBounds := tomo.Bounds (
dot.X, dot.Y,
width, height)
element.entity.PlaceChild(index, childBounds)
element.contentBounds = element.contentBounds.Union(childBounds)
dot.X += width + margin.X
columnIndex ++
}
element.contentBounds =
element.contentBounds.Sub(element.contentBounds.Min)
element.entity.NotifyScrollBoundsChange()
if element.onScrollBoundsChange != nil {
element.onScrollBoundsChange()
}
}
func (element *List) Adopt (child tomo.Element) {
element.entity.Adopt(child)
element.scratch[child] = scratchEntry { }
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *List) Disown (child tomo.Element) {
index := element.entity.IndexOf(child)
if index < 0 { return }
if index == element.selected {
element.selected = -1
element.entity.SelectChild(index, false)
}
element.entity.Disown(index)
delete(element.scratch, child)
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *List) DisownAll () {
func () {
for index := 0; index < element.entity.CountChildren(); index ++ {
index := index
defer element.entity.Disown(index)
}
} ()
element.scratch = make(map[tomo.Element] scratchEntry)
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *List) HandleChildMouseDown (x, y int, button input.Button, child tomo.Element) {
if child, ok := child.(tomo.Selectable); ok {
index := element.entity.IndexOf(child)
if element.selected == index { return }
if element.selected >= 0 {
element.entity.SelectChild(element.selected, false)
}
element.selected = index
element.entity.SelectChild(index, true)
}
}
func (element *List) HandleChildMouseUp (int, int, input.Button, tomo.Element) { }
func (element *List) HandleChildMinimumSizeChange (child tomo.Element) {
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *List) HandleChildFlexibleHeightChange (child tomo.Flexible) {
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *List) DrawBackground (destination canvas.Canvas) {
element.entity.DrawBackground(destination)
}
// SetTheme sets the element's theme.
func (element *List) SetTheme (theme tomo.Theme) {
if theme == element.theme.Theme { return }
element.theme.Theme = theme
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
// Collapse forces a minimum width and height upon the list. If a zero value is
// given for a dimension, its minimum will be determined by the list's content.
// If the list's height goes beyond the forced size, it will need to be accessed
// via scrolling. If an entry's width goes beyond the forced size, its text will
// be truncated so that it fits.
func (element *List) Collapse (width, height int) {
if
element.forcedMinimumWidth == width &&
element.forcedMinimumHeight == height {
return
}
element.forcedMinimumWidth = width
element.forcedMinimumHeight = height
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
// ScrollContentBounds returns the full content size of the element.
func (element *List) ScrollContentBounds () image.Rectangle {
return element.contentBounds
}
// ScrollViewportBounds returns the size and position of the element's
// viewport relative to ScrollBounds.
func (element *List) ScrollViewportBounds () image.Rectangle {
padding := element.theme.Padding(tomo.PatternBackground)
bounds := padding.Apply(element.entity.Bounds())
bounds = bounds.Sub(bounds.Min).Add(element.scroll)
return bounds
}
// ScrollTo scrolls the viewport to the specified point relative to
// ScrollBounds.
func (element *List) ScrollTo (position image.Point) {
if position.Y < 0 {
position.Y = 0
}
maxScrollHeight := element.maxScrollHeight()
if position.Y > maxScrollHeight {
position.Y = maxScrollHeight
}
element.scroll = position
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
// OnScrollBoundsChange sets a function to be called when the element's viewport
// bounds, content bounds, or scroll axes change.
func (element *List) OnScrollBoundsChange (callback func ()) {
element.onScrollBoundsChange = callback
}
// ScrollAxes returns the supported axes for scrolling.
func (element *List) ScrollAxes () (horizontal, vertical bool) {
return false, true
}
func (element *List) maxScrollHeight () (height int) {
padding := element.theme.Padding(tomo.PatternSunken)
viewportHeight := element.entity.Bounds().Dy() - padding.Vertical()
height = element.contentBounds.Dy() - viewportHeight
if height < 0 { height = 0 }
return
}
func (element *List) updateMinimumSize () {
margin := element.theme.Margin(tomo.PatternSunken)
padding := element.theme.Padding(tomo.PatternSunken)
for index := range element.columnSizes {
element.columnSizes[index] = 0
}
height := 0
rowHeight := 0
columnIndex := 0
nextLine := func () {
height += rowHeight
rowHeight = 0
columnIndex = 0
}
for index := 0; index < element.entity.CountChildren(); index ++ {
if columnIndex >= len(element.columnSizes) {
if index > 0 { height += margin.Y }
nextLine()
}
child := element.entity.Child(index)
entry := element.scratch[child]
entryWidth, entryHeight := element.entity.ChildMinimumSize(index)
entry.minBreadth = float64(entryWidth)
entry.minSize = float64(entryHeight)
element.scratch[child] = entry
if rowHeight < entryHeight {
rowHeight = entryHeight
}
if element.columnSizes[columnIndex] < entryWidth {
element.columnSizes[columnIndex] = entryWidth
}
columnIndex ++
}
nextLine()
width := 0; for index, size := range element.columnSizes {
width += size
if index > 0 { width += margin.X }
}
width += padding.Horizontal()
height += padding.Vertical()
if element.forcedMinimumHeight > 0 {
height = element.forcedMinimumHeight
}
if element.forcedMinimumWidth > 0 {
width = element.forcedMinimumWidth
}
element.entity.SetMinimumSize(width, height)
}

View File

@ -2,10 +2,8 @@ package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/popups" import "git.tebibyte.media/sashakoshka/tomo/popups"
import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements" import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/testing" import "git.tebibyte.media/sashakoshka/tomo/elements/testing"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
func main () { func main () {
@ -16,18 +14,16 @@ func run () {
window, _ := tomo.NewWindow(tomo.Bounds(0, 0, 300, 0)) window, _ := tomo.NewWindow(tomo.Bounds(0, 0, 300, 0))
window.SetTitle("List Sidebar") window.SetTitle("List Sidebar")
container := containers.NewContainer(layouts.Horizontal { true, true }) container := elements.NewHBox(true, true)
window.Adopt(container) window.Adopt(container)
var currentPage tomo.Element var currentPage tomo.Element
turnPage := func (newPage tomo.Element) { turnPage := func (newPage tomo.Element) {
container.Warp (func () { if currentPage != nil {
if currentPage != nil { container.Disown(currentPage)
container.Disown(currentPage) }
} container.Adopt(newPage, true)
container.Adopt(newPage, true) currentPage = newPage
currentPage = newPage
})
} }
intro := elements.NewLabel ( intro := elements.NewLabel (
@ -39,7 +35,7 @@ func run () {
}) })
mouse := testing.NewMouse() mouse := testing.NewMouse()
input := elements.NewTextBox("Write some text", "") input := elements.NewTextBox("Write some text", "")
form := containers.NewContainer(layouts.Vertical { true, false}) form := elements.NewVBox(false, true)
form.Adopt(elements.NewLabel("I have:", false), false) form.Adopt(elements.NewLabel("I have:", false), false)
form.Adopt(elements.NewSpacer(true), false) form.Adopt(elements.NewSpacer(true), false)
form.Adopt(elements.NewCheckbox("Skin", true), false) form.Adopt(elements.NewCheckbox("Skin", true), false)
@ -47,13 +43,21 @@ func run () {
form.Adopt(elements.NewCheckbox("Bone", false), false) form.Adopt(elements.NewCheckbox("Bone", false), false)
art := testing.NewArtist() art := testing.NewArtist()
makePage := func (name string, callback func ()) tomo.Selectable {
cell := elements.NewCell(elements.NewLabel(name, false))
cell.OnSelectionChange (func () {
if cell.Selected() { callback() }
})
return cell
}
list := elements.NewList ( list := elements.NewList (
elements.NewListEntry("button", func () { turnPage(button) }), 1,
elements.NewListEntry("mouse", func () { turnPage(mouse) }), makePage("button", func () { turnPage(button) }),
elements.NewListEntry("input", func () { turnPage(input) }), makePage("mouse", func () { turnPage(mouse) }),
elements.NewListEntry("form", func () { turnPage(form) }), makePage("input", func () { turnPage(input) }),
elements.NewListEntry("art", func () { turnPage(art) })) makePage("form", func () { turnPage(form) }),
list.OnNoEntrySelected(func () { turnPage (intro) }) makePage("art", func () { turnPage(art) }))
list.Collapse(96, 0) list.Collapse(96, 0)
container.Adopt(list, false) container.Adopt(list, false)

View File

@ -1,6 +1,6 @@
package main package main
// import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/elements" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
@ -18,48 +18,49 @@ func run () {
textBox := elements.NewTextBox("", copypasta) textBox := elements.NewTextBox("", copypasta)
disconnectedContainer := elements.NewHBox(false, true) disconnectedContainer := elements.NewHBox(false, true)
// list := elements.NewList ( list := elements.NewList (
// elements.NewListEntry("This is list item 0", nil), 1,
// elements.NewListEntry("This is list item 1", nil), elements.NewCell(elements.NewLabel("This is list item 0", false)),
// elements.NewListEntry("This is list item 2", nil), elements.NewCell(elements.NewLabel("This is list item 1", false)),
// elements.NewListEntry("This is list item 3", nil), elements.NewCell(elements.NewLabel("This is list item 2", false)),
// elements.NewListEntry("This is list item 4", nil), elements.NewCell(elements.NewLabel("This is list item 3", false)),
// elements.NewListEntry("This is list item 5", nil), elements.NewCell(elements.NewLabel("This is list item 4", false)),
// elements.NewListEntry("This is list item 6", nil), elements.NewCell(elements.NewLabel("This is list item 5", false)),
// elements.NewListEntry("This is list item 7", nil), elements.NewCell(elements.NewLabel("This is list item 6", false)),
// elements.NewListEntry("This is list item 8", nil), elements.NewCell(elements.NewLabel("This is list item 7", false)),
// elements.NewListEntry("This is list item 9", nil), elements.NewCell(elements.NewLabel("This is list item 8", false)),
// elements.NewListEntry("This is list item 10", nil), elements.NewCell(elements.NewLabel("This is list item 9", false)),
// elements.NewListEntry("This is list item 11", nil), elements.NewCell(elements.NewLabel("This is list item 10", false)),
// elements.NewListEntry("This is list item 12", nil), elements.NewCell(elements.NewLabel("This is list item 11", false)),
// elements.NewListEntry("This is list item 13", nil), elements.NewCell(elements.NewLabel("This is list item 12", false)),
// elements.NewListEntry("This is list item 14", nil), elements.NewCell(elements.NewLabel("This is list item 13", false)),
// elements.NewListEntry("This is list item 15", nil), elements.NewCell(elements.NewLabel("This is list item 14", false)),
// elements.NewListEntry("This is list item 16", nil), elements.NewCell(elements.NewLabel("This is list item 15", false)),
// elements.NewListEntry("This is list item 17", nil), elements.NewCell(elements.NewLabel("This is list item 16", false)),
// elements.NewListEntry("This is list item 18", nil), elements.NewCell(elements.NewLabel("This is list item 17", false)),
// elements.NewListEntry("This is list item 19", nil), elements.NewCell(elements.NewLabel("This is list item 18", false)),
// elements.NewListEntry("This is list item 20", nil)) elements.NewCell(elements.NewLabel("This is list item 19", false)),
// list.Collapse(0, 32) elements.NewCell(elements.NewLabel("This is list item 20", false)))
// scrollBar := elements.NewScrollBar(true) list.Collapse(0, 32)
// list.OnScrollBoundsChange (func () { scrollBar := elements.NewScrollBar(true)
// scrollBar.SetBounds ( list.OnScrollBoundsChange (func () {
// list.ScrollContentBounds(), scrollBar.SetBounds (
// list.ScrollViewportBounds()) list.ScrollContentBounds(),
// }) list.ScrollViewportBounds())
// scrollBar.OnScroll (func (viewport image.Point) { })
// list.ScrollTo(viewport) scrollBar.OnScroll (func (viewport image.Point) {
// }) list.ScrollTo(viewport)
})
container.Adopt(elements.NewLabel("A ScrollContainer:", false), false) container.Adopt(elements.NewLabel("A ScrollContainer:", false), false)
container.Adopt(elements.NewScroll(textBox, true, false), false) container.Adopt(elements.NewScroll(textBox, true, false), false)
// disconnectedContainer.Adopt(list, false) disconnectedContainer.Adopt(list, false)
disconnectedContainer.Adopt (elements.NewLabel ( disconnectedContainer.Adopt (elements.NewLabel (
"Notice how the scroll bar to the right can be used to " + "Notice how the scroll bar to the right can be used to " +
"control the list, despite not even touching it. It is " + "control the list, despite not even touching it. It is " +
"indeed a thing you can do. It is also terrible UI design so " + "indeed a thing you can do. It is also terrible UI design so " +
"don't do it.", true), true) "don't do it.", true), true)
// disconnectedContainer.Adopt(scrollBar, false) disconnectedContainer.Adopt(scrollBar, false)
container.Adopt(disconnectedContainer, true) container.Adopt(disconnectedContainer, true)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)