This repository has been archived by the owner on Jul 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extend the documentation on signals to cover more advanced usages
Motivated by #161
- Loading branch information
Showing
2 changed files
with
99 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
### More about signals and signal-handlers | ||
|
||
In addition to the ["simple" | ||
interface](../README.md#callbacks-and-signals), `signal_connect` | ||
supports an approach that allows your callback function to be directly | ||
compiled to machine code. Not only is this more efficient, but it can | ||
occasionally be useful in avoiding problems from callback interrupts. | ||
|
||
This alternative syntax is as follows: | ||
``` | ||
signal_connect(cb, widget, signalname, return_type, parameter_type_tuple, after, user_data=widget) | ||
``` | ||
where: | ||
|
||
- `cb` is your callback function. You should use a generic function | ||
(i.e., one defined as `function foo(x,y,z) ... end`), and the | ||
arguments and return type should match the GTK+ documentation for | ||
the widget and signal ([see | ||
examples](https://developer.gnome.org/gtk3/stable/GtkWidget.html#GtkWidget-accel-closures-changed)). | ||
**In contrast with the [simpler | ||
interface](../README.md#callbacks-and-signals), when writing these | ||
callbacks you must include the `user_data` argument**. See examples below. | ||
- `widget` is the widget that will send the signal | ||
- `signalname` is a string or symbol identifying the signal, e.g., | ||
`"clicked"` or `"button-press-event"` | ||
- `return_type` is the type of the value returned by your | ||
callback. Usually `Void` (for `void`) or `Cint` (for `gboolean`) | ||
- `parameter_type_tuple` specifies the types of the *middle* arguments | ||
to the callback function, omitting the first (the widget) and last | ||
(`user_data`). For example, for [`"clicked"`](https://developer.gnome.org/gtk3/stable/GtkButton.html#GtkButton-clicked) we have | ||
`parameter_type_tuple = ()` (because there are no middle arguments) | ||
and for [`"button-press-event"`](https://developer.gnome.org/gtk3/stable/GtkWidget.html#GtkWidget-button-press-event) we have `parameter_type_tuple = | ||
(Ptr{GdkEventButton},)`. | ||
- `after` is a boolean, `true` if you want your callback to run after | ||
the default handler for your signal. When in doubt, specify `false`. | ||
- `user_data` contains any additional information your callback needs | ||
to operate. For example, you can pass other widgets, tuples of | ||
values, etc. If omitted, it defaults to `widget`. | ||
|
||
The callback's argument need to match the GTK documentation, with the | ||
exception of the `user_data` argument: rather than a pointer, this | ||
will automatically be converted back to a Julia type for you. | ||
|
||
As an example, consider this GUI for which pressing a button updates | ||
a text counter: | ||
|
||
```jl | ||
box = @Box(:h) | ||
btn = @Button("click me") | ||
lbl = @Label("0") | ||
push!(box, btn) | ||
push!(box, lbl) | ||
win = @Window(box, "Callbacks") | ||
showall(win) | ||
|
||
const counter = [0] # Pack counter value inside array so it is a reference | ||
|
||
# "clicked" callback declaration is | ||
# void user_function(GtkButton *button, gpointer user_data) | ||
# But user_data gets converted into a Julia object automatically | ||
function button_cb(widgetptr::Ptr, user_data) | ||
widget = convert(Button, widgetptr) # pointer -> object | ||
label, cntr = user_data # unpack the user_data tuple | ||
cntr[] = cntr[]+1 # increment counter[1] | ||
setproperty!(label, :label, string(cntr[])) | ||
nothing # return type is void | ||
end | ||
|
||
signal_connect(button_cb, btn, "clicked", Void, (), false, (lbl, counter)) | ||
``` | ||
|
||
You should note that the value of `counter[]` matches the display in | ||
the GUI. |