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 2.5 Processing Keyboard Inputs |
|
Objective for this step
In this step, we will handle keyboard inputs to the calculator.
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 135 136 137 138 139 140 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
| <?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) { // get the button input and call process_input()
$value = $button->child->get_text(); // get the button value
echo "button_click: $value\n"; $this->process_input($value); // process the input
}
// process keyboard input
function on_keypress($widget, $event) {// get keyboard input and call process_input()
$keyval = $event->keyval; // get the keypress value
$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)) { $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) { 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
Since the processing of keyboard input is exactly the same as that of the buttons, we can reuse the entire code by extracting the processing of input into a function process_input($value), and calling this function from the callback functions of button and keypress.
What's Next
We have put in the core business logic of the calculator. It's a fully functional calculator now.
However, we have not put in any error checking yet, for example, if user enters two decimal points (1.2.3), or keys in 6*=.
We will put in the validation checks in the next step.
Links
|
Search PHP-GTK2 Manual
Full-text search on php-gtk2 manual
|