summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorDenis Declara <declara91@gmail.com>2012-03-20 10:09:49 +0000
committerDenis Declara <declara91@gmail.com>2012-03-20 10:09:49 +0000
commit1cd9c8450500b945614a12a762e06c057ee85bbe (patch)
tree9973553a223ef7d6c5f9d18c35766fb3e7296e57 /src/widgets
parentFix deprecated Gtk::Widget flags (diff)
parentdesktop cutting plotter dxf output. ignore orphaned clones (Bug 957086) (diff)
downloadinkscape-1cd9c8450500b945614a12a762e06c057ee85bbe.tar.gz
inkscape-1cd9c8450500b945614a12a762e06c057ee85bbe.zip
Merged with trunk
(bzr r11073.1.1)
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/CMakeLists.txt2
-rw-r--r--src/widgets/Makefile_insert2
-rw-r--r--src/widgets/gradient-image.cpp31
-rw-r--r--src/widgets/gradient-image.h1
-rw-r--r--src/widgets/gradient-toolbar.cpp179
-rw-r--r--src/widgets/gradient-vector.cpp371
-rw-r--r--src/widgets/gradient-vector.h9
-rw-r--r--src/widgets/paint-selector.cpp32
-rw-r--r--src/widgets/paint-selector.h1
-rw-r--r--src/widgets/stroke-marker-selector.cpp458
-rw-r--r--src/widgets/stroke-marker-selector.h104
-rw-r--r--src/widgets/stroke-style.cpp547
12 files changed, 1001 insertions, 736 deletions
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index 418cc5c6f..7b76ccc83 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -30,6 +30,7 @@ set(widgets_SRC
sp-xmlview-tree.cpp
spinbutton-events.cpp
spw-utilities.cpp
+ stroke-marker-selector.cpp
stroke-style.cpp
swatch-selector.cpp
toolbox.cpp
@@ -68,6 +69,7 @@ set(widgets_SRC
sp-xmlview-tree.h
spinbutton-events.h
spw-utilities.h
+ stroke-marker-selector.h
stroke-style.h
swatch-selector.h
toolbox.h
diff --git a/src/widgets/Makefile_insert b/src/widgets/Makefile_insert
index 86046b918..255767d43 100644
--- a/src/widgets/Makefile_insert
+++ b/src/widgets/Makefile_insert
@@ -62,6 +62,8 @@ ink_common_sources += \
widgets/sp-xmlview-content.h \
widgets/sp-xmlview-tree.cpp \
widgets/sp-xmlview-tree.h \
+ widgets/stroke-marker-selector.cpp \
+ widgets/stroke-marker-selector.h \
widgets/stroke-style.cpp \
widgets/stroke-style.h \
widgets/swatch-selector.cpp \
diff --git a/src/widgets/gradient-image.cpp b/src/widgets/gradient-image.cpp
index 09a06370d..b835dc36b 100644
--- a/src/widgets/gradient-image.cpp
+++ b/src/widgets/gradient-image.cpp
@@ -153,6 +153,37 @@ sp_gradient_image_new (SPGradient *gradient)
return (GtkWidget *) image;
}
+GdkPixbuf*
+sp_gradient_to_pixbuf (SPGradient *gr, int width, int height)
+{
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+ cairo_t *ct = cairo_create(s);
+
+ cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard();
+ cairo_set_source(ct, check);
+ cairo_paint(ct);
+ cairo_pattern_destroy(check);
+
+ if (gr) {
+ cairo_pattern_t *p = sp_gradient_create_preview_pattern(gr, width);
+ cairo_set_source(ct, p);
+ cairo_paint(ct);
+ cairo_pattern_destroy(p);
+ }
+
+ cairo_destroy(ct);
+ cairo_surface_flush(s);
+
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s),
+ GDK_COLORSPACE_RGB, TRUE, 8,
+ width, height, cairo_image_surface_get_stride(s),
+ ink_cairo_pixbuf_cleanup, s);
+ convert_pixbuf_argb32_to_normal(pixbuf);
+
+ return pixbuf;
+}
+
+
void
sp_gradient_image_set_gradient (SPGradientImage *image, SPGradient *gradient)
{
diff --git a/src/widgets/gradient-image.h b/src/widgets/gradient-image.h
index 0fbed879f..904ce4cac 100644
--- a/src/widgets/gradient-image.h
+++ b/src/widgets/gradient-image.h
@@ -43,6 +43,7 @@ struct SPGradientImageClass {
GType sp_gradient_image_get_type (void);
GtkWidget *sp_gradient_image_new (SPGradient *gradient);
+GdkPixbuf *sp_gradient_to_pixbuf (SPGradient *gr, int width, int height);
void sp_gradient_image_set_gradient (SPGradientImage *gi, SPGradient *gr);
#endif
diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp
index 6443e09cb..2e7d6b89d 100644
--- a/src/widgets/gradient-toolbar.cpp
+++ b/src/widgets/gradient-toolbar.cpp
@@ -141,35 +141,54 @@ void gr_apply_gradient (Inkscape::Selection *selection, GrDrag *drag, SPGradient
}
}
-void gr_item_activate (GtkMenuItem *menuitem, gpointer data)
+void gr_combo_box_changed (GtkComboBox *widget, gpointer data)
{
- SPGradient *gr = static_cast<SPGradient *>(g_object_get_data (G_OBJECT (menuitem), "gradient"));
- gr = sp_gradient_ensure_vector_normalized(gr);
+ GtkTreeIter iter;
+ if (!gtk_combo_box_get_active_iter (widget, &iter)) {
+ return;
+ }
- SPDesktop *desktop = static_cast<SPDesktop *>(data);
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
- SPEventContext *ev = sp_desktop_event_context (desktop);
+ GtkTreeModel *model = gtk_combo_box_get_model (widget);
+ SPGradient *gr = NULL;
+ gtk_tree_model_get (model, &iter, 2, &gr, -1);
- gr_apply_gradient (selection, ev? ev->get_drag() : NULL, gr);
+ if (gr) {
+ gr = sp_gradient_ensure_vector_normalized(gr);
- DocumentUndo::done(sp_desktop_document (desktop), SP_VERB_CONTEXT_GRADIENT,
- _("Assign gradient to object"));
-}
+ SPDesktop *desktop = static_cast<SPDesktop *>(data);
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ SPEventContext *ev = sp_desktop_event_context (desktop);
+
+ gr_apply_gradient (selection, ev? ev->get_drag() : NULL, gr);
+
+ DocumentUndo::done(sp_desktop_document (desktop), SP_VERB_CONTEXT_GRADIENT,
+ _("Assign gradient to object"));
+ }
-gchar *gr_prepare_label (SPObject *obj)
-{
- const gchar *id = obj->defaultLabel();
- if (strlen(id) > 15 && (!strncmp (id, "#linearGradient", 15) || !strncmp (id, "#radialGradient", 15)))
- return g_strdup_printf ("<small>#%s</small>", id+15);
- return g_strdup_printf ("<small>%s</small>", id);
}
+
+
GtkWidget *gr_vector_list(SPDesktop *desktop, bool selection_empty, SPGradient *gr_selected, bool gr_multi)
{
SPDocument *document = sp_desktop_document (desktop);
- GtkWidget *om = gtk_option_menu_new ();
- GtkWidget *m = gtk_menu_new ();
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+ GtkWidget *combo_box;
+
+ store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
+ combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "pixbuf", 0, NULL);
+ gtk_cell_renderer_set_padding(renderer, 5, 0);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "text", 1, NULL);
GSList *gl = NULL;
const GSList *gradients = document->getResourceList("gradient");
@@ -186,87 +205,65 @@ GtkWidget *gr_vector_list(SPDesktop *desktop, bool selection_empty, SPGradient *
if (!gl) {
// The document has no gradients
- GtkWidget *l = gtk_label_new("");
- gtk_label_set_markup (GTK_LABEL(l), _("<small>No gradients</small>"));
- GtkWidget *i = gtk_menu_item_new ();
- gtk_container_add (GTK_CONTAINER (i), l);
-
- gtk_widget_show (i);
- gtk_menu_shell_append(GTK_MENU_SHELL (m), i);
- gtk_widget_set_sensitive (om, FALSE);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, NULL, 1, _("No gradients"), 2, NULL, -1);
+ gtk_widget_set_sensitive (combo_box, FALSE);
+
} else if (selection_empty) {
// Document has gradients, but nothing is currently selected.
- GtkWidget *l = gtk_label_new("");
- gtk_label_set_markup (GTK_LABEL(l), _("<small>Nothing selected</small>"));
- GtkWidget *i = gtk_menu_item_new ();
- gtk_container_add (GTK_CONTAINER (i), l);
-
- gtk_widget_show (i);
- gtk_menu_shell_append(GTK_MENU_SHELL (m), i);
- gtk_widget_set_sensitive (om, FALSE);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, NULL, 1, _("Nothing selected"), 2, NULL, -1);
+ gtk_widget_set_sensitive (combo_box, FALSE);
+
} else {
if (gr_selected == NULL) {
- GtkWidget *l = gtk_label_new("");
- gtk_label_set_markup (GTK_LABEL(l), _("<small>No gradients in selection</small>"));
- GtkWidget *i = gtk_menu_item_new ();
- gtk_container_add (GTK_CONTAINER (i), l);
- gtk_widget_show (i);
- gtk_menu_shell_append(GTK_MENU_SHELL (m), i);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, NULL, 1, _("No gradient"), 2, NULL, -1);
+ gtk_widget_set_sensitive (combo_box, FALSE);
+
}
if (gr_multi) {
- GtkWidget *l = gtk_label_new("");
- gtk_label_set_markup (GTK_LABEL(l), _("<small>Multiple gradients</small>"));
- GtkWidget *i = gtk_menu_item_new ();
- gtk_container_add (GTK_CONTAINER (i), l);
- gtk_widget_show (i);
- gtk_menu_shell_append(GTK_MENU_SHELL (m), i);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, NULL, 1, _("Multiple gradients"), 2, NULL, -1);
+ gtk_widget_set_sensitive (combo_box, FALSE);
+
}
while (gl) {
SPGradient *gradient = SP_GRADIENT (gl->data);
gl = g_slist_remove (gl, gradient);
- GtkWidget *i = gtk_menu_item_new ();
- g_object_set_data (G_OBJECT (i), "gradient", gradient);
- g_signal_connect (G_OBJECT (i), "activate", G_CALLBACK (gr_item_activate), desktop);
-
- GtkWidget *image = sp_gradient_image_new (gradient);
-
- GtkWidget *hb = gtk_hbox_new (FALSE, 4);
- GtkWidget *l = gtk_label_new ("");
gchar *label = gr_prepare_label(gradient);
- gtk_label_set_markup (GTK_LABEL(l), label);
+ GdkPixbuf *pixb = sp_gradient_to_pixbuf (gradient, 64, 18);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, pixb, 1, label, 2, gradient, -1);
g_free (label);
- gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
- gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (hb), image, FALSE, FALSE, 0);
-
- gtk_widget_show_all (i);
-
- gtk_container_add (GTK_CONTAINER (i), hb);
-
- gtk_menu_shell_append(GTK_MENU_SHELL (m), i);
if (gradient == gr_selected) {
pos = idx;
}
idx ++;
}
- gtk_widget_set_sensitive (om, TRUE);
+ gtk_widget_set_sensitive (combo_box, TRUE);
}
- gtk_option_menu_set_menu (GTK_OPTION_MENU (om), m);
/* Select the current gradient, or the Multi/Nothing line */
- if (gr_multi || gr_selected == NULL)
- gtk_option_menu_set_history (GTK_OPTION_MENU (om), 0);
- else
- gtk_option_menu_set_history (GTK_OPTION_MENU (om), pos);
+ if (gr_multi || gr_selected == NULL) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , 0);
+ }
+ else {
+ gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , pos);
+ }
+
+ sp_set_font_size_smaller(combo_box);
- return om;
+ g_signal_connect (G_OBJECT (combo_box), "changed", G_CALLBACK (gr_combo_box_changed), desktop);
+
+ return combo_box;
}
@@ -377,10 +374,10 @@ static void gr_tb_selection_changed(Inkscape::Selection * /*selection*/, gpointe
if (selection) {
SPEventContext *ev = sp_desktop_event_context(desktop);
- GtkWidget *om = (GtkWidget *) g_object_get_data(G_OBJECT(widget), "menu");
- if (om) {
- gtk_widget_destroy(om);
- om = 0;
+ GtkWidget *combo_box = (GtkWidget *) g_object_get_data(G_OBJECT(widget), "combobox");
+ if (combo_box) {
+ gtk_widget_destroy(combo_box);
+ combo_box = 0;
}
SPGradient *gr_selected = 0;
@@ -391,13 +388,13 @@ static void gr_tb_selection_changed(Inkscape::Selection * /*selection*/, gpointe
gr_read_selection(selection, ev ? ev->get_drag() : 0, gr_selected, gr_multi, spr_selected, spr_multi);
- om = gr_vector_list(desktop, selection->isEmpty(), gr_selected, gr_multi);
- g_object_set_data(G_OBJECT(widget), "menu", om);
+ combo_box = gr_vector_list(desktop, selection->isEmpty(), gr_selected, gr_multi);
+ g_object_set_data(G_OBJECT(widget), "combobox", combo_box);
GtkWidget *buttons = (GtkWidget *) g_object_get_data(G_OBJECT(widget), "buttons");
gtk_widget_set_sensitive(buttons, (gr_selected && !gr_multi));
- gtk_box_pack_start(GTK_BOX(widget), om, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(widget), combo_box, TRUE, TRUE, 0);
gtk_widget_show_all(widget);
}
@@ -436,13 +433,19 @@ static void gr_disconnect_sigc (GObject */*obj*/, sigc::connection *connection)
static void
gr_edit (GtkWidget */*button*/, GtkWidget *widget)
{
- GtkWidget *om = (GtkWidget *) g_object_get_data (G_OBJECT(widget), "menu");
+ GtkWidget *combo_box = (GtkWidget *) g_object_get_data (G_OBJECT(widget), "combobox");
spinbutton_defocus(GTK_OBJECT(widget));
- if (om) {
- GtkWidget *i = gtk_menu_get_active (GTK_MENU (gtk_option_menu_get_menu (GTK_OPTION_MENU (om))));
- SPGradient *gr = (SPGradient *) g_object_get_data (G_OBJECT(i), "gradient");
+ if (combo_box) {
+ GtkTreeIter iter;
+ if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX(combo_box), &iter)) {
+ return;
+ }
+
+ GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(combo_box));
+ SPGradient *gr = NULL;
+ gtk_tree_model_get (model, &iter, 2, &gr, -1);
if (gr) {
GtkWidget *dialog = sp_gradient_vector_editor_new (gr);
@@ -469,10 +472,10 @@ GtkWidget * gr_change_widget(SPDesktop *desktop)
g_object_set_data(G_OBJECT(widget), "dtw", desktop->canvas);
g_object_set_data (G_OBJECT (widget), "desktop", desktop);
- GtkWidget *om = gr_vector_list (desktop, selection->isEmpty(), gr_selected, gr_multi);
- g_object_set_data (G_OBJECT (widget), "menu", om);
+ GtkWidget *combo_box = gr_vector_list(desktop, selection->isEmpty(), gr_selected, gr_multi);
+ g_object_set_data(G_OBJECT(widget), "combobox", combo_box);
- gtk_box_pack_start (GTK_BOX (widget), om, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (widget), combo_box, TRUE, TRUE, 0);
{
GtkWidget *buttons = gtk_hbox_new(FALSE, 1);
@@ -628,9 +631,9 @@ sp_gradient_toolbox_new(SPDesktop *desktop)
{
GtkWidget *vectors = gr_change_widget (desktop);
- GtkToolItem *vectors_toolitem = gtk_tool_item_new();
- gtk_container_add(GTK_CONTAINER(vectors_toolitem), vectors);
- gtk_toolbar_insert(GTK_TOOLBAR(tbl), vectors_toolitem, -1);
+ GtkToolItem *vectors_toolitem = gtk_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(vectors_toolitem), vectors);
+ gtk_toolbar_insert(GTK_TOOLBAR(tbl), vectors_toolitem, -1);
}
gtk_widget_show_all(tbl);
diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp
index eb421ade6..d6de0c492 100644
--- a/src/widgets/gradient-vector.cpp
+++ b/src/widgets/gradient-vector.cpp
@@ -63,7 +63,8 @@ static void sp_gvs_defs_release(SPObject *defs, SPGradientVectorSelector *gvs);
static void sp_gvs_defs_modified(SPObject *defs, guint flags, SPGradientVectorSelector *gvs);
static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs);
-static void sp_gvs_gradient_activate(GtkMenuItem *mi, SPGradientVectorSelector *gvs);
+static void gr_combo_box_changed (GtkComboBox *widget, SPGradientVectorSelector *gvs);
+static SPStop *get_selected_stop( GtkWidget *vb);
static GtkVBoxClass *parent_class;
static guint signals[LAST_SIGNAL] = {0};
@@ -132,9 +133,23 @@ static void sp_gradient_vector_selector_init(SPGradientVectorSelector *gvs)
new (&gvs->defs_release_connection) sigc::connection();
new (&gvs->defs_modified_connection) sigc::connection();
- gvs->menu = gtk_option_menu_new();
- gtk_widget_show(gvs->menu);
- gtk_box_pack_start(GTK_BOX(gvs), gvs->menu, TRUE, TRUE, 0);
+ gvs->store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
+ gvs->combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (gvs->store));
+ gvs->combo_connection = g_signal_connect (G_OBJECT (gvs->combo_box), "changed", G_CALLBACK (gr_combo_box_changed), gvs);
+
+ GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (gvs->combo_box), renderer, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (gvs->combo_box), renderer, "pixbuf", 0, NULL);
+ gtk_cell_renderer_set_padding(renderer, 5, 0);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (gvs->combo_box), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (gvs->combo_box), renderer, "text", 1, NULL);
+ gtk_cell_renderer_set_padding(renderer, 0, 0);
+
+ gtk_widget_show(gvs->combo_box);
+ gtk_box_pack_start(GTK_BOX(gvs), gvs->combo_box, TRUE, TRUE, 0);
+
}
static void sp_gradient_vector_selector_destroy(GtkObject *object)
@@ -219,7 +234,7 @@ void sp_gradient_vector_selector_set_gradient(SPGradientVectorSelector *gvs, SPD
sp_gvs_rebuild_gui_full(gvs);
if (!suppress) g_signal_emit(G_OBJECT(gvs), signals[VECTOR_SET], 0, gr);
} else if (gr != gvs->gr) {
- // Harder case - keep document, rebuild menus and stuff
+ // Harder case - keep document, rebuild list and stuff
// fixme: (Lauris)
suppress = TRUE;
sp_gradient_vector_selector_set_gradient(gvs, NULL, NULL);
@@ -246,16 +261,19 @@ SPGradient *sp_gradient_vector_selector_get_gradient(SPGradientVectorSelector *g
return gvs->gr;
}
-static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs)
+gchar *gr_prepare_label (SPObject *obj)
{
- /* Clear old menu, if there is any */
- if (gtk_option_menu_get_menu(GTK_OPTION_MENU(gvs->menu))) {
- gtk_option_menu_remove_menu(GTK_OPTION_MENU(gvs->menu));
- }
+ const gchar *id = obj->defaultLabel();
+ if (strlen(id) > 15 && (!strncmp (id, "#linearGradient", 15) || !strncmp (id, "#radialGradient", 15)))
+ return g_strdup_printf ("#%s", id+15);
+ return g_strdup_printf ("%s", id);
+}
- /* Create new menu widget */
- GtkWidget *m = gtk_menu_new();
- gtk_widget_show(m);
+static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs)
+{
+ /* Clear old list, if there is any */
+ gtk_list_store_clear(gvs->store);
+ GtkTreeIter iter;
/* Pick up all gradients with vectors */
GSList *gl = NULL;
@@ -274,112 +292,99 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs)
gint idx = 0;
if (!gvs->doc) {
- GtkWidget *i;
- i = gtk_menu_item_new_with_label(_("No document selected"));
- gtk_widget_show(i);
- gtk_menu_shell_append(GTK_MENU_SHELL(m), i);
- gtk_widget_set_sensitive(gvs->menu, FALSE);
+ gtk_list_store_append (gvs->store, &iter);
+ gtk_list_store_set (gvs->store, &iter, 0, NULL, 1, _("No document selected"), 2, NULL, -1);
+ gtk_widget_set_sensitive (gvs->combo_box, FALSE);
+
} else if (!gl) {
- GtkWidget *i;
- i = gtk_menu_item_new_with_label(_("No gradients in document"));
- gtk_widget_show(i);
- gtk_menu_shell_append(GTK_MENU_SHELL(m), i);
- gtk_widget_set_sensitive(gvs->menu, FALSE);
+ gtk_list_store_append (gvs->store, &iter);
+ gtk_list_store_set (gvs->store, &iter, 0, NULL, 1, _("No gradients in document"), 2, NULL, -1);
+ gtk_widget_set_sensitive (gvs->combo_box, FALSE);
+
} else if (!gvs->gr) {
- GtkWidget *i;
- i = gtk_menu_item_new_with_label(_("No gradient selected"));
- gtk_widget_show(i);
- gtk_menu_shell_append(GTK_MENU_SHELL(m), i);
- gtk_widget_set_sensitive(gvs->menu, FALSE);
+ gtk_list_store_append (gvs->store, &iter);
+ gtk_list_store_set (gvs->store, &iter, 0, NULL, 1, _("No gradient selected"), 2, NULL, -1);
+ gtk_widget_set_sensitive (gvs->combo_box, FALSE);
+
} else {
while (gl) {
SPGradient *gr;
- GtkWidget *i, *w;
gr = SP_GRADIENT(gl->data);
gl = g_slist_remove(gl, gr);
/* We have to know: */
/* Gradient destroy */
/* Gradient name change */
- i = gtk_menu_item_new();
- gtk_widget_show(i);
- g_object_set_data(G_OBJECT(i), "gradient", gr);
- g_signal_connect(G_OBJECT(i), "activate", G_CALLBACK(sp_gvs_gradient_activate), gvs);
-
- w = sp_gradient_image_new(gr);
- gtk_widget_show(w);
-
- if (gvs->idlabel) {
- GtkWidget *hb, *l;
- hb = gtk_hbox_new(FALSE, 4);
- gtk_widget_show(hb);
- l = gtk_label_new(gr->getId());
- gtk_widget_show(l);
- gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5);
- gtk_box_pack_start(GTK_BOX(hb), l, TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hb), w, FALSE, FALSE, 0);
- w = hb;
- }
- gtk_container_add(GTK_CONTAINER(i), w);
-
- gtk_menu_shell_append(GTK_MENU_SHELL(m), i);
+ gchar *label = gr_prepare_label(gr);
+ GdkPixbuf *pixb = sp_gradient_to_pixbuf (gr, 64, 18);
+ gtk_list_store_append (gvs->store, &iter);
+ gtk_list_store_set (gvs->store, &iter, 0, pixb, 1, label, 2, gr, -1);
+ g_free (label);
if (gr == gvs->gr) {
pos = idx;
}
idx += 1;
}
- gtk_widget_set_sensitive(gvs->menu, TRUE);
+ gtk_widget_set_sensitive (gvs->combo_box, TRUE);
}
- gtk_option_menu_set_menu(GTK_OPTION_MENU(gvs->menu), m);
- /* Set history */
- gtk_option_menu_set_history(GTK_OPTION_MENU(gvs->menu), pos);
+ /* Block signal to prevent recursive loop */
+ g_signal_handler_block(G_OBJECT (gvs->combo_box), gvs->combo_connection);
+
+ /* Set selected */
+ gtk_combo_box_set_active (GTK_COMBO_BOX(gvs->combo_box) , pos);
+
+ g_signal_handler_unblock(G_OBJECT (gvs->combo_box), gvs->combo_connection);
}
-static void sp_gvs_gradient_activate(GtkMenuItem *mi, SPGradientVectorSelector *gvs)
+static void gr_combo_box_changed (GtkComboBox *widget, SPGradientVectorSelector *gvs)
{
- SPGradient *gr, *norm;
+ GtkTreeIter iter;
+ if (!gtk_combo_box_get_active_iter (widget, &iter)) {
+ return;
+ }
- gr = (SPGradient*)g_object_get_data(G_OBJECT(mi), "gradient");
- /* Hmmm... bad things may happen here, if actual gradient is something new */
- /* Namely - menuitems etc. will be fucked up */
- /* Hmmm - probably we can just re-set it as menuitem data (Lauris) */
+ SPGradient *gr = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL(gvs->store), &iter, 2, &gr, -1);
- //g_print("SPGradientVectorSelector: gradient %s activated\n", gr->getId());
- //g_message("Setting to gradient %p swatch:%d solid:%d", gr, gr->isSwatch(), gr->isSolid());
+ if (gr) {
- norm = sp_gradient_ensure_vector_normalized(gr);
- if (norm != gr) {
- //g_print("SPGradientVectorSelector: become %s after normalization\n", norm->getId());
- /* But be careful that we do not have gradient saved anywhere else */
- g_object_set_data(G_OBJECT(mi), "gradient", norm);
- }
+ SPGradient *norm = sp_gradient_ensure_vector_normalized(gr);
+ if (norm != gr) {
+ //g_print("SPGradientVectorSelector: become %s after normalization\n", norm->getId());
+ /* But be careful that we do not have gradient saved anywhere else */
+ //g_object_set_data(G_OBJECT(mi), "gradient", norm);
+ gtk_list_store_set (gvs->store, &iter, 2, norm, -1);
+ }
+
+ /* fixme: Really we would want to use _set_vector */
+ /* Detach old */
+ if (gvs->gr) {
+ gvs->gradient_release_connection.disconnect();
+ gvs->gr = NULL;
+ }
+ /* Attach new */
+ if (norm) {
+ gvs->gradient_release_connection = norm->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_gvs_gradient_release), gvs));
+ gvs->gr = norm;
+ }
+
+ g_signal_emit(G_OBJECT(gvs), signals[VECTOR_SET], 0, norm);
+
+ if (norm != gr) {
+ /* We do extra undo push here */
+ /* If handler has already done it, it is just NOP */
+ // FIXME: looks like this is never a valid undo step, consider removing this
+ DocumentUndo::done(norm->document, SP_VERB_CONTEXT_GRADIENT,
+ /* TODO: annotate */ "gradient-vector.cpp:350");
+ }
- /* fixme: Really we would want to use _set_vector */
- /* Detach old */
- if (gvs->gr) {
- gvs->gradient_release_connection.disconnect();
- gvs->gr = NULL;
- }
- /* Attach new */
- if (norm) {
- gvs->gradient_release_connection = norm->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_gvs_gradient_release), gvs));
- gvs->gr = norm;
- }
- g_signal_emit(G_OBJECT(gvs), signals[VECTOR_SET], 0, norm);
- if (norm != gr) {
- /* We do extra undo push here */
- /* If handler has already done it, it is just NOP */
- // FIXME: looks like this is never a valid undo step, consider removing this
- DocumentUndo::done(norm->document, SP_VERB_CONTEXT_GRADIENT,
- /* TODO: annotate */ "gradient-vector.cpp:350");
}
}
-
static void sp_gvs_gradient_release(SPObject */*obj*/, SPGradientVectorSelector *gvs)
{
/* Disconnect gradient */
@@ -445,16 +450,15 @@ static void sp_gradient_vector_gradient_release(SPObject *obj, GtkWidget *widget
static void sp_gradient_vector_gradient_modified(SPObject *obj, guint flags, GtkWidget *widget);
static void sp_gradient_vector_color_dragged(SPColorSelector *csel, GtkObject *object);
static void sp_gradient_vector_color_changed(SPColorSelector *csel, GtkObject *object);
-static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_stop);
+static void update_stop_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_stop);
static gboolean blocked = FALSE;
static void grad_edit_dia_stop_added_or_removed(Inkscape::XML::Node */*repr*/, Inkscape::XML::Node */*child*/, Inkscape::XML::Node */*ref*/, gpointer data)
{
GtkWidget *vb = GTK_WIDGET(data);
- GtkWidget *mnu = (GtkWidget *)g_object_get_data(G_OBJECT(vb), "stopmenu");
SPGradient *gradient = (SPGradient *)g_object_get_data(G_OBJECT(vb), "gradient");
- update_stop_list(mnu, gradient, NULL);
+ update_stop_list(vb, gradient, NULL);
}
//FIXME!!! We must also listen to attr changes on all children (i.e. stops) too,
@@ -511,13 +515,15 @@ static void verify_grad(SPGradient *gradient)
}
}
-static void select_stop_in_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_stop)
+static void select_stop_in_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_stop)
{
+ GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(vb), "combo_box"));
+
int i = 0;
for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) {
if (SP_IS_STOP(ochild)) {
if (ochild == new_stop) {
- gtk_option_menu_set_history(GTK_OPTION_MENU(mnu), i);
+ gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , i);
break;
}
i++;
@@ -525,7 +531,7 @@ static void select_stop_in_list( GtkWidget *mnu, SPGradient *gradient, SPStop *n
}
}
-static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_stop)
+static void update_stop_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_stop)
{
if (!SP_IS_GRADIENT(gradient)) {
@@ -534,14 +540,19 @@ static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_
blocked = TRUE;
- /* Clear old menu, if there is any */
- if (gtk_option_menu_get_menu(GTK_OPTION_MENU(mnu))) {
- gtk_option_menu_remove_menu(GTK_OPTION_MENU(mnu));
+ /* Clear old list, if there is any */
+ GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(vb), "combo_box"));
+ if (!combo_box) {
+ return;
+ }
+ GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model (GTK_COMBO_BOX(combo_box));
+ if (!store) {
+ return;
}
+ gtk_list_store_clear(store);
+ GtkTreeIter iter;
- /* Create new menu widget */
- GtkWidget *m = gtk_menu_new();
- gtk_widget_show(m);
+ /* Populate the combobox store */
GSList *sl = NULL;
if ( gradient->hasStops() ) {
for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) {
@@ -551,43 +562,33 @@ static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_
}
}
if (!sl) {
- GtkWidget *i = gtk_menu_item_new_with_label(_("No stops in gradient"));
- gtk_widget_show(i);
- gtk_menu_shell_append(GTK_MENU_SHELL(m), i);
- gtk_widget_set_sensitive(mnu, FALSE);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, NULL, 1, _("No stops in gradient"), 2, NULL, -1);
+ gtk_widget_set_sensitive (combo_box, FALSE);
+
} else {
for (; sl != NULL; sl = sl->next){
if (SP_IS_STOP(sl->data)){
SPStop *stop = SP_STOP(sl->data);
- GtkWidget *i = gtk_menu_item_new();
- gtk_widget_show(i);
- g_object_set_data(G_OBJECT(i), "stop", stop);
- GtkWidget *hb = gtk_hbox_new(FALSE, 4);
- Gtk::Widget *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(sp_stop_get_rgba32(stop)));
- cpv->show();
- gtk_container_add( GTK_CONTAINER(hb), cpv->gobj() );
- g_object_set_data( G_OBJECT(i), "preview", cpv );
Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(sl->data)->getRepr();
- GtkWidget *l = gtk_label_new(repr->attribute("id"));
- gtk_widget_show(l);
- gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5);
- gtk_box_pack_start(GTK_BOX(hb), l, TRUE, TRUE, 0);
- gtk_widget_show(hb);
- gtk_container_add(GTK_CONTAINER(i), hb);
- gtk_menu_shell_append(GTK_MENU_SHELL(m), i);
+ Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(sp_stop_get_rgba32(stop)));
+ GdkPixbuf *pb = cpv->toPixbuf(64, 16);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, pb, 1, repr->attribute("id"), 2, stop, -1);
+ gtk_widget_set_sensitive (combo_box, FALSE);
}
}
- gtk_widget_set_sensitive(mnu, TRUE);
+ gtk_widget_set_sensitive(combo_box, TRUE);
}
- gtk_option_menu_set_menu(GTK_OPTION_MENU(mnu), m);
/* Set history */
if (new_stop == NULL) {
- gtk_option_menu_set_history(GTK_OPTION_MENU(mnu), 0);
+ gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , 0);
} else {
- select_stop_in_list(mnu, gradient, new_stop);
+ select_stop_in_list(vb, gradient, new_stop);
}
blocked = FALSE;
@@ -595,10 +596,9 @@ static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_
// user selected existing stop from list
-static void sp_grad_edit_select(GtkOptionMenu *mnu, GtkWidget *tbl)
+static void sp_grad_edit_combo_box_changed (GtkComboBox *widget, GtkWidget *tbl)
{
- GObject *item = G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu))));
- SPStop *stop = SP_STOP(g_object_get_data(item, "stop"));
+ SPStop *stop = get_selected_stop(tbl);
if (!stop) {
return;
}
@@ -649,26 +649,36 @@ static void sp_grad_edit_select(GtkOptionMenu *mnu, GtkWidget *tbl)
blocked = FALSE;
}
-
-
+static SPStop *get_selected_stop( GtkWidget *vb)
+{
+ SPStop *stop = NULL;
+ GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(vb), "combo_box"));
+ if (combo_box) {
+ GtkTreeIter iter;
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(combo_box), &iter)) {
+ GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model (GTK_COMBO_BOX(combo_box));
+ gtk_tree_model_get (GTK_TREE_MODEL(store), &iter, 2, &stop, -1);
+ }
+ }
+ return stop;
+}
static void offadjustmentChanged( GtkAdjustment *adjustment, GtkWidget *vb)
{
if (!blocked) {
blocked = TRUE;
- GtkOptionMenu *mnu = static_cast<GtkOptionMenu *>(g_object_get_data(G_OBJECT(vb), "stopmenu"));
- if ( g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop") ) {
- SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop"));
-
+ SPStop *stop = get_selected_stop(vb);
+ if (stop) {
stop->offset = gtk_adjustment_get_value (adjustment);
sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset);
DocumentUndo::maybeDone(stop->document, "gradient:stop:offset", SP_VERB_CONTEXT_GRADIENT,
_("Change gradient stop offset"));
- blocked = FALSE;
}
+
+ blocked = FALSE;
}
}
@@ -687,11 +697,9 @@ static void sp_grd_ed_add_stop(GtkWidget */*widget*/, GtkWidget *vb)
{
SPGradient *gradient = static_cast<SPGradient *>(g_object_get_data(G_OBJECT(vb), "gradient"));
verify_grad(gradient);
- GtkOptionMenu *mnu = static_cast<GtkOptionMenu *>(g_object_get_data(G_OBJECT(vb), "stopmenu"));
-
- SPStop *stop = static_cast<SPStop *>(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop"));
- if (stop == NULL) {
+ SPStop *stop = get_selected_stop(vb);
+ if (!stop) {
return;
}
@@ -734,7 +742,7 @@ static void sp_grd_ed_add_stop(GtkWidget */*widget*/, GtkWidget *vb)
sp_gradient_vector_widget_load_gradient(vb, gradient);
Inkscape::GC::release(new_stop_repr);
- update_stop_list(GTK_WIDGET(mnu), gradient, newstop);
+ update_stop_list(GTK_WIDGET(vb), gradient, newstop);
GtkWidget *offspin = GTK_WIDGET(g_object_get_data(G_OBJECT(vb), "offspn"));
GtkWidget *offslide =GTK_WIDGET(g_object_get_data(G_OBJECT(vb), "offslide"));
gtk_widget_set_sensitive(offslide, TRUE);
@@ -747,9 +755,11 @@ static void sp_grd_ed_del_stop(GtkWidget */*widget*/, GtkWidget *vb)
{
SPGradient *gradient = static_cast<SPGradient *>(g_object_get_data(G_OBJECT(vb), "gradient"));
- GtkOptionMenu *mnu = static_cast<GtkOptionMenu *>(g_object_get_data(G_OBJECT(vb), "stopmenu"));
- if (!g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop")) return;
- SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop"));
+ SPStop *stop = get_selected_stop(vb);
+ if (!stop) {
+ return;
+ }
+
if (gradient->vector.stops.size() > 2) { // 2 is the minimum
// if we delete first or last stop, move the next/previous to the edge
@@ -769,7 +779,7 @@ static void sp_grd_ed_del_stop(GtkWidget */*widget*/, GtkWidget *vb)
gradient->getRepr()->removeChild(stop->getRepr());
sp_gradient_vector_widget_load_gradient(vb, gradient);
- update_stop_list(GTK_WIDGET(mnu), gradient, NULL);
+ update_stop_list(GTK_WIDGET(vb), gradient, NULL);
DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT,
_("Delete gradient stop"));
}
@@ -792,14 +802,27 @@ static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *s
sp_repr_add_listener(gradient->getRepr(), &grad_edit_dia_repr_events, vb);
- /* Stop list */
- GtkWidget *mnu = gtk_option_menu_new();
- /* Create new menu widget */
- update_stop_list(GTK_WIDGET(mnu), gradient, NULL);
- g_signal_connect(G_OBJECT(mnu), "changed", G_CALLBACK(sp_grad_edit_select), vb);
- gtk_widget_show(mnu);
- g_object_set_data(G_OBJECT(vb), "stopmenu", mnu);
- gtk_box_pack_start(GTK_BOX(vb), mnu, FALSE, FALSE, 0);
+ /* ComboBox of stops with 3 columns,
+ * The color preview, the label and a pointer to the SPStop
+ */
+ GtkListStore *store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
+ GtkWidget *combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+
+ GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "pixbuf", 0, NULL);
+ gtk_cell_renderer_set_padding(renderer, 5, 0);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "text", 1, NULL);
+ gtk_widget_show(combo_box);
+ gtk_box_pack_start(GTK_BOX(vb), combo_box, FALSE, FALSE, 0);
+ g_object_set_data(G_OBJECT(vb), "combo_box", combo_box);
+
+ update_stop_list(GTK_WIDGET(vb), gradient, NULL);
+
+ g_signal_connect(G_OBJECT(combo_box), "changed", G_CALLBACK(sp_grad_edit_combo_box_changed), vb);
/* Add and Remove buttons */
GtkWidget *hb = gtk_hbox_new(FALSE, 1);
@@ -818,7 +841,6 @@ static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *s
gtk_widget_show(hb);
gtk_box_pack_start(GTK_BOX(vb),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
-
/* Offset Slider and stuff */
hb = gtk_hbox_new(FALSE, 0);
@@ -832,8 +854,12 @@ static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *s
GtkAdjustment *Offset_adj = NULL;
Offset_adj= (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 0.01, 0.01, 0.0);
g_object_set_data(G_OBJECT(vb), "offset", Offset_adj);
- GtkMenu *m = GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(mnu)));
- SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(m)), "stop"));
+
+ SPStop *stop = get_selected_stop(vb);
+ if (!stop) {
+ return NULL;
+ }
+
gtk_adjustment_set_value(Offset_adj, stop->offset);
/* Slider */
@@ -883,7 +909,7 @@ static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *s
sp_gradient_vector_widget_load_gradient(vb, gradient);
if (select_stop) {
- select_stop_in_list(GTK_WIDGET(mnu), gradient, select_stop);
+ select_stop_in_list(GTK_WIDGET(vb), gradient, select_stop);
}
return vb;
@@ -1018,8 +1044,10 @@ static void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradien
gradient->ensureVector();
- GtkOptionMenu *mnu = static_cast<GtkOptionMenu *>(g_object_get_data(G_OBJECT(widget), "stopmenu"));
- SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop"));
+ SPStop *stop = get_selected_stop(widget);
+ if (!stop) {
+ return;
+ }
// get the color selector
SPColorSelector *csel = SP_COLOR_SELECTOR(g_object_get_data(G_OBJECT(widget), "cselector"));
@@ -1030,7 +1058,7 @@ static void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradien
GtkWidget *w = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(widget), "preview"));
sp_gradient_image_set_gradient(SP_GRADIENT_IMAGE(w), gradient);
- update_stop_list(GTK_WIDGET(mnu), gradient, NULL);
+ update_stop_list(GTK_WIDGET(widget), gradient, NULL);
// Once the user edits a gradient, it stops being auto-collectable
if (gradient->getRepr()->attribute("inkscape:collect")) {
@@ -1135,9 +1163,10 @@ static void sp_gradient_vector_color_dragged(SPColorSelector *csel, GtkObject *o
ngr->ensureVector();
- GtkOptionMenu *mnu = static_cast<GtkOptionMenu *>(g_object_get_data(G_OBJECT(object), "stopmenu"));
- SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop"));
-
+ SPStop *stop = get_selected_stop(GTK_WIDGET(object));
+ if (!stop) {
+ return;
+ }
csel->base->getColorAlpha(stop->specified_color, stop->opacity);
stop->currentColor = false;
@@ -1170,8 +1199,10 @@ static void sp_gradient_vector_color_changed(SPColorSelector *csel, GtkObject *o
/* We rely on normalized vector, i.e. stops HAVE to exist */
g_return_if_fail(ngr->getFirstStop() != NULL);
- GtkOptionMenu *mnu = static_cast<GtkOptionMenu *>(g_object_get_data(G_OBJECT(object), "stopmenu"));
- SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop"));
+ SPStop *stop = get_selected_stop(GTK_WIDGET(object));
+ if (!stop) {
+ return;
+ }
csel = static_cast<SPColorSelector*>(g_object_get_data(G_OBJECT(object), "cselector"));
SPColor color;
@@ -1190,8 +1221,20 @@ static void sp_gradient_vector_color_changed(SPColorSelector *csel, GtkObject *o
blocked = FALSE;
- Inkscape::UI::Widget::ColorPreview *cpv = static_cast<Inkscape::UI::Widget::ColorPreview *>(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "preview"));
- cpv->setRgba32(sp_stop_get_rgba32(stop));
+ // Set the color in the selected stop after change
+ GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(object), "combo_box"));
+ if (combo_box) {
+ GtkTreeIter iter;
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(combo_box), &iter)) {
+ GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model (GTK_COMBO_BOX(combo_box));
+
+ Inkscape::UI::Widget::ColorPreview *cp = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(sp_stop_get_rgba32(stop)));
+ GdkPixbuf *pb = cp->toPixbuf(64, 16);
+
+ gtk_list_store_set (store, &iter, 0, pb, /*1, repr->attribute("id"),*/ 2, stop, -1);
+ }
+ }
+
}
/*
diff --git a/src/widgets/gradient-vector.h b/src/widgets/gradient-vector.h
index b198895e7..f33240504 100644
--- a/src/widgets/gradient-vector.h
+++ b/src/widgets/gradient-vector.h
@@ -29,6 +29,7 @@
#define SP_IS_GRADIENT_VECTOR_SELECTOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SP_TYPE_GRADIENT_VECTOR_SELECTOR))
class SPDocument;
+class SPObject;
class SPGradient;
class SPStop;
@@ -42,13 +43,16 @@ struct SPGradientVectorSelector {
SPDocument *doc;
SPGradient *gr;
- /* Vector menu */
- GtkWidget *menu;
+ /* ComboBox of gradient vectors */
+ GtkWidget *combo_box;
+ GtkListStore *store;
sigc::connection gradient_release_connection;
sigc::connection defs_release_connection;
sigc::connection defs_modified_connection;
+ gulong combo_connection;
+
void setSwatched();
};
@@ -71,6 +75,7 @@ SPGradient *sp_gradient_vector_selector_get_gradient (SPGradientVectorSelector *
/* fixme: rethink this (Lauris) */
GtkWidget *sp_gradient_vector_editor_new (SPGradient *gradient, SPStop *stop = NULL);
+gchar *gr_prepare_label (SPObject *obj);
#endif // SEEN_GRADIENT_VECTOR_H
diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp
index d330e2bac..d67160483 100644
--- a/src/widgets/paint-selector.cpp
+++ b/src/widgets/paint-selector.cpp
@@ -267,11 +267,18 @@ sp_paint_selector_init(SPPaintSelector *psel)
}
/* Frame */
- psel->frame = gtk_frame_new("");
+ psel->label = gtk_label_new("");
+ GtkWidget *lbbox = gtk_hbox_new(FALSE, 4);
+ gtk_widget_show(psel->label);
+ gtk_box_pack_start(GTK_BOX(lbbox), psel->label, false, false, 4);
+ gtk_box_pack_start(GTK_BOX(psel), lbbox, false, false, 4);
+
+ psel->frame = gtk_vbox_new(FALSE, 4);
gtk_widget_show(psel->frame);
- gtk_container_set_border_width(GTK_CONTAINER(psel->frame), 0);
+ //gtk_container_set_border_width(GTK_CONTAINER(psel->frame), 0);
gtk_box_pack_start(GTK_BOX(psel), psel->frame, TRUE, TRUE, 0);
+
/* Last used color */
psel->color.set( 0.0, 0.0, 0.0 );
psel->alpha = 1.0;
@@ -573,7 +580,7 @@ sp_paint_selector_set_mode_empty(SPPaintSelector *psel)
sp_paint_selector_clear_frame(psel);
- gtk_frame_set_label(GTK_FRAME(psel->frame), _("No objects"));
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>No objects</b>"));
}
static void
@@ -584,7 +591,7 @@ sp_paint_selector_set_mode_multiple(SPPaintSelector *psel)
sp_paint_selector_clear_frame(psel);
- gtk_frame_set_label(GTK_FRAME(psel->frame), _("Multiple styles"));
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Multiple styles</b>"));
}
static void
@@ -595,7 +602,7 @@ sp_paint_selector_set_mode_unset(SPPaintSelector *psel)
sp_paint_selector_clear_frame(psel);
- gtk_frame_set_label(GTK_FRAME(psel->frame), _("Paint is undefined"));
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Paint is undefined</b>"));
}
static void
@@ -606,7 +613,8 @@ sp_paint_selector_set_mode_none(SPPaintSelector *psel)
sp_paint_selector_clear_frame(psel);
- gtk_frame_set_label(GTK_FRAME(psel->frame), _("No paint"));
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>No paint</b>"));
+
}
/* Color paint */
@@ -663,6 +671,7 @@ static void sp_paint_selector_set_mode_color(SPPaintSelector *psel, SPPaintSelec
g_signal_connect(G_OBJECT(csel), "changed", G_CALLBACK(sp_paint_selector_color_changed), psel);
/* Pack everything to frame */
gtk_container_add(GTK_CONTAINER(psel->frame), vb);
+
psel->selector = vb;
/* Set color */
@@ -670,7 +679,8 @@ static void sp_paint_selector_set_mode_color(SPPaintSelector *psel, SPPaintSelec
}
- gtk_frame_set_label(GTK_FRAME(psel->frame), _("Flat color"));
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Flat color</b>"));
+
#ifdef SP_PS_VERBOSE
g_print("Color req\n");
#endif
@@ -733,10 +743,10 @@ static void sp_paint_selector_set_mode_gradient(SPPaintSelector *psel, SPPaintSe
if (mode == SPPaintSelector::MODE_GRADIENT_LINEAR) {
SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_LINEAR);
//sp_gradient_selector_set_mode(SP_GRADIENT_SELECTOR(gsel), SP_GRADIENT_SELECTOR_MODE_LINEAR);
- gtk_frame_set_label(GTK_FRAME(psel->frame), _("Linear gradient"));
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Linear gradient</b>"));
} else {
SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_RADIAL);
- gtk_frame_set_label(GTK_FRAME(psel->frame), _("Radial gradient"));
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Radial gradient</b>"));
}
#ifdef SP_PS_VERBOSE
g_print("Gradient req\n");
@@ -1016,7 +1026,7 @@ static void sp_paint_selector_set_mode_pattern(SPPaintSelector *psel, SPPaintSel
psel->selector = tbl;
g_object_set_data(G_OBJECT(psel->selector), "pattern-selector", tbl);
- gtk_frame_set_label(GTK_FRAME(psel->frame), _("Pattern fill"));
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Pattern fill</b>"));
}
#ifdef SP_PS_VERBOSE
g_print("Pattern req\n");
@@ -1091,7 +1101,7 @@ static void sp_paint_selector_set_mode_swatch(SPPaintSelector *psel, SPPaintSele
psel->selector = GTK_WIDGET(swatchsel->gobj());
g_object_set_data(G_OBJECT(psel->selector), "swatch-selector", swatchsel);
- gtk_frame_set_label(GTK_FRAME(psel->frame), _("Swatch fill"));
+ gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Swatch fill</b>"));
}
#ifdef SP_PS_VERBOSE
diff --git a/src/widgets/paint-selector.h b/src/widgets/paint-selector.h
index 69cfa602e..7400987ee 100644
--- a/src/widgets/paint-selector.h
+++ b/src/widgets/paint-selector.h
@@ -72,6 +72,7 @@ struct SPPaintSelector {
GtkWidget *evenodd, *nonzero;
GtkWidget *frame, *selector;
+ GtkWidget *label;
SPColor color;
float alpha;
diff --git a/src/widgets/stroke-marker-selector.cpp b/src/widgets/stroke-marker-selector.cpp
new file mode 100644
index 000000000..a39ebf8be
--- /dev/null
+++ b/src/widgets/stroke-marker-selector.cpp
@@ -0,0 +1,458 @@
+/**
+ * @file
+ * Combobox for selecting dash patterns - implementation.
+ */
+/* Author:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * bulia byak <buliabyak@users.sf.net>
+ * Maximilian Albert <maximilian.albert@gmail.com>
+ *
+ * Copyright (C) 2002 Lauris Kaplinski
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "stroke-marker-selector.h"
+
+#include <cstring>
+#include <string>
+#include <glibmm/i18n.h>
+#include <2geom/coord.h>
+
+
+#include "style.h"
+#include "dialogs/dialog-events.h"
+#include "desktop-handles.h"
+#include "desktop-style.h"
+#include "preferences.h"
+#include "path-prefix.h"
+#include "io/sys.h"
+#include "marker.h"
+#include "sp-defs.h"
+#include "sp-root.h"
+#include "ui/cache/svg_preview_cache.h"
+#include "helper/stock-items.h"
+
+#include <gtkmm/adjustment.h>
+#include "ui/widget/spinbutton.h"
+
+static Inkscape::UI::Cache::SvgPreview svg_preview_cache;
+
+MarkerComboBox::MarkerComboBox(gchar const *id) :
+ Gtk::ComboBox(),
+ combo_id(id),
+ updating(false),
+ is_history(false)
+{
+
+ marker_store = Gtk::ListStore::create(marker_columns);
+ set_model(marker_store);
+ pack_start(image_renderer, false);
+ pack_end(label_renderer, true);
+ label_renderer.set_padding(5, 0);
+ image_renderer.set_padding(5, 0);
+ set_cell_data_func(label_renderer, sigc::mem_fun(*this, &MarkerComboBox::prepareLabelRenderer));
+ set_cell_data_func(image_renderer, sigc::mem_fun(*this, &MarkerComboBox::prepareImageRenderer));
+ gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(gobj()), MarkerComboBox::separator_cb, NULL, NULL);
+
+ empty_image = new Gtk::Image();
+
+ sandbox = ink_markers_preview_doc ();
+ desktop = inkscape_active_desktop();
+ doc = sp_desktop_document(desktop);
+
+ init_combo();
+
+ show();
+}
+
+MarkerComboBox::~MarkerComboBox() {
+ delete combo_id;
+ delete sandbox;
+}
+
+/**
+ * Init the combobox widget to display markers from markers.svg
+ */
+void
+MarkerComboBox::init_combo()
+{
+ updating = false;
+
+ if (!doc) {
+ Gtk::TreeModel::Row row = *(marker_store->append());
+ row[marker_columns.label] = _("No document selected");
+ row[marker_columns.image] = NULL;
+ set_sensitive(false);
+ set_current(NULL);
+ return;
+ }
+
+ static SPDocument *markers_doc = NULL;
+
+ // add "None"
+ Gtk::TreeModel::Row row = *(marker_store->append());
+ row[marker_columns.label] = _("None");
+ row[marker_columns.marker] = g_strdup("none");
+ row[marker_columns.image] = NULL;
+
+ // find and load markers.svg
+ if (markers_doc == NULL) {
+ char *markers_source = g_build_filename(INKSCAPE_MARKERSDIR, "markers.svg", NULL);
+ if (Inkscape::IO::file_test(markers_source, G_FILE_TEST_IS_REGULAR)) {
+ markers_doc = SPDocument::createNewDoc(markers_source, FALSE);
+ }
+ g_free(markers_source);
+ }
+
+ // suck in from current doc
+ is_history = true;
+ sp_marker_list_from_doc(doc);
+ is_history = false;
+
+ // add separator
+ Gtk::TreeModel::Row row_sep = *(marker_store->append());
+ row_sep[marker_columns.label] = "Separator";
+ row_sep[marker_columns.isseparator] = true;
+ row_sep[marker_columns.image] = NULL;
+
+ // suck in from markers.svg
+ if (markers_doc) {
+ doc->ensureUpToDate();
+ sp_marker_list_from_doc(markers_doc);
+ }
+
+ set_sensitive(true);
+
+ /* Set history */
+ set_current(NULL);
+}
+
+/**
+ * Sets the current marker in the marker combobox.
+ */
+void MarkerComboBox::set_current(SPObject *marker)
+{
+ updating = true;
+
+ if (marker != NULL) {
+ bool mark_is_stock = false;
+ if (marker->getRepr()->attribute("inkscape:stockid")) {
+ mark_is_stock = true;
+ }
+
+ gchar *markname = 0;
+ if (mark_is_stock) {
+ markname = g_strdup(marker->getRepr()->attribute("inkscape:stockid"));
+ } else {
+ markname = g_strdup(marker->getRepr()->attribute("id"));
+ }
+
+ set_selected(markname);
+
+ g_free (markname);
+ }
+ else {
+ set_selected(NULL);
+ }
+
+ updating = false;
+
+}
+/**
+ * Return a uri string representing the current selected marker used for setting the marker style in the document
+ */
+const gchar * MarkerComboBox::get_active_marker_uri()
+{
+ /* Get Marker */
+ const gchar *markid = get_active()->get_value(marker_columns.marker);
+ if (!markid)
+ {
+ return NULL;
+ }
+
+ gchar const *marker = "";
+ if (strcmp(markid, "none")) {
+ bool stockid = get_active()->get_value(marker_columns.isstock);
+
+ gchar *markurn = g_strdup(markid);
+ if (stockid) markurn = g_strconcat("urn:inkscape:marker:",markid,NULL);
+ SPObject *mark = get_stock_item(markurn);
+ g_free(markurn);
+ if (mark) {
+ Inkscape::XML::Node *repr = mark->getRepr();
+ marker = g_strconcat("url(#", repr->attribute("id"), ")", NULL);
+ }
+ } else {
+ marker = g_strdup(markid);
+ }
+
+ return marker;
+}
+
+
+void MarkerComboBox::set_active_history() {
+ set_selected(get_active()->get_value(marker_columns.marker));
+}
+
+
+void MarkerComboBox::set_selected(const gchar *name) {
+
+ if (!name) {
+ set_active(0);
+ return;
+ }
+
+ for(Gtk::TreeIter iter = marker_store->children().begin();
+ iter != marker_store->children().end(); ++iter) {
+ Gtk::TreeModel::Row row = (*iter);
+ if (row[marker_columns.marker] &&
+ !strcmp(row[marker_columns.marker], name)) {
+ set_active(iter);
+ if (strcmp(name, "none"))
+ set_history(row);
+ return;
+ }
+ }
+}
+
+void MarkerComboBox::set_history(Gtk::TreeModel::Row match_row) {
+
+ if (!match_row) {
+ return;
+ }
+
+ for(Gtk::TreeIter iter = marker_store->children().begin();
+ iter != marker_store->children().end(); ++iter) {
+ Gtk::TreeModel::Row row = (*iter);
+ if (row[marker_columns.history] &&
+ !strcmp(row[marker_columns.marker], match_row[marker_columns.marker])) {
+ return;
+ }
+ }
+
+ // Add a new row to the history
+ Gtk::TreeModel::Row row = *(marker_store->insert_after(marker_store->children().begin()));
+ row[marker_columns.marker] = g_strdup(match_row.get_value(marker_columns.marker));
+ row[marker_columns.label] = match_row.get_value(marker_columns.label);
+ row[marker_columns.isstock] = match_row.get_value(marker_columns.isstock);
+ row[marker_columns.image] = match_row.get_value(marker_columns.image);
+ row[marker_columns.history] = true;
+}
+
+/**
+ * Pick up all markers from source, except those that are in
+ * current_doc (if non-NULL), and add items to the combo.
+ */
+void MarkerComboBox::sp_marker_list_from_doc(SPDocument *source)
+{
+ GSList *ml = get_marker_list(source);
+ GSList *clean_ml = NULL;
+
+ for (; ml != NULL; ml = ml->next) {
+ if (!SP_IS_MARKER(ml->data))
+ continue;
+
+ // Add to the list of markers we really do wish to show
+ clean_ml = g_slist_prepend (clean_ml, ml->data);
+ }
+ add_markers(clean_ml, source);
+
+ g_slist_free (ml);
+ g_slist_free (clean_ml);
+}
+
+/**
+ * Returns a list of markers in the defs of the given source document as a GSList object
+ * Returns NULL if there are no markers in the document.
+ */
+GSList *MarkerComboBox::get_marker_list (SPDocument *source)
+{
+ if (source == NULL)
+ return NULL;
+
+ GSList *ml = NULL;
+ SPDefs *defs = source->getDefs();
+ for ( SPObject *child = defs->firstChild(); child; child = child->getNext() )
+ {
+ if (SP_IS_MARKER(child)) {
+ ml = g_slist_prepend (ml, child);
+ }
+ }
+ return ml;
+}
+
+/**
+ * Adds previews of markers in marker_list to the combo
+ */
+void MarkerComboBox::add_markers (GSList *marker_list, SPDocument *source)
+{
+ // Do this here, outside of loop, to speed up preview generation:
+ Inkscape::Drawing drawing;
+ unsigned const visionkey = SPItem::display_key_new(1);
+ drawing.setRoot(sandbox->getRoot()->invoke_show(drawing, visionkey, SP_ITEM_SHOW_DISPLAY));
+
+ for (; marker_list != NULL; marker_list = marker_list->next) {
+
+ Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(marker_list->data)->getRepr();
+ bool isstock = (repr->attribute("inkscape:stockid"));
+ gchar const *markid = repr->attribute("id");
+
+ // generate preview
+ Gtk::Image *prv = create_marker_image (22, markid, source, drawing, visionkey);
+ prv->show();
+
+ Gtk::TreeModel::Row row = *(marker_store->append());
+ row[marker_columns.label] = g_strdup(markid);
+ row[marker_columns.marker] = g_strdup(markid);
+ row[marker_columns.isstock] = isstock;
+ row[marker_columns.image] = prv;
+ row[marker_columns.history] = is_history;
+
+ }
+
+ sandbox->getRoot()->invoke_hide(visionkey);
+}
+
+/**
+ * Creates a copy of the marker named mname, determines its visible and renderable
+ * area in the bounding box, and then renders it. This allows us to fill in
+ * preview images of each marker in the marker combobox.
+ */
+Gtk::Image *
+MarkerComboBox::create_marker_image(unsigned psize, gchar const *mname,
+ SPDocument *source, Inkscape::Drawing &drawing, unsigned /*visionkey*/)
+{
+ // Retrieve the marker named 'mname' from the source SVG document
+ SPObject const *marker = source->getObjectById(mname);
+ if (marker == NULL) {
+ return NULL;
+ }
+
+ // Create a copy repr of the marker with id="sample"
+ Inkscape::XML::Document *xml_doc = sandbox->getReprDoc();
+ Inkscape::XML::Node *mrepr = marker->getRepr()->duplicate(xml_doc);
+ mrepr->setAttribute("id", "sample");
+
+ // Replace the old sample in the sandbox by the new one
+ Inkscape::XML::Node *defsrepr = sandbox->getObjectById("defs")->getRepr();
+ SPObject *oldmarker = sandbox->getObjectById("sample");
+ if (oldmarker) {
+ oldmarker->deleteObject(false);
+ }
+
+ // TODO - This causes a SIGTRAP on windows
+ defsrepr->appendChild(mrepr);
+
+ Inkscape::GC::release(mrepr);
+
+// Uncomment this to get the sandbox documents saved (useful for debugging)
+ //FILE *fp = fopen (g_strconcat(combo_id, mname, ".svg", NULL), "w");
+ //sp_repr_save_stream(sandbox->getReprDoc(), fp);
+ //fclose (fp);
+
+ // object to render; note that the id is the same as that of the combo we're building
+ SPObject *object = sandbox->getObjectById(combo_id);
+ sandbox->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ sandbox->ensureUpToDate();
+
+ if (object == NULL || !SP_IS_ITEM(object)) {
+ return NULL; // sandbox broken?
+ }
+
+ SPItem *item = SP_ITEM(object);
+ // Find object's bbox in document
+ Geom::OptRect dbox = item->documentVisualBounds();
+
+ if (!dbox) {
+ return NULL;
+ }
+
+ /* Update to renderable state */
+ double sf = 0.8;
+
+ gchar *cache_name = g_strconcat(combo_id, mname, NULL);
+ Glib::ustring key = svg_preview_cache.cache_key(source->getURI(), cache_name, psize);
+ g_free (cache_name);
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key));
+
+ if (!pixbuf) {
+ pixbuf = Glib::wrap(render_pixbuf(drawing, sf, *dbox, psize));
+ svg_preview_cache.set_preview_in_cache(key, pixbuf->gobj());
+ }
+
+ // Create widget
+ Gtk::Image *pb = new Gtk::Image(pixbuf);
+
+ return pb;
+}
+
+void MarkerComboBox::prepareLabelRenderer( Gtk::TreeModel::const_iterator const &row ) {
+ Glib::ustring name=(*row)[marker_columns.label];
+ label_renderer.property_markup() = name.c_str();
+}
+
+void MarkerComboBox::prepareImageRenderer( Gtk::TreeModel::const_iterator const &row ) {
+
+ Gtk::Image *image = (*row)[marker_columns.image];
+ if (image)
+ image_renderer.property_pixbuf() = image->get_pixbuf();
+ else
+ image_renderer.property_pixbuf() = empty_image->get_pixbuf();
+}
+
+gboolean MarkerComboBox::separator_cb (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) {
+
+ gboolean sep = FALSE;
+ gtk_tree_model_get(model, iter, 5, &sep, -1);
+ return sep;
+}
+
+/**
+ * Returns a new document containing default start, mid, and end markers.
+ */
+SPDocument *MarkerComboBox::ink_markers_preview_doc ()
+{
+gchar const *buffer = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
+" <defs id=\"defs\" />"
+
+" <g id=\"marker-start\">"
+" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:url(#sample);marker-mid:none;marker-end:none\""
+" d=\"M 12.5,13 L 25,13\" id=\"path1\" />"
+" <rect style=\"fill:none;stroke:none\" id=\"rect2\""
+" width=\"25\" height=\"25\" x=\"0\" y=\"0\" />"
+" </g>"
+
+" <g id=\"marker-mid\">"
+" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:none;marker-mid:url(#sample);marker-end:none\""
+" d=\"M 0,113 L 12.5,113 L 25,113\" id=\"path11\" />"
+" <rect style=\"fill:none;stroke:none\" id=\"rect22\""
+" width=\"25\" height=\"25\" x=\"0\" y=\"100\" />"
+" </g>"
+
+" <g id=\"marker-end\">"
+" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:none;marker-mid:none;marker-end:url(#sample)\""
+" d=\"M 0,213 L 12.5,213\" id=\"path111\" />"
+" <rect style=\"fill:none;stroke:none\" id=\"rect222\""
+" width=\"25\" height=\"25\" x=\"0\" y=\"200\" />"
+" </g>"
+
+"</svg>";
+
+ return SPDocument::createNewDocFromMem (buffer, strlen(buffer), FALSE);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/widgets/stroke-marker-selector.h b/src/widgets/stroke-marker-selector.h
new file mode 100644
index 000000000..4365b7e2a
--- /dev/null
+++ b/src/widgets/stroke-marker-selector.h
@@ -0,0 +1,104 @@
+#ifndef SEEN_SP_MARKER_SELECTOR_NEW_H
+#define SEEN_SP_MARKER_SELECTOR_NEW_H
+
+/* Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Maximilian Albert <maximilian.albert> (gtkmm-ification)
+ *
+ * Copyright (C) 2002 Lauris Kaplinski
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/box.h>
+#include <gtkmm/combobox.h>
+#include <gtkmm/liststore.h>
+
+#include <sigc++/signal.h>
+
+#include "document.h"
+#include "inkscape.h"
+#include "display/drawing.h"
+
+namespace Gtk {
+class Container;
+class Adjustment;
+}
+
+/**
+ * ComboBox derived class for selecting stroke markers.
+ */
+
+class MarkerComboBox : public Gtk::ComboBox {
+public:
+ MarkerComboBox(gchar const *id);
+ ~MarkerComboBox();
+
+ sigc::signal<void> changed_signal;
+
+ void set_current(SPObject *marker);
+ void set_active_history();
+ void set_selected(const gchar *name);
+ const gchar *get_active_marker_uri();
+ bool update() { return updating; };
+ gchar const *get_id() { return combo_id; };
+
+private:
+
+ Glib::RefPtr<Gtk::ListStore> marker_store;
+ gchar const *combo_id;
+ bool updating;
+ bool is_history;
+ SPDesktop *desktop;
+ SPDocument *doc;
+ SPDocument *sandbox;
+ Gtk::Image *empty_image;
+ Gtk::CellRendererText label_renderer;
+ Gtk::CellRendererPixbuf image_renderer;
+
+ class MarkerColumns : public Gtk::TreeModel::ColumnRecord {
+ public:
+ Gtk::TreeModelColumn<Glib::ustring> label;
+ Gtk::TreeModelColumn<const gchar *> marker; // ustring doesnt work here on windows due to unicode
+ Gtk::TreeModelColumn<bool> isstock;
+ Gtk::TreeModelColumn<Gtk::Image *> image;
+ Gtk::TreeModelColumn<bool> history;
+ Gtk::TreeModelColumn<bool> isseparator;
+
+ MarkerColumns() {
+ add(label); add(marker); add(isstock); add(image); add(history); add(isseparator);
+ }
+ };
+ MarkerColumns marker_columns;
+
+ void init_combo();
+ void set_history(Gtk::TreeModel::Row match_row);
+ void sp_marker_list_from_doc(SPDocument *source);
+ GSList *get_marker_list (SPDocument *source);
+ void add_markers (GSList *marker_list, SPDocument *source);
+ SPDocument *ink_markers_preview_doc ();
+ Gtk::Image * create_marker_image(unsigned psize, gchar const *mname,
+ SPDocument *source, Inkscape::Drawing &drawing, unsigned /*visionkey*/);
+
+ /*
+ * Callbacks for drawing the combo box
+ */
+ void prepareLabelRenderer( Gtk::TreeModel::const_iterator const &row );
+ void prepareImageRenderer( Gtk::TreeModel::const_iterator const &row );
+ static gboolean separator_cb (GtkTreeModel *model, GtkTreeIter *iter, gpointer data);
+
+
+};
+
+#endif // SEEN_SP_MARKER_SELECTOR_NEW_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp
index a49a26734..f6afec18e 100644
--- a/src/widgets/stroke-style.cpp
+++ b/src/widgets/stroke-style.cpp
@@ -55,27 +55,25 @@
#include "xml/repr.h"
#include "stroke-style.h"
+#include "stroke-marker-selector.h"
#include "fill-style.h" // to get sp_fill_style_widget_set_desktop
#include "fill-n-stroke-factory.h"
-#include <gtkmm/optionmenu.h>
#include "verbs.h"
using Inkscape::DocumentUndo;
-/** Marker selection option menus */
-static Gtk::OptionMenu * marker_start_menu = NULL;
-static Gtk::OptionMenu * marker_mid_menu = NULL;
-static Gtk::OptionMenu * marker_end_menu = NULL;
-sigc::connection marker_start_menu_connection;
-sigc::connection marker_mid_menu_connection;
-sigc::connection marker_end_menu_connection;
+static MarkerComboBox *start_marker_combobox = NULL;
+static MarkerComboBox *mid_marker_combobox = NULL;
+static MarkerComboBox *end_marker_combobox = NULL;
-static SPObject *ink_extract_marker_name(gchar const *n, SPDocument *doc);
-static void ink_markers_menu_update(Gtk::Container* spw, SPMarkerLoc const which);
+sigc::connection start_marker_connection;
+sigc::connection mid_marker_connection;
+sigc::connection end_marker_connection;
-static Inkscape::UI::Cache::SvgPreview svg_preview_cache;
+static SPObject *ink_extract_marker_name(gchar const *n, SPDocument *doc);
+static void ink_markers_combo_update(Gtk::Container* spw, SPMarkerLoc const which);
Gtk::Widget *sp_stroke_style_paint_widget_new(void)
{
@@ -87,8 +85,6 @@ void sp_stroke_style_widget_set_desktop(Gtk::Widget *widget, SPDesktop *desktop)
sp_fill_style_widget_set_desktop(widget, desktop);
}
-
-
/* Line */
static void sp_stroke_style_line_selection_modified(SPWidget *spw, Inkscape::Selection *selection, guint flags, gpointer data);
@@ -105,7 +101,7 @@ static void sp_stroke_style_miterlimit_changed(Gtk::Container *spw);
static void sp_stroke_style_any_toggled(Gtk::ToggleButton *tb, Gtk::Container *spw);
static void sp_stroke_style_line_dash_changed(Gtk::Container *spw);
-static void sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects);
+static void sp_stroke_style_update_marker_combo(Gtk::Container *spw, GSList const *objects);
/**
@@ -145,303 +141,12 @@ sp_stroke_radio_button(Gtk::RadioButton *tb, char const *icon,
}
/**
- * Create sa copy of the marker named mname, determines its visible and renderable
- * area in menu_id's bounding box, and then renders it. This allows us to fill in
- * preview images of each marker in the marker menu.
- */
-static Gtk::Image *
-sp_marker_prev_new(unsigned psize, gchar const *mname,
- SPDocument *source, SPDocument *sandbox,
- gchar const *menu_id, Inkscape::Drawing &drawing, unsigned /*visionkey*/)
-{
- // Retrieve the marker named 'mname' from the source SVG document
- SPObject const *marker = source->getObjectById(mname);
- if (marker == NULL) {
- return NULL;
- }
-
- // Create a copy repr of the marker with id="sample"
- Inkscape::XML::Document *xml_doc = sandbox->getReprDoc();
- Inkscape::XML::Node *mrepr = marker->getRepr()->duplicate(xml_doc);
- mrepr->setAttribute("id", "sample");
-
- // Replace the old sample in the sandbox by the new one
- Inkscape::XML::Node *defsrepr = sandbox->getObjectById("defs")->getRepr();
- SPObject *oldmarker = sandbox->getObjectById("sample");
- if (oldmarker) {
- oldmarker->deleteObject(false);
- }
- defsrepr->appendChild(mrepr);
- Inkscape::GC::release(mrepr);
-
-// Uncomment this to get the sandbox documents saved (useful for debugging)
- //FILE *fp = fopen (g_strconcat(menu_id, mname, ".svg", NULL), "w");
- //sp_repr_save_stream(sandbox->getReprDoc(), fp);
- //fclose (fp);
-
- // object to render; note that the id is the same as that of the menu we're building
- SPObject *object = sandbox->getObjectById(menu_id);
- sandbox->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- sandbox->ensureUpToDate();
-
- if (object == NULL || !SP_IS_ITEM(object)) {
- return NULL; // sandbox broken?
- }
-
- SPItem *item = SP_ITEM(object);
- // Find object's bbox in document
- Geom::OptRect dbox = item->documentVisualBounds();
-
- if (!dbox) {
- return NULL;
- }
-
- /* Update to renderable state */
- double sf = 0.8;
-
- gchar *cache_name = g_strconcat(menu_id, mname, NULL);
- Glib::ustring key = svg_preview_cache.cache_key(source->getURI(), cache_name, psize);
- g_free (cache_name);
- // TODO: is this correct?
- Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key));
-
- if (!pixbuf) {
- pixbuf = Glib::wrap(render_pixbuf(drawing, sf, *dbox, psize));
- svg_preview_cache.set_preview_in_cache(key, pixbuf->gobj());
- }
-
- // Create widget
- Gtk::Image *pb = new Gtk::Image(pixbuf);
-
- return pb;
-}
-
-/**
- * Returns a list of markers in the defs of the given source document as a GSList object
- * Returns NULL if there are no markers in the document.
- */
-GSList *
-ink_marker_list_get (SPDocument *source)
-{
- if (source == NULL)
- return NULL;
-
- GSList *ml = NULL;
- SPDefs *defs = source->getDefs();
- for ( SPObject *child = defs->firstChild(); child; child = child->getNext() )
- {
- if (SP_IS_MARKER(child)) {
- ml = g_slist_prepend (ml, child);
- }
- }
- return ml;
-}
-
-#define MARKER_ITEM_MARGIN 0
-
-/**
- * Adds previews of markers in marker_list to the given menu widget
- */
-static void
-sp_marker_menu_build (Gtk::Menu *m, GSList *marker_list, SPDocument *source, SPDocument *sandbox, gchar const *menu_id)
-{
- // Do this here, outside of loop, to speed up preview generation:
- Inkscape::Drawing drawing;
- unsigned const visionkey = SPItem::display_key_new(1);
- drawing.setRoot(sandbox->getRoot()->invoke_show(drawing, visionkey, SP_ITEM_SHOW_DISPLAY));
-
- for (; marker_list != NULL; marker_list = marker_list->next) {
- Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(marker_list->data)->getRepr();
- Gtk::MenuItem *i = new Gtk::MenuItem();
- i->show();
-
- if (repr->attribute("inkscape:stockid")) {
- i->set_data("stockid", (void *) "true");
- } else {
- i->set_data("stockid", (void *) "false");
- }
-
- gchar const *markid = repr->attribute("id");
- i->set_data("marker", (void *) markid);
-
- Gtk::HBox *hb = new Gtk::HBox(false, MARKER_ITEM_MARGIN);
- hb->show();
-
- // generate preview
-
- Gtk::Image *prv = sp_marker_prev_new (22, markid, source, sandbox, menu_id, drawing, visionkey);
- prv->show();
- hb->pack_start(*prv, false, false, 6);
-
- // create label
- Gtk::Label *l = new Gtk::Label(repr->attribute("id"));
- l->show();
- l->set_alignment(0.0, 0.5);
-
- hb->pack_start(*l, true, true, 0);
-
- hb->show();
- i->add(*hb);
-
- m->append(*i);
- }
-
- sandbox->getRoot()->invoke_hide(visionkey);
-}
-
-/**
- * Pick up all markers from source, except those that are in
- * current_doc (if non-NULL), and add items to the m menu.
- */
-static void sp_marker_list_from_doc(Gtk::Menu *m, SPDocument * /*current_doc*/, SPDocument *source, SPDocument * /*markers_doc*/, SPDocument *sandbox, gchar const *menu_id)
-{
- GSList *ml = ink_marker_list_get(source);
- GSList *clean_ml = NULL;
-
- for (; ml != NULL; ml = ml->next) {
- if (!SP_IS_MARKER(ml->data))
- continue;
-
- // Add to the list of markers we really do wish to show
- clean_ml = g_slist_prepend (clean_ml, ml->data);
- }
- sp_marker_menu_build(m, clean_ml, source, sandbox, menu_id);
-
- g_slist_free (ml);
- g_slist_free (clean_ml);
-}
-
-/**
- * Returns a new document containing default start, mid, and end markers.
- */
-SPDocument *
-ink_markers_preview_doc ()
-{
-gchar const *buffer = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
-" <defs id=\"defs\" />"
-
-" <g id=\"marker-start\">"
-" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:url(#sample);marker-mid:none;marker-end:none\""
-" d=\"M 12.5,13 L 25,13\" id=\"path1\" />"
-" <rect style=\"fill:none;stroke:none\" id=\"rect2\""
-" width=\"25\" height=\"25\" x=\"0\" y=\"0\" />"
-" </g>"
-
-" <g id=\"marker-mid\">"
-" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:none;marker-mid:url(#sample);marker-end:none\""
-" d=\"M 0,113 L 12.5,113 L 25,113\" id=\"path11\" />"
-" <rect style=\"fill:none;stroke:none\" id=\"rect22\""
-" width=\"25\" height=\"25\" x=\"0\" y=\"100\" />"
-" </g>"
-
-" <g id=\"marker-end\">"
-" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:none;marker-mid:none;marker-end:url(#sample)\""
-" d=\"M 0,213 L 12.5,213\" id=\"path111\" />"
-" <rect style=\"fill:none;stroke:none\" id=\"rect222\""
-" width=\"25\" height=\"25\" x=\"0\" y=\"200\" />"
-" </g>"
-
-"</svg>";
-
- return SPDocument::createNewDocFromMem (buffer, strlen(buffer), FALSE);
-}
-
-static void
-ink_marker_menu_create_menu(Gtk::Menu *m, gchar const *menu_id, SPDocument *doc, SPDocument *sandbox)
-{
- static SPDocument *markers_doc = NULL;
-
- // add "None"
- Gtk::MenuItem *i = new Gtk::MenuItem();
- i->show();
-
- i->set_data("marker", (void *) "none");
-
- Gtk::HBox *hb = new Gtk::HBox(false, MARKER_ITEM_MARGIN);
- hb->show();
-
- Gtk::Label *l = new Gtk::Label( _("None") );
- l->show();
- l->set_alignment(0.0, 0.5);
-
- hb->pack_start(*l, true, true, 0);
-
- hb->show();
- i->add(*hb);
- m->append(*i);
-
- // find and load markers.svg
- if (markers_doc == NULL) {
- char *markers_source = g_build_filename(INKSCAPE_MARKERSDIR, "markers.svg", NULL);
- if (Inkscape::IO::file_test(markers_source, G_FILE_TEST_IS_REGULAR)) {
- markers_doc = SPDocument::createNewDoc(markers_source, FALSE);
- }
- g_free(markers_source);
- }
-
- // suck in from current doc
- sp_marker_list_from_doc(m, NULL, doc, markers_doc, sandbox, menu_id);
-
- // add separator
- {
- //Gtk::Separator *i = gtk_separator_menu_item_new();
- Gtk::SeparatorMenuItem *i = new Gtk::SeparatorMenuItem();
- i->show();
- m->append(*i);
- }
-
- // suck in from markers.svg
- if (markers_doc) {
- doc->ensureUpToDate();
- sp_marker_list_from_doc(m, doc, markers_doc, NULL, sandbox, menu_id);
- }
-
-}
-
-/**
- * Creates a menu widget to display markers from markers.svg
- */
-static Gtk::OptionMenu *
-ink_marker_menu(Gtk::Widget * /*tbl*/, gchar const *menu_id, SPDocument *sandbox)
-{
- SPDesktop *desktop = inkscape_active_desktop();
- SPDocument *doc = sp_desktop_document(desktop);
- Gtk::OptionMenu *mnu = new Gtk::OptionMenu();
-
- /* Create new menu widget */
- Gtk::Menu *m = new Gtk::Menu();
- m->show();
-
- mnu->set_data("updating", (gpointer) FALSE);
-
- if (!doc) {
- Gtk::MenuItem *i = new Gtk::MenuItem(_("No document selected"));
- i->show();
- m->append(*i);
- mnu->set_sensitive(false);
-
- } else {
- ink_marker_menu_create_menu(m, menu_id, doc, sandbox);
-
- mnu->set_sensitive(true);
- }
-
- mnu->set_data("menu_id", const_cast<gchar *>(menu_id));
- mnu->set_menu(*m);
-
- /* Set history */
- mnu->set_history(0);
-
- return mnu;
-}
-
-/**
- * Handles when user selects one of the markers from the marker menu.
- * Defines a uri string to refer to it, then applies it to all selected
+ * Handles when user selects one of the markers from the marker combobox.
+ * Gets the marker uri string and applies it to all selected
* items in the current desktop.
*/
static void
-sp_marker_select(Gtk::OptionMenu *mnu, Gtk::Container *spw, SPMarkerLoc const which)
+sp_marker_select(MarkerComboBox *marker_combo, Gtk::Container *spw, SPMarkerLoc const which)
{
if (spw->get_data("update")) {
return;
@@ -454,33 +159,17 @@ sp_marker_select(Gtk::OptionMenu *mnu, Gtk::Container *spw, SPMarkerLoc const wh
}
/* Get Marker */
- if (!mnu->get_menu()->get_active()->get_data("marker"))
- {
- return;
- }
- gchar *markid = static_cast<gchar *>(mnu->get_menu()->get_active()->get_data("marker"));
- gchar const *marker = "";
- if (strcmp(markid, "none")) {
- gchar *stockid = static_cast<gchar *>(mnu->get_menu()->get_active()->get_data("stockid"));
-
- gchar *markurn = markid;
- if (!strcmp(stockid,"true")) markurn = g_strconcat("urn:inkscape:marker:",markid,NULL);
- SPObject *mark = get_stock_item(markurn);
- if (mark) {
- Inkscape::XML::Node *repr = mark->getRepr();
- marker = g_strconcat("url(#", repr->attribute("id"), ")", NULL);
- }
- } else {
- marker = markid;
- }
+ gchar const *marker = marker_combo->get_active_marker_uri();
+
+
SPCSSAttr *css = sp_repr_css_attr_new();
- gchar const *menu_id = static_cast<gchar const *>(mnu->get_data("menu_id"));
- sp_repr_css_set_property(css, menu_id, marker);
+ gchar const *combo_id = marker_combo->get_id();
+ sp_repr_css_set_property(css, combo_id, marker);
- // Also update the marker dropdown menus, so the document's markers
- // show up at the top of the menu
+ // Also update the marker combobox, so the document's markers
+ // show up at the top of the combobox
// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL);
- ink_markers_menu_update(spw, which);
+ ink_markers_combo_update(spw, which);
Inkscape::Selection *selection = sp_desktop_selection(desktop);
GSList const *items = selection->itemList();
@@ -505,72 +194,26 @@ sp_marker_select(Gtk::OptionMenu *mnu, Gtk::Container *spw, SPMarkerLoc const wh
};
-static unsigned int
-ink_marker_menu_get_pos(Gtk::Menu *mnu, gchar const *markname)
-{
- if (markname == NULL)
- markname = static_cast<gchar const *>(mnu->get_active()->get_data("marker"));
-
- if (markname == NULL)
- return 0;
-
- std::vector<Gtk::Widget *> kids = mnu->get_children();
- unsigned int i = 0;
- for (; i < kids.size();) {
- gchar const *mark = static_cast<gchar const *>(kids[i]->get_data("marker"));
- if (mark && strcmp(mark, markname) == 0) {
- break;
- }
- ++i;
- }
-
- return i;
-}
-
static void
-ink_markers_menu_update(Gtk::Container* /*spw*/, SPMarkerLoc const which) {
- SPDesktop *desktop = inkscape_active_desktop();
- SPDocument *document = sp_desktop_document(desktop);
- SPDocument *sandbox = ink_markers_preview_doc ();
- Gtk::Menu *m;
- int pos;
+ink_markers_combo_update(Gtk::Container* /*spw*/, SPMarkerLoc const which) {
- // TODO: this code can be shortened by abstracting out marker_(start|mid|end)_...
switch (which) {
case SP_MARKER_LOC_START:
- marker_start_menu_connection.block();
- pos = ink_marker_menu_get_pos(marker_start_menu->get_menu(), NULL);
- m = new Gtk::Menu();
- m->show();
- ink_marker_menu_create_menu(m, "marker-start", document, sandbox);
- marker_start_menu->remove_menu();
- marker_start_menu->set_menu(*m);
- marker_start_menu->set_history(pos);
- marker_start_menu_connection.unblock();
+ start_marker_connection.block();
+ start_marker_combobox->set_active_history();
+ start_marker_connection.unblock();
break;
case SP_MARKER_LOC_MID:
- marker_mid_menu_connection.block();
- pos = ink_marker_menu_get_pos(marker_mid_menu->get_menu(), NULL);
- m = new Gtk::Menu();
- m->show();
- ink_marker_menu_create_menu(m, "marker-mid", document, sandbox);
- marker_mid_menu->remove_menu();
- marker_mid_menu->set_menu(*m);
- marker_mid_menu->set_history(pos);
- marker_mid_menu_connection.unblock();
+ mid_marker_connection.block();
+ mid_marker_combobox->set_active_history();
+ mid_marker_connection.unblock();
break;
case SP_MARKER_LOC_END:
- marker_end_menu_connection.block();
- pos = ink_marker_menu_get_pos(marker_end_menu->get_menu(), NULL);
- m = new Gtk::Menu();
- m->show();
- ink_marker_menu_create_menu(m, "marker-end", document, sandbox);
- marker_end_menu->remove_menu();
- marker_end_menu->set_menu(*m);
- marker_end_menu->set_history(pos);
- marker_end_menu_connection.unblock();
+ end_marker_connection.block();
+ end_marker_combobox->set_active_history();
+ end_marker_connection.unblock();
break;
default:
g_assert_not_reached();
@@ -675,7 +318,7 @@ Gtk::Container *sp_stroke_style_line_widget_new(void)
// TODO: when this is gtkmmified, use an Inkscape::UI::Widget::ScalarUnit instead of the separate
// spinbutton and unit selector for stroke width. In sp_stroke_style_line_update, use
-// setHundredPercent to remember the aeraged width corresponding to 100%. Then the
+// setHundredPercent to remember the averaged width corresponding to 100%. Then the
// stroke_width_set_unit will be removed (because ScalarUnit takes care of conversions itself), and
// with it, the two remaining calls of stroke_average_width, allowing us to get rid of that
// function in desktop-style.
@@ -822,48 +465,40 @@ Gtk::Container *sp_stroke_style_line_widget_new(void)
i++;
/* Drop down marker selectors*/
- // TODO: this code can be shortened by iterating over the possible menus!
-
- // doing this here once, instead of for each preview, to speed things up
- SPDocument *sandbox = ink_markers_preview_doc ();
-
// TRANSLATORS: Path markers are an SVG feature that allows you to attach arbitrary shapes
// (arrowheads, bullets, faces, whatever) to the start, end, or middle nodes of a path.
- //spw_label(t, _("_Start Markers:"), 0, i);
- marker_start_menu = ink_marker_menu(spw ,"marker-start", sandbox);
- spw_label(t, _("_Start Markers:"), 0, i, marker_start_menu);
- marker_start_menu->set_tooltip_text(_("Start Markers are drawn on the first node of a path or shape"));
- marker_start_menu_connection = marker_start_menu->signal_changed().connect(
- sigc::bind<Gtk::OptionMenu *, Gtk::Container *, SPMarkerLoc>(
- sigc::ptr_fun(&sp_marker_select), marker_start_menu, spw, SP_MARKER_LOC_START));
- marker_start_menu->show();
- t->attach(*marker_start_menu, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
- spw->set_data("start_mark_menu", marker_start_menu);
+ start_marker_combobox = manage(new MarkerComboBox("marker-start"));
+ spw_label(t, _("_Start Markers:"), 0, i, start_marker_combobox);
+ start_marker_combobox->set_tooltip_text(_("Start Markers are drawn on the first node of a path or shape"));
+ start_marker_connection = start_marker_combobox->signal_changed().connect(
+ sigc::bind<MarkerComboBox *, Gtk::Container *, SPMarkerLoc>(
+ sigc::ptr_fun(&sp_marker_select), start_marker_combobox, spw, SP_MARKER_LOC_START));
+ start_marker_combobox->show();
+ t->attach(*start_marker_combobox, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
+ spw->set_data("start_marker_combobox", start_marker_combobox);
i++;
- //spw_label(t, _("_Mid Markers:"), 0, i);
- marker_mid_menu = ink_marker_menu(spw ,"marker-mid", sandbox);
- spw_label(t, _("_Mid Markers:"), 0, i, marker_mid_menu);
- marker_mid_menu->set_tooltip_text(_("Mid Markers are drawn on every node of a path or shape except the first and last nodes"));
- marker_mid_menu_connection = marker_mid_menu->signal_changed().connect(
- sigc::bind<Gtk::OptionMenu *, Gtk::Container *, SPMarkerLoc>(
- sigc::ptr_fun(&sp_marker_select), marker_mid_menu,spw, SP_MARKER_LOC_MID));
- marker_mid_menu->show();
- t->attach(*marker_mid_menu, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
- spw->set_data("mid_mark_menu", marker_mid_menu);
+ mid_marker_combobox = manage(new MarkerComboBox("marker-mid"));
+ spw_label(t, _("_Mid Markers:"), 0, i, mid_marker_combobox);
+ mid_marker_combobox->set_tooltip_text(_("Mid Markers are drawn on every node of a path or shape except the first and last nodes"));
+ mid_marker_connection = mid_marker_combobox->signal_changed().connect(
+ sigc::bind<MarkerComboBox *, Gtk::Container *, SPMarkerLoc>(
+ sigc::ptr_fun(&sp_marker_select), mid_marker_combobox, spw, SP_MARKER_LOC_MID));
+ mid_marker_combobox->show();
+ t->attach(*mid_marker_combobox, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
+ spw->set_data("mid_marker_combobox", mid_marker_combobox);
i++;
- //spw_label(t, _("_End Markers:"), 0, i);
- marker_end_menu = ink_marker_menu(spw ,"marker-end", sandbox);
- spw_label(t, _("_End Markers:"), 0, i, marker_end_menu);
- marker_end_menu->set_tooltip_text(_("End Markers are drawn on the last node of a path or shape"));
- marker_end_menu_connection = marker_end_menu->signal_changed().connect(
- sigc::bind<Gtk::OptionMenu *, Gtk::Container *, SPMarkerLoc>(
- sigc::ptr_fun(&sp_marker_select), marker_end_menu, spw, SP_MARKER_LOC_END));
- marker_end_menu->show();
- t->attach(*marker_end_menu, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
- spw->set_data("end_mark_menu", marker_end_menu);
+ end_marker_combobox = manage(new MarkerComboBox("marker-end"));
+ spw_label(t, _("_End Markers:"), 0, i, end_marker_combobox);
+ end_marker_combobox->set_tooltip_text(_("End Markers are drawn on the last node of a path or shape"));
+ end_marker_connection = end_marker_combobox->signal_changed().connect(
+ sigc::bind<MarkerComboBox *, Gtk::Container *, SPMarkerLoc>(
+ sigc::ptr_fun(&sp_marker_select), end_marker_combobox, spw, SP_MARKER_LOC_END));
+ end_marker_combobox->show();
+ t->attach(*end_marker_combobox, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
+ spw->set_data("end_marker_combobox", end_marker_combobox);
i++;
// FIXME: we cheat and still use gtk+ signals
@@ -1090,7 +725,7 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel)
SPStyle * const style = object->style;
/* Markers */
- sp_stroke_style_update_marker_menus(spw, objects); // FIXME: make this desktop query too
+ sp_stroke_style_update_marker_combo(spw, objects); // FIXME: make this desktop query too
/* Dash */
sp_dash_selector_set_from_style(dsel, style); // FIXME: make this desktop query too
@@ -1270,6 +905,7 @@ static void sp_stroke_style_any_toggled(Gtk::ToggleButton *tb, Gtk::Container *s
return;
}
+
if (tb->get_active()) {
gchar const *join
@@ -1346,50 +982,18 @@ sp_stroke_style_set_cap_buttons(Gtk::Container *spw, Gtk::ToggleButton *active)
tb->set_active(active == tb);
}
-/**
- * Sets the current marker in the marker menu.
- */
-static void
-ink_marker_menu_set_current(SPObject *marker, Gtk::OptionMenu *mnu)
-{
- mnu->set_data("update", GINT_TO_POINTER(TRUE));
-
- Gtk::Menu *m = mnu->get_menu();
- if (marker != NULL) {
- bool mark_is_stock = false;
- if (marker->getRepr()->attribute("inkscape:stockid")) {
- mark_is_stock = true;
- }
-
- gchar *markname = 0;
- if (mark_is_stock) {
- markname = g_strdup(marker->getRepr()->attribute("inkscape:stockid"));
- } else {
- markname = g_strdup(marker->getRepr()->attribute("id"));
- }
-
- int markpos = ink_marker_menu_get_pos(m, markname);
- mnu->set_history(markpos);
-
- g_free (markname);
- }
- else {
- mnu->set_history(0);
- }
- mnu->set_data("update", GINT_TO_POINTER(FALSE));
-}
/**
- * Updates the marker menus to highlight the appropriate marker and scroll to
+ * Updates the marker combobox to highlight the appropriate marker and scroll to
* that marker.
*/
static void
-sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects)
+sp_stroke_style_update_marker_combo(Gtk::Container *spw, GSList const *objects)
{
struct { char const *key; int loc; } const keyloc[] = {
- { "start_mark_menu", SP_MARKER_LOC_START },
- { "mid_mark_menu", SP_MARKER_LOC_MID },
- { "end_mark_menu", SP_MARKER_LOC_END }
+ { "start_marker_combobox", SP_MARKER_LOC_START },
+ { "mid_marker_combobox", SP_MARKER_LOC_MID },
+ { "end_marker_combobox", SP_MARKER_LOC_END }
};
bool all_texts = true;
@@ -1400,9 +1004,9 @@ sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects)
}
for (unsigned i = 0; i < G_N_ELEMENTS(keyloc); ++i) {
- Gtk::OptionMenu *mnu = static_cast<Gtk::OptionMenu *>(spw->get_data(keyloc[i].key));
- // Per SVG spec, text objects cannot have markers; disable menus if only texts are selected
- mnu->set_sensitive(!all_texts);
+ MarkerComboBox *combo = static_cast<MarkerComboBox *>(spw->get_data(keyloc[i].key));
+ // Per SVG spec, text objects cannot have markers; disable combobox if only texts are selected
+ combo->set_sensitive(!all_texts);
}
// We show markers of the first object in the list only
@@ -1412,11 +1016,11 @@ sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects)
for (unsigned i = 0; i < G_N_ELEMENTS(keyloc); ++i) {
// For all three marker types,
- // find the corresponding menu
- Gtk::OptionMenu *mnu = static_cast<Gtk::OptionMenu *>(spw->get_data(keyloc[i].key));
+ // find the corresponding combobox item
+ MarkerComboBox *combo = static_cast<MarkerComboBox *>(spw->get_data(keyloc[i].key));
// Quit if we're in update state
- if (mnu->get_data("update")) {
+ if (combo->update()) {
return;
}
@@ -1425,13 +1029,14 @@ sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects)
// Extract the name of the marker that the object uses
SPObject *marker = ink_extract_marker_name(object->style->marker[keyloc[i].loc].value, object->document);
- // Scroll the menu to that marker
- ink_marker_menu_set_current(marker, mnu);
+ // Scroll the combobox to that marker
+ combo->set_current(marker);
} else {
- mnu->set_history(0);
+ combo->set_current(NULL);
}
}
+
}