01 May 2013 - After the site upgrade, all passwords were reset and you will need to ask the site for a login reset on your first connection.

Add icons to GtkMenu

The goal: icons in menus

When creating a soft, you'll often want to have a menu like in the majority of graphical softs. It's often clear in your mind but require more code than you want to do simple things using a plain GtkMenu. So here's a class to help you to quickly design such menus and will also allow you to display nice icon in your menus.

How to use it ?

first of all copy the class code to a file (ie: class-menu.php) and then include it in your code. Then here is a sample of code to show you how simple it is to create menu in your application so let's see:

<?php
if (strtoupper(substr(PHP_OS, 0,3)) == 'WIN')
 
dl('php_gtk.dll');
else
 
dl('php_gtk.so');

// This is the class file you just created
include_once('path_to_class-menu.php');

$w = &new GtkWindow();
$w->connect('destroy-event', 'shutdown');
$w->connect('delete-event', 'shutdown');
$w->set_position('center');

/**
* We realize the window to get the gdkwindow needed to
* create Xpm if we want to display icons in our menu
*/
$w->realize();
$gdkwindow  = $w->window;

/**
* We also create a gtkaccelgroup to manage accelkeys
* the class menu will attempt to create its own if none
* is given at creation time
*/
$accelgroup = &new GtkAccelGroup();
$w->add_accel_group($accelgroup);

// So we declare the menu and add it to the window
$menu = &new menu($gdkwindow, $accelgroup);
$w->add($menu->bar);

/**
* We know can add entrys to the menu
*/

// First the file menu
$menu->add_menu_item('file', null, 'file');

// Second we want a open file option in the file menu
$menu->add_menu_item(
 
$keyid='open',
 
$parent='file',
 
$label='_open',
 
$callback='openfilefunctionname',
 
$imgfile='img/fileopen.xpm');

// We also want a separator in the menu file
$menu->add_sep('file');
$menu->add_menu_item('quit', 'file', '_quit',
 
'shutdown', 'img/exit.xpm');
$menu->add_menu_item('help',null,'help');
$menu->add_menu_item('about','help','about',
 
'about_function_name');

$w->show_all();
gtk::main();

function
shutdown() {
 
gtk::main_quit();
}
?>

This would display a window with only a nice menu with icons and accelkey already defined. So now here's the menu class code.

Check the code to find more details on how to use methods.

<?php
/**
* Easy menu manipulation
* Copyright (c) Jonathan Gotti
*    <jonathan.gotti@the-ring.homelinux.net>
* @license http://opensource.org/licenses/lgpl-license.php
*    GNU Lesser General Public Licence
*/

class menu {
  var
$bar;

 
/** the gdkwindow used to create pixmaps */
 
var $gdkwindow;

 
/** the accel group to manage accelkeys */
 
var $accel_group;

 
/** used for easy access to menus */
 
var $menus;

 
/** used for easy access to menuitems */
 
var $items;

 
/**
  * constructor function
  * @param GdkWindow $gdkwindow
  * @param GtkAccelGroup $accel_group
  * @return menu object
  **/
 
function menu($gdkwindow=null, $accel_group=null) {
  if (
is_a($gdkwindow,'gdkwindow'))
   
$this->gdkwindow = &$gdkwindow;
   
$this->bar        = &new GtkMenuBar();
   
$this->bar->set_shadow_type(GTK_SHADOW_ETCHED_IN);
    if (
is_a($accel_group,'GtkAccelGroup')) {
     
$this->accel_group = &$accel_group;
    } else {
   
$this->accel_group = &new GtkAccelGroup();
    }
   
# showvar($GLOBALS['MAIN']);
 
}

 
/**
   * add an handlebox as box property
   * and pack the bar into it so you will need to pack
   * $this->box instead of $this->bar
   */
 
function add_handlebox() {
   
$this->box = &new GtkHandleBox();
   
$this->box->add($this->bar);
  }

 
/**
   * will add a separator to $parent menu
   * @param string $parent the parent menu keyindex
   */
 
function add_sep($parent) {
   
$this->add_menu_item('SEP', $parent);
  }

 
/**
   * add an item to the menu
   * @param string $key is the keyindex to acces the item
   *     inside the objects
   * @param string $parent the parent's keyindex
   * @param string $label the text to display for this item
   *     (can be null to get a separator)
  * @param mixed $callback the function name or
  *     array(object,methodname) to call on select
  * @param string $imgfile optionnal file path to an icon
  * @param bool   $sensitive
  * @param bool   $is_checkmenuitem
  * @param bool   $is_checked
  */
 
function add_menu_item($key,
   
$parent,
   
$label=null,
   
$callback=null,
   
$imgfile=null,
   
$sensitive=TRUE,
   
$is_checkmenuitem=FALSE,
   
$is_checked=FALSE) {
    while (
$this->items[$key]) { # ensure a unike keyid
     
preg_match("!(\d+)$!",$key,$m);
     
$int = $m[1];
      if (
is_numeric($int))       
       
$key = substr($key, 0, - strlen($int)) . ($int+1);
      else
       
$key .= '1';
     
// echo "int $int / " . is_numeric($int) . "\n";
   
}
    if ((!
$label) && $this->menus[$parent]) {
     
$this->items[$key] = &new GtkMenuItem();
     
$this->items[$key]->set_sensitive(FALSE);
     
$this->menus[$parent]->append($this->items[$key]);
      return;
    }
    if (!
$is_checkmenuitem) {
     
$this->items[$key]= &new GtkMenuItem($label);
    } else {
     
$this->items[$key]= &new GtkCheckMenuitem($label);
     
$this->items[$key]->set_active($is_checked);
    }
   
$lb = $this->items[$key]->child;

   
# add icon if needed
   
if (file_exists($imgfile)) {
      if (!
$this->gdkwindow) {
       
$this->bar->realize();
       
$this->gdkwindow = $this->bar->window;
      }
      if (
$img = Gdk::pixmap_create_from_xpm(
       
$this->gdkwindow,null,$imgfile)) {
       
$img = &new GtkPixmap($img[0], $img[1]);     
       
$this->items[$key]->remove($lb);
       
$box = &new GtkHBox();
       
$box->pack_start($img,0,0,2);
       
$box->pack_start($lb,0,0,2);       
       
$this->items[$key]->add($box);
      }
    }

   
# adding to parent menu
   
if (!$parent) {
     
$this->bar->append($this->items[$key]);
    } else {
      if (!
$this->items[$parent]) {
        echo
"[ERROR] menu::add_menu_item to non-existent parent '$parent'\n";
        return
FALSE;
      }
      if (!
$this->menus[$parent]) {
       
$this->menus[$parent] = &new GtkMenu();
       
$this->items[$parent]->set_submenu($this->menus[$parent]);
      }
     
$this->menus[$parent]->append($this->items[$key]);
    }

   
# add accellkey if needed
   
if (substr_count($label, '_')) { # add a keyboard shortcut
     
$acckey = $lb->parse_uline($label);
     
$this->items[$key]->add_accelerator('activate',
       
$this->accel_group,
       
$acckey,
       
GDK_CONTROL_MASK,
       
GTK_ACCEL_VISIBLE);
    }

   
#connect to callback
   
if($callback)
     
$this->items[$key]->connect('activate', $callback, $key);
  }

  function
destroy() {
    if(
$this->box)
     
$this->box->destroy();
    else
     
$this->bar->destroy();
  }
}
?>

If you have any idea to enhance this piece of code don't hesitate to mail me, i'll surely enjoy.

Hope this will help {{~Nathan}} at the-ring dot homelinux dot net