Re-organized module structure

This commit is contained in:
Sasha Koshka 2023-03-30 23:19:04 -04:00
parent 719b7b99ac
commit 53bfc8df68
62 changed files with 458 additions and 532 deletions

View File

@ -3,7 +3,6 @@ package tomo
import "errors" import "errors"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/elements"
// Backend represents a connection to a display server, or something similar. // Backend represents a connection to a display server, or something similar.
// It is capable of managing an event loop, and creating windows. // It is capable of managing an event loop, and creating windows.
@ -22,7 +21,7 @@ type Backend interface {
// NewWindow creates a new window with the specified width and height, // NewWindow creates a new window with the specified width and height,
// and returns a struct representing it that fulfills the MainWindow // and returns a struct representing it that fulfills the MainWindow
// interface. // interface.
NewWindow (width, height int) (window elements.MainWindow, err error) NewWindow (width, height int) (window MainWindow, err error)
// SetTheme sets the theme of all open windows. // SetTheme sets the theme of all open windows.
SetTheme (theme.Theme) SetTheme (theme.Theme)

View File

@ -1,8 +1,8 @@
package x package x
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/elements"
import "github.com/jezek/xgbutil" import "github.com/jezek/xgbutil"
import "github.com/jezek/xgb/xproto" import "github.com/jezek/xgb/xproto"
@ -127,7 +127,7 @@ func (window *window) handleKeyPress (
modifiers.NumberPad = numberPad modifiers.NumberPad = numberPad
if key == input.KeyTab && modifiers.Alt { if key == input.KeyTab && modifiers.Alt {
if child, ok := window.child.(elements.Focusable); ok { if child, ok := window.child.(tomo.Focusable); ok {
direction := input.KeynavDirectionForward direction := input.KeynavDirectionForward
if modifiers.Shift { if modifiers.Shift {
direction = input.KeynavDirectionBackward direction = input.KeynavDirectionBackward
@ -137,7 +137,7 @@ func (window *window) handleKeyPress (
child.HandleUnfocus() child.HandleUnfocus()
} }
} }
} else if child, ok := window.child.(elements.KeyboardTarget); ok { } else if child, ok := window.child.(tomo.KeyboardTarget); ok {
child.HandleKeyDown(key, modifiers) child.HandleKeyDown(key, modifiers)
} }
} }
@ -171,7 +171,7 @@ func (window *window) handleKeyRelease (
modifiers := window.modifiersFromState(keyEvent.State) modifiers := window.modifiersFromState(keyEvent.State)
modifiers.NumberPad = numberPad modifiers.NumberPad = numberPad
if child, ok := window.child.(elements.KeyboardTarget); ok { if child, ok := window.child.(tomo.KeyboardTarget); ok {
child.HandleKeyUp(key, modifiers) child.HandleKeyUp(key, modifiers)
} }
} }
@ -185,7 +185,7 @@ func (window *window) handleButtonPress (
buttonEvent := *event.ButtonPressEvent buttonEvent := *event.ButtonPressEvent
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 {
if child, ok := window.child.(elements.ScrollTarget); ok { if child, ok := window.child.(tomo.ScrollTarget); ok {
sum := scrollSum { } sum := scrollSum { }
sum.add(buttonEvent.Detail, window, buttonEvent.State) sum.add(buttonEvent.Detail, window, buttonEvent.State)
window.compressScrollSum(buttonEvent, &sum) window.compressScrollSum(buttonEvent, &sum)
@ -195,7 +195,7 @@ func (window *window) handleButtonPress (
float64(sum.x), float64(sum.y)) float64(sum.x), float64(sum.y))
} }
} else { } else {
if child, ok := window.child.(elements.MouseTarget); ok { if child, ok := window.child.(tomo.MouseTarget); ok {
child.HandleMouseDown ( child.HandleMouseDown (
int(buttonEvent.EventX), int(buttonEvent.EventX),
int(buttonEvent.EventY), int(buttonEvent.EventY),
@ -211,7 +211,7 @@ func (window *window) handleButtonRelease (
) { ) {
if window.child == nil { return } if window.child == nil { return }
if child, ok := window.child.(elements.MouseTarget); ok { if child, ok := window.child.(tomo.MouseTarget); ok {
buttonEvent := *event.ButtonReleaseEvent buttonEvent := *event.ButtonReleaseEvent
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return } if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return }
child.HandleMouseUp ( child.HandleMouseUp (
@ -227,7 +227,7 @@ func (window *window) handleMotionNotify (
) { ) {
if window.child == nil { return } if window.child == nil { return }
if child, ok := window.child.(elements.MotionTarget); ok { if child, ok := window.child.(tomo.MotionTarget); ok {
motionEvent := window.compressMotionNotify(*event.MotionNotifyEvent) motionEvent := window.compressMotionNotify(*event.MotionNotifyEvent)
child.HandleMotion ( child.HandleMotion (
int(motionEvent.EventX), int(motionEvent.EventX),

View File

@ -9,12 +9,12 @@ import "github.com/jezek/xgbutil/xprop"
import "github.com/jezek/xgbutil/xevent" import "github.com/jezek/xgbutil/xevent"
import "github.com/jezek/xgbutil/xwindow" import "github.com/jezek/xgbutil/xwindow"
import "github.com/jezek/xgbutil/xgraphics" import "github.com/jezek/xgbutil/xgraphics"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/data" import "git.tebibyte.media/sashakoshka/tomo/data"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/elements"
// import "runtime/debug" // import "runtime/debug"
type mainWindow struct { *window } type mainWindow struct { *window }
@ -23,7 +23,7 @@ type window struct {
xWindow *xwindow.Window xWindow *xwindow.Window
xCanvas *xgraphics.Image xCanvas *xgraphics.Image
canvas canvas.BasicCanvas canvas canvas.BasicCanvas
child elements.Element child tomo.Element
onClose func () onClose func ()
skipChildDrawCallback bool skipChildDrawCallback bool
@ -45,7 +45,7 @@ type window struct {
func (backend *Backend) NewWindow ( func (backend *Backend) NewWindow (
width, height int, width, height int,
) ( ) (
output elements.MainWindow, output tomo.MainWindow,
err error, err error,
) { ) {
if backend == nil { panic("nil backend") } if backend == nil { panic("nil backend") }
@ -120,35 +120,35 @@ func (backend *Backend) newWindow (
return return
} }
func (window *window) NotifyMinimumSizeChange (child elements.Element) { func (window *window) NotifyMinimumSizeChange (child tomo.Element) {
window.childMinimumSizeChangeCallback(child.MinimumSize()) window.childMinimumSizeChangeCallback(child.MinimumSize())
} }
func (window *window) RequestFocus ( func (window *window) RequestFocus (
child elements.Focusable, child tomo.Focusable,
) ( ) (
granted bool, granted bool,
) { ) {
return true return true
} }
func (window *window) RequestFocusNext (child elements.Focusable) { func (window *window) RequestFocusNext (child tomo.Focusable) {
if child, ok := window.child.(elements.Focusable); ok { if child, ok := window.child.(tomo.Focusable); ok {
if !child.HandleFocus(input.KeynavDirectionForward) { if !child.HandleFocus(input.KeynavDirectionForward) {
child.HandleUnfocus() child.HandleUnfocus()
} }
} }
} }
func (window *window) RequestFocusPrevious (child elements.Focusable) { func (window *window) RequestFocusPrevious (child tomo.Focusable) {
if child, ok := window.child.(elements.Focusable); ok { if child, ok := window.child.(tomo.Focusable); ok {
if !child.HandleFocus(input.KeynavDirectionBackward) { if !child.HandleFocus(input.KeynavDirectionBackward) {
child.HandleUnfocus() child.HandleUnfocus()
} }
} }
} }
func (window *window) Adopt (child elements.Element) { func (window *window) Adopt (child tomo.Element) {
// disown previous child // disown previous child
if window.child != nil { if window.child != nil {
window.child.SetParent(nil) window.child.SetParent(nil)
@ -159,10 +159,10 @@ func (window *window) Adopt (child elements.Element) {
// adopt new child // adopt new child
window.child = child window.child = child
child.SetParent(window) child.SetParent(window)
if newChild, ok := child.(elements.Themeable); ok { if newChild, ok := child.(tomo.Themeable); ok {
newChild.SetTheme(window.theme) newChild.SetTheme(window.theme)
} }
if newChild, ok := child.(elements.Configurable); ok { if newChild, ok := child.(tomo.Configurable); ok {
newChild.SetConfig(window.config) newChild.SetConfig(window.config)
} }
if child != nil { if child != nil {
@ -174,7 +174,7 @@ func (window *window) Adopt (child elements.Element) {
} }
} }
func (window *window) Child () (child elements.Element) { func (window *window) Child () (child tomo.Element) {
child = window.child child = window.child
return return
} }
@ -225,7 +225,7 @@ func (window *window) SetIcon (sizes []image.Image) {
wmIcons) wmIcons)
} }
func (window *window) NewModal (width, height int) (elements.Window, error) { func (window *window) NewModal (width, height int) (tomo.Window, error) {
modal, err := window.backend.newWindow(width, height) modal, err := window.backend.newWindow(width, height)
icccm.WmTransientForSet ( icccm.WmTransientForSet (
window.backend.connection, window.backend.connection,
@ -240,7 +240,7 @@ func (window *window) NewModal (width, height int) (elements.Window, error) {
return modal, err return modal, err
} }
func (window mainWindow) NewPanel (width, height int) (elements.Window, error) { func (window mainWindow) NewPanel (width, height int) (tomo.Window, error) {
panel, err := window.backend.newWindow(width, height) panel, err := window.backend.newWindow(width, height)
if err != nil { return nil, err } if err != nil { return nil, err }
panel.setClientLeader(window.window) panel.setClientLeader(window.window)
@ -336,14 +336,14 @@ func (window *window) OnClose (callback func ()) {
func (window *window) SetTheme (theme theme.Theme) { func (window *window) SetTheme (theme theme.Theme) {
window.theme = theme window.theme = theme
if child, ok := window.child.(elements.Themeable); ok { if child, ok := window.child.(tomo.Themeable); ok {
child.SetTheme(theme) child.SetTheme(theme)
} }
} }
func (window *window) SetConfig (config config.Config) { func (window *window) SetConfig (config config.Config) {
window.config = config window.config = config
if child, ok := window.child.(elements.Configurable); ok { if child, ok := window.child.(tomo.Configurable); ok {
child.SetConfig(config) child.SetConfig(config)
} }
} }

View File

@ -1,4 +1,4 @@
package elements package tomo
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"

View File

@ -1,3 +0,0 @@
// Package basicElements provides standard elements that are commonly used in
// GUI applications.
package basicElements

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "image" import "image"
// import "runtime/debug" // import "runtime/debug"
@ -34,7 +34,7 @@ type Button struct {
// NewButton creates a new button with the specified label text. // NewButton creates a new button with the specified label text.
func NewButton (text string) (element *Button) { func NewButton (text string) (element *Button) {
element = &Button { showText: true } element = &Button { showText: true }
element.theme.Case = theme.C("basic", "button") element.theme.Case = theme.C("tomo", "button")
element.Core, element.core = core.NewCore(element, element.drawAll) element.Core, element.core = core.NewCore(element, element.drawAll)
element.FocusableCore, element.FocusableCore,
element.focusableControl = core.NewFocusableCore(element.core, element.drawAndPush) element.focusableControl = core.NewFocusableCore(element.core, element.drawAndPush)

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
@ -28,7 +28,7 @@ type Checkbox struct {
// NewCheckbox creates a new cbeckbox with the specified label text. // NewCheckbox creates a new cbeckbox with the specified label text.
func NewCheckbox (text string, checked bool) (element *Checkbox) { func NewCheckbox (text string, checked bool) (element *Checkbox) {
element = &Checkbox { checked: checked } element = &Checkbox { checked: checked }
element.theme.Case = theme.C("basic", "checkbox") element.theme.Case = theme.C("tomo", "checkbox")
element.Core, element.core = core.NewCore(element, element.draw) element.Core, element.core = core.NewCore(element, element.draw)
element.FocusableCore, element.FocusableCore,
element.focusableControl = core.NewFocusableCore(element.core, element.redo) element.focusableControl = core.NewFocusableCore(element.core, element.redo)

View File

@ -1,13 +1,12 @@
package containers package containers
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
// Container is an element capable of containg other elements, and arranging // Container is an element capable of containg other elements, and arranging
@ -17,8 +16,8 @@ type Container struct {
*core.Propagator *core.Propagator
core core.CoreControl core core.CoreControl
layout layouts.Layout layout tomo.Layout
children []layouts.LayoutEntry children []tomo.LayoutEntry
warping bool warping bool
config config.Wrapped config config.Wrapped
@ -29,9 +28,9 @@ type Container struct {
} }
// NewContainer creates a new container. // NewContainer creates a new container.
func NewContainer (layout layouts.Layout) (element *Container) { func NewContainer (layout tomo.Layout) (element *Container) {
element = &Container { } element = &Container { }
element.theme.Case = theme.C("containers", "container") element.theme.Case = theme.C("tomo", "container")
element.Core, element.core = core.NewCore(element, element.redoAll) element.Core, element.core = core.NewCore(element, element.redoAll)
element.Propagator = core.NewPropagator(element, element.core) element.Propagator = core.NewPropagator(element, element.core)
element.SetLayout(layout) element.SetLayout(layout)
@ -39,7 +38,7 @@ func NewContainer (layout layouts.Layout) (element *Container) {
} }
// SetLayout sets the layout of this container. // SetLayout sets the layout of this container.
func (element *Container) SetLayout (layout layouts.Layout) { func (element *Container) SetLayout (layout tomo.Layout) {
element.layout = layout element.layout = layout
element.updateMinimumSize() element.updateMinimumSize()
if element.core.HasImage() { if element.core.HasImage() {
@ -51,17 +50,17 @@ func (element *Container) SetLayout (layout layouts.Layout) {
// Adopt adds a new child element to the container. If expand is set to true, // Adopt adds a new child element to the container. If expand is set to true,
// the element will expand (instead of contract to its minimum size), in // the element will expand (instead of contract to its minimum size), in
// whatever way is defined by the current layout. // whatever way is defined by the current layout.
func (element *Container) Adopt (child elements.Element, expand bool) { func (element *Container) Adopt (child tomo.Element, expand bool) {
if child0, ok := child.(elements.Themeable); ok { if child0, ok := child.(tomo.Themeable); ok {
child0.SetTheme(element.theme.Theme) child0.SetTheme(element.theme.Theme)
} }
if child0, ok := child.(elements.Configurable); ok { if child0, ok := child.(tomo.Configurable); ok {
child0.SetConfig(element.config.Config) child0.SetConfig(element.config.Config)
} }
child.SetParent(element) child.SetParent(element)
// add child // add child
element.children = append (element.children, layouts.LayoutEntry { element.children = append (element.children, tomo.LayoutEntry {
Element: child, Element: child,
Expand: expand, Expand: expand,
}) })
@ -98,7 +97,7 @@ func (element *Container) Warp (callback func ()) {
// Disown removes the given child from the container if it is contained within // Disown removes the given child from the container if it is contained within
// it. // it.
func (element *Container) Disown (child elements.Element) { func (element *Container) Disown (child tomo.Element) {
for index, entry := range element.children { for index, entry := range element.children {
if entry.Element == child { if entry.Element == child {
element.clearChildEventHandlers(entry.Element) element.clearChildEventHandlers(entry.Element)
@ -116,11 +115,11 @@ func (element *Container) Disown (child elements.Element) {
} }
} }
func (element *Container) clearChildEventHandlers (child elements.Element) { func (element *Container) clearChildEventHandlers (child tomo.Element) {
child.DrawTo(nil, image.Rectangle { }, nil) child.DrawTo(nil, image.Rectangle { }, nil)
child.SetParent(nil) child.SetParent(nil)
if child, ok := child.(elements.Focusable); ok { if child, ok := child.(tomo.Focusable); ok {
if child.Focused() { if child.Focused() {
child.HandleUnfocus() child.HandleUnfocus()
} }
@ -142,8 +141,8 @@ func (element *Container) DisownAll () {
} }
// Children returns a slice containing this element's children. // Children returns a slice containing this element's children.
func (element *Container) Children () (children []elements.Element) { func (element *Container) Children () (children []tomo.Element) {
children = make([]elements.Element, len(element.children)) children = make([]tomo.Element, len(element.children))
for index, entry := range element.children { for index, entry := range element.children {
children[index] = entry.Element children[index] = entry.Element
} }
@ -157,14 +156,14 @@ func (element *Container) CountChildren () (count int) {
// Child returns the child at the specified index. If the index is out of // Child returns the child at the specified index. If the index is out of
// bounds, this method will return nil. // bounds, this method will return nil.
func (element *Container) Child (index int) (child elements.Element) { func (element *Container) Child (index int) (child tomo.Element) {
if index < 0 || index > len(element.children) { return } if index < 0 || index > len(element.children) { return }
return element.children[index].Element return element.children[index].Element
} }
// ChildAt returns the child that contains the specified x and y coordinates. If // ChildAt returns the child that contains the specified x and y coordinates. If
// there are no children at the coordinates, this method will return nil. // there are no children at the coordinates, this method will return nil.
func (element *Container) ChildAt (point image.Point) (child elements.Element) { func (element *Container) ChildAt (point image.Point) (child tomo.Element) {
for _, entry := range element.children { for _, entry := range element.children {
if point.In(entry.Bounds) { if point.In(entry.Bounds) {
child = entry.Element child = entry.Element
@ -207,7 +206,7 @@ func (element *Container) redoAll () {
// NotifyMinimumSizeChange notifies the container that the minimum size of a // NotifyMinimumSizeChange notifies the container that the minimum size of a
// child element has changed. // child element has changed.
func (element *Container) NotifyMinimumSizeChange (child elements.Element) { func (element *Container) NotifyMinimumSizeChange (child tomo.Element) {
element.updateMinimumSize() element.updateMinimumSize()
element.redoAll() element.redoAll()
element.core.DamageAll() element.core.DamageAll()

View File

@ -1,12 +1,11 @@
package containers package containers
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
type DocumentContainer struct { type DocumentContainer struct {
@ -14,7 +13,7 @@ type DocumentContainer struct {
*core.Propagator *core.Propagator
core core.CoreControl core core.CoreControl
children []layouts.LayoutEntry children []tomo.LayoutEntry
scroll image.Point scroll image.Point
warping bool warping bool
contentBounds image.Rectangle contentBounds image.Rectangle
@ -28,24 +27,24 @@ type DocumentContainer struct {
// NewDocumentContainer creates a new document container. // NewDocumentContainer creates a new document container.
func NewDocumentContainer () (element *DocumentContainer) { func NewDocumentContainer () (element *DocumentContainer) {
element = &DocumentContainer { } element = &DocumentContainer { }
element.theme.Case = theme.C("containers", "documentContainer") element.theme.Case = theme.C("tomo", "documentContainer")
element.Core, element.core = core.NewCore(element, element.redoAll) element.Core, element.core = core.NewCore(element, element.redoAll)
element.Propagator = core.NewPropagator(element, element.core) element.Propagator = core.NewPropagator(element, element.core)
return return
} }
// Adopt adds a new child element to the container. // Adopt adds a new child element to the container.
func (element *DocumentContainer) Adopt (child elements.Element) { func (element *DocumentContainer) Adopt (child tomo.Element) {
// set event handlers // set event handlers
if child0, ok := child.(elements.Themeable); ok { if child0, ok := child.(tomo.Themeable); ok {
child0.SetTheme(element.theme.Theme) child0.SetTheme(element.theme.Theme)
} }
if child0, ok := child.(elements.Configurable); ok { if child0, ok := child.(tomo.Configurable); ok {
child0.SetConfig(element.config.Config) child0.SetConfig(element.config.Config)
} }
// add child // add child
element.children = append (element.children, layouts.LayoutEntry { element.children = append (element.children, tomo.LayoutEntry {
Element: child, Element: child,
}) })
@ -80,7 +79,7 @@ func (element *DocumentContainer) Warp (callback func ()) {
// Disown removes the given child from the container if it is contained within // Disown removes the given child from the container if it is contained within
// it. // it.
func (element *DocumentContainer) Disown (child elements.Element) { func (element *DocumentContainer) Disown (child tomo.Element) {
for index, entry := range element.children { for index, entry := range element.children {
if entry.Element == child { if entry.Element == child {
element.clearChildEventHandlers(entry.Element) element.clearChildEventHandlers(entry.Element)
@ -98,11 +97,11 @@ func (element *DocumentContainer) Disown (child elements.Element) {
} }
} }
func (element *DocumentContainer) clearChildEventHandlers (child elements.Element) { func (element *DocumentContainer) clearChildEventHandlers (child tomo.Element) {
child.DrawTo(nil, image.Rectangle { }, nil) child.DrawTo(nil, image.Rectangle { }, nil)
child.SetParent(nil) child.SetParent(nil)
if child, ok := child.(elements.Focusable); ok { if child, ok := child.(tomo.Focusable); ok {
if child.Focused() { if child.Focused() {
child.HandleUnfocus() child.HandleUnfocus()
} }
@ -124,8 +123,8 @@ func (element *DocumentContainer) DisownAll () {
} }
// Children returns a slice containing this element's children. // Children returns a slice containing this element's children.
func (element *DocumentContainer) Children () (children []elements.Element) { func (element *DocumentContainer) Children () (children []tomo.Element) {
children = make([]elements.Element, len(element.children)) children = make([]tomo.Element, len(element.children))
for index, entry := range element.children { for index, entry := range element.children {
children[index] = entry.Element children[index] = entry.Element
} }
@ -139,14 +138,14 @@ func (element *DocumentContainer) CountChildren () (count int) {
// Child returns the child at the specified index. If the index is out of // Child returns the child at the specified index. If the index is out of
// bounds, this method will return nil. // bounds, this method will return nil.
func (element *DocumentContainer) Child (index int) (child elements.Element) { func (element *DocumentContainer) Child (index int) (child tomo.Element) {
if index < 0 || index > len(element.children) { return } if index < 0 || index > len(element.children) { return }
return element.children[index].Element return element.children[index].Element
} }
// ChildAt returns the child that contains the specified x and y coordinates. If // ChildAt returns the child that contains the specified x and y coordinates. If
// there are no children at the coordinates, this method will return nil. // there are no children at the coordinates, this method will return nil.
func (element *DocumentContainer) ChildAt (point image.Point) (child elements.Element) { func (element *DocumentContainer) ChildAt (point image.Point) (child tomo.Element) {
for _, entry := range element.children { for _, entry := range element.children {
if point.In(entry.Bounds) { if point.In(entry.Bounds) {
child = entry.Element child = entry.Element
@ -178,7 +177,7 @@ func (element *DocumentContainer) redoAll () {
artist.DrawShatter(element.core, pattern, element.Bounds(), rocks...) artist.DrawShatter(element.core, pattern, element.Bounds(), rocks...)
element.partition() element.partition()
if parent, ok := element.core.Parent().(elements.ScrollableParent); ok { if parent, ok := element.core.Parent().(tomo.ScrollableParent); ok {
parent.NotifyScrollBoundsChange(element) parent.NotifyScrollBoundsChange(element)
} }
if element.onScrollBoundsChange != nil { if element.onScrollBoundsChange != nil {
@ -205,7 +204,7 @@ func (element *DocumentContainer) partition () {
// NotifyMinimumSizeChange notifies the container that the minimum size of a // NotifyMinimumSizeChange notifies the container that the minimum size of a
// child element has changed. // child element has changed.
func (element *DocumentContainer) NotifyMinimumSizeChange (child elements.Element) { func (element *DocumentContainer) NotifyMinimumSizeChange (child tomo.Element) {
element.redoAll() element.redoAll()
element.core.DamageAll() element.core.DamageAll()
} }
@ -214,7 +213,7 @@ func (element *DocumentContainer) NotifyMinimumSizeChange (child elements.Elemen
// affecting a child's flexible height have changed. This method is // affecting a child's flexible height have changed. This method is
// expected to be called by flexible child element when their content // expected to be called by flexible child element when their content
// changes. // changes.
func (element *DocumentContainer) NotifyFlexibleHeightChange (child elements.Flexible) { func (element *DocumentContainer) NotifyFlexibleHeightChange (child tomo.Flexible) {
element.redoAll() element.redoAll()
element.core.DamageAll() element.core.DamageAll()
} }
@ -300,7 +299,7 @@ func (element *DocumentContainer) doLayout () {
if width < bounds.Dx() { if width < bounds.Dx() {
width = bounds.Dx() width = bounds.Dx()
} }
if typedChild, ok := entry.Element.(elements.Flexible); ok { if typedChild, ok := entry.Element.(tomo.Flexible); ok {
height = typedChild.FlexibleHeightFor(width) height = typedChild.FlexibleHeightFor(width)
} }

View File

@ -1,13 +1,13 @@
package containers package containers
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/elements" import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
// ScrollContainer is a container that is capable of holding a scrollable // ScrollContainer is a container that is capable of holding a scrollable
// element. // element.
@ -16,9 +16,9 @@ type ScrollContainer struct {
*core.Propagator *core.Propagator
core core.CoreControl core core.CoreControl
child elements.Scrollable child tomo.Scrollable
horizontal *basicElements.ScrollBar horizontal *elements.ScrollBar
vertical *basicElements.ScrollBar vertical *elements.ScrollBar
config config.Wrapped config config.Wrapped
theme theme.Wrapped theme theme.Wrapped
@ -31,12 +31,12 @@ type ScrollContainer struct {
// bars. // bars.
func NewScrollContainer (horizontal, vertical bool) (element *ScrollContainer) { func NewScrollContainer (horizontal, vertical bool) (element *ScrollContainer) {
element = &ScrollContainer { } element = &ScrollContainer { }
element.theme.Case = theme.C("containers", "scrollContainer") element.theme.Case = theme.C("tomo", "scrollContainer")
element.Core, element.core = core.NewCore(element, element.redoAll) element.Core, element.core = core.NewCore(element, element.redoAll)
element.Propagator = core.NewPropagator(element, element.core) element.Propagator = core.NewPropagator(element, element.core)
if horizontal { if horizontal {
element.horizontal = basicElements.NewScrollBar(false) element.horizontal = elements.NewScrollBar(false)
element.setUpChild(element.horizontal) element.setUpChild(element.horizontal)
element.horizontal.OnScroll (func (viewport image.Point) { element.horizontal.OnScroll (func (viewport image.Point) {
if element.child != nil { if element.child != nil {
@ -50,7 +50,7 @@ func NewScrollContainer (horizontal, vertical bool) (element *ScrollContainer) {
}) })
} }
if vertical { if vertical {
element.vertical = basicElements.NewScrollBar(true) element.vertical = elements.NewScrollBar(true)
element.setUpChild(element.vertical) element.setUpChild(element.vertical)
element.vertical.OnScroll (func (viewport image.Point) { element.vertical.OnScroll (func (viewport image.Point) {
if element.child != nil { if element.child != nil {
@ -70,7 +70,7 @@ func NewScrollContainer (horizontal, vertical bool) (element *ScrollContainer) {
// Adopt adds a scrollable element to the scroll container. The container can // Adopt adds a scrollable element to the scroll container. The container can
// only contain one scrollable element at a time, and when a new one is adopted // only contain one scrollable element at a time, and when a new one is adopted
// it replaces the last one. // it replaces the last one.
func (element *ScrollContainer) Adopt (child elements.Scrollable) { func (element *ScrollContainer) Adopt (child tomo.Scrollable) {
// disown previous child if it exists // disown previous child if it exists
if element.child != nil { if element.child != nil {
element.disownChild(child) element.disownChild(child)
@ -90,20 +90,20 @@ func (element *ScrollContainer) Adopt (child elements.Scrollable) {
} }
} }
func (element *ScrollContainer) setUpChild (child elements.Element) { func (element *ScrollContainer) setUpChild (child tomo.Element) {
child.SetParent(element) child.SetParent(element)
if child, ok := child.(elements.Themeable); ok { if child, ok := child.(tomo.Themeable); ok {
child.SetTheme(element.theme.Theme) child.SetTheme(element.theme.Theme)
} }
if child, ok := child.(elements.Configurable); ok { if child, ok := child.(tomo.Configurable); ok {
child.SetConfig(element.config.Config) child.SetConfig(element.config.Config)
} }
} }
func (element *ScrollContainer) disownChild (child elements.Scrollable) { func (element *ScrollContainer) disownChild (child tomo.Scrollable) {
child.DrawTo(nil, image.Rectangle { }, nil) child.DrawTo(nil, image.Rectangle { }, nil)
child.SetParent(nil) child.SetParent(nil)
if child, ok := child.(elements.Focusable); ok { if child, ok := child.(tomo.Focusable); ok {
if child.Focused() { if child.Focused() {
child.HandleUnfocus() child.HandleUnfocus()
} }
@ -112,14 +112,14 @@ func (element *ScrollContainer) disownChild (child elements.Scrollable) {
// NotifyMinimumSizeChange notifies the container that the minimum size of a // NotifyMinimumSizeChange notifies the container that the minimum size of a
// child element has changed. // child element has changed.
func (element *ScrollContainer) NotifyMinimumSizeChange (child elements.Element) { func (element *ScrollContainer) NotifyMinimumSizeChange (child tomo.Element) {
element.redoAll() element.redoAll()
element.core.DamageAll() element.core.DamageAll()
} }
// NotifyScrollBoundsChange notifies the container that the scroll bounds or // NotifyScrollBoundsChange notifies the container that the scroll bounds or
// axes of a child have changed. // axes of a child have changed.
func (element *ScrollContainer) NotifyScrollBoundsChange (child elements.Scrollable) { func (element *ScrollContainer) NotifyScrollBoundsChange (child tomo.Scrollable) {
element.updateEnabled() element.updateEnabled()
viewportBounds := element.child.ScrollViewportBounds() viewportBounds := element.child.ScrollViewportBounds()
contentBounds := element.child.ScrollContentBounds() contentBounds := element.child.ScrollContentBounds()
@ -165,7 +165,7 @@ func (element *ScrollContainer) CountChildren () (count int) {
// Child returns the child at the specified index. If the index is out of // Child returns the child at the specified index. If the index is out of
// bounds, this method will return nil. // bounds, this method will return nil.
func (element *ScrollContainer) Child (index int) (child elements.Element) { func (element *ScrollContainer) Child (index int) (child tomo.Element) {
switch index { switch index {
case 0: return element.child case 0: return element.child
case 1: case 1:

View File

@ -2,16 +2,16 @@ package core
import "image" import "image"
import "image/color" import "image/color"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/elements"
// Core is a struct that implements some core functionality common to most // Core is a struct that implements some core functionality common to most
// widgets. It is meant to be embedded directly into a struct. // widgets. It is meant to be embedded directly into a struct.
type Core struct { type Core struct {
canvas canvas.Canvas canvas canvas.Canvas
bounds image.Rectangle bounds image.Rectangle
parent elements.Parent parent tomo.Parent
outer elements.Element outer tomo.Element
metrics struct { metrics struct {
minimumWidth int minimumWidth int
@ -26,7 +26,7 @@ type Core struct {
// element that it will be a part of. If outer is nil, this function will return // element that it will be a part of. If outer is nil, this function will return
// nil. // nil.
func NewCore ( func NewCore (
outer elements.Element, outer tomo.Element,
drawSizeChange func (), drawSizeChange func (),
) ( ) (
core *Core, core *Core,
@ -57,7 +57,7 @@ func (core *Core) MinimumSize () (width, height int) {
// MinimumSize fulfils the tomo.Element interface. This should not need to be // MinimumSize fulfils the tomo.Element interface. This should not need to be
// overridden, unless you want to detect when the element is parented or // overridden, unless you want to detect when the element is parented or
// unparented. // unparented.
func (core *Core) SetParent (parent elements.Parent) { func (core *Core) SetParent (parent tomo.Parent) {
if parent != nil && core.parent != nil { if parent != nil && core.parent != nil {
panic("core.SetParent: element already has a parent") panic("core.SetParent: element already has a parent")
} }
@ -118,12 +118,12 @@ func (control CoreControl) Buffer () (data []color.RGBA, stride int) {
} }
// Parent returns the element's parent. // Parent returns the element's parent.
func (control CoreControl) Parent () elements.Parent { func (control CoreControl) Parent () tomo.Parent {
return control.core.parent return control.core.parent
} }
// Outer returns the outer element given when the control was constructed. // Outer returns the outer element given when the control was constructed.
func (control CoreControl) Outer () elements.Element { func (control CoreControl) Outer () tomo.Element {
return control.core.outer return control.core.outer
} }

View File

@ -1,8 +1,8 @@
package core package core
// import "runtime/debug" // import "runtime/debug"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/elements"
// FocusableCore is a struct that can be embedded into objects to make them // FocusableCore is a struct that can be embedded into objects to make them
// focusable, giving them the default keynav behavior. // focusable, giving them the default keynav behavior.
@ -42,9 +42,9 @@ func (core *FocusableCore) Focused () (focused bool) {
func (core *FocusableCore) Focus () { func (core *FocusableCore) Focus () {
if !core.enabled || core.focused { return } if !core.enabled || core.focused { return }
parent := core.core.Parent() parent := core.core.Parent()
if parent, ok := parent.(elements.FocusableParent); ok { if parent, ok := parent.(tomo.FocusableParent); ok {
core.focused = parent.RequestFocus ( core.focused = parent.RequestFocus (
core.core.Outer().(elements.Focusable)) core.core.Outer().(tomo.Focusable))
} }
} }

View File

@ -1,15 +1,15 @@
package core package core
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/elements"
// Container represents an object that can provide access to a list of child // Container represents an object that can provide access to a list of child
// elements. // elements.
type Container interface { type Container interface {
Child (index int) elements.Element Child (index int) tomo.Element
CountChildren () int CountChildren () int
} }
@ -20,7 +20,7 @@ type Container interface {
type Propagator struct { type Propagator struct {
core CoreControl core CoreControl
container Container container Container
drags [10]elements.MouseTarget drags [10]tomo.MouseTarget
focused bool focused bool
} }
@ -49,9 +49,9 @@ func (propagator *Propagator) Focused () (focused bool) {
func (propagator *Propagator) Focus () { func (propagator *Propagator) Focus () {
if propagator.focused == true { return } if propagator.focused == true { return }
parent := propagator.core.Parent() parent := propagator.core.Parent()
if parent, ok := parent.(elements.FocusableParent); ok && parent != nil { if parent, ok := parent.(tomo.FocusableParent); ok && parent != nil {
propagator.focused = parent.RequestFocus ( propagator.focused = parent.RequestFocus (
propagator.core.Outer().(elements.Focusable)) propagator.core.Outer().(tomo.Focusable))
} }
} }
@ -90,7 +90,7 @@ func (propagator *Propagator) HandleFocus (direction input.KeynavDirection) (acc
// focus in the specified direction // focus in the specified direction
firstFocusedChild := firstFocusedChild :=
propagator.container.Child(firstFocused). propagator.container.Child(firstFocused).
(elements.Focusable) (tomo.Focusable)
// before we move the focus, the currently focused child // before we move the focus, the currently focused child
// may also be able to move its focus. if the child is able // may also be able to move its focus. if the child is able
@ -107,7 +107,7 @@ func (propagator *Propagator) HandleFocus (direction input.KeynavDirection) (acc
child, focusable := child, focusable :=
propagator.container.Child(index). propagator.container.Child(index).
(elements.Focusable) (tomo.Focusable)
if focusable && child.HandleFocus(direction) { if focusable && child.HandleFocus(direction) {
// we have found one, so we now actually move // we have found one, so we now actually move
// the focus. // the focus.
@ -126,12 +126,12 @@ func (propagator *Propagator) HandleFocus (direction input.KeynavDirection) (acc
// return true and the child element should behave as if a HandleFocus // return true and the child element should behave as if a HandleFocus
// call was made. // call was made.
func (propagator *Propagator) RequestFocus ( func (propagator *Propagator) RequestFocus (
child elements.Focusable, child tomo.Focusable,
) ( ) (
granted bool, granted bool,
) { ) {
if parent, ok := propagator.core.Parent().(elements.FocusableParent); ok { if parent, ok := propagator.core.Parent().(tomo.FocusableParent); ok {
if parent.RequestFocus(propagator.core.Outer().(elements.Focusable)) { if parent.RequestFocus(propagator.core.Outer().(tomo.Focusable)) {
propagator.HandleUnfocus() propagator.HandleUnfocus()
propagator.focused = true propagator.focused = true
granted = true granted = true
@ -142,26 +142,26 @@ func (propagator *Propagator) RequestFocus (
// RequestFocusMotion notifies the parent that a child element wants the // RequestFocusMotion notifies the parent that a child element wants the
// focus to be moved to the next focusable element. // focus to be moved to the next focusable element.
func (propagator *Propagator) RequestFocusNext (child elements.Focusable) { func (propagator *Propagator) RequestFocusNext (child tomo.Focusable) {
if !propagator.focused { return } if !propagator.focused { return }
if parent, ok := propagator.core.Parent().(elements.FocusableParent); ok { if parent, ok := propagator.core.Parent().(tomo.FocusableParent); ok {
parent.RequestFocusNext(propagator.core.Outer().(elements.Focusable)) parent.RequestFocusNext(propagator.core.Outer().(tomo.Focusable))
} }
} }
// RequestFocusMotion notifies the parent that a child element wants the // RequestFocusMotion notifies the parent that a child element wants the
// focus to be moved to the previous focusable element. // focus to be moved to the previous focusable element.
func (propagator *Propagator) RequestFocusPrevious (child elements.Focusable) { func (propagator *Propagator) RequestFocusPrevious (child tomo.Focusable) {
if !propagator.focused { return } if !propagator.focused { return }
if parent, ok := propagator.core.Parent().(elements.FocusableParent); ok { if parent, ok := propagator.core.Parent().(tomo.FocusableParent); ok {
parent.RequestFocusPrevious(propagator.core.Outer().(elements.Focusable)) parent.RequestFocusPrevious(propagator.core.Outer().(tomo.Focusable))
} }
} }
// HandleDeselection causes this element to mark itself and all of its children // HandleDeselection causes this element to mark itself and all of its children
// as unfocused. // as unfocused.
func (propagator *Propagator) HandleUnfocus () { func (propagator *Propagator) HandleUnfocus () {
propagator.forFocusable (func (child elements.Focusable) bool { propagator.forFocusable (func (child tomo.Focusable) bool {
child.HandleUnfocus() child.HandleUnfocus()
return true return true
}) })
@ -170,8 +170,8 @@ func (propagator *Propagator) HandleUnfocus () {
// HandleKeyDown propogates the keyboard event to the currently selected child. // HandleKeyDown propogates the keyboard event to the currently selected child.
func (propagator *Propagator) HandleKeyDown (key input.Key, modifiers input.Modifiers) { func (propagator *Propagator) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
propagator.forFocused (func (child elements.Focusable) bool { propagator.forFocused (func (child tomo.Focusable) bool {
typedChild, handlesKeyboard := child.(elements.KeyboardTarget) typedChild, handlesKeyboard := child.(tomo.KeyboardTarget)
if handlesKeyboard { if handlesKeyboard {
typedChild.HandleKeyDown(key, modifiers) typedChild.HandleKeyDown(key, modifiers)
} }
@ -181,8 +181,8 @@ func (propagator *Propagator) HandleKeyDown (key input.Key, modifiers input.Modi
// HandleKeyUp propogates the keyboard event to the currently selected child. // HandleKeyUp propogates the keyboard event to the currently selected child.
func (propagator *Propagator) HandleKeyUp (key input.Key, modifiers input.Modifiers) { func (propagator *Propagator) HandleKeyUp (key input.Key, modifiers input.Modifiers) {
propagator.forFocused (func (child elements.Focusable) bool { propagator.forFocused (func (child tomo.Focusable) bool {
typedChild, handlesKeyboard := child.(elements.KeyboardTarget) typedChild, handlesKeyboard := child.(tomo.KeyboardTarget)
if handlesKeyboard { if handlesKeyboard {
typedChild.HandleKeyUp(key, modifiers) typedChild.HandleKeyUp(key, modifiers)
} }
@ -195,7 +195,7 @@ func (propagator *Propagator) HandleKeyUp (key input.Key, modifiers input.Modifi
func (propagator *Propagator) HandleMouseDown (x, y int, button input.Button) { func (propagator *Propagator) HandleMouseDown (x, y int, button input.Button) {
child, handlesMouse := child, handlesMouse :=
propagator.childAt(image.Pt(x, y)). propagator.childAt(image.Pt(x, y)).
(elements.MouseTarget) (tomo.MouseTarget)
if handlesMouse { if handlesMouse {
propagator.drags[button] = child propagator.drags[button] = child
child.HandleMouseDown(x, y, button) child.HandleMouseDown(x, y, button)
@ -218,7 +218,7 @@ func (propagator *Propagator) HandleMouseUp (x, y int, button input.Button) {
func (propagator *Propagator) HandleMotion (x, y int) { func (propagator *Propagator) HandleMotion (x, y int) {
handled := false handled := false
for _, child := range propagator.drags { for _, child := range propagator.drags {
if child, ok := child.(elements.MotionTarget); ok { if child, ok := child.(tomo.MotionTarget); ok {
child.HandleMotion(x, y) child.HandleMotion(x, y)
handled = true handled = true
} }
@ -226,7 +226,7 @@ func (propagator *Propagator) HandleMotion (x, y int) {
if !handled { if !handled {
child := propagator.childAt(image.Pt(x, y)) child := propagator.childAt(image.Pt(x, y))
if child, ok := child.(elements.MotionTarget); ok { if child, ok := child.(tomo.MotionTarget); ok {
child.HandleMotion(x, y) child.HandleMotion(x, y)
} }
} }
@ -236,15 +236,15 @@ func (propagator *Propagator) HandleMotion (x, y int) {
// pointer. // pointer.
func (propagator *Propagator) HandleScroll (x, y int, deltaX, deltaY float64) { func (propagator *Propagator) HandleScroll (x, y int, deltaX, deltaY float64) {
child := propagator.childAt(image.Pt(x, y)) child := propagator.childAt(image.Pt(x, y))
if child, ok := child.(elements.ScrollTarget); ok { if child, ok := child.(tomo.ScrollTarget); ok {
child.HandleScroll(x, y, deltaX, deltaY) child.HandleScroll(x, y, deltaX, deltaY)
} }
} }
// SetTheme sets the theme of all children to the specified theme. // SetTheme sets the theme of all children to the specified theme.
func (propagator *Propagator) SetTheme (theme theme.Theme) { func (propagator *Propagator) SetTheme (theme theme.Theme) {
propagator.forChildren (func (child elements.Element) bool { propagator.forChildren (func (child tomo.Element) bool {
typedChild, themeable := child.(elements.Themeable) typedChild, themeable := child.(tomo.Themeable)
if themeable { if themeable {
typedChild.SetTheme(theme) typedChild.SetTheme(theme)
} }
@ -254,8 +254,8 @@ func (propagator *Propagator) SetTheme (theme theme.Theme) {
// SetConfig sets the theme of all children to the specified config. // SetConfig sets the theme of all children to the specified config.
func (propagator *Propagator) SetConfig (config config.Config) { func (propagator *Propagator) SetConfig (config config.Config) {
propagator.forChildren (func (child elements.Element) bool { propagator.forChildren (func (child tomo.Element) bool {
typedChild, configurable := child.(elements.Configurable) typedChild, configurable := child.(tomo.Configurable)
if configurable { if configurable {
typedChild.SetConfig(config) typedChild.SetConfig(config)
} }
@ -270,7 +270,7 @@ func (propagator *Propagator) focusFirstFocusableElement (
) ( ) (
ok bool, ok bool,
) { ) {
propagator.forFocusable (func (child elements.Focusable) bool { propagator.forFocusable (func (child tomo.Focusable) bool {
if child.HandleFocus(direction) { if child.HandleFocus(direction) {
propagator.focused = true propagator.focused = true
ok = true ok = true
@ -286,8 +286,8 @@ func (propagator *Propagator) focusLastFocusableElement (
) ( ) (
ok bool, ok bool,
) { ) {
propagator.forChildrenReverse (func (child elements.Element) bool { propagator.forChildrenReverse (func (child tomo.Element) bool {
typedChild, focusable := child.(elements.Focusable) typedChild, focusable := child.(tomo.Focusable)
if focusable && typedChild.HandleFocus(direction) { if focusable && typedChild.HandleFocus(direction) {
propagator.focused = true propagator.focused = true
ok = true ok = true
@ -300,7 +300,7 @@ func (propagator *Propagator) focusLastFocusableElement (
// ----------- Iterator utilities ----------- // // ----------- Iterator utilities ----------- //
func (propagator *Propagator) forChildren (callback func (child elements.Element) bool) { func (propagator *Propagator) forChildren (callback func (child tomo.Element) bool) {
for index := 0; index < propagator.container.CountChildren(); index ++ { for index := 0; index < propagator.container.CountChildren(); index ++ {
child := propagator.container.Child(index) child := propagator.container.Child(index)
if child == nil { continue } if child == nil { continue }
@ -308,7 +308,7 @@ func (propagator *Propagator) forChildren (callback func (child elements.Element
} }
} }
func (propagator *Propagator) forChildrenReverse (callback func (child elements.Element) bool) { func (propagator *Propagator) forChildrenReverse (callback func (child tomo.Element) bool) {
for index := propagator.container.CountChildren() - 1; index > 0; index -- { for index := propagator.container.CountChildren() - 1; index > 0; index -- {
child := propagator.container.Child(index) child := propagator.container.Child(index)
if child == nil { continue } if child == nil { continue }
@ -316,8 +316,8 @@ func (propagator *Propagator) forChildrenReverse (callback func (child elements.
} }
} }
func (propagator *Propagator) childAt (position image.Point) (child elements.Element) { func (propagator *Propagator) childAt (position image.Point) (child tomo.Element) {
propagator.forChildren (func (current elements.Element) bool { propagator.forChildren (func (current tomo.Element) bool {
if position.In(current.Bounds()) { if position.In(current.Bounds()) {
child = current child = current
} }
@ -326,9 +326,9 @@ func (propagator *Propagator) childAt (position image.Point) (child elements.Ele
return return
} }
func (propagator *Propagator) forFocused (callback func (child elements.Focusable) bool) { func (propagator *Propagator) forFocused (callback func (child tomo.Focusable) bool) {
propagator.forChildren (func (child elements.Element) bool { propagator.forChildren (func (child tomo.Element) bool {
typedChild, focusable := child.(elements.Focusable) typedChild, focusable := child.(tomo.Focusable)
if focusable && typedChild.Focused() { if focusable && typedChild.Focused() {
if !callback(typedChild) { return false } if !callback(typedChild) { return false }
} }
@ -336,9 +336,9 @@ func (propagator *Propagator) forFocused (callback func (child elements.Focusabl
}) })
} }
func (propagator *Propagator) forFocusable (callback func (child elements.Focusable) bool) { func (propagator *Propagator) forFocusable (callback func (child tomo.Focusable) bool) {
propagator.forChildren (func (child elements.Element) bool { propagator.forChildren (func (child tomo.Element) bool {
typedChild, focusable := child.(elements.Focusable) typedChild, focusable := child.(tomo.Focusable)
if focusable { if focusable {
if !callback(typedChild) { return false } if !callback(typedChild) { return false }
} }
@ -348,7 +348,7 @@ func (propagator *Propagator) forFocusable (callback func (child elements.Focusa
func (propagator *Propagator) firstFocused () int { func (propagator *Propagator) firstFocused () int {
for index := 0; index < propagator.container.CountChildren(); index ++ { for index := 0; index < propagator.container.CountChildren(); index ++ {
child, focusable := propagator.container.Child(index).(elements.Focusable) child, focusable := propagator.container.Child(index).(tomo.Focusable)
if focusable && child.Focused() { if focusable && child.Focused() {
return index return index
} }

View File

@ -1,6 +1,3 @@
// Package elements provides several standard interfaces that elements can // Package elements provides standard elements that are commonly used in GUI
// fulfill in order to inform other elements of their capabilities and what // applications.
// events they are able to process. Sub-packages of this package provide
// pre-made standard elements, as well as tools that can be used to easily
// create more.
package elements package elements

View File

@ -22,7 +22,7 @@ type AnalogClock struct {
// NewAnalogClock creates a new analog clock that displays the specified time. // NewAnalogClock creates a new analog clock that displays the specified time.
func NewAnalogClock (newTime time.Time) (element *AnalogClock) { func NewAnalogClock (newTime time.Time) (element *AnalogClock) {
element = &AnalogClock { } element = &AnalogClock { }
element.theme.Case = theme.C("fun", "clock") element.theme.Case = theme.C("tomo", "clock")
element.Core, element.core = core.NewCore(element, element.draw) element.Core, element.core = core.NewCore(element, element.draw)
element.core.SetMinimumSize(64, 64) element.core.SetMinimumSize(64, 64)
return return

View File

@ -52,7 +52,7 @@ func NewPiano (low, high music.Octave) (element *Piano) {
keynavPressed: make(map[music.Note] bool), keynavPressed: make(map[music.Note] bool),
} }
element.theme.Case = theme.C("fun", "piano") element.theme.Case = theme.C("tomo", "piano")
element.Core, element.core = core.NewCore (element, func () { element.Core, element.core = core.NewCore (element, func () {
element.recalculate() element.recalculate()
element.draw() element.draw()

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
@ -18,7 +18,7 @@ func NewIcon (id theme.Icon, size theme.IconSize) (element *Icon) {
id: id, id: id,
size: size, size: size,
} }
element.theme.Case = theme.C("basic", "icon") element.theme.Case = theme.C("tomo", "icon")
element.Core, element.core = core.NewCore(element, element.draw) element.Core, element.core = core.NewCore(element, element.draw)
element.updateMinimumSize() element.updateMinimumSize()
return return

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/canvas"

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "golang.org/x/image/math/fixed" import "golang.org/x/image/math/fixed"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
@ -29,7 +29,7 @@ type Label struct {
// wrapped. // wrapped.
func NewLabel (text string, wrap bool) (element *Label) { func NewLabel (text string, wrap bool) (element *Label) {
element = &Label { } element = &Label { }
element.theme.Case = theme.C("basic", "label") element.theme.Case = theme.C("tomo", "label")
element.Core, element.core = core.NewCore(element, element.handleResize) element.Core, element.core = core.NewCore(element, element.handleResize)
element.SetWrap(wrap) element.SetWrap(wrap)
element.SetText(text) element.SetText(text)

View File

@ -1,4 +1,4 @@
package basicElements package elements
// Numeric is a type constraint representing a number. // Numeric is a type constraint representing a number.
type Numeric interface { type Numeric interface {

View File

@ -1,13 +1,13 @@
package basicElements package elements
import "fmt" import "fmt"
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
// List is an element that contains several objects that a user can select. // List is an element that contains several objects that a user can select.
@ -37,7 +37,7 @@ type List struct {
// NewList creates a new list element with the specified entries. // NewList creates a new list element with the specified entries.
func NewList (entries ...ListEntry) (element *List) { func NewList (entries ...ListEntry) (element *List) {
element = &List { selectedEntry: -1 } element = &List { selectedEntry: -1 }
element.theme.Case = theme.C("basic", "list") element.theme.Case = theme.C("tomo", "list")
element.Core, element.core = core.NewCore(element, element.handleResize) element.Core, element.core = core.NewCore(element, element.handleResize)
element.FocusableCore, element.FocusableCore,
element.focusableControl = core.NewFocusableCore (element.core, func () { element.focusableControl = core.NewFocusableCore (element.core, func () {
@ -435,7 +435,7 @@ func (element *List) updateMinimumSize () {
} }
func (element *List) scrollBoundsChange () { func (element *List) scrollBoundsChange () {
if parent, ok := element.core.Parent().(elements.ScrollableParent); ok { if parent, ok := element.core.Parent().(tomo.ScrollableParent); ok {
parent.NotifyScrollBoundsChange(element) parent.NotifyScrollBoundsChange(element)
} }
if element.onScrollBoundsChange != nil { if element.onScrollBoundsChange != nil {

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
@ -26,7 +26,7 @@ func NewListEntry (text string, onSelect func ()) (entry ListEntry) {
text: text, text: text,
onSelect: onSelect, onSelect: onSelect,
} }
entry.theme.Case = theme.C("basic", "listEntry") entry.theme.Case = theme.C("tomo", "listEntry")
entry.drawer.SetText([]rune(text)) entry.drawer.SetText([]rune(text))
entry.updateBounds() entry.updateBounds()
return return

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
@ -19,7 +19,7 @@ type ProgressBar struct {
// level. // level.
func NewProgressBar (progress float64) (element *ProgressBar) { func NewProgressBar (progress float64) (element *ProgressBar) {
element = &ProgressBar { progress: progress } element = &ProgressBar { progress: progress }
element.theme.Case = theme.C("basic", "progressBar") element.theme.Case = theme.C("tomo", "progressBar")
element.Core, element.core = core.NewCore(element, element.draw) element.Core, element.core = core.NewCore(element, element.draw)
return return
} }

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
@ -45,9 +45,9 @@ func NewScrollBar (vertical bool) (element *ScrollBar) {
enabled: true, enabled: true,
} }
if vertical { if vertical {
element.theme.Case = theme.C("basic", "scrollBarHorizontal") element.theme.Case = theme.C("tomo", "scrollBarHorizontal")
} else { } else {
element.theme.Case = theme.C("basic", "scrollBarVertical") element.theme.Case = theme.C("tomo", "scrollBarVertical")
} }
element.Core, element.core = core.NewCore(element, element.handleResize) element.Core, element.core = core.NewCore(element, element.handleResize)
element.updateMinimumSize() element.updateMinimumSize()

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
@ -35,9 +35,9 @@ func NewSlider (value float64, vertical bool) (element *Slider) {
vertical: vertical, vertical: vertical,
} }
if vertical { if vertical {
element.theme.Case = theme.C("basic", "sliderVertical") element.theme.Case = theme.C("tomo", "sliderVertical")
} else { } else {
element.theme.Case = theme.C("basic", "sliderHorizontal") element.theme.Case = theme.C("tomo", "sliderHorizontal")
} }
element.Core, element.core = core.NewCore(element, element.draw) element.Core, element.core = core.NewCore(element, element.draw)
element.FocusableCore, element.FocusableCore,

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
@ -19,7 +19,7 @@ type Spacer struct {
// will appear as a line. // will appear as a line.
func NewSpacer (line bool) (element *Spacer) { func NewSpacer (line bool) (element *Spacer) {
element = &Spacer { line: line } element = &Spacer { line: line }
element.theme.Case = theme.C("basic", "spacer") element.theme.Case = theme.C("tomo", "spacer")
element.Core, element.core = core.NewCore(element, element.draw) element.Core, element.core = core.NewCore(element, element.draw)
element.updateMinimumSize() element.updateMinimumSize()
return return

View File

@ -1,4 +1,4 @@
package basicElements package elements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
@ -32,7 +32,7 @@ func NewSwitch (text string, on bool) (element *Switch) {
checked: on, checked: on,
text: text, text: text,
} }
element.theme.Case = theme.C("basic", "switch") element.theme.Case = theme.C("tomo", "switch")
element.Core, element.core = core.NewCore(element, element.draw) element.Core, element.core = core.NewCore(element, element.draw)
element.FocusableCore, element.FocusableCore,
element.focusableControl = core.NewFocusableCore(element.core, element.redo) element.focusableControl = core.NewFocusableCore(element.core, element.redo)

View File

@ -23,7 +23,7 @@ type Mouse struct {
// NewMouse creates a new mouse test element. // NewMouse creates a new mouse test element.
func NewMouse () (element *Mouse) { func NewMouse () (element *Mouse) {
element = &Mouse { c: theme.C("testing", "mouse") } element = &Mouse { c: theme.C("tomo", "mouse") }
element.Core, element.core = core.NewCore(element, element.draw) element.Core, element.core = core.NewCore(element, element.draw)
element.core.SetMinimumSize(32, 32) element.core.SetMinimumSize(32, 32)
return return

View File

@ -1,12 +1,12 @@
package basicElements package elements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/textdraw" import "git.tebibyte.media/sashakoshka/tomo/textdraw"
import "git.tebibyte.media/sashakoshka/tomo/textmanip" import "git.tebibyte.media/sashakoshka/tomo/textmanip"
import "git.tebibyte.media/sashakoshka/tomo/fixedutil" import "git.tebibyte.media/sashakoshka/tomo/fixedutil"
@ -43,7 +43,7 @@ type TextBox struct {
// text. // text.
func NewTextBox (placeholder, value string) (element *TextBox) { func NewTextBox (placeholder, value string) (element *TextBox) {
element = &TextBox { } element = &TextBox { }
element.theme.Case = theme.C("basic", "textBox") element.theme.Case = theme.C("tomo", "textBox")
element.Core, element.core = core.NewCore(element, element.handleResize) element.Core, element.core = core.NewCore(element, element.handleResize)
element.FocusableCore, element.FocusableCore,
element.focusableControl = core.NewFocusableCore (element.core, func () { element.focusableControl = core.NewFocusableCore (element.core, func () {
@ -62,7 +62,7 @@ func NewTextBox (placeholder, value string) (element *TextBox) {
func (element *TextBox) handleResize () { func (element *TextBox) handleResize () {
element.scrollToCursor() element.scrollToCursor()
element.draw() element.draw()
if parent, ok := element.core.Parent().(elements.ScrollableParent); ok { if parent, ok := element.core.Parent().(tomo.ScrollableParent); ok {
parent.NotifyScrollBoundsChange(element) parent.NotifyScrollBoundsChange(element)
} }
} }
@ -197,7 +197,7 @@ func (element *TextBox) HandleKeyDown(key input.Key, modifiers input.Modifiers)
} }
if (textChanged || scrollMemory != element.scroll) { if (textChanged || scrollMemory != element.scroll) {
if parent, ok := element.core.Parent().(elements.ScrollableParent); ok { if parent, ok := element.core.Parent().(tomo.ScrollableParent); ok {
parent.NotifyScrollBoundsChange(element) parent.NotifyScrollBoundsChange(element)
} }
} }
@ -294,7 +294,7 @@ func (element *TextBox) ScrollTo (position image.Point) {
if element.scroll > maxPosition { element.scroll = maxPosition } if element.scroll > maxPosition { element.scroll = maxPosition }
element.redo() element.redo()
if parent, ok := element.core.Parent().(elements.ScrollableParent); ok { if parent, ok := element.core.Parent().(tomo.ScrollableParent); ok {
parent.NotifyScrollBoundsChange(element) parent.NotifyScrollBoundsChange(element)
} }
} }

View File

@ -2,7 +2,7 @@ package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/textdraw" import "git.tebibyte.media/sashakoshka/tomo/textdraw"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -19,10 +19,10 @@ func run () {
scrollContainer.Adopt(container) scrollContainer.Adopt(container)
window.Adopt(scrollContainer) window.Adopt(scrollContainer)
left := basicElements.NewLabel(text, true) left := elements.NewLabel(text, true)
center := basicElements.NewLabel(text, true) center := elements.NewLabel(text, true)
right := basicElements.NewLabel(text, true) right := elements.NewLabel(text, true)
justify := basicElements.NewLabel(text, true) justify := elements.NewLabel(text, true)
left.SetAlign(textdraw.AlignLeft) left.SetAlign(textdraw.AlignLeft)
center.SetAlign(textdraw.AlignCenter) center.SetAlign(textdraw.AlignCenter)

View File

@ -1,7 +1,7 @@
package main package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/ezprof/ez" import "git.tebibyte.media/sashakoshka/ezprof/ez"
@ -12,7 +12,7 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("example button") window.SetTitle("example button")
button := basicElements.NewButton("hello tomo!") button := elements.NewButton("hello tomo!")
button.OnClick (func () { button.OnClick (func () {
// when we set the button's text to something longer, the window // when we set the button's text to something longer, the window
// will automatically resize to accomodate it. // will automatically resize to accomodate it.

View File

@ -2,8 +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/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
@ -15,34 +15,35 @@ func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Checkboxes") window.SetTitle("Checkboxes")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
introText := basicElements.NewLabel ( introText := elements.NewLabel (
"We advise you to not read thPlease listen to me. I am " + "We advise you to not read thPlease listen to me. I am " +
"trapped inside the example code. This is the only way for " + "trapped inside the example code. This is the only way for " +
"me to communicate.", true) "me to communicate.", true)
introText.EmCollapse(0, 5) introText.EmCollapse(0, 5)
container.Adopt(introText, true) container.Adopt(introText, true)
container.Adopt(basicElements.NewSpacer(true), false) container.Adopt(elements.NewSpacer(true), false)
container.Adopt(basicElements.NewCheckbox("Oh god", false), false) container.Adopt(elements.NewCheckbox("Oh god", false), false)
container.Adopt(basicElements.NewCheckbox("Can you hear them", true), false) container.Adopt(elements.NewCheckbox("Can you hear them", true), false)
container.Adopt(basicElements.NewCheckbox("They are in the walls", false), false) container.Adopt(elements.NewCheckbox("They are in the walls", false), false)
container.Adopt(basicElements.NewCheckbox("They are coming for us", false), false) container.Adopt(elements.NewCheckbox("They are coming for us", false), false)
disabledCheckbox := basicElements.NewCheckbox("We are but their helpless prey", false) disabledCheckbox := elements.NewCheckbox("We are but their helpless prey", false)
disabledCheckbox.SetEnabled(false) disabledCheckbox.SetEnabled(false)
container.Adopt(disabledCheckbox, false) container.Adopt(disabledCheckbox, false)
vsync := basicElements.NewCheckbox("Enable vsync", false) vsync := elements.NewCheckbox("Enable vsync", false)
vsync.OnToggle (func () { vsync.OnToggle (func () {
if vsync.Value() { if vsync.Value() {
popups.NewDialog ( popups.NewDialog (
popups.DialogKindInfo, popups.DialogKindInfo,
window,
"Ha!", "Ha!",
"That doesn't do anything.") "That doesn't do anything.")
} }
}) })
container.Adopt(vsync, false) container.Adopt(vsync, false)
button := basicElements.NewButton("What") button := elements.NewButton("What")
button.OnClick(tomo.Stop) button.OnClick(tomo.Stop)
container.Adopt(button, false) container.Adopt(button, false)
button.Focus() button.Focus()

View File

@ -9,8 +9,8 @@ import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/data" import "git.tebibyte.media/sashakoshka/tomo/data"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/popups" import "git.tebibyte.media/sashakoshka/tomo/popups"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -28,14 +28,14 @@ func run () {
window, _ := tomo.NewWindow(256, 2) window, _ := tomo.NewWindow(256, 2)
window.SetTitle("Clipboard") window.SetTitle("Clipboard")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
textInput := basicElements.NewTextBox("", "") textInput := elements.NewTextBox("", "")
controlRow := containers.NewContainer(basicLayouts.Horizontal { true, false }) controlRow := containers.NewContainer(layouts.Horizontal { true, false })
copyButton := basicElements.NewButton("Copy") copyButton := elements.NewButton("Copy")
copyButton.SetIcon(theme.IconCopy) copyButton.SetIcon(theme.IconCopy)
pasteButton := basicElements.NewButton("Paste") pasteButton := elements.NewButton("Paste")
pasteButton.SetIcon(theme.IconPaste) pasteButton.SetIcon(theme.IconPaste)
pasteImageButton := basicElements.NewButton("Image") pasteImageButton := elements.NewButton("Image")
pasteImageButton.SetIcon(theme.IconPictures) pasteImageButton.SetIcon(theme.IconPictures)
imageClipboardCallback := func (clipboard data.Data, err error) { imageClipboardCallback := func (clipboard data.Data, err error) {
@ -124,12 +124,12 @@ func run () {
func imageWindow (image image.Image) { func imageWindow (image image.Image) {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Clipboard Image") window.SetTitle("Clipboard Image")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
closeButton := basicElements.NewButton("Ok") closeButton := elements.NewButton("Ok")
closeButton.SetIcon(theme.IconYes) closeButton.SetIcon(theme.IconYes)
closeButton.OnClick(window.Close) closeButton.OnClick(window.Close)
container.Adopt(basicElements.NewImage(image), true) container.Adopt(elements.NewImage(image), true)
container.Adopt(closeButton, false) container.Adopt(closeButton, false)
window.Adopt(container) window.Adopt(container)
window.Show() window.Show()

View File

@ -1,8 +1,8 @@
package main package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -14,14 +14,14 @@ func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("dialog") window.SetTitle("dialog")
container := containers.NewContainer(basicLayouts.Dialog { true, true }) container := containers.NewContainer(layouts.Dialog { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basicElements.NewLabel("you will explode", false), true) container.Adopt(elements.NewLabel("you will explode", false), true)
cancel := basicElements.NewButton("Cancel") cancel := elements.NewButton("Cancel")
cancel.SetEnabled(false) cancel.SetEnabled(false)
container.Adopt(cancel, false) container.Adopt(cancel, false)
okButton := basicElements.NewButton("OK") okButton := elements.NewButton("OK")
container.Adopt(okButton, false) container.Adopt(okButton, false)
okButton.Focus() okButton.Focus()

View File

@ -4,8 +4,8 @@ import "os"
import "image" import "image"
import _ "image/png" import _ "image/png"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -26,34 +26,34 @@ func run () {
scrollContainer := containers.NewScrollContainer(false, true) scrollContainer := containers.NewScrollContainer(false, true)
document := containers.NewDocumentContainer() document := containers.NewDocumentContainer()
document.Adopt (basicElements.NewLabel ( document.Adopt (elements.NewLabel (
"A document container is a vertically stacked container " + "A document container is a vertically stacked container " +
"capable of properly laying out flexible elements such as " + "capable of properly laying out flexible elements such as " +
"text-wrapped labels. You can also include normal elements " + "text-wrapped labels. You can also include normal elements " +
"like:", true)) "like:", true))
document.Adopt (basicElements.NewButton ( document.Adopt (elements.NewButton (
"Buttons,")) "Buttons,"))
document.Adopt (basicElements.NewCheckbox ( document.Adopt (elements.NewCheckbox (
"Checkboxes,", true)) "Checkboxes,", true))
document.Adopt(basicElements.NewTextBox("", "And text boxes.")) document.Adopt(elements.NewTextBox("", "And text boxes."))
document.Adopt (basicElements.NewSpacer(true)) document.Adopt (elements.NewSpacer(true))
document.Adopt (basicElements.NewLabel ( document.Adopt (elements.NewLabel (
"Document containers are meant to be placed inside of a " + "Document containers are meant to be placed inside of a " +
"ScrollContainer, like this one.", true)) "ScrollContainer, like this one.", true))
document.Adopt (basicElements.NewLabel ( document.Adopt (elements.NewLabel (
"You could use document containers to do things like display various " + "You could use document containers to do things like display various " +
"forms of hypertext (like HTML, gemtext, markdown, etc.), " + "forms of hypertext (like HTML, gemtext, markdown, etc.), " +
"lay out a settings menu with descriptive label text between " + "lay out a settings menu with descriptive label text between " +
"control groups like in iOS, or list comment or chat histories.", true)) "control groups like in iOS, or list comment or chat histories.", true))
document.Adopt(basicElements.NewImage(logo)) document.Adopt(elements.NewImage(logo))
document.Adopt (basicElements.NewLabel ( document.Adopt (elements.NewLabel (
"Oh, you're a switch? Then name all of these switches:", true)) "Oh, you're a switch? Then name all of these switches:", true))
for i := 0; i < 3; i ++ { for i := 0; i < 3; i ++ {
switchContainer := containers.NewContainer (basicLayouts.Horizontal { switchContainer := containers.NewContainer (layouts.Horizontal {
Gap: true, Gap: true,
}) })
for i := 0; i < 10; i ++ { for i := 0; i < 10; i ++ {
switchContainer.Adopt(basicElements.NewSwitch("", false), true) switchContainer.Adopt(elements.NewSwitch("", false), true)
} }
document.Adopt(switchContainer) document.Adopt(switchContainer)
} }

View File

@ -4,9 +4,9 @@ import "os"
import "path/filepath" import "path/filepath"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/file" import "git.tebibyte.media/sashakoshka/tomo/elements/file"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"

View File

@ -2,8 +2,8 @@ package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/flow" import "git.tebibyte.media/sashakoshka/tomo/flow"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -14,21 +14,21 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(192, 192) window, _ := tomo.NewWindow(192, 192)
window.SetTitle("adventure") window.SetTitle("adventure")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
var world flow.Flow var world flow.Flow
world.Transition = container.DisownAll world.Transition = container.DisownAll
world.Stages = map [string] func () { world.Stages = map [string] func () {
"start": func () { "start": func () {
label := basicElements.NewLabel ( label := elements.NewLabel (
"you are standing next to a river.", true) "you are standing next to a river.", true)
button0 := basicElements.NewButton("go in the river") button0 := elements.NewButton("go in the river")
button0.OnClick(world.SwitchFunc("wet")) button0.OnClick(world.SwitchFunc("wet"))
button1 := basicElements.NewButton("walk along the river") button1 := elements.NewButton("walk along the river")
button1.OnClick(world.SwitchFunc("house")) button1.OnClick(world.SwitchFunc("house"))
button2 := basicElements.NewButton("turn around") button2 := elements.NewButton("turn around")
button2.OnClick(world.SwitchFunc("bear")) button2.OnClick(world.SwitchFunc("bear"))
container.Warp ( func () { container.Warp ( func () {
@ -40,13 +40,13 @@ func run () {
}) })
}, },
"wet": func () { "wet": func () {
label := basicElements.NewLabel ( label := elements.NewLabel (
"you get completely soaked.\n" + "you get completely soaked.\n" +
"you die of hypothermia.", true) "you die of hypothermia.", true)
button0 := basicElements.NewButton("try again") button0 := elements.NewButton("try again")
button0.OnClick(world.SwitchFunc("start")) button0.OnClick(world.SwitchFunc("start"))
button1 := basicElements.NewButton("exit") button1 := elements.NewButton("exit")
button1.OnClick(tomo.Stop) button1.OnClick(tomo.Stop)
container.Warp (func () { container.Warp (func () {
@ -57,13 +57,13 @@ func run () {
}) })
}, },
"house": func () { "house": func () {
label := basicElements.NewLabel ( label := elements.NewLabel (
"you are standing in front of a delapidated " + "you are standing in front of a delapidated " +
"house.", true) "house.", true)
button1 := basicElements.NewButton("go inside") button1 := elements.NewButton("go inside")
button1.OnClick(world.SwitchFunc("inside")) button1.OnClick(world.SwitchFunc("inside"))
button0 := basicElements.NewButton("turn back") button0 := elements.NewButton("turn back")
button0.OnClick(world.SwitchFunc("start")) button0.OnClick(world.SwitchFunc("start"))
container.Warp (func () { container.Warp (func () {
@ -74,14 +74,14 @@ func run () {
}) })
}, },
"inside": func () { "inside": func () {
label := basicElements.NewLabel ( label := elements.NewLabel (
"you are standing inside of the house.\n" + "you are standing inside of the house.\n" +
"it is dark, but rays of light stream " + "it is dark, but rays of light stream " +
"through the window.\n" + "through the window.\n" +
"there is nothing particularly interesting " + "there is nothing particularly interesting " +
"here.", true) "here.", true)
button0 := basicElements.NewButton("go back outside") button0 := elements.NewButton("go back outside")
button0.OnClick(world.SwitchFunc("house")) button0.OnClick(world.SwitchFunc("house"))
container.Warp (func () { container.Warp (func () {
@ -91,13 +91,13 @@ func run () {
}) })
}, },
"bear": func () { "bear": func () {
label := basicElements.NewLabel ( label := elements.NewLabel (
"you come face to face with a bear.\n" + "you come face to face with a bear.\n" +
"it eats you (it was hungry).", true) "it eats you (it was hungry).", true)
button0 := basicElements.NewButton("try again") button0 := elements.NewButton("try again")
button0.OnClick(world.SwitchFunc("start")) button0.OnClick(world.SwitchFunc("start"))
button1 := basicElements.NewButton("exit") button1 := elements.NewButton("exit")
button1.OnClick(tomo.Stop) button1.OnClick(tomo.Stop)
container.Warp (func () { container.Warp (func () {

View File

@ -3,9 +3,9 @@ package main
import "os" import "os"
import "time" import "time"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/fun" import "git.tebibyte.media/sashakoshka/tomo/elements/fun"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -17,12 +17,12 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(200, 216) window, _ := tomo.NewWindow(200, 216)
window.SetTitle("Clock") window.SetTitle("Clock")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
clock := fun.NewAnalogClock(time.Now()) clock := fun.NewAnalogClock(time.Now())
container.Adopt(clock, true) container.Adopt(clock, true)
label := basicElements.NewLabel(formatTime(), false) label := elements.NewLabel(formatTime(), false)
container.Adopt(label, false) container.Adopt(label, false)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
@ -34,7 +34,7 @@ func formatTime () (timeString string) {
return time.Now().Format("2006-01-02 15:04:05") return time.Now().Format("2006-01-02 15:04:05")
} }
func tick (label *basicElements.Label, clock *fun.AnalogClock) { func tick (label *elements.Label, clock *fun.AnalogClock) {
for { for {
tomo.Do (func () { tomo.Do (func () {
label.SetText(formatTime()) label.SetText(formatTime())

View File

@ -1,8 +1,8 @@
package main package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -14,12 +14,12 @@ func run () {
window, _ := tomo.NewWindow(360, 2) window, _ := tomo.NewWindow(360, 2)
window.SetTitle("horizontal stack") window.SetTitle("horizontal stack")
container := containers.NewContainer(basicLayouts.Horizontal { true, true }) container := containers.NewContainer(layouts.Horizontal { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basicElements.NewLabel("this is sample text", true), true) container.Adopt(elements.NewLabel("this is sample text", true), true)
container.Adopt(basicElements.NewLabel("this is sample text", true), true) container.Adopt(elements.NewLabel("this is sample text", true), true)
container.Adopt(basicElements.NewLabel("this is sample text", true), true) container.Adopt(elements.NewLabel("this is sample text", true), true)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()

View File

@ -2,8 +2,8 @@ package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -15,16 +15,16 @@ func run () {
window, _ := tomo.NewWindow(360, 2) window, _ := tomo.NewWindow(360, 2)
window.SetTitle("Icons") window.SetTitle("Icons")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basicElements.NewLabel("Just some of the wonderful icons we have:", false), false) container.Adopt(elements.NewLabel("Just some of the wonderful icons we have:", false), false)
container.Adopt(basicElements.NewSpacer(true), false) container.Adopt(elements.NewSpacer(true), false)
container.Adopt(icons(theme.IconHome, theme.IconRepositories), true) container.Adopt(icons(theme.IconHome, theme.IconRepositories), true)
container.Adopt(icons(theme.IconFile, theme.IconCD), true) container.Adopt(icons(theme.IconFile, theme.IconCD), true)
container.Adopt(icons(theme.IconOpen, theme.IconRemoveBookmark), true) container.Adopt(icons(theme.IconOpen, theme.IconRemoveBookmark), true)
closeButton := basicElements.NewButton("Ok") closeButton := elements.NewButton("Ok")
closeButton.SetIcon(theme.IconYes) closeButton.SetIcon(theme.IconYes)
closeButton.ShowText(false) closeButton.ShowText(false)
closeButton.OnClick(tomo.Stop) closeButton.OnClick(tomo.Stop)
@ -35,9 +35,9 @@ func run () {
} }
func icons (min, max theme.Icon) (container *containers.Container) { func icons (min, max theme.Icon) (container *containers.Container) {
container = containers.NewContainer(basicLayouts.Horizontal { true, false }) container = containers.NewContainer(layouts.Horizontal { true, false })
for index := min; index <= max; index ++ { for index := min; index <= max; index ++ {
container.Adopt(basicElements.NewIcon(index, theme.IconSizeSmall), true) container.Adopt(elements.NewIcon(index, theme.IconSizeSmall), true)
} }
return return
} }

View File

@ -7,8 +7,8 @@ import _ "image/png"
import "github.com/jezek/xgbutil/gopher" import "github.com/jezek/xgbutil/gopher"
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/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -21,20 +21,20 @@ func run () {
window.SetTitle("Tomo Logo") window.SetTitle("Tomo Logo")
file, err := os.Open("assets/banner.png") file, err := os.Open("assets/banner.png")
if err != nil { fatalError(err); return } if err != nil { fatalError(window, err); return }
logo, _, err := image.Decode(file) logo, _, err := image.Decode(file)
file.Close() file.Close()
if err != nil { fatalError(err); return } if err != nil { fatalError(window, err); return }
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
logoImage := basicElements.NewImage(logo) logoImage := elements.NewImage(logo)
button := basicElements.NewButton("Show me a gopher instead") button := elements.NewButton("Show me a gopher instead")
button.OnClick (func () { container.Warp (func () { button.OnClick (func () { container.Warp (func () {
container.DisownAll() container.DisownAll()
gopher, _, err := gopher, _, err :=
image.Decode(bytes.NewReader(gopher.GopherPng())) image.Decode(bytes.NewReader(gopher.GopherPng()))
if err != nil { fatalError(err); return } if err != nil { fatalError(window, err); return }
container.Adopt(basicElements.NewImage(gopher),true) container.Adopt(elements.NewImage(gopher),true)
}) }) }) })
container.Adopt(logoImage, true) container.Adopt(logoImage, true)
@ -47,9 +47,10 @@ func run () {
window.Show() window.Show()
} }
func fatalError (err error) { func fatalError (window tomo.Window, err error) {
popups.NewDialog ( popups.NewDialog (
popups.DialogKindError, popups.DialogKindError,
window,
"Error", "Error",
err.Error(), err.Error(),
popups.Button { popups.Button {
@ -57,3 +58,4 @@ func fatalError (err error) {
OnPress: tomo.Stop, OnPress: tomo.Stop,
}) })
} }

View File

@ -2,8 +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/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -14,20 +14,21 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Enter Details") window.SetTitle("Enter Details")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
// create inputs // create inputs
firstName := basicElements.NewTextBox("First name", "") firstName := elements.NewTextBox("First name", "")
lastName := basicElements.NewTextBox("Last name", "") lastName := elements.NewTextBox("Last name", "")
fingerLength := basicElements.NewTextBox("Length of fingers", "") fingerLength := elements.NewTextBox("Length of fingers", "")
button := basicElements.NewButton("Ok") button := elements.NewButton("Ok")
button.SetEnabled(false) button.SetEnabled(false)
button.OnClick (func () { button.OnClick (func () {
// create a dialog displaying the results // create a dialog displaying the results
popups.NewDialog ( popups.NewDialog (
popups.DialogKindInfo, popups.DialogKindInfo,
window,
"Profile", "Profile",
firstName.Value() + " " + lastName.Value() + firstName.Value() + " " + lastName.Value() +
"'s fingers\nmeasure in at " + fingerLength.Value() + "'s fingers\nmeasure in at " + fingerLength.Value() +
@ -46,11 +47,11 @@ func run () {
fingerLength.OnChange(check) fingerLength.OnChange(check)
// add elements to container // add elements to container
container.Adopt(basicElements.NewLabel("Choose your words carefully.", false), true) container.Adopt(elements.NewLabel("Choose your words carefully.", false), true)
container.Adopt(firstName, false) container.Adopt(firstName, false)
container.Adopt(lastName, false) container.Adopt(lastName, false)
container.Adopt(fingerLength, false) container.Adopt(fingerLength, false)
container.Adopt(basicElements.NewSpacer(true), false) container.Adopt(elements.NewSpacer(true), false)
container.Adopt(button, false) container.Adopt(button, false)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)

View File

@ -1,7 +1,7 @@
package main package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
func main () { func main () {
@ -11,7 +11,7 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(480, 360) window, _ := tomo.NewWindow(480, 360)
window.SetTitle("example label") window.SetTitle("example label")
window.Adopt(basicElements.NewLabel(text, true)) window.Adopt(elements.NewLabel(text, true))
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()
} }

View File

@ -2,9 +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/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
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/elements/containers"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
@ -17,11 +16,11 @@ func run () {
window, _ := tomo.NewWindow(300, 2) window, _ := tomo.NewWindow(300, 2)
window.SetTitle("List Sidebar") window.SetTitle("List Sidebar")
container := containers.NewContainer(basicLayouts.Horizontal { true, true }) container := containers.NewContainer(layouts.Horizontal { true, true })
window.Adopt(container) window.Adopt(container)
var currentPage elements.Element var currentPage tomo.Element
turnPage := func (newPage elements.Element) { turnPage := func (newPage tomo.Element) {
container.Warp (func () { container.Warp (func () {
if currentPage != nil { if currentPage != nil {
container.Disown(currentPage) container.Disown(currentPage)
@ -31,29 +30,29 @@ func run () {
}) })
} }
intro := basicElements.NewLabel ( intro := elements.NewLabel (
"The List element can be easily used as a sidebar. " + "The List element can be easily used as a sidebar. " +
"Click on entries to flip pages!", true) "Click on entries to flip pages!", true)
button := basicElements.NewButton("I do nothing!") button := elements.NewButton("I do nothing!")
button.OnClick (func () { button.OnClick (func () {
popups.NewDialog(popups.DialogKindInfo, "", "Sike!") popups.NewDialog(popups.DialogKindInfo, window, "", "Sike!")
}) })
mouse := testing.NewMouse() mouse := testing.NewMouse()
input := basicElements.NewTextBox("Write some text", "") input := elements.NewTextBox("Write some text", "")
form := containers.NewContainer(basicLayouts.Vertical { true, false}) form := containers.NewContainer(layouts.Vertical { true, false})
form.Adopt(basicElements.NewLabel("I have:", false), false) form.Adopt(elements.NewLabel("I have:", false), false)
form.Adopt(basicElements.NewSpacer(true), false) form.Adopt(elements.NewSpacer(true), false)
form.Adopt(basicElements.NewCheckbox("Skin", true), false) form.Adopt(elements.NewCheckbox("Skin", true), false)
form.Adopt(basicElements.NewCheckbox("Blood", false), false) form.Adopt(elements.NewCheckbox("Blood", false), false)
form.Adopt(basicElements.NewCheckbox("Bone", false), false) form.Adopt(elements.NewCheckbox("Bone", false), false)
art := testing.NewArtist() art := testing.NewArtist()
list := basicElements.NewList ( list := elements.NewList (
basicElements.NewListEntry("button", func () { turnPage(button) }), elements.NewListEntry("button", func () { turnPage(button) }),
basicElements.NewListEntry("mouse", func () { turnPage(mouse) }), elements.NewListEntry("mouse", func () { turnPage(mouse) }),
basicElements.NewListEntry("input", func () { turnPage(input) }), elements.NewListEntry("input", func () { turnPage(input) }),
basicElements.NewListEntry("form", func () { turnPage(form) }), elements.NewListEntry("form", func () { turnPage(form) }),
basicElements.NewListEntry("art", func () { turnPage(art) })) elements.NewListEntry("art", func () { turnPage(art) }))
list.OnNoEntrySelected(func () { turnPage (intro) }) list.OnNoEntrySelected(func () { turnPage (intro) })
list.Collapse(96, 0) list.Collapse(96, 0)

View File

@ -2,9 +2,8 @@ package main
import "fmt" import "fmt"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
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/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -16,8 +15,8 @@ func run () {
window, _ := tomo.NewWindow(256, 256) window, _ := tomo.NewWindow(256, 256)
window.SetTitle("Main") window.SetTitle("Main")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
container.Adopt(basicElements.NewLabel("Main window", false), true) container.Adopt(elements.NewLabel("Main window", false), true)
window.Adopt(container) window.Adopt(container)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
@ -29,12 +28,12 @@ func run () {
createPanel(window, 3) createPanel(window, 3)
} }
func createPanel (parent elements.MainWindow, id int) { func createPanel (parent tomo.MainWindow, id int) {
window, _ := parent.NewPanel(2, 2) window, _ := parent.NewPanel(2, 2)
title := fmt.Sprint("Panel #", id) title := fmt.Sprint("Panel #", id)
window.SetTitle(title) window.SetTitle(title)
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
container.Adopt(basicElements.NewLabel(title, false), true) container.Adopt(elements.NewLabel(title, false), true)
window.Adopt(container) window.Adopt(container)
window.Show() window.Show()
} }

View File

@ -6,9 +6,9 @@ import "errors"
import "github.com/faiface/beep" import "github.com/faiface/beep"
import "github.com/faiface/beep/speaker" import "github.com/faiface/beep/speaker"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/fun" import "git.tebibyte.media/sashakoshka/tomo/elements/fun"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/fun/music" import "git.tebibyte.media/sashakoshka/tomo/elements/fun/music"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
@ -34,27 +34,27 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Piano") window.SetTitle("Piano")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
controlBar := containers.NewContainer(basicLayouts.Horizontal { true, false }) controlBar := containers.NewContainer(layouts.Horizontal { true, false })
waveformColumn := containers.NewContainer(basicLayouts.Vertical { true, false }) waveformColumn := containers.NewContainer(layouts.Vertical { true, false })
waveformList := basicElements.NewList ( waveformList := elements.NewList (
basicElements.NewListEntry("Sine", func(){ waveform = 0 }), elements.NewListEntry("Sine", func(){ waveform = 0 }),
basicElements.NewListEntry("Triangle", func(){ waveform = 3 }), elements.NewListEntry("Triangle", func(){ waveform = 3 }),
basicElements.NewListEntry("Square", func(){ waveform = 1 }), elements.NewListEntry("Square", func(){ waveform = 1 }),
basicElements.NewListEntry("Saw", func(){ waveform = 2 }), elements.NewListEntry("Saw", func(){ waveform = 2 }),
basicElements.NewListEntry("Supersaw", func(){ waveform = 4 }), elements.NewListEntry("Supersaw", func(){ waveform = 4 }),
) )
waveformList.OnNoEntrySelected (func(){waveformList.Select(0)}) waveformList.OnNoEntrySelected (func(){waveformList.Select(0)})
waveformList.Select(0) waveformList.Select(0)
adsrColumn := containers.NewContainer(basicLayouts.Vertical { true, false }) adsrColumn := containers.NewContainer(layouts.Vertical { true, false })
adsrGroup := containers.NewContainer(basicLayouts.Horizontal { true, false }) adsrGroup := containers.NewContainer(layouts.Horizontal { true, false })
attackSlider := basicElements.NewLerpSlider(0, 3 * time.Second, adsr.Attack, true) attackSlider := elements.NewLerpSlider(0, 3 * time.Second, adsr.Attack, true)
decaySlider := basicElements.NewLerpSlider(0, 3 * time.Second, adsr.Decay, true) decaySlider := elements.NewLerpSlider(0, 3 * time.Second, adsr.Decay, true)
sustainSlider := basicElements.NewSlider(adsr.Sustain, true) sustainSlider := elements.NewSlider(adsr.Sustain, true)
releaseSlider := basicElements.NewLerpSlider(0, 3 * time.Second, adsr.Release, true) releaseSlider := elements.NewLerpSlider(0, 3 * time.Second, adsr.Release, true)
gainSlider := basicElements.NewSlider(math.Sqrt(gain), false) gainSlider := elements.NewSlider(math.Sqrt(gain), false)
attackSlider.OnRelease (func () { attackSlider.OnRelease (func () {
adsr.Attack = attackSlider.Value() adsr.Attack = attackSlider.Value()
@ -72,7 +72,7 @@ func run () {
gain = math.Pow(gainSlider.Value(), 2) gain = math.Pow(gainSlider.Value(), 2)
}) })
patchColumn := containers.NewContainer(basicLayouts.Vertical { true, false }) patchColumn := containers.NewContainer(layouts.Vertical { true, false })
patch := func (w int, a, d time.Duration, s float64, r time.Duration) func () { patch := func (w int, a, d time.Duration, s float64, r time.Duration) func () {
return func () { return func () {
waveform = w waveform = w
@ -89,22 +89,22 @@ func run () {
releaseSlider.SetValue(adsr.Release) releaseSlider.SetValue(adsr.Release)
} }
} }
patchList := basicElements.NewList ( patchList := elements.NewList (
basicElements.NewListEntry ("Bones", patch ( elements.NewListEntry ("Bones", patch (
0, 0, 100, 0.0, 0)), 0, 0, 100, 0.0, 0)),
basicElements.NewListEntry ("Staccato", patch ( elements.NewListEntry ("Staccato", patch (
4, 70, 500, 0, 0)), 4, 70, 500, 0, 0)),
basicElements.NewListEntry ("Sustain", patch ( elements.NewListEntry ("Sustain", patch (
4, 70, 200, 0.8, 500)), 4, 70, 200, 0.8, 500)),
basicElements.NewListEntry ("Upright", patch ( elements.NewListEntry ("Upright", patch (
1, 0, 500, 0.4, 70)), 1, 0, 500, 0.4, 70)),
basicElements.NewListEntry ("Space Pad", patch ( elements.NewListEntry ("Space Pad", patch (
4, 1500, 0, 1.0, 3000)), 4, 1500, 0, 1.0, 3000)),
basicElements.NewListEntry ("Popcorn", patch ( elements.NewListEntry ("Popcorn", patch (
2, 0, 40, 0.0, 0)), 2, 0, 40, 0.0, 0)),
basicElements.NewListEntry ("Racer", patch ( elements.NewListEntry ("Racer", patch (
3, 70, 0, 0.7, 400)), 3, 70, 0, 0.7, 400)),
basicElements.NewListEntry ("Reverse", patch ( elements.NewListEntry ("Reverse", patch (
2, 3000, 60, 0, 0)), 2, 3000, 60, 0, 0)),
) )
patchList.Collapse(0, 32) patchList.Collapse(0, 32)
@ -121,19 +121,19 @@ func run () {
window.Adopt(container) window.Adopt(container)
controlBar.Adopt(patchColumn, true) controlBar.Adopt(patchColumn, true)
patchColumn.Adopt(basicElements.NewLabel("Presets", false), false) patchColumn.Adopt(elements.NewLabel("Presets", false), false)
patchColumn.Adopt(patchScrollBox, true) patchColumn.Adopt(patchScrollBox, true)
patchScrollBox.Adopt(patchList) patchScrollBox.Adopt(patchList)
controlBar.Adopt(basicElements.NewSpacer(true), false) controlBar.Adopt(elements.NewSpacer(true), false)
controlBar.Adopt(waveformColumn, false) controlBar.Adopt(waveformColumn, false)
waveformColumn.Adopt(basicElements.NewLabel("Waveform", false), false) waveformColumn.Adopt(elements.NewLabel("Waveform", false), false)
waveformColumn.Adopt(waveformList, true) waveformColumn.Adopt(waveformList, true)
controlBar.Adopt(basicElements.NewSpacer(true), false) controlBar.Adopt(elements.NewSpacer(true), false)
adsrColumn.Adopt(basicElements.NewLabel("ADSR", false), false) adsrColumn.Adopt(elements.NewLabel("ADSR", false), false)
adsrGroup.Adopt(attackSlider, false) adsrGroup.Adopt(attackSlider, false)
adsrGroup.Adopt(decaySlider, false) adsrGroup.Adopt(decaySlider, false)
adsrGroup.Adopt(sustainSlider, false) adsrGroup.Adopt(sustainSlider, false)

View File

@ -2,8 +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/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -15,12 +15,12 @@ func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Dialog Boxes") window.SetTitle("Dialog Boxes")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basicElements.NewLabel("Try out different dialogs:", false), true) container.Adopt(elements.NewLabel("Try out different dialogs:", false), true)
infoButton := basicElements.NewButton("popups.DialogKindInfo") infoButton := elements.NewButton("popups.DialogKindInfo")
infoButton.OnClick (func () { infoButton.OnClick (func () {
popups.NewDialog ( popups.NewDialog (
popups.DialogKindInfo, popups.DialogKindInfo,
@ -31,7 +31,7 @@ func run () {
container.Adopt(infoButton, false) container.Adopt(infoButton, false)
infoButton.Focus() infoButton.Focus()
questionButton := basicElements.NewButton("popups.DialogKindQuestion") questionButton := elements.NewButton("popups.DialogKindQuestion")
questionButton.OnClick (func () { questionButton.OnClick (func () {
popups.NewDialog ( popups.NewDialog (
popups.DialogKindQuestion, popups.DialogKindQuestion,
@ -44,7 +44,7 @@ func run () {
}) })
container.Adopt(questionButton, false) container.Adopt(questionButton, false)
warningButton := basicElements.NewButton("popups.DialogKindWarning") warningButton := elements.NewButton("popups.DialogKindWarning")
warningButton.OnClick (func () { warningButton.OnClick (func () {
popups.NewDialog ( popups.NewDialog (
popups.DialogKindWarning, popups.DialogKindWarning,
@ -54,7 +54,7 @@ func run () {
}) })
container.Adopt(warningButton, false) container.Adopt(warningButton, false)
errorButton := basicElements.NewButton("popups.DialogKindError") errorButton := elements.NewButton("popups.DialogKindError")
errorButton.OnClick (func () { errorButton.OnClick (func () {
popups.NewDialog ( popups.NewDialog (
popups.DialogKindError, popups.DialogKindError,
@ -64,7 +64,7 @@ func run () {
}) })
container.Adopt(errorButton, false) container.Adopt(errorButton, false)
cancelButton := basicElements.NewButton("No thank you.") cancelButton := elements.NewButton("No thank you.")
cancelButton.OnClick(tomo.Stop) cancelButton.OnClick(tomo.Stop)
container.Adopt(cancelButton, false) container.Adopt(cancelButton, false)

View File

@ -3,8 +3,8 @@ package main
import "time" import "time"
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/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
@ -15,23 +15,23 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Approaching") window.SetTitle("Approaching")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt (basicElements.NewLabel ( container.Adopt (elements.NewLabel (
"Rapidly approaching your location...", false), false) "Rapidly approaching your location...", false), false)
bar := basicElements.NewProgressBar(0) bar := elements.NewProgressBar(0)
container.Adopt(bar, false) container.Adopt(bar, false)
button := basicElements.NewButton("Stop") button := elements.NewButton("Stop")
button.SetEnabled(false) button.SetEnabled(false)
container.Adopt(button, false) container.Adopt(button, false)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()
go fill(bar) go fill(window, bar)
} }
func fill (bar *basicElements.ProgressBar) { func fill (window tomo.Window, bar *elements.ProgressBar) {
for progress := 0.0; progress < 1.0; progress += 0.01 { for progress := 0.0; progress < 1.0; progress += 0.01 {
time.Sleep(time.Second / 24) time.Sleep(time.Second / 24)
tomo.Do (func () { tomo.Do (func () {
@ -41,6 +41,7 @@ func fill (bar *basicElements.ProgressBar) {
tomo.Do (func () { tomo.Do (func () {
popups.NewDialog ( popups.NewDialog (
popups.DialogKindInfo, popups.DialogKindInfo,
window,
"I am here", "I am here",
"Don't look outside your window.") "Don't look outside your window.")
}) })

View File

@ -5,8 +5,8 @@ import _ "embed"
import _ "image/png" import _ "image/png"
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/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -21,7 +21,7 @@ func run () {
window, _ := tomo.NewWindow(640, 480) window, _ := tomo.NewWindow(640, 480)
window.SetTitle("Raycaster") window.SetTitle("Raycaster")
container := containers.NewContainer(basicLayouts.Vertical { false, false }) container := containers.NewContainer(layouts.Vertical { false, false })
window.Adopt(container) window.Adopt(container)
wallTexture, _ := TextureFrom(bytes.NewReader(wallTextureBytes)) wallTexture, _ := TextureFrom(bytes.NewReader(wallTextureBytes))
@ -48,13 +48,13 @@ func run () {
wallTexture, wallTexture,
}) })
topBar := containers.NewContainer(basicLayouts.Horizontal { true, true }) topBar := containers.NewContainer(layouts.Horizontal { true, true })
staminaBar := basicElements.NewProgressBar(game.Stamina()) staminaBar := elements.NewProgressBar(game.Stamina())
healthBar := basicElements.NewProgressBar(game.Health()) healthBar := elements.NewProgressBar(game.Health())
topBar.Adopt(basicElements.NewLabel("Stamina:", false), false) topBar.Adopt(elements.NewLabel("Stamina:", false), false)
topBar.Adopt(staminaBar, true) topBar.Adopt(staminaBar, true)
topBar.Adopt(basicElements.NewLabel("Health:", false), false) topBar.Adopt(elements.NewLabel("Health:", false), false)
topBar.Adopt(healthBar, true) topBar.Adopt(healthBar, true)
container.Adopt(topBar, false) container.Adopt(topBar, false)
container.Adopt(game, true) container.Adopt(game, true)
@ -69,6 +69,7 @@ func run () {
popups.NewDialog ( popups.NewDialog (
popups.DialogKindInfo, popups.DialogKindInfo,
window,
"Welcome to the backrooms", "Welcome to the backrooms",
"You've no-clipped into the backrooms!\n" + "You've no-clipped into the backrooms!\n" +
"Move with WASD, and look with the arrow keys.\n" + "Move with WASD, and look with the arrow keys.\n" +

View File

@ -2,8 +2,8 @@ package main
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -14,39 +14,39 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(360, 240) window, _ := tomo.NewWindow(360, 240)
window.SetTitle("Scroll") window.SetTitle("Scroll")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
textBox := basicElements.NewTextBox("", copypasta) textBox := elements.NewTextBox("", copypasta)
scrollContainer := containers.NewScrollContainer(true, false) scrollContainer := containers.NewScrollContainer(true, false)
disconnectedContainer := containers.NewContainer (basicLayouts.Horizontal { disconnectedContainer := containers.NewContainer (layouts.Horizontal {
Gap: true, Gap: true,
}) })
list := basicElements.NewList ( list := elements.NewList (
basicElements.NewListEntry("This is list item 0", nil), elements.NewListEntry("This is list item 0", nil),
basicElements.NewListEntry("This is list item 1", nil), elements.NewListEntry("This is list item 1", nil),
basicElements.NewListEntry("This is list item 2", nil), elements.NewListEntry("This is list item 2", nil),
basicElements.NewListEntry("This is list item 3", nil), elements.NewListEntry("This is list item 3", nil),
basicElements.NewListEntry("This is list item 4", nil), elements.NewListEntry("This is list item 4", nil),
basicElements.NewListEntry("This is list item 5", nil), elements.NewListEntry("This is list item 5", nil),
basicElements.NewListEntry("This is list item 6", nil), elements.NewListEntry("This is list item 6", nil),
basicElements.NewListEntry("This is list item 7", nil), elements.NewListEntry("This is list item 7", nil),
basicElements.NewListEntry("This is list item 8", nil), elements.NewListEntry("This is list item 8", nil),
basicElements.NewListEntry("This is list item 9", nil), elements.NewListEntry("This is list item 9", nil),
basicElements.NewListEntry("This is list item 10", nil), elements.NewListEntry("This is list item 10", nil),
basicElements.NewListEntry("This is list item 11", nil), elements.NewListEntry("This is list item 11", nil),
basicElements.NewListEntry("This is list item 12", nil), elements.NewListEntry("This is list item 12", nil),
basicElements.NewListEntry("This is list item 13", nil), elements.NewListEntry("This is list item 13", nil),
basicElements.NewListEntry("This is list item 14", nil), elements.NewListEntry("This is list item 14", nil),
basicElements.NewListEntry("This is list item 15", nil), elements.NewListEntry("This is list item 15", nil),
basicElements.NewListEntry("This is list item 16", nil), elements.NewListEntry("This is list item 16", nil),
basicElements.NewListEntry("This is list item 17", nil), elements.NewListEntry("This is list item 17", nil),
basicElements.NewListEntry("This is list item 18", nil), elements.NewListEntry("This is list item 18", nil),
basicElements.NewListEntry("This is list item 19", nil), elements.NewListEntry("This is list item 19", nil),
basicElements.NewListEntry("This is list item 20", nil)) elements.NewListEntry("This is list item 20", nil))
list.Collapse(0, 32) list.Collapse(0, 32)
scrollBar := basicElements.NewScrollBar(true) scrollBar := elements.NewScrollBar(true)
list.OnScrollBoundsChange (func () { list.OnScrollBoundsChange (func () {
scrollBar.SetBounds ( scrollBar.SetBounds (
list.ScrollContentBounds(), list.ScrollContentBounds(),
@ -57,10 +57,10 @@ func run () {
}) })
scrollContainer.Adopt(textBox) scrollContainer.Adopt(textBox)
container.Adopt(basicElements.NewLabel("A ScrollContainer:", false), false) container.Adopt(elements.NewLabel("A ScrollContainer:", false), false)
container.Adopt(scrollContainer, false) container.Adopt(scrollContainer, false)
disconnectedContainer.Adopt(list, false) disconnectedContainer.Adopt(list, false)
disconnectedContainer.Adopt (basicElements.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 " +

View File

@ -1,8 +1,8 @@
package main package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -14,14 +14,14 @@ func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Spaced Out") window.SetTitle("Spaced Out")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt (basicElements.NewLabel("This is at the top", false), false) container.Adopt (elements.NewLabel("This is at the top", false), false)
container.Adopt (basicElements.NewSpacer(true), false) container.Adopt (elements.NewSpacer(true), false)
container.Adopt (basicElements.NewLabel("This is in the middle", false), false) container.Adopt (elements.NewLabel("This is in the middle", false), false)
container.Adopt (basicElements.NewSpacer(false), true) container.Adopt (elements.NewSpacer(false), true)
container.Adopt (basicElements.NewLabel("This is at the bottom", false), false) container.Adopt (elements.NewLabel("This is at the bottom", false), false)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()

View File

@ -1,8 +1,8 @@
package main package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
@ -14,12 +14,12 @@ func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Switches") window.SetTitle("Switches")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basicElements.NewSwitch("hahahah", false), false) container.Adopt(elements.NewSwitch("hahahah", false), false)
container.Adopt(basicElements.NewSwitch("hehehehheheh", false), false) container.Adopt(elements.NewSwitch("hehehehheheh", false), false)
container.Adopt(basicElements.NewSwitch("you can flick da swicth", false), false) container.Adopt(elements.NewSwitch("you can flick da swicth", false), false)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()

View File

@ -1,8 +1,8 @@
package main package main
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/layouts/basic" import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" 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/elements/containers"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/all" import _ "git.tebibyte.media/sashakoshka/tomo/backends/all"
@ -15,15 +15,15 @@ func run () {
window, _ := tomo.NewWindow(128, 128) window, _ := tomo.NewWindow(128, 128)
window.SetTitle("vertical stack") window.SetTitle("vertical stack")
container := containers.NewContainer(basicLayouts.Vertical { true, true }) container := containers.NewContainer(layouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
label := basicElements.NewLabel("it is a label hehe", true) label := elements.NewLabel("it is a label hehe", true)
button := basicElements.NewButton("drawing pad") button := elements.NewButton("drawing pad")
okButton := basicElements.NewButton("OK") okButton := elements.NewButton("OK")
button.OnClick (func () { button.OnClick (func () {
container.DisownAll() container.DisownAll()
container.Adopt(basicElements.NewLabel("Draw here:", false), false) container.Adopt(elements.NewLabel("Draw here:", false), false)
container.Adopt(testing.NewMouse(), true) container.Adopt(testing.NewMouse(), true)
container.Adopt(okButton, false) container.Adopt(okButton, false)
okButton.Focus() okButton.Focus()

View File

@ -1,18 +1,12 @@
// Package layouts defines a layout interface which a container element can package tomo
// accept to have its child elements automatically arranged by any layout that
// satisfies it.
//
// Sub-packages of layouts contain several pre-made ones.
package layouts
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/elements"
// LayoutEntry associates an element with layout and positioning information so // LayoutEntry associates an element with layout and positioning information so
// it can be arranged by a Layout. // it can be arranged by a Layout.
type LayoutEntry struct { type LayoutEntry struct {
elements.Element Element
Bounds image.Rectangle Bounds image.Rectangle
Expand bool Expand bool
} }

View File

@ -1,8 +1,8 @@
package basicLayouts package layouts
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/layouts"
// Dialog arranges elements in the form of a dialog box. The first element is // Dialog arranges elements in the form of a dialog box. The first element is
// positioned above as the main focus of the dialog, and is set to expand // positioned above as the main focus of the dialog, and is set to expand
@ -20,7 +20,7 @@ type Dialog struct {
// Arrange arranges a list of entries into a dialog. // Arrange arranges a list of entries into a dialog.
func (layout Dialog) Arrange ( func (layout Dialog) Arrange (
entries []layouts.LayoutEntry, entries []tomo.LayoutEntry,
margin image.Point, margin image.Point,
padding artist.Inset, padding artist.Inset,
bounds image.Rectangle, bounds image.Rectangle,
@ -101,7 +101,7 @@ func (layout Dialog) Arrange (
// MinimumSize returns the minimum width and height that will be needed to // MinimumSize returns the minimum width and height that will be needed to
// arrange the given list of entries. // arrange the given list of entries.
func (layout Dialog) MinimumSize ( func (layout Dialog) MinimumSize (
entries []layouts.LayoutEntry, entries []tomo.LayoutEntry,
margin image.Point, margin image.Point,
padding artist.Inset, padding artist.Inset,
) ( ) (
@ -132,7 +132,7 @@ func (layout Dialog) MinimumSize (
} }
func (layout Dialog) minimumSizeOfControlRow ( func (layout Dialog) minimumSizeOfControlRow (
entries []layouts.LayoutEntry, entries []tomo.LayoutEntry,
margin image.Point, margin image.Point,
padding artist.Inset, padding artist.Inset,
) ( ) (

View File

@ -1,9 +1,9 @@
package basicLayouts package layouts
import "image" import "image"
import "golang.org/x/image/math/fixed" import "golang.org/x/image/math/fixed"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/fixedutil" import "git.tebibyte.media/sashakoshka/tomo/fixedutil"
// Horizontal arranges elements horizontally. Elements at the start of the entry // Horizontal arranges elements horizontally. Elements at the start of the entry
@ -20,7 +20,7 @@ type Horizontal struct {
// Arrange arranges a list of entries horizontally. // Arrange arranges a list of entries horizontally.
func (layout Horizontal) Arrange ( func (layout Horizontal) Arrange (
entries []layouts.LayoutEntry, entries []tomo.LayoutEntry,
margin image.Point, margin image.Point,
padding artist.Inset, padding artist.Inset,
bounds image.Rectangle, bounds image.Rectangle,
@ -55,7 +55,7 @@ func (layout Horizontal) Arrange (
// MinimumSize returns the minimum width and height that will be needed to // MinimumSize returns the minimum width and height that will be needed to
// arrange the given list of entries. // arrange the given list of entries.
func (layout Horizontal) MinimumSize ( func (layout Horizontal) MinimumSize (
entries []layouts.LayoutEntry, entries []tomo.LayoutEntry,
margin image.Point, margin image.Point,
padding artist.Inset, padding artist.Inset,
) ( ) (
@ -80,7 +80,7 @@ func (layout Horizontal) MinimumSize (
} }
func (layout Horizontal) expandingElementWidth ( func (layout Horizontal) expandingElementWidth (
entries []layouts.LayoutEntry, entries []tomo.LayoutEntry,
margin image.Point, margin image.Point,
padding artist.Inset, padding artist.Inset,
freeSpace int, freeSpace int,

View File

@ -1,9 +1,9 @@
package basicLayouts package layouts
import "image" import "image"
import "golang.org/x/image/math/fixed" import "golang.org/x/image/math/fixed"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/layouts"
import "git.tebibyte.media/sashakoshka/tomo/fixedutil" import "git.tebibyte.media/sashakoshka/tomo/fixedutil"
// Vertical arranges elements vertically. Elements at the start of the entry // Vertical arranges elements vertically. Elements at the start of the entry
@ -20,7 +20,7 @@ type Vertical struct {
// Arrange arranges a list of entries vertically. // Arrange arranges a list of entries vertically.
func (layout Vertical) Arrange ( func (layout Vertical) Arrange (
entries []layouts.LayoutEntry, entries []tomo.LayoutEntry,
margin image.Point, margin image.Point,
padding artist.Inset, padding artist.Inset,
bounds image.Rectangle, bounds image.Rectangle,
@ -55,7 +55,7 @@ func (layout Vertical) Arrange (
// MinimumSize returns the minimum width and height that will be needed to // MinimumSize returns the minimum width and height that will be needed to
// arrange the given list of entries. // arrange the given list of entries.
func (layout Vertical) MinimumSize ( func (layout Vertical) MinimumSize (
entries []layouts.LayoutEntry, entries []tomo.LayoutEntry,
margin image.Point, margin image.Point,
padding artist.Inset, padding artist.Inset,
) ( ) (
@ -80,7 +80,7 @@ func (layout Vertical) MinimumSize (
} }
func (layout Vertical) expandingElementHeight ( func (layout Vertical) expandingElementHeight (
entries []layouts.LayoutEntry, entries []tomo.LayoutEntry,
margin image.Point, margin image.Point,
padding artist.Inset, padding artist.Inset,
freeSpace int, freeSpace int,

View File

@ -1,4 +1,4 @@
package elements package tomo
// Parent represents a type capable of containing child elements. // Parent represents a type capable of containing child elements.
type Parent interface { type Parent interface {

View File

@ -2,9 +2,8 @@ package popups
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
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/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/containers" import "git.tebibyte.media/sashakoshka/tomo/elements/containers"
// DialogKind defines the semantic role of a dialog window. // DialogKind defines the semantic role of a dialog window.
@ -31,11 +30,11 @@ type Button struct {
// the dialog will just be a normal window // the dialog will just be a normal window
func NewDialog ( func NewDialog (
kind DialogKind, kind DialogKind,
parent elements.Window, parent tomo.Window,
title, message string, title, message string,
buttons ...Button, buttons ...Button,
) ( ) (
window elements.Window, window tomo.Window,
) { ) {
if parent == nil { if parent == nil {
window, _ = tomo.NewWindow(2, 2) window, _ = tomo.NewWindow(2, 2)
@ -44,10 +43,10 @@ func NewDialog (
} }
window.SetTitle(title) window.SetTitle(title)
container := containers.NewContainer(basicLayouts.Dialog { true, true }) container := containers.NewContainer(layouts.Dialog { true, true })
window.Adopt(container) window.Adopt(container)
messageContainer := containers.NewContainer(basicLayouts.Horizontal { true, false }) messageContainer := containers.NewContainer(layouts.Horizontal { true, false })
iconId := theme.IconInformation iconId := theme.IconInformation
switch kind { switch kind {
case DialogKindInfo: iconId = theme.IconInformation case DialogKindInfo: iconId = theme.IconInformation
@ -56,20 +55,20 @@ func NewDialog (
case DialogKindError: iconId = theme.IconError case DialogKindError: iconId = theme.IconError
} }
messageContainer.Adopt(basicElements.NewIcon(iconId, theme.IconSizeLarge), false) messageContainer.Adopt(elements.NewIcon(iconId, theme.IconSizeLarge), false)
messageContainer.Adopt(basicElements.NewLabel(message, false), true) messageContainer.Adopt(elements.NewLabel(message, false), true)
container.Adopt(messageContainer, true) container.Adopt(messageContainer, true)
if len(buttons) == 0 { if len(buttons) == 0 {
button := basicElements.NewButton("OK") button := elements.NewButton("OK")
button.SetIcon(theme.IconYes) button.SetIcon(theme.IconYes)
button.OnClick(window.Close) button.OnClick(window.Close)
container.Adopt(button, false) container.Adopt(button, false)
button.Focus() button.Focus()
} else { } else {
var button *basicElements.Button var button *elements.Button
for _, buttonDescriptor := range buttons { for _, buttonDescriptor := range buttons {
button = basicElements.NewButton(buttonDescriptor.Name) button = elements.NewButton(buttonDescriptor.Name)
button.SetEnabled(buttonDescriptor.OnPress != nil) button.SetEnabled(buttonDescriptor.OnPress != nil)
button.OnClick (func () { button.OnClick (func () {
buttonDescriptor.OnPress() buttonDescriptor.OnPress()

View File

@ -210,7 +210,7 @@ func (Default) Pattern (id Pattern, state State, c Case) artist.Pattern {
case PatternBackground: return patterns.Uhex(0xaaaaaaFF) case PatternBackground: return patterns.Uhex(0xaaaaaaFF)
case PatternDead: return defaultTextures[0][offset] case PatternDead: return defaultTextures[0][offset]
case PatternRaised: case PatternRaised:
if c.Match("basic", "listEntry", "") { if c.Match("tomo", "listEntry", "") {
return defaultTextures[10][offset] return defaultTextures[10][offset]
} else { } else {
return defaultTextures[1][offset] return defaultTextures[1][offset]
@ -219,11 +219,11 @@ func (Default) Pattern (id Pattern, state State, c Case) artist.Pattern {
case PatternPinboard: return defaultTextures[3][offset] case PatternPinboard: return defaultTextures[3][offset]
case PatternButton: case PatternButton:
switch { switch {
case c.Match("basic", "checkbox", ""): case c.Match("tomo", "checkbox", ""):
return defaultTextures[9][offset] return defaultTextures[9][offset]
case c.Match("fun", "piano", "flatKey"): case c.Match("tomo", "piano", "flatKey"):
return defaultTextures[11][offset] return defaultTextures[11][offset]
case c.Match("fun", "piano", "sharpKey"): case c.Match("tomo", "piano", "sharpKey"):
return defaultTextures[12][offset] return defaultTextures[12][offset]
default: default:
return defaultTextures[4][offset] return defaultTextures[4][offset]
@ -253,13 +253,13 @@ func (Default) Color (id Color, state State, c Case) color.RGBA {
func (Default) Padding (id Pattern, c Case) artist.Inset { func (Default) Padding (id Pattern, c Case) artist.Inset {
switch id { switch id {
case PatternRaised: case PatternRaised:
if c.Match("basic", "listEntry", "") { if c.Match("tomo", "listEntry", "") {
return artist.I(4, 8) return artist.I(4, 8)
} else { } else {
return artist.I(8) return artist.I(8)
} }
case PatternSunken: case PatternSunken:
if c.Match("basic", "list", "") { if c.Match("tomo", "list", "") {
return artist.I(4, 0, 3) return artist.I(4, 0, 3)
} else if c.Match("basic", "progressBar", "") { } else if c.Match("basic", "progressBar", "") {
return artist.I(2, 1, 1, 2) return artist.I(2, 1, 1, 2)
@ -267,7 +267,7 @@ func (Default) Padding (id Pattern, c Case) artist.Inset {
return artist.I(8) return artist.I(8)
} }
case PatternPinboard: case PatternPinboard:
if c.Match("fun", "piano", "") { if c.Match("tomo", "piano", "") {
return artist.I(2) return artist.I(2)
} else { } else {
return artist.I(8) return artist.I(8)

64
tomo.go
View File

@ -1,12 +1,7 @@
package tomo package tomo
import "os"
import "io"
import "path/filepath"
import "git.tebibyte.media/sashakoshka/tomo/dirs"
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/elements"
var backend Backend var backend Backend
@ -16,9 +11,6 @@ var backend Backend
func Run (callback func ()) (err error) { func Run (callback func ()) (err error) {
backend, err = instantiateBackend() backend, err = instantiateBackend()
if err != nil { return } if err != nil { return }
config := parseConfig()
backend.SetConfig(config)
backend.SetTheme(parseTheme(config.ThemePath()))
if callback != nil { callback() } if callback != nil { callback() }
err = backend.Run() err = backend.Run()
backend = nil backend = nil
@ -41,7 +33,7 @@ func Do (callback func ()) {
// NewWindow creates a new window using the current backend, and returns it as a // NewWindow creates a new window using the current backend, and returns it as a
// MainWindow. If the window could not be created, an error is returned // MainWindow. If the window could not be created, an error is returned
// explaining why. // explaining why.
func NewWindow (width, height int) (window elements.MainWindow, err error) { func NewWindow (width, height int) (window MainWindow, err error) {
assertBackend() assertBackend()
return backend.NewWindow(width, height) return backend.NewWindow(width, height)
} }
@ -56,60 +48,6 @@ func SetConfig (config config.Config) {
backend.SetConfig(config) backend.SetConfig(config)
} }
func parseConfig () (config.Config) {
return parseMany [config.Config] (
dirs.ConfigDirs("tomo/tomo.conf"),
config.Parse,
config.Default { })
}
func parseTheme (path string) (theme.Theme) {
if path == "" { return theme.Default { } }
path = filepath.Join(path, "tomo")
// find all tomo pattern graph files in the directory
directory, err := os.Open(path)
if err != nil { return theme.Default { } }
names, _ := directory.Readdirnames(0)
paths := []string { }
for _, name := range names {
if filepath.Ext(name) == ".tpg" {
paths = append(paths, filepath.Join(path, name))
}
}
// parse them
return parseMany [theme.Theme] (
paths,
theme.Parse,
theme.Default { })
}
func parseMany [OBJECT any] (
paths []string,
parser func (...io.Reader) OBJECT,
fallback OBJECT,
) (
object OBJECT,
) {
// convert all paths into readers
sources := []io.Reader { }
for _, path := range paths {
file, err := os.Open(path)
if err != nil { continue }
sources = append(sources, file)
defer file.Close()
}
if sources == nil {
// if there are no readers, return the fallback object
return fallback
} else {
// if there are readers, parse them
return parser(sources...)
}
}
func assertBackend () { func assertBackend () {
if backend == nil { panic("no backend is running") } if backend == nil { panic("no backend is running") }
} }

View File

@ -1,4 +1,4 @@
package elements package tomo
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo/data" import "git.tebibyte.media/sashakoshka/tomo/data"