Redid the entity system a bit to make it more reliable
Now it supports things like parenting elements before they are added to a window and elements no longer have to constantly check for a nil entity
This commit is contained in:
parent
5cf0b162c0
commit
437aef0c27
@ -17,6 +17,9 @@ type Backend interface {
|
||||
// possible. This method must be safe to call from other threads.
|
||||
Do (callback func ())
|
||||
|
||||
// NewEntity creates a new entity for the specified element.
|
||||
NewEntity (owner Element) Entity
|
||||
|
||||
// NewWindow creates a new window within the specified bounding
|
||||
// rectangle. The position on screen may be overridden by the backend or
|
||||
// operating system.
|
||||
|
@ -19,29 +19,46 @@ type entity struct {
|
||||
isContainer bool
|
||||
}
|
||||
|
||||
func bind (parent *entity, window *window, element tomo.Element) *entity {
|
||||
entity := &entity {
|
||||
window: window,
|
||||
parent: parent,
|
||||
element: element,
|
||||
}
|
||||
entity.Invalidate()
|
||||
if _, ok := element.(tomo.Container); ok {
|
||||
func (backend *Backend) NewEntity (owner tomo.Element) tomo.Entity {
|
||||
entity := &entity { element: owner }
|
||||
if _, ok := owner.(tomo.Container); ok {
|
||||
entity.isContainer = true
|
||||
entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
element.Bind(entity)
|
||||
return entity
|
||||
}
|
||||
|
||||
func (entity *entity) unbind () {
|
||||
entity.element.Bind(nil)
|
||||
for _, childEntity := range entity.children {
|
||||
childEntity.unbind()
|
||||
func (ent *entity) unlink () {
|
||||
ent.propagate (func (child *entity) bool {
|
||||
child.window = nil
|
||||
delete(ent.window.system.drawingInvalid, child)
|
||||
return true
|
||||
})
|
||||
|
||||
delete(ent.window.system.drawingInvalid, ent)
|
||||
ent.parent = nil
|
||||
ent.window = nil
|
||||
}
|
||||
|
||||
func (entity *entity) link (parent *entity) {
|
||||
entity.parent = parent
|
||||
if parent.window != nil {
|
||||
entity.setWindow(parent.window)
|
||||
}
|
||||
}
|
||||
|
||||
func (ent *entity) setWindow (window *window) {
|
||||
ent.window = window
|
||||
ent.Invalidate()
|
||||
ent.InvalidateLayout()
|
||||
ent.propagate (func (child *entity) bool {
|
||||
child.window = window
|
||||
ent.Invalidate()
|
||||
ent.InvalidateLayout()
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (entity *entity) propagate (callback func (*entity) bool) {
|
||||
for _, child := range entity.children {
|
||||
if callback(child) { break }
|
||||
@ -61,6 +78,7 @@ func (entity *entity) childAt (point image.Point) *entity {
|
||||
// ----------- Entity ----------- //
|
||||
|
||||
func (entity *entity) Invalidate () {
|
||||
if entity.window == nil { return }
|
||||
if entity.window.system.invalidateIgnore { return }
|
||||
entity.window.drawingInvalid.Add(entity)
|
||||
}
|
||||
@ -77,39 +95,54 @@ func (entity *entity) SetMinimumSize (width, height int) {
|
||||
entity.minWidth = width
|
||||
entity.minHeight = height
|
||||
if entity.parent == nil {
|
||||
entity.window.setMinimumSize(width, height)
|
||||
if entity.window != nil {
|
||||
entity.window.setMinimumSize(width, height)
|
||||
}
|
||||
} else {
|
||||
entity.parent.element.(tomo.Container).
|
||||
HandleChildMinimumSizeChange(entity.element)
|
||||
}
|
||||
}
|
||||
|
||||
func (entity *entity) DrawBackground (destination canvas.Canvas, bounds image.Rectangle) {
|
||||
if entity.parent == nil { return }
|
||||
entity.parent.element.(tomo.Container).DrawBackground(destination, bounds)
|
||||
func (entity *entity) DrawBackground (destination canvas.Canvas) {
|
||||
if entity.parent != nil {
|
||||
entity.parent.element.(tomo.Container).DrawBackground(destination)
|
||||
} else if entity.window != nil {
|
||||
entity.window.system.theme.Pattern (
|
||||
tomo.PatternBackground,
|
||||
tomo.State { }).Draw (
|
||||
destination,
|
||||
entity.window.canvas.Bounds())
|
||||
}
|
||||
}
|
||||
|
||||
// ----------- ContainerEntity ----------- //
|
||||
|
||||
func (entity *entity) InvalidateLayout () {
|
||||
if entity.window == nil { return }
|
||||
if !entity.isContainer { return }
|
||||
entity.layoutInvalid = true
|
||||
entity.window.system.anyLayoutInvalid = true
|
||||
}
|
||||
|
||||
func (entity *entity) Adopt (child tomo.Element) {
|
||||
entity.children = append(entity.children, bind(entity, entity.window, child))
|
||||
func (ent *entity) Adopt (child tomo.Element) {
|
||||
childEntity, ok := child.Entity().(*entity)
|
||||
if !ok || childEntity == nil { return }
|
||||
childEntity.link(ent)
|
||||
ent.children = append(ent.children, childEntity)
|
||||
}
|
||||
|
||||
func (entity *entity) Insert (index int, child tomo.Element) {
|
||||
entity.children = append (
|
||||
entity.children[:index + 1],
|
||||
entity.children[index:]...)
|
||||
entity.children[index] = bind(entity, entity.window, child)
|
||||
func (ent *entity) Insert (index int, child tomo.Element) {
|
||||
childEntity, ok := child.Entity().(*entity)
|
||||
if !ok || childEntity == nil { return }
|
||||
ent.children = append (
|
||||
ent.children[:index + 1],
|
||||
ent.children[index:]...)
|
||||
ent.children[index] = childEntity
|
||||
}
|
||||
|
||||
func (entity *entity) Disown (index int) {
|
||||
entity.children[index].unbind()
|
||||
entity.children[index].unlink()
|
||||
entity.children = append (
|
||||
entity.children[:index],
|
||||
entity.children[index + 1:]...)
|
||||
@ -138,9 +171,7 @@ func (entity *entity) PlaceChild (index int, bounds image.Rectangle) {
|
||||
child.bounds = bounds
|
||||
child.clippedBounds = entity.bounds.Intersect(bounds)
|
||||
child.Invalidate()
|
||||
if child.isContainer {
|
||||
child.InvalidateLayout()
|
||||
}
|
||||
child.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (entity *entity) ChildMinimumSize (index int) (width, height int) {
|
||||
@ -151,10 +182,12 @@ func (entity *entity) ChildMinimumSize (index int) (width, height int) {
|
||||
// ----------- FocusableEntity ----------- //
|
||||
|
||||
func (entity *entity) Focused () bool {
|
||||
if entity.window == nil { return false }
|
||||
return entity.window.focused == entity
|
||||
}
|
||||
|
||||
func (entity *entity) Focus () {
|
||||
if entity.window == nil { return }
|
||||
previous := entity.window.focused
|
||||
entity.window.focused = entity
|
||||
if previous != nil {
|
||||
|
@ -3,6 +3,8 @@ package x
|
||||
import "image"
|
||||
import "git.tebibyte.media/sashakoshka/tomo"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||
|
||||
type entitySet map[*entity] struct { }
|
||||
|
||||
@ -24,8 +26,8 @@ type system struct {
|
||||
focused *entity
|
||||
canvas canvas.BasicCanvas
|
||||
|
||||
theme tomo.Theme
|
||||
config tomo.Config
|
||||
theme theme.Wrapped
|
||||
config config.Wrapped
|
||||
|
||||
invalidateIgnore bool
|
||||
drawingInvalid entitySet
|
||||
@ -41,7 +43,7 @@ func (system *system) initialize () {
|
||||
}
|
||||
|
||||
func (system *system) SetTheme (theme tomo.Theme) {
|
||||
system.theme = theme
|
||||
system.theme.Theme = theme
|
||||
system.propagate (func (entity *entity) bool {
|
||||
if child, ok := system.child.element.(tomo.Themeable); ok {
|
||||
child.SetTheme(theme)
|
||||
@ -51,7 +53,7 @@ func (system *system) SetTheme (theme tomo.Theme) {
|
||||
}
|
||||
|
||||
func (system *system) SetConfig (config tomo.Config) {
|
||||
system.config = config
|
||||
system.config.Config = config
|
||||
system.propagate (func (entity *entity) bool {
|
||||
if child, ok := system.child.element.(tomo.Configurable); ok {
|
||||
child.SetConfig(config)
|
||||
|
@ -67,6 +67,7 @@ func (backend *Backend) newWindow (
|
||||
|
||||
window.system.initialize()
|
||||
window.system.pushFunc = window.pasteAndPush
|
||||
window.theme.Case = tomo.C("tomo", "window")
|
||||
|
||||
window.xWindow, err = xwindow.Generate(backend.connection)
|
||||
if err != nil { return }
|
||||
@ -142,14 +143,18 @@ func (window *window) Window () tomo.Window {
|
||||
func (window *window) Adopt (child tomo.Element) {
|
||||
// disown previous child
|
||||
if window.child != nil {
|
||||
window.child.unbind()
|
||||
window.child.unlink()
|
||||
window.child = nil
|
||||
}
|
||||
|
||||
// adopt new child
|
||||
if child != nil {
|
||||
window.child = bind(nil, window, child)
|
||||
window.resizeChildToFit()
|
||||
childEntity, ok := child.Entity().(*entity)
|
||||
if ok && childEntity != nil {
|
||||
window.child = childEntity
|
||||
childEntity.setWindow(window)
|
||||
window.resizeChildToFit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
14
element.go
14
element.go
@ -6,13 +6,13 @@ import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||
|
||||
// Element represents a basic on-screen object.
|
||||
type Element interface {
|
||||
// Bind assigns an Entity to this element.
|
||||
Bind (Entity)
|
||||
|
||||
// Draw causes the element to draw to the specified canvas. The bounds
|
||||
// of this canvas specify the area that is actually drawn to, while the
|
||||
// Entity bounds specify the actual area of the element.
|
||||
Draw (canvas.Canvas)
|
||||
|
||||
// Entity returns this element's entity.
|
||||
Entity () Entity
|
||||
}
|
||||
|
||||
// Container is an element capable of containing child elements.
|
||||
@ -22,9 +22,11 @@ type Container interface {
|
||||
// Layout causes this element to arrange its children.
|
||||
Layout ()
|
||||
|
||||
// DrawBackground draws this element's background pattern at the
|
||||
// specified bounds to any canvas.
|
||||
DrawBackground (destination canvas.Canvas, bounds image.Rectangle)
|
||||
// DrawBackground causes the element to draw its background pattern to
|
||||
// the specified canvas. The bounds of this canvas specify the area that
|
||||
// is actually drawn to, while the Entity bounds specify the actual area
|
||||
// of the element.
|
||||
DrawBackground (canvas.Canvas)
|
||||
|
||||
// HandleChildMinimumSizeChange is called when a child's minimum size is
|
||||
// changed.
|
||||
|
@ -30,6 +30,7 @@ type Button struct {
|
||||
// NewButton creates a new button with the specified label text.
|
||||
func NewButton (text string) (element *Button) {
|
||||
element = &Button { showText: true, enabled: true }
|
||||
element.entity = tomo.NewEntity(element).(tomo.FocusableEntity)
|
||||
element.theme.Case = tomo.C("tomo", "button")
|
||||
element.drawer.SetFace (element.theme.FontFace (
|
||||
tomo.FontStyleRegular,
|
||||
@ -38,11 +39,9 @@ func NewButton (text string) (element *Button) {
|
||||
return
|
||||
}
|
||||
|
||||
// Bind binds this element to an entity.
|
||||
func (element *Button) Bind (entity tomo.Entity) {
|
||||
if entity == nil { element.entity = nil; return }
|
||||
element.entity = entity.(tomo.FocusableEntity)
|
||||
element.updateMinimumSize()
|
||||
// Entity returns this element's entity.
|
||||
func (element *Button) Entity () tomo.Entity {
|
||||
return element.entity
|
||||
}
|
||||
|
||||
// OnClick sets the function to be called when the button is clicked.
|
||||
@ -52,7 +51,6 @@ func (element *Button) OnClick (callback func ()) {
|
||||
|
||||
// Focus gives this element input focus.
|
||||
func (element *Button) Focus () {
|
||||
if element.entity == nil { return }
|
||||
if !element.entity.Focused() { element.entity.Focus() }
|
||||
}
|
||||
|
||||
@ -65,7 +63,6 @@ func (element *Button) Enabled () bool {
|
||||
func (element *Button) SetEnabled (enabled bool) {
|
||||
if element.enabled == enabled { return }
|
||||
element.enabled = enabled
|
||||
if element.entity == nil { return }
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
|
||||
@ -74,7 +71,6 @@ func (element *Button) SetText (text string) {
|
||||
if element.text == text { return }
|
||||
element.text = text
|
||||
element.drawer.SetText([]rune(text))
|
||||
if element.entity == nil { return }
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
@ -97,7 +93,6 @@ func (element *Button) SetIcon (id tomo.Icon) {
|
||||
func (element *Button) ShowText (showText bool) {
|
||||
if element.showText == showText { return }
|
||||
element.showText = showText
|
||||
if element.entity == nil { return }
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
@ -109,7 +104,6 @@ func (element *Button) SetTheme (new tomo.Theme) {
|
||||
element.drawer.SetFace (element.theme.FontFace (
|
||||
tomo.FontStyleRegular,
|
||||
tomo.FontSizeNormal))
|
||||
if element.entity == nil { return }
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
@ -118,14 +112,12 @@ func (element *Button) SetTheme (new tomo.Theme) {
|
||||
func (element *Button) SetConfig (new tomo.Config) {
|
||||
if new == element.config.Config { return }
|
||||
element.config.Config = new
|
||||
if element.entity == nil { return }
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
|
||||
// Draw causes the element to draw to the specified destination canvas.
|
||||
func (element *Button) Draw (destination canvas.Canvas) {
|
||||
if element.entity == nil { return }
|
||||
state := element.state()
|
||||
bounds := element.entity.Bounds()
|
||||
pattern := element.theme.Pattern(tomo.PatternButton, state)
|
||||
@ -182,7 +174,7 @@ func (element *Button) Draw (destination canvas.Canvas) {
|
||||
}
|
||||
|
||||
func (element *Button) HandleFocusChange () {
|
||||
if element.entity != nil { element.entity.Invalidate() }
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
|
||||
func (element *Button) HandleMouseDown (x, y int, button input.Button) {
|
||||
@ -190,32 +182,31 @@ func (element *Button) HandleMouseDown (x, y int, button input.Button) {
|
||||
element.Focus()
|
||||
if button != input.ButtonLeft { return }
|
||||
element.pressed = true
|
||||
if element.entity != nil { element.entity.Invalidate() }
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
|
||||
func (element *Button) HandleMouseUp (x, y int, button input.Button) {
|
||||
if element.entity == nil { return }
|
||||
if button != input.ButtonLeft { return }
|
||||
element.pressed = false
|
||||
within := image.Point { x, y }.In(element.entity.Bounds())
|
||||
if element.Enabled() && within && element.onClick != nil {
|
||||
element.onClick()
|
||||
}
|
||||
if element.entity != nil { element.entity.Invalidate() }
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
|
||||
func (element *Button) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
||||
if !element.Enabled() { return }
|
||||
if key == input.KeyEnter {
|
||||
element.pressed = true
|
||||
if element.entity != nil { element.entity.Invalidate() }
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Button) HandleKeyUp(key input.Key, modifiers input.Modifiers) {
|
||||
if key == input.KeyEnter && element.pressed {
|
||||
element.pressed = false
|
||||
if element.entity != nil { element.entity.Invalidate() }
|
||||
element.entity.Invalidate()
|
||||
if !element.Enabled() { return }
|
||||
if element.onClick != nil {
|
||||
element.onClick()
|
||||
|
@ -27,6 +27,7 @@ type Checkbox struct {
|
||||
// NewCheckbox creates a new cbeckbox with the specified label text.
|
||||
func NewCheckbox (text string, checked bool) (element *Checkbox) {
|
||||
element = &Checkbox { checked: checked, enabled: true }
|
||||
element.entity = tomo.NewEntity(element).(tomo.FocusableEntity)
|
||||
element.theme.Case = tomo.C("tomo", "checkbox")
|
||||
element.drawer.SetFace (element.theme.FontFace (
|
||||
tomo.FontStyleRegular,
|
||||
@ -35,11 +36,9 @@ func NewCheckbox (text string, checked bool) (element *Checkbox) {
|
||||
return
|
||||
}
|
||||
|
||||
// Bind binds this element to an entity.
|
||||
func (element *Checkbox) Bind (entity tomo.Entity) {
|
||||
if entity == nil { element.entity = nil; return }
|
||||
element.entity = entity.(tomo.FocusableEntity)
|
||||
element.updateMinimumSize()
|
||||
// Entity returns this element's entity.
|
||||
func (element *Checkbox) Entity () tomo.Entity {
|
||||
return element.entity
|
||||
}
|
||||
|
||||
// OnToggle sets the function to be called when the checkbox is toggled.
|
||||
@ -54,7 +53,6 @@ func (element *Checkbox) Value () (checked bool) {
|
||||
|
||||
// Focus gives this element input focus.
|
||||
func (element *Checkbox) Focus () {
|
||||
if element.entity == nil { return }
|
||||
if !element.entity.Focused() { element.entity.Focus() }
|
||||
}
|
||||
|
||||
@ -76,7 +74,6 @@ func (element *Checkbox) SetText (text string) {
|
||||
if element.text == text { return }
|
||||
element.text = text
|
||||
element.drawer.SetText([]rune(text))
|
||||
if element.entity == nil { return }
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
@ -88,7 +85,6 @@ func (element *Checkbox) SetTheme (new tomo.Theme) {
|
||||
element.drawer.SetFace (element.theme.FontFace (
|
||||
tomo.FontStyleRegular,
|
||||
tomo.FontSizeNormal))
|
||||
if element.entity == nil { return }
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
@ -97,15 +93,12 @@ func (element *Checkbox) SetTheme (new tomo.Theme) {
|
||||
func (element *Checkbox) SetConfig (new tomo.Config) {
|
||||
if new == element.config.Config { return }
|
||||
element.config.Config = new
|
||||
if element.entity == nil { return }
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
}
|
||||
|
||||
// Draw causes the element to draw to the specified destination canvas.
|
||||
func (element *Checkbox) Draw (destination canvas.Canvas) {
|
||||
if element.entity == nil { return }
|
||||
|
||||
bounds := element.entity.Bounds()
|
||||
boxBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()).Add(bounds.Min)
|
||||
|
||||
@ -116,7 +109,7 @@ func (element *Checkbox) Draw (destination canvas.Canvas) {
|
||||
On: element.checked,
|
||||
}
|
||||
|
||||
element.entity.DrawBackground(destination, bounds)
|
||||
element.entity.DrawBackground(destination)
|
||||
|
||||
pattern := element.theme.Pattern(tomo.PatternButton, state)
|
||||
pattern.Draw(destination, boxBounds)
|
||||
@ -135,7 +128,6 @@ func (element *Checkbox) Draw (destination canvas.Canvas) {
|
||||
}
|
||||
|
||||
func (element *Checkbox) HandleMouseDown (x, y int, button input.Button) {
|
||||
if element.entity == nil { return }
|
||||
if !element.Enabled() { return }
|
||||
element.Focus()
|
||||
element.pressed = true
|
||||
@ -143,7 +135,6 @@ func (element *Checkbox) HandleMouseDown (x, y int, button input.Button) {
|
||||
}
|
||||
|
||||
func (element *Checkbox) HandleMouseUp (x, y int, button input.Button) {
|
||||
if element.entity == nil { return }
|
||||
if button != input.ButtonLeft || !element.pressed { return }
|
||||
|
||||
element.pressed = false
|
||||
@ -167,7 +158,6 @@ func (element *Checkbox) HandleKeyDown (key input.Key, modifiers input.Modifiers
|
||||
}
|
||||
|
||||
func (element *Checkbox) HandleKeyUp (key input.Key, modifiers input.Modifiers) {
|
||||
if element.entity == nil { return }
|
||||
if key == input.KeyEnter && element.pressed {
|
||||
element.pressed = false
|
||||
element.checked = !element.checked
|
||||
|
@ -20,15 +20,15 @@ func NewIcon (id tomo.Icon, size tomo.IconSize) (element *Icon) {
|
||||
id: id,
|
||||
size: size,
|
||||
}
|
||||
element.entity = tomo.NewEntity(element)
|
||||
element.theme.Case = tomo.C("tomo", "icon")
|
||||
element.updateMinimumSize()
|
||||
return
|
||||
}
|
||||
|
||||
// Bind binds this element to an entity.
|
||||
func (element *Icon) Bind (entity tomo.Entity) {
|
||||
if entity == nil { element.entity = nil; return }
|
||||
element.entity = entity
|
||||
element.updateMinimumSize()
|
||||
// Entity returns this element's entity.
|
||||
func (element *Icon) Entity () tomo.Entity {
|
||||
return element.entity
|
||||
}
|
||||
|
||||
// SetIcon sets the element's icon.
|
||||
|
@ -16,15 +16,15 @@ type Image struct {
|
||||
// NewImage creates a new image element.
|
||||
func NewImage (image image.Image) (element *Image) {
|
||||
element = &Image { buffer: canvas.FromImage(image) }
|
||||
element.entity = tomo.NewEntity(element)
|
||||
bounds := element.buffer.Bounds()
|
||||
element.entity.SetMinimumSize(bounds.Dx(), bounds.Dy())
|
||||
return
|
||||
}
|
||||
|
||||
// Bind binds this element to an entity.
|
||||
func (element *Image) Bind (entity tomo.Entity) {
|
||||
if entity == nil { element.entity = nil; return }
|
||||
element.entity = entity
|
||||
bounds := element.buffer.Bounds()
|
||||
element.entity.SetMinimumSize(bounds.Dx(), bounds.Dy())
|
||||
// Entity returns this element's entity.
|
||||
func (element *Image) Entity () tomo.Entity {
|
||||
return element.entity
|
||||
}
|
||||
|
||||
// Draw causes the element to draw to the specified destination canvas.
|
||||
|
@ -29,6 +29,7 @@ type Label struct {
|
||||
func NewLabel (text string, wrap bool) (element *Label) {
|
||||
element = &Label { }
|
||||
element.theme.Case = tomo.C("tomo", "label")
|
||||
element.entity = tomo.NewEntity(element).(tomo.FlexibleEntity)
|
||||
element.drawer.SetFace (element.theme.FontFace (
|
||||
tomo.FontStyleRegular,
|
||||
tomo.FontSizeNormal))
|
||||
@ -37,11 +38,9 @@ func NewLabel (text string, wrap bool) (element *Label) {
|
||||
return
|
||||
}
|
||||
|
||||
// Bind binds this element to an entity.
|
||||
func (element *Label) Bind (entity tomo.Entity) {
|
||||
if entity == nil { element.entity = nil; return }
|
||||
element.entity = entity.(tomo.FlexibleEntity)
|
||||
element.updateMinimumSize()
|
||||
// Entity returns this element's entity.
|
||||
func (element *Label) Entity () tomo.Entity {
|
||||
return element.entity
|
||||
}
|
||||
|
||||
// EmCollapse forces a minimum width and height upon the label. The width is
|
||||
@ -128,14 +127,14 @@ func (element *Label) SetConfig (new tomo.Config) {
|
||||
func (element *Label) Draw (destination canvas.Canvas) {
|
||||
if element.entity == nil { return }
|
||||
|
||||
bounds := element.entity. Bounds()
|
||||
bounds := element.entity.Bounds()
|
||||
|
||||
if element.wrap {
|
||||
element.drawer.SetMaxWidth(bounds.Dx())
|
||||
element.drawer.SetMaxHeight(bounds.Dy())
|
||||
}
|
||||
|
||||
element.entity.DrawBackground(destination, bounds)
|
||||
element.entity.DrawBackground(destination)
|
||||
|
||||
textBounds := element.drawer.LayoutBounds()
|
||||
foreground := element.theme.Color (
|
||||
|
@ -24,9 +24,11 @@ type Entity interface {
|
||||
SetMinimumSize (width, height int)
|
||||
|
||||
// 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 (destination canvas.Canvas, bounds image.Rectangle)
|
||||
// to a canvas. This should be used for transparent elements like text
|
||||
// labels. If there is no parent element (that is, the element is
|
||||
// directly inside of the window), the backend will draw a default
|
||||
// background pattern.
|
||||
DrawBackground (canvas.Canvas)
|
||||
}
|
||||
|
||||
// ContainerEntity is given to elements that support the Container interface.
|
||||
|
6
tomo.go
6
tomo.go
@ -29,6 +29,12 @@ func Do (callback func ()) {
|
||||
backend.Do(callback)
|
||||
}
|
||||
|
||||
// NewEntity generates an entity for an element using the current backend.
|
||||
func NewEntity (owner Element) Entity {
|
||||
assertBackend()
|
||||
return backend.NewEntity(owner)
|
||||
}
|
||||
|
||||
// NewWindow creates a new window using the current backend, and returns it as a
|
||||
// MainWindow. If the window could not be created, an error is returned
|
||||
// explaining why.
|
||||
|
Reference in New Issue
Block a user