123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- // SPDX-License-Identifier: Unlicense OR MIT
- package material
- import (
- "image"
- "image/color"
- "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) SliderStyle {
- return SliderStyle{
- Color: th.Palette.ContrastBg,
- Float: float,
- FingerSize: th.FingerSize,
- }
- }
- type SliderStyle struct {
- Axis layout.Axis
- Color color.NRGBA
- Float *widget.Float
- FingerSize unit.Dp
- }
- func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions {
- const thumbRadius unit.Dp = 6
- tr := gtx.Dp(thumbRadius)
- trackWidth := gtx.Dp(2)
- axis := s.Axis
- // Keep a minimum length so that the track is always visible.
- minLength := tr + 3*tr + tr
- // Try to expand to finger size, but only if the constraints
- // allow for it.
- touchSizePx := min(gtx.Dp(s.FingerSize), axis.Convert(gtx.Constraints.Max).Y)
- sizeMain := max(axis.Convert(gtx.Constraints.Min).X, minLength)
- sizeCross := max(2*tr, touchSizePx)
- size := axis.Convert(image.Pt(sizeMain, sizeCross))
- o := axis.Convert(image.Pt(tr, 0))
- trans := op.Offset(o).Push(gtx.Ops)
- gtx.Constraints.Min = axis.Convert(image.Pt(sizeMain-2*tr, sizeCross))
- dims := s.Float.Layout(gtx, axis, thumbRadius)
- gtx.Constraints.Min = gtx.Constraints.Min.Add(axis.Convert(image.Pt(0, sizeCross)))
- thumbPos := tr + int(s.Float.Value*float32(axis.Convert(dims.Size).X))
- trans.Pop()
- color := s.Color
- if !gtx.Enabled() {
- color = f32color.Disabled(color)
- }
- rect := func(minx, miny, maxx, maxy int) image.Rectangle {
- r := image.Rect(minx, miny, maxx, maxy)
- if axis == layout.Vertical {
- r.Max.X, r.Min.X = sizeMain-r.Min.X, sizeMain-r.Max.X
- }
- r.Min = axis.Convert(r.Min)
- r.Max = axis.Convert(r.Max)
- return r
- }
- // Draw track before thumb.
- track := rect(
- tr, sizeCross/2-trackWidth/2,
- thumbPos, sizeCross/2+trackWidth/2,
- )
- paint.FillShape(gtx.Ops, color, clip.Rect(track).Op())
- // Draw track after thumb.
- track = rect(
- thumbPos, axis.Convert(track.Min).Y,
- sizeMain-tr, axis.Convert(track.Max).Y,
- )
- paint.FillShape(gtx.Ops, f32color.MulAlpha(color, 96), clip.Rect(track).Op())
- // Draw thumb.
- pt := image.Pt(thumbPos, sizeCross/2)
- thumb := rect(
- pt.X-tr, pt.Y-tr,
- pt.X+tr, pt.Y+tr,
- )
- paint.FillShape(gtx.Ops, color, clip.Ellipse(thumb).Op(gtx.Ops))
- return layout.Dimensions{Size: size}
- }
- func max(a, b int) int {
- if a > b {
- return a
- }
- return b
- }
- func min(a, b int) int {
- if a < b {
- return a
- }
- return b
- }
|