restructure-config #8
@ -6,8 +6,6 @@ import "git.tebibyte.media/sashakoshka/tomo/theme"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
|
||||
var buttonCase = theme.C("basic", "button")
|
||||
|
||||
// Button is a clickable button.
|
||||
type Button struct {
|
||||
*core.Core
|
||||
@ -25,19 +23,27 @@ type Button struct {
|
||||
// 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.Core, element.core = core.NewCore (
|
||||
element.draw,
|
||||
element.redo,
|
||||
element.redo,
|
||||
theme.C("basic", "button"))
|
||||
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.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() }
|
||||
@ -83,10 +89,7 @@ func (element *Button) HandleKeyDown (key input.Key, modifiers input.Modifiers)
|
||||
func (element *Button) HandleKeyUp(key input.Key, modifiers input.Modifiers) {
|
||||
if key == input.KeyEnter && element.pressed {
|
||||
element.pressed = false
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
element.redo()
|
||||
if !element.Enabled() { return }
|
||||
if element.onClick != nil {
|
||||
element.onClick()
|
||||
@ -111,33 +114,28 @@ func (element *Button) SetText (text string) {
|
||||
element.text = text
|
||||
element.drawer.SetText([]rune(text))
|
||||
textBounds := element.drawer.LayoutBounds()
|
||||
_, inset := theme.ButtonPattern(theme.PatternState { Case: buttonCase })
|
||||
minimumSize := inset.Inverse().Apply(textBounds).Inset(-theme.Padding())
|
||||
minimumSize := textBounds.Inset(-element.core.Config().Padding())
|
||||
element.core.SetMinimumSize(minimumSize.Dx(), minimumSize.Dy())
|
||||
if element.core.HasImage () {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
element.redo()
|
||||
}
|
||||
|
||||
func (element *Button) draw () {
|
||||
bounds := element.Bounds()
|
||||
|
||||
pattern, inset := theme.ButtonPattern(theme.PatternState {
|
||||
Case: buttonCase,
|
||||
state := theme.PatternState {
|
||||
Disabled: !element.Enabled(),
|
||||
Focused: element.Focused(),
|
||||
Focused: element.Focused(),
|
||||
Pressed: element.pressed,
|
||||
})
|
||||
}
|
||||
|
||||
pattern := element.core.Pattern(theme.PatternButton, state)
|
||||
|
||||
artist.FillRectangle(element, pattern, bounds)
|
||||
|
||||
innerBounds := inset.Apply(bounds)
|
||||
|
||||
textBounds := element.drawer.LayoutBounds()
|
||||
offset := image.Point {
|
||||
X: innerBounds.Min.X + (innerBounds.Dx() - textBounds.Dx()) / 2,
|
||||
Y: innerBounds.Min.Y + (innerBounds.Dy() - textBounds.Dy()) / 2,
|
||||
X: bounds.Min.X + (bounds.Dx() - textBounds.Dx()) / 2,
|
||||
Y: bounds.Min.Y + (bounds.Dy() - textBounds.Dy()) / 2,
|
||||
}
|
||||
|
||||
// account for the fact that the bounding rectangle will be shifted over
|
||||
@ -145,9 +143,6 @@ func (element *Button) draw () {
|
||||
offset.Y -= textBounds.Min.Y
|
||||
offset.X -= textBounds.Min.X
|
||||
|
||||
foreground, _ := theme.ForegroundPattern (theme.PatternState {
|
||||
Case: buttonCase,
|
||||
Disabled: !element.Enabled(),
|
||||
})
|
||||
foreground := element.core.Pattern(theme.PatternForeground, state)
|
||||
element.drawer.Draw(element, foreground, offset)
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ import "git.tebibyte.media/sashakoshka/tomo/theme"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
|
||||
var checkboxCase = theme.C("basic", "checkbox")
|
||||
|
||||
// Checkbox is a toggle-able checkbox with a label.
|
||||
type Checkbox struct {
|
||||
*core.Core
|
||||
@ -26,19 +24,27 @@ type Checkbox struct {
|
||||
// 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.Core, element.core = core.NewCore (
|
||||
element.draw,
|
||||
element.redo,
|
||||
element.redo,
|
||||
theme.C("basic", "checkbox"))
|
||||
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.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,7 +128,7 @@ func (element *Checkbox) SetText (text string) {
|
||||
element.core.SetMinimumSize(textBounds.Dy(), textBounds.Dy())
|
||||
} else {
|
||||
element.core.SetMinimumSize (
|
||||
textBounds.Dy() + theme.Padding() + textBounds.Dx(),
|
||||
textBounds.Dy() + element.core.Config().Padding() + textBounds.Dx(),
|
||||
textBounds.Dy())
|
||||
}
|
||||
|
||||
@ -136,35 +142,27 @@ func (element *Checkbox) draw () {
|
||||
bounds := element.Bounds()
|
||||
boxBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()).Add(bounds.Min)
|
||||
|
||||
backgroundPattern, _ := theme.BackgroundPattern(theme.PatternState {
|
||||
Case: checkboxCase,
|
||||
})
|
||||
artist.FillRectangle(element, backgroundPattern, bounds)
|
||||
|
||||
pattern, inset := theme.ButtonPattern(theme.PatternState {
|
||||
Case: checkboxCase,
|
||||
state := theme.PatternState {
|
||||
Disabled: !element.Enabled(),
|
||||
Focused: element.Focused(),
|
||||
Pressed: element.pressed,
|
||||
})
|
||||
On: element.checked,
|
||||
}
|
||||
|
||||
backgroundPattern := element.core.Pattern(theme.PatternBackground, state)
|
||||
artist.FillRectangle(element, backgroundPattern, bounds)
|
||||
|
||||
pattern := element.core.Pattern (theme.PatternButton, state)
|
||||
artist.FillRectangle(element, pattern, boxBounds)
|
||||
|
||||
textBounds := element.drawer.LayoutBounds()
|
||||
offset := bounds.Min.Add(image.Point {
|
||||
X: bounds.Dy() + theme.Padding(),
|
||||
X: bounds.Dy() + element.core.Config().Padding(),
|
||||
})
|
||||
|
||||
offset.Y -= textBounds.Min.Y
|
||||
offset.X -= textBounds.Min.X
|
||||
|
||||
foreground, _ := theme.ForegroundPattern (theme.PatternState {
|
||||
Case: checkboxCase,
|
||||
Disabled: !element.Enabled(),
|
||||
})
|
||||
foreground := element.core.Pattern(theme.PatternForeground, state)
|
||||
element.drawer.Draw(element, foreground, offset)
|
||||
|
||||
if element.checked {
|
||||
checkBounds := inset.Apply(boxBounds).Inset(2)
|
||||
artist.FillRectangle(element, foreground, checkBounds)
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,6 @@ import "git.tebibyte.media/sashakoshka/tomo/layouts"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
|
||||
var containerCase = theme.C("basic", "container")
|
||||
|
||||
// Container is an element capable of containg other elements, and arranging
|
||||
// them in a layout.
|
||||
type Container struct {
|
||||
@ -33,7 +31,11 @@ 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.Core, element.core = core.NewCore (
|
||||
element.redoAll,
|
||||
element.handleConfigChange,
|
||||
element.handleThemeChange,
|
||||
theme.C("basic", "container"))
|
||||
element.SetLayout(layout)
|
||||
return
|
||||
}
|
||||
@ -205,9 +207,7 @@ func (element *Container) redoAll () {
|
||||
|
||||
// draw a background
|
||||
bounds := element.Bounds()
|
||||
pattern, _ := theme.BackgroundPattern (theme.PatternState {
|
||||
Case: containerCase,
|
||||
})
|
||||
pattern := element.core.Pattern (theme.PatternBackground, theme.PatternState { })
|
||||
artist.FillRectangle(element, pattern, bounds)
|
||||
|
||||
// cut our canvas up and give peices to child elements
|
||||
@ -216,6 +216,24 @@ func (element *Container) redoAll () {
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) handleConfigChange () {
|
||||
for _, child := range element.children {
|
||||
if child0, ok := child.Element.(elements.Configurable); ok {
|
||||
child0.SetConfig(element.core.Config())
|
||||
}
|
||||
}
|
||||
element.redoAll()
|
||||
}
|
||||
|
||||
func (element *Container) handleThemeChange () {
|
||||
for _, child := range element.children {
|
||||
if child0, ok := child.Element.(elements.Themeable); ok {
|
||||
child0.SetTheme(element.core.Theme())
|
||||
}
|
||||
}
|
||||
element.redoAll()
|
||||
}
|
||||
|
||||
func (element *Container) HandleMouseDown (x, y int, button input.Button) {
|
||||
child, handlesMouse := element.ChildAt(image.Pt(x, y)).(elements.MouseTarget)
|
||||
if !handlesMouse { return }
|
||||
@ -266,7 +284,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,
|
||||
theme.Margin(), width)
|
||||
element.core.Config().Margin(), width)
|
||||
}
|
||||
|
||||
func (element *Container) OnFlexibleHeightChange (callback func ()) {
|
||||
@ -469,15 +487,15 @@ func (element *Container) childFocusRequestCallback (
|
||||
|
||||
func (element *Container) updateMinimumSize () {
|
||||
width, height := element.layout.MinimumSize (
|
||||
element.children, theme.Margin())
|
||||
element.children, element.core.Config().Margin())
|
||||
if element.flexible {
|
||||
height = element.layout.FlexibleHeightFor (
|
||||
element.children, theme.Margin(), width)
|
||||
element.children, element.core.Config().Margin(), width)
|
||||
}
|
||||
element.core.SetMinimumSize(width, height)
|
||||
}
|
||||
|
||||
func (element *Container) recalculate () {
|
||||
element.layout.Arrange (
|
||||
element.children, theme.Margin(), element.Bounds())
|
||||
element.children, element.core.Config().Margin(), element.Bounds())
|
||||
}
|
||||
|
@ -4,8 +4,6 @@ import "git.tebibyte.media/sashakoshka/tomo/theme"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
|
||||
var labelCase = theme.C("basic", "label")
|
||||
|
||||
// Label is a simple text box.
|
||||
type Label struct {
|
||||
*core.Core
|
||||
@ -22,14 +20,35 @@ type Label struct {
|
||||
// wrapped.
|
||||
func NewLabel (text string, wrap bool) (element *Label) {
|
||||
element = &Label { }
|
||||
element.Core, element.core = core.NewCore(element.handleResize)
|
||||
face := theme.FontFaceRegular()
|
||||
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.SetWrap(wrap)
|
||||
element.SetText(text)
|
||||
return
|
||||
}
|
||||
|
||||
func (element *Label) redo () {
|
||||
face := element.core.FontFace (
|
||||
theme.FontStyleRegular,
|
||||
theme.FontSizeNormal)
|
||||
element.drawer.SetFace(face)
|
||||
element.updateMinimumSize()
|
||||
bounds := element.Bounds()
|
||||
if element.wrap {
|
||||
element.drawer.SetMaxWidth(bounds.Dx())
|
||||
element.drawer.SetMaxHeight(bounds.Dy())
|
||||
}
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
|
||||
func (element *Label) handleResize () {
|
||||
bounds := element.Bounds()
|
||||
if element.wrap {
|
||||
@ -93,7 +112,7 @@ func (element *Label) SetWrap (wrap bool) {
|
||||
func (element *Label) updateMinimumSize () {
|
||||
if element.wrap {
|
||||
em := element.drawer.Em().Round()
|
||||
if em < 1 { em = theme.Padding() }
|
||||
if em < 1 { em = element.core.Config().Padding() }
|
||||
element.core.SetMinimumSize (
|
||||
em, element.drawer.LineHeight().Round())
|
||||
if element.onFlexibleHeightChange != nil {
|
||||
@ -108,15 +127,15 @@ func (element *Label) updateMinimumSize () {
|
||||
func (element *Label) draw () {
|
||||
bounds := element.Bounds()
|
||||
|
||||
pattern, _ := theme.BackgroundPattern(theme.PatternState {
|
||||
Case: labelCase,
|
||||
})
|
||||
pattern := element.core.Pattern (
|
||||
theme.PatternBackground,
|
||||
theme.PatternState { })
|
||||
artist.FillRectangle(element, pattern, bounds)
|
||||
|
||||
textBounds := element.drawer.LayoutBounds()
|
||||
|
||||
foreground, _ := theme.ForegroundPattern (theme.PatternState {
|
||||
Case: labelCase,
|
||||
})
|
||||
foreground := element.core.Pattern (
|
||||
theme.PatternForeground,
|
||||
theme.PatternState { })
|
||||
element.drawer.Draw (element, foreground, bounds.Min.Sub(textBounds.Min))
|
||||
}
|
||||
|
@ -8,8 +8,6 @@ import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
|
||||
var listCase = theme.C("basic", "list")
|
||||
|
||||
// List is an element that contains several objects that a user can select.
|
||||
type List struct {
|
||||
*core.Core
|
||||
@ -34,7 +32,11 @@ type List struct {
|
||||
// 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.Core, element.core = core.NewCore (
|
||||
element.handleResize,
|
||||
element.redo,
|
||||
element.redo,
|
||||
theme.C("basic", "list"))
|
||||
element.FocusableCore,
|
||||
element.focusableControl = core.NewFocusableCore (func () {
|
||||
if element.core.HasImage () {
|
||||
@ -63,6 +65,36 @@ func (element *List) handleResize () {
|
||||
}
|
||||
}
|
||||
|
||||
func (element *List) handleConfigChange () {
|
||||
for index, entry := range element.entries {
|
||||
entry.SetConfig(element.core.Config())
|
||||
element.entries[index] = entry
|
||||
}
|
||||
element.redo()
|
||||
}
|
||||
|
||||
func (element *List) handleThemeChange () {
|
||||
for index, entry := range element.entries {
|
||||
entry.SetConfig(element.core.Config())
|
||||
element.entries[index] = entry
|
||||
}
|
||||
element.redo()
|
||||
}
|
||||
|
||||
func (element *List) redo () {
|
||||
for index, entry := range element.entries {
|
||||
element.entries[index] = element.resizeEntryToFit(entry)
|
||||
}
|
||||
|
||||
if element.core.HasImage() {
|
||||
element.draw()
|
||||
element.core.DamageAll()
|
||||
}
|
||||
if element.onScrollBoundsChange != nil {
|
||||
element.onScrollBoundsChange()
|
||||
}
|
||||
}
|
||||
|
||||
// Collapse forces a minimum width and height upon the list. If a zero value is
|
||||
// given for a dimension, its minimum will be determined by the list's content.
|
||||
// If the list's height goes beyond the forced size, it will need to be accessed
|
||||
@ -164,9 +196,7 @@ func (element *List) ScrollAxes () (horizontal, vertical bool) {
|
||||
}
|
||||
|
||||
func (element *List) scrollViewportHeight () (height int) {
|
||||
_, inset := theme.ListPattern(theme.PatternState {
|
||||
Case: listCase,
|
||||
})
|
||||
inset := element.core.Inset(theme.PatternSunken)
|
||||
return element.Bounds().Dy() - inset[0] - inset[2]
|
||||
}
|
||||
|
||||
@ -198,6 +228,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())
|
||||
element.entries = append(element.entries, entry)
|
||||
|
||||
// recalculate, redraw, notify
|
||||
@ -290,7 +322,7 @@ func (element *List) Replace (index int, entry ListEntry) {
|
||||
}
|
||||
|
||||
func (element *List) selectUnderMouse (x, y int) (updated bool) {
|
||||
_, inset := theme.ListPattern(theme.PatternState { })
|
||||
inset := element.core.Inset(theme.PatternSunken)
|
||||
bounds := inset.Apply(element.Bounds())
|
||||
mousePoint := image.Pt(x, y)
|
||||
dot := image.Pt (
|
||||
@ -332,9 +364,7 @@ func (element *List) changeSelectionBy (delta int) (updated bool) {
|
||||
}
|
||||
|
||||
func (element *List) resizeEntryToFit (entry ListEntry) (resized ListEntry) {
|
||||
_, inset := theme.ListPattern(theme.PatternState {
|
||||
Case: listCase,
|
||||
})
|
||||
inset := element.core.Inset(theme.PatternSunken)
|
||||
entry.Collapse(element.forcedMinimumWidth - inset[3] - inset[1])
|
||||
return entry
|
||||
}
|
||||
@ -361,9 +391,7 @@ func (element *List) updateMinimumSize () {
|
||||
minimumHeight = element.contentHeight
|
||||
}
|
||||
|
||||
_, inset := theme.ListPattern(theme.PatternState {
|
||||
Case: listCase,
|
||||
})
|
||||
inset := element.core.Inset(theme.PatternSunken)
|
||||
minimumHeight += inset[0] + inset[2]
|
||||
|
||||
element.core.SetMinimumSize(minimumWidth, minimumHeight)
|
||||
@ -372,8 +400,8 @@ func (element *List) updateMinimumSize () {
|
||||
func (element *List) draw () {
|
||||
bounds := element.Bounds()
|
||||
|
||||
pattern, inset := theme.ListPattern(theme.PatternState {
|
||||
Case: listCase,
|
||||
inset := element.core.Inset(theme.PatternSunken)
|
||||
pattern := element.core.Pattern (theme.PatternSunken, theme.PatternState {
|
||||
Disabled: !element.Enabled(),
|
||||
Focused: element.Focused(),
|
||||
})
|
||||
|
@ -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/canvas"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||
|
||||
@ -15,6 +16,8 @@ type ListEntry struct {
|
||||
text string
|
||||
forcedMinimumWidth int
|
||||
onSelect func ()
|
||||
theme theme.Theme
|
||||
config config.Config
|
||||
}
|
||||
|
||||
func NewListEntry (text string, onSelect func ()) (entry ListEntry) {
|
||||
@ -23,7 +26,6 @@ func NewListEntry (text string, onSelect func ()) (entry ListEntry) {
|
||||
onSelect: onSelect,
|
||||
}
|
||||
entry.drawer.SetText([]rune(text))
|
||||
entry.drawer.SetFace(theme.FontFaceRegular())
|
||||
entry.updateBounds()
|
||||
return
|
||||
}
|
||||
@ -34,6 +36,19 @@ func (entry *ListEntry) Collapse (width int) {
|
||||
entry.updateBounds()
|
||||
}
|
||||
|
||||
func (entry *ListEntry) SetTheme (new theme.Theme) {
|
||||
entry.theme = new
|
||||
entry.drawer.SetFace (entry.theme.FontFace (
|
||||
theme.FontStyleRegular,
|
||||
theme.FontSizeNormal,
|
||||
listEntryCase))
|
||||
entry.updateBounds()
|
||||
}
|
||||
|
||||
func (entry *ListEntry) SetConfig (config config.Config) {
|
||||
entry.config = config
|
||||
}
|
||||
|
||||
func (entry *ListEntry) updateBounds () {
|
||||
entry.bounds = image.Rectangle { }
|
||||
entry.bounds.Max.Y = entry.drawer.LineHeight().Round()
|
||||
@ -43,8 +58,7 @@ func (entry *ListEntry) updateBounds () {
|
||||
entry.bounds.Max.X = entry.drawer.LayoutBounds().Dx()
|
||||
}
|
||||
|
||||
_, inset := theme.ItemPattern(theme.PatternState {
|
||||
})
|
||||
inset := entry.theme.Inset(theme.PatternRaised, listEntryCase)
|
||||
entry.bounds.Max.Y += inset[0] + inset[2]
|
||||
|
||||
entry.textPoint =
|
||||
@ -60,20 +74,16 @@ func (entry *ListEntry) Draw (
|
||||
) (
|
||||
updatedRegion image.Rectangle,
|
||||
) {
|
||||
pattern, _ := theme.ItemPattern(theme.PatternState {
|
||||
Case: listEntryCase,
|
||||
state := theme.PatternState {
|
||||
Focused: focused,
|
||||
On: on,
|
||||
})
|
||||
}
|
||||
pattern := entry.theme.Pattern (theme.PatternRaised, listEntryCase, state)
|
||||
artist.FillRectangle (
|
||||
destination,
|
||||
pattern,
|
||||
entry.Bounds().Add(offset))
|
||||
foreground, _ := theme.ForegroundPattern (theme.PatternState {
|
||||
Case: listEntryCase,
|
||||
Focused: focused,
|
||||
On: on,
|
||||
})
|
||||
foreground := entry.theme.Pattern (theme.PatternForeground, listEntryCase, state)
|
||||
return entry.drawer.Draw (
|
||||
destination,
|
||||
foreground,
|
||||
|
@ -16,11 +16,24 @@ type ProgressBar struct {
|
||||
// level.
|
||||
func NewProgressBar (progress float64) (element *ProgressBar) {
|
||||
element = &ProgressBar { progress: progress }
|
||||
element.Core, element.core = core.NewCore(element.draw)
|
||||
element.core.SetMinimumSize(theme.Padding() * 2, theme.Padding() * 2)
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
// SetProgress sets the progress level of the bar.
|
||||
func (element *ProgressBar) SetProgress (progress float64) {
|
||||
if progress == element.progress { return }
|
||||
@ -34,13 +47,18 @@ func (element *ProgressBar) SetProgress (progress float64) {
|
||||
func (element *ProgressBar) draw () {
|
||||
bounds := element.Bounds()
|
||||
|
||||
pattern, inset := theme.SunkenPattern(theme.PatternState { })
|
||||
pattern := element.core.Pattern (
|
||||
theme.PatternSunken,
|
||||
theme.PatternState { })
|
||||
inset := element.core.Inset(theme.PatternSunken)
|
||||
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, _ := theme.AccentPattern(theme.PatternState { })
|
||||
accent := element.core.Pattern (
|
||||
theme.PatternSunken,
|
||||
theme.PatternState { })
|
||||
artist.FillRectangle(element, accent, meterBounds)
|
||||
}
|
||||
|
@ -22,27 +22,27 @@ type Core struct {
|
||||
theme theme.Theme
|
||||
c theme.Case
|
||||
|
||||
drawSizeChange func ()
|
||||
onConfigChange func ()
|
||||
onThemeChange func ()
|
||||
handleSizeChange func ()
|
||||
handleConfigChange func ()
|
||||
handleThemeChange func ()
|
||||
onMinimumSizeChange func ()
|
||||
onDamage func (region canvas.Canvas)
|
||||
}
|
||||
|
||||
// NewCore creates a new element core and its corresponding control.
|
||||
func NewCore (
|
||||
drawSizeChange func (),
|
||||
onConfigChange func (),
|
||||
onThemeChange func (),
|
||||
handleSizeChange func (),
|
||||
handleConfigChange func (),
|
||||
handleThemeChange func (),
|
||||
c theme.Case,
|
||||
) (
|
||||
core *Core,
|
||||
control CoreControl,
|
||||
) {
|
||||
core = &Core {
|
||||
drawSizeChange: drawSizeChange,
|
||||
onConfigChange: onConfigChange,
|
||||
onThemeChange: onThemeChange,
|
||||
core = &Core {
|
||||
handleSizeChange: handleSizeChange,
|
||||
handleConfigChange: handleConfigChange,
|
||||
handleThemeChange: handleThemeChange,
|
||||
c: c,
|
||||
}
|
||||
control = CoreControl { core: core }
|
||||
@ -88,8 +88,8 @@ func (core *Core) MinimumSize () (width, height int) {
|
||||
// overridden.
|
||||
func (core *Core) DrawTo (canvas canvas.Canvas) {
|
||||
core.canvas = canvas
|
||||
if core.drawSizeChange != nil {
|
||||
core.drawSizeChange()
|
||||
if core.handleSizeChange != nil {
|
||||
core.handleSizeChange()
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,8 +109,8 @@ func (core *Core) OnMinimumSizeChange (callback func ()) {
|
||||
// to be overridden.
|
||||
func (core *Core) SetConfig (config config.Config) {
|
||||
core.config = config
|
||||
if core.onConfigChange != nil {
|
||||
core.onConfigChange()
|
||||
if core.handleConfigChange != nil {
|
||||
core.handleConfigChange()
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,8 +118,8 @@ func (core *Core) SetConfig (config config.Config) {
|
||||
// to be overridden.
|
||||
func (core *Core) SetTheme (theme theme.Theme) {
|
||||
core.theme = theme
|
||||
if core.onThemeChange != nil {
|
||||
core.onThemeChange()
|
||||
if core.handleThemeChange != nil {
|
||||
core.handleThemeChange()
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user