atomize-modules #7

Merged
sashakoshka merged 5 commits from atomize-modules into main 2023-02-02 22:51:23 +00:00
40 changed files with 304 additions and 759 deletions
Showing only changes of commit 892c74a9da - Show all commits

View File

@ -3,11 +3,11 @@ package artist
import "math" import "math"
import "image" import "image"
import "image/color" import "image/color"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo/canvas"
// FillEllipse draws a filled ellipse with the specified pattern. // FillEllipse draws a filled ellipse with the specified pattern.
func FillEllipse ( func FillEllipse (
destination tomo.Canvas, destination canvas.Canvas,
source Pattern, source Pattern,
bounds image.Rectangle, bounds image.Rectangle,
) ( ) (
@ -36,7 +36,7 @@ func FillEllipse (
// StrokeEllipse draws the outline of an ellipse with the specified line weight // StrokeEllipse draws the outline of an ellipse with the specified line weight
// and pattern. // and pattern.
func StrokeEllipse ( func StrokeEllipse (
destination tomo.Canvas, destination canvas.Canvas,
source Pattern, source Pattern,
weight int, weight int,
bounds image.Rectangle, bounds image.Rectangle,

View File

@ -2,14 +2,14 @@ package artist
import "image" import "image"
import "image/color" import "image/color"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo/canvas"
// TODO: draw thick lines more efficiently // TODO: draw thick lines more efficiently
// Line draws a line from one point to another with the specified weight and // Line draws a line from one point to another with the specified weight and
// pattern. // pattern.
func Line ( func Line (
destination tomo.Canvas, destination canvas.Canvas,
source Pattern, source Pattern,
weight int, weight int,
min image.Point, min image.Point,
@ -46,7 +46,7 @@ func Line (
} }
func lineLow ( func lineLow (
destination tomo.Canvas, destination canvas.Canvas,
source Pattern, source Pattern,
weight int, weight int,
min image.Point, min image.Point,
@ -82,7 +82,7 @@ func lineLow (
} }
func lineHigh ( func lineHigh (
destination tomo.Canvas, destination canvas.Canvas,
source Pattern, source Pattern,
weight int, weight int,
min image.Point, min image.Point,

View File

@ -1,12 +1,12 @@
package artist package artist
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo/canvas"
// Paste transfers one canvas onto another, offset by the specified point. // Paste transfers one canvas onto another, offset by the specified point.
func Paste ( func Paste (
destination tomo.Canvas, destination canvas.Canvas,
source tomo.Canvas, source canvas.Canvas,
offset image.Point, offset image.Point,
) ( ) (
updatedRegion image.Rectangle, updatedRegion image.Rectangle,
@ -31,7 +31,7 @@ func Paste (
// FillRectangle draws a filled rectangle with the specified pattern. // FillRectangle draws a filled rectangle with the specified pattern.
func FillRectangle ( func FillRectangle (
destination tomo.Canvas, destination canvas.Canvas,
source Pattern, source Pattern,
bounds image.Rectangle, bounds image.Rectangle,
) ( ) (
@ -61,7 +61,7 @@ func FillRectangle (
// StrokeRectangle draws the outline of a rectangle with the specified line // StrokeRectangle draws the outline of a rectangle with the specified line
// weight and pattern. // weight and pattern.
func StrokeRectangle ( func StrokeRectangle (
destination tomo.Canvas, destination canvas.Canvas,
source Pattern, source Pattern,
weight int, weight int,
bounds image.Rectangle, bounds image.Rectangle,

View File

@ -6,7 +6,7 @@ import "unicode"
import "image/draw" import "image/draw"
import "golang.org/x/image/font" import "golang.org/x/image/font"
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/canvas"
type characterLayout struct { type characterLayout struct {
x int x int
@ -95,7 +95,7 @@ func (drawer *TextDrawer) SetAlignment (align Align) {
// Draw draws the drawer's text onto the specified canvas at the given offset. // Draw draws the drawer's text onto the specified canvas at the given offset.
func (drawer *TextDrawer) Draw ( func (drawer *TextDrawer) Draw (
destination tomo.Canvas, destination canvas.Canvas,
source Pattern, source Pattern,
offset image.Point, offset image.Point,
) ( ) (

View File

@ -1,90 +0,0 @@
package tomo
import "image"
import "image/draw"
import "image/color"
// Canvas is like draw.Image but is also able to return a raw pixel buffer for
// more efficient drawing. This interface can be easily satisfied using a
// BasicCanvas struct.
type Canvas interface {
draw.Image
Buffer () (data []color.RGBA, stride int)
}
// BasicCanvas is a general purpose implementation of tomo.Canvas.
type BasicCanvas struct {
pix []color.RGBA
stride int
rect image.Rectangle
}
// NewBasicCanvas creates a new basic canvas with the specified width and
// height, allocating a buffer for it.
func NewBasicCanvas (width, height int) (canvas BasicCanvas) {
canvas.pix = make([]color.RGBA, height * width)
canvas.stride = width
canvas.rect = image.Rect(0, 0, width, height)
return
}
// you know what it do
func (canvas BasicCanvas) Bounds () (bounds image.Rectangle) {
return canvas.rect
}
// you know what it do
func (canvas BasicCanvas) At (x, y int) (color.Color) {
if !image.Pt(x, y).In(canvas.rect) { return nil }
return canvas.pix[x + y * canvas.stride]
}
// you know what it do
func (canvas BasicCanvas) ColorModel () (model color.Model) {
return color.RGBAModel
}
// you know what it do
func (canvas BasicCanvas) Set (x, y int, c color.Color) {
if !image.Pt(x, y).In(canvas.rect) { return }
r, g, b, a := c.RGBA()
canvas.pix[x + y * canvas.stride] = color.RGBA {
R: uint8(r >> 8),
G: uint8(g >> 8),
B: uint8(b >> 8),
A: uint8(a >> 8),
}
}
// you know what it do
func (canvas BasicCanvas) Buffer () (data []color.RGBA, stride int) {
return canvas.pix, canvas.stride
}
// Reallocate efficiently reallocates the canvas. The data within will be
// garbage. This method will do nothing if this is a cut image.
func (canvas *BasicCanvas) Reallocate (width, height int) {
if canvas.rect.Min != (image.Point { }) { return }
previousLen := len(canvas.pix)
newLen := width * height
bigger := newLen > previousLen
smaller := newLen < previousLen / 2
if bigger || smaller {
canvas.pix = make (
[]color.RGBA,
((height * width) / 4096) * 4096 + 4096)
}
canvas.stride = width
canvas.rect = image.Rect(0, 0, width, height)
}
// Cut returns a sub-canvas of a given canvas.
func Cut (canvas Canvas, bounds image.Rectangle) (reduced BasicCanvas) {
// println(canvas.Bounds().String(), bounds.String())
bounds = bounds.Intersect(canvas.Bounds())
if bounds.Empty() { return }
reduced.rect = bounds
reduced.pix, reduced.stride = canvas.Buffer()
return
}

20
data.go
View File

@ -1,20 +0,0 @@
package tomo
import "io"
// Data represents arbitrary polymorphic data that can be used for data transfer
// between applications.
type Data map[Mime] io.ReadCloser
// Mime represents a MIME type.
type Mime struct {
// Type is the first half of the MIME type, and Subtype is the second
// half. The separating slash is not included in either. For example,
// text/html becomes:
// Mime { Type: "text", Subtype: "html" }
Type, Subtype string
}
var MimePlain = Mime { "text", "plain" }
var MimeFile = Mime { "text", "uri-list" }

View File

@ -1,177 +0,0 @@
package tomo
import "image"
// Element represents a basic on-screen object.
type Element interface {
// Element must implement the Canvas interface. Elements should start
// out with a completely blank buffer, and only allocate memory and draw
// on it for the first time when sent an EventResize event.
Canvas
// MinimumSize specifies the minimum amount of pixels this element's
// width and height may be set to. If the element is given a resize
// event with dimensions smaller than this, it will use its minimum
// instead of the offending dimension(s).
MinimumSize () (width, height int)
// DrawTo sets this element's canvas. This should only be called by the
// parent element. This is typically a region of the parent element's
// canvas.
DrawTo (canvas Canvas)
// OnDamage sets a function to be called when an area of the element is
// drawn on and should be pushed to the screen.
OnDamage (callback func (region Canvas))
// OnMinimumSizeChange sets a function to be called when the element's
// minimum size is changed.
OnMinimumSizeChange (callback func ())
}
// KeynavDirection represents a keyboard navigation direction.
type KeynavDirection int
const (
KeynavDirectionNeutral KeynavDirection = 0
KeynavDirectionBackward KeynavDirection = -1
KeynavDirectionForward KeynavDirection = 1
)
// Canon returns a well-formed direction.
func (direction KeynavDirection) Canon () (canon KeynavDirection) {
if direction > 0 {
return KeynavDirectionForward
} else if direction == 0 {
return KeynavDirectionNeutral
} else {
return KeynavDirectionBackward
}
}
// Focusable represents an element that has keyboard navigation support. This
// includes inputs, buttons, sliders, etc. as well as any elements that have
// children (so keyboard navigation events can be propagated downward).
type Focusable interface {
Element
// Focused returns whether or not this element is currently focused.
Focused () (selected bool)
// Focus focuses this element, if its parent element grants the
// request.
Focus ()
// HandleFocus causes this element to mark itself as focused. If the
// element does not have children, it is disabled, or there are no more
// selectable children in the given direction, it should return false
// and do nothing. Otherwise, it should select itself and any children
// (if applicable) and return true.
HandleFocus (direction KeynavDirection) (accepted bool)
// HandleDeselection causes this element to mark itself and all of its
// children as unfocused.
HandleUnfocus ()
// OnFocusRequest sets a function to be called when this element wants
// its parent element to focus it. Parent elements should return true if
// the request was granted, and false if it was not.
OnFocusRequest (func () (granted bool))
// OnFocusMotionRequest sets a function to be called when this
// element wants its parent element to focus the element behind or in
// front of it, depending on the specified direction. Parent elements
// should return true if the request was granted, and false if it was
// not.
OnFocusMotionRequest (func (direction KeynavDirection) (granted bool))
}
// KeyboardTarget represents an element that can receive keyboard input.
type KeyboardTarget interface {
Element
// HandleKeyDown is called when a key is pressed down or repeated while
// this element has keyboard focus. It is important to note that not
// every key down event is guaranteed to be paired with exactly one key
// up event. This is the reason a list of modifier keys held down at the
// time of the key press is given.
HandleKeyDown (key Key, modifiers Modifiers)
// HandleKeyUp is called when a key is released while this element has
// keyboard focus.
HandleKeyUp (key Key, modifiers Modifiers)
}
// MouseTarget represents an element that can receive mouse events.
type MouseTarget interface {
Element
// Each of these handler methods is passed the position of the mouse
// cursor at the time of the event as x, y.
// HandleMouseDown is called when a mouse button is pressed down on this
// element.
HandleMouseDown (x, y int, button Button)
// HandleMouseUp is called when a mouse button is released that was
// originally pressed down on this element.
HandleMouseUp (x, y int, button Button)
// HandleMouseMove is called when the mouse is moved over this element,
// or the mouse is moving while being held down and originally pressed
// down on this element.
HandleMouseMove (x, y int)
// HandleScroll is called when the mouse is scrolled. The X and Y
// direction of the scroll event are passed as deltaX and deltaY.
HandleMouseScroll (x, y int, deltaX, deltaY float64)
}
// Flexible represents an element who's preferred minimum height can change in
// response to its width.
type Flexible interface {
Element
// FlexibleHeightFor returns what the element's minimum height would be
// if resized to a specified width. This does not actually alter the
// state of the element in any way, but it may perform significant work,
// so it should be called sparingly.
//
// It is reccomended that parent containers check for this interface and
// take this method's value into account in order to support things like
// flow layouts and text wrapping, but it is not absolutely necessary.
// The element's MinimumSize method will still return the absolute
// minimum size that the element may be resized to.
//
// It is important to note that if a parent container checks for
// flexible chilren, it itself will likely need to be flexible.
FlexibleHeightFor (width int) (height int)
// OnFlexibleHeightChange sets a function to be called when the
// parameters affecting this element's flexible height are changed.
OnFlexibleHeightChange (callback func ())
}
// Scrollable represents an element that can be scrolled. It acts as a viewport
// through which its contents can be observed.
type Scrollable interface {
Element
// ScrollContentBounds returns the full content size of the element.
ScrollContentBounds () (bounds image.Rectangle)
// ScrollViewportBounds returns the size and position of the element's
// viewport relative to ScrollBounds.
ScrollViewportBounds () (bounds image.Rectangle)
// ScrollTo scrolls the viewport to the specified point relative to
// ScrollBounds.
ScrollTo (position image.Point)
// ScrollAxes returns the supported axes for scrolling.
ScrollAxes () (horizontal, vertical bool)
// OnScrollBoundsChange sets a function to be called when the element's
// ScrollContentBounds, ScrollViewportBounds, or ScrollAxes are changed.
OnScrollBoundsChange (callback func ())
}

View File

@ -1,7 +1,7 @@
package basic package basicElements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo" 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/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/elements/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
@ -38,10 +38,10 @@ func NewButton (text string) (element *Button) {
return return
} }
func (element *Button) HandleMouseDown (x, y int, button tomo.Button) { func (element *Button) HandleMouseDown (x, y int, button input.Button) {
if !element.Enabled() { return } if !element.Enabled() { return }
if !element.Focused() { element.Focus() } if !element.Focused() { element.Focus() }
if button != tomo.ButtonLeft { return } if button != input.ButtonLeft { return }
element.pressed = true element.pressed = true
if element.core.HasImage() { if element.core.HasImage() {
element.draw() element.draw()
@ -49,8 +49,8 @@ func (element *Button) HandleMouseDown (x, y int, button tomo.Button) {
} }
} }
func (element *Button) HandleMouseUp (x, y int, button tomo.Button) { func (element *Button) HandleMouseUp (x, y int, button input.Button) {
if button != tomo.ButtonLeft { return } if button != input.ButtonLeft { return }
element.pressed = false element.pressed = false
if element.core.HasImage() { if element.core.HasImage() {
element.draw() element.draw()
@ -69,9 +69,9 @@ func (element *Button) HandleMouseUp (x, y int, button tomo.Button) {
func (element *Button) HandleMouseMove (x, y int) { } func (element *Button) HandleMouseMove (x, y int) { }
func (element *Button) HandleMouseScroll (x, y int, deltaX, deltaY float64) { } func (element *Button) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
func (element *Button) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) { func (element *Button) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
if !element.Enabled() { return } if !element.Enabled() { return }
if key == tomo.KeyEnter { if key == input.KeyEnter {
element.pressed = true element.pressed = true
if element.core.HasImage() { if element.core.HasImage() {
element.draw() element.draw()
@ -80,8 +80,8 @@ func (element *Button) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
} }
} }
func (element *Button) HandleKeyUp(key tomo.Key, modifiers tomo.Modifiers) { func (element *Button) HandleKeyUp(key input.Key, modifiers input.Modifiers) {
if key == tomo.KeyEnter && element.pressed { if key == input.KeyEnter && element.pressed {
element.pressed = false element.pressed = false
if element.core.HasImage() { if element.core.HasImage() {
element.draw() element.draw()

View File

@ -1,7 +1,7 @@
package basic package basicElements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo" 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/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/elements/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
@ -39,7 +39,7 @@ func NewCheckbox (text string, checked bool) (element *Checkbox) {
return return
} }
func (element *Checkbox) HandleMouseDown (x, y int, button tomo.Button) { func (element *Checkbox) HandleMouseDown (x, y int, button input.Button) {
if !element.Enabled() { return } if !element.Enabled() { return }
element.Focus() element.Focus()
element.pressed = true element.pressed = true
@ -49,8 +49,8 @@ func (element *Checkbox) HandleMouseDown (x, y int, button tomo.Button) {
} }
} }
func (element *Checkbox) HandleMouseUp (x, y int, button tomo.Button) { func (element *Checkbox) HandleMouseUp (x, y int, button input.Button) {
if button != tomo.ButtonLeft || !element.pressed { return } if button != input.ButtonLeft || !element.pressed { return }
element.pressed = false element.pressed = false
within := image.Point { x, y }. within := image.Point { x, y }.
@ -71,8 +71,8 @@ func (element *Checkbox) HandleMouseUp (x, y int, button tomo.Button) {
func (element *Checkbox) HandleMouseMove (x, y int) { } func (element *Checkbox) HandleMouseMove (x, y int) { }
func (element *Checkbox) HandleMouseScroll (x, y int, deltaX, deltaY float64) { } func (element *Checkbox) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
func (element *Checkbox) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) { func (element *Checkbox) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
if key == tomo.KeyEnter { if key == input.KeyEnter {
element.pressed = true element.pressed = true
if element.core.HasImage() { if element.core.HasImage() {
element.draw() element.draw()
@ -81,8 +81,8 @@ func (element *Checkbox) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers)
} }
} }
func (element *Checkbox) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) { func (element *Checkbox) HandleKeyUp (key input.Key, modifiers input.Modifiers) {
if key == tomo.KeyEnter && element.pressed { if key == input.KeyEnter && element.pressed {
element.pressed = false element.pressed = false
element.checked = !element.checked element.checked = !element.checked
if element.core.HasImage() { if element.core.HasImage() {

View File

@ -1,9 +1,12 @@
package basic package basicElements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo" 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/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"
var containerCase = theme.C("basic", "container") var containerCase = theme.C("basic", "container")
@ -14,21 +17,21 @@ type Container struct {
*core.Core *core.Core
core core.CoreControl core core.CoreControl
layout tomo.Layout layout layouts.Layout
children []tomo.LayoutEntry children []layouts.LayoutEntry
drags [10]tomo.MouseTarget drags [10]elements.MouseTarget
warping bool warping bool
focused bool focused bool
focusable bool focusable bool
flexible bool flexible bool
onFocusRequest func () (granted bool) onFocusRequest func () (granted bool)
onFocusMotionRequest func (tomo.KeynavDirection) (granted bool) onFocusMotionRequest func (input.KeynavDirection) (granted bool)
onFlexibleHeightChange func () onFlexibleHeightChange func ()
} }
// NewContainer creates a new container. // NewContainer creates a new container.
func NewContainer (layout tomo.Layout) (element *Container) { func NewContainer (layout layouts.Layout) (element *Container) {
element = &Container { } element = &Container { }
element.Core, element.core = core.NewCore(element.redoAll) element.Core, element.core = core.NewCore(element.redoAll)
element.SetLayout(layout) element.SetLayout(layout)
@ -36,7 +39,7 @@ func NewContainer (layout tomo.Layout) (element *Container) {
} }
// SetLayout sets the layout of this container. // SetLayout sets the layout of this container.
func (element *Container) SetLayout (layout tomo.Layout) { func (element *Container) SetLayout (layout layouts.Layout) {
element.layout = layout element.layout = layout
if element.core.HasImage() { if element.core.HasImage() {
element.redoAll() element.redoAll()
@ -47,28 +50,28 @@ func (element *Container) SetLayout (layout tomo.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 tomo.Element, expand bool) { func (element *Container) Adopt (child elements.Element, expand bool) {
// set event handlers // set event handlers
child.OnDamage (func (region tomo.Canvas) { child.OnDamage (func (region canvas.Canvas) {
element.core.DamageRegion(region.Bounds()) element.core.DamageRegion(region.Bounds())
}) })
child.OnMinimumSizeChange(element.updateMinimumSize) child.OnMinimumSizeChange(element.updateMinimumSize)
if child0, ok := child.(tomo.Flexible); ok { if child0, ok := child.(elements.Flexible); ok {
child0.OnFlexibleHeightChange(element.updateMinimumSize) child0.OnFlexibleHeightChange(element.updateMinimumSize)
} }
if child0, ok := child.(tomo.Focusable); ok { if child0, ok := child.(elements.Focusable); ok {
child0.OnFocusRequest (func () (granted bool) { child0.OnFocusRequest (func () (granted bool) {
return element.childFocusRequestCallback(child0) return element.childFocusRequestCallback(child0)
}) })
child0.OnFocusMotionRequest ( child0.OnFocusMotionRequest (
func (direction tomo.KeynavDirection) (granted bool) { func (direction input.KeynavDirection) (granted bool) {
if element.onFocusMotionRequest == nil { return } if element.onFocusMotionRequest == nil { return }
return element.onFocusMotionRequest(direction) return element.onFocusMotionRequest(direction)
}) })
} }
// add child // add child
element.children = append (element.children, tomo.LayoutEntry { element.children = append (element.children, layouts.LayoutEntry {
Element: child, Element: child,
Expand: expand, Expand: expand,
}) })
@ -106,7 +109,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 tomo.Element) { func (element *Container) Disown (child elements.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)
@ -125,18 +128,18 @@ func (element *Container) Disown (child tomo.Element) {
} }
} }
func (element *Container) clearChildEventHandlers (child tomo.Element) { func (element *Container) clearChildEventHandlers (child elements.Element) {
child.DrawTo(nil) child.DrawTo(nil)
child.OnDamage(nil) child.OnDamage(nil)
child.OnMinimumSizeChange(nil) child.OnMinimumSizeChange(nil)
if child0, ok := child.(tomo.Focusable); ok { if child0, ok := child.(elements.Focusable); ok {
child0.OnFocusRequest(nil) child0.OnFocusRequest(nil)
child0.OnFocusMotionRequest(nil) child0.OnFocusMotionRequest(nil)
if child0.Focused() { if child0.Focused() {
child0.HandleUnfocus() child0.HandleUnfocus()
} }
} }
if child0, ok := child.(tomo.Flexible); ok { if child0, ok := child.(elements.Flexible); ok {
child0.OnFlexibleHeightChange(nil) child0.OnFlexibleHeightChange(nil)
} }
} }
@ -154,8 +157,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 []tomo.Element) { func (element *Container) Children () (children []elements.Element) {
children = make([]tomo.Element, len(element.children)) children = make([]elements.Element, len(element.children))
for index, entry := range element.children { for index, entry := range element.children {
children[index] = entry.Element children[index] = entry.Element
} }
@ -169,14 +172,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 tomo.Element) { func (element *Container) Child (index int) (child elements.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 tomo.Element) { func (element *Container) ChildAt (point image.Point) (child elements.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
@ -185,7 +188,7 @@ func (element *Container) ChildAt (point image.Point) (child tomo.Element) {
return return
} }
func (element *Container) childPosition (child tomo.Element) (position image.Point) { func (element *Container) childPosition (child elements.Element) (position image.Point) {
for _, entry := range element.children { for _, entry := range element.children {
if entry.Element == child { if entry.Element == child {
position = entry.Bounds.Min position = entry.Bounds.Min
@ -209,18 +212,18 @@ func (element *Container) redoAll () {
// cut our canvas up and give peices to child elements // cut our canvas up and give peices to child elements
for _, entry := range element.children { for _, entry := range element.children {
entry.DrawTo(tomo.Cut(element, entry.Bounds)) entry.DrawTo(canvas.Cut(element, entry.Bounds))
} }
} }
func (element *Container) HandleMouseDown (x, y int, button tomo.Button) { func (element *Container) HandleMouseDown (x, y int, button input.Button) {
child, handlesMouse := element.ChildAt(image.Pt(x, y)).(tomo.MouseTarget) child, handlesMouse := element.ChildAt(image.Pt(x, y)).(elements.MouseTarget)
if !handlesMouse { return } if !handlesMouse { return }
element.drags[button] = child element.drags[button] = child
child.HandleMouseDown(x, y, button) child.HandleMouseDown(x, y, button)
} }
func (element *Container) HandleMouseUp (x, y int, button tomo.Button) { func (element *Container) HandleMouseUp (x, y int, button input.Button) {
child := element.drags[button] child := element.drags[button]
if child == nil { return } if child == nil { return }
element.drags[button] = nil element.drags[button] = nil
@ -235,14 +238,14 @@ func (element *Container) HandleMouseMove (x, y int) {
} }
func (element *Container) HandleMouseScroll (x, y int, deltaX, deltaY float64) { func (element *Container) HandleMouseScroll (x, y int, deltaX, deltaY float64) {
child, handlesMouse := element.ChildAt(image.Pt(x, y)).(tomo.MouseTarget) child, handlesMouse := element.ChildAt(image.Pt(x, y)).(elements.MouseTarget)
if !handlesMouse { return } if !handlesMouse { return }
child.HandleMouseScroll(x, y, deltaX, deltaY) child.HandleMouseScroll(x, y, deltaX, deltaY)
} }
func (element *Container) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) { func (element *Container) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
element.forFocused (func (child tomo.Focusable) bool { element.forFocused (func (child elements.Focusable) bool {
child0, handlesKeyboard := child.(tomo.KeyboardTarget) child0, handlesKeyboard := child.(elements.KeyboardTarget)
if handlesKeyboard { if handlesKeyboard {
child0.HandleKeyDown(key, modifiers) child0.HandleKeyDown(key, modifiers)
} }
@ -250,9 +253,9 @@ func (element *Container) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers)
}) })
} }
func (element *Container) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) { func (element *Container) HandleKeyUp (key input.Key, modifiers input.Modifiers) {
element.forFocused (func (child tomo.Focusable) bool { element.forFocused (func (child elements.Focusable) bool {
child0, handlesKeyboard := child.(tomo.KeyboardTarget) child0, handlesKeyboard := child.(elements.KeyboardTarget)
if handlesKeyboard { if handlesKeyboard {
child0.HandleKeyUp(key, modifiers) child0.HandleKeyUp(key, modifiers)
} }
@ -261,7 +264,9 @@ func (element *Container) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) {
} }
func (element *Container) FlexibleHeightFor (width int) (height int) { func (element *Container) FlexibleHeightFor (width int) (height int) {
return element.layout.FlexibleHeightFor(element.children, width) return element.layout.FlexibleHeightFor (
element.children,
theme.Margin(), width)
} }
func (element *Container) OnFlexibleHeightChange (callback func ()) { func (element *Container) OnFlexibleHeightChange (callback func ()) {
@ -278,7 +283,7 @@ func (element *Container) Focus () {
} }
} }
func (element *Container) HandleFocus (direction tomo.KeynavDirection) (ok bool) { func (element *Container) HandleFocus (direction input.KeynavDirection) (ok bool) {
if !element.focusable { return false } if !element.focusable { return false }
direction = direction.Canon() direction = direction.Canon()
@ -288,12 +293,12 @@ func (element *Container) HandleFocus (direction tomo.KeynavDirection) (ok bool)
// the first or last focusable element depending on the // the first or last focusable element depending on the
// direction. // direction.
switch direction { switch direction {
case tomo.KeynavDirectionNeutral, tomo.KeynavDirectionForward: case input.KeynavDirectionNeutral, input.KeynavDirectionForward:
// if we recieve a neutral or forward direction, focus // if we recieve a neutral or forward direction, focus
// the first focusable element. // the first focusable element.
return element.focusFirstFocusableElement(direction) return element.focusFirstFocusableElement(direction)
case tomo.KeynavDirectionBackward: case input.KeynavDirectionBackward:
// if we recieve a backward direction, focus the last // if we recieve a backward direction, focus the last
// focusable element. // focusable element.
return element.focusLastFocusableElement(direction) return element.focusLastFocusableElement(direction)
@ -302,7 +307,7 @@ func (element *Container) HandleFocus (direction tomo.KeynavDirection) (ok bool)
// an element is currently focused, so we need to move the // an element is currently focused, so we need to move the
// focus in the specified direction // focus in the specified direction
firstFocusedChild := firstFocusedChild :=
element.children[firstFocused].Element.(tomo.Focusable) element.children[firstFocused].Element.(elements.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
@ -319,7 +324,7 @@ func (element *Container) HandleFocus (direction tomo.KeynavDirection) (ok bool)
child, focusable := child, focusable :=
element.children[index]. element.children[index].
Element.(tomo.Focusable) Element.(elements.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.
@ -334,11 +339,11 @@ func (element *Container) HandleFocus (direction tomo.KeynavDirection) (ok bool)
} }
func (element *Container) focusFirstFocusableElement ( func (element *Container) focusFirstFocusableElement (
direction tomo.KeynavDirection, direction input.KeynavDirection,
) ( ) (
ok bool, ok bool,
) { ) {
element.forFocusable (func (child tomo.Focusable) bool { element.forFocusable (func (child elements.Focusable) bool {
if child.HandleFocus(direction) { if child.HandleFocus(direction) {
element.focused = true element.focused = true
ok = true ok = true
@ -350,11 +355,11 @@ func (element *Container) focusFirstFocusableElement (
} }
func (element *Container) focusLastFocusableElement ( func (element *Container) focusLastFocusableElement (
direction tomo.KeynavDirection, direction input.KeynavDirection,
) ( ) (
ok bool, ok bool,
) { ) {
element.forFocusableBackward (func (child tomo.Focusable) bool { element.forFocusableBackward (func (child elements.Focusable) bool {
if child.HandleFocus(direction) { if child.HandleFocus(direction) {
element.focused = true element.focused = true
ok = true ok = true
@ -367,7 +372,7 @@ func (element *Container) focusLastFocusableElement (
func (element *Container) HandleUnfocus () { func (element *Container) HandleUnfocus () {
element.focused = false element.focused = false
element.forFocused (func (child tomo.Focusable) bool { element.forFocused (func (child elements.Focusable) bool {
child.HandleUnfocus() child.HandleUnfocus()
return true return true
}) })
@ -378,41 +383,41 @@ func (element *Container) OnFocusRequest (callback func () (granted bool)) {
} }
func (element *Container) OnFocusMotionRequest ( func (element *Container) OnFocusMotionRequest (
callback func (direction tomo.KeynavDirection) (granted bool), callback func (direction input.KeynavDirection) (granted bool),
) { ) {
element.onFocusMotionRequest = callback element.onFocusMotionRequest = callback
} }
func (element *Container) forFocused (callback func (child tomo.Focusable) bool) { func (element *Container) forFocused (callback func (child elements.Focusable) bool) {
for _, entry := range element.children { for _, entry := range element.children {
child, focusable := entry.Element.(tomo.Focusable) child, focusable := entry.Element.(elements.Focusable)
if focusable && child.Focused() { if focusable && child.Focused() {
if !callback(child) { break } if !callback(child) { break }
} }
} }
} }
func (element *Container) forFocusable (callback func (child tomo.Focusable) bool) { func (element *Container) forFocusable (callback func (child elements.Focusable) bool) {
for _, entry := range element.children { for _, entry := range element.children {
child, focusable := entry.Element.(tomo.Focusable) child, focusable := entry.Element.(elements.Focusable)
if focusable { if focusable {
if !callback(child) { break } if !callback(child) { break }
} }
} }
} }
func (element *Container) forFlexible (callback func (child tomo.Flexible) bool) { func (element *Container) forFlexible (callback func (child elements.Flexible) bool) {
for _, entry := range element.children { for _, entry := range element.children {
child, flexible := entry.Element.(tomo.Flexible) child, flexible := entry.Element.(elements.Flexible)
if flexible { if flexible {
if !callback(child) { break } if !callback(child) { break }
} }
} }
} }
func (element *Container) forFocusableBackward (callback func (child tomo.Focusable) bool) { func (element *Container) forFocusableBackward (callback func (child elements.Focusable) bool) {
for index := len(element.children) - 1; index >= 0; index -- { for index := len(element.children) - 1; index >= 0; index -- {
child, focusable := element.children[index].Element.(tomo.Focusable) child, focusable := element.children[index].Element.(elements.Focusable)
if focusable { if focusable {
if !callback(child) { break } if !callback(child) { break }
} }
@ -421,7 +426,7 @@ func (element *Container) forFocusableBackward (callback func (child tomo.Focusa
func (element *Container) firstFocused () (index int) { func (element *Container) firstFocused () (index int) {
for currentIndex, entry := range element.children { for currentIndex, entry := range element.children {
child, focusable := entry.Element.(tomo.Focusable) child, focusable := entry.Element.(elements.Focusable)
if focusable && child.Focused() { if focusable && child.Focused() {
return currentIndex return currentIndex
} }
@ -431,12 +436,12 @@ func (element *Container) firstFocused () (index int) {
func (element *Container) reflectChildProperties () { func (element *Container) reflectChildProperties () {
element.focusable = false element.focusable = false
element.forFocusable (func (tomo.Focusable) bool { element.forFocusable (func (elements.Focusable) bool {
element.focusable = true element.focusable = true
return false return false
}) })
element.flexible = false element.flexible = false
element.forFlexible (func (tomo.Flexible) bool { element.forFlexible (func (elements.Flexible) bool {
element.flexible = true element.flexible = true
return false return false
}) })
@ -446,16 +451,16 @@ func (element *Container) reflectChildProperties () {
} }
func (element *Container) childFocusRequestCallback ( func (element *Container) childFocusRequestCallback (
child tomo.Focusable, child elements.Focusable,
) ( ) (
granted bool, granted bool,
) { ) {
if element.onFocusRequest != nil && element.onFocusRequest() { if element.onFocusRequest != nil && element.onFocusRequest() {
element.forFocused (func (child tomo.Focusable) bool { element.forFocused (func (child elements.Focusable) bool {
child.HandleUnfocus() child.HandleUnfocus()
return true return true
}) })
child.HandleFocus(tomo.KeynavDirectionNeutral) child.HandleFocus(input.KeynavDirectionNeutral)
return true return true
} else { } else {
return false return false
@ -463,13 +468,16 @@ func (element *Container) childFocusRequestCallback (
} }
func (element *Container) updateMinimumSize () { func (element *Container) updateMinimumSize () {
width, height := element.layout.MinimumSize(element.children) width, height := element.layout.MinimumSize (
element.children, theme.Margin())
if element.flexible { if element.flexible {
height = element.layout.FlexibleHeightFor(element.children, width) height = element.layout.FlexibleHeightFor (
element.children, theme.Margin(), width)
} }
element.core.SetMinimumSize(width, height) element.core.SetMinimumSize(width, height)
} }
func (element *Container) recalculate () { func (element *Container) recalculate () {
element.layout.Arrange(element.children, element.Bounds()) element.layout.Arrange (
element.children, theme.Margin(), element.Bounds())
} }

View File

@ -1,4 +1,4 @@
package basic package basicElements
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"

View File

@ -1,9 +1,10 @@
package basic package basicElements
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/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
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/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
@ -73,10 +74,10 @@ func (element *List) Collapse (width, height int) {
element.updateMinimumSize() element.updateMinimumSize()
} }
func (element *List) HandleMouseDown (x, y int, button tomo.Button) { func (element *List) HandleMouseDown (x, y int, button input.Button) {
if !element.Enabled() { return } if !element.Enabled() { return }
if !element.Focused() { element.Focus() } if !element.Focused() { element.Focus() }
if button != tomo.ButtonLeft { return } if button != input.ButtonLeft { return }
element.pressed = true element.pressed = true
if element.selectUnderMouse(x, y) && element.core.HasImage() { if element.selectUnderMouse(x, y) && element.core.HasImage() {
element.draw() element.draw()
@ -84,8 +85,8 @@ func (element *List) HandleMouseDown (x, y int, button tomo.Button) {
} }
} }
func (element *List) HandleMouseUp (x, y int, button tomo.Button) { func (element *List) HandleMouseUp (x, y int, button input.Button) {
if button != tomo.ButtonLeft { return } if button != input.ButtonLeft { return }
element.pressed = false element.pressed = false
} }
@ -100,18 +101,18 @@ func (element *List) HandleMouseMove (x, y int) {
func (element *List) HandleMouseScroll (x, y int, deltaX, deltaY float64) { } func (element *List) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
func (element *List) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) { func (element *List) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
if !element.Enabled() { return } if !element.Enabled() { return }
altered := false altered := false
switch key { switch key {
case tomo.KeyLeft, tomo.KeyUp: case input.KeyLeft, input.KeyUp:
altered = element.changeSelectionBy(-1) altered = element.changeSelectionBy(-1)
case tomo.KeyRight, tomo.KeyDown: case input.KeyRight, input.KeyDown:
altered = element.changeSelectionBy(1) altered = element.changeSelectionBy(1)
case tomo.KeyEscape: case input.KeyEscape:
altered = element.selectEntry(-1) altered = element.selectEntry(-1)
} }
@ -121,7 +122,7 @@ func (element *List) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
} }
} }
func (element *List) HandleKeyUp(key tomo.Key, modifiers tomo.Modifiers) { } func (element *List) HandleKeyUp(key input.Key, modifiers input.Modifiers) { }
// ScrollContentBounds returns the full content size of the element. // ScrollContentBounds returns the full content size of the element.
func (element *List) ScrollContentBounds () (bounds image.Rectangle) { func (element *List) ScrollContentBounds () (bounds image.Rectangle) {
@ -383,7 +384,7 @@ func (element *List) draw () {
bounds.Min.X, bounds.Min.X,
bounds.Min.Y - element.scroll, bounds.Min.Y - element.scroll,
} }
innerCanvas := tomo.Cut(element, bounds) innerCanvas := canvas.Cut(element, bounds)
for index, entry := range element.entries { for index, entry := range element.entries {
entryPosition := dot entryPosition := dot
dot.Y += entry.Bounds().Dy() dot.Y += entry.Bounds().Dy()

View File

@ -1,8 +1,8 @@
package basic package basicElements
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/canvas"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
var listEntryCase = theme.C("basic", "listEntry") var listEntryCase = theme.C("basic", "listEntry")
@ -53,7 +53,7 @@ func (entry *ListEntry) updateBounds () {
} }
func (entry *ListEntry) Draw ( func (entry *ListEntry) Draw (
destination tomo.Canvas, destination canvas.Canvas,
offset image.Point, offset image.Point,
focused bool, focused bool,
on bool, on bool,

View File

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

View File

@ -1,9 +1,11 @@
package basic package basicElements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo" 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/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"
var scrollContainerCase = theme.C("basic", "scrollContainer") var scrollContainerCase = theme.C("basic", "scrollContainer")
@ -17,7 +19,7 @@ type ScrollContainer struct {
core core.CoreControl core core.CoreControl
focused bool focused bool
child tomo.Scrollable child elements.Scrollable
childWidth, childHeight int childWidth, childHeight int
horizontal struct { horizontal struct {
@ -41,7 +43,7 @@ type ScrollContainer struct {
} }
onFocusRequest func () (granted bool) onFocusRequest func () (granted bool)
onFocusMotionRequest func (tomo.KeynavDirection) (granted bool) onFocusMotionRequest func (input.KeynavDirection) (granted bool)
} }
// NewScrollContainer creates a new scroll container with the specified scroll // NewScrollContainer creates a new scroll container with the specified scroll
@ -64,7 +66,7 @@ func (element *ScrollContainer) handleResize () {
// 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 tomo.Scrollable) { func (element *ScrollContainer) Adopt (child elements.Scrollable) {
// disown previous child if it exists // disown previous child if it exists
if element.child != nil { if element.child != nil {
element.clearChildEventHandlers(child) element.clearChildEventHandlers(child)
@ -76,7 +78,7 @@ func (element *ScrollContainer) Adopt (child tomo.Scrollable) {
child.OnDamage(element.childDamageCallback) child.OnDamage(element.childDamageCallback)
child.OnMinimumSizeChange(element.updateMinimumSize) child.OnMinimumSizeChange(element.updateMinimumSize)
child.OnScrollBoundsChange(element.childScrollBoundsChangeCallback) child.OnScrollBoundsChange(element.childScrollBoundsChangeCallback)
if newChild, ok := child.(tomo.Focusable); ok { if newChild, ok := child.(elements.Focusable); ok {
newChild.OnFocusRequest ( newChild.OnFocusRequest (
element.childFocusRequestCallback) element.childFocusRequestCallback)
newChild.OnFocusMotionRequest ( newChild.OnFocusMotionRequest (
@ -96,19 +98,19 @@ func (element *ScrollContainer) Adopt (child tomo.Scrollable) {
} }
} }
func (element *ScrollContainer) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) { func (element *ScrollContainer) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
if child, ok := element.child.(tomo.KeyboardTarget); ok { if child, ok := element.child.(elements.KeyboardTarget); ok {
child.HandleKeyDown(key, modifiers) child.HandleKeyDown(key, modifiers)
} }
} }
func (element *ScrollContainer) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) { func (element *ScrollContainer) HandleKeyUp (key input.Key, modifiers input.Modifiers) {
if child, ok := element.child.(tomo.KeyboardTarget); ok { if child, ok := element.child.(elements.KeyboardTarget); ok {
child.HandleKeyUp(key, modifiers) child.HandleKeyUp(key, modifiers)
} }
} }
func (element *ScrollContainer) HandleMouseDown (x, y int, button tomo.Button) { func (element *ScrollContainer) HandleMouseDown (x, y int, button input.Button) {
point := image.Pt(x, y) point := image.Pt(x, y)
if point.In(element.horizontal.bar) { if point.In(element.horizontal.bar) {
element.horizontal.dragging = true element.horizontal.dragging = true
@ -140,12 +142,12 @@ func (element *ScrollContainer) HandleMouseDown (x, y int, button tomo.Button) {
element.scrollChildBy(0, -16) element.scrollChildBy(0, -16)
} }
} else if child, ok := element.child.(tomo.MouseTarget); ok { } else if child, ok := element.child.(elements.MouseTarget); ok {
child.HandleMouseDown(x, y, button) child.HandleMouseDown(x, y, button)
} }
} }
func (element *ScrollContainer) HandleMouseUp (x, y int, button tomo.Button) { func (element *ScrollContainer) HandleMouseUp (x, y int, button input.Button) {
if element.horizontal.dragging { if element.horizontal.dragging {
element.horizontal.dragging = false element.horizontal.dragging = false
element.drawHorizontalBar() element.drawHorizontalBar()
@ -156,7 +158,7 @@ func (element *ScrollContainer) HandleMouseUp (x, y int, button tomo.Button) {
element.drawVerticalBar() element.drawVerticalBar()
element.core.DamageRegion(element.vertical.bar) element.core.DamageRegion(element.vertical.bar)
} else if child, ok := element.child.(tomo.MouseTarget); ok { } else if child, ok := element.child.(elements.MouseTarget); ok {
child.HandleMouseUp(x, y, button) child.HandleMouseUp(x, y, button)
} }
} }
@ -168,7 +170,7 @@ func (element *ScrollContainer) HandleMouseMove (x, y int) {
} else if element.vertical.dragging { } else if element.vertical.dragging {
element.dragVerticalBar(image.Pt(x, y)) element.dragVerticalBar(image.Pt(x, y))
} else if child, ok := element.child.(tomo.MouseTarget); ok { } else if child, ok := element.child.(elements.MouseTarget); ok {
child.HandleMouseMove(x, y) child.HandleMouseMove(x, y)
} }
} }
@ -199,11 +201,11 @@ func (element *ScrollContainer) Focus () {
} }
func (element *ScrollContainer) HandleFocus ( func (element *ScrollContainer) HandleFocus (
direction tomo.KeynavDirection, direction input.KeynavDirection,
) ( ) (
accepted bool, accepted bool,
) { ) {
if child, ok := element.child.(tomo.Focusable); ok { if child, ok := element.child.(elements.Focusable); ok {
element.focused = true element.focused = true
return child.HandleFocus(direction) return child.HandleFocus(direction)
} else { } else {
@ -213,7 +215,7 @@ func (element *ScrollContainer) HandleFocus (
} }
func (element *ScrollContainer) HandleUnfocus () { func (element *ScrollContainer) HandleUnfocus () {
if child, ok := element.child.(tomo.Focusable); ok { if child, ok := element.child.(elements.Focusable); ok {
child.HandleUnfocus() child.HandleUnfocus()
} }
element.focused = false element.focused = false
@ -224,20 +226,20 @@ func (element *ScrollContainer) OnFocusRequest (callback func () (granted bool))
} }
func (element *ScrollContainer) OnFocusMotionRequest ( func (element *ScrollContainer) OnFocusMotionRequest (
callback func (direction tomo.KeynavDirection) (granted bool), callback func (direction input.KeynavDirection) (granted bool),
) { ) {
element.onFocusMotionRequest = callback element.onFocusMotionRequest = callback
} }
func (element *ScrollContainer) childDamageCallback (region tomo.Canvas) { func (element *ScrollContainer) childDamageCallback (region canvas.Canvas) {
element.core.DamageRegion(artist.Paste(element, region, image.Point { })) element.core.DamageRegion(artist.Paste(element, region, image.Point { }))
} }
func (element *ScrollContainer) childFocusRequestCallback () (granted bool) { func (element *ScrollContainer) childFocusRequestCallback () (granted bool) {
child, ok := element.child.(tomo.Focusable) child, ok := element.child.(elements.Focusable)
if !ok { return false } if !ok { return false }
if element.onFocusRequest != nil && element.onFocusRequest() { if element.onFocusRequest != nil && element.onFocusRequest() {
child.HandleFocus(tomo.KeynavDirectionNeutral) child.HandleFocus(input.KeynavDirectionNeutral)
return true return true
} else { } else {
return false return false
@ -245,7 +247,7 @@ func (element *ScrollContainer) childFocusRequestCallback () (granted bool) {
} }
func (element *ScrollContainer) childFocusMotionRequestCallback ( func (element *ScrollContainer) childFocusMotionRequestCallback (
direction tomo.KeynavDirection, direction input.KeynavDirection,
) ( ) (
granted bool, granted bool,
) { ) {
@ -253,19 +255,19 @@ func (element *ScrollContainer) childFocusMotionRequestCallback (
return element.onFocusMotionRequest(direction) return element.onFocusMotionRequest(direction)
} }
func (element *ScrollContainer) clearChildEventHandlers (child tomo.Scrollable) { func (element *ScrollContainer) clearChildEventHandlers (child elements.Scrollable) {
child.DrawTo(nil) child.DrawTo(nil)
child.OnDamage(nil) child.OnDamage(nil)
child.OnMinimumSizeChange(nil) child.OnMinimumSizeChange(nil)
child.OnScrollBoundsChange(nil) child.OnScrollBoundsChange(nil)
if child0, ok := child.(tomo.Focusable); ok { if child0, ok := child.(elements.Focusable); ok {
child0.OnFocusRequest(nil) child0.OnFocusRequest(nil)
child0.OnFocusMotionRequest(nil) child0.OnFocusMotionRequest(nil)
if child0.Focused() { if child0.Focused() {
child0.HandleUnfocus() child0.HandleUnfocus()
} }
} }
if child0, ok := child.(tomo.Flexible); ok { if child0, ok := child.(elements.Flexible); ok {
child0.OnFlexibleHeightChange(nil) child0.OnFlexibleHeightChange(nil)
} }
} }
@ -275,7 +277,7 @@ func (element *ScrollContainer) resizeChildToFit () {
0, 0, 0, 0,
element.childWidth, element.childWidth,
element.childHeight).Add(element.Bounds().Min) element.childHeight).Add(element.Bounds().Min)
element.child.DrawTo(tomo.Cut(element, childBounds)) element.child.DrawTo(canvas.Cut(element, childBounds))
} }
func (element *ScrollContainer) recalculate () { func (element *ScrollContainer) recalculate () {

View File

@ -1,4 +1,4 @@
package basic package basicElements
import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"

View File

@ -1,7 +1,7 @@
package basic package basicElements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo" 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/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/elements/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
@ -41,7 +41,7 @@ func NewSwitch (text string, on bool) (element *Switch) {
return return
} }
func (element *Switch) HandleMouseDown (x, y int, button tomo.Button) { func (element *Switch) HandleMouseDown (x, y int, button input.Button) {
if !element.Enabled() { return } if !element.Enabled() { return }
element.Focus() element.Focus()
element.pressed = true element.pressed = true
@ -51,8 +51,8 @@ func (element *Switch) HandleMouseDown (x, y int, button tomo.Button) {
} }
} }
func (element *Switch) HandleMouseUp (x, y int, button tomo.Button) { func (element *Switch) HandleMouseUp (x, y int, button input.Button) {
if button != tomo.ButtonLeft || !element.pressed { return } if button != input.ButtonLeft || !element.pressed { return }
element.pressed = false element.pressed = false
within := image.Point { x, y }. within := image.Point { x, y }.
@ -73,8 +73,8 @@ func (element *Switch) HandleMouseUp (x, y int, button tomo.Button) {
func (element *Switch) HandleMouseMove (x, y int) { } func (element *Switch) HandleMouseMove (x, y int) { }
func (element *Switch) HandleMouseScroll (x, y int, deltaX, deltaY float64) { } func (element *Switch) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
func (element *Switch) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) { func (element *Switch) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
if key == tomo.KeyEnter { if key == input.KeyEnter {
element.pressed = true element.pressed = true
if element.core.HasImage() { if element.core.HasImage() {
element.draw() element.draw()
@ -83,8 +83,8 @@ func (element *Switch) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
} }
} }
func (element *Switch) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) { func (element *Switch) HandleKeyUp (key input.Key, modifiers input.Modifiers) {
if key == tomo.KeyEnter && element.pressed { if key == input.KeyEnter && element.pressed {
element.pressed = false element.pressed = false
element.checked = !element.checked element.checked = !element.checked
if element.core.HasImage() { if element.core.HasImage() {

View File

@ -1,7 +1,7 @@
package basic package basicElements
import "image" import "image"
import "git.tebibyte.media/sashakoshka/tomo" 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/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/textmanip" import "git.tebibyte.media/sashakoshka/tomo/textmanip"
@ -24,7 +24,7 @@ type TextBox struct {
placeholderDrawer artist.TextDrawer placeholderDrawer artist.TextDrawer
valueDrawer artist.TextDrawer valueDrawer artist.TextDrawer
onKeyDown func (key tomo.Key, modifiers tomo.Modifiers) (handled bool) onKeyDown func (key input.Key, modifiers input.Modifiers) (handled bool)
onChange func () onChange func ()
onScrollBoundsChange func () onScrollBoundsChange func ()
} }
@ -59,16 +59,16 @@ func (element *TextBox) handleResize () {
} }
} }
func (element *TextBox) HandleMouseDown (x, y int, button tomo.Button) { func (element *TextBox) HandleMouseDown (x, y int, button input.Button) {
if !element.Enabled() { return } if !element.Enabled() { return }
if !element.Focused() { element.Focus() } if !element.Focused() { element.Focus() }
} }
func (element *TextBox) HandleMouseUp (x, y int, button tomo.Button) { } func (element *TextBox) HandleMouseUp (x, y int, button input.Button) { }
func (element *TextBox) HandleMouseMove (x, y int) { } func (element *TextBox) HandleMouseMove (x, y int) { }
func (element *TextBox) HandleMouseScroll (x, y int, deltaX, deltaY float64) { } func (element *TextBox) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
func (element *TextBox) HandleKeyDown(key tomo.Key, modifiers tomo.Modifiers) { func (element *TextBox) HandleKeyDown(key input.Key, modifiers input.Modifiers) {
if element.onKeyDown != nil && element.onKeyDown(key, modifiers) { if element.onKeyDown != nil && element.onKeyDown(key, modifiers) {
return return
} }
@ -77,7 +77,7 @@ func (element *TextBox) HandleKeyDown(key tomo.Key, modifiers tomo.Modifiers) {
altered := true altered := true
textChanged := false textChanged := false
switch { switch {
case key == tomo.KeyBackspace: case key == input.KeyBackspace:
if len(element.text) < 1 { break } if len(element.text) < 1 { break }
element.text, element.cursor = textmanip.Backspace ( element.text, element.cursor = textmanip.Backspace (
element.text, element.text,
@ -85,7 +85,7 @@ func (element *TextBox) HandleKeyDown(key tomo.Key, modifiers tomo.Modifiers) {
modifiers.Control) modifiers.Control)
textChanged = true textChanged = true
case key == tomo.KeyDelete: case key == input.KeyDelete:
if len(element.text) < 1 { break } if len(element.text) < 1 { break }
element.text, element.cursor = textmanip.Delete ( element.text, element.cursor = textmanip.Delete (
element.text, element.text,
@ -93,13 +93,13 @@ func (element *TextBox) HandleKeyDown(key tomo.Key, modifiers tomo.Modifiers) {
modifiers.Control) modifiers.Control)
textChanged = true textChanged = true
case key == tomo.KeyLeft: case key == input.KeyLeft:
element.cursor = textmanip.MoveLeft ( element.cursor = textmanip.MoveLeft (
element.text, element.text,
element.cursor, element.cursor,
modifiers.Control) modifiers.Control)
case key == tomo.KeyRight: case key == input.KeyRight:
element.cursor = textmanip.MoveRight ( element.cursor = textmanip.MoveRight (
element.text, element.text,
element.cursor, element.cursor,
@ -136,7 +136,7 @@ func (element *TextBox) HandleKeyDown(key tomo.Key, modifiers tomo.Modifiers) {
} }
} }
func (element *TextBox) HandleKeyUp(key tomo.Key, modifiers tomo.Modifiers) { } func (element *TextBox) HandleKeyUp(key input.Key, modifiers input.Modifiers) { }
func (element *TextBox) SetPlaceholder (placeholder string) { func (element *TextBox) SetPlaceholder (placeholder string) {
if element.placeholder == placeholder { return } if element.placeholder == placeholder { return }
@ -177,7 +177,7 @@ func (element *TextBox) Filled () (filled bool) {
} }
func (element *TextBox) OnKeyDown ( func (element *TextBox) OnKeyDown (
callback func (key tomo.Key, modifiers tomo.Modifiers) (handled bool), callback func (key input.Key, modifiers input.Modifiers) (handled bool),
) { ) {
element.onKeyDown = callback element.onKeyDown = callback
} }

View File

@ -2,12 +2,12 @@ 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"
// 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 tomo.Canvas canvas canvas.Canvas
metrics struct { metrics struct {
minimumWidth int minimumWidth int
@ -16,7 +16,7 @@ type Core struct {
drawSizeChange func () drawSizeChange func ()
onMinimumSizeChange func () onMinimumSizeChange func ()
onDamage func (region tomo.Canvas) onDamage func (region canvas.Canvas)
} }
// NewCore creates a new element core and its corresponding control. // NewCore creates a new element core and its corresponding control.
@ -49,7 +49,7 @@ func (core *Core) Set (x, y int, c color.Color) () {
core.canvas.Set(x, y, c) core.canvas.Set(x, y, c)
} }
// Buffer fulfills the tomo.Canvas interface. // Buffer fulfills the canvas.Canvas interface.
func (core *Core) Buffer () (data []color.RGBA, stride int) { func (core *Core) Buffer () (data []color.RGBA, stride int) {
if core.canvas == nil { return } if core.canvas == nil { return }
return core.canvas.Buffer() return core.canvas.Buffer()
@ -63,7 +63,7 @@ func (core *Core) MinimumSize () (width, height int) {
// DrawTo fulfills the tomo.Element interface. This should not need to be // DrawTo fulfills the tomo.Element interface. This should not need to be
// overridden. // overridden.
func (core *Core) DrawTo (canvas tomo.Canvas) { func (core *Core) DrawTo (canvas canvas.Canvas) {
core.canvas = canvas core.canvas = canvas
if core.drawSizeChange != nil { if core.drawSizeChange != nil {
core.drawSizeChange() core.drawSizeChange()
@ -72,7 +72,7 @@ func (core *Core) DrawTo (canvas tomo.Canvas) {
// OnDamage fulfils the tomo.Element interface. This should not need to be // OnDamage fulfils the tomo.Element interface. This should not need to be
// overridden. // overridden.
func (core *Core) OnDamage (callback func (region tomo.Canvas)) { func (core *Core) OnDamage (callback func (region canvas.Canvas)) {
core.onDamage = callback core.onDamage = callback
} }
@ -100,7 +100,7 @@ func (control CoreControl) HasImage () (has bool) {
// does not need to be called when responding to a resize event. // does not need to be called when responding to a resize event.
func (control CoreControl) DamageRegion (bounds image.Rectangle) { func (control CoreControl) DamageRegion (bounds image.Rectangle) {
if control.core.onDamage != nil { if control.core.onDamage != nil {
control.core.onDamage(tomo.Cut(control.core, bounds)) control.core.onDamage(canvas.Cut(control.core, bounds))
} }
} }

View File

@ -1,6 +1,6 @@
package core package core
import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo/input"
// 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.
@ -9,7 +9,7 @@ type FocusableCore struct {
enabled bool enabled bool
drawFocusChange func () drawFocusChange func ()
onFocusRequest func () (granted bool) onFocusRequest func () (granted bool)
onFocusMotionRequest func(tomo.KeynavDirection) (granted bool) onFocusMotionRequest func(input.KeynavDirection) (granted bool)
} }
// NewFocusableCore creates a new focusability core and its corresponding // NewFocusableCore creates a new focusability core and its corresponding
@ -46,13 +46,13 @@ func (core *FocusableCore) Focus () {
// HandleFocus causes this element to mark itself as focused, if it can // HandleFocus causes this element to mark itself as focused, if it can
// currently be. Otherwise, it will return false and do nothing. // currently be. Otherwise, it will return false and do nothing.
func (core *FocusableCore) HandleFocus ( func (core *FocusableCore) HandleFocus (
direction tomo.KeynavDirection, direction input.KeynavDirection,
) ( ) (
accepted bool, accepted bool,
) { ) {
direction = direction.Canon() direction = direction.Canon()
if !core.enabled { return false } if !core.enabled { return false }
if core.focused && direction != tomo.KeynavDirectionNeutral { if core.focused && direction != input.KeynavDirectionNeutral {
return false return false
} }
@ -80,7 +80,7 @@ func (core *FocusableCore) OnFocusRequest (callback func () (granted bool)) {
// should return true if the request was granted, and false if it was // should return true if the request was granted, and false if it was
// not. // not.
func (core *FocusableCore) OnFocusMotionRequest ( func (core *FocusableCore) OnFocusMotionRequest (
callback func (direction tomo.KeynavDirection) (granted bool), callback func (direction input.KeynavDirection) (granted bool),
) { ) {
core.onFocusMotionRequest = callback core.onFocusMotionRequest = callback
} }

View File

@ -2,7 +2,7 @@ package testing
import "image" import "image"
import "image/color" import "image/color"
import "git.tebibyte.media/sashakoshka/tomo" 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/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/elements/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
@ -44,12 +44,12 @@ func (element *Mouse) draw () {
bounds.Min.Add(image.Pt(bounds.Dx() - 2, 1))) bounds.Min.Add(image.Pt(bounds.Dx() - 2, 1)))
} }
func (element *Mouse) HandleMouseDown (x, y int, button tomo.Button) { func (element *Mouse) HandleMouseDown (x, y int, button input.Button) {
element.drawing = true element.drawing = true
element.lastMousePos = image.Pt(x, y) element.lastMousePos = image.Pt(x, y)
} }
func (element *Mouse) HandleMouseUp (x, y int, button tomo.Button) { func (element *Mouse) HandleMouseUp (x, y int, button input.Button) {
element.drawing = false element.drawing = false
mousePos := image.Pt(x, y) mousePos := image.Pt(x, y)
element.core.DamageRegion (artist.Line ( element.core.DamageRegion (artist.Line (

View File

@ -11,7 +11,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 := basic.NewButton("hello tomo!") button := basicElements.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,7 +2,7 @@ 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/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -14,22 +14,22 @@ func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Checkboxes") window.SetTitle("Checkboxes")
container := basic.NewContainer(layouts.Vertical { true, true }) container := basicElements.NewContainer(basicLayouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt (basic.NewLabel ( container.Adopt (basicElements.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), true) "me to communicate.", true), true)
container.Adopt(basic.NewSpacer(true), false) container.Adopt(basicElements.NewSpacer(true), false)
container.Adopt(basic.NewCheckbox("Oh god", false), false) container.Adopt(basicElements.NewCheckbox("Oh god", false), false)
container.Adopt(basic.NewCheckbox("Can you hear them", true), false) container.Adopt(basicElements.NewCheckbox("Can you hear them", true), false)
container.Adopt(basic.NewCheckbox("They are in the walls", false), false) container.Adopt(basicElements.NewCheckbox("They are in the walls", false), false)
container.Adopt(basic.NewCheckbox("They are coming for us", false), false) container.Adopt(basicElements.NewCheckbox("They are coming for us", false), false)
disabledCheckbox := basic.NewCheckbox("We are but their helpless prey", false) disabledCheckbox := basicElements.NewCheckbox("We are but their helpless prey", false)
disabledCheckbox.SetEnabled(false) disabledCheckbox.SetEnabled(false)
container.Adopt(disabledCheckbox, false) container.Adopt(disabledCheckbox, false)
vsync := basic.NewCheckbox("Enable vsync", false) vsync := basicElements.NewCheckbox("Enable vsync", false)
vsync.OnToggle (func () { vsync.OnToggle (func () {
if vsync.Value() { if vsync.Value() {
popups.NewDialog ( popups.NewDialog (
@ -39,7 +39,7 @@ func run () {
} }
}) })
container.Adopt(vsync, false) container.Adopt(vsync, false)
button := basic.NewButton("What") button := basicElements.NewButton("What")
button.OnClick(tomo.Stop) button.OnClick(tomo.Stop)
container.Adopt(button, false) container.Adopt(button, false)
button.Focus() button.Focus()

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/layouts" import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -13,14 +13,14 @@ func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("dialog") window.SetTitle("dialog")
container := basic.NewContainer(layouts.Dialog { true, true }) container := basicElements.NewContainer(basicLayouts.Dialog { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basic.NewLabel("you will explode", true), true) container.Adopt(basicElements.NewLabel("you will explode", true), true)
cancel := basic.NewButton("Cancel") cancel := basicElements.NewButton("Cancel")
cancel.SetEnabled(false) cancel.SetEnabled(false)
container.Adopt(cancel, false) container.Adopt(cancel, false)
okButton := basic.NewButton("OK") okButton := basicElements.NewButton("OK")
container.Adopt(okButton, false) container.Adopt(okButton, false)
okButton.Focus() okButton.Focus()

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/flow" import "git.tebibyte.media/sashakoshka/tomo/flow"
import "git.tebibyte.media/sashakoshka/tomo/layouts" import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -13,21 +13,21 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("adventure") window.SetTitle("adventure")
container := basic.NewContainer(layouts.Vertical { true, true }) container := basicElements.NewContainer(basicLayouts.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 := basic.NewLabel ( label := basicElements.NewLabel (
"you are standing next to a river.", true) "you are standing next to a river.", true)
button0 := basic.NewButton("go in the river") button0 := basicElements.NewButton("go in the river")
button0.OnClick(world.SwitchFunc("wet")) button0.OnClick(world.SwitchFunc("wet"))
button1 := basic.NewButton("walk along the river") button1 := basicElements.NewButton("walk along the river")
button1.OnClick(world.SwitchFunc("house")) button1.OnClick(world.SwitchFunc("house"))
button2 := basic.NewButton("turn around") button2 := basicElements.NewButton("turn around")
button2.OnClick(world.SwitchFunc("bear")) button2.OnClick(world.SwitchFunc("bear"))
container.Warp ( func () { container.Warp ( func () {
@ -39,13 +39,13 @@ func run () {
}) })
}, },
"wet": func () { "wet": func () {
label := basic.NewLabel ( label := basicElements.NewLabel (
"you get completely soaked.\n" + "you get completely soaked.\n" +
"you die of hypothermia.", true) "you die of hypothermia.", true)
button0 := basic.NewButton("try again") button0 := basicElements.NewButton("try again")
button0.OnClick(world.SwitchFunc("start")) button0.OnClick(world.SwitchFunc("start"))
button1 := basic.NewButton("exit") button1 := basicElements.NewButton("exit")
button1.OnClick(tomo.Stop) button1.OnClick(tomo.Stop)
container.Warp (func () { container.Warp (func () {
@ -56,13 +56,13 @@ func run () {
}) })
}, },
"house": func () { "house": func () {
label := basic.NewLabel ( label := basicElements.NewLabel (
"you are standing in front of a delapidated " + "you are standing in front of a delapidated " +
"house.", true) "house.", true)
button1 := basic.NewButton("go inside") button1 := basicElements.NewButton("go inside")
button1.OnClick(world.SwitchFunc("inside")) button1.OnClick(world.SwitchFunc("inside"))
button0 := basic.NewButton("turn back") button0 := basicElements.NewButton("turn back")
button0.OnClick(world.SwitchFunc("start")) button0.OnClick(world.SwitchFunc("start"))
container.Warp (func () { container.Warp (func () {
@ -73,14 +73,14 @@ func run () {
}) })
}, },
"inside": func () { "inside": func () {
label := basic.NewLabel ( label := basicElements.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 := basic.NewButton("go back outside") button0 := basicElements.NewButton("go back outside")
button0.OnClick(world.SwitchFunc("house")) button0.OnClick(world.SwitchFunc("house"))
container.Warp (func () { container.Warp (func () {
@ -90,13 +90,13 @@ func run () {
}) })
}, },
"bear": func () { "bear": func () {
label := basic.NewLabel ( label := basicElements.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 := basic.NewButton("try again") button0 := basicElements.NewButton("try again")
button0.OnClick(world.SwitchFunc("start")) button0.OnClick(world.SwitchFunc("start"))
button1 := basic.NewButton("exit") button1 := basicElements.NewButton("exit")
button1.OnClick(tomo.Stop) button1.OnClick(tomo.Stop)
container.Warp (func () { container.Warp (func () {

View File

@ -3,7 +3,7 @@ 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/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/fun" import "git.tebibyte.media/sashakoshka/tomo/elements/fun"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -16,12 +16,12 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("clock") window.SetTitle("clock")
container := basic.NewContainer(layouts.Vertical { true, true }) container := basicElements.NewContainer(basicLayouts.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 := basic.NewLabel(formatTime(), false) label := basicElements.NewLabel(formatTime(), false)
container.Adopt(label, false) container.Adopt(label, false)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
@ -33,7 +33,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 *basic.Label, clock *fun.AnalogClock) { func tick (label *basicElements.Label, clock *fun.AnalogClock) {
for { for {
tomo.Do (func () { tomo.Do (func () {
label.SetText(formatTime()) label.SetText(formatTime())

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/layouts" import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -13,12 +13,12 @@ func run () {
window, _ := tomo.NewWindow(360, 2) window, _ := tomo.NewWindow(360, 2)
window.SetTitle("horizontal stack") window.SetTitle("horizontal stack")
container := basic.NewContainer(layouts.Horizontal { true, true }) container := basicElements.NewContainer(basicLayouts.Horizontal { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basic.NewLabel("this is sample text", true), true) container.Adopt(basicElements.NewLabel("this is sample text", true), true)
container.Adopt(basic.NewLabel("this is sample text", true), true) container.Adopt(basicElements.NewLabel("this is sample text", true), true)
container.Adopt(basic.NewLabel("this is sample text", true), true) container.Adopt(basicElements.NewLabel("this is sample text", true), true)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()

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/popups" import "git.tebibyte.media/sashakoshka/tomo/popups"
import "git.tebibyte.media/sashakoshka/tomo/layouts" import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -13,14 +13,14 @@ 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 := basic.NewContainer(layouts.Vertical { true, true }) container := basicElements.NewContainer(basicLayouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
// create inputs // create inputs
firstName := basic.NewTextBox("First name", "") firstName := basicElements.NewTextBox("First name", "")
lastName := basic.NewTextBox("Last name", "") lastName := basicElements.NewTextBox("Last name", "")
fingerLength := basic.NewTextBox("Length of fingers", "") fingerLength := basicElements.NewTextBox("Length of fingers", "")
button := basic.NewButton("Ok") button := basicElements.NewButton("Ok")
button.SetEnabled(false) button.SetEnabled(false)
button.OnClick (func () { button.OnClick (func () {
@ -45,11 +45,11 @@ func run () {
fingerLength.OnChange(check) fingerLength.OnChange(check)
// add elements to container // add elements to container
container.Adopt(basic.NewLabel("Choose your words carefully.", false), true) container.Adopt(basicElements.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(basic.NewSpacer(true), false) container.Adopt(basicElements.NewSpacer(true), false)
container.Adopt(button, false) container.Adopt(button, false)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)

View File

@ -11,7 +11,7 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(480, 2) window, _ := tomo.NewWindow(480, 2)
window.SetTitle("example label") window.SetTitle("example label")
window.Adopt(basic.NewLabel(text, true)) window.Adopt(basicElements.NewLabel(text, true))
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()
} }

View File

@ -2,7 +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/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/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/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -15,11 +16,11 @@ func run () {
window, _ := tomo.NewWindow(300, 2) window, _ := tomo.NewWindow(300, 2)
window.SetTitle("List Sidebar") window.SetTitle("List Sidebar")
container := basic.NewContainer(layouts.Horizontal { true, true }) container := basicElements.NewContainer(basicLayouts.Horizontal { true, true })
window.Adopt(container) window.Adopt(container)
var currentPage tomo.Element var currentPage elements.Element
turnPage := func (newPage tomo.Element) { turnPage := func (newPage elements.Element) {
container.Warp (func () { container.Warp (func () {
if currentPage != nil { if currentPage != nil {
container.Disown(currentPage) container.Disown(currentPage)
@ -29,27 +30,27 @@ func run () {
}) })
} }
intro := basic.NewLabel ( intro := basicElements.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 := basic.NewButton("I do nothing!") button := basicElements.NewButton("I do nothing!")
button.OnClick (func () { button.OnClick (func () {
popups.NewDialog(popups.DialogKindInfo, "", "Sike!") popups.NewDialog(popups.DialogKindInfo, "", "Sike!")
}) })
mouse := testing.NewMouse() mouse := testing.NewMouse()
input := basic.NewTextBox("Write some text", "") input := basicElements.NewTextBox("Write some text", "")
form := basic.NewContainer(layouts.Vertical { true, false}) form := basicElements.NewContainer(basicLayouts.Vertical { true, false})
form.Adopt(basic.NewLabel("I have:", false), false) form.Adopt(basicElements.NewLabel("I have:", false), false)
form.Adopt(basic.NewSpacer(true), false) form.Adopt(basicElements.NewSpacer(true), false)
form.Adopt(basic.NewCheckbox("Skin", true), false) form.Adopt(basicElements.NewCheckbox("Skin", true), false)
form.Adopt(basic.NewCheckbox("Blood", false), false) form.Adopt(basicElements.NewCheckbox("Blood", false), false)
form.Adopt(basic.NewCheckbox("Bone", false), false) form.Adopt(basicElements.NewCheckbox("Bone", false), false)
list := basic.NewList ( list := basicElements.NewList (
basic.NewListEntry("button", func () { turnPage(button) }), basicElements.NewListEntry("button", func () { turnPage(button) }),
basic.NewListEntry("mouse", func () { turnPage(mouse) }), basicElements.NewListEntry("mouse", func () { turnPage(mouse) }),
basic.NewListEntry("input", func () { turnPage(input) }), basicElements.NewListEntry("input", func () { turnPage(input) }),
basic.NewListEntry("form", func () { turnPage(form) })) basicElements.NewListEntry("form", func () { turnPage(form) }))
list.OnNoEntrySelected(func () { turnPage (intro) }) list.OnNoEntrySelected(func () { turnPage (intro) })
list.Collapse(96, 0) list.Collapse(96, 0)

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

View File

@ -3,7 +3,7 @@ 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" import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -14,14 +14,14 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Approaching") window.SetTitle("Approaching")
container := basic.NewContainer(layouts.Vertical { true, true }) container := basicElements.NewContainer(basicLayouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt (basic.NewLabel ( container.Adopt (basicElements.NewLabel (
"Rapidly approaching your location...", false), false) "Rapidly approaching your location...", false), false)
bar := basic.NewProgressBar(0) bar := basicElements.NewProgressBar(0)
container.Adopt(bar, false) container.Adopt(bar, false)
button := basic.NewButton("Stop") button := basicElements.NewButton("Stop")
button.SetEnabled(false) button.SetEnabled(false)
container.Adopt(button, false) container.Adopt(button, false)
@ -30,7 +30,7 @@ func run () {
go fill(bar) go fill(bar)
} }
func fill (bar *basic.ProgressBar) { func fill (bar *basicElements.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 () {

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/layouts" import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -12,13 +12,13 @@ func main () {
func run () { func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Scroll") window.SetTitle("Scroll")
container := basic.NewContainer(layouts.Vertical { true, true }) container := basicElements.NewContainer(basicLayouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basic.NewLabel("look at this non sense", false), false) container.Adopt(basicElements.NewLabel("look at this non sense", false), false)
textBox := basic.NewTextBox("", "sample text sample text") textBox := basicElements.NewTextBox("", "sample text sample text")
scrollContainer := basic.NewScrollContainer(true, false) scrollContainer := basicElements.NewScrollContainer(true, false)
scrollContainer.Adopt(textBox) scrollContainer.Adopt(textBox)
container.Adopt(scrollContainer, true) container.Adopt(scrollContainer, true)

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/layouts" import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -13,14 +13,14 @@ func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Spaced Out") window.SetTitle("Spaced Out")
container := basic.NewContainer(layouts.Vertical { true, true }) container := basicElements.NewContainer(basicLayouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt (basic.NewLabel("This is at the top", false), false) container.Adopt (basicElements.NewLabel("This is at the top", false), false)
container.Adopt (basic.NewSpacer(true), false) container.Adopt (basicElements.NewSpacer(true), false)
container.Adopt (basic.NewLabel("This is in the middle", false), false) container.Adopt (basicElements.NewLabel("This is in the middle", false), false)
container.Adopt (basic.NewSpacer(false), true) container.Adopt (basicElements.NewSpacer(false), true)
container.Adopt (basic.NewLabel("This is at the bottom", false), false) container.Adopt (basicElements.NewLabel("This is at the bottom", false), false)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()

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/layouts" import "git.tebibyte.media/sashakoshka/tomo/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
import _ "git.tebibyte.media/sashakoshka/tomo/backends/x" import _ "git.tebibyte.media/sashakoshka/tomo/backends/x"
@ -13,12 +13,12 @@ func run () {
window, _ := tomo.NewWindow(2, 2) window, _ := tomo.NewWindow(2, 2)
window.SetTitle("Switches") window.SetTitle("Switches")
container := basic.NewContainer(layouts.Vertical { true, true }) container := basicElements.NewContainer(basicLayouts.Vertical { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basic.NewSwitch("hahahah", false), false) container.Adopt(basicElements.NewSwitch("hahahah", false), false)
container.Adopt(basic.NewSwitch("hehehehheheh", false), false) container.Adopt(basicElements.NewSwitch("hehehehheheh", false), false)
container.Adopt(basic.NewSwitch("you can flick da swicth", false), false) container.Adopt(basicElements.NewSwitch("you can flick da swicth", false), false)
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()

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

112
input.go
View File

@ -1,112 +0,0 @@
package tomo
import "unicode"
// Key represents a keyboard key.
type Key int
const (
KeyNone Key = 0
KeyInsert Key = 1
KeyMenu Key = 2
KeyPrintScreen Key = 3
KeyPause Key = 4
KeyCapsLock Key = 5
KeyScrollLock Key = 6
KeyNumLock Key = 7
KeyBackspace Key = 8
KeyTab Key = 9
KeyEnter Key = 10
KeyEscape Key = 11
KeyUp Key = 12
KeyDown Key = 13
KeyLeft Key = 14
KeyRight Key = 15
KeyPageUp Key = 16
KeyPageDown Key = 17
KeyHome Key = 18
KeyEnd Key = 19
KeyLeftShift Key = 20
KeyRightShift Key = 21
KeyLeftControl Key = 22
KeyRightControl Key = 23
KeyLeftAlt Key = 24
KeyRightAlt Key = 25
KeyLeftMeta Key = 26
KeyRightMeta Key = 27
KeyLeftSuper Key = 28
KeyRightSuper Key = 29
KeyLeftHyper Key = 30
KeyRightHyper Key = 31
KeyDelete Key = 127
KeyDead Key = 128
KeyF1 Key = 129
KeyF2 Key = 130
KeyF3 Key = 131
KeyF4 Key = 132
KeyF5 Key = 133
KeyF6 Key = 134
KeyF7 Key = 135
KeyF8 Key = 136
KeyF9 Key = 137
KeyF10 Key = 138
KeyF11 Key = 139
KeyF12 Key = 140
)
// Button represents a mouse button.
type Button int
const (
ButtonNone Button = iota
Button1
Button2
Button3
Button4
Button5
Button6
Button7
Button8
Button9
ButtonLeft Button = Button1
ButtonMiddle Button = Button2
ButtonRight Button = Button3
ButtonBack Button = Button8
ButtonForward Button = Button9
)
// Printable returns whether or not the key's character could show up on screen.
// If this function returns true, the key can be cast to a rune and used as
// such.
func (key Key) Printable () (printable bool) {
printable = unicode.IsPrint(rune(key))
return
}
// Modifiers lists what modifier keys are being pressed. This is used in
// conjunction with a Key code in a Key press event. These should be used
// instead of attempting to track the state of the modifier keys, because there
// is no guarantee that one press event will be coupled with one release event.
type Modifiers struct {
Shift bool
Control bool
Alt bool
Meta bool
Super bool
Hyper bool
// NumberPad does not represent a key, but it behaves like one. If it is
// set to true, the Key was pressed on the number pad. It is treated
// as a modifier key because if you don't care whether a key was pressed
// on the number pad or not, you can just ignore this value.
NumberPad bool
}

View File

@ -1,30 +0,0 @@
package tomo
import "image"
// LayoutEntry associates an element with layout and positioning information so
// it can be arranged by a Layout.
type LayoutEntry struct {
Element
Bounds image.Rectangle
Expand bool
}
// Layout is capable of arranging elements within a container. It is also able
// to determine the minimum amount of room it needs to do so.
type Layout interface {
// Arrange takes in a slice of entries and a bounding width and height,
// and changes the position of the entiries in the slice so that they
// are properly laid out. The given width and height should not be less
// than what is returned by MinimumSize.
Arrange (entries []LayoutEntry, bounds image.Rectangle)
// MinimumSize returns the minimum width and height that the layout
// needs to properly arrange the given slice of layout entries.
MinimumSize (entries []LayoutEntry) (width, height int)
// FlexibleHeightFor Returns the minimum height the layout needs to lay
// out the specified elements at the given width, taking into account
// flexible elements.
FlexibleHeightFor (entries []LayoutEntry, squeeze int) (height int)
}

View File

@ -1,7 +1,8 @@
package popups package popups
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/layouts/basic"
import "git.tebibyte.media/sashakoshka/tomo/elements/basic" import "git.tebibyte.media/sashakoshka/tomo/elements/basic"
// DialogKind defines the semantic role of a dialog window. // DialogKind defines the semantic role of a dialog window.
@ -30,24 +31,24 @@ func NewDialog (
title, message string, title, message string,
buttons ...Button, buttons ...Button,
) ( ) (
window tomo.Window, window elements.Window,
) { ) {
window, _ = tomo.NewWindow(2, 2) window, _ = tomo.NewWindow(2, 2)
window.SetTitle(title) window.SetTitle(title)
container := basic.NewContainer(layouts.Dialog { true, true }) container := basicElements.NewContainer(basicLayouts.Dialog { true, true })
window.Adopt(container) window.Adopt(container)
container.Adopt(basic.NewLabel(message, false), true) container.Adopt(basicElements.NewLabel(message, false), true)
if len(buttons) == 0 { if len(buttons) == 0 {
button := basic.NewButton("OK") button := basicElements.NewButton("OK")
button.OnClick(window.Close) button.OnClick(window.Close)
container.Adopt(button, false) container.Adopt(button, false)
button.Focus() button.Focus()
} else { } else {
var button *basic.Button var button *basicElements.Button
for _, buttonDescriptor := range buttons { for _, buttonDescriptor := range buttons {
button = basic.NewButton(buttonDescriptor.Name) button = basicElements.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

@ -1,39 +0,0 @@
package tomo
import "image"
// Window represents a top-level container generated by the currently running
// backend. It can contain a single element. It is hidden by default, and must
// be explicitly shown with the Show() method. If it contains no element, it
// displays a black (or transprent) background.
type Window interface {
// Adopt sets the root element of the window. There can only be one of
// these at one time.
Adopt (child Element)
// Child returns the root element of the window.
Child () (child Element)
// SetTitle sets the title that appears on the window's title bar. This
// method might have no effect with some backends.
SetTitle (title string)
// SetIcon taks in a list different sizes of the same icon and selects
// the best one to display on the window title bar, dock, or whatever is
// applicable for the given backend. This method might have no effect
// for some backends.
SetIcon (sizes []image.Image)
// Show shows the window. The window starts off hidden, so this must be
// called after initial setup to make sure it is visible.
Show ()
// Hide hides the window.
Hide ()
// Close closes the window.
Close ()
// OnClose specifies a function to be called when the window is closed.
OnClose (func ())
}