326. How to layout widgets using gtkhtml - Example 2?

Problem

This is the second example to illustrate how we can layout and align PHP-GTK widgets using HTML. (View the first example here)

In this second example, I use the example from the article How to change tab order - Example 4?

Please first run the example from that article so that you know what we're trying to achieve. We will achieve the same thing in this example, except that we will use GtkHTML to do the layout and alignment as shown below:

How to layout widgets using gtkhtml - Example 2?


Solution

  • If you use plain PHP-GTK2, you need to have a good understanding of hbox, vbox and the expand parameter to be able to align the twelve buttons as shown in the output above.
  • However, this is straightforward in HTML using tables.
  • We make use of the techniques as outlined in How to left or right align text using gtkhtml? and How to embed gtk widgets within html text using gtkhtml?
  • Note that HTML just takes care of the layout and alignment. All the creation and setup of the widgets (GtkEntry, GtkButton, etc.) are in PHP-GTK2.

Important Note:

  • This only works for PHP-GTK2 compliled with the additional library GtkHTML.
  • For linux, you have to recompile php-gtk2 to include this library.
  • For windows, you may refer to the article How to install PHP-GTK2 on windows. The latest beta release from official php-gtk2 website comes complete with GtkHTML.
  • In the php.ini, don't forget to add php-gtk.extensions = php_gtk_html2.dll to turn on GtkHTML.
  • Lastly, the most "tricky" part in running GtkHTML is that to run this script, you have to use gconfd-2 | php script.php.

    If you have installed the beta release of PHP-GTK2 on windows as outlined in this article, you will find the program gconfd-2.exe in the root directory of php-gtk.
  • In the event that you cannot get this sample code to work, I would suggest that you try to do a fresh install of the beta-release of PHP-GTK2 (details here). It should work out-of-the-box (just need to add php-gtk.extensions = php_gtk_html2.dll in php.ini as explained above). Note that you can still keep your original copy of php-gtk2 while having this new version.
  • You will most likely see the warning (php.exe:5348): Gdk-WARNING **: gdkselection-win32.c:1068: OpenClipboard failed: Invalid window handle.. Not really sure how to fix this yet. The script seems to run ok, though.


Sample Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
13   
14   
15   
16   
17   
18   
19   
20   
21   
22   
23   
24   
25   
26   
27   
28   
29   
30   
31   
32   
33   
34   
35   
36   
37   
38   
39   
40   
41   
42   
43   
44   
45   
46   
47   
50   
51   
52   
54   
55   
66   
67   
68   
69   
70   
71   
72   
73   
74   
75   
76   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
87   
90   
91   
92   
95   
96   
97   
98   
99   
100   
102   
103   
104   
107   
108   
109   
110   
111   
112   
113   
114   
115   
116   
117   
118   
119   
<?php
$window = new GtkWindow();
$window->set_title($argv[0]);
$window->set_size_request(400, 240);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

$window->realize();
$org_bg = $window->get_style()->bg[Gtk::STATE_NORMAL];

// init entry fields
$object_count = 0;

// setup GtkHTML
$gtkhtml = new GtkHTML();
$vbox->pack_start($gtkhtml, 0);

$html_text = "<p align=center><b><font size=+1 color=blue>
Layout widgets using GtkHTML - Example 2</font></b></p>

<table border=0 cellpadding=0 cellspacing=0>";

$buttonIDs = array(
    array(4,3,2,1),
    array(5,0,0,12),
    array(6,0,0,11),
    array(7,8,9,10)
);

for ($j=0; $j<4; ++$j) {
    $html_text .= "<tr>";
    for ($i=0; $i<4; ++$i) {
        $id = $buttonIDs[$j][$i];
        if ($id=='') {
            $html_text .= "<td></td>";
        } else {
            $label = "tab_order_$id";
            print "label = $label\n";
            $html_text .= "<td><OBJECT classid=button_$label></OBJECT></td>";
        }
    }
    $html_text .= "</tr>";
}

$html_text .= "</table>";

$gtkhtml->connect('object-requested', 'on_object_requested');

$gtkhtml->load_from_string($html_text);
$gtkhtml->modify_base(Gtk::STATE_NORMAL, $org_bg);

$window->show_all();
Gtk::main();

function on_object_requested($gtkhtml, $gtkhtmlembedded) {
    // the following is supposed to return the classid of the object
    // but it doesn't seem to work...
    $object_id = $gtkhtmlembedded->classid;

    // until we find out how to get the object_id
    // we will just do a hardcode mapping of the the object_id
    global $object_count;
    $object_id_mapping = array( 
    'button_tab_order_4', 'button_tab_order_3', 
            'button_tab_order_2', 'button_tab_order_1', 
    'button_tab_order_5', 'button_tab_order_12', 
    'button_tab_order_6', 'button_tab_order_11', 
    'button_tab_order_7', 'button_tab_order_8', 
            'button_tab_order_9', 'button_tab_order_10', 
    'button_Submit'); // note 1
    $object_id = $object_id_mapping[$object_count];
    ++$object_count;

    if (!preg_match('/([a-zA-Z]+)_+?(.+)/', $object_id, $matches)) return;
    $widget_type = $matches[1]; // note 2
    $widget_id = $matches[2]; // note 3

    switch($widget_type) {
        case 'button': // note 4
            $button_label = str_replace('_', ' ', $widget_id);
            $button = new GtkButton($button_label);
            $button->set_size_request(86, 33);
            $button->connect('clicked', 'on_button');
            $gtkhtmlembedded->add($button);
            $button->show();
            break;
    }

    return true;
}

function on_button($button) {
    $label = $button->get_label();
    echo "You clicked me: $label!\n";
}

?>

Output

As shown above.
 

Explanation

The above code is based on How to embed gtk widgets within html text using gtkhtml?

It achieves the same result as How to change tab order - Example 4?

What's new here:

  1. As explained in How to embed gtk widgets within html text using gtkhtml?, I still don't know how to retrieve the object ID in the signal handler. So in the meantime, I just do a hardcode mapping to get the object ID. If you know how to get the object ID, you can comment out these few lines. (Yes, please drop me a note to let me know how to do that too...!)
  2. Get the widget type.
  3. Get the widget ID.
  4. Create the buttons.

Note

  • As with everything else in this world, there's nothing that's "perfect". Same for GtkHTML.
  • While laying out widgets is easy using GtkHTML, there are some subtle differences as a result.
  • Try playing with this example and that of How to change tab order - Example 4? Below are listed some differences:
    • Pressing space bar doesn't activate the button.
    • Pressing the arrow keys (up, down, left, right) doesn't move to the next button.
    • It's not possible to set the tab order. (If you know how, please share with us...)
  • The implications: for exact control over all the fine details of the behavior of a widget, use direct PHP-GTK2, of course.
  • However, for people new to PHP-GTK2, especially those with a lot of PHP web programming experience, I still feel GtkHTML is a great tool for laying out widgets.

Related Links

Add comment


Security code
Refresh