X backend entity
This commit is contained in:
parent
407b957687
commit
bb9c5df088
154
backends/x/entity.go
Normal file
154
backends/x/entity.go
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package x
|
||||||
|
|
||||||
|
import "image"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
|
|
||||||
|
type entity struct {
|
||||||
|
window *window
|
||||||
|
parent *entity
|
||||||
|
children []*entity
|
||||||
|
element tomo.Element
|
||||||
|
|
||||||
|
drawDirty bool
|
||||||
|
layoutDirty bool
|
||||||
|
|
||||||
|
bounds image.Rectangle
|
||||||
|
minWidth int
|
||||||
|
minHeight int
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind (element tomo.Element) *entity {
|
||||||
|
entity := &entity { drawDirty: true }
|
||||||
|
if _, ok := element.(tomo.Container); ok {
|
||||||
|
entity.layoutDirty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
element.Bind(entity)
|
||||||
|
return entity
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) unbind () {
|
||||||
|
entity.element.Bind(nil)
|
||||||
|
for _, childEntity := range entity.children {
|
||||||
|
childEntity.unbind()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- Entity ----------- //
|
||||||
|
|
||||||
|
func (entity *entity) Invalidate () {
|
||||||
|
entity.drawDirty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) Bounds () image.Rectangle {
|
||||||
|
return entity.bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) Window () tomo.Window {
|
||||||
|
return entity.window
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) SetMinimumSize (width, height int) {
|
||||||
|
entity.minWidth = width
|
||||||
|
entity.minHeight = height
|
||||||
|
if entity.parent == nil { return }
|
||||||
|
entity.parent.element.(tomo.Container).HandleChildMinimumSizeChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) DrawBackground (destination canvas.Canvas, bounds image.Rectangle) {
|
||||||
|
if entity.parent == nil { return }
|
||||||
|
entity.parent.element.(tomo.Container).DrawBackground(destination, bounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- ContainerEntity ----------- //
|
||||||
|
|
||||||
|
func (entity *entity) InvalidateLayout () {
|
||||||
|
entity.layoutDirty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) Adopt (child tomo.Element) {
|
||||||
|
entity.children = append(entity.children, bind(child))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) Insert (index int, child tomo.Element) {
|
||||||
|
entity.children = append (
|
||||||
|
entity.children[:index + 1],
|
||||||
|
entity.children[index:]...)
|
||||||
|
entity.children[index] = bind(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) Disown (index int) {
|
||||||
|
entity.children[index].unbind()
|
||||||
|
entity.children = append (
|
||||||
|
entity.children[:index],
|
||||||
|
entity.children[index + 1:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) IndexOf (child tomo.Element) int {
|
||||||
|
for index, childEntity := range entity.children {
|
||||||
|
if childEntity.element == child {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) Child (index int) tomo.Element {
|
||||||
|
return entity.children[index].element
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) CountChildren () int {
|
||||||
|
return len(entity.children)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) PlaceChild (index int, bounds image.Rectangle) {
|
||||||
|
entity.children[index].bounds = bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) ChildMinimumSize (index int) (width, height int) {
|
||||||
|
childEntity := entity.children[index]
|
||||||
|
return childEntity.minWidth, childEntity.minHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- FocusableEntity ----------- //
|
||||||
|
|
||||||
|
func (entity *entity) Focused () bool {
|
||||||
|
return entity.window.focused == entity
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) Focus () {
|
||||||
|
previous := entity.window.focused
|
||||||
|
entity.window.focused = entity
|
||||||
|
if previous != nil {
|
||||||
|
previous.element.(tomo.Focusable).HandleFocusChange()
|
||||||
|
}
|
||||||
|
entity.element.(tomo.Focusable).HandleFocusChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) FocusNext () {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entity *entity) FocusPrevious () {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- FlexibleEntity ----------- //
|
||||||
|
|
||||||
|
func (entity *entity) NotifyFlexibleHeightChange () {
|
||||||
|
if entity.parent == nil { return }
|
||||||
|
if parent, ok := entity.parent.element.(tomo.FlexibleContainer); ok {
|
||||||
|
parent.HandleChildFlexibleHeightChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- ScrollableEntity ----------- //
|
||||||
|
|
||||||
|
func (entity *entity) NotifyScrollBoundsChange () {
|
||||||
|
if entity.parent == nil { return }
|
||||||
|
if parent, ok := entity.parent.element.(tomo.ScrollableContainer); ok {
|
||||||
|
parent.HandleChildScrollBoundsChange()
|
||||||
|
}
|
||||||
|
}
|
@ -24,9 +24,9 @@ type window struct {
|
|||||||
xWindow *xwindow.Window
|
xWindow *xwindow.Window
|
||||||
xCanvas *xgraphics.Image
|
xCanvas *xgraphics.Image
|
||||||
canvas canvas.BasicCanvas
|
canvas canvas.BasicCanvas
|
||||||
child tomo.Element
|
child *entity
|
||||||
|
focused *entity
|
||||||
onClose func ()
|
onClose func ()
|
||||||
skipChildDrawCallback bool
|
|
||||||
|
|
||||||
title, application string
|
title, application string
|
||||||
|
|
||||||
|
24
element.go
24
element.go
@ -25,6 +25,10 @@ type Container interface {
|
|||||||
// DrawBackground draws this element's background pattern at the
|
// DrawBackground draws this element's background pattern at the
|
||||||
// specified bounds to any canvas.
|
// specified bounds to any canvas.
|
||||||
DrawBackground (destination canvas.Canvas, bounds image.Rectangle)
|
DrawBackground (destination canvas.Canvas, bounds image.Rectangle)
|
||||||
|
|
||||||
|
// HandleChildMinimumSizeChange is called when a child's minimum size is
|
||||||
|
// changed.
|
||||||
|
HandleChildMinimumSizeChange ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focusable represents an element that has keyboard navigation support.
|
// Focusable represents an element that has keyboard navigation support.
|
||||||
@ -104,6 +108,16 @@ type Flexible interface {
|
|||||||
FlexibleHeightFor (width int) int
|
FlexibleHeightFor (width int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlexibleContainer represents an element that is capable of containing
|
||||||
|
// flexible children.
|
||||||
|
type FlexibleContainer interface {
|
||||||
|
Container
|
||||||
|
|
||||||
|
// HandleChildFlexibleHeightChange is called when the parameters
|
||||||
|
// affecting a child's flexible height are changed.
|
||||||
|
HandleChildFlexibleHeightChange ()
|
||||||
|
}
|
||||||
|
|
||||||
// Scrollable represents an element that can be scrolled. It acts as a viewport
|
// Scrollable represents an element that can be scrolled. It acts as a viewport
|
||||||
// through which its contents can be observed.
|
// through which its contents can be observed.
|
||||||
type Scrollable interface {
|
type Scrollable interface {
|
||||||
@ -124,6 +138,16 @@ type Scrollable interface {
|
|||||||
ScrollAxes () (horizontal, vertical bool)
|
ScrollAxes () (horizontal, vertical bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ScrollableContainer represents an element that is capable of containing
|
||||||
|
// scrollable children.
|
||||||
|
type ScrollableContainer interface {
|
||||||
|
Container
|
||||||
|
|
||||||
|
// HandleChildScrollBoundsChange is called when the content bounds,
|
||||||
|
// viewport bounds, or scroll axes of a child are changed.
|
||||||
|
HandleChildScrollBoundsChange()
|
||||||
|
}
|
||||||
|
|
||||||
// Collapsible represents an element who's minimum width and height can be
|
// Collapsible represents an element who's minimum width and height can be
|
||||||
// manually resized. Scrollable elements should implement this if possible.
|
// manually resized. Scrollable elements should implement this if possible.
|
||||||
type Collapsible interface {
|
type Collapsible interface {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package tomo
|
package tomo
|
||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
|
|
||||||
// Entity is a handle given to elements by the backend. Different types of
|
// Entity is a handle given to elements by the backend. Different types of
|
||||||
// entities may be assigned to elements that support different capabilities.
|
// entities may be assigned to elements that support different capabilities.
|
||||||
@ -25,13 +26,18 @@ type Entity interface {
|
|||||||
// DrawBackground asks the parent element to draw its background pattern
|
// DrawBackground asks the parent element to draw its background pattern
|
||||||
// within the specified rectangle. This should be used for transparent
|
// within the specified rectangle. This should be used for transparent
|
||||||
// elements like text labels.
|
// elements like text labels.
|
||||||
DrawBackground (bounds image.Rectangle)
|
DrawBackground (destination canvas.Canvas, bounds image.Rectangle)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerEntity is given to elements that support the Container interface.
|
// ContainerEntity is given to elements that support the Container interface.
|
||||||
type ContainerEntity interface {
|
type ContainerEntity interface {
|
||||||
Entity
|
Entity
|
||||||
|
|
||||||
|
// InvalidateLayout marks the element's layout as invalid. At the end of
|
||||||
|
// every event, the backend will ask all invalid containers to
|
||||||
|
// recalculate their layouts.
|
||||||
|
InvalidateLayout ()
|
||||||
|
|
||||||
// Adopt adds an element as a child.
|
// Adopt adds an element as a child.
|
||||||
Adopt (child Element)
|
Adopt (child Element)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user