Fast starting with Glade 2

When you are drawing User interfaces with a nice drawing tool like glade, the main difficulty is to connect your script (callbacks) to Gtk objects with signals. Connection is achieved throught object names:

  • you need to name properly each objects in glade,
  • after that, you can reference that name in your php script.

Here is a simple auto-signal connecting system based on the names of methods. See App class example below.

Note: this article is for PHP-GTK 2, but has an equivalent for PHP-GTK 1. See Fast Starting with Glade 1

You must name methods like this :

<?php
 
# 3 possibilities
 
function on_object_signal(){}
  function
on_object_name_signal(){}

 
# the last but the best one :
 
function on_object_name__complex_signal_name()
 
# complex_signal_name is converted to
  # complex-signal-name for GTK toolkit
?>

Here is the complete code ; you should separate the 2 classes.

<?php
error_reporting
(E_ALL);

# library
class GladeApp {
  function
load_glade($file) {
   
$this->wnd = &new GladeXML($file);
   
$list_of_methods=get_class_methods($this);
    for (
$i=0 ; $i < sizeof($list_of_methods) ; $i++) {
      if (
strstr($list_of_methods[$i], "on_")) {
        if (
preg_match('/on_(.+?)__(.+)$/'
         
$list_of_methods[$i], $values))
          {
         
$widget = $this->get_widget($values[1]);
         
$signal = $values[2];
         
$signal = str_replace('_', '-', $signal);
         
$widget->connect_simple($signal,
            array(
$this, $list_of_methods[$i]));
        } elseif (
preg_match('/on_(.+?_.+)_(.+)$/',
         
$list_of_methods[$i], $values))
          {
         
$widget = $this->get_widget($values[1]);
         
$widget->connect_simple($values[2],
            array(
$this, $list_of_methods[$i]));
        } elseif (
preg_match('/on_(.+?)_(.+?)$/',
         
$list_of_methods[$i], $values))
          {
         
$widget = $this->get_widget($values[1]);
         
$widget->connect_simple($values[2],
           array(
$this, $list_of_methods[$i]));
        }
      }
    }
  }

  function
get_widget($widget) {
    return
$this->wnd->get_widget($widget);
  }
}

# your class application
class App extends GladeApp {
  function
quit() {
   
gtk::main_quit();
  }

  function
on_button_quit_clicked() {
    echo
"application terminating ...\n";
   
$this->quit();
  }

  function
on_button_print_clicked() {
   
$entry = $this->get_widget('entry');
   
$txt = $entry->get_text();
    if (
$txt != '')
      echo
"$txt\n";
    else {
     
$label2 = $this->get_widget('label2');
     
$label2->set_text('please type some text before');
      }
    }

  function
on_button_delete_clicked() {
   
$entry = $this->get_widget('entry');
   
$entry->set_text('');
  }

  function
on_entry__key_press_event(){
    echo
"entry : key pressed\n";
  }
}

$a = new App();
$a->load_glade("test.glade");
gtk::main();
?>

The contents of the test.glade Glade file in XML format working with the App class are as follows.

<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">

<glade-interface>

<widget class="GtkWindow" id="window">
  <property name="visible">True</property>
  <property name="title" translatable="yes">window1</property>
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_NONE</property>
  <property name="modal">False</property>
  <property name="resizable">True</property>
  <property name="destroy_with_parent">False</property>
  <property name="decorated">True</property>
  <property name="skip_taskbar_hint">False</property>
  <property name="skip_pager_hint">False</property>
  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
  <property name="focus_on_map">True</property>

  <child>
    <widget class="GtkFixed" id="fixed1">
      <property name="visible">True</property>

      <child>
<widget class="GtkEntry" id="entry">
  <property name="width_request">216</property>
  <property name="height_request">32</property>
  <property name="visible">True</property>
  <property name="can_focus">True</property>
  <property name="editable">True</property>
  <property name="visibility">True</property>
  <property name="max_length">0</property>
  <property name="text" translatable="yes"></property>
  <property name="has_frame">True</property>
  <property name="invisible_char">*</property>
  <property name="activates_default">False</property>
</widget>
<packing>
  <property name="x">152</property>
  <property name="y">112</property>
</packing>
      </child>

      <child>
<widget class="GtkButton" id="button_print">
  <property name="width_request">58</property>
  <property name="height_request">27</property>
  <property name="visible">True</property>
  <property name="can_focus">True</property>
  <property name="label" translatable="yes">Print</property>
  <property name="use_underline">True</property>
  <property name="relief">GTK_RELIEF_NORMAL</property>
  <property name="focus_on_click">True</property>
</widget>
<packing>
  <property name="x">40</property>
  <property name="y">96</property>
</packing>
      </child>

      <child>
<widget class="GtkLabel" id="label1">
  <property name="width_request">224</property>
  <property name="height_request">40</property>
  <property name="visible">True</property>
  <property name="label" translatable="yes">write some text here
and press a button
</property>
  <property name="use_underline">False</property>
  <property name="use_markup">False</property>
  <property name="justify">GTK_JUSTIFY_LEFT</property>
  <property name="wrap">False</property>
  <property name="selectable">False</property>
  <property name="xalign">0.5</property>
  <property name="yalign">0.5</property>
  <property name="xpad">0</property>
  <property name="ypad">0</property>
  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
  <property name="width_chars">-1</property>
  <property name="single_line_mode">False</property>
  <property name="angle">0</property>
</widget>
<packing>
  <property name="x">152</property>
  <property name="y">64</property>
</packing>
      </child>

      <child>
<widget class="GtkButton" id="button_delete">
  <property name="width_request">58</property>
  <property name="height_request">27</property>
  <property name="visible">True</property>
  <property name="can_focus">True</property>
  <property name="label" translatable="yes">Delete</property>
  <property name="use_underline">True</property>
  <property name="relief">GTK_RELIEF_NORMAL</property>
  <property name="focus_on_click">True</property>
</widget>
<packing>
  <property name="x">40</property>
  <property name="y">128</property>
</packing>
      </child>

      <child>
<widget class="GtkButton" id="button_quit">
  <property name="width_request">58</property>
  <property name="height_request">27</property>
  <property name="visible">True</property>
  <property name="can_focus">True</property>
  <property name="label" translatable="yes">Quit</property>
  <property name="use_underline">True</property>
  <property name="relief">GTK_RELIEF_NORMAL</property>
  <property name="focus_on_click">True</property>
</widget>
<packing>
  <property name="x">40</property>
  <property name="y">200</property>
</packing>
      </child>

      <child>
<widget class="GtkLabel" id="label2">
  <property name="width_request">216</property>
  <property name="height_request">136</property>
  <property name="visible">True</property>
  <property name="label" translatable="yes">label2</property>
  <property name="use_underline">False</property>
  <property name="use_markup">False</property>
  <property name="justify">GTK_JUSTIFY_LEFT</property>
  <property name="wrap">False</property>
  <property name="selectable">False</property>
  <property name="xalign">0.5</property>
  <property name="yalign">0.5</property>
  <property name="xpad">0</property>
  <property name="ypad">0</property>
  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
  <property name="width_chars">-1</property>
  <property name="single_line_mode">False</property>
  <property name="angle">0</property>
</widget>
<packing>
  <property name="x">152</property>
  <property name="y">160</property>
</packing>
      </child>
    </widget>
  </child>
</widget>

</glade-interface>