testdata.go raw
1 // SPDX-License-Identifier: Unlicense OR MIT
2
3 // A simple app used for gogio's end-to-end tests.
4 package main
5
6 import (
7 "fmt"
8 "image"
9 "image/color"
10 "log"
11
12 "github.com/p9c/p9/pkg/gel/gio/app"
13 "github.com/p9c/p9/pkg/gel/gio/io/pointer"
14 "github.com/p9c/p9/pkg/gel/gio/io/system"
15 "github.com/p9c/p9/pkg/gel/gio/layout"
16 "github.com/p9c/p9/pkg/gel/gio/op"
17 "github.com/p9c/p9/pkg/gel/gio/op/clip"
18 "github.com/p9c/p9/pkg/gel/gio/op/paint"
19 )
20
21 func main() {
22 go func() {
23 w := app.NewWindow()
24 if err := loop(w); err != nil {
25 log.Fatal(err)
26 }
27 }()
28 app.Main()
29 }
30
31 type notifyFrame int
32
33 const (
34 notifyNone notifyFrame = iota
35 notifyInvalidate
36 notifyPrint
37 )
38
39 // notify keeps track of whether we want to print to stdout to notify the user
40 // when a frame is ready. Initially we want to notify about the first frame.
41 var notify = notifyInvalidate
42
43 type (
44 C = layout.Context
45 D = layout.Dimensions
46 )
47
48 func loop(w *app.Window) error {
49 topLeft := quarterWidget{
50 color: color.NRGBA{R: 0xde, G: 0xad, B: 0xbe, A: 0xff},
51 }
52 topRight := quarterWidget{
53 color: color.NRGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
54 }
55 botLeft := quarterWidget{
56 color: color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xff},
57 }
58 botRight := quarterWidget{
59 color: color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0x80},
60 }
61
62 var ops op.Ops
63 for {
64 e := <-w.Events()
65 switch e := e.(type) {
66 case system.DestroyEvent:
67 return e.Err
68 case system.FrameEvent:
69 gtx := layout.NewContext(&ops, e)
70 // Clear background to white, even on embedded platforms such as webassembly.
71 paint.Fill(gtx.Ops, color.NRGBA{A: 0xff, R: 0xff, G: 0xff, B: 0xff})
72 layout.Flex{Axis: layout.Vertical}.Layout(gtx,
73 layout.Flexed(1, func(gtx C) D {
74 return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
75 // r1c1
76 layout.Flexed(1, func(gtx C) D { return topLeft.Layout(gtx) }),
77 // r1c2
78 layout.Flexed(1, func(gtx C) D { return topRight.Layout(gtx) }),
79 )
80 }),
81 layout.Flexed(1, func(gtx C) D {
82 return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
83 // r2c1
84 layout.Flexed(1, func(gtx C) D { return botLeft.Layout(gtx) }),
85 // r2c2
86 layout.Flexed(1, func(gtx C) D { return botRight.Layout(gtx) }),
87 )
88 }),
89 )
90
91 e.Frame(gtx.Ops)
92
93 switch notify {
94 case notifyInvalidate:
95 notify = notifyPrint
96 w.Invalidate()
97 case notifyPrint:
98 notify = notifyNone
99 fmt.Println("gio frame ready")
100 }
101 }
102 }
103 }
104
105 // quarterWidget paints a quarter of the screen with one color. When clicked, it
106 // turns red, going back to its normal color when clicked again.
107 type quarterWidget struct {
108 color color.NRGBA
109
110 clicked bool
111 }
112
113 var red = color.NRGBA{R: 0xff, G: 0x00, B: 0x00, A: 0xff}
114
115 func (w *quarterWidget) Layout(gtx layout.Context) layout.Dimensions {
116 var color color.NRGBA
117 if w.clicked {
118 color = red
119 } else {
120 color = w.color
121 }
122
123 r := image.Rectangle{Max: gtx.Constraints.Max}
124 paint.FillShape(gtx.Ops, color, clip.Rect(r).Op())
125
126 pointer.Rect(image.Rectangle{
127 Max: image.Pt(gtx.Constraints.Max.X, gtx.Constraints.Max.Y),
128 }).Add(gtx.Ops)
129 pointer.InputOp{
130 Tag: w,
131 Types: pointer.Press,
132 }.Add(gtx.Ops)
133
134 for _, e := range gtx.Events(w) {
135 if e, ok := e.(pointer.Event); ok && e.Type == pointer.Press {
136 w.clicked = !w.clicked
137 // notify when we're done updating the frame.
138 notify = notifyInvalidate
139 }
140 }
141 return layout.Dimensions{Size: gtx.Constraints.Max}
142 }
143