gioui.org@v0.6.1-0.20240506124620-7a9ce51988ce/widget/decorations.go (about) 1 package widget 2 3 import ( 4 "fmt" 5 "math/bits" 6 7 "gioui.org/io/system" 8 "gioui.org/layout" 9 "gioui.org/op/clip" 10 ) 11 12 // Decorations handles the states of window decorations. 13 type Decorations struct { 14 clicks map[int]*Clickable 15 maximized bool 16 } 17 18 // LayoutMove lays out the widget that makes a window movable. 19 func (d *Decorations) LayoutMove(gtx layout.Context, w layout.Widget) layout.Dimensions { 20 dims := w(gtx) 21 defer clip.Rect{Max: dims.Size}.Push(gtx.Ops).Pop() 22 system.ActionInputOp(system.ActionMove).Add(gtx.Ops) 23 return dims 24 } 25 26 // Clickable returns the clickable for the given single action. 27 func (d *Decorations) Clickable(action system.Action) *Clickable { 28 if bits.OnesCount(uint(action)) != 1 { 29 panic(fmt.Errorf("not a single action")) 30 } 31 idx := bits.TrailingZeros(uint(action)) 32 click, found := d.clicks[idx] 33 if !found { 34 click = new(Clickable) 35 if d.clicks == nil { 36 d.clicks = make(map[int]*Clickable) 37 } 38 d.clicks[idx] = click 39 } 40 return click 41 } 42 43 // Perform updates the decorations as if the specified actions were 44 // performed by the user. 45 func (d *Decorations) Perform(actions system.Action) { 46 if actions&system.ActionMaximize != 0 { 47 d.maximized = true 48 } 49 if actions&(system.ActionUnmaximize|system.ActionMinimize|system.ActionFullscreen) != 0 { 50 d.maximized = false 51 } 52 } 53 54 // Update the state and return the set of actions activated by the user. 55 func (d *Decorations) Update(gtx layout.Context) system.Action { 56 var actions system.Action 57 for idx, clk := range d.clicks { 58 if !clk.Clicked(gtx) { 59 continue 60 } 61 action := system.Action(1 << idx) 62 switch { 63 case action == system.ActionMaximize && d.maximized: 64 action = system.ActionUnmaximize 65 case action == system.ActionUnmaximize && !d.maximized: 66 action = system.ActionMaximize 67 } 68 switch action { 69 case system.ActionMaximize, system.ActionUnmaximize: 70 d.maximized = !d.maximized 71 } 72 actions |= action 73 } 74 return actions 75 } 76 77 // Maximized returns whether the window is maximized. 78 func (d *Decorations) Maximized() bool { 79 return d.maximized 80 }