atomize-parent-hooks #4
@ -122,7 +122,7 @@ func (window *Window) handleButtonPress (
|
||||
sum := scrollSum { }
|
||||
sum.add(buttonEvent.Detail)
|
||||
window.compressScrollSum(buttonEvent, &sum)
|
||||
child.HandleScroll (
|
||||
child.HandleMouseScroll (
|
||||
int(buttonEvent.EventX),
|
||||
int(buttonEvent.EventY),
|
||||
float64(sum.x), float64(sum.y))
|
||||
|
@ -76,26 +76,39 @@ func (backend *Backend) NewWindow (
|
||||
}
|
||||
|
||||
func (window *Window) Adopt (child tomo.Element) {
|
||||
// disown previous child
|
||||
if window.child != nil {
|
||||
window.child.SetParentHooks (tomo.ParentHooks { })
|
||||
if previousChild, ok := window.child.(tomo.Selectable); ok {
|
||||
if previousChild.Selected() {
|
||||
previousChild.HandleDeselection()
|
||||
}
|
||||
window.child.OnDamage(nil)
|
||||
window.child.OnMinimumSizeChange(nil)
|
||||
}
|
||||
if previousChild, ok := window.child.(tomo.Flexible); ok {
|
||||
previousChild.OnFlexibleHeightChange(nil)
|
||||
}
|
||||
if previousChild, ok := window.child.(tomo.Selectable); ok {
|
||||
previousChild.OnSelectionRequest(nil)
|
||||
previousChild.OnSelectionMotionRequest(nil)
|
||||
if previousChild.Selected() {
|
||||
previousChild.HandleDeselection()
|
||||
}
|
||||
}
|
||||
|
||||
// adopt new child
|
||||
window.child = child
|
||||
if child != nil {
|
||||
child.SetParentHooks (tomo.ParentHooks {
|
||||
Draw: window.childDrawCallback,
|
||||
MinimumSizeChange: window.childMinimumSizeChangeCallback,
|
||||
FlexibleHeightChange: window.resizeChildToFit,
|
||||
SelectionRequest: window.childSelectionRequestCallback,
|
||||
})
|
||||
|
||||
window.resizeChildToFit()
|
||||
if newChild, ok := child.(tomo.Flexible); ok {
|
||||
newChild.OnFlexibleHeightChange(window.resizeChildToFit)
|
||||
}
|
||||
if newChild, ok := child.(tomo.Selectable); ok {
|
||||
newChild.OnSelectionRequest(window.childSelectionRequestCallback)
|
||||
}
|
||||
if child != nil {
|
||||
child.OnDamage(window.childDrawCallback)
|
||||
child.OnMinimumSizeChange (func () {
|
||||
window.childMinimumSizeChangeCallback (
|
||||
child.MinimumSize())
|
||||
})
|
||||
window.resizeChildToFit()
|
||||
window.childMinimumSizeChangeCallback(child.MinimumSize())
|
||||
}
|
||||
window.childMinimumSizeChangeCallback(child.MinimumSize())
|
||||
}
|
||||
|
||||
func (window *Window) Child () (child tomo.Element) {
|
||||
@ -204,7 +217,7 @@ func (window *Window) redrawChildEntirely () {
|
||||
func (window *Window) resizeChildToFit () {
|
||||
window.skipChildDrawCallback = true
|
||||
if child, ok := window.child.(tomo.Flexible); ok {
|
||||
minimumHeight := child.MinimumHeightFor(window.metrics.width)
|
||||
minimumHeight := child.FlexibleHeightFor(window.metrics.width)
|
||||
minimumWidth, _ := child.MinimumSize()
|
||||
|
||||
icccm.WmNormalHintsSet (
|
||||
|
134
element.go
134
element.go
@ -2,96 +2,6 @@ package tomo
|
||||
|
||||
import "image"
|
||||
|
||||
// ParentHooks is a struct that contains callbacks that let child elements send
|
||||
// information to their parent element without the child element knowing
|
||||
// anything about the parent element or containing any reference to it. When a
|
||||
// parent element adopts a child element, it must set these callbacks. They are
|
||||
// allowed to be nil.
|
||||
type ParentHooks struct {
|
||||
// Draw is called when a part of the child element's surface is updated.
|
||||
// The updated region will be passed to the callback as a sub-image.
|
||||
Draw func (region Canvas)
|
||||
|
||||
// MinimumSizeChange is called when the child element's minimum width
|
||||
// and/or height changes. When this function is called, the element will
|
||||
// have already been resized and there is no need to send it a resize
|
||||
// event.
|
||||
MinimumSizeChange func (width, height int)
|
||||
|
||||
// FlexibleHeightChange is called when the parameters affecting the
|
||||
// element's felxible height have changed.
|
||||
FlexibleHeightChange func ()
|
||||
|
||||
// ContentBoundsChange is called by scrollable elements when the
|
||||
// element's content bounds have changed. When this function is called,
|
||||
// the element will have already done any drawing necessary. This is
|
||||
// only intended for updating things like scrollbar positions.
|
||||
ContentBoundsChange func ()
|
||||
|
||||
// SelectionRequest is called when the child element element wants
|
||||
// itself to be selected. If the parent element chooses to grant the
|
||||
// request, it must send the child element a selection event and return
|
||||
// true.
|
||||
SelectionRequest func () (granted bool)
|
||||
|
||||
// SelectionMotionRequest is called when the child element wants the
|
||||
// parent element to select the previous/next element in relation to it.
|
||||
SelectionMotionRequest func (direction SelectionDirection) (granted bool)
|
||||
}
|
||||
|
||||
// RunDraw runs the Draw hook if it is not nil. If it is nil, it does nothing.
|
||||
func (hooks ParentHooks) RunDraw (region Canvas) {
|
||||
if hooks.Draw != nil {
|
||||
hooks.Draw(region)
|
||||
}
|
||||
}
|
||||
|
||||
// RunMinimumSizeChange runs the MinimumSizeChange hook if it is not nil. If it
|
||||
// is nil, it does nothing.
|
||||
func (hooks ParentHooks) RunMinimumSizeChange (width, height int) {
|
||||
if hooks.MinimumSizeChange != nil {
|
||||
hooks.MinimumSizeChange(width, height)
|
||||
}
|
||||
}
|
||||
|
||||
// RunFlexibleHeightChange runs the ExpandingHeightChange hook if it is not
|
||||
// nil. If it is nil, it does nothing.
|
||||
func (hooks ParentHooks) RunFlexibleHeightChange () {
|
||||
if hooks.FlexibleHeightChange != nil {
|
||||
hooks.FlexibleHeightChange()
|
||||
}
|
||||
}
|
||||
|
||||
// RunSelectionRequest runs the SelectionRequest hook if it is not nil. If it is
|
||||
// nil, it does nothing.
|
||||
func (hooks ParentHooks) RunSelectionRequest () (granted bool) {
|
||||
if hooks.SelectionRequest != nil {
|
||||
granted = hooks.SelectionRequest()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RunSelectionMotionRequest runs the SelectionMotionRequest hook if it is not
|
||||
// nil. If it is nil, it does nothing.
|
||||
func (hooks ParentHooks) RunSelectionMotionRequest (
|
||||
direction SelectionDirection,
|
||||
) (
|
||||
granted bool,
|
||||
) {
|
||||
if hooks.SelectionMotionRequest != nil {
|
||||
granted = hooks.SelectionMotionRequest(direction)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RunContentBoundsChange runs the ContentBoundsChange hook if it is not nil. If
|
||||
// it is nil, it does nothing.
|
||||
func (hooks ParentHooks) RunContentBoundsChange () {
|
||||
if hooks.ContentBoundsChange != nil {
|
||||
hooks.ContentBoundsChange()
|
||||
}
|
||||
}
|
||||
|
||||
// Element represents a basic on-screen object.
|
||||
type Element interface {
|
||||
// Element must implement the Canvas interface. Elements should start
|
||||
@ -109,11 +19,13 @@ type Element interface {
|
||||
// element's parent.
|
||||
Resize (width, height int)
|
||||
|
||||
// SetParentHooks gives the element callbacks that let it send
|
||||
// information to its parent element without it knowing anything about
|
||||
// the parent element or containing any reference to it. When a parent
|
||||
// element adopts a child element, it must set these callbacks.
|
||||
SetParentHooks (callbacks ParentHooks)
|
||||
// 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 ())
|
||||
}
|
||||
|
||||
// SelectionDirection represents a keyboard navigation direction.
|
||||
@ -156,6 +68,18 @@ type Selectable interface {
|
||||
// HandleDeselection causes this element to mark itself and all of its
|
||||
// children as deselected.
|
||||
HandleDeselection ()
|
||||
|
||||
// OnSelectionRequest sets a function to be called when this element
|
||||
// wants its parent element to select it. Parent elements should return
|
||||
// true if the request was granted, and false if it was not.
|
||||
OnSelectionRequest (func () (granted bool))
|
||||
|
||||
// OnSelectionMotionRequest sets a function to be called when this
|
||||
// element wants its parent element to select 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.
|
||||
OnSelectionMotionRequest (func (SelectionDirection) (granted bool))
|
||||
}
|
||||
|
||||
// KeyboardTarget represents an element that can receive keyboard input.
|
||||
@ -196,7 +120,7 @@ type MouseTarget interface {
|
||||
|
||||
// HandleScroll is called when the mouse is scrolled. The X and Y
|
||||
// direction of the scroll event are passed as deltaX and deltaY.
|
||||
HandleScroll (x, y int, deltaX, deltaY float64)
|
||||
HandleMouseScroll (x, y int, deltaX, deltaY float64)
|
||||
}
|
||||
|
||||
// Flexible represents an element who's preferred minimum height can change in
|
||||
@ -204,10 +128,10 @@ type MouseTarget interface {
|
||||
type Flexible interface {
|
||||
Element
|
||||
|
||||
// HeightForWidth 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.
|
||||
// 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
|
||||
@ -217,7 +141,11 @@ type Flexible interface {
|
||||
//
|
||||
// It is important to note that if a parent container checks for
|
||||
// flexible chilren, it itself will likely need to be flexible.
|
||||
MinimumHeightFor (width int) (height int)
|
||||
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
|
||||
@ -238,4 +166,8 @@ type Scrollable interface {
|
||||
|
||||
// ScrollAxes returns the supported axes for scrolling.
|
||||
ScrollAxes () (horizontal, vertical bool)
|
||||
|
||||
// OnScrollBoundsChange sets a function to be called when the element's
|
||||
// ScrollContentBounds or ScrollViewportBounds are changed.
|
||||
OnScrollBoundsChange (callback func ())
|
||||
}
|
||||
|
@ -14,10 +14,13 @@ type Button struct {
|
||||
pressed bool
|
||||
enabled bool
|
||||
selected bool
|
||||
onClick func ()
|
||||
|
||||
text string
|
||||
drawer artist.TextDrawer
|
||||
|
||||
onClick func ()
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
|
||||
}
|
||||
|
||||
// NewButton creates a new button with the specified label text.
|
||||
@ -41,7 +44,7 @@ func (element *Button) HandleMouseDown (x, y int, button tomo.Button) {
|
||||
element.pressed = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +53,7 @@ func (element *Button) HandleMouseUp (x, y int, button tomo.Button) {
|
||||
element.pressed = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
|
||||
within := image.Point { x, y }.
|
||||
@ -63,7 +66,7 @@ func (element *Button) HandleMouseUp (x, y int, button tomo.Button) {
|
||||
}
|
||||
|
||||
func (element *Button) HandleMouseMove (x, y int) { }
|
||||
func (element *Button) HandleScroll (x, y int, deltaX, deltaY float64) { }
|
||||
func (element *Button) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
|
||||
|
||||
func (element *Button) HandleKeyDown (
|
||||
key tomo.Key,
|
||||
@ -75,7 +78,7 @@ func (element *Button) HandleKeyDown (
|
||||
element.pressed = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,7 +88,7 @@ func (element *Button) HandleKeyUp(key tomo.Key, modifiers tomo.Modifiers) {
|
||||
element.pressed = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
if !element.enabled { return }
|
||||
if element.onClick != nil {
|
||||
@ -100,7 +103,9 @@ func (element *Button) Selected () (selected bool) {
|
||||
|
||||
func (element *Button) Select () {
|
||||
if !element.enabled { return }
|
||||
element.core.RequestSelection()
|
||||
if element.onSelectionRequest != nil {
|
||||
element.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Button) HandleSelection (
|
||||
@ -117,7 +122,7 @@ func (element *Button) HandleSelection (
|
||||
element.selected = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -126,10 +131,20 @@ func (element *Button) HandleDeselection () {
|
||||
element.selected = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Button) OnSelectionRequest (callback func () (granted bool)) {
|
||||
element.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
func (element *Button) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
element.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
// OnClick sets the function to be called when the button is clicked.
|
||||
func (element *Button) OnClick (callback func ()) {
|
||||
element.onClick = callback
|
||||
@ -141,7 +156,7 @@ func (element *Button) SetEnabled (enabled bool) {
|
||||
element.enabled = enabled
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +172,7 @@ func (element *Button) SetText (text string) {
|
||||
theme.Padding() * 2 + textBounds.Dy())
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,10 +15,13 @@ type Checkbox struct {
|
||||
checked bool
|
||||
enabled bool
|
||||
selected bool
|
||||
onClick func ()
|
||||
|
||||
text string
|
||||
drawer artist.TextDrawer
|
||||
|
||||
onClick func ()
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
|
||||
}
|
||||
|
||||
// NewCheckbox creates a new cbeckbox with the specified label text.
|
||||
@ -41,7 +44,7 @@ func (element *Checkbox) HandleMouseDown (x, y int, button tomo.Button) {
|
||||
element.pressed = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +60,7 @@ func (element *Checkbox) HandleMouseUp (x, y int, button tomo.Button) {
|
||||
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
if within && element.onClick != nil {
|
||||
element.onClick()
|
||||
@ -76,7 +79,7 @@ func (element *Checkbox) HandleKeyDown (
|
||||
element.pressed = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -87,7 +90,7 @@ func (element *Checkbox) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) {
|
||||
element.checked = !element.checked
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
if element.onClick != nil {
|
||||
element.onClick()
|
||||
@ -102,7 +105,10 @@ func (element *Checkbox) Selected () (selected bool) {
|
||||
|
||||
// Select requests that this element be selected.
|
||||
func (element *Checkbox) Select () {
|
||||
element.core.RequestSelection()
|
||||
if !element.enabled { return }
|
||||
if element.onSelectionRequest != nil {
|
||||
element.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Checkbox) HandleSelection (
|
||||
@ -119,7 +125,7 @@ func (element *Checkbox) HandleSelection (
|
||||
element.selected = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -128,10 +134,20 @@ func (element *Checkbox) HandleDeselection () {
|
||||
element.selected = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Checkbox) OnSelectionRequest (callback func () (granted bool)) {
|
||||
element.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
func (element *Checkbox) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
element.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
// OnClick sets the function to be called when the checkbox is toggled.
|
||||
func (element *Checkbox) OnClick (callback func ()) {
|
||||
element.onClick = callback
|
||||
@ -148,7 +164,7 @@ func (element *Checkbox) SetEnabled (enabled bool) {
|
||||
element.enabled = enabled
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +180,7 @@ func (element *Checkbox) SetText (text string) {
|
||||
textBounds.Dy())
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,10 @@ type Container struct {
|
||||
selected bool
|
||||
selectable bool
|
||||
flexible bool
|
||||
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
|
||||
onFlexibleHeightChange func ()
|
||||
}
|
||||
|
||||
// NewContainer creates a new container.
|
||||
@ -35,7 +39,7 @@ func (element *Container) SetLayout (layout tomo.Layout) {
|
||||
if element.core.HasImage() {
|
||||
element.recalculate()
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,38 +47,38 @@ func (element *Container) SetLayout (layout tomo.Layout) {
|
||||
// the element will expand (instead of contract to its minimum size), in
|
||||
// whatever way is defined by the current layout.
|
||||
func (element *Container) Adopt (child tomo.Element, expand bool) {
|
||||
child.SetParentHooks (tomo.ParentHooks {
|
||||
Draw: func (region tomo.Canvas) {
|
||||
element.drawChildRegion(child, region)
|
||||
},
|
||||
MinimumSizeChange: func (int, int) {
|
||||
element.updateMinimumSize()
|
||||
},
|
||||
FlexibleHeightChange: element.updateMinimumSize,
|
||||
SelectionRequest: func () (granted bool) {
|
||||
child, selectable := child.(tomo.Selectable)
|
||||
if !selectable { return }
|
||||
return element.childSelectionRequestCallback(child)
|
||||
},
|
||||
SelectionMotionRequest: func (
|
||||
direction tomo.SelectionDirection,
|
||||
) (
|
||||
granted bool,
|
||||
) {
|
||||
return element.core.RequestSelectionMotion(direction)
|
||||
},
|
||||
// set event handlers
|
||||
child.OnDamage (func (region tomo.Canvas) {
|
||||
element.drawChildRegion(child, region)
|
||||
})
|
||||
child.OnMinimumSizeChange(element.updateMinimumSize)
|
||||
if child0, ok := child.(tomo.Flexible); ok {
|
||||
child0.OnFlexibleHeightChange(element.updateMinimumSize)
|
||||
}
|
||||
if child0, ok := child.(tomo.Selectable); ok {
|
||||
child0.OnSelectionRequest (func () (granted bool) {
|
||||
return element.childSelectionRequestCallback(child0)
|
||||
})
|
||||
child0.OnSelectionMotionRequest (
|
||||
func (direction tomo.SelectionDirection) (granted bool) {
|
||||
if element.onSelectionMotionRequest == nil { return }
|
||||
return element.onSelectionMotionRequest(direction)
|
||||
})
|
||||
}
|
||||
|
||||
// add child
|
||||
element.children = append (element.children, tomo.LayoutEntry {
|
||||
Element: child,
|
||||
Expand: expand,
|
||||
})
|
||||
|
||||
// refresh stale data
|
||||
element.updateMinimumSize()
|
||||
element.reflectChildProperties()
|
||||
if element.core.HasImage() && !element.warping {
|
||||
element.recalculate()
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,7 +101,7 @@ func (element *Container) Warp (callback func ()) {
|
||||
if element.core.HasImage() {
|
||||
element.recalculate()
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,7 +110,7 @@ func (element *Container) Warp (callback func ()) {
|
||||
func (element *Container) Disown (child tomo.Element) {
|
||||
for index, entry := range element.children {
|
||||
if entry.Element == child {
|
||||
entry.SetParentHooks(tomo.ParentHooks { })
|
||||
element.clearChildEventHandlers(entry.Element)
|
||||
element.children = append (
|
||||
element.children[:index],
|
||||
element.children[index + 1:]...)
|
||||
@ -119,7 +123,22 @@ func (element *Container) Disown (child tomo.Element) {
|
||||
if element.core.HasImage() && !element.warping {
|
||||
element.recalculate()
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) clearChildEventHandlers (child tomo.Element) {
|
||||
child.OnDamage(nil)
|
||||
child.OnMinimumSizeChange(nil)
|
||||
if child0, ok := child.(tomo.Selectable); ok {
|
||||
child0.OnSelectionRequest(nil)
|
||||
child0.OnSelectionMotionRequest(nil)
|
||||
if child0.Selected() {
|
||||
child0.HandleDeselection()
|
||||
}
|
||||
}
|
||||
if child0, ok := child.(tomo.Flexible); ok {
|
||||
child0.OnFlexibleHeightChange(nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,7 +151,7 @@ func (element *Container) DisownAll () {
|
||||
if element.core.HasImage() && !element.warping {
|
||||
element.recalculate()
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,11 +228,11 @@ func (element *Container) HandleMouseMove (x, y int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) HandleScroll (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)
|
||||
if !handlesMouse { return }
|
||||
childPosition := element.childPosition(child)
|
||||
child.HandleScroll(x - childPosition.X, y - childPosition.Y, deltaX, deltaY)
|
||||
child.HandleMouseScroll(x - childPosition.X, y - childPosition.Y, deltaX, deltaY)
|
||||
}
|
||||
|
||||
func (element *Container) HandleKeyDown (
|
||||
@ -245,7 +264,9 @@ func (element *Container) Selected () (selected bool) {
|
||||
}
|
||||
|
||||
func (element *Container) Select () {
|
||||
element.core.RequestSelection()
|
||||
if element.onSelectionRequest != nil {
|
||||
element.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) HandleSelection (direction tomo.SelectionDirection) (ok bool) {
|
||||
@ -300,8 +321,12 @@ func (element *Container) HandleSelection (direction tomo.SelectionDirection) (o
|
||||
return false
|
||||
}
|
||||
|
||||
func (element *Container) MinimumHeightFor (width int) (height int) {
|
||||
return element.layout.MinimumHeightFor(element.children, width)
|
||||
func (element *Container) FlexibleHeightFor (width int) (height int) {
|
||||
return element.layout.FlexibleHeightFor(element.children, width)
|
||||
}
|
||||
|
||||
func (element *Container) OnFlexibleHeightChange (callback func ()) {
|
||||
element.onFlexibleHeightChange = callback
|
||||
}
|
||||
|
||||
func (element *Container) HandleDeselection () {
|
||||
@ -312,6 +337,16 @@ func (element *Container) HandleDeselection () {
|
||||
})
|
||||
}
|
||||
|
||||
func (element *Container) OnSelectionRequest (callback func () (granted bool)) {
|
||||
element.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
func (element *Container) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
element.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
func (element *Container) forSelected (callback func (child tomo.Selectable) bool) {
|
||||
for _, entry := range element.children {
|
||||
child, selectable := entry.Element.(tomo.Selectable)
|
||||
@ -379,7 +414,7 @@ func (element *Container) childSelectionRequestCallback (
|
||||
) (
|
||||
granted bool,
|
||||
) {
|
||||
if element.core.RequestSelection() {
|
||||
if element.onSelectionRequest != nil && element.onSelectionRequest() {
|
||||
element.forSelected (func (child tomo.Selectable) bool {
|
||||
child.HandleDeselection()
|
||||
return true
|
||||
@ -394,7 +429,7 @@ func (element *Container) childSelectionRequestCallback (
|
||||
func (element *Container) updateMinimumSize () {
|
||||
width, height := element.layout.MinimumSize(element.children)
|
||||
if element.flexible {
|
||||
height = element.layout.MinimumHeightFor(element.children, width)
|
||||
height = element.layout.FlexibleHeightFor(element.children, width)
|
||||
}
|
||||
element.core.SetMinimumSize(width, height)
|
||||
}
|
||||
@ -422,7 +457,7 @@ func (element *Container) drawChildRegion (child tomo.Element, region tomo.Canva
|
||||
for _, entry := range element.children {
|
||||
if entry.Element == child {
|
||||
artist.Paste(element.core, region, entry.Position)
|
||||
element.core.PushRegion (
|
||||
element.core.DamageRegion (
|
||||
region.Bounds().Add(entry.Position))
|
||||
break
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ type Label struct {
|
||||
wrap bool
|
||||
text string
|
||||
drawer artist.TextDrawer
|
||||
|
||||
onFlexibleHeightChange func ()
|
||||
}
|
||||
|
||||
// NewLabel creates a new label. If wrap is set to true, the text inside will be
|
||||
@ -38,9 +40,9 @@ func (element *Label) Resize (width, height int) {
|
||||
return
|
||||
}
|
||||
|
||||
// MinimumHeightFor returns the reccomended height for this element based on the
|
||||
// given width in order to allow the text to wrap properly.
|
||||
func (element *Label) MinimumHeightFor (width int) (height int) {
|
||||
// FlexibleHeightFor returns the reccomended height for this element based on
|
||||
// the given width in order to allow the text to wrap properly.
|
||||
func (element *Label) FlexibleHeightFor (width int) (height int) {
|
||||
if element.wrap {
|
||||
return element.drawer.ReccomendedHeightFor(width)
|
||||
} else {
|
||||
@ -49,6 +51,12 @@ func (element *Label) MinimumHeightFor (width int) (height int) {
|
||||
}
|
||||
}
|
||||
|
||||
// OnFlexibleHeightChange sets a function to be called when the parameters
|
||||
// affecting this element's flexible height are changed.
|
||||
func (element *Label) OnFlexibleHeightChange (callback func ()) {
|
||||
element.onFlexibleHeightChange = callback
|
||||
}
|
||||
|
||||
// SetText sets the label's text.
|
||||
func (element *Label) SetText (text string) {
|
||||
if element.text == text { return }
|
||||
@ -59,7 +67,7 @@ func (element *Label) SetText (text string) {
|
||||
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +86,7 @@ func (element *Label) SetWrap (wrap bool) {
|
||||
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +96,9 @@ func (element *Label) updateMinimumSize () {
|
||||
if em < 1 { em = theme.Padding() }
|
||||
element.core.SetMinimumSize (
|
||||
em, element.drawer.LineHeight().Round())
|
||||
element.core.NotifyFlexibleHeightChange()
|
||||
if element.onFlexibleHeightChange != nil {
|
||||
element.onFlexibleHeightChange()
|
||||
}
|
||||
} else {
|
||||
bounds := element.drawer.LayoutBounds()
|
||||
element.core.SetMinimumSize(bounds.Dx(), bounds.Dy())
|
||||
|
@ -34,7 +34,7 @@ func (element *ProgressBar) SetProgress (progress float64) {
|
||||
element.progress = progress
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,9 @@ type ScrollContainer struct {
|
||||
enabled bool
|
||||
bounds image.Rectangle
|
||||
}
|
||||
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
|
||||
}
|
||||
|
||||
// NewScrollContainer creates a new scroll container with the specified scroll
|
||||
@ -52,23 +55,20 @@ func (element *ScrollContainer) Resize (width, height int) {
|
||||
func (element *ScrollContainer) Adopt (child tomo.Scrollable) {
|
||||
// disown previous child if it exists
|
||||
if element.child != nil {
|
||||
element.child.SetParentHooks (tomo.ParentHooks { })
|
||||
if previousChild, ok := element.child.(tomo.Selectable); ok {
|
||||
if previousChild.Selected() {
|
||||
previousChild.HandleDeselection()
|
||||
}
|
||||
}
|
||||
element.clearChildEventHandlers(child)
|
||||
}
|
||||
|
||||
// adopt new child
|
||||
element.child = child
|
||||
if child != nil {
|
||||
child.SetParentHooks (tomo.ParentHooks {
|
||||
// Draw: window.childDrawCallback,
|
||||
// MinimumSizeChange: window.childMinimumSizeChangeCallback,
|
||||
// FlexibleHeightChange: window.resizeChildToFit,
|
||||
// SelectionRequest: window.childSelectionRequestCallback,
|
||||
})
|
||||
child.OnDamage(element.childDamageCallback)
|
||||
child.OnMinimumSizeChange(element.updateMinimumSize)
|
||||
if newChild, ok := child.(tomo.Selectable); ok {
|
||||
newChild.OnSelectionRequest (
|
||||
element.childSelectionRequestCallback)
|
||||
newChild.OnSelectionMotionRequest (
|
||||
element.childSelectionMotionRequestCallback)
|
||||
}
|
||||
|
||||
// TODO: somehow inform the core that we do not in fact want to
|
||||
// redraw the element.
|
||||
@ -84,6 +84,104 @@ func (element *ScrollContainer) Adopt (child tomo.Scrollable) {
|
||||
}
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) HandleKeyDown (
|
||||
key tomo.Key,
|
||||
modifiers tomo.Modifiers,
|
||||
repeated bool,
|
||||
) {
|
||||
if child, ok := element.child.(tomo.KeyboardTarget); ok {
|
||||
child.HandleKeyDown(key, modifiers, repeated)
|
||||
}
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) HandleKeyUp (key tomo.Key, modifiers tomo.Modifiers) {
|
||||
if child, ok := element.child.(tomo.KeyboardTarget); ok {
|
||||
child.HandleKeyUp(key, modifiers)
|
||||
}
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) Selected () (selected bool) {
|
||||
return element.selected
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) Select () {
|
||||
if element.onSelectionRequest != nil {
|
||||
element.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) HandleSelection (
|
||||
direction tomo.SelectionDirection,
|
||||
) (
|
||||
accepted bool,
|
||||
) {
|
||||
if child, ok := element.child.(tomo.Selectable); ok {
|
||||
element.selected = true
|
||||
return child.HandleSelection(direction)
|
||||
} else {
|
||||
element.selected = false
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) HandleDeselection () {
|
||||
if child, ok := element.child.(tomo.Selectable); ok {
|
||||
child.HandleDeselection()
|
||||
}
|
||||
element.selected = false
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) OnSelectionRequest (callback func () (granted bool)) {
|
||||
element.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
element.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) childDamageCallback (region tomo.Canvas) {
|
||||
element.core.DamageRegion(artist.Paste(element, region, image.Point { }))
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) childSelectionRequestCallback () (granted bool) {
|
||||
child, ok := element.child.(tomo.Selectable)
|
||||
if !ok { return false }
|
||||
if element.onSelectionRequest != nil && element.onSelectionRequest() {
|
||||
child.HandleSelection(tomo.SelectionDirectionNeutral)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) childSelectionMotionRequestCallback (
|
||||
direction tomo.SelectionDirection,
|
||||
) (
|
||||
granted bool,
|
||||
) {
|
||||
if element.onSelectionMotionRequest == nil {
|
||||
return
|
||||
}
|
||||
return element.onSelectionMotionRequest(direction)
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) clearChildEventHandlers (child tomo.Element) {
|
||||
child.OnDamage(nil)
|
||||
child.OnMinimumSizeChange(nil)
|
||||
if child0, ok := child.(tomo.Selectable); ok {
|
||||
child0.OnSelectionRequest(nil)
|
||||
child0.OnSelectionMotionRequest(nil)
|
||||
if child0.Selected() {
|
||||
child0.HandleDeselection()
|
||||
}
|
||||
}
|
||||
if child0, ok := child.(tomo.Flexible); ok {
|
||||
child0.OnFlexibleHeightChange(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (element *ScrollContainer) recalculate () {
|
||||
horizontal := &element.horizontal
|
||||
vertical := &element.vertical
|
||||
|
@ -34,7 +34,7 @@ func (element *Spacer) SetLine (line bool) {
|
||||
element.line = line
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,9 @@ type TextBox struct {
|
||||
|
||||
onKeyDown func (tomo.Key, tomo.Modifiers, bool) (bool)
|
||||
onChange func ()
|
||||
onSelectionRequest func () (granted bool)
|
||||
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
|
||||
onScrollBoundsChange func ()
|
||||
}
|
||||
|
||||
// NewTextBox creates a new text box with the specified placeholder text, and
|
||||
@ -119,7 +122,7 @@ func (element *TextBox) HandleKeyDown (
|
||||
|
||||
if altered && element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +133,9 @@ func (element *TextBox) Selected () (selected bool) {
|
||||
}
|
||||
|
||||
func (element *TextBox) Select () {
|
||||
element.core.RequestSelection()
|
||||
if element.onSelectionRequest != nil {
|
||||
element.onSelectionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *TextBox) HandleSelection (
|
||||
@ -147,7 +152,7 @@ func (element *TextBox) HandleSelection (
|
||||
element.selected = true
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -156,16 +161,26 @@ func (element *TextBox) HandleDeselection () {
|
||||
element.selected = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *TextBox) OnSelectionRequest (callback func () (granted bool)) {
|
||||
element.onSelectionRequest = callback
|
||||
}
|
||||
|
||||
func (element *TextBox) OnSelectionMotionRequest (
|
||||
callback func (direction tomo.SelectionDirection) (granted bool),
|
||||
) {
|
||||
element.onSelectionMotionRequest = callback
|
||||
}
|
||||
|
||||
func (element *TextBox) SetEnabled (enabled bool) {
|
||||
if element.enabled == enabled { return }
|
||||
element.enabled = enabled
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +193,7 @@ func (element *TextBox) SetPlaceholder (placeholder string) {
|
||||
element.updateMinimumSize()
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,7 +210,7 @@ func (element *TextBox) SetValue (text string) {
|
||||
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,9 +261,11 @@ func (element *TextBox) ScrollTo (position image.Point) {
|
||||
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.PushAll()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
if element.onScrollBoundsChange != nil {
|
||||
element.onScrollBoundsChange()
|
||||
}
|
||||
element.core.NotifyContentBoundsChange()
|
||||
}
|
||||
|
||||
// ScrollAxes returns the supported axes for scrolling.
|
||||
@ -256,6 +273,10 @@ func (element *TextBox) ScrollAxes () (horizontal, vertical bool) {
|
||||
return true, false
|
||||
}
|
||||
|
||||
func (element *TextBox) OnScrollBoundsChange (callback func ()) {
|
||||
element.onScrollBoundsChange = callback
|
||||
}
|
||||
|
||||
func (element *TextBox) updateMinimumSize () {
|
||||
textBounds := element.placeholderDrawer.LayoutBounds()
|
||||
element.core.SetMinimumSize (
|
||||
@ -286,7 +307,9 @@ func (element *TextBox) scrollToCursor () {
|
||||
element.scroll -= minX - cursorPosition.X
|
||||
if element.scroll < 0 { element.scroll = 0 }
|
||||
}
|
||||
element.core.NotifyContentBoundsChange()
|
||||
if element.onScrollBoundsChange != nil {
|
||||
element.onScrollBoundsChange()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *TextBox) draw () {
|
||||
|
@ -17,7 +17,9 @@ type Core struct {
|
||||
|
||||
selectable bool
|
||||
selected bool
|
||||
hooks tomo.ParentHooks
|
||||
|
||||
onMinimumSizeChange func ()
|
||||
onDamage func (region tomo.Canvas)
|
||||
}
|
||||
|
||||
// NewCore creates a new element core and its corresponding control.
|
||||
@ -58,10 +60,16 @@ func (core *Core) MinimumSize () (width, height int) {
|
||||
return core.metrics.minimumWidth, core.metrics.minimumHeight
|
||||
}
|
||||
|
||||
// SetParentHooks fulfils the tomo.Element interface. This should not need to be
|
||||
// OnDamage fulfils the tomo.Element interface. This should not need to be
|
||||
// overridden.
|
||||
func (core *Core) SetParentHooks (hooks tomo.ParentHooks) {
|
||||
core.hooks = hooks
|
||||
func (core *Core) OnDamage (callback func (region tomo.Canvas)) {
|
||||
core.onDamage = callback
|
||||
}
|
||||
|
||||
// OnMinimumSizeChange fulfils the tomo.Element interface. This should not need
|
||||
// to be overridden.
|
||||
func (core *Core) OnMinimumSizeChange (callback func ()) {
|
||||
core.onMinimumSizeChange = callback
|
||||
}
|
||||
|
||||
// CoreControl is a struct that can exert control over a Core struct. It can be
|
||||
@ -73,41 +81,24 @@ type CoreControl struct {
|
||||
core *Core
|
||||
}
|
||||
|
||||
// RequestSelection requests that the element's parent send it a selection
|
||||
// event. If the request was granted, it returns true. If it was denied, it
|
||||
// returns false.
|
||||
func (control CoreControl) RequestSelection () (granted bool) {
|
||||
return control.core.hooks.RunSelectionRequest()
|
||||
}
|
||||
|
||||
// RequestSelectionMotion requests that the element's parent deselect this
|
||||
// element and select the one to the left or right of it, depending on the
|
||||
// direction. If the requests was granted, it returns true. If it was denied, it
|
||||
// returns false.
|
||||
func (control CoreControl) RequestSelectionMotion (
|
||||
direction tomo.SelectionDirection,
|
||||
) (
|
||||
granted bool,
|
||||
) {
|
||||
return control.core.hooks.RunSelectionMotionRequest(direction)
|
||||
}
|
||||
|
||||
// HasImage returns true if the core has an allocated image buffer, and false if
|
||||
// it doesn't.
|
||||
func (control CoreControl) HasImage () (has bool) {
|
||||
return !control.Bounds().Empty()
|
||||
}
|
||||
|
||||
// PushRegion pushes the selected region of pixels to the parent element. This
|
||||
// DamageRegion pushes the selected region of pixels to the parent element. This
|
||||
// does not need to be called when responding to a resize event.
|
||||
func (control CoreControl) PushRegion (bounds image.Rectangle) {
|
||||
control.core.hooks.RunDraw(tomo.Cut(control, bounds))
|
||||
func (control CoreControl) DamageRegion (bounds image.Rectangle) {
|
||||
if control.core.onDamage != nil {
|
||||
control.core.onDamage(tomo.Cut(control, bounds))
|
||||
}
|
||||
}
|
||||
|
||||
// PushAll pushes all pixels to the parent element. This does not need to be
|
||||
// DamageAll pushes all pixels to the parent element. This does not need to be
|
||||
// called when responding to a resize event.
|
||||
func (control CoreControl) PushAll () {
|
||||
control.PushRegion(control.Bounds())
|
||||
func (control CoreControl) DamageAll () {
|
||||
control.DamageRegion(control.Bounds())
|
||||
}
|
||||
|
||||
// AllocateCanvas resizes the canvas, constraining the width and height so that
|
||||
@ -128,7 +119,9 @@ func (control CoreControl) SetMinimumSize (width, height int) {
|
||||
|
||||
core.metrics.minimumWidth = width
|
||||
core.metrics.minimumHeight = height
|
||||
core.hooks.RunMinimumSizeChange(width, height)
|
||||
if control.core.onMinimumSizeChange != nil {
|
||||
control.core.onMinimumSizeChange()
|
||||
}
|
||||
|
||||
// if there is an image buffer, and the current size is less
|
||||
// than this new minimum size, send core.parent a resize event.
|
||||
@ -143,18 +136,6 @@ func (control CoreControl) SetMinimumSize (width, height int) {
|
||||
}
|
||||
}
|
||||
|
||||
// NotifyFlexibleHeightChange notifies the parent element that this element's
|
||||
// flexible height has changed.
|
||||
func (control CoreControl) NotifyFlexibleHeightChange () {
|
||||
control.core.hooks.RunFlexibleHeightChange()
|
||||
}
|
||||
|
||||
// NotifyContentBoundsChange notifies the parent element that this element's
|
||||
// inner content bounds or scroll position have changed.
|
||||
func (control CoreControl) NotifyContentBoundsChange () {
|
||||
control.core.hooks.RunContentBoundsChange()
|
||||
}
|
||||
|
||||
// ConstrainSize contstrains the specified width and height to the minimum width
|
||||
// and height, and returns wether or not anything ended up being constrained.
|
||||
func (control CoreControl) ConstrainSize (
|
||||
|
@ -54,7 +54,7 @@ func (element *Mouse) HandleMouseDown (x, y int, button tomo.Button) {
|
||||
func (element *Mouse) HandleMouseUp (x, y int, button tomo.Button) {
|
||||
element.drawing = false
|
||||
mousePos := image.Pt(x, y)
|
||||
element.core.PushRegion (artist.Line (
|
||||
element.core.DamageRegion (artist.Line (
|
||||
element.core, element.color, 1,
|
||||
element.lastMousePos, mousePos))
|
||||
element.lastMousePos = mousePos
|
||||
@ -63,10 +63,10 @@ func (element *Mouse) HandleMouseUp (x, y int, button tomo.Button) {
|
||||
func (element *Mouse) HandleMouseMove (x, y int) {
|
||||
if !element.drawing { return }
|
||||
mousePos := image.Pt(x, y)
|
||||
element.core.PushRegion (artist.Line (
|
||||
element.core.DamageRegion (artist.Line (
|
||||
element.core, element.color, 1,
|
||||
element.lastMousePos, mousePos))
|
||||
element.lastMousePos = mousePos
|
||||
}
|
||||
|
||||
func (element *Mouse) HandleScroll (x, y int, deltaX, deltaY float64) { }
|
||||
func (element *Mouse) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
|
||||
|
@ -23,8 +23,8 @@ type Layout interface {
|
||||
// needs to properly arrange the given slice of layout entries.
|
||||
MinimumSize (entries []LayoutEntry) (width, height int)
|
||||
|
||||
// MinimumHeightFor Returns the minimum height the layout needs to lay
|
||||
// FlexibleHeightFor Returns the minimum height the layout needs to lay
|
||||
// out the specified elements at the given width, taking into account
|
||||
// flexible elements.
|
||||
MinimumHeightFor (entries []LayoutEntry, squeeze int) (height int)
|
||||
FlexibleHeightFor (entries []LayoutEntry, squeeze int) (height int)
|
||||
}
|
||||
|
@ -134,7 +134,9 @@ func (layout Dialog) MinimumSize (
|
||||
return
|
||||
}
|
||||
|
||||
func (layout Dialog) MinimumHeightFor (
|
||||
// FlexibleHeightFor Returns the minimum height the layout needs to lay out the
|
||||
// specified elements at the given width, taking into account flexible elements.
|
||||
func (layout Dialog) FlexibleHeightFor (
|
||||
entries []tomo.LayoutEntry,
|
||||
width int,
|
||||
) (
|
||||
@ -147,7 +149,7 @@ func (layout Dialog) MinimumHeightFor (
|
||||
if len(entries) > 0 {
|
||||
mainChildHeight := 0
|
||||
if child, flexible := entries[0].Element.(tomo.Flexible); flexible {
|
||||
mainChildHeight = child.MinimumHeightFor(width)
|
||||
mainChildHeight = child.FlexibleHeightFor(width)
|
||||
} else {
|
||||
_, mainChildHeight = entries[0].MinimumSize()
|
||||
}
|
||||
|
@ -75,7 +75,9 @@ func (layout Horizontal) MinimumSize (
|
||||
return
|
||||
}
|
||||
|
||||
func (layout Horizontal) MinimumHeightFor (
|
||||
// FlexibleHeightFor Returns the minimum height the layout needs to lay out the
|
||||
// specified elements at the given width, taking into account flexible elements.
|
||||
func (layout Horizontal) FlexibleHeightFor (
|
||||
entries []tomo.LayoutEntry,
|
||||
width int,
|
||||
) (
|
||||
@ -100,7 +102,7 @@ func (layout Horizontal) MinimumHeightFor (
|
||||
entryWidth = expandingElementWidth
|
||||
}
|
||||
if child, flexible := entry.Element.(tomo.Flexible); flexible {
|
||||
entryHeight = child.MinimumHeightFor(entryWidth)
|
||||
entryHeight = child.FlexibleHeightFor(entryWidth)
|
||||
}
|
||||
if entryHeight > height { height = entryHeight }
|
||||
|
||||
|
@ -32,7 +32,7 @@ func (layout Vertical) Arrange (entries []tomo.LayoutEntry, width, height int) {
|
||||
var entryMinHeight int
|
||||
|
||||
if child, flexible := entry.Element.(tomo.Flexible); flexible {
|
||||
entryMinHeight = child.MinimumHeightFor(width)
|
||||
entryMinHeight = child.FlexibleHeightFor(width)
|
||||
} else {
|
||||
_, entryMinHeight = entry.MinimumSize()
|
||||
}
|
||||
@ -102,9 +102,9 @@ func (layout Vertical) MinimumSize (
|
||||
return
|
||||
}
|
||||
|
||||
// MinimumHeightFor Returns the minimum height the layout needs to lay out the
|
||||
// FlexibleHeightFor Returns the minimum height the layout needs to lay out the
|
||||
// specified elements at the given width, taking into account flexible elements.
|
||||
func (layout Vertical) MinimumHeightFor (
|
||||
func (layout Vertical) FlexibleHeightFor (
|
||||
entries []tomo.LayoutEntry,
|
||||
width int,
|
||||
) (
|
||||
@ -118,7 +118,7 @@ func (layout Vertical) MinimumHeightFor (
|
||||
for index, entry := range entries {
|
||||
child, flexible := entry.Element.(tomo.Flexible)
|
||||
if flexible {
|
||||
height += child.MinimumHeightFor(width)
|
||||
height += child.FlexibleHeightFor(width)
|
||||
} else {
|
||||
_, entryHeight := entry.MinimumSize()
|
||||
height += entryHeight
|
||||
|
Reference in New Issue
Block a user