work on docs
[pspp] / src / ui / gui / psppire-keypad.c
index af0e592487f795179bb8cc76fde26e0d8fb46a3c..c394e219b98b20d60a0cc772ec1facdb8d1c8f31 100644 (file)
@@ -1,71 +1,44 @@
-/* PSPP - computes sample statistics.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2007, 2010, 2011, 2015, 2020 Free Software Foundation, Inc.
 
-   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 of the
-   License, or (at your option) any later version.
+   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 3 of the License, 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.
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
-
-#include <gtk/gtksignal.h>
-#include <gtk/gtktable.h>
-#include <gtk/gtkbutton.h>
-#include <gtk/gtklabel.h>
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 #include "psppire-keypad.h"
 
-enum {
-  INSERT_SYNTAX,
-  n_SIGNALS
-};
-
-static void psppire_keypad_class_init          (PsppireKeypadClass *klass);
-static void psppire_keypad_init                (PsppireKeypad      *kp);
+#include <gettext.h>
+#define _(msgid) gettext (msgid)
 
-static guint keypad_signals[n_SIGNALS] = { 0 };
-
-GType
-psppire_keypad_get_type (void)
-{
-  static GType kp_type = 0;
+enum
+  {
+   INSERT_SYNTAX,
+   ERASE,
+   n_SIGNALS
+  };
 
-  if (!kp_type)
-    {
-      static const GTypeInfo kp_info =
-      {
-       sizeof (PsppireKeypadClass),
-       NULL, /* base_init */
-        NULL, /* base_finalize */
-       (GClassInitFunc) psppire_keypad_class_init,
-        NULL, /* class_finalize */
-       NULL, /* class_data */
-        sizeof (PsppireKeypad),
-       0,
-       (GInstanceInitFunc) psppire_keypad_init,
-      };
-
-      kp_type = g_type_register_static (GTK_TYPE_EVENT_BOX, "PsppireKeypad",
-                                       &kp_info, 0);
-    }
+static guint keypad_signals [n_SIGNALS] = { 0 };
 
-  return kp_type;
-}
+G_DEFINE_TYPE (PsppireKeypad, psppire_keypad, GTK_TYPE_EVENT_BOX)
 
 static GObjectClass * parent_class = NULL;
 
 static void
 psppire_keypad_dispose (GObject *obj)
 {
-  PsppireKeypad *kp = (PsppireKeypad *)obj;
+  PsppireKeypad *kp = PSPPIRE_KEYPAD (obj);
 
   if (kp->dispose_has_run)
     return;
@@ -106,6 +79,16 @@ psppire_keypad_class_init (PsppireKeypadClass *klass)
                                         g_cclosure_marshal_VOID__STRING,
                                          G_TYPE_NONE, 1,
                                         G_TYPE_STRING);
+
+  keypad_signals[ERASE] = g_signal_new ("erase",
+                                        G_TYPE_FROM_CLASS (klass),
+                                        G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+                                        G_STRUCT_OFFSET (PsppireKeypadClass,
+                                                         keypad),
+                                         NULL,
+                                         NULL,
+                                        g_cclosure_marshal_VOID__VOID,
+                                         G_TYPE_NONE, 0);
 }
 
 
@@ -115,11 +98,12 @@ psppire_keypad_class_init (PsppireKeypadClass *klass)
    The order of these must correspond
    to the order of the button declarations
 */
-static const char *keypad_insert_text[] = {
-  "0",  "1",  "2", "3", "4", "5", "6", "7", "8", "9",
-  ".", "+", "-", "*", "**", "/", "=", "<>", "<", "<=",
-  ">", ">=", "&", "|", "~", "(", ")"
-};
+static const char * const keypad_insert_text[] =
+  {
+   "0",  "1",  "2", "3", "4", "5", "6", "7", "8", "9",
+   ".", "+", "-", "*", "**", "/", "=", "<>", "<", "<=",
+   ">", ">=", "&", "|", "~", "()", NULL
+  };
 
 
 /* Callback for any button click.
@@ -131,7 +115,11 @@ button_click (GtkButton *b, PsppireKeypad *kp)
 {
   const gchar *s = g_hash_table_lookup (kp->frag_table, b);
 
-  g_signal_emit (kp, keypad_signals [INSERT_SYNTAX], 0, s);
+
+  if (s)
+    g_signal_emit (kp, keypad_signals [INSERT_SYNTAX], 0, s);
+  else
+    g_signal_emit (kp, keypad_signals [ERASE], 0);
 }
 
 static const gint cols = 6;
@@ -148,17 +136,14 @@ add_button (PsppireKeypad *kp, GtkWidget **button,
 {
   g_object_set (G_OBJECT (*button), "focus-on-click", FALSE, NULL);
 
-  gtk_table_attach_defaults (GTK_TABLE (kp->table),
-                            *button,
-                            x1, x2,
-                            y1, y2);
+  gtk_grid_attach (GTK_GRID(kp->table), *button, x1, y1, x2 - x1, y2 - y1);
 
   gtk_widget_set_size_request (*button,
                               30 * rows / (float) cols,
                               30 * cols / (float) rows);
 
   g_hash_table_insert (kp->frag_table, *button,
-                      (void *) keypad_insert_text[(button - &kp->digit[0])] );
+                      (void *) keypad_insert_text[(button - &kp->digit[0])]);
 
   g_signal_connect (*button, "clicked",
                    G_CALLBACK (button_click), kp);
@@ -195,9 +180,6 @@ enter_leave_notify (GtkWidget   *widget,
  if (event->type == GDK_ENTER_NOTIFY)
    gtk_widget_grab_focus (widget);
 
- if (event->type == GDK_LEAVE_NOTIFY)
-   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
-
  return FALSE;
 }
 
@@ -206,7 +188,7 @@ key_release_callback (GtkWidget   *widget,
                      GdkEventKey *event,
                      gpointer     user_data)
 {
-  if ( ! (GTK_WIDGET_FLAGS (widget) & GTK_HAS_FOCUS) )
+  if (! gtk_widget_has_focus (widget))
     return FALSE;
 
   switch (event->keyval)
@@ -223,67 +205,67 @@ key_release_callback (GtkWidget   *widget,
     case '<':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "<");
       break;
-    case GDK_KP_Equal :
+    case GDK_KEY_KP_Equal :
     case '=':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "=");
       break;
-    case GDK_KP_Multiply :
+    case GDK_KEY_KP_Multiply :
     case '*':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "*");
       break;
-    case GDK_KP_Add :
+    case GDK_KEY_KP_Add :
     case '+':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "+");
       break;
-    case GDK_KP_Subtract :
+    case GDK_KEY_KP_Subtract :
     case '-':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "-");
       break;
-    case GDK_KP_Decimal :
+    case GDK_KEY_KP_Decimal :
     case '.':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, ".");
       break;
-    case GDK_KP_Divide :
+    case GDK_KEY_KP_Divide :
     case '/':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "/");
       break;
-    case GDK_KP_0 :
+    case GDK_KEY_KP_0 :
     case '0':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "0");
       break;
-    case GDK_KP_1 :
+    case GDK_KEY_KP_1 :
     case '1':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "1");
       break;
-    case GDK_KP_2 :
+    case GDK_KEY_KP_2 :
     case '2':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "2");
       break;
-    case GDK_KP_3 :
+    case GDK_KEY_KP_3 :
     case '3':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "3");
       break;
-    case GDK_KP_4 :
+    case GDK_KEY_KP_4 :
     case '4':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "4");
       break;
-    case GDK_KP_5 :
+    case GDK_KEY_KP_5 :
     case '5':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "5");
       break;
-    case GDK_KP_6 :
+    case GDK_KEY_KP_6 :
     case '6':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "6");
       break;
-    case GDK_KP_7 :
+    case GDK_KEY_KP_7 :
     case '7':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "7");
       break;
-    case GDK_KP_8 :
+    case GDK_KEY_KP_8 :
     case '8':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "8");
       break;
-    case GDK_KP_9 :
+    case GDK_KEY_KP_9 :
     case '9':
       g_signal_emit (widget, keypad_signals [INSERT_SYNTAX], 0, "9");
       break;
@@ -302,8 +284,7 @@ psppire_keypad_init (PsppireKeypad *kp)
   const int digit_voffset = 0;
   const int digit_hoffset = 3;
 
-  GTK_WIDGET_SET_FLAGS (kp, GTK_CAN_FOCUS);
-  GTK_WIDGET_UNSET_FLAGS (kp, GTK_HAS_FOCUS);
+  gtk_widget_set_can_focus (GTK_WIDGET (kp), TRUE);
 
   kp->dispose_has_run = FALSE;
 
@@ -318,17 +299,17 @@ psppire_keypad_init (PsppireKeypad *kp)
 
   kp->frag_table = g_hash_table_new (g_direct_hash, g_direct_equal);
 
-  kp->table = gtk_table_new (rows, cols, TRUE);
+  kp->table = gtk_grid_new ();
 
   /* Buttons for the digits */
   for (i = 0; i < 10; i++)
     {
       int j = i - 1;
       char buf[5];
-      snprintf (buf, 5, "%d", i);
+      g_snprintf (buf, 5, "%d", i);
       kp->digit[i] = gtk_button_new_with_label (buf);
 
-      if ( i == 0 )
+      if (i == 0)
        add_button (kp, &kp->digit[i],
                    digit_hoffset + 0, digit_hoffset + 2,
                    digit_voffset + 3, digit_voffset + 4);
@@ -348,89 +329,84 @@ psppire_keypad_init (PsppireKeypad *kp)
              digit_voffset + 4);
 
   kp->plus  = gtk_button_new_with_label ("+");
-  add_button (kp, &kp->plus, 0, 1,
-             0,1);
+  gtk_widget_set_tooltip_text (kp->plus, _("add"));
+  add_button (kp, &kp->plus, 0, 1, 0, 1);
 
   kp->minus = button_new_from_unicode (0x2212); /* MINUS SIGN */
-  add_button (kp, &kp->minus, 0, 1,
-             1,2);
+  gtk_widget_set_tooltip_text (kp->minus, _("subtract"));
+  add_button (kp, &kp->minus, 0, 1, 1, 2);
 
   kp->star  = button_new_from_unicode (0xD7);   /* MULTIPLICATION SIGN */
-  add_button (kp, &kp->star, 0, 1,
-             2,3);
+  gtk_widget_set_tooltip_text (kp->star, _("multiply"));
+  add_button (kp, &kp->star, 0, 1,  2, 3);
 
   kp->slash = button_new_from_unicode (0xF7);   /* DIVISION SIGN */
-  add_button (kp, &kp->slash, 0, 1,
-             3,4);
+  gtk_widget_set_tooltip_text (kp->slash, _("divide"));
+  add_button (kp, &kp->slash, 0, 1, 3, 4);
 
+  /* Exponention */
   {
     GtkWidget *label;
     char *markup =
       g_markup_printf_escaped ("<span style=\"italic\">x<sup>y</sup></span>");
 
     label = gtk_label_new ("**");
+
     gtk_label_set_markup (GTK_LABEL (label), markup);
     g_free (markup);
 
     kp->star_star = gtk_button_new ();
+    gtk_widget_set_tooltip_text (kp->star_star, _("raise x to the power of y"));
+
     gtk_container_add (GTK_CONTAINER (kp->star_star), label);
 
-    add_button (kp, &kp->star_star,
-               0, 1,
-               4, 5);
+    gtk_widget_show (label);
+
+    add_button (kp, &kp->star_star, 0, 1, 4, 5);
   }
 
 
   kp->gt = button_new_from_unicode (0x3E); /* GREATER-THAN SIGN*/
-  add_button (kp, &kp->gt, 2, 3,
-             0,1);
+  gtk_widget_set_tooltip_text (kp->gt, _("is greater than"));
+  add_button (kp, &kp->gt, 2, 3,  0, 1);
 
   kp->lt = button_new_from_unicode (0x3C); /* LESS-THAN SIGN*/
-  add_button (kp, &kp->lt, 1, 2,
-             0,1);
+  gtk_widget_set_tooltip_text (kp->lt, _("is less than"));
+  add_button (kp, &kp->lt, 1, 2, 0, 1);
 
   kp->ge = button_new_from_unicode (0x2265); /* GREATER-THAN OR EQUAL */
-  add_button (kp, &kp->ge, 2, 3,
-             1,2);
+  gtk_widget_set_tooltip_text (kp->ge, _("is no less than"));
+  add_button (kp, &kp->ge, 2, 3, 1, 2);
 
   kp->le = button_new_from_unicode (0x2264); /* LESS-THAN OR EQUAL */
-  add_button (kp, &kp->le, 1, 2,
-             1,2);
+  gtk_widget_set_tooltip_text (kp->le, _("is no greater than"));
+  add_button (kp, &kp->le, 1, 2, 1, 2);
 
   kp->neq = button_new_from_unicode (0x2260); /* NOT EQUAL */
-  add_button (kp, &kp->neq, 2, 3,
-             2,3);
+  gtk_widget_set_tooltip_text (kp->neq, _("is not equal to"));
+  add_button (kp, &kp->neq, 2, 3, 2, 3);
 
   kp->eq = gtk_button_new_with_label ("=");
-  add_button (kp, &kp->eq, 1, 2,
-             2,3);
+  gtk_widget_set_tooltip_text (kp->eq, _("is equal to"));
+  add_button (kp, &kp->eq, 1, 2, 2, 3);
 
   kp->parentheses = gtk_button_new_with_label ("()");
-  add_button (kp, &kp->parentheses, 2, 3,
-             4,5);
-
+  add_button (kp, &kp->parentheses, 2, 3, 4, 5);
 
   kp->delete = gtk_button_new_with_label ("Delete");
-  add_button (kp, &kp->delete, 3, 6,
-             4,5);
-
-
+  add_button (kp, &kp->delete, 3, 6, 4, 5);
 
   kp->and = button_new_from_unicode (0x2227); /* LOGICAL AND */
-  add_button (kp, &kp->and, 1, 2,
-             3,4);
-
+  gtk_widget_set_tooltip_text (kp->and, _("and"));
+  add_button (kp, &kp->and, 1, 2, 3, 4);
 
   kp->or = button_new_from_unicode (0x2228); /* LOGICAL OR */
-  add_button (kp, &kp->or, 2, 3,
-             3,4);
-
+  gtk_widget_set_tooltip_text (kp->or, _("or"));
+  add_button (kp, &kp->or, 2, 3, 3, 4);
 
   kp->not = button_new_from_unicode (0xAC); /* NOT SIGN */
-  add_button (kp, &kp->not, 1, 2,
-             4,5);
-
-
+  gtk_widget_set_tooltip_text (kp->not, _("not"));
+  add_button (kp, &kp->not, 1, 2, 4, 5);
 
   g_object_set (G_OBJECT (kp->table), "row-spacing", 5, NULL);
   g_object_set (G_OBJECT (kp->table), "column-spacing", 5, NULL);
@@ -443,7 +419,6 @@ psppire_keypad_init (PsppireKeypad *kp)
        GDK_LEAVE_NOTIFY_MASK |
        GDK_ENTER_NOTIFY_MASK |
         GDK_FOCUS_CHANGE_MASK);
-
 }