atomize-element-interface #2
|
@ -27,6 +27,8 @@ func (window *Window) handleConfigureNotify (
|
||||||
connection *xgbutil.XUtil,
|
connection *xgbutil.XUtil,
|
||||||
event xevent.ConfigureNotifyEvent,
|
event xevent.ConfigureNotifyEvent,
|
||||||
) {
|
) {
|
||||||
|
if window.child == nil { return }
|
||||||
|
|
||||||
configureEvent := *event.ConfigureNotifyEvent
|
configureEvent := *event.ConfigureNotifyEvent
|
||||||
|
|
||||||
newWidth := int(configureEvent.Width)
|
newWidth := int(configureEvent.Width)
|
||||||
|
@ -66,33 +68,29 @@ func (window *Window) handleKeyPress (
|
||||||
NumberPad: numberPad,
|
NumberPad: numberPad,
|
||||||
}
|
}
|
||||||
|
|
||||||
keyDownEvent := tomo.EventKeyDown {
|
if key == tomo.KeyTab && modifiers.Alt {
|
||||||
Key: key,
|
if _, ok := window.child.(tomo.Selectable); ok {
|
||||||
Modifiers: modifiers,
|
direction := tomo.SelectionDirectionForward
|
||||||
Repeated: false, // FIXME: return correct value here
|
if modifiers.Shift {
|
||||||
}
|
direction = tomo.SelectionDirectionBackward
|
||||||
|
|
||||||
if keyDownEvent.Key == tomo.KeyTab && keyDownEvent.Modifiers.Alt {
|
|
||||||
if window.child.Selectable() {
|
|
||||||
direction := 1
|
|
||||||
if keyDownEvent.Modifiers.Shift {
|
|
||||||
direction = -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.advanceSelectionInChild(direction)
|
window.advanceSelectionInChild(direction)
|
||||||
}
|
}
|
||||||
} else {
|
} else if child, ok := window.child.(tomo.KeyboardTarget); ok {
|
||||||
window.child.Handle(keyDownEvent)
|
// FIXME: pass correct value for repeated
|
||||||
|
child.HandleKeyDown(key, modifiers, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (window *Window) advanceSelectionInChild (direction int) {
|
func (window *Window) advanceSelectionInChild (direction tomo.SelectionDirection) {
|
||||||
if window.child.Selected() {
|
child := window.child.(tomo.Selectable)
|
||||||
if !window.child.AdvanceSelection(direction) {
|
if child.Selected() {
|
||||||
window.child.Handle(tomo.EventDeselect { })
|
if !child.HandleSelection(direction) {
|
||||||
|
child.HandleDeselection()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
window.child.Handle(tomo.EventSelect { })
|
child.HandleSelection(tomo.SelectionDirectionNeutral)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,10 +114,9 @@ func (window *Window) handleKeyRelease (
|
||||||
NumberPad: numberPad,
|
NumberPad: numberPad,
|
||||||
}
|
}
|
||||||
|
|
||||||
window.child.Handle (tomo.EventKeyUp {
|
if child, ok := window.child.(tomo.KeyboardTarget); ok {
|
||||||
Key: key,
|
child.HandleKeyUp(key, modifiers)
|
||||||
Modifiers: modifiers,
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (window *Window) handleButtonPress (
|
func (window *Window) handleButtonPress (
|
||||||
|
@ -128,48 +125,54 @@ func (window *Window) handleButtonPress (
|
||||||
) {
|
) {
|
||||||
if window.child == nil { return }
|
if window.child == nil { return }
|
||||||
|
|
||||||
|
if child, ok := window.child.(tomo.MouseTarget); ok {
|
||||||
buttonEvent := *event.ButtonPressEvent
|
buttonEvent := *event.ButtonPressEvent
|
||||||
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 {
|
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 {
|
||||||
sum := scrollSum { }
|
sum := scrollSum { }
|
||||||
sum.add(buttonEvent.Detail)
|
sum.add(buttonEvent.Detail)
|
||||||
window.compressScrollSum(buttonEvent, &sum)
|
window.compressScrollSum(buttonEvent, &sum)
|
||||||
window.child.Handle (tomo.EventScroll {
|
child.HandleScroll (
|
||||||
X: int(buttonEvent.EventX),
|
int(buttonEvent.EventX),
|
||||||
Y: int(buttonEvent.EventY),
|
int(buttonEvent.EventY),
|
||||||
ScrollX: sum.x,
|
float64(sum.x), float64(sum.y))
|
||||||
ScrollY: sum.y,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
window.child.Handle (tomo.EventMouseDown {
|
child.HandleMouseDown (
|
||||||
Button: tomo.Button(buttonEvent.Detail),
|
int(buttonEvent.EventX),
|
||||||
X: int(buttonEvent.EventX),
|
int(buttonEvent.EventY),
|
||||||
Y: int(buttonEvent.EventY),
|
tomo.Button(buttonEvent.Detail))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (window *Window) handleButtonRelease (
|
func (window *Window) handleButtonRelease (
|
||||||
connection *xgbutil.XUtil,
|
connection *xgbutil.XUtil,
|
||||||
event xevent.ButtonReleaseEvent,
|
event xevent.ButtonReleaseEvent,
|
||||||
) {
|
) {
|
||||||
|
if window.child == nil { return }
|
||||||
|
|
||||||
|
if child, ok := window.child.(tomo.MouseTarget); ok {
|
||||||
buttonEvent := *event.ButtonReleaseEvent
|
buttonEvent := *event.ButtonReleaseEvent
|
||||||
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return }
|
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return }
|
||||||
window.child.Handle (tomo.EventMouseUp {
|
child.HandleMouseUp (
|
||||||
Button: tomo.Button(buttonEvent.Detail),
|
int(buttonEvent.EventX),
|
||||||
X: int(buttonEvent.EventX),
|
int(buttonEvent.EventY),
|
||||||
Y: int(buttonEvent.EventY),
|
tomo.Button(buttonEvent.Detail))
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (window *Window) handleMotionNotify (
|
func (window *Window) handleMotionNotify (
|
||||||
connection *xgbutil.XUtil,
|
connection *xgbutil.XUtil,
|
||||||
event xevent.MotionNotifyEvent,
|
event xevent.MotionNotifyEvent,
|
||||||
) {
|
) {
|
||||||
|
if window.child == nil { return }
|
||||||
|
|
||||||
|
if child, ok := window.child.(tomo.MouseTarget); ok {
|
||||||
motionEvent := window.compressMotionNotify(*event.MotionNotifyEvent)
|
motionEvent := window.compressMotionNotify(*event.MotionNotifyEvent)
|
||||||
window.child.Handle (tomo.EventMouseMove {
|
child.HandleMouseMove (
|
||||||
X: int(motionEvent.EventX),
|
int(motionEvent.EventX),
|
||||||
Y: int(motionEvent.EventY),
|
int(motionEvent.EventY))
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,11 @@ func (backend *Backend) NewWindow (
|
||||||
func (window *Window) Adopt (child tomo.Element) {
|
func (window *Window) Adopt (child tomo.Element) {
|
||||||
if window.child != nil {
|
if window.child != nil {
|
||||||
child.SetParentHooks (tomo.ParentHooks { })
|
child.SetParentHooks (tomo.ParentHooks { })
|
||||||
if child.Selected() { child.Handle(tomo.EventDeselect { }) }
|
if previousChild, ok := window.child.(tomo.Selectable); ok {
|
||||||
|
if previousChild.Selected() {
|
||||||
|
previousChild.HandleDeselection()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
window.child = child
|
window.child = child
|
||||||
if child != nil {
|
if child != nil {
|
||||||
|
@ -88,7 +92,6 @@ func (window *Window) Adopt (child tomo.Element) {
|
||||||
SelectionRequest: window.childSelectionRequestCallback,
|
SelectionRequest: window.childSelectionRequestCallback,
|
||||||
})
|
})
|
||||||
|
|
||||||
if child.Selectable() { child.Handle(tomo.EventSelect { }) }
|
|
||||||
window.resizeChildToFit()
|
window.resizeChildToFit()
|
||||||
}
|
}
|
||||||
window.childMinimumSizeChangeCallback(child.MinimumSize())
|
window.childMinimumSizeChangeCallback(child.MinimumSize())
|
||||||
|
@ -199,13 +202,19 @@ func (window *Window) redrawChildEntirely () {
|
||||||
|
|
||||||
func (window *Window) resizeChildToFit () {
|
func (window *Window) resizeChildToFit () {
|
||||||
window.skipChildDrawCallback = true
|
window.skipChildDrawCallback = true
|
||||||
window.child.Handle(tomo.EventResize {
|
if child, ok := window.child.(tomo.Expanding); ok {
|
||||||
Width: window.metrics.width,
|
minimumHeight := child.MinimumHeightFor(window.metrics.width)
|
||||||
Height: window.metrics.height,
|
_, minimumWidth := child.MinimumSize()
|
||||||
})
|
window.childMinimumSizeChangeCallback (
|
||||||
window.skipChildDrawCallback = false
|
minimumWidth, minimumHeight)
|
||||||
|
} else {
|
||||||
|
window.child.Resize (
|
||||||
|
window.metrics.width,
|
||||||
|
window.metrics.height)
|
||||||
window.redrawChildEntirely()
|
window.redrawChildEntirely()
|
||||||
}
|
}
|
||||||
|
window.skipChildDrawCallback = false
|
||||||
|
}
|
||||||
|
|
||||||
func (window *Window) childDrawCallback (region tomo.Canvas) {
|
func (window *Window) childDrawCallback (region tomo.Canvas) {
|
||||||
if window.skipChildDrawCallback { return }
|
if window.skipChildDrawCallback { return }
|
||||||
|
@ -246,7 +255,9 @@ func (window *Window) childMinimumSizeChangeCallback (width, height int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (window *Window) childSelectionRequestCallback () (granted bool) {
|
func (window *Window) childSelectionRequestCallback () (granted bool) {
|
||||||
window.child.Handle(tomo.EventSelect { })
|
if child, ok := window.child.(tomo.Selectable); ok {
|
||||||
|
child.HandleSelection(tomo.SelectionDirectionNeutral)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
30
element.go
30
element.go
|
@ -53,17 +53,21 @@ type Element interface {
|
||||||
// on it for the first time when sent an EventResize event.
|
// on it for the first time when sent an EventResize event.
|
||||||
Canvas
|
Canvas
|
||||||
|
|
||||||
// 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)
|
|
||||||
|
|
||||||
// MinimumSize specifies the minimum amount of pixels this element's
|
// MinimumSize specifies the minimum amount of pixels this element's
|
||||||
// width and height may be set to. If the element is given a resize
|
// 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
|
// event with dimensions smaller than this, it will use its minimum
|
||||||
// instead of the offending dimension(s).
|
// instead of the offending dimension(s).
|
||||||
MinimumSize () (width, height int)
|
MinimumSize () (width, height int)
|
||||||
|
|
||||||
|
// Resize resizes the element. This should only be called by the
|
||||||
|
// 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectionDirection represents a keyboard navigation direction.
|
// SelectionDirection represents a keyboard navigation direction.
|
||||||
|
@ -110,7 +114,7 @@ type KeyboardTarget interface {
|
||||||
|
|
||||||
// HandleKeyUp is called when a key is released while this element has
|
// HandleKeyUp is called when a key is released while this element has
|
||||||
// keyboard focus.
|
// keyboard focus.
|
||||||
HandleKeyUp (key Key)
|
HandleKeyUp (key Key, modifiers Modifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MouseTarget represents an element that can receive mouse events.
|
// MouseTarget represents an element that can receive mouse events.
|
||||||
|
@ -137,3 +141,15 @@ type MouseTarget interface {
|
||||||
// direction of the scroll event are passed as deltaX and deltaY.
|
// direction of the scroll event are passed as deltaX and deltaY.
|
||||||
HandleScroll (x, y int, deltaX, deltaY float64)
|
HandleScroll (x, y int, deltaX, deltaY float64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expanding represents an element who's minimum height can change in response
|
||||||
|
// to a change in its width.
|
||||||
|
type Expanding interface {
|
||||||
|
Element
|
||||||
|
|
||||||
|
// HeightForWidth returns what the element's minimum height would be if
|
||||||
|
// resized to the 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 used sparingly.
|
||||||
|
MinimumHeightFor (width int) (height int)
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user