
\chapter{GladeVCP}

GladeVCP is an EMC2 component which adds the ability to add a virtual
control panel to EMC user interfaces like Axis or Touchy. It is similar
to PyVCP; whereas PyVCP panels are created by editing an XML file
manually, GladeVCP uses the glade WYSIWYG user interface editor. Therefore,
it's faster and easier to create visually pleasing panels with GladeVCP.
\begin{description}
\item [{Note:}] Until GladeVCP is fully integrated with EMC2 please refer
to the EMC wiki page GladeVcpSetup for instructions on installing
and setting up GladeVCP.
\end{description}

\section{Creating your first GladeVCP UI component}

Either modify an existing UI component, or start a new one with running
glade. In the left tab, expand the 'HAL Python' components. Create
a window as top level window from the 'Toplevels' section, which by
default will be named window1. Leave that name as is - gladevcp assumes
the top level window has this name. Add a HAL\_Box or a HAL\_Table
from 'HAL Python' to the frame, and pick and place some elements like
LED, button etc in its box.

This will look like so:

%
\begin{figure}[H]
\caption{Glade}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/glade-myui}
\end{figure}


Select File->Save as, give it a name like 'myui.ui' and make sure
it's saved as 'GtkBuilder' file (radio button left bottom corner in
Save dialog). The convention for GtkBuilder file extension is '.ui'.
You can now run it with:
\begin{lyxcode}
gladevcp~myui.ui
\end{lyxcode}

\section{Integrating the example UI into Axis}

While you could run your UI as a separate top level window side-by-side
with Axis, having it within the Axis frame as a tab side-by-side with
the Preview and DRO tabs is more elegant. To do so, edit your .ini
file and add two variables to the DISPLAY section of ini file:
\begin{lyxcode}
{\small EMBED\_TAB\_NAME~=~GladeVCP}{\small \par}

{\small EMBED\_TAB\_COMMAND~=~gladevcp~-c~gladevcp-test~-w~\{XID\}~-H~gladevcp-test.hal~gladevcp-test.ui}{\small \par}
\end{lyxcode}
Try it out by running Axis - there should be a new tab called 'GladeVCP'
near the DRO tab. Select that tab, you should see the example panel
nicely fit within Axis like so:

%
\begin{figure}[H]


\caption{GladeVCP in Axis}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/axis-gladevcp}
\end{figure}



\section{Integrating into Touchy}

Touchy also understands EMBED\_TAB\_NAME/EMBED\_TAB\_COMMAND variables
from INI file so instructions for it are equal to Axis.


\section{Axis: linking HAL pins in the example UI}

To be useful, the pins in your UI need to be linked to the rest of
your setup. Usually this is done by running one or several HAL files
through the HALFILE and POSTGUI\_HALFILE statements in the HAL section
of your .ini file.

For gladevcp components this not currently possible because all of
these HALFILE statements are run before gladevcp is started, so linking
to your UI's pins from there would refer to pins which do not yet
exist. You therefore need to prepare a file of all HAL commands which
refer to / link with your UI's pins and pass it to the gladevcp command
in the EMBED\_TAB\_COMMAND statement like so:

EMBED\_TAB\_COMMAND = gladevcp -c gladevcp-test -H gladevcp-test.hal
-w \{XID\} gladevcp-test.glade

There is an example gladevcp-test.hal file in the emc2-dev/lib/python/gladevcp
directory. Before using it in the EMBED\_TAB\_NAME statement, make
sure the loadusr statements at the top are commented out.


\section{Adding custom user callbacks in Python}

This is just a very minimal example to convey the idea - for a detailed
description on how to program a gladevcp application, see GladeVCPprogramming
and HalWidgets.

gladevcp cannot only manipulate or display HAL pins, you can also
write regular event handlers in Python. This could be used, among
others, to execute MDI commands. Here's how you do it:

Write a Python module like so and save as e.g. handlers.py:
\begin{lyxcode}
nhits~=~0

def~on\_button\_press(gtkobj,data=None):

global~nhits~nhits~+=~1~gtkobj.set\_label(\textquotedbl{}hits:~\%d\textquotedbl{}~\%~nhits)
\end{lyxcode}
In glade, define a button or HAL button, select the 'Signals' tab,
and in the GtkButton properties select the 'pressed' line. Enter 'on\_button\_press'
there, and save the glade file.

Then add the option '-u handlers.py' to the gladevcp command line.
If your event handlers are spread over several files, just add multiple
'-u <pyfilename>' options.

Now, pressing the button should change its label since it's set in
the callback function.

What the -u flag does is: all Python functions in this file are collected
and setup as potential callback handlers for your Gtk widgets - they
can be referenced from glade 'Signals' tabs. The callback handlers
are called with the particular object instance as parameter, like
the GtkButton instance above, so you can apply any GtkButton method
from there.

Or do some more useful stuff, like calling an MDI command!


\section{Gladevcp command line options}

See also 'man gladevcp' . This is the usage message when you run 'gladevcp
-h':

Usage: gladevcp {[}options{]} myfile.ui

Options:
\begin{description}
\item [{-h,~--help}] show this help message and exit
\item [{-c~NAME}] Set component name to NAME. Default is base name of
UI file
\item [{-d}] Enable debug output
\item [{-g~GEOMETRY}] Set geometry WIDTHxHEIGHT+XOFFSET+YOFFSET.Values
are in pixel units, XOFFSET/YOFFSET is referenced from top left of
screen use -g WIDTHxHEIGHT for just setting size or -g +XOFFSET+YOFFSET
for just position -H FILE execute hal statements from FILE with halcmd
after the component is set up and ready
\item [{-x~XID}] Re-parent gladevcp into an existing window XID instead
of creating a new top level window
\item [{-u~FILE}] Use File's as additional user defined modules with handlers
\item [{-U~USEROPT}] pass USEROPTs to Python modules
\end{description}

\section{Troubleshooting}
\begin{itemize}
\item make sure your have the development version of emc2 installed. You
don't need the axisrc file any more, this was mentioned in the old
GladeVcp wiki page.
\item run gladevcp or Axis from a terminal window. If you get Python errors,
check whether there's still a /usr/lib/python2.6/dist-packages/hal.so
file lying around besides the newer /usr/lib/python2.6/dist-packages/\_hal.so
(note underscore); if yes, remove the hal.so file. It has been superseded
by hal.py in the same directory and thus creates confusion.
\item if you're using run-in-place, do a 'make clean' to remove any accidentially
left over hal.so file, then 'make'.
\item if you're using 'HAL\_table' or 'HAL\_HBox' widgets, be aware they
have an HAL pin associated with it which is off by default. This pin
controls whether these container's children are active or not.
\end{itemize}

\chapter{GladeVCP Programming}


\section{PyVCP to GladeVCP}

Stock gladevcp can be used pretty much in the style of PyVCP - the
major difference being that in the case of gladevcp, the glade user
interface editor is used to design a screen layout, whereas PyVCP
is driven by manually edited XML files. Also, PyVCP uses the TkInter
widgets, whereas gladevcp uses the much richer GTK toolkit. Both support
'HAL widgets' - widgets with one or more associated HAL pin which
is the interface to the rest of EMC. Stock gladevcp and PyVCP panels
are really just a bunch of virtual switches, dials, leds an so forth,
wired to the outside world through the HAL layer, designed to set
and read ints, bits and floats values.

Most widget sets, and their associated user interface editors, support
the concept of callbacks - functions in user-written code which are
executed when 'something happens' in the UI - events like mouse clicks,
characters typed, mouse movement, timer events, window hiding and
exposure and so forth. Both PyVCP and stock gladevcp mainly do two
things: mapping events on HAL widgets to actions like a value change
of the associated HAL pin, and in the other direction - detecting
if HAL pin values changed and updating the associated widget, like
a LED, a meter, a bar, or just some label displaying a value. However,
neither PyVCP nor stock gladevcp provide support for other actions
than changing HAL values. Doing something more complex, like executing
MDI commands to call a G-code subroutine, is outside scope.


\section{Hal Widgets}

GladeVcp includes a collection of Gtk widgets with attached HAL pins
called HAL Widgets, intended to control, display or otherwise interact
with the EMC HAL layer. They are intended to be used with the glade
user interface editor. With proper installation, the HAL Widgets should
show up in glade's 'HAL Python' widget group. Many HAL specific fields
in the glade 'General' section have an associated mouse-over tool
tip.



HAL signals come in two variants, bits and numbers. Bits are off/on
signals. Numbers can be \textquotedbl{}float\textquotedbl{}, \textquotedbl{}s32\textquotedbl{}
or \textquotedbl{}u32\textquotedbl{}. For more information on HAL
data types see the {[}->{]} section. The GladeVcp widgets can either
display the value of the signal with an indicator widget, or modify
the signal value with a control widget. Thus there are four classes
of GladeVcp widgets that you can connect to a HAL signal. Another
class of helper widgets allow you to organize and label your panel.
\begin{itemize}
\item Widgets for indicating \textquotedbl{}bit\textquotedbl{} signals:
HAL\_LED
\item Widgets for controlling \textquotedbl{}bit\textquotedbl{} signals:
HAL\_Button, HAL\_RadioButton, HAL\_CheckButton, HAL\_RadioButton
\item Widgets for indicating \textquotedbl{}number\textquotedbl{} signals:
HAL\_Label, HAL\_ProgressBar, HAL\_Bar, HAL\_VBar, HAL\_Meter
\item Widgets for controlling \textquotedbl{}number\textquotedbl{} signals:
HAL\_SpinButton, HAL\_HScale, HAL\_VScale
\item Helper widgets: HAL\_Table, HAL\_HBox
\item Tool Path preview: HAL\_Gremlin
\end{itemize}
HAL Widgets inherit methods, properties and signals from the underlying
Gtk widgets, so it is helpful to consult the Gtk and PyGTK documentation
as well.


\subsection*{Widget and HAL pin naming}

Most HAL widgets have a single associated HAL pin with the same name
as the widget (glade: General->Name). Exceptions to this rule currently
are the HAL\_Spinbutton, which has two pins: a <widgetname>-f (float)
and a <widgetname>-s (s32) pin, and the HAL\_ProgressBar, which has
a <widgetname> value input pin, and a <widgetname>.scale input pin.


\subsection*{Setting pin and widget values}

As a general rule, if you need to set a HAL output widget's value
from Python code, do so by calling the underlying Gtk 'setter' (e.g.
set\_active(), set\_value()) - do not try to set the associated pin's
value by halcomp{[}pinname{]} = value directly because the widget
'will not notice'.

It might be tempting to 'set HAL widget input pins' programmatically.
Note this defeats the purpose of an input pin in the first place -
it should be linked to, and react to signals generated by other HAL
components. While there is currently no write protection on writing
to input pins in HAL Python, this doesn't make sense. You might use
setp pinname value in the associated halfile for testing though.

It is perfectly OK to set an output HAL pin's value with halcomp{[}pinname{]}
= value provided this HAL pin is not associated with a widget, that
is, has been created by the hal\_glib.GPin(halcomp.newpin(<name>,<type>,<direction>)
method (see GladeVCProgramming for an example).


\subsection*{The hal-pin-changed signal}

Event-driven programming means that the UI tells you when \textquotedbl{}something
happens\textquotedbl{} - through a callback, like when a button was
pressed. The output HAL widgets (those which display a HAL pin's value)
like LED, Bar, VBar, Meter etc, support the hal-pin-changed signal
which may cause a callback into your Python code when - well, a HAL
pin changes its value. This means there's no more need for permanent
polling of HAL pin changes in your code, the widgets do that in the
background and let you know. The example in configs/gladevcp/examples/complex
shows how this is handled in Python.

Here is an example how to set a hal-pin-changed signal for a HAL\_LED
in the glade UI editor:

%
\begin{figure}[H]


\caption{Hal Pin Change}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/hal-pin-change}
\end{figure}



\subsection*{Buttons}

This group of widget is derived from various Gtk buttons and consists
of HAL\_Button, HAL\_ToggleButton, HAL\_RadioButton and CheckButton
widgets. All of them have a single output BIT pin named identical
to the widget. Buttons have no additional properties compared to their
base Gtk classes.
\begin{itemize}
\item HAL\_Button: instantaneous action, does not retain state. Important
signal: pressed
\item HAL\_ToggleButton, HAL\_CheckButton: retains on/off state. Important
signal: toggled
\item HAL\_RadioButton: a one-of-many group. Important signal: toggled (per
button).
\item Important common methods: set\_active(), get\_active()
\item Important properties: label, image
\end{itemize}
%
\begin{figure}


\caption{Buttons}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/checkbutton}\includegraphics[scale=0.8]{gui/images/radiobutton}
\end{figure}


Hint: Defining radio button groups in glade:

- decide on default active button

- in the other button's General->Group select the default active button's
name in the 'Choose a Radio Button in this project' dialog.

See configs/gladevcp/by-widget/radiobutton for a gladevcp application
and UI file for working with radio buttons.


\subsection*{Scales}

HAL\_HScale and HAL\_VScale are derived from the GtkHScale and GtkVScale
respectively. They have one output FLOAT pin with name equal to widget
name. Scales have no additional properties.

%
\begin{figure}[H]


\caption{Scale}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/hscale}
\end{figure}


Hint: To make a scale useful in glade, add an 'Adjustment' (General->Adjustment->New
or existing adjustment) and edit the adjustment object. It defines
the default/min/max/increment

values. Also, set adjustment 'Page size' and 'Page increment' to zero
to avoid warnings.


\subsection*{SpinButton}

HAL SpinButton is derived from GtkSpinButton and holds two pins:
\begin{itemize}
\item \{widgetname\}-f: out FLOAT pin
\item \{widgetname\}-s: out S32 pin
\end{itemize}
%
\begin{figure}


\caption{SpinButton}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/spinbutton}
\end{figure}


Hint: to be useful, Spinbuttons need an adjustment value like scales,
see above.


\subsection*{Label}

HAL\_Label is simple widget based on GtkLabel which represents a HAL
pin value in a user-defined format. The pin's HAL type depends on
the label\_pin\_type property (0:S32, 1:float, 2:U32), see also the
tooltip on General->HAL pin type (note this is different from PyVCP
which has three label widgets, one for each type).

The text displayed depends on the text\_template property - an Python
format string to represent the pin value. It defaults to \textquotedbl{}\%s\textquotedbl{}
(values are converted by the str() function) but may contain anything
legit in a as argument to Pythons format() method.

Example: Distance: \%.03f will display the text and the pin value
with 3 fractional digits padded with zeros for a FLOAT pin.


\subsection*{Containers: HAL\_HBox and HAL\_Table}

Compared to their Gtk counterparts they have one input BIT pin which
controls if their child widgets are sensitive or not. If the pin is
low then child widgets are inactive which is the default.

Hint: if you find some part of your gladevcp application is 'grayed
out' (insensitive), see whether a container's pin is unset.


\subsection*{LED}

The HAL\_Led simulates a real indicator LED . It has a single input
BIT pin which controls it's state: ON or OFF. Leds have several properties
which control their look and feel:
\begin{itemize}
\item on\_color: a String defining ON color of led. May be any valid gtk.gdk.Color
name. Not working on Ubuntu 8.04.
\item off\_color: String defining OFF color of led. May be any valid gtk.gdk.Color
name or special value \textquotedbl{}dark\textquotedbl{}. \textquotedbl{}dark\textquotedbl{}
means that OFF color will be set to 0.4 value of ON color. Not working
on Ubuntu 8.04.
\item pick\_color\_on, pick\_color\_off: Colors for ON and OFF states may
be represented as \#RRRRGGGGBBBB strings. These are optional properties
which have precedence over \textquotedbl{}on\_color\textquotedbl{}
and \textquotedbl{}off\_color\textquotedbl{}.
\item led\_size: LED radius (for square - half of LED's side)
\item led\_shape: LED Shape. Valid values are 0 for round, 1 for oval and
2 for square shapes.
\item led\_blink\_rate: if set and led is ON then it's blinking. Blink frequency
is equal to \textquotedbl{}led\_blink\_rate\textquotedbl{} specified
in milliseconds.
\end{itemize}
As an input widget, LED also supports the hal-pin-changed signal.
If you want to get a notification in your code when the LED's HAL
pin was changed, then connect this signal to a handler, for example
on\_led\_pin\_changed and provide the handler as follows:
\begin{lyxcode}
def~on\_led\_pin\_changed(self,hal\_led,data=None):

print~\textquotedbl{}on\_led\_pin\_changed()~-~HAL~pin~value:\textquotedbl{},hal\_led.hal\_pin.get()
\end{lyxcode}
This will be called at any edge of the signal and also during program
start up to report the current value.

Example LEDs:

%
\begin{figure}[H]


\caption{LED}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/leds}
\end{figure}



\subsection*{ProgressBar}



Note: This widget might go away. Use the HAL\_HBar and HAL\_VBar widgets
instead.

The HAL\_ProgressBar is derived from gtk.ProgressBar and has two float
HAL input pins:
\begin{itemize}
\item <widgetname> - the current value to be displayed
\item <widgetname>.scale - the maximum absolute value of input
\end{itemize}
It has the following properties:
\begin{itemize}
\item scale - value scale. set maximum absolute value of input. Same as
setting the <widgetname>.scale pin. A float, range from -2{*}{*}24
to 2{*}{*}24.
\item green\_limit - green zone limit lower limit 
\item yellow\_limit - yellow zone limit lower limit
\item red\_limit - red zone limit lower limit
\item text\_template - Text template to display the current value of the
<widgetname> pin. Python formatting may be used for dict \{\textquotedbl{}value\textquotedbl{}:value\}
\end{itemize}


%
\begin{figure}[H]
\caption{Progressbar}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/progressbar2}
\end{figure}



\subsection*{ComboBox}

HAL\_ComboBox is derived from gtk.ComboBox. It enables choice of a
value from a dropdown list.

It exports two HAL pins:
\begin{itemize}
\item <widgetname>-f: the current value, type FLOAT
\item <widgetname>-s: the current value, type S32
\end{itemize}
It has the following property which can be set in glade:
\begin{lyxcode}
column:~the~column~index,~type~S32,~defaults~to~-1,~range~from~-1..100~.
\end{lyxcode}
In default mode this widgets sets the pins to the index of the chosen
list entry. So if your widget has three labels, it may only assume
values 0,1 and 2.

In column mode (column > -1), the value reported is chosen from the
ListStore array as defined in Glade. So typically your widget definition
would have two columns in the ListStore , one with text displayed
in the dropdown, and an int or float value to use for that choice.

There's an example in configs/gladevcp/by-widget/combobox/combobox.\{py,ui\}
which uses column mode to pick a float value from the ListStore.

If you're confused like me about how to edit ComboBox ListStores and
CellRenderer , see http://www.youtube.com/watch?v=Z5\_F-rW2cL8.


\subsection*{Bars}

HAL Bar and VBar widgets for horizontal and vertical bars representing
float values. They have one input FLOAT hal pin. Both bars have the
following properties:
\begin{itemize}
\item invert: Swap min and max direction. An inverted HBar grows from right
to left, an inverted VBar from top to bottom.
\item min, max: Minimum and maximum value of desired range. It is not an
error condition if the current value is outside this range.
\item zero: Zero point of range. If it's inside of min/max range then the
bar will grow from that value and not from the left (or right) side
of the widget. Useful to represent values that may be both positive
or negative.
\item force\_width, force\_height: Forced width or height of widget. If
not set then size will be deduced from packing or from fixed widget
size and bar will fill whole area.
\item text\_template: Like in Label sets text format for min/max/current
values. Can be used to turn off value display.
\item bg\_color: Background (inactive) color of bar.
\item z0\_color, z1\_color, z2\_color: Colors of different value zones.
Defaults are \textquotedbl{}green\textquotedbl{}, \textquotedbl{}yellow\textquotedbl{}
and \textquotedbl{}red\textquotedbl{}. For description of zones see
\textquotedbl{}z{*}\_border\textquotedbl{} properties.
\item {*} z0\_border, z1\_border: Define up bounds of color zones. By default
only one zone is enabled. If you want more then one zone set \textquotedbl{}z0\_border\textquotedbl{}
and \textquotedbl{}z1\_border\textquotedbl{} to desired values so
zone 0 will fill from 0 to first border, zone 1 will fill from first
to second border and zone 2 -- from last border to 1. Borders are
set as fractions, values from 0 to 1.
\end{itemize}
Examples:

%
\begin{figure}[H]


\caption{Bars}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/hal_hbar}\includegraphics[scale=0.8]{gui/images/vscale}
\end{figure}



\subsection*{Meter}

HAL Meter is widget like PyVCP meter representing float value. It
have one input FLOAT hal pin. Widget has following properties:
\begin{itemize}
\item min, max: Minimum and maximum value of desired range. It is not an
error condition if the current value is outside this range.
\item force\_size: Forced diameter of widget. If not set then size will
be deduced from packing or from fixed widget size and meter will fill
all available space with respect to aspect ratio.
\item text\_template: Like in Label sets text format for current value.
Can be used to turn off value display.
\item label: Large label above center of meter.
\item sublabel: Small label below center of meter.
\item bg\_color: Background color of meter.
\item z0\_color, z1\_color, </t>z2\_color</tt>: Colors of different value
zones. Defaults are \textquotedbl{}green\textquotedbl{}, \textquotedbl{}yellow\textquotedbl{}
and \textquotedbl{}red\textquotedbl{}. For description of zones see
\textquotedbl{}z{*}\_border\textquotedbl{} properties.
\item z0\_border, z1\_border: Define up bounds of color zones. By default
only one zone is enabled. If you want more then one zone set \textquotedbl{}z0\_border\textquotedbl{}
and \textquotedbl{}z1\_border\textquotedbl{} to desired values so
zone 0 will fill from min to first border, zone 1 will fill from first
to second border and zone 2 -- from last border to max. Borders are
set as values in range min-max.
\end{itemize}
Examples:

%
\begin{figure}
\caption{Hal Meter}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/hal_meter}
\end{figure}



\subsection*{Gremlin tool path preview for .ngc files}

Gremlin is a plot preview widget similar to the Axis preview window.
It assumes a running EMC environment like Axis or Touchy. To connect
to it, inspects the INI\_FILE\_NAME environment variable. Gremlin
displays the current .ngc file - it does monitor for changes and reloads
the ngc file if the file name in Axis/Touchy changes. If you run it
in a gladevcp application when EMC is not running you might get a
traceback because the Gremlin widget cant find EMC status, like the
current file name.

Gremlin does not export any HAL pins. It has the following properties:
\begin{itemize}
\item view : may be any of 'x', 'y', 'z', 'p' (perspective) . Defaults to
'z' view.
\item enable\_dro : boolean; wether to draw a DRO on the plot or not. Defaults
to 'True'.
\end{itemize}
Example:

%
\begin{figure}[H]


\caption{Gremlin}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/gremlin}
\end{figure}



\section{Action Widgets}

GladeVcp includes a collection of \textquotedbl{}canned actions\textquotedbl{}
called EMC Action Widgets for the glade user interface editor. Other
than HAL widgets, which interact with HAL pins, EMC Actions interact
with EMC and the G-code interpreter.

EMC Action Widgets are derived from the Gtk.Action widget. The Action
widget in a nutshell:
\begin{itemize}
\item it is an object available in glade
\item it has no visual appearance by itself
\item it's purpose: associate a visible, sensitive UI component like menu,
toolbutton, button with a command. See these widget's 'General->Related
Action' property.
\item the \textquotedbl{}canned action\textquotedbl{} will be executed when
the associated UI component is triggered (button press, menu click..)
\item it provides an easy way to execute commands without resorting to Python
programming.
\end{itemize}
The appearance of EMC Actions in glade is roughly as follows:

%
\begin{figure}[H]


\caption{Actions}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/emc-actions}
\end{figure}


Tooltip hovers provide a description.


\subsection*{Action widget types}


\subsubsection*{EMC Action widgets}

These are one-shot type widgets. They implement a single action and
are for use in simple buttons, menu entries or radio/check groups.


\subsubsection*{EMC ToggleAction widgets}

These are bi-modal widgets. They implement two actions or use a second
(usually pressed) state to indicate that currently an action is running.
Toggle actions are aimed for use in ToggleButtons, ToggleToolButtons
or toggling menu items. A simplex example is the ESTOP toggle button.

Currently the following widgets are available:
\begin{itemize}
\item The ESTOP toggle sends ESTOP or ESTOP\_RESET commands to EMC depending
on it's state.
\item The ON/OFF toggle sends STATE\_ON and STATE\_OFF commands.
\item Pause/Resume sends AUTO\_PAUSE or AUTO\_RESUME commands.
\end{itemize}
The following toggle actions have only one associated command and
use the 'pressed' state to indicate that the requested operation is
running:
\begin{itemize}
\item The Run toggle sends an AUTO\_RUN command and waits in the pressed
state until the interpreter is idle again.
\item The Stop toggle is inactive until the interpreter enters the active
state (is running G-code) and then allows user to send AUTO\_ABORT
command.
\item The MDI toggle sends given MDI command and waits for its completion
in 'pressed' inactive state.
\end{itemize}

\subsubsection*{The Action\_MDI Toggle and Action\_MDI widgets}

These widgets provide a means to execute arbitrary MDI commands.


\subsubsection*{A simple example: Execute MDI command on button press}

Here's a glade UI file which conveys the basics:

Open it in glade and study how it's done. Start Axis, and then start
this from a terminal window with gladevcp whoareyou.ui . See the hal\_action\_mdi1
Action and it's MDI command property - this just executes (MSG, \textquotedbl{}Hi,
I'm an EMC\_Action\_MDI\textquotedbl{}) so there should be a message
popup in Axis like so:

%
\begin{figure}[H]


\caption{Who Are You}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/whoareyou}
\end{figure}


You'll notice that the button associated with the Action\_MDI action
is grayed out if the machine is off, in E-Stop or the program is running.
It will automatically become active when the machine is turned on
and out of E-Stop, and the program is idle.


\subsubsection*{Parameter processing in the Action\_MDI and ToggleAction\_MDI widgets}

Optionally, 'MDI command' strings may have parameters substituted
before they are passed to the interpreter. Parameters currently may
be names of HAL pins in the gladevcp component (in a later release,
this will be extended to cover HAL pins of other components as well).
This is how it works:
\begin{itemize}
\item assume you have a HAL SpinBox named speed, and you want to pass it's
current value as a parameter in an MDI command.
\item The HAL SpinBox? will have a float-type HAL pin named speed-f (see
HalWidgets description).
\item To substitute this value in the MDI command, insert the HAL pin name
enclosed like so: \$\{pin-name\}
\item for the above HAL SpinBox, we could use (MSG, \textquotedbl{}The speed
is: \$\{speed-f\}\textquotedbl{}) just to show what's happening.
\end{itemize}
Here's the example UI file for gladevcp: , and here's what you get:

%
\begin{figure}[H]
\caption{Speed}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/speed}
\end{figure}



\subsubsection*{An advanced example: Feeding parameters to an O-word subroutine}

It's perfectly OK to call an O-word subroutine in an MDI command,
and pass HAL pin values as actual parameters. Here's an example UI
file upload:owordsub.ui and O-word sub:

Place oword.ngc so Axis can find it, and run gladevcp owordsub.ui
from a terminal window. This looks like so:

%
\begin{figure}[H]


\caption{O Word}


\noindent \centering{}\includegraphics[scale=0.8]{gui/images/oword}
\end{figure}



\subsubsection*{Preparing for an MDI Action, and cleaning up afterwards}

The EMC G-Code interpreter has a single global set of variables, like
feed, spindle speed, relative/absolute mode and others. If you use
G code commands or O-word subs, some of these variables might get
changed by the command or subroutine - for example, a probing subroutine
will very likely set the feed value quite low. With no further precautions,
your previous feed setting will be overwritten by the probing subroutine's
value.

To deal with this surprising and undesirable side effect of a given
O-word subroutine or G-code statement executed with an EMC ToggleAction\_MDI,
you might associate pre-MDI and post-MDI handlers with a given EMC
ToggleAction\_MDI. These handlers are optional and provide a way to
save any state before executing the MDI Action, and to restore it
to previous values. The signal names are mdi-command-start and mdi-command-stop;
the handler names can be set in glade like any other handler.

Here's an example how a feed value might be saved and restored by
such handlers (note that EMC command and status channels are available
as self.emc and self.stat through the \_EMC\_ActionBase class:
\begin{lyxcode}
def~on\_mdi\_command\_start(self,~action,~userdata=None):

~~~~action.stat.poll()

~~~~self.start\_feed~=~action.stat.settings{[}1{]}



def~on\_mdi\_command\_stop(self,~action,~userdata=None):

~~~~action.emc.mdi('F\%.1f'~\%~(self.start\_feed))

~~~~while~action.emc.wait\_complete()~==~-1:

~~~~~~~~pass
\end{lyxcode}
Only the Action\_MDI Toggle widget supports these signals.


\subsubsection*{Using the EMC Stat object to deal with status changes}

Many actions depend on EMC status - is it in manual, MDI or auto mode?
is a program running, paused or idle? You cannot start an MDI command
while a G-code program is running, so this needs to be taken care
of. Many EMC actions take care of this themselves, and related buttons
and menu entries are deactivated when the operation is currently impossible.

When using Python event handlers - which are at a lower level than
Actions - one needs to take care of dealing with status dependencies
oneself. For this purpose, there's the EMC Stat widget: to associate
EMC status changes with event handlers.

EMC Stat has no visible component - you just add it to your UI with
glade. Once added, you can associate handlers with its following signals:
\begin{itemize}
\item state-related: \textquotedbl{}state-estop\textquotedbl{}, \textquotedbl{}state-estop-reset\textquotedbl{},
\textquotedbl{}state-on\textquotedbl{}, \textquotedbl{}state-off\textquotedbl{}
- emitted when E-Stop condtion occurs, is reset, machine is turned
on, or is turned off
\item mode-related: \textquotedbl{}mode-manual\textquotedbl{}, \textquotedbl{}mode-mdi\textquotedbl{},
\textquotedbl{}mode-auto\textquotedbl{} - emitted when EMC enters
that particular mode
\item interpreter-related: \textquotedbl{}interp-run\textquotedbl{}, \textquotedbl{}interp-idle\textquotedbl{},
\textquotedbl{}interp-paused\textquotedbl{}, \textquotedbl{}interp-reading\textquotedbl{},
\textquotedbl{}interp-waiting\textquotedbl{} - emitted when the G-code
interpreter changes into that mode
\end{itemize}

\section{User Defined Actions}

As most of the infrastructure to support user-defined actions in glade
and the GTK widget set is in place, the new gladevcp version really
just provides a way for the user to write a Python module whose class
methods - or in the simple case, just functions - can be referred
to in glade as event handlers, a way to import this module(s) into
gladevcp at runtime and properly link it with the rest of the HAL
layer.


\subsection*{HAL value change events}

We also extended the way the HAL input pins interact with the gladevcp
panel. Beyond HAL widgets displaying pin values, there is now a way
to attach a 'value-changed' callback to a HAL pin, which fits nicely
with the event-driven structure of a typical widget application: every
activity, be it mouse click, key, timer expired, or the change of
a HAL pin's value, generates a callback and is handled by the same
orthogonal mechanism.

Note that the above refers to explicitly declared HAL pins. HAL widgets
come with a pre-defined signal 'hal-pin-changed', see the HalWidgets
page for details.

See the 'Adding HAL pins' section below for details.


\subsection*{Persistent values in GladeVCP}

A annoying aspect of gladevcp in its earlier form and pyvcp is the
fact that you may change values through text entry, sliders, spin
boxes, toggle buttons etc, but their settings are not saved and restored
at the next run of EMC - they start at the default value as set in
the panel or widget definition. Therefore I added an easy-to-use mechanism
to save and restore the state of HAL widgets, and program variables
(in fact instance attributes) as well. This mechanism uses the popular
'.ini' file syntax and has safeguards against the .ini file and the
corresponding user interface or program variables getting out of sync
- just imagine renaming, adding or deleting widgets in glade: an .ini
file lying around from a previous program version, or an entirely
different user interface, would be not be able to restore the state
properly. This situation is detected through a signature which depends
on all object names and types which are saved and to be restored.
In the case of signature mismatch, a new .ini file with default settings
is generated.


\subsection*{Programming model}

The overall protocol is as follows:
\begin{itemize}
\item design your UI with glade, and set signal handlers where you want
actions associated with a widget
\item write a Python module which contains callable objects (see 'handler
models' below)
\item pass your module's path name to gladevcp with the '-u <module>' option
\item gladevcp imports the module, inspects it for signal handlers and connects
them to the widget tree
\item the main event loop is run.
\end{itemize}

\subsubsection*{The simple handler model}

For simple tasks it's sufficient to define functions named after the
glade signal handlers. These will be called when the corresponding
event happens in the widget tree. Here's a trivial example - it assumes
that the 'pressed' signal of a GTK Button or HAL Button is linked
to a callback called 'on\_button\_press':
\begin{lyxcode}
nhits~=~0

def~on\_button\_press(gtkobj,data=None):

global~nhits

nhits~+=~1

gtkobj.set\_label(\textquotedbl{}hits:~\%d\textquotedbl{}~\%~nhits)
\end{lyxcode}
Add this function to a Python file and run as follows:
\begin{lyxcode}
gladevcp~-u~<myhandler>.py~mygui.ui
\end{lyxcode}
Note communication between handlers has to go through global variables,
which does not scale well and is positively un-pythonic. This is why
we came up with the class-based handler model.


\subsubsection*{The class-based handler model}

The idea here is: handlers are linked to class methods. The underlying
class(es) are instantiated and inspected during gladevcp startup and
linked to the widget tree as signal handlers. So the task now is to
write:
\begin{itemize}
\item one or more several class definition(s) with one or several methods,
in one module or split over several modules,
\item a function 'get\_handlers' in each module which will return a list
of class instances to gladevcp - their method names will be linked
to signal handlers
\end{itemize}
Here is a minimum user-defined handler example module:
\begin{lyxcode}
Class~MyCallbacks~:

def~on\_this\_signal(self,obj,data=None):

print~\textquotedbl{}this\_signal~happened,~obj=\textquotedbl{},obj

def~get\_handlers(halcomp,builder,useropts):

return~{[}MyCallbacks~(){]}
\end{lyxcode}
Now, 'on\_this\_signal' will be available as signal handler to your
widget tree.


\subsubsection*{The get\_handlers protocol}

If during module inspection gladevcp finds a function 'get\_handlers',
it calls it as follows:

get\_handlers(halcomp,builder,useropts)

the arguments are:
\begin{itemize}
\item halcomp - refers to the HAL component under construction
\item builder - widget tree - result of reading the UI definition (either
referring to a GTKBuilder or libglade-type object)
\item useropts - a list of strings collected from the gladevcp command line
'-U <useropts>' option
\end{itemize}
gladevcp then inspects the list of class instances and retrieves their
method names. Qualifying method names are connected to the widget
tree as signal handlers. Only method names which do not begin with
an '\_' (underscore) are considered.

Note that regardless whether you're using the libglade or the new
GtkBuilder format for your glade UI, widgets can always be referred
to as \textbf{builder.get\_object(<widgetname>)}. Also, the complete
list of widgets is available as \textbf{builder.get\_objects()} regardless
of UI format.


\subsection*{Initialization sequence}

It is important to know in which state of affairs your get\_handlers()
function is called so you know what is safe to do there and what not.
First, modules are imported and initialized in command line order.
After successful import, get\_handlers() is called in the following
state:
\begin{itemize}
\item the widget tree is created, but not yet realized (no toplevel window.show()
has been executed yet)
\item the halcomp HAL component is set up and all HAL widget's pins have
already been added to it
\item it is safe to add more HAL pins because halcomp.ready() has not yet
been called at this point, so you may add your own pins, for instance
in the class \_\_init\_\_() method.
\end{itemize}
Once all modules have been imported and method names extracted, the
following steps happen:
\begin{itemize}
\item all qualifying method names will be connected to the widget tree with
connect\_signals()/signal\_autoconnect() (depending on the type of
UI imported - GtkBuilder vs the old libglade format).
\item the HAL component is finalized with halcomp.ready()
\item if a window ID was passed as argument, the widget tree is re-parented
to run in this window, and glade's toplevel window1 is abandoned (see
FAQ)
\item if a HAL command file was passed with '-H halfile', it is executed
with halcmd
\item the gtk main loop is run.
\end{itemize}
So when your handler class is initialized, all widgets are existent
but not yet realized (displayed on screen). And the HAL component
isn't ready as well, so its unsafe to access pins values in your \_\_init\_\_()
method.

If you want to have a callback to execute at program start after it
is safe to access HAL pins, then a connect a handler to the realize
signal of the top level window1 (which might be its only real purpose).
At this point gladevcp is done with all setup tasks, the halfile has
been run, and gladevcp is about to enter the gtk main loop.


\subsection*{Multiple callbacks with the same name}

Within a class, method names must be unique. However, it is OK to
have multiple class instances passed to gladevcp by get\_handlers()
with identically named methods. When the corresponding signal occurs,
these methods will be called in definition order - module by module,
and within a module, in the order class instances are returned by
get\_handlers().


\subsection*{The gladevcp -U <useropts> flag}

Instead of extending gladevcp for any conceivable option which could
potentially be useful for a handler class, you may use the -U <useroption>
flag (repeatedly if you wish). This flag collects a list of <useroption>
strings. This list is passed to the get\_handlers() function (useropts
argument). Your code is free to interpret these strings as you see
fit. An possible usage would be to pass them to the Python exec function
in your get\_handlers() as follows:
\begin{lyxcode}
debug~=~0

...

def~get\_handlers(halcomp,builder,useropts):

...

global~debug~\#~assuming~there's~a~global~var

for~cmd~in~useropts:

exec~cmd~in~globals()
\end{lyxcode}
This way you can pass arbitrary Python statements to your module through
the gladevcp -U option, for example:

gladevcp -U debug=42 -U \textquotedbl{}print 'debug=\%d' \% debug\textquotedbl{}
...

This should set debug to 2 and confirm that your module actually did
it.


\subsection*{Persistence}

If you want any of: GTK widget state, HAL widgets output pin's values
and/or class attributes of your handler class to be retained across
invocations, proceed as follows:
\begin{itemize}
\item import the gladevcp.persistence module
\item decide which instance attributes, and their default values you want
to have retained, if any
\item decide which widgets should have their state retained
\item describe these decisions in your handler class' \_\_init\_\_() method
through a nested dictionary as follows:\end{itemize}
\begin{lyxcode}
def~\_\_init\_\_(self,~halcomp,builder,useropts):

self.halcomp~=~halcomp

self.builder~=~builder

self.useropts~=~useropts

self.defaults~=~\{

~~~~\#~the~following~names~will~be~saved/restored~as~method~attributes

~~~~\#~the~save/restore~mechanism~is~strongly~typed~-~the~variables~type~will~be~derived~from~the~type~of~the

~~~~\#~initialization~value.~Currently~supported~types~are:~int,~float,~bool,~string

~~~~IniFile.vars~:~\{~'nhits'~:~0,~'a':~1.67,~'d':~True~,'c'~:~\textquotedbl{}a~string\textquotedbl{}\},

~~~~\#~to~save/restore~all~widget's~state~which~might~remotely~make~sense,~add~this:

~~~~IniFile.widgets~:~widget\_defaults(builder.get\_objects())

~~~~\#~a~sensible~alternative~might~be~to~retain~only~all~HAL~output~widgets'~state:

~~~~\#~IniFile.widgets:~widget\_defaults(select\_widgets(self.builder.get\_objects(),~hal\_only=True,output\_only~=~True)),

\}
\end{lyxcode}
and associate an .ini file with this descriptor:
\begin{lyxcode}
self.ini\_filename~=~\_\_name\_\_~+~'.ini'

self.ini~=~IniFile(self.ini\_filename,self.defaults,self.builder)

self.ini.restore\_state(self)
\end{lyxcode}
after restore\_state(), self will have attributes set if as running
the following:
\begin{lyxcode}
self.nhits~=~0

self.a~=~1.67

self.d~=~True

self.c~=~\textquotedbl{}a~string\textquotedbl{}
\end{lyxcode}
Note that types are saved and preserved on restore. This example assumes
that the ini file didn't exist or had the default values from self.defaults.

After this incantation, you can use the following IniFil methods:
\begin{itemize}
\item ini.save\_state(obj) - saves objs's attributes as per IniFil.vars
dictionary and the widget state as described in IniFile.widgets in
self.defaults
\item ini.create\_default\_ini() - create a .ini file with default values
\item ini.restore\_state(obj) - restore HAL out pins and obj's attributes
as saved/initialized to default as above
\end{itemize}
To save the widget and/or variable state on exit, connect a signal
handler to the window1 (toplevel) destroy event:
\begin{lyxcode}
def~on\_destroy(self,obj,data=None):

~~~~self.ini.save\_state(self)
\end{lyxcode}
Next time you start the gladevcp application, the widgets should come
up in the state when the application was closed.


\subsection*{Hand-editing .ini files}

You can do that, but note that the values in self.defaults override
your edits if there is a syntax or type error in your edit. The error
is detected, a console message will hint about that happened, and
the bad inifile will be renamed to have the .BAD suffix. Subsequent
bad ini files overwrite earlier .BAD files.


\subsection*{Adding HAL pins}

If you need HAL pins which are not associated with a specific HAL
widget, add them as follows:
\begin{lyxcode}
import~hal\_glib

...

\#~in~your~handler~class~\_\_init\_\_():

self.example\_trigger~=~hal\_glib.GPin(halcomp.newpin('example-trigger',~hal.HAL\_BIT,~hal.HAL\_IN))
\end{lyxcode}
To get a callback when this pin's value changes, associate a \textbf{value-change}
callback with this pin, add:
\begin{lyxcode}
self.example\_trigger.connect('value-changed',~self.\_on\_example\_trigger\_change)
\end{lyxcode}
and define a callback method (or function, in this case leave out
the 'self' parameter):
\begin{lyxcode}
\#~note~'\_'~-~this~method~will~not~be~visible~to~the~widget~tree

def~\_on\_example\_trigger\_change(self,pin,userdata=None):

print~\textquotedbl{}pin~value~changed~to:\textquotedbl{}~\%~(pin.get())
\end{lyxcode}

\subsection*{Adding timers}

Since gladevcp uses GTK widgets which rely on the GObject base class,
the full glib functionally is available. Here is an example for a
timer callback:
\begin{lyxcode}
def~\_on\_timer\_tick(self,userdata=None):

...

return~True~\#~to~restart~the~timer;~return~False~for~on-shot

...

\#~demonstrate~a~slow~background~timer~-~granularity~is~one~second

\#~for~a~faster~timer~(granularity~1msec),~use~this:

\#~glib.timeout\_add(100,~self.\_on\_timer\_tick,userdata)~\#~10Hz

glib.timeout\_add\_seconds(1,~self.\_on\_timer\_tick)
\end{lyxcode}

\subsection*{Implementation note: Key handling in Axis}

We believe key handling works OK, but since it is new code, we're
telling about it you so you can watch out for problems; please let
us know of errors or odd behavior. This is the story:

Axis uses the TkInter widget set. GladeVCP applications use Gtk widgets
and run in a separate process context. They are hooked into Axis with
the Xembed protocol. This allows a child application like gladevcp
to properly fit in a parent's window, and - in theory - have integrated
event handling.

However, this assumes that both parent and child application properly
support the Xembed protocol, which Gtk does, but TkInter doesn't.
A consequence of this is that certain keys would not be forwarded
from a gladevcp panel to Axis properly under all circumstances. One
of these situations was the case when an Entry, or SpinButton widget
had focus: in this case, for instance an Escape key would not have
been forwarded to Axis and cause an abort as it should, with potentially
disastrous consequences.

Therefore, key events in gladevcp are explicitly handled, and selectively
forwarded to Axis, to assure that such situations cannot arise. For
details, see the keyboard\_forward() function in lib/python/gladevcp/xembed.py.


\subsection*{FAQ}
\begin{itemize}
\item I get an unexpected unmap event in my handler function right after
startup. What's this?: This is a consequence of your glade UI file
having the window1 Visible property set to True, together with re-parenting
the gladevcp window into Axis or touchy. The gladevcp widget tree
is created, including a top level window, and then 'reparented into
Axis', leaving that toplevel window laying around orphaned. To avoid
having this useless empty window hanging around, it is unmapped (made
invisible), which is the cause of the unmap signal you get. Suggested
fix: set window1.visible to False, and ignore an initial unmap event.
\item my gladevcp program starts, but no window appears where I expect it
to be?: The window Axis allocates for gladevcp will obtain the 'natural
size' of all its child widgets combined. It's the child widget's job
to request a size (width and/or height). However, not all widgets
do request a width greater than 0, for instance the Graph widget in
its current form. If there's such a widget in your glade file and
it's the one which defines the layout you might want to set its width
explicitly. Note that setting the window1 width and height properties
in glade does not make sense because this window will be orphaned
during re-parenting and hence its geometry will have no impact on
layout (see above). The general rule is: if you manually run a UI
file with 'gladevcp <uifile>' and its window has reasonable geometry,
it should come up in Axis properly as well.
\end{itemize}

\subsection*{Examples, and rolling your own gladevcp application}

Visit emc2/configs/gladevcp for running examples. The templates subdirectory
has starters for your own projects.
