|
The Glade Compiler
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:
Mumps Programming Language Distro
The Glade Compiler
What is Glade?
"... 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
- 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:
|
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.glade
from a terminal window (assumes Glade has been installed on your
system). Glade XML files have the .glade extension.
The leftmost panel gives the names and layout hierarchy of the
widgets. At the top is a GtkWindow which contains
a GtkFixed container which itself contains individual widgets that
are buttons and labels. Each line
gives the name of widget widget followed by its GTK data type.
Widgets are arranged hierarchically based on containment.
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 text and begin typing on.... The
Glade GUI will fill in the rest.
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:
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
The files created by this process are:
-
-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
These are files that containg declarations, initializations, and #include
code that will be incorporated into the template file gtk.c.
-
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
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.
- The file gtk is the exectutable. If you execute it you get:
- The signal handler for the SampleGtkToggleButton toggled signal
is in file on.SampleGtkToggleButton.toggled.h which contains the
following:
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)));
}
- If, in the app window, you click the SampleGtkToggleButton, the
button will darken to indicate it has been depressed. This will
raise the toggled signal and the function in on.SampleGtkToggleButton.toggled.h
will be invoked. This will cause a message to
appear on the invoking terminal window indicating that the button is
active or inactive. This message is from the signal handler:
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)
#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
|
gtk2.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
|
gtk3.h (created by the compiler)
#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
|
Template file gtk.c
//#*+++++++++++++++++++++++++++++++++++++++++
//#+
//#+ 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"
|
Signal Handlers (created by the compiler)
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)));
}
|
Other Widget Collections
- Directory mumps/Mumps-Projects/GTK-Compiler/C-Examples/Input-Widgets
- Directory mumps/Mumps-Projects/GTK-Compiler/C-Examples/Slider-Widgets
- Improved buttons example
mumps/Mumps-Projects/Glade-Compiler/C-Examples/Button-Widgets
- Directory mumps/Mumps-Projects/GTK-Compiler/MDH-Examples/Mesh-Tree
|