mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
feat(tracker/gioui): preferences.yml for window size or maximized (#185)
This commit is contained in:
parent
4169356845
commit
7ff3c942cb
@ -26,6 +26,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
([#77][i77])
|
([#77][i77])
|
||||||
- User can define own keybindings in `os.UserConfigDir()/sointu/keybindings.yml`
|
- User can define own keybindings in `os.UserConfigDir()/sointu/keybindings.yml`
|
||||||
([#94][i94], [#151][i151])
|
([#94][i94], [#151][i151])
|
||||||
|
- User can define preferred window size in
|
||||||
|
`os.UserConfigDir()/sointu/preferences.yml` ([#184][i184])
|
||||||
- A small number above the instrument name identifies the MIDI channel /
|
- A small number above the instrument name identifies the MIDI channel /
|
||||||
instrument number, with numbering starting from 1 ([#154][i154])
|
instrument number, with numbering starting from 1 ([#154][i154])
|
||||||
- The filter unit frequency parameter is displayed in Hz, corresponding roughly
|
- The filter unit frequency parameter is displayed in Hz, corresponding roughly
|
||||||
|
@ -3,8 +3,6 @@ package gioui
|
|||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -28,16 +26,7 @@ var keyActionMap = map[KeyAction]string{} // holds an informative string of the
|
|||||||
|
|
||||||
func loadCustomKeyBindings() []KeyBinding {
|
func loadCustomKeyBindings() []KeyBinding {
|
||||||
var keyBindings []KeyBinding
|
var keyBindings []KeyBinding
|
||||||
configDir, err := os.UserConfigDir()
|
_, err := ReadCustomConfigYml("keybindings.yml", &keyBindings)
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
path := filepath.Join(configDir, "sointu", "keybindings.yml")
|
|
||||||
bytes, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err = yaml.Unmarshal(bytes, &keyBindings)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
65
tracker/gioui/preferences.go
Normal file
65
tracker/gioui/preferences.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package gioui
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
"gioui.org/unit"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Preferences struct {
|
||||||
|
Window WindowPreferences
|
||||||
|
YmlError error
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowPreferences struct {
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
Maximized bool `yaml:",omitempty"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed preferences.yml
|
||||||
|
var defaultPreferencesYaml []byte
|
||||||
|
|
||||||
|
func loadDefaultPreferences() Preferences {
|
||||||
|
var preferences Preferences
|
||||||
|
err := yaml.Unmarshal(defaultPreferencesYaml, &preferences)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("failed to unmarshal preferences: %w", err))
|
||||||
|
}
|
||||||
|
return preferences
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadCustomConfigYml modifies the target argument, i.e. needs a pointer
|
||||||
|
func ReadCustomConfigYml(filename string, target interface{}) (exists bool, err error) {
|
||||||
|
configDir, err := os.UserConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
path := filepath.Join(configDir, "sointu", filename)
|
||||||
|
bytes, err2 := os.ReadFile(path)
|
||||||
|
if err2 != nil {
|
||||||
|
return false, err2
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal(bytes, target)
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakePreferences() Preferences {
|
||||||
|
preferences := loadDefaultPreferences()
|
||||||
|
exists, err := ReadCustomConfigYml("preferences.yml", &preferences)
|
||||||
|
if exists {
|
||||||
|
preferences.YmlError = err
|
||||||
|
}
|
||||||
|
return preferences
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Preferences) WindowSize() (unit.Dp, unit.Dp) {
|
||||||
|
return unit.Dp(p.Window.Width), unit.Dp(p.Window.Height)
|
||||||
|
}
|
4
tracker/gioui/preferences.yml
Normal file
4
tracker/gioui/preferences.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
window:
|
||||||
|
width: 800
|
||||||
|
height: 600
|
||||||
|
maximized: false
|
@ -18,7 +18,6 @@ import (
|
|||||||
"gioui.org/op/clip"
|
"gioui.org/op/clip"
|
||||||
"gioui.org/op/paint"
|
"gioui.org/op/paint"
|
||||||
"gioui.org/text"
|
"gioui.org/text"
|
||||||
"gioui.org/unit"
|
|
||||||
"gioui.org/widget/material"
|
"gioui.org/widget/material"
|
||||||
"gioui.org/x/explorer"
|
"gioui.org/x/explorer"
|
||||||
"github.com/vsariola/sointu/tracker"
|
"github.com/vsariola/sointu/tracker"
|
||||||
@ -51,8 +50,9 @@ type (
|
|||||||
|
|
||||||
filePathString tracker.String
|
filePathString tracker.String
|
||||||
|
|
||||||
quitWG sync.WaitGroup
|
quitWG sync.WaitGroup
|
||||||
execChan chan func()
|
execChan chan func()
|
||||||
|
preferences Preferences
|
||||||
|
|
||||||
*tracker.Model
|
*tracker.Model
|
||||||
}
|
}
|
||||||
@ -89,9 +89,16 @@ func NewTracker(model *tracker.Model) *Tracker {
|
|||||||
Model: model,
|
Model: model,
|
||||||
|
|
||||||
filePathString: model.FilePath().String(),
|
filePathString: model.FilePath().String(),
|
||||||
|
preferences: MakePreferences(),
|
||||||
}
|
}
|
||||||
t.Theme.Shaper = text.NewShaper(text.WithCollection(fontCollection))
|
t.Theme.Shaper = text.NewShaper(text.WithCollection(fontCollection))
|
||||||
t.PopupAlert = NewPopupAlert(model.Alerts(), t.Theme.Shaper)
|
t.PopupAlert = NewPopupAlert(model.Alerts(), t.Theme.Shaper)
|
||||||
|
if t.preferences.YmlError != nil {
|
||||||
|
model.Alerts().Add(
|
||||||
|
fmt.Sprintf("Preferences YML Error: %s", t.preferences.YmlError),
|
||||||
|
tracker.Warning,
|
||||||
|
)
|
||||||
|
}
|
||||||
t.Theme.Palette.Fg = primaryColor
|
t.Theme.Palette.Fg = primaryColor
|
||||||
t.Theme.Palette.ContrastFg = black
|
t.Theme.Palette.ContrastFg = black
|
||||||
t.TrackEditor.scrollTable.Focus()
|
t.TrackEditor.scrollTable.Focus()
|
||||||
@ -101,9 +108,7 @@ func NewTracker(model *tracker.Model) *Tracker {
|
|||||||
|
|
||||||
func (t *Tracker) Main() {
|
func (t *Tracker) Main() {
|
||||||
titleFooter := ""
|
titleFooter := ""
|
||||||
w := new(app.Window)
|
w := t.newWindow()
|
||||||
w.Option(app.Title("Sointu Tracker"))
|
|
||||||
w.Option(app.Size(unit.Dp(800), unit.Dp(600)))
|
|
||||||
t.InstrumentEditor.Focus()
|
t.InstrumentEditor.Focus()
|
||||||
recoveryTicker := time.NewTicker(time.Second * 30)
|
recoveryTicker := time.NewTicker(time.Second * 30)
|
||||||
t.Explorer = explorer.NewExplorer(w)
|
t.Explorer = explorer.NewExplorer(w)
|
||||||
@ -127,9 +132,7 @@ func (t *Tracker) Main() {
|
|||||||
}
|
}
|
||||||
if !t.Quitted() {
|
if !t.Quitted() {
|
||||||
// TODO: uh oh, there's no way of canceling the destroyevent in gioui? so we create a new window just to show the dialog
|
// TODO: uh oh, there's no way of canceling the destroyevent in gioui? so we create a new window just to show the dialog
|
||||||
w = new(app.Window)
|
w = t.newWindow()
|
||||||
w.Option(app.Title("Sointu Tracker"))
|
|
||||||
w.Option(app.Size(unit.Dp(800), unit.Dp(600)))
|
|
||||||
t.Explorer = explorer.NewExplorer(w)
|
t.Explorer = explorer.NewExplorer(w)
|
||||||
go eventLoop(w, events, acks)
|
go eventLoop(w, events, acks)
|
||||||
}
|
}
|
||||||
@ -165,6 +168,16 @@ func (t *Tracker) Main() {
|
|||||||
t.quitWG.Done()
|
t.quitWG.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tracker) newWindow() *app.Window {
|
||||||
|
w := new(app.Window)
|
||||||
|
w.Option(app.Title("Sointu Tracker"))
|
||||||
|
w.Option(app.Size(t.preferences.WindowSize()))
|
||||||
|
if t.preferences.Window.Maximized {
|
||||||
|
w.Option(app.Maximized.Option())
|
||||||
|
}
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
func eventLoop(w *app.Window, events chan<- event.Event, acks <-chan struct{}) {
|
func eventLoop(w *app.Window, events chan<- event.Event, acks <-chan struct{}) {
|
||||||
// Iterate window events, sending each to the old event loop and waiting for
|
// Iterate window events, sending each to the old event loop and waiting for
|
||||||
// a signal that processing is complete before iterating again.
|
// a signal that processing is complete before iterating again.
|
||||||
|
Loading…
Reference in New Issue
Block a user