GTK LOGO mongoose
glade
 Calendar program being edited in Glade


EuGTK 4.11.11 and Glade

Drag and Drop interface construction


Overview

It is now possible to use Glade to design your EuGTK program interface. I've tested with Glade versions 3.16 and 3.18. You will still have to write snippets of code in Euphoria to handle user events - just as you would when using Visual Basic™, Delphi™, etc.

Begin by reading Starting Glade I and II for an introduction, thenread the rest of this page for details.

Glade has a preview button so that you can see, to a limited extent, what your program will look like. Controls won't be linked (can't respond to user interaction) until you load the glade XML into your Euphoria program and provide the 'handler' functions. Often, these handler functions will only require a few lines of code.

EuGTK will try to help you with this task by supplying a ready-made template for undeclared functions, which you copy and paste into your Euphoria code using whatever text exitor you prefer.

This template will appear on the terminal from which you run your program. See the screenshot below.

You must run programs from a terminal (x-term, for example) while developing and testing. There's no way around this.

Your program begins as usual:
template

 include GtkEngine.e

Next, you tell EuGTK's built-in builder object to load your program's XML description from the file created by Glade. The builder will try to connect any signals for which you have declared a handler (in the Glade Properties/Signals tabs). Finally, you call main() to start the GTK processing loop.

include GtkEngine.e
add(builder,"~/demos/examples/widgets.glade")
main()

With just those three lines of code, you are now ready to run your program!

Of course, it won't do anything, except perhaps spit out a message telling you that you haven't bothered to write handlers for events declared in Glade.

You should run the program (preferably from WEE with terminal, the BEAR, Geany using gneui.ex, or directly from an x-term). EuGTK will prompt you with an error message and hopefully a function template for the missing function. You can copy and paste that into your editor, and then fill in the body of the function. Put these functions after the call to main().

hint

Note that when using Glade, your Euphoria code may use string identifiers to refer to objects, rather than having to obtain a pointer (a.k.a. 'handle') to them first.

Glade will assign a unique identifier for widgets (which it calls the ID:). The ID will be something like 'checkbutton1', 'checkbutton2', 'radiobutton1', etc.

This ID property is found on the General tab of the Properties dialog. You may change the IDs if you wish, sometimes changing them can make your code clearer.

Obviously, you should avoid naming two controls with the same name.

If you are using multiple Glade files, you will almost certainly have more than one 'button1', etc. but this isn't a problem, because a namespace will be prepended. See namespaces below.



Namespaces

When writing a large program with multiple windows, Glade can become difficult to navigate safely. Click on the wrong thing in Glade, and you may lose all your work. This isn't good, so you should try to break up your program into small, safe 'modules', each with it's own Euphoria include (.e) file and corresponding Glade (.glade) file.

Let's say, for example, I'm going to need a 'main' window, a pop-up 'edit' window, and the usual "About..." dialog. I'd create three Glade files, one named main.glade, the second edit.glade, and the third about.glade. After laying out these three windows using Glade, it's very likely that Glade will have used identical names for controls in the files. 'button1', for example, might appear in all three. You could, if you wish, wade thru all your Glade files and rename these as necessary to prevent conflicts, but EuGTK version 4.8.9 and up offers a less labor-intensive way.

EuGTK namespacing allows you to refer to these controls by name in a manner familiar to Euphoria programmers:
"button1" (the button1 in main.ex); "edit:button1" and "about:button1" (buttons in the respective edit.e and about.e files).

	set("edit:window1","background","blue")
Note that these are strings. If you wish to convert them to Euphoria objects, you can, starting with EuGTK 4.8.9, use the new pointer() function:
	constant win1 = pointer("edit:window1")
Other files can now access the edit.e window in the normal Euphoria way:
	set(win1,"background",...)

There seems to be no noticeable delay when accessing controls via the string names. In a test which read and set label text using the constant 'handle' to the label, 20,000 iterations per second were reported. When using the label's name in string form, 18,900 per second were reported.

hint

When using the string form, the namespace prefix will be the same as the Glade file name (sans the .glade part) which the include file loaded into the GTK builder.

When exported as a Eu constant or variable, the namespace prefix will be whatever namespace the included .e file declares. To prevent confusion, it's probably best to use identical names. IOW, code in 'foo.e' would have the namespace foo.

To keep things neatly organized, you should put your Eu code in separate files as well: main.ex, edit.e, and about.e.

Your Eu file main.ex would then include the line:

	add(builder,"main.glade")

And your edit.e include file would have the lines:

namespace edit
include GtkEngine.e
add(builder,"edit.glade")

To examine the namespaced names as loaded by EuGTK, add the line with define BUILDER to your main program prior to including GtkEngine.e, or add -d BUILDER to the command-line. The namespaced names will be shown on the xterm when you run your program. (as shown above)

Glade objects loaded by the main (.ex) program will not be namespaced. Those items can be addressed directly without a namespace qualifier. This is done so that small programs which don't need multiple Glade 'includes' can use code that isn't cluttered with unnecessary namespacery.


Widget names

Confusingly, Glade also has a Widget name: property, found under the Common tab, which you should avoid using except under special circumstances. It isn't normally needed. EuGTK refers to widgets created by Glade by their ID:, e.g. the main window of a program created by Glade would have the default ID of "window1", and your EuGTK program would access that window as "window1".

There are a few 'trick' uses for this Widget name property, however:

One possible use is to pass data to functions which handle more than one control. For example, you might have a set of radio buttons which all call a single handler function. That function could examine the control's 'name' to determine what to do. If, for example, the buttons select various colors, each button could have a different color as the name property: 'red', 'green', or 'blue', etc.

A more complex use might be to pass function names to a central 'dispatch' function, which could then call the desired function by converting the 'name' into a routine_id.

Some of the demos in the glade subfolder utilize these tricks. See, for example, the hello.* files: hello.ex, es.e, etc...


Cautions

The XML file created by Glade may include a "requires..." line, demanding a certain GTK version be present. You may find it helpful to remove that line under certain conditions, for example when designing your program on Linux with a current version of GTK/Glade, but running it on Windows™, which lags behind the other platforms. Just use a plain-text editor to zap the offending line.


Common Problems

  1. I run my program without errors but can't see anything!
    You must click on the 'visible' property checkbox for your main window. This is found on the 'Common' tab under 'Widget Flags'.
    Oh, and while you're there, be sure to link the main window's destroy signal to the built-in function Quit, so that your program will clean up after itself when finished! You must do these two things for the main window of every program you write.
  2. I put buttons in a dialog, such as FileChooserDialog, but they don't do anything!
    Set a unique 'Response ID' for each button. This is found on the 'General' tab under 'Button Attributes'.
    This ID is returned when the dialog closes as a result of a button being clicked.
  3. How do I make menu items work like check menu items or radio menu items?
    I don't know how to do that using Glade. You'll have to write code in Euphoria, or <gasp!> try to edit the .glade xml directly.
  4. I want to use widget x, but can't find it on the Glade palette
    Some things are hard to find, and some just aren't there. New GTK widgets introduced since GTK 3.10 are partially missing. If you're working on the 'bleeding edge' of GTK3, you probably should be coding by hand.
  5. How do I know how to name the function that responds to a signal?
    If you click on the widget's Signals tab, you'll see a list of signals that can be linked.
    For example, a button has a 'clicked' signal. You then click on the <type here> space adjacent to the signal name, and press the 'o' key.
    (That's the letter o, not a zero!)
    When you do, a suggested function handler name will be plugged in. You can, of course, type in any global function name you prefer here. For example, the handler name for a Quit or Exit button should usually be Quit (no quotes)
    This will call EuGTK's built-in Quit() function when the button is clicked.
  6. I want to write one Eu function to handle multiple controls.
    Instead of accepting the default handler name, supply your own For example, if you have 3 buttons, Glade will supply handler names:
    • on_button1_clicked
    • on_button2_clicked
    • on_button3_clicked
    You simply remove the 1,2,and 3 from the handler names, and name your Eu function on_button_clicked. All 3 buttons will call that function. It's then your job to sort them out.


Compiling, Binding, etc...

As usual, you can compile, bind, or shroud your program. If you do any of these, your program will still load the GUI description from the Glade XML file at run-time. This could be either good or bad, depending upon your perspective.

The benefits:

The drawbacks:

hint

Knowing the way some users think...
It's almost certain that someone will see that Glade™* file,
think "I don't care about air fresheners.." and delete it.

* brand name for a common type of room deodorizer in the U.S.

One easy solution to this problem is to copy the glade XML, paste it into a new file, enclose it in triple quotes, and assign it to an exported constant. Below, the added code is in red, while the XML from Glade is shown in black:

  export constant XML = """
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Generated with glade 3.16.1 -->
    <interface>
    <requires lib="gtk+" version="3.10"/>
    ---etc---
  """

Save this new file as an include, perhaps widgets.xml, with the widgets namespace, and then your code becomes:

    include GtkEngine.e
    include widgets.xml
    add(builder,widgets:XML) -- EuGTK can add objects from either a string variable or a filename
    main()

Now you can bind or compile your program and the interface will be 'hard coded' into it. Changing or deleting the widgets.xml or widgets.glade files will make no difference. No changes to your program interface can be made without re-compiling or re-binding.