#include "disobedience.h"
static GtkWidget *globals_window;
-static void globals_close(GtkButton attribute((unused)) *button,
- gpointer attribute((unused)) userdata);
-static struct globals_row {
+struct globals_row;
+
+/** @brief Handler for the presentation form of a global preference */
+struct global_handler {
+ /** @brief Initialize */
+ void (*init)(struct globals_row *row);
+
+ /** @brief Convert presentation form to string */
+ const char *(*get)(struct globals_row *row);
+
+ /** @brief Convert string to presentation form */
+ void (*set)(struct globals_row *row, const char *value);
+};
+
+/** @brief Definition of a global preference */
+struct globals_row {
const char *label;
const char *pref;
- GtkWidget *entry;
-} globals_rows[] = {
- { "Required tags", "required-tags", NULL },
- { "Prohibited tags", "prohibited-tags", NULL },
- { "Plating", "playing", NULL },
- { "Random play", "random-play", NULL },
+ GtkWidget *widget;
+ const struct global_handler *handler;
+ int initialized;
+};
+
+static void globals_close(GtkButton attribute((unused)) *button,
+ gpointer attribute((unused)) userdata);
+static void globals_row_changed(struct globals_row *row);
+
+/** @brief Called when the user changes the contents of a string entry */
+static void global_string_entry_changed(GtkEditable attribute((unused)) *editable,
+ gpointer user_data) {
+ struct globals_row *row = user_data;
+ globals_row_changed(row);
+}
+
+/** @brief Initialize a global presented as a string */
+static void global_string_init(struct globals_row *row) {
+ row->widget = gtk_entry_new();
+ g_signal_connect(row->widget, "changed",
+ G_CALLBACK(global_string_entry_changed), row);
+}
+
+static const char *global_string_get(struct globals_row *row) {
+ return gtk_entry_get_text(GTK_ENTRY(row->widget));
+}
+
+static void global_string_set(struct globals_row *row, const char *value) {
+ /* Identify unset and empty lists */
+ if(!value)
+ value = "";
+ /* Skip trivial updates (we'll see one as a consequence of each
+ * update we make...) */
+ if(strcmp(gtk_entry_get_text(GTK_ENTRY(row->widget)), value))
+ gtk_entry_set_text(GTK_ENTRY(row->widget), value);
+}
+
+/** @brief String global preference */
+static const struct global_handler global_string = {
+ global_string_init,
+ global_string_get,
+ global_string_set,
+};
+
+/** @brief Called when the user changes the contents of a string entry */
+static void global_boolean_toggled(GtkToggleButton attribute((unused)) *button,
+ gpointer user_data) {
+ struct globals_row *row = user_data;
+ globals_row_changed(row);
+}
+
+static void global_boolean_init(struct globals_row *row) {
+ row->widget = gtk_check_button_new();
+ g_signal_connect(row->widget, "toggled",
+ G_CALLBACK(global_boolean_toggled), row);
+}
+
+static const char *global_boolean_get(struct globals_row *row) {
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(row->widget)) ? "yes" : "no";
+}
+
+static void global_boolean_set(struct globals_row *row, const char *value) {
+ gboolean new_state = !(value && strcmp(value, "yes"));
+ if(new_state != gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(row->widget)))
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->widget), new_state);
+}
+
+/** @brief Boolean global preference */
+static const struct global_handler global_boolean = {
+ global_boolean_init,
+ global_boolean_get,
+ global_boolean_set,
+};
+
+/** @brief Table of global preferences */
+static struct globals_row globals_rows[] = {
+ { "Required tags", "required-tags", NULL, &global_string, 0 },
+ { "Prohibited tags", "prohibited-tags", NULL, &global_string, 0 },
+ { "Playing", "playing", NULL, &global_boolean, 0 },
+ { "Random play", "random-play", NULL, &global_boolean, 0 },
};
#define NGLOBALS (sizeof globals_rows / sizeof *globals_rows)
popup_protocol_error(0, err);
else if(globals_window) {
struct globals_row *row = v;
- /* Identify unset and empty lists */
- if(!value)
- value = "";
- /* Skip trivial updates (we'll see one as a consequence of each
- * update we make...) */
- if(strcmp(gtk_entry_get_text(GTK_ENTRY(row->entry)), value))
- gtk_entry_set_text(GTK_ENTRY(row->entry), value);
+ row->handler->set(row, value);
+ row->initialized = 1;
}
}
disorder_eclient_get_global(client, globals_get_completed, row->pref, row);
}
-/** @brief Called when the user changes the contents of some entry */
-static void globals_entry_changed(GtkEditable *editable, gpointer user_data) {
- struct globals_row *row = user_data;
- const char *new_value = gtk_entry_get_text(GTK_ENTRY(editable));
- if(*new_value)
- disorder_eclient_set_global(client, NULL, row->pref, new_value, row);
- else
- disorder_eclient_unset_global(client, NULL, row->pref, row);
+static void globals_row_changed(struct globals_row *row) {
+ if(row->initialized) {
+ const char *new_value = row->handler->get(row);
+ if(new_value)
+ disorder_eclient_set_global(client, NULL, row->pref, new_value, row);
+ else
+ disorder_eclient_unset_global(client, NULL, row->pref, row);
+ }
}
/** @brief Display the globals window */
gtk_widget_set_style(table, tool_style);\
for(size_t n = 0; n < NGLOBALS; ++n) {
+ globals_rows[n].initialized = 0;
label = gtk_label_new(globals_rows[n].label);
gtk_widget_set_style(label, tool_style);
gtk_misc_set_alignment(GTK_MISC(label), 1/*right*/, 0/*bottom*/);
n, n+1, /* top/bottom_attach */
GTK_FILL, 0, /* x/yoptions */
1, 1); /* x/ypadding */
- globals_rows[n].entry = gtk_entry_new();
- gtk_widget_set_style(globals_rows[n].entry, tool_style);
- gtk_table_attach(GTK_TABLE(table), globals_rows[n].entry,
+ globals_rows[n].handler->init(&globals_rows[n]);
+ gtk_widget_set_style(globals_rows[n].widget, tool_style);
+ gtk_table_attach(GTK_TABLE(table), globals_rows[n].widget,
1, 2, /* left/right_attach */
n, n+1, /* top/bottom_attach */
GTK_FILL, 0, /* x/yoptions */
1, 1); /* x/ypadding */
- g_signal_connect(globals_rows[n].entry, "changed",
- G_CALLBACK(globals_entry_changed), &globals_rows[n]);
globals_get(&globals_rows[n]);
}
hbox = create_buttons_box(globals_buttons,
}
/** @brief Called when any global pref changes */
-static void globals_pref_changed(const char *event,
+static void globals_pref_changed(const char attribute((unused)) *event,
void *eventdata,
- void *callbackdata) {
+ void attribute((unused)) *callbackdata) {
const char *pref = eventdata;
if(!globals_window)
return; /* not paying attention */