mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 02:15:34 +00:00
widget/material: update Decorations
Fix actions not processed and move the Layout method from Decorations to DecorationsStyle. Also clarify the comment for the app.Window.Decorated option. Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
This commit is contained in:
+4
-4
@@ -1068,11 +1068,11 @@ func (w *window) resize(a system.Action) {
|
|||||||
case system.ActionResizeNorthWest:
|
case system.ActionResizeNorthWest:
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT
|
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT
|
||||||
case system.ActionResizeNorthEast:
|
case system.ActionResizeNorthEast:
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT
|
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT
|
||||||
case system.ActionResizeSouthEast:
|
case system.ActionResizeSouthEast:
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT
|
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT
|
||||||
case system.ActionResizeSouthWest:
|
case system.ActionResizeSouthWest:
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT
|
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1115,9 +1115,9 @@ func (w *window) SetCursor(name pointer.CursorName) {
|
|||||||
case pointer.CursorTopLeftResize:
|
case pointer.CursorTopLeftResize:
|
||||||
name = "top_left_corner"
|
name = "top_left_corner"
|
||||||
case pointer.CursorTopRightResize:
|
case pointer.CursorTopRightResize:
|
||||||
name = "bottom_left_corner"
|
|
||||||
case pointer.CursorBottomLeftResize:
|
|
||||||
name = "top_right_corner"
|
name = "top_right_corner"
|
||||||
|
case pointer.CursorBottomLeftResize:
|
||||||
|
name = "bottom_left_corner"
|
||||||
case pointer.CursorBottomRightResize:
|
case pointer.CursorBottomRightResize:
|
||||||
name = "bottom_right_corner"
|
name = "bottom_right_corner"
|
||||||
case pointer.CursorLeftResize:
|
case pointer.CursorLeftResize:
|
||||||
|
|||||||
+11
-11
@@ -68,7 +68,7 @@ type Window struct {
|
|||||||
decorations struct {
|
decorations struct {
|
||||||
op.Ops
|
op.Ops
|
||||||
Config
|
Config
|
||||||
*material.Decorations
|
*material.DecorationsStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks callbacks
|
callbacks callbacks
|
||||||
@@ -688,7 +688,7 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) image.Point
|
|||||||
if w.decorations.Config.Decorated || w.decorations.Config.Mode == Fullscreen {
|
if w.decorations.Config.Decorated || w.decorations.Config.Mode == Fullscreen {
|
||||||
return e.Size
|
return e.Size
|
||||||
}
|
}
|
||||||
deco := w.decorations.Decorations
|
deco := w.decorations.DecorationsStyle
|
||||||
if deco == nil {
|
if deco == nil {
|
||||||
theme := material.NewTheme(gofont.Collection())
|
theme := material.NewTheme(gofont.Collection())
|
||||||
allActions := system.ActionMinimize | system.ActionMaximize | system.ActionUnmaximize |
|
allActions := system.ActionMinimize | system.ActionMaximize | system.ActionUnmaximize |
|
||||||
@@ -697,10 +697,9 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) image.Point
|
|||||||
system.ActionResizeWest | system.ActionResizeEast |
|
system.ActionResizeWest | system.ActionResizeEast |
|
||||||
system.ActionResizeNorthWest | system.ActionResizeSouthWest |
|
system.ActionResizeNorthWest | system.ActionResizeSouthWest |
|
||||||
system.ActionResizeNorthEast | system.ActionResizeSouthEast
|
system.ActionResizeNorthEast | system.ActionResizeSouthEast
|
||||||
deco = &material.Decorations{
|
style := material.Decorate(theme, allActions)
|
||||||
DecorationsStyle: material.Decorate(theme, allActions),
|
deco = &style
|
||||||
}
|
w.decorations.DecorationsStyle = &style
|
||||||
w.decorations.Decorations = deco
|
|
||||||
}
|
}
|
||||||
// Update the decorations based on the current window mode.
|
// Update the decorations based on the current window mode.
|
||||||
var actions system.Action
|
var actions system.Action
|
||||||
@@ -716,9 +715,9 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) image.Point
|
|||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("unknown WindowMode %v", m))
|
panic(fmt.Errorf("unknown WindowMode %v", m))
|
||||||
}
|
}
|
||||||
deco.Perform(actions)
|
deco.Decorations.Perform(actions)
|
||||||
// Update the window based on the actions on the decorations.
|
// Update the window based on the actions on the decorations.
|
||||||
d.Perform(deco.Actions())
|
d.Perform(deco.Decorations.Actions())
|
||||||
|
|
||||||
gtx := layout.Context{
|
gtx := layout.Context{
|
||||||
Ops: o,
|
Ops: o,
|
||||||
@@ -728,7 +727,7 @@ func (w *Window) decorate(d driver, e system.FrameEvent, o *op.Ops) image.Point
|
|||||||
Constraints: layout.Exact(e.Size),
|
Constraints: layout.Exact(e.Size),
|
||||||
}
|
}
|
||||||
rec := op.Record(o)
|
rec := op.Record(o)
|
||||||
dims := deco.Decorate(gtx, w.decorations.Config.Title)
|
dims := deco.Layout(gtx, w.decorations.Config.Title)
|
||||||
op.Defer(o, rec.Stop())
|
op.Defer(o, rec.Stop())
|
||||||
// Offset to place the frame content below the decorations.
|
// Offset to place the frame content below the decorations.
|
||||||
size := image.Point{Y: dims.Size.Y}
|
size := image.Point{Y: dims.Size.Y}
|
||||||
@@ -837,8 +836,9 @@ func CustomRenderer(custom bool) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decorated controls whether automatic window decorations
|
// Decorated controls whether Gio and/or the platform are responsible
|
||||||
// are enabled.
|
// for drawing window decorations. Providing false indicates that
|
||||||
|
// the application will either be undecorated or will draw its own decorations.
|
||||||
func Decorated(enabled bool) Option {
|
func Decorated(enabled bool) Option {
|
||||||
return func(_ unit.Metric, cnf *Config) {
|
return func(_ unit.Metric, cnf *Config) {
|
||||||
cnf.Decorated = enabled
|
cnf.Decorated = enabled
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
|
|
||||||
// DecorationsStyle provides the style elements for Decorations.
|
// DecorationsStyle provides the style elements for Decorations.
|
||||||
type DecorationsStyle struct {
|
type DecorationsStyle struct {
|
||||||
|
Decorations
|
||||||
Actions system.Action
|
Actions system.Action
|
||||||
Title LabelStyle
|
Title LabelStyle
|
||||||
Background color.NRGBA
|
Background color.NRGBA
|
||||||
@@ -39,7 +40,6 @@ func Decorate(th *Theme, actions system.Action) DecorationsStyle {
|
|||||||
|
|
||||||
// Decorations provides window decorations.
|
// Decorations provides window decorations.
|
||||||
type Decorations struct {
|
type Decorations struct {
|
||||||
DecorationsStyle
|
|
||||||
actions struct {
|
actions struct {
|
||||||
layout.List
|
layout.List
|
||||||
clicks []widget.Clickable
|
clicks []widget.Clickable
|
||||||
@@ -54,22 +54,23 @@ type Decorations struct {
|
|||||||
maximized bool
|
maximized bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decorate a window with the title and actions defined in DecorationsStyle.
|
// Layout a window with the title and actions defined in DecorationsStyle.
|
||||||
// The space used by the decorations is returned as an inset for the window
|
func (d *DecorationsStyle) Layout(gtx layout.Context, title string) layout.Dimensions {
|
||||||
// content.
|
|
||||||
func (d *Decorations) Decorate(gtx layout.Context, title string) layout.Dimensions {
|
|
||||||
rec := op.Record(gtx.Ops)
|
rec := op.Record(gtx.Ops)
|
||||||
dims := d.layoutDecorations(gtx, title)
|
label := d.Title
|
||||||
|
label.Text = title
|
||||||
|
paint.ColorOp{Color: d.Foreground}.Add(gtx.Ops)
|
||||||
|
dims := d.Decorations.layoutDecorations(gtx, d.Actions, label.Layout)
|
||||||
decos := rec.Stop()
|
decos := rec.Stop()
|
||||||
r := clip.Rect{Max: dims.Size}
|
r := clip.Rect{Max: dims.Size}
|
||||||
paint.FillShape(gtx.Ops, d.DecorationsStyle.Background, r.Op())
|
paint.FillShape(gtx.Ops, d.Background, r.Op())
|
||||||
decos.Add(gtx.Ops)
|
decos.Add(gtx.Ops)
|
||||||
d.layoutResizing(gtx)
|
d.Decorations.layoutResizing(gtx, d.Actions)
|
||||||
return dims
|
return dims
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decorations) layoutResizing(gtx layout.Context) {
|
func (d *Decorations) layoutResizing(gtx layout.Context, actions system.Action) {
|
||||||
cs := gtx.Constraints.Min
|
cs := gtx.Constraints.Max
|
||||||
wh := gtx.Px(unit.Dp(10))
|
wh := gtx.Px(unit.Dp(10))
|
||||||
s := []struct {
|
s := []struct {
|
||||||
system.Action
|
system.Action
|
||||||
@@ -80,13 +81,13 @@ func (d *Decorations) layoutResizing(gtx layout.Context) {
|
|||||||
{system.ActionResizeWest, image.Rect(cs.X-wh, 0, 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.ActionResizeEast, image.Rect(0, 0, wh, cs.Y)},
|
||||||
{system.ActionResizeNorthWest, image.Rect(0, 0, wh, wh)},
|
{system.ActionResizeNorthWest, image.Rect(0, 0, wh, wh)},
|
||||||
{system.ActionResizeSouthWest, image.Rect(cs.X-wh, 0, cs.X, wh)},
|
{system.ActionResizeNorthEast, image.Rect(cs.X-wh, 0, cs.X, wh)},
|
||||||
{system.ActionResizeNorthEast, image.Rect(0, cs.Y-wh, wh, cs.Y)},
|
{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)},
|
{system.ActionResizeSouthEast, image.Rect(cs.X-wh, cs.Y-wh, cs.X, cs.Y)},
|
||||||
}
|
}
|
||||||
for i, data := range s {
|
for i, data := range s {
|
||||||
action := data.Action
|
action := data.Action
|
||||||
if d.DecorationsStyle.Actions&action == 0 {
|
if actions&action == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rsz := &d.actions.resize[i]
|
rsz := &d.actions.resize[i]
|
||||||
@@ -106,7 +107,7 @@ func (d *Decorations) layoutResizing(gtx layout.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decorations) layoutDecorations(gtx layout.Context, title string) layout.Dimensions {
|
func (d *Decorations) layoutDecorations(gtx layout.Context, actions system.Action, title layout.Widget) layout.Dimensions {
|
||||||
gtx.Constraints.Min.Y = 0
|
gtx.Constraints.Min.Y = 0
|
||||||
inset := layout.UniformInset(unit.Dp(10))
|
inset := layout.UniformInset(unit.Dp(10))
|
||||||
return layout.Flex{
|
return layout.Flex{
|
||||||
@@ -115,9 +116,8 @@ func (d *Decorations) layoutDecorations(gtx layout.Context, title string) layout
|
|||||||
Spacing: layout.SpaceBetween,
|
Spacing: layout.SpaceBetween,
|
||||||
}.Layout(gtx,
|
}.Layout(gtx,
|
||||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||||
d.DecorationsStyle.Title.Text = title
|
dims := inset.Layout(gtx, title)
|
||||||
dims := inset.Layout(gtx, d.DecorationsStyle.Title.Layout)
|
if actions&system.ActionMove != 0 {
|
||||||
if d.DecorationsStyle.Actions&system.ActionMove != 0 {
|
|
||||||
d.actions.move.Events(gtx.Metric, gtx, gesture.Both)
|
d.actions.move.Events(gtx.Metric, gtx, gesture.Both)
|
||||||
|
|
||||||
st := clip.Rect{Max: dims.Size}.Push(gtx.Ops)
|
st := clip.Rect{Max: dims.Size}.Push(gtx.Ops)
|
||||||
@@ -131,27 +131,16 @@ func (d *Decorations) layoutDecorations(gtx layout.Context, title string) layout
|
|||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
// Remove the unmaximize action as it is taken care of by maximize.
|
// Remove the unmaximize action as it is taken care of by maximize.
|
||||||
actions := d.DecorationsStyle.Actions &^ system.ActionUnmaximize
|
actions := actions &^ system.ActionUnmaximize
|
||||||
an := bits.OnesCount(uint(actions))
|
an := bits.OnesCount(uint(actions))
|
||||||
if n := len(d.actions.clicks); n < an {
|
if n := len(d.actions.clicks); n < an {
|
||||||
d.actions.clicks = append(d.actions.clicks, make([]widget.Clickable, an-n)...)
|
d.actions.clicks = append(d.actions.clicks, make([]widget.Clickable, an-n)...)
|
||||||
}
|
}
|
||||||
|
action := system.Action(1)
|
||||||
return d.actions.Layout(gtx, an, func(gtx layout.Context, idx int) layout.Dimensions {
|
return d.actions.Layout(gtx, an, func(gtx layout.Context, idx int) layout.Dimensions {
|
||||||
action := system.Action(1 << idx)
|
defer func() { action <<= 1 }()
|
||||||
var w layout.Widget
|
for actions&action == 0 {
|
||||||
switch actions & action {
|
action <<= 1
|
||||||
case system.ActionMinimize:
|
|
||||||
w = d.minimizeWindow
|
|
||||||
case system.ActionMaximize:
|
|
||||||
if d.maximized {
|
|
||||||
w = d.maximizedWindow
|
|
||||||
} else {
|
|
||||||
w = d.maximizeWindow
|
|
||||||
}
|
|
||||||
case system.ActionClose:
|
|
||||||
w = d.closeWindow
|
|
||||||
default:
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
}
|
||||||
click := &d.actions.clicks[idx]
|
click := &d.actions.clicks[idx]
|
||||||
if click.Clicked() {
|
if click.Clicked() {
|
||||||
@@ -168,6 +157,21 @@ func (d *Decorations) layoutDecorations(gtx layout.Context, title string) layout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Clickable(gtx, click, func(gtx layout.Context) layout.Dimensions {
|
return Clickable(gtx, click, func(gtx layout.Context) layout.Dimensions {
|
||||||
|
var w layout.Widget
|
||||||
|
switch actions & action {
|
||||||
|
case system.ActionMinimize:
|
||||||
|
w = minimizeWindow
|
||||||
|
case system.ActionMaximize:
|
||||||
|
if d.maximized {
|
||||||
|
w = maximizedWindow
|
||||||
|
} else {
|
||||||
|
w = maximizeWindow
|
||||||
|
}
|
||||||
|
case system.ActionClose:
|
||||||
|
w = closeWindow
|
||||||
|
default:
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
return inset.Layout(gtx, w)
|
return inset.Layout(gtx, w)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -200,13 +204,12 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// minimizeWindows draws a line icon representing the minimize action.
|
// minimizeWindows draws a line icon representing the minimize action.
|
||||||
func (d *Decorations) minimizeWindow(gtx layout.Context) layout.Dimensions {
|
func minimizeWindow(gtx layout.Context) layout.Dimensions {
|
||||||
paint.ColorOp{Color: d.DecorationsStyle.Foreground}.Add(gtx.Ops)
|
|
||||||
size := gtx.Px(winIconSize)
|
size := gtx.Px(winIconSize)
|
||||||
size32 := float32(size)
|
size32 := float32(size)
|
||||||
margin := float32(gtx.Px(winIconMargin))
|
margin := float32(gtx.Px(winIconMargin))
|
||||||
width := float32(gtx.Px(winIconStroke))
|
width := float32(gtx.Px(winIconStroke))
|
||||||
p := &d.path
|
var p clip.Path
|
||||||
p.Begin(gtx.Ops)
|
p.Begin(gtx.Ops)
|
||||||
p.MoveTo(f32.Point{X: margin, Y: size32 - margin})
|
p.MoveTo(f32.Point{X: margin, Y: size32 - margin})
|
||||||
p.LineTo(f32.Point{X: size32 - 2*margin, Y: size32 - margin})
|
p.LineTo(f32.Point{X: size32 - 2*margin, Y: size32 - margin})
|
||||||
@@ -220,8 +223,7 @@ func (d *Decorations) minimizeWindow(gtx layout.Context) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// maximizeWindow draws a rectangle representing the maximize action.
|
// maximizeWindow draws a rectangle representing the maximize action.
|
||||||
func (d *Decorations) maximizeWindow(gtx layout.Context) layout.Dimensions {
|
func maximizeWindow(gtx layout.Context) layout.Dimensions {
|
||||||
paint.ColorOp{Color: d.DecorationsStyle.Foreground}.Add(gtx.Ops)
|
|
||||||
size := gtx.Px(winIconSize)
|
size := gtx.Px(winIconSize)
|
||||||
size32 := float32(size)
|
size32 := float32(size)
|
||||||
margin := float32(gtx.Px(winIconMargin))
|
margin := float32(gtx.Px(winIconMargin))
|
||||||
@@ -245,8 +247,7 @@ func (d *Decorations) maximizeWindow(gtx layout.Context) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// maximizedWindow draws interleaved rectangles representing the un-maximize action.
|
// maximizedWindow draws interleaved rectangles representing the un-maximize action.
|
||||||
func (d *Decorations) maximizedWindow(gtx layout.Context) layout.Dimensions {
|
func maximizedWindow(gtx layout.Context) layout.Dimensions {
|
||||||
paint.ColorOp{Color: d.DecorationsStyle.Foreground}.Add(gtx.Ops)
|
|
||||||
size := gtx.Px(winIconSize)
|
size := gtx.Px(winIconSize)
|
||||||
size32 := float32(size)
|
size32 := float32(size)
|
||||||
margin := float32(gtx.Px(winIconMargin))
|
margin := float32(gtx.Px(winIconMargin))
|
||||||
@@ -273,13 +274,12 @@ func (d *Decorations) maximizedWindow(gtx layout.Context) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// closeWindow draws a cross representing the close action.
|
// closeWindow draws a cross representing the close action.
|
||||||
func (d *Decorations) closeWindow(gtx layout.Context) layout.Dimensions {
|
func closeWindow(gtx layout.Context) layout.Dimensions {
|
||||||
paint.ColorOp{Color: d.DecorationsStyle.Foreground}.Add(gtx.Ops)
|
|
||||||
size := gtx.Px(winIconSize)
|
size := gtx.Px(winIconSize)
|
||||||
size32 := float32(size)
|
size32 := float32(size)
|
||||||
margin := float32(gtx.Px(winIconMargin))
|
margin := float32(gtx.Px(winIconMargin))
|
||||||
width := float32(gtx.Px(winIconStroke))
|
width := float32(gtx.Px(winIconStroke))
|
||||||
p := &d.path
|
var p clip.Path
|
||||||
p.Begin(gtx.Ops)
|
p.Begin(gtx.Ops)
|
||||||
p.MoveTo(f32.Point{X: margin, Y: margin})
|
p.MoveTo(f32.Point{X: margin, Y: margin})
|
||||||
p.LineTo(f32.Point{X: size32 - margin, Y: size32 - margin})
|
p.LineTo(f32.Point{X: size32 - margin, Y: size32 - margin})
|
||||||
|
|||||||
Reference in New Issue
Block a user