ui/text: use BlockOp as materials

Before this change, clients were expected to set up the current
material (color or image) before laying out Labels and Editors.
This was done to avoid garbage from a hypothetical material
interface covering both colors and images.

However, some widgets need more than one material: the Editor had
HintImage for the hint text material.

This change implements generalized materials through blocks:
anywhere a material is expected, a ui.BlockOp is is assumed to
contain the operation(s) needed for setting the desired material.

This way we avoid allocations (interfaces) and keep the
abstraction over material types.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-07-05 16:52:13 +02:00
parent 30a558d10d
commit 86bc3e612d
3 changed files with 13 additions and 5 deletions
+3
View File
@@ -213,6 +213,9 @@ func (b *BlockOp) decode(data []byte, refs []interface{}) {
} }
func (b BlockOp) Add(o *Ops) { func (b BlockOp) Add(o *Ops) {
if b.ops == nil {
return
}
data := make([]byte, ops.TypeBlockLen) data := make([]byte, ops.TypeBlockLen)
data[0] = byte(ops.TypeBlock) data[0] = byte(ops.TypeBlock)
bo := binary.LittleEndian bo := binary.LittleEndian
+8 -5
View File
@@ -27,8 +27,9 @@ type Editor struct {
SingleLine bool SingleLine bool
Submit bool Submit bool
Hint string Material ui.BlockOp
HintImage image.Image Hint string
HintMaterial ui.BlockOp
oldCfg ui.Config oldCfg ui.Config
blinkStart time.Time blinkStart time.Time
@@ -202,8 +203,10 @@ func (e *Editor) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
Offset: off, Offset: off,
} }
ui.PushOp{}.Add(ops) ui.PushOp{}.Add(ops)
if e.HintImage != nil && e.rr.len() == 0 { if e.rr.len() > 0 {
draw.ImageOp{Img: e.HintImage, Rect: e.HintImage.Bounds()}.Add(ops) e.Material.Add(ops)
} else {
e.HintMaterial.Add(ops)
} }
for { for {
str, lineOff, ok := e.it.Next() str, lineOff, ok := e.it.Next()
@@ -216,7 +219,6 @@ func (e *Editor) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
draw.DrawOp{Rect: toRectF(clip).Sub(lineOff)}.Add(ops) draw.DrawOp{Rect: toRectF(clip).Sub(lineOff)}.Add(ops)
ui.PopOp{}.Add(ops) ui.PopOp{}.Add(ops)
} }
ui.PopOp{}.Add(ops)
if e.focused { if e.focused {
now := e.Config.Now now := e.Config.Now
dt := now.Sub(e.blinkStart) dt := now.Sub(e.blinkStart)
@@ -246,6 +248,7 @@ func (e *Editor) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
redraw.Add(ops) redraw.Add(ops)
} }
} }
ui.PopOp{}.Add(ops)
baseline := e.padTop + e.dims.Baseline baseline := e.padTop + e.dims.Baseline
pointer.AreaRect(e.viewSize).Add(ops) pointer.AreaRect(e.viewSize).Add(ops)
+2
View File
@@ -17,6 +17,7 @@ import (
type Label struct { type Label struct {
Face Face Face Face
Material ui.BlockOp
Alignment Alignment Alignment Alignment
Text string Text string
MaxLines int MaxLines int
@@ -108,6 +109,7 @@ func (l Label) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
ui.PushOp{}.Add(ops) ui.PushOp{}.Add(ops)
ui.TransformOp{Transform: ui.Offset(off)}.Add(ops) ui.TransformOp{Transform: ui.Offset(off)}.Add(ops)
l.Face.Path(str).Add(ops) l.Face.Path(str).Add(ops)
l.Material.Add(ops)
draw.DrawOp{Rect: lclip}.Add(ops) draw.DrawOp{Rect: lclip}.Add(ops)
ui.PopOp{}.Add(ops) ui.PopOp{}.Add(ops)
} }