mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 00:45:35 +00:00
text: remove themable properties from Editor and Label
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+44
-59
@@ -4,11 +4,11 @@ package text
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"math"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/gesture"
|
||||
"gioui.org/io/event"
|
||||
"gioui.org/io/key"
|
||||
@@ -23,15 +23,6 @@ import (
|
||||
|
||||
// Editor implements an editable and scrollable text area.
|
||||
type Editor struct {
|
||||
Font Font
|
||||
// Material for drawing the text.
|
||||
Material op.MacroOp
|
||||
// Hint contains the text displayed to the user when the
|
||||
// Editor is empty.
|
||||
Hint string
|
||||
// Material is used to draw the hint.
|
||||
HintMaterial op.MacroOp
|
||||
|
||||
Alignment Alignment
|
||||
// SingleLine force the text to stay on a single line.
|
||||
// SingleLine also sets the scrolling direction to
|
||||
@@ -50,6 +41,7 @@ type Editor struct {
|
||||
viewSize image.Point
|
||||
valid bool
|
||||
lines []Line
|
||||
shapes []line
|
||||
dims layout.Dimensions
|
||||
carWidth fixed.Int26_6
|
||||
requestFocus bool
|
||||
@@ -80,6 +72,11 @@ type ChangeEvent struct{}
|
||||
// and a carriage return key is pressed.
|
||||
type SubmitEvent struct{}
|
||||
|
||||
type line struct {
|
||||
offset f32.Point
|
||||
clip paint.ClipOp
|
||||
}
|
||||
|
||||
const (
|
||||
blinksPerSecond = 1
|
||||
maxBlinkDuration = 10 * time.Second
|
||||
@@ -168,31 +165,17 @@ func (e *Editor) Focus() {
|
||||
}
|
||||
|
||||
// Layout flushes any remaining events and lays out the editor.
|
||||
func (e *Editor) Layout(gtx *layout.Context, s *Shaper) {
|
||||
e.layout(gtx, s, e.Font)
|
||||
var stack op.StackOp
|
||||
stack.Push(gtx.Ops)
|
||||
if e.Len() > 0 {
|
||||
paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(gtx.Ops)
|
||||
e.Material.Add(gtx.Ops)
|
||||
} else {
|
||||
paint.ColorOp{Color: color.RGBA{A: 0xaa}}.Add(gtx.Ops)
|
||||
e.HintMaterial.Add(gtx.Ops)
|
||||
}
|
||||
e.draw(gtx, s, e.Font)
|
||||
paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(gtx.Ops)
|
||||
e.Material.Add(gtx.Ops)
|
||||
e.drawCaret(gtx)
|
||||
stack.Pop()
|
||||
}
|
||||
|
||||
func (e *Editor) layout(gtx *layout.Context, s *Shaper, font Font) {
|
||||
for _, ok := e.Event(gtx); ok; _, ok = e.Event(gtx) {
|
||||
}
|
||||
func (e *Editor) Layout(gtx *layout.Context, sh *Shaper, font Font) {
|
||||
if e.font != font {
|
||||
e.invalidate()
|
||||
e.font = font
|
||||
}
|
||||
e.layout(gtx, sh)
|
||||
}
|
||||
|
||||
func (e *Editor) layout(gtx *layout.Context, sh *Shaper) {
|
||||
for _, ok := e.Event(gtx); ok; _, ok = e.Event(gtx) {
|
||||
}
|
||||
// Crude configuration change detection.
|
||||
if scale := gtx.Px(unit.Sp(100)); scale != e.scale {
|
||||
e.invalidate()
|
||||
@@ -211,7 +194,7 @@ func (e *Editor) layout(gtx *layout.Context, s *Shaper, font Font) {
|
||||
}
|
||||
|
||||
if !e.valid {
|
||||
e.layoutText(gtx, s, font)
|
||||
e.layoutText(gtx, sh, e.font)
|
||||
e.valid = true
|
||||
}
|
||||
|
||||
@@ -223,6 +206,29 @@ func (e *Editor) layout(gtx *layout.Context, s *Shaper, font Font) {
|
||||
e.scrollToCaret()
|
||||
}
|
||||
|
||||
off := image.Point{
|
||||
X: -e.scrollOff.X,
|
||||
Y: -e.scrollOff.Y,
|
||||
}
|
||||
clip := textPadding(e.lines)
|
||||
clip.Max = clip.Max.Add(e.viewSize)
|
||||
it := lineIterator{
|
||||
Lines: e.lines,
|
||||
Clip: clip,
|
||||
Alignment: e.Alignment,
|
||||
Width: e.viewSize.X,
|
||||
Offset: off,
|
||||
}
|
||||
e.shapes = e.shapes[:0]
|
||||
for {
|
||||
str, off, ok := it.Next()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
path := sh.Shape(gtx, e.font, str)
|
||||
e.shapes = append(e.shapes, line{off, path})
|
||||
}
|
||||
|
||||
key.InputOp{Key: e, Focus: e.requestFocus}.Add(gtx.Ops)
|
||||
e.requestFocus = false
|
||||
pointerPadding := gtx.Px(unit.Dp(4))
|
||||
@@ -251,38 +257,20 @@ func (e *Editor) layout(gtx *layout.Context, s *Shaper, font Font) {
|
||||
gtx.Dimensions = layout.Dimensions{Size: e.viewSize, Baseline: e.dims.Baseline}
|
||||
}
|
||||
|
||||
func (e *Editor) draw(gtx *layout.Context, s *Shaper, font Font) {
|
||||
var stack op.StackOp
|
||||
stack.Push(gtx.Ops)
|
||||
off := image.Point{
|
||||
X: -e.scrollOff.X,
|
||||
Y: -e.scrollOff.Y,
|
||||
}
|
||||
func (e *Editor) PaintText(gtx *layout.Context) {
|
||||
clip := textPadding(e.lines)
|
||||
clip.Max = clip.Max.Add(e.viewSize)
|
||||
it := lineIterator{
|
||||
Lines: e.lines,
|
||||
Clip: clip,
|
||||
Alignment: e.Alignment,
|
||||
Width: e.viewSize.X,
|
||||
Offset: off,
|
||||
}
|
||||
for {
|
||||
str, lineOff, ok := it.Next()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
for _, shape := range e.shapes {
|
||||
var stack op.StackOp
|
||||
stack.Push(gtx.Ops)
|
||||
op.TransformOp{}.Offset(lineOff).Add(gtx.Ops)
|
||||
s.Shape(gtx, font, str).Add(gtx.Ops)
|
||||
paint.PaintOp{Rect: toRectF(clip).Sub(lineOff)}.Add(gtx.Ops)
|
||||
op.TransformOp{}.Offset(shape.offset).Add(gtx.Ops)
|
||||
shape.clip.Add(gtx.Ops)
|
||||
paint.PaintOp{Rect: toRectF(clip).Sub(shape.offset)}.Add(gtx.Ops)
|
||||
stack.Pop()
|
||||
}
|
||||
stack.Pop()
|
||||
}
|
||||
|
||||
func (e *Editor) drawCaret(gtx *layout.Context) {
|
||||
func (e *Editor) PaintCaret(gtx *layout.Context) {
|
||||
if !e.caretOn {
|
||||
return
|
||||
}
|
||||
@@ -387,9 +375,6 @@ func (e *Editor) moveCoord(c unit.Converter, pos image.Point) {
|
||||
|
||||
func (e *Editor) layoutText(c unit.Converter, s *Shaper, font Font) {
|
||||
txt := e.rr.String()
|
||||
if txt == "" {
|
||||
txt = e.Hint
|
||||
}
|
||||
opts := LayoutOptions{SingleLine: e.SingleLine, MaxWidth: e.maxWidth}
|
||||
textLayout := s.Layout(c, font, txt, opts)
|
||||
lines := textLayout.Lines
|
||||
|
||||
+3
-14
@@ -5,7 +5,6 @@ package text
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"unicode/utf8"
|
||||
|
||||
"gioui.org/f32"
|
||||
@@ -18,15 +17,8 @@ import (
|
||||
|
||||
// Label is a widget for laying out and drawing text.
|
||||
type Label struct {
|
||||
Font Font
|
||||
|
||||
// Material is a macro recording the material to draw the
|
||||
// text. Use a ColorOp for colored text.
|
||||
Material op.MacroOp
|
||||
// Alignment specify the text alignment.
|
||||
Alignment Alignment
|
||||
// Text is the string to draw.
|
||||
Text string
|
||||
// MaxLines limits the number of lines. Zero means no limit.
|
||||
MaxLines int
|
||||
}
|
||||
@@ -89,9 +81,9 @@ func (l *lineIterator) Next() (String, f32.Point, bool) {
|
||||
return String{}, f32.Point{}, false
|
||||
}
|
||||
|
||||
func (l Label) Layout(gtx *layout.Context, s *Shaper) {
|
||||
func (l Label) Layout(gtx *layout.Context, s *Shaper, font Font, txt string) {
|
||||
cs := gtx.Constraints
|
||||
textLayout := s.Layout(gtx, l.Font, l.Text, LayoutOptions{MaxWidth: cs.Width.Max})
|
||||
textLayout := s.Layout(gtx, font, txt, LayoutOptions{MaxWidth: cs.Width.Max})
|
||||
lines := textLayout.Lines
|
||||
if max := l.MaxLines; max > 0 && len(lines) > max {
|
||||
lines = lines[:max]
|
||||
@@ -115,10 +107,7 @@ func (l Label) Layout(gtx *layout.Context, s *Shaper) {
|
||||
var stack op.StackOp
|
||||
stack.Push(gtx.Ops)
|
||||
op.TransformOp{}.Offset(off).Add(gtx.Ops)
|
||||
s.Shape(gtx, l.Font, str).Add(gtx.Ops)
|
||||
// Set a default color in case the material is empty.
|
||||
paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(gtx.Ops)
|
||||
l.Material.Add(gtx.Ops)
|
||||
s.Shape(gtx, font, str).Add(gtx.Ops)
|
||||
paint.PaintOp{Rect: lclip}.Add(gtx.Ops)
|
||||
stack.Pop()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user