Mastering Glade for PHP-GTK2
PHP-GTK2 Cookbook Vol.2
PHP-GTK2 Cookbook Vol.1
Intro to Glade for PHP-GTK2
PHP-GTK2 Demystified
PHP-GTK ExplorerYour "secret weapon" for learning, exploring, understanding and mastering PHP-GTK2!
[Free Download Here]
|
|
|
| Calculator - Step 4. Improve on User Interface |
|
Objective for this step
Once we have the core business logic, and foolproofed the application, we can start improving the user interface (UI), such as making it nicer, or giving a better user experience.
Here are a few examples:
- Change this to a 4 or 8 line display so that user can see clearly what has been entered earlier
- Store the results in a history and allowing user to refer back or use any result in the history
- Allow user to change past entry, e.g. the user entered 123+457, press the '=' sign, and realized that it should be 123+456. The user can press a button, go back to edit 457 to 456, and then press the '=' sign.
As mentioned earlier, the focus here is php-gtk2, and not the mechanics of the application itself. So we will only add a few cosmetic changes to the calculator here.
The Code
Note: If you have installed php-gtk2 using Gnope Installer on Windows, and if running the sample code below gives you warning that the Symbolic names for keys (e.g. Gdk::KEY_Return) is not defined, you might want to update your php-gtk2 with the latest php-gtk2.dll available here. Simply download the php-gtk2.dll and replace the copy in the folder php-gtk2\ext. The latest compilation has put in the Symbolic names for keys listed here. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 24 25 26 27 28 29 30 31 32 33 37 38 39 45 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 79 80 81 82 83 84 85 86 87 88 89 90 91 92 95 96 97 98 103 104 105 106 107 108 109 110 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
| <?php
class Calculator{
var $operator = ''; var $stack = array(); var $is_entering_number = 0;
// constructor
function Calculator() { }
function main() { $this->setup_window(); $this->setup_layout(); $this->window->show_all(); // display the calculator
Gtk::main(); // and let's go!
}
function setup_window() { $this->window = new GtkWindow(); $this->window->set_size_request(200, 240); $this->window->connect_simple('destroy', array('Gtk','main_quit')); $this->window->connect('key-press-event', array(&$this, "on_keypress")); }
function setup_layout() { // setup a vbox to hold display and buttons
$vbox = new GtkVBox(); $this->window->add($vbox);
// setup display
$this->display = new GtkEntry(); $this->display->set_alignment(1.0); // right-justified
$this->display->set_editable(false); // for display only
$vbox->pack_start($this->display);
// the button labels
$button_label = array( array('BackSpc', 'CE', 'C'), array('7', '8', '9', '/', 'sqrt'), array('4', '5', '6', '*', '%'), array('1', '2', '3', '-', '1/x'), array('0', '+/-', '.', '+', '=') );
// setup the buttons
for ($j=0; $j<5; ++$j) { $hbox = new GtkHBox(); $vbox->pack_start($hbox); // use a hbox to hold each row of buttons
for ($i=0; $i<5; ++$i) { if ($j==0 && $i>2) continue; // first row contains only 3 buttons
$value = $button_label[$j][$i]; $button = new GtkButton($value); $button->set_size_request(40, 32); // set the size
$button->connect('clicked', array(&$this, "on_button")); if (preg_match("/^([0-9]|\.)$/", $value)) // digits
$button->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#FFFF33')); if (preg_match("/^(\+|-|\*|\/){1}$/", $value)) // +-*/
$button->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#ff99ff')); if ($value=='C' || $value=='CE') // Clear
$button->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#FF3366')); if ($value=='=') // =
$button->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#0099FF')); $hbox->pack_start($button); } } }
// process button click
function on_button($button) { $value = $button->child->get_text(); echo "button_click: $value\n"; $this->process_input($value); }
// process keyboard input
function on_keypress($widget, $event) { $keyval = $event->keyval; $value = chr($keyval); // get the ASCII equivalent
if (preg_match("/[0-9\+\-\*\/\.=]/", $value) || $keyval==Gdk::KEY_Return || $keyval==Gdk::KEY_BackSpace) { if ($keyval==Gdk::KEY_Return) $value='='; if ($keyval==Gdk::KEY_BackSpace) $value='BackSpc'; $this->process_input($value); $this->display->set_position(-1); // move the cursor to the end of display
} }
// process input
function process_input($value) { if (preg_match("/^([0-9]|\.)$/", $value)) { $number = array_pop($this->stack); if (preg_match("/^([0-9]|\.)+$/", $number)) { if ($value=='.') { if (strpos($number,'.')===false) $number .= $value; } else { $number .= $value; } } else { if ($number!='') array_push($this->stack, $number); $number = $value; } array_push($this->stack, $number); $this->display->set_text($number);
} elseif (preg_match("/^(\+|-|\*|\/|=){1}$/", $value)) { // perform binary operations
if (count($this->stack)<3) { if (preg_match("/^([0-9]|\.)+$/", end($this->stack))) if ($value!='=') array_push($this->stack, $value); } else { $number2 = array_pop($this->stack); $operator = array_pop($this->stack); $number1 = array_pop($this->stack); switch ($operator) { case '+': $result = $number1 + $number2; break; case '-': $result = $number1 - $number2; break; case '*': $result = $number1 * $number2; break; case '/': $result = $number1 / $number2; break; } $this->display->set_text($result); array_push($this->stack, $result); if ($value!='=') array_push($this->stack, $value); }
//process unary operators
} elseif ($value=='1/x' || $value=='sqrt' || $value=='%' || $value=='+/-') { if (count($this->stack)>=1) { $number = array_pop($this->stack); switch ($value) { case '1/x': $result = 1/$number; break; case 'sqrt': $result = sqrt($number); break; case '%': $result = $number / 100; break; case '+/-': $result = -$number; break; } $this->display->set_text($result); array_push($this->stack, $result); }
} elseif ($value=='C') { $this->stack=array(); $this->display->set_text('0');
} elseif ($value=='CE') { if (preg_match("/^([0-9]|\.)+$/", end($this->stack))) { $number = array_pop($this->stack); $this->display->set_text('0'); }
} elseif ($value=='BackSpc') { if (preg_match("/^([0-9]|\.)+$/", end($this->stack))) { $number = array_pop($this->stack); $number = substr($number, 0, strlen($number)-1); $this->display->set_text($number); array_push($this->stack, $number); } } $this->show_stack(); // show current stack
}
// prints the current stack content
function show_stack() { echo "current stack content:\n"; for ($i=count($this->stack)-1; $i>=0; --$i) { echo "stack[$i] = {$this->stack[$i]}\n"; } echo "\n"; } }
$cal = new Calculator(); // cerate a new calculator
$cal->main(); // let's run it!
?> |
Sample Output

Links
|
Search PHP-GTK2 Manual
Full-text search on php-gtk2 manual
|