mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-20 05:54:34 -04:00
refactor(tracker/gioui): separate SplitStyle from SplitState
This commit is contained in:
parent
ba281ca7c0
commit
e59fbb50cf
@ -11,83 +11,29 @@ import (
|
|||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Split struct {
|
type (
|
||||||
// Ratio keeps the current layout.
|
SplitState struct {
|
||||||
// 0 is center, -1 completely to the left, 1 completely to the right.
|
// Ratio keeps the current layout.
|
||||||
Ratio float32
|
// 0 is center, -1 completely to the left, 1 completely to the right.
|
||||||
// Bar is the width for resizing the layout
|
Ratio float32
|
||||||
Bar unit.Dp
|
// Axis is the split direction: layout.Horizontal splits the view in left
|
||||||
// Axis is the split direction: layout.Horizontal splits the view in left
|
// and right, layout.Vertical splits the view in top and bottom
|
||||||
// and right, layout.Vertical splits the view in top and bottom
|
Axis layout.Axis
|
||||||
Axis layout.Axis
|
drag bool
|
||||||
// Minimum sizes of the first and second widget in the split, in dp
|
dragID pointer.ID
|
||||||
MinSize1, MinSize2 unit.Dp
|
dragCoord float32
|
||||||
|
|
||||||
drag bool
|
|
||||||
dragID pointer.ID
|
|
||||||
dragCoord float32
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultBarWidth = unit.Dp(10)
|
|
||||||
|
|
||||||
func (s *Split) Update(gtx layout.Context) {
|
|
||||||
for {
|
|
||||||
ev, ok := gtx.Event(pointer.Filter{
|
|
||||||
Target: s,
|
|
||||||
Kinds: pointer.Press | pointer.Drag | pointer.Release,
|
|
||||||
// TODO: there should be a grab; there was Grab: s.drag,
|
|
||||||
})
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
e, ok := ev.(pointer.Event)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch e.Kind {
|
|
||||||
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
|
|
||||||
// when the user start dragging, the new display ratio becomes the underlying ratio
|
|
||||||
s.Ratio = s.calculateRatio(gtx)
|
|
||||||
|
|
||||||
case pointer.Drag:
|
|
||||||
if s.dragID != e.PointerID {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.Axis == layout.Horizontal {
|
|
||||||
s.Ratio += (e.Position.X - s.dragCoord) / float32(gtx.Constraints.Max.X) * 2
|
|
||||||
s.dragCoord = e.Position.X
|
|
||||||
} else {
|
|
||||||
s.Ratio += (e.Position.Y - s.dragCoord) / float32(gtx.Constraints.Max.Y) * 2
|
|
||||||
s.dragCoord = e.Position.Y
|
|
||||||
}
|
|
||||||
|
|
||||||
case pointer.Release, pointer.Cancel:
|
|
||||||
if s.dragID == e.PointerID {
|
|
||||||
// when the user release the grab, the new display ratio becomes the underlying ratio
|
|
||||||
s.Ratio = s.calculateRatio(gtx)
|
|
||||||
}
|
|
||||||
s.drag = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Split) Layout(gtx layout.Context, first, second layout.Widget) layout.Dimensions {
|
SplitStyle struct {
|
||||||
s.Update(gtx)
|
Bar unit.Dp
|
||||||
|
MinSize1, MinSize2 unit.Dp
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
size1, size2, bar := s.calculateSplitSizes(gtx)
|
func (s *SplitState) Layout(gtx layout.Context, st *SplitStyle, first, second layout.Widget) layout.Dimensions {
|
||||||
|
s.update(gtx, st)
|
||||||
|
|
||||||
|
size1, size2, bar := s.calculateSplitSizes(gtx, st)
|
||||||
secondOffset := size1 + bar
|
secondOffset := size1 + bar
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -142,8 +88,62 @@ func (s *Split) Layout(gtx layout.Context, first, second layout.Widget) layout.D
|
|||||||
return layout.Dimensions{Size: gtx.Constraints.Max}
|
return layout.Dimensions{Size: gtx.Constraints.Max}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Split) calculateRatio(gtx layout.Context) float32 {
|
func (s *SplitState) update(gtx layout.Context, st *SplitStyle) {
|
||||||
size1, size2, bar := s.calculateSplitSizes(gtx)
|
for {
|
||||||
|
ev, ok := gtx.Event(pointer.Filter{
|
||||||
|
Target: s,
|
||||||
|
Kinds: pointer.Press | pointer.Drag | pointer.Release,
|
||||||
|
// TODO: there should be a grab; there was Grab: s.drag,
|
||||||
|
})
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
e, ok := ev.(pointer.Event)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch e.Kind {
|
||||||
|
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
|
||||||
|
// when the user start dragging, the new display ratio becomes the underlying ratio
|
||||||
|
s.Ratio = s.calculateRatio(gtx, st)
|
||||||
|
|
||||||
|
case pointer.Drag:
|
||||||
|
if s.dragID != e.PointerID {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Axis == layout.Horizontal {
|
||||||
|
s.Ratio += (e.Position.X - s.dragCoord) / float32(gtx.Constraints.Max.X) * 2
|
||||||
|
s.dragCoord = e.Position.X
|
||||||
|
} else {
|
||||||
|
s.Ratio += (e.Position.Y - s.dragCoord) / float32(gtx.Constraints.Max.Y) * 2
|
||||||
|
s.dragCoord = e.Position.Y
|
||||||
|
}
|
||||||
|
|
||||||
|
case pointer.Release, pointer.Cancel:
|
||||||
|
if s.dragID == e.PointerID {
|
||||||
|
// when the user release the grab, the new display ratio becomes the underlying ratio
|
||||||
|
s.Ratio = s.calculateRatio(gtx, st)
|
||||||
|
}
|
||||||
|
s.drag = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SplitState) calculateRatio(gtx layout.Context, st *SplitStyle) float32 {
|
||||||
|
size1, size2, bar := s.calculateSplitSizes(gtx, st)
|
||||||
total := size1 + size2 + bar
|
total := size1 + size2 + bar
|
||||||
if total <= 0 {
|
if total <= 0 {
|
||||||
return 0
|
return 0
|
||||||
@ -151,10 +151,10 @@ func (s *Split) calculateRatio(gtx layout.Context) float32 {
|
|||||||
return 2*float32(size1+bar/2)/float32(total) - 1
|
return 2*float32(size1+bar/2)/float32(total) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Split) calculateSplitSizes(gtx layout.Context) (size1, size2, bar int) {
|
func (s *SplitState) calculateSplitSizes(gtx layout.Context, st *SplitStyle) (size1, size2, bar int) {
|
||||||
bar = gtx.Dp(s.Bar)
|
bar = gtx.Dp(st.Bar)
|
||||||
if bar <= 1 {
|
if bar <= 1 {
|
||||||
bar = gtx.Dp(defaultBarWidth)
|
bar = gtx.Dp(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
total := gtx.Constraints.Max.Y
|
total := gtx.Constraints.Max.Y
|
||||||
@ -169,8 +169,8 @@ func (s *Split) calculateSplitSizes(gtx layout.Context) (size1, size2, bar int)
|
|||||||
}
|
}
|
||||||
totalSize := total - bar
|
totalSize := total - bar
|
||||||
size1 = int((s.Ratio+1)/2*float32(total) - float32(bar)/2)
|
size1 = int((s.Ratio+1)/2*float32(total) - float32(bar)/2)
|
||||||
minSize1 := gtx.Dp(s.MinSize1)
|
minSize1 := gtx.Dp(st.MinSize1)
|
||||||
minSize2 := gtx.Dp(s.MinSize2)
|
minSize2 := gtx.Dp(st.MinSize2)
|
||||||
|
|
||||||
// we always hide the smaller split first
|
// we always hide the smaller split first
|
||||||
if s.Ratio < 0 {
|
if s.Ratio < 0 {
|
||||||
|
@ -100,6 +100,7 @@ type Theme struct {
|
|||||||
Menu PopupStyle
|
Menu PopupStyle
|
||||||
Dialog PopupStyle
|
Dialog PopupStyle
|
||||||
}
|
}
|
||||||
|
Split SplitStyle
|
||||||
ScrollBar ScrollBarStyle
|
ScrollBar ScrollBarStyle
|
||||||
|
|
||||||
// iconCache is used to cache the icons created from iconvg data
|
// iconCache is used to cache the icons created from iconvg data
|
||||||
|
@ -210,3 +210,4 @@ dialog:
|
|||||||
titleinset: { top: 12, left: 20, right: 20 }
|
titleinset: { top: 12, left: 20, right: 20 }
|
||||||
textinset: { top: 12, bottom: 12, left: 20, right: 20 }
|
textinset: { top: 12, bottom: 12, left: 20, right: 20 }
|
||||||
buttons: *textbutton
|
buttons: *textbutton
|
||||||
|
split: { bar: 10, minsize1: 180, minsize2: 180 }
|
||||||
|
@ -33,9 +33,9 @@ type (
|
|||||||
Theme *Theme
|
Theme *Theme
|
||||||
OctaveNumberInput *NumericUpDownState
|
OctaveNumberInput *NumericUpDownState
|
||||||
InstrumentVoices *NumericUpDownState
|
InstrumentVoices *NumericUpDownState
|
||||||
TopHorizontalSplit *Split
|
TopHorizontalSplit *SplitState
|
||||||
BottomHorizontalSplit *Split
|
BottomHorizontalSplit *SplitState
|
||||||
VerticalSplit *Split
|
VerticalSplit *SplitState
|
||||||
KeyNoteMap Keyboard[key.Name]
|
KeyNoteMap Keyboard[key.Name]
|
||||||
PopupAlert *AlertsState
|
PopupAlert *AlertsState
|
||||||
Zoom int
|
Zoom int
|
||||||
@ -79,9 +79,9 @@ func NewTracker(model *tracker.Model) *Tracker {
|
|||||||
OctaveNumberInput: NewNumericUpDownState(),
|
OctaveNumberInput: NewNumericUpDownState(),
|
||||||
InstrumentVoices: NewNumericUpDownState(),
|
InstrumentVoices: NewNumericUpDownState(),
|
||||||
|
|
||||||
TopHorizontalSplit: &Split{Ratio: -.5, MinSize1: 180, MinSize2: 180},
|
TopHorizontalSplit: &SplitState{Ratio: -.5},
|
||||||
BottomHorizontalSplit: &Split{Ratio: -.6, MinSize1: 180, MinSize2: 180},
|
BottomHorizontalSplit: &SplitState{Ratio: -.6},
|
||||||
VerticalSplit: &Split{Axis: layout.Vertical, MinSize1: 180, MinSize2: 180},
|
VerticalSplit: &SplitState{Axis: layout.Vertical},
|
||||||
|
|
||||||
DialogState: new(DialogState),
|
DialogState: new(DialogState),
|
||||||
InstrumentEditor: NewInstrumentEditor(model),
|
InstrumentEditor: NewInstrumentEditor(model),
|
||||||
@ -219,6 +219,7 @@ func (t *Tracker) Layout(gtx layout.Context, w *app.Window) {
|
|||||||
t.layoutTop(gtx)
|
t.layoutTop(gtx)
|
||||||
} else {
|
} else {
|
||||||
t.VerticalSplit.Layout(gtx,
|
t.VerticalSplit.Layout(gtx,
|
||||||
|
&t.Theme.Split,
|
||||||
t.layoutTop,
|
t.layoutTop,
|
||||||
t.layoutBottom)
|
t.layoutBottom)
|
||||||
}
|
}
|
||||||
@ -341,6 +342,7 @@ func (t *Tracker) explorerCreateFile(success func(io.WriteCloser), filename stri
|
|||||||
|
|
||||||
func (t *Tracker) layoutBottom(gtx layout.Context) layout.Dimensions {
|
func (t *Tracker) layoutBottom(gtx layout.Context) layout.Dimensions {
|
||||||
return t.BottomHorizontalSplit.Layout(gtx,
|
return t.BottomHorizontalSplit.Layout(gtx,
|
||||||
|
&t.Theme.Split,
|
||||||
func(gtx C) D {
|
func(gtx C) D {
|
||||||
return t.OrderEditor.Layout(gtx, t)
|
return t.OrderEditor.Layout(gtx, t)
|
||||||
},
|
},
|
||||||
@ -352,6 +354,7 @@ func (t *Tracker) layoutBottom(gtx layout.Context) layout.Dimensions {
|
|||||||
|
|
||||||
func (t *Tracker) layoutTop(gtx layout.Context) layout.Dimensions {
|
func (t *Tracker) layoutTop(gtx layout.Context) layout.Dimensions {
|
||||||
return t.TopHorizontalSplit.Layout(gtx,
|
return t.TopHorizontalSplit.Layout(gtx,
|
||||||
|
&t.Theme.Split,
|
||||||
func(gtx C) D {
|
func(gtx C) D {
|
||||||
return t.SongPanel.Layout(gtx, t)
|
return t.SongPanel.Layout(gtx, t)
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user