rendered paste body<?phperror_reporting(E_ALL);class Actions { protected $actions; protected $definitions; function __construct(){ $this->actions = array(); $this->definitions = array(); } public function add($name, $label, $tooltip, $stock_id, $type='button', $set_active=false, $radio_value=null, $radio_group=null){ if($stock_id == null) $stock_id = Gtk::STOCK_MISSING_IMAGE; switch($type){ case 'button': $this->actions[$name] = new GtkAction($name, $label, $tooltip, $stock_id); break; case 'toggle': $this->actions[$name] = $action = new GtkToggleAction($name, $label, $tooltip, $stock_id); if($set_active) $action->set_active(true); break; case 'radio': $this->actions[$name] = $action = new GtkRadioAction($name, $label, $tooltip, $stock_id, $radio_value); if(isset($this->actions[$radio_group])) $action->set_group($this->actions[$radio_group]); if($set_active) $action->set_active(true); break; } # register definitions for future use (getting stock item value) $this->definitions[$name] = array($name, $label, $tooltip, $stock_id, $type, $set_active, $radio_value, $radio_group); } public function get($key){ if(!isset($this->actions[$key])){ trigger_error('key not found : ' . $key); return null; } return $this->actions[$key]; } public function type($key){ if(!isset($this->actions[$key])){ trigger_error('key not found : ' . $key); return null; } return $this->types[$key]; } public function get_stock_id($key){ if(!isset($this->actions[$key])){ trigger_error('key not found : ' . $key); return null; } return $this->definitions[$key][3]; } public function exists($key){ return isset($this->actions[$key]); } public function create_tool_item($key){ if(!isset($this->actions[$key])){ trigger_error('can create tool item ; action not found : ' . $key); return null; } $tooltips = Tooltips::instance(); $action = $this->get($key); $widget = $action->create_tool_item(); $tooltips->set_tip($widget, $action->get_property('tooltip')); return $widget; } public function create_menu_item($key, $set_tooltip=false){ if(!isset($this->actions[$key])){ trigger_error('can create menu item ; action not found : ' . $key); return null; } $action = $this->get($key); if(file_exists($this->get_stock_id($key))) $widget = $this->create_tool_button($this->get_stock_id($key), $actions) else $widget = $action->create_menu_item(); # don't set tooltip info by default. if($set_tooltip){ $tooltips = Tooltips::instance(); $tooltips->set_tip($widget, $action->get_property('tooltip')); } return $widget; } protected function create_tool_button($icon, $label){ if(!file_exists($icon)) return null; $img = GtkImage::new_from_file($icon); $button = new GtkToolButton($img, $label); return $button; } public function connect($signal, $function, $userdata=null){ foreach($this->actions as $action){ $action->connect($signal, $function, $userdata); } } public function connect_simple($signal, $function, $userdata=null){ foreach($this->actions as $action){ $action->connect_simple($signal, $function, $userdata); } }}## for sources see Callicore project :# http://callicore.net/# http://websvn.bluga.net/wsvn/Callicore/desktop/trunk/?rev=0&sc=0#class Tooltips extends GtkTooltips{ /** * singleton instance for this class * @var $singleton instanceof Tooltips */ static protected $singleton; /** * switches on to allow construct to occur * @var $check bool */ static protected $check = FALSE; /** * public function __construct * * @return void */ public function __construct() { if(self::$check == FALSE) { throw new Exception('Tooltips is a singleton class - use Tooltips::instance() to retrieve the current object'); } self::$singleton = $this; parent::__construct(); self::$singleton = $this; $this->set_delay(500); $this->enable(); } /** * public function set_tip * * overrides original function and does gettext, also * fixes tooltips for GtkToolItem stuff * * @param object $wiget instanceof GtkObject * @return void */ public function set_tip($widget, $tooltip) { if($widget instanceof GtkToolItem) { $widget->set_tooltip($this, $tooltip); } else { parent::set_tip($widget, $tooltip); } return; } /** * static public function instance * * this is how you "construct" a Tooltips object * * @return object instanceof Tooltips */ static public function instance() { if(is_null(self::$singleton)) { self::$check = TRUE; self::$singleton = new Tooltips(); self::$check = FALSE; } return self::$singleton; } /** * public function __clone() * * disable cloning of a singleton * * @return void */ public function __clone() { throw new Exception('Cannot clone singleton object Tooltips'); return; }}/** * ActionToolbar class extended from GtkToolbar * * - builds buttons from a description array * - description array can take attributes : (label, tip, icon) * * public methods : * - __construct($specs, $actions) : builds a Toolbar with specs and actions arrays. * * specs array format : * * $spec = array('File', 'Open', 'Quit'); # simple format * * if icon is not a stock icon and not a regular file, it defaults to Gtk::STOCK_MISSING_IMAGE * * */class ActionToolbar extends GtkToolbar{ protected $specs; protected $buttons; protected $signal; protected $actions; function __construct($specs, $actions=null){ parent::__construct(); $this->specs = $specs; $this->buttons = array(); $this->actions = $actions; $this->buildUI($specs, $this->actions); } /** * construct toolbar managed objects (GtkToolButton) * */ protected function buildUI($specs, $actions){ $count=0; # count buttons group; add a toolbar space if not first group. foreach($specs as $group_key=>$group){ if($count>0) $this->insert(new GtkSeparatorToolItem(), -1); foreach($group as $_key=>$item){ $action = $actions->get($item); if($actions->exists($item)){ $button = $actions->create_tool_item($item); $this->insert($button, -1); } else { trigger_error('action not found for item : ' . $item); } } $count++; } } /** * Create toolbar buttons with rigth parameters (label, icon, tip) * and register tooltip feature. * */ /* not used now protected function create_button($label, $icon, $tip, $use_stock_image=true){ $tooltips = 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; } */}class ActionMenubar extends GtkMenubar{ protected $specs; protected $actions; function __construct($specs, $actions){ parent::__construct(); $this->specs = $specs; $this->actions = $actions; $this->buildUI($specs, $actions); } protected function buildUI($specs, $actions){ foreach($specs as $group_key=>$group){ $this->append($menu_item = new GtkMenuItem($group_key)); $menu = new GtkMenu(); $menu_item->set_submenu($menu); if(is_array($group)) $this->create_menu($menu, $group, $actions); } } protected function create_menu($menu, $menu_specs, $actions){ foreach($menu_specs as $_key=>$item){ if(is_array($item)){ $submenu = new GtkMenu(); $menu->append($menu_item = new GtkMenuItem($_key)); $menu_item->set_submenu($submenu); $this->create_menu($submenu, $item, $actions); } else { # separator item label is '---' with as many - as you want if(preg_match('/^-.*$/', $item)){ $menu->append(new GtkSeparatorMenuItem()); } elseif($actions->exists($item)){ $menu_item = $actions->create_menu_item($item); $menu->append($menu_item); } else{ trigger_error('action not found : ' . $item); $menu->append($menu_item = new GtkMenuItem(' - ' . $item . ' - ')); } } } }}class MainWindow extends GtkWindow{ protected $menubar; protected $toolbar; protected $statusbar; protected $drawing_area; protected $vbox; protected $actions; function __construct(){ parent::__construct(); $this->buildUI(); $this->main_window_setup(); $this->initial_setup(); $this->show_all(); } protected function buildUI(){ $this->actions_initialize(); $this->menubar = $this->create_menubar($this->actions); $this->toolbar = $this->create_toolbar($this->actions); $this->statusbar = new GtkStatusbar(); $this->drawing_area = new GtkDrawingArea(); $vbox = $this->vbox = new GtkVbox; $this->add($vbox); $vbox->pack_start($this->menubar, 0, 0); $vbox->pack_start($this->toolbar, 0, 0); $vbox->pack_start($this->drawing_area, true, true); $vbox->pack_end($this->statusbar, 0, 0); } # user defines setup; may be what you need. protected function initial_setup(){ # display only icons on toolbar $this->toolbar->set_toolbar_style(Gtk::TOOLBAR_ICONS); # set Cut, Paste unsensitive $this->actions->get('edit_cut')->set_sensitive(false); $this->actions->get('edit_paste')->set_sensitive(false); } protected function main_window_setup(){ $this->set_title('App class test'); $this->set_size_request(400, 200); $this->connect_simple('destroy', array($this, 'on_destroy')); $this->set_position(Gtk::WIN_POS_CENTER); } protected function actions_initialize(){ $this->actions = new Actions(); # actions manager. # in order : name, Label, tooltip, stock_icon; $this->actions->add('file_new', 'New', 'New', Gtk::STOCK_NEW); $this->actions->add('file_open', 'Open', 'Open ...', Gtk::STOCK_OPEN); $this->actions->add('file_close', 'Close', 'Close', Gtk::STOCK_CLOSE); $this->actions->add('file_quit', 'Quit', 'Quit', Gtk::STOCK_QUIT); $this->actions->add('edit_cut', 'Cut', 'Cut', Gtk::STOCK_CUT); $this->actions->add('edit_copy', 'Copy', 'Copy', Gtk::STOCK_COPY); $this->actions->add('edit_paste', 'Paste', 'Paste', Gtk::STOCK_PASTE); $this->actions->add('edit_group', 'Group', 'Group Objects', 'Group.png'); $this->actions->add('view_toolbar', 'Toolbar', 'Toolbar', null, $type='toggle', true); $this->actions->add('view_menubar', 'Menubar', 'Menubar', null, $type='toggle', false); $this->actions->add('view_zoom', 'Zoom', 'Zoom', null); $this->actions->add('view_zoom_50', '50%', '50 percent', null, $type='radio', false, 50 , null); $this->actions->add('view_zoom_100', '100%', '100 percent', null, $type='radio', true, 100, 'view_zoom_50'); $this->actions->add('view_zoom_150', '150%', '150 percent', null, $type='radio', false, 150, 'view_zoom_50'); $this->actions->add('view_zoom_special_a4', 'A4', 'A4 format', null); $this->actions->add('view_zoom_special_a3', 'A3', 'A3 format', null); $this->actions->add('view_zoom_special_userdef', 'User def ...', 'user defined format', null); $this->actions->add('help_about', 'About', 'About', null); $this->actions->add('help_php', 'Php', 'Php', null); $this->actions->add('help_phpgtk', 'Php-Gtk', 'Php-Gtk', null); $this->actions->add('help_gnope', 'Gnope', 'Gnope', null); } protected function create_menubar($actions){ $specs = array( '_File' => array('file_new', 'file_open', 'file_close', '---', 'file_quit'), '_Edit' => array('edit_cut', 'edit_copy', 'edit_paste', '---', 'edit_group'), '_View' => array( 'view_toolbar', 'view_menubar', 'Zoom' => array ( 'view_zoom_50', 'view_zoom_100', 'view_zoom_150', 'special' => array('view_zoom_special_a4', 'view_zoom_special_a3', 'view_zoom_special_userdef') ) ), '_Help' => array('help_php', 'help_phpgtk', 'help_gnope', 'help_about') ); $menubar = new ActionMenubar($specs, $actions); return $menubar; } protected function create_toolbar($actions){ $specs = array( 'file' => array('file_new', 'file_open', 'file_close', 'file_quit'), 'edit' => array('edit_cut', 'edit_copy', 'edit_paste', 'edit_group'), 'zoom' => array('view_zoom_50', 'view_zoom_100', 'view_zoom_150') ); return new ActionToolbar($specs, $actions); } /** * shutdown function ; should be overriden. * */ public function on_destroy(){ Gtk::main_quit(); } /** * * add 'activate' signal capabilities to Application class. * * user callback synopsys : void function action_activate($action, $action_name, $userdata=null) * */ public function connect($signal, $func, $userdata=null){ if($signal == 'activate'){ $_userdata = array( 'userdata' => &$userdata, 'func' => &$func, ); return $this->actions->connect($signal, array($this, 'on_activate'), $_userdata); } return parent::connect($signal, $function, $userdata); } /** * signal callback relay ; internal use only (should be private or protected). */ public function on_activate($action, $userdata){ # call user callback with right parametrers $userdata['func']($action, $action->get_name(), $userdata['userdata']); }}$windows = array();$windows[] = $main_win = new MainWindow();$main_win->connect('activate', 'action_activate', $main_win);Gtk::main();function action_activate($action, $action_name, $userdata=null){ global $windows; if(is_a($action, 'GtkRadioAction')){ if($action->get_active()){ $value = $action->get_current_value(); echo "action activate : $action_name ($value)\n"; } } else echo "action activate : $action_name\n"; switch($action_name){ case 'file_quit': Gtk::main_quit(); break; case 'file_new': $windows[] = $new_window = new MainWindow(); $new_window->connect('activate', 'action_activate', $new_window); break; case 'file_close': # don't work now ... $main_win = $userdata; unset($main_win); break; }}?>