Updated kn translations
[gcalctool.git] / src / math-buttons.vala
blob102eedfa52eb918c5a93dde6ab9e987636d9fd9b
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 enum ButtonMode
13 BASIC,
14 ADVANCED,
15 FINANCIAL,
16 PROGRAMMING
19 public class MathButtons : Gtk.Box
21 private MathEquation equation;
23 private ButtonMode _mode;
24 public ButtonMode mode
26 get { return _mode; }
27 set
29 if (_mode == value)
30 return;
31 _mode = value;
33 if (mode == ButtonMode.PROGRAMMING)
34 equation.number_base = _programming_base;
35 else
36 equation.number_base = 10;
38 load_buttons ();
40 converter.set_visible (mode == ButtonMode.ADVANCED || mode == ButtonMode.FINANCIAL);
41 if (mode == ButtonMode.ADVANCED)
43 converter.set_category (null);
44 converter.set_conversion (equation.source_units, equation.target_units);
46 else if (mode == ButtonMode.FINANCIAL)
48 converter.set_category ("currency");
49 converter.set_conversion (equation.source_currency, equation.target_currency);
53 private int _programming_base = 10;
55 private MathConverter converter;
57 private Gtk.Builder basic_ui;
58 private Gtk.Builder advanced_ui;
59 private Gtk.Builder financial_ui;
60 private Gtk.Builder programming_ui;
62 private Gtk.Widget bas_panel;
63 private Gtk.Widget adv_panel;
64 private Gtk.Widget fin_panel;
65 private Gtk.Widget prog_panel;
66 private Gtk.Widget? active_panel = null;
68 private Gtk.Menu shift_left_menu;
69 private Gtk.Menu shift_right_menu;
71 private Gtk.Menu function_menu;
73 private List<Gtk.ToggleButton> superscript_toggles;
74 private List<Gtk.ToggleButton> subscript_toggles;
76 private Gtk.ComboBox base_combo;
77 private Gtk.Label base_label;
78 private Gtk.Widget bit_panel;
79 private List<Gtk.Label> bit_labels;
81 private Gtk.Dialog character_code_dialog;
82 private Gtk.Entry character_code_entry;
84 /* The names of each field in the dialogs for the financial functions */
85 private const string[] ctrm_entries = {"ctrm_pint", "ctrm_fv", "ctrm_pv"};
86 private const string[] ddb_entries = {"ddb_cost", "ddb_life", "ddb_period"};
87 private const string[] fv_entries = {"fv_pmt", "fv_pint", "fv_n"};
88 private const string[] gpm_entries = {"gpm_cost", "gpm_margin"};
89 private const string[] pmt_entries = {"pmt_prin", "pmt_pint", "pmt_n"};
90 private const string[] pv_entries = {"pv_pmt", "pv_pint", "pv_n"};
91 private const string[] rate_entries = {"rate_fv", "rate_pv", "rate_n"};
92 private const string[] sln_entries = {"sln_cost", "sln_salvage", "sln_life"};
93 private const string[] syd_entries = {"syd_cost", "syd_salvage", "syd_life"};
94 private const string[] term_entries = {"term_pmt","term_fv", "term_pint"};
96 public MathButtons (MathEquation equation)
98 Object (orientation: Gtk.Orientation.VERTICAL);
99 spacing = 6;
100 show.connect (load_buttons);
101 this.equation = equation;
103 equation.notify["display"].connect ((pspec) => { update_bit_panel (); });
104 equation.notify["number-mode"].connect ((pspec) => { number_mode_changed_cb (); });
105 equation.notify["angle-units"].connect ((pspec) => { update_bit_panel (); });
106 equation.notify["number-format"].connect ((pspec) => { update_bit_panel (); });
107 number_mode_changed_cb ();
108 update_bit_panel ();
111 private void load_finc_dialogs ()
113 load_finc_dialog ("ctrm_dialog", ctrm_entries, FinancialDialog.CTRM_DIALOG);
114 load_finc_dialog ("ddb_dialog", ddb_entries, FinancialDialog.DDB_DIALOG);
115 load_finc_dialog ("fv_dialog", fv_entries, FinancialDialog.FV_DIALOG);
116 load_finc_dialog ("gpm_dialog", gpm_entries, FinancialDialog.GPM_DIALOG);
117 load_finc_dialog ("pmt_dialog", pmt_entries, FinancialDialog.PMT_DIALOG);
118 load_finc_dialog ("pv_dialog", pv_entries, FinancialDialog.PV_DIALOG);
119 load_finc_dialog ("rate_dialog", rate_entries, FinancialDialog.RATE_DIALOG);
120 load_finc_dialog ("sln_dialog", sln_entries, FinancialDialog.SLN_DIALOG);
121 load_finc_dialog ("syd_dialog", syd_entries, FinancialDialog.SYD_DIALOG);
122 load_finc_dialog ("term_dialog", term_entries, FinancialDialog.TERM_DIALOG);
125 private void load_finc_dialog (string name, string[] entry_names, FinancialDialog function)
127 var dialog = financial_ui.get_object (name) as Gtk.Dialog;
128 dialog.set_data<int> ("finc-function", function);
129 dialog.response.connect (finc_response_cb);
130 for (var i = 0; i < entry_names.length; i++)
132 var entry = financial_ui.get_object (entry_names[i]) as Gtk.Entry;
133 if (i != ctrm_entries.length - 1)
134 entry.set_data<Gtk.Entry> ("next-entry", financial_ui.get_object (entry_names[i+1]) as Gtk.Entry);
135 entry.activate.connect (finc_activate_cb);
139 private void update_bit_panel ()
141 if (bit_panel == null)
142 return;
144 var x = equation.number;
146 uint64 bits = 0;
147 var enabled = x != null;
148 if (enabled)
150 var max = new Number.unsigned_integer (uint64.MAX);
151 var fraction = x.fractional_part ();
152 if (x.is_negative () || x.compare (max) > 0 || !fraction.is_zero ())
153 enabled = false;
154 else
155 bits = x.to_unsigned_integer ();
158 bit_panel.set_sensitive (enabled);
159 base_label.set_sensitive (enabled);
161 if (!enabled)
162 return;
164 var i = 0;
165 foreach (var label in bit_labels)
167 var text = " 0";
168 if ((bits & (1LL << i)) != 0)
169 text = " 1";
170 label.set_text (text);
171 i++;
174 var number_base = equation.number_base;
175 var label = "";
176 if (number_base != 8)
177 label += "%llo₈".printf (bits);
178 if (number_base != 10)
180 if (label != "")
181 label += " = ";
182 label += "%llu₁₀".printf (bits);
184 if (number_base != 16)
186 if (label != "")
187 label += " = ";
188 label += "%llX₁₆".printf (bits);
191 base_label.set_text (label);
194 private void base_combobox_changed_cb (Gtk.ComboBox combo)
196 var model = combo.get_model ();
197 Gtk.TreeIter iter;
198 combo.get_active_iter (out iter);
199 int value;
200 model.get (iter, 1, out value, -1);
202 programming_base = value;
205 private void base_changed_cb ()
207 if (mode != ButtonMode.PROGRAMMING)
208 return;
210 _programming_base = equation.number_base;
212 var model = base_combo.get_model ();
213 Gtk.TreeIter iter;
214 var valid = model.get_iter_first (out iter);
215 while (valid)
217 int v;
218 model.get (iter, 1, out v, -1);
219 if (v == programming_base)
220 break;
221 valid = model.iter_next (ref iter);
223 if (!valid)
224 valid = model.get_iter_first (out iter);
226 base_combo.set_active_iter (iter);
229 private Gtk.Widget load_mode (ButtonMode mode)
231 const string objects[] = { "button_panel", "character_code_dialog", "currency_dialog",
232 "ctrm_dialog", "ddb_dialog", "fv_dialog", "gpm_dialog",
233 "pmt_dialog", "pv_dialog", "rate_dialog", "sln_dialog",
234 "syd_dialog", "term_dialog", "adjustment1", "adjustment2", null };
236 Gtk.Builder builder;
237 string builder_filename;
238 switch (mode)
240 default:
241 case ButtonMode.BASIC:
242 if (bas_panel != null)
243 return bas_panel;
244 builder = basic_ui = new Gtk.Builder ();
245 builder_filename = Path.build_filename (UI_DIR, "buttons-basic.ui");
246 break;
247 case ButtonMode.ADVANCED:
248 if (adv_panel != null)
249 return adv_panel;
250 builder = advanced_ui = new Gtk.Builder ();
251 builder_filename = Path.build_filename (UI_DIR, "buttons-advanced.ui");
252 break;
253 case ButtonMode.FINANCIAL:
254 if (fin_panel != null)
255 return fin_panel;
256 builder = financial_ui = new Gtk.Builder ();
257 builder_filename = Path.build_filename (UI_DIR, "buttons-financial.ui");
258 break;
259 case ButtonMode.PROGRAMMING:
260 if (prog_panel != null)
261 return prog_panel;
262 builder = programming_ui = new Gtk.Builder ();
263 builder_filename = Path.build_filename (UI_DIR, "buttons-programming.ui");
264 break;
267 // FIXME: Show dialog if failed to load
270 builder.add_objects_from_file (builder_filename, objects);
272 catch (Error e)
274 warning ("Error loading button UI: %s", e.message);
276 var panel = builder.get_object ("button_panel") as Gtk.Widget;
277 pack_end (panel, true, true, 0);
279 switch (mode)
281 default:
282 case ButtonMode.BASIC:
283 bas_panel = panel;
284 break;
285 case ButtonMode.ADVANCED:
286 adv_panel = panel;
287 break;
288 case ButtonMode.FINANCIAL:
289 fin_panel = panel;
290 break;
291 case ButtonMode.PROGRAMMING:
292 prog_panel = panel;
293 break;
296 /* Configure buttons */
297 /* Tooltip for the Pi button */
298 setup_button (builder, "pi", "π", _("Pi [Ctrl+P]"));
299 /* Tooltip for the Euler's Number button */
300 setup_button (builder, "eulers_number", "e", _("Euler’s Number"));
301 setup_button (builder, "imaginary", "i", null);
302 setup_button (builder, "numeric_point", null, null);
303 /* Tooltip for the subscript button */
304 setup_button (builder, "subscript", null, _("Subscript mode [Alt]"));
305 /* Tooltip for the superscript button */
306 setup_button (builder, "superscript", null, _("Superscript mode [Ctrl]"));
307 /* Tooltip for the scientific exponent button */
308 setup_button (builder, "exponential", null, _("Scientific exponent [Ctrl+E]"));
309 /* Tooltip for the add button */
310 setup_button (builder, "add", "+", _("Add [+]"));
311 /* Tooltip for the subtract button */
312 setup_button (builder, "subtract", "−", _("Subtract [-]"));
313 /* Tooltip for the multiply button */
314 setup_button (builder, "multiply", "×", _("Multiply [*]"));
315 /* Tooltip for the divide button */
316 setup_button (builder, "divide", "÷", _("Divide [/]"));
317 /* Tooltip for the modulus divide button */
318 setup_button (builder, "modulus_divide", " mod ", _("Modulus divide"));
319 /* Tooltip for the additional functions button */
320 setup_button (builder, "function", null, _("Additional Functions"));
321 /* Tooltip for the exponent button */
322 setup_button (builder, "x_pow_y", "^", _("Exponent [^ or **]"));
323 /* Tooltip for the square button */
324 setup_button (builder, "x_squared", "²", _("Square [Ctrl+2]"));
325 /* Tooltip for the percentage button */
326 setup_button (builder, "percentage", "%", _("Percentage [%]"));
327 /* Tooltip for the factorial button */
328 setup_button (builder, "factorial", "!", _("Factorial [!]"));
329 /* Tooltip for the absolute value button */
330 setup_button (builder, "abs", "|", _("Absolute value [|]"));
331 /* Tooltip for the complex argument component button */
332 setup_button (builder, "arg", "Arg ", _("Complex argument"));
333 /* Tooltip for the complex conjugate button */
334 setup_button (builder, "conjugate", "conj ", _("Complex conjugate"));
335 /* Tooltip for the root button */
336 setup_button (builder, "root", "√", _("Root [Ctrl+R]"));
337 /* Tooltip for the square root button */
338 setup_button (builder, "square_root", "√", _("Square root [Ctrl+R]"));
339 /* Tooltip for the logarithm button */
340 setup_button (builder, "logarithm", "log ", _("Logarithm"));
341 /* Tooltip for the natural logarithm button */
342 setup_button (builder, "natural_logarithm", "ln ", _("Natural Logarithm"));
343 /* Tooltip for the sine button */
344 setup_button (builder, "sine", "sin ", _("Sine"));
345 /* Tooltip for the cosine button */
346 setup_button (builder, "cosine", "cos ", _("Cosine"));
347 /* Tooltip for the tangent button */
348 setup_button (builder, "tangent", "tan ", _("Tangent"));
349 /* Tooltip for the hyperbolic sine button */
350 setup_button (builder, "hyperbolic_sine", "sinh ", _("Hyperbolic Sine"));
351 /* Tooltip for the hyperbolic cosine button */
352 setup_button (builder, "hyperbolic_cosine", "cosh ", _("Hyperbolic Cosine"));
353 /* Tooltip for the hyperbolic tangent button */
354 setup_button (builder, "hyperbolic_tangent", "tanh ", _("Hyperbolic Tangent"));
355 /* Tooltip for the inverse button */
356 setup_button (builder, "inverse", "⁻¹", _("Inverse [Ctrl+I]"));
357 /* Tooltip for the boolean AND button */
358 setup_button (builder, "and", "∧", _("Boolean AND"));
359 /* Tooltip for the boolean OR button */
360 setup_button (builder, "or", "∨", _("Boolean OR"));
361 /* Tooltip for the exclusive OR button */
362 setup_button (builder, "xor", "⊻", _("Boolean Exclusive OR"));
363 /* Tooltip for the boolean NOT button */
364 setup_button (builder, "not", "¬", _("Boolean NOT"));
365 /* Tooltip for the integer component button */
366 setup_button (builder, "integer_portion", "int ", _("Integer Component"));
367 /* Tooltip for the fractional component button */
368 setup_button (builder, "fractional_portion", "frac ", _("Fractional Component"));
369 /* Tooltip for the real component button */
370 setup_button (builder, "real_portion", "Re ", _("Real Component"));
371 /* Tooltip for the imaginary component button */
372 setup_button (builder, "imaginary_portion", "Im ", _("Imaginary Component"));
373 /* Tooltip for the ones' complement button */
374 setup_button (builder, "ones_complement", "ones ", _("Ones' Complement"));
375 /* Tooltip for the two's complement button */
376 setup_button (builder, "twos_complement", "twos ", _("Two's Complement"));
377 /* Tooltip for the truncate button */
378 setup_button (builder, "trunc", "trunc ", _("Truncate"));
379 /* Tooltip for the start group button */
380 setup_button (builder, "start_group", "(", _("Start Group [(]"));
381 /* Tooltip for the end group button */
382 setup_button (builder, "end_group", ")", _("End Group [)]"));
383 /* Tooltip for the memory button */
384 setup_button (builder, "memory", null, _("Memory"));
385 /* Tooltip for the insert character code button */
386 setup_button (builder, "character", null, _("Insert Character Code"));
387 /* Tooltip for the solve button */
388 setup_button (builder, "result", null, _("Calculate Result"));
389 /* Tooltip for the factor button */
390 setup_button (builder, "factor", null, _("Factorize [Ctrl+F]"));
391 /* Tooltip for the clear button */
392 setup_button (builder, "clear", null, _("Clear Display [Escape]"));
393 /* Tooltip for the undo button */
394 setup_button (builder, "undo", null, _("Undo [Ctrl+Z]"));
395 /* Tooltip for the shift left button */
396 setup_button (builder, "shift_left", null, _("Shift Left"));
397 /* Tooltip for the shift right button */
398 setup_button (builder, "shift_right", null, _("Shift Right"));
399 /* Tooltip for the compounding term button */
400 setup_button (builder, "finc_compounding_term", null, _("Compounding Term"));
401 /* Tooltip for the double declining depreciation button */
402 setup_button (builder, "finc_double_declining_depreciation", null, _("Double Declining Depreciation"));
403 /* Tooltip for the future value button */
404 setup_button (builder, "finc_future_value", null, _("Future Value"));
405 /* Tooltip for the financial term button */
406 setup_button (builder, "finc_term", null, _("Financial Term"));
407 /* Tooltip for the sum of the years digits depreciation button */
408 setup_button (builder, "finc_sum_of_the_years_digits_depreciation", null, _("Sum of the Years Digits Depreciation"));
409 /* Tooltip for the straight line depreciation button */
410 setup_button (builder, "finc_straight_line_depreciation", null, _("Straight Line Depreciation"));
411 /* Tooltip for the periodic interest rate button */
412 setup_button (builder, "finc_periodic_interest_rate", null, _("Periodic Interest Rate"));
413 /* Tooltip for the present value button */
414 setup_button (builder, "finc_present_value", null, _("Present Value"));
415 /* Tooltip for the periodic payment button */
416 setup_button (builder, "finc_periodic_payment", null, _("Periodic Payment"));
417 /* Tooltip for the gross profit margin button */
418 setup_button (builder, "finc_gross_profit_margin", null, _("Gross Profit Margin"));
420 /* Set special button data */
421 for (var i = 0; i < 16; i++)
423 var name = "calc_%d_button".printf (i);
424 var button = builder.get_object (name) as Gtk.Button;
425 if (button != null)
427 button.set_data<int> ("calc_digit", i);
428 button.set_label (equation.get_digit_text (i).to_string ());
429 button.clicked.connect ((widget) => { equation.insert_digit (widget.get_data<int> ("calc_digit")); });
432 var button = builder.get_object ("calc_subtract_button") as Gtk.Button;
433 if (button != null)
434 button.clicked.connect (() => { equation.insert_subtract (); });
435 button = builder.get_object ("calc_undo_button") as Gtk.Button;
436 if (button != null)
437 button.clicked.connect (() => { equation.undo (); });
438 button = builder.get_object ("calc_result_button") as Gtk.Button;
439 if (button != null)
440 button.clicked.connect (() => { equation.solve (); });
441 button = builder.get_object ("calc_clear_button") as Gtk.Button;
442 if (button != null)
443 button.clicked.connect (() => { equation.clear (); });
444 button = builder.get_object ("calc_memory_button") as Gtk.Button;
445 if (button != null)
446 button.clicked.connect (memory_cb);
447 button = builder.get_object ("calc_function_button") as Gtk.Button;
448 if (button != null)
449 button.clicked.connect (function_cb);
450 button = builder.get_object ("calc_factor_button") as Gtk.Button;
451 if (button != null)
452 button.clicked.connect (() => { equation.factorize (); });
453 button = builder.get_object ("calc_exponential_button") as Gtk.Button;
454 if (button != null)
455 button.clicked.connect (() => { equation.insert_exponent (); });
456 button = builder.get_object ("calc_shift_left_button") as Gtk.Button;
457 if (button != null)
458 button.clicked.connect (shift_left_cb);
459 button = builder.get_object ("calc_shift_right_button") as Gtk.Button;
460 if (button != null)
461 button.clicked.connect (shift_right_cb);
462 button = builder.get_object ("calc_character_button") as Gtk.Button;
463 if (button != null)
464 button.clicked.connect (insert_character_code_cb);
465 button = builder.get_object ("calc_numeric_point_button") as Gtk.Button;
466 if (button != null)
468 button.set_label (equation.serializer.get_radix ().to_string ());
469 button.clicked.connect (() => { equation.insert_numeric_point (); });
472 var toggle_button = builder.get_object ("calc_superscript_button") as Gtk.ToggleButton;
473 if (toggle_button != null)
475 superscript_toggles.append (toggle_button);
476 if (equation.number_mode == NumberMode.SUPERSCRIPT)
477 toggle_button.set_active (true);
478 toggle_button.clicked.connect (set_superscript_cb);
480 toggle_button = builder.get_object ("calc_subscript_button") as Gtk.ToggleButton;
481 if (toggle_button != null)
483 subscript_toggles.append (toggle_button);
484 if (equation.number_mode == NumberMode.SUBSCRIPT)
485 toggle_button.set_active (true);
486 toggle_button.clicked.connect (set_subscript_cb);
489 if (mode == ButtonMode.PROGRAMMING)
491 base_label = builder.get_object ("base_label") as Gtk.Label;
492 character_code_dialog = builder.get_object ("character_code_dialog") as Gtk.Dialog;
493 character_code_dialog.response.connect (character_code_dialog_response_cb);
494 character_code_dialog.delete_event.connect (character_code_dialog_delete_cb);
495 character_code_entry = builder.get_object ("character_code_entry") as Gtk.Entry;
496 character_code_entry.activate.connect (character_code_dialog_activate_cb);
498 bit_panel = builder.get_object ("bit_table") as Gtk.Widget;
499 bit_labels = new List<Gtk.Label> ();
500 var i = 0;
501 while (true)
503 var name = "bit_label_%d".printf (i);
504 var label = builder.get_object (name) as Gtk.Label;
505 if (label == null)
506 break;
507 bit_labels.append (label);
508 name = "bit_eventbox_%d".printf (i);
509 var box = builder.get_object (name) as Gtk.EventBox;
510 box.set_data<int> ("bit_index", i);
511 box.button_press_event.connect (bit_toggle_cb);
512 i++;
514 bit_labels.reverse ();
516 base_combo = builder.get_object ("base_combo") as Gtk.ComboBox;
517 var model = new Gtk.ListStore (2, typeof (string), typeof (int));
518 base_combo.model = model;
519 Gtk.TreeIter iter;
520 model.append (out iter);
521 model.set (iter, 0,
522 /* Number display mode combo: Binary, e.g. 10011010010₂ */
523 _("Binary"), 1, 2, -1);
524 model.append (out iter);
525 model.set (iter, 0,
526 /* Number display mode combo: Octal, e.g. 2322₈ */
527 _("Octal"), 1, 8, -1);
528 model.append (out iter);
529 model.set (iter, 0,
530 /* Number display mode combo: Decimal, e.g. 1234 */
531 _("Decimal"), 1, 10, -1);
532 model.append (out iter);
533 model.set (iter, 0,
534 /* Number display mode combo: Hexadecimal, e.g. 4D2₁₆ */
535 _("Hexadecimal"), 1, 16, -1);
536 var renderer = new Gtk.CellRendererText ();
537 base_combo.pack_start (renderer, true);
538 base_combo.add_attribute (renderer, "text", 0);
540 base_combo.changed.connect (base_combobox_changed_cb);
541 equation.notify["number-base"].connect ((pspec) => { base_changed_cb (); } );
542 base_changed_cb ();
545 /* Setup financial functions */
546 if (mode == ButtonMode.FINANCIAL)
548 load_finc_dialogs ();
550 button = builder.get_object ("calc_finc_compounding_term_button") as Gtk.Button;
551 if (button != null)
553 button.set_data<string> ("finc-dialog-name", "ctrm_dialog");
554 button.clicked.connect (finc_cb);
556 button = builder.get_object ("calc_finc_double_declining_depreciation_button") as Gtk.Button;
557 if (button != null)
559 button.set_data<string> ("finc-dialog-name", "ddb_dialog");
560 button.clicked.connect (finc_cb);
562 button = builder.get_object ("calc_finc_future_value_button") as Gtk.Button;
563 if (button != null)
565 button.set_data<string> ("finc-dialog-name", "fv_dialog");
566 button.clicked.connect (finc_cb);
568 button = builder.get_object ("calc_finc_gross_profit_margin_button") as Gtk.Button;
569 if (button != null)
571 button.set_data<string> ("finc-dialog-name", "gpm_dialog");
572 button.clicked.connect (finc_cb);
574 button = builder.get_object ("calc_finc_periodic_payment_button") as Gtk.Button;
575 if (button != null)
577 button.set_data<string> ("finc-dialog-name", "pmt_dialog");
578 button.clicked.connect (finc_cb);
580 button = builder.get_object ("calc_finc_present_value_button") as Gtk.Button;
581 if (button != null)
583 button.set_data<string> ("finc-dialog-name", "pv_dialog");
584 button.clicked.connect (finc_cb);
586 button = builder.get_object ("calc_finc_periodic_interest_rate_button") as Gtk.Button;
587 if (button != null)
589 button.set_data<string> ("finc-dialog-name", "rate_dialog");
590 button.clicked.connect (finc_cb);
592 button = builder.get_object ("calc_finc_straight_line_depreciation_button") as Gtk.Button;
593 if (button != null)
595 button.set_data<string> ("finc-dialog-name", "sln_dialog");
596 button.clicked.connect (finc_cb);
598 button = builder.get_object ("calc_finc_sum_of_the_years_digits_depreciation_button") as Gtk.Button;
599 if (button != null)
601 button.set_data<string> ("finc-dialog-name", "syd_dialog");
602 button.clicked.connect (finc_cb);
604 button = builder.get_object ("calc_finc_term_button") as Gtk.Button;
605 if (button != null)
607 button.set_data<string> ("finc-dialog-name", "term_dialog");
608 button.clicked.connect (finc_cb);
612 builder.connect_signals (this);
614 update_bit_panel ();
616 return panel;
619 private void setup_button (Gtk.Builder builder, string name, string? data, string? tooltip)
621 var widget_name = "calc_%s_button".printf (name);
622 var button = builder.get_object (widget_name) as Gtk.Button;
623 if (button == null)
624 return;
626 if (data != null)
628 button.set_data<string> ("calc_text", data);
629 button.clicked.connect ((widget) => { equation.insert (widget.get_data<string> ("calc_text")); });
632 if (tooltip != null)
633 button.set_tooltip_text (tooltip);
635 button.get_accessible ().set_name (name);
638 private void converter_changed_cb ()
640 Unit from_unit, to_unit;
641 converter.get_conversion (out from_unit, out to_unit);
642 if (mode == ButtonMode.FINANCIAL)
644 equation.source_currency = from_unit.name;
645 equation.target_currency = to_unit.name;
647 else
649 equation.source_units = from_unit.name;
650 equation.target_units = to_unit.name;
654 private void load_buttons ()
656 if (!get_visible ())
657 return;
659 if (converter == null)
661 converter = new MathConverter (equation);
662 converter.changed.connect (converter_changed_cb);
663 pack_start (converter, false, true, 0);
666 var panel = load_mode (mode);
667 if (active_panel == panel)
668 return;
670 /* Hide old buttons */
671 if (active_panel != null)
672 active_panel.hide ();
674 /* Load and display new buttons */
675 active_panel = panel;
676 if (panel != null)
677 panel.show ();
680 public int programming_base
682 get { return _programming_base; }
685 if (_programming_base == value)
686 return;
688 _programming_base = value;
689 notify_property ("programming-base");
691 if (mode == ButtonMode.PROGRAMMING)
692 equation.number_base = value;
696 private void popup_button_menu (Gtk.Button button, Gtk.Menu menu)
698 menu.set_data<Gtk.Widget> ("button", button);
699 menu.popup (null, null, button_menu_position_func, 1, Gtk.get_current_event_time ());
702 private void button_menu_position_func (Gtk.Menu menu, out int x, out int y, out bool push_in)
704 var button = menu.get_data<Gtk.Button> ("button");
705 int origin_x, origin_y;
706 button.get_window ().get_origin (out origin_x, out origin_y);
707 var border = button.get_border_width ();
708 Gtk.Allocation allocation;
709 button.get_allocation (out allocation);
710 x = (int) (origin_x + allocation.x + border);
711 y = (int) (origin_y + allocation.y + border);
714 private void memory_cb (Gtk.Widget widget)
716 var popup = new MathVariablePopup (equation);
717 popup.set_transient_for (widget.get_toplevel () as Gtk.Window);
719 Gtk.Allocation allocation;
720 widget.get_allocation (out allocation);
721 int x, y;
722 widget.get_window ().get_root_coords (allocation.x, allocation.y, out x, out y);
723 popup.move (x, y);
724 popup.show ();
727 private void shift_left_cb (Gtk.Button button)
729 if (shift_left_menu == null)
731 shift_left_menu = new Gtk.Menu ();
732 shift_left_menu.set_reserve_toggle_size (false);
734 for (var i = 1; i < 16; i++)
736 string format;
737 if (i < 10)
739 /* Left Shift Popup: Menu item to shift left by n places (n < 10) */
740 format = ngettext ("_%d place", "_%d places", i);
742 else
744 /* Left Shift Popup: Menu item to shift left by n places (n >= 10) */
745 format = ngettext ("%d place", "%d places", i);
747 var text = format.printf (i);
748 var label = new Gtk.Label.with_mnemonic (text);
750 var item = new Gtk.MenuItem ();
751 item.set_data<int> ("shiftcount", i);
752 item.add (label);
753 shift_left_menu.append (item);
754 item.activate.connect ((widget) => { equation.shift (widget.get_data<int> ("shiftcount")); });
756 label.show ();
757 item.show ();
761 popup_button_menu (button, shift_left_menu);
764 private void shift_right_cb (Gtk.Button button)
766 if (shift_right_menu == null)
768 shift_right_menu = new Gtk.Menu ();
769 shift_right_menu.set_reserve_toggle_size (false);
771 for (var i = 1; i < 16; i++)
773 string format;
774 if (i < 10)
776 /* Right Shift Popup: Menu item to shift right by n places (n < 10) */
777 format = ngettext ("_%d place", "_%d places", i);
779 else
781 /* Right Shift Popup: Menu item to shift right by n places (n >= 10) */
782 format = ngettext ("%d place", "%d places", i);
784 var text = format.printf (i);
785 var label = new Gtk.Label.with_mnemonic (text);
787 var item = new Gtk.MenuItem ();
788 item.set_data<int> ("shiftcount", -i);
789 item.add (label);
790 shift_right_menu.append (item);
791 item.activate.connect ((widget) => { equation.shift (widget.get_data<int> ("shiftcount")); });
793 label.show ();
794 item.show ();
798 popup_button_menu (button, shift_right_menu);
801 private void function_cb (Gtk.Button button)
803 if (function_menu == null)
805 function_menu = new Gtk.Menu ();
806 function_menu.set_reserve_toggle_size (false);
808 /* Tooltip for the integer component button */
809 add_function_menu_item (function_menu, _("Integer Component"), "int ");
810 /* Tooltip for the fractional component button */
811 add_function_menu_item (function_menu, _("Fractional Component"), "frac ");
812 /* Tooltip for the round button */
813 add_function_menu_item (function_menu, _("Round"), "round ");
814 /* Tooltip for the floor button */
815 add_function_menu_item (function_menu, _("Floor"), "floor ");
816 /* Tooltip for the ceiling button */
817 add_function_menu_item (function_menu, _("Ceiling"), "ceil ");
818 /* Tooltip for the ceiling button */
819 add_function_menu_item (function_menu, _("Sign"), "sgn ");
822 popup_button_menu (button, function_menu);
825 private void add_function_menu_item (Gtk.Menu menu, string label, string function)
827 var item = new Gtk.MenuItem.with_label (label);
828 item.set_data<string> ("function", function);
829 menu.append (item);
830 item.activate.connect ((widget) => { equation.insert (widget.get_data<string> ("function")); });
831 item.show ();
834 private void finc_cb (Gtk.Widget widget)
836 var name = widget.get_data<string> ("finc-dialog-name");
837 var dialog = financial_ui.get_object (name) as Gtk.Dialog;
838 dialog.run ();
839 dialog.hide ();
842 private void insert_character_code_cb (Gtk.Widget widget)
844 character_code_dialog.present ();
847 private void finc_activate_cb (Gtk.Widget widget)
849 var next_entry = widget.get_data<Gtk.Entry> ("next-entry");
850 if (next_entry == null)
852 var dialog = widget.get_toplevel () as Gtk.Dialog;
853 if (dialog.is_toplevel ())
855 dialog.response (Gtk.ResponseType.OK);
856 return;
859 else
860 next_entry.grab_focus ();
863 private void finc_response_cb (Gtk.Widget widget, int response_id)
865 if (response_id != Gtk.ResponseType.OK)
866 return;
868 var function = (FinancialDialog) widget.get_data<int> ("finc-function");
869 var entries = new string[0];
870 switch (function)
872 case FinancialDialog.CTRM_DIALOG:
873 entries = ctrm_entries;
874 break;
875 case FinancialDialog.DDB_DIALOG:
876 entries = ddb_entries;
877 break;
878 case FinancialDialog.FV_DIALOG:
879 entries = fv_entries;
880 break;
881 case FinancialDialog.GPM_DIALOG:
882 entries = gpm_entries;
883 break;
884 case FinancialDialog.PMT_DIALOG:
885 entries = pmt_entries;
886 break;
887 case FinancialDialog.PV_DIALOG:
888 entries = pv_entries;
889 break;
890 case FinancialDialog.RATE_DIALOG:
891 entries = rate_entries;
892 break;
893 case FinancialDialog.SLN_DIALOG:
894 entries = sln_entries;
895 break;
896 case FinancialDialog.SYD_DIALOG:
897 entries = syd_entries;
898 break;
899 case FinancialDialog.TERM_DIALOG:
900 entries = term_entries;
901 break;
904 Number arg[4] = { new Number.integer (0), new Number.integer (0), new Number.integer (0), new Number.integer (0) };
905 for (var i = 0; i < entries.length; i++)
907 var entry = financial_ui.get_object (entries[i]) as Gtk.Entry;
908 arg[i] = mp_set_from_string (entry.get_text ());
909 entry.set_text ("0");
911 var first_entry = financial_ui.get_object (entries[0]) as Gtk.Entry;
912 first_entry.grab_focus ();
914 do_finc_expression (equation, function, arg[0], arg[1], arg[2], arg[3]);
917 private void character_code_dialog_response_cb (Gtk.Widget dialog, int response_id)
919 var text = character_code_entry.get_text ();
921 if (response_id == Gtk.ResponseType.OK)
923 var x = new Number.integer (0);
924 for (var i = 0; text[i] != '\0'; i++)
926 x = x.add (new Number.integer (text[i]));
927 x = x.shift (8);
930 equation.insert_number (x);
933 dialog.hide ();
936 private void character_code_dialog_activate_cb (Gtk.Widget entry)
938 character_code_dialog_response_cb (character_code_dialog, Gtk.ResponseType.OK);
941 private bool character_code_dialog_delete_cb (Gtk.Widget dialog, Gdk.EventAny event)
943 character_code_dialog_response_cb (dialog, Gtk.ResponseType.CANCEL);
944 return true;
947 private bool bit_toggle_cb (Gtk.Widget event_box, Gdk.EventButton event)
949 equation.toggle_bit (event_box.get_data<int> ("bit_index"));
950 return true;
953 private void remove_trailing_spaces ()
955 var insert_mark = equation.get_insert ();
956 Gtk.TextIter start, end;
957 equation.get_iter_at_mark (out end, insert_mark);
958 start = end;
959 while (start.backward_char ())
961 if (!start.get_char ().isspace ())
962 break;
963 equation.delete (ref start, ref end);
967 private void set_superscript_cb (Gtk.Button widget)
969 var button = widget as Gtk.ToggleButton;
971 if (button.get_active ())
973 equation.number_mode = NumberMode.SUPERSCRIPT;
974 if (!equation.has_selection)
975 remove_trailing_spaces ();
977 else if (equation.number_mode == NumberMode.SUPERSCRIPT)
978 equation.number_mode = NumberMode.NORMAL;
981 private void set_subscript_cb (Gtk.Button widget)
983 var button = widget as Gtk.ToggleButton;
985 if (button.get_active ())
987 equation.number_mode = NumberMode.SUBSCRIPT;
988 if (!equation.has_selection)
989 remove_trailing_spaces ();
991 else if (equation.number_mode == NumberMode.SUBSCRIPT)
992 equation.number_mode = NumberMode.NORMAL;
995 private void number_mode_changed_cb ()
997 var mode = equation.number_mode;
998 foreach (var toggle in superscript_toggles)
999 toggle.set_active (mode == NumberMode.SUPERSCRIPT);
1000 foreach (var toggle in subscript_toggles)
1001 toggle.set_active (mode == NumberMode.SUBSCRIPT);