diff --git a/elements/basic/button.go b/elements/basic/button.go index 3dc09a6..9c573ac 100644 --- a/elements/basic/button.go +++ b/elements/basic/button.go @@ -7,7 +7,9 @@ import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/artist" type Button struct { - core Core + *Core + core CoreControl + pressed bool enabled bool onClick func () @@ -18,7 +20,7 @@ type Button struct { func NewButton (text string) (element *Button) { element = &Button { enabled: true } - element.core = NewCore(element) + element.Core, element.core = NewCore(element) element.drawer.SetFace(theme.FontFaceRegular()) element.SetText(text) return @@ -94,48 +96,12 @@ func (element *Button) OnClick (callback func ()) { element.onClick = callback } -func (element *Button) ColorModel () (model color.Model) { - return color.RGBAModel -} - -func (element *Button) At (x, y int) (pixel color.Color) { - pixel = element.core.At(x, y) +func (element *Button) AdvanceSelection (direction int) (ok bool) { return } -func (element *Button) RGBAAt (x, y int) (pixel color.RGBA) { - pixel = element.core.RGBAAt(x, y) - return -} - -func (element *Button) Bounds () (bounds image.Rectangle) { - bounds = element.core.Bounds() - return -} - -func (element *Button) SetDrawCallback (draw func (region tomo.Image)) { - element.core.SetDrawCallback(draw) -} - -func (element *Button) SetMinimumSizeChangeCallback ( - notify func (width, height int), -) { - element.core.SetMinimumSizeChangeCallback(notify) -} - func (element *Button) Selectable () (selectable bool) { - selectable = true - return -} - -func (element *Button) MinimumWidth () (minimum int) { - minimum = element.core.MinimumWidth() - return -} - -func (element *Button) MinimumHeight () (minimum int) { - minimum = element.core.MinimumHeight() - return + return true } func (element *Button) draw () { diff --git a/elements/basic/core.go b/elements/basic/core.go index f37cfeb..8fe4449 100644 --- a/elements/basic/core.go +++ b/elements/basic/core.go @@ -5,24 +5,23 @@ import "image/color" import "git.tebibyte.media/sashakoshka/tomo" // Core is a struct that implements some core functionality common to most -// widgets. It is possible to embed this directly into a struct, but this is not -// reccomended as it exposes internal functionality. +// widgets. It is meant to be embedded directly into a struct. type Core struct { - *image.RGBA + canvas *image.RGBA parent tomo.Element - - drawCallback func (region tomo.Image) - minimumSizeChangeCallback func (width, height int) metrics struct { minimumWidth int minimumHeight int } + + hooks tomo.ParentHooks } -// Core creates a new element core. -func NewCore (parent tomo.Element) (core Core) { - core = Core { parent: parent } +// NewCore creates a new element core and its corresponding control. +func NewCore (parent tomo.Element) (core *Core, control CoreControl) { + core = &Core { parent: parent } + control = CoreControl { core: core } return } @@ -31,81 +30,75 @@ func (core Core) ColorModel () (model color.Model) { } func (core Core) At (x, y int) (pixel color.Color) { - if core.RGBA == nil { return color.RGBA { } } - pixel = core.RGBA.At(x, y) + if core.canvas == nil { return color.RGBA { } } + pixel = core.canvas.At(x, y) return } func (core Core) RGBAAt (x, y int) (pixel color.RGBA) { - if core.RGBA == nil { return color.RGBA { } } - pixel = core.RGBA.RGBAAt(x, y) + if core.canvas == nil { return color.RGBA { } } + pixel = core.canvas.RGBAAt(x, y) return } func (core Core) Bounds () (bounds image.Rectangle) { - if core.RGBA != nil { bounds = core.RGBA.Bounds() } + if core.canvas != nil { bounds = core.canvas.Bounds() } return } -func (core *Core) SetDrawCallback (draw func (region tomo.Image)) { - core.drawCallback = draw +func (core *Core) SetParentHooks (hooks tomo.ParentHooks) { + core.hooks = hooks } -func (core *Core) SetMinimumSizeChangeCallback ( - notify func (width, height int), -) { - core.minimumSizeChangeCallback = notify +func (core Core) MinimumSize () (width, height int) { + return core.metrics.minimumWidth, core.metrics.minimumHeight } -func (core Core) HasImage () (has bool) { - has = core.RGBA != nil +// CoreControl is a struct that can exert control over a control struct. It can +// be used as a canvas. It must not be directly embedded into an element, but +// instead kept as a private member. +type CoreControl struct { + *image.RGBA + core *Core +} + +func (control CoreControl) HasImage () (has bool) { + has = control.RGBA != nil return } -func (core Core) PushRegion (bounds image.Rectangle) { - if core.drawCallback != nil { - core.drawCallback(core.SubImage(bounds). - (*image.RGBA)) - } +func (control CoreControl) PushRegion (bounds image.Rectangle) { + core := control.core + core.hooks.RunDraw(control.SubImage(bounds).(*image.RGBA)) } -func (core Core) PushAll () { - core.PushRegion(core.Bounds()) +func (control CoreControl) PushAll () { + control.PushRegion(control.Bounds()) } -func (core *Core) AllocateCanvas (width, height int) { - width, height, _ = core.ConstrainSize(width, height) - core.RGBA = image.NewRGBA(image.Rect (0, 0, width, height)) +func (control CoreControl) AllocateCanvas (width, height int) { + core := control.core + width, height, _ = control.ConstrainSize(width, height) + core.canvas = image.NewRGBA(image.Rect (0, 0, width, height)) + control.RGBA = core.canvas } -func (core Core) MinimumWidth () (minimum int) { - minimum = core.metrics.minimumWidth - return -} - -func (core Core) MinimumHeight () (minimum int) { - minimum = core.metrics.minimumHeight - return -} - -func (core *Core) SetMinimumSize (width, height int) { +func (control CoreControl) SetMinimumSize (width, height int) { + core := control.core if width != core.metrics.minimumWidth || height != core.metrics.minimumHeight { core.metrics.minimumWidth = width core.metrics.minimumHeight = height - - if core.minimumSizeChangeCallback != nil { - core.minimumSizeChangeCallback(width, height) - } + core.hooks.RunMinimumSizeChange(width, height) // if there is an image buffer, and the current size is less // than this new minimum size, send core.parent a resize event. - if core.HasImage() { - bounds := core.Bounds() + if control.HasImage() { + bounds := control.Bounds() imageWidth, imageHeight, - constrained := core.ConstrainSize ( + constrained := control.ConstrainSize ( bounds.Dx(), bounds.Dy()) if constrained { @@ -118,12 +111,13 @@ func (core *Core) SetMinimumSize (width, height int) { } } -func (core Core) ConstrainSize ( +func (control CoreControl) ConstrainSize ( inWidth, inHeight int, ) ( outWidth, outHeight int, constrained bool, ) { + core := control.core outWidth = inWidth outHeight = inHeight if outWidth < core.metrics.minimumWidth { diff --git a/tomo.go b/tomo.go index 50ef91c..990d228 100644 --- a/tomo.go +++ b/tomo.go @@ -121,7 +121,7 @@ type Window interface { // SetIcon taks in a list different sizes of the same icon and selects // the best one to display on the window title bar, dock, or whatever is // applicable for the given backend. This method might have no effect - // with some backends. + // for some backends. SetIcon (sizes []image.Image) // Show shows the window. The window starts off hidden, so this must be