doodle/ui/label.go
Noah Petherbridge 20771fbe13 Draw Actors Embedded in Levels in Edit Mode
Add the JSON format for embedding Actors (Doodad instances) inside of a
Level. I made a test map that manually inserted a couple of actors.

Actors are given to the Canvas responsible for the Level via the
function `InstallActors()`. So it means you'll call LoadLevel and then
InstallActors to hook everything up.

The Canvas creates sub-Canvas widgets from each Actor.

After drawing the main level geometry from the Canvas.Chunker, it calls
the drawActors() function which does the same but for Actors.

Levels keep a global map of all Actors that exist. For any Actors that
are visible within the Viewport, their sub-Canvas widgets are presented
appropriately on top of the parent Canvas. In case their sub-Canvas
overlaps the parent's boundaries, their sub-Canvas is resized and moved
appropriately.

- Allow the MainWindow to be resized at run time, and the UI
  recalculates its sizing and position.
- Made the in-game Shell properties editable via environment variables.
  The kirsle.env file sets a blue and pink color scheme.
- Begin the ground work for Levels and Doodads to embed files inside
  their data via the level.FileSystem type.
- UI: Labels can now contain line break characters. It will
  appropriately render multiple lines of render.Text and take into
  account the proper BoxSize to contain them all.
- Add environment variable DOODLE_DEBUG_ALL=true that will turn on ALL
  debug overlay and visualization options.
- Add debug overlay to "tag" each Canvas widget with some of its
  details, like its Name and World Position. Can be enabled with the
  environment variable DEBUG_CANVAS_LABEL=true
- Improved the FPS debug overlay to show in labeled columns and multiple
  colors, with easy ability to add new data points to it.
2018-10-19 13:32:25 -07:00

126 lines
2.5 KiB
Go

package ui
import (
"fmt"
"strings"
"git.kirsle.net/apps/doodle/render"
)
// DefaultFont is the default font settings used for a Label.
var DefaultFont = render.Text{
Size: 12,
Color: render.Black,
}
// Label is a simple text label widget.
type Label struct {
BaseWidget
// Configurable fields for the constructor.
Text string
TextVariable *string
Font render.Text
width int32
height int32
lineHeight int
}
// NewLabel creates a new label.
func NewLabel(c Label) *Label {
w := &Label{
Text: c.Text,
TextVariable: c.TextVariable,
Font: DefaultFont,
}
if !c.Font.IsZero() {
w.Font = c.Font
}
w.IDFunc(func() string {
return fmt.Sprintf(`Label<"%s">`, w.text().Text)
})
return w
}
// text returns the label's displayed text, coming from the TextVariable if
// available or else the Text attribute instead.
func (w *Label) text() render.Text {
if w.TextVariable != nil {
w.Font.Text = *w.TextVariable
return w.Font
}
w.Font.Text = w.Text
return w.Font
}
// Value returns the current text value displayed in the widget, whether it was
// the hardcoded value or a TextVariable.
func (w *Label) Value() string {
return w.text().Text
}
// Compute the size of the label widget.
func (w *Label) Compute(e render.Engine) {
text := w.text()
lines := strings.Split(text.Text, "\n")
// Max rect to encompass all lines of text.
var maxRect = render.Rect{}
for _, line := range lines {
text.Text = line // only this line at this time.
rect, err := e.ComputeTextRect(text)
if err != nil {
log.Error("%s: failed to compute text rect: %s", w, err)
return
}
if rect.W > maxRect.W {
maxRect.W = rect.W
}
maxRect.H += rect.H
w.lineHeight = int(rect.H)
}
var (
padX = w.Font.Padding + w.Font.PadX
padY = w.Font.Padding + w.Font.PadY
)
if !w.FixedSize() {
w.resizeAuto(render.Rect{
W: maxRect.W + (padX * 2),
H: maxRect.H + (padY * 2),
})
}
w.MoveTo(render.Point{
X: maxRect.X + w.BoxThickness(1),
Y: maxRect.Y + w.BoxThickness(1),
})
}
// Present the label widget.
func (w *Label) Present(e render.Engine, P render.Point) {
if w.Hidden() {
return
}
border := w.BoxThickness(1)
var (
text = w.text()
padX = w.Font.Padding + w.Font.PadX
padY = w.Font.Padding + w.Font.PadY
)
w.DrawBox(e, P)
for i, line := range strings.Split(text.Text, "\n") {
text.Text = line
e.DrawText(text, render.Point{
X: P.X + border + padX,
Y: P.Y + border + padY + int32(i*w.lineHeight),
})
}
}