nitdoc: load js libs from require.js
[nit.git] / examples / calculator.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 import gtk
18
19 class CalculatorContext
20 var result : nullable Float = null
21
22 var last_op : nullable Char = null
23
24 var current : nullable Float = null
25 var after_point : nullable Int = null
26
27 fun push_op( op : Char )
28 do
29 apply_last_op_if_any
30 last_op = op # store for next push_op
31
32 # prepare next current
33 after_point = null
34 current = null
35 end
36
37 fun push_digit( digit : Int )
38 do
39 var current = current
40 if current == null then current = 0.0
41
42 var after_point = after_point
43 if after_point == null then
44 current = current * 10.0 + digit.to_f
45 else
46 current = current + digit.to_f * 10.0.pow(after_point.to_f)
47 after_point -= 1
48 end
49
50 self.current = current
51 end
52
53 fun switch_to_decimals
54 do
55 if after_point != null then return
56
57 after_point = -1
58 end
59
60 fun apply_last_op_if_any
61 do
62 var op = last_op
63
64 var result = result
65 if result == null then result = 0.0
66
67 var current = current
68 if current == null then current = 0.0
69
70 if op == null then
71 result = current
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
80 end
81 self.result = result
82 self.current = null
83 end
84 end
85
86 class CalculatorGui
87 super GtkCallable
88
89 var win : GtkWindow
90 var container : GtkGrid
91
92 var lbl_disp : GtkLabel
93 var but_eq : GtkButton
94
95 var context = new CalculatorContext
96
97 redef fun signal( sender, user_data )
98 do
99 if user_data isa Char then # is an operation
100 var c = user_data
101 if c == '.' then
102 context.switch_to_decimals
103 else
104 context.push_op( c )
105 lbl_disp.text = context.result.to_s
106 end
107 else if user_data isa Int then # is a number
108 var n = user_data
109 context.push_digit( n )
110 lbl_disp.text = context.current.to_s
111 end
112 end
113
114 init
115 do
116 init_gtk
117
118 win = new GtkWindow( 0 )
119
120 container = new GtkGrid(2,1,true)
121 win.add( container )
122
123 lbl_disp = new GtkLabel( "_" )
124 container.attach( lbl_disp, 0, 0, 5, 1 )
125
126 # digits
127 for n in [0..9] do
128 var but = new GtkButton.with_label( n.to_s )
129 but.request_size( 64, 64 )
130 but.signal_connect( "clicked", self, n )
131 if n == 0 then
132 container.attach( but, 0, 4, 1, 1 )
133 else container.attach( but, (n-1)%3, 3-(n-1)/3, 1, 1 )
134 end
135
136 # operators
137 var r = 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 )
143 r+=1
144 end
145
146 # =
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 )
151
152 # .
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 )
157
158 win.show_all
159 end
160 end
161
162 # context tests
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
173
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
184
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
191
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
202
203 # graphical application
204
205 if "NIT_TESTING".environ != "true" then
206 var app = new CalculatorGui
207 run_gtk
208 end