chiark / gitweb /
New feature in midend.c which allows us to ask for the number of the
authorSimon Tatham <anakin@pobox.com>
Tue, 8 Apr 2008 16:25:39 +0000 (16:25 +0000)
committerSimon Tatham <anakin@pobox.com>
Tue, 8 Apr 2008 16:25:39 +0000 (16:25 +0000)
currently selected preset, if any. I've used this in the GTK front
end to have the Type menu mark the currently selected menu item.
(After considerable beating of GTK with sticks, I might add. Grr.)
Currently the same UI feature is not yet supported on Windows or
MacOS, but I hope to do those too at some point if it's feasible.

[originally from svn r7980]

devel.but
gtk.c
midend.c
puzzles.h

index 1df57cff1e3217054a97482bb7b21ef72755275b..e481ec6311bca011881328df67186860bf5f6c5b 100644 (file)
--- a/devel.but
+++ b/devel.but
@@ -2728,6 +2728,16 @@ are owned by the mid-end structure: the front end should not ever
 free them directly, because they will be freed automatically during
 \cw{midend_free()}.
 
+\H{midend-which-preset} \cw{midend_which_preset()}
+
+\c int midend_which_preset(midend *me);
+
+Returns the numeric index of the preset game parameter structure
+which matches the current game parameters, or a negative number if
+no preset matches. Front ends could use this to maintain a tick
+beside one of the items in the menu (or tick the \q{Custom} option
+if the return value is less than zero).
+
 \H{midend-wants-statusbar} \cw{midend_wants_statusbar()}
 
 \c int midend_wants_statusbar(midend *me);
diff --git a/gtk.c b/gtk.c
index c7713a1c4283f77dfc6d0d1f8e86527843aaded5..1f991d6a20c9f1f72570eb454b8d794a0786f19d 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -79,6 +79,8 @@ void fatal(char *fmt, ...)
  * GTK front end to puzzles.
  */
 
+static void update_preset_tick(frontend *fe);
+
 struct font {
 #ifdef USE_PANGO
     PangoFontDescription *desc;
@@ -122,6 +124,9 @@ struct frontend {
     int pw, ph;                        /* pixmap size (w, h are area size) */
     int ox, oy;                        /* offset of pixmap in drawing area */
     char *filesel_name;
+    int npresets;
+    GtkWidget **preset_bullets;
+    GtkWidget *preset_custom_bullet;
 };
 
 void get_random_seed(void **randseed, int *randseedsize)
@@ -844,6 +849,7 @@ static void config_ok_button_clicked(GtkButton *button, gpointer data)
     else {
        fe->cfgret = TRUE;
        gtk_widget_destroy(fe->cfgbox);
+       update_preset_tick(fe);
     }
 }
 
@@ -1100,6 +1106,29 @@ static void get_size(frontend *fe, int *px, int *py)
        gdk_window_resize(GTK_WIDGET(win)->window, x, y)
 #endif
 
+static void update_menuitem_bullet(GtkWidget *label, int visible)
+{
+    if (visible) {
+       gtk_label_set_text(GTK_LABEL(label), "\xE2\x80\xA2");
+    } else {
+       gtk_label_set_text(GTK_LABEL(label), "");
+    }
+}
+
+static void update_preset_tick(frontend *fe)
+{
+    int n = midend_which_preset(fe->me);
+    int i;
+
+    if (fe->preset_bullets) {
+       for (i = 0; i < fe->npresets; i++)
+           update_menuitem_bullet(fe->preset_bullets[i], n == i);
+    }
+    if (fe->preset_custom_bullet) {
+       update_menuitem_bullet(fe->preset_custom_bullet, n < 0);
+    }
+}
+
 static void resize_fe(frontend *fe)
 {
     int x, y;
@@ -1129,6 +1158,7 @@ static void menu_preset_event(GtkMenuItem *menuitem, gpointer data)
 
     midend_set_params(fe->me, params);
     midend_new_game(fe->me);
+    update_preset_tick(fe);
     resize_fe(fe);
 }
 
@@ -1358,6 +1388,7 @@ static void menu_load_event(GtkMenuItem *menuitem, gpointer data)
             return;
         }
 
+       update_preset_tick(fe);
         resize_fe(fe);
     }
 }
@@ -1448,6 +1479,34 @@ static void add_menu_separator(GtkContainer *cont)
 
 enum { ARG_EITHER, ARG_SAVE, ARG_ID }; /* for argtype */
 
+static GtkWidget *make_preset_menuitem(GtkWidget **bulletlabel,
+                                      const char *name)
+{
+    GtkWidget *hbox, *lab1, *lab2, *menuitem;
+    GtkRequisition req;
+
+    hbox = gtk_hbox_new(FALSE, 0);
+    gtk_widget_show(hbox);
+    lab1 = gtk_label_new("\xE2\x80\xA2 ");
+    gtk_widget_show(lab1);
+    gtk_box_pack_start(GTK_BOX(hbox), lab1, FALSE, FALSE, 0);
+    gtk_misc_set_alignment(GTK_MISC(lab1), 0.0, 0.0);
+    lab2 = gtk_label_new(name);
+    gtk_widget_show(lab2);
+    gtk_box_pack_start(GTK_BOX(hbox), lab2, TRUE, TRUE, 0);
+    gtk_misc_set_alignment(GTK_MISC(lab2), 0.0, 0.0);
+
+    gtk_widget_size_request(lab1, &req);
+    gtk_widget_set_usize(lab1, req.width, -1);
+    gtk_label_set_text(GTK_LABEL(lab1), "");
+
+    menuitem = gtk_menu_item_new();
+    gtk_container_add(GTK_CONTAINER(menuitem), hbox);
+
+    *bulletlabel = lab1;
+    return menuitem;
+}
+
 static frontend *new_window(char *arg, int argtype, char **error)
 {
     frontend *fe;
@@ -1583,13 +1642,17 @@ static frontend *new_window(char *arg, int argtype, char **error)
         submenu = gtk_menu_new();
         gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
 
+       fe->npresets = n;
+       fe->preset_bullets = snewn(n, GtkWidget *);
+
         for (i = 0; i < n; i++) {
             char *name;
             game_params *params;
 
             midend_fetch_preset(fe->me, i, &name, &params);
 
-            menuitem = gtk_menu_item_new_with_label(name);
+           menuitem = make_preset_menuitem(&fe->preset_bullets[i], name);
+
             gtk_container_add(GTK_CONTAINER(submenu), menuitem);
             gtk_object_set_data(GTK_OBJECT(menuitem), "user-data", params);
             gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
@@ -1598,14 +1661,23 @@ static frontend *new_window(char *arg, int argtype, char **error)
         }
 
        if (thegame.can_configure) {
-            menuitem = gtk_menu_item_new_with_label("Custom...");
+           menuitem = make_preset_menuitem(&fe->preset_custom_bullet,
+                                           "Custom...");
+
+            gtk_container_add(GTK_CONTAINER(submenu), menuitem);
             gtk_object_set_data(GTK_OBJECT(menuitem), "user-data",
                                GPOINTER_TO_INT(CFG_SETTINGS));
-            gtk_container_add(GTK_CONTAINER(submenu), menuitem);
             gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
                                GTK_SIGNAL_FUNC(menu_config_event), fe);
             gtk_widget_show(menuitem);
-       }
+       } else
+           fe->preset_custom_bullet = NULL;
+
+       update_preset_tick(fe);
+    } else {
+       fe->npresets = 0;
+       fe->preset_bullets = NULL;
+       fe->preset_custom_bullet = NULL;
     }
 
     add_menu_separator(GTK_CONTAINER(menu));
index 250a479e3a59a952582f9b965de88fc7ca745f48..87df28a4e84f0192b6e795e215ad455479104c71 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -31,7 +31,7 @@ struct midend {
     const game *ourgame;
 
     game_params **presets;
-    char **preset_names;
+    char **preset_names, **preset_encodings;
     int npresets, presetsize;
 
     /*
@@ -115,6 +115,7 @@ midend *midend_new(frontend *fe, const game *ourgame,
     me->oldstate = NULL;
     me->presets = NULL;
     me->preset_names = NULL;
+    me->preset_encodings = NULL;
     me->npresets = me->presetsize = 0;
     me->anim_time = me->anim_pos = 0.0F;
     me->flash_time = me->flash_pos = 0.0F;
@@ -186,9 +187,11 @@ void midend_free(midend *me)
        for (i = 0; i < me->npresets; i++) {
            sfree(me->presets[i]);
            sfree(me->preset_names[i]);
+           sfree(me->preset_encodings[i]);
        }
        sfree(me->presets);
        sfree(me->preset_names);
+       sfree(me->preset_encodings);
     }
     if (me->ui)
         me->ourgame->free_ui(me->ui);
@@ -836,10 +839,14 @@ int midend_num_presets(midend *me)
                                       game_params *);
                 me->preset_names = sresize(me->preset_names, me->presetsize,
                                            char *);
+                me->preset_encodings = sresize(me->preset_encodings,
+                                              me->presetsize, char *);
             }
 
             me->presets[me->npresets] = preset;
             me->preset_names[me->npresets] = name;
+            me->preset_encodings[me->npresets] =
+               me->ourgame->encode_params(preset, TRUE);;
             me->npresets++;
         }
     }
@@ -890,10 +897,14 @@ int midend_num_presets(midend *me)
                                           game_params *);
                     me->preset_names = sresize(me->preset_names,
                                                me->presetsize, char *);
+                    me->preset_encodings = sresize(me->preset_encodings,
+                                                  me->presetsize, char *);
                 }
 
                 me->presets[me->npresets] = preset;
                 me->preset_names[me->npresets] = dupstr(name);
+                me->preset_encodings[me->npresets] =
+                   me->ourgame->encode_params(preset, TRUE);
                 me->npresets++;
             }
         }
@@ -910,6 +921,22 @@ void midend_fetch_preset(midend *me, int n,
     *params = me->presets[n];
 }
 
+int midend_which_preset(midend *me)
+{
+    char *encoding = me->ourgame->encode_params(me->params, TRUE);
+    int i, ret;
+
+    ret = -1;
+    for (i = 0; i < me->npresets; i++)
+       if (!strcmp(encoding, me->preset_encodings[i])) {
+           ret = i;
+           break;
+       }
+
+    sfree(encoding);
+    return ret;
+}
+
 int midend_wants_statusbar(midend *me)
 {
     return me->ourgame->wants_statusbar;
index 2a9f517e27c0ce870682c5116919c62594ce021c..1c5342d9b5081909b685682095eeee9a326a851f 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -235,6 +235,7 @@ void midend_timer(midend *me, float tplus);
 int midend_num_presets(midend *me);
 void midend_fetch_preset(midend *me, int n,
                          char **name, game_params **params);
+int midend_which_preset(midend *me);
 int midend_wants_statusbar(midend *me);
 enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_FRONTEND_SPECIFIC };
 config_item *midend_get_config(midend *me, int which, char **wintitle);