~pierrec/giox

ref: 8b5b6cd9a4f1a665581b251b751ffc22205812fa giox/widgetx/modal.go -rw-r--r-- 1.5 KiB
8b5b6cd9pierre widgetx: replaced Modal ReleaseKeys with Keys as []string 10 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package widgetx

import (
	"image"
	"image/color"

	"gioui.org/io/key"
	"gioui.org/io/pointer"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/op/clip"
	"gioui.org/op/paint"
	"gioui.org/widget"
)

// Modal displays a widget and deactivates its background by grabbing
// keyboard and mouse events as specified by the Release fields.
type Modal struct {
	Background   color.NRGBA
	Keys         []string
	ReleaseMouse bool
	click        widget.Clickable
	changed      bool
}

func (m *Modal) update(gtx layout.Context) {
	defer func() {
		if m.changed {
			// Force a refresh as Modal is a defer op.
			op.InvalidateOp{}.Add(gtx.Ops)
		}
	}()
	if m.click.Clicked() {
		m.changed = true
		return
	}
	for _, ev := range gtx.Events(m) {
		if e, ok := ev.(key.Event); ok {
			for _, k := range m.Keys {
				if e.Name == k {
					m.changed = true
					return
				}
			}
		}
	}
}

// Layout displays the modal as a defer operation.
func (m *Modal) Layout(gtx layout.Context) layout.Dimensions {
	m.update(gtx)
	macro := op.Record(gtx.Ops)
	size := gtx.Constraints.Min
	if len(m.Keys) > 0 {
		key.InputOp{Tag: m}.Add(gtx.Ops)
		key.FocusOp{Tag: m}.Add(gtx.Ops)
	}
	if !m.ReleaseMouse {
		pointer.Rect(image.Rectangle{Max: size}).Add(gtx.Ops)
		m.click.Layout(gtx)
	}
	paint.FillShape(gtx.Ops, m.Background, clip.Rect{Max: size}.Op())
	op.Defer(gtx.Ops, macro.Stop())
	return layout.Dimensions{Size: size}
}

// Changed returns whether or not the area was clicked or ESC was pressed.
func (m *Modal) Changed() bool {
	changed := m.changed
	m.changed = false
	return changed
}