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 3. Validation Checks |
|
Objective for this step
In this step, we will try to "foolproof" our calculator by putting in some validation checks .
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 86 87 88 89 94 95 96 97 98 99 100 101 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 141 142 143 144 145 146 147 148 149 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
| <?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
$button = new GtkButton($button_label[$j][$i]); $button->set_size_request(40, 32); // set the size
$button->connect('clicked', array(&$this, "on_button")); $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; // note 1
} 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))) // note 2
if ($value!='=') // note 3
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!
?> |
Explanation
Below are some of the validation checks that we have put in:
- don't allow two decimal points e.g. 1.2.3
- + - * / - will only be added to stack if top of stack is a number
- if there is only one number on stack, and the user press '=', the '=' should be go to stack.
There are many more other validation checks that need to put in place if you really want to make this calculator "foolproof". We won't go into all since the focus here is php-gtk2 as oppose to calculator.
Links
|
Search PHP-GTK2 Manual
Full-text search on php-gtk2 manual
|