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