mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-18 13:04:25 -04:00
feat: embed license in executable and add menu item to show it
This commit is contained in:
parent
6f1db6b392
commit
fb0fa4af92
@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- Help menu, with a menu item to show the license ([#196][i196])
|
||||
- Show CPU load percentage in the song panel ([#192][i192])
|
||||
- Theme can be user configured, in theme.yml. This theme.yml should be placed in
|
||||
the usual sointu config directory (i.e.
|
||||
@ -337,3 +338,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
[i176]: https://github.com/vsariola/sointu/issues/176
|
||||
[i186]: https://github.com/vsariola/sointu/issues/186
|
||||
[i192]: https://github.com/vsariola/sointu/issues/192
|
||||
[i196]: https://github.com/vsariola/sointu/issues/196
|
||||
|
3
LICENSE
3
LICENSE
@ -1,7 +1,8 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Dominik Ries
|
||||
(c) 2020 Veikko Sariola
|
||||
(c) 2020-2025 Veikko Sariola, moitias, qm210, LeStahl,
|
||||
petersalomonsen, anticore
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
4
song.go
4
song.go
@ -1,6 +1,7 @@
|
||||
package sointu
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"errors"
|
||||
)
|
||||
|
||||
@ -92,6 +93,9 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
//go:embed LICENSE
|
||||
var License string
|
||||
|
||||
func (s *Score) SongPos(songRow int) SongPos {
|
||||
if s.RowsPerPattern == 0 {
|
||||
return SongPos{OrderRow: 0, PatternRow: 0}
|
||||
|
@ -92,6 +92,7 @@ type (
|
||||
Item MIDIDevice
|
||||
*Model
|
||||
}
|
||||
ShowLicense Model
|
||||
)
|
||||
|
||||
// Action methods
|
||||
@ -123,6 +124,9 @@ func (a Action) Do() {
|
||||
}
|
||||
|
||||
func (a Action) Enabled() bool {
|
||||
if a.doer == nil {
|
||||
return false // no doer, not allowed
|
||||
}
|
||||
if a.enabler == nil {
|
||||
return true // no enabler, always allowed
|
||||
}
|
||||
@ -588,6 +592,9 @@ func (m *ExportFloat) Do() { m.dialog = ExportFloatExplorer }
|
||||
func (m *Model) ExportInt16() Action { return MakeEnabledAction((*ExportInt16)(m)) }
|
||||
func (m *ExportInt16) Do() { m.dialog = ExportInt16Explorer }
|
||||
|
||||
func (m *Model) ShowLicense() Action { return MakeEnabledAction((*ShowLicense)(m)) }
|
||||
func (m *ShowLicense) Do() { m.dialog = License }
|
||||
|
||||
func (m *Model) SelectMidiInput(item MIDIDevice) Action {
|
||||
return MakeEnabledAction(SelectMidiInput{Item: item, Model: m})
|
||||
}
|
||||
|
@ -92,13 +92,15 @@ func (d *Dialog) handleKeys(gtx C) {
|
||||
for d.BtnCancel.Clicked(gtx) {
|
||||
d.cancel.Do()
|
||||
}
|
||||
if d.alt.Enabled() {
|
||||
if d.alt.Enabled() && d.cancel.Enabled() {
|
||||
d.handleKeysForButton(gtx, &d.BtnAlt, &d.BtnCancel, &d.BtnOk)
|
||||
d.handleKeysForButton(gtx, &d.BtnCancel, &d.BtnOk, &d.BtnAlt)
|
||||
d.handleKeysForButton(gtx, &d.BtnOk, &d.BtnAlt, &d.BtnCancel)
|
||||
} else {
|
||||
} else if d.ok.Enabled() {
|
||||
d.handleKeysForButton(gtx, &d.BtnOk, &d.BtnCancel, &d.BtnCancel)
|
||||
d.handleKeysForButton(gtx, &d.BtnCancel, &d.BtnOk, &d.BtnOk)
|
||||
} else {
|
||||
d.handleKeysForButton(gtx, &d.BtnCancel, &d.BtnCancel, &d.BtnCancel)
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,18 +119,17 @@ func (d *DialogStyle) Layout(gtx C) D {
|
||||
layout.Rigid(Label(d.Theme, &d.Theme.Dialog.Text, d.Text).Layout),
|
||||
layout.Rigid(func(gtx C) D {
|
||||
return layout.E.Layout(gtx, func(gtx C) D {
|
||||
gtx.Constraints.Min.X = gtx.Dp(unit.Dp(120))
|
||||
if d.dialog.alt.Enabled() {
|
||||
return layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceBetween}.Layout(gtx,
|
||||
layout.Rigid(d.OkStyle.Layout),
|
||||
layout.Rigid(d.AltStyle.Layout),
|
||||
layout.Rigid(d.CancelStyle.Layout),
|
||||
)
|
||||
fl := layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceBetween}
|
||||
ok := layout.Rigid(d.OkStyle.Layout)
|
||||
alt := layout.Rigid(d.AltStyle.Layout)
|
||||
cancel := layout.Rigid(d.CancelStyle.Layout)
|
||||
if d.dialog.alt.Enabled() && d.dialog.cancel.Enabled() {
|
||||
return fl.Layout(gtx, ok, alt, cancel)
|
||||
}
|
||||
return layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceBetween}.Layout(gtx,
|
||||
layout.Rigid(d.OkStyle.Layout),
|
||||
layout.Rigid(d.CancelStyle.Layout),
|
||||
)
|
||||
if d.dialog.ok.Enabled() {
|
||||
return fl.Layout(gtx, ok, cancel)
|
||||
}
|
||||
return fl.Layout(gtx, cancel)
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
@ -185,6 +185,8 @@ func (t *Tracker) KeyEvent(e key.Event, gtx C) {
|
||||
t.SplitTrack().Do()
|
||||
case "SplitInstrument":
|
||||
t.SplitInstrument().Do()
|
||||
case "ShowLicense":
|
||||
t.ShowLicense().Do()
|
||||
// Booleans
|
||||
case "PanicToggle":
|
||||
t.Panic().Toggle()
|
||||
|
@ -32,7 +32,6 @@ func (l LabelWidget) Layout(gtx C) D {
|
||||
textColor := textColorMacro.Stop()
|
||||
t := widget.Label{
|
||||
Alignment: l.Alignment,
|
||||
MaxLines: 1,
|
||||
}
|
||||
if l.ShadowColor.A > 0 {
|
||||
shadowColorMacro := op.Record(gtx.Ops)
|
||||
|
@ -307,6 +307,7 @@ type MenuBar struct {
|
||||
fileMenuItems []MenuItem
|
||||
editMenuItems []MenuItem
|
||||
midiMenuItems []MenuItem
|
||||
helpMenuItems []MenuItem
|
||||
|
||||
panicHint string
|
||||
PanicBtn *Clickable
|
||||
@ -314,8 +315,8 @@ type MenuBar struct {
|
||||
|
||||
func NewMenuBar(model *tracker.Model) *MenuBar {
|
||||
ret := &MenuBar{
|
||||
Clickables: make([]Clickable, 3),
|
||||
Menus: make([]Menu, 3),
|
||||
Clickables: make([]Clickable, 4),
|
||||
Menus: make([]Menu, 4),
|
||||
PanicBtn: new(Clickable),
|
||||
panicHint: makeHint("Panic", " (%s)", "PanicToggle"),
|
||||
}
|
||||
@ -341,6 +342,9 @@ func NewMenuBar(model *tracker.Model) *MenuBar {
|
||||
Doer: model.SelectMidiInput(input),
|
||||
})
|
||||
}
|
||||
ret.helpMenuItems = []MenuItem{
|
||||
{IconBytes: icons.ActionCopyright, Text: "License", ShortcutText: keyActionMap["ShowLicense"], Doer: model.ShowLicense()},
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@ -356,11 +360,12 @@ func (t *MenuBar) Layout(gtx C, tr *Tracker) D {
|
||||
fileFC := layout.Rigid(tr.layoutMenu(gtx, "File", &t.Clickables[0], &t.Menus[0], unit.Dp(200), t.fileMenuItems...))
|
||||
editFC := layout.Rigid(tr.layoutMenu(gtx, "Edit", &t.Clickables[1], &t.Menus[1], unit.Dp(200), t.editMenuItems...))
|
||||
midiFC := layout.Rigid(tr.layoutMenu(gtx, "MIDI", &t.Clickables[2], &t.Menus[2], unit.Dp(200), t.midiMenuItems...))
|
||||
helpFC := layout.Rigid(tr.layoutMenu(gtx, "?", &t.Clickables[3], &t.Menus[3], unit.Dp(200), t.helpMenuItems...))
|
||||
panicFC := layout.Flexed(1, func(gtx C) D { return layout.E.Layout(gtx, panicBtn.Layout) })
|
||||
if len(t.midiMenuItems) > 0 {
|
||||
return flex.Layout(gtx, fileFC, editFC, midiFC, panicFC)
|
||||
return flex.Layout(gtx, fileFC, editFC, midiFC, helpFC, panicFC)
|
||||
}
|
||||
return flex.Layout(gtx, fileFC, editFC, panicFC)
|
||||
return flex.Layout(gtx, fileFC, editFC, helpFC, panicFC)
|
||||
}
|
||||
|
||||
type PlayBar struct {
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"gioui.org/op/paint"
|
||||
"gioui.org/text"
|
||||
"gioui.org/x/explorer"
|
||||
"github.com/vsariola/sointu"
|
||||
"github.com/vsariola/sointu/tracker"
|
||||
)
|
||||
|
||||
@ -39,6 +40,7 @@ type (
|
||||
|
||||
SaveChangesDialog *Dialog
|
||||
WaveTypeDialog *Dialog
|
||||
LicenseDialog *Dialog
|
||||
|
||||
ModalDialog layout.Widget
|
||||
InstrumentEditor *InstrumentEditor
|
||||
@ -79,6 +81,7 @@ func NewTracker(model *tracker.Model) *Tracker {
|
||||
|
||||
SaveChangesDialog: NewDialog(model.SaveSong(), model.DiscardSong(), model.Cancel()),
|
||||
WaveTypeDialog: NewDialog(model.ExportInt16(), model.ExportFloat(), model.Cancel()),
|
||||
LicenseDialog: NewDialog(tracker.MakeAction(nil), tracker.MakeAction(nil), model.Cancel()),
|
||||
InstrumentEditor: NewInstrumentEditor(model),
|
||||
OrderEditor: NewOrderEditor(model),
|
||||
TrackEditor: NewNoteEditor(model),
|
||||
@ -291,6 +294,10 @@ func (t *Tracker) showDialog(gtx C) {
|
||||
t.explorerCreateFile(func(wc io.WriteCloser) {
|
||||
t.WriteWav(wc, t.Dialog() == tracker.ExportInt16Explorer)
|
||||
}, filename)
|
||||
case tracker.License:
|
||||
dstyle := ConfirmDialog(gtx, t.Theme, t.LicenseDialog, "License", sointu.License)
|
||||
dstyle.CancelStyle.Text = "Close"
|
||||
dstyle.Layout(gtx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,6 +155,7 @@ const (
|
||||
ExportInt16Explorer
|
||||
QuitChanges
|
||||
QuitSaveExplorer
|
||||
License
|
||||
)
|
||||
|
||||
const maxUndo = 64
|
||||
|
Reference in New Issue
Block a user