Noah Petherbridge
5434484b6e
The `level.Canvas` is a widget that holds onto its Palette and Grid and has interactions to allow scrolling and editing the grid using the swatches available on the palette. Thus all of the logic in the Editor Mode for drawing directly onto the root SDL surface are now handled inside a level.Canvas instance. The `level.Canvas` widget has the following properties: * Like any widget it has an X,Y position and a width/height. * It has a Scroll position to control which slice of its drawing will be visible inside its bounding box. * It supports levels having negative coordinates for their pixels. It doesn't care. The default Scroll position is (0,0) at the top left corner of the widget but you can scroll into the negatives and see the negative pixels. * Keyboard keys will scroll the viewport inside the canvas. * The canvas draws only the pixels that are visible inside its bounding box. This feature will eventually pave the way toward: * Doodads being dropped on top of your map, each Doodad being its own Canvas widget. * Using drawings as button icons for the user interface, as the Canvas is a normal widget.
119 lines
2.7 KiB
Go
119 lines
2.7 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"git.kirsle.net/apps/doodle/render"
|
|
"git.kirsle.net/apps/doodle/ui/theme"
|
|
)
|
|
|
|
// CheckButton implements a checkbox and radiobox widget. It's based on a
|
|
// Button and holds a boolean or string pointer (boolean for checkbox,
|
|
// string for radio).
|
|
type CheckButton struct {
|
|
Button
|
|
BoolVar *bool
|
|
StringVar *string
|
|
Value string
|
|
}
|
|
|
|
// NewCheckButton creates a new CheckButton.
|
|
func NewCheckButton(name string, boolVar *bool, child Widget) *CheckButton {
|
|
w := &CheckButton{
|
|
BoolVar: boolVar,
|
|
}
|
|
w.Button.child = child
|
|
w.IDFunc(func() string {
|
|
return fmt.Sprintf("CheckButton<%s %+v>", name, w.BoolVar)
|
|
})
|
|
|
|
w.setup()
|
|
return w
|
|
}
|
|
|
|
// NewRadioButton creates a CheckButton bound to a string variable.
|
|
func NewRadioButton(name string, stringVar *string, value string, child Widget) *CheckButton {
|
|
w := &CheckButton{
|
|
StringVar: stringVar,
|
|
Value: value,
|
|
}
|
|
w.Button.child = child
|
|
w.IDFunc(func() string {
|
|
return fmt.Sprintf(`RadioButton<%s "%s" %s>`, name, w.Value, strconv.FormatBool(*w.StringVar == w.Value))
|
|
})
|
|
w.setup()
|
|
return w
|
|
}
|
|
|
|
// Compute to re-evaluate the button state (in the case of radio buttons where
|
|
// a different button will affect the state of this one when clicked).
|
|
func (w *CheckButton) Compute(e render.Engine) {
|
|
if w.StringVar != nil {
|
|
// Radio button, always re-assign the border style in case a sister
|
|
// radio button has changed the value.
|
|
if *w.StringVar == w.Value {
|
|
w.SetBorderStyle(BorderSunken)
|
|
} else {
|
|
w.SetBorderStyle(BorderRaised)
|
|
}
|
|
}
|
|
w.Button.Compute(e)
|
|
}
|
|
|
|
// setup the common things between checkboxes and radioboxes.
|
|
func (w *CheckButton) setup() {
|
|
var borderStyle BorderStyle = BorderRaised
|
|
if w.BoolVar != nil {
|
|
if *w.BoolVar == true {
|
|
borderStyle = BorderSunken
|
|
}
|
|
}
|
|
|
|
w.Configure(Config{
|
|
BorderSize: 2,
|
|
BorderStyle: borderStyle,
|
|
OutlineSize: 1,
|
|
OutlineColor: theme.ButtonOutlineColor,
|
|
Background: theme.ButtonBackgroundColor,
|
|
})
|
|
|
|
w.Handle(MouseOver, func(p render.Point) {
|
|
w.hovering = true
|
|
w.SetBackground(theme.ButtonHoverColor)
|
|
})
|
|
w.Handle(MouseOut, func(p render.Point) {
|
|
w.hovering = false
|
|
w.SetBackground(theme.ButtonBackgroundColor)
|
|
})
|
|
|
|
w.Handle(MouseDown, func(p render.Point) {
|
|
w.clicked = true
|
|
w.SetBorderStyle(BorderSunken)
|
|
})
|
|
w.Handle(MouseUp, func(p render.Point) {
|
|
w.clicked = false
|
|
})
|
|
|
|
w.Handle(Click, func(p render.Point) {
|
|
var sunken bool
|
|
if w.BoolVar != nil {
|
|
if *w.BoolVar {
|
|
*w.BoolVar = false
|
|
} else {
|
|
*w.BoolVar = true
|
|
sunken = true
|
|
}
|
|
} else if w.StringVar != nil {
|
|
*w.StringVar = w.Value
|
|
sunken = true
|
|
}
|
|
|
|
if sunken {
|
|
w.SetBorderStyle(BorderSunken)
|
|
} else {
|
|
w.SetBorderStyle(BorderRaised)
|
|
}
|
|
})
|
|
}
|