From 18d198d76483008ca2ad38cb26bee92fa42e3f69 Mon Sep 17 00:00:00 2001 From: "5684185+vsariola@users.noreply.github.com" <5684185+vsariola@users.noreply.github.com> Date: Tue, 24 Jun 2025 19:59:31 +0300 Subject: [PATCH] refactor(tracker/gioui): bind Alerts to Model during Layout --- tracker/gioui/{popup_alert.go => alerts.go} | 71 +++++++++++++-------- tracker/gioui/theme.go | 6 +- tracker/gioui/theme.yml | 2 + tracker/gioui/tracker.go | 7 +- 4 files changed, 52 insertions(+), 34 deletions(-) rename tracker/gioui/{popup_alert.go => alerts.go} (50%) diff --git a/tracker/gioui/popup_alert.go b/tracker/gioui/alerts.go similarity index 50% rename from tracker/gioui/popup_alert.go rename to tracker/gioui/alerts.go index ee316cd..78137b9 100644 --- a/tracker/gioui/popup_alert.go +++ b/tracker/gioui/alerts.go @@ -9,44 +9,63 @@ import ( "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" - "gioui.org/unit" "github.com/vsariola/sointu/tracker" ) -type PopupAlert struct { - alerts *tracker.Alerts - prevUpdate time.Time +type ( + AlertsState struct { + prevUpdate time.Time + } + + AlertStyle struct { + Bg color.NRGBA + Text LabelStyle + } + + AlertStyles struct { + Info AlertStyle + Warning AlertStyle + Error AlertStyle + Margin layout.Inset + Inset layout.Inset + } + + AlertsWidget struct { + Theme *Theme + Model *tracker.Alerts + State *AlertsState + } +) + +func NewAlertsState() *AlertsState { + return &AlertsState{prevUpdate: time.Now()} } -type PopupAlertStyle struct { - Bg color.NRGBA - Text LabelStyle +func Alerts(m *tracker.Alerts, th *Theme, st *AlertsState) AlertsWidget { + return AlertsWidget{ + Theme: th, + Model: m, + State: st, + } } -var alertMargin = layout.UniformInset(unit.Dp(6)) -var alertInset = layout.UniformInset(unit.Dp(6)) - -func NewPopupAlert(alerts *tracker.Alerts) *PopupAlert { - return &PopupAlert{alerts: alerts, prevUpdate: time.Now()} -} - -func (a *PopupAlert) Layout(gtx C, th *Theme) D { +func (a *AlertsWidget) Layout(gtx C) D { now := time.Now() - if a.alerts.Update(now.Sub(a.prevUpdate)) { + if a.Model.Update(now.Sub(a.State.prevUpdate)) { gtx.Execute(op.InvalidateCmd{At: now.Add(50 * time.Millisecond)}) } - a.prevUpdate = now + a.State.prevUpdate = now var totalY float64 = float64(gtx.Dp(38)) - for _, alert := range a.alerts.Iterate { - var alertStyle *PopupAlertStyle + for _, alert := range a.Model.Iterate { + var alertStyle *AlertStyle switch alert.Priority { case tracker.Warning: - alertStyle = &th.Alert.Warning + alertStyle = &a.Theme.Alert.Warning case tracker.Error: - alertStyle = &th.Alert.Error + alertStyle = &a.Theme.Alert.Error default: - alertStyle = &th.Alert.Info + alertStyle = &a.Theme.Alert.Info } bgWidget := func(gtx C) D { paint.FillShape(gtx.Ops, alertStyle.Bg, clip.Rect{ @@ -54,8 +73,8 @@ func (a *PopupAlert) Layout(gtx C, th *Theme) D { }.Op()) return D{Size: gtx.Constraints.Min} } - labelStyle := Label(th, &alertStyle.Text, alert.Message) - alertMargin.Layout(gtx, func(gtx C) D { + labelStyle := Label(a.Theme, &alertStyle.Text, alert.Message) + a.Theme.Alert.Margin.Layout(gtx, func(gtx C) D { return layout.S.Layout(gtx, func(gtx C) D { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() gtx.Constraints.Min.X = gtx.Constraints.Max.X @@ -63,11 +82,11 @@ func (a *PopupAlert) Layout(gtx C, th *Theme) D { dims := layout.Stack{Alignment: layout.Center}.Layout(gtx, layout.Expanded(bgWidget), layout.Stacked(func(gtx C) D { - return alertInset.Layout(gtx, labelStyle.Layout) + return a.Theme.Alert.Inset.Layout(gtx, labelStyle.Layout) }), ) macro := recording.Stop() - delta := float64(dims.Size.Y + gtx.Dp(alertMargin.Bottom)) + delta := float64(dims.Size.Y + gtx.Dp(a.Theme.Alert.Margin.Bottom)) op.Offset(image.Point{0, int(-totalY*alert.FadeLevel + delta*(1-alert.FadeLevel))}).Add((gtx.Ops)) totalY += delta macro.Add(gtx.Ops) diff --git a/tracker/gioui/theme.go b/tracker/gioui/theme.go index bddeb52..5fb0c3a 100644 --- a/tracker/gioui/theme.go +++ b/tracker/gioui/theme.go @@ -35,11 +35,7 @@ type Theme struct { ErrorColor color.NRGBA Bg color.NRGBA } - Alert struct { - Warning PopupAlertStyle - Error PopupAlertStyle - Info PopupAlertStyle - } + Alert AlertStyles NoteEditor struct { TrackTitle LabelStyle OrderRow LabelStyle diff --git a/tracker/gioui/theme.yml b/tracker/gioui/theme.yml index 54786b9..1d2233d 100644 --- a/tracker/gioui/theme.yml +++ b/tracker/gioui/theme.yml @@ -110,6 +110,8 @@ alert: info: bg: { r: 50, g: 50, b: 51, a: 255 } text: { textsize: 16, color: *highemphasis, shadowcolor: *black } + margin: { top: 6, bottom: 6, left: 6, right: 6 } + inset: { top: 6, bottom: 6, left: 6, right: 6 } ordereditor: tracktitle: { textsize: 12, color: *mediumemphasis } rowtitle: diff --git a/tracker/gioui/tracker.go b/tracker/gioui/tracker.go index e5f5109..5b30d0d 100644 --- a/tracker/gioui/tracker.go +++ b/tracker/gioui/tracker.go @@ -37,7 +37,7 @@ type ( BottomHorizontalSplit *Split VerticalSplit *Split KeyNoteMap Keyboard[key.Name] - PopupAlert *PopupAlert + PopupAlert *AlertsState Zoom int DialogState *DialogState @@ -96,7 +96,7 @@ func NewTracker(model *tracker.Model) *Tracker { } t.SongPanel = NewSongPanel(t) t.KeyNoteMap = MakeKeyboard[key.Name](model.Broker()) - t.PopupAlert = NewPopupAlert(model.Alerts()) + t.PopupAlert = NewAlertsState() var warn error if t.Theme, warn = NewTheme(); warn != nil { model.Alerts().AddAlert(tracker.Alert{ @@ -222,7 +222,8 @@ func (t *Tracker) Layout(gtx layout.Context, w *app.Window) { t.layoutTop, t.layoutBottom) } - t.PopupAlert.Layout(gtx, t.Theme) + alerts := Alerts(t.Alerts(), t.Theme, t.PopupAlert) + alerts.Layout(gtx) t.showDialog(gtx) // this is the top level input handler for the whole app // it handles all the global key events and clipboard events