Elements are no longer images

This commit is contained in:
Sasha Koshka 2023-02-13 01:49:33 -05:00
parent 7f0462d588
commit 8ac5108211
18 changed files with 117 additions and 112 deletions

View File

@ -254,7 +254,7 @@ func (window *Window) reallocateCanvas () {
}
func (window *Window) redrawChildEntirely () {
window.pushRegion(window.paste(window.child))
window.pushRegion(window.paste(window.canvas))
}

View File

@ -143,7 +143,7 @@ func (element *Button) draw () {
pattern := element.theme.Pattern(theme.PatternButton, state)
artist.FillRectangle(element, pattern, bounds)
artist.FillRectangle(element.core, pattern, bounds)
textBounds := element.drawer.LayoutBounds()
offset := image.Point {
@ -161,5 +161,5 @@ func (element *Button) draw () {
}
foreground := element.theme.Pattern(theme.PatternForeground, state)
element.drawer.Draw(element, foreground, offset)
element.drawer.Draw(element.core, foreground, offset)
}

View File

@ -171,10 +171,10 @@ func (element *Checkbox) draw () {
backgroundPattern := element.theme.Pattern (
theme.PatternBackground, state)
artist.FillRectangle(element, backgroundPattern, bounds)
artist.FillRectangle(element.core, backgroundPattern, bounds)
pattern := element.theme.Pattern(theme.PatternButton, state)
artist.FillRectangle(element, pattern, boxBounds)
artist.FillRectangle(element.core, pattern, boxBounds)
textBounds := element.drawer.LayoutBounds()
offset := bounds.Min.Add(image.Point {
@ -185,5 +185,5 @@ func (element *Checkbox) draw () {
offset.X -= textBounds.Min.X
foreground := element.theme.Pattern(theme.PatternForeground, state)
element.drawer.Draw(element, foreground, offset)
element.drawer.Draw(element.core, foreground, offset)
}

View File

@ -230,12 +230,12 @@ func (element *Container) redoAll () {
theme.PatternBackground,
theme.PatternState { })
for _, tile := range tiles {
artist.FillRectangle(element, pattern, tile)
artist.FillRectangle(element.core, pattern, tile)
}
// cut our canvas up and give peices to child elements
for _, entry := range element.children {
entry.DrawTo(canvas.Cut(element, entry.Bounds))
entry.DrawTo(canvas.Cut(element.core, entry.Bounds))
}
}

View File

@ -19,5 +19,5 @@ func NewImage (image image.Image) (element *Image) {
}
func (element *Image) draw () {
artist.FillRectangle(element, element.buffer, element.Bounds())
artist.FillRectangle(element.core, element.buffer, element.Bounds())
}

View File

@ -154,12 +154,12 @@ func (element *Label) draw () {
pattern := element.theme.Pattern (
theme.PatternBackground,
theme.PatternState { })
artist.FillRectangle(element, pattern, bounds)
artist.FillRectangle(element.core, pattern, bounds)
textBounds := element.drawer.LayoutBounds()
foreground := element.theme.Pattern (
theme.PatternForeground,
theme.PatternState { })
element.drawer.Draw(element, foreground, bounds.Min.Sub(textBounds.Min))
element.drawer.Draw(element.core, foreground, bounds.Min.Sub(textBounds.Min))
}

View File

@ -439,14 +439,14 @@ func (element *List) draw () {
Disabled: !element.Enabled(),
Focused: element.Focused(),
})
artist.FillRectangle(element, pattern, bounds)
artist.FillRectangle(element.core, pattern, bounds)
bounds = inset.Apply(bounds)
dot := image.Point {
bounds.Min.X,
bounds.Min.Y - element.scroll,
}
innerCanvas := canvas.Cut(element, bounds)
innerCanvas := canvas.Cut(element.core, bounds)
for index, entry := range element.entries {
entryPosition := dot
dot.Y += entry.Bounds().Dy()

View File

@ -71,7 +71,7 @@ func (element *ProgressBar) draw () {
theme.PatternSunken,
theme.PatternState { })
inset := element.theme.Inset(theme.PatternSunken)
artist.FillRectangle(element, pattern, bounds)
artist.FillRectangle(element.core, pattern, bounds)
bounds = inset.Apply(bounds)
meterBounds := image.Rect (
bounds.Min.X, bounds.Min.Y,
@ -80,5 +80,5 @@ func (element *ProgressBar) draw () {
accent := element.theme.Pattern (
theme.PatternAccent,
theme.PatternState { })
artist.FillRectangle(element, accent, meterBounds)
artist.FillRectangle(element.core, accent, meterBounds)
}

View File

@ -302,7 +302,7 @@ func (element *ScrollContainer) OnFocusMotionRequest (
}
func (element *ScrollContainer) childDamageCallback (region canvas.Canvas) {
element.core.DamageRegion(artist.Paste(element, region, image.Point { }))
element.core.DamageRegion(artist.Paste(element.core, region, image.Point { }))
}
func (element *ScrollContainer) childFocusRequestCallback () (granted bool) {
@ -345,7 +345,7 @@ func (element *ScrollContainer) resizeChildToFit () {
0, 0,
element.childWidth,
element.childHeight).Add(element.Bounds().Min)
element.child.DrawTo(canvas.Cut(element, childBounds))
element.child.DrawTo(canvas.Cut(element.core, childBounds))
}
func (element *ScrollContainer) recalculate () {
@ -437,11 +437,10 @@ func (element *ScrollContainer) recalculate () {
}
func (element *ScrollContainer) draw () {
artist.Paste(element, element.child, image.Point { })
deadPattern := element.theme.Pattern (
theme.PatternDead, theme.PatternState { })
artist.FillRectangle (
element, deadPattern,
element.core, deadPattern,
image.Rect (
element.vertical.gutter.Min.X,
element.horizontal.gutter.Min.Y,
@ -457,10 +456,10 @@ func (element *ScrollContainer) drawHorizontalBar () {
Pressed: element.horizontal.dragging,
}
gutterPattern := element.horizontal.theme.Pattern(theme.PatternGutter, state)
artist.FillRectangle(element, gutterPattern, element.horizontal.gutter)
artist.FillRectangle(element.core, gutterPattern, element.horizontal.gutter)
handlePattern := element.horizontal.theme.Pattern(theme.PatternHandle, state)
artist.FillRectangle(element, handlePattern, element.horizontal.bar)
artist.FillRectangle(element.core, handlePattern, element.horizontal.bar)
}
func (element *ScrollContainer) drawVerticalBar () {
@ -469,10 +468,10 @@ func (element *ScrollContainer) drawVerticalBar () {
Pressed: element.vertical.dragging,
}
gutterPattern := element.vertical.theme.Pattern(theme.PatternGutter, state)
artist.FillRectangle(element, gutterPattern, element.vertical.gutter)
artist.FillRectangle(element.core, gutterPattern, element.vertical.gutter)
handlePattern := element.vertical.theme.Pattern(theme.PatternHandle, state)
artist.FillRectangle(element, handlePattern, element.vertical.bar)
artist.FillRectangle(element.core, handlePattern, element.vertical.bar)
}
func (element *ScrollContainer) dragHorizontalBar (mousePosition image.Point) {

View File

@ -196,11 +196,11 @@ func (element *Slider) draw () {
Pressed: element.dragging,
}
artist.FillRectangle (
element,
element.core,
element.theme.Pattern(theme.PatternGutter, state),
bounds)
artist.FillRectangle (
element,
element.core,
element.theme.Pattern(theme.PatternHandle, state),
element.bar)
}

View File

@ -64,11 +64,11 @@ func (element *Spacer) draw () {
pattern := element.theme.Pattern (
theme.PatternForeground,
theme.PatternState { })
artist.FillRectangle(element, pattern, bounds)
artist.FillRectangle(element.core, pattern, bounds)
} else {
pattern := element.theme.Pattern (
theme.PatternBackground,
theme.PatternState { })
artist.FillRectangle(element, pattern, bounds)
artist.FillRectangle(element.core, pattern, bounds)
}
}

View File

@ -166,7 +166,7 @@ func (element *Switch) draw () {
}
backgroundPattern := element.theme.Pattern (
theme.PatternBackground, state)
artist.FillRectangle (element, backgroundPattern, bounds)
artist.FillRectangle (element.core, backgroundPattern, bounds)
if element.checked {
handleBounds.Min.X += bounds.Dy()
@ -184,11 +184,11 @@ func (element *Switch) draw () {
gutterPattern := element.theme.Pattern (
theme.PatternGutter, state)
artist.FillRectangle(element, gutterPattern, gutterBounds)
artist.FillRectangle(element.core, gutterPattern, gutterBounds)
handlePattern := element.theme.Pattern (
theme.PatternHandle, state)
artist.FillRectangle(element, handlePattern, handleBounds)
artist.FillRectangle(element.core, handlePattern, handleBounds)
textBounds := element.drawer.LayoutBounds()
offset := bounds.Min.Add(image.Point {
@ -200,5 +200,5 @@ func (element *Switch) draw () {
foreground := element.theme.Pattern (
theme.PatternForeground, state)
element.drawer.Draw(element, foreground, offset)
element.drawer.Draw(element.core, foreground, offset)
}

View File

@ -296,7 +296,7 @@ func (element *TextBox) draw () {
Focused: element.Focused(),
}
pattern := element.theme.Pattern(theme.PatternSunken, state)
artist.FillRectangle(element, pattern, bounds)
artist.FillRectangle(element.core, pattern, bounds)
if len(element.text) == 0 && !element.Focused() {
// draw placeholder
@ -309,7 +309,7 @@ func (element *TextBox) draw () {
theme.PatternForeground,
theme.PatternState { Disabled: true })
element.placeholderDrawer.Draw (
element,
element.core,
foreground,
offset.Sub(textBounds.Min))
} else {
@ -322,7 +322,7 @@ func (element *TextBox) draw () {
foreground := element.theme.Pattern (
theme.PatternForeground, state)
element.valueDrawer.Draw (
element,
element.core,
foreground,
offset.Sub(textBounds.Min))
@ -331,7 +331,7 @@ func (element *TextBox) draw () {
cursorPosition := element.valueDrawer.PositionOf (
element.cursor)
artist.Line (
element,
element.core,
foreground, 1,
cursorPosition.Add(offset),
image.Pt (

View File

@ -33,35 +33,13 @@ func NewCore (
return
}
// ColorModel fulfills the draw.Image interface.
func (core *Core) ColorModel () (model color.Model) {
return color.RGBAModel
}
// ColorModel fulfills the draw.Image interface.
func (core *Core) At (x, y int) (pixel color.Color) {
if core.canvas == nil { return }
return core.canvas.At(x, y)
}
// ColorModel fulfills the draw.Image interface.
// Bounds fulfills the tomo.Element interface. This should not need to be
// overridden.
func (core *Core) Bounds () (bounds image.Rectangle) {
if core.canvas == nil { return }
return core.canvas.Bounds()
}
// ColorModel fulfills the draw.Image interface.
func (core *Core) Set (x, y int, c color.Color) () {
if core.canvas == nil { return }
core.canvas.Set(x, y, c)
}
// Buffer fulfills the canvas.Canvas interface.
func (core *Core) Buffer () (data []color.RGBA, stride int) {
if core.canvas == nil { return }
return core.canvas.Buffer()
}
// MinimumSize fulfils the tomo.Element interface. This should not need to be
// overridden.
func (core *Core) MinimumSize () (width, height int) {
@ -97,6 +75,35 @@ type CoreControl struct {
core *Core
}
// ColorModel fulfills the draw.Image interface.
func (control CoreControl) ColorModel () (model color.Model) {
return color.RGBAModel
}
// At fulfills the draw.Image interface.
func (control CoreControl) At (x, y int) (pixel color.Color) {
if control.core.canvas == nil { return }
return control.core.canvas.At(x, y)
}
// Bounds fulfills the draw.Image interface.
func (control CoreControl) Bounds () (bounds image.Rectangle) {
if control.core.canvas == nil { return }
return control.core.canvas.Bounds()
}
// Set fulfills the draw.Image interface.
func (control CoreControl) Set (x, y int, c color.Color) () {
if control.core.canvas == nil { return }
control.core.canvas.Set(x, y, c)
}
// Buffer fulfills the canvas.Canvas interface.
func (control CoreControl) Buffer () (data []color.RGBA, stride int) {
if control.core.canvas == nil { return }
return control.core.canvas.Buffer()
}
// HasImage returns true if the core has an allocated image buffer, and false if
// it doesn't.
func (control CoreControl) HasImage () (has bool) {
@ -107,7 +114,7 @@ func (control CoreControl) HasImage () (has bool) {
// does not need to be called when responding to a resize event.
func (control CoreControl) DamageRegion (bounds image.Rectangle) {
if control.core.onDamage != nil {
control.core.onDamage(canvas.Cut(control.core, bounds))
control.core.onDamage(canvas.Cut(control.core.canvas, bounds))
}
}

View File

@ -8,16 +8,9 @@ import "git.tebibyte.media/sashakoshka/tomo/config"
// Element represents a basic on-screen object.
type Element interface {
// Element must implement the Canvas interface. Elements should start
// out with a completely blank buffer, and only allocate memory and draw
// on it for the first time when sent an EventResize event.
canvas.Canvas
// MinimumSize specifies the minimum amount of pixels this element's
// width and height may be set to. If the element is given a resize
// event with dimensions smaller than this, it will use its minimum
// instead of the offending dimension(s).
MinimumSize () (width, height int)
// Bounds reports the element's bounding box. This must reflect the
// bounding box of the last canvas given to the element by DrawTo.
Bounds () (bounds image.Rectangle)
// DrawTo sets this element's canvas. This should only be called by the
// parent element. This is typically a region of the parent element's
@ -28,6 +21,12 @@ type Element interface {
// drawn on and should be pushed to the screen.
OnDamage (callback func (region canvas.Canvas))
// MinimumSize specifies the minimum amount of pixels this element's
// width and height may be set to. If the element is given a resize
// event with dimensions smaller than this, it will use its minimum
// instead of the offending dimension(s).
MinimumSize () (width, height int)
// OnMinimumSizeChange sets a function to be called when the element's
// minimum size is changed.
OnMinimumSizeChange (callback func ())

View File

@ -280,7 +280,7 @@ func (element *Piano) draw () {
}
pattern := element.theme.Pattern(theme.PatternPinboard, state)
// inset := element.theme.Inset(theme.PatternSunken)
artist.FillRectangle(element, pattern, element.Bounds())
artist.FillRectangle(element.core, pattern, element.Bounds())
for _, key := range element.flatKeys {
_, keynavPressed := element.keynavPressed[key.Note]
@ -308,7 +308,7 @@ func (element *Piano) drawFlat (
state.Pressed = pressed
pattern := element.theme.Theme.Pattern (
theme.PatternButton, state, theme.C("fun", "flatKey"))
artist.FillRectangle(element, pattern, bounds)
artist.FillRectangle(element.core, pattern, bounds)
}
func (element *Piano) drawSharp (
@ -319,5 +319,5 @@ func (element *Piano) drawSharp (
state.Pressed = pressed
pattern := element.theme.Theme.Pattern (
theme.PatternButton, state, theme.C("fun", "sharpKey"))
artist.FillRectangle(element, pattern, bounds)
artist.FillRectangle(element.core, pattern, bounds)
}

View File

@ -27,7 +27,7 @@ func NewArtist () (element *Artist) {
func (element *Artist) draw () {
bounds := element.Bounds()
artist.FillRectangle(element, artist.NewUniform(hex(0)), bounds)
artist.FillRectangle(element.core, artist.NewUniform(hex(0)), bounds)
element.cellBounds.Max.X = bounds.Min.X + bounds.Dx() / 5
element.cellBounds.Max.Y = bounds.Min.Y + (bounds.Dy() - 48) / 8
@ -36,7 +36,7 @@ func (element *Artist) draw () {
// 0, 0
artist.FillRectangle (
element,
element.core,
artist.Beveled {
artist.NewUniform(hex(0xFF0000FF)),
artist.NewUniform(hex(0x0000FFFF)),
@ -45,13 +45,13 @@ func (element *Artist) draw () {
// 1, 0
artist.StrokeRectangle (
element,
element.core,
artist.NewUniform(hex(0x00FF00FF)), 3,
element.cellAt(1, 0))
// 2, 0
artist.FillRectangle (
element,
element.core,
artist.NewMultiBordered (
artist.Stroke { Pattern: uhex(0xFF0000FF), Weight: 1 },
artist.Stroke { Pattern: uhex(0x888800FF), Weight: 2 },
@ -63,7 +63,7 @@ func (element *Artist) draw () {
// 3, 0
artist.FillRectangle (
element,
element.core,
artist.Bordered {
Stroke: artist.Stroke { Pattern: uhex(0x0000FFFF), Weight: 5 },
Fill: uhex(0xFF0000FF),
@ -72,7 +72,7 @@ func (element *Artist) draw () {
// 4, 0
artist.FillRectangle (
element,
element.core,
artist.Padded {
Stroke: uhex(0xFFFFFFFF),
Fill: uhex(0x666666FF),
@ -83,7 +83,7 @@ func (element *Artist) draw () {
// 0, 1 - 3, 1
for x := 0; x < 4; x ++ {
artist.FillRectangle (
element,
element.core,
artist.Striped {
First: artist.Stroke { Pattern: uhex(0xFF8800FF), Weight: 7 },
Second: artist.Stroke { Pattern: uhex(0x0088FFFF), Weight: 2 },
@ -100,17 +100,17 @@ func (element *Artist) draw () {
// 0, 3
artist.StrokeRectangle (
element,uhex(0x888888FF), 1,
element.core, uhex(0x888888FF), 1,
element.cellAt(0, 3))
artist.FillEllipse(element, uhex(0x00FF00FF), element.cellAt(0, 3))
artist.FillEllipse(element.core, uhex(0x00FF00FF), element.cellAt(0, 3))
// 1, 3 - 3, 3
for x := 1; x < 4; x ++ {
artist.StrokeRectangle (
element,uhex(0x888888FF), 1,
element.core,uhex(0x888888FF), 1,
element.cellAt(x, 3))
artist.StrokeEllipse (
element,
element.core,
[]artist.Pattern {
uhex(0xFF0000FF),
uhex(0x00FF00FF),
@ -131,7 +131,7 @@ func (element *Artist) draw () {
tiles := shatter.Shatter(element.cellAt(4, 3), rocks...)
for index, tile := range tiles {
artist.FillRectangle (
element, []artist.Pattern {
element.core, []artist.Pattern {
uhex(0xFF0000FF),
uhex(0x00FF00FF),
uhex(0x0000FFFF),
@ -146,7 +146,7 @@ func (element *Artist) draw () {
// 0, 4 - 3, 4
for x := 0; x < 4; x ++ {
artist.FillEllipse (
element,
element.core,
artist.Split {
First: uhex(0xFF0000FF),
Second: uhex(0x0000FFFF),
@ -163,11 +163,11 @@ func (element *Artist) draw () {
"%dms\n%dus",
drawTime.Milliseconds(),
drawTime.Microseconds())))
textDrawer.Draw(element, uhex(0xFFFFFFFF), image.Pt(8, bounds.Max.Y - 24))
textDrawer.Draw(element.core, uhex(0xFFFFFFFF), image.Pt(8, bounds.Max.Y - 24))
// 0, 5
artist.FillRectangle (
element,
element.core,
artist.QuadBeveled {
uhex(0x880000FF),
uhex(0x00FF00FF),
@ -178,7 +178,7 @@ func (element *Artist) draw () {
// 1, 5
artist.FillRectangle (
element,
element.core,
artist.Checkered {
First: artist.QuadBeveled {
uhex(0x880000FF),
@ -198,7 +198,7 @@ func (element *Artist) draw () {
// 2, 5
artist.FillRectangle (
element,
element.core,
artist.Dotted {
Foreground: uhex(0x00FF00FF),
Background: artist.Checkered {
@ -214,7 +214,7 @@ func (element *Artist) draw () {
// 3, 5
artist.FillRectangle (
element,
element.core,
artist.Tiled {
Pattern: artist.QuadBeveled {
uhex(0x880000FF),
@ -230,7 +230,7 @@ func (element *Artist) draw () {
// 0, 6 - 3, 6
for x := 0; x < 4; x ++ {
artist.FillRectangle (
element,
element.core,
artist.Gradient {
First: uhex(0xFF0000FF),
Second: uhex(0x0000FFFF),
@ -241,7 +241,7 @@ func (element *Artist) draw () {
// 0, 7
artist.FillEllipse (
element,
element.core,
artist.EllipticallyBordered {
Fill: artist.Gradient {
First: uhex(0x00FF00FF),
@ -254,7 +254,7 @@ func (element *Artist) draw () {
// 1, 7
artist.FillRectangle (
element,
element.core,
artist.Noisy {
Low: uhex(0x000000FF),
High: uhex(0xFFFFFFFF),
@ -265,7 +265,7 @@ func (element *Artist) draw () {
// 2, 7
artist.FillRectangle (
element,
element.core,
artist.Noisy {
Low: uhex(0x000000FF),
High: artist.Gradient {
@ -280,7 +280,7 @@ func (element *Artist) draw () {
// 3, 7
artist.FillRectangle (
element,
element.core,
artist.Noisy {
Low: uhex(0x000000FF),
High: uhex(0xFFFFFFFF),
@ -294,33 +294,33 @@ func (element *Artist) draw () {
func (element *Artist) lines (weight int, bounds image.Rectangle) {
bounds = bounds.Inset(4)
c := uhex(0xFFFFFFFF)
artist.Line(element, c, weight, bounds.Min, bounds.Max)
artist.Line(element.core, c, weight, bounds.Min, bounds.Max)
artist.Line (
element, c, weight,
element.core, c, weight,
image.Pt(bounds.Max.X, bounds.Min.Y),
image.Pt(bounds.Min.X, bounds.Max.Y))
artist.Line (
element, c, weight,
element.core, c, weight,
image.Pt(bounds.Max.X, bounds.Min.Y + 16),
image.Pt(bounds.Min.X, bounds.Max.Y - 16))
artist.Line (
element, c, weight,
element.core, c, weight,
image.Pt(bounds.Min.X, bounds.Min.Y + 16),
image.Pt(bounds.Max.X, bounds.Max.Y - 16))
artist.Line (
element, c, weight,
element.core, c, weight,
image.Pt(bounds.Min.X + 20, bounds.Min.Y),
image.Pt(bounds.Max.X - 20, bounds.Max.Y))
artist.Line (
element, c, weight,
element.core, c, weight,
image.Pt(bounds.Max.X - 20, bounds.Min.Y),
image.Pt(bounds.Min.X + 20, bounds.Max.Y))
artist.Line (
element, c, weight,
element.core, c, weight,
image.Pt(bounds.Min.X, bounds.Min.Y + bounds.Dy() / 2),
image.Pt(bounds.Max.X, bounds.Min.Y + bounds.Dy() / 2))
artist.Line (
element, c, weight,
element.core, c, weight,
image.Pt(bounds.Min.X + bounds.Dx() / 2, bounds.Min.Y),
image.Pt(bounds.Min.X + bounds.Dx() / 2, bounds.Max.Y))
}

View File

@ -53,19 +53,19 @@ func (element *Mouse) draw () {
bounds := element.Bounds()
pattern := element.theme.Pattern (
theme.PatternAccent,
element.c,
theme.PatternState { })
artist.FillRectangle(element, pattern, bounds)
theme.PatternState { },
element.c)
artist.FillRectangle(element.core, pattern, bounds)
artist.StrokeRectangle (
element,
element.core,
artist.NewUniform(color.Black), 1,
bounds)
artist.Line (
element, artist.NewUniform(color.White), 1,
element.core, artist.NewUniform(color.White), 1,
bounds.Min.Add(image.Pt(1, 1)),
bounds.Min.Add(image.Pt(bounds.Dx() - 2, bounds.Dy() - 2)))
artist.Line (
element, artist.NewUniform(color.White), 1,
element.core, artist.NewUniform(color.White), 1,
bounds.Min.Add(image.Pt(1, bounds.Dy() - 2)),
bounds.Min.Add(image.Pt(bounds.Dx() - 2, 1)))
}
@ -79,7 +79,7 @@ func (element *Mouse) HandleMouseUp (x, y int, button input.Button) {
element.drawing = false
mousePos := image.Pt(x, y)
element.core.DamageRegion (artist.Line (
element, element.color, 1,
element.core, element.color, 1,
element.lastMousePos, mousePos))
element.lastMousePos = mousePos
}
@ -88,7 +88,7 @@ func (element *Mouse) HandleMouseMove (x, y int) {
if !element.drawing { return }
mousePos := image.Pt(x, y)
element.core.DamageRegion (artist.Line (
element, element.color, 1,
element.core, element.color, 1,
element.lastMousePos, mousePos))
element.lastMousePos = mousePos
}