Styling now supports selection

This commit is contained in:
Sasha Koshka 2023-01-09 15:14:36 -05:00
parent d1ec5f2cec
commit 70e0566f3f
6 changed files with 125 additions and 120 deletions

View File

@ -84,6 +84,7 @@ func (window *Window) Adopt (child tomo.Element) {
child.SetParentHooks (tomo.ParentHooks {
Draw: window.childDrawCallback,
MinimumSizeChange: window.childMinimumSizeChangeCallback,
SelectionRequest: window.childSelectionRequestCallback,
})
window.resizeChildToFit()
}
@ -239,6 +240,10 @@ func (window *Window) childMinimumSizeChangeCallback (width, height int) {
}
}
func (window *Window) childSelectionRequestCallback () {
window.child.Handle(tomo.EventSelect { })
}
func (window *Window) pushRegion (region image.Rectangle) {
if window.xCanvas == nil { panic("whoopsie!!!!!!!!!!!!!!") }
image, ok := window.xCanvas.SubImage(region).(*xgraphics.Image)

View File

@ -1,7 +1,6 @@
package basic
import "image"
import "image/color"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/artist"
@ -10,8 +9,9 @@ type Button struct {
*Core
core CoreControl
pressed bool
enabled bool
pressed bool
enabled bool
selected bool
onClick func ()
text string
@ -39,6 +39,7 @@ func (element *Button) Handle (event tomo.Event) {
if !element.enabled { break }
mouseDownEvent := event.(tomo.EventMouseDown)
element.Select()
if mouseDownEvent.Button != tomo.ButtonLeft { break }
element.pressed = true
if element.core.HasImage() {
@ -63,11 +64,39 @@ func (element *Button) Handle (event tomo.Event) {
if within && element.onClick != nil {
element.onClick()
}
case tomo.EventSelect:
element.selected = true
case tomo.EventDeselect:
element.selected = false
// TODO: handle selection events, and the enter key
}
return
}
func (element *Button) OnClick (callback func ()) {
element.onClick = callback
}
func (element *Button) AdvanceSelection (direction int) (ok bool) {
wasSelected := element.selected
element.selected = false
if element.core.HasImage() && wasSelected {
element.draw()
element.core.PushAll()
}
return
}
func (element *Button) Selectable () (selectable bool) {
return true
}
func (element *Button) Select () {
element.core.Select()
}
func (element *Button) SetEnabled (enabled bool) {
if element.enabled == enabled { return }
element.enabled = enabled
@ -92,24 +121,15 @@ func (element *Button) SetText (text string) {
}
}
func (element *Button) OnClick (callback func ()) {
element.onClick = callback
}
func (element *Button) AdvanceSelection (direction int) (ok bool) {
return
}
func (element *Button) Selectable () (selectable bool) {
return true
}
func (element *Button) draw () {
bounds := element.core.Bounds()
artist.ChiseledRectangle (
element.core,
theme.RaisedProfile(element.pressed, element.enabled),
theme.RaisedProfile (
element.pressed,
element.enabled,
element.selected),
bounds)
innerBounds := bounds

View File

@ -67,16 +67,19 @@ func (control CoreControl) HasImage () (has bool) {
return
}
func (control CoreControl) Select () {
control.core.hooks.RunSelectionRequest()
}
func (control CoreControl) PushRegion (bounds image.Rectangle) {
core := control.core
core.hooks.RunDraw(control.SubImage(bounds).(*image.RGBA))
control.core.hooks.RunDraw(control.SubImage(bounds).(*image.RGBA))
}
func (control CoreControl) PushAll () {
control.PushRegion(control.Bounds())
}
func (control CoreControl) AllocateCanvas (width, height int) {
func (control *CoreControl) AllocateCanvas (width, height int) {
core := control.core
width, height, _ = control.ConstrainSize(width, height)
core.canvas = image.NewRGBA(image.Rect (0, 0, width, height))

View File

@ -1,24 +1,24 @@
package basic
import "image"
import "image/color"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/artist"
type Label struct {
core Core
*Core
core CoreControl
text string
drawer artist.TextDrawer
}
func NewLabel (text string) (element *Label) {
element = &Label { }
element.core = NewCore(element)
element.Core, element.core = NewCore(element)
face := theme.FontFaceRegular()
element.drawer.SetFace(face)
element.SetText(text)
// FIXME: set the minimum size to one char
metrics := face.Metrics()
emspace, _ := face.GlyphAdvance('M')
intEmspace := emspace.Round()
@ -52,46 +52,11 @@ func (element *Label) SetText (text string) {
}
}
func (element *Label) ColorModel () (model color.Model) {
return color.RGBAModel
}
func (element *Label) At (x, y int) (pixel color.Color) {
pixel = element.core.At(x, y)
return
}
func (element *Label) RGBAAt (x, y int) (pixel color.RGBA) {
pixel = element.core.RGBAAt(x, y)
return
}
func (element *Label) Bounds () (bounds image.Rectangle) {
bounds = element.core.Bounds()
return
}
func (element *Label) SetDrawCallback (draw func (region tomo.Image)) {
element.core.SetDrawCallback(draw)
}
func (element *Label) SetMinimumSizeChangeCallback (
notify func (width, height int),
) {
element.core.SetMinimumSizeChangeCallback(notify)
}
func (element *Label) Selectable () (selectable bool) {
return
}
func (element *Label) MinimumWidth () (minimum int) {
minimum = element.core.MinimumWidth()
return
}
func (element *Label) MinimumHeight () (minimum int) {
minimum = element.core.MinimumHeight()
func (element *Label) AdvanceSelection (direction int) (ok bool) {
return
}

View File

@ -7,13 +7,14 @@ import "git.tebibyte.media/sashakoshka/tomo/artist"
// Test is a simple element that can be used as a placeholder.
type Test struct {
core Core
*Core
core CoreControl
}
// NewTest creates a new test element.
func NewTest () (element *Test) {
element = &Test { }
element.core = NewCore(element)
element.Core, element.core = NewCore(element)
element.core.SetMinimumSize(32, 32)
return
}
@ -46,45 +47,10 @@ func (element *Test) Handle (event tomo.Event) {
return
}
func (element *Test) ColorModel () (model color.Model) {
return color.RGBAModel
}
func (element *Test) At (x, y int) (pixel color.Color) {
pixel = element.core.At(x, y)
return
}
func (element *Test) RGBAAt (x, y int) (pixel color.RGBA) {
pixel = element.core.RGBAAt(x, y)
return
}
func (element *Test) Bounds () (bounds image.Rectangle) {
bounds = element.core.Bounds()
return
}
func (element *Test) SetDrawCallback (draw func (region tomo.Image)) {
element.core.SetDrawCallback(draw)
}
func (element *Test) SetMinimumSizeChangeCallback (
notify func (width, height int),
) {
element.core.SetMinimumSizeChangeCallback(notify)
}
func (element *Test) Selectable () (selectable bool) {
return
}
func (element *Test) MinimumWidth () (minimum int) {
minimum = element.core.MinimumWidth()
return
}
func (element *Test) MinimumHeight () (minimum int) {
minimum = element.core.MinimumHeight()
func (element *Test) AdvanceSelection (direction int) (ok bool) {
return
}

View File

@ -10,11 +10,15 @@ import "git.tebibyte.media/sashakoshka/tomo/defaultfont"
// none of these colors are final! TODO: generate these values from a theme
// file at startup.
var foregroundImage = artist.NewUniform(color.Gray16 { 0x0000})
var foregroundImage = artist.NewUniform(color.Gray16 { 0x0000})
var disabledForegroundImage = artist.NewUniform(color.Gray16 { 0x5555})
var accentImage = artist.NewUniform(color.RGBA { 0xFF, 0x22, 0x00, 0xFF})
var highlightImage = artist.NewUniform(color.Gray16 { 0xEEEE })
var shadowImage = artist.NewUniform(color.Gray16 { 0x3333 })
var accentImage = artist.NewUniform(color.RGBA { 0x3E, 0x81, 0x69, 0xFF})
var highlightImage = artist.NewUniform(color.Gray16 { 0xEEEE })
var shadowImage = artist.NewUniform(color.Gray16 { 0x3333 })
var weakShadeImage = artist.NewUniform(color.Gray16 { 0x7777 })
var strokeImage = artist.NewUniform(color.Gray16 { 0x0000 })
var weakStrokeImage = artist.NewUniform(color.Gray16 { 0x3333 })
var insetShadowImage = artist.NewUniform(color.Gray16 { 0x7777 })
var backgroundImage = artist.NewUniform(color.Gray16 { 0xAAAA})
var backgroundProfile = artist.ShadingProfile {
@ -31,42 +35,66 @@ var raisedImage = artist.NewUniform(color.RGBA { 0x8D, 0x98, 0x94, 0xFF})
var raisedProfile = artist.ShadingProfile {
Highlight: highlightImage,
Shadow: shadowImage,
Stroke: artist.NewUniform(color.Gray16 { 0x0000 }),
Stroke: strokeImage,
Fill: raisedImage,
StrokeWeight: 1,
ShadingWeight: 1,
}
var selectedRaisedProfile = artist.ShadingProfile {
Highlight: highlightImage,
Shadow: shadowImage,
Stroke: accentImage,
Fill: raisedImage,
StrokeWeight: 1,
ShadingWeight: 1,
}
var engravedRaisedProfile = artist.ShadingProfile {
Highlight: artist.NewUniform(color.Gray16 { 0x7777 }),
Highlight: weakShadeImage,
Shadow: raisedImage,
Stroke: artist.NewUniform(color.Gray16 { 0x0000 }),
Stroke: strokeImage,
Fill: raisedImage,
StrokeWeight: 1,
ShadingWeight: 1,
}
var selectedEngravedRaisedProfile = artist.ShadingProfile {
Highlight: insetShadowImage,
Shadow: raisedImage,
Stroke: accentImage,
Fill: raisedImage,
StrokeWeight: 1,
ShadingWeight: 1,
}
var disabledRaisedProfile = artist.ShadingProfile {
Highlight: artist.NewUniform(color.Gray16 { 0x7777 }),
Shadow: artist.NewUniform(color.Gray16 { 0x7777 }),
Stroke: artist.NewUniform(color.Gray16 { 0x3333 }),
Fill: raisedImage,
Highlight: weakShadeImage,
Shadow: weakShadeImage,
Stroke: weakStrokeImage,
Fill: backgroundImage,
StrokeWeight: 1,
ShadingWeight: 0,
}
var inputImage = artist.NewUniform(color.Gray16 { 0xFFFF })
var inputProfile = artist.ShadingProfile {
Highlight: shadowImage,
Shadow: highlightImage,
Stroke: artist.NewUniform(color.Gray16 { 0x0000 }),
Highlight: insetShadowImage,
Shadow: inputImage,
Stroke: strokeImage,
Fill: inputImage,
StrokeWeight: 1,
ShadingWeight: 1,
}
var selectedInputProfile = artist.ShadingProfile {
Highlight: insetShadowImage,
Shadow: inputImage,
Stroke: accentImage,
Fill: inputImage,
StrokeWeight: 1,
ShadingWeight: 1,
}
var disabledInputProfile = artist.ShadingProfile {
Highlight: artist.NewUniform(color.Gray16 { 0x7777 }),
Shadow: artist.NewUniform(color.Gray16 { 0x7777 }),
Stroke: artist.NewUniform(color.Gray16 { 0x3333 }),
Fill: inputImage,
Highlight: weakShadeImage,
Shadow: backgroundImage,
Stroke: accentImage,
Fill: backgroundImage,
StrokeWeight: 1,
ShadingWeight: 0,
}
@ -82,12 +110,26 @@ func BackgroundProfile (engraved bool) artist.ShadingProfile {
// RaisedProfile returns the shading profile to be used for raised objects such
// as buttons.
func RaisedProfile (engraved bool, enabled bool) artist.ShadingProfile {
func RaisedProfile (
engraved bool,
enabled bool,
selected bool,
) (
artist.ShadingProfile,
) {
if enabled {
if engraved {
return engravedRaisedProfile
if selected {
return selectedEngravedRaisedProfile
} else {
return engravedRaisedProfile
}
} else {
return raisedProfile
if selected {
return selectedRaisedProfile
} else {
return raisedProfile
}
}
} else {
return disabledRaisedProfile
@ -95,9 +137,13 @@ func RaisedProfile (engraved bool, enabled bool) artist.ShadingProfile {
}
// InputProfile returns the shading profile to be used for input fields.
func InputProfile (enabled bool) artist.ShadingProfile {
func InputProfile (enabled bool, selected bool) artist.ShadingProfile {
if enabled {
return inputProfile
if selected {
return selectedInputProfile
} else {
return inputProfile
}
} else {
return disabledInputProfile
}