diff options
author | Alexey Yakovenko <waker@users.sourceforge.net> | 2013-10-20 20:53:22 +0200 |
---|---|---|
committer | Alexey Yakovenko <waker@users.sourceforge.net> | 2013-10-20 20:53:22 +0200 |
commit | 1233aa87bcad5a87024ebe9031fc732172cd99ff (patch) | |
tree | 65c04eab84f09bc947f1a549c80dd6a0007cd458 | |
parent | e3f56e349af1f8481f4aeb7dc428f9e68804b35e (diff) |
gtkui: proper single-instance widget support
-rw-r--r-- | plugins/gtkui/gtkui.c | 30 | ||||
-rw-r--r-- | plugins/gtkui/gtkui_api.h | 10 | ||||
-rw-r--r-- | plugins/gtkui/widgets.c | 139 | ||||
-rw-r--r-- | plugins/gtkui/widgets.h | 2 | ||||
-rw-r--r-- | plugins/pltbrowser/pltbrowser.c | 2 |
5 files changed, 88 insertions, 95 deletions
diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c index 44d3a31f..00e44073 100644 --- a/plugins/gtkui/gtkui.c +++ b/plugins/gtkui/gtkui.c @@ -959,21 +959,21 @@ gtkui_thread (void *ctx) { gtk_init (&argc, (char ***)&argv); // register widget types - w_reg_widget (_("Playlist with tabs"), w_tabbed_playlist_create, "tabbed_playlist", NULL); - w_reg_widget (NULL, w_box_create, "box", NULL); - w_reg_widget (_("Splitter (top and bottom)"), w_vsplitter_create, "vsplitter", NULL); - w_reg_widget (_("Splitter (left and right)"), w_hsplitter_create, "hsplitter", NULL); - w_reg_widget (NULL, w_placeholder_create, "placeholder", NULL); -// w_reg_widget (_("Tabs"), w_tabs_create, "tabs", NULL); - w_reg_widget (_("Playlist tabs"), w_tabstrip_create, "tabstrip", NULL); - w_reg_widget (_("Playlist"), w_playlist_create, "playlist", NULL); - w_reg_widget (_("Selection properties"), w_selproperties_create, "selproperties", NULL); - w_reg_widget (_("Album art display"), w_coverart_create, "coverart", NULL); - w_reg_widget (_("Scope"), w_scope_create, "scope", NULL); - w_reg_widget (_("Spectrum"), w_spectrum_create, "spectrum", NULL); - w_reg_widget (_("HBox"), w_hbox_create, "hbox", NULL); - w_reg_widget (_("VBox"), w_vbox_create, "vbox", NULL); - w_reg_widget (_("Button"), w_button_create, "button", NULL); + w_reg_widget (_("Playlist with tabs"), DDB_WF_SINGLE_INSTANCE, w_tabbed_playlist_create, "tabbed_playlist", NULL); + w_reg_widget (_("Playlist"), DDB_WF_SINGLE_INSTANCE, w_playlist_create, "playlist", NULL); + w_reg_widget (NULL, 0, w_box_create, "box", NULL); + w_reg_widget (_("Splitter (top and bottom)"), 0, w_vsplitter_create, "vsplitter", NULL); + w_reg_widget (_("Splitter (left and right)"), 0, w_hsplitter_create, "hsplitter", NULL); + w_reg_widget (NULL, 0, w_placeholder_create, "placeholder", NULL); +// w_reg_widget (_("Tabs"), 0, w_tabs_create, "tabs", NULL); + w_reg_widget (_("Playlist tabs"), 0, w_tabstrip_create, "tabstrip", NULL); + w_reg_widget (_("Selection properties"), 0, w_selproperties_create, "selproperties", NULL); + w_reg_widget (_("Album art display"), 0, w_coverart_create, "coverart", NULL); + w_reg_widget (_("Scope"), 0, w_scope_create, "scope", NULL); + w_reg_widget (_("Spectrum"), 0, w_spectrum_create, "spectrum", NULL); + w_reg_widget (_("HBox"), 0, w_hbox_create, "hbox", NULL); + w_reg_widget (_("VBox"), 0, w_vbox_create, "vbox", NULL); + w_reg_widget (_("Button"), 0, w_button_create, "button", NULL); mainwin = create_mainwin (); diff --git a/plugins/gtkui/gtkui_api.h b/plugins/gtkui/gtkui_api.h index 55580d37..789a674a 100644 --- a/plugins/gtkui/gtkui_api.h +++ b/plugins/gtkui/gtkui_api.h @@ -121,6 +121,12 @@ typedef struct ddb_gtkui_widget_s { struct ddb_gtkui_widget_s *next; // points to next widget in the same container } ddb_gtkui_widget_t; + +// flags for passing to w_reg_widget + +// tell the widget manager, that this widget can only have single instance +#define DDB_WF_SINGLE_INSTANCE 0x00000001 + typedef struct { DB_gui_t gui; @@ -130,10 +136,10 @@ typedef struct { // register new widget type; // type strings are passed at the end of argument list terminated with NULL // for example: - // w_reg_widget("My Visualization", my_viz_create, "my_viz_ng", "my_viz", NULL); + // w_reg_widget("My Visualization", 0, my_viz_create, "my_viz_ng", "my_viz", NULL); // this call will register new type "my_viz_ng", with support for another // "my_viz" type string - void (*w_reg_widget) (const char *title, ddb_gtkui_widget_t *(*create_func) (void), ...); + void (*w_reg_widget) (const char *title, uint32_t flags, ddb_gtkui_widget_t *(*create_func) (void), ...); // unregister existing widget type void (*w_unreg_widget) (const char *type); diff --git a/plugins/gtkui/widgets.c b/plugins/gtkui/widgets.c index 951d8a80..22b567f4 100644 --- a/plugins/gtkui/widgets.c +++ b/plugins/gtkui/widgets.c @@ -65,6 +65,7 @@ typedef struct w_creator_s { const char *type; const char *title; // set to NULL to avoid exposing this widget type to user + uint32_t flags; int compat; // when this is set to 1 -- it's a backwards compatibility creator, and must be skipped in GUI ddb_gtkui_widget_t *(*create_func) (void); struct w_creator_s *next; @@ -93,10 +94,6 @@ typedef struct { int hideheaders; } w_playlist_t; -// FIXME: hack for 0.6: prevent multiple instances of playlist widget, because -// we saving per-playlist config is not implemented yet -static int num_playlist_widgets; - typedef struct { w_playlist_t plt; DdbTabStrip *tabstrip; @@ -209,6 +206,15 @@ w_get_design_mode (void) { return design_mode; } +static gboolean +w_init_cb (void *data) { + ddb_gtkui_widget_t *w = data; + if (w->init) { + w->init (w); + } + return FALSE; +} + void w_append (ddb_gtkui_widget_t *cont, ddb_gtkui_widget_t *child) { child->parent = cont; @@ -228,7 +234,7 @@ w_append (ddb_gtkui_widget_t *cont, ddb_gtkui_widget_t *child) { cont->append (cont, child); } if (child->init) { - child->init (child); + g_idle_add (w_init_cb, child); } } @@ -261,15 +267,6 @@ w_remove (ddb_gtkui_widget_t *cont, ddb_gtkui_widget_t *child) { child->parent = NULL; } -gboolean -w_init_cb (void *data) { - ddb_gtkui_widget_t *w = data; - if (w->init) { - w->init (w); - } - return FALSE; -} - void w_replace (ddb_gtkui_widget_t *w, ddb_gtkui_widget_t *from, ddb_gtkui_widget_t *to) { if (w->replace) { @@ -282,6 +279,7 @@ w_replace (ddb_gtkui_widget_t *w, ddb_gtkui_widget_t *from, ddb_gtkui_widget_t * w_remove (w, from); w_destroy (from); w_append (w, to); + // we don't call init here, because w_append does it automatically } } @@ -429,29 +427,19 @@ w_save (void) { deadbeef->conf_save (); } -static int -get_num_playlists (ddb_gtkui_widget_t *w) { - int num = 0; - if (!strcmp (w->type, "playlist") || !strcmp (w->type, "tabbed_playlist")) { - w_playlist_t *plt = (w_playlist_t *)w; - if (plt->list) { - num++; - } - } - for (w = w->children; w; w = w->next) { - num += get_num_playlists (w); - } - return num; -} - static void on_replace_activate (GtkMenuItem *menuitem, gpointer user_data) { for (w_creator_t *cr = w_creators; cr; cr = cr->next) { if (cr->type == user_data) { - int num = get_num_playlists (current_widget); - num_playlist_widgets -= num; - w_replace (current_widget->parent, current_widget, w_create (user_data)); - num_playlist_widgets += num; + // hack for single-instance + // first replace with a placeholder, so that the original widget is destroyed + // then do the real replacement + ddb_gtkui_widget_t *w = w_create ("placeholder"); + w_replace (current_widget->parent, current_widget, w); + current_widget = w; + w = w_create (user_data); + w_replace (current_widget->parent, current_widget, w); + current_widget = w; } } w_save (); @@ -516,21 +504,16 @@ on_paste_activate (GtkMenuItem *menuitem, gpointer user_data) { if (!paste_buffer[0]) { return; } - ddb_gtkui_widget_t *w = NULL; + + ddb_gtkui_widget_t *w = w_create ("placeholder"); + w_replace (current_widget->parent, current_widget, w); + current_widget = w; + + w = NULL; w_create_from_string (paste_buffer, &w); - if (parent->replace) { - parent->replace (parent, current_widget, w); - } - else { - w_remove (parent, current_widget); - w_destroy (current_widget); - current_widget = w; - w_append (parent, current_widget); - } - if (w->init) { - w->init (w); - } + w_replace (parent, current_widget, w); w_save (); + current_widget = w; } void @@ -662,7 +645,7 @@ w_override_signals (GtkWidget *widget, gpointer user_data) { } void -w_reg_widget (const char *title, ddb_gtkui_widget_t *(*create_func) (void), ...) { +w_reg_widget (const char *title, uint32_t flags, ddb_gtkui_widget_t *(*create_func) (void), ...) { int compat = 0; va_list vl; @@ -683,6 +666,7 @@ w_reg_widget (const char *title, ddb_gtkui_widget_t *(*create_func) (void), ...) memset (c, 0, sizeof (w_creator_t)); c->type = type; c->title = title; + c->flags = flags; c->compat = compat; c->create_func = create_func; c->next = w_creators; @@ -713,14 +697,45 @@ w_unreg_widget (const char *type) { int w_is_registered (const char *type) { - // FIXME + for (w_creator_t *c = w_creators; c; c = c->next) { + if (!strcmp (c->type, type)) { + return 1; + } + } return 0; } +static int +get_num_widgets (ddb_gtkui_widget_t *w, const char *type) { + int num = 0; + if (!strcmp (w->type, type)) { + num++; + } + for (w = w->children; w; w = w->next) { + num += get_num_widgets (w, type); + } + return num; +} + ddb_gtkui_widget_t * w_create (const char *type) { for (w_creator_t *c = w_creators; c; c = c->next) { if (!strcmp (c->type, type)) { + if (c->flags & DDB_WF_SINGLE_INSTANCE) { + int num = get_num_widgets (rootwidget, c->type); + if (num) { + // create dummy + ddb_gtkui_widget_t *w = malloc (sizeof (ddb_gtkui_widget_t)); + memset (w, 0, sizeof (ddb_gtkui_widget_t)); + w->type = "dummy"; + w->widget = gtk_event_box_new (); + GtkWidget *label = gtk_label_new_with_mnemonic (_("Multiple widgets of this type are not supported")); + gtk_widget_show (label); + gtk_container_add (GTK_CONTAINER (w->widget), label); + w_override_signals (w->widget, w); + return w; + } + } ddb_gtkui_widget_t *w = c->create_func (); w->type = c->type; @@ -1803,34 +1818,17 @@ w_playlist_initmenu (struct ddb_gtkui_widget_s *w, GtkWidget *menu) { w); } -void -w_playlist_destroy (ddb_gtkui_widget_t *w) { - num_playlist_widgets--; -} - ddb_gtkui_widget_t * w_tabbed_playlist_create (void) { w_tabbed_playlist_t *w = malloc (sizeof (w_tabbed_playlist_t)); memset (w, 0, sizeof (w_tabbed_playlist_t)); - if (num_playlist_widgets > 0) { - w->plt.base.widget = gtk_event_box_new (); - GtkWidget *label = gtk_label_new_with_mnemonic (_("Multiple playlist widgets are not supported yet")); - gtk_widget_show (label); - gtk_container_add (GTK_CONTAINER (w->plt.base.widget), label); - w_override_signals (w->plt.base.widget, w); - return (ddb_gtkui_widget_t*)w; - } - - num_playlist_widgets++; - GtkWidget *vbox = gtk_vbox_new (FALSE, 0); w->plt.base.widget = vbox; w->plt.base.save = w_playlist_save; w->plt.base.load = w_playlist_load; w->plt.base.init = w_playlist_init; w->plt.base.initmenu = w_playlist_initmenu; - w->plt.base.destroy = w_playlist_destroy; gtk_widget_show (vbox); GtkWidget *tabstrip = ddb_tabstrip_new (); @@ -1862,16 +1860,6 @@ ddb_gtkui_widget_t * w_playlist_create (void) { w_playlist_t *w = malloc (sizeof (w_playlist_t)); memset (w, 0, sizeof (w_playlist_t)); - if (num_playlist_widgets > 0) { - w->base.widget = gtk_event_box_new (); - GtkWidget *label = gtk_label_new_with_mnemonic (_("Multiple playlist widgets are not supported yet")); - gtk_widget_show (label); - gtk_container_add (GTK_CONTAINER (w->base.widget), label); - w_override_signals (w->base.widget, w); - return (ddb_gtkui_widget_t*)w; - } - - num_playlist_widgets++; w->base.widget = gtk_event_box_new (); w->list = DDB_LISTVIEW (ddb_listview_new ()); @@ -1879,7 +1867,6 @@ w_playlist_create (void) { w->base.load = w_playlist_load; w->base.init = w_playlist_init; w->base.initmenu = w_playlist_initmenu; - w->base.destroy = w_playlist_destroy; gtk_widget_show (GTK_WIDGET (w->list)); main_playlist_init (GTK_WIDGET (w->list)); if (deadbeef->conf_get_int ("gtkui.headers.visible", 1)) { diff --git a/plugins/gtkui/widgets.h b/plugins/gtkui/widgets.h index 9d262b6d..f7496906 100644 --- a/plugins/gtkui/widgets.h +++ b/plugins/gtkui/widgets.h @@ -40,7 +40,7 @@ int w_get_design_mode (void); void -w_reg_widget (const char *title, ddb_gtkui_widget_t *(*create_func) (void), ...); +w_reg_widget (const char *title, uint32_t flags, ddb_gtkui_widget_t *(*create_func) (void), ...); void w_unreg_widget (const char *type); diff --git a/plugins/pltbrowser/pltbrowser.c b/plugins/pltbrowser/pltbrowser.c index aefd23fc..3ebf02f5 100644 --- a/plugins/pltbrowser/pltbrowser.c +++ b/plugins/pltbrowser/pltbrowser.c @@ -248,7 +248,7 @@ pltbrowser_connect (void) { fprintf (stderr, "pltbrowser: can't find gtkui plugin\n"); return -1; } - gtkui_plugin->w_reg_widget (_("Playlist browser"), w_pltbrowser_create, "pltbrowser", NULL); + gtkui_plugin->w_reg_widget (_("Playlist browser"), 0, w_pltbrowser_create, "pltbrowser", NULL); return 0; } |