summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsu_v <suv-sf@users.sourceforge.net>2012-09-23 17:24:25 +0000
committer~suv <suv-sf@users.sourceforge.net>2012-09-23 17:24:25 +0000
commitac16411f213f98407fc42c1d04eb4ae6c187e4a6 (patch)
treeb8fd94caee6b202043810a7366ab3f032882a48f /src
parentadd newly linked-in m4 files to .bzrignore (diff)
parentFix for 170395 : Add Trace Bitmap to context menu of images : Focus fix (diff)
downloadinkscape-ac16411f213f98407fc42c1d04eb4ae6c187e4a6.tar.gz
inkscape-ac16411f213f98407fc42c1d04eb4ae6c187e4a6.zip
merge from trunk (r11698)
(bzr r11668.1.10)
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/attribute-rel-util.cpp17
-rw-r--r--src/attribute-rel-util.h2
-rw-r--r--src/document.cpp32
-rw-r--r--src/ege-adjustment-action.cpp10
-rw-r--r--src/event-context.cpp10
-rw-r--r--src/extension/dbus/application-interface.cpp41
-rw-r--r--src/extension/dbus/application-interface.h17
-rw-r--r--src/extension/dbus/dbus-init.cpp3
-rw-r--r--src/extension/dbus/dbus-init.h1
-rw-r--r--src/extension/dbus/document-interface.cpp57
-rw-r--r--src/extension/dbus/document-interface.h14
-rw-r--r--src/extension/init.cpp6
-rw-r--r--src/extension/internal/Makefile_insert5
-rw-r--r--src/extension/internal/gdkpixbuf-input.cpp9
-rw-r--r--src/extension/internal/vsd-input.cpp289
-rw-r--r--src/extension/internal/vsd-input.h54
-rw-r--r--src/extension/param/float.cpp25
-rw-r--r--src/extension/param/int.cpp25
-rw-r--r--src/file.cpp9
-rw-r--r--src/filters/componenttransfer.cpp2
-rw-r--r--src/gradient-chemistry.cpp129
-rw-r--r--src/gradient-chemistry.h4
-rw-r--r--src/gradient-context.cpp13
-rw-r--r--src/id-clash.cpp35
-rw-r--r--src/id-clash.h1
-rw-r--r--src/ink-comboboxentry-action.cpp69
-rw-r--r--src/ink-comboboxentry-action.h4
-rw-r--r--src/interface.cpp64
-rw-r--r--src/interface.h6
-rw-r--r--src/marker.cpp33
-rw-r--r--src/marker.h2
-rw-r--r--src/menus-skeleton.h1
-rw-r--r--src/preferences.cpp12
-rw-r--r--src/selection-chemistry.cpp30
-rw-r--r--src/selection-chemistry.h1
-rw-r--r--src/sp-gradient.cpp36
-rw-r--r--src/sp-gradient.h1
-rw-r--r--src/sp-object.cpp10
-rw-r--r--src/sp-shape.cpp2
-rw-r--r--src/style.cpp12
-rw-r--r--src/style.h2
-rw-r--r--src/ui/dialog/document-properties.cpp18
-rw-r--r--src/ui/dialog/fill-and-stroke.cpp2
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp88
-rw-r--r--src/ui/dialog/filter-effects-dialog.h1
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp8
-rw-r--r--src/ui/dialog/inkscape-preferences.h2
-rw-r--r--src/ui/dialog/layer-properties.cpp147
-rw-r--r--src/ui/dialog/layer-properties.h44
-rw-r--r--src/ui/dialog/livepatheffect-add.cpp3
-rw-r--r--src/ui/widget/Makefile_insert4
-rw-r--r--src/ui/widget/filter-effect-chooser.cpp15
-rw-r--r--src/ui/widget/filter-effect-chooser.h8
-rw-r--r--src/ui/widget/gimpspinscale.c1089
-rw-r--r--src/ui/widget/gimpspinscale.h76
-rw-r--r--src/ui/widget/layer-selector.cpp26
-rw-r--r--src/ui/widget/layer-selector.h5
-rw-r--r--src/ui/widget/object-composite-settings.cpp58
-rw-r--r--src/ui/widget/object-composite-settings.h12
-rw-r--r--src/ui/widget/selected-style.cpp11
-rw-r--r--src/ui/widget/spin-scale.cpp248
-rw-r--r--src/ui/widget/spin-scale.h117
-rw-r--r--src/ui/widget/spin-slider.cpp2
-rw-r--r--src/ui/widget/style-swatch.cpp17
-rw-r--r--src/verbs.cpp6
-rw-r--r--src/verbs.h1
-rw-r--r--src/widgets/gradient-toolbar.cpp22
-rw-r--r--src/widgets/stroke-marker-selector.cpp8
-rw-r--r--src/widgets/stroke-marker-selector.h5
-rw-r--r--src/widgets/stroke-style.cpp86
-rw-r--r--src/widgets/stroke-style.h15
-rw-r--r--src/widgets/text-toolbar.cpp24
-rw-r--r--src/xml/repr-css.cpp29
-rw-r--r--src/xml/repr.h2
-rw-r--r--src/xml/simple-node.cpp7
76 files changed, 2872 insertions, 431 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6eefa381c..3a727b8e2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,6 +51,7 @@ all_libs = \
$(PYTHON_LIBS) \
$(INKBOARD_LIBS) \
$(LIBWPG_LIBS) \
+ $(LIBVISIO_LIBS) \
$(DBUS_LIBS) \
$(GDL_LIBS) \
$(IMAGEMAGICK_LIBS)
@@ -74,6 +75,7 @@ INCLUDES = \
$(IMAGEMAGICK_CFLAGS) \
$(INKBOARD_CFLAGS) \
$(LIBWPG_CFLAGS) \
+ $(LIBVISIO_CFLAGS) \
$(DBUS_CFLAGS) \
$(GDL_CFLAGS) \
$(XFT_CFLAGS) \
diff --git a/src/attribute-rel-util.cpp b/src/attribute-rel-util.cpp
index 239e359e2..cf94c0c1e 100644
--- a/src/attribute-rel-util.cpp
+++ b/src/attribute-rel-util.cpp
@@ -128,17 +128,13 @@ void sp_attribute_clean_style(Node *repr, unsigned int flags) {
// Find element's style
SPCSSAttr *css = sp_repr_css_attr( repr, "style" );
-
sp_attribute_clean_style(repr, css, flags);
- // g_warning( "sp_repr_write_stream_element(): Final style:" );
- //sp_repr_css_print( css );
-
// Convert css node's properties data to string and set repr node's attribute "style" to that string.
// sp_repr_css_set( repr, css, "style"); // Don't use as it will cause loop.
- gchar *value = sp_repr_css_write_string(css);
- repr->setAttribute("style", value);
- if (value) g_free (value);
+ Glib::ustring value;
+ sp_repr_css_write_string(css, value);
+ repr->setAttribute("style", value.c_str());
sp_repr_css_attr_unref( css );
}
@@ -147,7 +143,7 @@ void sp_attribute_clean_style(Node *repr, unsigned int flags) {
/**
* Clean CSS style on an element.
*/
-gchar * sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags) {
+Glib::ustring sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags) {
g_return_val_if_fail (repr != NULL, NULL);
g_return_val_if_fail (repr->type() == Inkscape::XML::ELEMENT_NODE, NULL);
@@ -155,11 +151,12 @@ gchar * sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int f
SPCSSAttr *css = sp_repr_css_attr_new();
sp_repr_css_attr_add_from_string( css, string );
sp_attribute_clean_style(repr, css, flags);
- gchar* string_cleaned = sp_repr_css_write_string( css );
+ Glib::ustring string_cleaned;
+ sp_repr_css_write_string (css, string_cleaned);
sp_repr_css_attr_unref( css );
- return string_cleaned;
+ return string_cleaned;
}
diff --git a/src/attribute-rel-util.h b/src/attribute-rel-util.h
index d9d270a13..449a66d9e 100644
--- a/src/attribute-rel-util.h
+++ b/src/attribute-rel-util.h
@@ -61,7 +61,7 @@ void sp_attribute_clean_style(Node *repr, unsigned int flags);
/**
* Clean style properties for one style string.
*/
-gchar* sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags);
+Glib::ustring sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags);
/**
* Clean style properties for one CSS.
diff --git a/src/document.cpp b/src/document.cpp
index 5eaab3eca..e28356969 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -865,6 +865,9 @@ SPObject *SPDocument::getObjectById(Glib::ustring const &id) const
SPObject *SPDocument::getObjectById(gchar const *id) const
{
g_return_val_if_fail(id != NULL, NULL);
+ if (!priv || !priv->iddef) {
+ return NULL;
+ }
GQuark idq = g_quark_from_string(id);
gpointer rv = g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq));
@@ -1450,10 +1453,33 @@ void SPDocument::importDefs(SPDocument *source)
prevent_id_clashes(source, this);
for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
- Inkscape::XML::Node * dup = def->duplicate(this->getReprDoc());
- target_defs->appendChild(dup);
- Inkscape::GC::release(dup);
+
+ // Prevent duplicates of solid swatches by checking if equivalent swatch already exists
+ gboolean duplicate = false;
+ SPObject *src = source->getObjectByRepr(def);
+ if (src && SP_IS_GRADIENT(src)) {
+ SPGradient *gr = SP_GRADIENT(src);
+ if (gr->isSolid() || gr->getVector()->isSolid()) {
+ for (SPObject *trg = this->getDefs()->firstChild() ; trg ; trg = trg->getNext()) {
+ if (trg && SP_IS_GRADIENT(trg) && src != trg) {
+ if (gr->isEquivalent(SP_GRADIENT(trg))) {
+ // Change object references to the existing equivalent gradient
+ change_def_references(src, trg);
+ duplicate = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!duplicate) {
+ Inkscape::XML::Node * dup = def->duplicate(this->getReprDoc());
+ target_defs->appendChild(dup);
+ Inkscape::GC::release(dup);
+ }
}
+
}
/*
diff --git a/src/ege-adjustment-action.cpp b/src/ege-adjustment-action.cpp
index 7881498b9..cf179478d 100644
--- a/src/ege-adjustment-action.cpp
+++ b/src/ege-adjustment-action.cpp
@@ -47,6 +47,7 @@
#include "icon-size.h"
#include "ege-adjustment-action.h"
+#include "ui/widget/gimpspinscale.h"
static void ege_adjustment_action_class_init( EgeAdjustmentActionClass* klass );
@@ -835,15 +836,8 @@ static GtkWidget* create_tool_item( GtkAction* action )
if ( act->private_data->appearanceMode == APPEARANCE_FULL ) {
/* Slider */
- gchar *leakyForNow = g_value_dup_string( &value );
-#if GTK_CHECK_VERSION(3,0,0)
- spinbutton = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, act->private_data->adj);
-#else
- spinbutton = gtk_hscale_new( act->private_data->adj);
-#endif
+ spinbutton = gimp_spin_scale_new (act->private_data->adj, g_value_get_string( &value ), 0);
gtk_widget_set_size_request(spinbutton, 100, -1);
- gtk_scale_set_digits( GTK_SCALE(spinbutton), 0 );
- g_signal_connect( G_OBJECT(spinbutton), "format-value", G_CALLBACK(slider_format_falue), leakyForNow );
} else if ( act->private_data->appearanceMode == APPEARANCE_MINIMAL ) {
spinbutton = gtk_scale_button_new( GTK_ICON_SIZE_MENU, 0, 100, 2, 0 );
diff --git a/src/event-context.cpp b/src/event-context.cpp
index 848865b95..2c9ed1abd 100644
--- a/src/event-context.cpp
+++ b/src/event-context.cpp
@@ -691,9 +691,11 @@ static gint sp_event_context_private_root_handler(
int const wheel_scroll = prefs->getIntLimited(
"/options/wheelscroll/value", 40, 0, 1000);
+#if GTK_CHECK_VERSION(3,0,0)
// Size of smooth-scrolls (only used in GTK+ 3)
gdouble delta_x = 0;
gdouble delta_y = 0;
+#endif
/* shift + wheel, pan left--right */
if (event->scroll.state & GDK_SHIFT_MASK) {
@@ -1059,10 +1061,18 @@ static void set_event_location(SPDesktop *desktop, GdkEvent *event) {
* Create popup menu and tell Gtk to show it.
*/
void sp_event_root_menu_popup(SPDesktop *desktop, SPItem *item, GdkEvent *event) {
+
+ // It seems the param item is the SPItem at the bottom of the z-order
+ // Using the same function call used on left click in sp_select_context_item_handler() to get top of z-order
+ // fixme: sp_canvas_arena should set the top z-order object as arena->active
+ item = sp_event_context_find_item (desktop,
+ Geom::Point(event->button.x, event->button.y), FALSE, FALSE);
+
/* fixme: This is not what I want but works for now (Lauris) */
if (event->type == GDK_KEY_PRESS) {
item = sp_desktop_selection(desktop)->singleItem();
}
+
ContextMenu* CM = new ContextMenu(desktop, item);
CM->show();
diff --git a/src/extension/dbus/application-interface.cpp b/src/extension/dbus/application-interface.cpp
index a652b7c96..8ee7bd12f 100644
--- a/src/extension/dbus/application-interface.cpp
+++ b/src/extension/dbus/application-interface.cpp
@@ -39,6 +39,9 @@ application_interface_class_init (ApplicationInterfaceClass *klass)
static void
application_interface_init (ApplicationInterface *object)
{
+ dbus_g_error_domain_register (INKSCAPE_ERROR,
+ NULL,
+ INKSCAPE_TYPE_ERROR);
}
@@ -48,6 +51,44 @@ application_interface_new (void)
return (ApplicationInterface*)g_object_new (TYPE_APPLICATION_INTERFACE, NULL);
}
+/*
+ * Error stuff...
+ *
+ * To add a new error type, edit here and in the .h InkscapeError enum.
+ */
+GQuark
+inkscape_error_quark (void)
+{
+ static GQuark quark = 0;
+ if (!quark)
+ quark = g_quark_from_static_string ("inkscape_error");
+
+ return quark;
+}
+
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType inkscape_error_get_type(void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GEnumValue values[] =
+ {
+
+ ENUM_ENTRY(INKSCAPE_ERROR_SELECTION, "Incompatible_Selection"),
+ ENUM_ENTRY(INKSCAPE_ERROR_OBJECT, "Incompatible_Object"),
+ ENUM_ENTRY(INKSCAPE_ERROR_VERB, "Failed_Verb"),
+ ENUM_ENTRY(INKSCAPE_ERROR_OTHER, "Generic_Error"),
+ { 0, 0, 0 }
+ };
+
+ etype = g_enum_register_static("InkscapeError", values);
+ }
+
+ return etype;
+}
+
/****************************************************************************
DESKTOP FUNCTIONS
****************************************************************************/
diff --git a/src/extension/dbus/application-interface.h b/src/extension/dbus/application-interface.h
index e782bd1ad..88219a6b0 100644
--- a/src/extension/dbus/application-interface.h
+++ b/src/extension/dbus/application-interface.h
@@ -45,6 +45,23 @@ struct _ApplicationInterfaceClass {
GObjectClass parent;
};
+
+typedef enum
+{
+ INKSCAPE_ERROR_SELECTION,
+ INKSCAPE_ERROR_OBJECT,
+ INKSCAPE_ERROR_VERB,
+ INKSCAPE_ERROR_OTHER
+} InkscapeError;
+
+
+
+#define INKSCAPE_ERROR (inkscape_error_quark ())
+#define INKSCAPE_TYPE_ERROR (inkscape_error_get_type ())
+
+GQuark inkscape_error_quark (void);
+GType inkscape_error_get_type (void);
+
/****************************************************************************
DESKTOP FUNCTIONS
****************************************************************************/
diff --git a/src/extension/dbus/dbus-init.cpp b/src/extension/dbus/dbus-init.cpp
index 1b6baa979..9ff6897e5 100644
--- a/src/extension/dbus/dbus-init.cpp
+++ b/src/extension/dbus/dbus-init.cpp
@@ -128,9 +128,6 @@ dbus_init_desktop_interface (SPDesktop * dt)
DBusGConnection *connection;
DBusGProxy *proxy;
DocumentInterface *obj;
- dbus_g_error_domain_register (INKSCAPE_ERROR,
- NULL,
- INKSCAPE_TYPE_ERROR);
std::string name("/org/inkscape/desktop_");
std::stringstream out;
diff --git a/src/extension/dbus/dbus-init.h b/src/extension/dbus/dbus-init.h
index 4b07acfb4..025011f28 100644
--- a/src/extension/dbus/dbus-init.h
+++ b/src/extension/dbus/dbus-init.h
@@ -12,6 +12,7 @@
#include "desktop.h"
+
namespace Inkscape {
namespace Extension {
namespace Dbus {
diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp
index c67234b34..56d1dfdbd 100644
--- a/src/extension/dbus/document-interface.cpp
+++ b/src/extension/dbus/document-interface.cpp
@@ -17,6 +17,7 @@
#include "file.h" //IO
#include "document-interface.h"
+#include "application-interface.h"
#include <string.h>
#include <dbus/dbus-glib.h>
#include "desktop-handles.h" //sp_desktop_document()
@@ -222,11 +223,12 @@ dbus_create_node (SPDesktop *desk, const gchar *type)
*/
gchar *finish_create_shape (DocumentInterface *object, GError ** /*error*/, Inkscape::XML::Node *newNode, gchar *desc)
{
-
SPCSSAttr *style = sp_desktop_get_style(object->desk, TRUE);
if (style) {
- newNode->setAttribute("style", sp_repr_css_write_string(style), TRUE);
+ Glib::ustring str;
+ sp_repr_css_write_string(style, str);
+ newNode->setAttribute("style", str.c_str(), TRUE);
}
else {
newNode->setAttribute("style", "fill:#0000ff;fill-opacity:1;stroke:#c900b9;stroke-width:0;stroke-miterlimit:0;stroke-opacity:1;stroke-dasharray:none", TRUE);
@@ -320,43 +322,7 @@ document_interface_new (void)
return (DocumentInterface*)g_object_new (TYPE_DOCUMENT_INTERFACE, NULL);
}
-/*
- * Error stuff...
- *
- * To add a new error type, edit here and in the .h InkscapeError enum.
- */
-GQuark
-inkscape_error_quark (void)
-{
- static GQuark quark = 0;
- if (!quark)
- quark = g_quark_from_static_string ("inkscape_error");
-
- return quark;
-}
-
-#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
-GType inkscape_error_get_type(void)
-{
- static GType etype = 0;
-
- if (etype == 0) {
- static const GEnumValue values[] =
- {
-
- ENUM_ENTRY(INKSCAPE_ERROR_SELECTION, "Incompatible_Selection"),
- ENUM_ENTRY(INKSCAPE_ERROR_OBJECT, "Incompatible_Object"),
- ENUM_ENTRY(INKSCAPE_ERROR_VERB, "Failed_Verb"),
- ENUM_ENTRY(INKSCAPE_ERROR_OTHER, "Generic_Error"),
- { 0, 0, 0 }
- };
-
- etype = g_enum_register_static("InkscapeError", values);
- }
-
- return etype;
-}
/****************************************************************************
MISC FUNCTIONS
@@ -565,7 +531,7 @@ gchar *document_interface_node(DocumentInterface *object, gchar *type, GError **
}
/****************************************************************************
- ENVIORNMENT FUNCTIONS
+ ENVIRONMENT FUNCTIONS
****************************************************************************/
gdouble
document_interface_document_get_width (DocumentInterface *object)
@@ -582,7 +548,9 @@ document_interface_document_get_height (DocumentInterface *object)
gchar *document_interface_document_get_css(DocumentInterface *object, GError ** /*error*/)
{
SPCSSAttr *current = (object->desk)->current;
- return sp_repr_css_write_string(current);
+ Glib::ustring str;
+ sp_repr_css_write_string(current, str);
+ return (str.empty() ? NULL : g_strdup (str.c_str()));
}
gboolean document_interface_document_merge_css(DocumentInterface *object,
@@ -803,7 +771,9 @@ document_interface_modify_css (DocumentInterface *object, gchar *shape,
SPCSSAttr * oldstyle = sp_repr_css_attr (node, style);
sp_repr_css_set_property(oldstyle, cssattrb, newval);
- node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE);
+ Glib::ustring str;
+ sp_repr_css_write_string (oldstyle, str);
+ node->setAttribute (style, str.c_str(), TRUE);
return TRUE;
}
@@ -826,7 +796,10 @@ document_interface_merge_css (DocumentInterface *object, gchar *shape,
SPCSSAttr * oldstyle = sp_repr_css_attr (node, style);
sp_repr_css_merge(oldstyle, newstyle);
- node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE);
+ Glib::ustring str;
+ sp_repr_css_write_string (oldstyle, str);
+ node->setAttribute (style, str.c_str(), TRUE);
+
return TRUE;
}
diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h
index e7e55cb7d..5fcbb919b 100644
--- a/src/extension/dbus/document-interface.h
+++ b/src/extension/dbus/document-interface.h
@@ -56,19 +56,7 @@ struct _DocumentInterfaceClass {
GObjectClass parent;
};
-typedef enum
-{
- INKSCAPE_ERROR_SELECTION,
- INKSCAPE_ERROR_OBJECT,
- INKSCAPE_ERROR_VERB,
- INKSCAPE_ERROR_OTHER
-} InkscapeError;
-
-#define INKSCAPE_ERROR (inkscape_error_quark ())
-#define INKSCAPE_TYPE_ERROR (inkscape_error_get_type ())
-
-GQuark inkscape_error_quark (void);
-GType inkscape_error_get_type (void);
+
struct DBUSPoint {
int x;
diff --git a/src/extension/init.cpp b/src/extension/init.cpp
index cd7c52d5e..425c0743b 100644
--- a/src/extension/init.cpp
+++ b/src/extension/init.cpp
@@ -51,6 +51,9 @@
#ifdef WITH_LIBWPG
#include "internal/wpg-input.h"
#endif
+#ifdef WITH_LIBVISIO
+#include "internal/vsd-input.h"
+#endif
#include "preferences.h"
#include "io/sys.h"
#ifdef WITH_DBUS
@@ -179,6 +182,9 @@ init()
#ifdef WITH_LIBWPG
Internal::WpgInput::init();
#endif
+#ifdef WITH_LIBVISIO
+ Internal::VsdInput::init();
+#endif
/* Effects */
Internal::BlurEdge::init();
diff --git a/src/extension/internal/Makefile_insert b/src/extension/internal/Makefile_insert
index d1b2da8cd..c4dbaa77a 100644
--- a/src/extension/internal/Makefile_insert
+++ b/src/extension/internal/Makefile_insert
@@ -4,7 +4,12 @@ if WITH_LIBWPG
ink_common_sources += \
extension/internal/wpg-input.cpp \
extension/internal/wpg-input.h
+endif
+if WITH_LIBVISIO
+ink_common_sources += \
+ extension/internal/vsd-input.cpp \
+ extension/internal/vsd-input.h
endif
if USE_IMAGE_MAGICK
diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp
index 6e6038993..abfad518f 100644
--- a/src/extension/internal/gdkpixbuf-input.cpp
+++ b/src/extension/internal/gdkpixbuf-input.cpp
@@ -80,6 +80,7 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
double width = gdk_pixbuf_get_width(pb);
double height = gdk_pixbuf_get_height(pb);
double defaultxdpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", PX_PER_IN);
+ bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi");
ImageResolution *ir = 0;
double xscale = 1;
double yscale = 1;
@@ -91,9 +92,9 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
xscale = 72.0 / (double)dpi;
}
} else {
- if (!ir)
+ if (!ir && !forcexdpi)
ir = new ImageResolution(uri);
- if (ir->ok())
+ if (ir && ir->ok())
xscale = 900.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi
else
xscale = 90.0 / defaultxdpi;
@@ -107,9 +108,9 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
yscale = 72.0 / (double)dpi;
}
} else {
- if (!ir)
+ if (!ir && !forcexdpi)
ir = new ImageResolution(uri);
- if (ir->ok())
+ if (ir && ir->ok())
yscale = 900.0 / floor(10.*ir->y() + .5); // round-off to 0.1 dpi
else
yscale = 90.0 / defaultxdpi;
diff --git a/src/extension/internal/vsd-input.cpp b/src/extension/internal/vsd-input.cpp
new file mode 100644
index 000000000..6d71ce72a
--- /dev/null
+++ b/src/extension/internal/vsd-input.cpp
@@ -0,0 +1,289 @@
+/*
+ * This file came from libwpg as a source, their utility wpg2svg
+ * specifically. It has been modified to work as an Inkscape extension.
+ * The Inkscape extension code is covered by this copyright, but the
+ * rest is covered by the one bellow.
+ *
+ * Authors:
+ * Fridrich Strba (fridrich.strba@bluewin.ch)
+ *
+ * Copyright (C) 2012 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ *
+ */
+
+#include <stdio.h>
+#include "config.h"
+
+#include "vsd-input.h"
+
+#ifdef WITH_LIBVISIO
+
+#include <string>
+#include <cstring>
+
+#include <libvisio/libvisio.h>
+#include <libwpd-stream/libwpd-stream.h>
+
+#include <gtkmm/alignment.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/drawingarea.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/scale.h>
+
+#include "extension/system.h"
+#include "extension/input.h"
+#include "document.h"
+
+#include "document-private.h"
+#include "document-undo.h"
+#include "inkscape.h"
+
+#include "dialogs/dialog-events.h"
+#include <gtk/gtk.h>
+#include "ui/widget/spinbutton.h"
+#include "ui/widget/frame.h"
+#include <glibmm/i18n.h>
+
+#include <gdkmm/general.h>
+
+#include "svg-view.h"
+#include "svg-view-widget.h"
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+
+class VsdImportDialog : public Gtk::Dialog {
+public:
+ VsdImportDialog(const std::vector<WPXString> &vec);
+ virtual ~VsdImportDialog();
+
+ bool showDialog();
+ unsigned getSelectedPage();
+ void getImportSettings(Inkscape::XML::Node *prefs);
+
+private:
+ void _setPreviewPage(unsigned page);
+
+ // Signal handlers
+#if !WITH_GTKMM_3_0
+ bool _onExposePreview(GdkEventExpose *event);
+#endif
+
+ void _onPageNumberChanged();
+
+ class Gtk::Button * cancelbutton;
+ class Gtk::Button * okbutton;
+ class Gtk::Label * _labelSelect;
+ class Inkscape::UI::Widget::SpinButton * _pageNumberSpin;
+ class Gtk::Label * _labelTotalPages;
+ class Gtk::VBox * vbox1;
+ class Gtk::VBox * vbox2;
+ class Gtk::Widget * _previewArea;
+
+ const std::vector<WPXString> &_vec; // Document to be imported
+ unsigned _current_page; // Current selected page
+ int _preview_width, _preview_height; // Size of the preview area
+};
+
+VsdImportDialog::VsdImportDialog(const std::vector<WPXString> &vec)
+ : _vec(vec), _current_page(1)
+{
+ int num_pages = _vec.size();
+ if ( num_pages <= 1 )
+ return;
+ cancelbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-cancel")));
+ okbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-ok")));
+ _labelSelect = Gtk::manage(new class Gtk::Label(_("Select page:")));
+
+ // Page number
+#if WITH_GTKMM_3_0
+ Glib::RefPtr<Gtk::Adjustment> _pageNumberSpin_adj = Gtk::Adjustment::create(1, 1, _vec.size(), 1, 10, 0);
+ _pageNumberSpin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(_pageNumberSpin_adj, 1, 1));
+#else
+ Gtk::Adjustment *_pageNumberSpin_adj = Gtk::manage(
+ new class Gtk::Adjustment(1, 1, _vec.size(), 1, 10, 0));
+ _pageNumberSpin = Gtk::manage(new class Inkscape::UI::Widget::SpinButton(*_pageNumberSpin_adj, 1, 1));
+#endif
+ _labelTotalPages = Gtk::manage(new class Gtk::Label());
+ gchar *label_text = g_strdup_printf(_("out of %i"), num_pages);
+ _labelTotalPages->set_label(label_text);
+ g_free(label_text);
+
+ vbox1 = Gtk::manage(new class Gtk::VBox(false, 4));
+ SPDocument *doc = SPDocument::createNewDocFromMem(_vec[0].cstr(), strlen(_vec[0].cstr()), 0);
+ _previewArea = Glib::wrap(sp_svg_view_widget_new(doc));
+
+ vbox2 = Gtk::manage(new class Gtk::VBox(false, 4));
+ cancelbutton->set_can_focus();
+ cancelbutton->set_can_default();
+ cancelbutton->set_relief(Gtk::RELIEF_NORMAL);
+ okbutton->set_can_focus();
+ okbutton->set_can_default();
+ okbutton->set_relief(Gtk::RELIEF_NORMAL);
+ this->get_action_area()->property_layout_style().set_value(Gtk::BUTTONBOX_END);
+ _labelSelect->set_line_wrap(false);
+ _labelSelect->set_use_markup(false);
+ _labelSelect->set_selectable(false);
+ _pageNumberSpin->set_can_focus();
+ _pageNumberSpin->set_update_policy(Gtk::UPDATE_ALWAYS);
+ _pageNumberSpin->set_numeric(true);
+ _pageNumberSpin->set_digits(0);
+ _pageNumberSpin->set_wrap(false);
+ _labelTotalPages->set_line_wrap(false);
+ _labelTotalPages->set_use_markup(false);
+ _labelTotalPages->set_selectable(false);
+ vbox2->pack_start(*_previewArea, Gtk::PACK_SHRINK, 0);
+ this->get_vbox()->set_homogeneous(false);
+ this->get_vbox()->set_spacing(0);
+ this->get_vbox()->pack_start(*vbox2);
+ this->set_title(_("Page Selector"));
+ this->set_modal(true);
+ sp_transientize((GtkWidget *)this->gobj()); //Make transient
+ this->property_window_position().set_value(Gtk::WIN_POS_NONE);
+ this->set_resizable(true);
+ this->property_destroy_with_parent().set_value(false);
+ this->get_action_area()->add(*_labelSelect);
+ this->add_action_widget(*_pageNumberSpin, -7);
+ this->get_action_area()->add(*_labelTotalPages);
+ this->add_action_widget(*cancelbutton, -6);
+ this->add_action_widget(*okbutton, -5);
+ cancelbutton->show();
+ okbutton->show();
+ _labelSelect->show();
+ _pageNumberSpin->show();
+ _labelTotalPages->show();
+ vbox1->show();
+ _previewArea->show();
+ vbox2->show();
+
+ // Connect signals
+ _pageNumberSpin_adj->signal_value_changed().connect(sigc::mem_fun(*this, &VsdImportDialog::_onPageNumberChanged));
+}
+
+VsdImportDialog::~VsdImportDialog() {}
+
+bool VsdImportDialog::showDialog()
+{
+ show();
+ gint b = run();
+ hide();
+ if ( b == Gtk::RESPONSE_OK ) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+unsigned VsdImportDialog::getSelectedPage()
+{
+ return _current_page;
+}
+
+void VsdImportDialog::_onPageNumberChanged()
+{
+ int page = _pageNumberSpin->get_value_as_int();
+ _current_page = CLAMP(page, 1, _vec.size());
+ _setPreviewPage(_current_page);
+}
+
+/**
+ * \brief Renders the given page's thumbnail
+ */
+void VsdImportDialog::_setPreviewPage(unsigned page)
+{
+ SPDocument *doc = SPDocument::createNewDocFromMem(_vec[page-1].cstr(), strlen(_vec[page-1].cstr()), 0);
+ Gtk::Widget * tmpPreviewArea = Glib::wrap(sp_svg_view_widget_new(doc));
+ std::swap(_previewArea, tmpPreviewArea);
+ if (tmpPreviewArea) {
+ _previewArea->set_size_request( tmpPreviewArea->get_width(), tmpPreviewArea->get_height() );
+ delete tmpPreviewArea;
+ }
+ vbox2->pack_start(*_previewArea, Gtk::PACK_SHRINK, 0);
+ _previewArea->show_now();
+}
+
+SPDocument *VsdInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri)
+{
+ WPXFileStream input(uri);
+
+ if (!libvisio::VisioDocument::isSupported(&input)) {
+ return NULL;
+ }
+
+ libvisio::VSDStringVector output;
+ if (!libvisio::VisioDocument::generateSVG(&input, output)) {
+ return NULL;
+ }
+
+ if (output.empty()) {
+ return NULL;
+ }
+
+ std::vector<WPXString> tmpSVGOutput;
+ for (unsigned i=0; i<output.size(); ++i) {
+ WPXString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
+ tmpString.append(output[i]);
+ tmpSVGOutput.push_back(tmpString);
+ }
+
+ unsigned page_num = 1;
+
+ // If only one page is present, import that one without bothering user
+ if (tmpSVGOutput.size() > 1) {
+ VsdImportDialog *dlg = 0;
+ if (inkscape_use_gui()) {
+ dlg = new VsdImportDialog(tmpSVGOutput);
+ if (!dlg->showDialog()) {
+ delete dlg;
+ return NULL;
+ }
+ }
+
+ // Get needed page
+ if (dlg) {
+ page_num = dlg->getSelectedPage();
+ if (page_num < 1)
+ page_num = 1;
+ if (page_num > tmpSVGOutput.size())
+ page_num = tmpSVGOutput.size();
+ }
+ }
+
+ SPDocument * doc = SPDocument::createNewDocFromMem(tmpSVGOutput[page_num-1].cstr(), strlen(tmpSVGOutput[page_num-1].cstr()), TRUE);
+ return doc;
+}
+
+#include "clear-n_.h"
+
+void VsdInput::init(void)
+{
+ Inkscape::Extension::build_from_mem(
+ "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
+ "<name>" N_("VSD Input") "</name>\n"
+ "<id>org.inkscape.input.vsd</id>\n"
+ "<input>\n"
+ "<extension>.vsd</extension>\n"
+ "<mimetype>application/vnd.visio</mimetype>\n"
+ "<filetypename>" N_("Microsoft Visio Diagram (*.vsd)") "</filetypename>\n"
+ "<filetypetooltip>" N_("File format used by Microsoft Visio 6 and later") "</filetypetooltip>\n"
+ "</input>\n"
+ "</inkscape-extension>", new VsdInput());
+} // init
+
+} } } /* namespace Inkscape, Extension, Implementation */
+#endif /* WITH_LIBVISIO */
+
+/*
+ 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=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/extension/internal/vsd-input.h b/src/extension/internal/vsd-input.h
new file mode 100644
index 000000000..acc52debf
--- /dev/null
+++ b/src/extension/internal/vsd-input.h
@@ -0,0 +1,54 @@
+/*
+ * This code abstracts the libwpg interfaces into the Inkscape
+ * input extension interface.
+ *
+ * Authors:
+ * Fridrich Strba (fridrich.strba@bluewin.ch)
+ *
+ * Copyright (C) 2012 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef __EXTENSION_INTERNAL_VSDOUTPUT_H__
+#define __EXTENSION_INTERNAL_VSDOUTPUT_H__
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef WITH_LIBVISIO
+
+#include <gtkmm/dialog.h>
+
+#include "../implementation/implementation.h"
+
+namespace Inkscape {
+namespace Extension {
+namespace Internal {
+
+class VsdInput : public Inkscape::Extension::Implementation::Implementation {
+ VsdInput () { };
+public:
+ SPDocument *open( Inkscape::Extension::Input *mod,
+ const gchar *uri );
+ static void init( void );
+
+};
+
+} } } /* namespace Inkscape, Extension, Implementation */
+
+#endif /* WITH_LIBVISIO */
+#endif /* __EXTENSION_INTERNAL_VSDOUTPUT_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=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/extension/param/float.cpp b/src/extension/param/float.cpp
index b9ffe68d2..81508f6c0 100644
--- a/src/extension/param/float.cpp
+++ b/src/extension/param/float.cpp
@@ -14,6 +14,7 @@
#include <gtkmm/box.h>
#include <gtkmm/scale.h>
#include "ui/widget/spinbutton.h"
+#include "ui/widget/spin-scale.h"
#include "xml/node.h"
#include "extension/extension.h"
@@ -175,9 +176,6 @@ Gtk::Widget * ParamFloat::get_widget(SPDocument * doc, Inkscape::XML::Node * nod
}
Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
- Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START));
- label->show();
- hbox->pack_start(*label, true, true, _indent);
#if WITH_GTKMM_3_0
ParamFloatAdjustment * pfa = new ParamFloatAdjustment(this, doc, node, changeSignal);
@@ -187,24 +185,27 @@ Gtk::Widget * ParamFloat::get_widget(SPDocument * doc, Inkscape::XML::Node * nod
#endif
if (_mode == FULL) {
-#if WITH_GTKMM_3_0
- Gtk::HScale * scale = Gtk::manage(new Gtk::HScale(fadjust));
-#else
- Gtk::HScale * scale = Gtk::manage(new Gtk::HScale(*fadjust));
-#endif
- scale->set_draw_value(false);
- scale->set_size_request(200, -1);
+
+ UI::Widget::SpinScale *scale = new UI::Widget::SpinScale(_(_text), fadjust, _precision);
+ scale->set_size_request(400, -1);
scale->show();
hbox->pack_start(*scale, false, false);
+
}
+ else if (_mode == MINIMAL) {
+
+ Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START));
+ label->show();
+ hbox->pack_start(*label, true, true, _indent);
#if WITH_GTKMM_3_0
Inkscape::UI::Widget::SpinButton * spin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(fadjust, 0.1, _precision));
#else
Inkscape::UI::Widget::SpinButton * spin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(*fadjust, 0.1, _precision));
#endif
- spin->show();
- hbox->pack_start(*spin, false, false);
+ spin->show();
+ hbox->pack_start(*spin, false, false);
+ }
hbox->show();
diff --git a/src/extension/param/int.cpp b/src/extension/param/int.cpp
index 7cb930f50..c286018fd 100644
--- a/src/extension/param/int.cpp
+++ b/src/extension/param/int.cpp
@@ -14,6 +14,7 @@
#include <gtkmm/box.h>
#include <gtkmm/scale.h>
#include "ui/widget/spinbutton.h"
+#include "ui/widget/spin-scale.h"
#include "xml/node.h"
#include "extension/extension.h"
@@ -156,9 +157,7 @@ ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal
}
Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
- Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START));
- label->show();
- hbox->pack_start(*label, true, true, _indent);
+
#if WITH_GTKMM_3_0
ParamIntAdjustment * pia = new ParamIntAdjustment(this, doc, node, changeSignal);
@@ -168,24 +167,26 @@ ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal
#endif
if (_mode == FULL) {
-#if WITH_GTKMM_3_0
- Gtk::HScale * scale = Gtk::manage(new Gtk::HScale(fadjust));
-#else
- Gtk::HScale * scale = Gtk::manage(new Gtk::HScale(*fadjust));
-#endif
- scale->set_draw_value(false);
- scale->set_size_request(200, -1);
+
+ UI::Widget::SpinScale *scale = new UI::Widget::SpinScale(_(_text), fadjust, 0);
+ scale->set_size_request(400, -1);
scale->show();
hbox->pack_start(*scale, false, false);
}
+ else if (_mode == MINIMAL) {
+ Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START));
+ label->show();
+ hbox->pack_start(*label, true, true, _indent);
+
#if WITH_GTKMM_3_0
Inkscape::UI::Widget::SpinButton * spin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(fadjust, 1.0, 0));
#else
Inkscape::UI::Widget::SpinButton * spin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(*fadjust, 1.0, 0));
#endif
- spin->show();
- hbox->pack_start(*spin, false, false);
+ spin->show();
+ hbox->pack_start(*spin, false, false);
+ }
hbox->show();
diff --git a/src/file.cpp b/src/file.cpp
index dcdae1700..778306d5d 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -1142,6 +1142,8 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
place_to_insert = in_doc->getRoot();
}
+ in_doc->importDefs(doc);
+
// Construct a new object representing the imported image,
// and insert it into the current document.
SPObject *new_obj = NULL;
@@ -1162,12 +1164,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
// don't lose top-level defs or style elements
else if (child->getRepr()->type() == Inkscape::XML::ELEMENT_NODE) {
const gchar *tag = child->getRepr()->name();
- if (!strcmp(tag, "svg:defs")) {
- for ( SPObject *x = child->firstChild(); x; x = x->getNext() ) {
- in_defs->getRepr()->addChild(x->getRepr()->duplicate(xml_in_doc), last_def);
- }
- }
- else if (!strcmp(tag, "svg:style")) {
+ if (!strcmp(tag, "svg:style")) {
in_doc->getRoot()->appendChildRepr(child->getRepr()->duplicate(xml_in_doc));
}
}
diff --git a/src/filters/componenttransfer.cpp b/src/filters/componenttransfer.cpp
index 99d8616f4..8cc388dd0 100644
--- a/src/filters/componenttransfer.cpp
+++ b/src/filters/componenttransfer.cpp
@@ -100,7 +100,7 @@ sp_feComponentTransfer_build(SPObject *object, SPDocument *document, Inkscape::X
/*LOAD ATTRIBUTES FROM REPR HERE*/
//do we need this?
- document->addResource("feComponentTransfer", object);
+ //document->addResource("feComponentTransfer", object);
}
static void sp_feComponentTransfer_children_modified(SPFeComponentTransfer *sp_componenttransfer)
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index 6b1376fb5..ed4e81f0d 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -20,10 +20,19 @@
#include <2geom/transforms.h>
#include <2geom/bezier-curve.h>
+#include <2geom/crossing.h>
+#include <2geom/line.h>
+#include <2geom/angle.h>
#include "style.h"
#include "document-private.h"
+#include "document-undo.h"
#include "desktop-style.h"
+#include "desktop-handles.h"
+#include "event-context.h"
+#include "selection.h"
+#include "verbs.h"
+#include <glibmm/i18n.h>
#include "sp-gradient-reference.h"
#include "sp-gradient-vector.h"
@@ -44,6 +53,7 @@
#define noSP_GR_VERBOSE
+using Inkscape::DocumentUndo;
namespace {
@@ -355,10 +365,45 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item)
g_free(c);
}
} else if (SP_IS_LINEARGRADIENT(gr)) {
- sp_repr_set_svg_double(repr, "x1", (center - Geom::Point(width/2, 0))[Geom::X]);
- sp_repr_set_svg_double(repr, "y1", (center - Geom::Point(width/2, 0))[Geom::Y]);
- sp_repr_set_svg_double(repr, "x2", (center + Geom::Point(width/2, 0))[Geom::X]);
- sp_repr_set_svg_double(repr, "y2", (center + Geom::Point(width/2, 0))[Geom::Y]);
+
+ // Assume horizontal gradient by default (as per SVG 1.1)
+ Geom::Point pStart = center - Geom::Point(width/2, 0);
+ Geom::Point pEnd = center + Geom::Point(width/2, 0);
+
+ // Get the preferred gradient angle from prefs
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ double angle = prefs->getDouble("/dialogs/gradienteditor/angle", 0.0);
+
+ if (angle != 0.0) {
+
+ Geom::Line grl(center, Geom::deg_to_rad(angle));
+ Geom::LineSegment bbl1(bbox->corner(0), bbox->corner(1));
+ Geom::LineSegment bbl2(bbox->corner(1), bbox->corner(2));
+ Geom::LineSegment bbl3(bbox->corner(2), bbox->corner(3));
+ Geom::LineSegment bbl4(bbox->corner(3), bbox->corner(0));
+
+ // Find where our gradient line intersects the bounding box.
+ if (intersection(bbl1, grl)) {
+ pStart = bbl1.pointAt((*intersection(bbl1, grl)).ta);
+ pEnd = bbl3.pointAt((*intersection(bbl3, grl)).ta);
+ if (intersection(bbl1, grl.ray(grl.angle()))) {
+ std::swap(pStart, pEnd);
+ }
+ } else if (intersection(bbl2, grl)) {
+ pStart = bbl2.pointAt((*intersection(bbl2, grl)).ta);
+ pEnd = bbl4.pointAt((*intersection(bbl4, grl)).ta);
+ if (intersection(bbl2, grl.ray(grl.angle()))) {
+ std::swap(pStart, pEnd);
+ }
+ }
+
+ }
+
+ sp_repr_set_svg_double(repr, "x1", pStart[Geom::X]);
+ sp_repr_set_svg_double(repr, "y1", pStart[Geom::Y]);
+ sp_repr_set_svg_double(repr, "x2", pEnd[Geom::X]);
+ sp_repr_set_svg_double(repr, "y2", pEnd[Geom::Y]);
+
} else {
// Mesh
// THIS IS BEING CALLED TWICE WHENEVER A NEW GRADIENT IS CREATED, WRITING HERE CAUSES PROBLEMS
@@ -914,6 +959,44 @@ void sp_item_gradient_reverse_vector(SPItem *item, Inkscape::PaintTarget fill_or
g_slist_free (child_objects);
}
+void sp_item_gradient_invert_vector_color(SPItem *item, Inkscape::PaintTarget fill_or_stroke)
+{
+#ifdef SP_GR_VERBOSE
+ g_message("sp_item_gradient_invert_vector_color(%p, %d)", item, fill_or_stroke);
+#endif
+ SPGradient *gradient = getGradient(item, fill_or_stroke);
+ if (!gradient || !SP_IS_GRADIENT(gradient))
+ return;
+
+ SPGradient *vector = gradient->getVector();
+ if (!vector) // orphan!
+ return;
+
+ vector = sp_gradient_fork_vector_if_necessary (vector);
+ if ( gradient != vector && gradient->ref->getObject() != vector ) {
+ sp_gradient_repr_set_link(gradient->getRepr(), vector);
+ }
+
+ for ( SPObject *child = vector->firstChild(); child; child = child->getNext()) {
+ if (SP_IS_STOP(child)) {
+ guint32 color = sp_stop_get_rgba32(SP_STOP(child));
+ //g_message("Stop color %d", color);
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c),
+ SP_RGBA32_U_COMPOSE(
+ (255 - SP_RGBA32_R_U(color)),
+ (255 - SP_RGBA32_G_U(color)),
+ (255 - SP_RGBA32_B_U(color)),
+ SP_RGBA32_A_U(color)
+ )
+ );
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "stop-color", c);
+ sp_repr_css_change(child->getRepr(), css, "style");
+ sp_repr_css_attr_unref (css);
+ }
+ }
+}
/**
Set the position of point point_type of the gradient applied to item (either fill_or_stroke) to
@@ -1469,6 +1552,44 @@ SPGradient *sp_gradient_vector_for_object( SPDocument *const doc, SPDesktop *con
return sp_document_default_gradient_vector( doc, color, singleStop );
}
+void sp_gradient_invert_selected_gradients(SPDesktop *desktop, Inkscape::PaintTarget fill_or_stroke)
+{
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
+
+ for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
+ sp_item_gradient_invert_vector_color(SP_ITEM(i->data), fill_or_stroke);
+ }
+
+ // we did an undoable action
+ DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_GRADIENT,
+ _("Invert gradient colors"));
+}
+
+void sp_gradient_reverse_selected_gradients(SPDesktop *desktop)
+{
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
+ SPEventContext *ev = sp_desktop_event_context(desktop);
+
+ if (!ev) {
+ return;
+ }
+
+ GrDrag *drag = ev->get_drag();
+
+ // First try selected dragger
+ if (drag && drag->selected) {
+ drag->selected_reverse_vector();
+ } else { // If no drag or no dragger selected, act on selection (both fill and stroke gradients)
+ for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
+ sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_FILL);
+ sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_STROKE);
+ }
+ }
+
+ // we did an undoable action
+ DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_GRADIENT,
+ _("Reverse gradient"));
+}
/*
Local Variables:
diff --git a/src/gradient-chemistry.h b/src/gradient-chemistry.h
index 2f3ea4303..50422458c 100644
--- a/src/gradient-chemistry.h
+++ b/src/gradient-chemistry.h
@@ -70,6 +70,9 @@ SPStop *sp_vector_add_stop(SPGradient *vector, SPStop* prev_stop, SPStop* next_s
void sp_gradient_transform_multiply(SPGradient *gradient, Geom::Affine postmul, bool set);
+void sp_gradient_reverse_selected_gradients(SPDesktop *desktop);
+
+void sp_gradient_invert_selected_gradients(SPDesktop *desktop, Inkscape::PaintTarget fill_or_stroke);
/**
* Fetches either the fill or the stroke gradient from the given item.
@@ -97,6 +100,7 @@ void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint
guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke);
void sp_item_gradient_edit_stop(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke);
void sp_item_gradient_reverse_vector(SPItem *item, Inkscape::PaintTarget fill_or_stroke);
+void sp_item_gradient_invert_vector_color(SPItem *item, Inkscape::PaintTarget fill_or_stroke);
#endif // SEEN_SP_GRADIENT_CHEMISTRY_H
diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp
index aa8c8b929..5b0e261de 100644
--- a/src/gradient-context.cpp
+++ b/src/gradient-context.cpp
@@ -837,18 +837,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event)
case GDK_KEY_r:
case GDK_KEY_R:
if (MOD__SHIFT_ONLY) {
- // First try selected dragger
- if (drag && drag->selected) {
- drag->selected_reverse_vector();
- } else { // If no drag or no dragger selected, act on selection (both fill and stroke gradients)
- for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
- sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_FILL);
- sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_STROKE);
- }
- }
- // we did an undoable action
- DocumentUndo::done(sp_desktop_document (desktop), SP_VERB_CONTEXT_GRADIENT,
- _("Invert gradient"));
+ sp_gradient_reverse_selected_gradients(desktop);
ret = TRUE;
}
break;
diff --git a/src/id-clash.cpp b/src/id-clash.cpp
index d8299652b..7a1e000fb 100644
--- a/src/id-clash.cpp
+++ b/src/id-clash.cpp
@@ -26,6 +26,7 @@
#include "xml/node.h"
#include "xml/repr.h"
#include "sp-root.h"
+#include "sp-gradient.h"
typedef enum { REF_HREF, REF_STYLE, REF_URL, REF_CLIPBOARD } ID_REF_TYPE;
@@ -259,10 +260,9 @@ fix_up_refs(const refmap_type *refmap, const id_changelist_type &id_changes)
gchar *url = g_strdup_printf("url(#%s)", obj->getId());
sp_repr_css_set_property(style, it->attr, url);
g_free(url);
- gchar *style_string = sp_repr_css_write_string(style);
- it->elem->getRepr()->setAttribute("style", style_string);
- g_free(style_string);
-
+ Glib::ustring style_string;
+ sp_repr_css_write_string(style, style_string);
+ it->elem->getRepr()->setAttribute("style", style_string.c_str());
} else {
g_assert(0); // shouldn't happen
}
@@ -292,6 +292,33 @@ prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc)
}
/*
+ * Change any references of svg:def from_obj into to_obj
+ */
+void
+change_def_references(SPObject *from_obj, SPObject *to_obj)
+{
+ refmap_type *refmap = new refmap_type;
+ id_changelist_type id_changes;
+ SPDocument *current_doc = from_obj->document;
+ std::string old_id(from_obj->getId());
+
+ find_references(current_doc->getRoot(), refmap);
+
+ refmap_type::const_iterator pos = refmap->find(old_id);
+ if (pos != refmap->end()) {
+ std::list<IdReference>::const_iterator it;
+ const std::list<IdReference>::const_iterator it_end = pos->second.end();
+ for (it = pos->second.begin(); it != it_end; ++it) {
+ if (it->type == REF_STYLE) {
+ sp_style_set_property_url(it->elem, it->attr, to_obj, false);
+ }
+ }
+ }
+
+ delete refmap;
+}
+
+/*
* Change the id of a SPObject to new_name
* If there is an id clash then rename to something similar
*/
diff --git a/src/id-clash.h b/src/id-clash.h
index de3cd29d3..f93bd3d72 100644
--- a/src/id-clash.h
+++ b/src/id-clash.h
@@ -5,6 +5,7 @@
void prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc);
void rename_id(SPObject *elem, Glib::ustring const &newname);
+void change_def_references(SPObject *replace_obj, SPObject *with_obj);
#endif /* !SEEN_ID_CLASH_H */
diff --git a/src/ink-comboboxentry-action.cpp b/src/ink-comboboxentry-action.cpp
index 869296f87..99a48ae5d 100644
--- a/src/ink-comboboxentry-action.cpp
+++ b/src/ink-comboboxentry-action.cpp
@@ -27,6 +27,7 @@
#include <string.h>
#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
#include "ink-comboboxentry-action.h"
@@ -42,6 +43,7 @@ static gint check_comma_separated_text( Ink_ComboBoxEntry_Action* action );
static void combo_box_changed_cb( GtkComboBox* widget, gpointer data );
static void entry_activate_cb( GtkEntry* widget, gpointer data );
static gboolean match_selected_cb( GtkEntryCompletion* widget, GtkTreeModel* model, GtkTreeIter* iter, gpointer data );
+static gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data );
enum {
PROP_MODEL = 1,
@@ -50,7 +52,8 @@ enum {
PROP_ENTRY_WIDTH,
PROP_EXTRA_WIDTH,
PROP_CELL_DATA_FUNC,
- PROP_POPUP
+ PROP_POPUP,
+ PROP_FOCUS_WIDGET
};
enum {
@@ -105,6 +108,11 @@ static void ink_comboboxentry_action_set_property (GObject *object, guint proper
action->popup = g_value_get_boolean( value );
break;
+ case PROP_FOCUS_WIDGET:
+ action->focusWidget = (GtkWidget*)g_value_get_pointer( value );
+ break;
+
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@@ -145,6 +153,11 @@ static void ink_comboboxentry_action_get_property (GObject *object, guint proper
g_value_set_boolean (value, action->popup);
break;
+ case PROP_FOCUS_WIDGET:
+ g_value_set_pointer (value, action->focusWidget);
+ break;
+
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@@ -240,6 +253,13 @@ static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass *
false,
(GParamFlags)G_PARAM_READWRITE));
+ g_object_class_install_property( gobject_class,
+ PROP_FOCUS_WIDGET,
+ g_param_spec_pointer( "focus-widget",
+ "Focus Widget",
+ "The widget to return focus to",
+ (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
+
// We need to know when GtkComboBoxEvent or Menu ready for reading
signals[CHANGED] = g_signal_new( "changed",
G_TYPE_FROM_CLASS(klass),
@@ -269,6 +289,7 @@ static void ink_comboboxentry_action_init (Ink_ComboBoxEntry_Action *action)
action->popup = false;
action->warning = NULL;
action->altx_name = NULL;
+ action->focusWidget = NULL;
}
GType ink_comboboxentry_action_get_type ()
@@ -306,7 +327,8 @@ Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new (const gchar *name,
GtkTreeModel *model,
gint entry_width,
gint extra_width,
- void *cell_data_func )
+ void *cell_data_func,
+ GtkWidget *focusWidget)
{
g_return_val_if_fail (name != NULL, NULL);
@@ -319,6 +341,7 @@ Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new (const gchar *name,
"entry_width", entry_width,
"extra_width", extra_width,
"cell_data_func", cell_data_func,
+ "focus-widget", focusWidget,
NULL);
}
@@ -415,6 +438,7 @@ GtkWidget* create_tool_item( GtkAction* action )
// Add signal for GtkEntry to check if finished typing.
g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(entry_activate_cb), action );
+ g_signal_connect( G_OBJECT(child), "key-press-event", G_CALLBACK(keypress_cb), action );
}
@@ -561,6 +585,7 @@ void ink_comboboxentry_action_popup_enable( Ink_ComboBoxEntry_Action* action ) {
g_signal_connect (G_OBJECT (action->entry_completion), "match-selected", G_CALLBACK (match_selected_cb), action );
+
}
}
@@ -764,3 +789,43 @@ static gboolean match_selected_cb( GtkEntryCompletion* /*widget*/, GtkTreeModel*
return false;
}
+void ink_comboboxentry_action_defocus( Ink_ComboBoxEntry_Action* action )
+{
+ if ( action->focusWidget ) {
+ gtk_widget_grab_focus( action->focusWidget );
+ }
+}
+
+gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data )
+{
+ gboolean wasConsumed = FALSE; /* default to report event not consumed */
+ guint key = 0;
+ Ink_ComboBoxEntry_Action* action = INK_COMBOBOXENTRY_ACTION( data );
+ gdk_keymap_translate_keyboard_state( gdk_keymap_get_for_display( gdk_display_get_default() ),
+ event->hardware_keycode, (GdkModifierType)event->state,
+ 0, &key, 0, 0, 0 );
+
+ switch ( key ) {
+
+ // TODO Add bindings for Tab/LeftTab
+ case GDK_KEY_Escape:
+ {
+ //gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), action->private_data->lastVal );
+ ink_comboboxentry_action_defocus( action );
+ wasConsumed = TRUE;
+ }
+ break;
+
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ {
+ ink_comboboxentry_action_defocus( action );
+ //wasConsumed = TRUE;
+ }
+ break;
+
+
+ }
+
+ return wasConsumed;
+}
diff --git a/src/ink-comboboxentry-action.h b/src/ink-comboboxentry-action.h
index 95306bcaa..7d4093f4e 100644
--- a/src/ink-comboboxentry-action.h
+++ b/src/ink-comboboxentry-action.h
@@ -59,6 +59,7 @@ struct _Ink_ComboBoxEntry_Action {
gboolean popup; // Do we pop-up an entry-completion dialog?
gchar *warning; // Text for warning that entry isn't in list.
gchar *altx_name; // Target for Alt-X keyboard shortcut.
+ GtkWidget *focusWidget;
};
@@ -74,7 +75,8 @@ Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new ( const gchar *name,
GtkTreeModel *model,
gint entry_width = -1,
gint extra_width = -1,
- gpointer cell_data_func = NULL );
+ gpointer cell_data_func = NULL,
+ GtkWidget* focusWidget = NULL);
GtkTreeModel *ink_comboboxentry_action_get_model( Ink_ComboBoxEntry_Action* action );
GtkComboBox *ink_comboboxentry_action_get_comboboxentry( Ink_ComboBoxEntry_Action* action );
diff --git a/src/interface.cpp b/src/interface.cpp
index b10ba3077..fdfdce5ae 100644
--- a/src/interface.cpp
+++ b/src/interface.cpp
@@ -79,6 +79,7 @@
// #include "inkscape.h"
#include "ui/dialog/dialog-manager.h"
// #include "../xml/repr.h"
+#include "ui/dialog/layer-properties.h"
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
@@ -322,6 +323,7 @@ sp_ui_close_view(GtkWidget */*widget*/)
SPDocument *doc = SPDocument::createNewDoc( templateUri.c_str() , TRUE, true );
dt->change_document(doc);
sp_namedview_window_from_document(dt);
+ sp_namedview_update_layers_from_document(dt);
return;
}
@@ -1766,15 +1768,16 @@ void ContextMenu::MakeItemMenu (void)
AddSeparator();
/* Select item */
- mi = manage(new Gtk::MenuItem(_("_Select This"),1));
- if (_desktop->selection->includes(_item)) {
- mi->set_sensitive(FALSE);
- } else {
- mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemSelectThis));
+ if (Inkscape::Verb::getbyid( "org.inkscape.followlink" )) {
+ mi = manage(new Gtk::MenuItem(_("_Select This"),1));
+ if (_desktop->selection->includes(_item)) {
+ mi->set_sensitive(FALSE);
+ } else {
+ mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemSelectThis));
+ }
+ mi->show();
+ append(*mi);
}
- mi->show();
- append(*mi);
-
mi = manage(new Gtk::MenuItem(_("Select Same")));
@@ -1821,6 +1824,16 @@ void ContextMenu::MakeItemMenu (void)
mi->show();
select_same_submenu->append(*mi);
+ /* Move to layer */
+ mi = manage(new Gtk::MenuItem(_("_Move to layer ..."),1));
+ if (_desktop->selection->isEmpty()) {
+ mi->set_sensitive(FALSE);
+ } else {
+ mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemMoveTo));
+ }
+ mi->show();
+ append(*mi);
+
/* Create link */
mi = manage(new Gtk::MenuItem(_("Create _Link"),1));
mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemCreateLink));
@@ -1936,6 +1949,13 @@ void ContextMenu::ItemSelectThis(void)
_desktop->selection->set(_item);
}
+void ContextMenu::ItemMoveTo(void)
+{
+ Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(_desktop, _desktop->currentLayer());
+}
+
+
+
void ContextMenu::ItemCreateLink(void)
{
Inkscape::XML::Document *xml_doc = _desktop->doc()->getReprDoc();
@@ -2034,7 +2054,18 @@ void ContextMenu::AnchorLinkProperties(void)
void ContextMenu::AnchorLinkFollow(void)
{
- /* shell out to an external browser here */
+
+ if (_desktop->selection->isEmpty()) {
+ _desktop->selection->set(_item);
+ }
+ // Opening the selected links with a python extension
+ Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.inkscape.followlink" );
+ if (verb) {
+ SPAction *action = verb->get_action(_desktop);
+ if (action) {
+ sp_action_perform(action, NULL);
+ }
+ }
}
void ContextMenu::AnchorLinkRemove(void)
@@ -2066,6 +2097,15 @@ void ContextMenu::MakeImageMenu (void)
mi->set_sensitive( FALSE );
}
+ /* Trace Bitmap */
+ mi = manage(new Gtk::MenuItem(_("_Trace Bitmap..."),1));
+ mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageTraceBitmap));
+ mi->show();
+ insert(*mi,positionOfLastDialog++);
+ if (_desktop->selection->isEmpty()) {
+ mi->set_sensitive(FALSE);
+ }
+
/* Embed image */
if (Inkscape::Verb::getbyid( "org.ekips.filter.embedselectedimages" )) {
mi = manage(new Gtk::MenuItem(C_("Context menu", "Embed Image")));
@@ -2177,6 +2217,12 @@ void ContextMenu::ImageEdit(void)
}
}
+void ContextMenu::ImageTraceBitmap(void)
+{
+ inkscape_dialogs_unhide();
+ _desktop->_dlg_mgr->showDialog("Trace");
+}
+
void ContextMenu::ImageEmbed(void)
{
if (_desktop->selection->isEmpty()) {
diff --git a/src/interface.h b/src/interface.h
index aa0281db3..891e39957 100644
--- a/src/interface.h
+++ b/src/interface.h
@@ -171,6 +171,7 @@ class ContextMenu : public Gtk::Menu
//callbacks for the context menu entries of an SP_TYPE_ITEM object
void ItemProperties(void);
void ItemSelectThis(void);
+ void ItemMoveTo(void);
void SelectSameFillStroke(void);
void SelectSameFillColor(void);
void SelectSameStrokeColor(void);
@@ -224,6 +225,11 @@ class ContextMenu : public Gtk::Menu
void ImageEmbed(void);
/**
+ * callback, is executed on clicking the "Trace Bitmap" menu entry
+ */
+ void ImageTraceBitmap(void);
+
+ /**
* callback, is executed on clicking the "Extract Image" menu entry
*/
void ImageExtract(void);
diff --git a/src/marker.cpp b/src/marker.cpp
index a5681e180..45582caa4 100644
--- a/src/marker.cpp
+++ b/src/marker.cpp
@@ -27,6 +27,7 @@
#include "marker.h"
#include "document.h"
#include "document-private.h"
+#include "preferences.h"
struct SPMarkerView {
SPMarkerView *next;
@@ -727,6 +728,38 @@ const gchar *generate_marker(GSList *reprs, Geom::Rect bounds, SPDocument *docum
return mark_id;
}
+SPObject *sp_marker_fork_if_necessary(SPObject *marker)
+{
+ if (marker->hrefcount < 2) {
+ return marker;
+ }
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ gboolean colorStock = prefs->getBool("/options/markers/colorStockMarkers", true);
+ gboolean colorCustom = prefs->getBool("/options/markers/colorCustomMarkers", false);
+ const gchar *stock = marker->getRepr()->attribute("inkscape:isstock");
+ gboolean isStock = (!stock || !strcmp(stock,"true"));
+
+ if (isStock ? !colorStock : !colorCustom) {
+ return marker;
+ }
+
+ SPDocument *doc = marker->document;
+ Inkscape::XML::Document *xml_doc = doc->getReprDoc();
+ // Turn off garbage-collectable or it might be collected before we can use it
+ marker->getRepr()->setAttribute("inkscape:collect", NULL);
+ Inkscape::XML::Node *mark_repr = marker->getRepr()->duplicate(xml_doc);
+ doc->getDefs()->getRepr()->addChild(mark_repr, NULL);
+ if (!mark_repr->attribute("inkscape:stockid")) {
+ mark_repr->setAttribute("inkscape:stockid", mark_repr->attribute("id"));
+ }
+ marker->getRepr()->setAttribute("inkscape:collect", "always");
+
+ SPObject *marker_new = static_cast<SPObject *>(doc->getObjectByRepr(mark_repr));
+ Inkscape::GC::release(mark_repr);
+ return marker_new;
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/marker.h b/src/marker.h
index 6fdb82aa3..e8d2dd9a1 100644
--- a/src/marker.h
+++ b/src/marker.h
@@ -90,6 +90,6 @@ Inkscape::DrawingItem *sp_marker_show_instance (SPMarker *marker, Inkscape::Draw
Geom::Affine const &base, float linewidth);
void sp_marker_hide (SPMarker *marker, unsigned int key);
const gchar *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move);
-
+SPObject *sp_marker_fork_if_necessary(SPObject *marker);
#endif
diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h
index 999fb52fc..09366a33f 100644
--- a/src/menus-skeleton.h
+++ b/src/menus-skeleton.h
@@ -167,6 +167,7 @@ static char const menus_skeleton[] =
" <separator/>\n"
" <verb verb-id=\"LayerMoveToNext\" />\n"
" <verb verb-id=\"LayerMoveToPrev\" />\n"
+" <verb verb-id=\"LayerMoveTo\" />\n"
" <separator/>\n"
" <verb verb-id=\"LayerRaise\" />\n"
" <verb verb-id=\"LayerLower\" />\n"
diff --git a/src/preferences.cpp b/src/preferences.cpp
index 4615fd6e1..1f985a629 100644
--- a/src/preferences.cpp
+++ b/src/preferences.cpp
@@ -489,18 +489,18 @@ void Preferences::setString(Glib::ustring const &pref_path, Glib::ustring const
void Preferences::setStyle(Glib::ustring const &pref_path, SPCSSAttr *style)
{
- gchar *css_str = sp_repr_css_write_string(style);
- _setRawValue(pref_path, css_str);
- g_free(css_str);
+ Glib::ustring css_str;
+ sp_repr_css_write_string(style, css_str);
+ _setRawValue(pref_path, css_str.c_str());
}
void Preferences::mergeStyle(Glib::ustring const &pref_path, SPCSSAttr *style)
{
SPCSSAttr *current = getStyle(pref_path);
sp_repr_css_merge(current, style);
- gchar *css_str = sp_repr_css_write_string(current);
- _setRawValue(pref_path, css_str);
- g_free(css_str);
+ Glib::ustring css_str;
+ sp_repr_css_write_string(current, css_str);
+ _setRawValue(pref_path, css_str.c_str());
sp_repr_css_attr_unref(current);
}
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 068928d8f..4cdab4336 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -1314,6 +1314,36 @@ void sp_selection_to_prev_layer(SPDesktop *dt, bool suppressDone)
g_slist_free(const_cast<GSList *>(items));
}
+void sp_selection_to_layer(SPDesktop *dt, SPObject *moveto, bool suppressDone)
+{
+ Inkscape::Selection *selection = sp_desktop_selection(dt);
+
+ // check if something is selected
+ if (selection->isEmpty()) {
+ dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to move."));
+ return;
+ }
+
+ GSList const *items = g_slist_copy(const_cast<GSList *>(selection->itemList()));
+
+ if (moveto) {
+ GSList *temp_clip = NULL;
+ sp_selection_copy_impl(items, &temp_clip, dt->doc()->getReprDoc()); // we're in the same doc, so no need to copy defs
+ sp_selection_delete_impl(items, false, false);
+ GSList *copied = sp_selection_paste_impl(sp_desktop_document(dt), moveto, &temp_clip);
+ selection->setReprList((GSList const *) copied);
+ g_slist_free(copied);
+ if (temp_clip) g_slist_free(temp_clip);
+ if (moveto) dt->setCurrentLayer(moveto);
+ if ( !suppressDone ) {
+ DocumentUndo::done(sp_desktop_document(dt), SP_VERB_LAYER_MOVE_TO,
+ _("Move selection to layer"));
+ }
+ }
+
+ g_slist_free(const_cast<GSList *>(items));
+}
+
bool
selection_contains_original(SPItem *item, Inkscape::Selection *selection)
{
diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h
index 0ae2a9b06..3c9c1aea9 100644
--- a/src/selection-chemistry.h
+++ b/src/selection-chemistry.h
@@ -97,6 +97,7 @@ void sp_selection_paste_size_separately(SPDesktop *desktop, bool apply_x, bool a
void sp_selection_to_next_layer( SPDesktop *desktop, bool suppressDone = false );
void sp_selection_to_prev_layer( SPDesktop *desktop, bool suppressDone = false );
+void sp_selection_to_layer( SPDesktop *desktop, SPObject *layer, bool suppressDone = false );
void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d = true, bool compensate = true);
void sp_selection_remove_transform (SPDesktop *desktop);
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index 262c35db1..5efa3c84f 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -346,6 +346,41 @@ void SPGradient::setSwatch( bool swatch )
}
}
+
+/**
+ * return true if this gradient is "equivalent" to that gradient.
+ * Equivalent meaning they have the same stop count, same stop colors and same stop opacity
+ * @param that - A gradient to compare this to
+ */
+gboolean SPGradient::isEquivalent(SPGradient *that)
+{
+ //TODO Make this work for mesh gradients
+
+ if (this->getStopCount() != that->getStopCount())
+ return FALSE;
+
+ if (this->hasStops() != that->hasStops())
+ return FALSE;
+
+ if (!this->getVector() || !that->getVector())
+ return FALSE;
+
+ SPStop *as = this->getVector()->getFirstStop();
+ SPStop *bs = that->getVector()->getFirstStop();
+
+ while (as && bs) {
+ if (!as->getEffectiveColor().isClose(bs->getEffectiveColor(), 0.001) ||
+ as->offset != bs->offset) {
+ return FALSE;
+ }
+ as = as->getNextStop();
+ bs = bs->getNextStop();
+ }
+
+ return TRUE;
+}
+
+
/**
* Return stop's color as 32bit value.
*/
@@ -2211,6 +2246,7 @@ sp_meshgradient_repr_write(SPMeshGradient *mg)
mg->array.write( mg );
}
+
/*
Local Variables:
mode:c++
diff --git a/src/sp-gradient.h b/src/sp-gradient.h
index 61b459eee..a21a413f4 100644
--- a/src/sp-gradient.h
+++ b/src/sp-gradient.h
@@ -143,6 +143,7 @@ public:
SPStop* getFirstStop();
int getStopCount() const;
+ gboolean isEquivalent(SPGradient *b);
/** Mesh Gradients **************/
diff --git a/src/sp-object.cpp b/src/sp-object.cpp
index 892c89a15..9ceeaf262 100644
--- a/src/sp-object.cpp
+++ b/src/sp-object.cpp
@@ -1031,15 +1031,9 @@ Inkscape::XML::Node * SPObject::sp_object_private_write(SPObject *object, Inksca
if( prefs->getBool("/options/svgoutput/check_on_editing") ) {
unsigned int flags = sp_attribute_clean_get_prefs();
- gchar *s_cleaned = sp_attribute_clean_style( repr, s, flags );
-
- // g_warning("SPObject::sp_object_private_write: %s", object->getId() );
- // g_warning(" old: :%s:", repr->attribute("style") );
- // g_warning(" new: :%s:", s );
- // g_warning(" cleaned: :%s:", s_cleaned );
-
+ Glib::ustring s_cleaned = sp_attribute_clean_style( repr, s, flags );
g_free( s );
- s = s_cleaned;
+ s = (s_cleaned.empty() ? NULL : g_strdup (s_cleaned.c_str()));
}
if( s == NULL || strcmp(s,"") == 0 ) {
diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp
index f27b3c9db..a9a9c7781 100644
--- a/src/sp-shape.cpp
+++ b/src/sp-shape.cpp
@@ -614,7 +614,7 @@ Geom::OptRect SPShape::sp_shape_bbox(SPItem const *item, Geom::Affine const &tra
tr = Geom::Scale(style->stroke_width.computed) * tr;
}
tr = marker_item->transform * marker->c2p * tr * transform;
- bbox |= marker_item->visualBounds();
+ bbox |= marker_item->visualBounds(tr);
}
}
}
diff --git a/src/style.cpp b/src/style.cpp
index ba720d538..ab8b646aa 100644
--- a/src/style.cpp
+++ b/src/style.cpp
@@ -3892,10 +3892,9 @@ sp_style_write_istring(gchar *p, gint const len, gchar const *const key,
if (val->inherit) {
res = g_snprintf(p, len, "%s:inherit;", key);
} else {
- gchar *val_quoted = css2_escape_quote(val->value);
- if (val_quoted) {
- res = g_snprintf(p, len, "%s:%s;", key, val_quoted);
- g_free (val_quoted);
+ Glib::ustring val_quoted = css2_escape_quote(val->value);
+ if (~val_quoted.empty()) {
+ res = g_snprintf(p, len, "%s:%s;", key, val_quoted.c_str());
}
}
}
@@ -4712,8 +4711,7 @@ attribute_unquote(gchar const *val)
/**
* Quote and/or escape string for writing to CSS (style=). Returned value must be g_free'd.
*/
-gchar *
-css2_escape_quote(gchar const *val) {
+Glib::ustring css2_escape_quote(gchar const *val) {
Glib::ustring t;
bool quote = false;
@@ -4757,7 +4755,7 @@ css2_escape_quote(gchar const *val) {
t.push_back('\'');
}
- return (t.empty() ? NULL : g_strdup (t.c_str()));
+ return t;
}
/*
diff --git a/src/style.h b/src/style.h
index eeb742c00..5b7fb559a 100644
--- a/src/style.h
+++ b/src/style.h
@@ -622,7 +622,7 @@ void sp_style_unset_property_attrs(SPObject *o);
void sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *linked, bool recursive);
gchar *attribute_unquote(gchar const *val);
-gchar *css2_escape_quote(gchar const *val);
+Glib::ustring css2_escape_quote(gchar const *val);
#endif // SEEN_SP_STYLE_H
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index c7be0877d..7bd1b81c0 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -959,16 +959,18 @@ void DocumentProperties::removeEmbeddedScript(){
const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
while ( current ) {
- SPObject* obj = SP_OBJECT(current->data);
- if (id == obj->getId()){
+ if (current->data && SP_IS_OBJECT(current->data)) {
+ SPObject* obj = SP_OBJECT(current->data);
+ if (id == obj->getId()){
- //XML Tree being used directly here while it shouldn't be.
- Inkscape::XML::Node *repr = obj->getRepr();
- if (repr){
- sp_repr_unparent(repr);
+ //XML Tree being used directly here while it shouldn't be.
+ Inkscape::XML::Node *repr = obj->getRepr();
+ if (repr){
+ sp_repr_unparent(repr);
- // inform the document, so we can undo
- DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EMBEDDED_SCRIPT, _("Remove embedded script"));
+ // inform the document, so we can undo
+ DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EMBEDDED_SCRIPT, _("Remove embedded script"));
+ }
}
}
current = g_slist_next(current);
diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp
index 74c19fea7..c7efd3bf2 100644
--- a/src/ui/dialog/fill-and-stroke.cpp
+++ b/src/ui/dialog/fill-and-stroke.cpp
@@ -63,7 +63,7 @@ FillAndStroke::FillAndStroke()
_layoutPageStrokePaint();
_layoutPageStrokeStyle();
- contents->pack_start(_composite_settings, false, false, 0);
+ contents->pack_start(_composite_settings, true, true, 0);
show_all_children();
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index 317cb2773..c3c44f6c3 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -78,8 +78,8 @@ namespace Dialog {
using Inkscape::UI::Widget::AttrWidget;
using Inkscape::UI::Widget::ComboBoxEnum;
-using Inkscape::UI::Widget::DualSpinSlider;
-using Inkscape::UI::Widget::SpinSlider;
+using Inkscape::UI::Widget::DualSpinScale;
+using Inkscape::UI::Widget::SpinScale;
// Returns the number of inputs available for the filter primitive type
@@ -484,8 +484,8 @@ public:
: AttrWidget(SP_ATTR_VALUES),
// TRANSLATORS: this dialog is accessible via menu Filters - Filter editor
_matrix(SP_ATTR_VALUES, _("This matrix determines a linear transform on color space. Each line affects one of the color components. Each column determines how much of each color component from the input is passed to the output. The last column does not depend on input colors, so can be used to adjust a constant component value.")),
- _saturation(0, 0, 1, 0.1, 0.01, 2, SP_ATTR_VALUES),
- _angle(0, 0, 360, 0.1, 0.01, 1, SP_ATTR_VALUES),
+ _saturation("", 0, 0, 1, 0.1, 0.01, 2, SP_ATTR_VALUES),
+ _angle("", 0, 0, 360, 0.1, 0.01, 1, SP_ATTR_VALUES),
_label(_("None"), Gtk::ALIGN_START),
_use_stored(false),
_saturation_store(0),
@@ -567,8 +567,8 @@ private:
}
MatrixAttr _matrix;
- SpinSlider _saturation;
- SpinSlider _angle;
+ SpinScale _saturation;
+ SpinScale _angle;
Gtk::Label _label;
// Store separate values for the different color modes
@@ -808,22 +808,22 @@ public:
return cmv;
}
- // SpinSlider
- SpinSlider* add_spinslider(double def, const SPAttributeEnum attr, const Glib::ustring& label,
+ // SpinScale
+ SpinScale* add_spinscale(double def, const SPAttributeEnum attr, const Glib::ustring& label,
const double lo, const double hi, const double step_inc, const double climb, const int digits, char* tip_text = NULL)
{
- SpinSlider* spinslider = new SpinSlider(def, lo, hi, step_inc, climb, digits, attr, tip_text);
+ SpinScale* spinslider = new SpinScale("", def, lo, hi, step_inc, climb, digits, attr, tip_text);
add_widget(spinslider, label);
add_attr_widget(spinslider);
return spinslider;
}
- // DualSpinSlider
- DualSpinSlider* add_dualspinslider(const SPAttributeEnum attr, const Glib::ustring& label,
+ // DualSpinScale
+ DualSpinScale* add_dualspinscale(const SPAttributeEnum attr, const Glib::ustring& label,
const double lo, const double hi, const double step_inc,
const double climb, const int digits, char* tip_text1 = NULL, char* tip_text2 = NULL)
{
- DualSpinSlider* dss = new DualSpinSlider(lo, lo, hi, step_inc, climb, digits, attr, tip_text1, tip_text2);
+ DualSpinScale* dss = new DualSpinScale("", "", lo, lo, hi, step_inc, climb, digits, attr, tip_text1, tip_text2);
add_widget(dss, label);
add_attr_widget(dss);
return dss;
@@ -971,8 +971,8 @@ public:
// FIXME: these range values are complete crap
_settings.type(LIGHT_DISTANT);
- _settings.add_spinslider(0, SP_ATTR_AZIMUTH, _("Azimuth"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the XY plane, in degrees"));
- _settings.add_spinslider(0, SP_ATTR_ELEVATION, _("Elevation"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the YZ plane, in degrees"));
+ _settings.add_spinscale(0, SP_ATTR_AZIMUTH, _("Azimuth"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the XY plane, in degrees"));
+ _settings.add_spinscale(0, SP_ATTR_ELEVATION, _("Elevation"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the YZ plane, in degrees"));
_settings.type(LIGHT_POINT);
_settings.add_multispinbutton(/*default x:*/ (double) 0, /*default y:*/ (double) 0, /*default z:*/ (double) 0, SP_ATTR_X, SP_ATTR_Y, SP_ATTR_Z, _("Location:"), -99999, 99999, 1, 100, 0, _("X coordinate"), _("Y coordinate"), _("Z coordinate"));
@@ -982,9 +982,9 @@ public:
_settings.add_multispinbutton(/*default x:*/ (double) 0, /*default y:*/ (double) 0, /*default z:*/ (double) 0,
SP_ATTR_POINTSATX, SP_ATTR_POINTSATY, SP_ATTR_POINTSATZ,
_("Points At"), -99999, 99999, 1, 100, 0, _("X coordinate"), _("Y coordinate"), _("Z coordinate"));
- _settings.add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Specular Exponent"), 1, 100, 1, 1, 0, _("Exponent value controlling the focus for the light source"));
+ _settings.add_spinscale(1, SP_ATTR_SPECULAREXPONENT, _("Specular Exponent"), 1, 100, 1, 1, 0, _("Exponent value controlling the focus for the light source"));
//TODO: here I have used 100 degrees as default value. But spec says that if not specified, no limiting cone is applied. So, there should be a way for the user to set a "no limiting cone" option.
- _settings.add_spinslider(100, SP_ATTR_LIMITINGCONEANGLE, _("Cone Angle"), 1, 100, 1, 1, 0, _("This is the angle between the spot light axis (i.e. the axis between the light source and the point to which it is pointing at) and the spot light cone. No light is projected outside this cone."));
+ _settings.add_spinscale(100, SP_ATTR_LIMITINGCONEANGLE, _("Cone Angle"), 1, 100, 1, 1, 0, _("This is the angle between the spot light axis (i.e. the axis between the light source and the point to which it is pointing at) and the spot light cone. No light is projected outside this cone."));
}
Gtk::VBox& get_box()
@@ -2331,7 +2331,7 @@ void FilterEffectsDialog::show_all_vfunc()
void FilterEffectsDialog::init_settings_widgets()
{
- // TODO: Find better range/climb-rate/digits values for the SpinSliders,
+ // TODO: Find better range/climb-rate/digits values for the SpinScales,
// most of the current values are complete guesses!
_empty_settings.set_sensitive(false);
@@ -2358,18 +2358,18 @@ void FilterEffectsDialog::init_settings_widgets()
/*
//TRANSLATORS: for info on "Slope" and "Intercept", see http://id.mind.net/~zona/mmts/functionInstitute/linearFunctions/lsif.html
_settings->add_combo(COMPONENTTRANSFER_TYPE_IDENTITY, SP_ATTR_TYPE, _("Type"), ComponentTransferTypeConverter);
- _ct_slope = _settings->add_spinslider(1, SP_ATTR_SLOPE, _("Slope"), -10, 10, 0.1, 0.01, 2);
- _ct_intercept = _settings->add_spinslider(0, SP_ATTR_INTERCEPT, _("Intercept"), -10, 10, 0.1, 0.01, 2);
- _ct_amplitude = _settings->add_spinslider(1, SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 10, 0.1, 0.01, 2);
- _ct_exponent = _settings->add_spinslider(1, SP_ATTR_EXPONENT, _("Exponent"), 0, 10, 0.1, 0.01, 2);
- _ct_offset = _settings->add_spinslider(0, SP_ATTR_OFFSET, _("Offset"), -10, 10, 0.1, 0.01, 2);*/
+ _ct_slope = _settings->add_spinscale(1, SP_ATTR_SLOPE, _("Slope"), -10, 10, 0.1, 0.01, 2);
+ _ct_intercept = _settings->add_spinscale(0, SP_ATTR_INTERCEPT, _("Intercept"), -10, 10, 0.1, 0.01, 2);
+ _ct_amplitude = _settings->add_spinscale(1, SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 10, 0.1, 0.01, 2);
+ _ct_exponent = _settings->add_spinscale(1, SP_ATTR_EXPONENT, _("Exponent"), 0, 10, 0.1, 0.01, 2);
+ _ct_offset = _settings->add_spinscale(0, SP_ATTR_OFFSET, _("Offset"), -10, 10, 0.1, 0.01, 2);*/
_settings->type(NR_FILTER_COMPOSITE);
_settings->add_combo(COMPOSITE_OVER, SP_ATTR_OPERATOR, _("Operator:"), CompositeOperatorConverter);
- _k1 = _settings->add_spinslider(0, SP_ATTR_K1, _("K1:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively."));
- _k2 = _settings->add_spinslider(0, SP_ATTR_K2, _("K2:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively."));
- _k3 = _settings->add_spinslider(0, SP_ATTR_K3, _("K3:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively."));
- _k4 = _settings->add_spinslider(0, SP_ATTR_K4, _("K4:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively."));
+ _k1 = _settings->add_spinscale(0, SP_ATTR_K1, _("K1:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively."));
+ _k2 = _settings->add_spinscale(0, SP_ATTR_K2, _("K2:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively."));
+ _k3 = _settings->add_spinscale(0, SP_ATTR_K3, _("K3:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively."));
+ _k4 = _settings->add_spinscale(0, SP_ATTR_K4, _("K4:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively."));
_settings->type(NR_FILTER_CONVOLVEMATRIX);
_convolve_order = _settings->add_dualspinbutton((char*)"3", SP_ATTR_ORDER, _("Size:"), 1, 5, 1, 1, 0, _("width of the convolve matrix"), _("height of the convolve matrix"));
@@ -2377,50 +2377,50 @@ void FilterEffectsDialog::init_settings_widgets()
//TRANSLATORS: for info on "Kernel", see http://en.wikipedia.org/wiki/Kernel_(matrix)
_convolve_matrix = _settings->add_matrix(SP_ATTR_KERNELMATRIX, _("Kernel:"), _("This matrix describes the convolve operation that is applied to the input image in order to calculate the pixel colors at the output. Different arrangements of values in this matrix result in various possible visual effects. An identity matrix would lead to a motion blur effect (parallel to the matrix diagonal) while a matrix filled with a constant non-zero value would lead to a common blur effect."));
_convolve_order->signal_attr_changed().connect(sigc::mem_fun(*this, &FilterEffectsDialog::convolve_order_changed));
- _settings->add_spinslider(0, SP_ATTR_DIVISOR, _("Divisor:"), 0, 1000, 1, 0.1, 2, _("After applying the kernelMatrix to the input image to yield a number, that number is divided by divisor to yield the final destination color value. A divisor that is the sum of all the matrix values tends to have an evening effect on the overall color intensity of the result."));
- _settings->add_spinslider(0, SP_ATTR_BIAS, _("Bias:"), -10, 10, 1, 0.01, 1, _("This value is added to each component. This is useful to define a constant value as the zero response of the filter."));
+ _settings->add_spinscale(0, SP_ATTR_DIVISOR, _("Divisor:"), 0, 1000, 1, 0.1, 2, _("After applying the kernelMatrix to the input image to yield a number, that number is divided by divisor to yield the final destination color value. A divisor that is the sum of all the matrix values tends to have an evening effect on the overall color intensity of the result."));
+ _settings->add_spinscale(0, SP_ATTR_BIAS, _("Bias:"), -10, 10, 1, 0.01, 1, _("This value is added to each component. This is useful to define a constant value as the zero response of the filter."));
_settings->add_combo(CONVOLVEMATRIX_EDGEMODE_DUPLICATE, SP_ATTR_EDGEMODE, _("Edge Mode:"), ConvolveMatrixEdgeModeConverter, _("Determines how to extend the input image as necessary with color values so that the matrix operations can be applied when the kernel is positioned at or near the edge of the input image."));
_settings->add_checkbutton(false, SP_ATTR_PRESERVEALPHA, _("Preserve Alpha"), "true", "false", _("If set, the alpha channel won't be altered by this filter primitive."));
_settings->type(NR_FILTER_DIFFUSELIGHTING);
_settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Diffuse Color:"), _("Defines the color of the light source"));
- _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.01, 0.001, 3, _("This value amplifies the heights of the bump map defined by the input alpha channel"));
- _settings->add_spinslider(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model."));
- _settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1);
+ _settings->add_spinscale(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.01, 0.001, 3, _("This value amplifies the heights of the bump map defined by the input alpha channel"));
+ _settings->add_spinscale(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model."));
+ _settings->add_dualspinscale(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1);
_settings->add_lightsource();
_settings->type(NR_FILTER_DISPLACEMENTMAP);
- _settings->add_spinslider(0, SP_ATTR_SCALE, _("Scale:"), 0, 100, 1, 0.01, 1, _("This defines the intensity of the displacement effect."));
+ _settings->add_spinscale(0, SP_ATTR_SCALE, _("Scale:"), 0, 100, 1, 0.01, 1, _("This defines the intensity of the displacement effect."));
_settings->add_combo(DISPLACEMENTMAP_CHANNEL_ALPHA, SP_ATTR_XCHANNELSELECTOR, _("X displacement:"), DisplacementMapChannelConverter, _("Color component that controls the displacement in the X direction"));
_settings->add_combo(DISPLACEMENTMAP_CHANNEL_ALPHA, SP_ATTR_YCHANNELSELECTOR, _("Y displacement:"), DisplacementMapChannelConverter, _("Color component that controls the displacement in the Y direction"));
_settings->type(NR_FILTER_FLOOD);
_settings->add_color(/*default: black*/ 0, SP_PROP_FLOOD_COLOR, _("Flood Color:"), _("The whole filter region will be filled with this color."));
- _settings->add_spinslider(1, SP_PROP_FLOOD_OPACITY, _("Opacity:"), 0, 1, 0.1, 0.01, 2);
+ _settings->add_spinscale(1, SP_PROP_FLOOD_OPACITY, _("Opacity:"), 0, 1, 0.1, 0.01, 2);
_settings->type(NR_FILTER_GAUSSIANBLUR);
- _settings->add_dualspinslider(SP_ATTR_STDDEVIATION, _("Standard Deviation:"), 0.01, 100, 1, 0.01, 1, _("The standard deviation for the blur operation."));
+ _settings->add_dualspinscale(SP_ATTR_STDDEVIATION, _("Standard Deviation:"), 0.01, 100, 1, 0.01, 1, _("The standard deviation for the blur operation."));
_settings->type(NR_FILTER_MERGE);
_settings->add_no_params();
_settings->type(NR_FILTER_MORPHOLOGY);
_settings->add_combo(MORPHOLOGY_OPERATOR_ERODE, SP_ATTR_OPERATOR, _("Operator:"), MorphologyOperatorConverter, _("Erode: performs \"thinning\" of input image.\nDilate: performs \"fattenning\" of input image."));
- _settings->add_dualspinslider(SP_ATTR_RADIUS, _("Radius:"), 0, 100, 1, 0.01, 1);
+ _settings->add_dualspinscale(SP_ATTR_RADIUS, _("Radius:"), 0, 100, 1, 0.01, 1);
_settings->type(NR_FILTER_IMAGE);
_settings->add_fileorelement(SP_ATTR_XLINK_HREF, _("Source of Image:"));
_settings->type(NR_FILTER_OFFSET);
- _settings->add_spinslider(0, SP_ATTR_DX, _("Delta X:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted to the right"));
- _settings->add_spinslider(0, SP_ATTR_DY, _("Delta Y:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted downwards"));
+ _settings->add_spinscale(0, SP_ATTR_DX, _("Delta X:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted to the right"));
+ _settings->add_spinscale(0, SP_ATTR_DY, _("Delta Y:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted downwards"));
_settings->type(NR_FILTER_SPECULARLIGHTING);
_settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Specular Color:"), _("Defines the color of the light source"));
- _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.1, 0.01, 2, _("This value amplifies the heights of the bump map defined by the input alpha channel"));
- _settings->add_spinslider(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model."));
- _settings->add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 50, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\"."));
- _settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1);
+ _settings->add_spinscale(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.1, 0.01, 2, _("This value amplifies the heights of the bump map defined by the input alpha channel"));
+ _settings->add_spinscale(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model."));
+ _settings->add_spinscale(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 50, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\"."));
+ _settings->add_dualspinscale(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1);
_settings->add_lightsource();
_settings->type(NR_FILTER_TILE);
@@ -2429,9 +2429,9 @@ void FilterEffectsDialog::init_settings_widgets()
_settings->type(NR_FILTER_TURBULENCE);
// _settings->add_checkbutton(false, SP_ATTR_STITCHTILES, _("Stitch Tiles"), "stitch", "noStitch");
_settings->add_combo(TURBULENCE_TURBULENCE, SP_ATTR_TYPE, _("Type:"), TurbulenceTypeConverter, _("Indicates whether the filter primitive should perform a noise or turbulence function."));
- _settings->add_dualspinslider(SP_ATTR_BASEFREQUENCY, _("Base Frequency:"), 0, 1, 0.001, 0.01, 3);
- _settings->add_spinslider(1, SP_ATTR_NUMOCTAVES, _("Octaves:"), 1, 10, 1, 1, 0);
- _settings->add_spinslider(0, SP_ATTR_SEED, _("Seed:"), 0, 1000, 1, 1, 0, _("The starting number for the pseudo random number generator."));
+ _settings->add_dualspinscale(SP_ATTR_BASEFREQUENCY, _("Base Frequency:"), 0, 1, 0.001, 0.01, 3);
+ _settings->add_spinscale(1, SP_ATTR_NUMOCTAVES, _("Octaves:"), 1, 10, 1, 1, 0);
+ _settings->add_spinscale(0, SP_ATTR_SEED, _("Seed:"), 0, 1000, 1, 1, 0, _("The starting number for the pseudo random number generator."));
}
void FilterEffectsDialog::add_primitive()
diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h
index 38811354e..acdeecb71 100644
--- a/src/ui/dialog/filter-effects-dialog.h
+++ b/src/ui/dialog/filter-effects-dialog.h
@@ -20,6 +20,7 @@
#include "sp-filter.h"
#include "ui/widget/combo-enums.h"
#include "ui/widget/spin-slider.h"
+#include "ui/widget/spin-scale.h"
#include "xml/helper-observer.h"
#include "ui/dialog/desktop-tracker.h"
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 7ee2aa444..62f48cce0 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -478,6 +478,11 @@ void InkscapePreferences::initPageTools()
_page_gradient.add_line( false, "", _misc_gradienteditor, "",
_("When on, the Gradient Edit button in the Fill & Stroke dialog will show the legacy Gradient Editor dialog, when off the Gradient Tool will be used"), true);
+ _misc_gradientangle.init("/dialogs/gradienteditor/angle", -359, 359, 1, 90, 0, false, false);
+ _page_gradient.add_line( false, _("Linear gradient _angle:"), _misc_gradientangle, "",
+ _("Default angle of new linear gradients in degrees (clockwise from horizontal"), false);
+
+
//Dropper
this->AddPage(_page_dropper, _("Dropper"), iter_tools, PREFS_PAGE_TOOLS_DROPPER);
this->AddSelcueCheckbox(_page_dropper, "/tools/dropper", true);
@@ -1389,6 +1394,9 @@ void InkscapePreferences::initPageBitmaps()
_importexport_import_res.init("/dialogs/import/defaultxdpi/value", 0.0, 6000.0, 1.0, 1.0, PX_PER_IN, true, false);
_page_bitmaps.add_line( false, _("Default _import resolution:"), _importexport_import_res, _("dpi"),
_("Default bitmap resolution (in dots per inch) for bitmap import"), false);
+ _importexport_import_res_override.init(_("Override file resolution"), "/dialogs/import/forcexdpi", false);
+ _page_bitmaps.add_line( false, "", _importexport_import_res_override, "",
+ _("Use default bitmap resolution in favor of information from file"));
this->AddPage(_page_bitmaps, _("Bitmaps"), PREFS_PAGE_BITMAPS);
}
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index 948a3f87b..d60035515 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -290,6 +290,7 @@ protected:
UI::Widget::PrefSpinButton _importexport_export_res;
UI::Widget::PrefSpinButton _importexport_import_res;
+ UI::Widget::PrefCheckButton _importexport_import_res_override;
UI::Widget::PrefSlider _snap_delay;
UI::Widget::PrefSlider _snap_weight;
UI::Widget::PrefCheckButton _font_dialog;
@@ -300,6 +301,7 @@ protected:
UI::Widget::PrefCheckButton _misc_default_metadata;
UI::Widget::PrefCheckButton _misc_forkvectors;
UI::Widget::PrefCheckButton _misc_gradienteditor;
+ UI::Widget::PrefSpinButton _misc_gradientangle;
UI::Widget::PrefCheckButton _misc_scripts;
UI::Widget::PrefCheckButton _misc_namedicon_delay;
diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp
index 465192aee..35a235dbc 100644
--- a/src/ui/dialog/layer-properties.cpp
+++ b/src/ui/dialog/layer-properties.cpp
@@ -28,7 +28,10 @@
#include "sp-item.h"
#include "verbs.h"
#include "selection.h"
-
+#include "selection-chemistry.h"
+#include "ui/icon-names.h"
+#include "ui/widget/imagetoggler.h"
+#include "event-context.h"
namespace Inkscape {
namespace UI {
@@ -51,7 +54,7 @@ LayerPropertiesDialog::LayerPropertiesDialog()
0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
_layout_table.attach(_layer_name_entry,
1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
- mainVBox->pack_start(_layout_table, false, false, 4);
+ mainVBox->pack_start(_layout_table, true, true, 4);
// Buttons
_close_button.set_use_stock(true);
@@ -82,6 +85,7 @@ LayerPropertiesDialog::LayerPropertiesDialog()
}
LayerPropertiesDialog::~LayerPropertiesDialog() {
+
_setDesktop(NULL);
_setLayer(NULL);
}
@@ -168,6 +172,131 @@ LayerPropertiesDialog::_setup_position_controls() {
show_all_children();
}
+void
+LayerPropertiesDialog::_setup_layers_controls() {
+
+ ModelColumns *zoop = new ModelColumns();
+ _model = zoop;
+ _store = Gtk::TreeStore::create( *zoop );
+ _tree.set_model( _store );
+ _tree.set_headers_visible(false);
+
+ Inkscape::UI::Widget::ImageToggler *eyeRenderer = manage( new Inkscape::UI::Widget::ImageToggler(
+ INKSCAPE_ICON("object-visible"), INKSCAPE_ICON("object-hidden")) );
+ int visibleColNum = _tree.append_column("vis", *eyeRenderer) - 1;
+ Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum);
+ if ( col ) {
+ col->add_attribute( eyeRenderer->property_active(), _model->_colVisible );
+ }
+
+ Inkscape::UI::Widget::ImageToggler * renderer = manage( new Inkscape::UI::Widget::ImageToggler(
+ INKSCAPE_ICON("object-locked"), INKSCAPE_ICON("object-unlocked")) );
+ int lockedColNum = _tree.append_column("lock", *renderer) - 1;
+ col = _tree.get_column(lockedColNum);
+ if ( col ) {
+ col->add_attribute( renderer->property_active(), _model->_colLocked );
+ }
+
+ Gtk::CellRendererText *_text_renderer = manage(new Gtk::CellRendererText());
+ int nameColNum = _tree.append_column("Name", *_text_renderer) - 1;
+ Gtk::TreeView::Column *_name_column = _tree.get_column(nameColNum);
+ _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel);
+
+ _tree.set_expander_column( *_tree.get_column(nameColNum) );
+ _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &LayerPropertiesDialog::_handleKeyEvent), false );
+ _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayerPropertiesDialog::_handleButtonEvent) );
+
+ _scroller.add( _tree );
+ _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
+ _scroller.set_shadow_type(Gtk::SHADOW_IN);
+ _scroller.set_size_request(220, 180);
+
+ SPDocument* document = _desktop->doc();
+ SPRoot* root = document->getRoot();
+ if ( root ) {
+ SPObject* target = _desktop->currentLayer();
+ _store->clear();
+ _addLayer( document, (SPObject *)root, 0, target, 0 );
+ }
+
+ _layout_table.remove(_layer_name_entry);
+ _layout_table.remove(_layer_name_label);
+
+ _layout_table.attach(_scroller,
+ 0, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL | Gtk::EXPAND);
+ show_all_children();
+}
+
+void LayerPropertiesDialog::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level )
+{
+ int _maxNestDepth = 20;
+ if ( _desktop && _desktop->layer_manager && layer && (level < _maxNestDepth) ) {
+ unsigned int counter = _desktop->layer_manager->childCount(layer);
+ for ( unsigned int i = 0; i < counter; i++ ) {
+ SPObject *child = _desktop->layer_manager->nthChildOf(layer, i);
+ if ( child ) {
+#if DUMP_LAYERS
+ g_message(" %3d layer:%p {%s} [%s]", level, child, child->id, child->label() );
+#endif // DUMP_LAYERS
+
+ Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend();
+ Gtk::TreeModel::Row row = *iter;
+ row[_model->_colObject] = child;
+ row[_model->_colLabel] = child->label() ? child->label() : child->getId();
+ row[_model->_colVisible] = SP_IS_ITEM(child) ? !SP_ITEM(child)->isHidden() : false;
+ row[_model->_colLocked] = SP_IS_ITEM(child) ? SP_ITEM(child)->isLocked() : false;
+
+ if ( target && child == target ) {
+ _tree.expand_to_path( _store->get_path(iter) );
+
+ Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
+ select->select(iter);
+
+ //_checkTreeSelection();
+ }
+
+ _addLayer( doc, child, &row, target, level + 1 );
+ }
+ }
+ }
+}
+
+SPObject* LayerPropertiesDialog::_selectedLayer()
+{
+ SPObject* obj = 0;
+
+ Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
+ if ( iter ) {
+ Gtk::TreeModel::Row row = *iter;
+ obj = row[_model->_colObject];
+ }
+
+ return obj;
+}
+
+bool LayerPropertiesDialog::_handleKeyEvent(GdkEventKey *event)
+{
+
+ switch (get_group0_keyval(event)) {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter: {
+ _strategy->perform(*this);
+ _close();
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+void LayerPropertiesDialog::_handleButtonEvent(GdkEventButton* event)
+{
+ if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
+ _strategy->perform(*this);
+ _close();
+ }
+}
+
/** Formats the label for a given layer row
*/
void LayerPropertiesDialog::_prepareLabelRenderer(
@@ -231,6 +360,20 @@ void LayerPropertiesDialog::Create::perform(LayerPropertiesDialog &dialog) {
desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("New layer created."));
}
+void LayerPropertiesDialog::Move::setup(LayerPropertiesDialog &dialog) {
+ dialog.set_title(_("Move to Layer"));
+ //TODO: find an unused layer number, forming name from _("Layer ") + "%d"
+ dialog._layer_name_entry.set_text(_("Layer"));
+ dialog._apply_button.set_label(_("_Move"));
+ dialog._setup_layers_controls();
+}
+
+void LayerPropertiesDialog::Move::perform(LayerPropertiesDialog &dialog) {
+
+ SPObject *moveto = dialog._selectedLayer();
+ sp_selection_to_layer(dialog._desktop, moveto, false);
+}
+
void LayerPropertiesDialog::_setDesktop(SPDesktop *desktop) {
if (desktop) {
Inkscape::GC::anchor (desktop);
diff --git a/src/ui/dialog/layer-properties.h b/src/ui/dialog/layer-properties.h
index c7d7de130..46b31ad35 100644
--- a/src/ui/dialog/layer-properties.h
+++ b/src/ui/dialog/layer-properties.h
@@ -18,8 +18,12 @@
#include <gtkmm/table.h>
#include <gtkmm/combobox.h>
#include <gtkmm/liststore.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/scrolledwindow.h>
#include "layer-fns.h"
+#include "ui/widget/layer-selector.h"
class SPDesktop;
@@ -40,6 +44,9 @@ class LayerPropertiesDialog : public Gtk::Dialog {
static void showCreate(SPDesktop *desktop, SPObject *layer) {
_showDialog(Create::instance(), desktop, layer);
}
+ static void showMove(SPDesktop *desktop, SPObject *layer) {
+ _showDialog(Move::instance(), desktop, layer);
+ }
protected:
struct Strategy {
@@ -57,9 +64,15 @@ protected:
void setup(LayerPropertiesDialog &dialog);
void perform(LayerPropertiesDialog &dialog);
};
+ struct Move : public Strategy {
+ static Move &instance() { static Move instance; return instance; }
+ void setup(LayerPropertiesDialog &dialog);
+ void perform(LayerPropertiesDialog &dialog);
+ };
friend class Rename;
friend class Create;
+ friend class Move;
Strategy *_strategy;
SPDesktop *_desktop;
@@ -82,6 +95,31 @@ protected:
Gtk::Table _layout_table;
bool _position_visible;
+ class ModelColumns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+
+ ModelColumns()
+ {
+ add(_colObject);
+ add(_colVisible);
+ add(_colLocked);
+ add(_colLabel);
+ }
+ virtual ~ModelColumns() {}
+
+ Gtk::TreeModelColumn<SPObject*> _colObject;
+ Gtk::TreeModelColumn<Glib::ustring> _colLabel;
+ Gtk::TreeModelColumn<bool> _colVisible;
+ Gtk::TreeModelColumn<bool> _colLocked;
+ };
+
+ Gtk::TreeView _tree;
+ ModelColumns* _model;
+ Glib::RefPtr<Gtk::TreeStore> _store;
+ Gtk::ScrolledWindow _scroller;
+
+
PositionDropdownColumns _dropdown_columns;
Gtk::CellRendererText _label_renderer;
Glib::RefPtr<Gtk::ListStore> _dropdown_list;
@@ -104,8 +142,14 @@ protected:
void _close();
void _setup_position_controls();
+ void _setup_layers_controls();
void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row);
+ void _addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level );
+ SPObject* _selectedLayer();
+ bool _handleKeyEvent(GdkEventKey *event);
+ void _handleButtonEvent(GdkEventButton* event);
+
private:
LayerPropertiesDialog(LayerPropertiesDialog const &); // no copy
LayerPropertiesDialog &operator=(LayerPropertiesDialog const &); // no assign
diff --git a/src/ui/dialog/livepatheffect-add.cpp b/src/ui/dialog/livepatheffect-add.cpp
index c22aace37..e899dbcfc 100644
--- a/src/ui/dialog/livepatheffect-add.cpp
+++ b/src/ui/dialog/livepatheffect-add.cpp
@@ -48,6 +48,7 @@ LivePathEffectAdd::LivePathEffectAdd() :
effectlist_treeview.set_model(effectlist_store);
effectlist_treeview.set_headers_visible(false);
effectlist_treeview.append_column("Name", _columns.name);
+ //effectlist_treeview.set_activates_default(true);
/**
* Initialize Effect list
@@ -68,7 +69,7 @@ LivePathEffectAdd::LivePathEffectAdd() :
* Buttons
*/
close_button.set_use_stock(true);
- close_button.set_can_default();
+ //close_button.set_can_default();
add_button.set_use_underline(true);
add_button.set_can_default();
diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert
index 8589f16b0..bbda64648 100644
--- a/src/ui/widget/Makefile_insert
+++ b/src/ui/widget/Makefile_insert
@@ -19,6 +19,8 @@ ink_common_sources += \
ui/widget/entry.h \
ui/widget/filter-effect-chooser.h \
ui/widget/filter-effect-chooser.cpp \
+ ui/widget/gimpspinscale.c \
+ ui/widget/gimpspinscale.h \
ui/widget/frame.cpp \
ui/widget/frame.h \
ui/widget/imageicon.cpp \
@@ -62,6 +64,8 @@ ink_common_sources += \
ui/widget/selected-style.cpp \
ui/widget/spinbutton.h \
ui/widget/spinbutton.cpp \
+ ui/widget/spin-scale.h \
+ ui/widget/spin-scale.cpp \
ui/widget/spin-slider.h \
ui/widget/spin-slider.cpp \
ui/widget/style-subject.h \
diff --git a/src/ui/widget/filter-effect-chooser.cpp b/src/ui/widget/filter-effect-chooser.cpp
index 8d6bcf60f..65706a9dc 100644
--- a/src/ui/widget/filter-effect-chooser.cpp
+++ b/src/ui/widget/filter-effect-chooser.cpp
@@ -22,12 +22,9 @@ namespace UI {
namespace Widget {
SimpleFilterModifier::SimpleFilterModifier(int flags)
- : _hb_blur(false, 0),
- _lb_blend(_("Blend mode:")),
- _lb_blur(_("_Blur:")),
- _lb_blur_unit(_("%")),
+ : _lb_blend(_("Blend mode:")),
_blend(BlendModeConverter, SP_ATTR_INVALID, false),
- _blur(0, 0, 100, 1, 0.01, 1)
+ _blur(_("Blur (%)"), 0, 0, 100, 1, 0.01, 1)
{
_flags = flags;
@@ -37,11 +34,7 @@ SimpleFilterModifier::SimpleFilterModifier(int flags)
_hb_blend.pack_start(_blend);
}
if (flags & BLUR) {
- add(_hb_blur);
- _lb_blur.set_alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER);
- _hb_blur.pack_start(_lb_blur, false, false, 0);
- _hb_blur.pack_start(_blur, true, true, 0);
- _hb_blur.pack_start(_lb_blur_unit, false, false, 3);
+ add(_blur);
}
show_all_children();
@@ -49,8 +42,6 @@ SimpleFilterModifier::SimpleFilterModifier(int flags)
_hb_blend.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());
_blend.signal_changed().connect(signal_blend_blur_changed());
_blur.signal_value_changed().connect(signal_blend_blur_changed());
}
diff --git a/src/ui/widget/filter-effect-chooser.h b/src/ui/widget/filter-effect-chooser.h
index 6afb6c180..ae3ec07c4 100644
--- a/src/ui/widget/filter-effect-chooser.h
+++ b/src/ui/widget/filter-effect-chooser.h
@@ -18,6 +18,7 @@
#include "combo-enums.h"
#include "filter-enums.h"
#include "spin-slider.h"
+#include "spin-scale.h"
namespace Inkscape {
namespace UI {
@@ -45,17 +46,14 @@ public:
double get_blur_value() const;
void set_blur_value(const double);
void set_blur_sensitive(const bool);
- Gtk::Label *get_blur_label() { return &_lb_blur; };
-
private:
int _flags;
Gtk::HBox _hb_blend;
- Gtk::HBox _hb_blur;
- Gtk::Label _lb_blend, _lb_blur, _lb_blur_unit;
+ Gtk::Label _lb_blend;
ComboBoxEnum<Inkscape::Filters::FilterBlendMode> _blend;
- SpinSlider _blur;
+ SpinScale _blur;
sigc::signal<void> _signal_blend_blur_changed;
};
diff --git a/src/ui/widget/gimpspinscale.c b/src/ui/widget/gimpspinscale.c
new file mode 100644
index 000000000..1b7ac7bfe
--- /dev/null
+++ b/src/ui/widget/gimpspinscale.c
@@ -0,0 +1,1089 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpspinscale.c
+ * Copyright (C) 2010 Michael Natterer <mitch@gimp.org>
+ * 2012 Øyvind Kolås <pippin@gimp.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <math.h>
+#include <string.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "gimpspinscale.h"
+
+
+enum
+{
+ PROP_0,
+ PROP_LABEL,
+ PROP_FOCUS_WIDGET
+};
+
+typedef enum
+{
+ TARGET_NUMBER,
+ TARGET_UPPER,
+ TARGET_LOWER
+#if WITH_GTKMM_3_0
+ ,TARGET_NONE
+#endif
+} SpinScaleTarget;
+
+typedef enum
+{
+ APPEARANCE_FULL = 1, /* Full size suitable for tablets */
+ APPEARANCE_COMPACT, /* Compact, suitable for desktops with mouse control */
+} SpinScaleAppearance;
+
+typedef struct _GimpSpinScalePrivate GimpSpinScalePrivate;
+
+struct _GimpSpinScalePrivate
+{
+ gchar *label;
+
+ gboolean scale_limits_set;
+ gdouble scale_lower;
+ gdouble scale_upper;
+ gdouble gamma;
+
+ PangoLayout *layout;
+ gboolean changing_value;
+ gboolean relative_change;
+ gdouble start_x;
+ gdouble start_value;
+
+ GtkWidget* focusWidget;
+ gboolean transferFocus;
+ SpinScaleAppearance appearanceMode;
+};
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+ GIMP_TYPE_SPIN_SCALE, \
+ GimpSpinScalePrivate))
+
+
+static void gimp_spin_scale_dispose (GObject *object);
+static void gimp_spin_scale_finalize (GObject *object);
+static void gimp_spin_scale_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_spin_scale_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void gimp_spin_scale_style_set (GtkWidget *widget,
+ GtkStyle *prev_style);
+
+#if WITH_GTKMM_3_0
+static void gimp_spin_scale_get_preferred_width (GtkWidget *widget,
+ gint *minimum_width,
+ gint *natural_width);
+static void gimp_spin_scale_get_preferred_height (GtkWidget *widget,
+ gint *minimum_width,
+ gint *natural_width);
+static gboolean gimp_spin_scale_draw (GtkWidget *widget,
+ cairo_t *cr);
+#else
+static void gimp_spin_scale_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+
+static gboolean gimp_spin_scale_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+#endif
+
+static gboolean gimp_spin_scale_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean gimp_spin_scale_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean gimp_spin_scale_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event);
+static gboolean gimp_spin_scale_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gboolean gimp_spin_scale_keypress( GtkWidget *widget,
+ GdkEventKey *event);
+
+static void gimp_spin_scale_defocus( GtkSpinButton *spin_button );
+
+static void gimp_spin_scale_value_changed (GtkSpinButton *spin_button);
+
+
+G_DEFINE_TYPE (GimpSpinScale, gimp_spin_scale, GTK_TYPE_SPIN_BUTTON);
+
+#define parent_class gimp_spin_scale_parent_class
+
+
+static void
+gimp_spin_scale_class_init (GimpSpinScaleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkSpinButtonClass *spin_button_class = GTK_SPIN_BUTTON_CLASS (klass);
+
+ object_class->dispose = gimp_spin_scale_dispose;
+ object_class->finalize = gimp_spin_scale_finalize;
+ object_class->set_property = gimp_spin_scale_set_property;
+ object_class->get_property = gimp_spin_scale_get_property;
+
+ widget_class->style_set = gimp_spin_scale_style_set;
+#if WITH_GTKMM_3_0
+ widget_class->get_preferred_width = gimp_spin_scale_get_preferred_width;
+ widget_class->get_preferred_height = gimp_spin_scale_get_preferred_height;
+ widget_class->draw = gimp_spin_scale_draw;
+#else
+ widget_class->size_request = gimp_spin_scale_size_request;
+ widget_class->expose_event = gimp_spin_scale_expose;
+#endif
+ widget_class->button_press_event = gimp_spin_scale_button_press;
+ widget_class->button_release_event = gimp_spin_scale_button_release;
+ widget_class->motion_notify_event = gimp_spin_scale_motion_notify;
+ widget_class->leave_notify_event = gimp_spin_scale_leave_notify;
+ widget_class->key_press_event = gimp_spin_scale_keypress;
+
+ spin_button_class->value_changed = gimp_spin_scale_value_changed;
+
+ g_object_class_install_property (object_class, PROP_LABEL,
+ g_param_spec_string ("label", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private (klass, sizeof (GimpSpinScalePrivate));
+}
+
+static void
+gimp_spin_scale_init (GimpSpinScale *scale)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (scale);
+
+ gtk_entry_set_alignment (GTK_ENTRY (scale), 1.0);
+ gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (scale), TRUE);
+
+ private->gamma = 1.0;
+ private->focusWidget = NULL;
+ private->transferFocus = FALSE;
+ private->appearanceMode = APPEARANCE_COMPACT;
+}
+
+static void
+gimp_spin_scale_dispose (GObject *object)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (object);
+
+ if (private->layout)
+ {
+ g_object_unref (private->layout);
+ private->layout = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_spin_scale_finalize (GObject *object)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (object);
+
+ if (private->label)
+ {
+ g_free (private->label);
+ private->label = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_spin_scale_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (object);
+
+ switch (property_id)
+ {
+ case PROP_LABEL:
+ g_free (private->label);
+ private->label = g_value_dup_string (value);
+ if (private->layout)
+ {
+ g_object_unref (private->layout);
+ private->layout = NULL;
+ }
+ gtk_widget_queue_resize (GTK_WIDGET (object));
+ break;
+
+ case PROP_FOCUS_WIDGET:
+ {
+ /* TODO unhook prior */
+ private->focusWidget = (GtkWidget*)g_value_get_pointer( value );
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_spin_scale_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (object);
+
+ switch (property_id)
+ {
+ case PROP_LABEL:
+ g_value_set_string (value, private->label);
+ break;
+
+ case PROP_FOCUS_WIDGET:
+ g_value_set_pointer( value, private->focusWidget );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+void
+gimp_spin_scale_set_focuswidget( GtkWidget *scale, GtkWidget* widget )
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (scale);
+
+ /* TODO unhook prior */
+
+ private->focusWidget = widget;
+}
+
+void
+gimp_spin_scale_set_appearance( GtkWidget *widget, const gchar *appearance)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (widget);
+
+ if ( strcmp("full", appearance) == 0 ) {
+ private->appearanceMode = APPEARANCE_FULL;
+ } else if ( strcmp("compact", appearance) == 0 ) {
+ private->appearanceMode = APPEARANCE_COMPACT;
+ }
+}
+
+static void
+#if WITH_GTKMM_3_0
+gimp_spin_scale_get_preferred_width (GtkWidget *widget,
+ gint *minimum_width,
+ gint *natural_width)
+#else
+gimp_spin_scale_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+#endif
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (widget);
+ GtkStyle *style = gtk_widget_get_style (widget);
+ PangoContext *context = gtk_widget_get_pango_context (widget);
+ PangoFontMetrics *metrics;
+
+#if WITH_GTKMM_3_0
+ GTK_WIDGET_CLASS (parent_class)->get_preferred_width (widget,
+ minimum_width,
+ natural_width);
+#else
+ gint height;
+ GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
+#endif
+
+ metrics = pango_context_get_metrics (context, style->font_desc,
+ pango_context_get_language (context));
+
+#if WITH_GTKMM_3_0
+#else
+ height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
+ pango_font_metrics_get_descent (metrics));
+
+ if (private->appearanceMode == APPEARANCE_COMPACT) {
+ requisition->height += 1;
+ } else {
+ requisition->height += height;
+ }
+
+#endif
+
+
+ if (private->label)
+ {
+ gint char_width;
+ gint digit_width;
+ gint char_pixels;
+
+ char_width = pango_font_metrics_get_approximate_char_width (metrics);
+ digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
+ char_pixels = PANGO_PIXELS (MAX (char_width, digit_width));
+
+#if WITH_GTKMM_3_0
+ *minimum_width += char_pixels * 3;
+ *natural_width += char_pixels * 3;
+#else
+ /* ~3 chars for the ellipses */
+ requisition->width += char_pixels * 3;
+#endif
+
+ }
+
+ pango_font_metrics_unref (metrics);
+}
+
+#if WITH_GTKMM_3_0
+static void
+gimp_spin_scale_get_preferred_height (GtkWidget *widget,
+ gint *minimum_height,
+ gint *natural_height)
+{
+ GtkStyle *style = gtk_widget_get_style (widget);
+ PangoContext *context = gtk_widget_get_pango_context (widget);
+ PangoFontMetrics *metrics;
+ //gint height;
+
+ GTK_WIDGET_CLASS (parent_class)->get_preferred_height (widget,
+ minimum_height,
+ natural_height);
+
+ metrics = pango_context_get_metrics (context, style->font_desc,
+ pango_context_get_language (context));
+
+ //height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
+ // pango_font_metrics_get_descent (metrics));
+
+ *minimum_height += 1;
+ *natural_height += 1;
+
+ pango_font_metrics_unref (metrics);
+}
+#endif
+
+static void
+gimp_spin_scale_style_set (GtkWidget *widget,
+ GtkStyle *prev_style)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (widget);
+
+ GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
+
+ if (private->layout)
+ {
+ g_object_unref (private->layout);
+ private->layout = NULL;
+ }
+}
+
+
+static gboolean
+
+#if WITH_GTKMM_3_0
+ gimp_spin_scale_draw (GtkWidget *widget, cairo_t *cr)
+#else
+ gimp_spin_scale_expose (GtkWidget *widget, GdkEventExpose *event)
+#endif
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (widget);
+ GtkStyle *style = gtk_widget_get_style (widget);
+
+
+#if WITH_GTKMM_3_0
+ GtkAllocation allocation;
+
+ cairo_save (cr);
+ GTK_WIDGET_CLASS (parent_class)->draw (widget, cr);
+ cairo_restore (cr);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+
+#else
+ cairo_t *cr;
+ gint w;
+
+ GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
+
+ cr = gdk_cairo_create (event->window);
+ gdk_cairo_region (cr, event->region);
+ cairo_clip (cr);
+
+ w = gdk_window_get_width (event->window);
+
+#endif
+
+ cairo_set_line_width (cr, 1.0);
+
+
+#if WITH_GTKMM_3_0
+ if (private->label)
+ {
+ GdkRectangle text_area;
+ gint minimum_width;
+ gint natural_width;
+#else
+ if (private->label &&
+ gtk_widget_is_drawable (widget) &&
+ event->window == gtk_entry_get_text_window (GTK_ENTRY (widget)))
+ {
+ GtkRequisition requisition;
+ GtkAllocation allocation;
+#endif
+
+ PangoRectangle logical;
+ gint layout_offset_x;
+ gint layout_offset_y;
+
+#if WITH_GTKMM_3_0
+ gtk_entry_get_text_area (GTK_ENTRY (widget), &text_area);
+
+ GTK_WIDGET_CLASS (parent_class)->get_preferred_width (widget,
+ &minimum_width,
+ &natural_width);
+#else
+ GTK_WIDGET_CLASS (parent_class)->size_request (widget, &requisition);
+ gtk_widget_get_allocation (widget, &allocation);
+#endif
+
+ if (! private->layout)
+ {
+ private->layout = gtk_widget_create_pango_layout (widget,
+ private->label);
+ pango_layout_set_ellipsize (private->layout, PANGO_ELLIPSIZE_END);
+ }
+
+ pango_layout_set_width (private->layout,
+ PANGO_SCALE *
+#if WITH_GTKMM_3_0
+ (allocation.width - minimum_width + 10));
+#else
+ (allocation.width - requisition.width + 10));
+#endif
+ pango_layout_get_pixel_extents (private->layout, NULL, &logical);
+
+ gtk_entry_get_layout_offsets (GTK_ENTRY (widget), NULL, &layout_offset_y);
+
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+#if WITH_GTKMM_3_0
+ layout_offset_x = text_area.x + text_area.width - logical.width - 4;
+#else
+ layout_offset_x = w - logical.width - 4;
+#endif
+ else
+ layout_offset_x = 4;
+
+ layout_offset_x -= logical.x;
+
+#if WITH_GTKMM_3_0
+ cairo_move_to (cr, layout_offset_x, text_area.y + layout_offset_y-3);
+#else
+ cairo_move_to (cr, layout_offset_x, layout_offset_y-3);
+#endif
+
+ gdk_cairo_set_source_color (cr,
+ &style->text[gtk_widget_get_state (widget)]);
+
+ pango_cairo_show_layout (cr, private->layout);
+ }
+
+#if WITH_GTKMM_3_0
+#else
+ cairo_destroy (cr);
+#endif
+
+ return FALSE;
+}
+
+#if WITH_GTKMM_3_0
+/* Returns TRUE if a translation should be done */
+static gboolean
+gtk_widget_get_translation_to_window (GtkWidget *widget,
+ GdkWindow *window,
+ int *x,
+ int *y)
+{
+ GdkWindow *w, *widget_window;
+
+ if (!gtk_widget_get_has_window (widget))
+ {
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ *x = -allocation.x;
+ *y = -allocation.y;
+ }
+ else
+ {
+ *x = 0;
+ *y = 0;
+ }
+
+ widget_window = gtk_widget_get_window (widget);
+
+ for (w = window; w && w != widget_window; w = gdk_window_get_parent (w))
+ {
+ int wx, wy;
+ gdk_window_get_position (w, &wx, &wy);
+ *x += wx;
+ *y += wy;
+ }
+
+ if (w == NULL)
+ {
+ *x = 0;
+ *y = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+gimp_spin_scale_event_to_widget_coords (GtkWidget *widget,
+ GdkWindow *window,
+ gdouble event_x,
+ gdouble event_y,
+ gint *widget_x,
+ gint *widget_y)
+{
+ gint tx, ty;
+
+ if (gtk_widget_get_translation_to_window (widget, window, &tx, &ty))
+ {
+ event_x += tx;
+ event_y += ty;
+ }
+
+ *widget_x = event_x;
+ *widget_y = event_y;
+}
+#endif
+
+static SpinScaleTarget
+gimp_spin_scale_get_target (GtkWidget *widget,
+ gdouble x,
+ gdouble y)
+{
+ GtkAllocation allocation;
+ PangoRectangle logical;
+ gint layout_x;
+ gint layout_y;
+
+ gtk_widget_get_allocation (widget, &allocation);
+ gtk_entry_get_layout_offsets (GTK_ENTRY (widget), &layout_x, &layout_y);
+ pango_layout_get_pixel_extents (gtk_entry_get_layout (GTK_ENTRY (widget)),
+ NULL, &logical);
+
+#if WITH_GTKMM_3_0
+ GdkRectangle text_area;
+ gtk_entry_get_text_area (GTK_ENTRY (widget), &text_area);
+
+ if (x >= text_area.x && x < text_area.width &&
+ y >= text_area.y && y < text_area.height)
+ {
+ x -= text_area.x;
+ y -= text_area.y;
+
+ if (x > layout_x && x < layout_x + logical.width &&
+ y > layout_y && y < layout_y + logical.height)
+ {
+ return TARGET_NUMBER;
+ }
+ else if (y > text_area.height / 2)
+ {
+ return TARGET_LOWER;
+ }
+
+ return TARGET_UPPER;
+ }
+
+ return TARGET_NONE;
+#else
+ if (x > layout_x && x < layout_x + logical.width &&
+ y > layout_y && y < layout_y + logical.height)
+ {
+ return TARGET_NUMBER;
+ }
+
+ else if (y > allocation.height / 2)
+ {
+ return TARGET_LOWER;
+ }
+ return TARGET_UPPER;
+#endif
+}
+
+static void
+gimp_spin_scale_get_limits (GimpSpinScale *scale,
+ gdouble *lower,
+ gdouble *upper)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (scale);
+
+ if (private->scale_limits_set)
+ {
+ *lower = private->scale_lower;
+ *upper = private->scale_upper;
+ }
+ else
+ {
+ GtkSpinButton *spin_button = GTK_SPIN_BUTTON (scale);
+ GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button);
+
+ *lower = gtk_adjustment_get_lower (adjustment);
+ *upper = gtk_adjustment_get_upper (adjustment);
+ }
+}
+
+static void
+gimp_spin_scale_change_value (GtkWidget *widget,
+ gdouble x)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (widget);
+ GtkSpinButton *spin_button = GTK_SPIN_BUTTON (widget);
+ GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button);
+ gdouble lower;
+ gdouble upper;
+ gdouble value;
+#if WITH_GTKMM_3_0
+#else
+#endif
+#if WITH_GTKMM_3_0
+ GdkRectangle text_area;
+ gtk_entry_get_text_area (GTK_ENTRY (widget), &text_area);
+ gimp_spin_scale_get_limits (GIMP_SPIN_SCALE (widget), &lower, &upper);
+#else
+ GdkWindow *text_window = gtk_entry_get_text_window (GTK_ENTRY (widget));
+ gint width;
+
+ gimp_spin_scale_get_limits (GIMP_SPIN_SCALE (widget), &lower, &upper);
+ width = gdk_window_get_width (text_window);
+
+#endif
+
+
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+#if WITH_GTKMM_3_0
+ x = text_area.width - x;
+#else
+ x = width - x;
+#endif
+
+
+ if (private->relative_change)
+ {
+ gdouble diff;
+ gdouble step;
+
+
+#if WITH_GTKMM_3_0
+ step = (upper - lower) / text_area.width / 10.0;
+#else
+ step = (upper - lower) / width / 10.0;
+#endif
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+
+#if WITH_GTKMM_3_0
+ diff = x - (text_area.width - private->start_x);
+#else
+ diff = x - (width - private->start_x);
+#endif
+ else
+ diff = x - private->start_x;
+
+ value = (private->start_value + diff * step);
+ }
+ else
+ {
+ gdouble fraction;
+
+
+#if WITH_GTKMM_3_0
+ fraction = x / (gdouble) text_area.width;
+#else
+ fraction = x / (gdouble) width;
+#endif
+ if (fraction > 0.0)
+ fraction = pow (fraction, private->gamma);
+
+ value = fraction * (upper - lower) + lower;
+ }
+
+ gtk_adjustment_set_value (adjustment, value);
+}
+
+static gboolean
+gimp_spin_scale_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (widget);
+
+ private->changing_value = FALSE;
+ private->relative_change = FALSE;
+
+#if WITH_GTKMM_3_0
+ gint x, y;
+ gimp_spin_scale_event_to_widget_coords (widget, event->window,
+ event->x, event->y,
+ &x, &y);
+ switch (gimp_spin_scale_get_target (widget, x, y))
+ {
+ case TARGET_UPPER:
+ private->changing_value = TRUE;
+
+ gtk_widget_grab_focus (widget);
+
+ gimp_spin_scale_change_value (widget, x);
+
+ return TRUE;
+
+ case TARGET_LOWER:
+ private->changing_value = TRUE;
+
+ gtk_widget_grab_focus (widget);
+
+ private->relative_change = TRUE;
+ private->start_x = x;
+ private->start_value = gtk_adjustment_get_value (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget)));
+
+ return TRUE;
+
+ default:
+ break;
+ }
+#else
+ if (event->window == gtk_entry_get_text_window (GTK_ENTRY (widget)))
+ {
+ switch (gimp_spin_scale_get_target (widget, event->x, event->y))
+ {
+ case TARGET_UPPER:
+ private->changing_value = TRUE;
+
+ gtk_widget_grab_focus (widget);
+
+ gimp_spin_scale_change_value (widget, event->x);
+
+ return TRUE;
+
+ case TARGET_LOWER:
+ private->changing_value = TRUE;
+
+ gtk_widget_grab_focus (widget);
+
+ private->relative_change = TRUE;
+ private->start_x = event->x;
+ private->start_value = gtk_adjustment_get_value (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget)));
+
+ return TRUE;
+
+ default:
+ break;
+ }
+ }
+#endif
+
+ return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
+}
+
+static gboolean
+gimp_spin_scale_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (widget);
+#if WITH_GTKMM_3_0
+ gint x, y;
+
+ gimp_spin_scale_event_to_widget_coords (widget, event->window,
+ event->x, event->y,
+ &x, &y);
+#endif
+
+ if (private->changing_value)
+ {
+ private->changing_value = FALSE;
+#if WITH_GTKMM_3_0
+ gimp_spin_scale_change_value (widget, x);
+#else
+ gimp_spin_scale_change_value (widget, event->x);
+#endif
+ return TRUE;
+ }
+
+ return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
+}
+
+static gboolean
+gimp_spin_scale_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (widget);
+#if WITH_GTKMM_3_0
+ gint x, y;
+
+ gimp_spin_scale_event_to_widget_coords (widget, event->window,
+ event->x, event->y,
+ &x, &y);
+#endif
+
+ if (private->changing_value)
+ {
+#if WITH_GTKMM_3_0
+ gimp_spin_scale_change_value (widget, x);
+#else
+ gimp_spin_scale_change_value (widget, event->x);
+#endif
+
+ return TRUE;
+ }
+
+ GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
+
+ if (! (event->state &
+ (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK))
+#if WITH_GTKMM_3_0
+#else
+ && event->window == gtk_entry_get_text_window (GTK_ENTRY (widget))
+#endif
+ )
+ {
+ GdkDisplay *display = gtk_widget_get_display (widget);
+ GdkCursor *cursor = NULL;
+
+#if WITH_GTKMM_3_0
+ switch (gimp_spin_scale_get_target (widget, x, y))
+#else
+ switch (gimp_spin_scale_get_target (widget, event->x, event->y))
+#endif
+ {
+ case TARGET_NUMBER:
+ cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
+ break;
+
+ case TARGET_UPPER:
+ cursor = gdk_cursor_new_for_display (display, GDK_SB_UP_ARROW);
+ break;
+
+ case TARGET_LOWER:
+ cursor = gdk_cursor_new_for_display (display, GDK_SB_H_DOUBLE_ARROW);
+ break;
+
+ default:
+ break;
+ }
+
+
+#if WITH_GTKMM_3_0
+ if (cursor)
+ {
+ gdk_window_set_cursor (event->window, cursor);
+ g_object_unref (cursor);
+ }
+#else
+ gdk_window_set_cursor (event->window, cursor);
+ gdk_cursor_unref (cursor);
+#endif
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gimp_spin_scale_leave_notify (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ gdk_window_set_cursor (event->window, NULL);
+
+ return GTK_WIDGET_CLASS (parent_class)->leave_notify_event (widget, event);
+}
+
+gboolean gimp_spin_scale_keypress( GtkWidget *widget, GdkEventKey *event)
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (widget);
+ guint key = 0;
+ gdk_keymap_translate_keyboard_state( gdk_keymap_get_for_display( gdk_display_get_default() ),
+ event->hardware_keycode, (GdkModifierType)event->state,
+ 0, &key, 0, 0, 0 );
+
+ switch ( key ) {
+
+ case GDK_KEY_Escape:
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ {
+ private->transferFocus = TRUE;
+ gimp_spin_scale_defocus( GTK_SPIN_BUTTON(widget) );
+ }
+ break;
+
+ }
+
+ return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
+}
+
+static void
+gimp_spin_scale_defocus( GtkSpinButton *spin_button )
+{
+ GimpSpinScalePrivate *private = GET_PRIVATE (spin_button);
+
+ if ( private->transferFocus ) {
+ if ( private->focusWidget ) {
+ gtk_widget_grab_focus( private->focusWidget );
+ }
+ }
+}
+
+static void
+gimp_spin_scale_value_changed (GtkSpinButton *spin_button)
+{
+ GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button);
+ GimpSpinScalePrivate *private = GET_PRIVATE (spin_button);
+ gdouble lower;
+ gdouble upper;
+ gdouble value;
+
+ gimp_spin_scale_get_limits (GIMP_SPIN_SCALE (spin_button), &lower, &upper);
+
+ value = CLAMP (gtk_adjustment_get_value (adjustment), lower, upper);
+
+
+ gtk_entry_set_progress_fraction (GTK_ENTRY (spin_button),
+ pow ((value - lower) / (upper - lower),
+ 1.0 / private->gamma));
+
+ // TODO - Allow scrollwheel to change value then return focus,
+ // but clicks/keypress should keep focus in the control
+ //if ( gtk_widget_has_focus( GTK_WIDGET(spin_button) ) ) {
+ // gimp_spin_scale_defocus( spin_button );
+ //}
+}
+
+
+/* public functions */
+
+GtkWidget *
+gimp_spin_scale_new (GtkAdjustment *adjustment,
+ const gchar *label,
+ gint digits)
+{
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), NULL);
+
+ return g_object_new (GIMP_TYPE_SPIN_SCALE,
+ "adjustment", adjustment,
+ "label", label,
+ "digits", digits,
+ NULL);
+}
+
+void
+gimp_spin_scale_set_scale_limits (GimpSpinScale *scale,
+ gdouble lower,
+ gdouble upper)
+{
+ GimpSpinScalePrivate *private;
+ GtkSpinButton *spin_button;
+ GtkAdjustment *adjustment;
+
+ g_return_if_fail (GIMP_IS_SPIN_SCALE (scale));
+
+ private = GET_PRIVATE (scale);
+ spin_button = GTK_SPIN_BUTTON (scale);
+ adjustment = gtk_spin_button_get_adjustment (spin_button);
+
+ g_return_if_fail (lower >= gtk_adjustment_get_lower (adjustment));
+ g_return_if_fail (upper <= gtk_adjustment_get_upper (adjustment));
+
+ private->scale_limits_set = TRUE;
+ private->scale_lower = lower;
+ private->scale_upper = upper;
+ private->gamma = 1.0;
+
+ gimp_spin_scale_value_changed (spin_button);
+}
+
+void
+gimp_spin_scale_set_gamma (GimpSpinScale *scale,
+ gdouble gamma)
+{
+ GimpSpinScalePrivate *private;
+
+ g_return_if_fail (GIMP_IS_SPIN_SCALE (scale));
+
+ private = GET_PRIVATE (scale);
+
+ private->gamma = gamma;
+
+ gimp_spin_scale_value_changed (GTK_SPIN_BUTTON (scale));
+}
+
+gdouble
+gimp_spin_scale_get_gamma (GimpSpinScale *scale)
+{
+ GimpSpinScalePrivate *private;
+
+ g_return_val_if_fail (GIMP_IS_SPIN_SCALE (scale), 1.0);
+
+ private = GET_PRIVATE (scale);
+
+ return private->gamma;
+}
+
+void
+gimp_spin_scale_unset_scale_limits (GimpSpinScale *scale)
+{
+ GimpSpinScalePrivate *private;
+
+ g_return_if_fail (GIMP_IS_SPIN_SCALE (scale));
+
+ private = GET_PRIVATE (scale);
+
+ private->scale_limits_set = FALSE;
+ private->scale_lower = 0.0;
+ private->scale_upper = 0.0;
+
+ gimp_spin_scale_value_changed (GTK_SPIN_BUTTON (scale));
+}
+
+gboolean
+gimp_spin_scale_get_scale_limits (GimpSpinScale *scale,
+ gdouble *lower,
+ gdouble *upper)
+{
+ GimpSpinScalePrivate *private;
+
+ g_return_val_if_fail (GIMP_IS_SPIN_SCALE (scale), FALSE);
+
+ private = GET_PRIVATE (scale);
+
+ if (lower)
+ *lower = private->scale_lower;
+
+ if (upper)
+ *upper = private->scale_upper;
+
+ return private->scale_limits_set;
+}
diff --git a/src/ui/widget/gimpspinscale.h b/src/ui/widget/gimpspinscale.h
new file mode 100644
index 000000000..ad63625ac
--- /dev/null
+++ b/src/ui/widget/gimpspinscale.h
@@ -0,0 +1,76 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpspinscale.h
+ * Copyright (C) 2010 Michael Natterer <mitch@gimp.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_SPIN_SCALE_H__
+#define __GIMP_SPIN_SCALE_H__
+
+#ifndef WITH_GIMP
+#include <gtk/gtk.h>
+#endif
+
+G_BEGIN_DECLS
+
+#define GIMP_TYPE_SPIN_SCALE (gimp_spin_scale_get_type ())
+#define GIMP_SPIN_SCALE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SPIN_SCALE, GimpSpinScale))
+#define GIMP_SPIN_SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_SPIN_SCALE, GimpSpinScaleClass))
+#define GIMP_IS_SPIN_SCALE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_SPIN_SCALE))
+#define GIMP_IS_SPIN_SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_SPIN_SCALE))
+#define GIMP_SPIN_SCALE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_SPIN_SCALE, GimpSpinScaleClass))
+
+
+typedef struct _GimpSpinScale GimpSpinScale;
+typedef struct _GimpSpinScaleClass GimpSpinScaleClass;
+
+struct _GimpSpinScale
+{
+ GtkSpinButton parent_instance;
+};
+
+struct _GimpSpinScaleClass
+{
+ GtkSpinButtonClass parent_class;
+};
+
+
+GType gimp_spin_scale_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gimp_spin_scale_new (GtkAdjustment *adjustment,
+ const gchar *label,
+ gint digits);
+
+void gimp_spin_scale_set_scale_limits (GimpSpinScale *scale,
+ gdouble lower,
+ gdouble upper);
+void gimp_spin_scale_unset_scale_limits (GimpSpinScale *scale);
+gboolean gimp_spin_scale_get_scale_limits (GimpSpinScale *scale,
+ gdouble *lower,
+ gdouble *upper);
+
+void gimp_spin_scale_set_gamma (GimpSpinScale *scale,
+ gdouble gamma);
+gdouble gimp_spin_scale_get_gamma (GimpSpinScale *scale);
+
+void gimp_spin_scale_set_focuswidget( GtkWidget *scale, GtkWidget* widget );
+
+void gimp_spin_scale_set_appearance( GtkWidget *scale, const gchar *appearance);
+
+G_END_DECLS
+
+#endif /* __GIMP_SPIN_SCALE_H__ */
diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp
index c6622627b..a80a1aba0 100644
--- a/src/ui/widget/layer-selector.cpp
+++ b/src/ui/widget/layer-selector.cpp
@@ -185,7 +185,10 @@ void LayerSelector::setDesktop(SPDesktop *desktop) {
if (_desktop) {
// _desktop_shutdown_connection.disconnect();
- _layer_changed_connection.disconnect();
+ if (_current_layer_changed_connection)
+ _current_layer_changed_connection.disconnect();
+ if (_layers_changed_connection)
+ _layers_changed_connection.disconnect();
// g_signal_handlers_disconnect_by_func(_desktop, (gpointer)&detach, this);
}
_desktop = desktop;
@@ -195,9 +198,13 @@ void LayerSelector::setDesktop(SPDesktop *desktop) {
// sigc::bind (sigc::ptr_fun (detach), this));
// g_signal_connect_after(_desktop, "shutdown", GCallback(detach), this);
- _layer_changed_connection = _desktop->connectCurrentLayerChanged(
- sigc::mem_fun(*this, &LayerSelector::_selectLayer)
- );
+ LayerManager *mgr = _desktop->layer_manager;
+ if ( mgr ) {
+ _current_layer_changed_connection = mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayerSelector::_selectLayer) );
+ //_layerUpdatedConnection = mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayerSelector::_updateLayer) );
+ _layers_changed_connection = mgr->connectChanged( sigc::mem_fun(*this, &LayerSelector::_layersChanged) );
+ }
+
_selectLayer(_desktop->currentLayer());
}
}
@@ -230,6 +237,11 @@ private:
}
+void LayerSelector::_layersChanged()
+{
+ //_selectLayer(_desktop->currentLayer());
+}
+
/** Selects the given layer in the dropdown selector.
*/
void LayerSelector::_selectLayer(SPObject *layer) {
@@ -300,11 +312,13 @@ void LayerSelector::_setDesktopLayer() {
Gtk::ListStore::iterator selected(_selector.get_active());
SPObject *layer=_selector.get_active()->get_value(_model_columns.object);
if ( _desktop && layer ) {
- _layer_changed_connection.block();
+ _current_layer_changed_connection.block();
+ _layers_changed_connection.block();
_desktop->layer_manager->setCurrentLayer(layer);
- _layer_changed_connection.unblock();
+ _current_layer_changed_connection.unblock();
+ _layers_changed_connection.unblock();
_selectLayer(_desktop->currentLayer());
}
diff --git a/src/ui/widget/layer-selector.h b/src/ui/widget/layer-selector.h
index 6fbdc9857..ff9e4ddfc 100644
--- a/src/ui/widget/layer-selector.h
+++ b/src/ui/widget/layer-selector.h
@@ -68,7 +68,8 @@ private:
Glib::RefPtr<Gtk::ListStore> _layer_model;
// sigc::connection _desktop_shutdown_connection;
- sigc::connection _layer_changed_connection;
+ sigc::connection _layers_changed_connection;
+ sigc::connection _current_layer_changed_connection;
sigc::connection _selection_changed_connection;
sigc::connection _visibility_toggled_connection;
sigc::connection _lock_toggled_connection;
@@ -76,6 +77,8 @@ private:
SPObject *_layer;
void _selectLayer(SPObject *layer);
+ void _layersChanged();
+
void _setDesktopLayer();
void _buildEntry(unsigned depth, SPObject &object);
diff --git a/src/ui/widget/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp
index 1cb384501..2789676ea 100644
--- a/src/ui/widget/object-composite-settings.cpp
+++ b/src/ui/widget/object-composite-settings.cpp
@@ -16,6 +16,7 @@
#include <glibmm/i18n.h>
+#include "desktop.h"
#include "desktop-handles.h"
#include "desktop-style.h"
#include "document.h"
@@ -32,6 +33,7 @@
#include "ui/icon-names.h"
#include "display/sp-canvas.h"
#include "ui/widget/style-subject.h"
+#include "ui/widget/gimpspinscale.h"
namespace Inkscape {
namespace UI {
@@ -62,50 +64,34 @@ ObjectCompositeSettings::ObjectCompositeSettings(unsigned int verb_code, char co
_blur_tag(Glib::ustring(history_prefix) + ":blur"),
_opacity_tag(Glib::ustring(history_prefix) + ":opacity"),
_opacity_vbox(false, 0),
- _opacity_label(_("Opacity:")),
- _opacity_label_unit(_("%")),
-#if WITH_GTKMM_3_0
- _opacity_adjustment(Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 1.0, 0.0)),
-#else
- _opacity_adjustment(100.0, 0.0, 100.0, 1.0, 1.0, 0.0),
-#endif
- _opacity_hscale(_opacity_adjustment),
- _opacity_spin_button(_opacity_adjustment, 0.01, 1),
+ _opacity_scale(_("Opacity (%)"), 100.0, 0.0, 100.0, 1.0, 1.0, 1),
_fe_cb(flags),
_fe_vbox(false, 0),
- _fe_alignment(1, 1, 1, 1),
_blocked(false)
{
// Filter Effects
pack_start(_fe_vbox, false, false, 2);
- _fe_alignment.set_padding(0, 0, 4, 0);
- _fe_alignment.add(_fe_cb);
- _fe_vbox.pack_start(_fe_alignment, false, false, 0);
+ _fe_vbox.pack_start(_fe_cb, false, false, 0);
_fe_cb.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_blendBlurValueChanged));
// Opacity
pack_start(_opacity_vbox, false, false, 2);
- _opacity_label.set_alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER);
- _opacity_hbox.pack_start(_opacity_label, false, false, 3);
- //_opacity_vbox.pack_start(_opacity_label_box, false, false, 0);
- _opacity_vbox.pack_start(_opacity_hbox, false, false, 0);
- _opacity_hbox.pack_start(_opacity_hscale, true, true, 0);
- _opacity_hbox.pack_start(_opacity_spin_button, false, false, 0);
- _opacity_hbox.pack_start(_opacity_label_unit, false, false, 3);
- _opacity_hscale.set_draw_value(false);
-#if WITH_GTKMM_3_0
- _opacity_adjustment->signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged));
- _opacity_label.set_mnemonic_widget(_opacity_hscale);
-#else
- _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged));
- _opacity_label.set_mnemonic_widget(_opacity_hscale);
-#endif
+ _opacity_vbox.pack_start(_opacity_scale);
+
+ _opacity_scale.set_appearance("compact");
+
+ _opacity_scale.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged));
+
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ _opacity_scale.set_focuswidget(GTK_WIDGET(desktop->canvas));
/* SizeGroup keeps the blur and opacity labels aligned in Fill & Stroke dlg */
+/*
GtkSizeGroup *labels = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
gtk_size_group_add_widget(labels, (GtkWidget *) _opacity_label.gobj());
gtk_size_group_add_widget(labels, (GtkWidget *) _fe_cb.get_blur_label()->gobj());
+*/
show_all_children();
@@ -223,11 +209,7 @@ ObjectCompositeSettings::_opacityValueChanged()
SPCSSAttr *css = sp_repr_css_attr_new ();
Inkscape::CSSOStringStream os;
-#if WITH_GTKMM_3_0
- os << CLAMP (_opacity_adjustment->get_value() / 100, 0.0, 1.0);
-#else
- os << CLAMP (_opacity_adjustment.get_value() / 100, 0.0, 1.0);
-#endif
+ os << CLAMP (_opacity_scale.get_adjustment()->get_value() / 100, 0.0, 1.0);
sp_repr_css_set_property (css, "opacity", os.str().c_str());
_subject->setCSS(css);
@@ -263,18 +245,14 @@ ObjectCompositeSettings::_subjectChanged() {
switch (result) {
case QUERY_STYLE_NOTHING:
- _opacity_hbox.set_sensitive(false);
+ _opacity_vbox.set_sensitive(false);
// gtk_widget_set_sensitive (opa, FALSE);
break;
case QUERY_STYLE_SINGLE:
case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently
case QUERY_STYLE_MULTIPLE_SAME:
- _opacity_hbox.set_sensitive(true);
-#if WITH_GTKMM_3_0
- _opacity_adjustment->set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value));
-#else
- _opacity_adjustment.set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value));
-#endif
+ _opacity_vbox.set_sensitive(true);
+ _opacity_scale.get_adjustment()->set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value));
break;
}
diff --git a/src/ui/widget/object-composite-settings.h b/src/ui/widget/object-composite-settings.h
index 32da626d6..d3a208525 100644
--- a/src/ui/widget/object-composite-settings.h
+++ b/src/ui/widget/object-composite-settings.h
@@ -45,22 +45,12 @@ private:
Glib::ustring _opacity_tag;
Gtk::VBox _opacity_vbox;
- Gtk::HBox _opacity_hbox;
- Gtk::Label _opacity_label;
- Gtk::Label _opacity_label_unit;
-#if WITH_GTKMM_3_0
- Glib::RefPtr<Gtk::Adjustment> _opacity_adjustment;
-#else
- Gtk::Adjustment _opacity_adjustment;
-#endif
- Gtk::HScale _opacity_hscale;
- Inkscape::UI::Widget::SpinButton _opacity_spin_button;
+ Inkscape::UI::Widget::SpinScale _opacity_scale;
StyleSubject *_subject;
SimpleFilterModifier _fe_cb;
Gtk::VBox _fe_vbox;
- Gtk::Alignment _fe_alignment;
bool _blocked;
gulong _desktop_activated;
diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp
index a37f36eea..a4313f677 100644
--- a/src/ui/widget/selected-style.cpp
+++ b/src/ui/widget/selected-style.cpp
@@ -48,6 +48,7 @@
#include "pixmaps/cursor-adj-s.xpm"
#include "pixmaps/cursor-adj-l.xpm"
#include "sp-cursor.h"
+#include "gradient-chemistry.h"
static gdouble const _sw_presets[] = { 32 , 16 , 10 , 8 , 6 , 4 , 3 , 2 , 1.5 , 1 , 0.75 , 0.5 , 0.25 , 0.1 };
static gchar const *const _sw_presets_str[] = {"32", "16", "10", "8", "6", "4", "3", "2", "1.5", "1", "0.75", "0.5", "0.25", "0.1"};
@@ -598,6 +599,12 @@ void SelectedStyle::on_fill_invert() {
SPCSSAttr *css = sp_repr_css_attr_new ();
guint32 color = _thisselected[SS_FILL];
gchar c[64];
+ if (_mode[SS_FILL] == SS_LGRADIENT || _mode[SS_FILL] == SS_RGRADIENT) {
+ sp_gradient_invert_selected_gradients(_desktop, Inkscape::FOR_FILL);
+ return;
+
+ }
+
if (_mode[SS_FILL] != SS_COLOR) return;
sp_svg_write_color (c, sizeof(c),
SP_RGBA32_U_COMPOSE(
@@ -618,6 +625,10 @@ void SelectedStyle::on_stroke_invert() {
SPCSSAttr *css = sp_repr_css_attr_new ();
guint32 color = _thisselected[SS_STROKE];
gchar c[64];
+ if (_mode[SS_STROKE] == SS_LGRADIENT || _mode[SS_STROKE] == SS_RGRADIENT) {
+ sp_gradient_invert_selected_gradients(_desktop, Inkscape::FOR_STROKE);
+ return;
+ }
if (_mode[SS_STROKE] != SS_COLOR) return;
sp_svg_write_color (c, sizeof(c),
SP_RGBA32_U_COMPOSE(
diff --git a/src/ui/widget/spin-scale.cpp b/src/ui/widget/spin-scale.cpp
new file mode 100644
index 000000000..00c575568
--- /dev/null
+++ b/src/ui/widget/spin-scale.cpp
@@ -0,0 +1,248 @@
+/*
+ * Author:
+ *
+ * Copyright (C) 2012 Author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#include <glib.h>
+#include <glibmm/i18n.h>
+#include <glibmm/stringutils.h>
+#include <gtkmm/adjustment.h>
+
+#include "spin-scale.h"
+#include "ui/widget/gimpspinscale.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+SpinScale::SpinScale(const char* label, double value, double lower, double upper, double step_inc,
+ double climb_rate, int digits, const SPAttributeEnum a, const char* tip_text)
+ : AttrWidget(a, value)
+{
+
+#if WITH_GTKMM_3_0
+ _adjustment = Gtk::Adjustment::create(value, lower, upper, step_inc);
+ _spinscale = gimp_spin_scale_new (_adjustment->gobj(), label, digits);
+#else
+ _adjustment = new Gtk::Adjustment(value, lower, upper, step_inc);
+ _spinscale = gimp_spin_scale_new (_adjustment->gobj(), label, digits);
+#endif
+
+ signal_value_changed().connect(signal_attr_changed().make_slot());
+
+ pack_start(*Gtk::manage(Glib::wrap(_spinscale)));
+
+ if (tip_text){
+ gtk_widget_set_tooltip_text( _spinscale, tip_text );
+ }
+
+ show_all_children();
+}
+
+SpinScale::SpinScale(const char* label,
+#if WITH_GTKMM_3_0
+ Glib::RefPtr<Gtk::Adjustment> adj,
+#else
+ Gtk::Adjustment *adj,
+#endif
+ int digits, const SPAttributeEnum a, const char* tip_text)
+ : AttrWidget(a, 0.0),
+ _adjustment(adj)
+
+{
+
+ _spinscale = gimp_spin_scale_new (_adjustment->gobj(), label, digits);
+
+ signal_value_changed().connect(signal_attr_changed().make_slot());
+
+ pack_start(*Gtk::manage(Glib::wrap(_spinscale)));
+
+ if (tip_text){
+ gtk_widget_set_tooltip_text( _spinscale, tip_text );
+ }
+
+ show_all_children();
+}
+
+Glib::ustring SpinScale::get_as_attribute() const
+{
+ const double val = _adjustment->get_value();
+
+ //if(_spin.get_digits() == 0)
+ // return Glib::Ascii::dtostr((int)val);
+ //else
+ return Glib::Ascii::dtostr(val);
+}
+
+void SpinScale::set_from_attribute(SPObject* o)
+{
+ const gchar* val = attribute_value(o);
+ if(val)
+ _adjustment->set_value(Glib::Ascii::strtod(val));
+ else
+ _adjustment->set_value(get_default()->as_double());
+}
+
+Glib::SignalProxy0<void> SpinScale::signal_value_changed()
+{
+ return _adjustment->signal_value_changed();
+}
+
+double SpinScale::get_value() const
+{
+ return _adjustment->get_value();
+}
+
+void SpinScale::set_value(const double val)
+{
+ _adjustment->set_value(val);
+}
+
+void SpinScale::set_focuswidget(GtkWidget *widget)
+{
+ gimp_spin_scale_set_focuswidget(_spinscale, widget);
+}
+
+
+void SpinScale::set_appearance(const gchar* appearance)
+{
+ gimp_spin_scale_set_appearance(_spinscale, appearance);
+}
+
+#if WITH_GTKMM_3_0
+const Glib::RefPtr<Gtk::Adjustment> SpinScale::get_adjustment() const
+#else
+const Gtk::Adjustment *SpinScale::get_adjustment() const
+#endif
+{
+ return _adjustment;
+}
+#if WITH_GTKMM_3_0
+Glib::RefPtr<Gtk::Adjustment> SpinScale::get_adjustment()
+#else
+Gtk::Adjustment *SpinScale::get_adjustment()
+#endif
+{
+ return _adjustment;
+}
+
+
+DualSpinScale::DualSpinScale(const char* label1, const char* label2, double value, double lower, double upper, double step_inc,
+ double climb_rate, int digits, const SPAttributeEnum a, char* tip_text1, char* tip_text2)
+ : AttrWidget(a),
+ _s1(label1, value, lower, upper, step_inc, climb_rate, digits, SP_ATTR_INVALID, tip_text1),
+ _s2(label2, value, lower, upper, step_inc, climb_rate, digits, SP_ATTR_INVALID, tip_text2),
+ //TRANSLATORS: "Link" means to _link_ two sliders together
+ _link(C_("Sliders", "Link"))
+{
+ signal_value_changed().connect(signal_attr_changed().make_slot());
+
+ _s1.get_adjustment()->signal_value_changed().connect(_signal_value_changed.make_slot());
+ _s2.get_adjustment()->signal_value_changed().connect(_signal_value_changed.make_slot());
+ _s1.get_adjustment()->signal_value_changed().connect(sigc::mem_fun(*this, &DualSpinScale::update_linked));
+
+ _link.signal_toggled().connect(sigc::mem_fun(*this, &DualSpinScale::link_toggled));
+
+ Gtk::VBox* vb = Gtk::manage(new Gtk::VBox);
+ vb->add(_s1);
+ vb->add(_s2);
+ pack_start(*vb);
+ pack_start(_link, false, false);
+ _link.set_active(true);
+
+ show_all();
+}
+
+Glib::ustring DualSpinScale::get_as_attribute() const
+{
+ if(_link.get_active())
+ return _s1.get_as_attribute();
+ else
+ return _s1.get_as_attribute() + " " + _s2.get_as_attribute();
+}
+
+void DualSpinScale::set_from_attribute(SPObject* o)
+{
+ const gchar* val = attribute_value(o);
+ if(val) {
+ // Split val into parts
+ gchar** toks = g_strsplit(val, " ", 2);
+
+ if(toks) {
+ double v1 = 0.0, v2 = 0.0;
+ if(toks[0])
+ v1 = v2 = Glib::Ascii::strtod(toks[0]);
+ if(toks[1])
+ v2 = Glib::Ascii::strtod(toks[1]);
+
+ _link.set_active(toks[1] == 0);
+
+ _s1.get_adjustment()->set_value(v1);
+ _s2.get_adjustment()->set_value(v2);
+
+ g_strfreev(toks);
+ }
+ }
+}
+
+sigc::signal<void>& DualSpinScale::signal_value_changed()
+{
+ return _signal_value_changed;
+}
+
+const SpinScale& DualSpinScale::get_SpinScale1() const
+{
+ return _s1;
+}
+
+SpinScale& DualSpinScale::get_SpinScale1()
+{
+ return _s1;
+}
+
+const SpinScale& DualSpinScale::get_SpinScale2() const
+{
+ return _s2;
+}
+
+SpinScale& DualSpinScale::get_SpinScale2()
+{
+ return _s2;
+}
+
+/*void DualSpinScale::remove_scale()
+{
+ _s1.remove_scale();
+ _s2.remove_scale();
+}*/
+
+void DualSpinScale::link_toggled()
+{
+ _s2.set_sensitive(!_link.get_active());
+ update_linked();
+}
+
+void DualSpinScale::update_linked()
+{
+ if(_link.get_active())
+ _s2.set_value(_s1.get_value());
+}
+
+
+} // 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-scale.h b/src/ui/widget/spin-scale.h
new file mode 100644
index 000000000..a8403307f
--- /dev/null
+++ b/src/ui/widget/spin-scale.h
@@ -0,0 +1,117 @@
+/*
+ * Author:
+ *
+ * Copyright (C) 2012 Author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_SPIN_SCALE_H
+#define INKSCAPE_UI_WIDGET_SPIN_SCALE_H
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/box.h>
+#include <gtkmm/scale.h>
+#include <gtkmm/togglebutton.h>
+#include "spinbutton.h"
+#include "attr-widget.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Wrap the gimpspinscale class
+ * A combo widget with label, scale slider, spinbutton and adjustment
+ */
+class SpinScale : public Gtk::HBox, public AttrWidget
+{
+
+public:
+ SpinScale(const char* label, double value, double lower, double upper, double step_inc, double climb_rate,
+ int digits, const SPAttributeEnum a = SP_ATTR_INVALID, const char* tip_text = NULL);
+
+ SpinScale(const char* label,
+#if WITH_GTKMM_3_0
+ Glib::RefPtr<Gtk::Adjustment> adj,
+#else
+ Gtk::Adjustment *adj,
+#endif
+ int digits, const SPAttributeEnum a = SP_ATTR_INVALID, const char* tip_text = NULL);
+
+ virtual Glib::ustring get_as_attribute() const;
+ virtual void set_from_attribute(SPObject*);
+
+ // Shortcuts to _adjustment
+ Glib::SignalProxy0<void> signal_value_changed();
+ double get_value() const;
+ void set_value(const double);
+ void set_focuswidget(GtkWidget *widget);
+ void set_appearance(const gchar* appearance);
+
+#if WITH_GTKMM_3_0
+ const Glib::RefPtr<Gtk::Adjustment> get_adjustment() const;
+ Glib::RefPtr<Gtk::Adjustment> get_adjustment();
+#else
+ const Gtk::Adjustment *get_adjustment() const;
+ Gtk::Adjustment *get_adjustment();
+#endif
+
+private:
+#if WITH_GTKMM_3_0
+ Glib::RefPtr<Gtk::Adjustment> _adjustment;
+#else
+ Gtk::Adjustment *_adjustment;
+#endif
+
+ GtkWidget *_spinscale;
+};
+
+
+/**
+ * Contains two SpinScales for controlling number-opt-number attributes.
+ *
+ * @see SpinScale
+ */
+class DualSpinScale : public Gtk::HBox, public AttrWidget
+{
+public:
+ DualSpinScale(const char* label1, const char* label2, double value, double lower, double upper, double step_inc,
+ double climb_rate, int digits, const SPAttributeEnum, char* tip_text1, char* tip_text2);
+
+ virtual Glib::ustring get_as_attribute() const;
+ virtual void set_from_attribute(SPObject*);
+
+ sigc::signal<void>& signal_value_changed();
+
+ const SpinScale& get_SpinScale1() const;
+ SpinScale& get_SpinScale1();
+
+ const SpinScale& get_SpinScale2() const;
+ SpinScale& get_SpinScale2();
+
+ //void remove_scale();
+private:
+ void link_toggled();
+ void update_linked();
+ sigc::signal<void> _signal_value_changed;
+ SpinScale _s1, _s2;
+ Gtk::ToggleButton _link;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_SPIN_SCALE_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/ui/widget/spin-slider.cpp b/src/ui/widget/spin-slider.cpp
index 97ae18e20..323b1209c 100644
--- a/src/ui/widget/spin-slider.cpp
+++ b/src/ui/widget/spin-slider.cpp
@@ -186,7 +186,7 @@ void DualSpinSlider::set_from_attribute(SPObject* o)
gchar** toks = g_strsplit(val, " ", 2);
if(toks) {
- double v1, v2;
+ double v1 = 0.0, v2 = 0.0;
if(toks[0])
v1 = v2 = Glib::Ascii::strtod(toks[0]);
if(toks[1])
diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp
index 1ee26e803..857ae7019 100644
--- a/src/ui/widget/style-swatch.cpp
+++ b/src/ui/widget/style-swatch.cpp
@@ -227,8 +227,7 @@ StyleSwatch::setWatchedTool(const char *path, bool synthesize)
}
-void
-StyleSwatch::setStyle(SPCSSAttr *css)
+void StyleSwatch::setStyle(SPCSSAttr *css)
{
if (_css)
sp_repr_css_attr_unref (_css);
@@ -239,18 +238,18 @@ StyleSwatch::setStyle(SPCSSAttr *css)
_css = sp_repr_css_attr_new();
sp_repr_css_merge(_css, css);
- gchar const *css_string = sp_repr_css_write_string (_css);
+ Glib::ustring css_string;
+ sp_repr_css_write_string (_css, css_string);
SPStyle *temp_spstyle = sp_style_new(SP_ACTIVE_DOCUMENT);
- if (css_string)
- sp_style_merge_from_style_string (temp_spstyle, css_string);
-
+ if (~css_string.empty()) {
+ sp_style_merge_from_style_string (temp_spstyle, css_string.c_str());
+ }
+
setStyle (temp_spstyle);
-
sp_style_unref (temp_spstyle);
}
-void
-StyleSwatch::setStyle(SPStyle *query)
+void StyleSwatch::setStyle(SPStyle *query)
{
_place[SS_FILL].remove();
_place[SS_STROKE].remove();
diff --git a/src/verbs.cpp b/src/verbs.cpp
index d02472383..edfc45f8e 100644
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
@@ -1190,6 +1190,10 @@ void LayerVerb::perform(SPAction *action, void *data)
sp_selection_to_prev_layer(dt);
break;
}
+ case SP_VERB_LAYER_MOVE_TO: {
+ Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(dt, dt->currentLayer());
+ break;
+ }
case SP_VERB_LAYER_TO_TOP:
case SP_VERB_LAYER_TO_BOTTOM:
case SP_VERB_LAYER_RAISE:
@@ -2465,6 +2469,8 @@ Verb *Verb::_base_verbs[] = {
N_("Move selection to the layer above the current"), INKSCAPE_ICON("selection-move-to-layer-above")),
new LayerVerb(SP_VERB_LAYER_MOVE_TO_PREV, "LayerMoveToPrev", N_("Move Selection to Layer Bel_ow"),
N_("Move selection to the layer below the current"), INKSCAPE_ICON("selection-move-to-layer-below")),
+ new LayerVerb(SP_VERB_LAYER_MOVE_TO, "LayerMoveTo", N_("Move Selection to Layer..."),
+ N_("Move selection to layer"), INKSCAPE_ICON("layer-rename")),
new LayerVerb(SP_VERB_LAYER_TO_TOP, "LayerToTop", N_("Layer to _Top"),
N_("Raise the current layer to the top"), INKSCAPE_ICON("layer-top")),
new LayerVerb(SP_VERB_LAYER_TO_BOTTOM, "LayerToBottom", N_("Layer to _Bottom"),
diff --git a/src/verbs.h b/src/verbs.h
index 2f0ae85c1..aa801803c 100644
--- a/src/verbs.h
+++ b/src/verbs.h
@@ -139,6 +139,7 @@ enum {
SP_VERB_LAYER_PREV,
SP_VERB_LAYER_MOVE_TO_NEXT,
SP_VERB_LAYER_MOVE_TO_PREV,
+ SP_VERB_LAYER_MOVE_TO,
SP_VERB_LAYER_TO_TOP,
SP_VERB_LAYER_TO_BOTTOM,
SP_VERB_LAYER_RAISE,
diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp
index ae85ed515..7542e16b3 100644
--- a/src/widgets/gradient-toolbar.cpp
+++ b/src/widgets/gradient-toolbar.cpp
@@ -633,27 +633,7 @@ static void gr_linked_changed(GtkToggleAction *act, gpointer /*data*/)
static void gr_reverse(GtkWidget * /*button*/, gpointer data)
{
SPDesktop *desktop = static_cast<SPDesktop *>(data);
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
- SPEventContext *ev = sp_desktop_event_context(desktop);
-
- if (!ev) {
- return;
- }
-
- GrDrag *drag = ev->get_drag();
-
- // First try selected dragger
- if (drag && drag->selected) {
- drag->selected_reverse_vector();
- } else { // If no drag or no dragger selected, act on selection (both fill and stroke gradients)
- for (GSList const* i = selection->itemList(); i != NULL; i = i->next) {
- sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_FILL);
- sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_STROKE);
- }
- }
- // we did an undoable action
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_GRADIENT,
- _("Invert gradient"));
+ sp_gradient_reverse_selected_gradients(desktop);
}
/*
diff --git a/src/widgets/stroke-marker-selector.cpp b/src/widgets/stroke-marker-selector.cpp
index 0016dcf1f..206f166f9 100644
--- a/src/widgets/stroke-marker-selector.cpp
+++ b/src/widgets/stroke-marker-selector.cpp
@@ -45,9 +45,10 @@
static Inkscape::UI::Cache::SvgPreview svg_preview_cache;
-MarkerComboBox::MarkerComboBox(gchar const *id) :
+MarkerComboBox::MarkerComboBox(gchar const *id, int l) :
Gtk::ComboBox(),
combo_id(id),
+ loc(l),
updating(false),
markerCount(0)
{
@@ -256,11 +257,6 @@ const gchar * MarkerComboBox::get_active_marker_uri()
return marker;
}
-bool MarkerComboBox::isSelectedStock()
-{
- return get_active()->get_value(marker_columns.stock);
-}
-
void MarkerComboBox::set_active_history() {
const gchar *markid = get_active()->get_value(marker_columns.marker);
diff --git a/src/widgets/stroke-marker-selector.h b/src/widgets/stroke-marker-selector.h
index 14c5ad758..02038ea42 100644
--- a/src/widgets/stroke-marker-selector.h
+++ b/src/widgets/stroke-marker-selector.h
@@ -32,7 +32,7 @@ class Adjustment;
class MarkerComboBox : public Gtk::ComboBox {
public:
- MarkerComboBox(gchar const *id);
+ MarkerComboBox(gchar const *id, int loc);
~MarkerComboBox();
void setDesktop(SPDesktop *desktop);
@@ -45,14 +45,15 @@ public:
const gchar *get_active_marker_uri();
bool update() { return updating; };
gchar const *get_id() { return combo_id; };
- bool isSelectedStock();
void update_marker_image(gchar const *mname);
+ int get_loc() { return loc; };
private:
Glib::RefPtr<Gtk::ListStore> marker_store;
gchar const *combo_id;
+ int loc;
bool updating;
guint markerCount;
SPDesktop *desktop;
diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp
index 2c39945f7..5f686881f 100644
--- a/src/widgets/stroke-style.cpp
+++ b/src/widgets/stroke-style.cpp
@@ -291,7 +291,7 @@ StrokeStyle::StrokeStyle() :
// 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.
- startMarkerCombo = manage(new MarkerComboBox("marker-start"));
+ startMarkerCombo = manage(new MarkerComboBox("marker-start", SP_MARKER_LOC_START));
spw_label(table, _("_Start Markers:"), 0, i, startMarkerCombo);
startMarkerCombo->set_tooltip_text(_("Start Markers are drawn on the first node of a path or shape"));
startMarkerConn = startMarkerCombo->signal_changed().connect(
@@ -301,7 +301,7 @@ StrokeStyle::StrokeStyle() :
table->attach(*startMarkerCombo, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
i++;
- midMarkerCombo = manage(new MarkerComboBox("marker-mid"));
+ midMarkerCombo = manage(new MarkerComboBox("marker-mid", SP_MARKER_LOC_MID));
spw_label(table, _("_Mid Markers:"), 0, i, midMarkerCombo);
midMarkerCombo->set_tooltip_text(_("Mid Markers are drawn on every node of a path or shape except the first and last nodes"));
midMarkerConn = midMarkerCombo->signal_changed().connect(
@@ -311,7 +311,7 @@ StrokeStyle::StrokeStyle() :
table->attach(*midMarkerCombo, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
i++;
- endMarkerCombo = manage(new MarkerComboBox("marker-end"));
+ endMarkerCombo = manage(new MarkerComboBox("marker-end", SP_MARKER_LOC_END));
spw_label(table, _("_End Markers:"), 0, i, endMarkerCombo);
endMarkerCombo->set_tooltip_text(_("End Markers are drawn on the last node of a path or shape"));
endMarkerConn = endMarkerCombo->signal_changed().connect(
@@ -429,11 +429,7 @@ StrokeStyle::markerSelectCB(MarkerComboBox *marker_combo, StrokeStyle *spw, SPMa
if (selrepr) {
sp_repr_css_change_recursive(selrepr, css, "style");
SPObject *markerObj = getMarkerObj(marker, document);
- if (!marker_combo->isSelectedStock()) {
- // If arrow, marker will already be forked
- markerObj = spw->forkMarker(item, markerObj, marker_combo);
- }
- spw->setMarkerColor(item, markerObj, marker_combo);
+ spw->setMarkerColor(markerObj, marker_combo->get_loc(), item);
}
item->requestModified(SP_OBJECT_MODIFIED_FLAG);
@@ -570,74 +566,46 @@ StrokeStyle::selectionChangedCB()
}
/*
- * Make a new copy of a marker, set as auto collectable
- * Set the referencing items url to the new marker
+ * Fork marker if necessary and set the referencing items url to the new marker
* Return the new marker
*/
SPObject *
-StrokeStyle::forkMarker(SPItem *item, SPObject *marker, MarkerComboBox *marker_combo)
+StrokeStyle::forkMarker(SPObject *marker, int loc, SPItem *item)
{
-
if (!item || !marker) {
return NULL;
}
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- gboolean colorStock = prefs->getBool("/options/markers/colorStockMarkers", true);
- gboolean colorCustom = prefs->getBool("/options/markers/colorCustomMarkers", false);
- const gchar *stock = marker->getRepr()->attribute("inkscape:isstock");
- gboolean isStock = (!stock || !strcmp(stock,"true"));
- gchar const *combo_id = marker_combo->get_id();
-
- if (isStock ? !colorStock : !colorCustom) {
- return marker;
- }
-
+ gchar const *marker_id = SPMarkerNames[loc].key;
/*
- * Optimization
- * If this item already has this marker elsewhere (start/mid or end),
+ * Optimization when all the references to this marker are from this item
* then we can reuse it and dont need to fork
*/
- SPCSSAttr *css = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS);
Glib::ustring urlId = Glib::ustring::format("url(#", marker->getRepr()->attribute("id"), ")");
- const gchar *markers[3] = { "marker-start", "marker-mid", "marker-end" };
- //gboolean exists = false;
- for (int i = 0; i < 3; i++) {
- if (!strcmp(marker_combo->get_id(), markers[i])) {
- continue;
- }
- const char *urlMark = sp_repr_css_property(css, markers[i], "");
- if (!strcmp(urlId.c_str(), urlMark)) {
- return marker;
+ unsigned int refs = 0;
+ for (int i = SP_MARKER_LOC_START; i < SP_MARKER_LOC_QTY; i++) {
+ if (item->style->marker[i].set && !strcmp(urlId.c_str(), item->style->marker[i].value)) {
+ refs++;
}
}
+ if (marker->hrefcount <= refs) {
+ return marker;
+ }
-
- SPDocument *doc = SP_ACTIVE_DOCUMENT;
- SPDefs *defs = doc->getDefs();
- Inkscape::XML::Document *xml_doc = doc->getReprDoc();
- // Turn off garbage-collectable or it might be collected before we can use it
- marker->getRepr()->setAttribute("inkscape:collect", NULL);
- Inkscape::XML::Node *mark_repr = marker->getRepr()->duplicate(xml_doc);
- defs->getRepr()->addChild(mark_repr, NULL);
- gchar const *markid = marker->getRepr()->attribute("inkscape:stockid") ? marker->getRepr()->attribute("inkscape:stockid") : marker->getRepr()->attribute("id");
- mark_repr->setAttribute("inkscape:stockid", markid);
+ marker = sp_marker_fork_if_necessary(marker);
// Update the items url to new marker
+ Inkscape::XML::Node *mark_repr = marker->getRepr();
SPCSSAttr *css_item = sp_repr_css_attr_new();
- sp_repr_css_set_property(css_item, combo_id, g_strconcat("url(#", mark_repr->attribute("id"), ")", NULL));
+ sp_repr_css_set_property(css_item, marker_id, g_strconcat("url(#", mark_repr->attribute("id"), ")", NULL));
sp_repr_css_change_recursive(item->getRepr(), css_item, "style");
- // privates are garbage-collectable
- mark_repr->setAttribute("inkscape:collect", "always");
- marker->getRepr()->setAttribute("inkscape:collect", "always");
-
Inkscape::GC::release(mark_repr);
sp_repr_css_attr_unref(css_item);
css_item = 0;
- return doc->getObjectById(mark_repr->attribute("id"));
+ return marker;
}
/**
@@ -650,7 +618,7 @@ StrokeStyle::forkMarker(SPItem *item, SPObject *marker, MarkerComboBox *marker_c
*
*/
void
-StrokeStyle::setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *marker_combo)
+StrokeStyle::setMarkerColor(SPObject *marker, int loc, SPItem *item)
{
if (!item || !marker) {
@@ -667,6 +635,9 @@ StrokeStyle::setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *mark
return;
}
+ // Check if we need to fork this marker
+ marker = forkMarker(marker, loc, item);
+
Inkscape::XML::Node *repr = marker->getRepr()->firstChild();
if (!repr) {
return;
@@ -674,9 +645,9 @@ StrokeStyle::setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *mark
// Current line style
SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS);
- const char *lstroke = getItemColorForMarker(item, FOR_STROKE, marker_combo);
+ const char *lstroke = getItemColorForMarker(item, FOR_STROKE, loc);
const char *lstroke_opacity = sp_repr_css_property(css_item, "stroke-opacity", "1");
- const char *lfill = getItemColorForMarker(item, FOR_FILL, marker_combo);
+ const char *lfill = getItemColorForMarker(item, FOR_FILL, loc);
const char *lfill_opacity = sp_repr_css_property(css_item, "fill-opacity", "1");
// Current marker style
@@ -725,7 +696,7 @@ StrokeStyle::setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *mark
* If its a gradient, then return first or last stop color
*/
const char *
-StrokeStyle::getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_stroke, MarkerComboBox *marker_combo)
+StrokeStyle::getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_stroke, int loc)
{
SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS);
const char *color;
@@ -736,11 +707,12 @@ StrokeStyle::getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_s
if (!strncmp (color, "url(", 4)) {
// If the item has a gradient use the first stop color for the marker
+
SPGradient *grad = getGradient(item, fill_or_stroke);
if (grad) {
SPGradient *vector = grad->getVector(FALSE);
SPStop *stop = vector->getFirstStop();
- if (marker_combo == endMarkerCombo) {
+ if (loc == SP_MARKER_LOC_END) {
stop = sp_last_stop(vector);
}
if (stop) {
@@ -1231,7 +1203,7 @@ StrokeStyle::updateAllMarkers(GSList const *objects)
gboolean update = prefs->getBool("/options/markers/colorUpdateMarkers", true);
if (update) {
- setMarkerColor(SP_ITEM(object), marker, combo);
+ setMarkerColor(marker, combo->get_loc(), SP_ITEM(object));
SPDocument *document = sp_desktop_document(desktop);
DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE,
diff --git a/src/widgets/stroke-style.h b/src/widgets/stroke-style.h
index 546880bc2..d437f7e12 100644
--- a/src/widgets/stroke-style.h
+++ b/src/widgets/stroke-style.h
@@ -67,6 +67,15 @@ class Widget;
class Container;
}
+struct { gchar const *key; gint value; } const SPMarkerNames[] = {
+ {"marker-all", SP_MARKER_LOC},
+ {"marker-start", SP_MARKER_LOC_START},
+ {"marker-mid", SP_MARKER_LOC_MID},
+ {"marker-end", SP_MARKER_LOC_END},
+ {"", SP_MARKER_LOC_QTY},
+ {NULL, -1}
+};
+
/**
* Creates an instance of a paint style widget.
*/
@@ -106,9 +115,9 @@ private:
void setCapButtons(Gtk::ToggleButton *active);
void scaleLine();
void setScaledDash(SPCSSAttr *css, int ndash, double *dash, double offset, double scale);
- void setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *marker_combo);
- SPObject *forkMarker(SPItem *item, SPObject *marker, MarkerComboBox *marker_combo);
- const char *getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_stroke, MarkerComboBox *marker_combo);
+ void setMarkerColor(SPObject *marker, int loc, SPItem *item);
+ SPObject *forkMarker(SPObject *marker, int loc, SPItem *item);
+ const char *getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_stroke, int loc);
Gtk::RadioButton * makeRadioButton(Gtk::RadioButton *tb, char const *icon,
Gtk::HBox *hb, gchar const *key, gchar const *data);
diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp
index dcfd109d8..60ede002f 100644
--- a/src/widgets/text-toolbar.cpp
+++ b/src/widgets/text-toolbar.cpp
@@ -1222,13 +1222,16 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT);
double size = sp_style_css_size_px_to_units(query->font_size.computed, unit);
- gchar size_text[G_ASCII_DTOSTR_BUF_SIZE];
- g_ascii_dtostr (size_text, sizeof (size_text), size);
+ //gchar size_text[G_ASCII_DTOSTR_BUF_SIZE];
+ //g_ascii_dtostr (size_text, sizeof (size_text), size);
+
+ Inkscape::CSSOStringStream os;
+ os << size;
Ink_ComboBoxEntry_Action* fontSizeAction =
INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontSizeAction" ) );
sp_text_set_sizes(GTK_LIST_STORE(ink_comboboxentry_action_get_model(fontSizeAction)), unit);
- ink_comboboxentry_action_set_active_text( fontSizeAction, size_text );
+ ink_comboboxentry_action_set_active_text( fontSizeAction, os.str().c_str() );
Glib::ustring tooltip = Glib::ustring::format("Font size (", sp_style_get_css_unit_string(unit), ")");
ink_comboboxentry_action_set_tooltip ( fontSizeAction, tooltip.c_str());
@@ -1461,7 +1464,8 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
GTK_TREE_MODEL(model),
-1, // Entry width
50, // Extra list width
- (gpointer)cell_data_func ); // Cell layout
+ (gpointer)cell_data_func,// Cell layout
+ GTK_WIDGET(desktop->canvas)); // Focus widget
ink_comboboxentry_action_popup_enable( act ); // Enable entry completion
gchar *const warning = _("Font not found on system");
ink_comboboxentry_action_set_warning( act, warning ); // Show icon with tooltip if missing font
@@ -1495,7 +1499,11 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
_(tooltip.c_str()),
NULL,
GTK_TREE_MODEL(model_size),
- 4 ); // Width in characters
+ 4, // Width in characters
+ 0, // Extra list width
+ NULL, // Cell layout
+ GTK_WIDGET(desktop->canvas)); // Focus widget
+
g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontsize_value_changed), holder );
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
g_object_set_data( holder, "TextFontSizeAction", act );
@@ -1510,7 +1518,11 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
_("Font style"),
NULL,
GTK_TREE_MODEL(model_style),
- 12 ); // Width in characters
+ 12, // Width in characters
+ 0, // Extra list width
+ NULL, // Cell layout
+ GTK_WIDGET(desktop->canvas)); // Focus widget
+
g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontstyle_value_changed), holder );
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
g_object_set_data( holder, "TextFontStyleAction", act );
diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp
index 594ac83c6..7fba4d7c6 100644
--- a/src/xml/repr-css.cpp
+++ b/src/xml/repr-css.cpp
@@ -270,10 +270,9 @@ double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double def
/**
* Write a style attribute string from a list of properties stored in an SPCSAttr object.
*/
-gchar *sp_repr_css_write_string(SPCSSAttr *css)
+void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str)
{
- Glib::ustring buffer;
-
+ str.clear();
for ( List<AttributeRecord const> iter = css->attributeList() ;
iter ; ++iter )
{
@@ -281,26 +280,21 @@ gchar *sp_repr_css_write_string(SPCSSAttr *css)
continue;
}
- buffer.append(g_quark_to_string(iter->key));
- buffer.push_back(':');
+ str.append(g_quark_to_string(iter->key));
+ str.push_back(':');
if (!strcmp(g_quark_to_string(iter->key), "font-family")
|| !strcmp(g_quark_to_string(iter->key), "-inkscape-font-specification")) {
// we only quote font-family/font-specification, as SPStyle does
- gchar *val_quoted = css2_escape_quote (iter->value);
- if (val_quoted) {
- buffer.append(val_quoted);
- g_free (val_quoted);
- }
+ Glib::ustring val_quoted = css2_escape_quote (iter->value);
+ str.append(val_quoted);
} else {
- buffer.append(iter->value); // unquoted
+ str.append(iter->value); // unquoted
}
if (rest(iter)) {
- buffer.push_back(';');
+ str.push_back(';');
}
}
-
- return (buffer.empty() ? NULL : g_strdup (buffer.c_str()));
}
/**
@@ -312,7 +306,8 @@ void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
g_assert(css != NULL);
g_assert(attr != NULL);
- gchar *value = sp_repr_css_write_string(css);
+ Glib::ustring value;
+ sp_repr_css_write_string(css, value);
/*
* If the new value is different from the old value, this will sometimes send a signal via
@@ -320,9 +315,7 @@ void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
* SPObject::sp_object_repr_attr_changed and thus updates the object's SPStyle. This update
* results in another call to repr->setAttribute().
*/
- repr->setAttribute(attr, value);
-
- if (value) g_free (value);
+ repr->setAttribute(attr, value.c_str());
}
/**
diff --git a/src/xml/repr.h b/src/xml/repr.h
index 86a798e3e..debd0f489 100644
--- a/src/xml/repr.h
+++ b/src/xml/repr.h
@@ -79,7 +79,7 @@ void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name);
bool sp_repr_css_property_is_unset(SPCSSAttr *css, gchar const *name);
double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double defval);
-gchar *sp_repr_css_write_string(SPCSSAttr *css);
+void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str);
void sp_repr_css_set(Inkscape::XML::Node *repr, SPCSSAttr *css, gchar const *key);
void sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src);
void sp_repr_css_attr_add_from_string(SPCSSAttr *css, const gchar *data);
diff --git a/src/xml/simple-node.cpp b/src/xml/simple-node.cpp
index c197d648b..55bd28afe 100644
--- a/src/xml/simple-node.cpp
+++ b/src/xml/simple-node.cpp
@@ -318,8 +318,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_
// Check usefulness of attributes on elements in the svg namespace, optionally don't add them to tree.
Glib::ustring element = g_quark_to_string(_name);
- //g_warning("setAttribute: %s: %s: %s", element.c_str(), name, value);
-
+ // g_message("setAttribute: %s: %s: %s", element.c_str(), name, value);
gchar* cleaned_value = g_strdup( value );
// Only check elements in SVG name space and don't block setting attribute to NULL.
@@ -347,7 +346,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_
// tree (and thus has no parent), default values will not be tested.
if( !strcmp( name, "style" ) && (flags >= SP_ATTR_CLEAN_STYLE_WARN) ) {
g_free( cleaned_value );
- cleaned_value = sp_attribute_clean_style( this, value, flags );
+ cleaned_value = const_cast<char*>(sp_attribute_clean_style( this, value, flags ).c_str());
// if( g_strcmp0( value, cleaned_value ) ) {
// g_warning( "SimpleNode::setAttribute: %s", id.c_str() );
// g_warning( " original: %s", value);
@@ -401,9 +400,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_
_observers.notifyAttributeChanged(*this, key, old_value, new_value);
//g_warning( "setAttribute notified: %s: %s: %s: %s", name, element.c_str(), old_value, new_value );
}
-
g_free( cleaned_value );
-
}
void SimpleNode::addChild(Node *generic_child, Node *generic_ref) {