diff options
Diffstat (limited to 'shiny/example/basic/main.go')
-rw-r--r-- | shiny/example/basic/main.go | 187 |
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{}) + } + } +} |