~eliasnaur/gio-patches

gio: widget,widget/material: add Axis to the Float widget so that Sliders can also be laid out vertically v1 PROPOSED

~pierrec
~pierrec: 1
 widget,widget/material: add Axis to the Float widget so that Sliders can also be laid out vertically

 2 files changed, 74 insertions(+), 34 deletions(-)
#394684 apple.yml success
#394685 freebsd.yml success
#394686 linux.yml success
#394687 openbsd.yml success
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~eliasnaur/gio-patches/patches/19521/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH gio] widget,widget/material: add Axis to the Float widget so that Sliders can also be laid out vertically Export this patch

~pierrec
From: pierre <pierre.curto@gmail.com>

Signed-off-by: pierre <pierre.curto@gmail.com>
---
 widget/float.go           | 24 ++++++++---
 widget/material/slider.go | 84 ++++++++++++++++++++++++++-------------
 2 files changed, 74 insertions(+), 34 deletions(-)

diff --git a/widget/float.go b/widget/float.go
index 3c59a26..1a7838f 100644
--- a/widget/float.go
+++ b/widget/float.go
@@ -14,6 +14,7 @@ import (
// Float is for selecting a value in a range.
type Float struct {
	Value float32
	Axis  layout.Axis

	drag    gesture.Drag
	pos     float32 // position normalized to [0, 1]
@@ -24,13 +25,15 @@ type Float struct {
// Dragging returns whether the value is being interacted with.
func (f *Float) Dragging() bool { return f.drag.Dragging() }

// Layout processes events.
// Layout updates the value according to drag events along the f's main axis.
//
// The range of f is set by the minimum constraints main axis value.
func (f *Float) Layout(gtx layout.Context, pointerMargin int, min, max float32) layout.Dimensions {
	size := gtx.Constraints.Min
	f.length = float32(size.X)
	f.length = float32(f.Axis.Main(size))

	var de *pointer.Event
	for _, e := range f.drag.Events(gtx.Metric, gtx, gesture.Horizontal) {
	for _, e := range f.drag.Events(gtx.Metric, gtx, gesture.Axis(f.Axis)) {
		if e.Type == pointer.Press || e.Type == pointer.Drag {
			de = &e
		}
@@ -38,7 +41,11 @@ func (f *Float) Layout(gtx layout.Context, pointerMargin int, min, max float32)

	value := f.Value
	if de != nil {
		f.pos = de.Position.X / f.length
		xy := de.Position.X
		if f.Axis == layout.Vertical {
			xy = de.Position.Y
		}
		f.pos = xy / f.length
		value = min + (max-min)*f.pos
	} else if min != max {
		f.pos = value/(max-min) - min
@@ -54,8 +61,13 @@ func (f *Float) Layout(gtx layout.Context, pointerMargin int, min, max float32)

	defer op.Save(gtx.Ops).Load()
	rect := image.Rectangle{Max: size}
	rect.Min.X -= pointerMargin
	rect.Max.X += pointerMargin
	if f.Axis == layout.Horizontal {
		rect.Min.X -= pointerMargin
		rect.Max.X += pointerMargin
	} else {
		rect.Min.Y -= pointerMargin
		rect.Max.Y += pointerMargin
	}
	pointer.Rect(rect).Add(gtx.Ops)
	f.drag.Add(gtx.Ops)

diff --git a/widget/material/slider.go b/widget/material/slider.go
index 1ce95ff..9b48d3f 100644
--- a/widget/material/slider.go
+++ b/widget/material/slider.go
@@ -43,26 +43,47 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions {
	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
	if s.Float.Axis == layout.Horizontal {
		if size.X < minLength {
			size.X = minLength
		}
		size.Y = 2 * thumbRadiusInt
	} else {
		if size.Y < minLength {
			size.Y = minLength
		}
		size.X = 2 * thumbRadiusInt
	}
	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 max := s.Float.Axis.Cross(gtx.Constraints.Max); touchSizePx > max {
		touchSizePx = max
	}
	if size.Y < touchSizePx {
		size.Y = 2 * (touchSizePx / 2)
	var sizeMain, sizeCross int
	if s.Float.Axis == layout.Horizontal {
		if size.Y < touchSizePx {
			size.Y = 2 * (touchSizePx / 2)
		}
		sizeMain, sizeCross = size.X, size.Y
	} else {
		if size.X < touchSizePx {
			size.X = 2 * (touchSizePx / 2)
		}
		sizeMain, sizeCross = size.Y, size.X
	}

	st := op.Save(gtx.Ops)
	op.Offset(f32.Pt(thumbRadius, 0)).Add(gtx.Ops)
	gtx.Constraints.Min = image.Pt(size.X-2*thumbRadiusInt, size.Y)
	o := axisPoint32(s.Float.Axis, thumbRadius, 0)
	op.Offset(o).Add(gtx.Ops)
	gtx.Constraints.Min = axisPoint(s.Float.Axis, sizeMain-2*thumbRadiusInt, sizeCross)
	s.Float.Layout(gtx, thumbRadiusInt, s.Min, s.Max)
	gtx.Constraints.Min.Y = size.Y
	if s.Float.Axis == layout.Horizontal {
		gtx.Constraints.Min.Y = sizeCross
	} else {
		gtx.Constraints.Min.X = sizeCross
	}
	thumbPos := thumbRadius + s.Float.Pos()
	st.Load()

@@ -74,14 +95,8 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions {
	// Draw track before thumb.
	st = op.Save(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,
		},
		Min: axisPoint32(s.Float.Axis, thumbRadius, float32(sizeCross/2)-trackWidth/2),
		Max: axisPoint32(s.Float.Axis, thumbPos, float32(sizeCross/2)+trackWidth/2),
	}
	clip.RRect{Rect: track}.Add(gtx.Ops)
	paint.ColorOp{Color: color}.Add(gtx.Ops)
@@ -90,8 +105,13 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions {

	// Draw track after thumb.
	st = op.Save(gtx.Ops)
	track.Min.X = thumbPos
	track.Max.X = float32(size.X) - thumbRadius
	if s.Float.Axis == layout.Horizontal {
		track.Min.X = thumbPos
		track.Max.X = float32(size.X) - thumbRadius
	} else {
		track.Min.Y = thumbPos
		track.Max.Y = float32(size.Y) - thumbRadius
	}
	clip.RRect{Rect: track}.Add(gtx.Ops)
	paint.ColorOp{Color: f32color.MulAlpha(color, 96)}.Add(gtx.Ops)
	paint.PaintOp{}.Add(gtx.Ops)
@@ -100,14 +120,8 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions {
	// Draw thumb.
	st = op.Save(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,
		},
		Min: axisPoint32(s.Float.Axis, thumbPos-thumbRadius, float32(sizeCross/2)-thumbRadius),
		Max: axisPoint32(s.Float.Axis, thumbPos+thumbRadius, float32(sizeCross/2)+thumbRadius),
	}
	rr := thumbRadius
	clip.RRect{
@@ -120,3 +134,17 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions {

	return layout.Dimensions{Size: size}
}

func axisPoint(a layout.Axis, x, y int) image.Point {
	if a == layout.Horizontal {
		return image.Pt(x, y)
	}
	return image.Pt(y, x)
}

func axisPoint32(a layout.Axis, x, y float32) f32.Point {
	if a == layout.Horizontal {
		return f32.Pt(x, y)
	}
	return f32.Pt(y, x)
}
-- 
2.26.2
Nice.

Split the subject into a short primer and a commit message.

On Wed Jan 13, 2021 at 10:28, ~pierrec wrote: