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.

Stock dialog: MsgBox

PHP-GTK 1 message box When working in graphical user interface mode, one often needs to display a message to the user who's waiting for an action, like a confirmation box as this is a frequent task, here's a class to do this efficiently with minimal application code.

Requirements

PHP-GTK 1 popup message box First of all, we will think of what we need.

  • a title setting is required
  • we will display different messages in different situations
  • we want the application to stop and wait for user input
  • buttons must be configurable
  • signal emitted by the msgbox on show, clicked or destroy events
  • if the label is too long we want a GtkText instead of a GtkLabel
  • we must know which button was clicked

The MsgBox class

So here's the code of our msgbox class. Don't be afraid by its length: most of the code volume is taken by the stock pixmaps embedded in the source.

<?php
/**
* @author Jonathan Gotti
* @package GUI_OBJECTS
* @license GNU Lesser General Public Licence
* http://opensource.org/licenses/lgpl-license.php
*/
class msgbox{
  var
$gtkwindow;
  var
$gdkwindow;
  var
$mode;
  var
$buttons;
  var
$label;
  var
$actionbox;
  var
$box;
  var
$mainbox;
  var
$pixmap;
 
/**
   * create the message box
   * @param string $title the window title
   * @param mixed $icon (int iconid|string filename|array xpm_data)
   *   the icon to display. Stock icons are:
   * - 0 for question
   * - 1 for exclamation
   * - 2 for X
   * @param string $label the message label
   * @param string $buttons is the button label
   *   separated by '|' (ie: "OK|CANCEL")
   * @param int $mode define various window setting
   * - 0 is default
   * - add 1 for a POPUP window
   * - add 2 for a modal one
   * (ie: 3 will be popup and modal window)
   * @param bool $forced_txt set it to true to force the
   *   message to be a gtktext without regard to its length
   */
 
function msgbox($label, $icon=0, $buttons='cancel|ok',
   
$title = NULL, $mode = 2, $forced_txt =FALSE) {

   
# set the window as popup accordingly to $mode
   
$this->gtkwindow = &new gtkwindow((($mode%2 == 1)
      ?
GTK_WINDOW_POPUP
     
: GTK_WINDOW_DIALOG)
      );
   
$this->gtkwindow->set_title($title);
   
$this->gtkwindow->realize();
   
$this->gdkwindow = $this->gtkwindow->window;
   
$this->frame = &new gtkframe();
   
$this->mainbox = &new gtkvbox(0, 5);
   
$this->box = &new gtkhbox(0, 5);
   
$this->gtkwindow->add($this->frame);
   
$this->frame->add($this->mainbox);

   
# THE ACTION BOX
   
$this->actionbox = &new gtkhbuttonbox();
   
$this->actionbox->set_spacing(5);
   
$this->actionbox->set_layout(GTK_BUTTONBOX_END);

   
# CREATE BUTTONS
   
$buttons = explode('|', $buttons);
   
$bt_count= count($buttons);
    foreach(
$buttons as $lb) {
     
$this->buttons[$lb] = &new gtkbutton($lb);
     
$this->buttons[$lb]->connect('clicked',
        array(&
$this, 'clicked'), $lb);
     
$this->actionbox->add($this->buttons[$lb]);
      if(++
$i == $bt_count)
       
$this->gtkwindow->set_focus($this->buttons[$lb]);
    }

   
# ARRANGING WIDGETS
   
$this->mainbox->pack_start($this->box, 1, 1, 0);
   
$separator = &new gtkhseparator();
   
$this->mainbox->pack_end($this->actionbox, 0, 0, 2);
   
$this->mainbox->pack_end($separator, 0, 0, 0);
    if(
$mode >= 2) #set the window to modal if needed
     
$this->gtkwindow->set_modal(TRUE);
   
# load the needed icons
   
$this->load_icon($icon);
    if (
$this->pixmap)
     
$this->box->pack_start($this->pixmap, 0, 0, 5);
    if(
strlen($label) < 250 && !$forced_txt) {
     
$this->label = &new gtklabel($label);
     
$this->label->set_justify(GTK_JUSTIFY_LEFT);
     
$this->box->pack_start($this->label, 1, 1, 5);
    } else {
     
$this->txt = &new gtktext();
     
$this->txt->set_word_wrap(FALSE);
     
$this->txt->insert(NULL, NULL, NULL, $label);
     
$this->scroll = &new gtkscrolledwindow();
     
$this->scroll->add($this->txt);
     
$this->scroll->set_policy(
       
GTK_POLICY_AUTOMATIC,
       
GTK_POLICY_AUTOMATIC);
     
$this->scroll->set_usize(450, 150);
     
$this->box->pack_start($this->scroll, 1, 1, 5);
    }
  }

 
/**
   * known signal 'destroy','show', 'clicked'
   * @param string $signal may be 'clicked','destroy','show'
   * @param mixed $callback (string function name
   *   or array(object,methodname))
   */
 
function connect($signal, $callback) {
   
$args[0] = &$this;
    for(
$i = 1 ; $i < func_num_args() ; $i++) {
     
$args[$i] = &func_get_arg($i);
    }
   
$this->cbs[$signal] = array($callback, $args);
  }

 
/** self explained */
 
function show() {
   
$this->gtkwindow->connect('delete-event',
      array(&
$this, 'destroy'));
   
$this->gtkwindow->connect('destroy-event',
      array(&
$this, 'destroy'));
   
$this->gtkwindow->set_position('center');
   
$this->gtkwindow->show_all();
    if(
is_array($this->cbs['show']))
     
call_user_func_array(
       
$this->cbs['show'][0],
       
$this->cbs['show'][1]
        );

   
# this will block your script parsing until gtk::main_quit() is called
   
gtk::main();
  }

 
/** self explained */
 
function destroy() {
   
$this->gtkwindow->destroy();
    if(
is_array($this->cbs['destroy']))
     
call_user_func_array(
       
$this->cbs['destroy'][0],
       
$this->cbs['destroy'][1]
        );
   
# this will quit the gtk loop we launched in the show method
    # and then the script continue to be parsed where it stoped.
   
gtk::main_quit();
  }

 
/** self explained */
 
function clicked($call_wdgt,$string) {
   
$this->clicked_button = $string;
    if (
is_array($this->cbs['clicked']))
     
call_user_func_array(
       
$this->cbs['clicked'][0],
       
$this->cbs['clicked'][1]
        );
   
$this->destroy();
  }

 
/**
   * load predefined icons by id
   * @internal
   * @private
   * @see msgbox constructor
   * @uses file2pixmap
   */
 
function load_icon($icon = 0) {
    if (!
is_numeric($icon))
      return
FALSE;

    switch(
$icon) {
      case
1:
       
$xpmd = array(
       
"31 31 32 1",
       
"` c #070319",
       
". c #a59816",
       
"# c #f0cc08",
       
"a c #4f4424",
       
"b c None",//#d4d2cc",
       
"c c #faec09",
       
"d c #473729",
       
"e c #f9dc05",
       
"f c #6a612d",
       
"g c #baa521",
       
"h c #f0f352",
       
"i c #fcfb0f",
       
"j c #bcb2c4",
       
"k c #cabc18",
       
"l c #0e055a",
       
"m c #1e2983",
       
"n c #646dc9",
       
"o c #6c8cac",
       
"p c #2d4eac",
       
"q c #4461b5",
       
"r c #3f1581",
       
"s c #816f11",
       
"t c #35316e",
       
"u c #211734",
       
"v c #54467c",
       
"w c #9c9a5c",
       
"x c #cda704",
       
"y c #151a71",
       
"z c #767040",
       
"A c #e0b706",
       
"B c #37345a",
       
"C c #e4db3b",
       
"bbbbbbbbbbbbbhiioobbbbbbbbbbbbb",
       
"bbbbbbbbbbbbCiiicznbbbbbbbbbbbb",
       
"bbbbbbbbbbbCcciiikmnbbbbbbbbbbb",
       
"bbbbbbbbbbbCcihiiifpbbbbbbbbbbb",
       
"bbbbbbbbbbCCciihiikyqbbbbbbbbbb",
       
"bbbbbbbbbbCCciiiiiifpbbbbbbbbbb",
       
"bbbbbjbbb#Cciiiiiiikyqbbbjbbbbb",
       
"bbbbbbbbbCCcii#Ciiicftbbbbbbbjb",
       
"bbbbbbbb#eCiCa``fiiikmqbbbbbbbb",
       
"bbbbbbbbC#cif```u.iiczmbbbbbbbb",
       
"bbbbjbb##Ciif``l`.iiikyqbbbbbbb",
       
"bbbbbbbC#ciis``lugiiccfmbbbbbbb",
       
"bbbbbb###cii.`lla#iicckyqbbbbbb",
       
"bbbbbb#CeiciCa`rsciiiccfmbbbbbb",
       
"bbbbbA##cicicayt.iccicckyqbbbbb",
       
"bbbbbk#Cccccismvgicciieefmbbbbb",
       
"bbbb###eiceci.ld#ieeiieckyqbjbb",
       
"bbbbk##cceceikuveiceciceezybbbb",
       
"bbbA##ecceeeiedfcceeecieekyqbbb",
       
"bbbk##cceeeeccffieeeeciceezmbbb",
       
"bb###eceeeeeecAAceeeeecieeAypbb",
       
"bbAA#cceeeeeccciceeeeeeiheezmbb",
       
"bA##eeee#eecea``sceee#eeie##ypb",
       
"bkA#eee#e#eis```uxi#e#eecc#ezyb",
       
"A#A#ee#e#e#if`ultgi#e##eec##Ayr",
       
"AA##eee#ee#isu`njAc#eee#eee##vr",
       
"kAA#########c.fzA############zl",
       
"wxAAAAAAAAAAA###AAAAAAAAAAAA#dy",
       
"bgxxxxxxxxxxxxxxxxxxxxxxxxxAfyy",
       
"bbqtttrBttttttttBtBtttrBttBrymb",
       
"bbbqppppppppptppppppppppppppppb");
        break;
      case
2:
       
$xpmd = array(
       
"31 31 32 1",
       
"` c #1d100f",
       
". c #ac8684",
       
"# c #980204",
       
"a c #9c5351",
       
"b c #d00506",
       
"c c #d33738",
       
"d c #f40e0e",
       
"e c #d74a49",
       
"f c #aecdcd",
       
"g c #b12d2d",
       
"h c #f66767",
       
"i c #d91717",
       
"j c #b80405",
       
"k c #665a58",
       
"l c #fa2f2f",
       
"m c None",
       
"n c #e00808",
       
"o c #570607",
       
"p c #f78b8b",
       
"q c #9cbebc",
       
"r c #967372",
       
"s c #342e2c",
       
"t c #f8fdfb",
       
"u c #c8e5e7",
       
"v c #7f0204",
       
"w c #fca1a1",
       
"x c #7c6161",
       
"y c #fc504f",
       
"z c #fc7979",
       
"A c #bf4f4f",
       
"B c #3c0204",
       
"C c #bc7274",
       
"mmmmmmmmmmmmhyyyyhzmmmmmmmmmmmm",
       
"mmmmmmmmmlyhzpzpzhyllhmmmmmmmmm",
       
"mmmmmmmlyhzpwwwwzzzhyll.mmmmmmm",
       
"mmmmmmlyhzpwwwwwpzzhyyllemmmmmm",
       
"mmmmmlyhzpwpwpzzzzhhyyyllimmmmm",
       
"mmmmdyyhzzzzhyyyyyyyyyllldgmmmm",
       
"mmmdyyyhhhyylddddlllyllllliammm",
       
"mmlllyyyrxldddddddddxalllidirmm",
       
"mmilyllrfurdddndndnkqqaddlii#mm",
       
"mlllllruttmrnnnndnkqttf.diiijkm",
       
"miilllhfttturndnnxqttttyndbibsm",
       
"miiddddyuttturnbrqttttennibji#m",
       
"hiildldneutttu..uttttybnnbijj#k",
       
"cibiddnnncutttttttttebbbbbjjjjs",
       
"ijiniinnbneutttttttebjbbbbbjjj`",
       
"jijinnbbbbbettttttcbbbbbbjjj#js",
       
"gjbbbbbnbbj.ttttttpjjbjjbjjj#j`",
       
"cjjjbbbbbjxfttttttu.jbjbjjj###`",
       
"h#jjjbbbjxftttttttturjjjjj##jvs",
       
"m#jjjjbjkqttttcetttturjjjj###vm",
       
"m#j#jbjkfttttejjAtttturj#j###Bm",
       
"mg#j#jrfttttAjjjjAutttt.#####`m",
       
"mmj#j#gftttejjjjj#Autttg##v#omm",
       
"mmg####gtte#j#j#jj#Attg##v#v`fm",
       
"mmmj####AA#j#j#j##j#Acvvvv#Bmmm",
       
"mmmm#########j##j####v#vv#Bmmmm",
       
"mmmmm##v############vvvv#ommmmm",
       
"mmmmmm##vv#######v#vvvvvBmmmmmm",
       
"mmmmmmmv#vvvvvvvvvvvv#vBmmmmmmm",
       
"mmmmmmmmmvv#vvvvvvvvvBmmmmmmmmm",
       
"mmmmmmmmmmmmovvvvoommmmmmmmmmmm");
        break;
      default:
       
$xpmd = array(
       
"31 31 32 1",
       
"` c #040d62",
       
". c #698ab6",
       
"# c #accded",
       
"a c #97989b",
       
"b c none",//#d4d2cc",
       
"c c #404f68",
       
"d c #c6e2fa",
       
"e c #a3b4c4",
       
"f c #4e5964",
       
"g c #86a9cd",
       
"h c #c2cdda",
       
"i c #bac0c6",
       
"j c #dceefb",
       
"k c #0b3188",
       
"l c #9dbcdd",
       
"m c #5a738c",
       
"n c #f5f9fa",
       
"o c #244ea4",
       
"p c #34436a",
       
"q c #4476d4",
       
"r c #7d99b3",
       
"s c #6b7a8e",
       
"t c #445e9c",
       
"u c #05227f",
       
"v c #89b4e1",
       
"w c #173d94",
       
"x c #a0a7ae",
       
"y c #5c6672",
       
"z c #5376b8",
       
"A c #7a9bcb",
       
"B c #dae5f2",
       
"C c #2c62c4",
       
"bbbbbbbbbbhjnBnjnBBBbbbbbbbbbbb",
       
"bbbbbbbhjnnnnnnnnnnnjBihbbbbbbb",
       
"bbbbbijnnnnnnnnnnnnnnnBbbbbbbbb",
       
"bbbbinnnnnnnnnnnnnnnnnnjbehbbbb",
       
"bbbinBnnnnnnBgzz.eBnnnnnBbhbbbb",
       
"bbiBBnnnnnnekkzw``phnnnnnBhihbb",
       
"bbBBnnnnnndw`.niku`oBnnnnjBexhb",
       
"biBnnnnnnnx`ukhBcuuuljjnnnBhxxb",
       
"bbBnnnnjnnlukwljtuukgnjjnjj#eei",
       
"ibjnnjnjnndAzABdouukljjjjnj#ixy",
       
"hhjnjjjnjjnjjjnekkwzdnjjdjjdlxs",
       
"ihBjnjjjjjjjnnjzuCAdjdjdjjdh#xs",
       
"",
       
"bbbbbbbbixfysgrv#v.fcxibbbbbbbb",
       
"bbbbbbbbbbibamgglvsxibbbbibbbbb",
       
"bbbbbbbbbbbbbamvlvmxbbbbbbbbbbb",
       
"bbbbibbbbbbbbbamvvmxbbbbbbbbbbb",
       
"bbbbbbbbbbbbbbbamvmxbbbbbbbbbbb",
       
"bbbbbbbbbbbbbbbiammxbbbbbbbbbbb",
       
"bbbbbbbbbbbbibbbbacxbbbbbbbibbb");
      }

     
# create pixmap
     
$pix = gdk::pixmap_create_from_xpm_d($this->gdkwindow,
       
NULL, $xpmd);
     
$this->pixmap = &new gtkpixmap($pix[0], $pix[1]);
    }
  }
?>

Using MsgBox

Invocation wrapper

Now we have an easy to use object to display MsgBox, but we want a one line way to display such messages so we'll create a function (take this as a sample of use) for this.

<?php
/**
* this will display a blocking msgbox waiting for user input.
* it will return the clicked button string
* see class message box for more details about params
* @param string $title
* @param mixed $icon_type
* @param string $label
* @param string $button_labels
* @param int mode
*/
function gtkgui_msgbox($title = 'Confirmation.',
 
$icon_type = 0,
 
$label = 'Do you wish to continue ?',
 
$button_labels = 'cancel|ok',
 
$mode = 0) {
     
 
$msg = &new msgbox($label, $icon_type,
   
$button_labels, $title, $mode);
 
$msg->show();
  return
$msg->clicked_button;
}
?>

Now it's really easy to get a user input. For example, we can do :

<?php
....
$msg = gtkgui_msgbox('Quit', 0, 'Do you really want to quit',
 
'cancel|ok', 2);
if(
$msg != 'ok')
  exit;
# else continue to do what you want
....
?>

By doing this the script will stop when we call the gtkgui_msgbox function, until the user clicks a button or destroys the box. When the user clicks the script continues where it had stopped and $msg value is the button clicked label ("ok" or "cancel" in this case), so we can check the user response.

Debugging with MsgBox

PHP-GTK 1 debug
  message box

Another common usage I found for this is a debug function which will display some variables contents in such a MsgBox. It's really usefull to check what's going on with your code when developping, instead of using echo or print. It also includes a nice "kill app" button which does exactly what you think it should. Here it is :

<?php
/**
* msgbox showing print_r(args), all callbacks connected
* it will block the script execution until you press
* continue and adds a "kill app" button wich will
* immediately end your program when clicked
* @param mixed as many variables as you want to check values
*/
function showvar() {
 
$argc = func_num_args();
 
# formatting string to display
 
for ($i = 0 ; $i < $argc ; $i++) {
   
$arg = @func_get_arg($i);
   
$str .= print_r($arg, 1) . "\n";
  }
 
$msg = &new msgbox($str, 2, 'kill app|continue', 'Debug');
 
$msg->show();
  if (
'kill app' == $msg->clicked_button)
    exit;
}

# sample use will open a msgbox displaying var
for ($i = 33 ; $i < 127 ; $i++) {
  echo
"LOOP $i => " . chr($i) . "\n";
 
$var[$i] = chr($i);
}

showvar($var);
?>

Voila! I hope this will be helpfull to you, don't hesitate to send me your comments, enhancements or simply feedbacks.

This work was inspired from another messagebox class found at http://binary.gamer.net.nz/ (seems to be unavailabe now).

PHP-GTK 2

A PHP-GTK 2 version would likely be shorter, making use of GtkDialog and stock icons bundled in GTK 2.

Could you write it ? If so, submit it to the site !