Updated kn translations
[gcalctool.git] / src / math-display.vala
bloba466f26336c289e28c742e517da89def60856fab
1 /*
2 * Copyright (C) 2008-2012 Robert Ancell
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free Software
6 * Foundation, either version 2 of the License, or (at your option) any later
7 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
8 * license.
9 */
11 public class MathDisplay : Gtk.Viewport
13 /* Equation being displayed */
14 private MathEquation _equation;
15 public MathEquation equation { get { return _equation; } }
17 /* Display widget */
18 Gtk.TextView text_view;
20 /* Buffer that shows errors etc */
21 Gtk.TextBuffer info_buffer;
23 /* Spinner widget that shows if we're calculating a response */
24 Gtk.Spinner spinner;
26 public MathDisplay (MathEquation equation)
28 _equation = equation;
30 var main_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
31 add (main_box);
33 text_view = new Gtk.TextView.with_buffer (equation);
34 text_view.set_wrap_mode (Gtk.WrapMode.WORD);
35 text_view.set_accepts_tab (false);
36 text_view.set_pixels_above_lines (8);
37 text_view.set_pixels_below_lines (2);
38 /* TEMP: Disabled for now as GTK+ doesn't properly render a right aligned right margin, see bug #482688 */
39 /*text_view.set_right_margin (6);*/
40 text_view.set_justification (Gtk.Justification.RIGHT);
41 text_view.ensure_style ();
42 var font_desc = text_view.get_style ().font_desc.copy ();
43 font_desc.set_size (16 * Pango.SCALE);
44 text_view.modify_font (font_desc);
45 text_view.set_name ("displayitem");
46 text_view.get_accessible ().set_role (Atk.Role.EDITBAR);
47 //FIXME:<property name="AtkObject::accessible-description" translatable="yes" comments="Accessible description for the area in which results are displayed">Result Region</property>
48 text_view.key_press_event.connect (key_press_cb);
50 main_box.pack_start (text_view, true, true, 0);
52 var info_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6);
53 main_box.pack_start (info_box, false, true, 0);
55 var info_view = new Gtk.TextView ();
56 info_view.set_wrap_mode (Gtk.WrapMode.WORD);
57 info_view.set_can_focus (true); // FIXME: This should be false but it locks the cursor inside the main view for some reason
58 info_view.set_cursor_visible (false); // FIXME: Just here so when incorrectly gets focus doesn't look editable
59 info_view.set_editable (false);
60 info_view.set_justification (Gtk.Justification.RIGHT);
61 /* TEMP: Disabled for now as GTK+ doesn't properly render a right aligned right margin, see bug #482688 */
62 /*info_view.set_right_margin (6);*/
63 info_box.pack_start (info_view, true, true, 0);
64 info_buffer = info_view.get_buffer ();
66 spinner = new Gtk.Spinner ();
67 info_box.pack_end (spinner, false, false, 0);
68 style = info_view.get_style ();
69 for (var i = 0; i < 5; i++)
70 modify_bg (i, style.base[i]);
72 info_box.show ();
73 info_view.show ();
74 text_view.show ();
75 main_box.show ();
77 equation.notify["status"].connect ((pspec) => { status_changed_cb (); });
78 status_changed_cb ();
80 equation.notify["error-token-end"].connect ((pspec) => { error_status_changed_cb (); });
83 protected override bool key_press_event (Gdk.EventKey event)
85 return text_view.key_press_event (event);
88 private bool key_press_cb (Gdk.EventKey event)
90 /* Treat keypad keys as numbers even when numlock is off */
91 uint new_keyval = 0;
92 switch (event.keyval)
94 case Gdk.Key.KP_Insert:
95 new_keyval = Gdk.Key.@0;
96 break;
97 case Gdk.Key.KP_End:
98 new_keyval = Gdk.Key.@1;
99 break;
100 case Gdk.Key.KP_Down:
101 new_keyval = Gdk.Key.@2;
102 break;
103 case Gdk.Key.KP_Page_Down:
104 new_keyval = Gdk.Key.@3;
105 break;
106 case Gdk.Key.KP_Left:
107 new_keyval = Gdk.Key.@4;
108 break;
109 case Gdk.Key.KP_Begin: /* This is apparently what "5" does when numlock is off. */
110 new_keyval = Gdk.Key.@5;
111 break;
112 case Gdk.Key.KP_Right:
113 new_keyval = Gdk.Key.@6;
114 break;
115 case Gdk.Key.KP_Home:
116 new_keyval = Gdk.Key.@7;
117 break;
118 case Gdk.Key.KP_Up:
119 new_keyval = Gdk.Key.@8;
120 break;
121 case Gdk.Key.KP_Page_Up:
122 new_keyval = Gdk.Key.@9;
123 break;
126 if (new_keyval != 0)
128 var new_event = event; // FIXME: Does this copy?
129 new_event.keyval = new_keyval;
130 return key_press_event (new_event);
133 var state = event.state & (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK);
134 var c = Gdk.keyval_to_unicode (event.keyval);
136 /* Solve on enter */
137 if (event.keyval == Gdk.Key.Return || event.keyval == Gdk.Key.KP_Enter)
139 equation.solve ();
140 return true;
143 /* Clear on escape */
144 if ((event.keyval == Gdk.Key.Escape && state == 0) ||
145 (event.keyval == Gdk.Key.BackSpace && state == Gdk.ModifierType.CONTROL_MASK) ||
146 (event.keyval == Gdk.Key.Delete && state == Gdk.ModifierType.SHIFT_MASK))
148 equation.clear ();
149 return true;
152 /* Numeric keypad will often insert '.' regardless of locale */
153 if (event.keyval == Gdk.Key.KP_Decimal)
155 equation.insert_numeric_point ();
156 return true;
159 /* Substitute */
160 if (state == 0)
162 if (c == '*')
164 equation.insert ("×");
165 return true;
167 if (c == '/')
169 equation.insert ("÷");
170 return true;
172 if (c == '-')
174 equation.insert_subtract ();
175 return true;
179 /* Shortcuts */
180 if (state == Gdk.ModifierType.CONTROL_MASK)
182 switch (event.keyval)
184 case Gdk.Key.bracketleft:
185 equation.insert ("⌈");
186 return true;
187 case Gdk.Key.bracketright:
188 equation.insert ("⌉");
189 return true;
190 case Gdk.Key.e:
191 equation.insert_exponent ();
192 return true;
193 case Gdk.Key.f:
194 equation.factorize ();
195 return true;
196 case Gdk.Key.i:
197 equation.insert ("⁻¹");
198 return true;
199 case Gdk.Key.p:
200 equation.insert ("π");
201 return true;
202 case Gdk.Key.r:
203 equation.insert ("√");
204 return true;
205 case Gdk.Key.u:
206 equation.insert ("µ");
207 return true;
208 case Gdk.Key.minus:
209 equation.insert ("⁻");
210 return true;
211 case Gdk.Key.apostrophe:
212 equation.insert ("°");
213 return true;
216 if (state == Gdk.ModifierType.MOD1_MASK)
218 switch (event.keyval)
220 case Gdk.Key.bracketleft:
221 equation.insert ("⌊");
222 return true;
223 case Gdk.Key.bracketright:
224 equation.insert ("⌋");
225 return true;
229 if (state == Gdk.ModifierType.CONTROL_MASK || equation.number_mode == NumberMode.SUPERSCRIPT)
231 switch (event.keyval)
233 case Gdk.Key.@0:
234 case Gdk.Key.KP_0:
235 equation.insert ("⁰");
236 return true;
237 case Gdk.Key.@1:
238 case Gdk.Key.KP_1:
239 equation.insert ("¹");
240 return true;
241 case Gdk.Key.@2:
242 case Gdk.Key.KP_2:
243 equation.insert ("²");
244 return true;
245 case Gdk.Key.@3:
246 case Gdk.Key.KP_3:
247 equation.insert ("³");
248 return true;
249 case Gdk.Key.@4:
250 case Gdk.Key.KP_4:
251 equation.insert ("⁴");
252 return true;
253 case Gdk.Key.@5:
254 case Gdk.Key.KP_5:
255 equation.insert ("⁵");
256 return true;
257 case Gdk.Key.@6:
258 case Gdk.Key.KP_6:
259 equation.insert ("⁶");
260 return true;
261 case Gdk.Key.@7:
262 case Gdk.Key.KP_7:
263 equation.insert ("⁷");
264 return true;
265 case Gdk.Key.@8:
266 case Gdk.Key.KP_8:
267 equation.insert ("⁸");
268 return true;
269 case Gdk.Key.@9:
270 case Gdk.Key.KP_9:
271 equation.insert ("⁹");
272 return true;
275 else if (state == Gdk.ModifierType.MOD1_MASK || equation.number_mode == NumberMode.SUBSCRIPT)
277 switch (event.keyval)
279 case Gdk.Key.@0:
280 case Gdk.Key.KP_0:
281 equation.insert ("₀");
282 return true;
283 case Gdk.Key.@1:
284 case Gdk.Key.KP_1:
285 equation.insert ("₁");
286 return true;
287 case Gdk.Key.@2:
288 case Gdk.Key.KP_2:
289 equation.insert ("₂");
290 return true;
291 case Gdk.Key.@3:
292 case Gdk.Key.KP_3:
293 equation.insert ("₃");
294 return true;
295 case Gdk.Key.@4:
296 case Gdk.Key.KP_4:
297 equation.insert ("₄");
298 return true;
299 case Gdk.Key.@5:
300 case Gdk.Key.KP_5:
301 equation.insert ("₅");
302 return true;
303 case Gdk.Key.@6:
304 case Gdk.Key.KP_6:
305 equation.insert ("₆");
306 return true;
307 case Gdk.Key.@7:
308 case Gdk.Key.KP_7:
309 equation.insert ("₇");
310 return true;
311 case Gdk.Key.@8:
312 case Gdk.Key.KP_8:
313 equation.insert ("₈");
314 return true;
315 case Gdk.Key.@9:
316 case Gdk.Key.KP_9:
317 equation.insert ("₉");
318 return true;
322 return false;
325 private void status_changed_cb ()
327 info_buffer.set_text (equation.status, -1);
328 if (equation.in_solve && !spinner.get_visible ())
330 spinner.show ();
331 spinner.start ();
333 else if (!equation.in_solve && spinner.get_visible ())
335 spinner.hide ();
336 spinner.stop ();
340 private void error_status_changed_cb ()
342 /* If both start and end location of error token are the same, no need to select anything. */
343 if (equation.error_token_end - equation.error_token_start == 0)
344 return;
346 Gtk.TextIter start, end;
347 equation.get_start_iter (out start);
348 equation.get_start_iter (out end);
350 start.set_offset ((int) equation.error_token_start);
351 end.set_offset ((int) equation.error_token_end);
353 equation.select_range (start, end);