Kevin C. O'Kane
Professor Emeritus
Computer Science Department
University of Northern Iowa
Cedar Falls, IA 50613
Last Update: December 4, 2022
Note: this project is not affiliated with The Glade Project so don't blame them for my mistakes!
Latest Source Code Version:
The Glade Compiler is included in the Mumps distribution in the projects directory:
The Glade Compiler
-
What is Glade?
- Glade produces an XML representation of your GTK GUI layout. The XML file can be read by GTK functions that, together with your code, can build and display this layout.
- Each active widget in the layout (for example, a button) will most likely have a signal defined in the layout. Signals are raised when actions are performed on a widget. In the case of a button widget, the most common signal is "clicked".
- Glade will build the XML file describing to your app. This includes iformation giving the location, size, function, and signals associated each widget in the app.
- The programmer is responsible to build a program based to implement the GUI layout. This includes the basic GTK main loop, declaration of GTK pointers and creation of signal handlers.
- When a user of an app generates a signal, for example, clicking a button, the GTK main loop attempts to call the signal handler associated with the action or event (for example, a button clicked signal handler). The programmer is responsible for writing the handler to do whatever clicking the button is supposed to do.
- While the working content of any app is mainly found in the signal or event handlers, the setup to build the code to the point where signal handlers can be written can be tedious.
- The purpose of this compiler is to read the XML file and create the basic software, including skeletal signal handlers, to realize a working model of the basic layout.
- Each signal handler created by the compiler contains basic code to support the signal including accessing data from the signaling widget (for example, determining the position of a GUI slider whose movement resulted in a slider moved signal).
- In summary, if you can build a layout, the compiler will build you a working version of it.
- Based on user choice, the compiler generates code in C, C++, or Mumps.
- Not all GTK widgets are supported at present and work is in process to add more recognized widgets as well as add additional GUI support features. As of this point in time, the dfollowing widgets are supported:
"... Glade is a RAD tool to enable quick & easy development of user interfaces for the GTK toolkit and the GNOME desktop environment.The user interfaces designed in Glade are saved as XML, and by using the GtkBuilder GTK object these can be loaded by applications dynamically as needed.
By using GtkBuilder, Glade XML files can be used in numerous programming languages including C, C++, C#, Vala, Java, Perl, Python,and others.
Glade is Free Software released under the GNU GPL License. ..." The Glade Project
GtkCellRendererText GtkWindow GtkFixed GtkButton GtkComboBox GtkEntryBuffer GtkSwitch GtkLevelBar GtkVolumeButton GtkImage GtkIconView GtkProgressBar GtkSpinner GtkDrawingArea GtkCalendar GtkFontButton GtkAdjustment GtkRadioButton GtkScale GtkBox GtkMenu GtkMenuButton GtkLockButton GtkFileChooserButton GtkFrame | GtkColorButton GtkSpinButton GtkScrollbar GtkLabel GtkToggleButton GtkEntry GtkSearchEntry GtkViewport GtkScrolledWindow GtkTextView GtkTextBuffer GtkInfoBar GtkCheckButton GtkTreeView GtkTreeSelection GtkTreeViewColumn GtkCellRendererText GtkListStore GtkTreeStore GtkStackSwitcher GtkStack GtkSeparator |
Examples
The following examples use the mumps/Mumps-Projects/GTK-Compiler/C-Examples/Button-Widgets directory and code from the distro.
Before you attempt to run the examples, you will need to install software. The installation scripts are in the distro directory:
mumps/Mumps-Language-Processors/Mumps-Interpreter-Compiler-Library
In that directory, as root, run:
ConfigureNativeMumps.script
followed by:
CompileNativeSingleUserMumps.script
DO NOT run the Makefile.
The first script will check if you have the needed software and, if not, install it. This only woks of systems that use apt/apt-get.
The second script configures the code, compiles it, then installs it to /usr/bin.
All examples were run under Linux Mint 20.3 Una with Mate 1.26.0 and GTK 3.22.16 and Glade 3.22.2
The following image shows the Glade GUI with an example layout containing several common button related widgets.
To run the Glade GUI from mumps/Mumps-Projects/Glade-Compiler/C-Examples directory on your computer, in a file explorer, double click on the file mumps.glade or type the command
glade mumps.gladefrom a terminal window (assumes Glade has been installed on your system). Glade XML files have the .glade extension.
The button highlighted is a GtkToggleButton whose name (see ID at top of rightmost panel) is SampleGtkTogglebutton. The ID is assigned by the programmer/designer of the app.
Near the bottom of the rightmost panel, under Label with Optional Image, is the text that appears inside the button. The remainder of the rightmost settings panel are defaults.
In the following figure we see the second tab of the right most panel:
This is the tab where you position the widget within the app container. The numbers are in pixels where 0 represents the rightmost / topmost pixel of the app window.
The next tab consists mostly of defaults except for the width and height requests near the bootom. These determine the size of the widget. The defaults are usually too large (80x100). The request boxes are unchecked which means the widget will only be large enough to for its contents which, in this case, is the SampleGtkToggleButton label. Values of -1 also mean the height or width will only be large enough to contain the assigned content.
Next is the tab where you establish signals for events you want to process:
The main action for a toggle button is the toggled signal. The name of the signal handler is: on_SampleGtkToggleButton_toggled. The programmer enters this name. This is the name of the function that will be invoked if the button is toggled. The name should be on_ followed by the widget ID followed by _toggled.
Hint: a standard name such as shown will be inserted for you if you click on the
BE SURE TO HIT ENTER to confirm you selection.
The XML file from Glade is a text file named xxx.glade where xxx is set by the
user when they create the project.
In the case of the code for the GtkCompiler, it is assumed, at present, that this file
is named mumps.glade.
Once the layout has been saved, you run make -B which builds the skelatal project code:
The files created by this process are:
These are files that containg declarations, initializations, and #include
code that will be incorporated into the template file gtk.c.
These are the signal handler files. Each contains a function to handle the named signal.
If the name of the signal handler function is on_SampleGtkRadio1_toggled
the files name will be on.SampleGtkCheckButton.toggled.h
These files will also be included into the gtk.c template program at the end.
Upon invocation of the handler and indication of the button status, the user can perform
whatever action the button was intended for.
Files Created and Used in the Button Example:
gtk1.h (created by the compiler)
Other Widget Collections
rm -f on.* key.dat data.dat
../../GtkCompiler.mps "C" < mumps.glade
Mumps GTK Application Builder Mon Aug 1 12:26:13 2022
-----------
ComboBoxExample GtkComboBox
signal=on_ComboBoxExample_changed
Creating signal handler: on.ComboBoxExample.changed.h
ExampleFontButton GtkFontButton
signal=on_ExampleFontButton_font_set
Creating signal handler: on.ExampleFontButton.font.set.h
ExampleSwitch GtkSwitch
signal=on_ExampleSwitch_state_set
Creating signal handler: on.ExampleSwitch.state.set.h
SampleColorButton GtkColorButton
signal=on_SampleColorButton_color_set
Creating signal handler: on.SampleColorButton.color.set.h
SampleGtkButton GtkButton
signal=on_SampleGtkButton_clicked
Creating signal handler: on.SampleGtkButton.clicked.h
SampleGtkCheckButton GtkCheckButton
signal=on_SampleGtkCheckButton_toggled
Creating signal handler: on.SampleGtkCheckButton.toggled.h
SampleGtkRadio1 GtkRadioButton
signal=on_SampleGtkRadio1_toggled
Creating signal handler: on.SampleGtkRadio1.toggled.h
SampleGtkRadio2 GtkRadioButton
signal=on_SampleGtkRadio2_toggled
Creating signal handler: on.SampleGtkRadio2.toggled.h
SampleGtkRadio3 GtkRadioButton
signal=on_SampleGtkRadio3_toggled
Creating signal handler: on.SampleGtkRadio3.toggled.h
SampleGtkToggleButton GtkToggleButton
signal=on_SampleGtkToggleButton_toggled
Creating signal handler: on.SampleGtkToggleButton.toggled.h
cbentry GtkEntry
signal=on_cbentry_changed
Creating signal handler: on.cbentry.changed.h
entrybuffer1 GtkEntryBuffer
fixed1 GtkFixed
label1 GtkLabel
label2 GtkLabel
label3 GtkLabel
lbl4 GtkLabel
liststore1 GtkListStore
page_0 GtkFixed
page_1 GtkFixed
stack1 GtkStack
window GtkWindow
-----------
gcc -O3 -fdiagnostics-color=never \
-pthread `pkg-config --cflags --libs glib-2.0` \
-o gtk gtk.c `pkg-config --libs glib-2.0` -lpthread \
`pkg-config --cflags --libs gtk+-3.0` -export-dynamic
-rw-rw-r-- 1 okane okane 702 Aug 1 12:26 gtk1.h
-rw-rw-r-- 1 okane okane 2055 Aug 1 12:26 gtk2.h
-rw-rw-r-- 1 okane okane 541 Aug 1 12:26 gtk3.h
on.cbentry.changed.h
on.SampleColorButton.color.set.h
on.SampleGtkRadio2.toggled.h
on.ComboBoxExample.changed.h
on.SampleGtkButton.clicked.h
on.SampleGtkRadio3.toggled.h
on.ExampleFontButton.font.set.h
on.SampleGtkCheckButton.toggled.h
on.SampleGtkToggleButton.toggled.h
on.ExampleSwitch.state.set.h
on.SampleGtkRadio1.toggled.h
void on_SampleGtkToggleButton_toggled(GtkWidget *w) {
printf("%s\n", "on.SampleGtkToggleButton.toggled.h");
printf("\ttoggled = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
}
gtk2.h (created by the compiler)
#ifndef GTK1_H
#define GTK1_H
#include
#include
GtkBuilder *builder;
GtkEntryBuffer *entrybuffer1;
GtkListStore *liststore1;
GtkWindow *window;
GtkFixed *fixed1;
GtkToggleButton *SampleGtkToggleButton;
GtkCheckButton *SampleGtkCheckButton;
GtkRadioButton *SampleGtkRadio1;
GtkRadioButton *SampleGtkRadio2;
GtkRadioButton *SampleGtkRadio3;
GtkButton *SampleGtkButton;
GtkColorButton *SampleColorButton;
GtkSwitch *ExampleSwitch;
GtkLabel *label1;
GtkLabel *label2;
GtkFontButton *ExampleFontButton;
GtkComboBox *ComboBoxExample;
GtkEntry *cbentry;
#endif
gtk3.h (created by the compiler)
#ifndef GTK2_H
#define GTK2_H
gtk_init(&argc, &argv);
builder = gtk_builder_new_from_file ("mumps.glade");
entrybuffer1 = GTK_ENTRY_BUFFER(gtk_builder_get_object(builder, "entrybuffer1"));
liststore1 = GTK_LIST_STORE(gtk_builder_get_object(builder, "liststore1"));
window = GTK_WINDOW(gtk_builder_get_object(builder, "window"));
fixed1 = GTK_FIXED(gtk_builder_get_object(builder, "fixed1"));
SampleGtkToggleButton = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "SampleGtkToggleButton"));
SampleGtkCheckButton = GTK_CHECK_BUTTON(gtk_builder_get_object(builder, "SampleGtkCheckButton"));
SampleGtkRadio1 = GTK_RADIO_BUTTON(gtk_builder_get_object(builder, "SampleGtkRadio1"));
SampleGtkRadio2 = GTK_RADIO_BUTTON(gtk_builder_get_object(builder, "SampleGtkRadio2"));
SampleGtkRadio3 = GTK_RADIO_BUTTON(gtk_builder_get_object(builder, "SampleGtkRadio3"));
SampleGtkButton = GTK_BUTTON(gtk_builder_get_object(builder, "SampleGtkButton"));
SampleColorButton = GTK_COLOR_BUTTON(gtk_builder_get_object(builder, "SampleColorButton"));
ExampleSwitch = GTK_SWITCH(gtk_builder_get_object(builder, "ExampleSwitch"));
label1 = GTK_LABEL(gtk_builder_get_object(builder, "label1"));
label2 = GTK_LABEL(gtk_builder_get_object(builder, "label2"));
ExampleFontButton = GTK_FONT_BUTTON(gtk_builder_get_object(builder, "ExampleFontButton"));
ComboBoxExample = GTK_COMBO_BOX(gtk_builder_get_object(builder, "ComboBoxExample"));
cbentry = GTK_ENTRY(gtk_builder_get_object(builder, "cbentry"));
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_builder_connect_signals(builder, NULL);
gtk_widget_show(GTK_WIDGET(window));
#endif
Template file gtk.c
#ifndef GTK3_H
#define GTK3_H
#include "on.SampleGtkToggleButton.toggled.h"
#include "on.SampleGtkCheckButton.toggled.h"
#include "on.SampleGtkRadio1.toggled.h"
#include "on.SampleGtkRadio2.toggled.h"
#include "on.SampleGtkRadio3.toggled.h"
#include "on.SampleGtkButton.clicked.h"
#include "on.SampleColorButton.color.set.h"
#include "on.ExampleSwitch.state.set.h"
#include "on.ExampleFontButton.font.set.h"
#include "on.ComboBoxExample.changed.h"
#include "on.cbentry.changed.h"
#endif
Signal Handlers (created by the compiler)
//#*+++++++++++++++++++++++++++++++++++++++++
//#+
//#+ GTK Compiler
//#+
//#+ Copyright (C) 2022 by Kevin C. O'Kane
//#+
//#+ Kevin C. O'Kane
//#+ kc.okane@gmail.com
//#+ okane@uni.edu
//#+ https://www.cs.uni.edu/~okane
//#+ https://threadsafebooks.com/
//#+
//#+ This program is free software; you can redistribute it and/or modify
//#+ it under the terms of the GNU General Public License as published by
//#+ the Free Software Foundation; either version 2 of the License, or
//#+ (at your option) any later version.
//#+
//#+ This program is distributed in the hope that it will be useful,
//#+ but WITHOUT ANY WARRANTY; without even the implied warranty of
//#+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//#+ GNU General Public License for more details.
//#+
//#+ You should have received a copy of the GNU General Public License
//#+ along with this program; if not, write to the Free Software
//#+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//#+
//#+ July 16, 2022
//#*+++++++++++++++++++++++++++++++++++++++++
#include "gtk1.h"
int main(int argc, char **argv) {
#include "gtk2.h"
#include "user.h"
gtk_main();
printf("\nBye-bye\n");
}
#include "gtk3.h"
on.SampleGtkToggleButton.toggled.h
void on_SampleGtkToggleButton_toggled(GtkWidget *w) {
printf("%s\n", "on.SampleGtkToggleButton.toggled.h");
printf("\ttoggled = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
}
on.SampleGtkCheckButton.toggled.h
void on_SampleGtkCheckButton_toggled(GtkWidget *w) {
printf("%s\n", "on.SampleGtkCheckButton.toggled.h");
printf("\tchecked = %d\n", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
}
on.SampleGtkRadio1.toggled.h
void on_SampleGtkRadio1_toggled(GtkWidget *w) {
printf("%s\n", "on.SampleGtkRadio1.toggled.h");
printf("\tButton SampleGtkRadio1 clicked\n");
printf("\tSampleGtkRadio1");
if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(w)) == 1)
printf(" active\n"); else printf(" inactive\n");
}
on.SampleGtkRadio2.toggled.h
void on_SampleGtkRadio2_toggled(GtkWidget *w) {
printf("%s\n", "on.SampleGtkRadio2.toggled.h");
printf("\tButton SampleGtkRadio2 clicked\n");
printf("\tSampleGtkRadio2");
if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(w)) == 1)
printf(" active\n"); else printf(" inactive\n");
}
on.SampleGtkRadio3.toggled.h
void on_SampleGtkRadio3_toggled(GtkWidget *w) {
printf("%s\n", "on.SampleGtkRadio3.toggled.h");
printf("\tButton SampleGtkRadio3 clicked\n");
printf("\tSampleGtkRadio3");
if(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(w)) == 1)
printf(" active\n"); else printf(" inactive\n");
}
on.SampleGtkButton.clicked.h
void on_SampleGtkButton_clicked(GtkWidget *w) {
printf("%s\n", "on.SampleGtkButton.clicked.h");
printf("\tButton clicked\n");
}
on.SampleColorButton.color.set.h
void on_SampleColorButton_color_set(GtkWidget *w) {
printf("%s\n", "on.SampleColorButton.color.set.h");
GdkRGBA r;
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER(w), &r);
printf("red=%f green=%f blue=%f alpha=%f\n", r.red, r.green, r.blue, r.alpha );
}
on.ExampleSwitch.state.set.h
void on_ExampleSwitch_state_set(GtkWidget *w) {
printf("%s\n", "on.ExampleSwitch.state.set.h");
printf("\tActive: %d\n", gtk_switch_get_active (GTK_SWITCH(w)));
}
on.ExampleFontButton.font.set.h
void on_ExampleFontButton_font_set(GtkWidget *w) {
printf("%s\n", "on.ExampleFontButton.font.set.h");
printf("\tfont = %s\n", gtk_font_chooser_get_font(GTK_FONT_CHOOSER(w)));
}
on.ComboBoxExample.changed.h
void on_ComboBoxExample_changed(GtkWidget *w) {
printf("%s\n", "on.ComboBoxExample.changed.h");
}
on.cbentry.changed.h
void on_cbentry_changed(GtkWidget *w) {
printf("%s\n", "on.cbentry.changed.h");
printf("\t%s\n", gtk_entry_get_text(GTK_ENTRY(w)));
}