G’MIC script writers may be interested by this.
As you know, a G’MIC script has the possibility to create its own display windows, and manage user events associated to them. It can be useful sometimes to write commands that allows such interactive displays, and a few of the G’MIC commands and filters use this feature (e.g. display
, x_warp
, x_morph
, x_pacman
, and more generally, all the x_something
commands…).
Before beginning with the explanations on how it works, be aware that these are pretty basic features, with a lot of limitations. Don’t ever think you can write a full-featured GUI library in G’MIC That being said, let us describe the basic principles.
Basically, only three things have to be known to start managing display windows:
- Command
window
(shortcutw
), is used to make a display window visible, move it, resize it, set its title, and display an image in it. It’s a all-in-one command
There are in fact 10 different versions of this command:window0
(akaw0
),window1
(akaw1
), …,window9
(akaw9
) to manage each of the 10 available display windows in G’MIC (no, you don’t want to open more than 10 windows simultaneously. It’s actually possible but with a lot of tricks, probably not suitable for this doc). Commandwindow
(akaw
) is actually equivalent towindow0
(akaw0
). Note that there are no needs to create a display window. There are all already created, just not visible by default.
According to the reference documentation, the arguments to window
are:
window (+):
_width[%]>=-1,_height[%]>=-1,_normalization,_fullscreen,_pos_x[%],_pos_y[%],_title
They are (almost) self-explanatory.
-
width
andheight
are the desired size you want for the display window (set to-1
to keep their values unchanged from one call ofw
to another). Setwidth
to0
to hide/close the display window. -
normalization
sets the normalization mode used when displaying an image into the display window. Most used values here is either0
(no-normalization, so you have to ensure your image values are in 8bits-range [0-255]), or1
(which means the display window always normalizes image values in [0,255] before displaying it). -
fullscreen
can be0
(no fullscreen, default) or1
(fullscreen window). -
pos_x
andpos_y
are the desired(x,y)
position of the upper-left corner of the window. These parameters can be ignored if we want to let the system determine this by itself (which is the case most of the time). -
title
is the string that will be displayed on the window title bar.
And most important, the selected image(s) on which the command is applied (i.e. w[img]
) tells which image must be displayed (or updated) in the display window. This selection can be empty (i.e. w[]
), in which case the content of the display window in unchanged (use an empty selection if you want just to resize/move the display window, or change its title bar, for instance).
This selection can also contain multiple images, in which case all images are displayed side by side on the display window.
-
Substituting expressions such as
{*,feature}
or{*0,feature}
(replace the0
by the index of the display window you are working with) : they provide information about display window and what happens in them (in particular, user events). For instance,{*,ESC}
is evaluated as0
or1
whether the keyESC
is being pressed or not. In the same way,{*}
is equal to0
is the window is not visible anymore (it has been closed by the user). The state of mouse buttons and the mouse coordinates are retrieved with{*,b}
and{*,x,y}
. Have a look to theSubstitution Rules
section in the reference documentation to see all the info that can be retrieved from a display window. Window position, and size can be also retrieved with such substituting expressions. -
The last important thing to know is the command
wait
. It is used to wait for a user event (when called without parameters), or wait for a certain amount of time (with an argument in milliseconds), which is useful if you want to display animations in your display window.
And that’s it. With these three things, you can do almost everything possible in terms of window management with G’MIC.
Let me show you next a simple example of code, with a mini-drawing application written in G’MIC:
# My first interactive G'MIC script.
foo :
rm
512,512,1,3 # Create the image[0] that will be our canvas image.
w. 512,512,0,"My 1st interactive G'MIC script" # Make the default display window #0 visible.
do
x,y,b,ww,wh={*,x,y,b,w,h} # Retrieve mouse coordinates, button state and window size.
if $b" && "$x>=0 # One of the buttons is pressed and mouse is over the canvas?
if narg($ox)
line[0] $ox,$oy,$x,$y,1,255 # Draw a segment from previous position, if any.
fi
circle[0] $x,$y,5,1,255,128,0 # Draw a circle in image[0] corresponding to the mouse position.
ox,oy=$x,$y # Save coordinates to link with possibly next point.
w[0] # Refresh the window display with the updated image.
else
ox,oy=
fi
wait # Wait for a user event.
if {*,r} w[] 512,512 fi # Make sure the display window keeps a size of 512x512.
while {*}" && "!{*,ESC} # Loop while window has not been closed, or key ESC pressed.
w[] 0 # Close/hide the display window.
I won’t comment much here, everything is already commented in the code.
The most common tasks related to display windows (drawing, and managing user events) are illustrated here.
Here is an animation of what you get with that sample code:
This simple example could be of course improved in several ways, for instance, by allowing the display window to be resized to any size. Here for simplicity, I ensure that the windows keeps a size of 512x512.
Additional tricks:
-
Command
cursor
can be used to show/hide the pointer icon when mouse is over a display window. Default value is1
(visible), but you can set it to0
if you want to draw your own pointer icon on your display window (this is done for instance indisplay
). -
What is important to understand is that there are no things as ‘event signals’ that can be written in your scripts. The event handling loop is always done explicitly by the script, as we all did before GUI library existed . As you can see with the example code above, its is actually very simple to achieve, so no worry about that.
Well that’s it for now, if you have any questions about this particular topic, just let me know.