From b9837def5ce054a0a7daacf71840529e790afae7 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Mon, 2 Oct 2023 17:22:12 -0500 Subject: [PATCH] widget: [API] move Decorations state update to Actions Similar to a previous change for Clickable and Bool this change separates state changes from Decorations.Layout to Actions so that access may happen before Layout. Signed-off-by: Elias Naur --- app/window.go | 2 +- widget/decorations.go | 52 +++++++++++++++++++--------------- widget/material/decorations.go | 2 +- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/app/window.go b/app/window.go index 342d2f62..20f92c48 100644 --- a/app/window.go +++ b/app/window.go @@ -1024,7 +1024,7 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) (size, offse } style.Layout(gtx) // Update the window based on the actions on the decorations. - w.Perform(deco.Actions()) + w.Perform(deco.Update(gtx)) // Offset to place the frame content below the decorations. decoHeight := gtx.Dp(w.decorations.Config.decoHeight) if w.decorations.currentHeight != decoHeight { diff --git a/widget/decorations.go b/widget/decorations.go index 184c38d9..299fc415 100644 --- a/widget/decorations.go +++ b/widget/decorations.go @@ -12,12 +12,11 @@ import ( // Decorations handles the states of window decorations. type Decorations struct { - clicks []Clickable + clicks map[int]*Clickable resize [8]struct { gesture.Hover gesture.Drag } - actions system.Action maximized bool } @@ -30,27 +29,18 @@ func (d *Decorations) LayoutMove(gtx layout.Context, w layout.Widget) layout.Dim } // Clickable returns the clickable for the given single action. -func (d *Decorations) Clickable(gtx layout.Context, action system.Action) *Clickable { +func (d *Decorations) Clickable(action system.Action) *Clickable { if bits.OnesCount(uint(action)) != 1 { panic(fmt.Errorf("not a single action")) } idx := bits.TrailingZeros(uint(action)) - if n := idx - len(d.clicks); n >= 0 { - d.clicks = append(d.clicks, make([]Clickable, n+1)...) - } - click := &d.clicks[idx] - if click.Clicked(gtx) { - if action == system.ActionMaximize { - if d.maximized { - d.maximized = false - d.actions |= system.ActionUnmaximize - } else { - d.maximized = true - d.actions |= system.ActionMaximize - } - } else { - d.actions |= action + click, found := d.clicks[idx] + if !found { + click = new(Clickable) + if d.clicks == nil { + d.clicks = make(map[int]*Clickable) } + d.clicks[idx] = click } return click } @@ -66,11 +56,27 @@ func (d *Decorations) Perform(actions system.Action) { } } -// Actions returns the set of actions activated by the user. -func (d *Decorations) Actions() system.Action { - a := d.actions - d.actions = 0 - return a +// Update the state and return the set of actions activated by the user. +func (d *Decorations) Update(gtx layout.Context) system.Action { + var actions system.Action + for idx, clk := range d.clicks { + if !clk.Clicked(gtx) { + continue + } + action := system.Action(1 << idx) + switch { + case action == system.ActionMaximize && d.maximized: + action = system.ActionUnmaximize + case action == system.ActionUnmaximize && !d.maximized: + action = system.ActionMaximize + } + switch action { + case system.ActionMaximize, system.ActionUnmaximize: + d.maximized = !d.maximized + } + actions |= action + } + return actions } // Maximized returns whether the window is maximized. diff --git a/widget/material/decorations.go b/widget/material/decorations.go index 6e67f6fb..d327dbbc 100644 --- a/widget/material/decorations.go +++ b/widget/material/decorations.go @@ -85,7 +85,7 @@ func (d DecorationsStyle) layoutDecorations(gtx layout.Context) layout.Dimension default: continue } - cl := d.Decorations.Clickable(gtx, a) + cl := d.Decorations.Clickable(a) dims := cl.Layout(gtx, func(gtx layout.Context) layout.Dimensions { semantic.Button.Add(gtx.Ops) return layout.Stack{Alignment: layout.Center}.Layout(gtx,