Skip to content

Instantly share code, notes, and snippets.

@tux21b
Created June 6, 2020 14:12
Show Gist options
  • Save tux21b/b2a2a1b8ae1dd0f24b6729ed3f33eb9d to your computer and use it in GitHub Desktop.
Save tux21b/b2a2a1b8ae1dd0f24b6729ed3f33eb9d to your computer and use it in GitHub Desktop.
// Problem:
// The green and red area (and the intersection) receive
// click events (press and release).
// The green area also receives hover events (enter and leave),
// but the red one does not.
package main
import (
"image"
"image/color"
"log"
"gioui.org/app"
"gioui.org/f32"
"gioui.org/io/pointer"
"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
)
func main() {
go func() {
w := app.NewWindow()
if err := loop(w); err != nil {
log.Fatal(err)
}
}()
app.Main()
}
func loop(w *app.Window) error {
var ops op.Ops
var btn Button
for {
e := <-w.Events()
switch e := e.(type) {
case system.DestroyEvent:
return e.Err
case system.FrameEvent:
gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size)
btn.Layout(gtx)
e.Frame(gtx.Ops)
}
}
}
type Button struct {
active bool
hover bool
}
func (b *Button) Layout(gtx layout.Context) layout.Dimensions {
for _, ev := range gtx.Queue.Events(b) {
log.Println("event", ev)
if x, ok := ev.(pointer.Event); ok {
switch x.Type {
case pointer.Enter:
b.hover = true
case pointer.Leave:
b.hover = false
case pointer.Press:
b.active = true
case pointer.Release:
b.active = false
}
}
}
defer op.Push(gtx.Ops).Pop()
rect := f32.Rect(100, 100, 400, 400)
rr := unit.Px(50)
clip.Rect{Rect: rect, SE: rr.V, SW: rr.V, NE: rr.V, NW: rr.V}.Add(gtx.Ops)
col := color.RGBA{B: 100, A: 0xff}
if b.hover {
col = color.RGBA{B: 150, A: 0xff}
}
if b.active {
col = color.RGBA{B: 200, A: 0xff}
}
paint.ColorOp{Color: col}.Add(gtx.Ops)
paint.PaintOp{Rect: rect}.Add(gtx.Ops)
func() {
defer op.Push(gtx.Ops).Pop()
drawBorderRect(gtx, f32.Rect(150, 100, 350, 400), color.RGBA{R: 0xFF, A: 0xFF})
pointer.Rect(image.Rect(150, 100, 350, 400)).Add(gtx.Ops)
pointer.InputOp{Tag: b, Types: pointer.Enter | pointer.Leave | pointer.Press | pointer.Release}.Add(gtx.Ops)
}()
func() {
defer op.Push(gtx.Ops).Pop()
drawBorderRect(gtx, f32.Rect(100, 150, 400, 350), color.RGBA{G: 0xFF, A: 0xFF})
pointer.Rect(image.Rect(100, 150, 400, 350)).Add(gtx.Ops)
pointer.InputOp{Tag: b, Types: pointer.Enter | pointer.Leave | pointer.Press | pointer.Release}.Add(gtx.Ops)
}()
return layout.Dimensions{
Size: image.Point{500, 500},
}
}
func drawBorderRect(gfx layout.Context, rect f32.Rectangle, fill color.RGBA) {
border := unit.Px(2).V
paint.ColorOp{Color: fill}.Add(gfx.Ops)
paint.PaintOp{Rect: f32.Rect(rect.Min.X, rect.Min.Y, rect.Min.X+border, rect.Max.Y)}.Add(gfx.Ops) // left
paint.PaintOp{Rect: f32.Rect(rect.Max.X - border, rect.Min.Y, rect.Max.X, rect.Max.Y)}.Add(gfx.Ops) // right
paint.PaintOp{Rect: f32.Rect(rect.Min.X, rect.Min.Y, rect.Max.X, rect.Min.Y+border)}.Add(gfx.Ops) // top
paint.PaintOp{Rect: f32.Rect(rect.Min.X, rect.Max.Y - border, rect.Max.X, rect.Max.Y)}.Add(gfx.Ops) // bottom
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment