From 296303210f31696f1eb8f3bccd7c71a787113b25 Mon Sep 17 00:00:00 2001 From: Egon Elbre Date: Sat, 12 Dec 2020 13:21:06 +0200 Subject: [PATCH] widget/material: remove padding from Slider Remove padding from the sides of the Slider to align them with other components. However, since sliders still need to be used with fingers try to enforce a minimum finger height, if there is sufficient room. The sides don't need similar treatment since after grabbing it's possible to move the finger beyond the touch area, without losing interaction. To not enforce finger size, the theme can be adjusted: theme.FingerSize = unit.Px(0) Signed-off-by: Egon Elbre --- widget/material/slider.go | 48 ++++++++++++++++++++++++--------------- widget/material/theme.go | 6 +++++ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/widget/material/slider.go b/widget/material/slider.go index fca46049..801e19c8 100644 --- a/widget/material/slider.go +++ b/widget/material/slider.go @@ -19,10 +19,11 @@ import ( // Slider is for selecting a value in a range. func Slider(th *Theme, float *widget.Float, min, max float32) SliderStyle { return SliderStyle{ - Min: min, - Max: max, - Color: th.Palette.ContrastBg, - Float: float, + Min: min, + Max: max, + Color: th.Palette.ContrastBg, + Float: float, + FingerSize: th.FingerSize, } } @@ -30,28 +31,39 @@ type SliderStyle struct { Min, Max float32 Color color.NRGBA Float *widget.Float + + FingerSize unit.Value } func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { thumbRadiusInt := gtx.Px(unit.Dp(6)) trackWidth := float32(gtx.Px(unit.Dp(2))) thumbRadius := float32(thumbRadiusInt) - halfWidthInt := 2 * thumbRadiusInt - halfWidth := float32(halfWidthInt) size := gtx.Constraints.Min // Keep a minimum length so that the track is always visible. - minLength := halfWidthInt + 3*thumbRadiusInt + halfWidthInt + minLength := thumbRadiusInt + 3*thumbRadiusInt + thumbRadiusInt if size.X < minLength { size.X = minLength } - size.Y = 2 * halfWidthInt + size.Y = 2 * thumbRadiusInt + + // Try to expand to finger size, but only if the constraints + // allow for it. + touchSizePx := gtx.Px(s.FingerSize) + if touchSizePx > gtx.Constraints.Max.Y { + touchSizePx = gtx.Constraints.Max.Y + } + if size.Y < touchSizePx { + size.Y = 2 * (touchSizePx / 2) + } st := op.Push(gtx.Ops) - op.Offset(f32.Pt(halfWidth, 0)).Add(gtx.Ops) - gtx.Constraints.Min = image.Pt(size.X-2*halfWidthInt, size.Y) - s.Float.Layout(gtx, halfWidthInt, s.Min, s.Max) - thumbPos := halfWidth + s.Float.Pos() + op.Offset(f32.Pt(thumbRadius, 0)).Add(gtx.Ops) + gtx.Constraints.Min = image.Pt(size.X-2*thumbRadiusInt, size.Y) + s.Float.Layout(gtx, thumbRadiusInt, s.Min, s.Max) + gtx.Constraints.Min.Y = size.Y + thumbPos := thumbRadius + s.Float.Pos() st.Pop() color := s.Color @@ -63,12 +75,12 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { st = op.Push(gtx.Ops) track := f32.Rectangle{ Min: f32.Point{ - X: halfWidth, - Y: halfWidth - trackWidth/2, + X: thumbRadius, + Y: float32(size.Y/2) - trackWidth/2, }, Max: f32.Point{ X: thumbPos, - Y: halfWidth + trackWidth/2, + Y: float32(size.Y/2) + trackWidth/2, }, } clip.RRect{Rect: track}.Add(gtx.Ops) @@ -79,7 +91,7 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { // Draw track after thumb. st = op.Push(gtx.Ops) track.Min.X = thumbPos - track.Max.X = float32(size.X) - halfWidth + track.Max.X = float32(size.X) - thumbRadius clip.RRect{Rect: track}.Add(gtx.Ops) paint.ColorOp{Color: f32color.MulAlpha(color, 96)}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) @@ -90,11 +102,11 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { thumb := f32.Rectangle{ Min: f32.Point{ X: thumbPos - thumbRadius, - Y: halfWidth - thumbRadius, + Y: float32(size.Y/2) - thumbRadius, }, Max: f32.Point{ X: thumbPos + thumbRadius, - Y: halfWidth + thumbRadius, + Y: float32(size.Y/2) + thumbRadius, }, } rr := thumbRadius diff --git a/widget/material/theme.go b/widget/material/theme.go index d37a2331..8cc44c7c 100644 --- a/widget/material/theme.go +++ b/widget/material/theme.go @@ -40,6 +40,9 @@ type Theme struct { RadioChecked *widget.Icon RadioUnchecked *widget.Icon } + + // FingerSize is the minimum touch target size. + FingerSize unit.Value } func NewTheme(fontCollection []text.FontFace) *Theme { @@ -59,6 +62,9 @@ func NewTheme(fontCollection []text.FontFace) *Theme { t.Icon.RadioChecked = mustIcon(widget.NewIcon(icons.ToggleRadioButtonChecked)) t.Icon.RadioUnchecked = mustIcon(widget.NewIcon(icons.ToggleRadioButtonUnchecked)) + // 38dp is on the lower end of possible finger size. + t.FingerSize = unit.Dp(38) + return t }