1 /* Copyright (c) 2008-2009 Robert Ancell
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 #include <glib/gi18n.h>
21 #include "math-buttons.h"
22 #include "math-converter.h"
23 #include "financial.h"
25 #include "mp-serializer.h"
34 static GType button_mode_type
;
36 #define MAXBITS 64 /* Bit panel: number of bit fields. */
38 struct MathButtonsPrivate
40 MathEquation
*equation
;
43 gint programming_base
;
45 GtkBuilder
*basic_ui
, *advanced_ui
, *financial_ui
, *programming_ui
;
47 GdkColor color_numbers
, color_action
, color_operator
, color_function
, color_memory
, color_group
;
49 GtkWidget
*bas_panel
, *adv_panel
, *fin_panel
, *prog_panel
;
50 GtkWidget
*active_panel
;
52 GtkWidget
*shift_left_menu
, *shift_right_menu
;
54 GtkWidget
*function_menu
;
56 GList
*superscript_toggles
;
57 GList
*subscript_toggles
;
59 GtkWidget
*base_combo
;
60 GtkWidget
*base_label
;
62 GtkWidget
*bit_labels
[MAXBITS
];
64 GtkWidget
*source_currency_combo
;
65 GtkWidget
*target_currency_combo
;
66 MpSerializer
*currency_serializer
;
67 GtkWidget
*currency_label
;
69 GtkWidget
*character_code_dialog
;
70 GtkWidget
*character_code_entry
;
73 G_DEFINE_TYPE (MathButtons
, math_buttons
, GTK_TYPE_VBOX
);
75 #define UI_BASIC_FILE UI_DIR "/buttons-basic.ui"
76 #define UI_ADVANCED_FILE UI_DIR "/buttons-advanced.ui"
77 #define UI_FINANCIAL_FILE UI_DIR "/buttons-financial.ui"
78 #define UI_PROGRAMMING_FILE UI_DIR "/buttons-programming.ui"
80 #define GET_WIDGET(ui, name) \
81 GTK_WIDGET(gtk_builder_get_object((ui), (name)))
83 #define WM_WIDTH_FACTOR 10
84 #define WM_HEIGHT_FACTOR 30
98 const char *widget_name
;
104 static ButtonData button_data
[] = {
106 /* Tooltip for the Pi button */
108 {"eulers_number", "e", NUMBER
,
109 /* Tooltip for the Euler's Number button */
110 N_("Euler’s Number")},
111 {"imaginary", "i", NUMBER
, NULL
},
112 {"numeric_point", NULL
, NUMBER
, NULL
},
113 {"subscript", NULL
, NUMBER_BOLD
,
114 /* Tooltip for the subscript button */
115 N_("Subscript mode [Alt]")},
116 {"superscript", NULL
, NUMBER_BOLD
,
117 /* Tooltip for the superscript button */
118 N_("Superscript mode [Ctrl]")},
119 {"exponential", NULL
, NUMBER_BOLD
,
120 /* Tooltip for the scientific exponent button */
121 N_("Scientific exponent [Ctrl+E]")},
122 {"add", "+", OPERATOR
,
123 /* Tooltip for the add button */
125 {"subtract", "−", OPERATOR
,
126 /* Tooltip for the subtract button */
128 {"multiply", "×", OPERATOR
,
129 /* Tooltip for the multiply button */
131 {"divide", "÷", OPERATOR
,
132 /* Tooltip for the divide button */
134 {"modulus_divide", " mod ", OPERATOR
,
135 /* Tooltip for the modulus divide button */
136 N_("Modulus divide")},
137 {"function", NULL
, FUNCTION
,
138 /* Tooltip for the additional functions button */
139 N_("Additional Functions")},
140 {"x_pow_y", "^", FUNCTION
,
141 /* Tooltip for the exponent button */
142 N_("Exponent [^ or **]")},
143 {"x_squared", "²", FUNCTION
,
144 /* Tooltip for the square button */
145 N_("Square [Ctrl+2]")},
146 {"percentage", "%", NUMBER
,
147 /* Tooltip for the percentage button */
148 N_("Percentage [%]")},
149 {"factorial", "!", FUNCTION
,
150 /* Tooltip for the factorial button */
151 N_("Factorial [!]")},
152 {"abs", "|", FUNCTION
,
153 /* Tooltip for the absolute value button */
154 N_("Absolute value [|]")},
155 {"arg", "Arg ", FUNCTION
,
156 /* Tooltip for the complex argument component button */
157 N_("Complex argument")},
158 {"conjugate", "conj ", FUNCTION
,
159 /* Tooltip for the complex conjugate button */
160 N_("Complex conjugate")},
161 {"root", "√", FUNCTION
,
162 /* Tooltip for the root button */
163 N_("Root [Ctrl+R]")},
164 {"square_root", "√", FUNCTION
,
165 /* Tooltip for the square root button */
166 N_("Square root [Ctrl+R]")},
167 {"logarithm", "log ", FUNCTION
,
168 /* Tooltip for the logarithm button */
170 {"natural_logarithm", "ln ", FUNCTION
,
171 /* Tooltip for the natural logarithm button */
172 N_("Natural Logarithm")},
173 {"sine", "sin ", FUNCTION
,
174 /* Tooltip for the sine button */
176 {"cosine", "cos ", FUNCTION
,
177 /* Tooltip for the cosine button */
179 {"tangent", "tan ", FUNCTION
,
180 /* Tooltip for the tangent button */
182 {"hyperbolic_sine", "sinh ", FUNCTION
,
183 /* Tooltip for the hyperbolic sine button */
184 N_("Hyperbolic Sine")},
185 {"hyperbolic_cosine", "cosh ", FUNCTION
,
186 /* Tooltip for the hyperbolic cosine button */
187 N_("Hyperbolic Cosine")},
188 {"hyperbolic_tangent", "tanh ", FUNCTION
,
189 /* Tooltip for the hyperbolic tangent button */
190 N_("Hyperbolic Tangent")},
191 {"inverse", "⁻¹", FUNCTION
,
192 /* Tooltip for the inverse button */
193 N_("Inverse [Ctrl+I]")},
194 {"and", "∧", OPERATOR
,
195 /* Tooltip for the boolean AND button */
197 {"or", "∨", OPERATOR
,
198 /* Tooltip for the boolean OR button */
200 {"xor", "⊻", OPERATOR
,
201 /* Tooltip for the exclusive OR button */
202 N_("Boolean Exclusive OR")},
203 {"not", "¬", FUNCTION
,
204 /* Tooltip for the boolean NOT button */
206 {"integer_portion", "int ", FUNCTION
,
207 /* Tooltip for the integer component button */
208 N_("Integer Component")},
209 {"fractional_portion", "frac ", FUNCTION
,
210 /* Tooltip for the fractional component button */
211 N_("Fractional Component")},
212 {"real_portion", "Re ", FUNCTION
,
213 /* Tooltip for the real component button */
214 N_("Real Component")},
215 {"imaginary_portion", "Im ", FUNCTION
,
216 /* Tooltip for the imaginary component button */
217 N_("Imaginary Component")},
218 {"ones_complement", "ones ", FUNCTION
,
219 /* Tooltip for the ones complement button */
220 N_("Ones Complement")},
221 {"twos_complement", "twos ", FUNCTION
,
222 /* Tooltip for the twos complement button */
223 N_("Twos Complement")},
224 {"trunc", "trunc ", FUNCTION
,
225 /* Tooltip for the truncate button */
227 {"start_group", "(", GROUP
,
228 /* Tooltip for the start group button */
229 N_("Start Group [(]")},
230 {"end_group", ")", GROUP
,
231 /* Tooltip for the end group button */
232 N_("End Group [)]")},
233 {"store", NULL
, MEMORY
,
234 /* Tooltip for the assign variable button */
235 N_("Assign Variable")},
236 {"recall", NULL
, MEMORY
,
237 /* Tooltip for the insert variable button */
238 N_("Insert Variable")},
239 {"character", NULL
, MEMORY
,
240 /* Tooltip for the insert character code button */
241 N_("Insert Character Code")},
242 {"result", NULL
, ACTION
,
243 /* Tooltip for the solve button */
244 N_("Calculate Result")},
245 {"factor", NULL
, ACTION
,
246 /* Tooltip for the factor button */
247 N_("Factorize [Ctrl+F]")},
248 {"clear", NULL
, GROUP
,
249 /* Tooltip for the clear button */
250 N_("Clear Display [Escape]")},
251 {"undo", NULL
, GROUP
,
252 /* Tooltip for the undo button */
253 N_("Undo [Ctrl+Z]")},
254 {"shift_left", NULL
, ACTION
,
255 /* Tooltip for the shift left button */
257 {"shift_right", NULL
, ACTION
,
258 /* Tooltip for the shift right button */
260 {"finc_compounding_term", NULL
, FUNCTION
,
261 /* Tooltip for the compounding term button */
262 N_("Compounding Term")},
263 {"finc_double_declining_depreciation", NULL
, FUNCTION
,
264 /* Tooltip for the double declining depreciation button */
265 N_("Double Declining Depreciation")},
266 {"finc_future_value", NULL
, FUNCTION
,
267 /* Tooltip for the future value button */
269 {"finc_term", NULL
, FUNCTION
,
270 /* Tooltip for the financial term button */
271 N_("Financial Term")},
272 {"finc_sum_of_the_years_digits_depreciation", NULL
, FUNCTION
,
273 /* Tooltip for the sum of the years digits depreciation button */
274 N_("Sum of the Years Digits Depreciation")},
275 {"finc_straight_line_depreciation", NULL
, FUNCTION
,
276 /* Tooltip for the straight line depreciation button */
277 N_("Straight Line Depreciation")},
278 {"finc_periodic_interest_rate", NULL
, FUNCTION
,
279 /* Tooltip for the periodic interest rate button */
280 N_("Periodic Interest Rate")},
281 {"finc_present_value", NULL
, FUNCTION
,
282 /* Tooltip for the present value button */
283 N_("Present Value")},
284 {"finc_periodic_payment", NULL
, FUNCTION
,
285 /* Tooltip for the periodic payment button */
286 N_("Periodic Payment")},
287 {"finc_gross_profit_margin", NULL
, FUNCTION
,
288 /* Tooltip for the gross profit margin button */
289 N_("Gross Profit Margin")},
290 {NULL
, NULL
, 0, NULL
}
294 CURRENCY_TARGET_UPPER
,
295 CURRENCY_TARGET_LOWER
298 /* The names of each field in the dialogs for the financial functions */
299 static char *finc_dialog_fields
[][5] = {
300 {"ctrm_pint", "ctrm_fv", "ctrm_pv", NULL
, NULL
},
301 {"ddb_cost", "ddb_life", "ddb_period", NULL
, NULL
},
302 {"fv_pmt", "fv_pint", "fv_n", NULL
, NULL
},
303 {"gpm_cost", "gpm_margin", NULL
, NULL
, NULL
},
304 {"pmt_prin", "pmt_pint", "pmt_n", NULL
, NULL
},
305 {"pv_pmt", "pv_pint", "pv_n", NULL
, NULL
},
306 {"rate_fv", "rate_pv", "rate_n", NULL
, NULL
},
307 {"sln_cost", "sln_salvage", "sln_life", NULL
, NULL
},
308 {"syd_cost", "syd_salvage", "syd_life", "syd_period", NULL
},
309 {"term_pmt", "term_fv", "term_pint", NULL
, NULL
},
310 {NULL
, NULL
, NULL
, NULL
, NULL
}
315 math_buttons_new(MathEquation
*equation
)
317 return g_object_new(math_buttons_get_type(), "equation", equation
, NULL
);
322 set_tint(GtkWidget
*widget
, GdkColor
*tint
, gint alpha
)
330 gtk_widget_ensure_style(widget
);
331 style
= gtk_widget_get_style(widget
);
333 for (j
= 0; j
< 5; j
++) {
336 color
.red
= (style
->bg
[j
].red
* (10 - alpha
) + tint
->red
* alpha
) / 10;
337 color
.green
= (style
->bg
[j
].green
* (10 - alpha
) + tint
->green
* alpha
) / 10;
338 color
.blue
= (style
->bg
[j
].blue
* (10 - alpha
) + tint
->blue
* alpha
) / 10;
340 gtk_widget_modify_bg(widget
, j
, &color
);
346 set_data(GtkBuilder
*ui
, const gchar
*object_name
, const gchar
*name
, const char *value
)
349 object
= gtk_builder_get_object(ui
, object_name
);
351 g_object_set_data(object
, name
, GINT_TO_POINTER(value
));
356 set_int_data(GtkBuilder
*ui
, const gchar
*object_name
, const gchar
*name
, gint value
)
359 object
= gtk_builder_get_object(ui
, object_name
);
361 g_object_set_data(object
, name
, GINT_TO_POINTER(value
));
366 load_finc_dialogs(MathButtons
*buttons
)
370 set_int_data(buttons
->priv
->financial_ui
, "ctrm_dialog", "finc_dialog", FINC_CTRM_DIALOG
);
371 set_int_data(buttons
->priv
->financial_ui
, "ddb_dialog", "finc_dialog", FINC_DDB_DIALOG
);
372 set_int_data(buttons
->priv
->financial_ui
, "fv_dialog", "finc_dialog", FINC_FV_DIALOG
);
373 set_int_data(buttons
->priv
->financial_ui
, "gpm_dialog", "finc_dialog", FINC_GPM_DIALOG
);
374 set_int_data(buttons
->priv
->financial_ui
, "pmt_dialog", "finc_dialog", FINC_PMT_DIALOG
);
375 set_int_data(buttons
->priv
->financial_ui
, "pv_dialog", "finc_dialog", FINC_PV_DIALOG
);
376 set_int_data(buttons
->priv
->financial_ui
, "rate_dialog", "finc_dialog", FINC_RATE_DIALOG
);
377 set_int_data(buttons
->priv
->financial_ui
, "sln_dialog", "finc_dialog", FINC_SLN_DIALOG
);
378 set_int_data(buttons
->priv
->financial_ui
, "syd_dialog", "finc_dialog", FINC_SYD_DIALOG
);
379 set_int_data(buttons
->priv
->financial_ui
, "term_dialog", "finc_dialog", FINC_TERM_DIALOG
);
381 for (i
= 0; finc_dialog_fields
[i
][0] != NULL
; i
++) {
382 for (j
= 0; finc_dialog_fields
[i
][j
]; j
++) {
384 o
= gtk_builder_get_object (buttons
->priv
->financial_ui
, finc_dialog_fields
[i
][j
]);
385 g_object_set_data(o
, "finc_field", GINT_TO_POINTER(j
));
386 g_object_set_data(o
, "finc_dialog", GINT_TO_POINTER(i
));
393 update_bit_panel(MathButtons
*buttons
)
402 if (!buttons
->priv
->bit_panel
)
405 enabled
= math_equation_get_number(buttons
->priv
->equation
, &x
);
408 MPNumber max
, fraction
;
410 mp_set_from_unsigned_integer(G_MAXUINT64
, &max
);
411 mp_fractional_part(&x
, &fraction
);
412 if (mp_is_negative(&x
) || mp_is_greater_than(&x
, &max
) || !mp_is_zero(&fraction
))
415 bits
= mp_cast_to_unsigned_int(&x
);
418 gtk_widget_set_sensitive(buttons
->priv
->bit_panel
, enabled
);
419 gtk_widget_set_sensitive(buttons
->priv
->base_label
, enabled
);
424 for (i
= 0; i
< MAXBITS
; i
++) {
427 if (bits
& (1LL << (MAXBITS
-i
-1)))
431 gtk_label_set_text(GTK_LABEL(buttons
->priv
->bit_labels
[i
]), label
);
434 base
= math_equation_get_base(buttons
->priv
->equation
);
435 label
= g_string_new("");
438 g_string_append(label
, " = ");
439 g_string_append_printf(label
, "%lo", bits
);
440 g_string_append(label
, "₈");
444 g_string_append(label
, " = ");
445 g_string_append_printf(label
, "%lu", bits
);
446 g_string_append(label
, "₁₀");
450 g_string_append(label
, " = ");
451 g_string_append_printf(label
, "%lX", bits
);
452 g_string_append(label
, "₁₆");
455 gtk_label_set_text(GTK_LABEL(buttons
->priv
->base_label
), label
->str
);
456 g_string_free(label
, TRUE
);
461 update_currency_label(MathButtons
*buttons
)
466 if (!buttons
->priv
->currency_label
)
469 if (!math_equation_get_number(buttons
->priv
->equation
, &x
))
472 if (currency_convert(&x
,
473 math_equation_get_source_currency(buttons
->priv
->equation
),
474 math_equation_get_target_currency(buttons
->priv
->equation
),
476 char *input_text
, *output_text
;
477 const char *source_symbol
, *target_symbol
;
479 input_text
= mp_serializer_to_string(buttons
->priv
->currency_serializer
, &x
);
480 output_text
= mp_serializer_to_string(buttons
->priv
->currency_serializer
, &value
);
482 source_symbol
= currency_get_info(math_equation_get_source_currency(buttons
->priv
->equation
))->symbol
;
483 target_symbol
= currency_get_info(math_equation_get_target_currency(buttons
->priv
->equation
))->symbol
;
485 /* Translators: first and third %s are currency symbols, second and fourth are amounts in these currencies, you may want to change the order of these, example: $100 = €100 */
486 label
= g_strdup_printf(_("%s%s = %s%s"),
487 source_symbol
, input_text
,
488 target_symbol
, output_text
);
493 label
= g_strdup("");
495 gtk_label_set_text(GTK_LABEL(buttons
->priv
->currency_label
), label
);
501 display_changed_cb(MathEquation
*equation
, GParamSpec
*spec
, MathButtons
*buttons
)
503 update_currency_label(buttons
);
504 update_bit_panel(buttons
);
509 base_combobox_changed_cb(GtkWidget
*combo
, MathButtons
*buttons
)
515 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(combo
));
516 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo
), &iter
);
517 gtk_tree_model_get(model
, &iter
, 1, &value
, -1);
519 math_equation_set_base(buttons
->priv
->equation
, value
);
524 base_changed_cb(MathEquation
*equation
, GParamSpec
*spec
, MathButtons
*buttons
)
530 if (buttons
->priv
->mode
!= PROGRAMMING
)
533 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(buttons
->priv
->base_combo
));
534 valid
= gtk_tree_model_get_iter_first(model
, &iter
);
535 buttons
->priv
->programming_base
= math_equation_get_base(buttons
->priv
->equation
);
540 gtk_tree_model_get(model
, &iter
, 1, &v
, -1);
541 if (v
== buttons
->priv
->programming_base
)
543 valid
= gtk_tree_model_iter_next(model
, &iter
);
546 valid
= gtk_tree_model_get_iter_first(model
, &iter
);
548 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons
->priv
->base_combo
), &iter
);
553 source_currency_combo_changed_cb(GtkWidget
*combo
, MathButtons
*buttons
)
559 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(combo
));
560 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo
), &iter
);
561 gtk_tree_model_get(model
, &iter
, 0, &value
, -1);
563 math_equation_set_source_currency(buttons
->priv
->equation
, value
);
569 source_currency_changed_cb(MathEquation
*equation
, GParamSpec
*spec
, MathButtons
*buttons
)
575 if (buttons
->priv
->mode
!= FINANCIAL
)
578 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(buttons
->priv
->source_currency_combo
));
579 valid
= gtk_tree_model_get_iter_first(model
, &iter
);
585 gtk_tree_model_get(model
, &iter
, 0, &v
, -1);
586 matched
= strcmp(math_equation_get_source_currency(buttons
->priv
->equation
), v
) == 0;
590 valid
= gtk_tree_model_iter_next(model
, &iter
);
593 valid
= gtk_tree_model_get_iter_first(model
, &iter
);
595 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons
->priv
->source_currency_combo
), &iter
);
596 update_currency_label(buttons
);
601 target_currency_combo_changed_cb(GtkWidget
*combo
, MathButtons
*buttons
)
607 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(combo
));
608 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo
), &iter
);
609 gtk_tree_model_get(model
, &iter
, 0, &value
, -1);
611 math_equation_set_target_currency(buttons
->priv
->equation
, value
);
617 target_currency_changed_cb(MathEquation
*equation
, GParamSpec
*spec
, MathButtons
*buttons
)
623 if (buttons
->priv
->mode
!= FINANCIAL
)
626 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(buttons
->priv
->target_currency_combo
));
627 valid
= gtk_tree_model_get_iter_first(model
, &iter
);
633 gtk_tree_model_get(model
, &iter
, 0, &v
, -1);
634 matched
= strcmp(math_equation_get_target_currency(buttons
->priv
->equation
), v
) == 0;
638 valid
= gtk_tree_model_iter_next(model
, &iter
);
641 valid
= gtk_tree_model_get_iter_first(model
, &iter
);
643 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons
->priv
->target_currency_combo
), &iter
);
644 update_currency_label(buttons
);
649 load_mode(MathButtons
*buttons
, ButtonMode mode
)
651 GtkBuilder
*builder
, **builder_ptr
;
654 const gchar
*builder_file
;
655 static gchar
*objects
[] = { "button_panel", "character_code_dialog", "currency_dialog",
656 "ctrm_dialog", "ddb_dialog", "fv_dialog", "gpm_dialog",
657 "pmt_dialog", "pv_dialog", "rate_dialog", "sln_dialog",
658 "syd_dialog", "term_dialog", "adjustment1", "adjustment2", NULL
};
659 GtkWidget
*widget
, **panel
;
660 GError
*error
= NULL
;
665 builder_ptr
= &buttons
->priv
->basic_ui
;
666 builder_file
= UI_BASIC_FILE
;
667 panel
= &buttons
->priv
->bas_panel
;
670 builder_ptr
= &buttons
->priv
->advanced_ui
;
671 builder_file
= UI_ADVANCED_FILE
;
672 panel
= &buttons
->priv
->adv_panel
;
675 builder_ptr
= &buttons
->priv
->financial_ui
;
676 builder_file
= UI_FINANCIAL_FILE
;
677 panel
= &buttons
->priv
->fin_panel
;
680 builder_ptr
= &buttons
->priv
->programming_ui
;
681 builder_file
= UI_PROGRAMMING_FILE
;
682 panel
= &buttons
->priv
->prog_panel
;
689 builder
= *builder_ptr
= gtk_builder_new();
690 // FIXME: Show dialog if failed to load
691 gtk_builder_add_objects_from_file(builder
, builder_file
, objects
, &error
);
693 g_warning("Error loading button UI: %s", error
->message
);
694 g_clear_error(&error
);
696 *panel
= GET_WIDGET(builder
, "button_panel");
697 gtk_box_pack_end(GTK_BOX(buttons
), *panel
, TRUE
, TRUE
, 0);
699 /* Configure buttons */
700 for (i
= 0; button_data
[i
].widget_name
!= NULL
; i
++) {
704 name
= g_strdup_printf("calc_%s_button", button_data
[i
].widget_name
);
705 object
= gtk_builder_get_object(*builder_ptr
, name
);
710 button
= GTK_WIDGET(object
);
711 if (button_data
[i
].data
)
712 g_object_set_data(object
, "calc_text", (gpointer
) button_data
[i
].data
);
714 if (button_data
[i
].tooltip
)
715 gtk_widget_set_tooltip_text(button
, _(button_data
[i
].tooltip
));
717 atk_object_set_name(gtk_widget_get_accessible(button
), button_data
[i
].widget_name
);
719 switch (button_data
[i
].class) {
721 set_tint(button
, &buttons
->priv
->color_numbers
, 1);
724 set_tint(button
, &buttons
->priv
->color_numbers
, 2);
727 set_tint(button
, &buttons
->priv
->color_operator
, 1);
730 set_tint(button
, &buttons
->priv
->color_function
, 1);
733 set_tint(button
, &buttons
->priv
->color_memory
, 1);
736 set_tint(button
, &buttons
->priv
->color_group
, 1);
739 set_tint(button
, &buttons
->priv
->color_action
, 2);
744 /* Set special button data */
745 for (i
= 0; i
< 16; i
++) {
748 name
= g_strdup_printf("calc_%d_button", i
);
749 button
= GET_WIDGET(builder
, name
);
754 g_object_set_data(G_OBJECT(button
), "calc_digit", GINT_TO_POINTER(i
));
755 set_tint(button
, &buttons
->priv
->color_numbers
, 1);
756 len
= g_unichar_to_utf8(math_equation_get_digit_text(buttons
->priv
->equation
, i
), buffer
);
758 gtk_button_set_label(GTK_BUTTON(button
), buffer
);
762 widget
= GET_WIDGET(builder
, "calc_numeric_point_button");
764 MpSerializer
*serializer
= math_equation_get_serializer(buttons
->priv
->equation
);
767 len
= g_unichar_to_utf8(mp_serializer_get_radix(serializer
), buffer
);
769 gtk_button_set_label(GTK_BUTTON(widget
), buffer
);
772 widget
= GET_WIDGET(builder
, "calc_superscript_button");
774 buttons
->priv
->superscript_toggles
= g_list_append(buttons
->priv
->superscript_toggles
, widget
);
775 if (math_equation_get_number_mode(buttons
->priv
->equation
) == SUPERSCRIPT
)
776 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), TRUE
);
778 widget
= GET_WIDGET(builder
, "calc_subscript_button");
780 buttons
->priv
->subscript_toggles
= g_list_append(buttons
->priv
->subscript_toggles
, widget
);
781 if (math_equation_get_number_mode(buttons
->priv
->equation
) == SUBSCRIPT
)
782 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), TRUE
);
785 if (mode
== ADVANCED
) {
786 GtkWidget
*converter
;
788 converter
= GTK_WIDGET(math_converter_new(buttons
->priv
->equation
));
789 gtk_widget_show(converter
);
790 gtk_box_pack_start(GTK_BOX(*panel
), converter
, FALSE
, TRUE
, 0);
793 if (mode
== PROGRAMMING
) {
796 GtkCellRenderer
*renderer
;
798 buttons
->priv
->base_label
= GET_WIDGET(builder
, "base_label");
799 buttons
->priv
->character_code_dialog
= GET_WIDGET(builder
, "character_code_dialog");
800 buttons
->priv
->character_code_entry
= GET_WIDGET(builder
, "character_code_entry");
802 buttons
->priv
->bit_panel
= GET_WIDGET(builder
, "bit_table");
803 for (i
= 0; i
< MAXBITS
; i
++) {
804 name
= g_strdup_printf("bit_label_%d", i
);
805 buttons
->priv
->bit_labels
[i
] = GET_WIDGET(builder
, name
);
807 name
= g_strdup_printf("bit_eventbox_%d", i
);
808 set_int_data(builder
, name
, "bit_index", i
);
811 buttons
->priv
->base_combo
= GET_WIDGET(builder
, "base_combo");
812 model
= gtk_list_store_new(2, G_TYPE_STRING
, G_TYPE_INT
, G_TYPE_INT
);
813 gtk_combo_box_set_model(GTK_COMBO_BOX(buttons
->priv
->base_combo
), GTK_TREE_MODEL(model
));
814 gtk_list_store_append(GTK_LIST_STORE(model
), &iter
);
815 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, 0,
816 /* Number display mode combo: Binary, e.g. 10011010010₂ */
817 _("Binary"), 1, 2, -1);
818 gtk_list_store_append(GTK_LIST_STORE(model
), &iter
);
819 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, 0,
820 /* Number display mode combo: Octal, e.g. 2322₈ */
821 _("Octal"), 1, 8, -1);
822 gtk_list_store_append(GTK_LIST_STORE(model
), &iter
);
823 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, 0,
824 /* Number display mode combo: Decimal, e.g. 1234 */
825 _("Decimal"), 1, 10, -1);
826 gtk_list_store_append(GTK_LIST_STORE(model
), &iter
);
827 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, 0,
828 /* Number display mode combo: Hexadecimal, e.g. 4D2₁₆ */
829 _("Hexadecimal"), 1, 16, -1);
830 renderer
= gtk_cell_renderer_text_new();
831 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(buttons
->priv
->base_combo
), renderer
, TRUE
);
832 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(buttons
->priv
->base_combo
), renderer
, "text", 0);
834 g_signal_connect(buttons
->priv
->base_combo
, "changed", G_CALLBACK(base_combobox_changed_cb
), buttons
);
835 g_signal_connect(buttons
->priv
->equation
, "notify::base", G_CALLBACK(base_changed_cb
), buttons
);
836 base_changed_cb(buttons
->priv
->equation
, NULL
, buttons
);
839 /* Setup financial functions */
840 if (mode
== FINANCIAL
) {
842 GtkCellRenderer
*renderer
;
844 load_finc_dialogs(buttons
);
846 buttons
->priv
->source_currency_combo
= GET_WIDGET(builder
, "source_currency_combo");
847 buttons
->priv
->target_currency_combo
= GET_WIDGET(builder
, "target_currency_combo");
848 buttons
->priv
->currency_label
= GET_WIDGET(builder
, "currency_label");
850 buttons
->priv
->currency_serializer
= mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC
, 10, 2);
852 model
= gtk_list_store_new(1, G_TYPE_STRING
);
854 for (i
= 0; currency_info
[i
].short_name
!= NULL
; i
++) {
857 gtk_list_store_append(GTK_LIST_STORE(model
), &iter
);
858 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, 0, currency_info
[i
].short_name
, -1);
861 gtk_combo_box_set_model(GTK_COMBO_BOX(buttons
->priv
->source_currency_combo
), GTK_TREE_MODEL(model
));
862 gtk_combo_box_set_model(GTK_COMBO_BOX(buttons
->priv
->target_currency_combo
), GTK_TREE_MODEL(model
));
864 renderer
= gtk_cell_renderer_text_new();
865 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(buttons
->priv
->source_currency_combo
), renderer
, TRUE
);
866 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(buttons
->priv
->source_currency_combo
), renderer
, "text", 0);
867 renderer
= gtk_cell_renderer_text_new();
868 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(buttons
->priv
->target_currency_combo
), renderer
, TRUE
);
869 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(buttons
->priv
->target_currency_combo
), renderer
, "text", 0);
871 g_signal_connect(buttons
->priv
->source_currency_combo
, "changed", G_CALLBACK(source_currency_combo_changed_cb
), buttons
);
872 g_signal_connect(buttons
->priv
->target_currency_combo
, "changed", G_CALLBACK(target_currency_combo_changed_cb
), buttons
);
873 g_signal_connect(buttons
->priv
->equation
, "notify::source-currency", G_CALLBACK(source_currency_changed_cb
), buttons
);
874 g_signal_connect(buttons
->priv
->equation
, "notify::target-currency", G_CALLBACK(target_currency_changed_cb
), buttons
);
875 source_currency_changed_cb(buttons
->priv
->equation
, NULL
, buttons
);
876 target_currency_changed_cb(buttons
->priv
->equation
, NULL
, buttons
);
878 set_data(builder
, "calc_finc_compounding_term_button", "finc_dialog", "ctrm_dialog");
879 set_data(builder
, "calc_finc_double_declining_depreciation_button", "finc_dialog", "ddb_dialog");
880 set_data(builder
, "calc_finc_future_value_button", "finc_dialog", "fv_dialog");
881 set_data(builder
, "calc_finc_gross_profit_margin_button", "finc_dialog", "gpm_dialog");
882 set_data(builder
, "calc_finc_periodic_payment_button", "finc_dialog", "pmt_dialog");
883 set_data(builder
, "calc_finc_present_value_button", "finc_dialog", "pv_dialog");
884 set_data(builder
, "calc_finc_periodic_interest_rate_button", "finc_dialog", "rate_dialog");
885 set_data(builder
, "calc_finc_straight_line_depreciation_button", "finc_dialog", "sln_dialog");
886 set_data(builder
, "calc_finc_sum_of_the_years_digits_depreciation_button", "finc_dialog", "syd_dialog");
887 set_data(builder
, "calc_finc_term_button", "finc_dialog", "term_dialog");
890 gtk_builder_connect_signals(builder
, buttons
);
892 display_changed_cb(buttons
->priv
->equation
, NULL
, buttons
);
900 load_buttons(MathButtons
*buttons
)
904 if (!gtk_widget_get_visible(GTK_WIDGET(buttons
)))
907 panel
= load_mode(buttons
, buttons
->priv
->mode
);
908 if (buttons
->priv
->active_panel
== panel
)
911 /* Hide old buttons */
912 if (buttons
->priv
->active_panel
)
913 gtk_widget_hide(buttons
->priv
->active_panel
);
915 /* Load and display new buttons */
916 buttons
->priv
->active_panel
= panel
;
918 gtk_widget_show(panel
);
923 math_buttons_set_mode(MathButtons
*buttons
, ButtonMode mode
)
927 if (buttons
->priv
->mode
== mode
)
930 old_mode
= buttons
->priv
->mode
;
931 buttons
->priv
->mode
= mode
;
933 if (mode
== PROGRAMMING
)
934 math_equation_set_base(buttons
->priv
->equation
, buttons
->priv
->programming_base
);
936 math_equation_set_base(buttons
->priv
->equation
, 10);
938 load_buttons(buttons
);
940 g_object_notify(G_OBJECT(buttons
), "mode");
945 math_buttons_get_mode(MathButtons
*buttons
)
947 return buttons
->priv
->mode
;
952 math_buttons_set_programming_base(MathButtons
*buttons
, gint base
)
954 buttons
->priv
->programming_base
= base
;
959 math_buttons_get_programming_base(MathButtons
*buttons
)
961 return buttons
->priv
->programming_base
;
965 void exponent_cb(GtkWidget
*widget
, MathButtons
*buttons
);
968 exponent_cb(GtkWidget
*widget
, MathButtons
*buttons
)
970 math_equation_insert_exponent(buttons
->priv
->equation
);
974 void subtract_cb(GtkWidget
*widget
, MathButtons
*buttons
);
977 subtract_cb(GtkWidget
*widget
, MathButtons
*buttons
)
979 math_equation_insert_subtract(buttons
->priv
->equation
);
983 void button_cb(GtkWidget
*widget
, MathButtons
*buttons
);
986 button_cb(GtkWidget
*widget
, MathButtons
*buttons
)
988 math_equation_insert(buttons
->priv
->equation
, g_object_get_data(G_OBJECT(widget
), "calc_text"));
992 void solve_cb(GtkWidget
*widget
, MathButtons
*buttons
);
995 solve_cb(GtkWidget
*widget
, MathButtons
*buttons
)
997 math_equation_solve(buttons
->priv
->equation
);
1001 void clear_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1004 clear_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1006 math_equation_clear(buttons
->priv
->equation
);
1010 void delete_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1013 delete_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1015 math_equation_delete(buttons
->priv
->equation
);
1019 void undo_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1022 undo_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1024 math_equation_undo(buttons
->priv
->equation
);
1029 shift_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1031 math_equation_shift(buttons
->priv
->equation
, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
), "shiftcount")));
1036 button_menu_position_func(GtkMenu
*menu
, gint
*x
, gint
*y
,
1037 gboolean
*push_in
, gpointer user_data
)
1039 GtkWidget
*button
= user_data
;
1040 GtkAllocation allocation
;
1044 gdk_window_get_origin(gtk_widget_get_window(button
), &loc
.x
, &loc
.y
);
1045 border
= gtk_container_get_border_width(GTK_CONTAINER(button
));
1046 gtk_widget_get_allocation(button
, &allocation
);
1047 *x
= loc
.x
+ allocation
.x
+ border
;
1048 *y
= loc
.y
+ allocation
.y
+ border
;
1053 popup_button_menu(GtkWidget
*widget
, GtkMenu
*menu
)
1055 gtk_menu_popup(menu
, NULL
, NULL
,
1056 button_menu_position_func
, widget
, 1, gtk_get_current_event_time());
1061 save_variable_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1068 delete_variable_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1075 make_register_menu_item(MathButtons
*buttons
, const gchar
*name
, const MPNumber
*value
, gboolean can_modify
, GCallback callback
)
1078 GtkWidget
*item
, *label
;
1081 MpSerializer
*serializer
= math_equation_get_serializer(buttons
->priv
->equation
);
1082 text
= mp_serializer_to_string(serializer
, value
);
1083 mstr
= g_strdup_printf("<span weight=\"bold\">%s</span> = %s", name
, text
);
1087 mstr
= g_strdup_printf("<span weight=\"bold\">%s</span>", name
);
1088 label
= gtk_label_new(mstr
);
1089 gtk_label_set_use_markup(GTK_LABEL(label
), TRUE
);
1090 gtk_misc_set_alignment(GTK_MISC(label
), 0.0, 0.5);
1093 item
= gtk_menu_item_new();
1095 // FIXME: Buttons don't work inside menus...
1096 if (0) {//can_modify) {
1097 GtkWidget
*hbox
, *button
;
1099 hbox
= gtk_hbox_new(FALSE
, 6);
1100 gtk_container_add(GTK_CONTAINER(item
), hbox
);
1102 gtk_box_pack_start(GTK_BOX(hbox
), label
, TRUE
, TRUE
, 0);
1104 button
= gtk_button_new();
1105 gtk_button_set_image(GTK_BUTTON(button
), gtk_image_new_from_stock(GTK_STOCK_DELETE
, GTK_ICON_SIZE_MENU
));
1106 gtk_button_set_relief(GTK_BUTTON(button
), GTK_RELIEF_NONE
);
1107 gtk_box_pack_end(GTK_BOX(hbox
), button
, FALSE
, TRUE
, 0);
1108 g_signal_connect(G_OBJECT(button
), "clicked", G_CALLBACK(delete_variable_cb
), buttons
);
1110 button
= gtk_button_new();
1111 gtk_button_set_image(GTK_BUTTON(button
), gtk_image_new_from_stock(GTK_STOCK_SAVE
, GTK_ICON_SIZE_MENU
));
1112 gtk_button_set_relief(GTK_BUTTON(button
), GTK_RELIEF_NONE
);
1113 gtk_box_pack_end(GTK_BOX(hbox
), button
, FALSE
, TRUE
, 0);
1114 g_signal_connect(G_OBJECT(button
), "clicked", G_CALLBACK(save_variable_cb
), buttons
);
1117 gtk_container_add(GTK_CONTAINER(item
), label
);
1119 g_object_set_data(G_OBJECT(item
), "register_id", g_strdup(name
)); // FIXME: Memory leak
1120 g_signal_connect(item
, "activate", callback
, buttons
);
1127 store_menu_cb(GtkMenuItem
*menu
, MathButtons
*buttons
)
1129 math_equation_store(buttons
->priv
->equation
, g_object_get_data(G_OBJECT(menu
), "register_id"));
1133 void store_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1136 store_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1143 menu
= gtk_menu_new();
1144 gtk_menu_set_reserve_toggle_size(GTK_MENU(menu
), FALSE
);
1145 set_tint(menu
, &buttons
->priv
->color_memory
, 1);
1147 names
= math_variables_get_names(math_equation_get_variables(buttons
->priv
->equation
));
1148 if (names
[0] == NULL
) {
1149 item
= gtk_menu_item_new_with_label(/* Text shown in store menu when no variables defined */
1150 _("No variables defined"));
1151 gtk_widget_set_sensitive(item
, FALSE
);
1152 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1154 for (i
= 0; names
[i
]; i
++) {
1156 value
= math_variables_get_value(math_equation_get_variables(buttons
->priv
->equation
), names
[i
]);
1157 item
= make_register_menu_item(buttons
, names
[i
], value
, TRUE
, G_CALLBACK(store_menu_cb
));
1158 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1164 //item = gtk_menu_item_new_with_label(_("Add variable"));
1165 //gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1167 gtk_widget_show_all(menu
);
1168 popup_button_menu(widget
, GTK_MENU(menu
));
1173 recall_menu_cb(GtkMenuItem
*menu
, MathButtons
*buttons
)
1175 math_equation_recall(buttons
->priv
->equation
, g_object_get_data(G_OBJECT(menu
), "register_id"));
1179 void recall_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1182 recall_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1189 menu
= gtk_menu_new();
1190 gtk_menu_set_reserve_toggle_size(GTK_MENU(menu
), FALSE
);
1191 set_tint(menu
, &buttons
->priv
->color_memory
, 1);
1193 names
= math_variables_get_names(math_equation_get_variables(buttons
->priv
->equation
));
1194 if (names
[0] == NULL
) {
1195 item
= gtk_menu_item_new_with_label(/* Text shown in recall menu when no variables defined */
1196 _("No variables defined"));
1197 gtk_widget_set_sensitive(item
, FALSE
);
1198 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1200 for (i
= 0; names
[i
]; i
++) {
1202 value
= math_variables_get_value(math_equation_get_variables(buttons
->priv
->equation
), names
[i
]);
1203 item
= make_register_menu_item(buttons
, names
[i
], value
, TRUE
, G_CALLBACK(recall_menu_cb
));
1204 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1209 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), gtk_separator_menu_item_new());
1210 item
= make_register_menu_item(buttons
, "ans", math_equation_get_answer(buttons
->priv
->equation
), FALSE
, G_CALLBACK(recall_menu_cb
));
1211 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1212 item
= make_register_menu_item(buttons
, "rand", NULL
, FALSE
, G_CALLBACK(recall_menu_cb
));
1213 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1215 gtk_widget_show_all(menu
);
1216 popup_button_menu(widget
, GTK_MENU(menu
));
1220 void shift_left_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1223 shift_left_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1225 if (!buttons
->priv
->shift_left_menu
) {
1229 menu
= buttons
->priv
->shift_left_menu
= gtk_menu_new();
1230 gtk_menu_set_reserve_toggle_size(GTK_MENU(menu
), FALSE
);
1231 set_tint(menu
, &buttons
->priv
->color_action
, 1);
1233 for (i
= 1; i
< 16; i
++) {
1234 GtkWidget
*item
, *label
;
1235 gchar
*format
, *text
;
1238 /* Left Shift Popup: Menu item to shift left by n places (n < 10) */
1239 format
= ngettext("_%d place", "_%d places", i
);
1242 /* Left Shift Popup: Menu item to shift left by n places (n >= 10) */
1243 format
= ngettext("%d place", "%d places", i
);
1245 text
= g_strdup_printf(format
, i
);
1246 label
= gtk_label_new_with_mnemonic(text
);
1248 item
= gtk_menu_item_new();
1249 g_object_set_data(G_OBJECT(item
), "shiftcount", GINT_TO_POINTER(i
));
1250 gtk_container_add(GTK_CONTAINER(item
), label
);
1251 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1252 g_signal_connect(item
, "activate", G_CALLBACK(shift_cb
), buttons
);
1254 gtk_widget_show(label
);
1255 gtk_widget_show(item
);
1260 popup_button_menu(widget
, GTK_MENU(buttons
->priv
->shift_left_menu
));
1264 void shift_right_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1267 shift_right_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1269 if (!buttons
->priv
->shift_right_menu
) {
1273 menu
= buttons
->priv
->shift_right_menu
= gtk_menu_new();
1274 gtk_menu_set_reserve_toggle_size(GTK_MENU(menu
), FALSE
);
1275 set_tint(menu
, &buttons
->priv
->color_action
, 1);
1277 for (i
= 1; i
< 16; i
++) {
1278 GtkWidget
*item
, *label
;
1279 gchar
*format
, *text
;
1282 /* Right Shift Popup: Menu item to shift right by n places (n < 10) */
1283 format
= ngettext("_%d place", "_%d places", i
);
1286 /* Right Shift Popup: Menu item to shift right by n places (n >= 10) */
1287 format
= ngettext("%d place", "%d places", i
);
1289 text
= g_strdup_printf(format
, i
);
1290 label
= gtk_label_new_with_mnemonic(text
);
1292 item
= gtk_menu_item_new();
1293 g_object_set_data(G_OBJECT(item
), "shiftcount", GINT_TO_POINTER(-i
));
1294 gtk_container_add(GTK_CONTAINER(item
), label
);
1295 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1296 g_signal_connect(item
, "activate", G_CALLBACK(shift_cb
), buttons
);
1298 gtk_widget_show(label
);
1299 gtk_widget_show(item
);
1304 popup_button_menu(widget
, GTK_MENU(buttons
->priv
->shift_right_menu
));
1309 insert_function_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1311 math_equation_insert(buttons
->priv
->equation
, g_object_get_data(G_OBJECT(widget
), "function"));
1315 void function_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1318 function_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1320 if (!buttons
->priv
->function_menu
) {
1325 gchar
*name
, *function
;
1328 { /* Tooltip for the integer component button */
1329 N_("Integer Component"), "int " },
1330 { /* Tooltip for the fractional component button */
1331 N_("Fractional Component"), "frac " },
1332 { /* Tooltip for the round button */
1333 N_("Round"), "round " },
1334 { /* Tooltip for the floor button */
1335 N_("Floor"), "floor " },
1336 { /* Tooltip for the ceiling button */
1337 N_("Ceiling"), "ceil " },
1338 { /* Tooltip for the ceiling button */
1339 N_("Sign"), "sgn " },
1343 menu
= buttons
->priv
->function_menu
= gtk_menu_new();
1344 gtk_menu_set_reserve_toggle_size(GTK_MENU(menu
), FALSE
);
1345 set_tint(menu
, &buttons
->priv
->color_function
, 1);
1347 for (i
= 0; functions
[i
].name
!= NULL
; i
++) {
1350 item
= gtk_menu_item_new_with_label(_(functions
[i
].name
));
1351 g_object_set_data(G_OBJECT(item
), "function", g_strdup(functions
[i
].function
));
1352 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1353 g_signal_connect(item
, "activate", G_CALLBACK(insert_function_cb
), buttons
);
1354 gtk_widget_show(item
);
1358 popup_button_menu(widget
, GTK_MENU(buttons
->priv
->function_menu
));
1362 void factorize_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1365 factorize_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1367 math_equation_factorize(buttons
->priv
->equation
);
1371 void digit_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1374 digit_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1376 math_equation_insert_digit(buttons
->priv
->equation
, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
), "calc_digit")));
1380 void numeric_point_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1383 numeric_point_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1385 math_equation_insert_numeric_point(buttons
->priv
->equation
);
1390 void finc_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1393 finc_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1397 name
= g_object_get_data(G_OBJECT(widget
), "finc_dialog");
1398 gtk_dialog_run(GTK_DIALOG(GET_WIDGET(buttons
->priv
->financial_ui
, name
)));
1399 gtk_widget_hide(GTK_WIDGET(GET_WIDGET(buttons
->priv
->financial_ui
, name
)));
1403 void insert_character_code_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1406 insert_character_code_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1408 gtk_window_present(GTK_WINDOW(buttons
->priv
->character_code_dialog
));
1412 void finc_activate_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1415 finc_activate_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1419 dialog
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
), "finc_dialog"));
1420 field
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
), "finc_field"));
1422 if (finc_dialog_fields
[dialog
][field
+1] == NULL
) {
1423 GtkWidget
*dialog_widget
;
1424 dialog_widget
= gtk_widget_get_toplevel(widget
);
1425 if (gtk_widget_is_toplevel(dialog_widget
)) {
1426 gtk_dialog_response(GTK_DIALOG(dialog_widget
),
1432 GtkWidget
*next_widget
;
1433 next_widget
= GET_WIDGET(buttons
->priv
->financial_ui
, finc_dialog_fields
[dialog
][field
+1]);
1434 gtk_widget_grab_focus(next_widget
);
1439 void finc_response_cb(GtkWidget
*widget
, gint response_id
, MathButtons
*buttons
);
1442 finc_response_cb(GtkWidget
*widget
, gint response_id
, MathButtons
*buttons
)
1449 if (response_id
!= GTK_RESPONSE_OK
)
1452 dialog
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget
), "finc_dialog"));
1454 for (i
= 0; i
< 4; i
++) {
1455 if (finc_dialog_fields
[dialog
][i
] == NULL
) {
1458 entry
= GET_WIDGET(buttons
->priv
->financial_ui
, finc_dialog_fields
[dialog
][i
]);
1459 mp_set_from_string(gtk_entry_get_text(GTK_ENTRY(entry
)), 10, &arg
[i
]);
1460 gtk_entry_set_text(GTK_ENTRY(entry
), "0");
1462 gtk_widget_grab_focus(GET_WIDGET(buttons
->priv
->financial_ui
, finc_dialog_fields
[dialog
][0]));
1464 do_finc_expression(buttons
->priv
->equation
, dialog
, &arg
[0], &arg
[1], &arg
[2], &arg
[3]);
1468 void character_code_dialog_response_cb(GtkWidget
*dialog
, gint response_id
, MathButtons
*buttons
);
1471 character_code_dialog_response_cb(GtkWidget
*dialog
, gint response_id
, MathButtons
*buttons
)
1475 text
= gtk_entry_get_text(GTK_ENTRY(buttons
->priv
->character_code_entry
));
1477 if (response_id
== GTK_RESPONSE_OK
) {
1481 mp_set_from_integer(0, &x
);
1483 mp_add_integer(&x
, text
[i
], &x
);
1485 mp_shift(&x
, 8, &x
);
1492 math_equation_insert_number(buttons
->priv
->equation
, &x
);
1495 gtk_widget_hide(dialog
);
1499 void character_code_dialog_activate_cb(GtkWidget
*entry
, MathButtons
*buttons
);
1502 character_code_dialog_activate_cb(GtkWidget
*entry
, MathButtons
*buttons
)
1504 character_code_dialog_response_cb(buttons
->priv
->character_code_dialog
, GTK_RESPONSE_OK
, buttons
);
1508 gboolean
character_code_dialog_delete_cb(GtkWidget
*dialog
, GdkEvent
*event
, MathButtons
*buttons
);
1511 character_code_dialog_delete_cb(GtkWidget
*dialog
, GdkEvent
*event
, MathButtons
*buttons
)
1513 character_code_dialog_response_cb(dialog
, GTK_RESPONSE_CANCEL
, buttons
);
1518 gboolean
bit_toggle_cb(GtkWidget
*event_box
, GdkEventButton
*event
, MathButtons
*buttons
);
1521 bit_toggle_cb(GtkWidget
*event_box
, GdkEventButton
*event
, MathButtons
*buttons
)
1523 math_equation_toggle_bit(buttons
->priv
->equation
, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(event_box
), "bit_index")));
1529 remove_trailing_spaces(MathButtons
*buttons
)
1531 GtkTextMark
*insert_mark
;
1532 GtkTextIter start
, end
;
1533 insert_mark
= gtk_text_buffer_get_insert (GTK_TEXT_BUFFER(buttons
->priv
->equation
));
1534 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(buttons
->priv
->equation
), &end
, insert_mark
);
1536 while (gtk_text_iter_backward_char(&start
)) {
1537 if (!g_unichar_isspace(gtk_text_iter_get_char(&start
)))
1539 gtk_text_buffer_delete(GTK_TEXT_BUFFER(buttons
->priv
->equation
), &start
, &end
);
1544 void set_superscript_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1547 set_superscript_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1549 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
))) {
1550 math_equation_set_number_mode(buttons
->priv
->equation
, SUPERSCRIPT
);
1551 if (!gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(buttons
->priv
->equation
))) {
1552 remove_trailing_spaces(buttons
);
1555 else if (math_equation_get_number_mode(buttons
->priv
->equation
) == SUPERSCRIPT
)
1556 math_equation_set_number_mode(buttons
->priv
->equation
, NORMAL
);
1560 void set_subscript_cb(GtkWidget
*widget
, MathButtons
*buttons
);
1563 set_subscript_cb(GtkWidget
*widget
, MathButtons
*buttons
)
1565 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
))) {
1566 math_equation_set_number_mode(buttons
->priv
->equation
, SUBSCRIPT
);
1567 if (!gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(buttons
->priv
->equation
))) {
1568 remove_trailing_spaces(buttons
);
1571 else if (math_equation_get_number_mode(buttons
->priv
->equation
) == SUBSCRIPT
)
1572 math_equation_set_number_mode(buttons
->priv
->equation
, NORMAL
);
1577 number_mode_changed_cb(MathEquation
*equation
, GParamSpec
*spec
, MathButtons
*buttons
)
1582 mode
= math_equation_get_number_mode(equation
);
1584 for (i
= buttons
->priv
->superscript_toggles
; i
; i
= i
->next
) {
1585 GtkWidget
*widget
= i
->data
;
1586 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), mode
== SUPERSCRIPT
);
1588 for (i
= buttons
->priv
->subscript_toggles
; i
; i
= i
->next
) {
1589 GtkWidget
*widget
= i
->data
;
1590 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget
), mode
== SUBSCRIPT
);
1596 math_buttons_set_property(GObject
*object
,
1598 const GValue
*value
,
1603 self
= MATH_BUTTONS(object
);
1607 self
->priv
->equation
= g_value_get_object(value
);
1608 math_buttons_set_mode(self
, self
->priv
->mode
);
1609 g_signal_connect(self
->priv
->equation
, "notify::display", G_CALLBACK(display_changed_cb
), self
);
1610 g_signal_connect(self
->priv
->equation
, "notify::number-mode", G_CALLBACK(number_mode_changed_cb
), self
);
1611 g_signal_connect(self
->priv
->equation
, "notify::angle-units", G_CALLBACK(display_changed_cb
), self
);
1612 g_signal_connect(self
->priv
->equation
, "notify::number-format", G_CALLBACK(display_changed_cb
), self
);
1613 number_mode_changed_cb(self
->priv
->equation
, NULL
, self
);
1614 display_changed_cb(self
->priv
->equation
, NULL
, self
);
1617 math_buttons_set_mode(self
, g_value_get_int(value
));
1620 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
1627 math_buttons_get_property(GObject
*object
,
1634 self
= MATH_BUTTONS(object
);
1638 g_value_set_object(value
, self
->priv
->equation
);
1641 g_value_set_int(value
, self
->priv
->mode
);
1644 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
1651 math_buttons_class_init(MathButtonsClass
*klass
)
1653 static GEnumValue button_mode_values
[] =
1655 {BASIC
, "basic", "basic"},
1656 {ADVANCED
, "advanced", "advanced"},
1657 {FINANCIAL
, "financial", "financial"},
1658 {PROGRAMMING
, "programming", "programming"},
1661 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
1663 object_class
->get_property
= math_buttons_get_property
;
1664 object_class
->set_property
= math_buttons_set_property
;
1666 g_type_class_add_private(klass
, sizeof(MathButtonsPrivate
));
1668 button_mode_type
= g_enum_register_static("ButtonMode", button_mode_values
);
1670 g_object_class_install_property(object_class
,
1672 g_param_spec_object("equation",
1674 "Equation being controlled",
1675 math_equation_get_type(),
1676 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
1677 g_object_class_install_property(object_class
,
1679 g_param_spec_enum("mode",
1684 G_PARAM_READWRITE
));
1689 math_buttons_init(MathButtons
*buttons
)
1691 buttons
->priv
= G_TYPE_INSTANCE_GET_PRIVATE(buttons
, math_buttons_get_type(), MathButtonsPrivate
);
1692 buttons
->priv
->programming_base
= 10;
1693 gdk_color_parse("#0000FF", &buttons
->priv
->color_numbers
);
1694 gdk_color_parse("#00FF00", &buttons
->priv
->color_action
);
1695 gdk_color_parse("#FF0000", &buttons
->priv
->color_operator
);
1696 gdk_color_parse("#00FFFF", &buttons
->priv
->color_function
);
1697 gdk_color_parse("#FF00FF", &buttons
->priv
->color_memory
);
1698 gdk_color_parse("#FFFFFF", &buttons
->priv
->color_group
);
1699 g_signal_connect(G_OBJECT(buttons
), "show", G_CALLBACK(load_buttons
), NULL
);