restructure-config #8
@ -165,6 +165,7 @@ func (drawer *TextDrawer) LineHeight () (height fixed.Int26_6) {
|
|||||||
// have its maximum width set to the given width. This does not alter the
|
// have its maximum width set to the given width. This does not alter the
|
||||||
// drawer's state.
|
// drawer's state.
|
||||||
func (drawer *TextDrawer) ReccomendedHeightFor (width int) (height int) {
|
func (drawer *TextDrawer) ReccomendedHeightFor (width int) (height int) {
|
||||||
|
if drawer.face == nil { return }
|
||||||
if !drawer.layoutClean { drawer.recalculate() }
|
if !drawer.layoutClean { drawer.recalculate() }
|
||||||
metrics := drawer.face.Metrics()
|
metrics := drawer.face.Metrics()
|
||||||
dot := fixed.Point26_6 { 0, metrics.Height }
|
dot := fixed.Point26_6 { 0, metrics.Height }
|
||||||
|
@ -50,3 +50,44 @@ func (Default) ScrollVelocity () int {
|
|||||||
func (Default) ThemePath () (string) {
|
func (Default) ThemePath () (string) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapped wraps a configuration and uses Default if it is nil.
|
||||||
|
type Wrapped struct {
|
||||||
|
Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// Padding returns the amount of internal padding elements should have.
|
||||||
|
// An element's inner content (such as text) should be inset by this
|
||||||
|
// amount, in addition to the inset returned by the pattern of its
|
||||||
|
// background.
|
||||||
|
func (wrapped Wrapped) Padding () int {
|
||||||
|
return wrapped.ensure().Padding()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Margin returns how much space should be put in between elements.
|
||||||
|
func (wrapped Wrapped) Margin () int {
|
||||||
|
return wrapped.ensure().Margin()
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleWidth returns how large grab handles should typically be. This
|
||||||
|
// is important for accessibility reasons.
|
||||||
|
func (wrapped Wrapped) HandleWidth () int {
|
||||||
|
return wrapped.ensure().HandleWidth()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScrollVelocity returns how many pixels should be scrolled every time
|
||||||
|
// a scroll button is pressed.
|
||||||
|
func (wrapped Wrapped) ScrollVelocity () int {
|
||||||
|
return wrapped.ensure().ScrollVelocity()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ThemePath returns the directory path to the theme.
|
||||||
|
func (wrapped Wrapped) ThemePath () string {
|
||||||
|
return wrapped.ensure().ThemePath()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wrapped Wrapped) ensure () (real Config) {
|
||||||
|
real = wrapped.Config
|
||||||
|
if real == nil { real = Default { } }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -18,18 +18,16 @@ type Button struct {
|
|||||||
pressed bool
|
pressed bool
|
||||||
text string
|
text string
|
||||||
|
|
||||||
config config.Config
|
config config.Wrapped
|
||||||
theme theme.Theme
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
|
|
||||||
onClick func ()
|
onClick func ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewButton creates a new button with the specified label text.
|
// NewButton creates a new button with the specified label text.
|
||||||
func NewButton (text string) (element *Button) {
|
func NewButton (text string) (element *Button) {
|
||||||
element = &Button {
|
element = &Button { }
|
||||||
c: theme.C("basic", "button"),
|
element.theme.Case = theme.C("basic", "button")
|
||||||
}
|
|
||||||
element.Core, element.core = core.NewCore(element.draw)
|
element.Core, element.core = core.NewCore(element.draw)
|
||||||
element.FocusableCore,
|
element.FocusableCore,
|
||||||
element.focusableControl = core.NewFocusableCore(element.redo)
|
element.focusableControl = core.NewFocusableCore(element.redo)
|
||||||
@ -103,18 +101,19 @@ func (element *Button) SetText (text string) {
|
|||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *Button) SetTheme (new theme.Theme) {
|
func (element *Button) SetTheme (new theme.Theme) {
|
||||||
element.theme = new
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
theme.FontStyleRegular,
|
theme.FontStyleRegular,
|
||||||
theme.FontSizeNormal,
|
theme.FontSizeNormal))
|
||||||
element.c))
|
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *Button) SetConfig (new config.Config) {
|
func (element *Button) SetConfig (new config.Config) {
|
||||||
element.config = new
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
@ -141,7 +140,7 @@ func (element *Button) draw () {
|
|||||||
Pressed: element.pressed,
|
Pressed: element.pressed,
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern := element.theme.Pattern(theme.PatternButton, element.c, state)
|
pattern := element.theme.Pattern(theme.PatternButton, state)
|
||||||
|
|
||||||
artist.FillRectangle(element, pattern, bounds)
|
artist.FillRectangle(element, pattern, bounds)
|
||||||
|
|
||||||
@ -156,6 +155,10 @@ func (element *Button) draw () {
|
|||||||
offset.Y -= textBounds.Min.Y
|
offset.Y -= textBounds.Min.Y
|
||||||
offset.X -= textBounds.Min.X
|
offset.X -= textBounds.Min.X
|
||||||
|
|
||||||
foreground := element.theme.Pattern(theme.PatternForeground, element.c, state)
|
if element.pressed {
|
||||||
|
offset = offset.Add(element.theme.Sink(theme.PatternButton))
|
||||||
|
}
|
||||||
|
|
||||||
|
foreground := element.theme.Pattern(theme.PatternForeground, state)
|
||||||
element.drawer.Draw(element, foreground, offset)
|
element.drawer.Draw(element, foreground, offset)
|
||||||
}
|
}
|
||||||
|
@ -19,19 +19,16 @@ type Checkbox struct {
|
|||||||
checked bool
|
checked bool
|
||||||
text string
|
text string
|
||||||
|
|
||||||
config config.Config
|
config config.Wrapped
|
||||||
theme theme.Theme
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
|
|
||||||
onToggle func ()
|
onToggle func ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCheckbox creates a new cbeckbox with the specified label text.
|
// NewCheckbox creates a new cbeckbox with the specified label text.
|
||||||
func NewCheckbox (text string, checked bool) (element *Checkbox) {
|
func NewCheckbox (text string, checked bool) (element *Checkbox) {
|
||||||
element = &Checkbox {
|
element = &Checkbox { checked: checked }
|
||||||
checked: checked,
|
element.theme.Case = theme.C("basic", "checkbox")
|
||||||
c: theme.C("basic", "checkbox"),
|
|
||||||
}
|
|
||||||
element.Core, element.core = core.NewCore(element.draw)
|
element.Core, element.core = core.NewCore(element.draw)
|
||||||
element.FocusableCore,
|
element.FocusableCore,
|
||||||
element.focusableControl = core.NewFocusableCore(element.redo)
|
element.focusableControl = core.NewFocusableCore(element.redo)
|
||||||
@ -126,18 +123,19 @@ func (element *Checkbox) SetText (text string) {
|
|||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *Checkbox) SetTheme (new theme.Theme) {
|
func (element *Checkbox) SetTheme (new theme.Theme) {
|
||||||
element.theme = new
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
theme.FontStyleRegular,
|
theme.FontStyleRegular,
|
||||||
theme.FontSizeNormal,
|
theme.FontSizeNormal))
|
||||||
element.c))
|
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *Checkbox) SetConfig (new config.Config) {
|
func (element *Checkbox) SetConfig (new config.Config) {
|
||||||
element.config = new
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
@ -172,10 +170,10 @@ func (element *Checkbox) draw () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
backgroundPattern := element.theme.Pattern (
|
backgroundPattern := element.theme.Pattern (
|
||||||
theme.PatternBackground, element.c, state)
|
theme.PatternBackground, state)
|
||||||
artist.FillRectangle(element, backgroundPattern, bounds)
|
artist.FillRectangle(element, backgroundPattern, bounds)
|
||||||
|
|
||||||
pattern := element.theme.Pattern(theme.PatternButton, element.c, state)
|
pattern := element.theme.Pattern(theme.PatternButton, state)
|
||||||
artist.FillRectangle(element, pattern, boxBounds)
|
artist.FillRectangle(element, pattern, boxBounds)
|
||||||
|
|
||||||
textBounds := element.drawer.LayoutBounds()
|
textBounds := element.drawer.LayoutBounds()
|
||||||
@ -186,7 +184,6 @@ func (element *Checkbox) draw () {
|
|||||||
offset.Y -= textBounds.Min.Y
|
offset.Y -= textBounds.Min.Y
|
||||||
offset.X -= textBounds.Min.X
|
offset.X -= textBounds.Min.X
|
||||||
|
|
||||||
foreground := element.theme.Pattern (
|
foreground := element.theme.Pattern(theme.PatternForeground, state)
|
||||||
theme.PatternForeground, element.c, state)
|
|
||||||
element.drawer.Draw(element, foreground, offset)
|
element.drawer.Draw(element, foreground, offset)
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,8 @@ type Container struct {
|
|||||||
focusable bool
|
focusable bool
|
||||||
flexible bool
|
flexible bool
|
||||||
|
|
||||||
config config.Config
|
config config.Wrapped
|
||||||
theme theme.Theme
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
|
|
||||||
onFocusRequest func () (granted bool)
|
onFocusRequest func () (granted bool)
|
||||||
onFocusMotionRequest func (input.KeynavDirection) (granted bool)
|
onFocusMotionRequest func (input.KeynavDirection) (granted bool)
|
||||||
@ -35,9 +34,8 @@ type Container struct {
|
|||||||
|
|
||||||
// NewContainer creates a new container.
|
// NewContainer creates a new container.
|
||||||
func NewContainer (layout layouts.Layout) (element *Container) {
|
func NewContainer (layout layouts.Layout) (element *Container) {
|
||||||
element = &Container {
|
element = &Container { }
|
||||||
c: theme.C("basic", "container"),
|
element.theme.Case = theme.C("basic", "container")
|
||||||
}
|
|
||||||
element.Core, element.core = core.NewCore(element.redoAll)
|
element.Core, element.core = core.NewCore(element.redoAll)
|
||||||
element.SetLayout(layout)
|
element.SetLayout(layout)
|
||||||
return
|
return
|
||||||
@ -57,6 +55,12 @@ func (element *Container) SetLayout (layout layouts.Layout) {
|
|||||||
// whatever way is defined by the current layout.
|
// whatever way is defined by the current layout.
|
||||||
func (element *Container) Adopt (child elements.Element, expand bool) {
|
func (element *Container) Adopt (child elements.Element, expand bool) {
|
||||||
// set event handlers
|
// set event handlers
|
||||||
|
if child0, ok := child.(elements.Themeable); ok {
|
||||||
|
child0.SetTheme(element.theme.Theme)
|
||||||
|
}
|
||||||
|
if child0, ok := child.(elements.Configurable); ok {
|
||||||
|
child0.SetConfig(element.config.Config)
|
||||||
|
}
|
||||||
child.OnDamage (func (region canvas.Canvas) {
|
child.OnDamage (func (region canvas.Canvas) {
|
||||||
element.core.DamageRegion(region.Bounds())
|
element.core.DamageRegion(region.Bounds())
|
||||||
})
|
})
|
||||||
@ -212,7 +216,6 @@ func (element *Container) redoAll () {
|
|||||||
bounds := element.Bounds()
|
bounds := element.Bounds()
|
||||||
pattern := element.theme.Pattern (
|
pattern := element.theme.Pattern (
|
||||||
theme.PatternBackground,
|
theme.PatternBackground,
|
||||||
element.c,
|
|
||||||
theme.PatternState { })
|
theme.PatternState { })
|
||||||
artist.FillRectangle(element, pattern, bounds)
|
artist.FillRectangle(element, pattern, bounds)
|
||||||
|
|
||||||
@ -225,10 +228,11 @@ func (element *Container) redoAll () {
|
|||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *Container) SetTheme (new theme.Theme) {
|
func (element *Container) SetTheme (new theme.Theme) {
|
||||||
element.theme = new
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
for _, child := range element.children {
|
for _, child := range element.children {
|
||||||
if child0, ok := child.Element.(elements.Themeable); ok {
|
if child0, ok := child.Element.(elements.Themeable); ok {
|
||||||
child0.SetTheme(element.theme)
|
child0.SetTheme(element.theme.Theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
@ -237,7 +241,8 @@ func (element *Container) SetTheme (new theme.Theme) {
|
|||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *Container) SetConfig (new config.Config) {
|
func (element *Container) SetConfig (new config.Config) {
|
||||||
element.config = new
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
for _, child := range element.children {
|
for _, child := range element.children {
|
||||||
if child0, ok := child.Element.(elements.Configurable); ok {
|
if child0, ok := child.Element.(elements.Configurable); ok {
|
||||||
child0.SetConfig(element.config)
|
child0.SetConfig(element.config)
|
||||||
|
@ -14,9 +14,8 @@ type Label struct {
|
|||||||
text string
|
text string
|
||||||
drawer artist.TextDrawer
|
drawer artist.TextDrawer
|
||||||
|
|
||||||
config config.Config
|
config config.Wrapped
|
||||||
theme theme.Theme
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
|
|
||||||
onFlexibleHeightChange func ()
|
onFlexibleHeightChange func ()
|
||||||
}
|
}
|
||||||
@ -24,7 +23,8 @@ type Label struct {
|
|||||||
// NewLabel creates a new label. If wrap is set to true, the text inside will be
|
// NewLabel creates a new label. If wrap is set to true, the text inside will be
|
||||||
// wrapped.
|
// wrapped.
|
||||||
func NewLabel (text string, wrap bool) (element *Label) {
|
func NewLabel (text string, wrap bool) (element *Label) {
|
||||||
element = &Label { c: theme.C("basic", "label") }
|
element = &Label { }
|
||||||
|
element.theme.Case = theme.C("basic", "label")
|
||||||
element.Core, element.core = core.NewCore(element.handleResize)
|
element.Core, element.core = core.NewCore(element.handleResize)
|
||||||
element.SetWrap(wrap)
|
element.SetWrap(wrap)
|
||||||
element.SetText(text)
|
element.SetText(text)
|
||||||
@ -34,8 +34,7 @@ func NewLabel (text string, wrap bool) (element *Label) {
|
|||||||
func (element *Label) redo () {
|
func (element *Label) redo () {
|
||||||
face := element.theme.FontFace (
|
face := element.theme.FontFace (
|
||||||
theme.FontStyleRegular,
|
theme.FontStyleRegular,
|
||||||
theme.FontSizeNormal,
|
theme.FontSizeNormal)
|
||||||
element.c)
|
|
||||||
element.drawer.SetFace(face)
|
element.drawer.SetFace(face)
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
bounds := element.Bounds()
|
bounds := element.Bounds()
|
||||||
@ -109,11 +108,11 @@ func (element *Label) SetWrap (wrap bool) {
|
|||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *Label) SetTheme (new theme.Theme) {
|
func (element *Label) SetTheme (new theme.Theme) {
|
||||||
element.theme = new
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
theme.FontStyleRegular,
|
theme.FontStyleRegular,
|
||||||
theme.FontSizeNormal,
|
theme.FontSizeNormal))
|
||||||
element.c))
|
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
|
|
||||||
if element.core.HasImage () {
|
if element.core.HasImage () {
|
||||||
@ -124,7 +123,8 @@ func (element *Label) SetTheme (new theme.Theme) {
|
|||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *Label) SetConfig (new config.Config) {
|
func (element *Label) SetConfig (new config.Config) {
|
||||||
element.config = new
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
|
|
||||||
if element.core.HasImage () {
|
if element.core.HasImage () {
|
||||||
@ -153,7 +153,6 @@ func (element *Label) draw () {
|
|||||||
|
|
||||||
pattern := element.theme.Pattern (
|
pattern := element.theme.Pattern (
|
||||||
theme.PatternBackground,
|
theme.PatternBackground,
|
||||||
element.c,
|
|
||||||
theme.PatternState { })
|
theme.PatternState { })
|
||||||
artist.FillRectangle(element, pattern, bounds)
|
artist.FillRectangle(element, pattern, bounds)
|
||||||
|
|
||||||
@ -161,7 +160,6 @@ func (element *Label) draw () {
|
|||||||
|
|
||||||
foreground := element.theme.Pattern (
|
foreground := element.theme.Pattern (
|
||||||
theme.PatternForeground,
|
theme.PatternForeground,
|
||||||
element.c,
|
|
||||||
theme.PatternState { })
|
theme.PatternState { })
|
||||||
element.drawer.Draw(element, foreground, bounds.Min.Sub(textBounds.Min))
|
element.drawer.Draw(element, foreground, bounds.Min.Sub(textBounds.Min))
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,8 @@ type List struct {
|
|||||||
scroll int
|
scroll int
|
||||||
entries []ListEntry
|
entries []ListEntry
|
||||||
|
|
||||||
config config.Config
|
config config.Wrapped
|
||||||
theme theme.Theme
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
|
|
||||||
onScrollBoundsChange func ()
|
onScrollBoundsChange func ()
|
||||||
onNoEntrySelected func ()
|
onNoEntrySelected func ()
|
||||||
@ -36,10 +35,8 @@ type List struct {
|
|||||||
|
|
||||||
// NewList creates a new list element with the specified entries.
|
// NewList creates a new list element with the specified entries.
|
||||||
func NewList (entries ...ListEntry) (element *List) {
|
func NewList (entries ...ListEntry) (element *List) {
|
||||||
element = &List {
|
element = &List { selectedEntry: -1 }
|
||||||
selectedEntry: -1,
|
element.theme.Case = theme.C("basic", "list")
|
||||||
c: theme.C("basic", "list"),
|
|
||||||
}
|
|
||||||
element.Core, element.core = core.NewCore(element.handleResize)
|
element.Core, element.core = core.NewCore(element.handleResize)
|
||||||
element.FocusableCore,
|
element.FocusableCore,
|
||||||
element.focusableControl = core.NewFocusableCore (func () {
|
element.focusableControl = core.NewFocusableCore (func () {
|
||||||
@ -71,9 +68,10 @@ func (element *List) handleResize () {
|
|||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *List) SetTheme (new theme.Theme) {
|
func (element *List) SetTheme (new theme.Theme) {
|
||||||
element.theme = new
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
for index, entry := range element.entries {
|
for index, entry := range element.entries {
|
||||||
entry.SetConfig(element.config)
|
entry.SetTheme(element.theme.Theme)
|
||||||
element.entries[index] = entry
|
element.entries[index] = entry
|
||||||
}
|
}
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
@ -82,7 +80,8 @@ func (element *List) SetTheme (new theme.Theme) {
|
|||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *List) SetConfig (new config.Config) {
|
func (element *List) SetConfig (new config.Config) {
|
||||||
element.config = new
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
for index, entry := range element.entries {
|
for index, entry := range element.entries {
|
||||||
entry.SetConfig(element.config)
|
entry.SetConfig(element.config)
|
||||||
element.entries[index] = entry
|
element.entries[index] = entry
|
||||||
@ -206,7 +205,7 @@ func (element *List) ScrollAxes () (horizontal, vertical bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (element *List) scrollViewportHeight () (height int) {
|
func (element *List) scrollViewportHeight () (height int) {
|
||||||
inset := element.theme.Inset(theme.PatternSunken, element.c)
|
inset := element.theme.Inset(theme.PatternSunken)
|
||||||
return element.Bounds().Dy() - inset[0] - inset[2]
|
return element.Bounds().Dy() - inset[0] - inset[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +237,7 @@ func (element *List) CountEntries () (count int) {
|
|||||||
func (element *List) Append (entry ListEntry) {
|
func (element *List) Append (entry ListEntry) {
|
||||||
// append
|
// append
|
||||||
entry.Collapse(element.forcedMinimumWidth)
|
entry.Collapse(element.forcedMinimumWidth)
|
||||||
entry.SetTheme(element.theme)
|
entry.SetTheme(element.theme.Theme)
|
||||||
entry.SetConfig(element.config)
|
entry.SetConfig(element.config)
|
||||||
element.entries = append(element.entries, entry)
|
element.entries = append(element.entries, entry)
|
||||||
|
|
||||||
@ -332,7 +331,7 @@ func (element *List) Replace (index int, entry ListEntry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (element *List) selectUnderMouse (x, y int) (updated bool) {
|
func (element *List) selectUnderMouse (x, y int) (updated bool) {
|
||||||
inset := element.theme.Inset(theme.PatternSunken, element.c)
|
inset := element.theme.Inset(theme.PatternSunken)
|
||||||
bounds := inset.Apply(element.Bounds())
|
bounds := inset.Apply(element.Bounds())
|
||||||
mousePoint := image.Pt(x, y)
|
mousePoint := image.Pt(x, y)
|
||||||
dot := image.Pt (
|
dot := image.Pt (
|
||||||
@ -374,7 +373,7 @@ func (element *List) changeSelectionBy (delta int) (updated bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (element *List) resizeEntryToFit (entry ListEntry) (resized ListEntry) {
|
func (element *List) resizeEntryToFit (entry ListEntry) (resized ListEntry) {
|
||||||
inset := element.theme.Inset(theme.PatternSunken, element.c)
|
inset := element.theme.Inset(theme.PatternSunken)
|
||||||
entry.Collapse(element.forcedMinimumWidth - inset[3] - inset[1])
|
entry.Collapse(element.forcedMinimumWidth - inset[3] - inset[1])
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
@ -401,7 +400,7 @@ func (element *List) updateMinimumSize () {
|
|||||||
minimumHeight = element.contentHeight
|
minimumHeight = element.contentHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
inset := element.theme.Inset(theme.PatternSunken, element.c)
|
inset := element.theme.Inset(theme.PatternSunken)
|
||||||
minimumHeight += inset[0] + inset[2]
|
minimumHeight += inset[0] + inset[2]
|
||||||
|
|
||||||
element.core.SetMinimumSize(minimumWidth, minimumHeight)
|
element.core.SetMinimumSize(minimumWidth, minimumHeight)
|
||||||
@ -410,8 +409,8 @@ func (element *List) updateMinimumSize () {
|
|||||||
func (element *List) draw () {
|
func (element *List) draw () {
|
||||||
bounds := element.Bounds()
|
bounds := element.Bounds()
|
||||||
|
|
||||||
inset := element.theme.Inset(theme.PatternSunken, element.c)
|
inset := element.theme.Inset(theme.PatternSunken)
|
||||||
pattern := element.theme.Pattern (theme.PatternSunken, element.c, theme.PatternState {
|
pattern := element.theme.Pattern (theme.PatternSunken, theme.PatternState {
|
||||||
Disabled: !element.Enabled(),
|
Disabled: !element.Enabled(),
|
||||||
Focused: element.Focused(),
|
Focused: element.Focused(),
|
||||||
})
|
})
|
||||||
|
@ -14,9 +14,8 @@ type ListEntry struct {
|
|||||||
text string
|
text string
|
||||||
forcedMinimumWidth int
|
forcedMinimumWidth int
|
||||||
|
|
||||||
theme theme.Theme
|
config config.Wrapped
|
||||||
config config.Config
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
|
|
||||||
onSelect func ()
|
onSelect func ()
|
||||||
}
|
}
|
||||||
@ -25,8 +24,8 @@ func NewListEntry (text string, onSelect func ()) (entry ListEntry) {
|
|||||||
entry = ListEntry {
|
entry = ListEntry {
|
||||||
text: text,
|
text: text,
|
||||||
onSelect: onSelect,
|
onSelect: onSelect,
|
||||||
c: theme.C("basic", "listEntry"),
|
|
||||||
}
|
}
|
||||||
|
entry.theme.Case = theme.C("basic", "listEntry")
|
||||||
entry.drawer.SetText([]rune(text))
|
entry.drawer.SetText([]rune(text))
|
||||||
entry.updateBounds()
|
entry.updateBounds()
|
||||||
return
|
return
|
||||||
@ -39,16 +38,17 @@ func (entry *ListEntry) Collapse (width int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (entry *ListEntry) SetTheme (new theme.Theme) {
|
func (entry *ListEntry) SetTheme (new theme.Theme) {
|
||||||
entry.theme = new
|
if new == entry.theme.Theme { return }
|
||||||
|
entry.theme.Theme = new
|
||||||
entry.drawer.SetFace (entry.theme.FontFace (
|
entry.drawer.SetFace (entry.theme.FontFace (
|
||||||
theme.FontStyleRegular,
|
theme.FontStyleRegular,
|
||||||
theme.FontSizeNormal,
|
theme.FontSizeNormal))
|
||||||
entry.c))
|
|
||||||
entry.updateBounds()
|
entry.updateBounds()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *ListEntry) SetConfig (config config.Config) {
|
func (entry *ListEntry) SetConfig (new config.Config) {
|
||||||
entry.config = config
|
if new == entry.config.Config { return }
|
||||||
|
entry.config.Config = new
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *ListEntry) updateBounds () {
|
func (entry *ListEntry) updateBounds () {
|
||||||
@ -60,7 +60,7 @@ func (entry *ListEntry) updateBounds () {
|
|||||||
entry.bounds.Max.X = entry.drawer.LayoutBounds().Dx()
|
entry.bounds.Max.X = entry.drawer.LayoutBounds().Dx()
|
||||||
}
|
}
|
||||||
|
|
||||||
inset := entry.theme.Inset(theme.PatternRaised, entry.c)
|
inset := entry.theme.Inset(theme.PatternRaised)
|
||||||
entry.bounds.Max.Y += inset[0] + inset[2]
|
entry.bounds.Max.Y += inset[0] + inset[2]
|
||||||
|
|
||||||
entry.textPoint =
|
entry.textPoint =
|
||||||
@ -80,12 +80,12 @@ func (entry *ListEntry) Draw (
|
|||||||
Focused: focused,
|
Focused: focused,
|
||||||
On: on,
|
On: on,
|
||||||
}
|
}
|
||||||
pattern := entry.theme.Pattern (theme.PatternRaised, entry.c, state)
|
pattern := entry.theme.Pattern (theme.PatternRaised, state)
|
||||||
artist.FillRectangle (
|
artist.FillRectangle (
|
||||||
destination,
|
destination,
|
||||||
pattern,
|
pattern,
|
||||||
entry.Bounds().Add(offset))
|
entry.Bounds().Add(offset))
|
||||||
foreground := entry.theme.Pattern (theme.PatternForeground, entry.c, state)
|
foreground := entry.theme.Pattern (theme.PatternForeground, state)
|
||||||
return entry.drawer.Draw (
|
return entry.drawer.Draw (
|
||||||
destination,
|
destination,
|
||||||
foreground,
|
foreground,
|
||||||
|
@ -12,18 +12,15 @@ type ProgressBar struct {
|
|||||||
core core.CoreControl
|
core core.CoreControl
|
||||||
progress float64
|
progress float64
|
||||||
|
|
||||||
theme theme.Theme
|
config config.Wrapped
|
||||||
config config.Config
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProgressBar creates a new progress bar displaying the given progress
|
// NewProgressBar creates a new progress bar displaying the given progress
|
||||||
// level.
|
// level.
|
||||||
func NewProgressBar (progress float64) (element *ProgressBar) {
|
func NewProgressBar (progress float64) (element *ProgressBar) {
|
||||||
element = &ProgressBar {
|
element = &ProgressBar { progress: progress }
|
||||||
progress: progress,
|
element.theme.Case = theme.C("basic", "progressBar")
|
||||||
c: theme.C("basic", "progressBar"),
|
|
||||||
}
|
|
||||||
element.Core, element.core = core.NewCore(element.draw)
|
element.Core, element.core = core.NewCore(element.draw)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -40,14 +37,16 @@ func (element *ProgressBar) SetProgress (progress float64) {
|
|||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *ProgressBar) SetTheme (new theme.Theme) {
|
func (element *ProgressBar) SetTheme (new theme.Theme) {
|
||||||
element.theme = new
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *ProgressBar) SetConfig (new config.Config) {
|
func (element *ProgressBar) SetConfig (new config.Config) {
|
||||||
element.config = new
|
if new == nil || new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
@ -70,9 +69,8 @@ func (element *ProgressBar) draw () {
|
|||||||
|
|
||||||
pattern := element.theme.Pattern (
|
pattern := element.theme.Pattern (
|
||||||
theme.PatternSunken,
|
theme.PatternSunken,
|
||||||
element.c,
|
|
||||||
theme.PatternState { })
|
theme.PatternState { })
|
||||||
inset := element.theme.Inset(theme.PatternSunken, element.c)
|
inset := element.theme.Inset(theme.PatternSunken)
|
||||||
artist.FillRectangle(element, pattern, bounds)
|
artist.FillRectangle(element, pattern, bounds)
|
||||||
bounds = inset.Apply(bounds)
|
bounds = inset.Apply(bounds)
|
||||||
meterBounds := image.Rect (
|
meterBounds := image.Rect (
|
||||||
@ -80,8 +78,7 @@ func (element *ProgressBar) draw () {
|
|||||||
bounds.Min.X + int(float64(bounds.Dx()) * element.progress),
|
bounds.Min.X + int(float64(bounds.Dx()) * element.progress),
|
||||||
bounds.Max.Y)
|
bounds.Max.Y)
|
||||||
accent := element.theme.Pattern (
|
accent := element.theme.Pattern (
|
||||||
theme.PatternSunken,
|
theme.PatternAccent,
|
||||||
element.c,
|
|
||||||
theme.PatternState { })
|
theme.PatternState { })
|
||||||
artist.FillRectangle(element, accent, meterBounds)
|
artist.FillRectangle(element, accent, meterBounds)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ type ScrollContainer struct {
|
|||||||
childWidth, childHeight int
|
childWidth, childHeight int
|
||||||
|
|
||||||
horizontal struct {
|
horizontal struct {
|
||||||
c theme.Case
|
theme theme.Wrapped
|
||||||
exists bool
|
exists bool
|
||||||
enabled bool
|
enabled bool
|
||||||
dragging bool
|
dragging bool
|
||||||
@ -31,7 +31,7 @@ type ScrollContainer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vertical struct {
|
vertical struct {
|
||||||
c theme.Case
|
theme theme.Wrapped
|
||||||
exists bool
|
exists bool
|
||||||
enabled bool
|
enabled bool
|
||||||
dragging bool
|
dragging bool
|
||||||
@ -41,9 +41,8 @@ type ScrollContainer struct {
|
|||||||
bar image.Rectangle
|
bar image.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
theme theme.Theme
|
config config.Wrapped
|
||||||
config config.Config
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
|
|
||||||
onFocusRequest func () (granted bool)
|
onFocusRequest func () (granted bool)
|
||||||
onFocusMotionRequest func (input.KeynavDirection) (granted bool)
|
onFocusMotionRequest func (input.KeynavDirection) (granted bool)
|
||||||
@ -52,12 +51,12 @@ type ScrollContainer struct {
|
|||||||
// NewScrollContainer creates a new scroll container with the specified scroll
|
// NewScrollContainer creates a new scroll container with the specified scroll
|
||||||
// bars.
|
// bars.
|
||||||
func NewScrollContainer (horizontal, vertical bool) (element *ScrollContainer) {
|
func NewScrollContainer (horizontal, vertical bool) (element *ScrollContainer) {
|
||||||
element = &ScrollContainer { c: theme.C("basic", "scrollContainer") }
|
element = &ScrollContainer { }
|
||||||
element.horizontal.c = theme.C("basic", "scrollBarHorizontal")
|
element.theme.Case = theme.C("basic", "scrollContainer")
|
||||||
element.vertical.c = theme.C("basic", "scrollBarVertical")
|
element.horizontal.theme.Case = theme.C("basic", "scrollBarHorizontal")
|
||||||
|
element.vertical.theme.Case = theme.C("basic", "scrollBarVertical")
|
||||||
|
|
||||||
element.Core, element.core = core.NewCore(element.handleResize)
|
element.Core, element.core = core.NewCore(element.handleResize)
|
||||||
element.updateMinimumSize()
|
|
||||||
element.horizontal.exists = horizontal
|
element.horizontal.exists = horizontal
|
||||||
element.vertical.exists = vertical
|
element.vertical.exists = vertical
|
||||||
return
|
return
|
||||||
@ -81,6 +80,12 @@ func (element *ScrollContainer) Adopt (child elements.Scrollable) {
|
|||||||
// adopt new child
|
// adopt new child
|
||||||
element.child = child
|
element.child = child
|
||||||
if child != nil {
|
if child != nil {
|
||||||
|
if child0, ok := child.(elements.Themeable); ok {
|
||||||
|
child0.SetTheme(element.theme.Theme)
|
||||||
|
}
|
||||||
|
if child0, ok := child.(elements.Configurable); ok {
|
||||||
|
child0.SetConfig(element.config.Config)
|
||||||
|
}
|
||||||
child.OnDamage(element.childDamageCallback)
|
child.OnDamage(element.childDamageCallback)
|
||||||
child.OnMinimumSizeChange(element.updateMinimumSize)
|
child.OnMinimumSizeChange(element.updateMinimumSize)
|
||||||
child.OnScrollBoundsChange(element.childScrollBoundsChangeCallback)
|
child.OnScrollBoundsChange(element.childScrollBoundsChangeCallback)
|
||||||
@ -102,6 +107,34 @@ func (element *ScrollContainer) Adopt (child elements.Scrollable) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTheme sets the element's theme.
|
||||||
|
func (element *ScrollContainer) SetTheme (new theme.Theme) {
|
||||||
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
|
if child, ok := element.child.(elements.Themeable); ok {
|
||||||
|
child.SetTheme(element.theme.Theme)
|
||||||
|
}
|
||||||
|
if element.core.HasImage() {
|
||||||
|
element.recalculate()
|
||||||
|
element.resizeChildToFit()
|
||||||
|
element.draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConfig sets the element's configuration.
|
||||||
|
func (element *ScrollContainer) SetConfig (new config.Config) {
|
||||||
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
|
if child, ok := element.child.(elements.Configurable); ok {
|
||||||
|
child.SetConfig(element.config.Config)
|
||||||
|
}
|
||||||
|
if element.core.HasImage() {
|
||||||
|
element.recalculate()
|
||||||
|
element.resizeChildToFit()
|
||||||
|
element.draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (element *ScrollContainer) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
func (element *ScrollContainer) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
||||||
if child, ok := element.child.(elements.KeyboardTarget); ok {
|
if child, ok := element.child.(elements.KeyboardTarget); ok {
|
||||||
child.HandleKeyDown(key, modifiers)
|
child.HandleKeyDown(key, modifiers)
|
||||||
@ -289,8 +322,8 @@ func (element *ScrollContainer) recalculate () {
|
|||||||
horizontal := &element.horizontal
|
horizontal := &element.horizontal
|
||||||
vertical := &element.vertical
|
vertical := &element.vertical
|
||||||
|
|
||||||
gutterInsetHorizontal := element.theme.Inset(theme.PatternGutter, horizontal.c)
|
gutterInsetHorizontal := horizontal.theme.Inset(theme.PatternGutter)
|
||||||
gutterInsetVertical := element.theme.Inset(theme.PatternGutter, vertical.c)
|
gutterInsetVertical := vertical.theme.Inset(theme.PatternGutter)
|
||||||
|
|
||||||
bounds := element.Bounds()
|
bounds := element.Bounds()
|
||||||
thicknessHorizontal :=
|
thicknessHorizontal :=
|
||||||
@ -376,7 +409,7 @@ func (element *ScrollContainer) recalculate () {
|
|||||||
func (element *ScrollContainer) draw () {
|
func (element *ScrollContainer) draw () {
|
||||||
artist.Paste(element, element.child, image.Point { })
|
artist.Paste(element, element.child, image.Point { })
|
||||||
deadPattern := element.theme.Pattern (
|
deadPattern := element.theme.Pattern (
|
||||||
theme.PatternDead, element.c, theme.PatternState { })
|
theme.PatternDead, theme.PatternState { })
|
||||||
artist.FillRectangle (
|
artist.FillRectangle (
|
||||||
element, deadPattern,
|
element, deadPattern,
|
||||||
image.Rect (
|
image.Rect (
|
||||||
@ -393,12 +426,10 @@ func (element *ScrollContainer) drawHorizontalBar () {
|
|||||||
Disabled: !element.horizontal.enabled,
|
Disabled: !element.horizontal.enabled,
|
||||||
Pressed: element.horizontal.dragging,
|
Pressed: element.horizontal.dragging,
|
||||||
}
|
}
|
||||||
gutterPattern := element.theme.Pattern (
|
gutterPattern := element.horizontal.theme.Pattern(theme.PatternGutter, state)
|
||||||
theme.PatternGutter, element.horizontal.c, state)
|
|
||||||
artist.FillRectangle(element, gutterPattern, element.horizontal.gutter)
|
artist.FillRectangle(element, gutterPattern, element.horizontal.gutter)
|
||||||
|
|
||||||
handlePattern := element.theme.Pattern (
|
handlePattern := element.horizontal.theme.Pattern(theme.PatternHandle, state)
|
||||||
theme.PatternHandle, element.horizontal.c, state)
|
|
||||||
artist.FillRectangle(element, handlePattern, element.horizontal.bar)
|
artist.FillRectangle(element, handlePattern, element.horizontal.bar)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,12 +438,10 @@ func (element *ScrollContainer) drawVerticalBar () {
|
|||||||
Disabled: !element.vertical.enabled,
|
Disabled: !element.vertical.enabled,
|
||||||
Pressed: element.vertical.dragging,
|
Pressed: element.vertical.dragging,
|
||||||
}
|
}
|
||||||
gutterPattern := element.theme.Pattern (
|
gutterPattern := element.vertical.theme.Pattern(theme.PatternGutter, state)
|
||||||
theme.PatternGutter, element.vertical.c, state)
|
|
||||||
artist.FillRectangle(element, gutterPattern, element.vertical.gutter)
|
artist.FillRectangle(element, gutterPattern, element.vertical.gutter)
|
||||||
|
|
||||||
handlePattern := element.theme.Pattern (
|
handlePattern := element.vertical.theme.Pattern(theme.PatternHandle, state)
|
||||||
theme.PatternHandle, element.vertical.c, state)
|
|
||||||
artist.FillRectangle(element, handlePattern, element.vertical.bar)
|
artist.FillRectangle(element, handlePattern, element.vertical.bar)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,10 +464,8 @@ func (element *ScrollContainer) dragVerticalBar (mousePosition image.Point) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (element *ScrollContainer) updateMinimumSize () {
|
func (element *ScrollContainer) updateMinimumSize () {
|
||||||
gutterInsetHorizontal := element.theme.Inset (
|
gutterInsetHorizontal := element.horizontal.theme.Inset(theme.PatternGutter)
|
||||||
theme.PatternGutter, element.horizontal.c)
|
gutterInsetVertical := element.vertical.theme.Inset(theme.PatternGutter)
|
||||||
gutterInsetVertical := element.theme.Inset (
|
|
||||||
theme.PatternGutter, element.vertical.c)
|
|
||||||
|
|
||||||
thicknessHorizontal :=
|
thicknessHorizontal :=
|
||||||
element.config.HandleWidth() +
|
element.config.HandleWidth() +
|
||||||
|
@ -11,16 +11,16 @@ type Spacer struct {
|
|||||||
core core.CoreControl
|
core core.CoreControl
|
||||||
line bool
|
line bool
|
||||||
|
|
||||||
theme theme.Theme
|
config config.Wrapped
|
||||||
config config.Config
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSpacer creates a new spacer. If line is set to true, the spacer will be
|
// 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,
|
// filled with a line color, and if compressed to its minimum width or height,
|
||||||
// will appear as a line.
|
// will appear as a line.
|
||||||
func NewSpacer (line bool) (element *Spacer) {
|
func NewSpacer (line bool) (element *Spacer) {
|
||||||
element = &Spacer { line: line, c: theme.C("basic", "spacer") }
|
element = &Spacer { line: line }
|
||||||
|
element.theme.Case = theme.C("basic", "spacer")
|
||||||
element.Core, element.core = core.NewCore(element.draw)
|
element.Core, element.core = core.NewCore(element.draw)
|
||||||
element.core.SetMinimumSize(1, 1)
|
element.core.SetMinimumSize(1, 1)
|
||||||
return
|
return
|
||||||
@ -38,13 +38,15 @@ func (element *Spacer) SetLine (line bool) {
|
|||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *Spacer) SetTheme (new theme.Theme) {
|
func (element *Spacer) SetTheme (new theme.Theme) {
|
||||||
element.theme = new
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *Spacer) SetConfig (new config.Config) {
|
func (element *Spacer) SetConfig (new config.Config) {
|
||||||
element.config = new
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,13 +63,11 @@ func (element *Spacer) draw () {
|
|||||||
if element.line {
|
if element.line {
|
||||||
pattern := element.theme.Pattern (
|
pattern := element.theme.Pattern (
|
||||||
theme.PatternForeground,
|
theme.PatternForeground,
|
||||||
element.c,
|
|
||||||
theme.PatternState { })
|
theme.PatternState { })
|
||||||
artist.FillRectangle(element, pattern, bounds)
|
artist.FillRectangle(element, pattern, bounds)
|
||||||
} else {
|
} else {
|
||||||
pattern := element.theme.Pattern (
|
pattern := element.theme.Pattern (
|
||||||
theme.PatternBackground,
|
theme.PatternBackground,
|
||||||
element.c,
|
|
||||||
theme.PatternState { })
|
theme.PatternState { })
|
||||||
artist.FillRectangle(element, pattern, bounds)
|
artist.FillRectangle(element, pattern, bounds)
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,8 @@ type Switch struct {
|
|||||||
checked bool
|
checked bool
|
||||||
text string
|
text string
|
||||||
|
|
||||||
theme theme.Theme
|
config config.Wrapped
|
||||||
config config.Config
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
|
|
||||||
onToggle func ()
|
onToggle func ()
|
||||||
}
|
}
|
||||||
@ -32,8 +31,8 @@ func NewSwitch (text string, on bool) (element *Switch) {
|
|||||||
element = &Switch {
|
element = &Switch {
|
||||||
checked: on,
|
checked: on,
|
||||||
text: text,
|
text: text,
|
||||||
c: theme.C("basic", "switch"),
|
|
||||||
}
|
}
|
||||||
|
element.theme.Case = theme.C("basic", "switch")
|
||||||
element.Core, element.core = core.NewCore(element.draw)
|
element.Core, element.core = core.NewCore(element.draw)
|
||||||
element.FocusableCore,
|
element.FocusableCore,
|
||||||
element.focusableControl = core.NewFocusableCore(element.redo)
|
element.focusableControl = core.NewFocusableCore(element.redo)
|
||||||
@ -116,18 +115,19 @@ func (element *Switch) SetText (text string) {
|
|||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *Switch) SetTheme (new theme.Theme) {
|
func (element *Switch) SetTheme (new theme.Theme) {
|
||||||
element.theme = new
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
theme.FontStyleRegular,
|
theme.FontStyleRegular,
|
||||||
theme.FontSizeNormal,
|
theme.FontSizeNormal))
|
||||||
element.c))
|
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *Switch) SetConfig (new config.Config) {
|
func (element *Switch) SetConfig (new config.Config) {
|
||||||
element.config = new
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
@ -165,7 +165,7 @@ func (element *Switch) draw () {
|
|||||||
Pressed: element.pressed,
|
Pressed: element.pressed,
|
||||||
}
|
}
|
||||||
backgroundPattern := element.theme.Pattern (
|
backgroundPattern := element.theme.Pattern (
|
||||||
theme.PatternBackground, element.c, state)
|
theme.PatternBackground, state)
|
||||||
artist.FillRectangle (element, backgroundPattern, bounds)
|
artist.FillRectangle (element, backgroundPattern, bounds)
|
||||||
|
|
||||||
if element.checked {
|
if element.checked {
|
||||||
@ -183,11 +183,11 @@ func (element *Switch) draw () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gutterPattern := element.theme.Pattern (
|
gutterPattern := element.theme.Pattern (
|
||||||
theme.PatternGutter, element.c, state)
|
theme.PatternGutter, state)
|
||||||
artist.FillRectangle(element, gutterPattern, gutterBounds)
|
artist.FillRectangle(element, gutterPattern, gutterBounds)
|
||||||
|
|
||||||
handlePattern := element.theme.Pattern (
|
handlePattern := element.theme.Pattern (
|
||||||
theme.PatternHandle, element.c, state)
|
theme.PatternHandle, state)
|
||||||
artist.FillRectangle(element, handlePattern, handleBounds)
|
artist.FillRectangle(element, handlePattern, handleBounds)
|
||||||
|
|
||||||
textBounds := element.drawer.LayoutBounds()
|
textBounds := element.drawer.LayoutBounds()
|
||||||
@ -199,6 +199,6 @@ func (element *Switch) draw () {
|
|||||||
offset.X -= textBounds.Min.X
|
offset.X -= textBounds.Min.X
|
||||||
|
|
||||||
foreground := element.theme.Pattern (
|
foreground := element.theme.Pattern (
|
||||||
theme.PatternForeground, element.c, state)
|
theme.PatternForeground, state)
|
||||||
element.drawer.Draw(element, foreground, offset)
|
element.drawer.Draw(element, foreground, offset)
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,8 @@ type TextBox struct {
|
|||||||
placeholderDrawer artist.TextDrawer
|
placeholderDrawer artist.TextDrawer
|
||||||
valueDrawer artist.TextDrawer
|
valueDrawer artist.TextDrawer
|
||||||
|
|
||||||
theme theme.Theme
|
config config.Wrapped
|
||||||
config config.Config
|
theme theme.Wrapped
|
||||||
c theme.Case
|
|
||||||
|
|
||||||
onKeyDown func (key input.Key, modifiers input.Modifiers) (handled bool)
|
onKeyDown func (key input.Key, modifiers input.Modifiers) (handled bool)
|
||||||
onChange func ()
|
onChange func ()
|
||||||
@ -36,7 +35,8 @@ type TextBox struct {
|
|||||||
// a value. When the value is empty, the placeholder will be displayed in gray
|
// a value. When the value is empty, the placeholder will be displayed in gray
|
||||||
// text.
|
// text.
|
||||||
func NewTextBox (placeholder, value string) (element *TextBox) {
|
func NewTextBox (placeholder, value string) (element *TextBox) {
|
||||||
element = &TextBox { c: theme.C("basic", "textBox") }
|
element = &TextBox { }
|
||||||
|
element.theme.Case = theme.C("basic", "textBox")
|
||||||
element.Core, element.core = core.NewCore(element.handleResize)
|
element.Core, element.core = core.NewCore(element.handleResize)
|
||||||
element.FocusableCore,
|
element.FocusableCore,
|
||||||
element.focusableControl = core.NewFocusableCore (func () {
|
element.focusableControl = core.NewFocusableCore (func () {
|
||||||
@ -252,11 +252,11 @@ func (element *TextBox) scrollToCursor () {
|
|||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *TextBox) SetTheme (new theme.Theme) {
|
func (element *TextBox) SetTheme (new theme.Theme) {
|
||||||
element.theme = new
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
face := element.theme.FontFace (
|
face := element.theme.FontFace (
|
||||||
theme.FontStyleRegular,
|
theme.FontStyleRegular,
|
||||||
theme.FontSizeNormal,
|
theme.FontSizeNormal)
|
||||||
element.c)
|
|
||||||
element.placeholderDrawer.SetFace(face)
|
element.placeholderDrawer.SetFace(face)
|
||||||
element.valueDrawer.SetFace(face)
|
element.valueDrawer.SetFace(face)
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
@ -265,19 +265,19 @@ func (element *TextBox) SetTheme (new theme.Theme) {
|
|||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *TextBox) SetConfig (new config.Config) {
|
func (element *TextBox) SetConfig (new config.Config) {
|
||||||
element.config = new
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.redo()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *TextBox) updateMinimumSize () {
|
func (element *TextBox) updateMinimumSize () {
|
||||||
textBounds := element.placeholderDrawer.LayoutBounds()
|
textBounds := element.placeholderDrawer.LayoutBounds()
|
||||||
inset := element.theme.Inset(theme.PatternInput, element.c)
|
|
||||||
element.core.SetMinimumSize (
|
element.core.SetMinimumSize (
|
||||||
textBounds.Dx() +
|
textBounds.Dx() +
|
||||||
element.config.Padding() * 2 + inset[3] + inset[1],
|
element.config.Padding() * 2,
|
||||||
element.placeholderDrawer.LineHeight().Round() +
|
element.placeholderDrawer.LineHeight().Round() +
|
||||||
element.config.Padding() * 2 + inset[0] + inset[2])
|
element.config.Padding() * 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *TextBox) redo () {
|
func (element *TextBox) redo () {
|
||||||
@ -295,7 +295,7 @@ func (element *TextBox) draw () {
|
|||||||
Disabled: !element.Enabled(),
|
Disabled: !element.Enabled(),
|
||||||
Focused: element.Focused(),
|
Focused: element.Focused(),
|
||||||
}
|
}
|
||||||
pattern := element.theme.Pattern(theme.PatternSunken, element.c, state)
|
pattern := element.theme.Pattern(theme.PatternSunken, state)
|
||||||
artist.FillRectangle(element, pattern, bounds)
|
artist.FillRectangle(element, pattern, bounds)
|
||||||
|
|
||||||
if len(element.text) == 0 && !element.Focused() {
|
if len(element.text) == 0 && !element.Focused() {
|
||||||
@ -306,7 +306,7 @@ func (element *TextBox) draw () {
|
|||||||
Y: element.config.Padding(),
|
Y: element.config.Padding(),
|
||||||
})
|
})
|
||||||
foreground := element.theme.Pattern (
|
foreground := element.theme.Pattern (
|
||||||
theme.PatternForeground, element.c,
|
theme.PatternForeground,
|
||||||
theme.PatternState { Disabled: true })
|
theme.PatternState { Disabled: true })
|
||||||
element.placeholderDrawer.Draw (
|
element.placeholderDrawer.Draw (
|
||||||
element,
|
element,
|
||||||
@ -320,7 +320,7 @@ func (element *TextBox) draw () {
|
|||||||
Y: element.config.Padding(),
|
Y: element.config.Padding(),
|
||||||
})
|
})
|
||||||
foreground := element.theme.Pattern (
|
foreground := element.theme.Pattern (
|
||||||
theme.PatternForeground, element.c, state)
|
theme.PatternForeground, state)
|
||||||
element.valueDrawer.Draw (
|
element.valueDrawer.Draw (
|
||||||
element,
|
element,
|
||||||
foreground,
|
foreground,
|
||||||
|
@ -4,7 +4,6 @@ import "fmt"
|
|||||||
import "time"
|
import "time"
|
||||||
import "image"
|
import "image"
|
||||||
import "image/color"
|
import "image/color"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/defaultfont"
|
import "git.tebibyte.media/sashakoshka/tomo/defaultfont"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||||
@ -20,8 +19,7 @@ type Artist struct {
|
|||||||
// NewArtist creates a new artist test element.
|
// NewArtist creates a new artist test element.
|
||||||
func NewArtist () (element *Artist) {
|
func NewArtist () (element *Artist) {
|
||||||
element = &Artist { }
|
element = &Artist { }
|
||||||
element.Core, element.core = core.NewCore (
|
element.Core, element.core = core.NewCore(element.draw)
|
||||||
element.draw, nil, nil, theme.C("testing", "artist"))
|
|
||||||
element.core.SetMinimumSize(480, 600)
|
element.core.SetMinimumSize(480, 600)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package testing
|
|||||||
import "image"
|
import "image"
|
||||||
import "image/color"
|
import "image/color"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/input"
|
import "git.tebibyte.media/sashakoshka/tomo/input"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/config"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||||
@ -15,21 +16,33 @@ type Mouse struct {
|
|||||||
drawing bool
|
drawing bool
|
||||||
color artist.Pattern
|
color artist.Pattern
|
||||||
lastMousePos image.Point
|
lastMousePos image.Point
|
||||||
|
|
||||||
|
config config.Config
|
||||||
|
theme theme.Theme
|
||||||
|
c theme.Case
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMouse creates a new mouse test element.
|
// NewMouse creates a new mouse test element.
|
||||||
func NewMouse () (element *Mouse) {
|
func NewMouse () (element *Mouse) {
|
||||||
element = &Mouse { }
|
element = &Mouse { c: theme.C("testing", "mouse") }
|
||||||
element.Core, element.core = core.NewCore (
|
element.Core, element.core = core.NewCore(element.draw)
|
||||||
element.draw,
|
|
||||||
element.redo,
|
|
||||||
element.redo,
|
|
||||||
theme.C("testing", "mouse"))
|
|
||||||
element.core.SetMinimumSize(32, 32)
|
element.core.SetMinimumSize(32, 32)
|
||||||
element.color = artist.NewUniform(color.Black)
|
element.color = artist.NewUniform(color.Black)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTheme sets the element's theme.
|
||||||
|
func (element *Mouse) SetTheme (new theme.Theme) {
|
||||||
|
element.theme = new
|
||||||
|
element.redo()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConfig sets the element's configuration.
|
||||||
|
func (element *Mouse) SetConfig (new config.Config) {
|
||||||
|
element.config = new
|
||||||
|
element.redo()
|
||||||
|
}
|
||||||
|
|
||||||
func (element *Mouse) redo () {
|
func (element *Mouse) redo () {
|
||||||
if !element.core.HasImage() { return }
|
if !element.core.HasImage() { return }
|
||||||
element.draw()
|
element.draw()
|
||||||
@ -38,7 +51,10 @@ func (element *Mouse) redo () {
|
|||||||
|
|
||||||
func (element *Mouse) draw () {
|
func (element *Mouse) draw () {
|
||||||
bounds := element.Bounds()
|
bounds := element.Bounds()
|
||||||
pattern := element.core.Pattern(theme.PatternAccent, theme.PatternState { })
|
pattern := element.theme.Pattern (
|
||||||
|
theme.PatternAccent,
|
||||||
|
element.c,
|
||||||
|
theme.PatternState { })
|
||||||
artist.FillRectangle(element, pattern, bounds)
|
artist.FillRectangle(element, pattern, bounds)
|
||||||
artist.StrokeRectangle (
|
artist.StrokeRectangle (
|
||||||
element,
|
element,
|
||||||
|
@ -41,7 +41,7 @@ func (Default) Pattern (
|
|||||||
case PatternBackground:
|
case PatternBackground:
|
||||||
return backgroundPattern
|
return backgroundPattern
|
||||||
case PatternForeground:
|
case PatternForeground:
|
||||||
if state.Disabled {
|
if state.Disabled || c == C("basic", "spacer") {
|
||||||
return weakForegroundPattern
|
return weakForegroundPattern
|
||||||
} else {
|
} else {
|
||||||
return foregroundPattern
|
return foregroundPattern
|
||||||
@ -77,6 +77,16 @@ func (Default) Pattern (
|
|||||||
} else {
|
} else {
|
||||||
return listPattern
|
return listPattern
|
||||||
}
|
}
|
||||||
|
} else if c == C("basic", "textBox") {
|
||||||
|
if state.Disabled {
|
||||||
|
return disabledInputPattern
|
||||||
|
} else {
|
||||||
|
if state.Focused {
|
||||||
|
return selectedInputPattern
|
||||||
|
} else {
|
||||||
|
return inputPattern
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return sunkenPattern
|
return sunkenPattern
|
||||||
}
|
}
|
||||||
@ -86,7 +96,7 @@ func (Default) Pattern (
|
|||||||
if state.Disabled {
|
if state.Disabled {
|
||||||
return disabledButtonPattern
|
return disabledButtonPattern
|
||||||
} else {
|
} else {
|
||||||
if state.Pressed {
|
if state.Pressed || state.On && c == C("basic", "checkbox") {
|
||||||
if state.Focused {
|
if state.Focused {
|
||||||
return pressedSelectedButtonPattern
|
return pressedSelectedButtonPattern
|
||||||
} else {
|
} else {
|
||||||
@ -144,13 +154,15 @@ func (Default) Inset (pattern Pattern, c Case) Inset {
|
|||||||
switch pattern {
|
switch pattern {
|
||||||
case PatternRaised:
|
case PatternRaised:
|
||||||
if c == C("basic", "listEntry") {
|
if c == C("basic", "listEntry") {
|
||||||
return Inset { 2, 1, 2, 1 }
|
return Inset { 4, 6, 4, 6 }
|
||||||
} else {
|
} else {
|
||||||
return Inset { 1, 1, 1, 1 }
|
return Inset { 1, 1, 1, 1 }
|
||||||
}
|
}
|
||||||
case PatternSunken:
|
case PatternSunken:
|
||||||
if c == C("basic", "list") {
|
if c == C("basic", "list") {
|
||||||
return Inset { 4, 6, 4, 6 }
|
return Inset { 2, 1, 2, 1 }
|
||||||
|
} else if c == C("basic", "progressBar") {
|
||||||
|
return Inset { 2, 1, 1, 2 }
|
||||||
} else {
|
} else {
|
||||||
return Inset { 1, 1, 1, 1 }
|
return Inset { 1, 1, 1, 1 }
|
||||||
}
|
}
|
||||||
|
@ -46,3 +46,33 @@ type PatternState struct {
|
|||||||
// or outline.
|
// or outline.
|
||||||
Invalid bool
|
Invalid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FontStyle specifies stylistic alterations to a font face.
|
||||||
|
type FontStyle int; const (
|
||||||
|
FontStyleRegular FontStyle = 0
|
||||||
|
FontStyleBold FontStyle = 1
|
||||||
|
FontStyleItalic FontStyle = 2
|
||||||
|
FontStyleBoldItalic FontStyle = 1 | 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// FontSize specifies the general size of a font face in a semantic way.
|
||||||
|
type FontSize int; const (
|
||||||
|
// FontSizeNormal is the default font size that should be used for most
|
||||||
|
// things.
|
||||||
|
FontSizeNormal FontSize = iota
|
||||||
|
|
||||||
|
// FontSizeLarge is a larger font size suitable for things like section
|
||||||
|
// headings.
|
||||||
|
FontSizeLarge
|
||||||
|
|
||||||
|
// FontSizeHuge is a very large font size suitable for things like
|
||||||
|
// titles, wizard step names, digital clocks, etc.
|
||||||
|
FontSizeHuge
|
||||||
|
|
||||||
|
// FontSizeSmall is a smaller font size. Try not to use this unless it
|
||||||
|
// makes a lot of sense to do so, because it can negatively impact
|
||||||
|
// accessibility. It is useful for things like copyright notices at the
|
||||||
|
// bottom of some window that the average user doesn't actually care
|
||||||
|
// about.
|
||||||
|
FontSizeSmall
|
||||||
|
)
|
||||||
|
@ -4,36 +4,6 @@ import "image"
|
|||||||
import "golang.org/x/image/font"
|
import "golang.org/x/image/font"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||||
|
|
||||||
// FontStyle specifies stylistic alterations to a font face.
|
|
||||||
type FontStyle int; const (
|
|
||||||
FontStyleRegular FontStyle = 0
|
|
||||||
FontStyleBold FontStyle = 1
|
|
||||||
FontStyleItalic FontStyle = 2
|
|
||||||
FontStyleBoldItalic FontStyle = 1 | 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// FontSize specifies the general size of a font face in a semantic way.
|
|
||||||
type FontSize int; const (
|
|
||||||
// FontSizeNormal is the default font size that should be used for most
|
|
||||||
// things.
|
|
||||||
FontSizeNormal FontSize = iota
|
|
||||||
|
|
||||||
// FontSizeLarge is a larger font size suitable for things like section
|
|
||||||
// headings.
|
|
||||||
FontSizeLarge
|
|
||||||
|
|
||||||
// FontSizeHuge is a very large font size suitable for things like
|
|
||||||
// titles, wizard step names, digital clocks, etc.
|
|
||||||
FontSizeHuge
|
|
||||||
|
|
||||||
// FontSizeSmall is a smaller font size. Try not to use this unless it
|
|
||||||
// makes a lot of sense to do so, because it can negatively impact
|
|
||||||
// accessibility. It is useful for things like copyright notices at the
|
|
||||||
// bottom of some window that the average user doesn't actually care
|
|
||||||
// about.
|
|
||||||
FontSizeSmall
|
|
||||||
)
|
|
||||||
|
|
||||||
// Pattern lists a number of cannonical pattern types, each with its own ID.
|
// Pattern lists a number of cannonical pattern types, each with its own ID.
|
||||||
// This allows custom elements to follow themes, even those that do not
|
// This allows custom elements to follow themes, even those that do not
|
||||||
// explicitly support them.
|
// explicitly support them.
|
||||||
@ -98,3 +68,49 @@ type Theme interface {
|
|||||||
// sinking effect.
|
// sinking effect.
|
||||||
Sink (Pattern, Case) image.Point
|
Sink (Pattern, Case) image.Point
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapped wraps any theme and injects a case into it automatically so that it
|
||||||
|
// doesn't need to be specified for each query. Additionally, if the underlying
|
||||||
|
// theme is nil, it just uses the default theme instead.
|
||||||
|
type Wrapped struct {
|
||||||
|
Theme
|
||||||
|
Case
|
||||||
|
}
|
||||||
|
|
||||||
|
// FontFace returns the proper font for a given style and size.
|
||||||
|
func (wrapped Wrapped) FontFace (style FontStyle, size FontSize) font.Face {
|
||||||
|
real := wrapped.ensure()
|
||||||
|
return real.FontFace(style, size, wrapped.Case)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon returns an appropriate icon given an icon name.
|
||||||
|
func (wrapped Wrapped) Icon (name string) artist.Pattern {
|
||||||
|
real := wrapped.ensure()
|
||||||
|
return real.Icon(name, wrapped.Case)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern returns an appropriate pattern given a pattern name and state.
|
||||||
|
func (wrapped Wrapped) Pattern (id Pattern, state PatternState) artist.Pattern {
|
||||||
|
real := wrapped.ensure()
|
||||||
|
return real.Pattern(id, wrapped.Case, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inset returns the area on all sides of a given pattern that is not meant to
|
||||||
|
// be drawn on.
|
||||||
|
func (wrapped Wrapped) Inset (id Pattern) Inset {
|
||||||
|
real := wrapped.ensure()
|
||||||
|
return real.Inset(id, wrapped.Case)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sink returns a vector that should be added to an element's inner content when
|
||||||
|
// it is pressed down (if applicable) to simulate a 3D sinking effect.
|
||||||
|
func (wrapped Wrapped) Sink (id Pattern) image.Point {
|
||||||
|
real := wrapped.ensure()
|
||||||
|
return real.Sink(id, wrapped.Case)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wrapped Wrapped) ensure () (real Theme) {
|
||||||
|
real = wrapped.Theme
|
||||||
|
if real == nil { real = Default { } }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user