32c2f72a09cfd43afdf5750375ebdf41295d2291
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 )
34 last_op
= op
# store for next push_op
37 # prepare next current
42 fun push_digit
( digit
: Int )
45 if current
== null then current
= 0.0
47 var after_point
= after_point
48 if after_point
== null then
49 current
= current
* 10.0 + digit
.to_f
51 current
= current
+ digit
.to_f
* 10.0.pow
(after_point
.to_f
)
55 self.current
= current
58 fun switch_to_decimals
60 if after_point
!= null then return
65 fun apply_last_op_if_any
70 if result
== null then result
= 0.0
73 if current
== null then current
= 0.0
77 else if op
== '+' then
78 result
= result
+ current
79 else if op
== '-' then
80 result
= result
- current
81 else if op
== '/' then
82 result
= result
/ current
83 else if op
== '*' then
84 result
= result
* current
95 var container
: GtkGrid
97 var lbl_disp
: GtkLabel
98 var but_eq
: GtkButton
99 var but_dot
: GtkButton
101 var context
= new CalculatorContext
103 redef fun signal
( sender
, user_data
)
105 var after_point
= context
.after_point
106 if after_point
== null then
109 after_point
= (after_point
.abs
)
112 if user_data
isa Char then # is an operation
115 but_dot
.set_sensitive
= false
116 context
.switch_to_decimals
117 lbl_disp
.text
= "{context.current.to_i}."
119 but_dot
.set_sensitive
= true
122 var s
= context
.result
.to_precision_native
(6)
123 var index
: nullable Int = null
124 for i
in s
.length
.times
do
126 if chiffre
== '0' and index
== null then
128 else if chiffre
!= '0' then
132 if index
!= null then
133 s
= s
.substring
(0, index
)
134 if s
[s
.length-1
] == ',' then s
= s
.substring
(0, s
.length-1
)
138 else if user_data
isa Int then # is a number
140 context
.push_digit
( n
)
141 lbl_disp
.text
= context
.current
.to_precision_native
(after_point
)
149 win
= new GtkWindow( 0 )
151 container
= new GtkGrid(5,5,true)
154 lbl_disp
= new GtkLabel( "_" )
155 container
.attach
( lbl_disp
, 0, 0, 5, 1 )
159 var but
= new GtkButton.with_label
( n
.to_s
)
160 but
.request_size
( 64, 64 )
161 but
.signal_connect
( "clicked", self, n
)
163 container
.attach
( but
, 0, 4, 1, 1 )
164 else container
.attach
( but
, (n-1
)%3, 3-(n-1
)/3, 1, 1 )
169 for op
in ['+', '-', '*', '/' ] do
170 var but
= new GtkButton.with_label
( op
.to_s
)
171 but
.request_size
( 64, 64 )
172 but
.signal_connect
( "clicked", self, op
)
173 container
.attach
( but
, 3, r
, 1, 1 )
178 but_eq
= new GtkButton.with_label
( "=" )
179 but_eq
.request_size
( 64, 64 )
180 but_eq
.signal_connect
( "clicked", self, '=' )
181 container
.attach
( but_eq
, 4, 3, 1, 2 )
184 but_dot
= new GtkButton.with_label
( "." )
185 but_dot
.request_size
( 64, 64 )
186 but_dot
.signal_connect
( "clicked", self, '.' )
187 container
.attach
( but_dot
, 1, 4, 1, 1 )
190 var but_c
= new GtkButton.with_label
( "C" )
191 but_c
.request_size
( 64, 64 )
192 but_c
.signal_connect
("clicked", self, 'C')
193 container
.attach
( but_c
, 2, 4, 1, 1 )
200 var context
= new CalculatorContext
201 context
.push_digit
( 1 )
202 context
.push_digit
( 2 )
203 context
.push_op
( '+' )
204 context
.push_digit
( 3 )
205 context
.push_op
( '*' )
206 context
.push_digit
( 2 )
207 context
.push_op
( '=' )
208 var r
= context
.result
.to_precision
( 2 )
209 assert r
== "30.00" else print r
211 context
= new CalculatorContext
212 context
.push_digit
( 1 )
213 context
.push_digit
( 4 )
214 context
.switch_to_decimals
215 context
.push_digit
( 1 )
216 context
.push_op
( '*' )
217 context
.push_digit
( 3 )
218 context
.push_op
( '=' )
219 r
= context
.result
.to_precision
( 2 )
220 assert r
== "42.30" else print r
222 context
.push_op
( '+' )
223 context
.push_digit
( 1 )
224 context
.push_digit
( 1 )
225 context
.push_op
( '=' )
226 r
= context
.result
.to_precision
( 2 )
227 assert r
== "53.30" else print r
229 context
= new CalculatorContext
230 context
.push_digit
( 4 )
231 context
.push_digit
( 2 )
232 context
.switch_to_decimals
233 context
.push_digit
( 3 )
234 context
.push_op
( '/' )
235 context
.push_digit
( 3 )
236 context
.push_op
( '=' )
237 r
= context
.result
.to_precision
( 2 )
238 assert r
== "14.10" else print r
240 #test multiple decimals
241 context
= new CalculatorContext
242 context
.push_digit
( 5 )
243 context
.push_digit
( 0 )
244 context
.switch_to_decimals
245 context
.push_digit
( 1 )
246 context
.push_digit
( 2 )
247 context
.push_digit
( 3 )
248 context
.push_op
( '+' )
249 context
.push_digit
( 1 )
250 context
.push_op
( '=' )
251 r
= context
.result
.to_precision
( 3 )
252 assert r
== "51.123" else print r
255 context
= new CalculatorContext
256 context
.push_digit
( 1 )
257 context
.push_digit
( 0 )
258 context
.push_op
( '+' )
259 context
.push_digit
( 1 )
260 context
.push_digit
( 0 )
261 context
.push_op
( '=' )
262 context
.push_op
( 'C' )
263 r
= context
.result
.to_precision
( 1 )
264 assert r
== "0.0" else print r
266 # graphical application
268 if "NIT_TESTING".environ
!= "true" then
269 var app
= new CalculatorGui