-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresizer.go.bak
109 lines (98 loc) · 2.6 KB
/
resizer.go.bak
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package ux
import (
"image"
"gioui.org/gesture"
"gioui.org/io/pointer"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/clip"
)
// Resize provides a draggable handle in between two widgets for resizing their area.
type Resize struct {
// Axis defines how the widgets and the handle are laid out.
Axis layout.Axis
// Ratio defines how much space is available to the first widget.
Ratio float32
float float
w1, w2, handle layout.Widget
}
func NewResize(w1, w2, handle layout.Widget) *Resize {
r := &Resize{
Axis: 0,
Ratio: 0,
float: float{},
w1: w1,
w2: w2,
handle: nil,
}
return r
}
// Layout displays w1 and w2 with handle in between.
//
// The widgets w1 and w2 must be able to gracefully resize their minimum and maximum dimensions
// in order for the resize to be smooth.
func (rs *Resize) Layout(gtx layout.Context, w1, w2, handle layout.Widget) layout.Dimensions {
// Compute the first widget's max maxIndentWidth/height.
rs.float.Length = rs.Axis.Convert(gtx.Constraints.Max).X
rs.float.Pos = int(rs.Ratio * float32(rs.float.Length))
oldPos := rs.float.Pos
m := op.Record(gtx.Ops)
dims := rs.float.Layout(gtx, rs.Axis, handle)
c := m.Stop()
if rs.float.Pos != oldPos {
// We update rs.Ratio conditionally to avoid cumulating rounding errors when changing the constraints instead of
// dragging the handle.
rs.Ratio = float32(rs.float.Pos) / float32(rs.float.Length)
}
return layout.Flex{
Axis: rs.Axis,
}.Layout(gtx,
layout.Flexed(rs.Ratio, w1),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
c.Add(gtx.Ops)
return dims
}),
layout.Flexed(1-rs.Ratio, w2),
)
}
type float struct {
Length int // max constraint for the axis
Pos int // position in pixels of the handle
drag gesture.Drag
}
func (f *float) Layout(gtx layout.Context, axis layout.Axis, w layout.Widget) layout.Dimensions {
gtx.Constraints.Min = image.Point{}
dims := w(gtx)
var de *pointer.Event
for {
e, ok := f.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(axis))
if !ok {
break
}
if e.Kind == pointer.Drag {
de = &e
}
}
if de != nil {
xy := de.Position.X
if axis == layout.Vertical {
xy = de.Position.Y
}
f.Pos += int(xy)
}
// Clamp the handle position, leaving it always visible.
if f.Pos < 0 {
f.Pos = 0
} else if f.Pos > f.Length {
f.Pos = f.Length
}
rect := image.Rectangle{Max: dims.Size}
defer clip.Rect(rect).Push(gtx.Ops).Pop()
f.drag.Add(gtx.Ops)
cursor := pointer.CursorRowResize
if axis == layout.Horizontal {
cursor = pointer.CursorColResize
}
cursor.Add(gtx.Ops)
return layout.Dimensions{Size: dims.Size}
}