Files
gio/widget/material/slider.go
T
Egon Elbre 296303210f 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 <egonelbre@gmail.com>
2020-12-14 15:56:56 +01:00

123 lines
2.7 KiB
Go

// SPDX-License-Identifier: Unlicense OR MIT
package material
import (
"image"
"image/color"
"gioui.org/f32"
"gioui.org/internal/f32color"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
"gioui.org/widget"
)
// 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,
FingerSize: th.FingerSize,
}
}
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)
size := gtx.Constraints.Min
// Keep a minimum length so that the track is always visible.
minLength := thumbRadiusInt + 3*thumbRadiusInt + thumbRadiusInt
if size.X < minLength {
size.X = minLength
}
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(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
if gtx.Queue == nil {
color = f32color.MulAlpha(color, 150)
}
// Draw track before thumb.
st = op.Push(gtx.Ops)
track := f32.Rectangle{
Min: f32.Point{
X: thumbRadius,
Y: float32(size.Y/2) - trackWidth/2,
},
Max: f32.Point{
X: thumbPos,
Y: float32(size.Y/2) + trackWidth/2,
},
}
clip.RRect{Rect: track}.Add(gtx.Ops)
paint.ColorOp{Color: color}.Add(gtx.Ops)
paint.PaintOp{}.Add(gtx.Ops)
st.Pop()
// Draw track after thumb.
st = op.Push(gtx.Ops)
track.Min.X = thumbPos
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)
st.Pop()
// Draw thumb.
st = op.Push(gtx.Ops)
thumb := f32.Rectangle{
Min: f32.Point{
X: thumbPos - thumbRadius,
Y: float32(size.Y/2) - thumbRadius,
},
Max: f32.Point{
X: thumbPos + thumbRadius,
Y: float32(size.Y/2) + thumbRadius,
},
}
rr := thumbRadius
clip.RRect{
Rect: thumb,
NE: rr, NW: rr, SE: rr, SW: rr,
}.Add(gtx.Ops)
paint.ColorOp{Color: color}.Add(gtx.Ops)
paint.PaintOp{}.Add(gtx.Ops)
st.Pop()
return layout.Dimensions{Size: size}
}