CC_Tooltips - easy php-gtk tooltip management

This is the first article in a series on the features and usage of Callicore Desktop. CC Desktop is a "framework" for php-gtk2 applications. Basically it includes commonly used widgets and classes to make developing programs quick and easy.

Tooltips are useful snippets of information displayed in a pop-up window that appears when a mouse pointer hovers over an object. Gtk+ has a tooltips class with methods that allow tooltips to be set on a widget and the group of tooltips to be disabled and enabled. Tooltips in PHP_Gtk2 aren't difficult to use, but Callicore has a class - CC_Tooltips - that makes tooltip handling quick and easy. Like almost all Callicore Desktop classes, "additional requirements" are kept to an absolute minimum. The tooltips class requires only one other class - CC_Exception - which is with the main CC static class file. If you don't want the extra requirement you can simply replace CC_Exception with Exception in the source.

In order for a GtkTooltips object to work correctly with PHP_Gtk2 it needs to be global. But having a bunch of global variables does not make for reusable or decoupled code. In fact it can lead to mysterious problems down the road, especially when working with a large application. The solution, of course, is to make your GtkTooltips a singleton instance. But, what if you want two GtkTooltips objects? Well then you're out of luck. There is a limitation with Gtk+ that an object can only have one tooltip attached to it (kind of annoying). There is "private" tooltip data that you can assign to a widget in addition to the regular tooltip. The general idea behind this was to allow more detailed 'what is this' data. Gtk+ used to have built in functionality for this circumstance by using private tips and GtkTipsQuery. But GtkTipsQuery is now deprecated and isn't even implemented in PHP_Gtk2 and there is no way to duplicate the functionality.

CC_Tooltips extends the base GtkTooltips class to enhance the functionality. It handles a few "special cases" and forces the object to be a singleton. The "standard" way to do singletons in PHP5 is to make the constructor protected or private, make the __clone method protected or private, add a protected static singleton property to store the object, and add an public "instance" or "singleton" method to retrieve the object. Since CC_Tooltips extends GtkTooltips (which has a public constructor), Callicore can't change the visibility of the constructor, so we fake it. Instead we keep a static protected check property that the CC_Tooltips::instance() method sets to true - the constructor then checks to make sure this property is set, and throws an error identical to PHP's if the property is not set. Kind of a hack, but effective.

CC_Tooltips has a few additional features as well. First of all, all items must have their own x window to have a tooltip set. The set_tip method is overridden to check for this - if the widget does NOT have it's own window, an event box is added to the same location and the item is placed inside, then the tooltip is set on the event box. Also toolitems have their own method to set tooltips, they can't be set the same way other widgets are. The set_tip method detects this and reacts appropriately so you can use the same api for everything. Finally, the class adds support for tooltips in gtktreeviews and gtkiconviews - send the gtkpath the tooltip should apply to with your set tip call and the rest should be done for you.

The following is a short example script that shows how to set tips on everything using CC_Tooltips :)
[php]
// include tooltips file
include('tooltips.class.php');

// grab the object
$tips = CC_Tooltips::instance();

// window to put stuff in
$window = new GtkWindow();
$window->set_title('Tooltips Test');
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
$window->set_default_size(300, 200);
$tips->set_tip($window, 'This will NOT show!');

// set a tooltip on a vbox, even though it shouldn't be possible :)
$window->add($vbox = new GtkVBox());
$tips->set_tip($vbox, 'weird');

//the model
$store = new GtkListStore(Gtk::TYPE_STRING);
$store->append(array('dog'));
$store->append(array('cat'));
$store->append(array('pig'));
$store->append(array('horse'));

//a treeview
$treeview = new GtkTreeView($store);

//the text renderer is used to display text
$renderer = new GtkCellRendererText();
$animal = new GtkTreeViewColumn('Animal', $renderer, 'text', 0);
$treeview->append_column($animal);

// scrolling treeview added
$scroll = new GtkScrolledWindow();
$scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
$scroll->add($treeview);
$vbox->add($scroll);

// foreach each available path in the treeview, set a tooltip
foreach($store as $path => $item)
{
$tips->set_tip($treeview, 'The animal is ' . $item[0], array($path));
}

// a "normal" tooltip
$vbox->add($button = new GtkButton('Is this fun?'));
$tips->set_tip($button, 'a normal tip');

// tooltips in toolbars are now set just like everything else
$tools = new GtkToolbar();
$button = GtkToolButton::new_from_stock(Gtk::STOCK_NEW);
$tips->set_tip($button, 'create a new file');
$tools->insert($button, -1);
$button = GtkToolButton::new_from_stock(Gtk::STOCK_OPEN);
$tips->set_tip($button, 'open a file');
$tools->insert($button, -1);
$vbox->add($tools);

//show and run it
$window->show_all();
Gtk::main();
[/php]

Comments

Be the first to write a comment!

Post a Reply