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
|
||||
xCanvas *xgraphics.Image
|
||||
canvas canvas.BasicCanvas
|
||||
child tomo.Element
|
||||
child *entity
|
||||
focused *entity
|
||||
onClose func ()
|
||||
skipChildDrawCallback bool
|
||||
|
||||
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
|
||||
// specified bounds to any canvas.
|
||||
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.
|
||||
@ -104,6 +108,16 @@ type Flexible interface {
|
||||
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
|
||||
// through which its contents can be observed.
|
||||
type Scrollable interface {
|
||||
@ -124,6 +138,16 @@ type Scrollable interface {
|
||||
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
|
||||
// manually resized. Scrollable elements should implement this if possible.
|
||||
type Collapsible interface {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package tomo
|
||||
|
||||
import "image"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||
|
||||
// Entity is a handle given to elements by the backend. Different types of
|
||||
// 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
|
||||
// within the specified rectangle. This should be used for transparent
|
||||
// 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.
|
||||
type ContainerEntity interface {
|
||||
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 (child Element)
|
||||
|
||||
|
Reference in New Issue
Block a user