Chapter 4 - Event Area
Goals
In this chapter we capture user input using a technique we’ll call an eventArea
.
Outline
So far we’ve set up our program, reacted to user input and laid out our application on screed. The final piece to the puzzle is to actually capture keyboard and mouse input.
We first create a clip area where events are to be collected from, and then specify which events to listen for. As always it’s fairly straight forward, but we’ll take the time to step through it
Code
pointer.Scroll
First we listen for mouse or trackpad events. This is done by waiting for en event that matches a filter.
// Scrolled a mouse wheel?
for {
ev, ok := gtx.Event(
pointer.Filter{
Target: tag,
Kinds: pointer.Scroll,
ScrollY: pointer.ScrollRange{Min: -1, Max: +1},
},
)
if !ok {
break
}
fmt.Printf("SCROLL: %+v\n", ev)
scrollY = scrollY + unit.Dp(ev.(pointer.Event).Scroll.Y*float32(fontSize))
if scrollY < 0 {
scrollY = 0
}
}
The filter defines that this code will wait for a pointer.Scroll
of a given range. The range can be anything really, but the most important thing is that it containts positive and negative range. Apart from that it could easily be +/- 1 or +/- 100 or whatever, but check your device sensitivity. It can’t be zero though, then no scrolls will happen.
pointer.Press
Here we filter for pointer.Press
, i.e. clicking down with the mouse.
// Pressed a mouse button?
for {
ev, ok := gtx.Event(
pointer.Filter{
Target: tag,
Kinds: pointer.Press,
},
)
if !ok {
break
}
fmt.Printf("PRESS : %+v\n", ev)
// Start / stop
autoscroll = !autoscroll
}
key.Filter
This filter explicitly filters the keys relevant for us. Some are normal letters while others are named keys, such as arrows.
for {
ev, ok := gtx.Event(
key.Filter{Name: key.NameSpace},
key.Filter{Optional: key.ModShift, Name: "U"},
key.Filter{Optional: key.ModShift, Name: "D"},
key.Filter{Optional: key.ModShift, Name: "J"},
key.Filter{Optional: key.ModShift, Name: "K"},
key.Filter{Optional: key.ModShift, Name: key.NameUpArrow},
key.Filter{Optional: key.ModShift, Name: key.NameDownArrow},
key.Filter{Optional: key.ModShift, Name: key.NamePageUp},
key.Filter{Optional: key.ModShift, Name: key.NamePageDown},
key.Filter{Optional: key.ModShift, Name: "F"},
key.Filter{Optional: key.ModShift, Name: "S"},
key.Filter{Optional: key.ModShift, Name: "+"},
key.Filter{Optional: key.ModShift, Name: "-"},
key.Filter{Optional: key.ModShift, Name: "W"},
key.Filter{Optional: key.ModShift, Name: "N"},
key.Filter{Optional: key.ModShift, Name: "C"},
)
For each key we then define what is to happen when it is pressed. For example
// Faster scrollspeed
if name == "F" {
autoscroll = true
autospeed += stepSize
}
// Slower scrollspeed
if name == "S" {
if autospeed > 0 {
autospeed -= stepSize
}
if autospeed <= 0 {
autospeed = 0
autoscroll = false
}
}
Finalize
We have now completed the full frame and it’s time to draw all operations from &ops
on screen:
// Frame completes the FrameEvent
winE.Frame(&ops)
Comments
Thank you so much, and well done my friend! High fives, fist bumps, back slaps and cheers all around. Thanks a lot for staying together on this tour of Gio’s event handling. We’ve covered a lot of ground, but also built a really nifty little app that scales, scrolls, zooms and moves, all at the will of our fingertips. That’s pretty neat.
If this was useful, please star the repo on Github, or even better, drop me a line. I really love hearing what people build with Gio.
Thanks and all the best!