diff --git a/devel.but b/devel.but index 1df57cf..e481ec6 100644 --- 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 c7713a1..1f991d6 100644 --- 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, ¶ms); - 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)); diff --git a/midend.c b/midend.c index 250a479..87df28a 100644 --- 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; diff --git a/puzzles.h b/puzzles.h index 2a9f517..1c5342d 100644 --- 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);