Team LiB
Previous Section Next Section

A Simple GNOME Program in Several Languages

This program will simply show a Window that has a button to quit the application. When that button is clicked it will ask you if you are sure, and if you click yes it will close the application. To run this program, type in the following as

gnome-example.s:

#PURPOSE:  This program is meant to be an example
#          of what GUI programs look like written
#          with the GNOME libraries
#
#INPUT:    The user can only click on the "Quit"
#          button or close the window
#
#OUTPUT:   The application will close
#
#PROCESS:  If the user clicks on the "Quit" button,
#          the program will display a dialog asking
#          if they are sure.  If they click Yes, it
#          will close the application.  Otherwise
#          it will continue running
#

.section .data

###GNOME definitions - These were found in the GNOME
#                      header files for the C language
#                      and converted into their assembly
#                     equivalents

#GNOME Button Names
GNOME_STOCK_BUTTON_YES:
.ascii "Button_Yes\0"
GNOME_STOCK_BUTTON_NO:
.ascii "Button_No\0"

#Gnome MessageBox Types
GNOME_MESSAGE_BOX_QUESTION:
.ascii "question\0"

#Standard definition of NULL
.equ NULL, 0

#GNOME signal definitions
signal_destroy:
.ascii "destroy\0"
signal_delete_event:
.ascii "delete_event\0"
signal_clicked:
.ascii "clicked\0"

###Application-specific definitions

#Application information
app_id:
.ascii "gnome-example\0"
app_version:
.ascii "1.000\0"
app_title:
.ascii "Gnome Example Program\0"

#Text for Buttons and windows
button_quit_text:
.ascii "I Want to Quit the GNOME Example Program\0"
quit_question:
.ascii "Are you sure you want to quit?\0"


.section .bss

#Variables to save the created widgets in
.equ WORD_SIZE, 4
.lcomm appPtr, WORD_SIZE
.lcomm btnQuit, WORD_SIZE

.section .text

.globl main
.type main, @function
main:
 pushl %ebp
 movl  %esp, %ebp

 #Initialize GNOME libraries
 pushl 12(%ebp)     #argv
 pushl 8 (%ebp)     #argc
 pushl $app_version
 pushl $app_id
 call  gnome_init
 addl  $16, %esp    #recover the stack

 #Create new application window
 pushl $app_title    #Window title
 pushl $app_id       #Application ID
 call  gnome_app__new
 addl  $8, %esp      #recover the stack
 movl  %eax, appPtr  #save the window pointer
 #Create new button
 pushl $button_quit_text #button text
 call  gtk_button_new_with_label
 addl  $4, %esp          #recover the stack
 movl  %eax, btnQuit     #save the button pointer

 #Make the button show up inside the application window
 pushl btnQuit
 pushl appPtr
 call  gnome_app_set_contents
 addl  $8, %esp

#Makes the button show up (only after it's window
#shows up, though)
pushl btnQuit
call  gtk_widget_show
addl  $4, %esp

#Makes the application window show up
pushl appPtr
call  gtk_widget_show
addl  $4, %esp

#Have GNOME call our delete_handler function
#whenever a "delete" event occurs
pushl $NULL            #extra data to pass to our
                       #function (we don't use any)
pushl $delete_handler  #function address to call
pushl $signal_delete_event #name of the signal
pushl appPtr           #widget to listen for events on
call  gtk_signal_connect
addl  $16, %esp        #recover stack

#Have GNOME call our destroy_handler function
#whenever a "destroy" event occurs
 pushl $NULL            #extra data to pass to our
                        #function (we don't use any)
 pushl $destroy_handler #function address to call
 pushl $signal_destroy  #name of the signal
 pushl appPtr           #widget to listen for events on
 call  gtk_signal_connect
 addl  $16, %esp        #recover stack

 #Have GNOME call our click_handler function
 #whenever a "click" event occurs.  Note that
 #the previous signals were listening on the
 #application window, while this one is only
 #listening on the button
 pushl $NULL
 pushl $click_handler
 pushl $signal_clicked
 pushl btnQuit
 call  gtk_signal_connect
 addl  $16, %esp

 #Transfer control to GNOME.  Everything that
 #happens from here out is in reaction to user
 #events, which call signal handlers.  This main
 #function just sets up the main window and connects
 #signal handlers, and the signal handlers take
 #care of the rest
 call gtk_main

 #After the program is finished, leave
 movl  $0, %eax
 leave
 ret

#A "destroy" event happens when the widget is being
#removed.  In this case, when the application window
#is being removed, we simply want the event loop to
#quit
destroy_handler:
 pushl %ebp
 movl  %esp, %ebp

 #This causes gtk to exit it's event loop
 #as soon as it can.
 call gtk_main_quit

 movl $0, %eax
 leave
 ret

#A "delete" event happens when the application window
#gets clicked in the "x" that you normally use to
#close a window
delete_handler:
 movl  $1, %eax
 ret

#A "click" event happens when the widget gets clicked
click_handler:
 pushl %ebp
 movl  %esp, %ebp

 #Create the "Are you sure" dialog
 pushl $NULL                       #End of buttons
 pushl $GNOME_STOCK_BUTTON_NO      #Button 1
 pushl $GNOME_STOCK_BUTTON_YES     #Button 0
 pushl $GNOME_MESSAGE_BOX_QUESTION #Dialog type
 pushl $quit_question              #Dialog mesasge
 call  gnome_message_box_new
 addl  $16, %esp                   #recover stack
 #%eax now holds the pointer to the dialog window

 #Setting Modal to 1 prevents any other user
 #interaction while the dialog is being shown
 pushl $1
 pushl %eax
 call  gtk_window_set_modal
 popl  %eax
 addl  $4, %esp

 #Now we show the dialog
 pushl %eax
 call  gtk_widget_show
 popl  %eax

 #This sets up all the necessary signal handlers
 #in order to just show the dialog, close it when
 #one of the buttons is clicked, and return the
 #number of the button that the user clicked on.
 #The button number is based on the order the buttons
 #were pushed on in the gnome_message_box_new function
 pushl %eax
 call  gnome_dialog_run_and_close
 addl  $4, %esp

 #Button 0 is the Yes button.  If this is the
 #button they clicked on, tell GNOME to quit
 #it's event loop.  Otherwise, do nothing
 cmpl  $0, %eax
 jne   click_handler_end

 call gtk_main_quit

click_handler_end:
 leave
 ret

To build this application, execute the following commands:

as gnome-example.s -o gnome-example.o
gcc gnome-example.o 'gnome-config --libs gnomeui' \
    -o gnome-example

Then type in ./gnome-example to run it.

This program, like most GUI programs, makes heavy use of passing pointers to functions as parameters. In this program you create widgets with the GNOME functions and then you set up functions to be called when certain events happen. These functions are called callback functions. All of the event processing is handled by the function gtk_main, so you don't have to worry about how the events are being processed. All you have to do is have callbacks set up to wait for them.

Here is a short description of all of the GNOME functions that were used in this program:

gnome_init

gnome_app_new

gtk_button_new_with_label

gnome_app_set_contents

gtk_widget_show

gtk_signal_connect

gtk_main

gtk_main_quit

gnome_message_box_new

gtk_window_set_modal

gnome_dialog_run_and_close

The following is the same program written in the C language. Type it in as gnome-example-c.c:

/* PURPOSE:  This program is meant to be an example
           of what GUI programs look like written
           with the GNOME libraries
 */

#include <gnome.h>

/* Program definitions */
#define MY_APP_TITLE "Gnome Example Program"
#define MY_APP_ID "gnome-example"
#define MY_APP_VERSION "1.000"
#define MY_BUTTON_TEXT "I Want to Quit the Example Program"
#define MY_QUIT_QUESTION "Are you sure you want to quit?"

/* Must declare functions before they are used */
int destroy_handler(gpointer window,
  GdkEventAny *e,
  gpointer data);
int delete_handler(gpointer window,
  GdkEventAny *e,
  gpointer data);
int click__handler(gpointer window,
  GdkEventAny *e,
  gpointer data);

int main(int argc, char **argv)
{
 gpointer appPtr;  /* application window */
 gpointer btnQuit; /* quit button */

 /* Initialize GNOME libraries */
 gnome_init(MY_APP_ID, MY_APP_VERSION, argc, argv);

 /* Create new application window */
 appPtr = gnome_app_new(MY_APP_ID, MY_APP_TITLE);

 /* Create new button */
 btnQuit = gtk_button_new_with_label(MY_BUTTON_TEXT);

 /* Make the button show up inside the application window */
 gnome_app_set_contents(appPtr, btnQuit);

 /* Makes the button show up */
 gtk_widget_show(btnQuit);

 /* Makes the application window show up */
 gtk_widget_show(appPtr);

 /* Connect the signal handlers */
 gtk_signal_connect(appPtr, "delete_event",
   GTK_SIGNAL_FUNC(delete_handler), NULL);
 gtk_signal_connect(appPtr, "destroy",
   GTK_SIGNAL_FUNC(destroy_handler), NULL);
 gtk_signal_connect(btnQuit, "clicked",
   GTK_SIGNAL_FUNC(click_handler), NULL);

 /* Transfer control to GNOME */
 gtk_main();

 return 0;
}

/* Function to receive the "destroy" signal */
int destroy_handler(gpointer window,
  GdkEventAny *e,
  gpointer data)
{
 /* Leave GNOME event loop */
 gtk_main_quit();
 return 0;
}

/* Function to receive the "delete_event" signal */
int delete_handler(gpointer window,
  GdkEventAny *e,
  gpointer data)
{
 return 0;
}
/* Function to receive the "clicked" signal */
int click_handler(gpointer window,
  GdkEventAny *e,
  gpointer data)
{
 gpointer msgbox;
 int buttonClicked;

 /* Create the "Are you sure" dialog */
 msgbox = gnome_message_box_new(
  MY_QUIT_QUESTION,
  GNOME_MESSAGE_BOX_QUESTION,
  GNOME_STOCK_BUTTON_YES,
  GNOME_STOCK_BUTTON_NO,
  NULL);
 gtk_window_set_modal(msgbox, 1);
 gtk_widget_show(msgbox);

 /* Run dialog box */
 buttonClicked = gnome_dialog_run_and_close(msgbox);

 /* Button 0 is the Yes button. If this is the
 button they clicked on, tell GNOME to quit
 it's event loop.  Otherwise, do nothing */
 if(buttonClicked == 0)
 {
  gtk_main_quit();
 }

 return 0;
}

To compile it, type

gcc gnome-example-c.c 'gnome-config --cflags \
    --libs gnomeui' -o gnome-example-c

Run it by typing ./gnome-example-c.

Finally, we have a version in Python. Type it in as gnome-example.py:

#PURPOSE:  This program is meant to be an example
#          of what GUI programs look like written
#          with the GNOME libraries
#

#lmport GNOME libraries
import gtk
import gnome.ui

####DEFINE CALLBACK FUNCTIONS FIRST####

#In Python, functions have to be defined before
#they are used, so we have to define our callback
#functions first.

def destroy_handler(event):
 gtk.mainquit()
 return 0

def delete_handler(window, event):
 return 0

def click_handler(event):
 #Create the "Are you sure" dialog
 msgbox = gnome.ui.GnomeMessageBox(
  "Are you sure you want to quit?",
  gnome.ui.MESSAGE_BOX_QUESTION,
  gnome.ui.STOCK_BUTTON_YES,
  gnome.ui.STOCK_BUTTON_NO)
 msgbox.set_modal(1)
 msgbox.show()

 result = msgbox.run_and_close()

 #Button 0 is the Yes button.  If this is the
 #button they clicked on, tell GNOME to quit
 #it's event loop.  Otherwise, do nothing
 if (result == 0):
  gtk.mainquit()

 return 0

####MAIN PROGRAM####

#Create new application window
myapp = gnome.ui.GnomeApp(
 "gnome-example", "Gnome Example Program")

#Create new button
mybutton = gtk.GtkButton(
 "I Want to Quit the GNOME Example program")
myapp.set_contents(mybutton)

#Makes the button show up
mybutton.show()

#Makes the application window show up
myapp.show()

#Connect signal handlers
myapp.connect("delete_event", delete_handler)
myapp.connect("destroy", destroy_handler)
mybutton.connect("clicked", click_handler)
#Transfer control to GNOME
gtk.mainloop()

To run it type python gnome-example .py.


Team LiB
Previous Section Next Section