mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
widget{,/material}: surface line height manipulation
This commit surfaces fields to manipulate the line height of all label and editor types. It's unfortunate how this spreads through the API, but I don't see a good way to eliminate that right now. Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
@@ -35,6 +35,12 @@ type Editor struct {
|
|||||||
text textView
|
text textView
|
||||||
// Alignment controls the alignment of text within the editor.
|
// Alignment controls the alignment of text within the editor.
|
||||||
Alignment text.Alignment
|
Alignment text.Alignment
|
||||||
|
// LineHeight determines the gap between baselines of text. If zero, a sensible
|
||||||
|
// default will be used.
|
||||||
|
LineHeight unit.Sp
|
||||||
|
// LineHeightScale is multiplied by LineHeight to determine the final gap
|
||||||
|
// between baselines. If zero, a sensible default will be used.
|
||||||
|
LineHeightScale float32
|
||||||
// SingleLine force the text to stay on a single line.
|
// SingleLine force the text to stay on a single line.
|
||||||
// SingleLine also sets the scrolling direction to
|
// SingleLine also sets the scrolling direction to
|
||||||
// horizontal.
|
// horizontal.
|
||||||
@@ -504,6 +510,8 @@ func (e *Editor) initBuffer() {
|
|||||||
e.text.SetSource(e.buffer)
|
e.text.SetSource(e.buffer)
|
||||||
}
|
}
|
||||||
e.text.Alignment = e.Alignment
|
e.text.Alignment = e.Alignment
|
||||||
|
e.text.LineHeight = e.LineHeight
|
||||||
|
e.text.LineHeightScale = e.LineHeightScale
|
||||||
e.text.SingleLine = e.SingleLine
|
e.text.SingleLine = e.SingleLine
|
||||||
e.text.Mask = e.Mask
|
e.text.Mask = e.Mask
|
||||||
e.text.WrapPolicy = e.WrapPolicy
|
e.text.WrapPolicy = e.WrapPolicy
|
||||||
|
|||||||
+18
-9
@@ -30,6 +30,12 @@ type Label struct {
|
|||||||
Truncator string
|
Truncator string
|
||||||
// WrapPolicy configures how displayed text will be broken into lines.
|
// WrapPolicy configures how displayed text will be broken into lines.
|
||||||
WrapPolicy text.WrapPolicy
|
WrapPolicy text.WrapPolicy
|
||||||
|
// LineHeight controls the distance between the baselines of lines of text.
|
||||||
|
// If zero, a sensible default will be used.
|
||||||
|
LineHeight unit.Sp
|
||||||
|
// LineHeightScale applies a scaling factor to the LineHeight. If zero, a
|
||||||
|
// sensible default will be used.
|
||||||
|
LineHeightScale float32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Layout the label with the given shaper, font, size, text, and material.
|
// Layout the label with the given shaper, font, size, text, and material.
|
||||||
@@ -49,16 +55,19 @@ type TextInfo struct {
|
|||||||
func (l Label) LayoutDetailed(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, txt string, textMaterial op.CallOp) (layout.Dimensions, TextInfo) {
|
func (l Label) LayoutDetailed(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, txt string, textMaterial op.CallOp) (layout.Dimensions, TextInfo) {
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
textSize := fixed.I(gtx.Sp(size))
|
textSize := fixed.I(gtx.Sp(size))
|
||||||
|
lineHeight := fixed.I(gtx.Sp(l.LineHeight))
|
||||||
lt.LayoutString(text.Parameters{
|
lt.LayoutString(text.Parameters{
|
||||||
Font: font,
|
Font: font,
|
||||||
PxPerEm: textSize,
|
PxPerEm: textSize,
|
||||||
MaxLines: l.MaxLines,
|
MaxLines: l.MaxLines,
|
||||||
Truncator: l.Truncator,
|
Truncator: l.Truncator,
|
||||||
Alignment: l.Alignment,
|
Alignment: l.Alignment,
|
||||||
WrapPolicy: l.WrapPolicy,
|
WrapPolicy: l.WrapPolicy,
|
||||||
MaxWidth: cs.Max.X,
|
MaxWidth: cs.Max.X,
|
||||||
MinWidth: cs.Min.X,
|
MinWidth: cs.Min.X,
|
||||||
Locale: gtx.Locale,
|
Locale: gtx.Locale,
|
||||||
|
LineHeight: lineHeight,
|
||||||
|
LineHeightScale: l.LineHeightScale,
|
||||||
}, txt)
|
}, txt)
|
||||||
m := op.Record(gtx.Ops)
|
m := op.Record(gtx.Ops)
|
||||||
viewport := image.Rectangle{Max: cs.Max}
|
viewport := image.Rectangle{Max: cs.Max}
|
||||||
|
|||||||
@@ -16,8 +16,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type EditorStyle struct {
|
type EditorStyle struct {
|
||||||
Font font.Font
|
Font font.Font
|
||||||
TextSize unit.Sp
|
// LineHeight controls the distance between the baselines of lines of text.
|
||||||
|
// If zero, a sensible default will be used.
|
||||||
|
LineHeight unit.Sp
|
||||||
|
// LineHeightScale applies a scaling factor to the LineHeight. If zero, a
|
||||||
|
// sensible default will be used.
|
||||||
|
LineHeightScale float32
|
||||||
|
TextSize unit.Sp
|
||||||
// Color is the text color.
|
// Color is the text color.
|
||||||
Color color.NRGBA
|
Color color.NRGBA
|
||||||
// Hint contains the text displayed when the editor is empty.
|
// Hint contains the text displayed when the editor is empty.
|
||||||
@@ -64,7 +70,12 @@ func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro := op.Record(gtx.Ops)
|
macro := op.Record(gtx.Ops)
|
||||||
tl := widget.Label{Alignment: e.Editor.Alignment, MaxLines: maxlines}
|
tl := widget.Label{
|
||||||
|
Alignment: e.Editor.Alignment,
|
||||||
|
MaxLines: maxlines,
|
||||||
|
LineHeight: e.LineHeight,
|
||||||
|
LineHeightScale: e.LineHeightScale,
|
||||||
|
}
|
||||||
dims := tl.Layout(gtx, e.shaper, e.Font, e.TextSize, e.Hint, hintColor)
|
dims := tl.Layout(gtx, e.shaper, e.Font, e.TextSize, e.Hint, hintColor)
|
||||||
call := macro.Stop()
|
call := macro.Stop()
|
||||||
|
|
||||||
@@ -74,6 +85,8 @@ func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
if h := dims.Size.Y; gtx.Constraints.Min.Y < h {
|
if h := dims.Size.Y; gtx.Constraints.Min.Y < h {
|
||||||
gtx.Constraints.Min.Y = h
|
gtx.Constraints.Min.Y = h
|
||||||
}
|
}
|
||||||
|
e.Editor.LineHeight = e.LineHeight
|
||||||
|
e.Editor.LineHeightScale = e.LineHeightScale
|
||||||
dims = e.Editor.Layout(gtx, e.shaper, e.Font, e.TextSize, textColor, selectionColor)
|
dims = e.Editor.Layout(gtx, e.shaper, e.Font, e.TextSize, textColor, selectionColor)
|
||||||
if e.Editor.Len() == 0 {
|
if e.Editor.Len() == 0 {
|
||||||
call.Add(gtx.Ops)
|
call.Add(gtx.Ops)
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ type LabelStyle struct {
|
|||||||
Text string
|
Text string
|
||||||
// TextSize determines the size of the text glyphs.
|
// TextSize determines the size of the text glyphs.
|
||||||
TextSize unit.Sp
|
TextSize unit.Sp
|
||||||
|
// LineHeight controls the distance between the baselines of lines of text.
|
||||||
|
// If zero, a sensible default will be used.
|
||||||
|
LineHeight unit.Sp
|
||||||
|
// LineHeightScale applies a scaling factor to the LineHeight. If zero, a
|
||||||
|
// sensible default will be used.
|
||||||
|
LineHeightScale float32
|
||||||
|
|
||||||
// Shaper is the text shaper used to display this labe. This field is automatically
|
// Shaper is the text shaper used to display this labe. This field is automatically
|
||||||
// set using by all constructor functions. If constructing a LabelStyle literal, you
|
// set using by all constructor functions. If constructing a LabelStyle literal, you
|
||||||
@@ -132,13 +138,17 @@ func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
l.State.MaxLines = l.MaxLines
|
l.State.MaxLines = l.MaxLines
|
||||||
l.State.Truncator = l.Truncator
|
l.State.Truncator = l.Truncator
|
||||||
l.State.WrapPolicy = l.WrapPolicy
|
l.State.WrapPolicy = l.WrapPolicy
|
||||||
|
l.State.LineHeight = l.LineHeight
|
||||||
|
l.State.LineHeightScale = l.LineHeightScale
|
||||||
return l.State.Layout(gtx, l.Shaper, l.Font, l.TextSize, textColor, selectColor)
|
return l.State.Layout(gtx, l.Shaper, l.Font, l.TextSize, textColor, selectColor)
|
||||||
}
|
}
|
||||||
tl := widget.Label{
|
tl := widget.Label{
|
||||||
Alignment: l.Alignment,
|
Alignment: l.Alignment,
|
||||||
MaxLines: l.MaxLines,
|
MaxLines: l.MaxLines,
|
||||||
Truncator: l.Truncator,
|
Truncator: l.Truncator,
|
||||||
WrapPolicy: l.WrapPolicy,
|
WrapPolicy: l.WrapPolicy,
|
||||||
|
LineHeight: l.LineHeight,
|
||||||
|
LineHeightScale: l.LineHeightScale,
|
||||||
}
|
}
|
||||||
return tl.Layout(gtx, l.Shaper, l.Font, l.TextSize, l.Text, textColor)
|
return tl.Layout(gtx, l.Shaper, l.Font, l.TextSize, l.Text, textColor)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-3
@@ -59,9 +59,15 @@ type Selectable struct {
|
|||||||
// if text was cut off. Defaults to "…" if left empty.
|
// if text was cut off. Defaults to "…" if left empty.
|
||||||
Truncator string
|
Truncator string
|
||||||
// WrapPolicy configures how displayed text will be broken into lines.
|
// WrapPolicy configures how displayed text will be broken into lines.
|
||||||
WrapPolicy text.WrapPolicy
|
WrapPolicy text.WrapPolicy
|
||||||
initialized bool
|
// LineHeight controls the distance between the baselines of lines of text.
|
||||||
source stringSource
|
// If zero, a sensible default will be used.
|
||||||
|
LineHeight unit.Sp
|
||||||
|
// LineHeightScale applies a scaling factor to the LineHeight. If zero, a
|
||||||
|
// sensible default will be used.
|
||||||
|
LineHeightScale float32
|
||||||
|
initialized bool
|
||||||
|
source stringSource
|
||||||
// scratch is a buffer reused to efficiently read text out of the
|
// scratch is a buffer reused to efficiently read text out of the
|
||||||
// textView.
|
// textView.
|
||||||
scratch []byte
|
scratch []byte
|
||||||
@@ -181,6 +187,8 @@ func (l *Selectable) Truncated() bool {
|
|||||||
// paint material for the text and selection rectangles, respectively.
|
// paint material for the text and selection rectangles, respectively.
|
||||||
func (l *Selectable) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, textMaterial, selectionMaterial op.CallOp) layout.Dimensions {
|
func (l *Selectable) Layout(gtx layout.Context, lt *text.Shaper, font font.Font, size unit.Sp, textMaterial, selectionMaterial op.CallOp) layout.Dimensions {
|
||||||
l.initialize()
|
l.initialize()
|
||||||
|
l.text.LineHeight = l.LineHeight
|
||||||
|
l.text.LineHeightScale = l.LineHeightScale
|
||||||
l.text.Alignment = l.Alignment
|
l.text.Alignment = l.Alignment
|
||||||
l.text.MaxLines = l.MaxLines
|
l.text.MaxLines = l.MaxLines
|
||||||
l.text.Truncator = l.Truncator
|
l.text.Truncator = l.Truncator
|
||||||
|
|||||||
@@ -44,6 +44,12 @@ type textSource interface {
|
|||||||
// be scrolled, and for configuring and drawing text selection boxes.
|
// be scrolled, and for configuring and drawing text selection boxes.
|
||||||
type textView struct {
|
type textView struct {
|
||||||
Alignment text.Alignment
|
Alignment text.Alignment
|
||||||
|
// LineHeight controls the distance between the baselines of lines of text.
|
||||||
|
// If zero, a sensible default will be used.
|
||||||
|
LineHeight unit.Sp
|
||||||
|
// LineHeightScale applies a scaling factor to the LineHeight. If zero, a
|
||||||
|
// sensible default will be used.
|
||||||
|
LineHeightScale float32
|
||||||
// SingleLine forces the text to stay on a single line.
|
// SingleLine forces the text to stay on a single line.
|
||||||
// SingleLine also sets the scrolling direction to
|
// SingleLine also sets the scrolling direction to
|
||||||
// horizontal.
|
// horizontal.
|
||||||
@@ -273,6 +279,14 @@ func (e *textView) Update(gtx layout.Context, lt *text.Shaper, font font.Font, s
|
|||||||
e.params.WrapPolicy = e.WrapPolicy
|
e.params.WrapPolicy = e.WrapPolicy
|
||||||
e.invalidate()
|
e.invalidate()
|
||||||
}
|
}
|
||||||
|
if lh := fixed.I(gtx.Sp(e.LineHeight)); lh != e.params.LineHeight {
|
||||||
|
e.params.LineHeight = lh
|
||||||
|
e.invalidate()
|
||||||
|
}
|
||||||
|
if e.LineHeightScale != e.params.LineHeightScale {
|
||||||
|
e.params.LineHeightScale = e.LineHeightScale
|
||||||
|
e.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
e.makeValid()
|
e.makeValid()
|
||||||
if eventHandling != nil {
|
if eventHandling != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user