[gnome-nibbles] Revert "Remove score-dialog that doesn't work, remaining score functionality should be working"



commit a953eebe74af5709fa50b19bc03048a114f8bb87
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Tue Nov 5 20:47:20 2013 -0600

    Revert "Remove score-dialog that doesn't work, remaining score functionality should be working"
    
    This reverts commit 3e08f33ba06145a7363ea7a6b9782c26dfc81062.
    
    Conflicts:
        src/main.c

 src/Makefile.am           |    2 +
 src/games-scores-dialog.c |  610 +++++++++++++++++++++++++++++++++++++++++++++
 src/games-scores-dialog.h |   81 ++++++
 src/gnibbles.c            |   36 +++-
 src/main.c                |   10 +
 5 files changed, 738 insertions(+), 1 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 11d2120..28982fb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,6 +17,8 @@ gnome_nibbles_SOURCES = \
        games-score.c                   \
        games-scores.c                  \
        games-scores.h                  \
+       games-scores-dialog.c   \
+       games-scores-dialog.h   \
        gnibbles.h \
        gnibbles.c \
        properties.h \
diff --git a/src/games-scores-dialog.c b/src/games-scores-dialog.c
new file mode 100644
index 0000000..556a177
--- /dev/null
+++ b/src/games-scores-dialog.c
@@ -0,0 +1,610 @@
+/* -*- mode: C -*-
+
+   games-scores-dialog.c
+   Copyright 2004, 2005, 2006 Callum McKenzie
+
+   This library is free software; you can redistribute it and'or modify
+   it under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This library 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Authors:   Callum McKenzie <callum physics otago ac nz> */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "games-scores-dialog.h"
+
+G_DEFINE_TYPE (GamesScoresDialog, games_scores_dialog, GTK_TYPE_DIALOG);
+
+struct GamesScoresDialogPrivate {
+  GtkWidget *message;
+  GtkWidget *hdiv;
+  GtkWidget *combo;
+  GtkWidget *label;
+  GtkWidget *catbar;
+  GtkListStore *list;
+  GtkTreeView *treeview;
+  GtkCellRenderer *namerenderer;
+  GtkTreeViewColumn *column;
+  GtkTreeViewColumn *namecolumn;
+  GtkTreeViewColumn *timecolumn;
+  GamesScores *scores;
+  GHashTable *categories;
+  GHashTable *catindices;
+  gint catcounter;
+  gint hilight;
+  gint sethilight;
+  gboolean preservehilight;
+  gulong cursor_handler_id;
+
+  /* FIXME: This should be a property. */
+  gint style;
+};
+
+static void
+games_scores_dialog_finalize (GObject *o)
+{
+  GamesScoresDialog *dialog = GAMES_SCORES_DIALOG (o);
+
+  if (dialog->priv->scores)
+    g_object_unref (dialog->priv->scores);
+
+  if (dialog->priv->categories)
+    g_hash_table_destroy (dialog->priv->categories);
+  if (dialog->priv->catindices)
+    g_hash_table_destroy (dialog->priv->catindices);
+
+  G_OBJECT_CLASS (games_scores_dialog_parent_class)->finalize (o);
+}
+
+static void
+games_scores_dialog_class_init (GamesScoresDialogClass *klass)
+{
+  g_type_class_add_private (klass, sizeof (GamesScoresDialogPrivate));
+
+  G_OBJECT_CLASS (klass)->finalize = games_scores_dialog_finalize;
+}
+
+/**
+ * add_category:
+ * @self: a pointer to a GamesScoresDialog
+ * @key: an identifier for the category. This should also be a valid
+ * score category for the gnome_score system.
+ * @name: the category name
+ * 
+ * Adds a new category to combo box selector.
+ *
+ **/
+static void games_scores_dialog_add_category (GamesScoresDialog *self, 
+                                      const gchar *key, 
+                                      const gchar *name)
+{
+  gchar *k;
+
+  k = g_strdup (key);
+
+  g_hash_table_insert (self->priv->categories, k, 
+                        GINT_TO_POINTER (self->priv->catcounter));
+  g_hash_table_insert (self->priv->catindices, 
+                        GINT_TO_POINTER (self->priv->catcounter),
+                        k);
+  self->priv->catcounter++;
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->priv->combo), name);
+}
+
+/* This is a helper function for loading the initial list of categories
+ * in a _foreach function. If only C had lambda... */
+static void games_scores_dialog_load_categories (GamesScoresCategory *cat, 
+                                                GamesScoresDialog *self) 
+{
+    /* category->name is already translated here! */
+    games_scores_dialog_add_category (self, cat->key, cat->name);
+}
+
+/**
+ * set_style:
+ * @self: a pointer to a GamesScoresDialog
+ * @style: the style to use
+ * 
+ * Sets the style of score displayed. e.g. GAMES_SCORES_STYLE_TIME
+ * displays the scores as times. Note that the order of the scores
+ * is determined at the gnome_score layer but their interpretation
+ * is at this layer.
+ *
+ **/
+static void games_scores_dialog_set_style (GamesScoresDialog *self, GamesScoreStyle style) 
+{
+  const gchar *header;
+
+  self->priv->style = style;
+  switch (style) {
+  case GAMES_SCORES_STYLE_TIME_DESCENDING:
+  case GAMES_SCORES_STYLE_TIME_ASCENDING:
+    /* Score dialog column header for the score time (e.g. 1 minute) */
+    header = C_("score-dialog", "Time");
+    break;
+  case GAMES_SCORES_STYLE_PLAIN_DESCENDING:
+  case GAMES_SCORES_STYLE_PLAIN_ASCENDING:
+  default:
+    /* Score dialog column header for the score value (e.g. 30 moves) */
+    header = C_("score-dialog", "Score");
+  }
+
+  gtk_tree_view_column_set_title (self->priv->column, header);
+}
+
+/**
+ * set_category:
+ * @self: a pointer to a GamesScoresDialog
+ * @key: the category to change to
+ * 
+ * Sets the category the scores dialog is displaying.
+ *
+ **/
+static void games_scores_dialog_set_category (GamesScoresDialog *self, 
+                                             const gchar *key) 
+{
+  gpointer value;
+  int idx;
+
+  value = g_hash_table_lookup (self->priv->categories, key);
+  idx = GPOINTER_TO_INT (value);
+
+  self->priv->preservehilight = TRUE;
+  gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->combo), idx);
+}
+
+/**
+ * new:
+ * @domain: the scores domain to use, usually the application name
+ * @title: the title for the dialog
+ * 
+ * Creates a new high scores dialog. Use gtk_dialog_run and 
+ * gtk_widget_destroy to manage it.
+ *
+ * Returns: a new widget
+ *
+ **/
+GtkWidget * games_scores_dialog_new (GtkWindow *parent_window, GamesScores *scores, const gchar *title)
+{
+  GamesScoresDialog *dialog = GAMES_SCORES_DIALOG (g_object_new (GAMES_TYPE_SCORES_DIALOG, NULL));
+
+  dialog->priv->scores = g_object_ref (scores);
+  games_scores_dialog_set_style (dialog, games_scores_get_style (scores));
+  dialog->priv->preservehilight = FALSE;
+
+  gtk_window_set_title (GTK_WINDOW (dialog), title);
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
+
+  _games_scores_category_foreach (scores, 
+                                  (GamesScoresCategoryForeachFunc) games_scores_dialog_load_categories,
+                                  dialog);
+
+  if (dialog->priv->catcounter <= 1) {
+    gtk_widget_hide (dialog->priv->catbar);
+  }
+
+  return (GtkWidget *)dialog;
+}
+
+/* Retrieve the edited name from a new high score. */
+static void games_scores_dialog_name_edited (GtkCellRendererText *cell, 
+                                            gchar *path, gchar *new_text, 
+                                            GamesScoresDialog *self)
+{
+  GtkTreeIter iter;
+  gchar *old_name = NULL;
+
+  gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (self->priv->list), 
+                                      &iter, path);
+
+  /* Get old name for comparison */
+  gtk_tree_model_get (GTK_TREE_MODEL (self->priv->list),
+                      &iter, 0, &old_name, -1);
+                           
+  gtk_list_store_set (self->priv->list, &iter, 0, new_text, -1);
+
+  games_scores_update_score_name (self->priv->scores, new_text, old_name);
+}
+
+/* Prevent editing of any cell in the high score list but the one we set. */
+static void games_scores_dialog_cursor_changed (GtkTreeView *treeview, 
+                                               GamesScoresDialog *self)
+{
+  g_object_set (self->priv->namerenderer, "editable", FALSE, NULL);
+}    
+
+/* These contortions are to ensure that only the single most-recent
+ * entry can be edited. */
+static gboolean games_scores_dialog_set_edit (GamesScoresDialog *self)
+{
+  GtkTreePath *path;
+  GtkTreeSelection *selection;
+
+  /* Just in case we've been closed as soon as we're created. */
+  if (!gtk_widget_get_realized (GTK_WIDGET (self)))
+    return FALSE;
+
+  /* Temporarily disable the code that prevents editing when the
+   * cursor changes position. */
+  g_signal_handler_block (self->priv->treeview, 
+                           self->priv->cursor_handler_id); 
+  g_object_set (self->priv->namerenderer, "editable", TRUE, NULL);
+  selection = gtk_tree_view_get_selection (self->priv->treeview);
+  path = gtk_tree_path_new_from_indices (self->priv->hilight - 1, -1);
+  gtk_tree_selection_select_path (selection, path);
+  gtk_tree_view_set_cursor (self->priv->treeview, path, 
+                             self->priv->namecolumn, TRUE);
+  g_signal_handler_unblock (self->priv->treeview, 
+                             self->priv->cursor_handler_id); 
+  gtk_tree_path_free (path);
+
+  return FALSE;
+}
+
+/* Yet another part of the puzzle that lets the correct high-score be
+ * editable. */
+static void games_scores_dialog_set_hilight_private (GamesScoresDialog *self) 
+{
+  if (self->priv->hilight == 0) {
+    g_object_set (self->priv->namerenderer, "editable", FALSE, NULL);
+    return;
+  }
+
+  if (self->priv->hilight == self->priv->sethilight)
+    return;
+
+  self->priv->sethilight = self->priv->hilight;
+
+  /* We can't set the hilight editable immediately in case we are
+   * still in the process of being created and the editing subwindow
+   * gets put in the wrong place. Attaching to the expose signal
+   * doesn't seem to have the desired effect, so instead we just
+   * wait until all other work is done. */
+  g_idle_add ((GSourceFunc)games_scores_dialog_set_edit, self);
+}
+
+/* Load up the list with the current set of scores. */
+static void games_scores_dialog_redraw (GamesScoresDialog *self) {
+  GtkTreeIter iter;
+  const gchar *name;
+  gint score;
+  gchar *ss;
+  gint timestamp;
+  GDateTime *datetime;
+  gchar *time;
+  gdouble dscore;
+  GList *scorelist;
+
+  gtk_list_store_clear (self->priv->list);
+
+  scorelist = games_scores_get (self->priv->scores);
+
+  while (scorelist) {
+    name = games_score_get_name ((GamesScore *)scorelist->data);
+    timestamp = games_score_get_time ((GamesScore *)scorelist->data);
+    datetime = g_date_time_new_from_unix_local (timestamp);
+    time = g_date_time_format (datetime,"%d/%m/%y");
+
+    switch (self->priv->style) {
+    case GAMES_SCORES_STYLE_TIME_ASCENDING:
+    case GAMES_SCORES_STYLE_TIME_DESCENDING:
+      dscore = games_score_get_value_as_time ((GamesScore *)scorelist->data);
+      score = (int) (100.0 * dscore + 0.5);
+      ss = g_strdup_printf (/* Score format for time based scores.  %1$d is the time in minutes, %2$d is the 
time in seconds */
+                            C_("score-dialog", "%1$dm %2$ds"),
+                            score/100, score%100);
+      break; 
+    case GAMES_SCORES_STYLE_PLAIN_ASCENDING:
+    case GAMES_SCORES_STYLE_PLAIN_DESCENDING:
+    default:
+      score = games_score_get_value_as_plain ((GamesScore *)scorelist->data);
+      ss = g_strdup_printf ("%d", score);
+    }
+    gtk_list_store_append (self->priv->list, &iter);
+    gtk_list_store_set (self->priv->list, &iter, 0, name, 1, time, 2, ss, -1);
+    g_free (ss);
+    g_free (time);
+    scorelist = g_list_next (scorelist);
+  }
+    
+  games_scores_dialog_set_hilight_private (self);
+}
+
+/* Change the currently viewed score category. There is a little bit
+ * of silly-buggers here to make sure the change is temporary and
+ * we end up on the right page next time. */
+static void games_scores_dialog_change_category (GtkComboBox *widget, 
+                                                GamesScoresDialog *self)
+{
+  gchar *catcopy;
+  gint idx;
+  gchar *newcat;
+  
+  /* This seems like a bit of a hack, but since we're trying to
+   * temporarily change the category it sort of makes sense. */
+
+  catcopy = g_strdup (games_scores_get_category (self->priv->scores));
+  idx = gtk_combo_box_get_active (widget);
+  newcat = g_hash_table_lookup (self->priv->catindices,
+                                GINT_TO_POINTER (idx));
+
+  games_scores_set_category (self->priv->scores, newcat);
+  if (self->priv->preservehilight) {
+    self->priv->preservehilight = FALSE;
+  } else {
+    self->priv->hilight = 0;
+  }
+  games_scores_dialog_redraw (self);
+  games_scores_set_category (self->priv->scores, catcopy);
+
+  g_free (catcopy);
+}
+
+/* This is to make sure we update ourselves when the window goes through
+ * a hide/show cycle. */
+/* FIXME: We should monitor the high scores list (or get games-scores to
+ * send us a signal. */
+static void games_scores_dialog_show (GamesScoresDialog *self)
+{ 
+  const gchar *cat;
+  
+  cat = games_scores_get_category (self->priv->scores);
+  if (cat)
+    games_scores_dialog_set_category (self, cat);
+  games_scores_dialog_redraw (self);
+}
+
+/* This is the other half of ensuring the hide/show cycle works properly. */
+static void games_scores_dialog_hide (GamesScoresDialog *self) {
+  self->priv->hilight = 0;
+  gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (self->priv->treeview));
+}
+
+/**
+ * set_category_description:
+ * @self: a pointer to a GamesScoresDialog
+ * @description: A description of the categories 
+ * 
+ * Sets the category description label. i.e. the widget to the
+ * left of the category combo box. 
+ *
+ **/
+void games_scores_dialog_set_category_description (GamesScoresDialog *self, 
+                                                  const gchar *description)
+{
+  gchar *lstr;
+
+  lstr = g_strdup_printf ("<b>%s</b>", description);
+  gtk_label_set_markup (GTK_LABEL (self->priv->label), lstr);
+  gtk_label_set_use_underline (GTK_LABEL (self->priv->label), TRUE);
+  g_free(lstr);
+}
+
+/**
+ * set_message:
+ * @self: a pointer to a GamesScoresDialog
+ * @message: the message
+ * 
+ * Sets the message at the top of the dialog. Pango markup is understood.
+ *
+ **/
+void games_scores_dialog_set_message (GamesScoresDialog *self, 
+                                     const gchar *message)
+{
+  if ((message == NULL) || (*message == '\0')) {
+    gtk_widget_hide (self->priv->message);
+    gtk_widget_hide (self->priv->hdiv);
+  } else {
+    gtk_widget_show (self->priv->message);
+    gtk_widget_show (self->priv->hdiv);
+    gtk_label_set_label (GTK_LABEL (self->priv->message), message);
+  }
+}
+
+/**
+ * set_category_description:
+ * @self: a pointer to a GamesScoresDialog
+ * @pos: the position in the high score list to hilight. Should be in the
+ * range 1 to 10.
+ * 
+ * Hilights an entry in the high score list. This is suitable for indicating
+ * to the player where the game they just played is.
+ *
+ **/
+void games_scores_dialog_set_hilight (GamesScoresDialog *self, guint pos)
+{
+  if ((pos < 1) || (pos > GAMES_SCORES_SIGNIFICANT))
+    return;
+
+  self->priv->hilight = pos;
+  games_scores_dialog_set_hilight_private (self);
+}
+
+/**
+ * set_buttons:
+ * @self: a pointer to a GamesScoresDialog
+ * @buttons: An or-ed list of GamesScoresButtons
+ * 
+ * Changes the button sets at the buttom of the dialog
+ *
+ **/
+void games_scores_dialog_set_buttons (GamesScoresDialog *self, guint buttons)
+{
+  /* Remove an existing buttons. */
+  gtk_container_foreach (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (self))),
+                         (GtkCallback) (gtk_widget_destroy), NULL);
+
+  /* The default is a single close button, suitable for the scores
+     menu item. */
+  if (buttons == 0)
+       buttons = GAMES_SCORES_CLOSE_BUTTON;
+
+  if (buttons & GAMES_SCORES_QUIT_BUTTON) {
+       gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_QUIT,
+                              GTK_RESPONSE_REJECT);
+      gtk_dialog_set_default_response (GTK_DIALOG (self), 
+                                        GTK_RESPONSE_REJECT);
+  }
+
+  if (buttons & GAMES_SCORES_UNDO_BUTTON) {
+       gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_UNDO,
+                              GTK_RESPONSE_DELETE_EVENT);
+      gtk_dialog_set_default_response (GTK_DIALOG (self), 
+                                        GTK_RESPONSE_DELETE_EVENT);
+  }
+
+  if (buttons & GAMES_SCORES_NEW_GAME_BUTTON) {
+       gtk_dialog_add_button (GTK_DIALOG (self), _("New Game"),
+                              GTK_RESPONSE_ACCEPT);
+      gtk_dialog_set_default_response (GTK_DIALOG (self), 
+                                        GTK_RESPONSE_ACCEPT);
+  }
+
+  if (buttons & GAMES_SCORES_CLOSE_BUTTON) {
+       gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CLOSE,
+                              GTK_RESPONSE_CLOSE);
+      gtk_dialog_set_default_response (GTK_DIALOG (self), 
+                                        GTK_RESPONSE_CLOSE);
+  }
+}
+
+static void games_scores_dialog_init (GamesScoresDialog *self) 
+{
+  GtkWidget *vbox;
+  GtkWidget *scroll;
+  GtkWidget *listview;
+  GtkTreeViewColumn *column;
+  GtkTreeViewColumn *timecolumn;
+  GtkCellRenderer *renderer;
+  GtkCellRenderer *timerenderer;
+
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GAMES_TYPE_SCORES_DIALOG,
+                                            GamesScoresDialogPrivate);
+
+  self->priv->style = GAMES_SCORES_STYLE_PLAIN_DESCENDING;
+  /* These two hashes are the reverse of each other. As an optimisation 
+   * they share the same set of strings (as keys in the first case and
+   * as data in the second). The first hash is responsible for 
+   * deallocating the memory for the strings. These two are only
+   * valid as a pair. */
+  self->priv->categories = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                    g_free, NULL);
+  self->priv->catindices = g_hash_table_new (g_direct_hash, g_direct_equal);
+  self->priv->catcounter = 0;
+  self->priv->hilight = 0;
+  self->priv->sethilight = -1;
+  gtk_container_set_border_width (GTK_CONTAINER (self), 5);
+  gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), 2);
+
+  g_signal_connect (G_OBJECT (self), "show", 
+                     G_CALLBACK (games_scores_dialog_show), NULL);
+  g_signal_connect (G_OBJECT (self), "hide", 
+                     G_CALLBACK (games_scores_dialog_hide), NULL);
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+  gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))),
+                    vbox, TRUE, TRUE, 0);
+
+  scroll = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+                                   GTK_POLICY_AUTOMATIC,
+                                   GTK_POLICY_AUTOMATIC);
+  gtk_widget_set_size_request (scroll, 250, 265);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
+                                        GTK_SHADOW_ETCHED_IN);
+  gtk_box_pack_end (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
+  
+  self->priv->message = gtk_label_new ("");
+  gtk_label_set_use_markup (GTK_LABEL (self->priv->message), TRUE);
+  gtk_label_set_justify (GTK_LABEL (self->priv->message), 
+                          GTK_JUSTIFY_CENTER);    
+  gtk_box_pack_start (GTK_BOX (vbox), self->priv->message, FALSE, FALSE, 0);
+
+  self->priv->hdiv = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+  gtk_box_pack_start (GTK_BOX (vbox), self->priv->hdiv, FALSE, FALSE, 0);
+
+  self->priv->catbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_box_pack_start (GTK_BOX (vbox), self->priv->catbar, FALSE, FALSE, 0);
+
+  self->priv->label = gtk_label_new (NULL);
+  gtk_label_set_use_markup (GTK_LABEL (self->priv->label), TRUE);
+  gtk_box_pack_start (GTK_BOX (self->priv->catbar), self->priv->label,
+                       FALSE, FALSE, 0);       
+ 
+  self->priv->combo = gtk_combo_box_text_new ();
+  gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (self->priv->combo), FALSE);
+  gtk_box_pack_start (GTK_BOX (self->priv->catbar), 
+                       self->priv->combo, TRUE, TRUE, 0);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (self->priv->label), self->priv->combo);
+
+  g_signal_connect (G_OBJECT (self->priv->combo), "changed", 
+                     G_CALLBACK (games_scores_dialog_change_category), self);
+
+  self->priv->list = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+  listview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (self->priv->list));
+  self->priv->treeview = GTK_TREE_VIEW (listview);
+  self->priv->cursor_handler_id = 
+    g_signal_connect (G_OBJECT (self->priv->treeview), 
+                       "cursor-changed", 
+                       G_CALLBACK (games_scores_dialog_cursor_changed), self);
+  
+  self->priv->namerenderer = gtk_cell_renderer_text_new ();
+  g_signal_connect (self->priv->namerenderer, "edited", 
+                     G_CALLBACK (games_scores_dialog_name_edited), self);
+
+  self->priv->namecolumn = gtk_tree_view_column_new_with_attributes (/* Score dialog column header for the 
name of the player who recorded the score */
+                                                                     C_("score-dialog", "Name"),
+                                                                     self->priv->namerenderer,
+                                                                     "text", 0,
+                                                                     NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (listview),
+                                GTK_TREE_VIEW_COLUMN (self->priv->namecolumn));
+
+  timerenderer = gtk_cell_renderer_text_new ();
+  timecolumn = gtk_tree_view_column_new_with_attributes (/* Score dialog column header for the date the 
score was recorded */
+                                                         _("Date"),
+                                                         timerenderer,
+                                                         "text", 1,
+                                                         NULL);
+  g_object_set (G_OBJECT (timerenderer), "xalign", 1.0, NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (listview),
+                               GTK_TREE_VIEW_COLUMN (timecolumn));
+  self->priv->timecolumn = timecolumn;
+
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes ("", renderer, "text", 2, NULL);
+  g_object_set (G_OBJECT (renderer), "xalign", 1.0, NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (listview),
+                                GTK_TREE_VIEW_COLUMN (column));
+  self->priv->column = column;
+ 
+  gtk_container_add (GTK_CONTAINER (scroll), listview);
+  
+  games_scores_dialog_set_buttons (self, GAMES_SCORES_CLOSE_BUTTON);
+
+  gtk_window_set_destroy_with_parent (GTK_WINDOW (self), TRUE);
+
+  gtk_widget_grab_focus (self->priv->combo);
+
+  gtk_widget_show_all (vbox);
+  gtk_widget_hide (self->priv->hdiv);
+  gtk_widget_hide (self->priv->message);
+}
+
+/* FIXME: There is basically no range checking. */
+
diff --git a/src/games-scores-dialog.h b/src/games-scores-dialog.h
new file mode 100644
index 0000000..8b168ae
--- /dev/null
+++ b/src/games-scores-dialog.h
@@ -0,0 +1,81 @@
+/* -*- mode: C -*-
+
+   games-scores-dialog.h
+   Copyright 2004, 2005, 2006 Callum McKenzie
+
+   This library is free software; you can redistribute it and'or modify
+   it under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This library 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Authors:   Callum McKenzie <callum physics otago ac nz> */
+
+#ifndef GAMES_SCORES_DIALOG_H
+#define GAMES_SCORES_DIALOG_H
+
+#include <gtk/gtk.h>
+
+#include "games-score.h" /* For GamesScoreStyle. */
+#include "games-scores.h"
+
+G_BEGIN_DECLS
+#define GAMES_TYPE_SCORES_DIALOG (games_scores_dialog_get_type ())
+#define GAMES_SCORES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+                                  GAMES_TYPE_SCORES_DIALOG, \
+                                  GamesScoresDialog))
+#define GAMES_SCORES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+                                          GAMES_TYPE_SCORES_DIALOG, \
+                                          GamesScoresDialogClass))
+#define GAMES_IS_SCORES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                                     GAMES_TYPE_SCORES_DIALOG))
+#define GAMES_IS_SCORES_DIALOG_CLASS(kls) (G_TYPE_CHECK_CLASS_TYPE ((kls), \
+                                           GAMES_TYPE_SCORES_DIALOG))
+#define GAMES_GET_SCORES_DIALOG_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                                            GAMES_TYPE_SCORES_DIALOG, \
+                                            GamesScoresDialogClass))
+
+/* This enumeration is to provide common buttons for the dialog. */
+
+typedef enum {
+  GAMES_SCORES_CLOSE_BUTTON = 1,
+  GAMES_SCORES_NEW_GAME_BUTTON = 2,    
+  GAMES_SCORES_UNDO_BUTTON = 4,
+  GAMES_SCORES_QUIT_BUTTON = 8,
+} GamesScoresButtons;
+
+typedef struct GamesScoresDialogPrivate GamesScoresDialogPrivate;
+
+typedef struct {
+  GtkDialog dialog;
+  /*< private >*/
+  GamesScoresDialogPrivate *priv;
+} GamesScoresDialog;
+
+typedef struct {
+  GtkDialogClass parent_class;
+} GamesScoresDialogClass;
+
+GType      games_scores_dialog_get_type                 (void);
+GtkWidget *games_scores_dialog_new                      (GtkWindow *parent_window,
+                                                         GamesScores *scores,
+                                                         const gchar *title);
+void       games_scores_dialog_set_category_description (GamesScoresDialog *self, 
+                                                         const gchar *description);
+void       games_scores_dialog_set_hilight              (GamesScoresDialog *self,
+                                                         guint pos);
+void       games_scores_dialog_set_message              (GamesScoresDialog *self, 
+                                                         const gchar *message);
+void       games_scores_dialog_set_buttons              (GamesScoresDialog *self,
+                                                         guint buttons);
+
+G_END_DECLS
+#endif
diff --git a/src/gnibbles.c b/src/gnibbles.c
index 29fff5c..e6603ba 100644
--- a/src/gnibbles.c
+++ b/src/gnibbles.c
@@ -1,4 +1,4 @@
-//* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 
 /*
  *   Gnome Nibbles: Gnome Worm Game
@@ -40,6 +40,7 @@
 #include "board.h"
 #include "sound.h"
 #include "worm.h"
+#include "games-scores-dialog.h"
 #include "games-scores.h"
 
 GnibblesWorm *worms[NUMWORMS];
@@ -329,6 +330,38 @@ gnibbles_keypress_worms (guint keyval)
 }
 
 void
+gnibbles_show_scores (GtkWidget * window, gint pos)
+{
+  static GtkWidget *scoresdialog = NULL;
+  gchar *message;
+
+  if (!scoresdialog) {
+    scoresdialog = games_scores_dialog_new (GTK_WINDOW (window),
+                                            highscores,
+                                            _("Nibbles Scores"));
+    games_scores_dialog_set_category_description (GAMES_SCORES_DIALOG
+                                                  (scoresdialog),
+                                                  _("Speed:"));
+  }
+  if (pos > 0) {
+    games_scores_dialog_set_hilight (GAMES_SCORES_DIALOG (scoresdialog), pos);
+    message = g_strdup_printf ("<b>%s</b>\n\n%s",
+                               _("Congratulations!"),
+                               pos == 1 ? _("Your score is the best!") :
+                               _("Your score has made the top ten."));
+    games_scores_dialog_set_message (GAMES_SCORES_DIALOG (scoresdialog),
+                                     message);
+    g_free (message);
+  } else {
+    games_scores_dialog_set_message (GAMES_SCORES_DIALOG (scoresdialog),
+                                     NULL);
+  }
+
+  gtk_dialog_run (GTK_DIALOG (scoresdialog));
+  gtk_widget_hide (scoresdialog);
+}
+
+void
 gnibbles_log_score (GtkWidget * window)
 {
   gint pos;
@@ -347,4 +380,5 @@ gnibbles_log_score (GtkWidget * window)
 
   pos = games_scores_add_plain_score (highscores, worms[0]->score);
 
+  gnibbles_show_scores (window, pos);
 }
diff --git a/src/main.c b/src/main.c
index 45170ef..71a6be2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -330,6 +330,12 @@ pause_game_cb (GtkAction * action, gpointer data)
   }
 }
 
+static void
+show_scores_cb (GtkAction * action, gpointer data)
+{
+  gnibbles_show_scores (window, 0);
+}
+
 void
 end_game (void)
 {
@@ -587,6 +593,8 @@ static const GtkActionEntry action_entry[] = {
    G_CALLBACK (end_game_cb)},
   {"Pause", NULL, N_("_Pause"), NULL, NULL,
    G_CALLBACK (pause_game_cb)},
+  {"Scores", NULL, N_("_Scores"), NULL, NULL,
+   G_CALLBACK (show_scores_cb)},
   {"Quit", GTK_STOCK_QUIT, NULL, NULL, NULL, G_CALLBACK (quit_cb)},
   {"Preferences", GTK_STOCK_PREFERENCES, NULL, NULL, NULL,
    G_CALLBACK (gnibbles_preferences_cb)},
@@ -603,6 +611,8 @@ static const char ui_description[] =
   "      <separator/>"
   "      <menuitem action='Pause'/>"
   "      <separator/>"
+  "      <menuitem action='Scores'/>"
+  "      <separator/>"
   "      <menuitem action='Quit'/>"
   "    </menu>"
   "    <menu action='ViewMenu'>"


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