mirror of
https://github.com/vsariola/sointu.git
synced 2025-11-12 21:02:52 -05:00
drafting
This commit is contained in:
parent
0bd652dcbb
commit
bdd729efc1
@ -66,14 +66,10 @@ func (e *Editor) Layout(gtx C, str tracker.String, th *Theme, style *EditorStyle
|
|||||||
// just consume all events if the user did not consume them
|
// just consume all events if the user did not consume them
|
||||||
}
|
}
|
||||||
if e.widgetEditor.Text() != str.Value() {
|
if e.widgetEditor.Text() != str.Value() {
|
||||||
line, col := e.widgetEditor.CaretPos()
|
|
||||||
// if the user has moved the caret, put it in the end
|
|
||||||
e.widgetEditor.SetText(str.Value())
|
e.widgetEditor.SetText(str.Value())
|
||||||
if line > 0 || col > 0 {
|
|
||||||
l := len(e.widgetEditor.Text())
|
l := len(e.widgetEditor.Text())
|
||||||
e.widgetEditor.SetCaret(l, l)
|
e.widgetEditor.SetCaret(l, l)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
me := material.Editor(&th.Material, &e.widgetEditor, hint)
|
me := material.Editor(&th.Material, &e.widgetEditor, hint)
|
||||||
me.Font = style.Font
|
me.Font = style.Font
|
||||||
me.TextSize = style.TextSize
|
me.TextSize = style.TextSize
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
package gioui
|
package gioui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image"
|
||||||
|
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
|
"gioui.org/op/clip"
|
||||||
|
"gioui.org/op/paint"
|
||||||
"gioui.org/text"
|
"gioui.org/text"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
"github.com/vsariola/sointu/tracker"
|
"github.com/vsariola/sointu/tracker"
|
||||||
|
"golang.org/x/exp/shiny/materialdesign/icons"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -14,6 +19,7 @@ type (
|
|||||||
userPresetsBtn *Clickable
|
userPresetsBtn *Clickable
|
||||||
builtinPresetsBtn *Clickable
|
builtinPresetsBtn *Clickable
|
||||||
clearSearchBtn *Clickable
|
clearSearchBtn *Clickable
|
||||||
|
dirBtn *Clickable
|
||||||
dirList *DragList
|
dirList *DragList
|
||||||
resultList *DragList
|
resultList *DragList
|
||||||
}
|
}
|
||||||
@ -21,13 +27,14 @@ type (
|
|||||||
|
|
||||||
func NewInstrumentPresets(m *tracker.Model) *InstrumentPresets {
|
func NewInstrumentPresets(m *tracker.Model) *InstrumentPresets {
|
||||||
return &InstrumentPresets{
|
return &InstrumentPresets{
|
||||||
searchEditor: NewEditor(false, false, text.Start),
|
searchEditor: NewEditor(true, true, text.Start),
|
||||||
gmDlsBtn: new(Clickable),
|
gmDlsBtn: new(Clickable),
|
||||||
clearSearchBtn: new(Clickable),
|
clearSearchBtn: new(Clickable),
|
||||||
userPresetsBtn: new(Clickable),
|
userPresetsBtn: new(Clickable),
|
||||||
builtinPresetsBtn: new(Clickable),
|
builtinPresetsBtn: new(Clickable),
|
||||||
dirList: NewDragList(m.Instruments().List(), layout.Vertical),
|
dirBtn: new(Clickable),
|
||||||
resultList: NewDragList(m.Instruments().List(), layout.Vertical),
|
dirList: NewDragList(m.PresetDirList().List(), layout.Vertical),
|
||||||
|
resultList: NewDragList(m.PresetDirList().List(), layout.Vertical),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,19 +44,67 @@ func (ip *InstrumentPresets) layout(gtx C) D {
|
|||||||
gmDlsBtn := ToggleBtn(tr.NoGmDls(), tr.Theme, ip.gmDlsBtn, "No gm.dls", "Exclude presets using gm.dls")
|
gmDlsBtn := ToggleBtn(tr.NoGmDls(), tr.Theme, ip.gmDlsBtn, "No gm.dls", "Exclude presets using gm.dls")
|
||||||
userPresetsFilterBtn := ToggleBtn(tr.UserPresetFilter(), tr.Theme, ip.userPresetsBtn, "User", "Show only user presets")
|
userPresetsFilterBtn := ToggleBtn(tr.UserPresetFilter(), tr.Theme, ip.userPresetsBtn, "User", "Show only user presets")
|
||||||
builtinPresetsFilterBtn := ToggleBtn(tr.BuiltinPresetsFilter(), tr.Theme, ip.builtinPresetsBtn, "Builtin", "Show only builtin presets")
|
builtinPresetsFilterBtn := ToggleBtn(tr.BuiltinPresetsFilter(), tr.Theme, ip.builtinPresetsBtn, "Builtin", "Show only builtin presets")
|
||||||
|
dirElem := func(gtx C, i int) D {
|
||||||
|
return Label(tr.Theme, &tr.Theme.Dialog.Text, tr.Model.PresetDirList().Value(i)).Layout(gtx)
|
||||||
|
}
|
||||||
|
dirs := func(gtx C) D {
|
||||||
|
return FilledDragList(tr.Theme, ip.dirList).Layout(gtx, dirElem, nil)
|
||||||
|
}
|
||||||
|
bottom := func(gtx C) D {
|
||||||
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||||
|
layout.Rigid(dirs),
|
||||||
|
layout.Rigid(dirs),
|
||||||
|
)
|
||||||
|
}
|
||||||
// layout
|
// layout
|
||||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
return layout.Flex{Axis: layout.Vertical, Alignment: layout.Start, Spacing: 6}.Layout(gtx,
|
||||||
|
layout.Rigid(ip.layoutSearch),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return layout.UniformInset(unit.Dp(4)).Layout(gtx, func(gtx C) D {
|
return layout.UniformInset(unit.Dp(4)).Layout(gtx, func(gtx C) D {
|
||||||
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||||
layout.Flexed(1, func(gtx C) D {
|
|
||||||
return ip.searchEditor.Layout(gtx, tr.Model.PresetSearchString(), tr.Theme, &tr.Theme.InstrumentEditor.InstrumentComment, "Search presets")
|
|
||||||
}),
|
|
||||||
layout.Rigid(userPresetsFilterBtn.Layout),
|
layout.Rigid(userPresetsFilterBtn.Layout),
|
||||||
layout.Rigid(builtinPresetsFilterBtn.Layout),
|
layout.Rigid(builtinPresetsFilterBtn.Layout),
|
||||||
layout.Rigid(gmDlsBtn.Layout),
|
layout.Rigid(gmDlsBtn.Layout),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
layout.Rigid(bottom),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ip *InstrumentPresets) layoutSearch(gtx C) D {
|
||||||
|
// draw search icon on left and clear button on right
|
||||||
|
// return ip.searchEditor.Layout(gtx, tr.Model.PresetSearchString(), tr.Theme, &tr.Theme.InstrumentEditor.InstrumentComment, "Search presets")
|
||||||
|
tr := TrackerFromContext(gtx)
|
||||||
|
bg := func(gtx C) D {
|
||||||
|
rr := gtx.Dp(18)
|
||||||
|
defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops).Pop()
|
||||||
|
paint.Fill(gtx.Ops, tr.Theme.Material.ContrastFg)
|
||||||
|
return D{Size: gtx.Constraints.Min}
|
||||||
|
}
|
||||||
|
// icon, search editor, clear button
|
||||||
|
icon := func(gtx C) D {
|
||||||
|
return tr.Theme.IconButton.Enabled.Inset.Layout(gtx, func(gtx C) D {
|
||||||
|
return tr.Theme.Icon(icons.ActionSearch).Layout(gtx, tr.Theme.Material.Fg)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ed := func(gtx C) D {
|
||||||
|
return ip.searchEditor.Layout(gtx, tr.Model.PresetSearchString(), tr.Theme, &tr.Theme.InstrumentEditor.UnitComment, "Search presets")
|
||||||
|
}
|
||||||
|
clr := func(gtx C) D {
|
||||||
|
btn := ActionIconBtn(tr.ClearPresetSearch(), tr.Theme, ip.clearSearchBtn, icons.ContentClear, "Clear search")
|
||||||
|
return btn.Layout(gtx)
|
||||||
|
}
|
||||||
|
w := func(gtx C) D {
|
||||||
|
gtx.Constraints.Max.X = min(gtx.Dp(360), gtx.Constraints.Max.X)
|
||||||
|
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
||||||
|
layout.Rigid(icon),
|
||||||
|
layout.Flexed(1, ed),
|
||||||
|
layout.Rigid(clr),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return layout.Stack{}.Layout(gtx,
|
||||||
|
layout.Expanded(bg),
|
||||||
|
layout.Stacked(w),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,11 +39,15 @@ type (
|
|||||||
UserPresetsFilter Model
|
UserPresetsFilter Model
|
||||||
PresetDirectory Model
|
PresetDirectory Model
|
||||||
PresetKind Model
|
PresetKind Model
|
||||||
|
ClearPresetSearch Model
|
||||||
|
PresetDirList Model
|
||||||
|
|
||||||
derivedPresetSearch struct {
|
derivedPresetSearch struct {
|
||||||
directory string
|
dirIndex int
|
||||||
noGmDls bool
|
noGmDls bool
|
||||||
kind PresetKindEnum
|
kind PresetKindEnum
|
||||||
|
dirs []string
|
||||||
|
results []int
|
||||||
}
|
}
|
||||||
|
|
||||||
PresetKindEnum int
|
PresetKindEnum int
|
||||||
@ -61,24 +65,23 @@ func (m *Model) updateDerivedPresetSearch() {
|
|||||||
lower := strings.ToLower(search)
|
lower := strings.ToLower(search)
|
||||||
parts := strings.Fields(lower)
|
parts := strings.Fields(lower)
|
||||||
// parse parts to see if they contain :
|
// parse parts to see if they contain :
|
||||||
|
m.derived.presetSearch.dirs = []string{"All"}
|
||||||
m.derived.presetSearch.noGmDls = false
|
m.derived.presetSearch.noGmDls = false
|
||||||
m.derived.presetSearch.directory = ""
|
|
||||||
m.derived.presetSearch.kind = AllPresets
|
m.derived.presetSearch.kind = AllPresets
|
||||||
for _, part := range parts {
|
for _, part := range parts {
|
||||||
if strings.HasPrefix(part, "in:") && len(part) > 3 {
|
if strings.HasPrefix(part, "d:") && len(part) > 3 {
|
||||||
m.derived.presetSearch.directory = strings.TrimSpace(part[3:])
|
dir := strings.TrimSpace(part[3:])
|
||||||
} else if strings.HasPrefix(part, "gmdls:") && len(part) > 6 {
|
ind := slices.IndexFunc(m.derived.presetSearch.dirs, func(c string) bool { return c == dir })
|
||||||
val := strings.TrimSpace(part[6:])
|
m.derived.presetSearch.dirIndex = max(ind, 0)
|
||||||
m.derived.presetSearch.noGmDls = val == "no"
|
} else if strings.HasPrefix(part, "g:n") {
|
||||||
} else if strings.HasPrefix(part, "kind:") && len(part) > 5 {
|
m.derived.presetSearch.noGmDls = true
|
||||||
val := strings.TrimSpace(part[5:])
|
} else if strings.HasPrefix(part, "t:") && len(part) > 2 {
|
||||||
|
val := strings.TrimSpace(part[2:3])
|
||||||
switch val {
|
switch val {
|
||||||
case "builtin":
|
case "b":
|
||||||
m.derived.presetSearch.kind = BuiltinPresets
|
m.derived.presetSearch.kind = BuiltinPresets
|
||||||
case "user":
|
case "u":
|
||||||
m.derived.presetSearch.kind = UserPresets
|
m.derived.presetSearch.kind = UserPresets
|
||||||
default:
|
|
||||||
m.derived.presetSearch.kind = AllPresets
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,9 +104,9 @@ func (m *NoGmDlsFilter) SetValue(val bool) {
|
|||||||
if m.derived.presetSearch.noGmDls == val {
|
if m.derived.presetSearch.noGmDls == val {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m.d.PresetSearchString = removeFilters(m.d.PresetSearchString, "gmdls:")
|
m.d.PresetSearchString = removeFilters(m.d.PresetSearchString, "g:")
|
||||||
if val {
|
if val {
|
||||||
m.d.PresetSearchString = "gmdls:no " + m.d.PresetSearchString
|
m.d.PresetSearchString = "g:n " + m.d.PresetSearchString
|
||||||
}
|
}
|
||||||
(*Model)(m).updateDerivedPresetSearch()
|
(*Model)(m).updateDerivedPresetSearch()
|
||||||
}
|
}
|
||||||
@ -115,9 +118,9 @@ func (m *UserPresetsFilter) SetValue(val bool) {
|
|||||||
if (m.derived.presetSearch.kind == UserPresets) == val {
|
if (m.derived.presetSearch.kind == UserPresets) == val {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m.d.PresetSearchString = removeFilters(m.d.PresetSearchString, "kind:")
|
m.d.PresetSearchString = removeFilters(m.d.PresetSearchString, "t:")
|
||||||
if val {
|
if val {
|
||||||
m.d.PresetSearchString = "kind:user " + m.d.PresetSearchString
|
m.d.PresetSearchString = "t:u " + m.d.PresetSearchString
|
||||||
}
|
}
|
||||||
(*Model)(m).updateDerivedPresetSearch()
|
(*Model)(m).updateDerivedPresetSearch()
|
||||||
}
|
}
|
||||||
@ -129,9 +132,9 @@ func (m *BuiltinPresetsFilter) SetValue(val bool) {
|
|||||||
if (m.derived.presetSearch.kind == BuiltinPresets) == val {
|
if (m.derived.presetSearch.kind == BuiltinPresets) == val {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m.d.PresetSearchString = removeFilters(m.d.PresetSearchString, "kind:")
|
m.d.PresetSearchString = removeFilters(m.d.PresetSearchString, "t:")
|
||||||
if val {
|
if val {
|
||||||
m.d.PresetSearchString = "kind:builtin " + m.d.PresetSearchString
|
m.d.PresetSearchString = "t:b " + m.d.PresetSearchString
|
||||||
}
|
}
|
||||||
(*Model)(m).updateDerivedPresetSearch()
|
(*Model)(m).updateDerivedPresetSearch()
|
||||||
}
|
}
|
||||||
@ -156,6 +159,37 @@ func (m *PresetKind) SetValue(val int) bool {
|
|||||||
func (m *PresetKind) Enabled() bool { return true }
|
func (m *PresetKind) Enabled() bool { return true }
|
||||||
func (m *PresetKind) Range() IntRange { return IntRange{Min: -1, Max: 1} }
|
func (m *PresetKind) Range() IntRange { return IntRange{Min: -1, Max: 1} }
|
||||||
|
|
||||||
|
func (m *Model) ClearPresetSearch() Action { return MakeAction((*ClearPresetSearch)(m)) }
|
||||||
|
func (m *ClearPresetSearch) Enabled() bool { return len(m.d.PresetSearchString) > 0 }
|
||||||
|
func (m *ClearPresetSearch) Do() {
|
||||||
|
m.d.PresetSearchString = ""
|
||||||
|
(*Model)(m).updateDerivedPresetSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) PresetDirList() *PresetDirList { return (*PresetDirList)(m) }
|
||||||
|
func (v *PresetDirList) List() List { return List{v} }
|
||||||
|
func (m *PresetDirList) Count() int { return len(m.derived.presetSearch.dirs) }
|
||||||
|
func (m *PresetDirList) Selected() int { return m.derived.presetSearch.dirIndex }
|
||||||
|
func (m *PresetDirList) Selected2() int { return m.derived.presetSearch.dirIndex }
|
||||||
|
func (m *PresetDirList) SetSelected2(i int) {}
|
||||||
|
func (m *PresetDirList) Value(i int) string {
|
||||||
|
if i < 0 || i >= len(m.derived.presetSearch.dirs) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return m.derived.presetSearch.dirs[i]
|
||||||
|
}
|
||||||
|
func (m *PresetDirList) SetSelected(i int) {
|
||||||
|
i = min(max(i, 0), len(m.derived.presetSearch.dirs)-1)
|
||||||
|
if i < 0 || i >= len(m.derived.presetSearch.dirs) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.d.PresetSearchString = removeFilters(m.d.PresetSearchString, "d:")
|
||||||
|
if i > 0 {
|
||||||
|
m.d.PresetSearchString = "d: " + m.derived.presetSearch.dirs[i] + " " + m.d.PresetSearchString
|
||||||
|
}
|
||||||
|
(*Model)(m).updateDerivedPresetSearch()
|
||||||
|
}
|
||||||
|
|
||||||
func removeFilters(str string, prefix string) string {
|
func removeFilters(str string, prefix string) string {
|
||||||
parts := strings.Fields(str)
|
parts := strings.Fields(str)
|
||||||
newParts := make([]string, 0, len(parts))
|
newParts := make([]string, 0, len(parts))
|
||||||
|
|||||||
Reference in New Issue
Block a user