mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
widget/material: split Decorations state and style
Move Decorations to the widget package and rename material.Decorate to material.Decorations. This makes decorations in line with how the other widgets are used. Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
package widget
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"math/bits"
|
||||
|
||||
"gioui.org/gesture"
|
||||
"gioui.org/io/pointer"
|
||||
"gioui.org/io/system"
|
||||
"gioui.org/layout"
|
||||
"gioui.org/op/clip"
|
||||
"gioui.org/unit"
|
||||
)
|
||||
|
||||
// Decorations handles the states of window decorations.
|
||||
type Decorations struct {
|
||||
move gesture.Drag
|
||||
clicks []Clickable
|
||||
resize [8]struct {
|
||||
gesture.Hover
|
||||
gesture.Drag
|
||||
}
|
||||
actions system.Action
|
||||
maximized bool
|
||||
}
|
||||
|
||||
// LayoutMove lays out the widget that makes a window movable.
|
||||
func (d *Decorations) LayoutMove(gtx layout.Context, w layout.Widget) layout.Dimensions {
|
||||
dims := w(gtx)
|
||||
d.move.Events(gtx.Metric, gtx, gesture.Both)
|
||||
st := clip.Rect{Max: dims.Size}.Push(gtx.Ops)
|
||||
d.move.Add(gtx.Ops)
|
||||
if d.move.Pressed() {
|
||||
d.actions |= system.ActionMove
|
||||
}
|
||||
st.Pop()
|
||||
return dims
|
||||
}
|
||||
|
||||
// Clickable returns the clickable for the given single action.
|
||||
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() {
|
||||
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
|
||||
}
|
||||
}
|
||||
return click
|
||||
}
|
||||
|
||||
// LayoutResize lays out the resize actions.
|
||||
func (d *Decorations) LayoutResize(gtx layout.Context, actions system.Action) {
|
||||
cs := gtx.Constraints.Max
|
||||
wh := gtx.Px(unit.Dp(10))
|
||||
s := []struct {
|
||||
system.Action
|
||||
image.Rectangle
|
||||
}{
|
||||
{system.ActionResizeNorth, image.Rect(0, 0, cs.X, wh)},
|
||||
{system.ActionResizeSouth, image.Rect(0, cs.Y-wh, cs.X, cs.Y)},
|
||||
{system.ActionResizeWest, image.Rect(cs.X-wh, 0, cs.X, cs.Y)},
|
||||
{system.ActionResizeEast, image.Rect(0, 0, wh, cs.Y)},
|
||||
{system.ActionResizeNorthWest, image.Rect(0, 0, wh, wh)},
|
||||
{system.ActionResizeNorthEast, image.Rect(cs.X-wh, 0, cs.X, wh)},
|
||||
{system.ActionResizeSouthWest, image.Rect(0, cs.Y-wh, wh, cs.Y)},
|
||||
{system.ActionResizeSouthEast, image.Rect(cs.X-wh, cs.Y-wh, cs.X, cs.Y)},
|
||||
}
|
||||
for i, data := range s {
|
||||
action := data.Action
|
||||
if actions&action == 0 {
|
||||
continue
|
||||
}
|
||||
rsz := &d.resize[i]
|
||||
rsz.Events(gtx.Metric, gtx, gesture.Both)
|
||||
if rsz.Drag.Dragging() {
|
||||
d.actions |= action
|
||||
}
|
||||
st := clip.Rect(data.Rectangle).Push(gtx.Ops)
|
||||
if rsz.Hover.Hovered(gtx) {
|
||||
pointer.CursorNameOp{Name: action.CursorName()}.Add(gtx.Ops)
|
||||
}
|
||||
rsz.Drag.Add(gtx.Ops)
|
||||
pass := pointer.PassOp{}.Push(gtx.Ops)
|
||||
rsz.Hover.Add(gtx.Ops)
|
||||
pass.Pop()
|
||||
st.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
// Perform updates the decorations as if the specified actions were
|
||||
// performed by the user.
|
||||
func (d *Decorations) Perform(actions system.Action) {
|
||||
if actions&system.ActionMaximize != 0 {
|
||||
d.maximized = true
|
||||
}
|
||||
if actions&(system.ActionUnmaximize|system.ActionMinimize|system.ActionFullscreen) != 0 {
|
||||
d.maximized = false
|
||||
}
|
||||
}
|
||||
|
||||
// Actions returns the set of actions activated by the user.
|
||||
func (d *Decorations) Actions() system.Action {
|
||||
a := d.actions
|
||||
d.actions = 0
|
||||
return a
|
||||
}
|
||||
|
||||
// Maximized returns whether the window is maximized.
|
||||
func (d *Decorations) Maximized() bool {
|
||||
return d.maximized
|
||||
}
|
||||
Reference in New Issue
Block a user