[gcalctool] More GObjectification



commit 59197f2121178df3dc90e8dc094ab90e958d4bd1
Author: Robert Ancell <robert ancell gmail com>
Date:   Tue Apr 13 13:25:52 2010 +0800

    More GObjectification

 data/Makefile.am            |    1 -
 data/gcalctool.ui           |  179 ---------------
 src/Makefile.am             |    4 +-
 src/calctool.c              |   60 +++++-
 src/get.c                   |   51 -----
 src/get.h                   |    4 -
 src/math-buttons.c          |   79 ++++++-
 src/math-display.c          |    9 +-
 src/math-display.h          |    3 +-
 src/math-equation.c         |   32 ++--
 src/math-preferences.c      |    3 +-
 src/math-window.c           |  510 +++++++++++++++++++++++++++++++++++++++++++
 src/{ui.h => math-window.h} |   36 ++--
 src/ui.c                    |  390 ---------------------------------
 14 files changed, 683 insertions(+), 678 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 4ec30f6..d06c5da 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -1,6 +1,5 @@
 uidir = $(datadir)/gcalctool
 ui_DATA = \
-	gcalctool.ui \
 	preferences.ui \
 	buttons-basic.ui \
 	buttons-advanced.ui \
diff --git a/src/Makefile.am b/src/Makefile.am
index baf7dd0..886a71f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,6 +21,8 @@ gcalctool_SOURCES = \
 	math-equation.h \
 	math-preferences.c \
 	math-preferences.h \
+	math-window.c \
+	math-window.h \
 	mp.c \
 	mp.h \
 	mp-binary.c \
@@ -38,8 +40,6 @@ gcalctool_SOURCES = \
 	financial.h \
 	register.c \
 	register.h \
-	ui.c \
-	ui.h \
 	unittest.c \
 	unittest.h
 
diff --git a/src/calctool.c b/src/calctool.c
index ad41287..cd4b821 100644
--- a/src/calctool.c
+++ b/src/calctool.c
@@ -26,11 +26,14 @@
 #include "currency.h"
 #include "unittest.h"
 #include "get.h"
-#include "ui.h"
+#include "math-window.h"
 #include "register.h"
 #include "mp-equation.h"
 
 
+static MathEquation *equation;
+static MathWindow *window;
+
 static void
 version(const gchar *progname)
 {
@@ -169,10 +172,30 @@ get_options(int argc, char *argv[])
 }
 
 
+static void
+quit_cb(MathWindow *window)
+{
+    set_int_resource(R_ACCURACY, math_equation_get_accuracy(equation));
+    set_int_resource(R_WORDLEN, math_equation_get_word_size(equation));
+    set_boolean_resource(R_TSEP, math_equation_get_show_thousands_separators(equation));
+    set_boolean_resource(R_ZEROES, math_equation_get_show_trailing_zeroes(equation));
+    //FIXME
+    //set_resource(R_DISPLAY, "?");
+    //set_resource(R_TRIG, "?");
+    //set_resource(R_MODE, "?");
+
+    currency_free_resources();
+    gtk_main_quit();
+}
+
+
 int
 main(int argc, char **argv)
 {
-    GCalctoolUI *ui;
+    int accuracy = 9, base = 10, word_size = 64;
+    gchar *angle_units;
+    gboolean show_tsep = FALSE, show_zeroes = FALSE;
+    gchar *number_format, *angle_unit, *button_mode;
   
     g_type_init();
 
@@ -185,12 +208,37 @@ main(int argc, char **argv)
 
     resources_init();
     register_init();
-    ui_gtk_init(&argc, &argv);
     get_options(argc, argv);
-    ui = ui_new();
-    ui_start(ui);
   
-    currency_free_resources();
+    equation = math_equation_new();
+    get_int_resource(R_ACCURACY, &accuracy);
+    get_int_resource(R_WORDLEN, &word_size);
+    get_boolean_resource(R_TSEP, &show_tsep);  
+    get_boolean_resource(R_ZEROES, &show_zeroes);
+    number_format = get_resource(R_DISPLAY);
+    angle_units = get_resource(R_TRIG);
+    button_mode = get_resource(R_MODE);
+
+    math_equation_set_accuracy(equation, accuracy);
+    math_equation_set_word_size(equation, word_size);
+    math_equation_set_show_thousands_separators(equation, show_tsep);
+    math_equation_set_show_trailing_zeroes(equation, show_zeroes);
+    //FIXME
+    //math_equation_set_number_format(equation, ?);
+    //math_equation_set_angle_units(equation, ?);
+
+    g_free(number_format);
+    g_free(angle_units);
+    g_free(button_mode);
+
+    gtk_init(&argc, &argv);
+
+    window = math_window_new(equation);
+    g_signal_connect(G_OBJECT(window), "quit", G_CALLBACK(quit_cb), NULL);
+    //FIXMEmath_buttons_set_mode(math_window_get_buttons(window), ADVANCED); // FIXME: We load the basic buttons even if we immediately switch to the next type
+
+    gtk_widget_show(GTK_WIDGET(window));
+    gtk_main();
 
     return(0);
 }
diff --git a/src/get.c b/src/get.c
index cb575a6..042d98e 100644
--- a/src/get.c
+++ b/src/get.c
@@ -31,8 +31,6 @@
 #include <gconf/gconf-client.h>
 
 #include "get.h"
-#include "register.h"
-#include "mp.h"
 
 #define MAXLINE 1024
 
@@ -140,55 +138,6 @@ get_enumerated_resource(const char *key, const char *values[], int *value)
 }
 
 
-/* Return the radix character. For most locales, this is a period.
- * If nl_langinfo(RADIXCHAR) returns an empty string, return ",".
- */
-const char *
-get_radix()
-{
-    const char *radix;
-
-    setlocale(LC_NUMERIC, "");
-    if ((radix = nl_langinfo(RADIXCHAR)) != NULL) {
-        radix = g_locale_to_utf8(radix, -1, NULL, NULL, NULL);
-    }
-
-    if (radix == NULL || radix[0] == '\0') {
-        return(".");
-    } else {
-        return(radix);
-    }
-}
-
-
-/* Return the thousands separator string. For most locales, this is a
- * comma.
- */
-const char *
-get_tsep()
-{
-    char *tsep;
-
-    setlocale(LC_NUMERIC, "");
-    if ((tsep = nl_langinfo(THOUSEP)) != NULL) {
-        tsep = g_locale_to_utf8(tsep, -1, NULL, NULL, NULL);
-    }
-
-    if (tsep == NULL) {
-        return("");
-    } else {
-        return(tsep);
-    }
-}
-
-
-int
-get_tsep_count()
-{
-    return 3;
-}
-
-
 void
 resources_init()
 {
diff --git a/src/get.h b/src/get.h
index 5d5044f..9f04847 100644
--- a/src/get.h
+++ b/src/get.h
@@ -40,8 +40,4 @@ int get_int_resource(const char *key, int *value);
 int get_boolean_resource(const char *key, int *value);
 int get_enumerated_resource(const char *key, const char *values[], int *value);
 
-const char *get_radix();
-const char *get_tsep();
-int get_tsep_count();
-
 #endif /* GET_H */
diff --git a/src/math-buttons.c b/src/math-buttons.c
index f09a1bb..df9a32c 100644
--- a/src/math-buttons.c
+++ b/src/math-buttons.c
@@ -23,9 +23,12 @@
 
 enum {
     PROP_0,
-    PROP_EQUATION
+    PROP_EQUATION,
+    PROP_MODE
 };
 
+static GType button_mode_type;
+
 #define MAXBITS 64      /* Bit panel: number of bit fields. */
 #define MAX_REGISTERS 6 // FIXME: Obsolete once use a hash table
 
@@ -39,6 +42,7 @@ struct MathButtonsPrivate
     GdkColor colour_numbers, colour_action, colour_operator, colour_function, colour_memory, colour_group;
 
     GtkWidget *bas_panel, *adv_panel, *fin_panel, *prog_panel;
+    GtkWidget *active_panel;
 
     GtkWidget *store_menu, *recall_menu;
     GtkWidget *recall_menu_labels[MAX_REGISTERS];
@@ -163,6 +167,8 @@ get_buttons(MathButtons *buttons, ButtonMode mode)
     case PROGRAMMING:
         return buttons->priv->prog_panel;
     }
+  
+    return NULL;
 }
 
 
@@ -285,7 +291,7 @@ load_finc_dialogs(MathButtons *buttons)
 }
 
 
-static void
+static GtkWidget *
 load_mode(MathButtons *buttons, ButtonMode mode)
 {
     GtkBuilder *builder, **builder_ptr;
@@ -321,6 +327,9 @@ load_mode(MathButtons *buttons, ButtonMode mode)
         panel = &buttons->priv->prog_panel;
         break;
     }
+  
+    if (*panel)
+        return *panel;
 
     builder = *builder_ptr = gtk_builder_new();
     // FIXME: Show dialog if failed to load
@@ -455,6 +464,32 @@ load_mode(MathButtons *buttons, ButtonMode mode)
     }
 
     gtk_builder_connect_signals(builder, buttons);
+  
+    return *panel;
+}
+
+
+
+static void
+load_buttons(MathButtons *buttons)
+{
+    GtkWidget *panel;
+
+    if (!gtk_widget_get_visible(GTK_WIDGET(buttons)))
+        return;
+
+    panel = load_mode(buttons, buttons->priv->mode);
+    if (buttons->priv->active_panel == panel)
+        return;
+
+    /* Hide old buttons */
+    if (buttons->priv->active_panel)
+        gtk_widget_hide(buttons->priv->active_panel);
+
+    /* Load and display new buttons */
+    buttons->priv->active_panel = panel;
+    if (panel)
+        gtk_widget_show(panel);
 }
 
 
@@ -462,18 +497,16 @@ void
 math_buttons_set_mode(MathButtons *buttons, ButtonMode mode)
 {
     ButtonMode old_mode;
+ 
+    if (buttons->priv->mode == mode)
+        return;
 
     old_mode = buttons->priv->mode;
     buttons->priv->mode = mode;
 
-    /* Hide the existing mode */
-    if (get_buttons(buttons, old_mode))
-        gtk_widget_hide(get_buttons(buttons, old_mode));
-  
-    /* Create the new mode if necessary */
-    if (!get_buttons(buttons, mode))
-        load_mode(buttons, mode);
-    gtk_widget_show(get_buttons(buttons, mode));
+    load_buttons(buttons);
+
+    g_object_notify(G_OBJECT(buttons), "mode");
 }
 
 
@@ -1144,11 +1177,15 @@ math_buttons_set_property (GObject      *object,
     switch (prop_id) {
     case PROP_EQUATION:
         self->priv->equation = g_value_get_object (value);
+        math_buttons_set_mode(self, self->priv->mode);
         g_signal_connect(self->priv->equation, "notify::number-mode", G_CALLBACK(number_mode_changed_cb), self);
         g_signal_connect(self->priv->equation, "notify::display", G_CALLBACK(display_changed_cb), self);
         number_mode_changed_cb(self->priv->equation, NULL, self);
         display_changed_cb(self->priv->equation, NULL, self);
         break;
+    case PROP_MODE:
+        math_buttons_set_mode(self, g_value_get_int (value));
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -1170,6 +1207,9 @@ math_buttons_get_property (GObject    *object,
     case PROP_EQUATION:
         g_value_set_object (value, self->priv->equation);
         break;
+    case PROP_MODE:
+        g_value_set_int (value, self->priv->mode);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -1180,6 +1220,14 @@ math_buttons_get_property (GObject    *object,
 static void
 math_buttons_class_init (MathButtonsClass *klass)
 {
+    static GEnumValue button_mode_values[] =
+    {
+      {BASIC,       "basic",       "basic"},
+      {ADVANCED,    "advanced",    "advanced"},
+      {FINANCIAL,   "financial",   "financial"},
+      {PROGRAMMING, "programming", "programming"},
+      {0, NULL, NULL}
+    };
     GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
     object_class->get_property = math_buttons_get_property;
@@ -1187,6 +1235,8 @@ math_buttons_class_init (MathButtonsClass *klass)
 
     g_type_class_add_private (klass, sizeof (MathButtonsPrivate));
 
+    button_mode_type = g_enum_register_static("ButtonMode", button_mode_values);
+
     g_object_class_install_property (object_class,
                                      PROP_EQUATION,
                                      g_param_spec_object ("equation",
@@ -1194,6 +1244,14 @@ math_buttons_class_init (MathButtonsClass *klass)
                                                           "Equation being controlled",
                                                           math_equation_get_type(),
                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property (object_class,
+                                     PROP_MODE,
+                                     g_param_spec_enum ("mode",
+                                                        "mode",
+                                                        "Button mode",
+                                                        button_mode_type,
+                                                        BASIC,
+                                                        G_PARAM_READWRITE));
 }
 
 
@@ -1219,4 +1277,5 @@ math_buttons_init (MathButtons *buttons)
     buttons->priv->colour_group.red = 65535;
     buttons->priv->colour_group.green = 65535;
     buttons->priv->colour_group.blue = 65535;
+    g_signal_connect(G_OBJECT(buttons), "show", G_CALLBACK(load_buttons), NULL);
 }
diff --git a/src/math-display.c b/src/math-display.c
index c62e9f8..3452a17 100644
--- a/src/math-display.c
+++ b/src/math-display.c
@@ -40,7 +40,14 @@ G_DEFINE_TYPE (MathDisplay, math_display, GTK_TYPE_VBOX);
 #define GET_WIDGET(ui, name)  GTK_WIDGET(gtk_builder_get_object(ui, name))
 
 MathDisplay *
-math_display_new(MathEquation *equation)
+math_display_new()
+{
+    return g_object_new (math_display_get_type(), "equation", math_equation_new(), NULL);
+}
+
+
+MathDisplay *
+math_display_new_with_equation(MathEquation *equation)
 {
     return g_object_new (math_display_get_type(), "equation", equation, NULL);
 }
diff --git a/src/math-display.h b/src/math-display.h
index 548509a..67e2aba 100644
--- a/src/math-display.h
+++ b/src/math-display.h
@@ -42,7 +42,8 @@ typedef struct
 } MathDisplayClass;
 
 GType math_display_get_type();
-MathDisplay *math_display_new(MathEquation *equation);
+MathDisplay *math_display_new();
+MathDisplay *math_display_new_with_equation(MathEquation *equation);
 MathEquation *math_display_get_equation(MathDisplay *display);
 
 #endif /* MATH_DISPLAY_H */
diff --git a/src/math-equation.c b/src/math-equation.c
index c2d5e6f..878ebb9 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -24,15 +24,14 @@
 #include <math.h>
 #include <errno.h>
 #include <glib.h>
+#include <langinfo.h>
 
 #include "math-equation.h"
 
 #include "mp.h"
-#include "ui.h"
 #include "mp-equation.h"
 #include "register.h"
 #include "currency.h"
-#include "get.h"
 
 
 enum {
@@ -1163,18 +1162,18 @@ math_equation_class_init (MathEquationClass *klass)
     };
     static GEnumValue number_format_values[] =
     {
-      {DEC, "DEC", "DEC"},
-      {BIN, "BIN", "BIN"},
-      {OCT, "OCT", "OCT"},
-      {HEX, "HEX", "HEX"},
-      {SCI, "SCI", "SCI"},
-      {ENG, "ENG", "ENG"},
+      {DEC, "decimal",     "decimal"},
+      {BIN, "binary",      "binary"},
+      {OCT, "octal",       "octal"},
+      {HEX, "hexadecimal", "hexadecimal"},
+      {SCI, "scientific",  "scientific"},
+      {ENG, "engineering", "engineering"},
       {0, NULL, NULL}
     };
     static GEnumValue angle_unit_values[] =
     {
-      {MP_RADIANS, "radians", "radians"},
-      {MP_DEGREES, "degrees", "degrees"},
+      {MP_RADIANS,  "radians",  "radians"},
+      {MP_DEGREES,  "degrees",  "degrees"},
       {MP_GRADIANS, "gradians", "gradians"},
       {0, NULL, NULL}
     };
@@ -1304,6 +1303,7 @@ math_equation_init(MathEquation *equation)
     /* Digits localized for the given language */
     const char *digit_values = _("0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F");
     const char *default_digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
+    gchar *radix, *tsep;
     gchar **digits;
     gboolean use_default_digits = FALSE;
     int i;
@@ -1324,10 +1324,14 @@ math_equation_init(MathEquation *equation)
     }
     g_strfreev(digits);
 
-    // FIXME: Take out of get.c
-    equation->priv->radix = get_radix();
-    equation->priv->tsep = get_tsep();
-    equation->priv->tsep_count = get_tsep_count();
+    setlocale(LC_NUMERIC, "");
+
+    radix = nl_langinfo(RADIXCHAR);
+    equation->priv->radix = radix ? g_locale_to_utf8(radix, -1, NULL, NULL, NULL) : g_strdup(".");
+    tsep = nl_langinfo(THOUSEP);
+    equation->priv->tsep = tsep ? g_locale_to_utf8(tsep, -1, NULL, NULL, NULL) : g_strdup(",");
+
+    equation->priv->tsep_count = 3;
 
     // Use GtkClipboad instead
     equation->priv->primary_atom = gdk_atom_intern("PRIMARY", FALSE);
diff --git a/src/math-preferences.c b/src/math-preferences.c
index 91a1b7c..ee25c30 100644
--- a/src/math-preferences.c
+++ b/src/math-preferences.c
@@ -231,7 +231,8 @@ create_gui(MathPreferencesDialog *dialog)
 
     gtk_window_set_title(GTK_WINDOW(dialog),
                          /* Title of preferences dialog */
-                         _("Preferences")); 
+                         _("Preferences"));
+    gtk_window_set_icon_name(GTK_WINDOW(dialog), "accessories-calculator");
     gtk_container_set_border_width(GTK_CONTAINER(dialog), 8);
     gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
     gtk_dialog_add_button(GTK_DIALOG(dialog),
diff --git a/src/math-window.c b/src/math-window.c
new file mode 100644
index 0000000..36cd3eb
--- /dev/null
+++ b/src/math-window.c
@@ -0,0 +1,510 @@
+/*  Copyright (c) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
+ *  Copyright (c) 2008-2009 Robert Ancell
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ *  02111-1307, USA.
+ */
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "math-window.h"
+#include "math-preferences.h"
+
+enum {
+    PROP_0,
+    PROP_EQUATION
+};
+
+struct MathWindowPrivate
+{
+    GtkWidget *menu_bar;
+    MathEquation *equation;
+    MathDisplay *display;
+    MathButtons *buttons;
+    MathPreferencesDialog *preferences_dialog;
+    gboolean right_aligned;
+    GtkWidget *mode_basic_menu_item, *mode_advanced_menu_item, *mode_financial_menu_item, *mode_programming_menu_item;
+};
+
+G_DEFINE_TYPE (MathWindow, math_window, GTK_TYPE_WINDOW);
+
+enum {
+    QUIT,
+    LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0, };
+
+
+MathWindow *
+math_window_new(MathEquation *equation)
+{
+    return g_object_new (math_window_get_type(), "equation", equation, NULL);
+}
+
+
+GtkWidget *
+math_window_get_menu_bar(MathWindow *window)
+{
+   return window->priv->menu_bar;
+}
+
+
+MathEquation *math_window_get_equation(MathWindow *window)
+{
+    return window->priv->equation;
+}
+
+
+MathDisplay *
+math_window_get_display(MathWindow *window)
+{
+    return window->priv->display;
+}
+
+
+MathButtons *
+math_window_get_buttons(MathWindow *window)
+{
+    return window->priv->buttons;
+}
+
+
+void
+math_window_critical_error(MathWindow *window, const gchar *title, const gchar *contents)
+{
+    GtkWidget *dialog;
+
+    dialog = gtk_message_dialog_new(NULL, 0,
+                                    GTK_MESSAGE_ERROR,
+                                    GTK_BUTTONS_NONE,
+                                    "%s", title);
+    gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
+                                             "%s", contents);
+    gtk_dialog_add_buttons(GTK_DIALOG(dialog), GTK_STOCK_QUIT, GTK_RESPONSE_ACCEPT, NULL);
+
+    gtk_dialog_run(GTK_DIALOG(dialog));
+
+    g_signal_emit(window, signals[QUIT], 0);
+}
+
+
+static void
+copy_cb(GtkWidget *widget, MathWindow *window)
+{
+    math_equation_copy(window->priv->equation);
+}
+
+
+static void
+paste_cb(GtkWidget *widget, MathWindow *window)
+{
+    math_equation_paste(window->priv->equation);
+}
+
+
+static void
+mode_changed_cb(GtkWidget *menu, MathWindow *window)
+{
+    int mode;
+
+    if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu)))
+        return;
+
+    mode = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu), "calcmode"));
+    math_buttons_set_mode(window->priv->buttons, mode);
+}
+
+
+static void
+show_preferences_cb(GtkMenuItem *menu, MathWindow *window)
+{
+    if (!window->priv->preferences_dialog) {
+        window->priv->preferences_dialog = math_preferences_dialog_new(window->priv->equation);
+        gtk_window_set_transient_for(GTK_WINDOW(window->priv->preferences_dialog), GTK_WINDOW(window));
+    }
+    gtk_window_present(GTK_WINDOW(window->priv->preferences_dialog));
+}
+
+
+static void
+help_cb(GtkWidget *widget, MathWindow *window)
+{
+    GdkScreen *screen;
+    GError *error = NULL;
+
+    screen = gtk_widget_get_screen (GTK_WIDGET (window));
+    gtk_show_uri (screen, "ghelp:gcalctool", gtk_get_current_event_time (), &error);
+
+    if (error != NULL)
+    {
+        GtkWidget *d;
+        /* Translators: Error message displayed when unable to launch help browser */
+        const char *message = _("Unable to open help file");
+
+        d = gtk_message_dialog_new (GTK_WINDOW (window),
+                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                    GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+                                    "%s", message);
+        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (d),
+                                                  "%s", error->message);
+        g_signal_connect (d, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+        gtk_window_present (GTK_WINDOW (d));
+
+        g_error_free (error);
+    }
+}
+
+
+static void
+about_cb(GtkWidget *widget, MathWindow *window)
+{
+    const gchar *authors[] = {
+        "Rich Burridge <rich burridge sun com>",
+        "Robert Ancell <robert ancell gmail com>",
+        "Klaus Niederkrüger <kniederk umpa ens-lyon fr>",
+        NULL
+    };
+    const gchar *documenters[] = {
+        "Sun Microsystems",
+        NULL
+    };
+
+    /* The translator credits. Please translate this with your name(s). */
+    const gchar *translator_credits = _("translator-credits");
+
+    /* The license this software is under (GPL2+) */
+    char *license = _("Gcalctool is free software; you can redistribute it and/or modify\n"
+          "it under the terms of the GNU General Public License as published by\n"
+          "the Free Software Foundation; either version 2 of the License, or\n"
+          "(at your option) any later version.\n"
+          "\n"
+          "Gcalctool is distributed in the hope that it will be useful,\n"
+          "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+          "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+          "GNU General Public License for more details.\n"
+          "\n"
+          "You should have received a copy of the GNU General Public License\n"
+          "along with Gcalctool; if not, write to the Free Software Foundation, Inc.,\n"
+          "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA");
+
+    gtk_show_about_dialog(GTK_WINDOW(window),
+                          "name",
+                          /* Program name in the about dialog */
+                          _("Gcalctool"),
+                          "version", VERSION,
+                          "copyright",
+                          /* Copyright notice in the about dialog */
+                          _("\xc2\xa9 1986â??2008 The Gcalctool authors"),
+                          "license", license,
+                          "comments",
+                          /* Short description in the about dialog */
+                          _("Calculator with financial and scientific modes."),
+                          "authors", authors,
+                          "documenters", documenters,
+                          "translator_credits", translator_credits,
+                          "logo-icon-name", "accessories-calculator",
+                          NULL);
+}
+
+
+static void
+quit_cb(GtkWidget *widget, MathWindow *window)
+{
+    g_signal_emit(window, signals[QUIT], 0);
+}
+
+
+static gboolean
+key_press_cb(MathWindow *window, GdkEventKey *event)
+{
+    gboolean result;
+    g_signal_emit_by_name(window->priv->display, "key-press-event", event, &result);
+    return result;
+}
+
+
+static void
+delete_cb(MathWindow *window, GdkEvent *event)
+{
+    g_signal_emit(window, signals[QUIT], 0);
+}
+
+
+static void
+scroll_changed_cb(GtkAdjustment *adjustment, MathWindow *window)
+{
+    if (window->priv->right_aligned)
+        gtk_adjustment_set_value(adjustment, gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment));
+}
+
+
+static void
+scroll_value_changed_cb(GtkAdjustment *adjustment, MathWindow *window)
+{
+    if (gtk_adjustment_get_value(adjustment) == gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment))
+        window->priv->right_aligned = TRUE;
+    else
+        window->priv->right_aligned = FALSE;
+}
+
+
+static void
+button_mode_changed_cb(MathButtons *buttons, GParamSpec *spec, MathWindow *window)
+{
+    GtkWidget *menu;
+
+    switch(math_buttons_get_mode(buttons))
+    {
+    case BASIC:
+      menu = window->priv->mode_basic_menu_item;
+      break;
+
+    case ADVANCED:
+      menu = window->priv->mode_advanced_menu_item;
+      break;
+
+    case FINANCIAL:
+      menu = window->priv->mode_financial_menu_item;
+      break;
+
+    case PROGRAMMING:
+      menu = window->priv->mode_programming_menu_item;
+      break;
+    }
+    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
+}
+
+
+static GtkWidget *
+add_menu(GtkWidget *menu_bar, const gchar *name)
+{
+    GtkWidget *menu_item, *menu;
+
+    menu_item = gtk_menu_item_new_with_mnemonic(name);
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_item);
+    gtk_widget_show(menu_item);
+    menu = gtk_menu_new();
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu);
+
+    return menu;
+}
+
+
+static GtkWidget *
+add_menu_item(GtkWidget *menu, GtkWidget *menu_item, GCallback callback, gpointer callback_data)
+{
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+    gtk_widget_show(menu_item);
+    if (callback)
+        g_signal_connect(G_OBJECT(menu_item), "activate", callback, callback_data);
+    return menu_item;
+}
+
+
+static GtkWidget *
+radio_menu_item_new(GSList **group, const gchar *name)
+{
+    GtkWidget *menu_item;
+    menu_item = gtk_radio_menu_item_new_with_mnemonic(*group, name);
+    *group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menu_item));
+    return menu_item;
+}
+
+
+static void
+create_menu(MathWindow *window)
+{
+    GtkAccelGroup *accel_group;
+    GtkWidget *menu, *menu_item;
+    GSList *group = NULL;
+  
+    accel_group = gtk_accel_group_new();
+    gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
+
+    /* Calculator menu */  
+    #define CALCULATOR_MENU_LABEL _("_Calculator")
+    /* Mode menu */
+    #define MODE_MENU_LABEL _("_Mode")
+    /* Help menu label */
+    #define HELP_MENU_LABEL _("_Help")
+    /* Basic menu label */  
+    #define MODE_BASIC_LABEL _("_Basic")
+    /* Advanced menu label */  
+    #define MODE_ADVANCED_LABEL _("_Advanced")
+    /* Financial menu label */  
+    #define MODE_FINANCIAL_LABEL _("_Financial")
+    /* Programming menu label */
+    #define MODE_PROGRAMMING_LABEL _("_Programming")
+    /* Help>Contents menu label */
+    #define HELP_CONTENTS_LABEL _("_Contents")
+
+    menu = add_menu(window->priv->menu_bar, CALCULATOR_MENU_LABEL);
+    add_menu_item(menu, gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY, accel_group), G_CALLBACK(copy_cb), window);
+    add_menu_item(menu, gtk_image_menu_item_new_from_stock(GTK_STOCK_PASTE, accel_group), G_CALLBACK(paste_cb), window);
+    add_menu_item(menu, gtk_separator_menu_item_new(), NULL, NULL);
+    add_menu_item(menu, gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES, accel_group), G_CALLBACK(show_preferences_cb), window);
+    add_menu_item(menu, gtk_separator_menu_item_new(), NULL, NULL);
+    add_menu_item(menu, gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group), G_CALLBACK(quit_cb), window);
+    // FIXME: Make Ctrl+W also work for quit
+
+    menu = add_menu(window->priv->menu_bar, MODE_MENU_LABEL);
+    window->priv->mode_basic_menu_item = add_menu_item(menu, radio_menu_item_new(&group, MODE_BASIC_LABEL), G_CALLBACK(mode_changed_cb), window);
+    g_object_set_data(G_OBJECT(window->priv->mode_basic_menu_item), "calcmode", GINT_TO_POINTER(BASIC));
+    window->priv->mode_advanced_menu_item = add_menu_item(menu, radio_menu_item_new(&group, MODE_ADVANCED_LABEL), G_CALLBACK(mode_changed_cb), window);
+    g_object_set_data(G_OBJECT(window->priv->mode_advanced_menu_item), "calcmode", GINT_TO_POINTER(ADVANCED));
+    window->priv->mode_financial_menu_item = add_menu_item(menu, radio_menu_item_new(&group, MODE_FINANCIAL_LABEL), G_CALLBACK(mode_changed_cb), window);
+    g_object_set_data(G_OBJECT(window->priv->mode_financial_menu_item), "calcmode", GINT_TO_POINTER(FINANCIAL));
+    window->priv->mode_programming_menu_item = add_menu_item(menu, radio_menu_item_new(&group, MODE_PROGRAMMING_LABEL), G_CALLBACK(mode_changed_cb), window);
+    g_object_set_data(G_OBJECT(window->priv->mode_programming_menu_item), "calcmode", GINT_TO_POINTER(PROGRAMMING));
+
+    menu = add_menu(window->priv->menu_bar, HELP_MENU_LABEL);
+    add_menu_item(menu, gtk_menu_item_new_with_mnemonic(HELP_CONTENTS_LABEL), G_CALLBACK(help_cb), window);
+    // FIXME: Make F1 shortcut for help
+    add_menu_item(menu, gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, accel_group), G_CALLBACK(about_cb), window);
+}
+
+
+static void
+create_gui(MathWindow *window)
+{
+    GtkWidget *main_vbox, *vbox;
+    GtkWidget *scrolled_window;
+    GError *error = NULL;
+    int i;
+
+    main_vbox = gtk_vbox_new(FALSE, 0);
+    gtk_container_add(GTK_CONTAINER(window), main_vbox);
+    gtk_widget_show(main_vbox);
+
+    window->priv->menu_bar = gtk_menu_bar_new();
+    gtk_box_pack_start(GTK_BOX(main_vbox), window->priv->menu_bar, TRUE, TRUE, 0);
+    gtk_widget_show(window->priv->menu_bar);
+  
+    create_menu(window);
+
+    vbox = gtk_vbox_new(FALSE, 6);
+    gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
+    gtk_box_pack_start(GTK_BOX(main_vbox), vbox, TRUE, TRUE, 0);  
+    gtk_widget_show(vbox);
+
+    scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN);
+    gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 3);
+    gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(scrolled_window), TRUE, TRUE, 0);
+    g_signal_connect(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(scrolled_window)), "changed", G_CALLBACK(scroll_changed_cb), window);
+    g_signal_connect(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(scrolled_window)), "value-changed", G_CALLBACK(scroll_value_changed_cb), window);
+    window->priv->right_aligned = TRUE;
+    gtk_widget_show(scrolled_window);
+
+    window->priv->display = math_display_new_with_equation(window->priv->equation);
+    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), GTK_WIDGET(window->priv->display));
+    gtk_widget_show(GTK_WIDGET(window->priv->display));
+
+    window->priv->buttons = math_buttons_new(window->priv->equation);
+    g_signal_connect(window->priv->buttons, "notify::mode", G_CALLBACK(button_mode_changed_cb), window);
+    button_mode_changed_cb(window->priv->buttons, NULL, window);
+    gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(window->priv->buttons), TRUE, TRUE, 0);
+    gtk_widget_show(GTK_WIDGET(window->priv->buttons));
+}
+
+
+static void
+math_window_set_property(GObject      *object,
+                         guint         prop_id,
+                         const GValue *value,
+                         GParamSpec   *pspec)
+{
+    MathWindow *self;
+
+    self = MATH_WINDOW (object);
+
+    switch (prop_id) {
+    case PROP_EQUATION:
+        self->priv->equation = g_value_get_object (value);
+        create_gui(self);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+
+static void
+math_window_get_property(GObject    *object,
+                         guint       prop_id,
+                         GValue     *value,
+                         GParamSpec *pspec)
+{
+    MathWindow *self;
+
+    self = MATH_WINDOW (object);
+
+    switch (prop_id) {
+    case PROP_EQUATION:
+        g_value_set_object (value, self->priv->equation);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+
+static void
+math_window_class_init (MathWindowClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->get_property = math_window_get_property;
+    object_class->set_property = math_window_set_property;
+
+    g_type_class_add_private (klass, sizeof (MathWindowPrivate));
+
+    g_object_class_install_property(object_class,
+                                    PROP_EQUATION,
+                                    g_param_spec_object("equation",
+                                                        "equation",
+                                                        "Equation being calculated",
+                                                        math_equation_get_type(),
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+    signals[QUIT] =
+        g_signal_new ("quit",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (MathWindowClass, quit),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0);
+}
+
+
+static void
+math_window_init(MathWindow *window)
+{
+    window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, math_window_get_type(), MathWindowPrivate);
+    gtk_window_set_title(GTK_WINDOW(window),
+                         /* Title of main window */
+                         _("Calculator"));
+    gtk_window_set_icon_name(GTK_WINDOW(window), "accessories-calculator");
+    gtk_window_set_role(GTK_WINDOW(window), "gcalctool");
+    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+    g_signal_connect_after(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press_cb), NULL);
+    g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(delete_cb), NULL);
+}
diff --git a/src/ui.h b/src/math-window.h
similarity index 55%
rename from src/ui.h
rename to src/math-window.h
index e591828..d272e4f 100644
--- a/src/ui.h
+++ b/src/math-window.h
@@ -17,8 +17,8 @@
  *  02111-1307, USA.
  */
 
-#ifndef UI_H
-#define UI_H
+#ifndef MATH_WINDOW_H
+#define MATH_WINDOW_H
 
 #include <glib-object.h>
 #include "math-equation.h"
@@ -27,35 +27,35 @@
 
 G_BEGIN_DECLS
 
-#define UI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ui_get_type(), GCalctoolUI))
+#define MATH_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_window_get_type(), MathWindow))
 
-typedef struct GCalctoolUIPrivate GCalctoolUIPrivate;
+typedef struct MathWindowPrivate MathWindowPrivate;
 
 typedef struct
 {
-    GObject             parent_instance;
-    GCalctoolUIPrivate *priv;
-} GCalctoolUI;
+    GtkWindow parent_instance;
+    MathWindowPrivate *priv;
+} MathWindow;
 
 typedef struct
 {
-    GObjectClass parent_class;
-} GCalctoolUIClass;
+    GtkWindowClass parent_class;
 
-void ui_gtk_init(int *argc, char ***argv);
+    void (*quit)(MathWindow *window);
+} MathWindowClass;
 
-GType ui_get_type();
+GType math_window_get_type();
 
-GCalctoolUI *ui_new(void);
+MathWindow *math_window_new(MathEquation *equation);
 
-MathEquation *ui_get_equation(GCalctoolUI *ui);
+GtkWidget *math_window_get_menu_bar(MathWindow *window);
 
-MathDisplay *ui_get_display(GCalctoolUI *ui);
+MathEquation *math_window_get_equation(MathWindow *window);
 
-MathButtons *ui_get_buttons(GCalctoolUI *ui);
+MathDisplay *math_window_get_display(MathWindow *window);
 
-void ui_critical_error(GCalctoolUI *ui, const gchar *title, const gchar *contents);
+MathButtons *math_window_get_buttons(MathWindow *window);
 
-void ui_start(GCalctoolUI *ui);
+void math_window_critical_error(MathWindow *window, const gchar *title, const gchar *contents);
 
-#endif /* UI_H */
+#endif /* MATH_WINDOW_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]