summaryrefslogtreecommitdiffstats
path: root/shiny/example/basic/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'shiny/example/basic/main.go')
-rw-r--r--shiny/example/basic/main.go187
1 files changed, 187 insertions, 0 deletions
diff --git a/shiny/example/basic/main.go b/shiny/example/basic/main.go
new file mode 100644
index 0000000..8a35268
--- /dev/null
+++ b/shiny/example/basic/main.go
@@ -0,0 +1,187 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build example
+// +build example
+
+//
+// This build tag means that "go install golang.org/x/exp/shiny/..." doesn't
+// install this example program. Use "go run main.go" to run it or "go install
+// -tags=example" to install it.
+
+// Basic is a basic example of a graphical application.
+package main
+
+import (
+ "fmt"
+ "image"
+ "image/color"
+ "log"
+ "math"
+
+ "golang.org/x/exp/shiny/driver"
+ "golang.org/x/exp/shiny/imageutil"
+ "golang.org/x/exp/shiny/screen"
+ "golang.org/x/image/math/f64"
+ "golang.org/x/mobile/event/key"
+ "golang.org/x/mobile/event/lifecycle"
+ "golang.org/x/mobile/event/paint"
+ "golang.org/x/mobile/event/size"
+)
+
+var (
+ blue0 = color.RGBA{0x00, 0x00, 0x1f, 0xff}
+ blue1 = color.RGBA{0x00, 0x00, 0x3f, 0xff}
+ darkGray = color.RGBA{0x3f, 0x3f, 0x3f, 0xff}
+ green = color.RGBA{0x00, 0x7f, 0x00, 0x7f}
+ red = color.RGBA{0x7f, 0x00, 0x00, 0x7f}
+ yellow = color.RGBA{0x3f, 0x3f, 0x00, 0x3f}
+
+ cos30 = math.Cos(math.Pi / 6)
+ sin30 = math.Sin(math.Pi / 6)
+)
+
+func main() {
+ driver.Main(func(s screen.Screen) {
+ w, err := s.NewWindow(&screen.NewWindowOptions{
+ Title: "Basic Shiny Example",
+ })
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer w.Release()
+
+ size0 := image.Point{256, 256}
+ b, err := s.NewBuffer(size0)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer b.Release()
+ drawGradient(b.RGBA())
+
+ t0, err := s.NewTexture(size0)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer t0.Release()
+ t0.Upload(image.Point{}, b, b.Bounds())
+
+ size1 := image.Point{32, 20}
+ t1, err := s.NewTexture(size1)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer t1.Release()
+ t1.Fill(t1.Bounds(), green, screen.Src)
+ t1.Fill(t1.Bounds().Inset(2), red, screen.Over)
+ t1.Fill(t1.Bounds().Inset(4), red, screen.Src)
+
+ var sz size.Event
+ for {
+ e := w.NextEvent()
+
+ // This print message is to help programmers learn what events this
+ // example program generates. A real program shouldn't print such
+ // messages; they're not important to end users.
+ format := "got %#v\n"
+ if _, ok := e.(fmt.Stringer); ok {
+ format = "got %v\n"
+ }
+ fmt.Printf(format, e)
+
+ switch e := e.(type) {
+ case lifecycle.Event:
+ if e.To == lifecycle.StageDead {
+ return
+ }
+
+ case key.Event:
+ if e.Code == key.CodeEscape {
+ return
+ }
+
+ case paint.Event:
+ const inset = 10
+ for _, r := range imageutil.Border(sz.Bounds(), inset) {
+ w.Fill(r, blue0, screen.Src)
+ }
+ w.Fill(sz.Bounds().Inset(inset), blue1, screen.Src)
+ w.Upload(image.Point{20, 0}, b, b.Bounds())
+ w.Fill(image.Rect(50, 50, 350, 120), red, screen.Over)
+
+ // By default, draw the entirety of the texture using the Over
+ // operator. Uncomment one or both of the lines below to see
+ // their different effects.
+ op := screen.Over
+ // op = screen.Src
+ t0Rect := t0.Bounds()
+ // t0Rect = image.Rect(16, 0, 240, 100)
+
+ // Draw the texture t0 twice, as a 1:1 copy and under the
+ // transform src2dst.
+ w.Copy(image.Point{150, 100}, t0, t0Rect, op, nil)
+ src2dst := f64.Aff3{
+ +0.5 * cos30, -1.0 * sin30, 100,
+ +0.5 * sin30, +1.0 * cos30, 200,
+ }
+ w.Draw(src2dst, t0, t0Rect, op, nil)
+ w.DrawUniform(src2dst, yellow, t0Rect.Inset(30), screen.Over, nil)
+
+ // Draw crosses at the transformed corners of t0Rect.
+ for _, sx := range []int{t0Rect.Min.X, t0Rect.Max.X} {
+ for _, sy := range []int{t0Rect.Min.Y, t0Rect.Max.Y} {
+ dx := int(src2dst[0]*float64(sx) + src2dst[1]*float64(sy) + src2dst[2])
+ dy := int(src2dst[3]*float64(sx) + src2dst[4]*float64(sy) + src2dst[5])
+ w.Fill(image.Rect(dx-0, dy-1, dx+1, dy+2), darkGray, screen.Src)
+ w.Fill(image.Rect(dx-1, dy-0, dx+2, dy+1), darkGray, screen.Src)
+ }
+ }
+
+ // Draw t1.
+ w.Copy(image.Point{400, 50}, t1, t1.Bounds(), screen.Src, nil)
+
+ w.Publish()
+
+ case size.Event:
+ sz = e
+
+ case error:
+ log.Print(e)
+ }
+ }
+ })
+}
+
+func drawGradient(m *image.RGBA) {
+ b := m.Bounds()
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ if x%64 == 0 || y%64 == 0 {
+ m.SetRGBA(x, y, color.RGBA{0xff, 0xff, 0xff, 0xff})
+ } else if x%64 == 63 || y%64 == 63 {
+ m.SetRGBA(x, y, color.RGBA{0x00, 0x00, 0xff, 0xff})
+ } else {
+ m.SetRGBA(x, y, color.RGBA{uint8(x), uint8(y), 0x00, 0xff})
+ }
+ }
+ }
+
+ // Round off the corners.
+ const radius = 64
+ lox := b.Min.X + radius - 1
+ loy := b.Min.Y + radius - 1
+ hix := b.Max.X - radius
+ hiy := b.Max.Y - radius
+ for y := 0; y < radius; y++ {
+ for x := 0; x < radius; x++ {
+ if x*x+y*y <= radius*radius {
+ continue
+ }
+ m.SetRGBA(lox-x, loy-y, color.RGBA{})
+ m.SetRGBA(hix+x, loy-y, color.RGBA{})
+ m.SetRGBA(lox-x, hiy+y, color.RGBA{})
+ m.SetRGBA(hix+x, hiy+y, color.RGBA{})
+ }
+ }
+}