mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
feat(tracker): add ability to copy, cut and paste units
This commit is contained in:
parent
338529012a
commit
5a2e87982e
@ -462,7 +462,7 @@ func (ie *InstrumentEditor) layoutInstrumentEditor(gtx C, t *Tracker) D {
|
||||
return layout.Stack{Alignment: layout.SE}.Layout(gtx,
|
||||
layout.Expanded(func(gtx C) D {
|
||||
defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop()
|
||||
key.InputOp{Tag: ie.unitDragList, Keys: "→|⏎|⌫|⌦|⎋|Ctrl-⏎"}.Add(gtx.Ops)
|
||||
key.InputOp{Tag: ie.unitDragList, Keys: "→|⏎|⌫|⌦|⎋|Ctrl-⏎|Ctrl-C|Ctrl-X"}.Add(gtx.Ops)
|
||||
for _, event := range gtx.Events(ie.unitDragList) {
|
||||
switch e := event.(type) {
|
||||
case key.Event:
|
||||
@ -480,6 +480,19 @@ func (ie *InstrumentEditor) layoutInstrumentEditor(gtx C, t *Tracker) D {
|
||||
ie.unitTypeEditor.SetCaret(l, l)
|
||||
case key.NameDeleteForward:
|
||||
t.DeleteUnit(true)
|
||||
case "C":
|
||||
contents, err := yaml.Marshal(t.Unit())
|
||||
if err == nil {
|
||||
clipboard.WriteOp{Text: string(contents)}.Add(gtx.Ops)
|
||||
t.Alert.Update("Unit copied to clipboard", Notify, time.Second*3)
|
||||
}
|
||||
case "X":
|
||||
contents, err := yaml.Marshal(t.Unit())
|
||||
if err == nil {
|
||||
clipboard.WriteOp{Text: string(contents)}.Add(gtx.Ops)
|
||||
t.Alert.Update("Unit cut to clipboard", Notify, time.Second*3)
|
||||
}
|
||||
t.DeleteUnit(true)
|
||||
case key.NameReturn:
|
||||
if e.Modifiers.Contain(key.ModShortcut) {
|
||||
t.AddUnit(true)
|
||||
|
@ -4,7 +4,9 @@ import (
|
||||
"image"
|
||||
"image/color"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gioui.org/io/clipboard"
|
||||
"gioui.org/io/key"
|
||||
"gioui.org/io/pointer"
|
||||
"gioui.org/layout"
|
||||
@ -15,6 +17,7 @@ import (
|
||||
"gioui.org/widget"
|
||||
"github.com/vsariola/sointu/tracker"
|
||||
"golang.org/x/exp/shiny/materialdesign/icons"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type ParamEditor struct {
|
||||
@ -22,6 +25,7 @@ type ParamEditor struct {
|
||||
scrollBar *ScrollBar
|
||||
Parameters []*ParameterWidget
|
||||
DeleteUnitBtn *widget.Clickable
|
||||
CopyUnitBtn *widget.Clickable
|
||||
ClearUnitBtn *widget.Clickable
|
||||
ChooseUnitTypeBtns []*widget.Clickable
|
||||
tag bool
|
||||
@ -41,6 +45,7 @@ func NewParamEditor() *ParamEditor {
|
||||
ret := &ParamEditor{
|
||||
DeleteUnitBtn: new(widget.Clickable),
|
||||
ClearUnitBtn: new(widget.Clickable),
|
||||
CopyUnitBtn: new(widget.Clickable),
|
||||
list: &layout.List{Axis: layout.Vertical},
|
||||
scrollBar: &ScrollBar{Axis: layout.Vertical},
|
||||
}
|
||||
@ -178,6 +183,15 @@ func (pe *ParamEditor) layoutUnitFooter(t *Tracker) layout.Widget {
|
||||
op.InvalidateOp{}.Add(gtx.Ops)
|
||||
t.InstrumentEditor.unitDragList.Focus()
|
||||
}
|
||||
for pe.CopyUnitBtn.Clicked() {
|
||||
op.InvalidateOp{}.Add(gtx.Ops)
|
||||
contents, err := yaml.Marshal(t.Unit())
|
||||
if err == nil {
|
||||
clipboard.WriteOp{Text: string(contents)}.Add(gtx.Ops)
|
||||
t.Alert.Update("Unit copied to clipboard", Notify, time.Second*3)
|
||||
}
|
||||
}
|
||||
copyUnitBtnStyle := IconButton(t.Theme, pe.CopyUnitBtn, icons.ContentContentCopy, true)
|
||||
deleteUnitBtnStyle := IconButton(t.Theme, pe.DeleteUnitBtn, icons.ActionDelete, t.CanDeleteUnit())
|
||||
text := t.Unit().Type
|
||||
if text == "" {
|
||||
@ -188,6 +202,7 @@ func (pe *ParamEditor) layoutUnitFooter(t *Tracker) layout.Widget {
|
||||
hintText := Label(text, white)
|
||||
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
||||
layout.Rigid(deleteUnitBtnStyle.Layout),
|
||||
layout.Rigid(copyUnitBtnStyle.Layout),
|
||||
layout.Rigid(func(gtx C) D {
|
||||
var dims D
|
||||
if t.Unit().Type != "" {
|
||||
|
@ -67,6 +67,15 @@ type Tracker struct {
|
||||
}
|
||||
|
||||
func (t *Tracker) UnmarshalContent(bytes []byte) error {
|
||||
var unit sointu.Unit
|
||||
if errJSON := json.Unmarshal(bytes, &unit); errJSON == nil {
|
||||
t.PasteUnit(unit)
|
||||
return nil
|
||||
}
|
||||
if errYaml := yaml.Unmarshal(bytes, &unit); errYaml == nil {
|
||||
t.PasteUnit(unit)
|
||||
return nil
|
||||
}
|
||||
var instr sointu.Instrument
|
||||
if errJSON := json.Unmarshal(bytes, &instr); errJSON == nil {
|
||||
if t.SetInstrument(instr) {
|
||||
|
@ -641,6 +641,24 @@ func (m *Model) SetUnitType(t string) {
|
||||
m.notifyPatchChange()
|
||||
}
|
||||
|
||||
func (m *Model) PasteUnit(unit sointu.Unit) {
|
||||
m.saveUndo("PasteUnit", 0)
|
||||
newUnits := make([]sointu.Unit, len(m.Instrument().Units)+1)
|
||||
m.unitIndex++
|
||||
copy(newUnits, m.Instrument().Units[:m.unitIndex])
|
||||
copy(newUnits[m.unitIndex+1:], m.Instrument().Units[m.unitIndex:])
|
||||
if _, ok := m.usedIDs[unit.ID]; ok {
|
||||
m.maxID++
|
||||
unit.ID = m.maxID
|
||||
}
|
||||
m.usedIDs[unit.ID] = true
|
||||
newUnits[m.unitIndex] = unit
|
||||
m.song.Patch[m.instrIndex].Units = newUnits
|
||||
m.paramIndex = 0
|
||||
m.clampPositions()
|
||||
m.notifyPatchChange()
|
||||
}
|
||||
|
||||
func (m *Model) SetUnitIndex(value int) {
|
||||
m.unitIndex = value
|
||||
m.paramIndex = 0
|
||||
|
Loading…
Reference in New Issue
Block a user