Migrated over some elements
This commit is contained in:
parent
4c6f1f80e7
commit
68128c94d8
@ -1,24 +1,19 @@
|
|||||||
package elements
|
package elements
|
||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
// import "runtime/debug"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/input"
|
import "git.tebibyte.media/sashakoshka/tomo/input"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
// import "git.tebibyte.media/sashakoshka/tomo/artist"
|
|
||||||
// import "git.tebibyte.media/sashakoshka/tomo/shatter"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
|
|
||||||
// Button is a clickable button.
|
// Button is a clickable button.
|
||||||
type Button struct {
|
type Button struct {
|
||||||
*core.Core
|
entity tomo.FocusableEntity
|
||||||
*core.FocusableCore
|
|
||||||
core core.CoreControl
|
|
||||||
focusableControl core.FocusableCoreControl
|
|
||||||
drawer textdraw.Drawer
|
drawer textdraw.Drawer
|
||||||
|
|
||||||
|
enabled bool
|
||||||
pressed bool
|
pressed bool
|
||||||
text string
|
text string
|
||||||
|
|
||||||
@ -36,9 +31,6 @@ type Button struct {
|
|||||||
func NewButton (text string) (element *Button) {
|
func NewButton (text string) (element *Button) {
|
||||||
element = &Button { showText: true }
|
element = &Button { showText: true }
|
||||||
element.theme.Case = tomo.C("tomo", "button")
|
element.theme.Case = tomo.C("tomo", "button")
|
||||||
element.Core, element.core = core.NewCore(element, element.drawAll)
|
|
||||||
element.FocusableCore,
|
|
||||||
element.focusableControl = core.NewFocusableCore(element.core, element.drawAndPush)
|
|
||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
tomo.FontStyleRegular,
|
tomo.FontStyleRegular,
|
||||||
tomo.FontSizeNormal))
|
tomo.FontSizeNormal))
|
||||||
@ -46,42 +38,11 @@ func NewButton (text string) (element *Button) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Button) HandleMouseDown (x, y int, button input.Button) {
|
// Bind binds this element to an entity.
|
||||||
if !element.Enabled() { return }
|
func (element *Button) Bind (entity tomo.Entity) {
|
||||||
if !element.Focused() { element.Focus() }
|
if entity == nil { element.entity = nil; return }
|
||||||
if button != input.ButtonLeft { return }
|
element.entity = entity.(tomo.FocusableEntity)
|
||||||
element.pressed = true
|
element.updateMinimumSize()
|
||||||
element.drawAndPush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Button) HandleMouseUp (x, y int, button input.Button) {
|
|
||||||
if button != input.ButtonLeft { return }
|
|
||||||
element.pressed = false
|
|
||||||
within := image.Point { x, y }.
|
|
||||||
In(element.Bounds())
|
|
||||||
if element.Enabled() && within && element.onClick != nil {
|
|
||||||
element.onClick()
|
|
||||||
}
|
|
||||||
element.drawAndPush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Button) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
|
||||||
if !element.Enabled() { return }
|
|
||||||
if key == input.KeyEnter {
|
|
||||||
element.pressed = true
|
|
||||||
element.drawAndPush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Button) HandleKeyUp(key input.Key, modifiers input.Modifiers) {
|
|
||||||
if key == input.KeyEnter && element.pressed {
|
|
||||||
element.pressed = false
|
|
||||||
element.drawAndPush()
|
|
||||||
if !element.Enabled() { return }
|
|
||||||
if element.onClick != nil {
|
|
||||||
element.onClick()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnClick sets the function to be called when the button is clicked.
|
// OnClick sets the function to be called when the button is clicked.
|
||||||
@ -89,19 +50,33 @@ func (element *Button) OnClick (callback func ()) {
|
|||||||
element.onClick = callback
|
element.onClick = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Focus gives this element input focus.
|
||||||
|
func (element *Button) Focus () {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if !element.entity.Focused() { element.entity.Focus() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enabled returns whether this button is enabled or not.
|
||||||
|
func (element *Button) Enabled () bool {
|
||||||
|
return element.enabled
|
||||||
|
}
|
||||||
|
|
||||||
// SetEnabled sets whether this button can be clicked or not.
|
// SetEnabled sets whether this button can be clicked or not.
|
||||||
func (element *Button) SetEnabled (enabled bool) {
|
func (element *Button) SetEnabled (enabled bool) {
|
||||||
element.focusableControl.SetEnabled(enabled)
|
if element.enabled == enabled { return }
|
||||||
|
element.enabled = enabled
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetText sets the button's label text.
|
// SetText sets the button's label text.
|
||||||
func (element *Button) SetText (text string) {
|
func (element *Button) SetText (text string) {
|
||||||
if element.text == text { return }
|
if element.text == text { return }
|
||||||
|
|
||||||
element.text = text
|
element.text = text
|
||||||
element.drawer.SetText([]rune(text))
|
element.drawer.SetText([]rune(text))
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.drawAndPush()
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetIcon sets the icon of the button. Passing theme.IconNone removes the
|
// SetIcon sets the icon of the button. Passing theme.IconNone removes the
|
||||||
@ -109,23 +84,22 @@ func (element *Button) SetText (text string) {
|
|||||||
func (element *Button) SetIcon (id tomo.Icon) {
|
func (element *Button) SetIcon (id tomo.Icon) {
|
||||||
if id == tomo.IconNone {
|
if id == tomo.IconNone {
|
||||||
element.hasIcon = false
|
element.hasIcon = false
|
||||||
element.updateMinimumSize()
|
|
||||||
element.drawAndPush()
|
|
||||||
} else {
|
} else {
|
||||||
if element.hasIcon && element.iconId == id { return }
|
if element.hasIcon && element.iconId == id { return }
|
||||||
element.hasIcon = true
|
element.hasIcon = true
|
||||||
element.iconId = id
|
element.iconId = id
|
||||||
}
|
}
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.drawAndPush()
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShowText sets whether or not the button's text will be displayed.
|
// ShowText sets whether or not the button's text will be displayed.
|
||||||
func (element *Button) ShowText (showText bool) {
|
func (element *Button) ShowText (showText bool) {
|
||||||
if element.showText == showText { return }
|
if element.showText == showText { return }
|
||||||
element.showText = showText
|
element.showText = showText
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.drawAndPush()
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
@ -135,74 +109,30 @@ func (element *Button) SetTheme (new tomo.Theme) {
|
|||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
tomo.FontStyleRegular,
|
tomo.FontStyleRegular,
|
||||||
tomo.FontSizeNormal))
|
tomo.FontSizeNormal))
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.drawAndPush()
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *Button) SetConfig (new tomo.Config) {
|
func (element *Button) SetConfig (new tomo.Config) {
|
||||||
if new == element.config.Config { return }
|
if new == element.config.Config { return }
|
||||||
element.config.Config = new
|
element.config.Config = new
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.drawAndPush()
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Button) updateMinimumSize () {
|
// Draw causes the element to draw to the specified destination canvas.
|
||||||
padding := element.theme.Padding(tomo.PatternButton)
|
func (element *Button) Draw (destination canvas.Canvas) {
|
||||||
margin := element.theme.Margin(tomo.PatternButton)
|
if element.entity == nil { return }
|
||||||
|
|
||||||
textBounds := element.drawer.LayoutBounds()
|
|
||||||
minimumSize := textBounds.Sub(textBounds.Min)
|
|
||||||
|
|
||||||
if element.hasIcon {
|
|
||||||
icon := element.theme.Icon(element.iconId, tomo.IconSizeSmall)
|
|
||||||
if icon != nil {
|
|
||||||
bounds := icon.Bounds()
|
|
||||||
if element.showText {
|
|
||||||
minimumSize.Max.X += bounds.Dx()
|
|
||||||
minimumSize.Max.X += margin.X
|
|
||||||
} else {
|
|
||||||
minimumSize.Max.X = bounds.Dx()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
minimumSize = padding.Inverse().Apply(minimumSize)
|
|
||||||
element.core.SetMinimumSize(minimumSize.Dx(), minimumSize.Dy())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Button) state () tomo.State {
|
|
||||||
return tomo.State {
|
|
||||||
Disabled: !element.Enabled(),
|
|
||||||
Focused: element.Focused(),
|
|
||||||
Pressed: element.pressed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Button) drawAndPush () {
|
|
||||||
if element.core.HasImage () {
|
|
||||||
element.drawAll()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Button) drawAll () {
|
|
||||||
element.drawBackground()
|
|
||||||
element.drawText()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Button) drawBackground () []image.Rectangle {
|
|
||||||
state := element.state()
|
state := element.state()
|
||||||
bounds := element.Bounds()
|
bounds := element.entity.Bounds()
|
||||||
pattern := element.theme.Pattern(tomo.PatternButton, state)
|
pattern := element.theme.Pattern(tomo.PatternButton, state)
|
||||||
|
|
||||||
pattern.Draw(element.core, bounds)
|
pattern.Draw(destination, bounds)
|
||||||
return []image.Rectangle { bounds }
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Button) drawText () {
|
|
||||||
state := element.state()
|
|
||||||
bounds := element.Bounds()
|
|
||||||
foreground := element.theme.Color(tomo.ColorForeground, state)
|
foreground := element.theme.Color(tomo.ColorForeground, state)
|
||||||
sink := element.theme.Sink(tomo.PatternButton)
|
sink := element.theme.Sink(tomo.PatternButton)
|
||||||
margin := element.theme.Margin(tomo.PatternButton)
|
margin := element.theme.Margin(tomo.PatternButton)
|
||||||
@ -240,7 +170,7 @@ func (element *Button) drawText () {
|
|||||||
}
|
}
|
||||||
offset.X += addedWidth / 2
|
offset.X += addedWidth / 2
|
||||||
|
|
||||||
icon.Draw(element.core, foreground, iconOffset)
|
icon.Draw(destination, foreground, iconOffset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,6 +178,84 @@ func (element *Button) drawText () {
|
|||||||
if element.pressed {
|
if element.pressed {
|
||||||
offset = offset.Add(sink)
|
offset = offset.Add(sink)
|
||||||
}
|
}
|
||||||
element.drawer.Draw(element.core, foreground, offset)
|
element.drawer.Draw(destination, foreground, offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Button) HandleFocusChange () {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Button) HandleMouseDown (x, y int, button input.Button) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if !element.Enabled() { return }
|
||||||
|
element.Focus()
|
||||||
|
if button != input.ButtonLeft { return }
|
||||||
|
element.pressed = true
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Button) HandleMouseUp (x, y int, button input.Button) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if button != input.ButtonLeft { return }
|
||||||
|
element.pressed = false
|
||||||
|
within := image.Point { x, y }.In(element.entity.Bounds())
|
||||||
|
if element.Enabled() && within && element.onClick != nil {
|
||||||
|
element.onClick()
|
||||||
|
}
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Button) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if !element.Enabled() { return }
|
||||||
|
if key == input.KeyEnter {
|
||||||
|
element.pressed = true
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Button) HandleKeyUp(key input.Key, modifiers input.Modifiers) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if key == input.KeyEnter && element.pressed {
|
||||||
|
element.pressed = false
|
||||||
|
element.entity.Invalidate()
|
||||||
|
if !element.Enabled() { return }
|
||||||
|
if element.onClick != nil {
|
||||||
|
element.onClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Button) updateMinimumSize () {
|
||||||
|
padding := element.theme.Padding(tomo.PatternButton)
|
||||||
|
margin := element.theme.Margin(tomo.PatternButton)
|
||||||
|
|
||||||
|
textBounds := element.drawer.LayoutBounds()
|
||||||
|
minimumSize := textBounds.Sub(textBounds.Min)
|
||||||
|
|
||||||
|
if element.hasIcon {
|
||||||
|
icon := element.theme.Icon(element.iconId, tomo.IconSizeSmall)
|
||||||
|
if icon != nil {
|
||||||
|
bounds := icon.Bounds()
|
||||||
|
if element.showText {
|
||||||
|
minimumSize.Max.X += bounds.Dx()
|
||||||
|
minimumSize.Max.X += margin.X
|
||||||
|
} else {
|
||||||
|
minimumSize.Max.X = bounds.Dx()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
minimumSize = padding.Inverse().Apply(minimumSize)
|
||||||
|
element.entity.SetMinimumSize(minimumSize.Dx(), minimumSize.Dy())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Button) state () tomo.State {
|
||||||
|
return tomo.State {
|
||||||
|
Disabled: !element.Enabled(),
|
||||||
|
Focused: element.entity.Focused(),
|
||||||
|
Pressed: element.pressed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,17 @@ package elements
|
|||||||
import "image"
|
import "image"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/input"
|
import "git.tebibyte.media/sashakoshka/tomo/input"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
// Checkbox is a toggle-able checkbox with a label.
|
// Checkbox is a toggle-able checkbox with a label.
|
||||||
type Checkbox struct {
|
type Checkbox struct {
|
||||||
*core.Core
|
entity tomo.FocusableEntity
|
||||||
*core.FocusableCore
|
|
||||||
core core.CoreControl
|
|
||||||
focusableControl core.FocusableCoreControl
|
|
||||||
drawer textdraw.Drawer
|
drawer textdraw.Drawer
|
||||||
|
|
||||||
|
enabled bool
|
||||||
pressed bool
|
pressed bool
|
||||||
checked bool
|
checked bool
|
||||||
text string
|
text string
|
||||||
@ -30,9 +28,6 @@ type Checkbox struct {
|
|||||||
func NewCheckbox (text string, checked bool) (element *Checkbox) {
|
func NewCheckbox (text string, checked bool) (element *Checkbox) {
|
||||||
element = &Checkbox { checked: checked }
|
element = &Checkbox { checked: checked }
|
||||||
element.theme.Case = tomo.C("tomo", "checkbox")
|
element.theme.Case = tomo.C("tomo", "checkbox")
|
||||||
element.Core, element.core = core.NewCore(element, element.draw)
|
|
||||||
element.FocusableCore,
|
|
||||||
element.focusableControl = core.NewFocusableCore(element.core, element.redo)
|
|
||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
tomo.FontStyleRegular,
|
tomo.FontStyleRegular,
|
||||||
tomo.FontSizeNormal))
|
tomo.FontSizeNormal))
|
||||||
@ -40,57 +35,11 @@ func NewCheckbox (text string, checked bool) (element *Checkbox) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Checkbox) HandleMouseDown (x, y int, button input.Button) {
|
// Bind binds this element to an entity.
|
||||||
if !element.Enabled() { return }
|
func (element *Checkbox) Bind (entity tomo.Entity) {
|
||||||
element.Focus()
|
if entity == nil { element.entity = nil; return }
|
||||||
element.pressed = true
|
element.entity = entity.(tomo.FocusableEntity)
|
||||||
if element.core.HasImage() {
|
element.updateMinimumSize()
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Checkbox) HandleMouseUp (x, y int, button input.Button) {
|
|
||||||
if button != input.ButtonLeft || !element.pressed { return }
|
|
||||||
|
|
||||||
element.pressed = false
|
|
||||||
within := image.Point { x, y }.
|
|
||||||
In(element.Bounds())
|
|
||||||
if within {
|
|
||||||
element.checked = !element.checked
|
|
||||||
}
|
|
||||||
|
|
||||||
if element.core.HasImage() {
|
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
if within && element.onToggle != nil {
|
|
||||||
element.onToggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Checkbox) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
|
||||||
if key == input.KeyEnter {
|
|
||||||
element.pressed = true
|
|
||||||
if element.core.HasImage() {
|
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Checkbox) 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()
|
|
||||||
}
|
|
||||||
if element.onToggle != nil {
|
|
||||||
element.onToggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnToggle sets the function to be called when the checkbox is toggled.
|
// OnToggle sets the function to be called when the checkbox is toggled.
|
||||||
@ -103,23 +52,33 @@ func (element *Checkbox) Value () (checked bool) {
|
|||||||
return element.checked
|
return element.checked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Focus gives this element input focus.
|
||||||
|
func (element *Checkbox) Focus () {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if !element.entity.Focused() { element.entity.Focus() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enabled returns whether this checkbox is enabled or not.
|
||||||
|
func (element *Checkbox) Enabled () bool {
|
||||||
|
return element.enabled
|
||||||
|
}
|
||||||
|
|
||||||
// SetEnabled sets whether this checkbox can be toggled or not.
|
// SetEnabled sets whether this checkbox can be toggled or not.
|
||||||
func (element *Checkbox) SetEnabled (enabled bool) {
|
func (element *Checkbox) SetEnabled (enabled bool) {
|
||||||
element.focusableControl.SetEnabled(enabled)
|
if element.enabled == enabled { return }
|
||||||
|
element.enabled = enabled
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetText sets the checkbox's label text.
|
// SetText sets the checkbox's label text.
|
||||||
func (element *Checkbox) SetText (text string) {
|
func (element *Checkbox) SetText (text string) {
|
||||||
if element.text == text { return }
|
if element.text == text { return }
|
||||||
|
|
||||||
element.text = text
|
element.text = text
|
||||||
element.drawer.SetText([]rune(text))
|
element.drawer.SetText([]rune(text))
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
if element.core.HasImage () {
|
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
@ -129,53 +88,38 @@ func (element *Checkbox) SetTheme (new tomo.Theme) {
|
|||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
tomo.FontStyleRegular,
|
tomo.FontStyleRegular,
|
||||||
tomo.FontSizeNormal))
|
tomo.FontSizeNormal))
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *Checkbox) SetConfig (new tomo.Config) {
|
func (element *Checkbox) SetConfig (new tomo.Config) {
|
||||||
if new == element.config.Config { return }
|
if new == element.config.Config { return }
|
||||||
element.config.Config = new
|
element.config.Config = new
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Checkbox) updateMinimumSize () {
|
// Draw causes the element to draw to the specified destination canvas.
|
||||||
textBounds := element.drawer.LayoutBounds()
|
func (element *Checkbox) Draw (destination canvas.Canvas) {
|
||||||
if element.text == "" {
|
if element.entity == nil { return }
|
||||||
element.core.SetMinimumSize(textBounds.Dy(), textBounds.Dy())
|
|
||||||
} else {
|
|
||||||
margin := element.theme.Margin(tomo.PatternBackground)
|
|
||||||
element.core.SetMinimumSize (
|
|
||||||
textBounds.Dy() + margin.X + textBounds.Dx(),
|
|
||||||
textBounds.Dy())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Checkbox) redo () {
|
bounds := element.entity.Bounds()
|
||||||
if element.core.HasImage () {
|
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Checkbox) draw () {
|
|
||||||
bounds := element.Bounds()
|
|
||||||
boxBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()).Add(bounds.Min)
|
boxBounds := image.Rect(0, 0, bounds.Dy(), bounds.Dy()).Add(bounds.Min)
|
||||||
|
|
||||||
state := tomo.State {
|
state := tomo.State {
|
||||||
Disabled: !element.Enabled(),
|
Disabled: !element.Enabled(),
|
||||||
Focused: element.Focused(),
|
Focused: element.entity.Focused(),
|
||||||
Pressed: element.pressed,
|
Pressed: element.pressed,
|
||||||
On: element.checked,
|
On: element.checked,
|
||||||
}
|
}
|
||||||
|
|
||||||
element.core.DrawBackground (
|
element.entity.DrawBackground(destination, bounds)
|
||||||
element.theme.Pattern(tomo.PatternBackground, state))
|
|
||||||
|
|
||||||
pattern := element.theme.Pattern(tomo.PatternButton, state)
|
pattern := element.theme.Pattern(tomo.PatternButton, state)
|
||||||
pattern.Draw(element.core, boxBounds)
|
pattern.Draw(destination, boxBounds)
|
||||||
|
|
||||||
textBounds := element.drawer.LayoutBounds()
|
textBounds := element.drawer.LayoutBounds()
|
||||||
margin := element.theme.Margin(tomo.PatternBackground)
|
margin := element.theme.Margin(tomo.PatternBackground)
|
||||||
@ -187,5 +131,61 @@ func (element *Checkbox) draw () {
|
|||||||
offset.X -= textBounds.Min.X
|
offset.X -= textBounds.Min.X
|
||||||
|
|
||||||
foreground := element.theme.Color(tomo.ColorForeground, state)
|
foreground := element.theme.Color(tomo.ColorForeground, state)
|
||||||
element.drawer.Draw(element.core, foreground, offset)
|
element.drawer.Draw(destination, foreground, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Checkbox) HandleMouseDown (x, y int, button input.Button) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if !element.Enabled() { return }
|
||||||
|
element.Focus()
|
||||||
|
element.pressed = true
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Checkbox) HandleMouseUp (x, y int, button input.Button) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if button != input.ButtonLeft || !element.pressed { return }
|
||||||
|
|
||||||
|
element.pressed = false
|
||||||
|
within := image.Point { x, y }.In(element.entity.Bounds())
|
||||||
|
if within {
|
||||||
|
element.checked = !element.checked
|
||||||
|
}
|
||||||
|
|
||||||
|
element.entity.Invalidate()
|
||||||
|
if within && element.onToggle != nil {
|
||||||
|
element.onToggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Checkbox) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if key == input.KeyEnter {
|
||||||
|
element.pressed = true
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Checkbox) HandleKeyUp (key input.Key, modifiers input.Modifiers) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
if key == input.KeyEnter && element.pressed {
|
||||||
|
element.pressed = false
|
||||||
|
element.checked = !element.checked
|
||||||
|
element.entity.Invalidate()
|
||||||
|
if element.onToggle != nil {
|
||||||
|
element.onToggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Checkbox) updateMinimumSize () {
|
||||||
|
textBounds := element.drawer.LayoutBounds()
|
||||||
|
if element.text == "" {
|
||||||
|
element.entity.SetMinimumSize(textBounds.Dy(), textBounds.Dy())
|
||||||
|
} else {
|
||||||
|
margin := element.theme.Margin(tomo.PatternBackground)
|
||||||
|
element.entity.SetMinimumSize (
|
||||||
|
textBounds.Dy() + margin.X + textBounds.Dx(),
|
||||||
|
textBounds.Dy())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,47 +2,72 @@ package elements
|
|||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
|
|
||||||
|
// Icon is an element capable of displaying a singular icon.
|
||||||
type Icon struct {
|
type Icon struct {
|
||||||
*core.Core
|
entity tomo.Entity
|
||||||
core core.CoreControl
|
theme theme.Wrapped
|
||||||
theme theme.Wrapped
|
id tomo.Icon
|
||||||
id tomo.Icon
|
size tomo.IconSize
|
||||||
size tomo.IconSize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Icon creates a new icon element.
|
||||||
func NewIcon (id tomo.Icon, size tomo.IconSize) (element *Icon) {
|
func NewIcon (id tomo.Icon, size tomo.IconSize) (element *Icon) {
|
||||||
element = &Icon {
|
element = &Icon {
|
||||||
id: id,
|
id: id,
|
||||||
size: size,
|
size: size,
|
||||||
}
|
}
|
||||||
element.theme.Case = tomo.C("tomo", "icon")
|
element.theme.Case = tomo.C("tomo", "icon")
|
||||||
element.Core, element.core = core.NewCore(element, element.draw)
|
|
||||||
element.updateMinimumSize()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind binds this element to an entity.
|
||||||
|
func (element *Icon) Bind (entity tomo.Entity) {
|
||||||
|
if entity == nil { element.entity = nil; return }
|
||||||
|
element.entity = entity
|
||||||
|
element.updateMinimumSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIcon sets the element's icon.
|
||||||
func (element *Icon) SetIcon (id tomo.Icon, size tomo.IconSize) {
|
func (element *Icon) SetIcon (id tomo.Icon, size tomo.IconSize) {
|
||||||
element.id = id
|
element.id = id
|
||||||
element.size = size
|
element.size = size
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
if element.core.HasImage() {
|
element.entity.Invalidate()
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *Icon) SetTheme (new tomo.Theme) {
|
func (element *Icon) SetTheme (new tomo.Theme) {
|
||||||
if new == element.theme.Theme { return }
|
if new == element.theme.Theme { return }
|
||||||
element.theme.Theme = new
|
element.theme.Theme = new
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
if element.core.HasImage() {
|
element.entity.Invalidate()
|
||||||
element.draw()
|
}
|
||||||
element.core.DamageAll()
|
|
||||||
|
// Draw causes the element to draw to the specified destination canvas.
|
||||||
|
func (element *Icon) Draw (destination canvas.Canvas) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
|
||||||
|
bounds := element.entity.Bounds()
|
||||||
|
state := tomo.State { }
|
||||||
|
element.theme.
|
||||||
|
Pattern(tomo.PatternBackground, state).
|
||||||
|
Draw(destination, bounds)
|
||||||
|
icon := element.icon()
|
||||||
|
if icon != nil {
|
||||||
|
iconBounds := icon.Bounds()
|
||||||
|
offset := image.Pt (
|
||||||
|
(bounds.Dx() - iconBounds.Dx()) / 2,
|
||||||
|
(bounds.Dy() - iconBounds.Dy()) / 2)
|
||||||
|
icon.Draw (
|
||||||
|
destination,
|
||||||
|
element.theme.Color(tomo.ColorForeground, state),
|
||||||
|
bounds.Min.Add(offset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,28 +78,9 @@ func (element *Icon) icon () artist.Icon {
|
|||||||
func (element *Icon) updateMinimumSize () {
|
func (element *Icon) updateMinimumSize () {
|
||||||
icon := element.icon()
|
icon := element.icon()
|
||||||
if icon == nil {
|
if icon == nil {
|
||||||
element.core.SetMinimumSize(0, 0)
|
element.entity.SetMinimumSize(0, 0)
|
||||||
} else {
|
} else {
|
||||||
bounds := icon.Bounds()
|
bounds := icon.Bounds()
|
||||||
element.core.SetMinimumSize(bounds.Dx(), bounds.Dy())
|
element.entity.SetMinimumSize(bounds.Dx(), bounds.Dy())
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Icon) draw () {
|
|
||||||
bounds := element.Bounds()
|
|
||||||
state := tomo.State { }
|
|
||||||
element.theme.
|
|
||||||
Pattern(tomo.PatternBackground, state).
|
|
||||||
Draw(element.core, bounds)
|
|
||||||
icon := element.icon()
|
|
||||||
if icon != nil {
|
|
||||||
iconBounds := icon.Bounds()
|
|
||||||
offset := image.Pt (
|
|
||||||
(bounds.Dx() - iconBounds.Dx()) / 2,
|
|
||||||
(bounds.Dy() - iconBounds.Dy()) / 2)
|
|
||||||
icon.Draw (
|
|
||||||
element.core,
|
|
||||||
element.theme.Color(tomo.ColorForeground, state),
|
|
||||||
bounds.Min.Add(offset))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,35 @@
|
|||||||
package elements
|
package elements
|
||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/artist/patterns"
|
import "git.tebibyte.media/sashakoshka/tomo/artist/patterns"
|
||||||
|
|
||||||
|
// TODO: this element is lame need to make it better
|
||||||
|
|
||||||
|
// Image is an element capable of displaying an image.
|
||||||
type Image struct {
|
type Image struct {
|
||||||
*core.Core
|
entity tomo.Entity
|
||||||
core core.CoreControl
|
|
||||||
buffer canvas.Canvas
|
buffer canvas.Canvas
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewImage creates a new image element.
|
||||||
func NewImage (image image.Image) (element *Image) {
|
func NewImage (image image.Image) (element *Image) {
|
||||||
element = &Image { buffer: canvas.FromImage(image) }
|
element = &Image { buffer: canvas.FromImage(image) }
|
||||||
element.Core, element.core = core.NewCore(element, element.draw)
|
|
||||||
bounds := image.Bounds()
|
|
||||||
element.core.SetMinimumSize(bounds.Dx(), bounds.Dy())
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Image) draw () {
|
// Bind binds this element to an entity.
|
||||||
(patterns.Texture { Canvas: element.buffer }).
|
func (element *Image) Bind (entity tomo.Entity) {
|
||||||
Draw(element.core, element.Bounds())
|
if entity == nil { element.entity = nil; return }
|
||||||
|
element.entity = entity
|
||||||
|
bounds := element.buffer.Bounds()
|
||||||
|
element.entity.SetMinimumSize(bounds.Dx(), bounds.Dy())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw causes the element to draw to the specified destination canvas.
|
||||||
|
func (element *Image) Draw (destination canvas.Canvas) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
(patterns.Texture { Canvas: element.buffer }).
|
||||||
|
Draw(destination, element.entity.Bounds())
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,14 @@ package elements
|
|||||||
|
|
||||||
import "golang.org/x/image/math/fixed"
|
import "golang.org/x/image/math/fixed"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
// Label is a simple text box.
|
// Label is a simple text box.
|
||||||
type Label struct {
|
type Label struct {
|
||||||
*core.Core
|
entity tomo.FlexibleEntity
|
||||||
core core.CoreControl
|
|
||||||
|
|
||||||
align textdraw.Align
|
align textdraw.Align
|
||||||
wrap bool
|
wrap bool
|
||||||
@ -19,11 +18,10 @@ type Label struct {
|
|||||||
|
|
||||||
forcedColumns int
|
forcedColumns int
|
||||||
forcedRows int
|
forcedRows int
|
||||||
|
minHeight int
|
||||||
|
|
||||||
config config.Wrapped
|
config config.Wrapped
|
||||||
theme theme.Wrapped
|
theme theme.Wrapped
|
||||||
|
|
||||||
onFlexibleHeightChange func ()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@ -31,7 +29,6 @@ type Label struct {
|
|||||||
func NewLabel (text string, wrap bool) (element *Label) {
|
func NewLabel (text string, wrap bool) (element *Label) {
|
||||||
element = &Label { }
|
element = &Label { }
|
||||||
element.theme.Case = tomo.C("tomo", "label")
|
element.theme.Case = tomo.C("tomo", "label")
|
||||||
element.Core, element.core = core.NewCore(element, element.handleResize)
|
|
||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
tomo.FontStyleRegular,
|
tomo.FontStyleRegular,
|
||||||
tomo.FontSizeNormal))
|
tomo.FontSizeNormal))
|
||||||
@ -40,29 +37,11 @@ func NewLabel (text string, wrap bool) (element *Label) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Label) redo () {
|
// Bind binds this element to an entity.
|
||||||
face := element.theme.FontFace (
|
func (element *Label) Bind (entity tomo.Entity) {
|
||||||
tomo.FontStyleRegular,
|
if entity == nil { element.entity = nil; return }
|
||||||
tomo.FontSizeNormal)
|
element.entity = entity.(tomo.FlexibleEntity)
|
||||||
element.drawer.SetFace(face)
|
|
||||||
element.updateMinimumSize()
|
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 {
|
|
||||||
element.drawer.SetMaxWidth(bounds.Dx())
|
|
||||||
element.drawer.SetMaxHeight(bounds.Dy())
|
|
||||||
}
|
|
||||||
element.draw()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EmCollapse forces a minimum width and height upon the label. The width is
|
// EmCollapse forces a minimum width and height upon the label. The width is
|
||||||
@ -73,6 +52,7 @@ func (element *Label) handleResize () {
|
|||||||
func (element *Label) EmCollapse (columns int, rows int) {
|
func (element *Label) EmCollapse (columns int, rows int) {
|
||||||
element.forcedColumns = columns
|
element.forcedColumns = columns
|
||||||
element.forcedRows = rows
|
element.forcedRows = rows
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,29 +62,19 @@ func (element *Label) FlexibleHeightFor (width int) (height int) {
|
|||||||
if element.wrap {
|
if element.wrap {
|
||||||
return element.drawer.ReccomendedHeightFor(width)
|
return element.drawer.ReccomendedHeightFor(width)
|
||||||
} else {
|
} else {
|
||||||
_, height = element.MinimumSize()
|
return element.minHeight
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFlexibleHeightChange sets a function to be called when the parameters
|
|
||||||
// affecting this element's flexible height are changed.
|
|
||||||
func (element *Label) OnFlexibleHeightChange (callback func ()) {
|
|
||||||
element.onFlexibleHeightChange = callback
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetText sets the label's text.
|
// SetText sets the label's text.
|
||||||
func (element *Label) SetText (text string) {
|
func (element *Label) SetText (text string) {
|
||||||
if element.text == text { return }
|
if element.text == text { return }
|
||||||
|
|
||||||
element.text = text
|
element.text = text
|
||||||
element.drawer.SetText([]rune(text))
|
element.drawer.SetText([]rune(text))
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
if element.core.HasImage () {
|
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetWrap sets wether or not the label's text wraps. If the text is set to
|
// SetWrap sets wether or not the label's text wraps. If the text is set to
|
||||||
@ -118,26 +88,19 @@ func (element *Label) SetWrap (wrap bool) {
|
|||||||
element.drawer.SetMaxHeight(0)
|
element.drawer.SetMaxHeight(0)
|
||||||
}
|
}
|
||||||
element.wrap = wrap
|
element.wrap = wrap
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
if element.core.HasImage () {
|
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAlign sets the alignment method of the label.
|
// SetAlign sets the alignment method of the label.
|
||||||
func (element *Label) SetAlign (align textdraw.Align) {
|
func (element *Label) SetAlign (align textdraw.Align) {
|
||||||
if align == element.align { return }
|
if align == element.align { return }
|
||||||
|
|
||||||
element.align = align
|
element.align = align
|
||||||
element.drawer.SetAlign(align)
|
element.drawer.SetAlign(align)
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
if element.core.HasImage () {
|
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
@ -147,24 +110,38 @@ func (element *Label) SetTheme (new tomo.Theme) {
|
|||||||
element.drawer.SetFace (element.theme.FontFace (
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
tomo.FontStyleRegular,
|
tomo.FontStyleRegular,
|
||||||
tomo.FontSizeNormal))
|
tomo.FontSizeNormal))
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
if element.core.HasImage () {
|
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
func (element *Label) SetConfig (new tomo.Config) {
|
func (element *Label) SetConfig (new tomo.Config) {
|
||||||
if new == element.config.Config { return }
|
if new == element.config.Config { return }
|
||||||
element.config.Config = new
|
element.config.Config = new
|
||||||
|
if element.entity == nil { return }
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
if element.core.HasImage () {
|
// Draw causes the element to draw to the specified destination canvas.
|
||||||
element.draw()
|
func (element *Label) Draw (destination canvas.Canvas) {
|
||||||
element.core.DamageAll()
|
if element.entity == nil { return }
|
||||||
|
|
||||||
|
bounds := element.entity. Bounds()
|
||||||
|
|
||||||
|
if element.wrap {
|
||||||
|
element.drawer.SetMaxWidth(bounds.Dx())
|
||||||
|
element.drawer.SetMaxHeight(bounds.Dy())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
element.entity.DrawBackground(destination, bounds)
|
||||||
|
|
||||||
|
textBounds := element.drawer.LayoutBounds()
|
||||||
|
foreground := element.theme.Color (
|
||||||
|
tomo.ColorForeground,
|
||||||
|
tomo.State { })
|
||||||
|
element.drawer.Draw(destination, foreground, bounds.Min.Sub(textBounds.Min))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Label) updateMinimumSize () {
|
func (element *Label) updateMinimumSize () {
|
||||||
@ -176,9 +153,8 @@ func (element *Label) updateMinimumSize () {
|
|||||||
em = element.theme.Padding(tomo.PatternBackground)[0]
|
em = element.theme.Padding(tomo.PatternBackground)[0]
|
||||||
}
|
}
|
||||||
width, height = em, element.drawer.LineHeight().Round()
|
width, height = em, element.drawer.LineHeight().Round()
|
||||||
if element.onFlexibleHeightChange != nil {
|
// FIXME we shoudl not have to pass in the element here
|
||||||
element.onFlexibleHeightChange()
|
element.entity.NotifyFlexibleHeightChange(element)
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
bounds := element.drawer.LayoutBounds()
|
bounds := element.drawer.LayoutBounds()
|
||||||
width, height = bounds.Dx(), bounds.Dy()
|
width, height = bounds.Dx(), bounds.Dy()
|
||||||
@ -196,18 +172,6 @@ func (element *Label) updateMinimumSize () {
|
|||||||
Mul(fixed.I(element.forcedRows)).Floor()
|
Mul(fixed.I(element.forcedRows)).Floor()
|
||||||
}
|
}
|
||||||
|
|
||||||
element.core.SetMinimumSize(width, height)
|
element.minHeight = height
|
||||||
}
|
element.entity.SetMinimumSize(width, height)
|
||||||
|
|
||||||
func (element *Label) draw () {
|
|
||||||
element.core.DrawBackground (
|
|
||||||
element.theme.Pattern(tomo.PatternBackground, tomo.State { }))
|
|
||||||
|
|
||||||
bounds := element.Bounds()
|
|
||||||
textBounds := element.drawer.LayoutBounds()
|
|
||||||
|
|
||||||
foreground := element.theme.Color (
|
|
||||||
tomo.ColorForeground,
|
|
||||||
tomo.State { })
|
|
||||||
element.drawer.Draw(element.core, foreground, bounds.Min.Sub(textBounds.Min))
|
|
||||||
}
|
}
|
||||||
|
177
elements/notdone/label.go
Normal file
177
elements/notdone/label.go
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package elements
|
||||||
|
|
||||||
|
import "golang.org/x/image/math/fixed"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
|
// Label is a simple text box.
|
||||||
|
type Label struct {
|
||||||
|
entity tomo.FlexibleEntity
|
||||||
|
|
||||||
|
align textdraw.Align
|
||||||
|
wrap bool
|
||||||
|
text string
|
||||||
|
drawer textdraw.Drawer
|
||||||
|
|
||||||
|
forcedColumns int
|
||||||
|
forcedRows int
|
||||||
|
minHeight int
|
||||||
|
|
||||||
|
config config.Wrapped
|
||||||
|
theme theme.Wrapped
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.theme.Case = tomo.C("tomo", "label")
|
||||||
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
|
tomo.FontStyleRegular,
|
||||||
|
tomo.FontSizeNormal))
|
||||||
|
element.SetWrap(wrap)
|
||||||
|
element.SetText(text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind binds this element to an entity.
|
||||||
|
func (element *Label) Bind (entity tomo.Entity) {
|
||||||
|
element.entity = entity.(tomo.FlexibleEntity)
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.updateMinimumSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmCollapse forces a minimum width and height upon the label. The width is
|
||||||
|
// measured in emspaces, and the height is measured in lines. If a zero value is
|
||||||
|
// given for a dimension, its minimum will be determined by the label's content.
|
||||||
|
// If the label's content is greater than these dimensions, it will be truncated
|
||||||
|
// to fit.
|
||||||
|
func (element *Label) EmCollapse (columns int, rows int) {
|
||||||
|
element.forcedColumns = columns
|
||||||
|
element.forcedRows = rows
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.updateMinimumSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlexibleHeightFor returns the reccomended height for this element based on
|
||||||
|
// the given width in order to allow the text to wrap properly.
|
||||||
|
func (element *Label) FlexibleHeightFor (width int) (height int) {
|
||||||
|
if element.wrap {
|
||||||
|
return element.drawer.ReccomendedHeightFor(width)
|
||||||
|
} else {
|
||||||
|
return element.minHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetText sets the label's text.
|
||||||
|
func (element *Label) SetText (text string) {
|
||||||
|
if element.text == text { return }
|
||||||
|
|
||||||
|
element.text = text
|
||||||
|
element.drawer.SetText([]rune(text))
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWrap sets wether or not the label's text wraps. If the text is set to
|
||||||
|
// wrap, the element will have a minimum size of a single character and
|
||||||
|
// automatically wrap its text. If the text is set to not wrap, the element will
|
||||||
|
// have a minimum size that fits its text.
|
||||||
|
func (element *Label) SetWrap (wrap bool) {
|
||||||
|
if wrap == element.wrap { return }
|
||||||
|
if !wrap {
|
||||||
|
element.drawer.SetMaxWidth(0)
|
||||||
|
element.drawer.SetMaxHeight(0)
|
||||||
|
}
|
||||||
|
element.wrap = wrap
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAlign sets the alignment method of the label.
|
||||||
|
func (element *Label) SetAlign (align textdraw.Align) {
|
||||||
|
if align == element.align { return }
|
||||||
|
element.align = align
|
||||||
|
element.drawer.SetAlign(align)
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTheme sets the element's theme.
|
||||||
|
func (element *Label) SetTheme (new tomo.Theme) {
|
||||||
|
if new == element.theme.Theme { return }
|
||||||
|
element.theme.Theme = new
|
||||||
|
element.drawer.SetFace (element.theme.FontFace (
|
||||||
|
tomo.FontStyleRegular,
|
||||||
|
tomo.FontSizeNormal))
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConfig sets the element's configuration.
|
||||||
|
func (element *Label) SetConfig (new tomo.Config) {
|
||||||
|
if new == element.config.Config { return }
|
||||||
|
element.config.Config = new
|
||||||
|
if element.entity == nil { return }
|
||||||
|
element.updateMinimumSize()
|
||||||
|
element.entity.Invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw causes the element to draw to the specified destination canvas.
|
||||||
|
func (element *Label) Draw (destination canvas.Canvas) {
|
||||||
|
if element.entity == nil { return }
|
||||||
|
|
||||||
|
bounds := element.entity. Bounds()
|
||||||
|
|
||||||
|
if element.wrap {
|
||||||
|
element.drawer.SetMaxWidth(bounds.Dx())
|
||||||
|
element.drawer.SetMaxHeight(bounds.Dy())
|
||||||
|
}
|
||||||
|
|
||||||
|
element.entity.DrawBackground(destination, bounds)
|
||||||
|
|
||||||
|
textBounds := element.drawer.LayoutBounds()
|
||||||
|
foreground := element.theme.Color (
|
||||||
|
tomo.ColorForeground,
|
||||||
|
tomo.State { })
|
||||||
|
element.drawer.Draw(destination, foreground, bounds.Min.Sub(textBounds.Min))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *Label) updateMinimumSize () {
|
||||||
|
var width, height int
|
||||||
|
|
||||||
|
if element.wrap {
|
||||||
|
em := element.drawer.Em().Round()
|
||||||
|
if em < 1 {
|
||||||
|
em = element.theme.Padding(tomo.PatternBackground)[0]
|
||||||
|
}
|
||||||
|
width, height = em, element.drawer.LineHeight().Round()
|
||||||
|
// FIXME we shoudl not have to pass in the element here
|
||||||
|
element.entity.NotifyFlexibleHeightChange(element)
|
||||||
|
} else {
|
||||||
|
bounds := element.drawer.LayoutBounds()
|
||||||
|
width, height = bounds.Dx(), bounds.Dy()
|
||||||
|
}
|
||||||
|
|
||||||
|
if element.forcedColumns > 0 {
|
||||||
|
width =
|
||||||
|
element.drawer.Em().
|
||||||
|
Mul(fixed.I(element.forcedColumns)).Floor()
|
||||||
|
}
|
||||||
|
|
||||||
|
if element.forcedRows > 0 {
|
||||||
|
height =
|
||||||
|
element.drawer.LineHeight().
|
||||||
|
Mul(fixed.I(element.forcedRows)).Floor()
|
||||||
|
}
|
||||||
|
|
||||||
|
element.minHeight = height
|
||||||
|
element.entity.SetMinimumSize(width, height)
|
||||||
|
}
|
@ -6,17 +6,18 @@ import "git.tebibyte.media/sashakoshka/tomo"
|
|||||||
import "git.tebibyte.media/sashakoshka/tomo/input"
|
import "git.tebibyte.media/sashakoshka/tomo/input"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||||
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/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
|
type listEntity interface {
|
||||||
|
tomo.FlexibleEntity
|
||||||
|
tomo.ContainerEntity
|
||||||
|
tomo.ScrollableEntity
|
||||||
|
}
|
||||||
|
|
||||||
// List is an element that contains several objects that a user can select.
|
// List is an element that contains several objects that a user can select.
|
||||||
type List struct {
|
type List struct {
|
||||||
*core.Core
|
entity listEntity
|
||||||
*core.FocusableCore
|
|
||||||
core core.CoreControl
|
|
||||||
focusableControl core.FocusableCoreControl
|
|
||||||
|
|
||||||
pressed bool
|
pressed bool
|
||||||
|
|
||||||
contentHeight int
|
contentHeight int
|
||||||
@ -25,7 +26,6 @@ type List struct {
|
|||||||
|
|
||||||
selectedEntry int
|
selectedEntry int
|
||||||
scroll int
|
scroll int
|
||||||
entries []ListEntry
|
|
||||||
|
|
||||||
config config.Wrapped
|
config config.Wrapped
|
||||||
theme theme.Wrapped
|
theme theme.Wrapped
|
||||||
@ -38,36 +38,14 @@ type List struct {
|
|||||||
func NewList (entries ...ListEntry) (element *List) {
|
func NewList (entries ...ListEntry) (element *List) {
|
||||||
element = &List { selectedEntry: -1 }
|
element = &List { selectedEntry: -1 }
|
||||||
element.theme.Case = tomo.C("tomo", "list")
|
element.theme.Case = tomo.C("tomo", "list")
|
||||||
element.Core, element.core = core.NewCore(element, element.handleResize)
|
|
||||||
element.FocusableCore,
|
|
||||||
element.focusableControl = core.NewFocusableCore (element.core, func () {
|
|
||||||
if element.core.HasImage () {
|
|
||||||
element.draw()
|
|
||||||
element.core.DamageAll()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
element.entries = make([]ListEntry, len(entries))
|
element.entries = make([]ListEntry, len(entries))
|
||||||
for index, entry := range entries {
|
for index, entry := range entries {
|
||||||
element.entries[index] = entry
|
element.entries[index] = entry
|
||||||
}
|
}
|
||||||
|
|
||||||
element.updateMinimumSize()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *List) handleResize () {
|
|
||||||
for index, entry := range element.entries {
|
|
||||||
element.entries[index] = element.resizeEntryToFit(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
if element.scroll > element.maxScrollHeight() {
|
|
||||||
element.scroll = element.maxScrollHeight()
|
|
||||||
}
|
|
||||||
element.draw()
|
|
||||||
element.scrollBoundsChange()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTheme sets the element's theme.
|
// SetTheme sets the element's theme.
|
||||||
func (element *List) SetTheme (new tomo.Theme) {
|
func (element *List) SetTheme (new tomo.Theme) {
|
||||||
if new == element.theme.Theme { return }
|
if new == element.theme.Theme { return }
|
||||||
@ -77,7 +55,7 @@ func (element *List) SetTheme (new tomo.Theme) {
|
|||||||
element.entries[index] = entry
|
element.entries[index] = entry
|
||||||
}
|
}
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.redo()
|
element.entity.Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig sets the element's configuration.
|
// SetConfig sets the element's configuration.
|
||||||
@ -92,18 +70,6 @@ func (element *List) SetConfig (new tomo.Config) {
|
|||||||
element.redo()
|
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()
|
|
||||||
}
|
|
||||||
element.scrollBoundsChange()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collapse forces a minimum width and height upon the list. If a zero value is
|
// 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.
|
// 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
|
// If the list's height goes beyond the forced size, it will need to be accessed
|
||||||
@ -213,19 +179,6 @@ func (element *List) ScrollAxes () (horizontal, vertical bool) {
|
|||||||
return false, true
|
return false, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *List) scrollViewportHeight () (height int) {
|
|
||||||
padding := element.theme.Padding(tomo.PatternSunken)
|
|
||||||
return element.Bounds().Dy() - padding[0] - padding[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *List) maxScrollHeight () (height int) {
|
|
||||||
height =
|
|
||||||
element.contentHeight -
|
|
||||||
element.scrollViewportHeight()
|
|
||||||
if height < 0 { height = 0 }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnNoEntrySelected sets a function to be called when the user chooses to
|
// OnNoEntrySelected sets a function to be called when the user chooses to
|
||||||
// deselect the current selected entry by clicking on empty space within the
|
// deselect the current selected entry by clicking on empty space within the
|
||||||
// list or by pressing the escape key.
|
// list or by pressing the escape key.
|
||||||
@ -443,7 +396,32 @@ func (element *List) scrollBoundsChange () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *List) draw () {
|
func (element *List) scrollViewportHeight () (height int) {
|
||||||
|
padding := element.theme.Padding(tomo.PatternSunken)
|
||||||
|
return element.Bounds().Dy() - padding[0] - padding[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *List) maxScrollHeight () (height int) {
|
||||||
|
height =
|
||||||
|
element.contentHeight -
|
||||||
|
element.scrollViewportHeight()
|
||||||
|
if height < 0 { height = 0 }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *List) Layout () {
|
||||||
|
for index, entry := range element.entries {
|
||||||
|
element.entries[index] = element.resizeEntryToFit(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
if element.scroll > element.maxScrollHeight() {
|
||||||
|
element.scroll = element.maxScrollHeight()
|
||||||
|
}
|
||||||
|
element.draw()
|
||||||
|
element.scrollBoundsChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *List) Draw (destination canvas.Canvas) {
|
||||||
bounds := element.Bounds()
|
bounds := element.Bounds()
|
||||||
padding := element.theme.Padding(tomo.PatternSunken)
|
padding := element.theme.Padding(tomo.PatternSunken)
|
||||||
innerBounds := padding.Apply(bounds)
|
innerBounds := padding.Apply(bounds)
|
@ -2,14 +2,11 @@ package elements
|
|||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
// ProgressBar displays a visual indication of how far along a task is.
|
// ProgressBar displays a visual indication of how far along a task is.
|
||||||
type ProgressBar struct {
|
type ProgressBar struct {
|
||||||
*core.Core
|
|
||||||
core core.CoreControl
|
|
||||||
progress float64
|
progress float64
|
||||||
|
|
||||||
config config.Wrapped
|
config config.Wrapped
|
@ -3,7 +3,6 @@ package elements
|
|||||||
import "image"
|
import "image"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/input"
|
import "git.tebibyte.media/sashakoshka/tomo/input"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
@ -19,9 +18,6 @@ import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
|||||||
// Typically, you wont't want to use a ScrollBar by itself. A ScrollContainer is
|
// Typically, you wont't want to use a ScrollBar by itself. A ScrollContainer is
|
||||||
// better for most cases.
|
// better for most cases.
|
||||||
type ScrollBar struct {
|
type ScrollBar struct {
|
||||||
*core.Core
|
|
||||||
core core.CoreControl
|
|
||||||
|
|
||||||
vertical bool
|
vertical bool
|
||||||
enabled bool
|
enabled bool
|
||||||
dragging bool
|
dragging bool
|
@ -3,17 +3,11 @@ package elements
|
|||||||
import "image"
|
import "image"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/input"
|
import "git.tebibyte.media/sashakoshka/tomo/input"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
// Slider is a slider control with a floating point value between zero and one.
|
// Slider is a slider control with a floating point value between zero and one.
|
||||||
type Slider struct {
|
type Slider struct {
|
||||||
*core.Core
|
|
||||||
*core.FocusableCore
|
|
||||||
core core.CoreControl
|
|
||||||
focusableControl core.FocusableCoreControl
|
|
||||||
|
|
||||||
value float64
|
value float64
|
||||||
vertical bool
|
vertical bool
|
||||||
dragging bool
|
dragging bool
|
@ -1,14 +1,11 @@
|
|||||||
package elements
|
package elements
|
||||||
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
// Spacer can be used to put space between two elements..
|
// Spacer can be used to put space between two elements..
|
||||||
type Spacer struct {
|
type Spacer struct {
|
||||||
*core.Core
|
|
||||||
core core.CoreControl
|
|
||||||
line bool
|
line bool
|
||||||
|
|
||||||
config config.Wrapped
|
config config.Wrapped
|
@ -4,17 +4,12 @@ import "image"
|
|||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
import "git.tebibyte.media/sashakoshka/tomo"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/input"
|
import "git.tebibyte.media/sashakoshka/tomo/input"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
// Switch is a toggle-able on/off switch with an optional label. It is
|
// Switch is a toggle-able on/off switch with an optional label. It is
|
||||||
// functionally identical to Checkbox, but plays a different semantic role.
|
// functionally identical to Checkbox, but plays a different semantic role.
|
||||||
type Switch struct {
|
type Switch struct {
|
||||||
*core.Core
|
|
||||||
*core.FocusableCore
|
|
||||||
core core.CoreControl
|
|
||||||
focusableControl core.FocusableCoreControl
|
|
||||||
drawer textdraw.Drawer
|
drawer textdraw.Drawer
|
||||||
|
|
||||||
pressed bool
|
pressed bool
|
@ -12,17 +12,11 @@ import "git.tebibyte.media/sashakoshka/tomo/textdraw"
|
|||||||
import "git.tebibyte.media/sashakoshka/tomo/textmanip"
|
import "git.tebibyte.media/sashakoshka/tomo/textmanip"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/fixedutil"
|
import "git.tebibyte.media/sashakoshka/tomo/fixedutil"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/artist/shapes"
|
import "git.tebibyte.media/sashakoshka/tomo/artist/shapes"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||||
|
|
||||||
// TextBox is a single-line text input.
|
// TextBox is a single-line text input.
|
||||||
type TextBox struct {
|
type TextBox struct {
|
||||||
*core.Core
|
|
||||||
*core.FocusableCore
|
|
||||||
core core.CoreControl
|
|
||||||
focusableControl core.FocusableCoreControl
|
|
||||||
|
|
||||||
lastClick time.Time
|
lastClick time.Time
|
||||||
dragging int
|
dragging int
|
||||||
dot textmanip.Dot
|
dot textmanip.Dot
|
Reference in New Issue
Block a user