1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
19 class CalculatorContext
20 var result
: nullable Float = null
22 var last_op
: nullable Char = null
24 var current
: nullable Float = null
25 var after_point
: nullable Int = null
27 fun push_op
( op
: Char )
30 last_op
= op
# store for next push_op
32 # prepare next current
37 fun push_digit
( digit
: Int )
40 if current
== null then current
= 0.0
42 var after_point
= after_point
43 if after_point
== null then
44 current
= current
* 10.0 + digit
.to_f
46 current
= current
+ digit
.to_f
* 10.0.pow
(after_point
.to_f
)
50 self.current
= current
53 fun switch_to_decimals
55 if after_point
!= null then return
60 fun apply_last_op_if_any
65 if result
== null then result
= 0.0
68 if current
== null then current
= 0.0
72 else if op
== '+' then
73 result
= result
+ current
74 else if op
== '-' then
75 result
= result
- current
76 else if op
== '/' then
77 result
= result
/ current
78 else if op
== '*' then
79 result
= result
* current
90 var container
: GtkGrid
92 var lbl_disp
: GtkLabel
93 var but_eq
: GtkButton
95 var context
= new CalculatorContext
97 redef fun signal
( sender
, user_data
)
99 if user_data
isa Char then # is an operation
102 context
.switch_to_decimals
105 lbl_disp
.text
= context
.result
.to_s
107 else if user_data
isa Int then # is a number
109 context
.push_digit
( n
)
110 lbl_disp
.text
= context
.current
.to_s
118 win
= new GtkWindow( 0 )
120 container
= new GtkGrid(2,1,true)
123 lbl_disp
= new GtkLabel( "_" )
124 container
.attach
( lbl_disp
, 0, 0, 5, 1 )
128 var but
= new GtkButton.with_label
( n
.to_s
)
129 but
.request_size
( 64, 64 )
130 but
.signal_connect
( "clicked", self, n
)
132 container
.attach
( but
, 0, 4, 1, 1 )
133 else container
.attach
( but
, (n-1
)%3, 3-(n-1
)/3, 1, 1 )
138 for op
in ['+', '-', '*', '/' ] do
139 var but
= new GtkButton.with_label
( op
.to_s
)
140 but
.request_size
( 64, 64 )
141 but
.signal_connect
( "clicked", self, op
)
142 container
.attach
( but
, 4, r
, 1, 1 )
147 but_eq
= new GtkButton.with_label
( "=" )
148 but_eq
.request_size
( 64, 64 )
149 but_eq
.signal_connect
( "clicked", self, '=' )
150 container
.attach
( but_eq
, 5, 3, 1, 2 )
153 var but_dot
= new GtkButton.with_label
( "." )
154 but_dot
.request_size
( 64, 64 )
155 but_dot
.signal_connect
( "clicked", self, '.' )
156 container
.attach
( but_dot
, 1, 4, 1, 1 )
163 var context
= new CalculatorContext
164 context
.push_digit
( 1 )
165 context
.push_digit
( 2 )
166 context
.push_op
( '+' )
167 context
.push_digit
( 3 )
168 context
.push_op
( '*' )
169 context
.push_digit
( 2 )
170 context
.push_op
( '=' )
171 var r
= context
.result
.to_precision
( 2 )
172 assert r
== "30.00" else print r
174 context
= new CalculatorContext
175 context
.push_digit
( 1 )
176 context
.push_digit
( 4 )
177 context
.switch_to_decimals
178 context
.push_digit
( 1 )
179 context
.push_op
( '*' )
180 context
.push_digit
( 3 )
181 context
.push_op
( '=' )
182 r
= context
.result
.to_precision
( 2 )
183 assert r
== "42.30" else print r
185 context
.push_op
( '+' )
186 context
.push_digit
( 1 )
187 context
.push_digit
( 1 )
188 context
.push_op
( '=' )
189 r
= context
.result
.to_precision
( 2 )
190 assert r
== "53.30" else print r
192 context
= new CalculatorContext
193 context
.push_digit
( 4 )
194 context
.push_digit
( 2 )
195 context
.switch_to_decimals
196 context
.push_digit
( 3 )
197 context
.push_op
( '/' )
198 context
.push_digit
( 3 )
199 context
.push_op
( '=' )
200 r
= context
.result
.to_precision
( 2 )
201 assert r
== "14.10" else print r
203 # graphical application
205 if "NIT_TESTING".environ
!= "true" then
206 var app
= new CalculatorGui