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
11 public enum ButtonMode
19 public class MathButtons
: Gtk
.Box
21 private MathEquation equation
;
23 private ButtonMode _mode
;
24 public ButtonMode mode
33 if (mode
== ButtonMode
.PROGRAMMING
)
34 equation
.number_base
= _programming_base
;
36 equation
.number_base
= 10;
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
);
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 ();
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)
144 var x
= equation
.number
;
147 var enabled
= x
!= null;
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 ())
155 bits
= x
.to_unsigned_integer ();
158 bit_panel
.set_sensitive (enabled
);
159 base_label
.set_sensitive (enabled
);
165 foreach (var label
in bit_labels
)
168 if ((bits
& (1LL << i
)) != 0)
170 label
.set_text (text
);
174 var number_base
= equation
.number_base
;
176 if (number_base
!= 8)
177 label
+= "%llo₈".printf (bits
);
178 if (number_base
!= 10)
182 label
+= "%llu₁₀".printf (bits
);
184 if (number_base
!= 16)
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 ();
198 combo
.get_active_iter (out iter
);
200 model
.get (iter
, 1, out value
, -1);
202 programming_base
= value
;
205 private void base_changed_cb ()
207 if (mode
!= ButtonMode
.PROGRAMMING
)
210 _programming_base
= equation
.number_base
;
212 var model
= base_combo
.get_model ();
214 var valid
= model
.get_iter_first (out iter
);
218 model
.get (iter
, 1, out v
, -1);
219 if (v
== programming_base
)
221 valid
= model
.iter_next (ref iter
);
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 };
237 string builder_filename
;
241 case ButtonMode
.BASIC
:
242 if (bas_panel
!= null)
244 builder
= basic_ui
= new Gtk
.Builder ();
245 builder_filename
= Path
.build_filename (UI_DIR
, "buttons-basic.ui");
247 case ButtonMode
.ADVANCED
:
248 if (adv_panel
!= null)
250 builder
= advanced_ui
= new Gtk
.Builder ();
251 builder_filename
= Path
.build_filename (UI_DIR
, "buttons-advanced.ui");
253 case ButtonMode
.FINANCIAL
:
254 if (fin_panel
!= null)
256 builder
= financial_ui
= new Gtk
.Builder ();
257 builder_filename
= Path
.build_filename (UI_DIR
, "buttons-financial.ui");
259 case ButtonMode
.PROGRAMMING
:
260 if (prog_panel
!= null)
262 builder
= programming_ui
= new Gtk
.Builder ();
263 builder_filename
= Path
.build_filename (UI_DIR
, "buttons-programming.ui");
267 // FIXME: Show dialog if failed to load
270 builder
.add_objects_from_file (builder_filename
, objects
);
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);
282 case ButtonMode
.BASIC
:
285 case ButtonMode
.ADVANCED
:
288 case ButtonMode
.FINANCIAL
:
291 case ButtonMode
.PROGRAMMING
:
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
;
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
;
434 button
.clicked
.connect (() => { equation
.insert_subtract (); });
435 button
= builder
.get_object ("calc_undo_button") as Gtk
.Button
;
437 button
.clicked
.connect (() => { equation
.undo (); });
438 button
= builder
.get_object ("calc_result_button") as Gtk
.Button
;
440 button
.clicked
.connect (() => { equation
.solve (); });
441 button
= builder
.get_object ("calc_clear_button") as Gtk
.Button
;
443 button
.clicked
.connect (() => { equation
.clear (); });
444 button
= builder
.get_object ("calc_memory_button") as Gtk
.Button
;
446 button
.clicked
.connect (memory_cb
);
447 button
= builder
.get_object ("calc_function_button") as Gtk
.Button
;
449 button
.clicked
.connect (function_cb
);
450 button
= builder
.get_object ("calc_factor_button") as Gtk
.Button
;
452 button
.clicked
.connect (() => { equation
.factorize (); });
453 button
= builder
.get_object ("calc_exponential_button") as Gtk
.Button
;
455 button
.clicked
.connect (() => { equation
.insert_exponent (); });
456 button
= builder
.get_object ("calc_shift_left_button") as Gtk
.Button
;
458 button
.clicked
.connect (shift_left_cb
);
459 button
= builder
.get_object ("calc_shift_right_button") as Gtk
.Button
;
461 button
.clicked
.connect (shift_right_cb
);
462 button
= builder
.get_object ("calc_character_button") as Gtk
.Button
;
464 button
.clicked
.connect (insert_character_code_cb
);
465 button
= builder
.get_object ("calc_numeric_point_button") as Gtk
.Button
;
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
> ();
503 var name
= "bit_label_%d".printf (i
);
504 var label
= builder
.get_object (name
) as Gtk
.Label
;
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
);
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
;
520 model
.append (out iter
);
522 /* Number display mode combo: Binary, e.g. 10011010010₂ */
523 _("Binary"), 1, 2, -1);
524 model
.append (out iter
);
526 /* Number display mode combo: Octal, e.g. 2322₈ */
527 _("Octal"), 1, 8, -1);
528 model
.append (out iter
);
530 /* Number display mode combo: Decimal, e.g. 1234 */
531 _("Decimal"), 1, 10, -1);
532 model
.append (out iter
);
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 (); } );
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
607 button
.set_data
<string> ("finc-dialog-name", "term_dialog");
608 button
.clicked
.connect (finc_cb
);
612 builder
.connect_signals (this
);
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
;
628 button
.set_data
<string> ("calc_text", data
);
629 button
.clicked
.connect ((widget
) => { equation
.insert (widget
.get_data
<string> ("calc_text")); });
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
;
649 equation
.source_units
= from_unit
.name
;
650 equation
.target_units
= to_unit
.name
;
654 private void load_buttons ()
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
)
670 /* Hide old buttons */
671 if (active_panel
!= null)
672 active_panel
.hide ();
674 /* Load and display new buttons */
675 active_panel
= panel
;
680 public int programming_base
682 get { return _programming_base
; }
685 if (_programming_base
== value
)
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
);
722 widget
.get_window ().get_root_coords (allocation
.x
, allocation
.y
, out x
, out y
);
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
++)
739 /* Left Shift Popup: Menu item to shift left by n places (n < 10) */
740 format
= ngettext ("_%d place", "_%d places", i
);
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
);
753 shift_left_menu
.append (item
);
754 item
.activate
.connect ((widget
) => { equation
.shift (widget
.get_data
<int> ("shiftcount")); });
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
++)
776 /* Right Shift Popup: Menu item to shift right by n places (n < 10) */
777 format
= ngettext ("_%d place", "_%d places", i
);
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
);
790 shift_right_menu
.append (item
);
791 item
.activate
.connect ((widget
) => { equation
.shift (widget
.get_data
<int> ("shiftcount")); });
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
);
830 item
.activate
.connect ((widget
) => { equation
.insert (widget
.get_data
<string> ("function")); });
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
;
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
);
860 next_entry
.grab_focus ();
863 private void finc_response_cb (Gtk
.Widget widget
, int response_id
)
865 if (response_id
!= Gtk
.ResponseType
.OK
)
868 var function
= (FinancialDialog
) widget
.get_data
<int> ("finc-function");
869 var entries
= new
string[0];
872 case FinancialDialog
.CTRM_DIALOG
:
873 entries
= ctrm_entries
;
875 case FinancialDialog
.DDB_DIALOG
:
876 entries
= ddb_entries
;
878 case FinancialDialog
.FV_DIALOG
:
879 entries
= fv_entries
;
881 case FinancialDialog
.GPM_DIALOG
:
882 entries
= gpm_entries
;
884 case FinancialDialog
.PMT_DIALOG
:
885 entries
= pmt_entries
;
887 case FinancialDialog
.PV_DIALOG
:
888 entries
= pv_entries
;
890 case FinancialDialog
.RATE_DIALOG
:
891 entries
= rate_entries
;
893 case FinancialDialog
.SLN_DIALOG
:
894 entries
= sln_entries
;
896 case FinancialDialog
.SYD_DIALOG
:
897 entries
= syd_entries
;
899 case FinancialDialog
.TERM_DIALOG
:
900 entries
= term_entries
;
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
]));
930 equation
.insert_number (x
);
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
);
947 private bool bit_toggle_cb (Gtk
.Widget event_box
, Gdk
.EventButton event
)
949 equation
.toggle_bit (event_box
.get_data
<int> ("bit_index"));
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
);
959 while (start
.backward_char ())
961 if (!start
.get_char ().isspace ())
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
);