summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 3a27629)
raw | patch | inline | side by side (parent: 3a27629)
author | mental <mental@users.sourceforge.net> | |
Sun, 24 Jun 2007 18:42:18 +0000 (18:42 +0000) | ||
committer | mental <mental@users.sourceforge.net> | |
Sun, 24 Jun 2007 18:42:18 +0000 (18:42 +0000) |
24 files changed:
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index 95abdfa5bc6c04d4316b2e288d5d9a44399697c7..5685dc4d6502208c853848a1e6dbff5d5b1c525f 100644 (file)
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
#include "style.h"
#include "prefs-utils.h"
#include "sp-use.h"
+#include "sp-feblend.h"
#include "sp-filter.h"
#include "sp-gaussian-blur.h"
#include "sp-flowtext.h"
}
}
+int
+objects_query_blend (GSList *objects, SPStyle *style_res)
+{
+ const int empty_prev = -2;
+ const int complex_filter = 5;
+ int blend = 0;
+ float blend_prev = empty_prev;
+ bool same_blend = true;
+ guint items = 0;
+
+ for (GSList const *i = objects; i != NULL; i = i->next) {
+ SPObject *obj = SP_OBJECT (i->data);
+ SPStyle *style = SP_OBJECT_STYLE (obj);
+ if(!style || !SP_IS_ITEM(obj)) continue;
+
+ items++;
+
+ //if object has a filter
+ if (style->filter.set && style->filter.filter) {
+ int blurcount = 0;
+ int blendcount = 0;
+
+ // determine whether filter is simple (blend and/or blur) or complex
+ for(SPObject *primitive_obj = style->filter.filter->children;
+ primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj);
+ primitive_obj = primitive_obj->next) {
+ SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj);
+ if(SP_IS_FEBLEND(primitive))
+ ++blendcount;
+ else if(SP_IS_GAUSSIANBLUR(primitive))
+ ++blurcount;
+ else {
+ blurcount = complex_filter;
+ break;
+ }
+ }
+
+ // simple filter
+ if(blurcount == 1 || blendcount == 1) {
+ for(SPObject *primitive_obj = style->filter.filter->children;
+ primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj);
+ primitive_obj = primitive_obj->next) {
+ if(SP_IS_FEBLEND(primitive_obj)) {
+ SPFeBlend *spblend = SP_FEBLEND(primitive_obj);
+ blend = spblend->blend_mode;
+ }
+ }
+ }
+ else {
+ blend = complex_filter;
+ }
+ }
+ // defaults to blend mode = "normal"
+ else {
+ blend = 0;
+ }
+
+ if(blend_prev != empty_prev && blend_prev != blend)
+ same_blend = false;
+ blend_prev = blend;
+ }
+
+ if (items > 0) {
+ style_res->filter_blend_mode.value = blend;
+ }
+
+ if (items == 0) {
+ return QUERY_STYLE_NOTHING;
+ } else if (items == 1) {
+ return QUERY_STYLE_SINGLE;
+ } else {
+ if(same_blend)
+ return QUERY_STYLE_MULTIPLE_SAME;
+ else
+ return QUERY_STYLE_MULTIPLE_DIFFERENT;
+ }
+}
+
/**
* Write to style_res the average blurring of a list of objects.
*/
} else if (property == QUERY_STYLE_PROPERTY_FONTNUMBERS) {
return objects_query_fontnumbers (list, style);
+ } else if (property == QUERY_STYLE_PROPERTY_BLEND) {
+ return objects_query_blend (list, style);
} else if (property == QUERY_STYLE_PROPERTY_BLUR) {
return objects_query_blur (list, style);
}
diff --git a/src/desktop-style.h b/src/desktop-style.h
index 112fe1372a4ab94ed8bd50cf1dd935629dd5b911..3f201aa285ce03d4cda9ff9c64295065fe1047d8 100644 (file)
--- a/src/desktop-style.h
+++ b/src/desktop-style.h
QUERY_STYLE_PROPERTY_FONTSTYLE, // font style
QUERY_STYLE_PROPERTY_FONTNUMBERS, // size, spacings
QUERY_STYLE_PROPERTY_MASTEROPACITY, // opacity
- QUERY_STYLE_PROPERTY_BLUR // blur
+ QUERY_STYLE_PROPERTY_BLEND, // blend
+ QUERY_STYLE_PROPERTY_BLUR // blur
};
void sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines);
index fbc9ab83fc432292aa2d5f39e87001ac64ef9e3c..b4358e5e54960e60a012edd5870728bceb1590da 100644 (file)
#include "helper/window.h"
#include "widgets/sp-widget.h"
#include "widgets/icon.h"
+#include "desktop.h"
#include "macros.h"
#include "inkscape.h"
#include "fill-style.h"
#include "document.h"
#include "document-private.h"
#include <selection.h>
+#include <ui/dialog/dialog-manager.h>
+#include "ui/widget/filter-effect-chooser.h"
#include "xml/repr.h"
#include "display/sp-canvas.h"
static void sp_fillstroke_selection_modified ( Inkscape::Application *inkscape, Inkscape::Selection *selection, guint flags, GtkObject *base );
static void sp_fillstroke_selection_changed ( Inkscape::Application *inkscape, Inkscape::Selection *selection, GtkObject *base );
static void sp_fillstroke_opacity_changed (GtkAdjustment *a, SPWidget *dlg);
-static void sp_fillstroke_blur_changed (GtkAdjustment *a, SPWidget *dlg);
+
+using Inkscape::UI::Widget::SimpleFilterModifier;
+static void sp_fillstroke_blend_blur_changed (SimpleFilterModifier *);
static void
sp_object_properties_dialog_destroy (GtkObject *object, gpointer data)
}
- /* Blur */
+ /* Filter Effects (gtkmm) */
+ GtkWidget *al_fe = gtk_alignment_new(1, 1, 1, 1);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(al_fe), 0, 0, 4, 0);
+ SimpleFilterModifier *cb_fe = Gtk::manage(new SimpleFilterModifier);
+ g_object_set_data(G_OBJECT(dlg), "filter_modifier", cb_fe);
+ cb_fe->signal_selection_changed().connect(
+ sigc::bind(sigc::ptr_fun(sp_fillstroke_blend_blur_changed), cb_fe));
+ cb_fe->signal_blend_blur_changed().connect(
+ sigc::bind(sigc::ptr_fun(sp_fillstroke_blend_blur_changed), cb_fe));
+ gtk_container_add(GTK_CONTAINER(al_fe), GTK_WIDGET(cb_fe->gobj()));
+
GtkWidget *b_vb = gtk_vbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vb), b_vb, FALSE, FALSE, 2);
gtk_object_set_data (GTK_OBJECT (dlg), "blur", b_vb);
-
- GtkWidget *blur_l_hb = gtk_hbox_new (FALSE, 4);
- GtkWidget *blur_l = gtk_label_new_with_mnemonic (_("_Blur, %"));
- gtk_misc_set_alignment (GTK_MISC (blur_l), 0.0, 1.0);
- gtk_box_pack_start (GTK_BOX (blur_l_hb), blur_l, FALSE, FALSE, 4);
- gtk_box_pack_start (GTK_BOX (b_vb), blur_l_hb, FALSE, FALSE, 0);
-
- GtkWidget *blur_hb = gtk_hbox_new (FALSE, 4);
- gtk_box_pack_start (GTK_BOX (b_vb), blur_hb, FALSE, FALSE, 0);
-
- GtkObject *blur_a = gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 0.0);
- gtk_object_set_data(GTK_OBJECT(dlg), "blur_adjustment", blur_a);
-
- GtkWidget *blur_s = gtk_hscale_new (GTK_ADJUSTMENT (blur_a));
- gtk_scale_set_draw_value (GTK_SCALE (blur_s), FALSE);
- gtk_box_pack_start (GTK_BOX (blur_hb), blur_s, TRUE, TRUE, 4);
- gtk_label_set_mnemonic_widget (GTK_LABEL(blur_l), blur_s);
-
- GtkWidget *blur_sb = gtk_spin_button_new (GTK_ADJUSTMENT (blur_a), 0.01, 1);
- gtk_box_pack_start (GTK_BOX (blur_hb), blur_sb, FALSE, FALSE, 0);
-
- gtk_signal_connect ( blur_a, "value_changed",
- GTK_SIGNAL_FUNC (sp_fillstroke_blur_changed),
- dlg );
-
+ gtk_box_pack_start (GTK_BOX (b_vb), al_fe, FALSE, FALSE, 0);
gtk_widget_show_all (b_vb);
break;
}
+ SimpleFilterModifier *mod = (SimpleFilterModifier*)g_object_get_data(G_OBJECT(dlg), "filter_modifier");
- GtkWidget *b = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (dlg), "blur"));
- GtkAdjustment *bluradjustment = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(dlg), "blur_adjustment"));
-
- //query now for current average blurring of selection
- int blur_result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_BLUR);
- switch (blur_result) {
- case QUERY_STYLE_NOTHING: //no blurring
- gtk_widget_set_sensitive (b, FALSE);
+ //query now for current filter mode and average blurring of selection
+ const int blend_result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_BLEND);
+ switch(blend_result) {
+ case QUERY_STYLE_NOTHING:
+ mod->set_sensitive(false);
break;
case QUERY_STYLE_SINGLE:
- case QUERY_STYLE_MULTIPLE_AVERAGED:
- case QUERY_STYLE_MULTIPLE_SAME:
- NR::Maybe<NR::Rect> bbox = sp_desktop_selection(SP_ACTIVE_DESKTOP)->bounds();
- if (bbox) {
- double perimeter = bbox->extent(NR::X) + bbox->extent(NR::Y);
- gtk_widget_set_sensitive (b, TRUE);
- //update blur widget value
- float radius = query->filter_gaussianBlur_deviation.value;
- float percent = radius * 400 / perimeter; // so that for a square, 100% == half side
- gtk_adjustment_set_value(bluradjustment, percent);
- }
+ case QUERY_STYLE_MULTIPLE_SAME:
+ mod->set_blend_mode(query->filter_blend_mode.value);
+ mod->set_sensitive(true);
+ break;
+ case QUERY_STYLE_MULTIPLE_DIFFERENT:
+ // TODO: set text
+ mod->set_sensitive(false);
break;
}
-
+
+ if(blend_result == QUERY_STYLE_SINGLE || blend_result == QUERY_STYLE_MULTIPLE_SAME) {
+ int blur_result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_BLUR);
+ switch (blur_result) {
+ case QUERY_STYLE_NOTHING: //no blurring
+ mod->set_blur_sensitive(false);
+ break;
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ NR::Maybe<NR::Rect> bbox = sp_desktop_selection(SP_ACTIVE_DESKTOP)->bounds();
+ if (bbox) {
+ double perimeter = bbox->extent(NR::X) + bbox->extent(NR::Y);
+ mod->set_blur_sensitive(true);
+ //update blur widget value
+ float radius = query->filter_gaussianBlur_deviation.value;
+ float percent = radius * 400 / perimeter; // so that for a square, 100% == half side
+ mod->set_blur_value(percent);
+ }
+ break;
+ }
+ }
g_free (query);
gtk_object_set_data (GTK_OBJECT (dlg), "blocked", GUINT_TO_POINTER (FALSE));
gtk_object_set_data (GTK_OBJECT (dlg), "blocked", GUINT_TO_POINTER (FALSE));
}
-
static void
-sp_fillstroke_blur_changed (GtkAdjustment *a, SPWidget *base)
+sp_fillstroke_blend_blur_changed (SimpleFilterModifier *m)
{
//if dialog is locked, return
if (gtk_object_get_data (GTK_OBJECT (dlg), "blocked"))
SPDocument *document = sp_desktop_document (desktop);
double perimeter = bbox->extent(NR::X) + bbox->extent(NR::Y);
- double radius = a->value * perimeter / 400;
+ const Glib::ustring blendmode = m->get_blend_mode();
+ double radius = m->get_blur_value() * perimeter / 400;
+
+ SPFilter *filter = m->get_selected_filter();
+ const bool remfilter = (blendmode == "normal" && radius == 0) || (blendmode == "filter" && !filter);
- //apply created filter to every selected item
- for (GSList const *i = items; i != NULL; i = i->next) {
-
- SPItem * item = SP_ITEM(i->data);
- SPStyle *style = SP_OBJECT_STYLE(item);
- g_assert(style != NULL);
-
- if (radius == 0.0) {
- remove_filter_gaussian_blur(item);
- } else {
- SPFilter *constructed = modify_filter_gaussian_blur_from_item(document, item, radius);
- sp_style_set_property_url (SP_OBJECT(item), "filter", SP_OBJECT(constructed), false);
+ if(blendmode != "filter" || filter) {
+ //apply created filter to every selected item
+ for (GSList const *i = items; i != NULL; i = i->next) {
+ SPItem * item = SP_ITEM(i->data);
+ SPStyle *style = SP_OBJECT_STYLE(item);
+ g_assert(style != NULL);
+
+ if(remfilter) {
+ remove_filter (item, false);
+ }
+ else {
+ if(blendmode != "filter")
+ filter = new_filter_simple_from_item(document, item, blendmode.c_str(), radius);
+ sp_style_set_property_url (SP_OBJECT(item), "filter", SP_OBJECT(filter), false);
+ }
+
+ //request update
+ SP_OBJECT(item)->requestDisplayUpdate(( SP_OBJECT_MODIFIED_FLAG |
+ SP_OBJECT_STYLE_MODIFIED_FLAG ));
}
- //request update
- SP_OBJECT(item)->requestDisplayUpdate(( SP_OBJECT_MODIFIED_FLAG |
- SP_OBJECT_STYLE_MODIFIED_FLAG ));
}
sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "fillstroke:blur", SP_VERB_DIALOG_FILL_STROKE, _("Change blur"));
index 4787e336e7d56fa21b742bb84ebc334959d816ee..ffed2cd033e148177e9be1261e509b438d020bdb 100644 (file)
BLEND_MULTIPLY,
BLEND_SCREEN,
BLEND_DARKEN,
- BLEND_LIGHTEN
+ BLEND_LIGHTEN,
+ BLEND_ENDMODE
};
class FilterBlend : public FilterPrimitive {
index fb4064a7e50e6568800ab8cf1ccf845a7b1856f0..336ac357619807cd86a6fe39d13ff22a5f0dcc36 100644 (file)
--- a/src/filter-chemistry.cpp
+++ b/src/filter-chemistry.cpp
#include "document-private.h"
#include "desktop-style.h"
+#include "sp-feblend.h"
#include "sp-filter.h"
#include "sp-gaussian-blur.h"
#include "svg/css-ostringstream.h"
}
}
+SPFilter *new_filter(SPDocument *document)
+{
+ g_return_val_if_fail(document != NULL, NULL);
+
+ SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);
+
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
+
+ // create a new filter
+ Inkscape::XML::Node *repr;
+ repr = xml_doc->createElement("svg:filter");
+
+ // Append the new filter node to defs
+ SP_OBJECT_REPR(defs)->appendChild(repr);
+ Inkscape::GC::release(repr);
+
+ // get corresponding object
+ SPFilter *f = SP_FILTER( document->getObjectByRepr(repr) );
+
+
+ g_assert(f != NULL);
+ g_assert(SP_IS_FILTER(f));
+
+ return f;
+}
+
+SPFilterPrimitive *
+filter_add_primitive(SPFilter *filter, const gchar *type)
+{
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(filter->document);
+
+ //create filter primitive node
+ Inkscape::XML::Node *repr;
+ repr = xml_doc->createElement(type);
+ repr->setAttribute("inkscape:collect", "always");
+
+ //set primitive as child of filter node
+ filter->repr->appendChild(repr);
+ Inkscape::GC::release(repr);
+
+ // get corresponding object
+ SPFilterPrimitive *prim = SP_FILTER_PRIMITIVE( filter->document->getObjectByRepr(repr) );
+
+ g_assert(prim != NULL);
+ g_assert(SP_IS_FILTER_PRIMITIVE(prim));
+
+ return prim;
+}
+
/**
* Creates a filter with blur primitive of specified radius for an item with the given matrix expansion, width and height
*/
@@ -134,11 +184,85 @@ new_filter_gaussian_blur (SPDocument *document, gdouble radius, double expansion
return f;
}
+
+/**
+ * Creates a simple filter with a blend primitive and a blur primitive of specified radius for
+ * an item with the given matrix expansion, width and height
+ */
+SPFilter *
+new_filter_blend_gaussian_blur (SPDocument *document, const char *blendmode, gdouble radius, double expansion,
+ double expansionX, double expansionY, double width, double height)
+{
+ g_return_val_if_fail(document != NULL, NULL);
+
+ SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);
+
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
+
+ // create a new filter
+ Inkscape::XML::Node *repr;
+ repr = xml_doc->createElement("svg:filter");
+ repr->setAttribute("inkscape:collect", "always");
+
+ // Append the new filter node to defs
+ SP_OBJECT_REPR(defs)->appendChild(repr);
+ Inkscape::GC::release(repr);
+
+ // get corresponding object
+ SPFilter *f = SP_FILTER( document->getObjectByRepr(repr) );
+
+ // Blend primitive
+ if(strcmp(blendmode, "normal")) {
+ Inkscape::XML::Node *b_repr;
+ b_repr = xml_doc->createElement("svg:feBlend");
+ b_repr->setAttribute("inkscape::collect", "always");
+ b_repr->setAttribute("mode", blendmode);
+
+ // set feBlend as child of filter node
+ repr->appendChild(b_repr);
+ Inkscape::GC::release(b_repr);
+
+ SPFeBlend *b = SP_FEBLEND(document->getObjectByRepr(b_repr));
+ g_assert(b != NULL);
+ g_assert(SP_IS_FEBLEND(b));
+ }
+ // Gaussian blur primitive
+ if(radius != 0) {
+ set_filter_area(repr, radius, expansion, expansionX, expansionY, width, height);
+
+ //create feGaussianBlur node
+ Inkscape::XML::Node *b_repr;
+ b_repr = xml_doc->createElement("svg:feGaussianBlur");
+ b_repr->setAttribute("inkscape:collect", "always");
+
+ double stdDeviation = radius;
+ if (expansion != 0)
+ stdDeviation /= expansion;
+
+ //set stdDeviation attribute
+ sp_repr_set_svg_double(b_repr, "stdDeviation", stdDeviation);
+
+ //set feGaussianBlur as child of filter node
+ repr->appendChild(b_repr);
+ Inkscape::GC::release(b_repr);
+
+ SPGaussianBlur *b = SP_GAUSSIANBLUR( document->getObjectByRepr(b_repr) );
+ g_assert(b != NULL);
+ g_assert(SP_IS_GAUSSIANBLUR(b));
+ }
+
+ g_assert(f != NULL);
+ g_assert(SP_IS_FILTER(f));
+
+ return f;
+}
+
/**
- * Creates a filter with blur primitive of specified radius for the given item
+ * Creates a simple filter for the given item with blend and blur primitives, using the
+ * specified mode and radius, respectively
*/
SPFilter *
-new_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble radius)
+new_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mode, gdouble radius)
{
NR::Maybe<NR::Rect> const r = sp_item_bbox_desktop(item);
NR::Matrix i2d = sp_item_i2d_affine (item);
- return (new_filter_gaussian_blur (document, radius, i2d.expansion(), i2d.expansionX(), i2d.expansionY(), width, height));
+ return (new_filter_blend_gaussian_blur (document, mode, radius, i2d.expansion(), i2d.expansionX(), i2d.expansionY(), width, height));
}
/**
gdouble radius)
{
if (!item->style || !item->style->filter.set) {
- return new_filter_gaussian_blur_from_item(document, item, radius);
+ //return new_filter_gaussian_blur_from_item(document, item, radius);
}
SPFilter *filter = SP_FILTER(item->style->filter.filter);
diff --git a/src/filter-chemistry.h b/src/filter-chemistry.h
index b727536adaf645a81f34e4de513d9a619c748fd2..125c527b290e9e6d1c37ab7113a1ea53c04dc159 100644 (file)
--- a/src/filter-chemistry.h
+++ b/src/filter-chemistry.h
#include "forward.h"
#include "sp-filter.h"
+SPFilterPrimitive *filter_add_primitive(SPFilter *filter, const gchar *type);
+SPFilter *new_filter (SPDocument *document);
SPFilter *new_filter_gaussian_blur (SPDocument *document, gdouble stdDeviation, double expansion, double expansionX, double expansionY, double width, double height);
-SPFilter *new_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble stdDeviation);
+SPFilter *new_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mode, gdouble stdDeviation);
SPFilter *modify_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble stdDeviation);
void remove_filter (SPObject *item, bool recursive);
void remove_filter_gaussian_blur (SPObject *item);
diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h
index 722d8a11e3ddb765f513e28bb42d6559fe867ea4..f560deeb0803bd2dd566cfdf07a862d5f599d870 100644 (file)
--- a/src/menus-skeleton.h
+++ b/src/menus-skeleton.h
" <verb verb-id=\"EffectLast\" />\n"
" <verb verb-id=\"EffectLastPref\" />\n"
" <separator/>\n"
+" <verb verb-id=\"DialogFilterEffects\" />\n"
" <effects-list/>\n"
" </submenu>\n"
#ifdef WITH_INKBOARD
diff --git a/src/style.h b/src/style.h
index 4538626beb22f62da20be513c8d007c5cd630847..544bde55778251ae3c9bf978c7cbd67ae3b5757a 100644 (file)
--- a/src/style.h
+++ b/src/style.h
/** Filter effect */
SPIFilter filter;
+ SPIEnum filter_blend_mode;
+
/** normally not used, but duplicates the Gaussian blur deviation (if any) from the attached
filter when the style is used for querying */
SPILength filter_gaussianBlur_deviation;
index 2b04d3e45c7093e5389e7e52fde230b4b2ce9a1d..c1cb65d295e4020a7ed582ea716d42dc63957445 100644 (file)
ui/dialog/filedialog.h \
ui/dialog/fill-and-stroke.cpp \
ui/dialog/fill-and-stroke.h \
+ ui/dialog/filter-effects-dialog.h \
+ ui/dialog/filter-effects-dialog.cpp \
ui/dialog/find.cpp \
ui/dialog/find.h \
ui/dialog/inkscape-preferences.cpp \
index d685f2e59bab7bd9ad65c9699870feab692db62a..6b02776102238e9d2c25c2a2bdfc03b26c11df4d 100644 (file)
#include "ui/dialog/export.h"
#include "ui/dialog/extension-editor.h"
#include "ui/dialog/fill-and-stroke.h"
+#include "ui/dialog/filter-effects-dialog.h"
#include "ui/dialog/find.h"
#include "ui/dialog/inkscape-preferences.h"
#include "ui/dialog/layer-editor.h"
registerFactory("Export", &create<Export>);
registerFactory("ExtensionEditor", &create<ExtensionEditor>);
registerFactory("FillAndStroke", &create<FillAndStroke>);
+ registerFactory("FilterEffectsDialog", &create<FilterEffectsDialog>);
registerFactory("Find", &create<Find>);
registerFactory("InkscapePreferences", &create<InkscapePreferences>);
registerFactory("LayerEditor", &create<LayerEditor>);
index 6206c4345139d74dc7c8bb4188cc8fb0de708f19..3559e3685433a74f986fc9dd628a2fa0f907efcb 100644 (file)
if (radius == 0.0) {
remove_filter (item, false);
} else {
- SPFilter *constructed = new_filter_gaussian_blur_from_item(document, item, radius);
- sp_style_set_property_url (SP_OBJECT(item), "filter", SP_OBJECT(constructed), false);
+ //SPFilter *constructed = new_filter_gaussian_blur_from_item(document, item, radius);
+ //sp_style_set_property_url (SP_OBJECT(item), "filter", SP_OBJECT(constructed), false);
}
//request update
SP_OBJECT(item)->requestDisplayUpdate(( SP_OBJECT_MODIFIED_FLAG |
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
--- /dev/null
@@ -0,0 +1,636 @@
+/**
+ * \brief Filter Effects dialog
+ *
+ * Authors:
+ * Nicholas Bishop <nicholasbishop@gmail.org>
+ *
+ * Copyright (C) 2007 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtktreeview.h>
+#include <gtkmm/cellrenderertext.h>
+#include <gtkmm/paned.h>
+#include <gtkmm/scale.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/stock.h>
+#include <glibmm/i18n.h>
+
+#include "application/application.h"
+#include "application/editor.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "dialog-manager.h"
+#include "document.h"
+#include "filter-chemistry.h"
+#include "filter-effects-dialog.h"
+#include "inkscape.h"
+#include "sp-filter-primitive.h"
+#include "sp-gaussian-blur.h"
+#include "sp-feoffset.h"
+#include "verbs.h"
+#include "xml/node.h"
+#include "xml/repr.h"
+#include <sstream>
+
+#include <iostream>
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+Glib::RefPtr<Gtk::Menu> create_popup_menu(Gtk::Widget& parent, sigc::slot<void> dup,
+ sigc::slot<void> rem)
+{
+ Glib::RefPtr<Gtk::Menu> menu(new Gtk::Menu);
+
+ menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Duplicate"), dup));
+ Gtk::MenuItem* mi = Gtk::manage(new Gtk::ImageMenuItem(Gtk::Stock::REMOVE));
+ menu->append(*mi);
+ mi->signal_activate().connect(rem);
+ mi->show();
+ menu->accelerate(parent);
+
+ return menu;
+}
+
+static void try_id_change(SPObject* ob, const Glib::ustring& text)
+{
+ // FIXME: this needs more serious error checking...
+ if(ob && !SP_ACTIVE_DOCUMENT->getObjectById(text.c_str())) {
+ SPException ex;
+ SP_EXCEPTION_INIT(&ex);
+ sp_object_setAttribute(ob, "id", text.c_str(), &ex);
+ sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILTER_EFFECTS, _("Set object ID"));
+ }
+}
+
+/*** FilterModifier ***/
+FilterEffectsDialog::FilterModifier::FilterModifier()
+ : _add(Gtk::Stock::ADD)
+{
+ Gtk::ScrolledWindow* sw = Gtk::manage(new Gtk::ScrolledWindow);
+ pack_start(*sw);
+ pack_start(_add, false, false);
+ sw->add(_list);
+
+ _list.set_model(_model);
+ _list.append_column_editable(_("_Filter"), _columns.id);
+ ((Gtk::CellRendererText*)_list.get_column(0)->get_first_cell_renderer())->
+ signal_edited().connect(sigc::mem_fun(*this, &FilterEffectsDialog::FilterModifier::filter_name_edited));
+
+ sw->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+ sw->set_shadow_type(Gtk::SHADOW_IN);
+ show_all_children();
+ _add.signal_clicked().connect(sigc::mem_fun(*this, &FilterModifier::add_filter));
+ _list.signal_button_press_event().connect_notify(
+ sigc::mem_fun(*this, &FilterModifier::filter_list_button_press));
+ _menu = create_popup_menu(*this, sigc::mem_fun(*this, &FilterModifier::duplicate_filter),
+ sigc::mem_fun(*this, &FilterModifier::remove_filter));
+
+ update_filters();
+}
+
+Glib::SignalProxy0<void> FilterEffectsDialog::FilterModifier::signal_selection_changed()
+{
+ return _list.get_selection()->signal_changed();
+}
+
+SPFilter* FilterEffectsDialog::FilterModifier::get_selected_filter()
+{
+ if(_list.get_selection()) {
+ Gtk::TreeModel::iterator i = _list.get_selection()->get_selected();
+
+ if(i)
+ return (*i)[_columns.filter];
+ }
+
+ return 0;
+}
+
+void FilterEffectsDialog::FilterModifier::select_filter(const SPFilter* filter)
+{
+ if(filter) {
+ for(Gtk::TreeModel::iterator i = _model->children().begin();
+ i != _model->children().end(); ++i) {
+ if((*i)[_columns.filter] == filter) {
+ _list.get_selection()->select(i);
+ break;
+ }
+ }
+ }
+}
+
+void FilterEffectsDialog::FilterModifier::filter_list_button_press(GdkEventButton* event)
+{
+ if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
+ const bool sensitive = get_selected_filter() != NULL;
+ _menu->items()[0].set_sensitive(sensitive);
+ _menu->items()[1].set_sensitive(sensitive);
+ _menu->popup(event->button, event->time);
+ }
+}
+
+void FilterEffectsDialog::FilterModifier::add_filter()
+{
+ SPDocument* doc = sp_desktop_document(SP_ACTIVE_DESKTOP);
+ SPFilter* filter = new_filter(doc);
+
+ update_filters();
+
+ select_filter(filter);
+
+ sp_document_done(doc, SP_VERB_DIALOG_FILTER_EFFECTS, _("Add filter"));
+}
+
+void FilterEffectsDialog::FilterModifier::remove_filter()
+{
+ SPFilter *filter = get_selected_filter();
+
+ if(filter) {
+ SPDocument* doc = filter->document;
+ sp_repr_unparent(filter->repr);
+
+ sp_document_done(doc, SP_VERB_DIALOG_FILTER_EFFECTS, _("Remove filter"));
+
+ update_filters();
+ }
+}
+
+void FilterEffectsDialog::FilterModifier::duplicate_filter()
+{
+ SPFilter *filter = get_selected_filter();
+
+ if(filter) {
+ //SPFilter *dupfilter = filter_duplicate(sp_desktop_document(SP_ACTIVE_DESKTOP), filter);
+
+ sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Duplicate filter"));
+
+ update_filters();
+ }
+}
+
+void FilterEffectsDialog::FilterModifier::filter_name_edited(const Glib::ustring& path, const Glib::ustring& text)
+{
+ Gtk::TreeModel::iterator i = _model->get_iter(path);
+
+ if(i)
+ try_id_change((SPObject*)(*i)[_columns.filter], text);
+}
+
+/*** SettingsFrame ***/
+FilterEffectsDialog::SettingsFrame::SettingsFrame()
+ : _where(0)
+{
+ set_col_spacings(12);
+ show();
+}
+
+void FilterEffectsDialog::SettingsFrame::init(Gtk::VBox& box)
+{
+ box.pack_start(*this, false, false);
+}
+
+void FilterEffectsDialog::SettingsFrame::add_setting(Gtk::Widget& w, const Glib::ustring& label)
+{
+ Gtk::Label *lbl = new Gtk::Label(label + ":", Gtk::ALIGN_LEFT);
+
+ attach(*Gtk::manage(lbl), 0, 1, _where, _where + 1, Gtk::FILL, Gtk::FILL);
+ attach(w, 1, 2, _where, _where + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+ lbl->show();
+ w.show();
+
+ ++_where;
+}
+
+/*** FilterEffectsDialog ***/
+
+FilterEffectsDialog::FilterEffectsDialog()
+ : Dialog ("dialogs.filtereffects", SP_VERB_DIALOG_FILTER_EFFECTS),
+ _add_primitive_type(FPConverter),
+ _add_primitive(Gtk::Stock::ADD),
+ _empty_settings("No primitive selected", Gtk::ALIGN_LEFT),
+ _blend_mode(BlendModeConverter),
+ _gaussianblur_stddeviation(1, 0, 100, 1, 0.01, 1),
+ _morphology_radius(1, 0, 100, 1, 0.01, 1),
+ _offset_dx(0, -100, 100, 1, 0.01, 1),
+ _offset_dy(0, -100, 100, 1, 0.01, 1),
+ _turbulence_basefrequency(1, 0, 100, 1, 0.01, 1),
+ _turbulence_numoctaves(1, 0, 100, 1, 0.01, 1),
+ _turbulence_seed(1, 0, 100, 1, 0.01, 1)
+{
+ // Initialize widget hierarchy
+ Gtk::HPaned* hpaned = Gtk::manage(new Gtk::HPaned);
+ Gtk::VBox* vb_prims = Gtk::manage(new Gtk::VBox);
+ Gtk::ScrolledWindow* sw_prims = Gtk::manage(new Gtk::ScrolledWindow);
+ Gtk::HBox* hb_prims = Gtk::manage(new Gtk::HBox);
+ Gtk::Frame* fr_settings = Gtk::manage(new Gtk::Frame("<b>Settings</b>"));
+ Gtk::Alignment* al_settings = Gtk::manage(new Gtk::Alignment);
+ get_vbox()->add(*hpaned);
+ hpaned->pack1(_filter_modifier);
+ hpaned->pack2(*vb_prims);
+ vb_prims->pack_start(*sw_prims);
+ vb_prims->pack_start(*hb_prims, false, false);
+ sw_prims->add(_primitive_list);
+ hb_prims->pack_end(_add_primitive, false, false);
+ hb_prims->pack_end(_add_primitive_type, false, false);
+ get_vbox()->pack_start(*fr_settings, false, false);
+ fr_settings->add(*al_settings);
+ al_settings->add(_settings);
+
+ // Primitive list
+ _primitive_model = Gtk::ListStore::create(_primitive_columns);
+ _primitive_list.set_reorderable(true);
+ _primitive_list.set_model(_primitive_model);
+ //_primitive_list.append_column_editable(_("_Primitive"), _primitive_columns.id);
+ _primitive_list.append_column("Type", _primitive_columns.type);
+ ((Gtk::CellRendererText*)_primitive_list.get_column(0)->get_first_cell_renderer())->
+ signal_edited().connect(sigc::mem_fun(*this, &FilterEffectsDialog::primitive_name_edited));
+ _filter_modifier.signal_selection_changed().connect(
+ sigc::mem_fun(*this, &FilterEffectsDialog::update_primitive_list));
+ _primitive_list.get_selection()->signal_changed().connect(
+ sigc::mem_fun(*this, &FilterEffectsDialog::update_settings_view));
+ _primitive_list.signal_button_press_event().connect_notify(
+ sigc::mem_fun(*this, &FilterEffectsDialog::primitive_list_button_press));
+ _primitive_list.signal_drag_end().connect(
+ sigc::mem_fun(*this, &FilterEffectsDialog::primitive_list_drag_end));
+
+ // Other widgets
+ sw_prims->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+ sw_prims->set_shadow_type(Gtk::SHADOW_IN);
+ al_settings->set_padding(0, 0, 12, 0);
+ fr_settings->set_shadow_type(Gtk::SHADOW_NONE);
+ ((Gtk::Label*)fr_settings->get_label_widget())->set_use_markup();
+ _add_primitive.signal_clicked().connect(sigc::mem_fun(*this, &FilterEffectsDialog::add_primitive));
+ _primitive_menu = create_popup_menu(*this, sigc::mem_fun(*this, &FilterEffectsDialog::duplicate_primitive),
+ sigc::mem_fun(*this, &FilterEffectsDialog::remove_primitive));
+
+ show_all_children();
+ init_settings_widgets();
+ update_primitive_list();
+ update_settings_view();
+}
+
+FilterEffectsDialog::~FilterEffectsDialog()
+{
+}
+
+void FilterEffectsDialog::primitive_list_button_press(GdkEventButton* event)
+{
+ if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
+ const bool sensitive = get_selected_primitive() != NULL;
+ _primitive_menu->items()[0].set_sensitive(sensitive);
+ _primitive_menu->items()[1].set_sensitive(sensitive);
+ _primitive_menu->popup(event->button, event->time);
+ }
+}
+
+// Reorder the filter primitives to match the list order
+void FilterEffectsDialog::primitive_list_drag_end(const Glib::RefPtr<Gdk::DragContext>&)
+{
+ int ndx = 0;
+ SPFilter* filter = _filter_modifier.get_selected_filter();
+
+ for(Gtk::TreeModel::iterator iter = _primitive_model->children().begin();
+ iter != _primitive_model->children().end(); ++iter) {
+ SPFilterPrimitive* prim = (*iter)[_primitive_columns.primitive];
+ if(prim)
+ ;//reorder_primitive(filter, prim->repr->position(), ndx); /* FIXME */
+ std::cout << prim->repr->position();
+ }
+
+ sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Reorder filter primitive"));
+}
+
+void FilterEffectsDialog::init_settings_widgets()
+{
+ _empty_settings.set_sensitive(false);
+ _settings.pack_start(_empty_settings);
+
+ _blend.init(_settings);
+ _blend.add_setting(_blend_mode, "Mode");
+ _blend_mode.signal_changed().connect(
+ sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_MODE));
+
+ _colormatrix.init(_settings);
+ _colormatrix.add_setting(_colormatrix_type, "Type");
+
+ _componenttransfer.init(_settings);
+
+ _composite.init(_settings);
+
+ _convolvematrix.init(_settings);
+
+ _diffuselighting.init(_settings);
+
+ _displacementmap.init(_settings);
+
+ _flood.init(_settings);
+
+ _gaussianblur.init(_settings);
+ _gaussianblur.add_setting(_gaussianblur_stddeviation, "Standard Deviation");
+ _gaussianblur_stddeviation.signal_value_changed().connect(
+ sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_STDDEVIATION));
+
+ _image.init(_settings);
+
+ _merge.init(_settings);
+
+ _morphology.init(_settings);
+ _morphology.add_setting(_morphology_operator, "Operator");
+ _morphology.add_setting(_morphology_radius, "Radius");
+
+ _offset.init(_settings);
+ _offset.add_setting(_offset_dx, "Delta X");
+ _offset_dx.signal_value_changed().connect(
+ sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_DX));
+ _offset.add_setting(_offset_dy, "Delta Y");
+ _offset_dy.signal_value_changed().connect(
+ sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_DY));
+
+ _specularlighting.init(_settings);
+
+ _tile.init(_settings);
+
+ _turbulence.init(_settings);
+ _turbulence.add_setting(_turbulence_basefrequency, "Base Frequency");
+ _turbulence.add_setting(_turbulence_numoctaves, "Octaves");
+ _turbulence.add_setting(_turbulence_seed, "Seed");
+ _turbulence.add_setting(_turbulence_stitchtiles, "Stitch Tiles");
+ _turbulence.add_setting(_turbulence_type, "Type");
+}
+
+void FilterEffectsDialog::add_primitive()
+{
+ SPFilter* filter = _filter_modifier.get_selected_filter();
+ const EnumData<NR::FilterPrimitiveType>* data = _add_primitive_type.get_active_data();
+
+ if(filter && data) {
+ SPFilterPrimitive* prim = filter_add_primitive(filter, data->name.c_str());
+
+ // Set default values
+ switch(data->id) {
+ case NR::NR_FILTER_BLEND:
+ sp_object_set(prim, SP_ATTR_MODE, BlendModeConverter.get_name(NR::BLEND_NORMAL).c_str());
+ break;
+ case NR::NR_FILTER_COLORMATRIX:
+ break;
+ case NR::NR_FILTER_COMPONENTTRANSFER:
+ break;
+ case NR::NR_FILTER_COMPOSITE:
+ break;
+ case NR::NR_FILTER_CONVOLVEMATRIX:
+ break;
+ case NR::NR_FILTER_DIFFUSELIGHTING:
+ break;
+ case NR::NR_FILTER_DISPLACEMENTMAP:
+ break;
+ case NR::NR_FILTER_FLOOD:
+ break;
+ case NR::NR_FILTER_GAUSSIANBLUR:
+ sp_object_set(prim, SP_ATTR_STDDEVIATION, "1");
+ break;
+ case NR::NR_FILTER_IMAGE:
+ break;
+ case NR::NR_FILTER_MERGE:
+ break;
+ case NR::NR_FILTER_MORPHOLOGY:
+ break;
+ case NR::NR_FILTER_OFFSET:
+ sp_object_set(prim, SP_ATTR_DX, "0");
+ sp_object_set(prim, SP_ATTR_DY, "0");
+ break;
+ case NR::NR_FILTER_SPECULARLIGHTING:
+ break;
+ case NR::NR_FILTER_TILE:
+ break;
+ case NR::NR_FILTER_TURBULENCE:
+ break;
+ default:
+ break;
+ }
+
+ update_primitive_list();
+ select_primitive(prim);
+
+ sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Add filter primitive"));
+ }
+}
+
+void FilterEffectsDialog::remove_primitive()
+{
+ Gtk::TreeModel::iterator i = _primitive_list.get_selection()->get_selected();
+
+ if(i) {
+ SPFilterPrimitive* prim = (*i)[_primitive_columns.primitive];
+
+ sp_repr_unparent(prim->repr);
+
+ sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_FILTER_EFFECTS,
+ _("Remove filter primitive"));
+
+ update_primitive_list();
+ }
+}
+
+void FilterEffectsDialog::duplicate_primitive()
+{
+ SPFilter* filter = _filter_modifier.get_selected_filter();
+ SPFilterPrimitive* origprim = get_selected_primitive();
+
+ if(filter && origprim) {
+ Inkscape::XML::Node *repr;
+ repr = SP_OBJECT_REPR(origprim)->duplicate(SP_OBJECT_REPR(origprim)->document());
+ SP_OBJECT_REPR(filter)->appendChild(repr);
+
+ sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Duplicate filter primitive"));
+
+ update_primitive_list();
+ }
+}
+
+// Edits the id of the primitive at path
+void FilterEffectsDialog::primitive_name_edited(const Glib::ustring& path, const Glib::ustring& text)
+{
+ Gtk::TreeModel::iterator i = _primitive_model->get_iter(path);
+
+ if(i)
+ try_id_change((*i)[_primitive_columns.primitive], text);
+}
+
+void FilterEffectsDialog::set_attr(const SPAttributeEnum attr)
+{
+ Gtk::TreeModel::iterator i = _primitive_list.get_selection()->get_selected();
+
+ if(i) {
+ SPFilter *filter = _filter_modifier.get_selected_filter();
+ SPFilterPrimitive* prim = (*i)[_primitive_columns.primitive];
+ std::ostringstream os;
+ Glib::ustring val;
+
+ if(attr == SP_ATTR_MODE) {
+ val = _blend_mode.get_active_data()->name;
+ }
+ else if(attr == SP_ATTR_STDDEVIATION) {
+ os << _gaussianblur_stddeviation.get_value();
+ val = os.str();
+ }
+ else if(attr == SP_ATTR_DX) {
+ os << _offset_dx.get_value();
+ val = os.str();
+ }
+ else if(attr == SP_ATTR_DY) {
+ os << _offset_dy.get_value();
+ val = os.str();
+ }
+
+ sp_object_set(prim, attr, val.c_str());
+ filter->requestModified(SP_OBJECT_MODIFIED_FLAG);
+
+ sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Set filter primitive attribute"));
+ }
+}
+
+/* Add all filter primitives in the current to the list.
+ Keeps the same selection if possible, otherwise selects the first element */
+void FilterEffectsDialog::update_primitive_list()
+{
+ SPFilter* f = _filter_modifier.get_selected_filter();
+ const SPFilterPrimitive* active_prim = get_selected_primitive();
+ bool active_found = false;
+
+ _primitive_model->clear();
+
+ if(f) {
+ _primitive_box.set_sensitive(true);
+
+ for(SPObject *prim_obj = f->children;
+ prim_obj && SP_IS_FILTER_PRIMITIVE(prim_obj);
+ prim_obj = prim_obj->next) {
+ SPFilterPrimitive *prim = SP_FILTER_PRIMITIVE(prim_obj);
+ if(prim) {
+ Gtk::TreeModel::Row row = *_primitive_model->append();
+ row[_primitive_columns.primitive] = prim;
+ row[_primitive_columns.type_id] = FPConverter.get_id_from_name(prim->repr->name());
+ row[_primitive_columns.type] = FPConverter.get_label(row[_primitive_columns.type_id]);
+ row[_primitive_columns.id] = SP_OBJECT_ID(prim);
+
+ if(prim == active_prim) {
+ _primitive_list.get_selection()->select(row);
+ active_found = true;
+ }
+ }
+ }
+
+ if(!active_found && _primitive_model->children().begin())
+ _primitive_list.get_selection()->select(_primitive_model->children().begin());
+ }
+ else {
+ _primitive_box.set_sensitive(false);
+ }
+}
+
+void FilterEffectsDialog::update_settings_view()
+{
+ SPFilterPrimitive* prim = get_selected_primitive();
+
+ // Hide all the settings except for common
+ Glib::ListHandle<Widget*> c = _settings.get_children();
+ for(Glib::ListHandle<Widget*>::iterator iter = c.begin();
+ iter != c.end(); ++iter) {
+ (*iter)->hide();
+ }
+
+ _settings.set_sensitive(false);
+ _empty_settings.show();
+
+ if(prim) {
+ const NR::FilterPrimitiveType tid = FPConverter.get_id_from_name(prim->repr->name());
+ if(tid == NR::NR_FILTER_BLEND) {
+ _blend.show();
+ const gchar* val = prim->repr->attribute("mode");
+ if(val)
+ _blend_mode.set_active(BlendModeConverter.get_id_from_name(val));
+ }
+ else if(tid == NR::NR_FILTER_COLORMATRIX)
+ _colormatrix.show();
+ else if(tid == NR::NR_FILTER_COMPONENTTRANSFER)
+ _componenttransfer.show();
+ else if(tid == NR::NR_FILTER_COMPOSITE)
+ _composite.show();
+ else if(tid == NR::NR_FILTER_CONVOLVEMATRIX)
+ _convolvematrix.show();
+ else if(tid == NR::NR_FILTER_DIFFUSELIGHTING)
+ _diffuselighting.show();
+ else if(tid == NR::NR_FILTER_DISPLACEMENTMAP)
+ _displacementmap.show();
+ else if(tid == NR::NR_FILTER_FLOOD)
+ _flood.show();
+ else if(tid == NR::NR_FILTER_GAUSSIANBLUR) {
+ _gaussianblur.show();
+ _gaussianblur_stddeviation.set_value(((SPGaussianBlur*)prim)->stdDeviation.getNumber());
+ }
+ else if(tid == NR::NR_FILTER_IMAGE)
+ _image.show();
+ else if(tid == NR::NR_FILTER_MERGE)
+ _merge.show();
+ else if(tid == NR::NR_FILTER_MORPHOLOGY)
+ _morphology.show();
+ else if(tid == NR::NR_FILTER_OFFSET) {
+ _offset.show();
+ _offset_dx.set_value(((SPFeOffset*)prim)->dx);
+ _offset_dy.set_value(((SPFeOffset*)prim)->dy);
+ }
+ else if(tid == NR::NR_FILTER_SPECULARLIGHTING)
+ _specularlighting.show();
+ else if(tid == NR::NR_FILTER_TILE)
+ _tile.show();
+ else if(tid == NR::NR_FILTER_TURBULENCE)
+ _turbulence.show();
+
+ _settings.set_sensitive(true);
+ _empty_settings.hide();
+ }
+}
+
+SPFilterPrimitive* FilterEffectsDialog::get_selected_primitive()
+{
+ if(_filter_modifier.get_selected_filter()) {
+ Gtk::TreeModel::iterator i = _primitive_list.get_selection()->get_selected();
+ if(i)
+ return (*i)[_primitive_columns.primitive];
+ }
+
+ return 0;
+}
+
+void FilterEffectsDialog::select_primitive(SPFilterPrimitive* prim)
+{
+ for(Gtk::TreeIter i = _primitive_model->children().begin();
+ i != _primitive_model->children().end(); ++i) {
+ if((*i)[_primitive_columns.primitive] == prim)
+ _primitive_list.get_selection()->select(i);
+ }
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ 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:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h
--- /dev/null
@@ -0,0 +1,193 @@
+/**
+ * \brief Filter Effects dialog
+ *
+ * Authors:
+ * Nicholas Bishop <nicholasbishop@gmail.com>
+ *
+ * Copyright (C) 2007 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_FILTER_EFFECTS_H
+#define INKSCAPE_UI_DIALOG_FILTER_EFFECTS_H
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/alignment.h>
+#include <gtkmm/box.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/drawingarea.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/liststore.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/treeview.h>
+
+#include "attributes.h"
+#include "dialog.h"
+#include "sp-filter.h"
+#include "ui/widget/filter-effect-chooser.h"
+#include "ui/widget/notebook-page.h"
+#include "ui/widget/spin-slider.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class FilterEffectsDialog : public Dialog {
+public:
+ FilterEffectsDialog();
+ virtual ~FilterEffectsDialog();
+
+ static FilterEffectsDialog *create() { return new FilterEffectsDialog(); }
+private:
+ class FilterModifier : public Gtk::VBox, public FilterEffectChooser
+ {
+ public:
+ FilterModifier();
+
+ virtual SPFilter* get_selected_filter();
+ virtual void select_filter(const SPFilter*);
+ virtual Glib::SignalProxy0<void> signal_selection_changed();
+ private:
+ void filter_list_button_press(GdkEventButton*);
+ void add_filter();
+ void remove_filter();
+ void duplicate_filter();
+ void filter_name_edited(const Glib::ustring& path, const Glib::ustring& text);
+
+ Gtk::TreeView _list;
+ Gtk::Button _add;
+ Glib::RefPtr<Gtk::Menu> _menu;
+ };
+
+ class PrimitiveColumns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ PrimitiveColumns()
+ {
+ add(primitive);
+ add(type_id);
+ add(type);
+ add(id);
+ }
+
+ Gtk::TreeModelColumn<SPFilterPrimitive*> primitive;
+ Gtk::TreeModelColumn<NR::FilterPrimitiveType> type_id;
+ Gtk::TreeModelColumn<Glib::ustring> type;
+ Gtk::TreeModelColumn<Glib::ustring> id;
+ };
+
+ class SettingsFrame : public Gtk::Table
+ {
+ public:
+ SettingsFrame();
+
+ void init(Gtk::VBox& box);
+ void add_setting(Gtk::Widget& w, const Glib::ustring& label);
+ private:
+ Gtk::Alignment _alignment;
+ Gtk::Table _table;
+ int _where;
+ };
+
+ void init_settings_widgets();
+
+ // Handlers
+ void add_primitive();
+ void remove_primitive();
+ void duplicate_primitive();
+ void primitive_name_edited(const Glib::ustring& path, const Glib::ustring& text);
+ void primitive_list_button_press(GdkEventButton* event);
+ void primitive_list_drag_end(const Glib::RefPtr<Gdk::DragContext>&);
+
+ void set_attr(const SPAttributeEnum);
+ void update_settings_view();
+ void update_primitive_list();
+
+ SPFilterPrimitive* get_selected_primitive();
+ void select_primitive(SPFilterPrimitive *prim);
+
+ // Filter effect selection
+ FilterModifier _filter_modifier;
+
+ // View/add primitives
+ Gtk::VBox _primitive_box;
+ Gtk::TreeView _primitive_list;
+ Glib::RefPtr<Gtk::ListStore> _primitive_model;
+ PrimitiveColumns _primitive_columns;
+ Glib::RefPtr<Gtk::Menu> _primitive_menu;
+ UI::Widget::ComboBoxEnum<NR::FilterPrimitiveType> _add_primitive_type;
+ Gtk::Button _add_primitive;
+
+ // Right pane (filter effect primitive settings)
+ Gtk::VBox _settings;
+ Gtk::Label _empty_settings;
+
+ SettingsFrame _blend;
+ UI::Widget::ComboBoxEnum<NR::FilterBlendMode> _blend_mode;
+
+ SettingsFrame _colormatrix;
+ Gtk::ComboBoxText _colormatrix_type;
+
+ SettingsFrame _componenttransfer;
+
+ SettingsFrame _composite;
+
+ SettingsFrame _convolvematrix;
+
+ SettingsFrame _diffuselighting;
+
+ SettingsFrame _displacementmap;
+
+ SettingsFrame _flood;
+
+ SettingsFrame _gaussianblur;
+ SpinSlider _gaussianblur_stddeviation;
+
+ SettingsFrame _image;
+
+ SettingsFrame _merge;
+
+ SettingsFrame _morphology;
+ Gtk::ComboBoxText _morphology_operator;
+ SpinSlider _morphology_radius;
+
+ SettingsFrame _offset;
+ SpinSlider _offset_dx;
+ SpinSlider _offset_dy;
+
+ SettingsFrame _specularlighting;
+
+ SettingsFrame _tile;
+
+ SettingsFrame _turbulence;
+ SpinSlider _turbulence_basefrequency;
+ SpinSlider _turbulence_numoctaves;
+ SpinSlider _turbulence_seed;
+ Gtk::ComboBoxText _turbulence_stitchtiles;
+ Gtk::ComboBoxText _turbulence_type;
+
+
+ FilterEffectsDialog(FilterEffectsDialog const &d);
+ FilterEffectsDialog& operator=(FilterEffectsDialog const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_FILTER_EFFECTS_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:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/stock.cpp b/src/ui/stock.cpp
index 7ceb86660e0107bdb5e7122473ca78808202e3bf..03e491340614c70ccee815bff957ca489ef0bff9 100644 (file)
--- a/src/ui/stock.cpp
+++ b/src/ui/stock.cpp
// Object menu
Gtk::StockID const FILL_STROKE("fill-stroke");
Gtk::StockID const OBJECT_PROPERTIES("object-properties");
+Gtk::StockID const FILTER_EFFECTS("filter-effects");
Gtk::StockID const GROUP("group");
Gtk::StockID const UNGROUP("upgroup");
Gtk::StockID const RAISE("raise");
diff --git a/src/ui/stock.h b/src/ui/stock.h
index 069ab66f315abe66b4e12965cd92448af7aafc00..733edacdb50a54139b0a856d7f8c2bd0f92a3c83 100644 (file)
--- a/src/ui/stock.h
+++ b/src/ui/stock.h
// Object menu
extern Gtk::StockID const FILL_STROKE;
extern Gtk::StockID const OBJECT_PROPERTIES;
+extern Gtk::StockID const FILTER_EFFECTS;
extern Gtk::StockID const GROUP;
extern Gtk::StockID const UNGROUP;
extern Gtk::StockID const RAISE;
index ca298cd5dbd4f3ed4c648a711fa34864aec44e87..8e423c8fbf140b5ada637cd6c30e068ada4ea29c 100644 (file)
Stock::OBJECT_PROPERTIES),
sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
+ _act_grp->add(Gtk::Action::create("FilterEffects",
+ Stock::FILTER_EFFECTS));
+
_act_grp->add(Gtk::Action::create("Group",
Stock::GROUP, Glib::ustring(),
_("PLACEHOLDER, do not translate")));
index 30d52de01446a84b71cddffbe508d903e79c6b73..72fb9cfc25723e8c8a213d32eca5940f50c17ede 100644 (file)
ui/widget/entity-entry.h \
ui/widget/entry.cpp \
ui/widget/entry.h \
+ ui/widget/filter-effect-chooser.h \
+ ui/widget/filter-effect-chooser.cpp \
+ ui/widget/filter-effect-enums.h \
ui/widget/handlebox.cpp \
ui/widget/handlebox.h \
ui/widget/icon-widget.cpp \
ui/widget/scalar.h \
ui/widget/selected-style.h \
ui/widget/selected-style.cpp \
+ ui/widget/spin-slider.h \
+ ui/widget/spin-slider.cpp \
ui/widget/style-swatch.h \
ui/widget/style-swatch.cpp \
ui/widget/svg-canvas.cpp \
diff --git a/src/ui/widget/filter-effect-chooser.cpp b/src/ui/widget/filter-effect-chooser.cpp
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Filter effect selection selection widget
+ *
+ * Author:
+ * Nicholas Bishop <nicholasbishop@gmail.com>
+ *
+ * Copyright (C) 2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm/i18n.h>
+
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "document.h"
+#include "filter-effect-chooser.h"
+#include "inkscape.h"
+#include "ui/dialog/dialog-manager.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+FilterEffectChooser::FilterEffectChooser()
+{
+ _model = Gtk::ListStore::create(_columns);
+
+ g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop",
+ G_CALLBACK(&FilterEffectChooser::on_activate_desktop), this);
+
+
+ on_activate_desktop(INKSCAPE, SP_ACTIVE_DESKTOP, this);
+}
+
+void FilterEffectChooser::on_activate_desktop(Inkscape::Application*, SPDesktop* desktop, FilterEffectChooser* fec)
+{
+ fec->update_filters();
+
+ fec->_doc_replaced.disconnect();
+ fec->_doc_replaced = desktop->connectDocumentReplaced(
+ sigc::mem_fun(fec, &FilterEffectChooser::on_document_replaced));
+
+ fec->_resource_changed.disconnect();
+ fec->_resource_changed =
+ sp_document_resources_changed_connect(sp_desktop_document(desktop), "filter",
+ sigc::mem_fun(fec, &FilterEffectChooser::update_filters));
+}
+
+void FilterEffectChooser::on_document_replaced(SPDesktop* desktop, SPDocument* document)
+{
+ update_filters();
+}
+
+/* Add all filters in the document to the combobox.
+ Keeps the same selection if possible, otherwise selects the first element */
+void FilterEffectChooser::update_filters()
+{
+ SPDesktop* desktop = SP_ACTIVE_DESKTOP;
+ SPDocument* document = sp_desktop_document(desktop);
+ const GSList* filters = sp_document_get_resource_list(document, "filter");
+
+ _model->clear();
+
+ for(const GSList *l = filters; l; l = l->next) {
+ Gtk::TreeModel::Row row = *_model->append();
+ SPFilter* f = (SPFilter*)l->data;
+ row[_columns.filter] = f;
+ const gchar* id = SP_OBJECT_ID(f);
+ row[_columns.id] = id ? id : "";
+ }
+}
+
+SimpleFilterModifier::SimpleFilterModifier()
+ : _lb_blend(_("_Blend mode:")),
+ _lb_blur(_("B_lur:"), Gtk::ALIGN_LEFT),
+ _lb_filter(_("F_ilter:"), Gtk::ALIGN_LEFT),
+ _blend(BlendModeConverter),
+ _blur(0, 0, 100, 1, 0.01, 1),
+ _edit_filters(_("_Edit"))
+{
+ add(_hb_blend);
+ add(_vb_blur);
+ add(_hb_filter);
+ _hb_blend.pack_start(_lb_blend, false, false);
+ _hb_blend.pack_start(_blend);
+ _vb_blur.add(_lb_blur);
+ _vb_blur.add(_blur);
+ _hb_filter.pack_start(_lb_filter, false, false);
+ _hb_filter.pack_start(_hb_filter_sub);
+ _hb_filter_sub.add(_filter);
+ _hb_filter_sub.add(_edit_filters);
+
+ show_all_children();
+
+ signal_show().connect(sigc::mem_fun(*this, &SimpleFilterModifier::blend_mode_changed));
+ _hb_blend.set_spacing(12);
+ _hb_filter.set_spacing(12);
+ _lb_blend.set_use_underline();
+ _lb_blend.set_mnemonic_widget(_blend);
+ _lb_blur.set_use_underline();
+ _lb_blur.set_mnemonic_widget(_blur.get_scale());
+ _lb_filter.set_use_underline();
+ _lb_filter.set_mnemonic_widget(_filter);
+ _blend.add_row("Filter");
+ _blend.signal_changed().connect(sigc::mem_fun(*this, &SimpleFilterModifier::blend_mode_changed));
+ _blend.signal_changed().connect(signal_blend_blur_changed());
+ _blur.signal_value_changed().connect(signal_blend_blur_changed());
+ _filter.set_model(_model);
+ _filter.pack_start(_columns.id);
+ _edit_filters.signal_clicked().connect(sigc::mem_fun(*this, &SimpleFilterModifier::show_filter_dialog));
+ _edit_filters.set_use_underline();
+
+ update_filters();
+}
+
+Glib::SignalProxy0<void> SimpleFilterModifier::signal_selection_changed()
+{
+ return _filter.signal_changed();
+}
+
+SPFilter* SimpleFilterModifier::get_selected_filter()
+{
+ Gtk::TreeModel::iterator i = _filter.get_active();
+
+ if(i)
+ return (*i)[_columns.filter];
+
+ return 0;
+}
+
+void SimpleFilterModifier::select_filter(const SPFilter* filter)
+{
+ if(filter) {
+ for(Gtk::TreeModel::iterator i = _model->children().begin();
+ i != _model->children().end(); ++i) {
+ if((*i)[_columns.filter] == filter) {
+ _filter.set_active(i);
+ break;
+ }
+ }
+ }
+}
+
+sigc::signal<void>& SimpleFilterModifier::signal_blend_blur_changed()
+{
+ return _signal_blend_blur_changed;
+}
+
+const Glib::ustring SimpleFilterModifier::get_blend_mode()
+{
+ return _blend.get_active_row_number() == 5 ? "filter" : _blend.get_active_data()->name;
+}
+
+void SimpleFilterModifier::set_blend_mode(const int val)
+{
+ _blend.set_active(val);
+}
+
+double SimpleFilterModifier::get_blur_value() const
+{
+ return _blur.get_value();
+}
+
+void SimpleFilterModifier::set_blur_value(const double val)
+{
+ _blur.set_value(val);
+}
+
+void SimpleFilterModifier::set_blur_sensitive(const bool s)
+{
+ _blur.set_sensitive(s);
+}
+
+void SimpleFilterModifier::update_filters()
+{
+ const SPFilter* active_filter = get_selected_filter();
+
+ FilterEffectChooser::update_filters();
+
+ if(_model->children().empty()) {
+ // Set state if no filters exist
+ Gtk::TreeModel::Row row = *_model->prepend();
+ row[_columns.filter] = 0;
+ row[_columns.id] = "None";
+ _filter.set_sensitive(false);
+ _filter.set_active(0);
+ }
+ else {
+ _filter.set_sensitive(true);
+ select_filter(active_filter);
+ }
+}
+
+void SimpleFilterModifier::show_filter_dialog()
+{
+ SP_ACTIVE_DESKTOP->_dlg_mgr->showDialog("FilterEffectsDialog");
+}
+
+void SimpleFilterModifier::blend_mode_changed()
+{
+ if(_blend.get_active_row_number() == 5) {
+ _vb_blur.hide();
+ _hb_filter.show();
+ }
+ else {
+ _hb_filter.hide();
+ _vb_blur.show();
+ }
+}
+
+/*** From filter-effect-enums.h ***/
+const EnumData<NR::FilterPrimitiveType> FPData[NR::NR_FILTER_ENDPRIMITIVETYPE] = {
+ {NR::NR_FILTER_BLEND, _("Blend"), "svg:feBlend"},
+ {NR::NR_FILTER_COLORMATRIX, _("Color Matrix"), "svg:feColorMatrix"},
+ {NR::NR_FILTER_COMPONENTTRANSFER, _("Component Transfer"), "svg:feComponentTransfer"},
+ {NR::NR_FILTER_COMPOSITE, _("Composite"), "svg:feComposite"},
+ {NR::NR_FILTER_CONVOLVEMATRIX, _("Convolve Matrix"), "svg:feConvolveMatrix"},
+ {NR::NR_FILTER_DIFFUSELIGHTING, _("Diffuse Lighting"), "svg:feDiffuseLighting"},
+ {NR::NR_FILTER_DISPLACEMENTMAP, _("Displacement Map"), "svg:feDisplacementMap"},
+ {NR::NR_FILTER_FLOOD, _("Flood"), "svg:feFlood"},
+ {NR::NR_FILTER_GAUSSIANBLUR, _("Gaussian Blur"), "svg:feGaussianBlur"},
+ {NR::NR_FILTER_IMAGE, _("Image"), "svg:feImage"},
+ {NR::NR_FILTER_MERGE, _("Merge"), "svg:feMerge"},
+ {NR::NR_FILTER_MORPHOLOGY, _("Morphology"), "svg:feMorphology"},
+ {NR::NR_FILTER_OFFSET, _("Offset"), "svg:feOffset"},
+ {NR::NR_FILTER_SPECULARLIGHTING, _("Specular Lighting"), "svg:feSpecularLighting"},
+ {NR::NR_FILTER_TILE, _("Tile"), "svg:feTile"},
+ {NR::NR_FILTER_TURBULENCE, _("Turbulence"), "svg:feTurbulence"}
+};
+const Converter<NR::FilterPrimitiveType> FPConverter(FPData, NR::NR_FILTER_ENDPRIMITIVETYPE);
+const EnumData<NR::FilterBlendMode> BlendModeData[NR::BLEND_ENDMODE] = {
+ {NR::BLEND_NORMAL, _("Normal"), "normal"},
+ {NR::BLEND_MULTIPLY, _("Multiply"), "multiply"},
+ {NR::BLEND_SCREEN, _("Screen"), "screen"},
+ {NR::BLEND_DARKEN, _("Darken"), "darken"},
+ {NR::BLEND_LIGHTEN, _("Lighten"), "lighten"}
+};
+const Converter<NR::FilterBlendMode> BlendModeConverter(BlendModeData, NR::BLEND_ENDMODE);
+
+}
+}
+}
+
+/*
+ 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:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/filter-effect-chooser.h b/src/ui/widget/filter-effect-chooser.h
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef __FILTER_EFFECT_CHOOSER_H__
+#define __FILTER_EFFECT_CHOOSER_H__
+
+/*
+ * Filter effect selection selection widget
+ *
+ * Author:
+ * Nicholas Bishop <nicholasbishop@gmail.com>
+ *
+ * Copyright (C) 2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/box.h>
+#include <gtkmm/combobox.h>
+#include <gtkmm/liststore.h>
+#include <gtkmm/treeview.h>
+
+#include "filter-effect-enums.h"
+#include "labelled.h"
+#include "spin-slider.h"
+#include "sp-filter.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class FilterEffectChooser
+{
+public:
+ virtual ~FilterEffectChooser() {}
+
+ virtual Glib::SignalProxy0<void> signal_selection_changed() = 0;
+ virtual SPFilter* get_selected_filter() = 0;
+ virtual void select_filter(const SPFilter*) = 0;
+protected:
+ FilterEffectChooser();
+
+ class Columns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ Columns()
+ {
+ add(filter);
+ add(id);
+ }
+
+ Gtk::TreeModelColumn<SPFilter*> filter;
+ Gtk::TreeModelColumn<Glib::ustring> id;
+ };
+
+ virtual void update_filters();
+
+ Glib::RefPtr<Gtk::ListStore> _model;
+ Columns _columns;
+private:
+ static void on_activate_desktop(Inkscape::Application*, SPDesktop*, FilterEffectChooser*);
+ void on_document_replaced(SPDesktop*, SPDocument*);
+
+ sigc::connection _doc_replaced;
+ sigc::connection _resource_changed;
+
+ Gtk::TreeView::Column _filter_column;
+};
+
+/* Allows basic control over feBlend and feGaussianBlur effects,
+ with an option to use the full filter effect controls. */
+class SimpleFilterModifier : public Gtk::VBox, public FilterEffectChooser
+{
+public:
+ SimpleFilterModifier();
+
+ virtual Glib::SignalProxy0<void> signal_selection_changed();
+ virtual SPFilter* get_selected_filter();
+ virtual void select_filter(const SPFilter*);
+
+ sigc::signal<void>& signal_blend_blur_changed();
+
+ const Glib::ustring get_blend_mode();
+ // Uses blend mode enum values, or -1 for a complex filter
+ void set_blend_mode(const int);
+
+ double get_blur_value() const;
+ void set_blur_value(const double);
+ void set_blur_sensitive(const bool);
+protected:
+ virtual void update_filters();
+private:
+ void show_filter_dialog();
+ void blend_mode_changed();
+
+ Gtk::HBox _hb_blend;
+ Gtk::VBox _vb_blur;
+ Gtk::HBox _hb_filter, _hb_filter_sub;
+ Gtk::Label _lb_blend, _lb_blur, _lb_filter;
+ ComboBoxEnum<NR::FilterBlendMode> _blend;
+ SpinSlider _blur;
+ Gtk::ComboBox _filter;
+ Gtk::Button _edit_filters;
+
+ sigc::signal<void> _signal_blend_blur_changed;
+};
+
+}
+}
+}
+
+#endif
+
+/*
+ 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:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/filter-effect-enums.h b/src/ui/widget/filter-effect-enums.h
--- /dev/null
@@ -0,0 +1,156 @@
+/**
+ * \brief Simplified management of enumerations for filter effects
+ *
+ * Authors:
+ * Nicholas Bishop <nicholasbishop@gmail.com>
+ *
+ * Copyright (C) 2007 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_FILTER_EFFECT_ENUMS_H
+#define INKSCAPE_UI_WIDGET_FILTER_EFFECT_ENUMS_H
+
+#include "display/nr-filter-blend.h"
+#include "display/nr-filter-types.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+template<typename E> struct EnumData
+{
+ E id;
+ const Glib::ustring label;
+ const Glib::ustring name;
+};
+
+template<typename E> class Converter
+{
+public:
+ typedef EnumData<E> Data;
+
+ Converter(const EnumData<E>* cd, const int endval)
+ : end(endval), _data(cd)
+ {}
+
+ E get_id_from_label(const Glib::ustring& label) const
+ {
+ for(int i = 0; i < end; ++i) {
+ if(_data[i].label == label)
+ return (E)i;
+ }
+
+ return (E)0;
+ }
+
+ E get_id_from_name(const Glib::ustring& name) const
+ {
+ for(int i = 0; i < end; ++i) {
+ if(_data[i].name == name)
+ return (E)i;
+ }
+
+ return (E)0;
+ }
+
+ const Glib::ustring& get_label(const E e) const
+ {
+ return _data[e].label;
+ }
+
+ const Glib::ustring& get_name(const E e) const
+ {
+ return _data[e].name;
+ }
+
+ const EnumData<E>& data(const int i) const
+ {
+ return _data[i];
+ }
+
+ const int end;
+private:
+ const EnumData<E>* _data;
+};
+
+template<typename E> class ComboBoxEnum : public Gtk::ComboBox
+{
+public:
+ ComboBoxEnum(const Converter<E>& c)
+ : _converter(c)
+ {
+ _model = Gtk::ListStore::create(_columns);
+ set_model(_model);
+
+ pack_start(_columns.label);
+
+ // Initialize list
+ for(int i = 0; i < _converter.end; ++i) {
+ Gtk::TreeModel::Row row = *_model->append();
+ const EnumData<E>* data = &_converter.data(i);
+ row[_columns.data] = data;
+ row[_columns.label] = _converter.get_label(data->id);
+ }
+
+ set_active(0);
+ }
+
+ const EnumData<E>* get_active_data()
+ {
+ Gtk::TreeModel::iterator i = this->get_active();
+ if(i)
+ return (*i)[_columns.data];
+ return 0;
+ }
+
+ void add_row(const Glib::ustring& s)
+ {
+ Gtk::TreeModel::Row row = *_model->append();
+ row[_columns.data] = 0;
+ row[_columns.label] = s;
+ }
+private:
+ class Columns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ Columns()
+ {
+ add(data);
+ add(label);
+ }
+
+ Gtk::TreeModelColumn<const EnumData<E>*> data;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+ };
+
+ Columns _columns;
+ Glib::RefPtr<Gtk::ListStore> _model;
+ const Converter<E>& _converter;
+};
+
+/*** Filter Primitives ***/
+extern const EnumData<NR::FilterPrimitiveType> FPData[NR::NR_FILTER_ENDPRIMITIVETYPE];
+extern const Converter<NR::FilterPrimitiveType> FPConverter;
+
+/*** feBlend Mode ***/
+extern const EnumData<NR::FilterBlendMode> BlendModeData[NR::BLEND_ENDMODE];
+extern const Converter<NR::FilterBlendMode> BlendModeConverter;
+
+}
+}
+}
+
+#endif
+
+/*
+ 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:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/spin-slider.cpp b/src/ui/widget/spin-slider.cpp
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * \brief Groups an HScale and a SpinButton together using the same Adjustment
+ *
+ * Author:
+ * Nicholas Bishop <nicholasbishop@gmail.com>
+ *
+ * Copyright (C) 2007 Author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#include "spin-slider.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+
+SpinSlider::SpinSlider(double value, double lower, double upper, double step_inc,
+ double climb_rate, int digits)
+ : _adjustment(value, lower, upper, step_inc),
+ _scale(_adjustment), _spin(_adjustment, climb_rate, digits)
+{
+ pack_start(_scale);
+ pack_start(_spin, false, false);
+
+ _scale.set_draw_value(false);
+
+ show_all_children();
+}
+
+Glib::SignalProxy0<void> SpinSlider::signal_value_changed()
+{
+ return _adjustment.signal_value_changed();
+}
+
+double SpinSlider::get_value() const
+{
+ return _adjustment.get_value();
+}
+
+void SpinSlider::set_value(const double val)
+{
+ _adjustment.set_value(val);
+}
+
+const Gtk::Adjustment& SpinSlider::get_adjustment() const
+{
+ return _adjustment;
+}
+Gtk::Adjustment& SpinSlider::get_adjustment()
+{
+ return _adjustment;
+}
+
+const Gtk::HScale& SpinSlider::get_scale() const
+{
+ return _scale;
+}
+Gtk::HScale& SpinSlider::get_scale()
+{
+ return _scale;
+}
+
+const Gtk::SpinButton& SpinSlider::get_spin_button() const
+{
+ return _spin;
+}
+Gtk::SpinButton& SpinSlider::get_spin_button()
+{
+ return _spin;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/spin-slider.h b/src/ui/widget/spin-slider.h
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * \brief Groups an HScale and a SpinButton together using the same Adjustment
+ *
+ * Author:
+ * Nicholas Bishop <nicholasbishop@gmail.com>
+ *
+ * Copyright (C) 2007 Author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_SPIN_SLIDER_H
+#define INKSCAPE_UI_WIDGET_SPIN_SLIDER_H
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/box.h>
+#include <gtkmm/scale.h>
+#include <gtkmm/spinbutton.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class SpinSlider : public Gtk::HBox
+{
+public:
+ SpinSlider(double value, double lower, double upper, double step_inc,
+ double climb_rate, int digits);
+
+ // Shortcuts to _adjustment
+ Glib::SignalProxy0<void> signal_value_changed();
+ double get_value() const;
+ void set_value(const double);
+
+ const Gtk::Adjustment& get_adjustment() const;
+ Gtk::Adjustment& get_adjustment();
+
+ const Gtk::HScale& get_scale() const;
+ Gtk::HScale& get_scale();
+
+ const Gtk::SpinButton& get_spin_button() const;
+ Gtk::SpinButton& get_spin_button();
+private:
+ Gtk::Adjustment _adjustment;
+ Gtk::HScale _scale;
+ Gtk::SpinButton _spin;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_SPIN_SLIDER_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/verbs.cpp b/src/verbs.cpp
index 04a49f37c4bd3a58d9ad03275d5e548d96a5f974..5a05407762a7d4f3e8f262f4fad141c44345a07c 100644 (file)
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
case SP_VERB_DIALOG_LAYERS:
show_panel( Inkscape::UI::Dialogs::LayersPanel::getInstance(), "dialogs.layers", SP_VERB_DIALOG_LAYERS );
break;
+ case SP_VERB_DIALOG_FILTER_EFFECTS:
+ dt->_dlg_mgr->showDialog("FilterEffectsDialog");
+ break;
default:
break;
}
N_("Query information about extensions"), NULL),
new DialogVerb(SP_VERB_DIALOG_LAYERS, "DialogLayers", N_("Layer_s..."),
N_("View Layers"), "layers"),
+ new DialogVerb(SP_VERB_DIALOG_FILTER_EFFECTS, "DialogFilterEffects", N_("Filter Effects..."),
+ N_("Manage SVG filter effects"), NULL),
/* Help */
new HelpVerb(SP_VERB_HELP_KEYS, "HelpKeys", N_("_Keys and Mouse"),
diff --git a/src/verbs.h b/src/verbs.h
index f8e25f94df78782cda5398f69500ba791778405c..aa589e36dd99a6647f2ddf5c0424097c9fa2a587 100644 (file)
--- a/src/verbs.h
+++ b/src/verbs.h
SP_VERB_DIALOG_INPUT,
SP_VERB_DIALOG_EXTENSIONEDITOR,
SP_VERB_DIALOG_LAYERS,
+ SP_VERB_DIALOG_FILTER_EFFECTS,
/* Help */
SP_VERB_HELP_KEYS,
SP_VERB_HELP_ABOUT_EXTENSIONS,