From dbb62ae0f6ced3db35c74627733f95102fc6cc93 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 10 Oct 2019 13:48:25 +0200 Subject: [PATCH] text: remove padding from Editor Before this change, the Editor computed a suitable padding for itself from its font and text. Varying the padding according to the particular font and text doesn't seem worth it and interferes with higher level widgets' ability to overlay hints and the like on top of the editor. Signed-off-by: Elias Naur --- text/editor.go | 106 +++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 60 deletions(-) diff --git a/text/editor.go b/text/editor.go index e4a42924..4603e97f 100644 --- a/text/editor.go +++ b/text/editor.go @@ -41,22 +41,20 @@ type Editor struct { // If not enabled, carriage returns are inserted as newlines in the text. Submit bool - scale int - font editorFont - blinkStart time.Time - focused bool - rr editBuffer - maxWidth int - viewSize image.Point - valid bool - lines []Line - dims layout.Dimensions - padTop, padBottom int - padLeft, padRight int - carWidth fixed.Int26_6 - requestFocus bool - caretOn bool - caretScroll bool + scale int + font Font + blinkStart time.Time + focused bool + rr editBuffer + maxWidth int + viewSize image.Point + valid bool + lines []Line + dims layout.Dimensions + carWidth fixed.Int26_6 + requestFocus bool + caretOn bool + caretScroll bool // carXOff is the offset to the current caret // position when moving between lines. @@ -201,17 +199,12 @@ func (e *Editor) layout(gtx *layout.Context, s *Shaper, font Font) { e.scale = scale } cs := gtx.Constraints - twoDp := gtx.Px(unit.Dp(2)) e.carWidth = fixed.I(gtx.Px(unit.Dp(1))) - e.padLeft, e.padRight = twoDp, twoDp maxWidth := cs.Width.Max if e.SingleLine { maxWidth = inf } - if maxWidth != inf { - maxWidth -= e.padLeft + e.padRight - } if maxWidth != e.maxWidth { e.maxWidth = maxWidth e.invalidate() @@ -232,8 +225,6 @@ func (e *Editor) layout(gtx *layout.Context, s *Shaper, font Font) { key.InputOp{Key: e, Focus: e.requestFocus}.Add(gtx.Ops) e.requestFocus = false - - baseline := e.padTop + e.dims.Baseline pointerPadding := gtx.Px(unit.Dp(4)) r := image.Rectangle{Max: e.viewSize} r.Min.X -= pointerPadding @@ -243,7 +234,6 @@ func (e *Editor) layout(gtx *layout.Context, s *Shaper, font Font) { pointer.RectAreaOp{Rect: r}.Add(gtx.Ops) e.scroller.Add(gtx.Ops) e.clicker.Add(gtx.Ops) - gtx.Dimensions = layout.Dimensions{Size: e.viewSize, Baseline: baseline} e.caretOn = false if e.focused { now := gtx.Now() @@ -257,21 +247,24 @@ func (e *Editor) layout(gtx *layout.Context, s *Shaper, font Font) { } e.caretOn = e.focused && (!blinking || dt%timePerBlink < timePerBlink/2) } + + 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 + e.padLeft, - Y: -e.scrollOff.Y + e.padTop, + X: -e.scrollOff.X, + Y: -e.scrollOff.Y, } - clip := e.clipRect() + clip := textPadding(e.lines) + clip.Max = clip.Max.Add(e.viewSize) it := lineIterator{ Lines: e.lines, Clip: clip, Alignment: e.Alignment, - Width: e.viewWidth(), + Width: e.viewSize.X, Offset: off, } for { @@ -304,10 +297,20 @@ func (e *Editor) drawCaret(gtx *layout.Context) { Max: image.Point{X: carX.Ceil() + e.carWidth.Ceil(), Y: carY + carDesc.Ceil()}, } carRect = carRect.Add(image.Point{ - X: -e.scrollOff.X + e.padLeft, - Y: -e.scrollOff.Y + e.padTop, + X: -e.scrollOff.X, + Y: -e.scrollOff.Y, }) - carRect = e.clipRect().Intersect(carRect) + clip := textPadding(e.lines) + // Account for caret width to each side. + whalf := (e.carWidth / 2).Ceil() + if clip.Max.X < whalf { + clip.Max.X = whalf + } + if clip.Min.X > -whalf { + clip.Min.X = -whalf + } + clip.Max = clip.Max.Add(e.viewSize) + carRect = clip.Intersect(carRect) if !carRect.Empty() { paint.PaintOp{Rect: toRectF(carRect)}.Add(gtx.Ops) } @@ -331,17 +334,11 @@ func (e *Editor) SetText(s string) { e.prepend(s) } -func (e *Editor) clipRect() image.Rectangle { - clip := textPadding(e.lines) - clip.Max = clip.Max.Add(e.viewSize) - return clip -} - func (e *Editor) scrollBounds() image.Rectangle { var b image.Rectangle if e.SingleLine { if len(e.lines) > 0 { - b.Min.X = align(e.Alignment, e.lines[0].Width, e.viewWidth()).Floor() + b.Min.X = align(e.Alignment, e.lines[0].Width, e.viewSize.X).Floor() if b.Min.X > 0 { b.Min.X = 0 } @@ -379,12 +376,12 @@ func (e *Editor) moveCoord(c unit.Converter, pos image.Point) { for _, l := range e.lines { y += (prevDesc + l.Ascent).Ceil() prevDesc = l.Descent - if y+prevDesc.Ceil() >= pos.Y+e.scrollOff.Y-e.padTop { + if y+prevDesc.Ceil() >= pos.Y+e.scrollOff.Y { break } carLine++ } - x := fixed.I(pos.X + e.scrollOff.X - e.padLeft) + x := fixed.I(pos.X + e.scrollOff.X) e.moveToLine(x, carLine) } @@ -409,18 +406,9 @@ func (e *Editor) layoutText(c unit.Converter, s *Shaper, font Font) { } } } - padTop, padBottom := textPadding(lines) - dims.Size.Y += padTop + padBottom - dims.Size.X += e.padLeft + e.padRight - e.padTop = padTop - e.padBottom = padBottom e.lines, e.dims = lines, dims } -func (e *Editor) viewWidth() int { - return e.viewSize.X - e.padLeft - e.padRight -} - func (e *Editor) layoutCaret() (carLine, carCol int, x fixed.Int26_6, y int) { e.adjustScroll() var idx int @@ -446,7 +434,7 @@ loop: } idx += len(l.Text.String) } - x += align(e.Alignment, e.lines[carLine].Width, e.viewWidth()) + x += align(e.Alignment, e.lines[carLine].Width, e.viewSize.X) return } @@ -530,7 +518,7 @@ func (e *Editor) moveToLine(carX fixed.Int26_6, carLine2 int) fixed.Int26_6 { } } l2 := e.lines[carLine2] - carX2 := align(e.Alignment, l2.Width, e.viewWidth()) + carX2 := align(e.Alignment, l2.Width, e.viewSize.X) // Only move past the end of the last line end := 0 if carLine2 < len(e.lines)-1 { @@ -587,7 +575,7 @@ func (e *Editor) moveEnd() { e.rr.caret += s x += adv } - a := align(e.Alignment, l.Width, e.viewWidth()) + a := align(e.Alignment, l.Width, e.viewSize.X) e.carXOff = l.Width + a - x } @@ -595,21 +583,19 @@ func (e *Editor) scrollToCaret() { carLine, _, x, y := e.layoutCaret() l := e.lines[carLine] if e.SingleLine { - minx := (x - e.carWidth/2).Ceil() - if d := minx - e.scrollOff.X + e.padLeft; d < 0 { + if d := x.Floor() - e.scrollOff.X; d < 0 { e.scrollOff.X += d } - maxx := (x + e.carWidth/2).Ceil() - if d := maxx - (e.scrollOff.X + e.viewSize.X - e.padRight); d > 0 { + if d := x.Ceil() - (e.scrollOff.X + e.viewSize.X); d > 0 { e.scrollOff.X += d } } else { - miny := y + l.Bounds.Min.Y.Floor() - if d := miny - e.scrollOff.Y + e.padTop; d < 0 { + miny := y - l.Ascent.Ceil() + if d := miny - e.scrollOff.Y; d < 0 { e.scrollOff.Y += d } - maxy := y + l.Bounds.Max.Y.Ceil() - if d := maxy - (e.scrollOff.Y + e.viewSize.Y - e.padBottom); d > 0 { + maxy := y + l.Descent.Ceil() + if d := maxy - (e.scrollOff.Y + e.viewSize.Y); d > 0 { e.scrollOff.Y += d } }