mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-25 08:24:50 -04:00
97 lines
2.4 KiB
Go
97 lines
2.4 KiB
Go
package gioui
|
|
|
|
import (
|
|
"image"
|
|
"image/color"
|
|
"math"
|
|
|
|
"gioui.org/f32"
|
|
"gioui.org/op/clip"
|
|
"gioui.org/op/paint"
|
|
"gioui.org/unit"
|
|
"github.com/vsariola/sointu/tracker"
|
|
)
|
|
|
|
const numSignalsDrawn = 8
|
|
|
|
type (
|
|
SignalRailStyle struct {
|
|
Color color.NRGBA
|
|
LineWidth unit.Dp
|
|
PortDiameter unit.Dp
|
|
PortColor color.NRGBA
|
|
}
|
|
|
|
SignalRailWidget struct {
|
|
Style *SignalRailStyle
|
|
Signal tracker.Signal
|
|
Width unit.Dp
|
|
Height unit.Dp
|
|
}
|
|
)
|
|
|
|
func SignalRail(th *Theme, signal tracker.Signal) SignalRailWidget {
|
|
return SignalRailWidget{
|
|
Style: &th.SignalRail,
|
|
Signal: signal,
|
|
Width: th.UnitEditor.Width,
|
|
Height: th.UnitEditor.Height,
|
|
}
|
|
}
|
|
|
|
func (s SignalRailWidget) Layout(gtx C) D {
|
|
w := gtx.Dp(s.Width)
|
|
h := gtx.Dp(s.Height)
|
|
l := gtx.Dp(s.Style.LineWidth)
|
|
d := gtx.Dp(s.Style.PortDiameter)
|
|
c := max(l, d) / 2
|
|
stride := (w - c*2) / numSignalsDrawn
|
|
var path clip.Path
|
|
path.Begin(gtx.Ops)
|
|
// Draw pass through signals
|
|
for i := range min(numSignalsDrawn, s.Signal.PassThrough) {
|
|
x := float32(i*stride + c)
|
|
path.MoveTo(f32.Pt(x, 0))
|
|
path.LineTo(f32.Pt(x, float32(h)))
|
|
}
|
|
// Draw the routing of input signals
|
|
for i := range min(len(s.Signal.StackUse.Inputs), numSignalsDrawn-s.Signal.PassThrough) {
|
|
input := s.Signal.StackUse.Inputs[i]
|
|
x1 := float32((i+s.Signal.PassThrough)*stride + c)
|
|
for _, link := range input {
|
|
x2 := float32((link+s.Signal.PassThrough)*stride + c)
|
|
path.MoveTo(f32.Pt(x1, 0))
|
|
path.LineTo(f32.Pt(x2, float32(h/2)))
|
|
}
|
|
}
|
|
// Draw the routing of output signals
|
|
for i := range min(s.Signal.StackUse.NumOutputs, numSignalsDrawn-s.Signal.PassThrough) {
|
|
x := float32((i+s.Signal.PassThrough)*stride + c)
|
|
path.MoveTo(f32.Pt(x, float32(h/2)))
|
|
path.LineTo(f32.Pt(x, float32(h)))
|
|
}
|
|
paint.FillShape(gtx.Ops, s.Style.Color,
|
|
clip.Stroke{
|
|
Path: path.End(),
|
|
Width: float32(l),
|
|
}.Op())
|
|
// Draw the circles on modified signals
|
|
|
|
for i := range min(len(s.Signal.StackUse.Modifies), numSignalsDrawn-s.Signal.PassThrough) {
|
|
if !s.Signal.StackUse.Modifies[i] {
|
|
continue
|
|
}
|
|
var circle clip.Path
|
|
x := float32((i + s.Signal.PassThrough) * stride)
|
|
circle.Begin(gtx.Ops)
|
|
circle.MoveTo(f32.Pt(x, float32(h/2)))
|
|
f := f32.Pt(x+float32(c), float32(h/2))
|
|
circle.ArcTo(f, f, float32(2*math.Pi))
|
|
p := clip.Outline{Path: circle.End()}.Op().Push(gtx.Ops)
|
|
paint.ColorOp{Color: s.Style.PortColor}.Add(gtx.Ops)
|
|
paint.PaintOp{}.Add(gtx.Ops)
|
|
p.Pop()
|
|
}
|
|
return D{Size: image.Pt(w, h)}
|
|
}
|