summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <waker@users.sourceforge.net>2013-10-20 20:53:22 +0200
committerGravatar Alexey Yakovenko <waker@users.sourceforge.net>2013-10-20 20:53:22 +0200
commit1233aa87bcad5a87024ebe9031fc732172cd99ff (patch)
tree65c04eab84f09bc947f1a549c80dd6a0007cd458
parente3f56e349af1f8481f4aeb7dc428f9e68804b35e (diff)
gtkui: proper single-instance widget support
-rw-r--r--plugins/gtkui/gtkui.c30
-rw-r--r--plugins/gtkui/gtkui_api.h10
-rw-r--r--plugins/gtkui/widgets.c139
-rw-r--r--plugins/gtkui/widgets.h2
-rw-r--r--plugins/pltbrowser/pltbrowser.c2
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;
}