android-go/examples/sensors/main.go

175 lines
3.7 KiB
Go

// +build darwin linux
package main
import (
"fmt"
"image/color"
"log"
"time"
"gioui.org/app"
"gioui.org/f32"
"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
"gioui.org/widget/material"
"gioui.org/font/gofont"
)
type vector struct {
x, y, z float64
}
var (
labchan chan string
senschan chan vector
)
type (
D = layout.Dimensions
C = layout.Context
)
func main() {
labchan = make(chan string)
senschan = make(chan vector)
log.Print("Staring event loop")
go eventloop()
app.Main()
log.Print("App closed")
}
func diffInsets(x, y system.Insets) bool {
return x.Top != y.Top ||
x.Bottom != y.Bottom ||
x.Left != y.Left ||
x.Right != y.Right
}
func eventloop() {
w := app.NewWindow(
app.Size(unit.Dp(400), unit.Dp(400)),
app.Title("Hello"))
th := material.NewTheme(gofont.Collection())
var ops op.Ops
sysinset := &layout.Inset{}
margin := layout.UniformInset(unit.Dp(10))
labels := []material.LabelStyle{}
list := &layout.List{Axis: layout.Vertical}
resetSysinset := func(x system.Insets) {
sysinset.Top = x.Top
sysinset.Bottom = x.Bottom
sysinset.Left = x.Left
sysinset.Right = x.Right
}
go func() {
labchan <- "Starting"
}()
var accel vector
accel.y = 1
lablist := func(gtx C) D {
return list.Layout(gtx, len(labels), func(gtx C, i int) D {
return labels[i].Layout(gtx)
})
}
vecview := func(gtx C) D {
f := layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceEvenly}
return f.Layout(gtx,
layout.Rigid(func(gtx C) D {
return material.Body1(th, fmt.Sprintf("x = %f", accel.x)).Layout(gtx)
}),
layout.Rigid(func(gtx C) D {
return material.Body1(th, fmt.Sprintf("y = %f", accel.y)).Layout(gtx)
}),
layout.Rigid(func(gtx C) D {
return material.Body1(th, fmt.Sprintf("z = %f", accel.z)).Layout(gtx)
}),
)
}
var cx, cy, cvx, cvy, cs float32 // circle position
cx = 200
cy = 200
cs = 50 // circle size (radius)
circle := func(gtx C, width, height float32) D {
// clip circle position and bounce off of the edges
if (cx < cs) { cx = cs; cvx = (-0.5) * cvx }
if (cy < cs) { cy = cs; cvy = (-0.5) * cvy }
if (cx > width - cs) { cx = width - cs; cvx = (-0.5) * cvx }
if (cy > height - cs) { cy = height - cs; cvy = (-0.5) * cvy }
blue := color.RGBA{0x3f, 0x51, 0xb5, 0x80}
r1 := f32.Rectangle{f32.Point{cx - cs, cy - cs}, f32.Point{cx + cs, cy + cs}}
clip.Rect{ Rect: r1, NE: cs, NW: cs, SE: cs, SW: cs}.Op(gtx.Ops).Add(gtx.Ops)
paint.ColorOp{Color: blue}.Add(gtx.Ops)
paint.PaintOp{Rect: r1}.Add(gtx.Ops)
var ret D
ret.Size.X = int(cs * 2)
ret.Size.Y = int(cs * 2)
return ret
}
ticker := time.NewTicker(time.Second / 60)
var t, told int64
t = time.Now().UnixNano()
for {
select {
case <- ticker.C:
told = t
t = time.Now().UnixNano()
elapsed := float32((t - told) / 1000000)
cvx = cvx - float32(accel.x/1000) * elapsed
cvy = cvy + float32(accel.y/1000) * elapsed
cx = cx + cvx * elapsed
cy = cy + cvy * elapsed
w.Invalidate()
case x := <-labchan:
labels = append(labels, material.Body1(th, x))
case x := <-senschan:
accel = x
case e := <-w.Events():
switch e := e.(type) {
case system.DestroyEvent:
return
case system.FrameEvent:
gtx := layout.NewContext(&ops, e)
resetSysinset(e.Insets)
sysinset.Layout(gtx, func(gtx C) D {
ret := margin.Layout(gtx, func(gtx C) D {
f1 := layout.Flex{Axis: layout.Vertical}
ret := f1.Layout(gtx,
layout.Rigid(vecview),
layout.Flexed(1, lablist),
)
circle(gtx, float32(ret.Size.X), float32(ret.Size.Y))
return ret
})
return ret
})
e.Frame(gtx.Ops)
}
}
}
}