2 * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * Copyright (C) 2008-2011 Robert Ancell.
5 * This program is free software: you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation, either version 2 of the License, or (at your option) any later
8 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
12 #include <glib/gi18n.h>
14 #include <gdk/gdkkeysyms.h>
16 #include "math-window.h"
17 #include "math-preferences.h"
24 struct MathWindowPrivate
27 MathEquation
*equation
;
30 MathPreferencesDialog
*preferences_dialog
;
31 gboolean right_aligned
;
32 GtkWidget
*mode_basic_menu_item
, *mode_advanced_menu_item
, *mode_financial_menu_item
, *mode_programming_menu_item
;
35 G_DEFINE_TYPE (MathWindow
, math_window
, GTK_TYPE_WINDOW
);
42 static guint signals
[LAST_SIGNAL
] = { 0, };
46 math_window_new(MathEquation
*equation
)
48 return g_object_new(math_window_get_type(), "equation", equation
, NULL
);
53 math_window_get_menu_bar(MathWindow
*window
)
55 g_return_val_if_fail(window
!= NULL
, NULL
);
56 return window
->priv
->menu_bar
;
61 math_window_get_equation(MathWindow
*window
)
63 g_return_val_if_fail(window
!= NULL
, NULL
);
64 return window
->priv
->equation
;
69 math_window_get_display(MathWindow
*window
)
71 g_return_val_if_fail(window
!= NULL
, NULL
);
72 return window
->priv
->display
;
77 math_window_get_buttons(MathWindow
*window
)
79 g_return_val_if_fail(window
!= NULL
, NULL
);
80 return window
->priv
->buttons
;
85 math_window_critical_error(MathWindow
*window
, const gchar
*title
, const gchar
*contents
)
89 g_return_if_fail(window
!= NULL
);
90 g_return_if_fail(title
!= NULL
);
91 g_return_if_fail(contents
!= NULL
);
93 dialog
= gtk_message_dialog_new(NULL
, 0,
97 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog
),
99 gtk_dialog_add_buttons(GTK_DIALOG(dialog
), GTK_STOCK_QUIT
, GTK_RESPONSE_ACCEPT
, NULL
);
101 gtk_dialog_run(GTK_DIALOG(dialog
));
103 g_signal_emit(window
, signals
[QUIT
], 0);
108 copy_cb(GtkWidget
*widget
, MathWindow
*window
)
110 math_equation_copy(window
->priv
->equation
);
115 paste_cb(GtkWidget
*widget
, MathWindow
*window
)
117 math_equation_paste(window
->priv
->equation
);
122 undo_cb(GtkWidget
*widget
, MathWindow
*window
)
124 math_equation_undo(window
->priv
->equation
);
129 redo_cb(GtkWidget
*widget
, MathWindow
*window
)
131 math_equation_redo(window
->priv
->equation
);
136 mode_changed_cb(GtkWidget
*menu
, MathWindow
*window
)
140 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu
)))
143 mode
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu
), "calcmode"));
144 math_buttons_set_mode(window
->priv
->buttons
, mode
);
149 show_preferences_cb(GtkMenuItem
*menu
, MathWindow
*window
)
151 if (!window
->priv
->preferences_dialog
) {
152 window
->priv
->preferences_dialog
= math_preferences_dialog_new(window
->priv
->equation
);
153 gtk_window_set_transient_for(GTK_WINDOW(window
->priv
->preferences_dialog
), GTK_WINDOW(window
));
155 gtk_window_present(GTK_WINDOW(window
->priv
->preferences_dialog
));
160 help_cb(GtkWidget
*widget
, MathWindow
*window
)
163 GError
*error
= NULL
;
165 screen
= gtk_widget_get_screen(GTK_WIDGET(window
));
166 gtk_show_uri(screen
, "help:gcalctool", gtk_get_current_event_time(), &error
);
171 /* Translators: Error message displayed when unable to launch help browser */
172 const char *message
= _("Unable to open help file");
174 d
= gtk_message_dialog_new(GTK_WINDOW (window
),
175 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
176 GTK_MESSAGE_ERROR
, GTK_BUTTONS_CLOSE
,
178 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG (d
),
179 "%s", error
->message
);
180 g_signal_connect(d
, "response", G_CALLBACK(gtk_widget_destroy
), NULL
);
181 gtk_window_present(GTK_WINDOW(d
));
189 about_cb(GtkWidget
*widget
, MathWindow
*window
)
191 const gchar
*authors
[] = {
192 "Rich Burridge <rich.burridge@gmail.com>",
193 "Robert Ancell <robert.ancell@gmail.com>",
194 "Klaus Niederkrüger <kniederk@umpa.ens-lyon.fr>",
195 "Robin Sonefors <ozamosi@flukkost.nu>",
198 const gchar
*documenters
[] = {
203 /* The translator credits. Please translate this with your name(s). */
204 const gchar
*translator_credits
= _("translator-credits");
206 /* The license this software is under (GPL2+) */
207 char *license
= _("Gcalctool is free software; you can redistribute it and/or modify\n"
208 "it under the terms of the GNU General Public License as published by\n"
209 "the Free Software Foundation; either version 2 of the License, or\n"
210 "(at your option) any later version.\n"
212 "Gcalctool is distributed in the hope that it will be useful,\n"
213 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
214 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
215 "GNU General Public License for more details.\n"
217 "You should have received a copy of the GNU General Public License\n"
218 "along with Gcalctool; if not, write to the Free Software Foundation, Inc.,\n"
219 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA");
221 gtk_show_about_dialog(GTK_WINDOW(window
),
223 /* Program name in the about dialog */
227 /* Copyright notice in the about dialog */
228 _("\xc2\xa9 1986–2010 The Gcalctool authors"),
231 /* Short description in the about dialog */
232 _("Calculator with financial and scientific modes."),
234 "documenters", documenters
,
235 "translator_credits", translator_credits
,
236 "logo-icon-name", "accessories-calculator",
242 quit_cb(GtkWidget
*widget
, MathWindow
*window
)
244 g_signal_emit(window
, signals
[QUIT
], 0);
249 key_press_cb(MathWindow
*window
, GdkEventKey
*event
)
252 g_signal_emit_by_name(window
->priv
->display
, "key-press-event", event
, &result
);
254 if (math_buttons_get_mode (window
->priv
->buttons
) == PROGRAMMING
&& (event
->state
& GDK_CONTROL_MASK
) == GDK_CONTROL_MASK
) {
255 switch(event
->keyval
)
259 math_equation_set_base (window
->priv
->equation
, 2);
263 math_equation_set_base (window
->priv
->equation
, 8);
267 math_equation_set_base (window
->priv
->equation
, 10);
271 math_equation_set_base (window
->priv
->equation
, 16);
281 delete_cb(MathWindow
*window
, GdkEvent
*event
)
283 g_signal_emit(window
, signals
[QUIT
], 0);
288 scroll_changed_cb(GtkAdjustment
*adjustment
, MathWindow
*window
)
290 if (window
->priv
->right_aligned
)
291 gtk_adjustment_set_value(adjustment
, gtk_adjustment_get_upper(adjustment
) - gtk_adjustment_get_page_size(adjustment
));
296 scroll_value_changed_cb(GtkAdjustment
*adjustment
, MathWindow
*window
)
298 if (gtk_adjustment_get_value(adjustment
) == gtk_adjustment_get_upper(adjustment
) - gtk_adjustment_get_page_size(adjustment
))
299 window
->priv
->right_aligned
= TRUE
;
301 window
->priv
->right_aligned
= FALSE
;
306 button_mode_changed_cb(MathButtons
*buttons
, GParamSpec
*spec
, MathWindow
*window
)
310 switch(math_buttons_get_mode(buttons
))
314 menu
= window
->priv
->mode_basic_menu_item
;
315 //FIXME: Should it revert to decimal mode? math_equation_set_number_format(window->priv->equation, DEC);
319 menu
= window
->priv
->mode_advanced_menu_item
;
323 menu
= window
->priv
->mode_financial_menu_item
;
327 menu
= window
->priv
->mode_programming_menu_item
;
330 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu
), TRUE
);
335 add_menu(GtkWidget
*menu_bar
, const gchar
*name
)
337 GtkWidget
*menu_item
, *menu
;
339 menu_item
= gtk_menu_item_new_with_mnemonic(name
);
340 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar
), menu_item
);
341 gtk_widget_show(menu_item
);
342 menu
= gtk_menu_new();
343 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item
), menu
);
350 add_menu_item(GtkWidget
*menu
, GtkWidget
*menu_item
, GCallback callback
, gpointer callback_data
)
352 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menu_item
);
353 gtk_widget_show(menu_item
);
355 g_signal_connect(G_OBJECT(menu_item
), "activate", callback
, callback_data
);
361 radio_menu_item_new(GSList
**group
, const gchar
*name
)
363 GtkWidget
*menu_item
;
364 menu_item
= gtk_radio_menu_item_new_with_mnemonic(*group
, name
);
365 *group
= gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menu_item
));
371 create_menu(MathWindow
*window
)
373 GtkAccelGroup
*accel_group
;
374 GtkWidget
*menu
, *menu_item
;
375 GSList
*group
= NULL
;
377 accel_group
= gtk_accel_group_new();
378 gtk_window_add_accel_group(GTK_WINDOW(window
), accel_group
);
380 /* Calculator menu */
381 #define CALCULATOR_MENU_LABEL _("_Calculator")
383 #define MODE_MENU_LABEL _("_Mode")
384 /* Help menu label */
385 #define HELP_MENU_LABEL _("_Help")
386 /* Basic menu label */
387 #define MODE_BASIC_LABEL _("_Basic")
388 /* Advanced menu label */
389 #define MODE_ADVANCED_LABEL _("_Advanced")
390 /* Financial menu label */
391 #define MODE_FINANCIAL_LABEL _("_Financial")
392 /* Programming menu label */
393 #define MODE_PROGRAMMING_LABEL _("_Programming")
394 /* Help>Contents menu label */
395 #define HELP_CONTENTS_LABEL _("_Contents")
397 menu
= add_menu(window
->priv
->menu_bar
, CALCULATOR_MENU_LABEL
);
398 add_menu_item(menu
, gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY
, accel_group
), G_CALLBACK(copy_cb
), window
);
399 add_menu_item(menu
, gtk_image_menu_item_new_from_stock(GTK_STOCK_PASTE
, accel_group
), G_CALLBACK(paste_cb
), window
);
400 menu_item
= add_menu_item(menu
, gtk_image_menu_item_new_from_stock(GTK_STOCK_UNDO
, accel_group
), G_CALLBACK(undo_cb
), window
);
401 gtk_widget_add_accelerator(menu_item
, "activate", accel_group
, GDK_KEY_z
, GDK_CONTROL_MASK
, GTK_ACCEL_VISIBLE
);
402 menu_item
= add_menu_item(menu
, gtk_image_menu_item_new_from_stock(GTK_STOCK_REDO
, accel_group
), G_CALLBACK(redo_cb
), window
);
403 gtk_widget_add_accelerator(menu_item
, "activate", accel_group
, GDK_KEY_z
, GDK_CONTROL_MASK
| GDK_SHIFT_MASK
, GTK_ACCEL_VISIBLE
);
404 add_menu_item(menu
, gtk_separator_menu_item_new(), NULL
, NULL
);
405 add_menu_item(menu
, gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES
, accel_group
), G_CALLBACK(show_preferences_cb
), window
);
406 add_menu_item(menu
, gtk_separator_menu_item_new(), NULL
, NULL
);
407 menu_item
= add_menu_item(menu
, gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT
, accel_group
), G_CALLBACK(quit_cb
), window
);
408 gtk_widget_add_accelerator(menu_item
, "activate", accel_group
, GDK_KEY_w
, GDK_CONTROL_MASK
, 0);
410 menu
= add_menu(window
->priv
->menu_bar
, MODE_MENU_LABEL
);
411 window
->priv
->mode_basic_menu_item
= add_menu_item(menu
, radio_menu_item_new(&group
, MODE_BASIC_LABEL
), G_CALLBACK(mode_changed_cb
), window
);
412 g_object_set_data(G_OBJECT(window
->priv
->mode_basic_menu_item
), "calcmode", GINT_TO_POINTER(BASIC
));
413 window
->priv
->mode_advanced_menu_item
= add_menu_item(menu
, radio_menu_item_new(&group
, MODE_ADVANCED_LABEL
), G_CALLBACK(mode_changed_cb
), window
);
414 g_object_set_data(G_OBJECT(window
->priv
->mode_advanced_menu_item
), "calcmode", GINT_TO_POINTER(ADVANCED
));
415 window
->priv
->mode_financial_menu_item
= add_menu_item(menu
, radio_menu_item_new(&group
, MODE_FINANCIAL_LABEL
), G_CALLBACK(mode_changed_cb
), window
);
416 g_object_set_data(G_OBJECT(window
->priv
->mode_financial_menu_item
), "calcmode", GINT_TO_POINTER(FINANCIAL
));
417 window
->priv
->mode_programming_menu_item
= add_menu_item(menu
, radio_menu_item_new(&group
, MODE_PROGRAMMING_LABEL
), G_CALLBACK(mode_changed_cb
), window
);
418 g_object_set_data(G_OBJECT(window
->priv
->mode_programming_menu_item
), "calcmode", GINT_TO_POINTER(PROGRAMMING
));
420 menu
= add_menu(window
->priv
->menu_bar
, HELP_MENU_LABEL
);
421 menu_item
= add_menu_item(menu
, gtk_menu_item_new_with_mnemonic(HELP_CONTENTS_LABEL
), G_CALLBACK(help_cb
), window
);
422 gtk_widget_add_accelerator(menu_item
, "activate", accel_group
, GDK_KEY_F1
, 0, GTK_ACCEL_VISIBLE
);
423 add_menu_item(menu
, gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT
, accel_group
), G_CALLBACK(about_cb
), window
);
428 create_gui(MathWindow
*window
)
430 GtkWidget
*main_vbox
, *vbox
;
431 GtkWidget
*scrolled_window
;
433 main_vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0);
434 gtk_container_add(GTK_CONTAINER(window
), main_vbox
);
435 gtk_widget_show(main_vbox
);
437 window
->priv
->menu_bar
= gtk_menu_bar_new();
438 gtk_box_pack_start(GTK_BOX(main_vbox
), window
->priv
->menu_bar
, FALSE
, FALSE
, 0);
439 gtk_widget_show(window
->priv
->menu_bar
);
443 vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 6);
444 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 6);
445 gtk_box_pack_start(GTK_BOX(main_vbox
), vbox
, TRUE
, TRUE
, 0);
446 gtk_widget_show(vbox
);
448 scrolled_window
= gtk_scrolled_window_new(NULL
, NULL
);
449 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_NEVER
);
450 gtk_box_pack_start(GTK_BOX(vbox
), GTK_WIDGET(scrolled_window
), FALSE
, FALSE
, 0);
451 g_signal_connect(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(scrolled_window
)), "changed", G_CALLBACK(scroll_changed_cb
), window
);
452 g_signal_connect(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(scrolled_window
)), "value-changed", G_CALLBACK(scroll_value_changed_cb
), window
);
453 window
->priv
->right_aligned
= TRUE
;
454 gtk_widget_show(scrolled_window
);
456 window
->priv
->display
= math_display_new_with_equation(window
->priv
->equation
);
457 gtk_container_add(GTK_CONTAINER(scrolled_window
), GTK_WIDGET(window
->priv
->display
));
458 gtk_widget_show(GTK_WIDGET(window
->priv
->display
));
460 window
->priv
->buttons
= math_buttons_new(window
->priv
->equation
);
461 g_signal_connect(window
->priv
->buttons
, "notify::mode", G_CALLBACK(button_mode_changed_cb
), window
);
462 button_mode_changed_cb(window
->priv
->buttons
, NULL
, window
);
463 gtk_box_pack_start(GTK_BOX(vbox
), GTK_WIDGET(window
->priv
->buttons
), TRUE
, TRUE
, 0);
464 gtk_widget_show(GTK_WIDGET(window
->priv
->buttons
));
469 math_window_set_property(GObject
*object
,
476 self
= MATH_WINDOW(object
);
480 self
->priv
->equation
= g_value_get_object(value
);
484 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
491 math_window_get_property(GObject
*object
,
498 self
= MATH_WINDOW(object
);
502 g_value_set_object(value
, self
->priv
->equation
);
505 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
512 math_window_class_init(MathWindowClass
*klass
)
514 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
516 object_class
->get_property
= math_window_get_property
;
517 object_class
->set_property
= math_window_set_property
;
519 g_type_class_add_private(klass
, sizeof(MathWindowPrivate
));
521 g_object_class_install_property(object_class
,
523 g_param_spec_object("equation",
525 "Equation being calculated",
526 math_equation_get_type(),
527 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
531 G_TYPE_FROM_CLASS (klass
),
533 G_STRUCT_OFFSET (MathWindowClass
, quit
),
535 g_cclosure_marshal_VOID__VOID
,
541 math_window_init(MathWindow
*window
)
543 window
->priv
= G_TYPE_INSTANCE_GET_PRIVATE(window
, math_window_get_type(), MathWindowPrivate
);
544 gtk_window_set_title(GTK_WINDOW(window
),
545 /* Title of main window */
547 gtk_window_set_icon_name(GTK_WINDOW(window
), "accessories-calculator");
548 gtk_window_set_role(GTK_WINDOW(window
), "gcalctool");
549 gtk_window_set_resizable(GTK_WINDOW(window
), FALSE
);
550 g_signal_connect_after(G_OBJECT(window
), "key-press-event", G_CALLBACK(key_press_cb
), NULL
);
551 g_signal_connect(G_OBJECT(window
), "delete-event", G_CALLBACK(delete_cb
), NULL
);