refactor(tracker/gioui): update gioui to newer version

This commit is contained in:
5684185+vsariola@users.noreply.github.com 2023-07-07 17:56:09 +03:00
parent f5980ecb79
commit 8c4f7ee61f
25 changed files with 457 additions and 402 deletions

20
go.mod
View File

@ -3,30 +3,36 @@ module github.com/vsariola/sointu
go 1.17 go 1.17
require ( require (
gioui.org v0.0.0-20210410094005-495c69018772 gioui.org v0.1.0
gioui.org/x v0.0.0-20210419013052-6db76265c4e1 gioui.org/x v0.1.0
github.com/Masterminds/sprig v2.22.0+incompatible github.com/Masterminds/sprig v2.22.0+incompatible
github.com/hajimehoshi/oto v0.6.6 github.com/hajimehoshi/oto v0.6.6
golang.org/x/exp v0.0.0-20201229011636-eab1b5eb1a03 golang.org/x/exp/shiny v0.0.0-20220827204233-334a2380cb91
gopkg.in/yaml.v2 v2.3.0 gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
pipelined.dev/audio/vst2 v0.10.1-0.20230513073541-08ee2a4520cb pipelined.dev/audio/vst2 v0.10.1-0.20230513073541-08ee2a4520cb
) )
require ( require (
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 // indirect
gioui.org/shader v1.0.6 // indirect
git.wow.st/gmp/jni v0.0.0-20210610011705-34026c7e22d0 // indirect
github.com/Masterminds/goutils v1.1.0 // indirect github.com/Masterminds/goutils v1.1.0 // indirect
github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/semver v1.5.0 // indirect
github.com/go-text/typesetting v0.0.0-20230602202114-9797aefac433 // indirect
github.com/godbus/dbus/v5 v5.0.6 // indirect
github.com/google/uuid v1.1.2 // indirect github.com/google/uuid v1.1.2 // indirect
github.com/huandu/xstrings v1.3.2 // indirect github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.11 // indirect github.com/imdario/mergo v0.3.11 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/stretchr/testify v1.6.1 // indirect github.com/stretchr/testify v1.6.1 // indirect
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 // indirect golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 // indirect
golang.org/x/image v0.7.0 // indirect
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f // indirect golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f // indirect
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197 // indirect golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.3.4 // indirect golang.org/x/text v0.9.0 // indirect
pipelined.dev/pipe v0.11.0 // indirect pipelined.dev/pipe v0.11.0 // indirect
pipelined.dev/signal v0.10.0 // indirect pipelined.dev/signal v0.10.0 // indirect
) )

73
go.sum
View File

@ -1,10 +1,21 @@
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
eliasnaur.com/font v0.0.0-20230308162249-dd43949cb42d h1:ARo7NCVvN2NdhLlJE9xAbKweuI9L6UgfTbYb0YwPacY=
eliasnaur.com/font v0.0.0-20230308162249-dd43949cb42d/go.mod h1:OYVuxibdk9OSLX8vAqydtRPP87PyTFcT9uH3MlEGBQA=
gioui.org v0.0.0-20210402191542-ce7f0da06ee3/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= gioui.org v0.0.0-20210402191542-ce7f0da06ee3/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
gioui.org v0.0.0-20210410094005-495c69018772 h1:QpGMsubuP4JVlZj5VvvFfRikbLDN0QJj71oX9ABeaqM= gioui.org v0.1.0 h1:fEDY5A4+epOdzjCBYSUC4BzvjWqsjfqf5D6mskbthOs=
gioui.org v0.0.0-20210410094005-495c69018772/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= gioui.org v0.1.0/go.mod h1:a3hz8FyrPMkt899D9YrxMGtyRzpPrJpz1Lzbssn81vI=
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJGFDjINIPi1jtO6pc=
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
gioui.org/shader v1.0.6 h1:cvZmU+eODFR2545X+/8XucgZdTtEjR3QWW6W65b0q5Y=
gioui.org/shader v1.0.6/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM=
gioui.org/x v0.0.0-20210419013052-6db76265c4e1 h1:NfHFIxNzNY/s7ePtrf9nCKr9f3gYiVS40rAIdbj5Q1k= gioui.org/x v0.0.0-20210419013052-6db76265c4e1 h1:NfHFIxNzNY/s7ePtrf9nCKr9f3gYiVS40rAIdbj5Q1k=
gioui.org/x v0.0.0-20210419013052-6db76265c4e1/go.mod h1:qsAS5EBzGhn3sJ98FJdA+ae+E5/DgmxjySERjjR1Zvg= gioui.org/x v0.0.0-20210419013052-6db76265c4e1/go.mod h1:qsAS5EBzGhn3sJ98FJdA+ae+E5/DgmxjySERjjR1Zvg=
gioui.org/x v0.1.0 h1:CvphvaQSroRaNEZ+JbXBkV3J3klA76U3JpieyEwHFX4=
gioui.org/x v0.1.0/go.mod h1:5qZxjtK/TVznMlcEOyn8OheiCZlArxF3IKnLqSehKXQ=
git.wow.st/gmp/jni v0.0.0-20210610011705-34026c7e22d0 h1:bGG/g4ypjrCJoSvFrP5hafr9PPB5aw8SjcOWWila7ZI=
git.wow.st/gmp/jni v0.0.0-20210610011705-34026c7e22d0/go.mod h1:+axXBRUTIDlCeE73IKeD/os7LoEnTKdkp8/gQOFjqyo=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
@ -16,6 +27,13 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-text/typesetting v0.0.0-20230602202114-9797aefac433 h1:Pdyvqsfi1QYgFfZa4R8otBOtgO+CGyBDMEG8cM3jwvE=
github.com/go-text/typesetting v0.0.0-20230602202114-9797aefac433/go.mod h1:KmrpWuSMFcO2yjmyhGpnBGQHSKAoEgMTSSzvLDzCuEA=
github.com/go-text/typesetting-utils v0.0.0-20230412163830-89e4bcfa3ecc h1:9Kf84pnrmmjdRzZIkomfjowmGUhHs20jkrWYw/I6CYc=
github.com/go-text/typesetting-utils v0.0.0-20230412163830-89e4bcfa3ecc/go.mod h1:RaqFwjcYyM5BjbYGwON0H5K0UqwO3sJlo9ukKha80ZE=
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hajimehoshi/oto v0.6.6 h1:HYSZ8cYZqOL4iHugvbcfhNN2smiSOsBMaoSBi4nnWcw= github.com/hajimehoshi/oto v0.6.6 h1:HYSZ8cYZqOL4iHugvbcfhNN2smiSOsBMaoSBi4nnWcw=
@ -24,6 +42,7 @@ github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/jezek/xgb v1.0.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
@ -33,20 +52,29 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE=
golang.org/x/exp v0.0.0-20201229011636-eab1b5eb1a03 h1:XlAInxBYX5nBofPaY51uv/x9xmRgZGr/lDOsePd2AcE=
golang.org/x/exp v0.0.0-20201229011636-eab1b5eb1a03/go.mod h1:I6l2HNBLBZEcrOoCpyKLdY2lHoRZ8lI4x60KMCQDft4= golang.org/x/exp v0.0.0-20201229011636-eab1b5eb1a03/go.mod h1:I6l2HNBLBZEcrOoCpyKLdY2lHoRZ8lI4x60KMCQDft4=
golang.org/x/exp v0.0.0-20221012211006-4de253d81b95 h1:sBdrWpxhGDdTAYNqbgBLAR+ULAPPhfgncLr1X0lyWtg=
golang.org/x/exp v0.0.0-20221012211006-4de253d81b95/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/exp/shiny v0.0.0-20220827204233-334a2380cb91 h1:ryT6Nf0R83ZgD8WnFFdfI8wCeyqgdXWN4+CkFVNPAT0=
golang.org/x/exp/shiny v0.0.0-20220827204233-334a2380cb91/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.3.0/go.mod h1:fXd9211C/0VTlYuAcOhW8dY/RtEJqODXOWBDpmYBf+A=
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw=
golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@ -56,26 +84,53 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197 h1:7+SpRyhoo46QjKkYInQXpcfxx3TYFEYkn131lwGE9/0= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
@ -85,10 +140,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
pipelined.dev/audio/vst2 v0.10.0 h1:exmszZmQ2KZeqfXnxqrQ2UsLexaz9B5WZHE2Kbbd/mg=
pipelined.dev/audio/vst2 v0.10.0/go.mod h1:wETLxsbBPftj6t4iVBCXvH/Xgd27ZgIC4hNnHDYNuz8=
pipelined.dev/audio/vst2 v0.10.1-0.20230501210043-10b5e35ddc62 h1:cDF8OupcD4iSldxY1j5kbMsXtBzrQ9ODJM7tnCzyul8=
pipelined.dev/audio/vst2 v0.10.1-0.20230501210043-10b5e35ddc62/go.mod h1:wETLxsbBPftj6t4iVBCXvH/Xgd27ZgIC4hNnHDYNuz8=
pipelined.dev/audio/vst2 v0.10.1-0.20230513073541-08ee2a4520cb h1:KupwowSEQavEdUQfZc3TKGzls96Dax1eva/0sBfdqHQ= pipelined.dev/audio/vst2 v0.10.1-0.20230513073541-08ee2a4520cb h1:KupwowSEQavEdUQfZc3TKGzls96Dax1eva/0sBfdqHQ=
pipelined.dev/audio/vst2 v0.10.1-0.20230513073541-08ee2a4520cb/go.mod h1:wETLxsbBPftj6t4iVBCXvH/Xgd27ZgIC4hNnHDYNuz8= pipelined.dev/audio/vst2 v0.10.1-0.20230513073541-08ee2a4520cb/go.mod h1:wETLxsbBPftj6t4iVBCXvH/Xgd27ZgIC4hNnHDYNuz8=
pipelined.dev/pipe v0.10.0/go.mod h1:aIt+NPlW0QLYByqYniG77lTxSvl7OtCNLws/m+Xz5ww= pipelined.dev/pipe v0.10.0/go.mod h1:aIt+NPlW0QLYByqYniG77lTxSvl7OtCNLws/m+Xz5ww=

View File

@ -1,10 +1,10 @@
package gioui package gioui
import ( import (
"image"
"image/color" "image/color"
"time" "time"
"gioui.org/f32"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op"
"gioui.org/op/clip" "gioui.org/op/clip"
@ -94,10 +94,10 @@ func (a *Alert) Layout(gtx C) D {
}.Op()) }.Op())
return D{Size: gtx.Constraints.Min} return D{Size: gtx.Constraints.Min}
} }
labelStyle := LabelStyle{Text: a.showMessage, Color: textColor, ShadeColor: shadeColor, Font: labelDefaultFont, Alignment: layout.Center, FontSize: unit.Dp(16)} labelStyle := LabelStyle{Text: a.showMessage, Color: textColor, ShadeColor: shadeColor, Font: labelDefaultFont, Alignment: layout.Center, FontSize: unit.Sp(16)}
return alertMargin.Layout(gtx, func(gtx C) D { return alertMargin.Layout(gtx, func(gtx C) D {
return layout.S.Layout(gtx, func(gtx C) D { return layout.S.Layout(gtx, func(gtx C) D {
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
gtx.Constraints.Min.X = gtx.Constraints.Max.X gtx.Constraints.Min.X = gtx.Constraints.Max.X
recording := op.Record(gtx.Ops) recording := op.Record(gtx.Ops)
dims := layout.Stack{Alignment: layout.Center}.Layout(gtx, dims := layout.Stack{Alignment: layout.Center}.Layout(gtx,
@ -107,8 +107,8 @@ func (a *Alert) Layout(gtx C) D {
}), }),
) )
macro := recording.Stop() macro := recording.Stop()
totalY := dims.Size.Y + gtx.Px(alertMargin.Bottom) totalY := dims.Size.Y + gtx.Dp(alertMargin.Bottom)
op.Offset(f32.Pt(0, float32((1-a.pos)*float64(totalY)))).Add((gtx.Ops)) op.Offset(image.Point{0, int((1 - a.pos) * float64(totalY))}).Add((gtx.Ops))
macro.Add(gtx.Ops) macro.Add(gtx.Ops)
return dims return dims
}) })

View File

@ -8,7 +8,7 @@ import (
) )
func IconButton(th *material.Theme, w *widget.Clickable, icon []byte, enabled bool) material.IconButtonStyle { func IconButton(th *material.Theme, w *widget.Clickable, icon []byte, enabled bool) material.IconButtonStyle {
ret := material.IconButton(th, w, widgetForIcon(icon)) ret := material.IconButton(th, w, widgetForIcon(icon), "")
ret.Background = transparent ret.Background = transparent
ret.Inset = layout.UniformInset(unit.Dp(6)) ret.Inset = layout.UniformInset(unit.Dp(6))
if enabled { if enabled {

View File

@ -46,7 +46,7 @@ func (d *DialogStyle) Layout(gtx C) D {
return layout.Flex{Axis: layout.Vertical, Alignment: layout.Middle}.Layout(gtx, return layout.Flex{Axis: layout.Vertical, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(Label(d.Text, highEmphasisTextColor)), layout.Rigid(Label(d.Text, highEmphasisTextColor)),
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
gtx.Constraints.Min.X = gtx.Px(unit.Dp(120)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(120))
if d.ShowAlt { if d.ShowAlt {
return layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceBetween}.Layout(gtx, return layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceBetween}.Layout(gtx,
layout.Rigid(d.OkStyle.Layout), layout.Rigid(d.OkStyle.Layout),

View File

@ -59,7 +59,13 @@ func (d *DragList) Focused() bool {
func (s *FilledDragListStyle) Layout(gtx C) D { func (s *FilledDragListStyle) Layout(gtx C) D {
swap := 0 swap := 0
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop()
keys := key.Set("↑|↓|Ctrl-↑|Ctrl-↓")
if s.dragList.List.Axis == layout.Horizontal {
keys = key.Set("←|→|Ctrl-←|Ctrl-→")
}
key.InputOp{Tag: &s.dragList.mainTag, Keys: keys}.Add(gtx.Ops)
if s.dragList.List.Axis == layout.Horizontal { if s.dragList.List.Axis == layout.Horizontal {
gtx.Constraints.Min.X = gtx.Constraints.Max.X gtx.Constraints.Min.X = gtx.Constraints.Max.X
@ -121,7 +127,7 @@ func (s *FilledDragListStyle) Layout(gtx C) D {
} }
inputFg := func(gtx C) D { inputFg := func(gtx C) D {
defer op.Save(gtx.Ops).Load() //defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
for _, ev := range gtx.Events(&s.dragList.tags[index]) { for _, ev := range gtx.Events(&s.dragList.tags[index]) {
e, ok := ev.(pointer.Event) e, ok := ev.(pointer.Event)
if !ok { if !ok {
@ -143,12 +149,13 @@ func (s *FilledDragListStyle) Layout(gtx C) D {
} }
} }
rect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y) rect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)
pointer.Rect(rect).Add(gtx.Ops) area := clip.Rect(rect).Push(gtx.Ops)
pointer.InputOp{Tag: &s.dragList.tags[index], pointer.InputOp{Tag: &s.dragList.tags[index],
Types: pointer.Press | pointer.Enter | pointer.Leave, Types: pointer.Press | pointer.Enter | pointer.Leave,
}.Add(gtx.Ops) }.Add(gtx.Ops)
area.Pop()
if index == s.dragList.SelectedItem { if index == s.dragList.SelectedItem {
for _, ev := range gtx.Events(s.dragList) { for _, ev := range gtx.Events(&s.dragList.focused) {
e, ok := ev.(pointer.Event) e, ok := ev.(pointer.Event)
if !ok { if !ok {
continue continue
@ -156,6 +163,7 @@ func (s *FilledDragListStyle) Layout(gtx C) D {
switch e.Type { switch e.Type {
case pointer.Press: case pointer.Press:
s.dragList.dragID = e.PointerID s.dragList.dragID = e.PointerID
s.dragList.drag = true
case pointer.Drag: case pointer.Drag:
if s.dragList.dragID != e.PointerID { if s.dragList.dragID != e.PointerID {
break break
@ -181,22 +189,24 @@ func (s *FilledDragListStyle) Layout(gtx C) D {
s.dragList.drag = false s.dragList.drag = false
} }
} }
pointer.InputOp{Tag: s.dragList, area := clip.Rect(rect).Push(gtx.Ops)
pointer.InputOp{Tag: &s.dragList.focused,
Types: pointer.Drag | pointer.Press | pointer.Release, Types: pointer.Drag | pointer.Press | pointer.Release,
Grab: s.dragList.drag, Grab: s.dragList.drag,
}.Add(gtx.Ops) }.Add(gtx.Ops)
pointer.CursorNameOp{Name: pointer.CursorGrab}.Add(gtx.Ops) pointer.CursorGrab.Add(gtx.Ops)
area.Pop()
} }
return layout.Dimensions{Size: gtx.Constraints.Min} return layout.Dimensions{Size: gtx.Constraints.Min}
} }
return layout.Stack{Alignment: layout.W}.Layout(gtx, return layout.Stack{Alignment: layout.W}.Layout(gtx,
layout.Expanded(bg), layout.Expanded(bg),
layout.Expanded(inputFg),
layout.Stacked(func(gtx C) D { layout.Stacked(func(gtx C) D {
return s.element(gtx, index) return s.element(gtx, index)
}), }),
layout.Expanded(inputFg)) )
} }
key.InputOp{Tag: &s.dragList.mainTag}.Add(gtx.Ops)
dims := s.dragList.List.Layout(gtx, s.Count, listElem) dims := s.dragList.List.Layout(gtx, s.Count, listElem)
if !s.dragList.swapped && swap != 0 && s.dragList.SelectedItem+swap >= 0 && s.dragList.SelectedItem+swap < s.Count { if !s.dragList.swapped && swap != 0 && s.dragList.SelectedItem+swap >= 0 && s.dragList.SelectedItem+swap < s.Count {
s.swap(s.dragList.SelectedItem, s.dragList.SelectedItem+swap) s.swap(s.dragList.SelectedItem, s.dragList.SelectedItem+swap)

View File

@ -8,6 +8,7 @@ import (
"gioui.org/io/pointer" "gioui.org/io/pointer"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op/clip"
"gioui.org/op/paint" "gioui.org/op/paint"
"gioui.org/unit" "gioui.org/unit"
"gioui.org/widget" "gioui.org/widget"
@ -77,7 +78,7 @@ func commonFileDialog(th *material.Theme, f *FileDialog) FileDialogStyle {
DirEditorStyle: material.Editor(th, &f.Directory, "Directory"), DirEditorStyle: material.Editor(th, &f.Directory, "Directory"),
FileNameStyle: material.Editor(th, &f.FileName, "Filename"), FileNameStyle: material.Editor(th, &f.FileName, "Filename"),
CancelStyle: LowEmphasisButton(th, &f.BtnCancel, "Cancel"), CancelStyle: LowEmphasisButton(th, &f.BtnCancel, "Cancel"),
UseAltExtStyle: material.Switch(th, &f.UseAltExt), UseAltExtStyle: material.Switch(th, &f.UseAltExt, "Change extension"),
} }
ret.UseAltExtStyle.Color.Enabled = white ret.UseAltExtStyle.Color.Enabled = white
ret.UseAltExtStyle.Color.Disabled = white ret.UseAltExtStyle.Color.Disabled = white
@ -174,11 +175,9 @@ func (f *FileDialogStyle) Layout(gtx C) D {
var text string var text string
if index < len(subDirs) { if index < len(subDirs) {
icon = widgetForIcon(icons.FileFolder) icon = widgetForIcon(icons.FileFolder)
icon.Color = primaryColor
text = subDirs[index] text = subDirs[index]
} else { } else {
icon = widgetForIcon(icons.EditorInsertDriveFile) icon = widgetForIcon(icons.EditorInsertDriveFile)
icon.Color = primaryColor
text = files[index-len(subDirs)] text = files[index-len(subDirs)]
} }
labelColor := highEmphasisTextColor labelColor := highEmphasisTextColor
@ -189,17 +188,20 @@ func (f *FileDialogStyle) Layout(gtx C) D {
layout.Stacked(func(gtx C) D { layout.Stacked(func(gtx C) D {
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
return icon.Layout(gtx, unit.Dp(24)) p := gtx.Dp(unit.Dp(24))
gtx.Constraints.Min = image.Pt(p, p)
return icon.Layout(gtx, primaryColor)
}), }),
layout.Rigid(Label(text, labelColor)), layout.Rigid(Label(text, labelColor)),
) )
}), }),
layout.Expanded(func(gtx C) D { layout.Expanded(func(gtx C) D {
rect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y) rect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)
pointer.Rect(rect).Add(gtx.Ops) area := clip.Rect(rect).Push(gtx.Ops)
pointer.InputOp{Tag: &f.dialog.tags[index], pointer.InputOp{Tag: &f.dialog.tags[index],
Types: pointer.Press | pointer.Drag | pointer.Release, Types: pointer.Press | pointer.Drag | pointer.Release,
}.Add(gtx.Ops) }.Add(gtx.Ops)
area.Pop()
return D{} return D{}
}), }),
) )
@ -215,14 +217,14 @@ func (f *FileDialogStyle) Layout(gtx C) D {
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(f.FolderUpStyle.Layout), layout.Rigid(f.FolderUpStyle.Layout),
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
return D{Size: image.Pt(gtx.Px(unit.Dp(6)), gtx.Px(unit.Dp(36)))} return D{Size: image.Pt(gtx.Dp(unit.Dp(6)), gtx.Dp(unit.Dp(36)))}
}), }),
layout.Rigid(f.DirEditorStyle.Layout)) layout.Rigid(f.DirEditorStyle.Layout))
}), }),
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
return layout.Stack{Alignment: layout.NE}.Layout(gtx, return layout.Stack{Alignment: layout.NE}.Layout(gtx,
layout.Stacked(func(gtx C) D { layout.Stacked(func(gtx C) D {
gtx.Constraints = layout.Exact(image.Pt(gtx.Px(unit.Dp(600)), gtx.Px(unit.Dp(400)))) gtx.Constraints = layout.Exact(image.Pt(gtx.Dp(unit.Dp(600)), gtx.Dp(unit.Dp(400))))
if listLen > 0 { if listLen > 0 {
return f.dialog.FileList.Layout(gtx, listLen, listElement) return f.dialog.FileList.Layout(gtx, listLen, listElement)
} else { } else {
@ -235,11 +237,11 @@ func (f *FileDialogStyle) Layout(gtx C) D {
) )
}), }),
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(36)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(36))
return layout.W.Layout(gtx, f.FileNameStyle.Layout) return layout.W.Layout(gtx, f.FileNameStyle.Layout)
}), }),
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
gtx.Constraints = layout.Exact(image.Pt(gtx.Px(unit.Dp(600)), gtx.Px(unit.Dp(36)))) gtx.Constraints = layout.Exact(image.Pt(gtx.Dp(unit.Dp(600)), gtx.Dp(unit.Dp(36))))
if f.ExtAlt != "" { if f.ExtAlt != "" {
mainLabelColor := disabledTextColor mainLabelColor := disabledTextColor
altLabelColor := disabledTextColor altLabelColor := disabledTextColor

View File

@ -13,6 +13,7 @@ import (
"gioui.org/io/pointer" "gioui.org/io/pointer"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op"
"gioui.org/op/clip"
"gioui.org/text" "gioui.org/text"
"gioui.org/unit" "gioui.org/unit"
"gioui.org/widget" "gioui.org/widget"
@ -96,10 +97,11 @@ func (ie *InstrumentEditor) Layout(gtx C, t *Tracker) D {
} }
} }
rect := image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y) rect := image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)
pointer.Rect(rect).Add(gtx.Ops) area := clip.Rect(rect).Push(gtx.Ops)
pointer.InputOp{Tag: &ie.tag, pointer.InputOp{Tag: &ie.tag,
Types: pointer.Press, Types: pointer.Press,
}.Add(gtx.Ops) }.Add(gtx.Ops)
area.Pop()
var icon []byte var icon []byte
if t.InstrEnlarged() { if t.InstrEnlarged() {
@ -118,8 +120,8 @@ func (ie *InstrumentEditor) Layout(gtx C, t *Tracker) D {
in := layout.UniformInset(unit.Dp(1)) in := layout.UniformInset(unit.Dp(1))
t.OctaveNumberInput.Value = t.Octave() t.OctaveNumberInput.Value = t.Octave()
numStyle := NumericUpDown(t.Theme, t.OctaveNumberInput, 0, 9) numStyle := NumericUpDown(t.Theme, t.OctaveNumberInput, 0, 9)
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(20))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(70))
dims := in.Layout(gtx, numStyle.Layout) dims := in.Layout(gtx, numStyle.Layout)
t.SetOctave(t.OctaveNumberInput.Value) t.SetOctave(t.OctaveNumberInput.Value)
return dims return dims
@ -185,8 +187,8 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D {
maxRemain := t.MaxInstrumentVoices() maxRemain := t.MaxInstrumentVoices()
t.InstrumentVoices.Value = t.Instrument().NumVoices t.InstrumentVoices.Value = t.Instrument().NumVoices
numStyle := NumericUpDown(t.Theme, t.InstrumentVoices, 0, maxRemain) numStyle := NumericUpDown(t.Theme, t.InstrumentVoices, 0, maxRemain)
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(20))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(70))
dims := numStyle.Layout(gtx) dims := numStyle.Layout(gtx)
t.SetInstrumentVoices(t.InstrumentVoices.Value) t.SetInstrumentVoices(t.InstrumentVoices.Value)
return dims return dims
@ -267,8 +269,8 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D {
func (ie *InstrumentEditor) layoutInstrumentNames(gtx C, t *Tracker) D { func (ie *InstrumentEditor) layoutInstrumentNames(gtx C, t *Tracker) D {
element := func(gtx C, i int) D { element := func(gtx C, i int) D {
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(36)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(36))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(30)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(30))
grabhandle := LabelStyle{Text: "", ShadeColor: black, Color: white, FontSize: unit.Sp(10), Alignment: layout.Center} grabhandle := LabelStyle{Text: "", ShadeColor: black, Color: white, FontSize: unit.Sp(10), Alignment: layout.Center}
if i == t.InstrIndex() { if i == t.InstrIndex() {
grabhandle.Text = ":::" grabhandle.Text = ":::"
@ -303,7 +305,7 @@ func (ie *InstrumentEditor) layoutInstrumentNames(gtx C, t *Tracker) D {
editor := material.Editor(t.Theme, ie.nameEditor, "Instr") editor := material.Editor(t.Theme, ie.nameEditor, "Instr")
editor.Color = color editor.Color = color
editor.HintColor = instrumentNameHintColor editor.HintColor = instrumentNameHintColor
editor.TextSize = unit.Dp(12) editor.TextSize = unit.Sp(12)
dims := layout.Center.Layout(gtx, editor.Layout) dims := layout.Center.Layout(gtx, editor.Layout)
t.SetInstrumentName(ie.nameEditor.Text()) t.SetInstrumentName(ie.nameEditor.Text())
return dims return dims
@ -332,34 +334,27 @@ func (ie *InstrumentEditor) layoutInstrumentNames(gtx C, t *Tracker) D {
instrumentList.HoverColor = instrumentHoverColor instrumentList.HoverColor = instrumentHoverColor
ie.instrumentDragList.SelectedItem = t.InstrIndex() ie.instrumentDragList.SelectedItem = t.InstrIndex()
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
pointer.PassOp{Pass: true}.Add(gtx.Ops) defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop()
spy, spiedGtx := eventx.Enspy(gtx) key.InputOp{Tag: ie.instrumentDragList, Keys: "↓"}.Add(gtx.Ops)
dims := instrumentList.Layout(spiedGtx)
for _, group := range spy.AllEvents() { for _, event := range gtx.Events(ie.instrumentDragList) {
for _, event := range group.Items { switch e := event.(type) {
switch e := event.(type) { case key.Event:
case key.Event: switch e.State {
if e.Modifiers.Contain(key.ModShortcut) { case key.Press:
continue switch e.Name {
} case key.NameDownArrow:
if !ie.nameEditor.Focused() { ie.unitDragList.Focus()
switch e.State { case key.NameReturn, key.NameEnter:
case key.Press: ie.nameEditor.Focus()
switch e.Name {
case key.NameDownArrow:
ie.unitDragList.Focus()
case key.NameReturn, key.NameEnter:
ie.nameEditor.Focus()
}
t.JammingPressed(e)
case key.Release:
t.JammingReleased(e)
}
} }
} }
} }
} }
dims := instrumentList.Layout(gtx)
if t.InstrIndex() != ie.instrumentDragList.SelectedItem { if t.InstrIndex() != ie.instrumentDragList.SelectedItem {
t.SetInstrIndex(ie.instrumentDragList.SelectedItem) t.SetInstrIndex(ie.instrumentDragList.SelectedItem)
op.InvalidateOp{}.Add(gtx.Ops) op.InvalidateOp{}.Add(gtx.Ops)
@ -371,7 +366,7 @@ func (ie *InstrumentEditor) layoutInstrumentEditor(gtx C, t *Tracker) D {
t.AddUnit(true) t.AddUnit(true)
ie.unitDragList.Focus() ie.unitDragList.Focus()
} }
addUnitBtnStyle := material.IconButton(t.Theme, ie.addUnitBtn, widgetForIcon(icons.ContentAdd)) addUnitBtnStyle := material.IconButton(t.Theme, ie.addUnitBtn, widgetForIcon(icons.ContentAdd), "Add unit")
addUnitBtnStyle.Color = t.Theme.ContrastFg addUnitBtnStyle.Color = t.Theme.ContrastFg
addUnitBtnStyle.Background = t.Theme.Fg addUnitBtnStyle.Background = t.Theme.Fg
addUnitBtnStyle.Inset = layout.UniformInset(unit.Dp(4)) addUnitBtnStyle.Inset = layout.UniformInset(unit.Dp(4))
@ -388,7 +383,7 @@ func (ie *InstrumentEditor) layoutInstrumentEditor(gtx C, t *Tracker) D {
} }
element := func(gtx C, i int) D { element := func(gtx C, i int) D {
gtx.Constraints = layout.Exact(image.Pt(gtx.Px(unit.Dp(120)), gtx.Px(unit.Dp(20)))) gtx.Constraints = layout.Exact(image.Pt(gtx.Dp(unit.Dp(120)), gtx.Dp(unit.Dp(20))))
u := units[i] u := units[i]
var color color.NRGBA = white var color color.NRGBA = white
@ -439,21 +434,7 @@ func (ie *InstrumentEditor) layoutInstrumentEditor(gtx C, t *Tracker) D {
editor.HintColor = instrumentNameHintColor editor.HintColor = instrumentNameHintColor
editor.TextSize = unit.Sp(12) editor.TextSize = unit.Sp(12)
editor.Font = labelDefaultFont editor.Font = labelDefaultFont
unitName = func(gtx C) D { unitName = editor.Layout
spy, spiedGtx := eventx.Enspy(gtx)
ret := editor.Layout(spiedGtx)
for _, group := range spy.AllEvents() {
for _, event := range group.Items {
switch e := event.(type) {
case key.Event:
if e.Name == key.NameEscape {
ie.unitDragList.Focus()
}
}
}
}
return ret
}
} else { } else {
unitNameLabel := LabelStyle{Text: u.Type, ShadeColor: black, Color: color, Font: labelDefaultFont, FontSize: unit.Sp(12)} unitNameLabel := LabelStyle{Text: u.Type, ShadeColor: black, Color: color, Font: labelDefaultFont, FontSize: unit.Sp(12)}
if unitNameLabel.Text == "" { if unitNameLabel.Text == "" {
@ -472,8 +453,7 @@ func (ie *InstrumentEditor) layoutInstrumentEditor(gtx C, t *Tracker) D {
) )
} }
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
pointer.PassOp{Pass: true}.Add(gtx.Ops)
unitList := FilledDragList(t.Theme, ie.unitDragList, len(units), element, t.SwapUnits) unitList := FilledDragList(t.Theme, ie.unitDragList, len(units), element, t.SwapUnits)
ie.unitDragList.SelectedItem = t.UnitIndex() ie.unitDragList.SelectedItem = t.UnitIndex()
return Surface{Gray: 30, Focus: ie.wasFocused}.Layout(gtx, func(gtx C) D { return Surface{Gray: 30, Focus: ie.wasFocused}.Layout(gtx, func(gtx C) D {
@ -481,53 +461,44 @@ func (ie *InstrumentEditor) layoutInstrumentEditor(gtx C, t *Tracker) D {
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
return layout.Stack{Alignment: layout.SE}.Layout(gtx, return layout.Stack{Alignment: layout.SE}.Layout(gtx,
layout.Expanded(func(gtx C) D { layout.Expanded(func(gtx C) D {
spy, spiedGtx := eventx.Enspy(gtx) defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop()
dims := unitList.Layout(spiedGtx) key.InputOp{Tag: ie.unitDragList, Keys: "→|⏎|⌫|⌦|⎋|Ctrl-⏎"}.Add(gtx.Ops)
prevUnitIndex := t.UnitIndex() for _, event := range gtx.Events(ie.unitDragList) {
if t.UnitIndex() != ie.unitDragList.SelectedItem { switch e := event.(type) {
t.SetUnitIndex(ie.unitDragList.SelectedItem) case key.Event:
ie.unitTypeEditor.SetText(t.Unit().Type) switch e.State {
} case key.Press:
if ie.unitDragList.Focused() { switch e.Name {
for _, group := range spy.AllEvents() { case key.NameEscape:
for _, event := range group.Items { ie.instrumentDragList.Focus()
switch e := event.(type) { case key.NameRightArrow:
case key.Event: ie.paramEditor.Focus()
switch e.State { case key.NameDeleteBackward:
case key.Press: t.SetUnitType("")
switch e.Name { ie.unitTypeEditor.Focus()
case key.NameUpArrow: l := len(ie.unitTypeEditor.Text())
if prevUnitIndex == 0 { ie.unitTypeEditor.SetCaret(l, l)
ie.instrumentDragList.Focus() case key.NameDeleteForward:
} t.DeleteUnit(true)
case key.NameRightArrow: case key.NameReturn:
ie.paramEditor.Focus() if e.Modifiers.Contain(key.ModShortcut) {
case key.NameDeleteBackward: t.AddUnit(true)
t.SetUnitType("") ie.unitDragList.SelectedItem = t.UnitIndex()
ie.unitTypeEditor.Focus() ie.unitTypeEditor.SetText("")
l := len(ie.unitTypeEditor.Text())
ie.unitTypeEditor.SetCaret(l, l)
case key.NameDeleteForward:
t.DeleteUnit(true)
case key.NameReturn:
if e.Modifiers.Contain(key.ModShortcut) {
t.AddUnit(true)
}
ie.unitTypeEditor.Focus()
l := len(ie.unitTypeEditor.Text())
ie.unitTypeEditor.SetCaret(l, l)
}
if e.Modifiers.Contain(key.ModShortcut) {
continue
}
t.JammingPressed(e)
case key.Release:
t.JammingReleased(e)
} }
ie.unitTypeEditor.Focus()
l := len(ie.unitTypeEditor.Text())
ie.unitTypeEditor.SetCaret(l, l)
} }
} }
} }
} }
dims := unitList.Layout(gtx)
if t.UnitIndex() != ie.unitDragList.SelectedItem {
t.SetUnitIndex(ie.unitDragList.SelectedItem)
ie.unitTypeEditor.SetText(t.Unit().Type)
}
return dims return dims
}), }),
layout.Expanded(func(gtx C) D { layout.Expanded(func(gtx C) D {

View File

@ -3,8 +3,9 @@ package gioui
import ( import (
"time" "time"
"gioui.org/app" "gioui.org/io/clipboard"
"gioui.org/io/key" "gioui.org/io/key"
"gioui.org/op"
"github.com/vsariola/sointu/tracker" "github.com/vsariola/sointu/tracker"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
@ -45,86 +46,80 @@ var noteMap = map[string]int{
} }
// KeyEvent handles incoming key events and returns true if repaint is needed. // KeyEvent handles incoming key events and returns true if repaint is needed.
func (t *Tracker) KeyEvent(e key.Event, window *app.Window) bool { func (t *Tracker) KeyEvent(e key.Event, o *op.Ops) {
if e.State == key.Press { if e.State == key.Press {
if t.OpenSongDialog.Visible || if t.OpenSongDialog.Visible ||
t.SaveSongDialog.Visible || t.SaveSongDialog.Visible ||
t.SaveInstrumentDialog.Visible || t.SaveInstrumentDialog.Visible ||
t.OpenInstrumentDialog.Visible || t.OpenInstrumentDialog.Visible ||
t.ExportWavDialog.Visible { t.ExportWavDialog.Visible {
return false return
} }
switch e.Name { switch e.Name {
case "C": case "C":
if e.Modifiers.Contain(key.ModShortcut) { if e.Modifiers.Contain(key.ModShortcut) {
contents, err := yaml.Marshal(t.Song()) contents, err := yaml.Marshal(t.Song())
if err == nil { if err == nil {
window.WriteClipboard(string(contents)) clipboard.WriteOp{Text: string(contents)}.Add(o)
t.Alert.Update("Song copied to clipboard", Notify, time.Second*3) t.Alert.Update("Song copied to clipboard", Notify, time.Second*3)
} }
return true return
} }
case "V": case "V":
if e.Modifiers.Contain(key.ModShortcut) { if e.Modifiers.Contain(key.ModShortcut) {
window.ReadClipboard() clipboard.ReadOp{Tag: t}.Add(o)
return true return
} }
case "Z": case "Z":
if e.Modifiers.Contain(key.ModShortcut) { if e.Modifiers.Contain(key.ModShortcut) {
t.Undo() t.Undo()
return true return
} }
case "Y": case "Y":
if e.Modifiers.Contain(key.ModShortcut) { if e.Modifiers.Contain(key.ModShortcut) {
t.Redo() t.Redo()
return true return
} }
case "N": case "N":
if e.Modifiers.Contain(key.ModShortcut) { if e.Modifiers.Contain(key.ModShortcut) {
t.NewSong(false) t.NewSong(false)
return true return
} }
case "S": case "S":
if e.Modifiers.Contain(key.ModShortcut) { if e.Modifiers.Contain(key.ModShortcut) {
t.SaveSongFile() t.SaveSongFile()
return false return
} }
case "O": case "O":
if e.Modifiers.Contain(key.ModShortcut) { if e.Modifiers.Contain(key.ModShortcut) {
t.OpenSongFile(false) t.OpenSongFile(false)
return true return
} }
case "F1": case "F1":
t.OrderEditor.Focus() t.OrderEditor.Focus()
return true return
case "F2": case "F2":
t.TrackEditor.Focus() t.TrackEditor.Focus()
return true return
case "F3": case "F3":
t.InstrumentEditor.Focus() t.InstrumentEditor.Focus()
return true return
case "F4": case "F4":
t.TrackEditor.Focus() t.TrackEditor.Focus()
return true return
case "F5": case "F5":
t.SetNoteTracking(true) t.SetNoteTracking(true)
startRow := t.Cursor().SongRow startRow := t.Cursor().SongRow
if t.OrderEditor.Focused() {
startRow.Row = 0
}
t.PlayFromPosition(startRow) t.PlayFromPosition(startRow)
return true return
case "F6": case "F6":
t.SetNoteTracking(false) t.SetNoteTracking(false)
startRow := t.Cursor().SongRow startRow := t.Cursor().SongRow
if t.OrderEditor.Focused() {
startRow.Row = 0
}
t.PlayFromPosition(startRow) t.PlayFromPosition(startRow)
return true return
case "F8": case "F8":
t.SetPlaying(false) t.SetPlaying(false)
return true return
case "Space": case "Space":
if !t.Playing() && !t.InstrEnlarged() { if !t.Playing() && !t.InstrEnlarged() {
t.SetNoteTracking(!e.Modifiers.Contain(key.ModShortcut)) t.SetNoteTracking(!e.Modifiers.Contain(key.ModShortcut))
@ -172,9 +167,10 @@ func (t *Tracker) KeyEvent(e key.Event, window *app.Window) bool {
} }
} }
} }
t.JammingPressed(e)
} else { // e.State == key.Release
t.JammingReleased(e)
} }
return false
} }
// NumberPressed handles incoming presses while in either of the hex number columns // NumberPressed handles incoming presses while in either of the hex number columns
@ -191,7 +187,7 @@ func (t *Tracker) NumberPressed(iv byte) {
t.SetNote(val) t.SetNote(val)
} }
func (t *Tracker) JammingPressed(e key.Event) { func (t *Tracker) JammingPressed(e key.Event) byte {
if val, ok := noteMap[e.Name]; ok { if val, ok := noteMap[e.Name]; ok {
if _, ok := t.KeyPlaying[e.Name]; !ok { if _, ok := t.KeyPlaying[e.Name]; !ok {
n := tracker.NoteAsValue(t.OctaveNumberInput.Value, val) n := tracker.NoteAsValue(t.OctaveNumberInput.Value, val)
@ -199,16 +195,17 @@ func (t *Tracker) JammingPressed(e key.Event) {
noteID := tracker.NoteIDInstr(instr, n) noteID := tracker.NoteIDInstr(instr, n)
t.NoteOn(noteID) t.NoteOn(noteID)
t.KeyPlaying[e.Name] = noteID t.KeyPlaying[e.Name] = noteID
return n
} }
} }
return 0
} }
func (t *Tracker) JammingReleased(e key.Event) { func (t *Tracker) JammingReleased(e key.Event) bool {
if noteID, ok := t.KeyPlaying[e.Name]; ok { if noteID, ok := t.KeyPlaying[e.Name]; ok {
t.NoteOff(noteID) t.NoteOff(noteID)
delete(t.KeyPlaying, e.Name) delete(t.KeyPlaying, e.Name)
if t.TrackEditor.focused && t.Playing() && t.Note() == 1 && t.NoteTracking() { return true
t.SetNote(0)
}
} }
return false
} }

View File

@ -4,7 +4,7 @@ import (
"image" "image"
"image/color" "image/color"
"gioui.org/f32" "gioui.org/font"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op"
"gioui.org/op/paint" "gioui.org/op/paint"
@ -18,20 +18,20 @@ type LabelStyle struct {
Color color.NRGBA Color color.NRGBA
ShadeColor color.NRGBA ShadeColor color.NRGBA
Alignment layout.Direction Alignment layout.Direction
Font text.Font Font font.Font
FontSize unit.Value FontSize unit.Sp
} }
func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions { func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions {
return layout.Stack{Alignment: l.Alignment}.Layout(gtx, return layout.Stack{Alignment: l.Alignment}.Layout(gtx,
layout.Stacked(func(gtx layout.Context) layout.Dimensions { layout.Stacked(func(gtx layout.Context) layout.Dimensions {
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
paint.ColorOp{Color: l.ShadeColor}.Add(gtx.Ops) paint.ColorOp{Color: l.ShadeColor}.Add(gtx.Ops)
op.Offset(f32.Pt(2, 2)).Add(gtx.Ops) op.Offset(image.Pt(2, 2)).Add(gtx.Ops)
dims := widget.Label{ dims := widget.Label{
Alignment: text.Start, Alignment: text.Start,
MaxLines: 1, MaxLines: 1,
}.Layout(gtx, textShaper, l.Font, l.FontSize, l.Text) }.Layout(gtx, textShaper, l.Font, l.FontSize, l.Text, op.CallOp{})
return layout.Dimensions{ return layout.Dimensions{
Size: dims.Size.Add(image.Pt(2, 2)), Size: dims.Size.Add(image.Pt(2, 2)),
Baseline: dims.Baseline, Baseline: dims.Baseline,
@ -42,7 +42,7 @@ func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions {
return widget.Label{ return widget.Label{
Alignment: text.Start, Alignment: text.Start,
MaxLines: 1, MaxLines: 1,
}.Layout(gtx, textShaper, l.Font, l.FontSize, l.Text) }.Layout(gtx, textShaper, l.Font, l.FontSize, l.Text, op.CallOp{})
}), }),
) )
} }

View File

@ -4,6 +4,9 @@ import (
"fmt" "fmt"
"image" "image"
"gioui.org/app"
"gioui.org/io/clipboard"
"gioui.org/io/key"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op/clip" "gioui.org/op/clip"
"gioui.org/op/paint" "gioui.org/op/paint"
@ -12,7 +15,21 @@ import (
type C = layout.Context type C = layout.Context
type D = layout.Dimensions type D = layout.Dimensions
func (t *Tracker) Layout(gtx layout.Context) { func (t *Tracker) Layout(gtx layout.Context, w *app.Window) {
// this is the top level input handler for the whole app
// it handles all the global key events and clipboard events
// we need to tell gio that we handle tabs too; otherwise
// it will steal them for focus switching
key.InputOp{Tag: t, Keys: "Tab|Shift-Tab"}.Add(gtx.Ops)
for _, ev := range gtx.Events(t) {
switch e := ev.(type) {
case key.Event:
t.KeyEvent(e, gtx.Ops)
case clipboard.Event:
t.UnmarshalContent([]byte(e.Text))
}
}
paint.FillShape(gtx.Ops, backgroundColor, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op()) paint.FillShape(gtx.Ops, backgroundColor, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op())
if t.InstrEnlarged() { if t.InstrEnlarged() {
t.layoutTop(gtx) t.layoutTop(gtx)

View File

@ -28,8 +28,8 @@ type MenuStyle struct {
IconColor color.NRGBA IconColor color.NRGBA
TextColor color.NRGBA TextColor color.NRGBA
ShortCutColor color.NRGBA ShortCutColor color.NRGBA
FontSize unit.Value FontSize unit.Sp
IconSize unit.Value IconSize unit.Dp
HoverColor color.NRGBA HoverColor color.NRGBA
} }
@ -82,16 +82,15 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D {
i2 := i // avoid loop variable getting updated in closure i2 := i // avoid loop variable getting updated in closure
item2 := item item2 := item
flexChildren[i] = layout.Rigid(func(gtx C) D { flexChildren[i] = layout.Rigid(func(gtx C) D {
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
var macro op.MacroOp var macro op.MacroOp
if i2 == m.Menu.hover-1 && !item2.Disabled { if i2 == m.Menu.hover-1 && !item2.Disabled {
macro = op.Record(gtx.Ops) macro = op.Record(gtx.Ops)
} }
icon := widgetForIcon(item2.IconBytes) icon := widgetForIcon(item2.IconBytes)
if !item2.Disabled { iconColor := m.IconColor
icon.Color = m.IconColor if item2.Disabled {
} else { iconColor = mediumEmphasisTextColor
icon.Color = mediumEmphasisTextColor
} }
iconInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(6)} iconInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(6)}
textLabel := LabelStyle{Text: item2.Text, FontSize: m.FontSize, Color: m.TextColor} textLabel := LabelStyle{Text: item2.Text, FontSize: m.FontSize, Color: m.TextColor}
@ -103,7 +102,9 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D {
dims := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, dims := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
return iconInset.Layout(gtx, func(gtx C) D { return iconInset.Layout(gtx, func(gtx C) D {
return icon.Layout(gtx, m.IconSize) p := gtx.Dp(unit.Dp(m.IconSize))
gtx.Constraints.Min = image.Pt(p, p)
return icon.Layout(gtx, iconColor)
}) })
}), }),
layout.Rigid(textLabel.Layout), layout.Rigid(textLabel.Layout),
@ -121,10 +122,11 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D {
} }
if !item2.Disabled { if !item2.Disabled {
rect := image.Rect(0, 0, dims.Size.X, dims.Size.Y) rect := image.Rect(0, 0, dims.Size.X, dims.Size.Y)
pointer.Rect(rect).Add(gtx.Ops) area := clip.Rect(rect).Push(gtx.Ops)
pointer.InputOp{Tag: &m.Menu.tags[i2], pointer.InputOp{Tag: &m.Menu.tags[i2],
Types: pointer.Press | pointer.Enter | pointer.Leave, Types: pointer.Press | pointer.Enter | pointer.Leave,
}.Add(gtx.Ops) }.Add(gtx.Ops)
area.Pop()
} }
return dims return dims
}) })
@ -144,7 +146,7 @@ func PopupMenu(th *material.Theme, menu *Menu) MenuStyle {
IconColor: white, IconColor: white,
TextColor: white, TextColor: white,
ShortCutColor: mediumEmphasisTextColor, ShortCutColor: mediumEmphasisTextColor,
FontSize: unit.Dp(16), FontSize: unit.Sp(16),
IconSize: unit.Dp(16), IconSize: unit.Dp(16),
HoverColor: menuHoverColor, HoverColor: menuHoverColor,
} }

View File

@ -7,7 +7,7 @@ import (
"golang.org/x/exp/shiny/materialdesign/icons" "golang.org/x/exp/shiny/materialdesign/icons"
"gioui.org/f32" "gioui.org/font"
"gioui.org/op/clip" "gioui.org/op/clip"
"gioui.org/op/paint" "gioui.org/op/paint"
"gioui.org/widget" "gioui.org/widget"
@ -34,15 +34,15 @@ type NumericUpDownStyle struct {
Min int Min int
Max int Max int
Color color.NRGBA Color color.NRGBA
Font text.Font Font font.Font
TextSize unit.Value TextSize unit.Sp
BorderColor color.NRGBA BorderColor color.NRGBA
IconColor color.NRGBA IconColor color.NRGBA
BackgroundColor color.NRGBA BackgroundColor color.NRGBA
CornerRadius unit.Value CornerRadius unit.Dp
Border unit.Value Border unit.Dp
ButtonWidth unit.Value ButtonWidth unit.Dp
UnitsPerStep unit.Value UnitsPerStep unit.Dp
shaper text.Shaper shaper text.Shaper
} }
@ -63,26 +63,23 @@ func NumericUpDown(th *material.Theme, number *NumberInput, min, max int) Numeri
ButtonWidth: unit.Dp(16), ButtonWidth: unit.Dp(16),
Border: unit.Dp(1), Border: unit.Dp(1),
UnitsPerStep: unit.Dp(8), UnitsPerStep: unit.Dp(8),
TextSize: th.TextSize.Scale(14.0 / 16.0), TextSize: th.TextSize * 14 / 16,
shaper: th.Shaper, shaper: *th.Shaper,
} }
} }
func (s NumericUpDownStyle) Layout(gtx C) D { func (s NumericUpDownStyle) Layout(gtx C) D {
size := gtx.Constraints.Min size := gtx.Constraints.Min
defer op.Save(gtx.Ops).Load() rr := gtx.Dp(s.CornerRadius)
rr := float32(gtx.Px(s.CornerRadius)) border := gtx.Dp(s.Border)
border := float32(gtx.Px(s.Border)) c := clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops)
clip.UniformRRect(f32.Rectangle{Max: f32.Point{
X: float32(gtx.Constraints.Min.X),
Y: float32(gtx.Constraints.Min.Y),
}}, rr).Add(gtx.Ops)
paint.Fill(gtx.Ops, s.BorderColor) paint.Fill(gtx.Ops, s.BorderColor)
op.Offset(f32.Pt(border, border)).Add(gtx.Ops) c.Pop()
clip.UniformRRect(f32.Rectangle{Max: f32.Point{ off := op.Offset(image.Pt(border, border)).Push(gtx.Ops)
X: float32(gtx.Constraints.Min.X) - border*2, c2 := clip.UniformRRect(image.Rectangle{Max: image.Pt(
Y: float32(gtx.Constraints.Min.Y) - border*2, gtx.Constraints.Min.X-border*2,
}}, rr-border).Add(gtx.Ops) gtx.Constraints.Min.Y-border*2,
)}, rr-border).Push(gtx.Ops)
gtx.Constraints.Min.X -= int(border * 2) gtx.Constraints.Min.X -= int(border * 2)
gtx.Constraints.Min.Y -= int(border * 2) gtx.Constraints.Min.Y -= int(border * 2)
gtx.Constraints.Max = gtx.Constraints.Min gtx.Constraints.Max = gtx.Constraints.Min
@ -97,12 +94,14 @@ func (s NumericUpDownStyle) Layout(gtx C) D {
if s.NumberInput.Value > s.Max { if s.NumberInput.Value > s.Max {
s.NumberInput.Value = s.Max s.NumberInput.Value = s.Max
} }
off.Pop()
c2.Pop()
return layout.Dimensions{Size: size} return layout.Dimensions{Size: size}
} }
func (s NumericUpDownStyle) button(height int, icon *widget.Icon, delta int, click *gesture.Click) layout.Widget { func (s NumericUpDownStyle) button(height int, icon *widget.Icon, delta int, click *gesture.Click) layout.Widget {
return func(gtx C) D { return func(gtx C) D {
btnWidth := gtx.Px(s.ButtonWidth) btnWidth := gtx.Dp(s.ButtonWidth)
return layout.Stack{Alignment: layout.Center}.Layout(gtx, return layout.Stack{Alignment: layout.Center}.Layout(gtx,
layout.Stacked(func(gtx layout.Context) layout.Dimensions { layout.Stacked(func(gtx layout.Context) layout.Dimensions {
//paint.FillShape(gtx.Ops, black, clip.Rect(image.Rect(0, 0, btnWidth, height)).Op()) //paint.FillShape(gtx.Ops, black, clip.Rect(image.Rect(0, 0, btnWidth, height)).Op())
@ -117,8 +116,12 @@ func (s NumericUpDownStyle) button(height int, icon *widget.Icon, delta int, cli
size = 1 size = 1
} }
if icon != nil { if icon != nil {
icon.Color = s.IconColor p := gtx.Dp(unit.Dp(size))
return icon.Layout(gtx, unit.Px(float32(size))) if p < 1 {
p = 1
}
gtx.Constraints = layout.Exact(image.Pt(p, p))
return icon.Layout(gtx, s.IconColor)
} }
return layout.Dimensions{} return layout.Dimensions{}
}), }),
@ -137,7 +140,7 @@ func (s NumericUpDownStyle) layoutText(gtx C) D {
}), }),
layout.Expanded(func(gtx layout.Context) layout.Dimensions { layout.Expanded(func(gtx layout.Context) layout.Dimensions {
paint.ColorOp{Color: s.Color}.Add(gtx.Ops) paint.ColorOp{Color: s.Color}.Add(gtx.Ops)
return widget.Label{Alignment: text.Middle}.Layout(gtx, s.shaper, s.Font, s.TextSize, fmt.Sprintf("%v", s.NumberInput.Value)) return widget.Label{Alignment: text.Middle}.Layout(gtx, &s.shaper, s.Font, s.TextSize, fmt.Sprintf("%v", s.NumberInput.Value), op.CallOp{})
}), }),
layout.Expanded(s.layoutDrag), layout.Expanded(s.layoutDrag),
) )
@ -145,7 +148,7 @@ func (s NumericUpDownStyle) layoutText(gtx C) D {
func (s NumericUpDownStyle) layoutDrag(gtx layout.Context) layout.Dimensions { func (s NumericUpDownStyle) layoutDrag(gtx layout.Context) layout.Dimensions {
{ // handle dragging { // handle dragging
pxPerStep := float32(gtx.Px(s.UnitsPerStep)) pxPerStep := float32(gtx.Dp(s.UnitsPerStep))
for _, ev := range gtx.Events(s.NumberInput) { for _, ev := range gtx.Events(s.NumberInput) {
if e, ok := ev.(pointer.Event); ok { if e, ok := ev.(pointer.Event); ok {
switch e.Type { switch e.Type {
@ -162,15 +165,16 @@ func (s NumericUpDownStyle) layoutDrag(gtx layout.Context) layout.Dimensions {
} }
// Avoid affecting the input tree with pointer events. // Avoid affecting the input tree with pointer events.
stack := op.Save(gtx.Ops) stack := op.Offset(image.Point{}).Push(gtx.Ops)
// register for input // register for input
dragRect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y) dragRect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)
pointer.Rect(dragRect).Add(gtx.Ops) area := clip.Rect(dragRect).Push(gtx.Ops)
pointer.InputOp{ pointer.InputOp{
Tag: s.NumberInput, Tag: s.NumberInput,
Types: pointer.Press | pointer.Drag | pointer.Release, Types: pointer.Press | pointer.Drag | pointer.Release,
}.Add(gtx.Ops) }.Add(gtx.Ops)
stack.Load() area.Pop()
stack.Pop()
} }
return layout.Dimensions{Size: gtx.Constraints.Min} return layout.Dimensions{Size: gtx.Constraints.Min}
} }
@ -184,11 +188,13 @@ func (s NumericUpDownStyle) layoutClick(gtx layout.Context, delta int, click *ge
} }
} }
// Avoid affecting the input tree with pointer events. // Avoid affecting the input tree with pointer events.
stack := op.Save(gtx.Ops) stack := op.Offset(image.Point{}).Push(gtx.Ops)
// register for input // register for input
clickRect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y) clickRect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)
pointer.Rect(clickRect).Add(gtx.Ops) area := clip.Rect(clickRect).Push(gtx.Ops)
click.Add(gtx.Ops) click.Add(gtx.Ops)
stack.Load() area.Pop()
stack.Pop()
return layout.Dimensions{Size: gtx.Constraints.Min} return layout.Dimensions{Size: gtx.Constraints.Min}
} }

View File

@ -6,7 +6,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"gioui.org/f32"
"gioui.org/io/key" "gioui.org/io/key"
"gioui.org/io/pointer" "gioui.org/io/pointer"
"gioui.org/layout" "gioui.org/layout"
@ -64,7 +63,7 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
key.FocusOp{Tag: &oe.tag}.Add(gtx.Ops) key.FocusOp{Tag: &oe.tag}.Add(gtx.Ops)
} }
case key.Event: case key.Event:
if !oe.focused || e.State != key.Press { if e.State != key.Press {
continue continue
} }
switch e.Name { switch e.Name {
@ -129,6 +128,14 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
case "-": case "-":
t.AdjustPatternNumber(-1, e.Modifiers.Contain(key.ModShortcut)) t.AdjustPatternNumber(-1, e.Modifiers.Contain(key.ModShortcut))
continue continue
case key.NameHome:
cursor := t.Cursor()
cursor.Track = 0
t.SetCursor(cursor)
case key.NameEnd:
cursor := t.Cursor()
cursor.Track = len(t.Song().Score.Tracks) - 1
t.SetCursor(cursor)
} }
if (e.Name != key.NameLeftArrow && if (e.Name != key.NameLeftArrow &&
e.Name != key.NameRightArrow && e.Name != key.NameRightArrow &&
@ -156,18 +163,18 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
} }
} }
} }
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
if oe.requestFocus { if oe.requestFocus {
oe.requestFocus = false oe.requestFocus = false
key.FocusOp{Tag: &oe.tag}.Add(gtx.Ops) key.FocusOp{Tag: &oe.tag}.Add(gtx.Ops)
} }
clip.Rect{Max: gtx.Constraints.Max}.Add(gtx.Ops) defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop()
rect := image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)
pointer.Rect(rect).Add(gtx.Ops)
pointer.InputOp{Tag: &oe.tag, pointer.InputOp{Tag: &oe.tag,
Types: pointer.Press, Types: pointer.Press,
}.Add(gtx.Ops) }.Add(gtx.Ops)
key.InputOp{Tag: &oe.tag}.Add(gtx.Ops)
key.InputOp{Tag: &oe.tag, Keys: "←|→|↑|↓|Shift-←|Shift-→|Shift-↑|Shift-↓|⏎|⇱|⇲|⌫|⌦|Ctrl-⌫|Ctrl-⌦|+|-|Space|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z"}.Add(gtx.Ops)
patternRect := tracker.SongRect{ patternRect := tracker.SongRect{
Corner1: tracker.SongPoint{SongRow: tracker.SongRow{Pattern: t.Cursor().Pattern}, Track: t.Cursor().Track}, Corner1: tracker.SongPoint{SongRow: tracker.SongRow{Pattern: t.Cursor().Pattern}, Track: t.Cursor().Track},
Corner2: tracker.SongPoint{SongRow: tracker.SongRow{Pattern: t.SelectionCorner().Pattern}, Track: t.SelectionCorner().Track}, Corner2: tracker.SongPoint{SongRow: tracker.SongRow{Pattern: t.SelectionCorner().Pattern}, Track: t.SelectionCorner().Track},
@ -176,8 +183,7 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
// draw the single letter titles for tracks // draw the single letter titles for tracks
{ {
gtx := gtx gtx := gtx
stack := op.Save(gtx.Ops) stack := op.Offset(image.Pt(patternRowMarkerWidth, 0)).Push(gtx.Ops)
op.Offset(f32.Pt(patternRowMarkerWidth, 0)).Add(gtx.Ops)
gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X-patternRowMarkerWidth, patternCellHeight)) gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X-patternRowMarkerWidth, patternCellHeight))
elem := func(gtx C, i int) D { elem := func(gtx C, i int) D {
gtx.Constraints = layout.Exact(image.Pt(patternCellWidth, patternCellHeight)) gtx.Constraints = layout.Exact(image.Pt(patternCellWidth, patternCellHeight))
@ -188,16 +194,16 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
} else { } else {
title = "?" title = "?"
} }
LabelStyle{Alignment: layout.N, Text: title, FontSize: unit.Dp(12), Color: mediumEmphasisTextColor}.Layout(gtx) LabelStyle{Alignment: layout.N, Text: title, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor}.Layout(gtx)
return D{Size: gtx.Constraints.Min} return D{Size: gtx.Constraints.Min}
} }
style := FilledDragList(t.Theme, oe.titleList, len(t.Song().Score.Tracks), elem, t.SwapTracks) style := FilledDragList(t.Theme, oe.titleList, len(t.Song().Score.Tracks), elem, t.SwapTracks)
style.HoverColor = transparent style.HoverColor = transparent
style.SelectedColor = transparent style.SelectedColor = transparent
style.Layout(gtx) style.Layout(gtx)
stack.Load() stack.Pop()
} }
op.Offset(f32.Pt(0, patternCellHeight)).Add(gtx.Ops) op.Offset(image.Pt(0, patternCellHeight)).Add(gtx.Ops)
gtx.Constraints.Max.Y -= patternCellHeight gtx.Constraints.Max.Y -= patternCellHeight
gtx.Constraints.Min.Y -= patternCellHeight gtx.Constraints.Min.Y -= patternCellHeight
element := func(gtx C, j int) D { element := func(gtx C, j int) D {
@ -205,18 +211,17 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
paint.FillShape(gtx.Ops, patternPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, patternCellHeight)}.Op()) paint.FillShape(gtx.Ops, patternPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, patternCellHeight)}.Op())
} }
paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops) paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops)
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j))) widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{})
stack := op.Save(gtx.Ops) stack := op.Offset(image.Pt(patternRowMarkerWidth, 0)).Push(gtx.Ops)
op.Offset(f32.Pt(patternRowMarkerWidth, 0)).Add(gtx.Ops)
for i, track := range t.Song().Score.Tracks { for i, track := range t.Song().Score.Tracks {
paint.FillShape(gtx.Ops, patternCellColor, clip.Rect{Min: image.Pt(1, 1), Max: image.Pt(patternCellWidth-1, patternCellHeight-1)}.Op()) paint.FillShape(gtx.Ops, patternCellColor, clip.Rect{Min: image.Pt(1, 1), Max: image.Pt(patternCellWidth-1, patternCellHeight-1)}.Op())
paint.ColorOp{Color: patternTextColor}.Add(gtx.Ops) paint.ColorOp{Color: patternTextColor}.Add(gtx.Ops)
if j >= 0 && j < len(track.Order) && track.Order[j] >= 0 { if j >= 0 && j < len(track.Order) && track.Order[j] >= 0 {
gtx := gtx gtx := gtx
gtx.Constraints.Max.X = patternCellWidth gtx.Constraints.Max.X = patternCellWidth
op.Offset(f32.Pt(0, -2)).Add(gtx.Ops) op.Offset(image.Pt(0, -2)).Add(gtx.Ops)
widget.Label{Alignment: text.Middle}.Layout(gtx, textShaper, trackerFont, trackerFontSize, patternIndexToString(track.Order[j])) widget.Label{Alignment: text.Middle}.Layout(gtx, textShaper, trackerFont, trackerFontSize, patternIndexToString(track.Order[j]), op.CallOp{})
op.Offset(f32.Pt(0, 2)).Add(gtx.Ops) op.Offset(image.Pt(0, 2)).Add(gtx.Ops)
} }
point := tracker.SongPoint{Track: i, SongRow: tracker.SongRow{Pattern: j}} point := tracker.SongPoint{Track: i, SongRow: tracker.SongRow{Pattern: j}}
if oe.focused || t.TrackEditor.Focused() { if oe.focused || t.TrackEditor.Focused() {
@ -231,9 +236,9 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
paint.FillShape(gtx.Ops, color, clip.Rect{Max: image.Pt(patternCellWidth, patternCellHeight)}.Op()) paint.FillShape(gtx.Ops, color, clip.Rect{Max: image.Pt(patternCellWidth, patternCellHeight)}.Op())
} }
} }
op.Offset(f32.Pt(patternCellWidth, 0)).Add(gtx.Ops) op.Offset(image.Pt(patternCellWidth, 0)).Add(gtx.Ops)
} }
stack.Load() stack.Pop()
return D{Size: image.Pt(gtx.Constraints.Max.X, patternCellHeight)} return D{Size: image.Pt(gtx.Constraints.Max.X, patternCellHeight)}
} }

View File

@ -94,12 +94,6 @@ func (pe *ParamEditor) Bind(t *Tracker) layout.Widget {
case key.NameEscape: case key.NameEscape:
t.InstrumentEditor.unitDragList.Focus() t.InstrumentEditor.unitDragList.Focus()
} }
if e.Modifiers.Contain(key.ModShortcut) {
continue
}
t.JammingPressed(e)
case key.Release:
t.JammingReleased(e)
} }
} }
} }
@ -118,12 +112,13 @@ func (pe *ParamEditor) Bind(t *Tracker) layout.Widget {
}), }),
layout.Rigid(pe.layoutUnitFooter(t))) layout.Rigid(pe.layoutUnitFooter(t)))
rect := image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y) rect := image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)
pointer.PassOp{Pass: true}.Add(gtx.Ops) area := clip.Rect(rect).Push(gtx.Ops)
pointer.Rect(rect).Add(gtx.Ops) defer pointer.PassOp{}.Push(gtx.Ops).Pop()
pointer.InputOp{Tag: &pe.tag, pointer.InputOp{Tag: &pe.tag,
Types: pointer.Press, Types: pointer.Press,
}.Add(gtx.Ops) }.Add(gtx.Ops)
key.InputOp{Tag: &pe.tag}.Add(gtx.Ops) key.InputOp{Tag: &pe.tag, Keys: "←|Shift-←|→|Shift-→|↑|↓|⎋"}.Add(gtx.Ops)
area.Pop()
return ret return ret
}) })
} }
@ -138,12 +133,12 @@ func (pe *ParamEditor) layoutUnitSliders(gtx C, t *Tracker) D {
listItem := func(gtx C, index int) D { listItem := func(gtx C, index int) D {
for pe.Parameters[index].Clicked() { for pe.Parameters[index].Clicked() {
if !pe.focused || t.ParamIndex() != index { if t.ParamIndex() != index {
pe.Focus()
t.SetParamIndex(index) t.SetParamIndex(index)
} else { } else {
t.ResetParam() t.ResetParam()
} }
pe.Focus()
} }
param, err := t.Param(index) param, err := t.Param(index)
if err != nil { if err != nil {
@ -199,7 +194,7 @@ func (pe *ParamEditor) layoutUnitFooter(t *Tracker) layout.Widget {
clearUnitBtnStyle := IconButton(t.Theme, pe.ClearUnitBtn, icons.ContentClear, true) clearUnitBtnStyle := IconButton(t.Theme, pe.ClearUnitBtn, icons.ContentClear, true)
dims = clearUnitBtnStyle.Layout(gtx) dims = clearUnitBtnStyle.Layout(gtx)
} }
return D{Size: image.Pt(gtx.Px(unit.Dp(48)), dims.Size.Y)} return D{Size: image.Pt(gtx.Dp(unit.Dp(48)), dims.Size.Y)}
}), }),
layout.Flexed(1, hintText), layout.Flexed(1, hintText),
) )
@ -230,9 +225,10 @@ func (pe *ParamEditor) layoutUnitTypeChooser(gtx C, t *Tracker) D {
return layout.Stack{Alignment: layout.W}.Layout(gtx, return layout.Stack{Alignment: layout.W}.Layout(gtx,
layout.Stacked(bg), layout.Stacked(bg),
layout.Expanded(func(gtx C) D { layout.Expanded(func(gtx C) D {
return leftMargin.Layout(gtx, labelStyle.Layout) return pe.ChooseUnitTypeBtns[i].Layout(gtx, func(gtx C) D {
}), return leftMargin.Layout(gtx, labelStyle.Layout)
layout.Expanded(pe.ChooseUnitTypeBtns[i].Layout)) })
}))
} }
return layout.Stack{}.Layout(gtx, return layout.Stack{}.Layout(gtx,
layout.Stacked(func(gtx C) D { layout.Stacked(func(gtx C) D {

View File

@ -47,19 +47,16 @@ func (p *ParameterWidget) Clicked() bool {
func (p ParameterStyle) Layout(gtx C) D { func (p ParameterStyle) Layout(gtx C) D {
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
return layout.Stack{}.Layout(gtx, return p.ParameterWidget.labelBtn.Layout(gtx, func(gtx C) D {
layout.Stacked(func(gtx C) D { gtx.Constraints.Min.X = gtx.Dp(unit.Dp(110))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(110)) return layout.E.Layout(gtx, Label(p.Parameter.Name, white))
return layout.E.Layout(gtx, Label(p.Parameter.Name, white)) })
}),
layout.Expanded(p.ParameterWidget.labelBtn.Layout),
)
}), }),
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
switch p.Parameter.Type { switch p.Parameter.Type {
case tracker.IntegerParameter: case tracker.IntegerParameter:
gtx.Constraints.Min.X = gtx.Px(unit.Dp(200)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(200))
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(40)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(40))
if p.Focus { if p.Focus {
paint.FillShape(gtx.Ops, cursorColor, clip.Rect{ paint.FillShape(gtx.Ops, cursorColor, clip.Rect{
Max: gtx.Constraints.Min, Max: gtx.Constraints.Min,
@ -74,15 +71,15 @@ func (p ParameterStyle) Layout(gtx C) D {
p.Parameter.Value = int(p.ParameterWidget.floatWidget.Value + 0.5) p.Parameter.Value = int(p.ParameterWidget.floatWidget.Value + 0.5)
return dims return dims
case tracker.BoolParameter: case tracker.BoolParameter:
gtx.Constraints.Min.X = gtx.Px(unit.Dp(60)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(60))
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(40)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(40))
if p.Focus { if p.Focus {
paint.FillShape(gtx.Ops, cursorColor, clip.Rect{ paint.FillShape(gtx.Ops, cursorColor, clip.Rect{
Max: gtx.Constraints.Min, Max: gtx.Constraints.Min,
}.Op()) }.Op())
} }
p.ParameterWidget.boolWidget.Value = p.Parameter.Value > p.Parameter.Min p.ParameterWidget.boolWidget.Value = p.Parameter.Value > p.Parameter.Min
boolStyle := material.Switch(p.Theme, &p.ParameterWidget.boolWidget) boolStyle := material.Switch(p.Theme, &p.ParameterWidget.boolWidget, "Toggle boolean parameter")
boolStyle.Color.Disabled = p.Theme.Fg boolStyle.Color.Disabled = p.Theme.Fg
boolStyle.Color.Enabled = white boolStyle.Color.Enabled = white
dims := layout.Center.Layout(gtx, boolStyle.Layout) dims := layout.Center.Layout(gtx, boolStyle.Layout)
@ -93,8 +90,8 @@ func (p ParameterStyle) Layout(gtx C) D {
} }
return dims return dims
case tracker.IDParameter: case tracker.IDParameter:
gtx.Constraints.Min.X = gtx.Px(unit.Dp(200)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(200))
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(40)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(40))
if p.Focus { if p.Focus {
paint.FillShape(gtx.Ops, cursorColor, clip.Rect{ paint.FillShape(gtx.Ops, cursorColor, clip.Rect{
Max: gtx.Constraints.Min, Max: gtx.Constraints.Min,

View File

@ -4,7 +4,6 @@ import (
"image" "image"
"image/color" "image/color"
"gioui.org/f32"
"gioui.org/io/pointer" "gioui.org/io/pointer"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op"
@ -17,11 +16,11 @@ type PopupStyle struct {
Visible *bool Visible *bool
SurfaceColor color.NRGBA SurfaceColor color.NRGBA
ShadowColor color.NRGBA ShadowColor color.NRGBA
ShadowN unit.Value ShadowN unit.Dp
ShadowE unit.Value ShadowE unit.Dp
ShadowW unit.Value ShadowW unit.Dp
ShadowS unit.Value ShadowS unit.Dp
SE, SW, NW, NE unit.Value SE, SW, NW, NE unit.Dp
} }
func Popup(visible *bool) PopupStyle { func Popup(visible *bool) PopupStyle {
@ -58,33 +57,30 @@ func (s PopupStyle) Layout(gtx C, contents layout.Widget) D {
} }
bg := func(gtx C) D { bg := func(gtx C) D {
pointer.PassOp{Pass: false}.Add(gtx.Ops)
rrect := clip.RRect{ rrect := clip.RRect{
Rect: f32.Rectangle{Max: f32.Pt(float32(gtx.Constraints.Min.X), float32(gtx.Constraints.Min.Y))}, Rect: image.Rectangle{Max: gtx.Constraints.Min},
SE: float32(gtx.Px(s.SE)), SE: gtx.Dp(s.SE),
SW: float32(gtx.Px(s.SW)), SW: gtx.Dp(s.SW),
NW: float32(gtx.Px(s.NW)), NW: gtx.Dp(s.NW),
NE: float32(gtx.Px(s.NE)), NE: gtx.Dp(s.NE),
} }
rrect2 := rrect rrect2 := rrect
rrect2.Rect.Min = rrect2.Rect.Min.Sub(f32.Pt(float32(gtx.Px(s.ShadowW)), float32(gtx.Px(s.ShadowN)))) rrect2.Rect.Min = rrect2.Rect.Min.Sub(image.Pt(gtx.Dp(s.ShadowW), gtx.Dp(s.ShadowN)))
rrect2.Rect.Max = rrect2.Rect.Max.Add(f32.Pt(float32(gtx.Px(s.ShadowE)), float32(gtx.Px(s.ShadowS)))) rrect2.Rect.Max = rrect2.Rect.Max.Add(image.Pt(gtx.Dp(s.ShadowE), gtx.Dp(s.ShadowS)))
paint.FillShape(gtx.Ops, s.ShadowColor, rrect2.Op(gtx.Ops)) paint.FillShape(gtx.Ops, s.ShadowColor, rrect2.Op(gtx.Ops))
paint.FillShape(gtx.Ops, s.SurfaceColor, rrect.Op(gtx.Ops)) paint.FillShape(gtx.Ops, s.SurfaceColor, rrect.Op(gtx.Ops))
rect := image.Rect(int(rrect2.Rect.Min.X), int(rrect2.Rect.Min.Y), int(rrect2.Rect.Max.X), int(rrect2.Rect.Max.Y)) area := clip.Rect(image.Rect(-1e6, -1e6, 1e6, 1e6)).Push(gtx.Ops)
state := op.Save(gtx.Ops)
pointer.InputOp{Tag: s.Visible, pointer.InputOp{Tag: s.Visible,
Types: pointer.Press, Types: pointer.Press,
Grab: true, Grab: true,
}.Add(gtx.Ops) }.Add(gtx.Ops)
state.Load() area.Pop()
state = op.Save(gtx.Ops) area = clip.Rect(rrect2.Rect).Push(gtx.Ops)
pointer.Rect(rect).Add(gtx.Ops) pointer.InputOp{Tag: &dummyTag,
pointer.InputOp{Tag: dummyTag,
Types: pointer.Press, Types: pointer.Press,
Grab: true, Grab: true,
}.Add(gtx.Ops) }.Add(gtx.Ops)
state.Load() area.Pop()
return D{Size: gtx.Constraints.Min} return D{Size: gtx.Constraints.Min}
} }
macro := op.Record(gtx.Ops) macro := op.Record(gtx.Ops)

View File

@ -5,7 +5,6 @@ import (
"image" "image"
"strings" "strings"
"gioui.org/f32"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op"
"gioui.org/op/clip" "gioui.org/op/clip"
@ -20,13 +19,13 @@ func (t *Tracker) layoutRowMarkers(gtx C) D {
paint.FillShape(gtx.Ops, rowMarkerSurfaceColor, clip.Rect{ paint.FillShape(gtx.Ops, rowMarkerSurfaceColor, clip.Rect{
Max: gtx.Constraints.Max, Max: gtx.Constraints.Max,
}.Op()) }.Op())
defer op.Save(gtx.Ops).Load() //defer op.Save(gtx.Ops).Load()
clip.Rect{Max: gtx.Constraints.Max}.Add(gtx.Ops) defer clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops).Pop()
op.Offset(f32.Pt(0, float32(gtx.Constraints.Max.Y-trackRowHeight)/2)).Add(gtx.Ops) op.Offset(image.Pt(0, (gtx.Constraints.Max.Y-trackRowHeight)/2)).Add(gtx.Ops)
cursorSongRow := t.Cursor().Pattern*t.Song().Score.RowsPerPattern + t.Cursor().Row cursorSongRow := t.Cursor().Pattern*t.Song().Score.RowsPerPattern + t.Cursor().Row
playPos := t.PlayPosition() playPos := t.PlayPosition()
playSongRow := playPos.Pattern*t.Song().Score.RowsPerPattern + playPos.Row playSongRow := playPos.Pattern*t.Song().Score.RowsPerPattern + playPos.Row
op.Offset(f32.Pt(0, (-1*trackRowHeight)*float32(cursorSongRow))).Add(gtx.Ops) op.Offset(image.Pt(0, (-1*trackRowHeight)*(cursorSongRow))).Add(gtx.Ops)
beatMarkerDensity := t.Song().RowsPerBeat beatMarkerDensity := t.Song().RowsPerBeat
for beatMarkerDensity <= 2 { for beatMarkerDensity <= 2 {
beatMarkerDensity *= 2 beatMarkerDensity *= 2
@ -44,16 +43,16 @@ func (t *Tracker) layoutRowMarkers(gtx C) D {
} }
if j == 0 { if j == 0 {
paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops) paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops)
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", i))) widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", i)), op.CallOp{})
} }
if t.TrackEditor.Focused() && songRow == cursorSongRow { if t.TrackEditor.Focused() && songRow == cursorSongRow {
paint.ColorOp{Color: trackerActiveTextColor}.Add(gtx.Ops) paint.ColorOp{Color: trackerActiveTextColor}.Add(gtx.Ops)
} else { } else {
paint.ColorOp{Color: rowMarkerRowTextColor}.Add(gtx.Ops) paint.ColorOp{Color: rowMarkerRowTextColor}.Add(gtx.Ops)
} }
op.Offset(f32.Pt(rowMarkerWidth/2, 0)).Add(gtx.Ops) op.Offset(image.Pt(rowMarkerWidth/2, 0)).Add(gtx.Ops)
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j))) widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{})
op.Offset(f32.Pt(-rowMarkerWidth/2, trackRowHeight)).Add(gtx.Ops) op.Offset(image.Pt(-rowMarkerWidth/2, trackRowHeight)).Add(gtx.Ops)
} }
} }
return layout.Dimensions{Size: image.Pt(rowMarkerWidth, gtx.Constraints.Max.Y)} return layout.Dimensions{Size: image.Pt(rowMarkerWidth, gtx.Constraints.Max.Y)}

View File

@ -20,10 +20,10 @@ type ScrollBar struct {
tag bool tag bool
} }
func (s *ScrollBar) Layout(gtx C, width unit.Value, numItems int, pos *layout.Position) D { func (s *ScrollBar) Layout(gtx C, width unit.Dp, numItems int, pos *layout.Position) D {
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
clip.Rect{Max: gtx.Constraints.Min}.Add(gtx.Ops) defer clip.Rect{Max: gtx.Constraints.Min}.Push(gtx.Ops).Pop()
gradientSize := gtx.Px(unit.Dp(4)) gradientSize := gtx.Dp(unit.Dp(4))
var totalPixelsEstimate, scrollBarRelLength float32 var totalPixelsEstimate, scrollBarRelLength float32
switch s.Axis { switch s.Axis {
case layout.Vertical: case layout.Vertical:
@ -52,9 +52,10 @@ func (s *ScrollBar) Layout(gtx C, width unit.Value, numItems int, pos *layout.Po
} }
scrollBarRelStart := (float32(pos.First)*totalPixelsEstimate/float32(numItems) + float32(pos.Offset)) / totalPixelsEstimate scrollBarRelStart := (float32(pos.First)*totalPixelsEstimate/float32(numItems) + float32(pos.Offset)) / totalPixelsEstimate
scrWidth := gtx.Px(width) scrWidth := gtx.Dp(width)
stack := op.Save(gtx.Ops) stack := op.Offset(image.Point{}).Push(gtx.Ops)
var area clip.Stack
switch s.Axis { switch s.Axis {
case layout.Vertical: case layout.Vertical:
if scrollBarRelLength < 1 && (s.dragging || s.hovering) { if scrollBarRelLength < 1 && (s.dragging || s.hovering) {
@ -63,7 +64,7 @@ func (s *ScrollBar) Layout(gtx C, width unit.Value, numItems int, pos *layout.Po
paint.FillShape(gtx.Ops, scrollBarColor, clip.Rect{Min: image.Pt(gtx.Constraints.Min.X-scrWidth, y1), Max: image.Pt(gtx.Constraints.Min.X, y2)}.Op()) paint.FillShape(gtx.Ops, scrollBarColor, clip.Rect{Min: image.Pt(gtx.Constraints.Min.X-scrWidth, y1), Max: image.Pt(gtx.Constraints.Min.X, y2)}.Op())
} }
rect := image.Rect(gtx.Constraints.Min.X-scrWidth, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y) rect := image.Rect(gtx.Constraints.Min.X-scrWidth, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)
pointer.Rect(rect).Add(gtx.Ops) area = clip.Rect(rect).Push(gtx.Ops)
case layout.Horizontal: case layout.Horizontal:
if scrollBarRelLength < 1 && (s.dragging || s.hovering) { if scrollBarRelLength < 1 && (s.dragging || s.hovering) {
x1 := int(scrollBarRelStart * float32(gtx.Constraints.Min.X)) x1 := int(scrollBarRelStart * float32(gtx.Constraints.Min.X))
@ -71,12 +72,14 @@ func (s *ScrollBar) Layout(gtx C, width unit.Value, numItems int, pos *layout.Po
paint.FillShape(gtx.Ops, scrollBarColor, clip.Rect{Min: image.Pt(x1, gtx.Constraints.Min.Y-scrWidth), Max: image.Pt(x2, gtx.Constraints.Min.Y)}.Op()) paint.FillShape(gtx.Ops, scrollBarColor, clip.Rect{Min: image.Pt(x1, gtx.Constraints.Min.Y-scrWidth), Max: image.Pt(x2, gtx.Constraints.Min.Y)}.Op())
} }
rect := image.Rect(0, gtx.Constraints.Min.Y-scrWidth, gtx.Constraints.Min.X, gtx.Constraints.Min.Y) rect := image.Rect(0, gtx.Constraints.Min.Y-scrWidth, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)
pointer.Rect(rect).Add(gtx.Ops) area = clip.Rect(rect).Push(gtx.Ops)
} }
pointer.InputOp{Tag: &s.dragStart, pointer.InputOp{Tag: &s.dragStart,
Types: pointer.Drag | pointer.Press | pointer.Cancel | pointer.Release, Types: pointer.Drag | pointer.Press | pointer.Cancel | pointer.Release,
Grab: s.dragging,
}.Add(gtx.Ops) }.Add(gtx.Ops)
stack.Load() area.Pop()
stack.Pop()
for _, ev := range gtx.Events(&s.dragStart) { for _, ev := range gtx.Events(&s.dragStart) {
e, ok := ev.(pointer.Event) e, ok := ev.(pointer.Event)
@ -105,12 +108,13 @@ func (s *ScrollBar) Layout(gtx C, width unit.Value, numItems int, pos *layout.Po
} }
} }
pointer.PassOp{Pass: true}.Add(gtx.Ops)
rect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y) rect := image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)
pointer.Rect(rect).Add(gtx.Ops) area2 := clip.Rect(rect).Push(gtx.Ops)
defer pointer.PassOp{}.Push(gtx.Ops).Pop()
pointer.InputOp{Tag: &s.tag, pointer.InputOp{Tag: &s.tag,
Types: pointer.Enter | pointer.Leave, Types: pointer.Enter | pointer.Leave,
}.Add(gtx.Ops) }.Add(gtx.Ops)
area2.Pop()
for _, ev := range gtx.Events(&s.tag) { for _, ev := range gtx.Events(&s.tag) {
e, ok := ev.(pointer.Event) e, ok := ev.(pointer.Event)

View File

@ -5,7 +5,6 @@ import (
"math" "math"
"time" "time"
"gioui.org/f32"
"gioui.org/io/clipboard" "gioui.org/io/clipboard"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op"
@ -41,29 +40,29 @@ func (t *Tracker) layoutSongPanel(gtx C) D {
) )
} }
func (t *Tracker) layoutMenu(title string, clickable *widget.Clickable, menu *Menu, width unit.Value, items ...MenuItem) layout.Widget { func (t *Tracker) layoutMenu(title string, clickable *widget.Clickable, menu *Menu, width unit.Dp, items ...MenuItem) layout.Widget {
for clickable.Clicked() { for clickable.Clicked() {
menu.Visible = true menu.Visible = true
} }
m := PopupMenu(t.Theme, menu) m := PopupMenu(t.Theme, menu)
return func(gtx C) D { return func(gtx C) D {
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
titleBtn := material.Button(t.Theme, clickable, title) titleBtn := material.Button(t.Theme, clickable, title)
titleBtn.Color = white titleBtn.Color = white
titleBtn.Background = transparent titleBtn.Background = transparent
titleBtn.CornerRadius = unit.Dp(0) titleBtn.CornerRadius = unit.Dp(0)
dims := titleBtn.Layout(gtx) dims := titleBtn.Layout(gtx)
op.Offset(f32.Pt(0, float32(dims.Size.Y))).Add(gtx.Ops) op.Offset(image.Pt(0, dims.Size.Y)).Add(gtx.Ops)
gtx.Constraints.Max.X = gtx.Px(width) gtx.Constraints.Max.X = gtx.Dp(width)
gtx.Constraints.Max.Y = gtx.Px(unit.Dp(1000)) gtx.Constraints.Max.Y = gtx.Dp(unit.Dp(1000))
m.Layout(gtx, items...) m.Layout(gtx, items...)
return dims return dims
} }
} }
func (t *Tracker) layoutMenuBar(gtx C) D { func (t *Tracker) layoutMenuBar(gtx C) D {
gtx.Constraints.Max.Y = gtx.Px(unit.Dp(36)) gtx.Constraints.Max.Y = gtx.Dp(unit.Dp(36))
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(36)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(36))
for clickedItem, hasClicked := t.Menus[0].Clicked(); hasClicked; { for clickedItem, hasClicked := t.Menus[0].Clicked(); hasClicked; {
switch clickedItem { switch clickedItem {
@ -95,7 +94,7 @@ func (t *Tracker) layoutMenuBar(gtx C) D {
t.Alert.Update("Song copied to clipboard", Notify, time.Second*3) t.Alert.Update("Song copied to clipboard", Notify, time.Second*3)
} }
case 3: case 3:
clipboard.ReadOp{Tag: &t.Menus[1]}.Add(gtx.Ops) clipboard.ReadOp{Tag: t}.Add(gtx.Ops)
case 4: case 4:
t.RemoveUnusedData() t.RemoveUnusedData()
} }
@ -150,8 +149,8 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
layout.Rigid(func(gtx layout.Context) layout.Dimensions { layout.Rigid(func(gtx layout.Context) layout.Dimensions {
t.SongLength.Value = t.Song().Score.Length t.SongLength.Value = t.Song().Score.Length
numStyle := NumericUpDown(t.Theme, t.SongLength, 1, math.MaxInt32) numStyle := NumericUpDown(t.Theme, t.SongLength, 1, math.MaxInt32)
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(20))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(70))
dims := in.Layout(gtx, numStyle.Layout) dims := in.Layout(gtx, numStyle.Layout)
t.SetSongLength(t.SongLength.Value) t.SetSongLength(t.SongLength.Value)
return dims return dims
@ -164,8 +163,8 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
layout.Rigid(func(gtx layout.Context) layout.Dimensions { layout.Rigid(func(gtx layout.Context) layout.Dimensions {
t.BPM.Value = t.Song().BPM t.BPM.Value = t.Song().BPM
numStyle := NumericUpDown(t.Theme, t.BPM, 1, 999) numStyle := NumericUpDown(t.Theme, t.BPM, 1, 999)
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(20))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(70))
dims := in.Layout(gtx, numStyle.Layout) dims := in.Layout(gtx, numStyle.Layout)
t.SetBPM(t.BPM.Value) t.SetBPM(t.BPM.Value)
return dims return dims
@ -178,8 +177,8 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
layout.Rigid(func(gtx layout.Context) layout.Dimensions { layout.Rigid(func(gtx layout.Context) layout.Dimensions {
t.RowsPerPattern.Value = t.Song().Score.RowsPerPattern t.RowsPerPattern.Value = t.Song().Score.RowsPerPattern
numStyle := NumericUpDown(t.Theme, t.RowsPerPattern, 1, 255) numStyle := NumericUpDown(t.Theme, t.RowsPerPattern, 1, 255)
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(20))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(70))
dims := in.Layout(gtx, numStyle.Layout) dims := in.Layout(gtx, numStyle.Layout)
t.SetRowsPerPattern(t.RowsPerPattern.Value) t.SetRowsPerPattern(t.RowsPerPattern.Value)
return dims return dims
@ -192,8 +191,8 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
layout.Rigid(func(gtx layout.Context) layout.Dimensions { layout.Rigid(func(gtx layout.Context) layout.Dimensions {
t.RowsPerBeat.Value = t.Song().RowsPerBeat t.RowsPerBeat.Value = t.Song().RowsPerBeat
numStyle := NumericUpDown(t.Theme, t.RowsPerBeat, 1, 32) numStyle := NumericUpDown(t.Theme, t.RowsPerBeat, 1, 32)
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(20))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(70))
dims := in.Layout(gtx, numStyle.Layout) dims := in.Layout(gtx, numStyle.Layout)
t.SetRowsPerBeat(t.RowsPerBeat.Value) t.SetRowsPerBeat(t.RowsPerBeat.Value)
return dims return dims
@ -206,8 +205,8 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
layout.Rigid(func(gtx layout.Context) layout.Dimensions { layout.Rigid(func(gtx layout.Context) layout.Dimensions {
numStyle := NumericUpDown(t.Theme, t.Step, 0, 8) numStyle := NumericUpDown(t.Theme, t.Step, 0, 8)
numStyle.UnitsPerStep = unit.Dp(20) numStyle.UnitsPerStep = unit.Dp(20)
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(20))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(70))
dims := in.Layout(gtx, numStyle.Layout) dims := in.Layout(gtx, numStyle.Layout)
return dims return dims
}), }),

View File

@ -3,10 +3,10 @@ package gioui
import ( import (
"image" "image"
"gioui.org/f32"
"gioui.org/io/pointer" "gioui.org/io/pointer"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op"
"gioui.org/op/clip"
"gioui.org/unit" "gioui.org/unit"
) )
@ -15,7 +15,7 @@ type Split struct {
// 0 is center, -1 completely to the left, 1 completely to the right. // 0 is center, -1 completely to the left, 1 completely to the right.
Ratio float32 Ratio float32
// Bar is the width for resizing the layout // Bar is the width for resizing the layout
Bar unit.Value Bar unit.Dp
// Axis is the split direction: layout.Horizontal splits the view in left // Axis is the split direction: layout.Horizontal splits the view in left
// and right, layout.Vertical splits the view in top and bottom // and right, layout.Vertical splits the view in top and bottom
Axis layout.Axis Axis layout.Axis
@ -28,9 +28,9 @@ type Split struct {
var defaultBarWidth = unit.Dp(10) var defaultBarWidth = unit.Dp(10)
func (s *Split) Layout(gtx layout.Context, first, second layout.Widget) layout.Dimensions { func (s *Split) Layout(gtx layout.Context, first, second layout.Widget) layout.Dimensions {
bar := gtx.Px(s.Bar) bar := gtx.Dp(s.Bar)
if bar <= 1 { if bar <= 1 {
bar = gtx.Px(defaultBarWidth) bar = gtx.Dp(defaultBarWidth)
} }
var coord int var coord int
@ -48,7 +48,6 @@ func (s *Split) Layout(gtx layout.Context, first, second layout.Widget) layout.D
{ // handle input { // handle input
// Avoid affecting the input tree with pointer events. // Avoid affecting the input tree with pointer events.
stack := op.Save(gtx.Ops)
for _, ev := range gtx.Events(s) { for _, ev := range gtx.Events(s) {
e, ok := ev.(pointer.Event) e, ok := ev.(pointer.Event)
@ -123,43 +122,43 @@ func (s *Split) Layout(gtx layout.Context, first, second layout.Widget) layout.D
} else { } else {
barRect = image.Rect(0, firstSize, gtx.Constraints.Max.X, secondOffset) barRect = image.Rect(0, firstSize, gtx.Constraints.Max.X, secondOffset)
} }
pointer.Rect(barRect).Add(gtx.Ops) area := clip.Rect(barRect).Push(gtx.Ops)
pointer.InputOp{Tag: s, pointer.InputOp{Tag: s,
Types: pointer.Press | pointer.Drag | pointer.Release, Types: pointer.Press | pointer.Drag | pointer.Release,
Grab: s.drag, Grab: s.drag,
}.Add(gtx.Ops) }.Add(gtx.Ops)
area.Pop()
stack.Load()
} }
{ {
gtx := gtx gtx := gtx
stack := op.Save(gtx.Ops)
if s.Axis == layout.Horizontal { if s.Axis == layout.Horizontal {
gtx.Constraints = layout.Exact(image.Pt(firstSize, gtx.Constraints.Max.Y)) gtx.Constraints = layout.Exact(image.Pt(firstSize, gtx.Constraints.Max.Y))
} else { } else {
gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X, firstSize)) gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X, firstSize))
} }
area := clip.Rect(image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)).Push(gtx.Ops)
first(gtx) first(gtx)
area.Pop()
stack.Load()
} }
{ {
gtx := gtx gtx := gtx
stack := op.Save(gtx.Ops)
var transform op.TransformStack
if s.Axis == layout.Horizontal { if s.Axis == layout.Horizontal {
op.Offset(f32.Pt(float32(secondOffset), 0)).Add(gtx.Ops) transform = op.Offset(image.Pt(secondOffset, 0)).Push(gtx.Ops)
gtx.Constraints = layout.Exact(image.Pt(secondSize, gtx.Constraints.Max.Y)) gtx.Constraints = layout.Exact(image.Pt(secondSize, gtx.Constraints.Max.Y))
} else { } else {
op.Offset(f32.Pt(0, float32(secondOffset))).Add(gtx.Ops) transform = op.Offset(image.Pt(0, secondOffset)).Push(gtx.Ops)
gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X, secondSize)) gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X, secondSize))
} }
area := clip.Rect(image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)).Push(gtx.Ops)
second(gtx) second(gtx)
area.Pop()
stack.Load() transform.Pop()
} }
return layout.Dimensions{Size: gtx.Constraints.Max} return layout.Dimensions{Size: gtx.Constraints.Max}

View File

@ -9,7 +9,7 @@ import (
) )
var fontCollection []text.FontFace = gofont.Collection() var fontCollection []text.FontFace = gofont.Collection()
var textShaper = text.NewCache(fontCollection) var textShaper = text.NewShaper(fontCollection)
var white = color.NRGBA{R: 255, G: 255, B: 255, A: 255} var white = color.NRGBA{R: 255, G: 255, B: 255, A: 255}
var black = color.NRGBA{R: 0, G: 0, B: 0, A: 255} var black = color.NRGBA{R: 0, G: 0, B: 0, A: 255}
@ -34,7 +34,7 @@ var rowMarkerPatternTextColor = secondaryColor
var rowMarkerRowTextColor = mediumEmphasisTextColor var rowMarkerRowTextColor = mediumEmphasisTextColor
var trackerFont = fontCollection[6].Font var trackerFont = fontCollection[6].Font
var trackerFontSize = unit.Px(16) var trackerFontSize = unit.Sp(16)
var trackerInactiveTextColor = highEmphasisTextColor var trackerInactiveTextColor = highEmphasisTextColor
var trackerActiveTextColor = color.NRGBA{R: 255, G: 255, B: 130, A: 255} var trackerActiveTextColor = color.NRGBA{R: 255, G: 255, B: 130, A: 255}
var trackerPlayColor = color.NRGBA{R: 55, G: 55, B: 61, A: 255} var trackerPlayColor = color.NRGBA{R: 55, G: 55, B: 61, A: 255}

View File

@ -6,7 +6,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"gioui.org/f32"
"gioui.org/io/key" "gioui.org/io/key"
"gioui.org/io/pointer" "gioui.org/io/pointer"
"gioui.org/layout" "gioui.org/layout"
@ -58,17 +57,23 @@ func (te *TrackEditor) Focus() {
} }
func (te *TrackEditor) Focused() bool { func (te *TrackEditor) Focused() bool {
return te.focused return te.focused || te.ChildFocused()
} }
func (te *TrackEditor) ChildFocused() bool {
return te.AddOctaveBtn.Focused() || te.AddSemitoneBtn.Focused() || te.DeleteTrackBtn.Focused() || te.NewTrackBtn.Focused() || te.NoteOffBtn.Focused() || te.SubtractOctaveBtn.Focused() || te.SubtractSemitoneBtn.Focused() || te.SubtractSemitoneBtn.Focused() || te.SubtractSemitoneBtn.Focused()
}
var trackerEditorKeys key.Set = "+|-|←|→|↑|↓|Ctrl-←|Ctrl-→|Ctrl-↑|Ctrl-↓|Shift-←|Shift-→|Shift-↑|Shift-↓|⏎|⇱|⇲|⌫|⌦|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|,|."
func (te *TrackEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions { func (te *TrackEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions {
for _, e := range gtx.Events(&te.tag) { for _, e := range gtx.Events(te) {
switch e := e.(type) { switch e := e.(type) {
case key.FocusEvent: case key.FocusEvent:
te.focused = e.Focus te.focused = e.Focus
case pointer.Event: case pointer.Event:
if e.Type == pointer.Press { if e.Type == pointer.Press {
key.FocusOp{Tag: &te.tag}.Add(gtx.Ops) key.FocusOp{Tag: te}.Add(gtx.Ops)
} }
case key.Event: case key.Event:
switch e.State { switch e.State {
@ -170,17 +175,18 @@ func (te *TrackEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions
t.SetCursor(t.Cursor().AddRows(t.Step.Value)) t.SetCursor(t.Cursor().AddRows(t.Step.Value))
t.SetSelectionCorner(t.Cursor()) t.SetSelectionCorner(t.Cursor())
} }
t.JammingPressed(e)
case key.Release: case key.Release:
t.JammingReleased(e) if noteID, ok := t.KeyPlaying[e.Name]; ok {
t.NoteOff(noteID)
delete(t.KeyPlaying, e.Name)
}
} }
} }
} }
if te.requestFocus { if te.requestFocus || te.ChildFocused() {
te.requestFocus = false te.requestFocus = false
key.FocusOp{Tag: &te.tag}.Add(gtx.Ops) key.FocusOp{Tag: te}.Add(gtx.Ops)
} }
rowMarkers := layout.Rigid(t.layoutRowMarkers) rowMarkers := layout.Rigid(t.layoutRowMarkers)
@ -235,14 +241,14 @@ func (te *TrackEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions
in := layout.UniformInset(unit.Dp(1)) in := layout.UniformInset(unit.Dp(1))
voiceUpDown := func(gtx C) D { voiceUpDown := func(gtx C) D {
numStyle := NumericUpDown(t.Theme, te.TrackVoices, 1, t.MaxTrackVoices()) numStyle := NumericUpDown(t.Theme, te.TrackVoices, 1, t.MaxTrackVoices())
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(20))
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(70))
return in.Layout(gtx, numStyle.Layout) return in.Layout(gtx, numStyle.Layout)
} }
t.TrackHexCheckBox.Value = t.Song().Score.Tracks[t.Cursor().Track].Effect t.TrackHexCheckBox.Value = t.Song().Score.Tracks[t.Cursor().Track].Effect
hexCheckBoxStyle := material.CheckBox(t.Theme, t.TrackHexCheckBox, "Hex") hexCheckBoxStyle := material.CheckBox(t.Theme, t.TrackHexCheckBox, "Hex")
dims := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, dims := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func(gtx C) D { return layout.Dimensions{Size: image.Pt(gtx.Px(unit.Dp(12)), 0)} }), layout.Rigid(func(gtx C) D { return layout.Dimensions{Size: image.Pt(gtx.Dp(unit.Dp(12)), 0)} }),
layout.Rigid(addSemitoneBtnStyle.Layout), layout.Rigid(addSemitoneBtnStyle.Layout),
layout.Rigid(subtractSemitoneBtnStyle.Layout), layout.Rigid(subtractSemitoneBtnStyle.Layout),
layout.Rigid(addOctaveBtnStyle.Layout), layout.Rigid(addOctaveBtnStyle.Layout),
@ -260,16 +266,16 @@ func (te *TrackEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions
} }
rect := image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y) rect := image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)
pointer.Rect(rect).Add(gtx.Ops) area := clip.Rect(rect).Push(gtx.Ops)
pointer.InputOp{Tag: &te.tag, pointer.InputOp{Tag: te,
Types: pointer.Press, Types: pointer.Press,
}.Add(gtx.Ops) }.Add(gtx.Ops)
key.InputOp{Tag: &te.tag}.Add(gtx.Ops) key.InputOp{Tag: te, Keys: trackerEditorKeys}.Add(gtx.Ops)
return Surface{Gray: 24, Focus: te.focused}.Layout(gtx, func(gtx C) D { dims := Surface{Gray: 24, Focus: te.Focused()}.Layout(gtx, func(gtx C) D {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx, return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx C) D { layout.Rigid(func(gtx C) D {
return Surface{Gray: 37, Focus: te.focused, FitSize: true}.Layout(gtx, menu) return Surface{Gray: 37, Focus: te.Focused(), FitSize: true}.Layout(gtx, menu)
}), }),
layout.Flexed(1, func(gtx C) D { layout.Flexed(1, func(gtx C) D {
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
@ -280,11 +286,14 @@ func (te *TrackEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions
}), }),
) )
}) })
area.Pop()
return dims
} }
func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D { func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D {
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
clip.Rect{Max: gtx.Constraints.Max}.Add(gtx.Ops) defer clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops).Pop()
cursorSongRow := t.Cursor().Pattern*t.Song().Score.RowsPerPattern + t.Cursor().Row cursorSongRow := t.Cursor().Pattern*t.Song().Score.RowsPerPattern + t.Cursor().Row
for _, ev := range gtx.Events(&te.trackJumpPointerTag) { for _, ev := range gtx.Events(&te.trackJumpPointerTag) {
e, ok := ev.(pointer.Event) e, ok := ev.(pointer.Event)
@ -302,11 +311,12 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D {
} }
} }
rect := image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y) rect := image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)
pointer.Rect(rect).Add(gtx.Ops) area := clip.Rect(rect).Push(gtx.Ops)
pointer.InputOp{Tag: &te.trackJumpPointerTag, pointer.InputOp{Tag: &te.trackJumpPointerTag,
Types: pointer.Press, Types: pointer.Press,
}.Add(gtx.Ops) }.Add(gtx.Ops)
stack := op.Save(gtx.Ops) area.Pop()
stack := op.Offset(image.Point{}).Push(gtx.Ops)
curVoice := 0 curVoice := 0
for _, trk := range t.Song().Score.Tracks { for _, trk := range t.Song().Score.Tracks {
gtx := gtx gtx := gtx
@ -341,14 +351,14 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D {
} }
} }
gtx.Constraints.Max.X = trackColWidth gtx.Constraints.Max.X = trackColWidth
LabelStyle{Alignment: layout.N, Text: instrName, FontSize: unit.Dp(12), Color: mediumEmphasisTextColor}.Layout(gtx) LabelStyle{Alignment: layout.N, Text: instrName, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor}.Layout(gtx)
op.Offset(f32.Pt(trackColWidth, 0)).Add(gtx.Ops) op.Offset(image.Point{trackColWidth, 0}).Add(gtx.Ops)
curVoice += trk.NumVoices curVoice += trk.NumVoices
} }
stack.Load() stack.Pop()
op.Offset(f32.Pt(0, float32(gtx.Constraints.Max.Y-trackRowHeight)/2)).Add(gtx.Ops) op.Offset(image.Point{0, (gtx.Constraints.Max.Y - trackRowHeight) / 2}).Add(gtx.Ops)
op.Offset(f32.Pt(0, (-1*trackRowHeight)*float32(cursorSongRow))).Add(gtx.Ops) op.Offset(image.Point{0, int((-1 * trackRowHeight) * (cursorSongRow))}).Add(gtx.Ops)
if te.focused || t.OrderEditor.Focused() { if te.Focused() || t.OrderEditor.Focused() {
x1, y1 := t.Cursor().Track, t.Cursor().Pattern x1, y1 := t.Cursor().Track, t.Cursor().Pattern
x2, y2 := t.SelectionCorner().Track, t.SelectionCorner().Pattern x2, y2 := t.SelectionCorner().Track, t.SelectionCorner().Pattern
if x1 > x2 { if x1 > x2 {
@ -365,7 +375,7 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D {
y2 *= trackRowHeight * t.Song().Score.RowsPerPattern y2 *= trackRowHeight * t.Song().Score.RowsPerPattern
paint.FillShape(gtx.Ops, inactiveSelectionColor, clip.Rect{Min: image.Pt(x1, y1), Max: image.Pt(x2, y2)}.Op()) paint.FillShape(gtx.Ops, inactiveSelectionColor, clip.Rect{Min: image.Pt(x1, y1), Max: image.Pt(x2, y2)}.Op())
} }
if te.focused { if te.Focused() {
x1, y1 := t.Cursor().Track, t.Cursor().Pattern*t.Song().Score.RowsPerPattern+t.Cursor().Row x1, y1 := t.Cursor().Track, t.Cursor().Pattern*t.Song().Score.RowsPerPattern+t.Cursor().Row
x2, y2 := t.SelectionCorner().Track, t.SelectionCorner().Pattern*t.Song().Score.RowsPerPattern+t.SelectionCorner().Row x2, y2 := t.SelectionCorner().Track, t.SelectionCorner().Pattern*t.Song().Score.RowsPerPattern+t.SelectionCorner().Row
if x1 > x2 { if x1 > x2 {
@ -401,27 +411,27 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D {
if l := t.Song().Score.LengthInRows(); lastRow >= l { if l := t.Song().Score.LengthInRows(); lastRow >= l {
lastRow = l - 1 lastRow = l - 1
} }
op.Offset(f32.Pt(0, float32(trackRowHeight*firstRow))).Add(gtx.Ops) op.Offset(image.Point{0, trackRowHeight * firstRow}).Add(gtx.Ops)
for trkIndex, trk := range t.Song().Score.Tracks { for trkIndex, trk := range t.Song().Score.Tracks {
stack := op.Save(gtx.Ops) stack := op.Offset(image.Point{}).Push(gtx.Ops)
for row := firstRow; row <= lastRow; row++ { for row := firstRow; row <= lastRow; row++ {
pat := row / t.Song().Score.RowsPerPattern pat := row / t.Song().Score.RowsPerPattern
patRow := row % t.Song().Score.RowsPerPattern patRow := row % t.Song().Score.RowsPerPattern
s := trk.Order.Get(pat) s := trk.Order.Get(pat)
if s < 0 { if s < 0 {
op.Offset(f32.Pt(0, trackRowHeight)).Add(gtx.Ops) op.Offset(image.Point{0, trackRowHeight}).Add(gtx.Ops)
continue continue
} }
if s >= 0 && patRow == 0 { if s >= 0 && patRow == 0 {
paint.ColorOp{Color: trackerPatMarker}.Add(gtx.Ops) paint.ColorOp{Color: trackerPatMarker}.Add(gtx.Ops)
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, patternIndexToString(s)) widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, patternIndexToString(s), op.CallOp{})
} }
if s >= 0 && patRow == 1 && t.IsPatternUnique(trkIndex, s) { if s >= 0 && patRow == 1 && t.IsPatternUnique(trkIndex, s) {
paint.ColorOp{Color: mediumEmphasisTextColor}.Add(gtx.Ops) paint.ColorOp{Color: mediumEmphasisTextColor}.Add(gtx.Ops)
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, "*") widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, "*", op.CallOp{})
} }
op.Offset(f32.Pt(patmarkWidth, 0)).Add(gtx.Ops) op.Offset(image.Point{patmarkWidth, 0}).Add(gtx.Ops)
if te.focused && t.Cursor().Row == patRow && t.Cursor().Pattern == pat { if te.Focused() && t.Cursor().Row == patRow && t.Cursor().Pattern == pat {
paint.ColorOp{Color: trackerActiveTextColor}.Add(gtx.Ops) paint.ColorOp{Color: trackerActiveTextColor}.Add(gtx.Ops)
} else { } else {
paint.ColorOp{Color: trackerInactiveTextColor}.Add(gtx.Ops) paint.ColorOp{Color: trackerInactiveTextColor}.Add(gtx.Ops)
@ -440,14 +450,14 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D {
default: default:
text = fmt.Sprintf("%02x", c) text = fmt.Sprintf("%02x", c)
} }
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(text)) widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(text), op.CallOp{})
} else { } else {
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, tracker.NoteStr(c)) widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, tracker.NoteStr(c), op.CallOp{})
} }
op.Offset(f32.Pt(-patmarkWidth, trackRowHeight)).Add(gtx.Ops) op.Offset(image.Point{-patmarkWidth, trackRowHeight}).Add(gtx.Ops)
} }
stack.Load() stack.Pop()
op.Offset(f32.Pt(trackColWidth, 0)).Add(gtx.Ops) op.Offset(image.Point{trackColWidth, 0}).Add(gtx.Ops)
} }
return layout.Dimensions{Size: gtx.Constraints.Max} return layout.Dimensions{Size: gtx.Constraints.Max}
} }

View File

@ -8,8 +8,6 @@ import (
"gioui.org/app" "gioui.org/app"
"gioui.org/font/gofont" "gioui.org/font/gofont"
"gioui.org/io/clipboard"
"gioui.org/io/key"
"gioui.org/io/system" "gioui.org/io/system"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op" "gioui.org/op"
@ -192,18 +190,9 @@ mainloop:
app.Title("Sointu Tracker"), app.Title("Sointu Tracker"),
) )
} }
case key.Event:
if t.KeyEvent(e, w) {
w.Invalidate()
}
case clipboard.Event:
err := t.UnmarshalContent([]byte(e.Text))
if err == nil {
w.Invalidate()
}
case system.FrameEvent: case system.FrameEvent:
gtx := layout.NewContext(&ops, e) gtx := layout.NewContext(&ops, e)
t.Layout(gtx) t.Layout(gtx, w)
e.Frame(gtx.Ops) e.Frame(gtx.Ops)
} }
} }
@ -211,5 +200,5 @@ mainloop:
break mainloop break mainloop
} }
} }
w.Close() w.Perform(system.ActionClose)
} }

View File

@ -3,7 +3,6 @@ package gioui
import ( import (
"image" "image"
"gioui.org/f32"
"gioui.org/op" "gioui.org/op"
"gioui.org/op/clip" "gioui.org/op/clip"
"gioui.org/op/paint" "gioui.org/op/paint"
@ -17,9 +16,9 @@ type VuMeter struct {
} }
func (v VuMeter) Layout(gtx C) D { func (v VuMeter) Layout(gtx C) D {
defer op.Save(gtx.Ops).Load() defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
gtx.Constraints.Max.Y = gtx.Px(unit.Dp(12)) gtx.Constraints.Max.Y = gtx.Dp(unit.Dp(12))
height := gtx.Px(unit.Dp(6)) height := gtx.Dp(unit.Dp(6))
for j := 0; j < 2; j++ { for j := 0; j < 2; j++ {
value := float32(v.Volume.Average[j]) + v.Range value := float32(v.Volume.Average[j]) + v.Range
if value > 0 { if value > 0 {
@ -41,7 +40,7 @@ func (v VuMeter) Layout(gtx C) D {
} }
paint.FillShape(gtx.Ops, color, clip.Rect(image.Rect(x-1, 0, x, height)).Op()) paint.FillShape(gtx.Ops, color, clip.Rect(image.Rect(x-1, 0, x, height)).Op())
} }
op.Offset(f32.Pt(0, float32(height))).Add(gtx.Ops) op.Offset(image.Point{0, height}).Add(gtx.Ops)
} }
return D{Size: gtx.Constraints.Max} return D{Size: gtx.Constraints.Max}
} }