324. How to embed gtk widgets within html text using gtkhtml?

Problem

You've seen how to display html text in PHP-GTK2 using GtkHTML in How to display html text using gtkhtml? With this, we are able to create a php-gtk browser as outlined in How to create a php gtk browser using gtkhtml - Part 1?

Then I showed how to create an html editor in How to create an html editor using gtkhtml - Part 1?

In this article, I'll show you the third most exciting (and possibly also the most useful) feature of GtkHTML — the ability to embed any Gtk widgets right inside the HTML text! Take a look at the sample output below. Did you see that I've embedded an GtkEntry right inside an HTML table as shown below:

How to embed gtk widgets within html text using gtkhtml?


Solution

  • First take a look at the article How to display a popup alert for required fields - Part 1?. I'm trying to achieve the same result, except that this time we are using GtkHTML.
  • I picked this example so that you can see clearly how you can embed Gtk widgets inside HTML text, and how embedded widgets can intermix with your normal code.
  • Embedded widgets are tagged with the tag OBJECT.
  • You need to use the signal 'object-requested' to be notified when GtkHTML sees an object.
  • You create the widget as per normal in the signal handler. Note that the PHP-GTK2 also passes you a pointer to $gtkhtmlembedded. All you need to do now is to add the widget to be embedded with $gtkhtmlembedded->add($widget). That's it!

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   
12   
13   
14   
15   
16   
17   
18   
19   
20   
21   
22   
23   
24   
25   
26   
27   
28   
29   
30   
31   
32   
33   
34   
36   
37   
38   
39   
40   
41   
42   
43   
45   
46   
47   
48   
49   
50   
51   
52   
53   
54   
55   
56   
57   
58   
59   
60   
61   
62   
63   
64   
65   
66   
67   
68   
69   
70   
71   
72   
73   
74   
76   
78   
79   
80   
81   
82   
83   
84   
85   
86   
<?php
$window = new GtkWindow();
$window->set_title($argv[0]);
$window->set_size_request(400, 150);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

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

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

$html_text = "<h3><font color=blue>Embed Gtk Widgets in GtkHTML</h3>
<table border=1>
<tr>
    <td><b>Please enter your name: </b></td>
    <td><OBJECT classid=entry1></OBJECT></td>
</tr>
</table>
";

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

$gtkhtml->load_from_string($html_text);
$gtkhtml->set_size_request(-1, 100);
$gtkhtml->modify_base(Gtk::STATE_NORMAL, $org_bg); // note 2

$submit_button = new GtkButton('Submit');
$submit_button->connect('clicked', 'on_submit_button');
$hbox = new GtkHBox();
$hbox->pack_start($submit_button, 0);
$vbox->pack_start($hbox, 0);

$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; // note 3

    global $entry;
    $entry = new GtkEntry(); // note 4
    $entry->connect('activate', 'on_activate');
    $gtkhtmlembedded->add($entry); // note 5
    $entry->show(); // note 6
    return true; // note 7
}

function on_activate($entry) {
    global $submit_button;
    $submit_button->clicked();
}

function on_submit_button($button) {
    global $entry;
    $input = $entry->get_text();
    echo "name = $input\n";
    if ($input=='') alert("Please enter your name!");
    $entry->grab_focus();
}

// display popup alert
function alert($msg) {
    $dialog = new GtkDialog('Alert', null, Gtk::DIALOG_MODAL);
    $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);
    $top_area = $dialog->vbox;
    $top_area->pack_start($hbox = new GtkHBox());
    $stock = GtkImage::new_from_stock(Gtk::STOCK_DIALOG_WARNING,
        Gtk::ICON_SIZE_DIALOG);
    $hbox->pack_start($stock, 0, 0);
    $hbox->pack_start(new GtkLabel($msg));
    $dialog->add_button(Gtk::STOCK_OK, Gtk::RESPONSE_OK);
    $dialog->set_has_separator(false);
    $dialog->show_all();
    $dialog->run();
    $dialog->destroy();
}

?>

Output

As shown above.
 

Explanation

The above code is based on How to display html text using gtkhtml?

It achieves the same result as How to display a popup alert for required fields - Part 1?

It also make use of the technique from How to set the background to original default color? to make the background color of GtkHTML the same gray as GtkWindow.

What's new here:

  1. Register the signal 'object-requested'.
  2. Set the background color of the GtkHTML to the default gray color of GtkWindow. Try commenting this line out and you'll know what I mean.
  3. Suppose to get the classid. But it doesn't work...! Possibly a bug or feature not implemented yet?
  4. Create a new GtkEntry.
  5. Embed it!
  6. Very important! Don't forget this, otherwise it won't show!
  7. VVIP! DON'T FORGOT THIS ONE too! Took me one hour to debug and find out about this!!! This tip alone is worth the trip coming to this site and reading this article, isn't it?

Note

  • If you run the code, you will most likely see the warming message:
    Notice: Undefined property: GtkHTMLEmbedded::$classid in C:\php-gtk2\php\test.php on line 42
  • I'm not sure if this is a bug or a feature not implemented yet in PHP-GTK2./li>
  • In any case, I've tried for the past one week, and still couldn't find any way to retrieve the object_id.
  • Without the object_id, it means that if you have more than one OBJECT tag in the HTML text, you will have no way to different between them.
  • Any of you have tried this before? Do you have any clues...?

P.S.

I'll show you in the next article why I feel this particular feature (i.e. the ability to embed Gtk widgets within HTML text) is so exciting and powerful...

Related Links

Add comment


Security code
Refresh