Lists are a thing now
Looks like child bounds arent clipped properly though, ugh
This commit is contained in:
parent
6b13e772a9
commit
0bf5c3b86c
@ -102,10 +102,10 @@ func (entity *entity) scrollTargetChildAt (point image.Point) *entity {
|
||||
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 parent, ok := entity.parent.element.(tomo.MouseTargetContainer); ok {
|
||||
callback(parent)
|
||||
callback(parent, entity.element)
|
||||
}
|
||||
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) {
|
||||
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
|
||||
element.HandleSelectionChange()
|
||||
}
|
||||
|
@ -212,11 +212,11 @@ func (window *window) handleButtonPress (
|
||||
point.X, point.Y,
|
||||
input.Button(buttonEvent.Detail))
|
||||
}
|
||||
callback := func (container tomo.MouseTargetContainer) {
|
||||
callback := func (container tomo.MouseTargetContainer, child tomo.Element) {
|
||||
container.HandleChildMouseDown (
|
||||
point.X, point.Y,
|
||||
input.Button(buttonEvent.Detail),
|
||||
underneath.element)
|
||||
child)
|
||||
}
|
||||
underneath.forMouseTargetContainers(callback)
|
||||
}
|
||||
@ -238,12 +238,12 @@ func (window *window) handleButtonRelease (
|
||||
int(buttonEvent.EventY),
|
||||
input.Button(buttonEvent.Detail))
|
||||
}
|
||||
callback := func (container tomo.MouseTargetContainer) {
|
||||
callback := func (container tomo.MouseTargetContainer, child tomo.Element) {
|
||||
container.HandleChildMouseUp (
|
||||
int(buttonEvent.EventX),
|
||||
int(buttonEvent.EventY),
|
||||
input.Button(buttonEvent.Detail),
|
||||
dragging.element)
|
||||
child)
|
||||
}
|
||||
dragging.forMouseTargetContainers(callback)
|
||||
}
|
||||
|
@ -212,14 +212,9 @@ func (Default) Pattern (id tomo.Pattern, state tomo.State, c tomo.Case) artist.P
|
||||
switch id {
|
||||
case tomo.PatternBackground: return patterns.Uhex(0xaaaaaaFF)
|
||||
case tomo.PatternDead: return defaultTextures[0][offset]
|
||||
case tomo.PatternRaised:
|
||||
if c.Match("tomo", "listEntry", "") {
|
||||
return defaultTextures[10][offset]
|
||||
} else {
|
||||
return defaultTextures[1][offset]
|
||||
}
|
||||
case tomo.PatternSunken: return defaultTextures[2][offset]
|
||||
case tomo.PatternPinboard: return defaultTextures[3][offset]
|
||||
case tomo.PatternRaised: return defaultTextures[1][offset]
|
||||
case tomo.PatternSunken: return defaultTextures[2][offset]
|
||||
case tomo.PatternPinboard: return defaultTextures[3][offset]
|
||||
case tomo.PatternButton:
|
||||
switch {
|
||||
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.
|
||||
func (Default) Padding (id tomo.Pattern, c tomo.Case) artist.Inset {
|
||||
switch id {
|
||||
case tomo.PatternRaised:
|
||||
if c.Match("tomo", "listEntry", "") {
|
||||
return artist.I(4, 8)
|
||||
} else {
|
||||
return artist.I(8)
|
||||
}
|
||||
case tomo.PatternSunken:
|
||||
if c.Match("tomo", "list", "") {
|
||||
return artist.I(4, 0, 3)
|
||||
} else if c.Match("tomo", "progressBar", "") {
|
||||
if c.Match("tomo", "progressBar", "") {
|
||||
return artist.I(2, 1, 1, 2)
|
||||
} else {
|
||||
return artist.I(8)
|
||||
|
@ -13,18 +13,19 @@ type cellEntity interface {
|
||||
// Cell is a single-element container that satisfies tomo.Selectable. It
|
||||
// provides styling based on whether or not it is selected.
|
||||
type Cell struct {
|
||||
entity cellEntity
|
||||
child tomo.Element
|
||||
enabled bool
|
||||
padding bool
|
||||
theme theme.Wrapped
|
||||
entity cellEntity
|
||||
child tomo.Element
|
||||
enabled bool
|
||||
theme theme.Wrapped
|
||||
|
||||
onSelectionChange func ()
|
||||
}
|
||||
|
||||
// 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()
|
||||
// method.
|
||||
func NewCell (child tomo.Element, padding bool) (element *Cell) {
|
||||
element = &Cell { padding: padding }
|
||||
func NewCell (child tomo.Element) (element *Cell) {
|
||||
element = &Cell { enabled: true }
|
||||
element.theme.Case = tomo.C("tomo", "cell")
|
||||
element.entity = tomo.NewEntity(element).(cellEntity)
|
||||
element.Adopt(child)
|
||||
@ -42,7 +43,7 @@ func (element *Cell) Draw (destination canvas.Canvas) {
|
||||
pattern := element.theme.Pattern(tomo.PatternTableCell, element.state())
|
||||
if element.child == nil {
|
||||
pattern.Draw(destination, bounds)
|
||||
} else if element.padding {
|
||||
} else {
|
||||
artist.DrawShatter (
|
||||
destination, pattern, bounds,
|
||||
element.child.Entity().Bounds())
|
||||
@ -54,9 +55,7 @@ func (element *Cell) Layout () {
|
||||
if element.child == nil { return }
|
||||
|
||||
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)
|
||||
}
|
||||
@ -80,6 +79,7 @@ func (element *Cell) Adopt (child tomo.Element) {
|
||||
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.invalidateChild()
|
||||
element.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
@ -93,9 +93,7 @@ func (element *Cell) SetEnabled (enabled bool) {
|
||||
if element.enabled == enabled { return }
|
||||
element.enabled = enabled
|
||||
element.entity.Invalidate()
|
||||
if child, ok := element.child.(tomo.Enableable); ok {
|
||||
child.SetEnabled(enabled)
|
||||
}
|
||||
element.invalidateChild()
|
||||
}
|
||||
|
||||
// SetTheme sets this element's theme.
|
||||
@ -104,11 +102,26 @@ func (element *Cell) SetTheme (theme tomo.Theme) {
|
||||
element.theme.Theme = theme
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.invalidateChild()
|
||||
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 () {
|
||||
element.entity.Invalidate()
|
||||
element.invalidateChild()
|
||||
if element.onSelectionChange != nil {
|
||||
element.onSelectionChange()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Cell) HandleChildMinimumSizeChange (tomo.Element) {
|
||||
@ -132,11 +145,15 @@ func (element *Cell) updateMinimumSize () {
|
||||
width += childWidth
|
||||
height += childHeight
|
||||
}
|
||||
if element.padding {
|
||||
padding := element.theme.Padding(tomo.PatternTableCell)
|
||||
width += padding.Horizontal()
|
||||
height += padding.Vertical()
|
||||
}
|
||||
padding := element.theme.Padding(tomo.PatternTableCell)
|
||||
width += padding.Horizontal()
|
||||
height += padding.Vertical()
|
||||
|
||||
element.entity.SetMinimumSize(width, height)
|
||||
}
|
||||
|
||||
func (element *Cell) invalidateChild () {
|
||||
if element.child != nil {
|
||||
element.child.Entity().Invalidate()
|
||||
}
|
||||
}
|
||||
|
315
elements/list.go
Normal file
315
elements/list.go
Normal 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)
|
||||
}
|
@ -2,10 +2,8 @@ package main
|
||||
|
||||
import "git.tebibyte.media/sashakoshka/tomo"
|
||||
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/testing"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
|
||||
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
|
||||
|
||||
func main () {
|
||||
@ -16,18 +14,16 @@ func run () {
|
||||
window, _ := tomo.NewWindow(tomo.Bounds(0, 0, 300, 0))
|
||||
window.SetTitle("List Sidebar")
|
||||
|
||||
container := containers.NewContainer(layouts.Horizontal { true, true })
|
||||
container := elements.NewHBox(true, true)
|
||||
window.Adopt(container)
|
||||
|
||||
var currentPage tomo.Element
|
||||
turnPage := func (newPage tomo.Element) {
|
||||
container.Warp (func () {
|
||||
if currentPage != nil {
|
||||
container.Disown(currentPage)
|
||||
}
|
||||
container.Adopt(newPage, true)
|
||||
currentPage = newPage
|
||||
})
|
||||
if currentPage != nil {
|
||||
container.Disown(currentPage)
|
||||
}
|
||||
container.Adopt(newPage, true)
|
||||
currentPage = newPage
|
||||
}
|
||||
|
||||
intro := elements.NewLabel (
|
||||
@ -39,7 +35,7 @@ func run () {
|
||||
})
|
||||
mouse := testing.NewMouse()
|
||||
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.NewSpacer(true), false)
|
||||
form.Adopt(elements.NewCheckbox("Skin", true), false)
|
||||
@ -47,13 +43,21 @@ func run () {
|
||||
form.Adopt(elements.NewCheckbox("Bone", false), false)
|
||||
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 (
|
||||
elements.NewListEntry("button", func () { turnPage(button) }),
|
||||
elements.NewListEntry("mouse", func () { turnPage(mouse) }),
|
||||
elements.NewListEntry("input", func () { turnPage(input) }),
|
||||
elements.NewListEntry("form", func () { turnPage(form) }),
|
||||
elements.NewListEntry("art", func () { turnPage(art) }))
|
||||
list.OnNoEntrySelected(func () { turnPage (intro) })
|
||||
1,
|
||||
makePage("button", func () { turnPage(button) }),
|
||||
makePage("mouse", func () { turnPage(mouse) }),
|
||||
makePage("input", func () { turnPage(input) }),
|
||||
makePage("form", func () { turnPage(form) }),
|
||||
makePage("art", func () { turnPage(art) }))
|
||||
list.Collapse(96, 0)
|
||||
|
||||
container.Adopt(list, false)
|
||||
|
@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
// import "image"
|
||||
import "image"
|
||||
import "git.tebibyte.media/sashakoshka/tomo"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements"
|
||||
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
|
||||
@ -18,48 +18,49 @@ func run () {
|
||||
textBox := elements.NewTextBox("", copypasta)
|
||||
|
||||
disconnectedContainer := elements.NewHBox(false, true)
|
||||
// list := elements.NewList (
|
||||
// elements.NewListEntry("This is list item 0", nil),
|
||||
// elements.NewListEntry("This is list item 1", nil),
|
||||
// elements.NewListEntry("This is list item 2", nil),
|
||||
// elements.NewListEntry("This is list item 3", nil),
|
||||
// elements.NewListEntry("This is list item 4", nil),
|
||||
// elements.NewListEntry("This is list item 5", nil),
|
||||
// elements.NewListEntry("This is list item 6", nil),
|
||||
// elements.NewListEntry("This is list item 7", nil),
|
||||
// elements.NewListEntry("This is list item 8", nil),
|
||||
// elements.NewListEntry("This is list item 9", nil),
|
||||
// elements.NewListEntry("This is list item 10", nil),
|
||||
// elements.NewListEntry("This is list item 11", nil),
|
||||
// elements.NewListEntry("This is list item 12", nil),
|
||||
// elements.NewListEntry("This is list item 13", nil),
|
||||
// elements.NewListEntry("This is list item 14", nil),
|
||||
// elements.NewListEntry("This is list item 15", nil),
|
||||
// elements.NewListEntry("This is list item 16", nil),
|
||||
// elements.NewListEntry("This is list item 17", nil),
|
||||
// elements.NewListEntry("This is list item 18", nil),
|
||||
// elements.NewListEntry("This is list item 19", nil),
|
||||
// elements.NewListEntry("This is list item 20", nil))
|
||||
// list.Collapse(0, 32)
|
||||
// scrollBar := elements.NewScrollBar(true)
|
||||
// list.OnScrollBoundsChange (func () {
|
||||
// scrollBar.SetBounds (
|
||||
// list.ScrollContentBounds(),
|
||||
// list.ScrollViewportBounds())
|
||||
// })
|
||||
// scrollBar.OnScroll (func (viewport image.Point) {
|
||||
// list.ScrollTo(viewport)
|
||||
// })
|
||||
list := elements.NewList (
|
||||
1,
|
||||
elements.NewCell(elements.NewLabel("This is list item 0", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 1", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 2", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 3", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 4", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 5", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 6", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 7", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 8", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 9", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 10", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 11", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 12", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 13", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 14", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 15", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 16", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 17", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 18", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 19", false)),
|
||||
elements.NewCell(elements.NewLabel("This is list item 20", false)))
|
||||
list.Collapse(0, 32)
|
||||
scrollBar := elements.NewScrollBar(true)
|
||||
list.OnScrollBoundsChange (func () {
|
||||
scrollBar.SetBounds (
|
||||
list.ScrollContentBounds(),
|
||||
list.ScrollViewportBounds())
|
||||
})
|
||||
scrollBar.OnScroll (func (viewport image.Point) {
|
||||
list.ScrollTo(viewport)
|
||||
})
|
||||
|
||||
container.Adopt(elements.NewLabel("A ScrollContainer:", false), false)
|
||||
container.Adopt(elements.NewScroll(textBox, true, false), false)
|
||||
// disconnectedContainer.Adopt(list, false)
|
||||
disconnectedContainer.Adopt(list, false)
|
||||
disconnectedContainer.Adopt (elements.NewLabel (
|
||||
"Notice how the scroll bar to the right can be used to " +
|
||||
"control the list, despite not even touching it. It is " +
|
||||
"indeed a thing you can do. It is also terrible UI design so " +
|
||||
"don't do it.", true), true)
|
||||
// disconnectedContainer.Adopt(scrollBar, false)
|
||||
disconnectedContainer.Adopt(scrollBar, false)
|
||||
container.Adopt(disconnectedContainer, true)
|
||||
|
||||
window.OnClose(tomo.Stop)
|
||||
|
Reference in New Issue
Block a user