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 <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-10-10 13:48:25 +02:00
parent f35fe407b3
commit dbb62ae0f6
+33 -47
View File
@@ -42,7 +42,7 @@ type Editor struct {
Submit bool Submit bool
scale int scale int
font editorFont font Font
blinkStart time.Time blinkStart time.Time
focused bool focused bool
rr editBuffer rr editBuffer
@@ -51,8 +51,6 @@ type Editor struct {
valid bool valid bool
lines []Line lines []Line
dims layout.Dimensions dims layout.Dimensions
padTop, padBottom int
padLeft, padRight int
carWidth fixed.Int26_6 carWidth fixed.Int26_6
requestFocus bool requestFocus bool
caretOn bool caretOn bool
@@ -201,17 +199,12 @@ func (e *Editor) layout(gtx *layout.Context, s *Shaper, font Font) {
e.scale = scale e.scale = scale
} }
cs := gtx.Constraints cs := gtx.Constraints
twoDp := gtx.Px(unit.Dp(2))
e.carWidth = fixed.I(gtx.Px(unit.Dp(1))) e.carWidth = fixed.I(gtx.Px(unit.Dp(1)))
e.padLeft, e.padRight = twoDp, twoDp
maxWidth := cs.Width.Max maxWidth := cs.Width.Max
if e.SingleLine { if e.SingleLine {
maxWidth = inf maxWidth = inf
} }
if maxWidth != inf {
maxWidth -= e.padLeft + e.padRight
}
if maxWidth != e.maxWidth { if maxWidth != e.maxWidth {
e.maxWidth = maxWidth e.maxWidth = maxWidth
e.invalidate() 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) key.InputOp{Key: e, Focus: e.requestFocus}.Add(gtx.Ops)
e.requestFocus = false e.requestFocus = false
baseline := e.padTop + e.dims.Baseline
pointerPadding := gtx.Px(unit.Dp(4)) pointerPadding := gtx.Px(unit.Dp(4))
r := image.Rectangle{Max: e.viewSize} r := image.Rectangle{Max: e.viewSize}
r.Min.X -= pointerPadding 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) pointer.RectAreaOp{Rect: r}.Add(gtx.Ops)
e.scroller.Add(gtx.Ops) e.scroller.Add(gtx.Ops)
e.clicker.Add(gtx.Ops) e.clicker.Add(gtx.Ops)
gtx.Dimensions = layout.Dimensions{Size: e.viewSize, Baseline: baseline}
e.caretOn = false e.caretOn = false
if e.focused { if e.focused {
now := gtx.Now() 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) 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) { func (e *Editor) draw(gtx *layout.Context, s *Shaper, font Font) {
var stack op.StackOp var stack op.StackOp
stack.Push(gtx.Ops) stack.Push(gtx.Ops)
off := image.Point{ off := image.Point{
X: -e.scrollOff.X + e.padLeft, X: -e.scrollOff.X,
Y: -e.scrollOff.Y + e.padTop, Y: -e.scrollOff.Y,
} }
clip := e.clipRect() clip := textPadding(e.lines)
clip.Max = clip.Max.Add(e.viewSize)
it := lineIterator{ it := lineIterator{
Lines: e.lines, Lines: e.lines,
Clip: clip, Clip: clip,
Alignment: e.Alignment, Alignment: e.Alignment,
Width: e.viewWidth(), Width: e.viewSize.X,
Offset: off, Offset: off,
} }
for { 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()}, Max: image.Point{X: carX.Ceil() + e.carWidth.Ceil(), Y: carY + carDesc.Ceil()},
} }
carRect = carRect.Add(image.Point{ carRect = carRect.Add(image.Point{
X: -e.scrollOff.X + e.padLeft, X: -e.scrollOff.X,
Y: -e.scrollOff.Y + e.padTop, 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() { if !carRect.Empty() {
paint.PaintOp{Rect: toRectF(carRect)}.Add(gtx.Ops) paint.PaintOp{Rect: toRectF(carRect)}.Add(gtx.Ops)
} }
@@ -331,17 +334,11 @@ func (e *Editor) SetText(s string) {
e.prepend(s) 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 { func (e *Editor) scrollBounds() image.Rectangle {
var b image.Rectangle var b image.Rectangle
if e.SingleLine { if e.SingleLine {
if len(e.lines) > 0 { 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 { if b.Min.X > 0 {
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 { for _, l := range e.lines {
y += (prevDesc + l.Ascent).Ceil() y += (prevDesc + l.Ascent).Ceil()
prevDesc = l.Descent prevDesc = l.Descent
if y+prevDesc.Ceil() >= pos.Y+e.scrollOff.Y-e.padTop { if y+prevDesc.Ceil() >= pos.Y+e.scrollOff.Y {
break break
} }
carLine++ carLine++
} }
x := fixed.I(pos.X + e.scrollOff.X - e.padLeft) x := fixed.I(pos.X + e.scrollOff.X)
e.moveToLine(x, carLine) 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 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) { func (e *Editor) layoutCaret() (carLine, carCol int, x fixed.Int26_6, y int) {
e.adjustScroll() e.adjustScroll()
var idx int var idx int
@@ -446,7 +434,7 @@ loop:
} }
idx += len(l.Text.String) 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 return
} }
@@ -530,7 +518,7 @@ func (e *Editor) moveToLine(carX fixed.Int26_6, carLine2 int) fixed.Int26_6 {
} }
} }
l2 := e.lines[carLine2] 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 // Only move past the end of the last line
end := 0 end := 0
if carLine2 < len(e.lines)-1 { if carLine2 < len(e.lines)-1 {
@@ -587,7 +575,7 @@ func (e *Editor) moveEnd() {
e.rr.caret += s e.rr.caret += s
x += adv 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 e.carXOff = l.Width + a - x
} }
@@ -595,21 +583,19 @@ func (e *Editor) scrollToCaret() {
carLine, _, x, y := e.layoutCaret() carLine, _, x, y := e.layoutCaret()
l := e.lines[carLine] l := e.lines[carLine]
if e.SingleLine { if e.SingleLine {
minx := (x - e.carWidth/2).Ceil() if d := x.Floor() - e.scrollOff.X; d < 0 {
if d := minx - e.scrollOff.X + e.padLeft; d < 0 {
e.scrollOff.X += d e.scrollOff.X += d
} }
maxx := (x + e.carWidth/2).Ceil() if d := x.Ceil() - (e.scrollOff.X + e.viewSize.X); d > 0 {
if d := maxx - (e.scrollOff.X + e.viewSize.X - e.padRight); d > 0 {
e.scrollOff.X += d e.scrollOff.X += d
} }
} else { } else {
miny := y + l.Bounds.Min.Y.Floor() miny := y - l.Ascent.Ceil()
if d := miny - e.scrollOff.Y + e.padTop; d < 0 { if d := miny - e.scrollOff.Y; d < 0 {
e.scrollOff.Y += d e.scrollOff.Y += d
} }
maxy := y + l.Bounds.Max.Y.Ceil() maxy := y + l.Descent.Ceil()
if d := maxy - (e.scrollOff.Y + e.viewSize.Y - e.padBottom); d > 0 { if d := maxy - (e.scrollOff.Y + e.viewSize.Y); d > 0 {
e.scrollOff.Y += d e.scrollOff.Y += d
} }
} }