From 6936353516e412b33669df023a6efb3aa7b5c8d8 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Wed, 8 Feb 2023 00:22:40 -0500 Subject: [PATCH] asuhfdjkshlk --- elements/basic/button.go | 79 +++++++++++--------- elements/basic/checkbox.go | 72 ++++++++++++------- elements/basic/container.go | 47 +++++++----- elements/basic/label.go | 58 ++++++++++----- elements/basic/list.go | 46 +++++++----- elements/basic/listentry.go | 16 +++-- elements/basic/progressbar.go | 61 +++++++++++----- elements/basic/scrollcontainer.go | 95 ++++++++++++------------ elements/basic/spacer.go | 44 +++++++++--- elements/basic/switch.go | 104 +++++++++++++++------------ elements/basic/textbox.go | 115 ++++++++++++++++-------------- elements/core/core.go | 90 ++--------------------- 12 files changed, 448 insertions(+), 379 deletions(-) diff --git a/elements/basic/button.go b/elements/basic/button.go index d2c5899..28e8566 100644 --- a/elements/basic/button.go +++ b/elements/basic/button.go @@ -3,6 +3,7 @@ package basicElements import "image" import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/elements/core" @@ -17,51 +18,37 @@ type Button struct { pressed bool text string + config config.Config + theme theme.Theme + c theme.Case + onClick func () } // NewButton creates a new button with the specified label text. func NewButton (text string) (element *Button) { - element = &Button { } - element.Core, element.core = core.NewCore ( - element.draw, - element.redo, - element.redo, - theme.C("basic", "button")) + element = &Button { + c: theme.C("basic", "button"), + } + element.Core, element.core = core.NewCore(element.draw) element.FocusableCore, element.focusableControl = core.NewFocusableCore(element.redo) element.SetText(text) return } -func (element *Button) redo () { - element.drawer.SetFace ( - element.core.FontFace(theme.FontStyleRegular, - theme.FontSizeNormal)) - if element.core.HasImage () { - element.draw() - element.core.DamageAll() - } -} - func (element *Button) HandleMouseDown (x, y int, button input.Button) { if !element.Enabled() { return } if !element.Focused() { element.Focus() } if button != input.ButtonLeft { return } element.pressed = true - if element.core.HasImage() { - element.draw() - element.core.DamageAll() - } + element.redo() } func (element *Button) HandleMouseUp (x, y int, button input.Button) { if button != input.ButtonLeft { return } element.pressed = false - if element.core.HasImage() { - element.draw() - element.core.DamageAll() - } + element.redo() within := image.Point { x, y }. In(element.Bounds()) @@ -79,10 +66,7 @@ func (element *Button) HandleKeyDown (key input.Key, modifiers input.Modifiers) if !element.Enabled() { return } if key == input.KeyEnter { element.pressed = true - if element.core.HasImage() { - element.draw() - element.core.DamageAll() - } + element.redo() } } @@ -113,12 +97,41 @@ func (element *Button) SetText (text string) { element.text = text element.drawer.SetText([]rune(text)) - textBounds := element.drawer.LayoutBounds() - minimumSize := textBounds.Inset(-element.core.Config().Padding()) - element.core.SetMinimumSize(minimumSize.Dx(), minimumSize.Dy()) + element.updateMinimumSize() element.redo() } +// SetTheme sets the element's theme. +func (element *Button) SetTheme (new theme.Theme) { + element.theme = new + element.drawer.SetFace (element.theme.FontFace ( + theme.FontStyleRegular, + theme.FontSizeNormal, + element.c)) + element.updateMinimumSize() + element.redo() +} + +// SetConfig sets the element's configuration. +func (element *Button) SetConfig (new config.Config) { + element.config = new + element.updateMinimumSize() + element.redo() +} + +func (element *Button) updateMinimumSize () { + textBounds := element.drawer.LayoutBounds() + minimumSize := textBounds.Inset(-element.config.Padding()) + element.core.SetMinimumSize(minimumSize.Dx(), minimumSize.Dy()) +} + +func (element *Button) redo () { + if element.core.HasImage () { + element.draw() + element.core.DamageAll() + } +} + func (element *Button) draw () { bounds := element.Bounds() @@ -128,7 +141,7 @@ func (element *Button) draw () { Pressed: element.pressed, } - pattern := element.core.Pattern(theme.PatternButton, state) + pattern := element.theme.Pattern(theme.PatternButton, element.c, state) artist.FillRectangle(element, pattern, bounds) @@ -143,6 +156,6 @@ func (element *Button) draw () { offset.Y -= textBounds.Min.Y offset.X -= textBounds.Min.X - foreground := element.core.Pattern(theme.PatternForeground, state) + foreground := element.theme.Pattern(theme.PatternForeground, element.c, state) element.drawer.Draw(element, foreground, offset) } diff --git a/elements/basic/checkbox.go b/elements/basic/checkbox.go index a7ba73e..d6a7680 100644 --- a/elements/basic/checkbox.go +++ b/elements/basic/checkbox.go @@ -3,6 +3,7 @@ package basicElements import "image" import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/elements/core" @@ -18,33 +19,26 @@ type Checkbox struct { checked bool text string + config config.Config + theme theme.Theme + c theme.Case + onToggle func () } // NewCheckbox creates a new cbeckbox with the specified label text. func NewCheckbox (text string, checked bool) (element *Checkbox) { - element = &Checkbox { checked: checked } - element.Core, element.core = core.NewCore ( - element.draw, - element.redo, - element.redo, - theme.C("basic", "checkbox")) + element = &Checkbox { + checked: checked, + c: theme.C("basic", "checkbox"), + } + element.Core, element.core = core.NewCore(element.draw) element.FocusableCore, element.focusableControl = core.NewFocusableCore(element.redo) element.SetText(text) return } -func (element *Checkbox) redo () { - element.drawer.SetFace ( - element.core.FontFace(theme.FontStyleRegular, - theme.FontSizeNormal)) - if element.core.HasImage () { - element.draw() - element.core.DamageAll() - } -} - func (element *Checkbox) HandleMouseDown (x, y int, button input.Button) { if !element.Enabled() { return } element.Focus() @@ -122,16 +116,44 @@ func (element *Checkbox) SetText (text string) { element.text = text element.drawer.SetText([]rune(text)) - textBounds := element.drawer.LayoutBounds() + element.updateMinimumSize() - if text == "" { + if element.core.HasImage () { + element.draw() + element.core.DamageAll() + } +} + +// SetTheme sets the element's theme. +func (element *Checkbox) SetTheme (new theme.Theme) { + element.theme = new + element.drawer.SetFace (element.theme.FontFace ( + theme.FontStyleRegular, + theme.FontSizeNormal, + element.c)) + element.updateMinimumSize() + element.redo() +} + +// SetConfig sets the element's configuration. +func (element *Checkbox) SetConfig (new config.Config) { + element.config = new + element.updateMinimumSize() + element.redo() +} + +func (element *Checkbox) updateMinimumSize () { + textBounds := element.drawer.LayoutBounds() + if element.text == "" { element.core.SetMinimumSize(textBounds.Dy(), textBounds.Dy()) } else { element.core.SetMinimumSize ( - textBounds.Dy() + element.core.Config().Padding() + textBounds.Dx(), + textBounds.Dy() + element.config.Padding() + textBounds.Dx(), textBounds.Dy()) } - +} + +func (element *Checkbox) redo () { if element.core.HasImage () { element.draw() element.core.DamageAll() @@ -149,20 +171,22 @@ func (element *Checkbox) draw () { On: element.checked, } - backgroundPattern := element.core.Pattern(theme.PatternBackground, state) + backgroundPattern := element.theme.Pattern ( + theme.PatternBackground, element.c, state) artist.FillRectangle(element, backgroundPattern, bounds) - pattern := element.core.Pattern (theme.PatternButton, state) + pattern := element.theme.Pattern(theme.PatternButton, element.c, state) artist.FillRectangle(element, pattern, boxBounds) textBounds := element.drawer.LayoutBounds() offset := bounds.Min.Add(image.Point { - X: bounds.Dy() + element.core.Config().Padding(), + X: bounds.Dy() + element.config.Padding(), }) offset.Y -= textBounds.Min.Y offset.X -= textBounds.Min.X - foreground := element.core.Pattern(theme.PatternForeground, state) + foreground := element.theme.Pattern ( + theme.PatternForeground, element.c, state) element.drawer.Draw(element, foreground, offset) } diff --git a/elements/basic/container.go b/elements/basic/container.go index 2719208..75bf24c 100644 --- a/elements/basic/container.go +++ b/elements/basic/container.go @@ -3,6 +3,7 @@ package basicElements import "image" import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/layouts" @@ -23,6 +24,10 @@ type Container struct { focusable bool flexible bool + config config.Config + theme theme.Theme + c theme.Case + onFocusRequest func () (granted bool) onFocusMotionRequest func (input.KeynavDirection) (granted bool) onFlexibleHeightChange func () @@ -30,12 +35,10 @@ type Container struct { // NewContainer creates a new container. func NewContainer (layout layouts.Layout) (element *Container) { - element = &Container { } - element.Core, element.core = core.NewCore ( - element.redoAll, - element.handleConfigChange, - element.handleThemeChange, - theme.C("basic", "container")) + element = &Container { + c: theme.C("basic", "container"), + } + element.Core, element.core = core.NewCore(element.redoAll) element.SetLayout(layout) return } @@ -207,7 +210,10 @@ func (element *Container) redoAll () { // draw a background bounds := element.Bounds() - pattern := element.core.Pattern (theme.PatternBackground, theme.PatternState { }) + pattern := element.theme.Pattern ( + theme.PatternBackground, + element.c, + theme.PatternState { }) artist.FillRectangle(element, pattern, bounds) // cut our canvas up and give peices to child elements @@ -216,21 +222,28 @@ func (element *Container) redoAll () { } } -func (element *Container) handleConfigChange () { + +// SetTheme sets the element's theme. +func (element *Container) SetTheme (new theme.Theme) { + element.theme = new for _, child := range element.children { - if child0, ok := child.Element.(elements.Configurable); ok { - child0.SetConfig(element.core.Config()) + if child0, ok := child.Element.(elements.Themeable); ok { + child0.SetTheme(element.theme) } } + element.updateMinimumSize() element.redoAll() } -func (element *Container) handleThemeChange () { +// SetConfig sets the element's configuration. +func (element *Container) SetConfig (new config.Config) { + element.config = new for _, child := range element.children { - if child0, ok := child.Element.(elements.Themeable); ok { - child0.SetTheme(element.core.Theme()) + if child0, ok := child.Element.(elements.Configurable); ok { + child0.SetConfig(element.config) } } + element.updateMinimumSize() element.redoAll() } @@ -284,7 +297,7 @@ func (element *Container) HandleKeyUp (key input.Key, modifiers input.Modifiers) func (element *Container) FlexibleHeightFor (width int) (height int) { return element.layout.FlexibleHeightFor ( element.children, - element.core.Config().Margin(), width) + element.config.Margin(), width) } func (element *Container) OnFlexibleHeightChange (callback func ()) { @@ -487,15 +500,15 @@ func (element *Container) childFocusRequestCallback ( func (element *Container) updateMinimumSize () { width, height := element.layout.MinimumSize ( - element.children, element.core.Config().Margin()) + element.children, element.config.Margin()) if element.flexible { height = element.layout.FlexibleHeightFor ( - element.children, element.core.Config().Margin(), width) + element.children, element.config.Margin(), width) } element.core.SetMinimumSize(width, height) } func (element *Container) recalculate () { element.layout.Arrange ( - element.children, element.core.Config().Margin(), element.Bounds()) + element.children, element.config.Margin(), element.Bounds()) } diff --git a/elements/basic/label.go b/elements/basic/label.go index 2803798..1448309 100644 --- a/elements/basic/label.go +++ b/elements/basic/label.go @@ -1,6 +1,7 @@ package basicElements import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/elements/core" @@ -13,31 +14,28 @@ type Label struct { text string drawer artist.TextDrawer + config config.Config + theme theme.Theme + c theme.Case + onFlexibleHeightChange func () } // NewLabel creates a new label. If wrap is set to true, the text inside will be // wrapped. func NewLabel (text string, wrap bool) (element *Label) { - element = &Label { } - element.Core, element.core = core.NewCore ( - element.handleResize, - element.redo, - element.redo, - theme.C("basic", "label")) - face := element.core.FontFace ( - theme.FontStyleRegular, - theme.FontSizeNormal) - element.drawer.SetFace(face) + element = &Label { c: theme.C("basic", "label") } + element.Core, element.core = core.NewCore(element.handleResize) element.SetWrap(wrap) element.SetText(text) return } func (element *Label) redo () { - face := element.core.FontFace ( + face := element.theme.FontFace ( theme.FontStyleRegular, - theme.FontSizeNormal) + theme.FontSizeNormal, + element.c) element.drawer.SetFace(face) element.updateMinimumSize() bounds := element.Bounds() @@ -109,10 +107,36 @@ func (element *Label) SetWrap (wrap bool) { } } +// SetTheme sets the element's theme. +func (element *Label) SetTheme (new theme.Theme) { + element.theme = new + element.drawer.SetFace (element.theme.FontFace ( + theme.FontStyleRegular, + theme.FontSizeNormal, + element.c)) + element.updateMinimumSize() + + if element.core.HasImage () { + element.draw() + element.core.DamageAll() + } +} + +// SetConfig sets the element's configuration. +func (element *Label) SetConfig (new config.Config) { + element.config = new + element.updateMinimumSize() + + if element.core.HasImage () { + element.draw() + element.core.DamageAll() + } +} + func (element *Label) updateMinimumSize () { if element.wrap { em := element.drawer.Em().Round() - if em < 1 { em = element.core.Config().Padding() } + if em < 1 { em = element.config.Padding() } element.core.SetMinimumSize ( em, element.drawer.LineHeight().Round()) if element.onFlexibleHeightChange != nil { @@ -127,15 +151,17 @@ func (element *Label) updateMinimumSize () { func (element *Label) draw () { bounds := element.Bounds() - pattern := element.core.Pattern ( + pattern := element.theme.Pattern ( theme.PatternBackground, + element.c, theme.PatternState { }) artist.FillRectangle(element, pattern, bounds) textBounds := element.drawer.LayoutBounds() - foreground := element.core.Pattern ( + foreground := element.theme.Pattern ( theme.PatternForeground, + element.c, theme.PatternState { }) - element.drawer.Draw (element, foreground, bounds.Min.Sub(textBounds.Min)) + element.drawer.Draw(element, foreground, bounds.Min.Sub(textBounds.Min)) } diff --git a/elements/basic/list.go b/elements/basic/list.go index d76ff0b..6da55b3 100644 --- a/elements/basic/list.go +++ b/elements/basic/list.go @@ -4,6 +4,7 @@ import "fmt" import "image" import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/elements/core" @@ -25,18 +26,21 @@ type List struct { scroll int entries []ListEntry + config config.Config + theme theme.Theme + c theme.Case + onScrollBoundsChange func () onNoEntrySelected func () } // NewList creates a new list element with the specified entries. func NewList (entries ...ListEntry) (element *List) { - element = &List { selectedEntry: -1 } - element.Core, element.core = core.NewCore ( - element.handleResize, - element.redo, - element.redo, - theme.C("basic", "list")) + element = &List { + selectedEntry: -1, + c: theme.C("basic", "list"), + } + element.Core, element.core = core.NewCore(element.handleResize) element.FocusableCore, element.focusableControl = core.NewFocusableCore (func () { if element.core.HasImage () { @@ -65,19 +69,25 @@ func (element *List) handleResize () { } } -func (element *List) handleConfigChange () { +// SetTheme sets the element's theme. +func (element *List) SetTheme (new theme.Theme) { + element.theme = new for index, entry := range element.entries { - entry.SetConfig(element.core.Config()) + entry.SetConfig(element.config) element.entries[index] = entry } + element.updateMinimumSize() element.redo() } -func (element *List) handleThemeChange () { +// SetConfig sets the element's configuration. +func (element *List) SetConfig (new config.Config) { + element.config = new for index, entry := range element.entries { - entry.SetConfig(element.core.Config()) + entry.SetConfig(element.config) element.entries[index] = entry } + element.updateMinimumSize() element.redo() } @@ -196,7 +206,7 @@ func (element *List) ScrollAxes () (horizontal, vertical bool) { } func (element *List) scrollViewportHeight () (height int) { - inset := element.core.Inset(theme.PatternSunken) + inset := element.theme.Inset(theme.PatternSunken, element.c) return element.Bounds().Dy() - inset[0] - inset[2] } @@ -228,8 +238,8 @@ func (element *List) CountEntries () (count int) { func (element *List) Append (entry ListEntry) { // append entry.Collapse(element.forcedMinimumWidth) - entry.SetTheme(element.core.Theme()) - entry.SetConfig(element.core.Config()) + entry.SetTheme(element.theme) + entry.SetConfig(element.config) element.entries = append(element.entries, entry) // recalculate, redraw, notify @@ -322,7 +332,7 @@ func (element *List) Replace (index int, entry ListEntry) { } func (element *List) selectUnderMouse (x, y int) (updated bool) { - inset := element.core.Inset(theme.PatternSunken) + inset := element.theme.Inset(theme.PatternSunken, element.c) bounds := inset.Apply(element.Bounds()) mousePoint := image.Pt(x, y) dot := image.Pt ( @@ -364,7 +374,7 @@ func (element *List) changeSelectionBy (delta int) (updated bool) { } func (element *List) resizeEntryToFit (entry ListEntry) (resized ListEntry) { - inset := element.core.Inset(theme.PatternSunken) + inset := element.theme.Inset(theme.PatternSunken, element.c) entry.Collapse(element.forcedMinimumWidth - inset[3] - inset[1]) return entry } @@ -391,7 +401,7 @@ func (element *List) updateMinimumSize () { minimumHeight = element.contentHeight } - inset := element.core.Inset(theme.PatternSunken) + inset := element.theme.Inset(theme.PatternSunken, element.c) minimumHeight += inset[0] + inset[2] element.core.SetMinimumSize(minimumWidth, minimumHeight) @@ -400,8 +410,8 @@ func (element *List) updateMinimumSize () { func (element *List) draw () { bounds := element.Bounds() - inset := element.core.Inset(theme.PatternSunken) - pattern := element.core.Pattern (theme.PatternSunken, theme.PatternState { + inset := element.theme.Inset(theme.PatternSunken, element.c) + pattern := element.theme.Pattern (theme.PatternSunken, element.c, theme.PatternState { Disabled: !element.Enabled(), Focused: element.Focused(), }) diff --git a/elements/basic/listentry.go b/elements/basic/listentry.go index 60b9618..79d91d8 100644 --- a/elements/basic/listentry.go +++ b/elements/basic/listentry.go @@ -6,8 +6,6 @@ import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/artist" -var listEntryCase = theme.C("basic", "listEntry") - // ListEntry is an item that can be added to a list. type ListEntry struct { drawer artist.TextDrawer @@ -15,15 +13,19 @@ type ListEntry struct { textPoint image.Point text string forcedMinimumWidth int - onSelect func () + theme theme.Theme config config.Config + c theme.Case + + onSelect func () } func NewListEntry (text string, onSelect func ()) (entry ListEntry) { entry = ListEntry { text: text, onSelect: onSelect, + c: theme.C("basic", "listEntry"), } entry.drawer.SetText([]rune(text)) entry.updateBounds() @@ -41,7 +43,7 @@ func (entry *ListEntry) SetTheme (new theme.Theme) { entry.drawer.SetFace (entry.theme.FontFace ( theme.FontStyleRegular, theme.FontSizeNormal, - listEntryCase)) + entry.c)) entry.updateBounds() } @@ -58,7 +60,7 @@ func (entry *ListEntry) updateBounds () { entry.bounds.Max.X = entry.drawer.LayoutBounds().Dx() } - inset := entry.theme.Inset(theme.PatternRaised, listEntryCase) + inset := entry.theme.Inset(theme.PatternRaised, entry.c) entry.bounds.Max.Y += inset[0] + inset[2] entry.textPoint = @@ -78,12 +80,12 @@ func (entry *ListEntry) Draw ( Focused: focused, On: on, } - pattern := entry.theme.Pattern (theme.PatternRaised, listEntryCase, state) + pattern := entry.theme.Pattern (theme.PatternRaised, entry.c, state) artist.FillRectangle ( destination, pattern, entry.Bounds().Add(offset)) - foreground := entry.theme.Pattern (theme.PatternForeground, listEntryCase, state) + foreground := entry.theme.Pattern (theme.PatternForeground, entry.c, state) return entry.drawer.Draw ( destination, foreground, diff --git a/elements/basic/progressbar.go b/elements/basic/progressbar.go index 3545e60..80806ca 100644 --- a/elements/basic/progressbar.go +++ b/elements/basic/progressbar.go @@ -2,6 +2,7 @@ package basicElements import "image" import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/elements/core" @@ -10,28 +11,21 @@ type ProgressBar struct { *core.Core core core.CoreControl progress float64 + + theme theme.Theme + config config.Config + c theme.Case } // NewProgressBar creates a new progress bar displaying the given progress // level. func NewProgressBar (progress float64) (element *ProgressBar) { - element = &ProgressBar { progress: progress } - element.Core, element.core = core.NewCore ( - element.draw, - element.redo, - element.redo, - theme.C("basic", "progressBar")) - return -} - -func (element *ProgressBar) redo () { - element.core.SetMinimumSize ( - element.core.Config().Padding() * 2, - element.core.Config().Padding() * 2) - if element.core.HasImage() { - element.draw() - element.core.DamageAll() + element = &ProgressBar { + progress: progress, + c: theme.C("basic", "progressBar"), } + element.Core, element.core = core.NewCore(element.draw) + return } // SetProgress sets the progress level of the bar. @@ -44,21 +38,50 @@ func (element *ProgressBar) SetProgress (progress float64) { } } +// SetTheme sets the element's theme. +func (element *ProgressBar) SetTheme (new theme.Theme) { + element.theme = new + element.updateMinimumSize() + element.redo() +} + +// SetConfig sets the element's configuration. +func (element *ProgressBar) SetConfig (new config.Config) { + element.config = new + element.updateMinimumSize() + element.redo() +} + +func (element (ProgressBar)) updateMinimumSize() { + element.core.SetMinimumSize ( + element.config.Padding() * 2, + element.config.Padding() * 2) +} + +func (element *ProgressBar) redo () { + if element.core.HasImage() { + element.draw() + element.core.DamageAll() + } +} + func (element *ProgressBar) draw () { bounds := element.Bounds() - pattern := element.core.Pattern ( + pattern := element.theme.Pattern ( theme.PatternSunken, + element.c, theme.PatternState { }) - inset := element.core.Inset(theme.PatternSunken) + inset := element.theme.Inset(theme.PatternSunken, element.c) artist.FillRectangle(element, pattern, bounds) bounds = inset.Apply(bounds) meterBounds := image.Rect ( bounds.Min.X, bounds.Min.Y, bounds.Min.X + int(float64(bounds.Dx()) * element.progress), bounds.Max.Y) - accent := element.core.Pattern ( + accent := element.theme.Pattern ( theme.PatternSunken, + element.c, theme.PatternState { }) artist.FillRectangle(element, accent, meterBounds) } diff --git a/elements/basic/scrollcontainer.go b/elements/basic/scrollcontainer.go index a3ccbbb..553cc5e 100644 --- a/elements/basic/scrollcontainer.go +++ b/elements/basic/scrollcontainer.go @@ -3,15 +3,12 @@ package basicElements import "image" import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/elements" import "git.tebibyte.media/sashakoshka/tomo/elements/core" -var scrollContainerCase = theme.C("basic", "scrollContainer") -var scrollBarHorizontalCase = theme.C("basic", "scrollBarHorizontal") -var scrollBarVerticalCase = theme.C("basic", "scrollBarVertical") - // ScrollContainer is a container that is capable of holding a scrollable // element. type ScrollContainer struct { @@ -23,6 +20,7 @@ type ScrollContainer struct { childWidth, childHeight int horizontal struct { + c theme.Case exists bool enabled bool dragging bool @@ -33,6 +31,7 @@ type ScrollContainer struct { } vertical struct { + c theme.Case exists bool enabled bool dragging bool @@ -41,6 +40,10 @@ type ScrollContainer struct { track image.Rectangle bar image.Rectangle } + + theme theme.Theme + config config.Config + c theme.Case onFocusRequest func () (granted bool) onFocusMotionRequest func (input.KeynavDirection) (granted bool) @@ -49,7 +52,10 @@ type ScrollContainer struct { // NewScrollContainer creates a new scroll container with the specified scroll // bars. func NewScrollContainer (horizontal, vertical bool) (element *ScrollContainer) { - element = &ScrollContainer { } + element = &ScrollContainer { c: theme.C("basic", "scrollContainer") } + element.horizontal.c = theme.C("basic", "scrollBarHorizontal") + element.vertical.c = theme.C("basic", "scrollBarVertical") + element.Core, element.core = core.NewCore(element.handleResize) element.updateMinimumSize() element.horizontal.exists = horizontal @@ -85,8 +91,6 @@ func (element *ScrollContainer) Adopt (child elements.Scrollable) { element.childFocusMotionRequestCallback) } - // TODO: somehow inform the core that we do not in fact want to - // redraw the element. element.updateMinimumSize() element.horizontal.enabled, @@ -111,6 +115,7 @@ func (element *ScrollContainer) HandleKeyUp (key input.Key, modifiers input.Modi } func (element *ScrollContainer) HandleMouseDown (x, y int, button input.Button) { + velocity := element.config.ScrollVelocity() point := image.Pt(x, y) if point.In(element.horizontal.bar) { element.horizontal.dragging = true @@ -123,9 +128,9 @@ func (element *ScrollContainer) HandleMouseDown (x, y int, button input.Button) // FIXME: x backend and scroll container should pull these // values from the same place if x > element.horizontal.bar.Min.X { - element.scrollChildBy(16, 0) + element.scrollChildBy(velocity, 0) } else { - element.scrollChildBy(-16, 0) + element.scrollChildBy(-velocity, 0) } } else if point.In(element.vertical.bar) { @@ -137,9 +142,9 @@ func (element *ScrollContainer) HandleMouseDown (x, y int, button input.Button) } else if point.In(element.vertical.gutter) { if y > element.vertical.bar.Min.Y { - element.scrollChildBy(0, 16) + element.scrollChildBy(0, velocity) } else { - element.scrollChildBy(0, -16) + element.scrollChildBy(0, -velocity) } } else if child, ok := element.child.(elements.MouseTarget); ok { @@ -281,22 +286,19 @@ func (element *ScrollContainer) resizeChildToFit () { } func (element *ScrollContainer) recalculate () { - _, gutterInsetHorizontal := theme.GutterPattern(theme.PatternState { - Case: scrollBarHorizontalCase, - }) - _, gutterInsetVertical := theme.GutterPattern(theme.PatternState { - Case: scrollBarHorizontalCase, - }) - horizontal := &element.horizontal vertical := &element.vertical + + gutterInsetHorizontal := element.theme.Inset(theme.PatternGutter, horizontal.c) + gutterInsetVertical := element.theme.Inset(theme.PatternGutter, vertical.c) + bounds := element.Bounds() thicknessHorizontal := - theme.HandleWidth() + + element.config.HandleWidth() + gutterInsetHorizontal[3] + gutterInsetHorizontal[1] thicknessVertical := - theme.HandleWidth() + + element.config.HandleWidth() + gutterInsetVertical[3] + gutterInsetVertical[1] @@ -373,9 +375,8 @@ func (element *ScrollContainer) recalculate () { func (element *ScrollContainer) draw () { artist.Paste(element, element.child, image.Point { }) - deadPattern, _ := theme.DeadPattern(theme.PatternState { - Case: scrollContainerCase, - }) + deadPattern := element.theme.Pattern ( + theme.PatternDead, element.c, theme.PatternState { }) artist.FillRectangle ( element, deadPattern, image.Rect ( @@ -388,32 +389,30 @@ func (element *ScrollContainer) draw () { } func (element *ScrollContainer) drawHorizontalBar () { - gutterPattern, _ := theme.GutterPattern (theme.PatternState { - Case: scrollBarHorizontalCase, - Disabled: !element.horizontal.enabled, - }) - artist.FillRectangle(element, gutterPattern, element.horizontal.gutter) - - handlePattern, _ := theme.HandlePattern (theme.PatternState { - Case: scrollBarHorizontalCase, + state := theme.PatternState { Disabled: !element.horizontal.enabled, Pressed: element.horizontal.dragging, - }) + } + gutterPattern := element.theme.Pattern ( + theme.PatternGutter, element.horizontal.c, state) + artist.FillRectangle(element, gutterPattern, element.horizontal.gutter) + + handlePattern := element.theme.Pattern ( + theme.PatternHandle, element.horizontal.c, state) artist.FillRectangle(element, handlePattern, element.horizontal.bar) } func (element *ScrollContainer) drawVerticalBar () { - gutterPattern, _ := theme.GutterPattern (theme.PatternState { - Case: scrollBarVerticalCase, - Disabled: !element.vertical.enabled, - }) - artist.FillRectangle(element, gutterPattern, element.vertical.gutter) - - handlePattern, _ := theme.HandlePattern (theme.PatternState { - Case: scrollBarVerticalCase, + state := theme.PatternState { Disabled: !element.vertical.enabled, Pressed: element.vertical.dragging, - }) + } + gutterPattern := element.theme.Pattern ( + theme.PatternGutter, element.vertical.c, state) + artist.FillRectangle(element, gutterPattern, element.vertical.gutter) + + handlePattern := element.theme.Pattern ( + theme.PatternHandle, element.vertical.c, state) artist.FillRectangle(element, handlePattern, element.vertical.bar) } @@ -436,19 +435,17 @@ func (element *ScrollContainer) dragVerticalBar (mousePosition image.Point) { } func (element *ScrollContainer) updateMinimumSize () { - _, gutterInsetHorizontal := theme.GutterPattern(theme.PatternState { - Case: scrollBarHorizontalCase, - }) - _, gutterInsetVertical := theme.GutterPattern(theme.PatternState { - Case: scrollBarHorizontalCase, - }) + gutterInsetHorizontal := element.theme.Inset ( + theme.PatternGutter, element.horizontal.c) + gutterInsetVertical := element.theme.Inset ( + theme.PatternGutter, element.vertical.c) thicknessHorizontal := - theme.HandleWidth() + + element.config.HandleWidth() + gutterInsetHorizontal[3] + gutterInsetHorizontal[1] thicknessVertical := - theme.HandleWidth() + + element.config.HandleWidth() + gutterInsetVertical[3] + gutterInsetVertical[1] diff --git a/elements/basic/spacer.go b/elements/basic/spacer.go index 931087e..5588e5f 100644 --- a/elements/basic/spacer.go +++ b/elements/basic/spacer.go @@ -1,23 +1,26 @@ package basicElements import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/elements/core" -var spacerCase = theme.C("basic", "spacer") - // Spacer can be used to put space between two elements.. type Spacer struct { *core.Core core core.CoreControl line bool + + theme theme.Theme + config config.Config + c theme.Case } // NewSpacer creates a new spacer. If line is set to true, the spacer will be // filled with a line color, and if compressed to its minimum width or height, // will appear as a line. func NewSpacer (line bool) (element *Spacer) { - element = &Spacer { line: line } + element = &Spacer { line: line, c: theme.C("basic", "spacer") } element.Core, element.core = core.NewCore(element.draw) element.core.SetMinimumSize(1, 1) return @@ -33,20 +36,39 @@ func (element *Spacer) SetLine (line bool) { } } +// SetTheme sets the element's theme. +func (element *Spacer) SetTheme (new theme.Theme) { + element.theme = new + element.redo() +} + +// SetConfig sets the element's configuration. +func (element *Spacer) SetConfig (new config.Config) { + element.config = new + element.redo() +} + +func (element *Spacer) redo () { + if !element.core.HasImage() { + element.draw() + element.core.DamageAll() + } +} + func (element *Spacer) draw () { bounds := element.Bounds() if element.line { - pattern, _ := theme.ForegroundPattern(theme.PatternState { - Case: spacerCase, - Disabled: true, - }) + pattern := element.theme.Pattern ( + theme.PatternForeground, + element.c, + theme.PatternState { }) artist.FillRectangle(element, pattern, bounds) } else { - pattern, _ := theme.BackgroundPattern(theme.PatternState { - Case: spacerCase, - Disabled: true, - }) + pattern := element.theme.Pattern ( + theme.PatternBackground, + element.c, + theme.PatternState { }) artist.FillRectangle(element, pattern, bounds) } } diff --git a/elements/basic/switch.go b/elements/basic/switch.go index 8a92e4e..994b77c 100644 --- a/elements/basic/switch.go +++ b/elements/basic/switch.go @@ -3,11 +3,10 @@ package basicElements import "image" import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/elements/core" -var switchCase = theme.C("basic", "switch") - // Switch is a toggle-able on/off switch with an optional label. It is // functionally identical to Checkbox, but plays a different semantic role. type Switch struct { @@ -21,23 +20,25 @@ type Switch struct { checked bool text string + theme theme.Theme + config config.Config + c theme.Case + onToggle func () } // NewSwitch creates a new switch with the specified label text. func NewSwitch (text string, on bool) (element *Switch) { - element = &Switch { checked: on, text: text } + element = &Switch { + checked: on, + text: text, + c: theme.C("basic", "switch"), + } element.Core, element.core = core.NewCore(element.draw) element.FocusableCore, - element.focusableControl = core.NewFocusableCore (func () { - if element.core.HasImage () { - element.draw() - element.core.DamageAll() - } - }) - element.drawer.SetFace(theme.FontFaceRegular()) + element.focusableControl = core.NewFocusableCore(element.redo) element.drawer.SetText([]rune(text)) - element.calculateMinimumSize() + element.updateMinimumSize() return } @@ -45,10 +46,7 @@ func (element *Switch) HandleMouseDown (x, y int, button input.Button) { if !element.Enabled() { return } element.Focus() element.pressed = true - if element.core.HasImage() { - element.draw() - element.core.DamageAll() - } + element.redo() } func (element *Switch) HandleMouseUp (x, y int, button input.Button) { @@ -76,10 +74,7 @@ func (element *Switch) HandleMouseScroll (x, y int, deltaX, deltaY float64) { } func (element *Switch) HandleKeyDown (key input.Key, modifiers input.Modifiers) { if key == input.KeyEnter { element.pressed = true - if element.core.HasImage() { - element.draw() - element.core.DamageAll() - } + element.redo() } } @@ -87,10 +82,7 @@ func (element *Switch) HandleKeyUp (key input.Key, modifiers input.Modifiers) { if key == input.KeyEnter && element.pressed { element.pressed = false element.checked = !element.checked - if element.core.HasImage() { - element.draw() - element.core.DamageAll() - } + element.redo() if element.onToggle != nil { element.onToggle() } @@ -118,15 +110,36 @@ func (element *Switch) SetText (text string) { element.text = text element.drawer.SetText([]rune(text)) - element.calculateMinimumSize() - + element.updateMinimumSize() + element.redo() +} + +// SetTheme sets the element's theme. +func (element *Switch) SetTheme (new theme.Theme) { + element.theme = new + element.drawer.SetFace (element.theme.FontFace ( + theme.FontStyleRegular, + theme.FontSizeNormal, + element.c)) + element.updateMinimumSize() + element.redo() +} + +// SetConfig sets the element's configuration. +func (element *Switch) SetConfig (new config.Config) { + element.config = new + element.updateMinimumSize() + element.redo() +} + +func (element *Switch) redo () { if element.core.HasImage () { element.draw() element.core.DamageAll() } } -func (element *Switch) calculateMinimumSize () { +func (element *Switch) updateMinimumSize () { textBounds := element.drawer.LayoutBounds() lineHeight := element.drawer.LineHeight().Round() @@ -134,7 +147,9 @@ func (element *Switch) calculateMinimumSize () { element.core.SetMinimumSize(lineHeight * 2, lineHeight) } else { element.core.SetMinimumSize ( - lineHeight * 2 + theme.Padding() + textBounds.Dx(), + lineHeight * 2 + + element.config.Padding() + + textBounds.Dx(), lineHeight) } } @@ -143,9 +158,14 @@ func (element *Switch) draw () { bounds := element.Bounds() handleBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()).Add(bounds.Min) gutterBounds := image.Rect(0, 0, bounds.Dy() * 2, bounds.Dy()).Add(bounds.Min) - backgroundPattern, _ := theme.BackgroundPattern(theme.PatternState { - Case: switchCase, - }) + + state := theme.PatternState { + Disabled: !element.Enabled(), + Focused: element.Focused(), + Pressed: element.pressed, + } + backgroundPattern := element.theme.Pattern ( + theme.PatternBackground, element.c, state) artist.FillRectangle (element, backgroundPattern, bounds) if element.checked { @@ -162,33 +182,23 @@ func (element *Switch) draw () { } } - gutterPattern, _ := theme.GutterPattern(theme.PatternState { - Case: switchCase, - Disabled: !element.Enabled(), - Focused: element.Focused(), - Pressed: element.pressed, - }) + gutterPattern := element.theme.Pattern ( + theme.PatternGutter, element.c, state) artist.FillRectangle(element, gutterPattern, gutterBounds) - handlePattern, _ := theme.HandlePattern(theme.PatternState { - Case: switchCase, - Disabled: !element.Enabled(), - Focused: element.Focused(), - Pressed: element.pressed, - }) + handlePattern := element.theme.Pattern ( + theme.PatternHandle, element.c, state) artist.FillRectangle(element, handlePattern, handleBounds) textBounds := element.drawer.LayoutBounds() offset := bounds.Min.Add(image.Point { - X: bounds.Dy() * 2 + theme.Padding(), + X: bounds.Dy() * 2 + element.config.Padding(), }) offset.Y -= textBounds.Min.Y offset.X -= textBounds.Min.X - foreground, _ := theme.ForegroundPattern (theme.PatternState { - Case: switchCase, - Disabled: !element.Enabled(), - }) + foreground := element.theme.Pattern ( + theme.PatternForeground, element.c, state) element.drawer.Draw(element, foreground, offset) } diff --git a/elements/basic/textbox.go b/elements/basic/textbox.go index 397d84f..fbd859b 100644 --- a/elements/basic/textbox.go +++ b/elements/basic/textbox.go @@ -3,12 +3,11 @@ package basicElements import "image" import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/theme" +import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/textmanip" import "git.tebibyte.media/sashakoshka/tomo/elements/core" -var textBoxCase = theme.C("basic", "textBox") - // TextBox is a single-line text input. type TextBox struct { *core.Core @@ -24,6 +23,10 @@ type TextBox struct { placeholderDrawer artist.TextDrawer valueDrawer artist.TextDrawer + theme theme.Theme + config config.Config + c theme.Case + onKeyDown func (key input.Key, modifiers input.Modifiers) (handled bool) onChange func () onScrollBoundsChange func () @@ -33,7 +36,7 @@ type TextBox struct { // a value. When the value is empty, the placeholder will be displayed in gray // text. func NewTextBox (placeholder, value string) (element *TextBox) { - element = &TextBox { } + element = &TextBox { c: theme.C("basic", "textBox") } element.Core, element.core = core.NewCore(element.handleResize) element.FocusableCore, element.focusableControl = core.NewFocusableCore (func () { @@ -42,8 +45,6 @@ func NewTextBox (placeholder, value string) (element *TextBox) { element.core.DamageAll() } }) - element.placeholderDrawer.SetFace(theme.FontFaceRegular()) - element.valueDrawer.SetFace(theme.FontFaceRegular()) element.placeholder = placeholder element.placeholderDrawer.SetText([]rune(placeholder)) element.updateMinimumSize() @@ -130,9 +131,8 @@ func (element *TextBox) HandleKeyDown(key input.Key, modifiers input.Modifiers) element.onScrollBoundsChange() } - if altered && element.core.HasImage () { - element.draw() - element.core.DamageAll() + if altered { + element.redo() } } @@ -145,10 +145,7 @@ func (element *TextBox) SetPlaceholder (placeholder string) { element.placeholderDrawer.SetText([]rune(placeholder)) element.updateMinimumSize() - if element.core.HasImage () { - element.draw() - element.core.DamageAll() - } + element.redo() } func (element *TextBox) SetValue (text string) { @@ -161,11 +158,7 @@ func (element *TextBox) SetValue (text string) { element.cursor = element.valueDrawer.Length() } element.scrollToCursor() - - if element.core.HasImage () { - element.draw() - element.core.DamageAll() - } + element.redo() } func (element *TextBox) Value () (value string) { @@ -203,7 +196,7 @@ func (element *TextBox) ScrollViewportBounds () (bounds image.Rectangle) { } func (element *TextBox) scrollViewportWidth () (width int) { - return element.Bounds().Inset(theme.Padding()).Dx() + return element.Bounds().Inset(element.config.Padding()).Dx() } // ScrollTo scrolls the viewport to the specified point relative to @@ -218,10 +211,7 @@ func (element *TextBox) ScrollTo (position image.Point) { maxPosition := contentBounds.Max.X - element.scrollViewportWidth() if element.scroll > maxPosition { element.scroll = maxPosition } - if element.core.HasImage () { - element.draw() - element.core.DamageAll() - } + element.redo() if element.onScrollBoundsChange != nil { element.onScrollBoundsChange() } @@ -236,18 +226,6 @@ func (element *TextBox) OnScrollBoundsChange (callback func ()) { element.onScrollBoundsChange = callback } -func (element *TextBox) updateMinimumSize () { - textBounds := element.placeholderDrawer.LayoutBounds() - _, inset := theme.InputPattern(theme.PatternState { - Case: textBoxCase, - }) - element.core.SetMinimumSize ( - textBounds.Dx() + - theme.Padding() * 2 + inset[3] + inset[1], - element.placeholderDrawer.LineHeight().Round() + - theme.Padding() * 2 + inset[0] + inset[2]) -} - func (element *TextBox) runOnChange () { if element.onChange != nil { element.onChange() @@ -257,7 +235,7 @@ func (element *TextBox) runOnChange () { func (element *TextBox) scrollToCursor () { if !element.core.HasImage() { return } - bounds := element.Bounds().Inset(theme.Padding()) + bounds := element.Bounds().Inset(element.config.Padding()) bounds = bounds.Sub(bounds.Min) bounds.Max.X -= element.valueDrawer.Em().Round() cursorPosition := element.valueDrawer.PositionOf(element.cursor) @@ -272,28 +250,64 @@ func (element *TextBox) scrollToCursor () { } } +// SetTheme sets the element's theme. +func (element *TextBox) SetTheme (new theme.Theme) { + element.theme = new + face := element.theme.FontFace ( + theme.FontStyleRegular, + theme.FontSizeNormal, + element.c) + element.placeholderDrawer.SetFace(face) + element.valueDrawer.SetFace(face) + element.updateMinimumSize() + element.redo() +} + +// SetConfig sets the element's configuration. +func (element *TextBox) SetConfig (new config.Config) { + element.config = new + element.updateMinimumSize() + element.redo() +} + +func (element *TextBox) updateMinimumSize () { + textBounds := element.placeholderDrawer.LayoutBounds() + inset := element.theme.Inset(theme.PatternInput, element.c) + element.core.SetMinimumSize ( + textBounds.Dx() + + element.config.Padding() * 2 + inset[3] + inset[1], + element.placeholderDrawer.LineHeight().Round() + + element.config.Padding() * 2 + inset[0] + inset[2]) +} + +func (element *TextBox) redo () { + if element.core.HasImage () { + element.draw() + element.core.DamageAll() + } +} + func (element *TextBox) draw () { bounds := element.Bounds() // FIXME: take index into account - pattern, inset := theme.InputPattern(theme.PatternState { - Case: textBoxCase, + state := theme.PatternState { Disabled: !element.Enabled(), Focused: element.Focused(), - }) + } + pattern := element.theme.Pattern(theme.PatternSunken, element.c, state) artist.FillRectangle(element, pattern, bounds) if len(element.text) == 0 && !element.Focused() { // draw placeholder textBounds := element.placeholderDrawer.LayoutBounds() offset := bounds.Min.Add (image.Point { - X: theme.Padding() + inset[3], - Y: theme.Padding() + inset[0], - }) - foreground, _ := theme.ForegroundPattern(theme.PatternState { - Case: textBoxCase, - Disabled: true, + X: element.config.Padding(), + Y: element.config.Padding(), }) + foreground := element.theme.Pattern ( + theme.PatternForeground, element.c, + theme.PatternState { Disabled: true }) element.placeholderDrawer.Draw ( element, foreground, @@ -302,13 +316,11 @@ func (element *TextBox) draw () { // draw input value textBounds := element.valueDrawer.LayoutBounds() offset := bounds.Min.Add (image.Point { - X: theme.Padding() + inset[3] - element.scroll, - Y: theme.Padding() + inset[0], - }) - foreground, _ := theme.ForegroundPattern(theme.PatternState { - Case: textBoxCase, - Disabled: !element.Enabled(), + X: element.config.Padding() - element.scroll, + Y: element.config.Padding(), }) + foreground := element.theme.Pattern ( + theme.PatternForeground, element.c, state) element.valueDrawer.Draw ( element, foreground, @@ -318,9 +330,6 @@ func (element *TextBox) draw () { // cursor cursorPosition := element.valueDrawer.PositionOf ( element.cursor) - foreground, _ := theme.ForegroundPattern(theme.PatternState { - Case: textBoxCase, - }) artist.Line ( element, foreground, 1, diff --git a/elements/core/core.go b/elements/core/core.go index 3635c08..88fb0b5 100644 --- a/elements/core/core.go +++ b/elements/core/core.go @@ -2,11 +2,7 @@ package core import "image" import "image/color" -import "golang.org/x/image/font" -import "git.tebibyte.media/sashakoshka/tomo/theme" -import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/canvas" -import "git.tebibyte.media/sashakoshka/tomo/artist" // Core is a struct that implements some core functionality common to most // widgets. It is meant to be embedded directly into a struct. @@ -18,32 +14,20 @@ type Core struct { minimumHeight int } - config config.Config - theme theme.Theme - c theme.Case - - handleSizeChange func () - handleConfigChange func () - handleThemeChange func () + drawSizeChange func () onMinimumSizeChange func () onDamage func (region canvas.Canvas) } // NewCore creates a new element core and its corresponding control. func NewCore ( - handleSizeChange func (), - handleConfigChange func (), - handleThemeChange func (), - c theme.Case, + drawSizeChange func (), ) ( core *Core, control CoreControl, ) { core = &Core { - handleSizeChange: handleSizeChange, - handleConfigChange: handleConfigChange, - handleThemeChange: handleThemeChange, - c: c, + drawSizeChange: drawSizeChange, } control = CoreControl { core: core } return @@ -88,8 +72,8 @@ func (core *Core) MinimumSize () (width, height int) { // overridden. func (core *Core) DrawTo (canvas canvas.Canvas) { core.canvas = canvas - if core.handleSizeChange != nil { - core.handleSizeChange() + if core.drawSizeChange != nil { + core.drawSizeChange() } } @@ -105,24 +89,6 @@ func (core *Core) OnMinimumSizeChange (callback func ()) { core.onMinimumSizeChange = callback } -// SetConfig fulfills the elements.Configurable interface. This should not need -// to be overridden. -func (core *Core) SetConfig (config config.Config) { - core.config = config - if core.handleConfigChange != nil { - core.handleConfigChange() - } -} - -// SetTheme fulfills the elements.Themeable interface. This should not need -// to be overridden. -func (core *Core) SetTheme (theme theme.Theme) { - core.theme = theme - if core.handleThemeChange != nil { - core.handleThemeChange() - } -} - // CoreControl is a struct that can exert control over a Core struct. It can be // used as a canvas. It must not be directly embedded into an element, but // instead kept as a private member. When a Core struct is created, a @@ -188,49 +154,3 @@ func (control CoreControl) ConstrainSize ( } return } - -// Config returns the current configuration. -func (control CoreControl) Config () (config.Config) { - return control.core.config -} - -// Theme returns the current theme. -func (control CoreControl) Theme () (theme.Theme) { - return control.core.theme -} - -// FontFace is like Theme.FontFace, but it automatically applies the correct -// case. -func (control CoreControl) FontFace ( - style theme.FontStyle, - size theme.FontSize, -) ( - face font.Face, -) { - return control.core.theme.FontFace(style, size, control.core.c) -} - -// Icon is like Theme.Icon, but it automatically applies the correct case. -func (control CoreControl) Icon (name string) (artist.Pattern) { - return control.core.theme.Icon(name, control.core.c) -} - -// Pattern is like Theme.Pattern, but it automatically applies the correct case. -func (control CoreControl) Pattern ( - id theme.Pattern, - state theme.PatternState, -) ( - pattern artist.Pattern, -) { - return control.core.theme.Pattern(id, control.core.c, state) -} - -// Inset is like Theme.Inset, but it automatically applies the correct case. -func (control CoreControl) Inset (id theme.Pattern) (inset theme.Inset) { - return control.core.theme.Inset(id, control.core.c) -} - -// Sink is like Theme.Sink, but it automatically applies the correct case. -func (control CoreControl) Sink (id theme.Pattern) (offset image.Point) { - return control.core.theme.Sink(id, control.core.c) -}