• 26 May 2013 - Since the new version attracted too many spammy registrations (around 250 fake accounts/day), user registrations are now protected by Mollom's spam protection service. Contact us if this causes some trouble.
  • 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.

Extending GtkToolbar to quickly build toolbars

Grapher class exampleA very easy way to build toolbars with icons, tooltips and an easy signal connect feature.

Details

Building GtkToolbar with buttons icons and tooltips require :

  1. creating a GtkToolbar widget,
  2. creating some GtkToolbarButtons from an external icon file,
  3. buttons can use stock icons (from systeme library),
  4. insert button to toolbar,
  5. setting up GtkTooltips to each buttons ; there must be only one instance of GtkTooltips object.
  6. setting up clicked signal callback to each buttons.
<?php
# pieces of code - this code is not working standalone.

$toolbar = new GtkToolbar();  // 1

$img = GtkImage::new_from_file($icon); // 2
$button = new GtkToolButton($img, $label); // 2

$button = GtkToolButton::new_from_stock(constant($stock_image_name)); // 3
$button->set_label($label); // 3

$menubar->insert($button, -1); // 4

$tooltips = new GtkTooltips();
$button->set_tooltip($tooltips, 'tip info'); // 5

$button->connect('clicked', 'button_signal_clicked' , $userdata); // 6
?>

all this tasks can be made in a quick way with Toolbar class. Look at example below; snapshot shows you the execution result.

Example usage

  1. this is a standard menubar in english,
  2. you can control attributes of toolbar button (label, tip, icon)
  3. an other toolbar description in french
  4. note defaults values
  5. french labels (external part visible for user) and english internals (coder)
  6. standard php-gtk windowing construction
  7. create a first toolbar with first description array, and set some toolbar attributes just as if Toolbar was a Gtktoolbar
  8. connect a signal callback for clicked signal,
  9. a second tooolbar localised in French,
  10. the signal callback ; have a look a function signature.

and that's all

<?php
#include class code here

// note 1
$specs1 = array(
'New',
'Open',
'Close',
'Quit',
 
'---',
 
'Group' => array(               // note 2
   
'label' => 'Group object',
   
'tip'   => 'Group object ...',
   
'icon'  => 'Group.png'
 
)
);

# a french Toolbar ;
# note : this is not the rigth way to localise a php-gtk2 application
# // note 3
$specs2 = array(
'Nouveau'  => array(
 
'label'   => 'Nouveau',
 
'icon'  => 'New',
 
'tip'  => 'Nouveau ...'
 
),
'Ouvrir'  => array(
 
'icon'  => 'Open'
 
# 'label' defaults to key (Ouvrir) // note 4
  # 'tips' defaults to key (Ouvrir)
 
),
'Fermer'  => array(
 
'icon'  => 'Close'                // note 5
 
),
'Quit'  => array(
 
'label' => 'Quitter',
 
'tip'   => 'Quitter ...'
 
)
);

// note 6
$window = new GtkWindow();
$window->connect_simple('destroy', array('gtk', 'main_quit'));
$window->set_title('Toolbar demo');
$window->set_position(Gtk::WIN_POS_CENTER);

 
$vbox = new GtkVbox();
 
$window->add($vbox);

   
// note 7
   
$toolbar = new Toolbar($specs1);
   
# # Gtk::TOOLBAR_ICONS, Gtk::TOOLBAR_TEXT,   Gtk::TOOLBAR_BOTH, Gtk::TOOLBAR_BOTH_HORIZ
   
$toolbar->set_toolbar_style(Gtk::TOOLBAR_BOTH);
   
$toolbar->set_size_request(300, -1);

  
// note 8
  
$toolbar->connect('clicked', 'toolbar_button_clicked', 'foobar');

   
$vbox->pack_start(new GtkLabel('toolbar1 - style=Gtk::TOOLBAR_BOTH'));
   
$vbox->pack_start($toolbar);

  
// note 9
   
$toolbar = new Toolbar($specs2);
   
$toolbar->set_toolbar_style(Gtk::TOOLBAR_ICONS);
   
$toolbar->set_size_request(300, -1);
   
$toolbar->connect('clicked', 'toolbar_button_clicked', 'foobar');

   
$vbox->pack_start(new GtkLabel('toolbar2 - a french toolbar with icons only (and tooltips)'));
   
$vbox->pack_start($toolbar);

$window->show_all();

Gtk::main();

// note 10
function toolbar_button_clicked($toolbar, $button_id, $userdata=null){
  echo
"button = $button_id ($userdata)\n";
  if(
$button_id == 'Quit')
   
Gtk::main_quit();
}
?>

Source (Tooltips)

This class is from Callicore project with a nice php-gtk2 framework in construction. You can't use multiple instance of GtkTooltips ; if you do, tooltips seems not working. So the choice here is to build a Singleton class using standard GtkTooltip.

<?php
# import here class Tooltips from Calicore project :
# http://websvn.bluga.net/wsvn/Callicore/desktop/trunk/lib/?rev=0&sc=0
# (file tooltips.class.php)
#

class CC_Tooltips extends GtkTooltips
{
  
# please complete ...
}
?>

Source Toolbar

here is full source code for Toolbar class with instructions in comments.

<?php
/**
* Toolbar class extended from GtkToolbar
*
*  - builds buttons from a description array
*  - description array can take attributes : (label, tip, icon)
*  - array keys are used by programmer for switching in signal callbacks,
*  - tooltips are build
*  - you can registrer to "clicked" signal just as if it was toolbar that was clicked.
*
* public methods :
*  - __construct($specs) : builds a Toolbar with specs array.
*  - connect($signal, $func, $userdata),
*  - connect_simple($signal, $func, $userdata) : overrides GtkToolbar signal registration
*    handles "clicked" signal internaly
*
* protected methods :
* signals :
*
* - "clicked" : this signal is emited (relayed) from toolbar buttons.
*  callback signature : void function function ($toolbar, $button_id, $userdata=null)
*
* specs array format :
*
* $spec = array('File', 'Open', 'Quit'); # simple format
*
* $spec = array(
*  'File' => array(
*    'label'  => 'your label'
*    'tip'    => 'your tip info'
*    'icon'   => Gtk::STOCK_* icon or a image file
*  );
*
* if icon is not a stock icon and not a regular file, it defaults to Gtk::STOCK_MISSING_IMAGE
*
*
*/

class Toolbar extends GtkToolbar{

  protected
$specs;
  protected
$buttons;
  protected
$signal;

  function
__construct($specs){
   
parent::__construct();
   
$this->specs = $specs;
   
$this->buttons = array();

   
$this->buildUI($specs);
  }

 
/**
  * construct toolbar managed objects (GtkToolButton)
  *
  */
 
protected function buildUI($specs){

    foreach(
$specs as $_key=>$button){


      if(
is_array($button)){
       
$record = $button;

       
# setup default values
       
$key = $_key;
       
$label = $_key;
       
$icon = $_key;
       
$tip = $_key;

        if(isset(
$record['label']))   $label = $record['label'];
        if(isset(
$record['tip']))     $tip   = $record['tip'];
        if(isset(
$record['icon']))    $icon  = $record['icon'];

       
$button = $this->buttons[$key] = $this->create_button($label, $icon, $tip);
       
$this->insert($button, -1);

      } else {
       
# separator '---'
       
if(preg_match('/^--.+/', $button)){
         
$button = new GtkSeparatortoolitem();
         
$this->insert($button, -1);
        } else{
         
# setup default values
         
$key = $button;
         
$label = $button;
         
$icon = $button;
         
$tip = $label;

         
$button = $this->buttons[$key] = $this->create_button($label, $icon, $tip);
         
$this->insert($button, -1);
        }
      }
    }
  }

 
/**
  * Create toolbar buttons with rigth parameters (label, icon, tip)
  * and register tooltip feature.
  *
  */
 
protected function create_button($label, $icon, $tip, $use_stock_image=true){
   
$tooltips = CC_Tooltips::instance();
   
# this does not work ; need to be a global variable or a singleton instance.
    # $tooltips = new GtkTooltips();

   
if(file_exists($icon)){
     
$img = GtkImage::new_from_file($icon);
     
$button = new GtkToolButton($img, $label);
     
$button->set_tooltip($tooltips, $tip);
    } else {
     
$stock_image_name = 'Gtk::STOCK_'.strtoupper($icon);
      if(!
defined($stock_image_name))
       
$stock_image_name = 'Gtk::STOCK_MISSING_IMAGE';
 
     
$button = GtkToolButton::new_from_stock(constant($stock_image_name));
     
$button->set_label($label);
     
$button->set_tooltip($tooltips, $tip);
    }
    return
$button;
  }

 
/**
  * public function connect($signal, $func, $userdata=null)
  *
  * if signal is "clicked", need to setup a callback with this signature
  *
  *    void function callback($toolbar, $button_id, $userdata=null)
  *
  *  else give signal registration to parent (GtkToolbar class)
  */
 
public function connect($signal, $func, $userdata=null){

   
# build a "relay" for signal callback ;
    # the goal is to call a callback with user-defined context
   
if($signal == 'clicked'){
     
$_userdata = array(
       
'userdata' => &$userdata,
       
'func'     => &$func
     
);
      foreach(
$this->buttons as $key=>$button){
       
$_userdata['button'] = $key;
       
$button->connect($signal, array($this, 'button_signal_clicked') , $_userdata);
      }
    }
    else
     
parent::connect($signal, $func, $userdata);
  }

 
/**
  * see connect method below.
  *
  */
 
public function connect_simple($signal, $func, $userdata=null){
    if(
$signal == 'clicked'){
     
$_userdata = array(
       
'userdata' => &$userdata,
       
'func'     => &$func
     
);
      foreach(
$this->buttons as $button){
       
$_userdata['button'] = $key;
       
$button->connect_simple($signal, array($this, 'button_signal_clicked'), $_userdata);
      }
    }
    else
     
parent::connect_simple($signal, $func, $userdata);
  }

 
/**
  * call user callback with signature :
  *  void function callback($toolbar, $button_id, $userdata=null)
  *
  * note : this method should be protected but can be called if protected outside of this class.
  *
  */
 
public function button_signal_clicked($toolbar, $userdata){
   
# call user callback with right parametrers
   
$userdata['func']($toolbar, $button_id=$userdata['button'], $userdata['userdata']);
  }
}
?>

Todo

If you need to manage a toolbar and a menu, changing active states for buttons in thoses 2 composants, the best way to acheive that task is in using GtkAction. A tutorial about this will be writen soon.

Links

PřílohaVelikost
Toolbar.php_.txt6.77 KB