package x import "image" import "git.tebibyte.media/tomo/tomo" import "git.tebibyte.media/tomo/tomo/input" import "git.tebibyte.media/tomo/tomo/canvas" type boxSet map[anyBox] struct { } func (set boxSet) Empty () bool { return set == nil || len(set) == 0 } func (set boxSet) Has (box anyBox) bool { if set == nil { return false } _, ok := set[box] return ok } func (set *boxSet) Add (box anyBox) { if *set == nil { *set = make(boxSet) } (*set)[box] = struct { } { } } func (set *boxSet) Pop () anyBox { for box := range *set { delete(*set, box) return box } return nil } type parent interface { window () *window canvas () canvas.Canvas notifyMinimumSizeChange (anyBox) } type anyBox interface { tomo.Box doDraw () doLayout () setParent (parent) recursiveRedo () canBeFocused () bool boxUnder (image.Point) anyBox recalculateMinimumSize () handleFocusEnter () handleFocusLeave () // handleDndEnter () // handleDndLeave () // handleDndDrop (data.Data) // handleMouseEnter () // handleMouseLeave () // handleMouseMove () handleMouseDown (input.Button) handleMouseUp (input.Button) // handleScroll (float64, float64) // handleKeyDown (input.Key, bool) // handleKeyUp (input.Key, bool) } func assertAnyBox (unknown tomo.Box) anyBox { if box, ok := unknown.(anyBox); ok { return box } else { panic("foregin box implementation, i did not make this!") } } func (window *window) SetRoot (root tomo.Object) { if window.root != nil { window.root.setParent(nil) } if root == nil { window.root = nil } else { box := assertAnyBox(root.Box()) box.setParent(window) window.invalidateLayout(box) window.root = box } window.recalculateMinimumSize() } func (window *window) window () *window { return window } func (window *window) canvas () canvas.Canvas { return window.xCanvas } func (window *window) notifyMinimumSizeChange (anyBox) { window.recalculateMinimumSize() } func (window *window) invalidateDraw (box anyBox) { window.needDraw.Add(box) } func (window *window) invalidateLayout (box anyBox) { // TODO: use a priority queue for this and have the value be the amount // of parents a box has window.needLayout.Add(box) window.invalidateDraw(box) } func (window *window) focus (box anyBox) { if window.focused == box { return } previous := window.focused window.focused = box if previous != nil { window.invalidateDraw(previous) previous.handleFocusLeave() } if box != nil { window.invalidateDraw(box) box.handleFocusEnter() } } func (this *window) boxUnder (point image.Point) anyBox { if this.root == nil { return nil } return this.root.boxUnder(point) } func (window *window) afterEvent () { if window.xCanvas == nil { return } if window.needRedo { // set child bounds childBounds := window.metrics.bounds childBounds = childBounds.Sub(childBounds.Min) window.root.SetBounds(childBounds) // full relayout/redraw if window.root != nil { window.root.recursiveRedo() } window.pushAll() window.needRedo = false return } for len(window.needLayout) > 0 { window.needLayout.Pop().doLayout() } var toPush image.Rectangle for len(window.needDraw) > 0 { box := window.needDraw.Pop() box.doDraw() toPush = toPush.Union(box.Bounds()) } if !toPush.Empty() { window.pushRegion(toPush) } }