Calculator - Step 2.4 Process the rest of the buttons

Objective for this step

In this step, we will finish up processing the rest of the buttons, including "C", "CE", "BackSpace" and "." (the decimal point).

The Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
16   
17   
18   
19   
20   
21   
22   
24   
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   
78   
79   
81   
82   
83   
84   
85   
86   
87   
88   
89   
90   
91   
93   
94   
95   
96   
97   
98   
99   
100   
101   
102   
103   
104   
105   
106   
107   
108   
109   
110   
111   
113   
114   
115   
116   
117   
118   
119   
120   
121   
122   
123   
124   
125   
126   
127   
128   
129   
130   
131   
132   
133   
134   
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   
<?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'));
    }

    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();
        $t = ($value=='1/x');
        echo "button_click: $value ($t)\n";

        if (preg_match("/^([0-9]|\.)$/", $value)) { // include also the decimal point
            $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(); // clears the stack
            $this->display->set_text('0');

        } elseif ($value=='CE') {
            if (preg_match("/^([0-9]|\.)+$/", end($this->stack))) { // make sure its a number
                $number = array_pop($this->stack); // clears the number on top of stack
                $this->display->set_text('0');
            }

        } elseif ($value=='BackSpc') {
            if (preg_match("/^([0-9]|\.)+$/", end($this->stack))) { // make sure its a number
                $number = array_pop($this->stack); // get the number
                $number = substr($number, 0, strlen($number)-1); // remove the right-most digit
                $this->display->set_text($number);
                array_push($this->stack, $number); // push it back to stack
            }
        }
        $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

  • '.' - just treat it like a number
  • 'C' - clears the entire stack
  • 'CE' - clears only the most recent number by popping the number off the top of the stock
  • 'BackSpace' - removes the rightmost digit of the number on the top of the stack

What's Next

We have finished processing all the buttons. We will deal with keyboard input in the next step.

Links

Search This Site

Google
Web This Site

Search PHP-GTK2 Manual

Full-text search on php-gtk2 manual

Members Login

Username:
Password:
Key:
What is this?
  Forget Password?