Skip to content

Event Handling

Ward edited this page Oct 4, 2019 · 1 revision

Code

Connect the message

wStaticText has a wEvent_CommandLeftClick event triggering by user click. To handle it, we need to connect between event message and the handler procedure.

import wNim/[wApp, wFrame, wPanel, wStaticText, wMessageDialog]

let app = App()
let frame = Frame(title="wNim Frame")
let panel = Panel(frame)
let label = StaticText(panel, label="Hello World")

proc handler() =
  MessageDialog(frame, "Hello World", "MessageDialog").display()

label.connect(wEvent_CommandLeftClick, handler)

label.center()
frame.center()
frame.show()

app.mainLoop()

We can use Nim's Do notation to create a anonymous handler:

import wNim/[wApp, wFrame, wPanel, wStaticText, wMessageDialog]

let app = App()
let frame = Frame(title="wNim Frame")
let panel = Panel(frame)
let label = StaticText(panel, label="Hello World")

label.connect(wEvent_CommandLeftClick) do ():
  MessageDialog(frame, "Hello World", "MessageDialog").display()

label.center()
frame.center()
frame.show()

app.mainLoop()

wNim provide dot as syntax sugar for connect, so this is the simplest way:

import wNim/[wApp, wFrame, wPanel, wStaticText, wMessageDialog]

let app = App()
let frame = Frame(title="wNim Frame")
let panel = Panel(frame)
let label = StaticText(panel, label="Hello World")

label.wEvent_CommandLeftClick do ():
  MessageDialog(frame, "Hello World", "MessageDialog").display()

label.center()
frame.center()
frame.show()

app.mainLoop()

Event Object

Sometimes, we need to know some information about the event. We can get it from the event object. The handler receive an event object from it's first parameter.

import wNim/[wApp, wFrame, wPanel, wStaticText, wMessageDialog, wEvent]

let app = App()
let frame = Frame(title="wNim Frame")
let panel = Panel(frame)
let label = StaticText(panel, label="Hello World")

label.wEvent_CommandLeftClick do (event: wEvent):
  MessageDialog(frame, $event.mousePos, "MessageDialog").display()

label.center()
frame.center()
frame.show()

app.mainLoop()

Propagation

An event can propagate upward to it's parent window until it been processed. wCommandEvent-derived events will propagate by default, and other events won't. The advantage of event propagation is that we can catch a lot of events in their parent window by using only one handler:

import wNim/[wApp, wFrame, wPanel, wStaticText, wMessageDialog, wEvent]

let app = App()
let frame = Frame(title="wNim Frame")
let panel = Panel(frame)
let label = StaticText(panel, label="Hello World")

frame.wEvent_CommandLeftClick do (event: wEvent): # We catch the event at "frame" level
  doassert(event of wCommandEvent) # Testing the event type
  doassert(event.window == label) # Testing the event source
  MessageDialog(frame, $event.mousePos, "MessageDialog").display()

label.center()
frame.center()
frame.show()

app.mainLoop()

Although every event has it's own propagation rule, the user can modify it freely, see wEvent

Skip Event

Some event has it's default handler. For example, a frame will resize it's only one child to take the entire frame client area (detail). We try adding another handler:

import wNim/[wApp, wFrame, wPanel, wStaticText, wMessageDialog, wEvent]

let app = App()
let frame = Frame(title="wNim Frame")
let panel = Panel(frame)
let label = StaticText(panel, label="Hello World")

frame.wEvent_Size do ():
  frame.title = $frame.size

label.center()
frame.center()
frame.show()

app.mainLoop()

If you change the frame size, you will see the title changed as we want, but the panel won't resize automatically anymore. This is because we replace the default event handler. To fix it, we need to "skip" the event handler, so the default event handler still works:

import wNim/[wApp, wFrame, wPanel, wStaticText, wMessageDialog, wEvent]

let app = App()
let frame = Frame(title="wNim Frame")
let panel = Panel(frame)
let label = StaticText(panel, label="Hello World")

frame.wEvent_Size do (event: wEvent):
  frame.title = $frame.size
  event.skip()

label.center()
frame.center()
frame.show()

app.mainLoop()
Clone this wiki locally