[gnome-nibbles/gnome-3-10] Revert "Remove score-dialog that doesn't work, remaining score functionality should be working"
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-nibbles/gnome-3-10] Revert "Remove score-dialog that doesn't work, remaining score functionality should be working"
- Date: Wed, 6 Nov 2013 04:39:53 +0000 (UTC)
commit a028d8f88f810f26cb08271470b7fe51d21aac46
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
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 9df28c3..6ca61d0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,6 +21,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 81625d6..d2b7028 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];
@@ -330,6 +331,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;
@@ -348,4 +381,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 d28ec89..0404c19 100644
--- a/src/main.c
+++ b/src/main.c
@@ -327,6 +327,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)
{
@@ -582,6 +588,8 @@ static const GtkActionEntry action_entry[] = {
G_CALLBACK (new_game_cb)},
{"EndGame", NULL, N_("_End Game"), NULL, NULL,
G_CALLBACK (end_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)},
@@ -598,6 +606,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]