mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
166 lines
3.7 KiB
Go
166 lines
3.7 KiB
Go
package gioui
|
|
|
|
import (
|
|
"image"
|
|
|
|
"gioui.org/io/pointer"
|
|
"gioui.org/layout"
|
|
"gioui.org/op"
|
|
"gioui.org/op/clip"
|
|
"gioui.org/unit"
|
|
)
|
|
|
|
type Split struct {
|
|
// Ratio keeps the current layout.
|
|
// 0 is center, -1 completely to the left, 1 completely to the right.
|
|
Ratio float32
|
|
// Bar is the width for resizing the layout
|
|
Bar unit.Dp
|
|
// Axis is the split direction: layout.Horizontal splits the view in left
|
|
// and right, layout.Vertical splits the view in top and bottom
|
|
Axis layout.Axis
|
|
|
|
drag bool
|
|
dragID pointer.ID
|
|
dragCoord float32
|
|
}
|
|
|
|
var defaultBarWidth = unit.Dp(10)
|
|
|
|
func (s *Split) Layout(gtx layout.Context, first, second layout.Widget) layout.Dimensions {
|
|
bar := gtx.Dp(s.Bar)
|
|
if bar <= 1 {
|
|
bar = gtx.Dp(defaultBarWidth)
|
|
}
|
|
|
|
var coord int
|
|
if s.Axis == layout.Horizontal {
|
|
coord = gtx.Constraints.Max.X
|
|
} else {
|
|
coord = gtx.Constraints.Max.Y
|
|
}
|
|
|
|
proportion := (s.Ratio + 1) / 2
|
|
firstSize := int(proportion*float32(coord) - float32(bar))
|
|
|
|
secondOffset := firstSize + bar
|
|
secondSize := coord - secondOffset
|
|
|
|
{ // handle input
|
|
// Avoid affecting the input tree with pointer events.
|
|
|
|
for _, ev := range gtx.Events(s) {
|
|
e, ok := ev.(pointer.Event)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
switch e.Type {
|
|
case pointer.Press:
|
|
if s.drag {
|
|
break
|
|
}
|
|
|
|
s.dragID = e.PointerID
|
|
if s.Axis == layout.Horizontal {
|
|
s.dragCoord = e.Position.X
|
|
} else {
|
|
s.dragCoord = e.Position.Y
|
|
}
|
|
s.drag = true
|
|
|
|
case pointer.Drag:
|
|
if s.dragID != e.PointerID {
|
|
break
|
|
}
|
|
|
|
var deltaCoord, deltaRatio float32
|
|
if s.Axis == layout.Horizontal {
|
|
deltaCoord = e.Position.X - s.dragCoord
|
|
s.dragCoord = e.Position.X
|
|
deltaRatio = deltaCoord * 2 / float32(gtx.Constraints.Max.X)
|
|
} else {
|
|
deltaCoord = e.Position.Y - s.dragCoord
|
|
s.dragCoord = e.Position.Y
|
|
deltaRatio = deltaCoord * 2 / float32(gtx.Constraints.Max.Y)
|
|
}
|
|
|
|
s.Ratio += deltaRatio
|
|
|
|
case pointer.Release:
|
|
fallthrough
|
|
case pointer.Cancel:
|
|
s.drag = false
|
|
}
|
|
}
|
|
|
|
low := -1 + float32(bar)/float32(coord)*2
|
|
const snapMargin = 0.1
|
|
|
|
if s.Ratio < low {
|
|
s.Ratio = low
|
|
}
|
|
|
|
if s.Ratio > 1 {
|
|
s.Ratio = 1
|
|
}
|
|
|
|
if s.Ratio < low+snapMargin {
|
|
firstSize = 0
|
|
secondOffset = bar
|
|
secondSize = coord - bar
|
|
} else if s.Ratio > 1-snapMargin {
|
|
firstSize = coord - bar
|
|
secondOffset = coord
|
|
secondSize = 0
|
|
}
|
|
|
|
// register for input
|
|
var barRect image.Rectangle
|
|
if s.Axis == layout.Horizontal {
|
|
barRect = image.Rect(firstSize, 0, secondOffset, gtx.Constraints.Max.Y)
|
|
} else {
|
|
barRect = image.Rect(0, firstSize, gtx.Constraints.Max.X, secondOffset)
|
|
}
|
|
area := clip.Rect(barRect).Push(gtx.Ops)
|
|
pointer.InputOp{Tag: s,
|
|
Types: pointer.Press | pointer.Drag | pointer.Release,
|
|
Grab: s.drag,
|
|
}.Add(gtx.Ops)
|
|
area.Pop()
|
|
}
|
|
|
|
{
|
|
gtx := gtx
|
|
|
|
if s.Axis == layout.Horizontal {
|
|
gtx.Constraints = layout.Exact(image.Pt(firstSize, gtx.Constraints.Max.Y))
|
|
} else {
|
|
gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X, firstSize))
|
|
}
|
|
area := clip.Rect(image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)).Push(gtx.Ops)
|
|
first(gtx)
|
|
area.Pop()
|
|
}
|
|
|
|
{
|
|
gtx := gtx
|
|
|
|
var transform op.TransformStack
|
|
if s.Axis == layout.Horizontal {
|
|
transform = op.Offset(image.Pt(secondOffset, 0)).Push(gtx.Ops)
|
|
gtx.Constraints = layout.Exact(image.Pt(secondSize, gtx.Constraints.Max.Y))
|
|
} else {
|
|
transform = op.Offset(image.Pt(0, secondOffset)).Push(gtx.Ops)
|
|
gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X, secondSize))
|
|
}
|
|
|
|
area := clip.Rect(image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)).Push(gtx.Ops)
|
|
second(gtx)
|
|
area.Pop()
|
|
transform.Pop()
|
|
}
|
|
|
|
return layout.Dimensions{Size: gtx.Constraints.Max}
|
|
}
|