mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
feat(tracker/gioui): refactor & rework playbar with the play buttons
This commit is contained in:
parent
42c95ab8ee
commit
40be82de46
@ -149,7 +149,7 @@ func (te *NoteEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (te *NoteEditor) layoutButtons(gtx C, t *Tracker) D {
|
func (te *NoteEditor) layoutButtons(gtx C, t *Tracker) D {
|
||||||
return Surface{Gray: 37, Focus: te.scrollTable.Focused() || te.scrollTable.ChildFocused(), FitSize: true}.Layout(gtx, func(gtx C) D {
|
return Surface{Gray: 37, Focus: te.scrollTable.Focused() || te.scrollTable.ChildFocused()}.Layout(gtx, func(gtx C) D {
|
||||||
addSemitoneBtnStyle := ActionButton(gtx, t.Theme, te.AddSemitoneBtn, "+1")
|
addSemitoneBtnStyle := ActionButton(gtx, t.Theme, te.AddSemitoneBtn, "+1")
|
||||||
subtractSemitoneBtnStyle := ActionButton(gtx, t.Theme, te.SubtractSemitoneBtn, "-1")
|
subtractSemitoneBtnStyle := ActionButton(gtx, t.Theme, te.SubtractSemitoneBtn, "-1")
|
||||||
addOctaveBtnStyle := ActionButton(gtx, t.Theme, te.AddOctaveBtn, "+12")
|
addOctaveBtnStyle := ActionButton(gtx, t.Theme, te.AddOctaveBtn, "+12")
|
||||||
@ -240,7 +240,7 @@ func (te *NoteEditor) layoutTracks(gtx C, t *Tracker) D {
|
|||||||
} else if mod(j, beatMarkerDensity) == 0 {
|
} else if mod(j, beatMarkerDensity) == 0 {
|
||||||
paint.FillShape(gtx.Ops, oneBeatHighlight, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op())
|
paint.FillShape(gtx.Ops, oneBeatHighlight, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op())
|
||||||
}
|
}
|
||||||
if t.SongPanel.PlayingBtn.Bool.Value() && j == playSongRow {
|
if t.Model.Playing().Value() && j == playSongRow {
|
||||||
paint.FillShape(gtx.Ops, trackerPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op())
|
paint.FillShape(gtx.Ops, trackerPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op())
|
||||||
}
|
}
|
||||||
return D{}
|
return D{}
|
||||||
|
@ -79,7 +79,7 @@ func (oe *OrderEditor) Layout(gtx C, t *Tracker) D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rowTitleBg := func(gtx C, j int) D {
|
rowTitleBg := func(gtx C, j int) D {
|
||||||
if t.SongPanel.PlayingBtn.Bool.Value() && j == t.PlayPosition().OrderRow {
|
if t.Model.Playing().Value() && j == t.PlayPosition().OrderRow {
|
||||||
paint.FillShape(gtx.Ops, patternPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, gtx.Dp(patternCellHeight))}.Op())
|
paint.FillShape(gtx.Ops, patternPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, gtx.Dp(patternCellHeight))}.Op())
|
||||||
}
|
}
|
||||||
return D{}
|
return D{}
|
||||||
|
@ -23,14 +23,9 @@ type SongPanel struct {
|
|||||||
Step *NumberInput
|
Step *NumberInput
|
||||||
SongLength *NumberInput
|
SongLength *NumberInput
|
||||||
|
|
||||||
RewindBtn *ActionClickable
|
PanicBtn *BoolClickable
|
||||||
PlayingBtn *BoolClickable
|
Scope *Oscilloscope
|
||||||
RecordBtn *BoolClickable
|
PlayBar *PlayBar
|
||||||
FollowBtn *BoolClickable
|
|
||||||
PanicBtn *BoolClickable
|
|
||||||
LoopBtn *BoolClickable
|
|
||||||
|
|
||||||
Scope *Oscilloscope
|
|
||||||
|
|
||||||
// File menu items
|
// File menu items
|
||||||
fileMenuItems []MenuItem
|
fileMenuItems []MenuItem
|
||||||
@ -44,14 +39,7 @@ type SongPanel struct {
|
|||||||
// Edit menu items
|
// Edit menu items
|
||||||
editMenuItems []MenuItem
|
editMenuItems []MenuItem
|
||||||
|
|
||||||
// Hints
|
panicHint string
|
||||||
rewindHint string
|
|
||||||
playHint, stopHint string
|
|
||||||
recordHint, stopRecordHint string
|
|
||||||
followOnHint, followOffHint string
|
|
||||||
panicHint string
|
|
||||||
loopOffHint, loopOnHint string
|
|
||||||
|
|
||||||
// Midi menu items
|
// Midi menu items
|
||||||
midiMenuItems []MenuItem
|
midiMenuItems []MenuItem
|
||||||
}
|
}
|
||||||
@ -66,12 +54,8 @@ func NewSongPanel(model *tracker.Model) *SongPanel {
|
|||||||
Step: NewNumberInput(model.Step().Int()),
|
Step: NewNumberInput(model.Step().Int()),
|
||||||
SongLength: NewNumberInput(model.SongLength().Int()),
|
SongLength: NewNumberInput(model.SongLength().Int()),
|
||||||
PanicBtn: NewBoolClickable(model.Panic().Bool()),
|
PanicBtn: NewBoolClickable(model.Panic().Bool()),
|
||||||
LoopBtn: NewBoolClickable(model.LoopToggle().Bool()),
|
|
||||||
RecordBtn: NewBoolClickable(model.IsRecording().Bool()),
|
|
||||||
FollowBtn: NewBoolClickable(model.Follow().Bool()),
|
|
||||||
PlayingBtn: NewBoolClickable(model.Playing().Bool()),
|
|
||||||
RewindBtn: NewActionClickable(model.PlaySongStart()),
|
|
||||||
Scope: NewOscilloscope(model),
|
Scope: NewOscilloscope(model),
|
||||||
|
PlayBar: NewPlayBar(model),
|
||||||
}
|
}
|
||||||
ret.fileMenuItems = []MenuItem{
|
ret.fileMenuItems = []MenuItem{
|
||||||
{IconBytes: icons.ContentClear, Text: "New Song", ShortcutText: keyActionMap["NewSong"], Doer: model.NewSong()},
|
{IconBytes: icons.ContentClear, Text: "New Song", ShortcutText: keyActionMap["NewSong"], Doer: model.NewSong()},
|
||||||
@ -95,17 +79,7 @@ func NewSongPanel(model *tracker.Model) *SongPanel {
|
|||||||
Doer: model.SelectMidiInput(input),
|
Doer: model.SelectMidiInput(input),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ret.rewindHint = makeHint("Rewind", "\n(%s)", "PlaySongStartUnfollow")
|
|
||||||
ret.playHint = makeHint("Play", " (%s)", "PlayCurrentPosUnfollow")
|
|
||||||
ret.stopHint = makeHint("Stop", " (%s)", "StopPlaying")
|
|
||||||
ret.panicHint = makeHint("Panic", " (%s)", "PanicToggle")
|
ret.panicHint = makeHint("Panic", " (%s)", "PanicToggle")
|
||||||
ret.recordHint = makeHint("Record", " (%s)", "RecordingToggle")
|
|
||||||
ret.stopRecordHint = makeHint("Stop", " (%s)", "RecordingToggle")
|
|
||||||
ret.followOnHint = makeHint("Follow on", " (%s)", "FollowToggle")
|
|
||||||
ret.followOffHint = makeHint("Follow off", " (%s)", "FollowToggle")
|
|
||||||
ret.loopOffHint = makeHint("Loop off", " (%s)", "LoopToggle")
|
|
||||||
ret.loopOnHint = makeHint("Loop on", " (%s)", "LoopToggle")
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,16 +121,22 @@ func (t *SongPanel) layoutMenuBar(gtx C, tr *Tracker) D {
|
|||||||
func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D {
|
func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D {
|
||||||
paint.FillShape(gtx.Ops, songSurfaceColor, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op())
|
paint.FillShape(gtx.Ops, songSurfaceColor, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op())
|
||||||
|
|
||||||
rewindBtnStyle := ActionIcon(gtx, tr.Theme, t.RewindBtn, icons.AVFastRewind, t.rewindHint)
|
|
||||||
playBtnStyle := ToggleIcon(gtx, tr.Theme, t.PlayingBtn, icons.AVPlayArrow, icons.AVStop, t.playHint, t.stopHint)
|
|
||||||
recordBtnStyle := ToggleIcon(gtx, tr.Theme, t.RecordBtn, icons.AVFiberManualRecord, icons.AVFiberSmartRecord, t.recordHint, t.stopRecordHint)
|
|
||||||
noteTrackBtnStyle := ToggleIcon(gtx, tr.Theme, t.FollowBtn, icons.ActionSpeakerNotesOff, icons.ActionSpeakerNotes, t.followOffHint, t.followOnHint)
|
|
||||||
loopBtnStyle := ToggleIcon(gtx, tr.Theme, t.LoopBtn, icons.NavigationArrowForward, icons.AVLoop, t.loopOffHint, t.loopOnHint)
|
|
||||||
|
|
||||||
scopeStyle := LineOscilloscope(t.Scope, tr.SignalAnalyzer().Waveform(), tr.Theme)
|
scopeStyle := LineOscilloscope(t.Scope, tr.SignalAnalyzer().Waveform(), tr.Theme)
|
||||||
|
|
||||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
layout.Rigid(func(gtx C) D {
|
||||||
|
return layout.Background{}.Layout(gtx,
|
||||||
|
func(gtx C) D {
|
||||||
|
// push defer clip op
|
||||||
|
defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)).Push(gtx.Ops).Pop()
|
||||||
|
paint.FillShape(gtx.Ops, songSurfaceColor, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op())
|
||||||
|
return D{Size: image.Pt(gtx.Constraints.Min.X, gtx.Constraints.Min.Y)}
|
||||||
|
},
|
||||||
|
func(gtx C) D {
|
||||||
|
return t.PlayBar.Layout(gtx, tr.Theme)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return layoutSongOptionRow(gtx, tr.Theme, "Song length", NumericUpDown(tr.Theme, t.SongLength, "Song Length").Layout)
|
return layoutSongOptionRow(gtx, tr.Theme, "Song length", NumericUpDown(tr.Theme, t.SongLength, "Song Length").Layout)
|
||||||
}),
|
}),
|
||||||
@ -173,15 +153,6 @@ func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D {
|
|||||||
return layoutSongOptionRow(gtx, tr.Theme, "Cursor step", NumericUpDown(tr.Theme, t.Step, "Cursor step").Layout)
|
return layoutSongOptionRow(gtx, tr.Theme, "Cursor step", NumericUpDown(tr.Theme, t.Step, "Cursor step").Layout)
|
||||||
}),
|
}),
|
||||||
layout.Rigid(VuMeter{Loudness: tr.Model.DetectorResult().Loudness[tracker.LoudnessShortTerm], Peak: tr.Model.DetectorResult().Peaks[tracker.PeakMomentary], Range: 100}.Layout),
|
layout.Rigid(VuMeter{Loudness: tr.Model.DetectorResult().Loudness[tracker.LoudnessShortTerm], Peak: tr.Model.DetectorResult().Peaks[tracker.PeakMomentary], Range: 100}.Layout),
|
||||||
layout.Rigid(func(gtx C) D {
|
|
||||||
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
|
||||||
layout.Rigid(rewindBtnStyle.Layout),
|
|
||||||
layout.Rigid(playBtnStyle.Layout),
|
|
||||||
layout.Rigid(recordBtnStyle.Layout),
|
|
||||||
layout.Rigid(noteTrackBtnStyle.Layout),
|
|
||||||
layout.Rigid(loopBtnStyle.Layout),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
layout.Flexed(1, scopeStyle.Layout),
|
layout.Flexed(1, scopeStyle.Layout),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
labelStyle := LabelStyle{Text: version.VersionOrHash, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, Shaper: tr.Theme.Shaper}
|
labelStyle := LabelStyle{Text: version.VersionOrHash, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, Shaper: tr.Theme.Shaper}
|
||||||
@ -202,3 +173,55 @@ func layoutSongOptionRow(gtx C, th *material.Theme, label string, widget layout.
|
|||||||
layout.Rigid(rightSpacer),
|
layout.Rigid(rightSpacer),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PlayBar struct {
|
||||||
|
RewindBtn *ActionClickable
|
||||||
|
PlayingBtn *BoolClickable
|
||||||
|
RecordBtn *BoolClickable
|
||||||
|
FollowBtn *BoolClickable
|
||||||
|
LoopBtn *BoolClickable
|
||||||
|
// Hints
|
||||||
|
rewindHint string
|
||||||
|
playHint, stopHint string
|
||||||
|
recordHint, stopRecordHint string
|
||||||
|
followOnHint, followOffHint string
|
||||||
|
loopOffHint, loopOnHint string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPlayBar(model *tracker.Model) *PlayBar {
|
||||||
|
ret := &PlayBar{
|
||||||
|
LoopBtn: NewBoolClickable(model.LoopToggle().Bool()),
|
||||||
|
RecordBtn: NewBoolClickable(model.IsRecording().Bool()),
|
||||||
|
FollowBtn: NewBoolClickable(model.Follow().Bool()),
|
||||||
|
PlayingBtn: NewBoolClickable(model.Playing().Bool()),
|
||||||
|
RewindBtn: NewActionClickable(model.PlaySongStart()),
|
||||||
|
}
|
||||||
|
ret.rewindHint = makeHint("Rewind", "\n(%s)", "PlaySongStartUnfollow")
|
||||||
|
ret.playHint = makeHint("Play", " (%s)", "PlayCurrentPosUnfollow")
|
||||||
|
ret.stopHint = makeHint("Stop", " (%s)", "StopPlaying")
|
||||||
|
ret.recordHint = makeHint("Record", " (%s)", "RecordingToggle")
|
||||||
|
ret.stopRecordHint = makeHint("Stop", " (%s)", "RecordingToggle")
|
||||||
|
ret.followOnHint = makeHint("Follow on", " (%s)", "FollowToggle")
|
||||||
|
ret.followOffHint = makeHint("Follow off", " (%s)", "FollowToggle")
|
||||||
|
ret.loopOffHint = makeHint("Loop off", " (%s)", "LoopToggle")
|
||||||
|
ret.loopOnHint = makeHint("Loop on", " (%s)", "LoopToggle")
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pb *PlayBar) Layout(gtx C, th *material.Theme) D {
|
||||||
|
rewindBtnStyle := ActionIcon(gtx, th, pb.RewindBtn, icons.AVFastRewind, pb.rewindHint)
|
||||||
|
playBtnStyle := ToggleIcon(gtx, th, pb.PlayingBtn, icons.AVPlayArrow, icons.AVStop, pb.playHint, pb.stopHint)
|
||||||
|
recordBtnStyle := ToggleIcon(gtx, th, pb.RecordBtn, icons.AVFiberManualRecord, icons.AVFiberSmartRecord, pb.recordHint, pb.stopRecordHint)
|
||||||
|
noteTrackBtnStyle := ToggleIcon(gtx, th, pb.FollowBtn, icons.ActionSpeakerNotesOff, icons.ActionSpeakerNotes, pb.followOffHint, pb.followOnHint)
|
||||||
|
loopBtnStyle := ToggleIcon(gtx, th, pb.LoopBtn, icons.NavigationArrowForward, icons.AVLoop, pb.loopOffHint, pb.loopOnHint)
|
||||||
|
|
||||||
|
return Surface{Gray: 37}.Layout(gtx, func(gtx C) D {
|
||||||
|
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
||||||
|
layout.Flexed(1, playBtnStyle.Layout),
|
||||||
|
layout.Rigid(rewindBtnStyle.Layout),
|
||||||
|
layout.Rigid(recordBtnStyle.Layout),
|
||||||
|
layout.Rigid(noteTrackBtnStyle.Layout),
|
||||||
|
layout.Rigid(loopBtnStyle.Layout),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -4,52 +4,39 @@ import (
|
|||||||
"image/color"
|
"image/color"
|
||||||
|
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op"
|
|
||||||
"gioui.org/op/clip"
|
"gioui.org/op/clip"
|
||||||
"gioui.org/op/paint"
|
"gioui.org/op/paint"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Surface struct {
|
type Surface struct {
|
||||||
Gray int
|
Gray int
|
||||||
Inset layout.Inset
|
Inset layout.Inset
|
||||||
FitSize bool
|
Focus bool
|
||||||
Focus bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Surface) Layout(gtx C, widget layout.Widget) D {
|
func (s Surface) Layout(gtx C, widget layout.Widget) D {
|
||||||
bg := func(gtx C) D {
|
return layout.Background{}.Layout(gtx,
|
||||||
grayInt := s.Gray
|
func(gtx C) D {
|
||||||
if s.Focus {
|
grayInt := s.Gray
|
||||||
grayInt += 8
|
if s.Focus {
|
||||||
}
|
grayInt += 8
|
||||||
var grayUint8 uint8
|
}
|
||||||
if grayInt < 0 {
|
var grayUint8 uint8
|
||||||
grayUint8 = 0
|
if grayInt < 0 {
|
||||||
} else if grayInt > 255 {
|
grayUint8 = 0
|
||||||
grayUint8 = 255
|
} else if grayInt > 255 {
|
||||||
} else {
|
grayUint8 = 255
|
||||||
grayUint8 = uint8(grayInt)
|
} else {
|
||||||
}
|
grayUint8 = uint8(grayInt)
|
||||||
color := color.NRGBA{R: grayUint8, G: grayUint8, B: grayUint8, A: 255}
|
}
|
||||||
paint.FillShape(gtx.Ops, color, clip.Rect{
|
color := color.NRGBA{R: grayUint8, G: grayUint8, B: grayUint8, A: 255}
|
||||||
Max: gtx.Constraints.Min,
|
paint.FillShape(gtx.Ops, color, clip.Rect{
|
||||||
}.Op())
|
Max: gtx.Constraints.Min,
|
||||||
return D{Size: gtx.Constraints.Min}
|
}.Op())
|
||||||
}
|
return D{Size: gtx.Constraints.Min}
|
||||||
fg := func(gtx C) D {
|
},
|
||||||
return s.Inset.Layout(gtx, widget)
|
func(gtx C) D {
|
||||||
}
|
return s.Inset.Layout(gtx, widget)
|
||||||
if s.FitSize {
|
},
|
||||||
macro := op.Record(gtx.Ops)
|
)
|
||||||
dims := fg(gtx)
|
|
||||||
call := macro.Stop()
|
|
||||||
gtx.Constraints = layout.Exact(dims.Size)
|
|
||||||
bg(gtx)
|
|
||||||
call.Add(gtx.Ops)
|
|
||||||
return dims
|
|
||||||
}
|
|
||||||
gtxbg := gtx
|
|
||||||
gtxbg.Constraints.Min = gtxbg.Constraints.Max
|
|
||||||
bg(gtxbg)
|
|
||||||
return fg(gtx)
|
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ var loopMarkerColor = color.NRGBA{R: 252, G: 186, B: 3, A: 255}
|
|||||||
var instrumentHoverColor = color.NRGBA{R: 30, G: 31, B: 38, A: 255}
|
var instrumentHoverColor = color.NRGBA{R: 30, G: 31, B: 38, A: 255}
|
||||||
var instrumentNameHintColor = color.NRGBA{R: 200, G: 200, B: 200, A: 255}
|
var instrumentNameHintColor = color.NRGBA{R: 200, G: 200, B: 200, A: 255}
|
||||||
|
|
||||||
var songSurfaceColor = color.NRGBA{R: 37, G: 37, B: 38, A: 255}
|
var songSurfaceColor = color.NRGBA{R: 24, G: 24, B: 24, A: 255}
|
||||||
|
|
||||||
var popupSurfaceColor = color.NRGBA{R: 50, G: 50, B: 51, A: 255}
|
var popupSurfaceColor = color.NRGBA{R: 50, G: 50, B: 51, A: 255}
|
||||||
var popupShadowColor = color.NRGBA{R: 0, G: 0, B: 0, A: 192}
|
var popupShadowColor = color.NRGBA{R: 0, G: 0, B: 0, A: 192}
|
||||||
|
@ -146,7 +146,7 @@ func (t *Tracker) Main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
gtx := app.NewContext(&ops, e)
|
gtx := app.NewContext(&ops, e)
|
||||||
if t.SongPanel.PlayingBtn.Bool.Value() && t.SongPanel.FollowBtn.Bool.Value() {
|
if t.Playing().Value() && t.Follow().Value() {
|
||||||
t.TrackEditor.scrollTable.RowTitleList.CenterOn(t.PlaySongRow())
|
t.TrackEditor.scrollTable.RowTitleList.CenterOn(t.PlaySongRow())
|
||||||
}
|
}
|
||||||
t.Layout(gtx, w)
|
t.Layout(gtx, w)
|
||||||
|
Loading…
Reference in New Issue
Block a user