widget: ensure empty editor makes space for caret

Prior to this change an editor with no content and a zero minimum
constraint would return itself has having width zero. This
prevented users from being able to see the editor when they
moved focus to it, as it could not display its caret. This
simple change ensures that, at minimum, the editor returns
its dimensions to include the width of a caret.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
Chris Waldon
2022-05-06 13:35:42 -04:00
committed by Elias Naur
parent c97f976e7d
commit 4996337d26
2 changed files with 43 additions and 5 deletions
+23 -5
View File
@@ -485,6 +485,17 @@ func (e *Editor) Focused() bool {
return e.focused
}
// calculateViewSize determines the size of the current visible content,
// ensuring that even if there is no text content, some space is reserved
// for the caret.
func (e *Editor) calculateViewSize(gtx layout.Context) image.Point {
base := e.dims.Size
if caretWidth := e.caretWidth(gtx); base.X < caretWidth {
base.X = caretWidth
}
return gtx.Constraints.Constrain(base)
}
// Layout lays out the editor. If content is not nil, it is laid out on top.
func (e *Editor) Layout(gtx layout.Context, sh text.Shaper, font text.Font, size unit.Value, content layout.Widget) layout.Dimensions {
if e.locale != gtx.Locale {
@@ -518,7 +529,7 @@ func (e *Editor) Layout(gtx layout.Context, sh text.Shaper, font text.Font, size
e.processEvents(gtx)
e.makeValid()
if viewSize := gtx.Constraints.Constrain(e.dims.Size); viewSize != e.viewSize {
if viewSize := e.calculateViewSize(gtx); viewSize != e.viewSize {
e.viewSize = viewSize
e.invalidate()
}
@@ -749,14 +760,21 @@ func (e *Editor) PaintText(gtx layout.Context) {
}
}
func (e *Editor) PaintCaret(gtx layout.Context) {
if !e.caret.on {
return
}
// caretWidth returns the width occupied by the caret for the current
// gtx.
func (e *Editor) caretWidth(gtx layout.Context) int {
carWidth2 := gtx.Px(unit.Dp(1)) / 2
if carWidth2 < 1 {
carWidth2 = 1
}
return carWidth2
}
func (e *Editor) PaintCaret(gtx layout.Context) {
if !e.caret.on {
return
}
carWidth2 := e.caretWidth(gtx)
caretPos, carAsc, carDesc := e.caretInfo()
carRect := image.Rectangle{
+20
View File
@@ -36,6 +36,26 @@ var english = system.Locale{
Direction: system.LTR,
}
// TestEditorZeroDimensions ensures that an empty editor still reserves
// space for displaying its caret when the constraints allow for it.
func TestEditorZeroDimensions(t *testing.T) {
gtx := layout.Context{
Ops: new(op.Ops),
Constraints: layout.Constraints{
Max: image.Pt(100, 100),
},
Locale: english,
}
cache := text.NewCache(gofont.Collection())
fontSize := unit.Px(10)
font := text.Font{}
e := new(Editor)
dims := e.Layout(gtx, cache, font, fontSize, nil)
if dims.Size.X < 1 || dims.Size.Y < 1 {
t.Errorf("expected empty editor to occupy enough space to display cursor, but returned dimensions %v", dims)
}
}
func TestEditorConfigurations(t *testing.T) {
gtx := layout.Context{
Ops: new(op.Ops),