- Open 'side4linux' and click on Project>Open Project in
the Main Menue.
- Double click on the 'DEMOS' Product Area,
- Double click on the 'SIDEdemos' Product,
- In
the file dialog double click the 'GNOMEC' folder, this takes you
to where 'GNOME' visual 'C' language projects are kept.
- Double
click on 'Sample1', this opens the 'Sample1' project folder ( we are
kindly providing your 'Sample' fixed and ready to go! )
- Double click on 'sample1.prf', this opens the 'Sample1'
project file.
- Now click on Project>Save Project As and save the
'Sample1' Project as 'Test2'.
- Close the current Project by clicking on Project>Close
Project.
- As in Step 1 open your 'Test2' project.
- Notice that project names are set to be an upper case
letter followed by lower case letters (easier on the IDE's Project
management routines).
- Notice
that the left bottom status bar window says 'Project: Test2' which is
the
Project Name.
- Notice that the next window says 'Ptype: GNOMEC' which is
the
Project Type.
- Now
click on the 'Autogen' toolbar button followed after a while by
the 'Build' button and you should be ready to continue.
- Change to another workspace and run the 'test2' binary in
the 'src' folder using Nautilus.
- Notice that when maximised the buttons get stretched. I
think we had better fix this now!
- From the Main Menue open Glade with
Project>Edit Project>Edit Project
Visuals with Glade
- Double click on the 'mainWindow' widget in the 'GNOME'
window to bring up the program visual.
- Click on the 'Hello' button and in the 'PROPERTIES' window
click the 'Packing' tab and set 'Expand' and 'Fill' to 'No' by clicking
on the toggle bar.
- Do the same for the 'Erase' button and then click next to
the buttons on the right to bring up 'hbox1' in the 'PROPERTIES' window
and repeat.
- Click 'Build' in the 'GLADE" window and close and click
'Build' in the IDE to complete the job.
- Notice that you 'build' twice! Once for the visuals
in Glade2 and once for the 'C' compiler in the side4linux IDE.
- Try running the test2 binary again, It should now look
like this with little buttons in the lower left.
The reason for all this is that visuals do not know what size
the screen will expand to hence the ability for you to decide what
should expand e.g. the text window and what should not e.g. the buttons.
Excercise -1 -- Add a
'shutdown' handler in Glade and connect it to a callback function in
'callbacks.c"
Now let us finally make some visuals do something! But first a
little discussion about event driven graphical user interfaces ( GUI's
). If you open 'main.c' you will see the following code,
/*
* Initial main.c file generated by Glade. Edit as required.
* Glade will not overwrite this file.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gnome.h>
#include "interface.h"
#include "support.h"
int main (int argc, char *argv[])
{
GtkWidget
*mainWindow;
#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#endif
gnome_program_init (PACKAGE, VERSION, LIBGNOMEUI_MODULE,
argc, argv,
GNOME_PARAM_APP_DATADIR, PACKAGE_DATA_DIR,
NULL);
/*
* The following code was added by Glade to create one of
each component
* (except popup menus), just so that you see something
after building
* the project. Delete any components that you don't want
shown initially.
*/
mainWindow = create_mainWindow ();
gtk_widget_show (mainWindow);
gtk_main ();
return 0;
}
Before we do anything we will need to remove the pointer to
'mainWindow' (our program window) and put it in a 'header' file so that
we can use the window pointer in our 'callbacks.c' callback functions.
so.. Open a new file and save as 'main.h'. Now cut and paste the line 'GtkWidget *mainWindow;'
from 'main.c' into the main.h file and save main.h. Put in the line of,
#include "main.h"
into both the top of 'main.c' file and 'callbacks.c' so that we can now
reference the main window in our program. We will need this pointer to
alter the text in our text window etc.
So 'main.c' now looks like,
/*
* Initial main.c file generated by Glade. Edit as required.
* Glade will not overwrite this file.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gnome.h>
#include "interface.h"
#include "support.h"
#include "main.h"
int main (int argc,
char *argv[])
{
#ifdef ENABLE_NLS
bindtextdomain
(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset
(GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
#endif
gnome_program_init (PACKAGE,
VERSION, LIBGNOMEUI_MODULE,
argc, argv,
GNOME_PARAM_APP_DATADIR, PACKAGE_DATA_DIR,
NULL);
/*
* The following code was
added by Glade to create one of each component
* (except popup menus),
just so that you see something after building
* the project. Delete any
components that you don't want shown initially.
*/
mainWindow = create_mainWindow
();
gtk_widget_show (mainWindow);
gtk_main ();
return 0;
}
Now 'mainWindow' is indeed of
type 'GtkWidget' so it is a
pointer to a 'widget' and the
function 'create_mainWindow
();' creates the widget after which it is assigned to the
pointer
'mainWindow' but becuase this is visual code you must then 'show' it.
You could also 'hide' it or
even 'destroy' it, waiting on 'create' for
the next valid pointer. The really different bit is the next line of
code 'gtk_main ();'.
This function locks the program into an 'event loop' where nothing happens
at all until there is some external 'trigger'
like a mouse click or keypress. When this happens a 'signal' is 'emitted'. This means nothing of
course until you 'connect'
that signal with a function (called a 'callback'
) that will actually do something. Now Glade has already provided some
of these 'callbacks' and has 'connected' them, have a look now in
'callbacks.c' by opening it into the Notebook. An example of the
'callbacks' is presented below,
void
on_new1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
}
So as you might guess this 'callback' function is connected to the 'new
file' signal that is 'emitted' when you click on 'New' in the Main
Menue of your program 'Test2'. The reason that nothing has happened
is that there is no code within that function! From this you can see
where we are going, the rest of 'Demo-2' is about generating the
'callback' code and allowing Glade to 'connect' them to 'signals'.
Take
it for granted that Glade will trash 'interface.c' and 'support.c' and
will also append any new callback functions to the end of
'callbacks.c'. This means that you can edit with 'main.c' and
'callbacks.c' but not the other two! Note that
'callbacks.c',interface.c'
and 'support.c' must be closed while Glade is working, that is why the
IDE will close these three files if they are open before launching
Glade.
So, now we get to do something! Open Glade, select the
'mainWindow' visual widget ( double click on it in the 'GLADE' window, where the
title bar shows 'Glade: test2' ) and look in the 'PROPERTIES' window.
The title bar should say 'Properties: mainWindow' Click on the
'Signals' tab, Click on the
little box at the end of the 'Signal:
bar ' (
above 'Handler:' ). A little box opens with 'Select Signal' in the
title bar. From this, scroll down until you see 'delete_event'. Click
on it to highlight it then click on 'OK'.
In the 'Signal' bar you should now see 'delete_event'
and in the 'Handler' bar should be 'on_mainWindow_delete_event'.
Click on 'Add'. which will add
a 'handler' fuction to 'callbacks.c' and generate the signal which is
'emitted' on program closure.
Now 'Build' and quit Glade to
return to the IDE and open 'callbacks.c'.
You should see the following function tacked onto the bottom of the
file (you may need to edit the presentation to match the coding style
of your own preference).
gboolean
on_mainWindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
return FALSE;
}
Put the following line into the function, 'gtk_main_quit();'
It now reads,
gboolean
on_mainWindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
gtk_main_quit();
return FALSE;
}
Now that fixes the orderly shutdown of the program by
breaking the 'main event
loop'.
Excercise -2 --
Add a 'startup' handler in Glade and connect it to a callback function
in 'callbacks.c"
Now that we have fixed the shutdown of the
program by breaking the 'main event
loop' we will also put in something to allow startup
initialisation. We will tack a callback onto that function we came
across earlier in 'main.c', namely,
'gtk_widget_show
(mainWindow);'
Repeating the procedure in Excercise-1, open Glade from the IDE, select
the
'mainWindow' visual widget ( double click on it in the 'GLADE' window ) and add the
handler 'on_mainWindow_show'
After clicking on 'Build' in the 'GLADE' window and closing
Glade, open 'callbacks.c' into the Notebook to add the following global
string below the
file includes at the top and before ,
'void
on_new1_activate(GtkMenuItem *menuitem, gpointer user_data)'
as shown below,
static gchar *msg;
// general use glib string that is global only within this file because
of the 'static' declaration
Now add the following line to the callback handler function 'void on_mainWindow_show(GtkWidget
*widget, gpointer user_data)' as follows,
msg = g_strdup_printf("Hello World!");
and the callback.c file
should now look something like,
#ifdef
HAVE_CONFIG_H
# include <config.h>
#endif
#include <gnome.h>
#include "callbacks.h"
#include "interface.h"
#include "support.h"
static gchar *msg;
// general use string that is global only within
this file
void on_new1_activate(GtkMenuItem
*menuitem, gpointer user_data)
{
}
.
.
etc., etc.,
.
.
gboolean
on_mainWindow_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
gtk_main_quit();
return FALSE;
}
void
on_mainWindow_show(GtkWidget *widget, gpointer user_data)
{
msg =
g_strdup_printf("Hello World!");
}
Note: You can add other intialisation routines here as well that your
own code may need at program start.
Excercise - 3 --
Add 'button' handlers in Glade and connect them to callback functions
in 'callbacks.c"
We are now going to complete the original object of the Demo-1 & 2
that is,
'We will build a visual program that
has two buttons, one to display 'Hello World!' in a text window and one
to erase the message from the text window'.
Re-open the Glade visual editor and bring up our 'mainWindow' widget
and click on the 'Hello' button to bring it up in the 'PROPERTIES'
window as in the following graphic,
Notice the black band
around the 'Hello' button which shows that it is selected, we will now
add the signal and callback.
In the 'PROPERTIES' window Click on the
'Signals' tab, Click on the
little box at the end of the 'Signal:
bar ' (
above 'Handler:' ). A little box opens with 'Select Signal' in the
title bar. From this, scroll down until you see 'clicked' (second option from the
top). Click
on it to highlight it then click on 'OK'.
Now click on 'Add' at bottom left to add the signal and handler. Do the
same for the 'Erase' button. Then do the double 'Builds' mentioned
earlier to add them to 'callbacks.c'. We are now in a position to
re-open 'callbacks.c' and add the action code to complete the Project
ready for testing.
Excercise - 4 --
Complete callback functions in 'callbacks.c" by adding action code
Add the following code to the two new
callback functions at the bottom of 'callbacks.c'.
void on_Hellobutton_clicked(GtkButton
*button, gpointer user_data)
{
GtkWidget
*textWindow; // pointer to
our text window
GtkTextBuffer
*text_buffer; // pointer to the text buffer inside our text
window
textWindow =
lookup_widget(GTK_WIDGET(mainWindow),"textview1"); // get pointer to
our text window
text_buffer =
gtk_text_view_get_buffer(GTK_TEXT_VIEW(textWindow)); // get pointer to
text buffer inside
gtk_text_buffer_set_text(text_buffer,msg,12);
}
void on_Erasebutton_clicked(GtkButton
*button, gpointer user_data)
{
GtkWidget
*textWindow; // pointer to
our text window
GtkTextBuffer
*text_buffer; // pointer to the text buffer inside our text
window
textWindow =
lookup_widget(GTK_WIDGET(mainWindow),"textview1"); // get pointer to
our text window
text_buffer =
gtk_text_view_get_buffer(GTK_TEXT_VIEW(textWindow)); // get pointer to
text buffer inside
msg = g_strdup_printf(" ");
gtk_text_buffer_set_text(text_buffer,msg,1);
msg = g_strdup_printf("Hello
World!");
}
Click on the 'Build' toolbar button and build the Project. Change to
the Project's 'src' directory with 'Nautilus' and click on the 'test2'
binary and try your buttons!
If the project did not build then check over your code against the
Excercises above, you can also open another invocation of 'side4linux'
on a separate workspace and open the 'Sample2' Project which is a
conpleted and tested copy of your 'Test2' and check for differences.
Now you may be wondering about the code we have just added. It comes
from the GTK library which is linked in automatically by the IDE.
Click on Help>Help Browser>Coding Help>GNOMEC project
(GNOMEC)>GTK functions (local)>MultiLinedTextEditor for reference.
You may be wondering about how we obtained the pointers to textWindow
and text_buffer. What we did was use the GTK widget look up function to
find them. Open 'interface.c' and search on
/* Store pointers to all widgets, for use by lookup_widget(). */
in the function 'GtkWidget* create_mainWindow (void)' to see what
pointers are available. Note that you can use this method as well to
reference all the visual pointers that Glade produces. (
Tools>Search in File )
OK, I have had enough! Time to do something else! This project
introduced the concept of visual programming using the GTK libraries.
There is more to understand but not much! We will cover some aspects of
visual programming in the next Demo. Until then, click on
Project>Close Project from the Main Menue and now close down the IDE
by clicking the 'X' in the top right corner.
We will provide other demos as
'side4linux' develops to
cover GNOME visual programming and integration into a real world
machine
controller.
GUI interface made with
Gtk and
Glade