summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c5e2a1c)
raw | patch | inline | side by side (parent: c5e2a1c)
author | tweenk <tweenk@users.sourceforge.net> | |
Sat, 21 Feb 2009 01:59:56 +0000 (01:59 +0000) | ||
committer | tweenk <tweenk@users.sourceforge.net> | |
Sat, 21 Feb 2009 01:59:56 +0000 (01:59 +0000) |
should be. Build libinkscape.a - should reduce link time.
93 files changed:
diff --git a/src/Makefile.am b/src/Makefile.am
index dece3edcfe9e4c2fefdbece3159c6edf11a728a9..517e89f1afd8e4057eb395810ce470af0492557c 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
## Process this file with automake to produce Makefile.in
-
# ################################################
-#
# G L O B A L
-#
# ################################################
# Should work in either automake1.7 or 1.8, but 1.6 doesn't
# Executables compiled by "make" and installed by "make install"
bin_PROGRAMS = inkscape inkview
+# Libraries which should be compiled by "make" but not installed.
+# Use this only for libraries that are really standalone, rather than for
+# source tree subdirectories.
+if WITH_INKBOARD
+libpedro = pedro/libpedro.a
+endif
+noinst_LIBRARIES = \
+ libinkscape.a \
+ dom/libdom.a \
+ libcroco/libcroco.a \
+ libavoid/libavoid.a \
+ libgdl/libgdl.a \
+ libcola/libcola.a \
+ libvpsc/libvpsc.a \
+ livarot/libvarot.a \
+ 2geom/lib2geom.a \
+ $(libpedro) \
+ libinkversion.a
+
+all_libs = \
+ $(noinst_LIBRARIES) \
+ $(INKSCAPE_LIBS) \
+ $(GNOME_VFS_LIBS) \
+ $(XFT_LIBS) \
+ $(FREETYPE_LIBS) \
+ $(kdeldadd) \
+ $(win32ldflags) \
+ $(CARBON_LDFLAGS) \
+ $(PERL_LIBS) \
+ $(PYTHON_LIBS) \
+ $(INKBOARD_LIBS) \
+ $(LIBWPG_LIBS) \
+ $(IMAGEMAGICK_LIBS)
+
# Add sources common for Inkscape and Inkview to this variable.
ink_common_sources =
# Add Inkscape-only sources here.
# Add Inkview-only sources here.
inkview_SOURCES =
-# Libraries which should be compiled by "make" but not installed.
-# Use this only for libraries that are really standalone, rather than for
-# source tree subdirectories.
-noinst_LIBRARIES = $(inkscape_private_libs)
-
INCLUDES = \
$(PERL_CFLAGS) $(PYTHON_CFLAGS) \
$(FREETYPE_CFLAGS) \
inkjar_libs = inkjar/libinkjar.a
endif
-# Extra files to remove when doing "make distclean"
-DISTCLEANFILES = \
- helper/sp-marshal.cpp \
- helper/sp-marshal.h \
- inkscape-version.cpp
-
-if WITH_INKBOARD
-libpedro = pedro/libpedro.a
-endif
-
-inkscape_private_libs = \
- dom/libdom.a \
- libcroco/libcroco.a \
- libavoid/libavoid.a \
- libgdl/libgdl.a \
- libcola/libcola.a \
- libvpsc/libvpsc.a \
- livarot/libvarot.a \
- 2geom/lib2geom.a \
- $(libpedro) \
- libinkversion.a
-
-all_libs = \
- $(inkscape_private_libs) \
- $(INKSCAPE_LIBS) \
- $(GNOME_VFS_LIBS) \
- $(XFT_LIBS) \
- $(FREETYPE_LIBS) \
- $(kdeldadd) \
- $(win32ldflags) \
- $(CARBON_LDFLAGS) \
- $(PERL_LIBS) \
- $(PYTHON_LIBS) \
- $(INKBOARD_LIBS) \
- $(LIBWPG_LIBS) \
- $(IMAGEMAGICK_LIBS)
-
# Include all partial makefiles from subdirectories
include Makefile_insert
include application/Makefile_insert
traits/reference.h \
$(jabber_whiteboard_SOURCES)
+# Extra files to remove when doing "make distclean"
+DISTCLEANFILES = \
+ helper/sp-marshal.cpp \
+ helper/sp-marshal.h \
+ inkscape-version.cpp
+
# ################################################
-#
# B I N A R I E S
-#
# ################################################
-inkscape_SOURCES += main.cpp $(ink_common_sources) $(win32_sources)
+# this should speed up the build
+libinkscape_a_SOURCES = $(ink_common_sources)
+
+inkscape_SOURCES += main.cpp $(win32_sources)
inkscape_LDADD = $(all_libs)
inkscape_LDFLAGS = --export-dynamic $(kdeldflags)
-inkview_SOURCES += inkview.cpp $(ink_common_sources) $(win32_sources)
+inkview_SOURCES += inkview.cpp $(win32_sources)
inkview_LDADD = $(all_libs)
+# ################################################
+# VERSION REPORTING
+# ################################################
+
+libinkversion_a_SOURCES = inkscape-version.cpp inkscape-version.h
+
+if USE_SVN_VERSION
+inkscape_version_deps = $(top_srcdir)/.svn/entries
+endif
+
+# If this is an SVN snapshot build, regenerate this file every time
+# someone updates the SVN working directory.
+inkscape-version.cpp: $(inkscape_version_deps)
+ VER_PREFIX="$(VERSION)"; \
+ if test -x "$(srcdir)/.svn" -a ! -z `which svn`; then \
+ VER_SVNREV=" r`svn info $(srcdir) | sed -n -e '/^Revision:/s/Revision: \(.*\)/\1/p'`"; \
+ if test ! -z "`svn status -q $(srcdir)`"; then \
+ VER_CUSTOM=" custom"; \
+ fi; \
+ fi; \
+ VERSION="$$VER_PREFIX$$VER_SVNREV$$VER_CUSTOM"; \
+ echo "namespace Inkscape { " \
+ "char const *version_string = \"$$VERSION\"; " \
+ "}" > inkscape-version.new.cpp; \
+ if cmp -s inkscape-version.new.cpp inkscape-version.cpp; then \
+ rm inkscape-version.new.cpp; \
+ else \
+ mv inkscape-version.new.cpp inkscape-version.cpp; \
+ fi; \
+ echo $$VERSION
+
# #################################
# ## TESTING STUFF (make check) ###
# #################################
diff --git a/src/Makefile_insert b/src/Makefile_insert
index 360f69cc45ad8bbae941c5e36fafd8ab4a959fc3..a3babf265720d4c24cc29e0886b06f42909d0c38 100644 (file)
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
## Makefile.am fragment, included by src/Makefile.am.
-
-# ################################################
-#
-# I N K S C A P E
-#
-# ################################################
-
-# libinkpre.a: any object that's sharable between inkscape & inkview,
-# and isn't needed by object files in subdirectories (i.e. libinkpre.a
-# comes before subdirectory libraries on the link line).
-#
-# Excludes winmain.cpp (a gui wrapper around main): I'm guessing that
-# it needs to be explicitly listed as a source of each graphical
-# binary: it isn't (to my knowledge) called by main (whether directly
-# or indirectly), so I don't think that putting it in a library will
-# suffice to get it linked in. Windows devel please confirm. -- pjrm.
-
ink_common_sources += \
algorithms/find-last-if.h \
algorithms/longest-common-suffix.h \
print.cpp print.h \
profile-manager.cpp profile-manager.h \
proj_pt.cpp proj_pt.h \
+ rdf.cpp rdf.h \
rect-context.cpp rect-context.h \
require-config.h \
round.h \
tools-switch.cpp tools-switch.h \
transf_mat_3x4.cpp transf_mat_3x4.h \
tweak-context.h tweak-context.cpp \
- ui/context-menu.cpp \
- ui/context-menu.h \
+ unclump.cpp unclump.h \
undo-stack-observer.h \
unicoderange.cpp unicoderange.h \
unit-constants.h \
sp-object.$(OBJEXT): helper/sp-marshal.h
view.$(OBJEXT): helper/sp-marshal.h
-libinkversion_a_SOURCES = inkscape-version.cpp inkscape-version.h
-
-if USE_SVN_VERSION
-inkscape_version_deps = $(top_srcdir)/.svn/entries
-endif
-
-# If this is an SVN snapshot build, regenerate this file every time
-# someone updates the SVN working directory.
-inkscape-version.cpp: $(inkscape_version_deps)
- VER_PREFIX="$(VERSION)"; \
- if test -x "$(srcdir)/.svn" -a ! -z `which svn`; then \
- VER_SVNREV=" r`svn info $(srcdir) | sed -n -e '/^Revision:/s/Revision: \(.*\)/\1/p'`"; \
- if test ! -z "`svn status -q $(srcdir)`"; then \
- VER_CUSTOM=" custom"; \
- fi; \
- fi; \
- VERSION="$$VER_PREFIX$$VER_SVNREV$$VER_CUSTOM"; \
- echo "namespace Inkscape { " \
- "char const *version_string = \"$$VERSION\"; " \
- "}" > inkscape-version.new.cpp; \
- if cmp -s inkscape-version.new.cpp inkscape-version.cpp; then \
- rm inkscape-version.new.cpp; \
- else \
- mv inkscape-version.new.cpp inkscape-version.cpp; \
- fi; \
- echo $$VERSION
-
# ######################
# ### CxxTest stuff ####
# ######################
diff --git a/src/conditions.cpp b/src/conditions.cpp
index 9a46f27d13f536caed9b4aa3c0c4734cd4e50080..4a18a6913be5ddebf2bae19315a599260f279f39 100644 (file)
--- a/src/conditions.cpp
+++ b/src/conditions.cpp
#include <glibmm/ustring.h>
#include "conditions.h"
#include "xml/repr.h"
-#include "dialogs/rdf.h"
+#include "rdf.h"
typedef bool (* condition_evaluator)(SPItem const *item, gchar const *value);
diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp
index 46fb00cca773cf27eeaac5f3b4df20ceb32d5e98..73cd646650d0f66077bac56885ec4d54229c3846 100644 (file)
--- a/src/desktop-events.cpp
+++ b/src/desktop-events.cpp
-#define __SP_DESKTOP_EVENTS_C__
-
-/*
- * Event handlers for SPDesktop
- *
- * Author:
+/** @file
+ * @brief Event handlers for SPDesktop
+ */
+/* Author:
* Lauris Kaplinski <lauris@kaplinski.com>
*
* Copyright (C) 1999-2002 Lauris Kaplinski
#endif
#include <map>
#include <string>
+#include <2geom/line.h>
+#include <glibmm/i18n.h>
+
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "dialogs/dialog-events.h"
+#include "display/canvas-axonomgrid.h"
+#include "display/canvas-grid.h"
#include "display/guideline.h"
#include "display/snap-indicator.h"
+#include "document.h"
+#include "event-context.h"
+#include "helper/action.h"
#include "helper/unit-menu.h"
#include "helper/units.h"
-#include "desktop.h"
-#include "document.h"
+#include "message-context.h"
+#include "preferences.h"
+#include "snap.h"
#include "sp-guide.h"
+#include "sp-metrics.h"
#include "sp-namedview.h"
-#include "desktop-handles.h"
-#include "event-context.h"
+#include "tools-switch.h"
+#include "ui/dialog/guides.h"
#include "widgets/desktop-widget.h"
-#include "sp-metrics.h"
-#include <glibmm/i18n.h>
-#include "dialogs/dialog-events.h"
-#include "message-context.h"
#include "xml/repr.h"
-#include "dialogs/guidelinedialog.h"
-#include "snap.h"
-#include "display/canvas-grid.h"
-#include "display/canvas-axonomgrid.h"
-#include "preferences.h"
-#include "helper/action.h"
-#include "tools-switch.h"
-#include <2geom/line.h>
static void snoop_extended(GdkEvent* event, SPDesktop *desktop);
static void init_extended();
index f7404a8b2146e7c50bdd0a2f48eb7ddc54169c7c..32a11e83115b8403a88122b9ca2c90451d5c5601 100644 (file)
dialogs/clonetiler.h \
dialogs/dialog-events.cpp \
dialogs/dialog-events.h \
- dialogs/eek-color-def.cpp \
- dialogs/eek-color-def.h \
- dialogs/eek-preview.cpp \
- dialogs/eek-preview.h \
dialogs/export.cpp \
dialogs/export.h \
- dialogs/extensions.cpp \
- dialogs/extensions.h \
- dialogs/fill-style.cpp \
- dialogs/fill-style.h \
dialogs/find.cpp \
dialogs/find.h \
- dialogs/guidelinedialog.cpp \
- dialogs/guidelinedialog.h \
- dialogs/iconpreview.cpp \
- dialogs/iconpreview.h \
- dialogs/in-dt-coordsys.cpp \
- dialogs/in-dt-coordsys.h \
dialogs/input.cpp \
dialogs/input.h \
dialogs/item-properties.cpp \
dialogs/item-properties.h \
- dialogs/layer-properties.cpp \
- dialogs/layer-properties.h \
- dialogs/layers-panel.cpp \
- dialogs/layers-panel.h \
dialogs/object-attributes.cpp \
dialogs/object-attributes.h \
- dialogs/rdf.cpp \
- dialogs/rdf.h \
- dialogs/sp-attribute-widget.cpp \
- dialogs/sp-attribute-widget.h \
dialogs/spellcheck.cpp \
dialogs/spellcheck.h \
- dialogs/stroke-style.cpp \
- dialogs/stroke-style.h \
- dialogs/swatches.cpp \
- dialogs/swatches.h \
dialogs/text-edit.cpp \
dialogs/text-edit.h \
- dialogs/unclump.cpp \
- dialogs/unclump.h \
dialogs/xml-tree.cpp \
dialogs/xml-tree.h
diff --git a/src/dialogs/eek-color-def.cpp b/src/dialogs/eek-color-def.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/** @file
- * @brief EEK color definition
- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Eek Color Definition.
- *
- * The Initial Developer of the Original Code is
- * Jon A. Cruz.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "config.h"
-
-#ifdef HAVE_LIBINTL_H
-#include <libintl.h>
-#endif
-
-#if !defined(_)
-#define _(s) gettext(s)
-#endif // !defined(_)
-
-#include "eek-color-def.h"
-
-namespace eek
-{
-
-ColorDef::ColorDef() :
- descr(_("none")),
- r(0),
- g(0),
- b(0),
- none(true),
- editable(false)
-{
-}
-
-ColorDef::ColorDef( unsigned int r, unsigned int g, unsigned int b, const std::string& description ) :
- descr(description),
- r(r),
- g(g),
- b(b),
- none(false),
- editable(false)
-{
-}
-
-ColorDef::~ColorDef()
-{
-}
-
-ColorDef::ColorDef( ColorDef const &other )
-{
- if ( this != &other ) {
- *this = other;
- }
-}
-
-ColorDef& ColorDef::operator=( ColorDef const &other )
-{
- if ( this != & other )
- {
- r = other.r;
- g = other.g;
- b = other.b;
- descr = other.descr;
- none = other.none;
- editable = other.editable;
- }
- return *this;
-}
-
-class ColorDef::HookData {
-public:
- HookData( ColorCallback cb, void* data ) {_cb = cb; _data = data;}
- ColorCallback _cb;
- void* _data;
-};
-
-void ColorDef::setRGB( unsigned int r, unsigned int g, unsigned int b )
-{
- if ( r != this->r || g != this->g || b != this->b ) {
- this->r = r;
- this->g = g;
- this->b = b;
-
- // beware of callbacks changing things
- for ( std::vector<HookData*>::iterator it = _listeners.begin(); it != _listeners.end(); ++it )
- {
- if ( (*it)->_cb )
- {
- (*it)->_cb( (*it)->_data );
- }
- }
- }
-}
-
-void ColorDef::addCallback( ColorCallback cb, void* data )
-{
- _listeners.push_back( new HookData(cb, data) );
-}
-
-void ColorDef::removeCallback( ColorCallback cb, void* data )
-{
- (void)cb;
- (void)data;
-}
-
-} // namespace eek
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/eek-color-def.h b/src/dialogs/eek-color-def.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/** @file
- * @brief EEK color definition
- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Eek Color Definition.
- *
- * The Initial Developer of the Original Code is
- * Jon A. Cruz.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef SEEN_EEK_COLOR_DEF_H
-#define SEEN_EEK_COLOR_DEF_H
-
-#include <string>
-#include <vector>
-
-namespace eek
-{
-
-typedef void (*ColorCallback)( void* data );
-
-
-class ColorDef
-{
-public:
- ColorDef();
- ColorDef( unsigned int r, unsigned int g, unsigned int b, const std::string& description );
- virtual ~ColorDef();
-
- ColorDef( ColorDef const &other );
- virtual ColorDef& operator=( ColorDef const &other );
-
- void setRGB( unsigned int r, unsigned int g, unsigned int b );
- unsigned int getR() const { return r; }
- unsigned int getG() const { return g; }
- unsigned int getB() const { return b; }
-
- void addCallback( ColorCallback cb, void* data );
- void removeCallback( ColorCallback cb, void* data );
-
- bool isEditable() const { return editable; }
- void setEditable( bool edit ) { editable = edit; }
-
- std::string descr;
-
-protected:
- unsigned int r;
- unsigned int g;
- unsigned int b;
- bool none;
- bool editable;
-
-private:
- class HookData;
-
- std::vector<HookData*> _listeners;
-};
-
-
-} // namespace eek
-
-#endif // SEEN_EEK_COLOR_DEF_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/eek-preview.cpp b/src/dialogs/eek-preview.cpp
+++ /dev/null
@@ -1,736 +0,0 @@
-/** @file
- * @brief EEK preview stuff
- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Eek Preview Stuffs.
- *
- * The Initial Developer of the Original Code is
- * Jon A. Cruz.
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <gtk/gtk.h>
-#include "eek-preview.h"
-
-#define PRIME_BUTTON_MAGIC_NUMBER 1
-
-#define FOCUS_PROP_ID 1
-
-/* Keep in sycn with last value in eek-preview.h */
-#define PREVIEW_SIZE_LAST PREVIEW_SIZE_HUGE
-#define PREVIEW_SIZE_NEXTFREE (PREVIEW_SIZE_HUGE + 1)
-
-#define PREVIEW_MAX_RATIO 500
-
-static void eek_preview_class_init( EekPreviewClass *klass );
-static void eek_preview_init( EekPreview *preview );
-
-static GtkWidgetClass* parent_class = 0;
-
-void eek_preview_set_color( EekPreview* preview, int r, int g, int b )
-{
- preview->_r = r;
- preview->_g = g;
- preview->_b = b;
-
- gtk_widget_queue_draw(GTK_WIDGET(preview));
-}
-
-
-void eek_preview_set_pixbuf( EekPreview* preview, GdkPixbuf* pixbuf )
-{
- preview->_previewPixbuf = pixbuf;
-
- gtk_widget_queue_draw(GTK_WIDGET(preview));
-
- if (preview->_scaled) {
- g_object_unref(preview->_scaled);
- preview->_scaled = 0;
- }
- preview->_scaledW = gdk_pixbuf_get_width(preview->_previewPixbuf);
- preview->_scaledH = gdk_pixbuf_get_height(preview->_previewPixbuf);
-}
-
-
-GType eek_preview_get_type(void)
-{
- static GType preview_type = 0;
-
- if (!preview_type) {
- static const GTypeInfo preview_info = {
- sizeof( EekPreviewClass ),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc)eek_preview_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof( EekPreview ),
- 0, /* n_preallocs */
- (GInstanceInitFunc)eek_preview_init,
- NULL /* value_table */
- };
-
-
- preview_type = g_type_register_static( GTK_TYPE_DRAWING_AREA, "EekPreview", &preview_info, (GTypeFlags)0 );
- }
-
- return preview_type;
-}
-
-static gboolean setupDone = FALSE;
-static GtkRequisition sizeThings[PREVIEW_SIZE_NEXTFREE];
-
-void eek_preview_set_size_mappings( guint count, GtkIconSize const* sizes )
-{
- gint width = 0;
- gint height = 0;
- gint smallest = 512;
- gint largest = 0;
- guint i = 0;
- guint delta = 0;
-
- for ( i = 0; i < count; ++i ) {
- gboolean worked = gtk_icon_size_lookup( sizes[i], &width, &height );
- if ( worked ) {
- if ( width < smallest ) {
- smallest = width;
- }
- if ( width > largest ) {
- largest = width;
- }
- }
- }
-
- smallest = (smallest * 3) / 4;
-
- delta = largest - smallest;
-
- for ( i = 0; i < G_N_ELEMENTS(sizeThings); ++i ) {
- guint val = smallest + ( (i * delta) / (G_N_ELEMENTS(sizeThings) - 1) );
- sizeThings[i].width = val;
- sizeThings[i].height = val;
- }
-
- setupDone = TRUE;
-}
-
-static void eek_preview_size_request( GtkWidget* widget, GtkRequisition* req )
-{
- gint width = 0;
- gint height = 0;
- EekPreview* preview = EEK_PREVIEW(widget);
-
- if ( !setupDone ) {
- GtkIconSize sizes[] = {
- GTK_ICON_SIZE_MENU,
- GTK_ICON_SIZE_SMALL_TOOLBAR,
- GTK_ICON_SIZE_LARGE_TOOLBAR,
- GTK_ICON_SIZE_BUTTON,
- GTK_ICON_SIZE_DIALOG
- };
- eek_preview_set_size_mappings( G_N_ELEMENTS(sizes), sizes );
- }
-
- width = sizeThings[preview->_size].width;
- height = sizeThings[preview->_size].height;
-
- if ( preview->_view == VIEW_TYPE_LIST ) {
- width *= 3;
- }
-
- if ( preview->_ratio != 100 ) {
- width = (width * preview->_ratio) / 100;
- if ( width < 0 ) {
- width = 1;
- }
- }
-
- req->width = width;
- req->height = height;
-}
-
-enum {
- CLICKED_SIGNAL,
- ALTCLICKED_SIGNAL,
- LAST_SIGNAL
-};
-
-
-static guint eek_preview_signals[LAST_SIGNAL] = { 0 };
-
-
-gboolean eek_preview_expose_event( GtkWidget* widget, GdkEventExpose* event )
-{
-/* g_message("Exposed!!! %s", GTK_WIDGET_HAS_FOCUS(widget) ? "XXX" : "---" ); */
- gint insetX = 0;
- gint insetY = 0;
-
- (void)event;
-/*
- gint lower = widget->allocation.width;
- lower = (widget->allocation.height < lower) ? widget->allocation.height : lower;
- if ( lower > 16 ) {
- insetX++;
- if ( lower > 18 ) {
- insetX++;
- if ( lower > 22 ) {
- insetX++;
- if ( lower > 24 ) {
- insetX++;
- if ( lower > 32 ) {
- insetX++;
- }
- }
- }
- }
- insetY = insetX;
- }
-*/
-
- if ( GTK_WIDGET_DRAWABLE( widget ) ) {
- GtkStyle* style = gtk_widget_get_style( widget );
-
- if ( insetX > 0 || insetY > 0 ) {
- gtk_paint_flat_box( style,
- widget->window,
- (GtkStateType)GTK_WIDGET_STATE(widget),
- GTK_SHADOW_NONE,
- NULL,
- widget,
- NULL,
- 0, 0,
- widget->allocation.width, widget->allocation.height);
- }
-
- GdkGC *gc = gdk_gc_new( widget->window );
- EekPreview* preview = EEK_PREVIEW(widget);
- GdkColor fg = {0, preview->_r, preview->_g, preview->_b};
-
- gdk_colormap_alloc_color( gdk_colormap_get_system(), &fg, FALSE, TRUE );
-
- gdk_gc_set_foreground( gc, &fg );
-
- gdk_draw_rectangle( widget->window,
- gc,
- TRUE,
- insetX, insetY,
- widget->allocation.width - (insetX * 2), widget->allocation.height - (insetY * 2) );
-
- if ( preview->_linked ) {
- /* Draw arrow */
- GdkRectangle possible = {insetX, insetY, (widget->allocation.width - (insetX * 2)), (widget->allocation.height - (insetY * 2)) };
- GdkRectangle area = {possible.x, possible.y, possible.width / 2, possible.height / 2 };
-
- /* Make it square */
- if ( area.width > area.height )
- area.width = area.height;
- if ( area.height > area.width )
- area.height = area.width;
-
- /* Center it horizontally */
- if ( area.width < possible.width ) {
- int diff = (possible.width - area.width) / 2;
- area.x += diff;
- }
-
-
- if ( preview->_linked & PREVIEW_LINK_IN ) {
- gtk_paint_arrow( style,
- widget->window,
- (GtkStateType)widget->state,
- GTK_SHADOW_ETCHED_IN,
- NULL, /* clip area. &area, */
- widget, /* may be NULL */
- NULL, /* detail */
- GTK_ARROW_DOWN,
- FALSE,
- area.x, area.y,
- area.width, area.height
- );
- }
-
- if ( preview->_linked & PREVIEW_LINK_OUT ) {
- GdkRectangle otherArea = {area.x, area.y, area.width, area.height};
- if ( otherArea.height < possible.height ) {
- otherArea.y = possible.y + (possible.height - otherArea.height);
- }
-
- gtk_paint_arrow( style,
- widget->window,
- (GtkStateType)widget->state,
- GTK_SHADOW_ETCHED_OUT,
- NULL, /* clip area. &area, */
- widget, /* may be NULL */
- NULL, /* detail */
- GTK_ARROW_UP,
- FALSE,
- otherArea.x, otherArea.y,
- otherArea.width, otherArea.height
- );
- }
-
- if ( preview->_linked & PREVIEW_LINK_OTHER ) {
- GdkRectangle otherArea = {insetX, area.y, area.width, area.height};
- if ( otherArea.height < possible.height ) {
- otherArea.y = possible.y + (possible.height - otherArea.height) / 2;
- }
-
- gtk_paint_arrow( style,
- widget->window,
- (GtkStateType)widget->state,
- GTK_SHADOW_ETCHED_OUT,
- NULL, /* clip area. &area, */
- widget, /* may be NULL */
- NULL, /* detail */
- GTK_ARROW_LEFT,
- FALSE,
- otherArea.x, otherArea.y,
- otherArea.width, otherArea.height
- );
- }
- }
-
- if ( preview->_previewPixbuf ) {
- GtkDrawingArea* da = &(preview->drawing);
- GdkDrawable* drawable = (GdkDrawable*) (((GtkWidget*)da)->window);
- gint w = 0;
- gint h = 0;
- gdk_drawable_get_size(drawable, &w, &h);
- if ((w != preview->_scaledW) || (h != preview->_scaledH)) {
- if (preview->_scaled) {
- g_object_unref(preview->_scaled);
- }
- preview->_scaled = gdk_pixbuf_scale_simple(preview->_previewPixbuf, w, h, GDK_INTERP_BILINEAR);
- preview->_scaledW = w;
- preview->_scaledH = h;
- }
-
- GdkPixbuf* pix = (preview->_scaled) ? preview->_scaled : preview->_previewPixbuf;
- gdk_draw_pixbuf( drawable, 0, pix, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0 );
- }
-
-
- if ( GTK_WIDGET_HAS_FOCUS(widget) ) {
- gtk_paint_focus( style,
- widget->window,
- GTK_STATE_NORMAL,
- NULL, /* GdkRectangle *area, */
- widget,
- NULL,
- 0 + 1, 0 + 1,
- widget->allocation.width - 2, widget->allocation.height - 2 );
- }
- }
-
-
- return FALSE;
-}
-
-
-static gboolean eek_preview_enter_cb( GtkWidget* widget, GdkEventCrossing* event )
-{
- if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
- EekPreview* preview = EEK_PREVIEW(widget);
- preview->_within = TRUE;
- gtk_widget_set_state( widget, preview->_hot ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT );
- }
- return FALSE;
-}
-
-static gboolean eek_preview_leave_cb( GtkWidget* widget, GdkEventCrossing* event )
-{
- if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
- EekPreview* preview = EEK_PREVIEW(widget);
- preview->_within = FALSE;
- gtk_widget_set_state( widget, GTK_STATE_NORMAL );
- }
- return FALSE;
-}
-
-/*
-static gboolean eek_preview_focus_in_event( GtkWidget* widget, GdkEventFocus* event )
-{
- g_message("focus IN");
- gboolean blip = parent_class->focus_in_event ? parent_class->focus_in_event(widget, event) : FALSE;
- return blip;
-}
-
-static gboolean eek_preview_focus_out_event( GtkWidget* widget, GdkEventFocus* event )
-{
- g_message("focus OUT");
- gboolean blip = parent_class->focus_out_event ? parent_class->focus_out_event(widget, event) : FALSE;
- return blip;
-}
-*/
-
-static gboolean eek_preview_button_press_cb( GtkWidget* widget, GdkEventButton* event )
-{
- if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
- EekPreview* preview = EEK_PREVIEW(widget);
-
- if ( preview->_takesFocus && !GTK_WIDGET_HAS_FOCUS(widget) ) {
- gtk_widget_grab_focus(widget);
- }
-
- if ( event->button == PRIME_BUTTON_MAGIC_NUMBER ) {
- preview->_hot = TRUE;
- if ( preview->_within ) {
- gtk_widget_set_state( widget, GTK_STATE_ACTIVE );
- }
- }
- }
-
- return FALSE;
-}
-
-static gboolean eek_preview_button_release_cb( GtkWidget* widget, GdkEventButton* event )
-{
- if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
- EekPreview* preview = EEK_PREVIEW(widget);
- preview->_hot = FALSE;
- gtk_widget_set_state( widget, GTK_STATE_NORMAL );
- if ( preview->_within && event->button == PRIME_BUTTON_MAGIC_NUMBER ) {
- gboolean isAlt = (event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK;
-
- if ( isAlt ) {
- g_signal_emit( widget, eek_preview_signals[ALTCLICKED_SIGNAL], 0, 2 );
- } else {
- g_signal_emit( widget, eek_preview_signals[CLICKED_SIGNAL], 0 );
- }
- }
- }
- return FALSE;
-}
-
-gboolean eek_preview_key_press_event( GtkWidget* widget, GdkEventKey* event)
-{
- (void)widget;
- (void)event;
- g_message("TICK");
- return FALSE;
-}
-
-gboolean eek_preview_key_release_event( GtkWidget* widget, GdkEventKey* event)
-{
- (void)widget;
- (void)event;
- g_message("tock");
- return FALSE;
-}
-
-static void eek_preview_get_property( GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GObjectClass* gobjClass = G_OBJECT_CLASS(parent_class);
- switch ( property_id ) {
- case FOCUS_PROP_ID:
- {
- EekPreview* preview = EEK_PREVIEW( object );
- g_value_set_boolean( value, preview->_takesFocus );
- }
- break;
- default:
- {
- if ( gobjClass->get_property ) {
- gobjClass->get_property( object, property_id, value, pspec );
- }
- }
- }
-}
-
-static void eek_preview_set_property( GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GObjectClass* gobjClass = G_OBJECT_CLASS(parent_class);
- switch ( property_id ) {
- case FOCUS_PROP_ID:
- {
- EekPreview* preview = EEK_PREVIEW( object );
- gboolean val = g_value_get_boolean( value );
- if ( val != preview->_takesFocus ) {
- preview->_takesFocus = val;
- }
- }
- break;
- default:
- {
- if ( gobjClass->set_property ) {
- gobjClass->set_property( object, property_id, value, pspec );
- }
- }
- }
-}
-
-
-static gboolean eek_preview_popup_menu( GtkWidget* widget )
-{
-/* g_message("Do the popup!"); */
- gboolean blip = parent_class->popup_menu ? parent_class->popup_menu(widget) : FALSE;
- return blip;
-}
-
-
-static void eek_preview_class_init( EekPreviewClass *klass )
-{
- GObjectClass* gobjClass = G_OBJECT_CLASS(klass);
- /*GtkObjectClass* objectClass = (GtkObjectClass*)klass;*/
- GtkWidgetClass* widgetClass = (GtkWidgetClass*)klass;
-
- gobjClass->set_property = eek_preview_set_property;
- gobjClass->get_property = eek_preview_get_property;
-
- /*objectClass->destroy = eek_preview_destroy;*/
-
- parent_class = (GtkWidgetClass*)g_type_class_peek_parent( klass );
-
- /*widgetClass->map = ;*/
- /*widgetClass->unmap = ;*/
- /*widgetClass->realize = ;*/
- /*widgetClass->unrealize = ;*/
- widgetClass->size_request = eek_preview_size_request;
- /*widgetClass->size_allocate = ;*/
- /*widgetClass->state_changed = ;*/
- /*widgetClass->style_set = ;*/
- /*widgetClass->grab_notify = ;*/
-
- widgetClass->button_press_event = eek_preview_button_press_cb;
- widgetClass->button_release_event = eek_preview_button_release_cb;
- /*widgetClass->delete_event = ;*/
- /*widgetClass->destroy_event = ;*/
- widgetClass->expose_event = eek_preview_expose_event;
-/* widgetClass->key_press_event = eek_preview_key_press_event; */
-/* widgetClass->key_release_event = eek_preview_key_release_event; */
- widgetClass->enter_notify_event = eek_preview_enter_cb;
- widgetClass->leave_notify_event = eek_preview_leave_cb;
- /*widgetClass->configure_event = ;*/
- /*widgetClass->focus_in_event = eek_preview_focus_in_event;*/
- /*widgetClass->focus_out_event = eek_preview_focus_out_event;*/
-
- /* selection */
- /*widgetClass->selection_get = ;*/
- /*widgetClass->selection_received = ;*/
-
-
- /* drag source: */
- /*widgetClass->drag_begin = ;*/
- /*widgetClass->drag_end = ;*/
- /*widgetClass->drag_data_get = ;*/
- /*widgetClass->drag_data_delete = ;*/
-
- /* drag target: */
- /*widgetClass->drag_leave = ;*/
- /*widgetClass->drag_motion = ;*/
- /*widgetClass->drag_drop = ;*/
- /*widgetClass->drag_data_received = ;*/
-
- /* For keybindings: */
- widgetClass->popup_menu = eek_preview_popup_menu;
- /*widgetClass->show_help = ;*/
-
- /* Accessibility support: */
- /*widgetClass->get_accessible = ;*/
- /*widgetClass->screen_changed = ;*/
- /*widgetClass->can_activate_accel = ;*/
-
-
- eek_preview_signals[CLICKED_SIGNAL] =
- g_signal_new( "clicked",
- G_TYPE_FROM_CLASS( klass ),
- (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
- G_STRUCT_OFFSET( EekPreviewClass, clicked ),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 );
-
- eek_preview_signals[ALTCLICKED_SIGNAL] =
- g_signal_new( "alt-clicked",
- G_TYPE_FROM_CLASS( klass ),
- (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
- G_STRUCT_OFFSET( EekPreviewClass, clicked ),
- NULL, NULL,
- g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
- 1, G_TYPE_INT );
-
-
- g_object_class_install_property( gobjClass,
- FOCUS_PROP_ID,
- g_param_spec_boolean(
- "focus-on-click",
- NULL,
- "flag to grab focus when clicked",
- TRUE,
- (GParamFlags)(G_PARAM_READWRITE | G_PARAM_CONSTRUCT)
- )
- );
-}
-
-void eek_preview_set_linked( EekPreview* splat, LinkType link )
-{
- link = (LinkType)(link & PREVIEW_LINK_ALL);
- if ( link != (LinkType)splat->_linked ) {
- splat->_linked = link;
-
- gtk_widget_queue_draw( GTK_WIDGET(splat) );
- }
-}
-
-LinkType eek_preview_get_linked( EekPreview* splat )
-{
- return (LinkType)splat->_linked;
-}
-
-gboolean eek_preview_get_focus_on_click( EekPreview* preview )
-{
- return preview->_takesFocus;
-}
-
-void eek_preview_set_focus_on_click( EekPreview* preview, gboolean focus_on_click )
-{
- if ( focus_on_click != preview->_takesFocus ) {
- preview->_takesFocus = focus_on_click;
- }
-}
-
-void eek_preview_set_details( EekPreview* preview, PreviewStyle prevstyle, ViewType view, PreviewSize size, guint ratio )
-{
- preview->_prevstyle = prevstyle;
- preview->_view = view;
-
- if ( size > PREVIEW_SIZE_LAST ) {
- size = PREVIEW_SIZE_LAST;
- }
- preview->_size = size;
-
- if ( ratio > PREVIEW_MAX_RATIO ) {
- ratio = PREVIEW_MAX_RATIO;
- }
- preview->_ratio = ratio;
-
- gtk_widget_queue_draw(GTK_WIDGET(preview));
-}
-
-static void eek_preview_init( EekPreview *preview )
-{
- GtkWidget* widg = GTK_WIDGET(preview);
- GTK_WIDGET_SET_FLAGS( widg, GTK_CAN_FOCUS );
- GTK_WIDGET_SET_FLAGS( widg, GTK_RECEIVES_DEFAULT );
-
- gtk_widget_set_sensitive( widg, TRUE );
-
- gtk_widget_add_events(widg, GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_KEY_PRESS_MASK
- | GDK_KEY_RELEASE_MASK
- | GDK_FOCUS_CHANGE_MASK
- | GDK_ENTER_NOTIFY_MASK
- | GDK_LEAVE_NOTIFY_MASK );
-
-/* gtk_widget_add_events( widg, GDK_ALL_EVENTS_MASK );*/
-
- preview->_r = 0x80;
- preview->_g = 0x80;
- preview->_b = 0xcc;
- preview->_scaledW = 0;
- preview->_scaledH = 0;
-
- preview->_hot = FALSE;
- preview->_within = FALSE;
- preview->_takesFocus = FALSE;
-
- preview->_prevstyle = PREVIEW_STYLE_ICON;
- preview->_view = VIEW_TYPE_LIST;
- preview->_size = PREVIEW_SIZE_SMALL;
- preview->_ratio = 100;
-
- preview->_previewPixbuf = 0;
- preview->_scaled = 0;
-
-/*
- GdkColor color = {0};
- color.red = (255 << 8) | 255;
-
- GdkColor whack = {0};
- whack.green = (255 << 8) | 255;
-
- gtk_widget_modify_bg( widg, GTK_STATE_NORMAL, &color );
- gtk_widget_modify_bg( widg, GTK_STATE_PRELIGHT, &whack );
-*/
-
-/* GTK_STATE_ACTIVE, */
-/* GTK_STATE_PRELIGHT, */
-/* GTK_STATE_SELECTED, */
-/* GTK_STATE_INSENSITIVE */
-
- if ( 0 ) {
- GdkColor color = {0,0,0,0};
-
- color.red = 0xffff;
- color.green = 0;
- color.blue = 0xffff;
- gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE );
- gtk_widget_modify_bg(widg, GTK_STATE_ACTIVE, &color);
-
- color.red = 0;
- color.green = 0xffff;
- color.blue = 0;
- gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE );
- gtk_widget_modify_bg(widg, GTK_STATE_SELECTED, &color);
-
- color.red = 0xffff;
- color.green = 0;
- color.blue = 0;
- gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE );
- gtk_widget_modify_bg( widg, GTK_STATE_PRELIGHT, &color );
- }
-}
-
-
-GtkWidget* eek_preview_new(void)
-{
- return GTK_WIDGET( g_object_new( EEK_PREVIEW_TYPE, NULL ) );
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/eek-preview.h b/src/dialogs/eek-preview.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/** @file
- * @brief EEK preview stuff
- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Eek Preview Stuffs.
- *
- * The Initial Developer of the Original Code is
- * Jon A. Cruz.
- * Portions created by the Initial Developer are Copyright (C) 2005-2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef SEEN_EEK_PREVIEW_H
-#define SEEN_EEK_PREVIEW_H
-
-#include <gdk/gdkpixbuf.h>
-#include <gtk/gtkdrawingarea.h>
-
-G_BEGIN_DECLS
-
-
-#define EEK_PREVIEW_TYPE (eek_preview_get_type())
-#define EEK_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST( (obj), EEK_PREVIEW_TYPE, EekPreview))
-#define EEK_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST( (klass), EEK_PREVIEW_TYPE, EekPreviewClass))
-#define IS_EEK_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE( (obj), EEK_PREVIEW_TYPE))
-#define IS_EEK_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE( (klass), EEK_PREVIEW_TYPE))
-#define EEK_PREVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS( (obj), EEK_PREVIEW_TYPE, EekPreviewClass))
-
-typedef enum {
- PREVIEW_STYLE_ICON = 0,
- PREVIEW_STYLE_PREVIEW,
- PREVIEW_STYLE_NAME,
- PREVIEW_STYLE_BLURB,
- PREVIEW_STYLE_ICON_NAME,
- PREVIEW_STYLE_ICON_BLURB,
- PREVIEW_STYLE_PREVIEW_NAME,
- PREVIEW_STYLE_PREVIEW_BLURB
-} PreviewStyle;
-
-typedef enum {
- VIEW_TYPE_LIST = 0,
- VIEW_TYPE_GRID
-} ViewType;
-
-typedef enum {
- PREVIEW_SIZE_TINY = 0,
- PREVIEW_SIZE_SMALL,
- PREVIEW_SIZE_MEDIUM,
- PREVIEW_SIZE_BIG,
- PREVIEW_SIZE_BIGGER,
- PREVIEW_SIZE_HUGE
-} PreviewSize;
-
-typedef enum {
- PREVIEW_LINK_NONE = 0,
- PREVIEW_LINK_IN = 1,
- PREVIEW_LINK_OUT = 2,
- PREVIEW_LINK_OTHER = 4,
- PREVIEW_LINK_ALL = 7
-} LinkType;
-
-typedef struct _EekPreview EekPreview;
-typedef struct _EekPreviewClass EekPreviewClass;
-
-
-struct _EekPreview
-{
- GtkDrawingArea drawing;
-
- int _r;
- int _g;
- int _b;
- int _scaledW;
- int _scaledH;
-
- gboolean _hot;
- gboolean _within;
- gboolean _takesFocus;
-
- PreviewStyle _prevstyle;
- ViewType _view;
- PreviewSize _size;
- guint _ratio;
- guint _linked;
- GdkPixbuf* _previewPixbuf;
- GdkPixbuf* _scaled;
-};
-
-struct _EekPreviewClass
-{
- GtkDrawingAreaClass parent_class;
-
- void (*clicked) (EekPreview* splat);
-};
-
-
-GType eek_preview_get_type(void) G_GNUC_CONST;
-GtkWidget* eek_preview_new(void);
-
-void eek_preview_set_details( EekPreview* splat, PreviewStyle prevstyle, ViewType view, PreviewSize size, guint ratio );
-void eek_preview_set_color( EekPreview* splat, int r, int g, int b );
-void eek_preview_set_pixbuf( EekPreview* splat, GdkPixbuf* pixbuf );
-
-void eek_preview_set_linked( EekPreview* splat, LinkType link );
-LinkType eek_preview_get_linked( EekPreview* splat );
-
-gboolean eek_preview_get_focus_on_click( EekPreview* preview );
-void eek_preview_set_focus_on_click( EekPreview* preview, gboolean focus_on_click );
-
-void eek_preview_set_size_mappings( guint count, GtkIconSize const* sizes );
-
-G_END_DECLS
-
-#endif /* SEEN_EEK_PREVIEW_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/extensions.cpp b/src/dialogs/extensions.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/** @file
- * @brief A simple dialog with information about extensions
- */
-/* Authors:
- * Jon A. Cruz
- *
- * Copyright (C) 2005 Jon A. Cruz
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <gtk/gtkdialog.h> //for GTK_RESPONSE* types
-#include <gtkmm/scrolledwindow.h>
-
-#include "extension/db.h"
-#include "extensions.h"
-
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-using Inkscape::Extension::Extension;
-
-ExtensionsPanel &ExtensionsPanel::getInstance()
-{
- ExtensionsPanel &instance = *new ExtensionsPanel();
-
- instance.rescan();
-
- return instance;
-}
-
-
-
-/**
- * Constructor
- */
-ExtensionsPanel::ExtensionsPanel() :
- _showAll(false)
-{
- Gtk::ScrolledWindow* scroller = new Gtk::ScrolledWindow();
-
- _view.set_editable(false);
-
- scroller->add(_view);
- add(*scroller);
-
- rescan();
-
- show_all_children();
-}
-
-void ExtensionsPanel::set_full(bool full)
-{
- if ( full != _showAll ) {
- _showAll = full;
- rescan();
- }
-}
-
-void ExtensionsPanel::listCB( Inkscape::Extension::Extension * in_plug, gpointer in_data )
-{
- ExtensionsPanel * self = (ExtensionsPanel*)in_data;
-
- const char* stateStr;
- Extension::state_t state = in_plug->get_state();
- switch ( state ) {
- case Extension::STATE_LOADED:
- {
- stateStr = "loaded";
- }
- break;
- case Extension::STATE_UNLOADED:
- {
- stateStr = "unloaded";
- }
- break;
- case Extension::STATE_DEACTIVATED:
- {
- stateStr = "deactivated";
- }
- break;
- default:
- stateStr = "unknown";
- }
-
- if ( self->_showAll || in_plug->deactivated() ) {
-// gchar* line = g_strdup_printf( " extension %c %c %s |%s|%s|",
-// (in_plug->loaded() ? 'X' : '-'),
-// (in_plug->deactivated() ? 'X' : '-'),
-// stateStr, in_plug->get_id(),
-// in_plug->get_name() );
- gchar* line = g_strdup_printf( "%s %s\n \"%s\"", stateStr, in_plug->get_name(), in_plug->get_id() );
-
- self->_view.get_buffer()->insert( self->_view.get_buffer()->end(), line );
- self->_view.get_buffer()->insert( self->_view.get_buffer()->end(), "\n" );
- //g_message( "%s", line );
- }
-
-
-
- return;
-}
-
-void ExtensionsPanel::rescan()
-{
- _view.get_buffer()->set_text("Extensions:\n");
-// g_message("/------------------");
-
- Inkscape::Extension::db.foreach(listCB, (gpointer)this);
-
-// g_message("\\------------------");
-}
-
-} //namespace Dialogs
-} //namespace UI
-} //namespace Inkscape
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/extensions.h b/src/dialogs/extensions.h
--- a/src/dialogs/extensions.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/** @file
- * A simple dialog with information about extensions
- */
-/* Authors:
- * Jon A. Cruz
- *
- * Copyright (C) 2005 The Inkscape Organization
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_EXTENSIONS_H
-#define SEEN_EXTENSIONS_H
-
-#include <gtkmm/textview.h>
-#include "ui/widget/panel.h"
-
-namespace Inkscape {
-namespace Extension {
-class Extension;
-}
-}
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-
-/**
- * A panel that displays information about extensions.
- */
-class ExtensionsPanel : public Inkscape::UI::Widget::Panel
-{
-public:
- ExtensionsPanel();
-
- static ExtensionsPanel &getInstance();
-
- void set_full(bool full);
-
-private:
- ExtensionsPanel(ExtensionsPanel const &); // no copy
- ExtensionsPanel &operator=(ExtensionsPanel const &); // no assign
-
- static void listCB(Inkscape::Extension::Extension *in_plug, gpointer in_data);
-
- void rescan();
-
- bool _showAll;
- Gtk::TextView _view;
-};
-
-} //namespace Dialogs
-} //namespace UI
-} //namespace Inkscape
-
-#endif // SEEN_EXTENSIONS_H
diff --git a/src/dialogs/fill-style.cpp b/src/dialogs/fill-style.cpp
+++ /dev/null
@@ -1,552 +0,0 @@
-/** @file
- * @brief Fill style widget
- */
-/* Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Frank Felfe <innerspace@iname.com>
- * bulia byak <buliabyak@users.sf.net>
- *
- * Copyright (C) 1999-2005 authors
- * Copyright (C) 2001-2002 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#define noSP_FS_VERBOSE
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <glibmm/i18n.h>
-
-#include "desktop-handles.h"
-#include "desktop-style.h"
-#include "display/sp-canvas.h"
-#include "document-private.h"
-#include "gradient-chemistry.h"
-#include "inkscape.h"
-#include "selection.h"
-#include "sp-linear-gradient.h"
-#include "sp-pattern.h"
-#include "sp-radial-gradient.h"
-#include "style.h"
-#include "widgets/paint-selector.h"
-#include "widgets/sp-widget.h"
-#include "xml/repr.h"
-
-#include "dialogs/fill-style.h"
-
-
-// These can be deleted once we sort out the libart dependence.
-
-#define ART_WIND_RULE_NONZERO 0
-
-static void sp_fill_style_widget_construct ( SPWidget *spw,
- SPPaintSelector *psel );
-
-static void sp_fill_style_widget_modify_selection ( SPWidget *spw,
- Inkscape::Selection *selection,
- guint flags,
- SPPaintSelector *psel );
-
-static void sp_fill_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw );
-
-static void sp_fill_style_widget_change_selection ( SPWidget *spw,
- Inkscape::Selection *selection,
- SPPaintSelector *psel );
-
-static void sp_fill_style_widget_update (SPWidget *spw);
-
-static void sp_fill_style_widget_paint_mode_changed ( SPPaintSelector *psel,
- SPPaintSelectorMode mode,
- SPWidget *spw );
-static void sp_fill_style_widget_fillrule_changed ( SPPaintSelector *psel,
- SPPaintSelectorFillRule mode,
- SPWidget *spw );
-
-static void sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw );
-static void sp_fill_style_widget_paint_changed (SPPaintSelector *psel, SPWidget *spw );
-
-GtkWidget *
-sp_fill_style_widget_new (void)
-{
- GtkWidget *spw = sp_widget_new_global (INKSCAPE);
-
- GtkWidget *vb = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (vb);
- gtk_container_add (GTK_CONTAINER (spw), vb);
-
- GtkWidget *psel = sp_paint_selector_new (true); // with fillrule selector
- gtk_widget_show (psel);
- gtk_box_pack_start (GTK_BOX (vb), psel, TRUE, TRUE, 0);
- g_object_set_data (G_OBJECT (spw), "paint-selector", psel);
-
- g_signal_connect ( G_OBJECT (psel), "mode_changed",
- G_CALLBACK (sp_fill_style_widget_paint_mode_changed),
- spw );
-
- g_signal_connect ( G_OBJECT (psel), "dragged",
- G_CALLBACK (sp_fill_style_widget_paint_dragged),
- spw );
-
- g_signal_connect ( G_OBJECT (psel), "changed",
- G_CALLBACK (sp_fill_style_widget_paint_changed),
- spw );
-
- g_signal_connect ( G_OBJECT (psel), "fillrule_changed",
- G_CALLBACK (sp_fill_style_widget_fillrule_changed),
- spw );
-
-
- g_signal_connect ( G_OBJECT (spw), "construct",
- G_CALLBACK (sp_fill_style_widget_construct), psel);
-
-//FIXME: switch these from spw signals to global inkscape object signals; spw just retranslates
-//those anyway; then eliminate spw
- g_signal_connect ( G_OBJECT (spw), "modify_selection",
- G_CALLBACK (sp_fill_style_widget_modify_selection), psel);
-
- g_signal_connect ( G_OBJECT (spw), "change_selection",
- G_CALLBACK (sp_fill_style_widget_change_selection), psel);
-
- g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_fill_style_widget_change_subselection), spw);
-
- sp_fill_style_widget_update (SP_WIDGET (spw));
-
- return spw;
-
-} // end of sp_fill_style_widget_new()
-
-
-
-static void
-sp_fill_style_widget_construct( SPWidget *spw, SPPaintSelector */*psel*/ )
-{
-#ifdef SP_FS_VERBOSE
- g_print ( "Fill style widget constructed: inkscape %p repr %p\n",
- spw->inkscape, spw->repr );
-#endif
- if (spw->inkscape) {
- sp_fill_style_widget_update (spw);
- }
-
-} // end of sp_fill_style_widget_construct()
-
-static void
-sp_fill_style_widget_modify_selection( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- guint flags,
- SPPaintSelector */*psel*/ )
-{
- if (flags & ( SP_OBJECT_MODIFIED_FLAG |
- SP_OBJECT_PARENT_MODIFIED_FLAG |
- SP_OBJECT_STYLE_MODIFIED_FLAG) )
- {
- sp_fill_style_widget_update (spw);
- }
-}
-
-static void
-sp_fill_style_widget_change_subselection( Inkscape::Application */*inkscape*/,
- SPDesktop */*desktop*/,
- SPWidget *spw )
-{
- sp_fill_style_widget_update (spw);
-}
-
-static void
-sp_fill_style_widget_change_selection( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- SPPaintSelector */*psel*/ )
-{
- sp_fill_style_widget_update (spw);
-}
-
-/**
-* \param sel Selection to use, or NULL.
-*/
-static void
-sp_fill_style_widget_update (SPWidget *spw)
-{
- if (g_object_get_data (G_OBJECT (spw), "update"))
- return;
-
- if (g_object_get_data (G_OBJECT (spw), "local")) {
- g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (FALSE)); // local change; do nothing, but reset the flag
- return;
- }
-
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
-
- SPPaintSelector *psel = SP_PAINT_SELECTOR (g_object_get_data (G_OBJECT (spw), "paint-selector"));
-
- // create temporary style
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- // query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection
- int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FILL);
-
- switch (result) {
- case QUERY_STYLE_NOTHING:
- {
- /* No paint at all */
- sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_EMPTY);
- break;
- }
-
- case QUERY_STYLE_SINGLE:
- case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector
- case QUERY_STYLE_MULTIPLE_SAME:
- {
- SPPaintSelectorMode pselmode = sp_style_determine_paint_selector_mode (query, true);
- sp_paint_selector_set_mode (psel, pselmode);
-
- sp_paint_selector_set_fillrule (psel, query->fill_rule.computed == ART_WIND_RULE_NONZERO?
- SP_PAINT_SELECTOR_FILLRULE_NONZERO : SP_PAINT_SELECTOR_FILLRULE_EVENODD);
-
- if (query->fill.set && query->fill.isColor()) {
- sp_paint_selector_set_color_alpha (psel, &query->fill.value.color, SP_SCALE24_TO_FLOAT (query->fill_opacity.value));
- } else if (query->fill.set && query->fill.isPaintserver()) {
-
- SPPaintServer *server = SP_STYLE_FILL_SERVER (query);
-
- if (SP_IS_LINEARGRADIENT (server)) {
- SPGradient *vector = sp_gradient_get_vector (SP_GRADIENT (server), FALSE);
- sp_paint_selector_set_gradient_linear (psel, vector);
-
- SPLinearGradient *lg = SP_LINEARGRADIENT (server);
- sp_paint_selector_set_gradient_properties (psel,
- SP_GRADIENT_UNITS (lg),
- SP_GRADIENT_SPREAD (lg));
- } else if (SP_IS_RADIALGRADIENT (server)) {
- SPGradient *vector = sp_gradient_get_vector (SP_GRADIENT (server), FALSE);
- sp_paint_selector_set_gradient_radial (psel, vector);
-
- SPRadialGradient *rg = SP_RADIALGRADIENT (server);
- sp_paint_selector_set_gradient_properties (psel,
- SP_GRADIENT_UNITS (rg),
- SP_GRADIENT_SPREAD (rg));
- } else if (SP_IS_PATTERN (server)) {
- SPPattern *pat = pattern_getroot (SP_PATTERN (server));
- sp_update_pattern_list (psel, pat);
- }
- }
- break;
- }
-
- case QUERY_STYLE_MULTIPLE_DIFFERENT:
- {
- sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_MULTIPLE);
- break;
- }
- }
-
- sp_style_unref(query);
-
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
-
-}
-
-
-static void
-sp_fill_style_widget_paint_mode_changed ( SPPaintSelector *psel,
- SPPaintSelectorMode /*mode*/,
- SPWidget *spw )
-{
- if (g_object_get_data (G_OBJECT (spw), "update"))
- return;
-
- /* TODO: Does this work? */
- /* TODO: Not really, here we have to get old color back from object */
- /* Instead of relying on paint widget having meaningful colors set */
- sp_fill_style_widget_paint_changed (psel, spw);
-}
-
-static void
-sp_fill_style_widget_fillrule_changed ( SPPaintSelector */*psel*/,
- SPPaintSelectorFillRule mode,
- SPWidget *spw )
-{
- if (g_object_get_data (G_OBJECT (spw), "update"))
- return;
-
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
-
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property (css, "fill-rule", mode == SP_PAINT_SELECTOR_FILLRULE_EVENODD? "evenodd":"nonzero");
-
- sp_desktop_set_style (desktop, css);
-
- sp_repr_css_attr_unref (css);
-
- sp_document_done (SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE,
- _("Change fill rule"));
-}
-
-static gchar const *undo_label_1 = "fill:flatcolor:1";
-static gchar const *undo_label_2 = "fill:flatcolor:2";
-static gchar const *undo_label = undo_label_1;
-
-/**
-This is called repeatedly while you are dragging a color slider, only for flat color
-modes. Previously it set the color in style but did not update the repr for efficiency, however
-this was flakey and didn't buy us almost anything. So now it does the same as _changed, except
-lumps all its changes for undo.
- */
-static void
-sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw)
-{
- if (!spw->inkscape) {
- return;
- }
-
- if (g_object_get_data (G_OBJECT (spw), "update")) {
- return;
- }
-
- if (g_object_get_data (G_OBJECT (spw), "local")) {
- // previous local flag not cleared yet;
- // this means dragged events come too fast, so we better skip this one to speed up display
- // (it's safe to do this in any case)
- return;
- }
-
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
-
- switch (psel->mode) {
-
- case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
- case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
- {
- sp_paint_selector_set_flat_color (psel, SP_ACTIVE_DESKTOP, "fill", "fill-opacity");
- sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set fill color"));
- g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (TRUE)); // local change, do not update from selection
- break;
- }
-
- default:
- g_warning ( "file %s: line %d: Paint %d should not emit 'dragged'",
- __FILE__, __LINE__, psel->mode );
- break;
-
- }
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
-}
-
-
-/**
-This is called (at least) when:
-1 paint selector mode is switched (e.g. flat color -> gradient)
-2 you finished dragging a gradient node and released mouse
-3 you changed a gradient selector parameter (e.g. spread)
-Must update repr.
- */
-static void
-sp_fill_style_widget_paint_changed ( SPPaintSelector *psel,
- SPWidget *spw )
-{
- if (g_object_get_data (G_OBJECT (spw), "update")) {
- return;
- }
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
-
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (!desktop) {
- return;
- }
- SPDocument *document = sp_desktop_document (desktop);
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
-
- GSList const *items = selection->itemList();
-
- switch (psel->mode) {
-
- case SP_PAINT_SELECTOR_MODE_EMPTY:
- // This should not happen.
- g_warning ( "file %s: line %d: Paint %d should not emit 'changed'",
- __FILE__, __LINE__, psel->mode);
- break;
- case SP_PAINT_SELECTOR_MODE_MULTIPLE:
- // This happens when you switch multiple objects with different gradients to flat color;
- // nothing to do here.
- break;
-
- case SP_PAINT_SELECTOR_MODE_NONE:
- {
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property (css, "fill", "none");
-
- sp_desktop_set_style (desktop, css);
-
- sp_repr_css_attr_unref (css);
-
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Remove fill"));
- break;
- }
-
- case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
- case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
- {
- // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events
- sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0);
-
- sp_paint_selector_set_flat_color (psel, desktop, "fill", "fill-opacity");
- sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set fill color"));
- // resume interruptibility
- sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop));
-
- // on release, toggle undo_label so that the next drag will not be lumped with this one
- if (undo_label == undo_label_1)
- undo_label = undo_label_2;
- else
- undo_label = undo_label_1;
-
- break;
- }
-
- case SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR:
- case SP_PAINT_SELECTOR_MODE_GRADIENT_RADIAL:
- if (items) {
- SPGradientType const gradient_type = ( psel->mode == SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR
- ? SP_GRADIENT_TYPE_LINEAR
- : SP_GRADIENT_TYPE_RADIAL );
-
- // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property(css, "fill-opacity", "1.0");
-
- SPGradient *vector = sp_paint_selector_get_gradient_vector(psel);
- if (!vector) {
- /* No vector in paint selector should mean that we just changed mode */
-
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- int result = objects_query_fillstroke ((GSList *) items, query, true);
- guint32 common_rgb = 0;
- if (result == QUERY_STYLE_MULTIPLE_SAME) {
- if (!query->fill.isColor()) {
- common_rgb = sp_desktop_get_color(desktop, true);
- } else {
- common_rgb = query->fill.value.color.toRGBA32( 0xff );
- }
- vector = sp_document_default_gradient_vector(document, common_rgb);
- }
- sp_style_unref(query);
-
- for (GSList const *i = items; i != NULL; i = i->next) {
- //FIXME: see above
- sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style");
-
- if (!vector) {
- sp_item_set_gradient(SP_ITEM(i->data),
- sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), true),
- gradient_type, true);
- } else {
- sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true);
- }
- }
- } else {
- /* We have changed from another gradient type, or modified spread/units within
- * this gradient type. */
- vector = sp_gradient_ensure_vector_normalized (vector);
- for (GSList const *i = items; i != NULL; i = i->next) {
- //FIXME: see above
- sp_repr_css_change_recursive (SP_OBJECT_REPR (i->data), css, "style");
-
- SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true);
- sp_gradient_selector_attrs_to_gradient (gr, psel);
- }
- }
-
- sp_repr_css_attr_unref (css);
-
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set gradient on fill"));
- }
- break;
-
- case SP_PAINT_SELECTOR_MODE_PATTERN:
-
- if (items) {
-
- SPPattern *pattern = sp_paint_selector_get_pattern (psel);
- if (!pattern) {
-
- /* No Pattern in paint selector should mean that we just
- * changed mode - dont do jack.
- */
-
- } else {
- Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern);
- SPCSSAttr *css = sp_repr_css_attr_new ();
- gchar *urltext = g_strdup_printf ("url(#%s)", patrepr->attribute("id"));
- sp_repr_css_set_property (css, "fill", urltext);
-
- // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
- sp_repr_css_set_property(css, "fill-opacity", "1.0");
-
- // cannot just call sp_desktop_set_style, because we don't want to touch those
- // objects who already have the same root pattern but through a different href
- // chain. FIXME: move this to a sp_item_set_pattern
- for (GSList const *i = items; i != NULL; i = i->next) {
- SPObject *selobj = SP_OBJECT (i->data);
-
- SPStyle *style = SP_OBJECT_STYLE (selobj);
- if (style && style->fill.isPaintserver()) {
- SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (selobj);
- if (SP_IS_PATTERN (server) && pattern_getroot (SP_PATTERN(server)) == pattern)
- // only if this object's pattern is not rooted in our selected pattern, apply
- continue;
- }
-
- sp_desktop_apply_css_recursive (selobj, css, true);
- }
-
- sp_repr_css_attr_unref (css);
- g_free (urltext);
-
- } // end if
-
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set pattern on fill"));
-
- } // end if
-
- break;
-
- case SP_PAINT_SELECTOR_MODE_UNSET:
- if (items) {
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_unset_property (css, "fill");
-
- sp_desktop_set_style (desktop, css);
- sp_repr_css_attr_unref (css);
-
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Unset fill"));
- }
- break;
-
- default:
- g_warning ( "file %s: line %d: Paint selector should not be in "
- "mode %d",
- __FILE__, __LINE__, psel->mode );
- break;
- }
-
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
-}
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/fill-style.h b/src/dialogs/fill-style.h
--- a/src/dialogs/fill-style.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/** @file
- * @brief Fill style configuration
- */
-/* Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2002 Lauris Kaplinski
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_DIALOGS_SP_FILL_STYLE_H
-#define SEEN_DIALOGS_SP_FILL_STYLE_H
-
-#include <glib.h>
-#include <gtk/gtkwidget.h>
-#include "forward.h"
-
-
-GtkWidget *sp_fill_style_widget_new (void);
-
-#endif
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/guidelinedialog.cpp b/src/dialogs/guidelinedialog.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/** @file
- * @brief Simple guideline dialog
- */
-/* Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Andrius R. <knutux@gmail.com>
- * Johan Engelen
- *
- * Copyright (C) 1999-2007 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include "display/guideline.h"
-#include "helper/unit-menu.h"
-#include "helper/units.h"
-#include "desktop.h"
-#include "document.h"
-#include "sp-guide.h"
-#include "sp-namedview.h"
-#include "desktop-handles.h"
-#include "event-context.h"
-#include "widgets/desktop-widget.h"
-#include "sp-metrics.h"
-#include <glibmm/i18n.h>
-#include "dialogs/dialog-events.h"
-#include "message-context.h"
-#include "xml/repr.h"
-#include <2geom/point.h>
-#include <2geom/angle.h>
-#include "guidelinedialog.h"
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-GuidelinePropertiesDialog::GuidelinePropertiesDialog(SPGuide *guide, SPDesktop *desktop)
-: _desktop(desktop), _guide(guide),
- _label_units(_("Unit:")),
- _label_X(_("X:")),
- _label_Y(_("Y:")),
- _label_degrees(_("Angle (degrees):")),
- _relative_toggle(_("Rela_tive change"), _("Move and/or rotate the guide relative to current settings")),
- _adjustment_x(0.0, -1e6, 1e6, 1.0, 10.0, 10.0),
- _adjustment_y(0.0, -1e6, 1e6, 1.0, 10.0, 10.0),
- _adj_angle(0.0, -360, 360, 1.0, 10.0, 10.0),
- _unit_selector(NULL), _mode(true), _oldpos(0.,0.), _oldangle(0.0)
-{
-}
-
-GuidelinePropertiesDialog::~GuidelinePropertiesDialog() {
-}
-
-void GuidelinePropertiesDialog::showDialog(SPGuide *guide, SPDesktop *desktop) {
- GuidelinePropertiesDialog dialog(guide, desktop);
- dialog._setup();
- dialog.run();
-}
-
-void GuidelinePropertiesDialog::_modeChanged()
-{
- _mode = !_relative_toggle.get_active();
- if (!_mode) {
- // relative
- _spin_angle.set_value(0);
-
- _spin_button_y.set_value(0);
- _spin_button_x.set_value(0);
- } else {
- // absolute
- _spin_angle.set_value(_oldangle);
-
- SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(_unit_selector->gobj()));
- gdouble const val_y = sp_pixels_get_units(_oldpos[Geom::Y], unit);
- _spin_button_y.set_value(val_y);
- gdouble const val_x = sp_pixels_get_units(_oldpos[Geom::X], unit);
- _spin_button_x.set_value(val_x);
- }
-}
-
-void GuidelinePropertiesDialog::_onApply()
-{
- double deg_angle = _spin_angle.get_value();
- if (!_mode)
- deg_angle += _oldangle;
- Geom::Point normal;
- if ( deg_angle == 90. || deg_angle == 270. || deg_angle == -90. || deg_angle == -270.) {
- normal = Geom::Point(1.,0.);
- } else if ( deg_angle == 0. || deg_angle == 180. || deg_angle == -180.) {
- normal = Geom::Point(0.,1.);
- } else {
- double rad_angle = Geom::deg_to_rad( deg_angle );
- normal = Geom::rot90(Geom::Point::polar(rad_angle, 1.0));
- }
- sp_guide_set_normal(*_guide, normal, true);
-
- SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(_unit_selector->gobj()));
- gdouble const raw_dist_x = _spin_button_x.get_value();
- gdouble const points_x = sp_units_get_pixels(raw_dist_x, unit);
- gdouble const raw_dist_y = _spin_button_y.get_value();
- gdouble const points_y = sp_units_get_pixels(raw_dist_y, unit);
- Geom::Point newpos(points_x, points_y);
- if (!_mode)
- newpos += _oldpos;
-
- sp_guide_moveto(*_guide, newpos, true);
-
- sp_document_done(SP_OBJECT_DOCUMENT(_guide), SP_VERB_NONE,
- _("Set guide properties"));
-}
-
-void GuidelinePropertiesDialog::_onOK()
-{
- _onApply();
-}
-
-void GuidelinePropertiesDialog::_onDelete()
-{
- SPDocument *doc = SP_OBJECT_DOCUMENT(_guide);
- sp_guide_remove(_guide);
- sp_document_done(doc, SP_VERB_NONE,
- _("Delete guide"));
-}
-
-void GuidelinePropertiesDialog::_response(gint response)
-{
- switch (response) {
- case Gtk::RESPONSE_OK:
- _onOK();
- break;
- case -12:
- _onDelete();
- break;
- case Gtk::RESPONSE_CANCEL:
- break;
- case Gtk::RESPONSE_DELETE_EVENT:
- break;
-/* case GTK_RESPONSE_APPLY:
- _onApply();
- break;
-*/
- default:
- g_assert_not_reached();
- }
-}
-
-void GuidelinePropertiesDialog::_setup() {
- set_title(_("Guideline"));
- add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
- add_button(Gtk::Stock::DELETE, -12);
- add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
-
- Gtk::VBox *mainVBox = get_vbox();
-
- _layout_table.set_spacings(4);
- _layout_table.resize (3, 4);
-
- mainVBox->pack_start(_layout_table, false, false, 0);
-
- _label_name.set_label("foo0");
- _layout_table.attach(_label_name,
- 0, 3, 0, 1, Gtk::FILL, Gtk::FILL);
- _label_name.set_alignment(0, 0.5);
-
- _label_descr.set_label("foo1");
- _layout_table.attach(_label_descr,
- 0, 3, 1, 2, Gtk::FILL, Gtk::FILL);
- _label_descr.set_alignment(0, 0.5);
-
- // indent
- _layout_table.attach(*manage(new Gtk::Label(" ")),
- 0, 1, 2, 3, Gtk::FILL, Gtk::FILL, 10);
-
- // mode radio button
- _layout_table.attach(_relative_toggle,
- 1, 3, 9, 10, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
- _relative_toggle.signal_toggled().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_modeChanged));
-
- // unitmenu
- /* fixme: We should allow percents here too, as percents of the canvas size */
- GtkWidget *unit_selector = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
- sp_unit_selector_set_unit(SP_UNIT_SELECTOR(unit_selector), _desktop->namedview->doc_units);
- _unit_selector = Gtk::manage(Glib::wrap(unit_selector));
-
- // position spinbuttons
- sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(unit_selector), GTK_ADJUSTMENT(_adjustment_x.gobj()));
- sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(unit_selector), GTK_ADJUSTMENT(_adjustment_y.gobj()));
- _spin_button_x.configure(_adjustment_x, 1.0 , 3);
- _spin_button_x.set_numeric();
- _spin_button_y.configure(_adjustment_y, 1.0 , 3);
- _spin_button_y.set_numeric();
- _layout_table.attach(_label_X,
- 1, 2, 4, 5, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
- _layout_table.attach(_spin_button_x,
- 2, 3, 4, 5, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
- _layout_table.attach(_label_Y,
- 1, 2, 5, 6, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
- _layout_table.attach(_spin_button_y,
- 2, 3, 5, 6, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
- gtk_signal_connect_object(GTK_OBJECT(_spin_button_x.gobj()), "activate",
- GTK_SIGNAL_FUNC(gtk_window_activate_default),
- gobj());
-
- _layout_table.attach(_label_units,
- 1, 2, 6, 7, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
- _layout_table.attach(*_unit_selector,
- 2, 3, 6, 7, Gtk::FILL, Gtk::FILL);
-
- // angle spinbutton
- _spin_angle.configure(_adj_angle, 5.0 , 3);
- _spin_angle.set_numeric();
- _spin_angle.show();
- _layout_table.attach(_label_degrees,
- 1, 2, 8, 9, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
- _layout_table.attach(_spin_angle,
- 2, 3, 8, 9, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
-
-
- // dialog
- set_default_response(Gtk::RESPONSE_OK);
- signal_response().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_response));
-
- // initialize dialog
- _oldpos = _guide->point_on_line;
- if (_guide->is_vertical()) {
- _oldangle = 90;
- } else if (_guide->is_horizontal()) {
- _oldangle = 0;
- } else {
- _oldangle = Geom::rad_to_deg( std::atan2( - _guide->normal_to_line[Geom::X], _guide->normal_to_line[Geom::Y] ) );
- }
-
- {
- Inkscape::XML::Node *repr = SP_OBJECT_REPR (_guide);
- const gchar *guide_id = repr->attribute("id");
- gchar *label = g_strdup_printf(_("Guideline ID: %s"), guide_id);
- _label_name.set_label(label);
- g_free(label);
- }
- {
- gchar *guide_description = sp_guide_description(_guide);
- gchar *label = g_strdup_printf(_("Current: %s"), guide_description);
- g_free(guide_description);
- _label_descr.set_markup(label);
- g_free(label);
- }
-
- _modeChanged(); // sets values of spinboxes.
-
- if ( _oldangle == 90. || _oldangle == 270. || _oldangle == -90. || _oldangle == -270.) {
- _spin_button_x.grab_focus();
- _spin_button_x.select_region(0, 20);
- } else if ( _oldangle == 0. || _oldangle == 180. || _oldangle == -180.) {
- _spin_button_y.grab_focus();
- _spin_button_y.select_region(0, 20);
- } else {
- _spin_angle.grab_focus();
- _spin_angle.select_region(0, 20);
- }
-
- set_position(Gtk::WIN_POS_MOUSE);
-
- show_all_children();
- set_modal(true);
- _desktop->setWindowTransient (gobj());
- property_destroy_with_parent() = true;
-}
-
-}
-}
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/guidelinedialog.h b/src/dialogs/guidelinedialog.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- *
- * \brief Dialog for modifying guidelines
- *
- * Author:
- * Andrius R. <knutux@gmail.com>
- * Johan Engelen
- *
- * Copyright (C) 2006-2007 Authors
- *
- * Released under GNU GPL. Read the file 'COPYING' for more information
- */
-
-#ifndef INKSCAPE_DIALOG_GUIDELINE_H
-#define INKSCAPE_DIALOG_GUIDELINE_H
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/table.h>
-#include <gtkmm/spinbutton.h>
-#include <gtkmm/label.h>
-#include <gtkmm/stock.h>
-#include <gtkmm/adjustment.h>
-#include "ui/widget/button.h"
-#include <2geom/point.h>
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-class GuidelinePropertiesDialog : public Gtk::Dialog {
-public:
- GuidelinePropertiesDialog(SPGuide *guide, SPDesktop *desktop);
- virtual ~GuidelinePropertiesDialog();
-
- Glib::ustring getName() const { return "GuidelinePropertiesDialog"; }
-
- static void showDialog(SPGuide *guide, SPDesktop *desktop);
-
-protected:
- void _setup();
-
- void _onApply();
- void _onOK();
- void _onDelete();
-
- void _response(gint response);
- void _modeChanged();
-
-private:
- GuidelinePropertiesDialog(GuidelinePropertiesDialog const &); // no copy
- GuidelinePropertiesDialog &operator=(GuidelinePropertiesDialog const &); // no assign
-
- SPDesktop *_desktop;
- SPGuide *_guide;
- Gtk::Table _layout_table;
- Gtk::Label _label_name;
- Gtk::Label _label_descr;
- Gtk::Label _label_units;
- Gtk::Label _label_X;
- Gtk::Label _label_Y;
- Gtk::Label _label_degrees;
- Inkscape::UI::Widget::CheckButton _relative_toggle;
- Gtk::Adjustment _adjustment_x;
- Gtk::SpinButton _spin_button_x;
- Gtk::Adjustment _adjustment_y;
- Gtk::SpinButton _spin_button_y;
-
- Gtk::Adjustment _adj_angle;
- Gtk::SpinButton _spin_angle;
-
- Gtk::Widget *_unit_selector;
- bool _mode;
- Geom::Point _oldpos;
- gdouble _oldangle;
-};
-
-} // namespace
-} // namespace
-} // namespace
-
-
-#endif // INKSCAPE_DIALOG_GUIDELINE_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/iconpreview.cpp b/src/dialogs/iconpreview.cpp
+++ /dev/null
@@ -1,309 +0,0 @@
-/** @file
- * @brief A simple dialog for previewing icon representation.
- */
-/* Authors:
- * Jon A. Cruz
- * Bob Jamison
- * Other dudes from The Inkscape Organization
- *
- * Copyright (C) 2004 Bob Jamison
- * Copyright (C) 2005 Jon A. Cruz
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "iconpreview.h"
-
-#include <gtk/gtk.h>
-
-#include <glib/gmem.h>
-#include <gtk/gtkdialog.h> //for GTK_RESPONSE* types
-#include <glibmm/i18n.h>
-#include <gtkmm/buttonbox.h>
-#include <gtkmm/stock.h>
-
-#include "preferences.h"
-#include "inkscape.h"
-#include "document.h"
-#include "desktop-handles.h"
-#include "selection.h"
-#include "desktop.h"
-#include "display/nr-arena.h"
-#include "sp-root.h"
-#include "xml/repr.h"
-
-extern "C" {
-// takes doc, root, icon, and icon name to produce pixels
-guchar *
-sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
- const gchar *name, unsigned int psize );
-}
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-
-IconPreviewPanel&
-IconPreviewPanel::getInstance()
-{
- static IconPreviewPanel &instance = *new IconPreviewPanel();
-
- instance.refreshPreview();
-
- return instance;
-}
-
-//#########################################################################
-//## E V E N T S
-//#########################################################################
-
-void IconPreviewPanel::on_button_clicked(int which)
-{
- if ( hot != which ) {
- buttons[hot]->set_active( false );
-
- hot = which;
- updateMagnify();
- _getContents()->queue_draw();
- }
-}
-
-
-
-
-//#########################################################################
-//## C O N S T R U C T O R / D E S T R U C T O R
-//#########################################################################
-/**
- * Constructor
- */
-IconPreviewPanel::IconPreviewPanel() :
- UI::Widget::Panel("", "/dialogs/iconpreview", SP_VERB_VIEW_ICON_PREVIEW),
- hot(1),
- refreshButton(0),
- selectionButton(0)
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- numEntries = 0;
-
- std::vector<Glib::ustring> pref_sizes = prefs->getAllDirs("/iconpreview/sizes/default");
- std::vector<int> rawSizes;
-
- for (std::vector<Glib::ustring>::iterator i = pref_sizes.begin(); i != pref_sizes.end(); ++i) {
- if (prefs->getBool(*i + "/show", true)) {
- int sizeVal = prefs->getInt(*i + "/value", -1);
- if (sizeVal > 0) {
- rawSizes.push_back(sizeVal);
- }
- }
- }
-
- if ( !rawSizes.empty() ) {
- numEntries = rawSizes.size();
- sizes = new int[numEntries];
- int i = 0;
- for ( std::vector<int>::iterator it = rawSizes.begin(); it != rawSizes.end(); ++it, ++i ) {
- sizes[i] = *it;
- }
- }
-
- if ( numEntries < 1 )
- {
- numEntries = 5;
- sizes = new int[numEntries];
- sizes[0] = 16;
- sizes[1] = 24;
- sizes[2] = 32;
- sizes[3] = 48;
- sizes[4] = 128;
- }
-
- pixMem = new guchar*[numEntries];
- images = new Gtk::Image*[numEntries];
- labels = new Glib::ustring*[numEntries];
- buttons = new Gtk::ToggleToolButton*[numEntries];
-
-
- for ( int i = 0; i < numEntries; i++ ) {
- char *label = g_strdup_printf(_("%d x %d"), sizes[i], sizes[i]);
- labels[i] = new Glib::ustring(label);
- g_free(label);
- pixMem[i] = 0;
- images[i] = 0;
- }
-
-
- magLabel.set_label( *labels[hot] );
-
- Gtk::VBox* magBox = new Gtk::VBox();
-
- magBox->pack_start( magnified );
- magBox->pack_start( magLabel, Gtk::PACK_SHRINK );
-
-
- Gtk::VBox * verts = new Gtk::VBox();
- for ( int i = 0; i < numEntries; i++ ) {
- pixMem[i] = new guchar[4 * sizes[i] * sizes[i]];
- memset( pixMem[i], 0x00, 4 * sizes[i] * sizes[i] );
-
- GdkPixbuf *pb = gdk_pixbuf_new_from_data( pixMem[i], GDK_COLORSPACE_RGB, TRUE, 8, sizes[i], sizes[i], sizes[i] * 4, /*(GdkPixbufDestroyNotify)g_free*/NULL, NULL );
- GtkImage* img = GTK_IMAGE( gtk_image_new_from_pixbuf( pb ) );
- images[i] = Glib::wrap(img);
- Glib::ustring label(*labels[i]);
- buttons[i] = new Gtk::ToggleToolButton(label);
- buttons[i]->set_active( i == hot );
- buttons[i]->set_icon_widget(*images[i]);
-
- tips.set_tip((*buttons[i]), label);
-
- buttons[i]->signal_clicked().connect( sigc::bind<int>( sigc::mem_fun(*this, &IconPreviewPanel::on_button_clicked), i) );
-
-
- verts->add(*buttons[i]);
- }
-
- iconBox.pack_start(splitter);
- splitter.pack1( *magBox, true, true );
- splitter.pack2( *verts, false, false );
-
-
- //## The Refresh button
-
-
- Gtk::HButtonBox* holder = new Gtk::HButtonBox( Gtk::BUTTONBOX_END );
- _getContents()->pack_end(*holder, false, false);
-
- selectionButton = new Gtk::ToggleButton(_("Selection")); // , GTK_RESPONSE_APPLY
- holder->pack_start( *selectionButton, false, false );
- tips.set_tip((*selectionButton), _("Selection only or whole document"));
- selectionButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::modeToggled) );
-
- gint val = prefs->getBool("/iconpreview/selectionOnly");
- selectionButton->set_active( val != 0 );
-
- refreshButton = new Gtk::Button(Gtk::Stock::REFRESH); // , GTK_RESPONSE_APPLY
- holder->pack_end( *refreshButton, false, false );
- tips.set_tip((*refreshButton), _("Refresh the icons"));
- refreshButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::refreshPreview) );
-
-
- _getContents()->pack_start(iconBox, Gtk::PACK_EXPAND_WIDGET);
-
- show_all_children();
-}
-
-//#########################################################################
-//## M E T H O D S
-//#########################################################################
-
-
-void IconPreviewPanel::refreshPreview()
-{
- SPDesktop *desktop = getDesktop();
- if ( desktop ) {
-
- if ( selectionButton && selectionButton->get_active() )
- {
- Inkscape::Selection * sel = sp_desktop_selection(desktop);
- if ( sel ) {
- //g_message("found a selection to play with");
-
- GSList const *items = sel->itemList();
- SPObject *target = 0;
- while ( items && !target ) {
- SPItem* item = SP_ITEM( items->data );
- SPObject * obj = SP_OBJECT(item);
- gchar const *id = SP_OBJECT_ID( obj );
- if ( id ) {
- target = obj;
- }
-
- items = g_slist_next(items);
- }
- if ( target ) {
- renderPreview(target);
- }
- }
- }
- else
- {
- SPObject *target = desktop->currentRoot();
- if ( target ) {
- renderPreview(target);
- }
- }
- }
-}
-
-void IconPreviewPanel::modeToggled()
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setBool("/iconpreview/selectionOnly", (selectionButton && selectionButton->get_active()));
-
- refreshPreview();
-}
-
-void IconPreviewPanel::renderPreview( SPObject* obj )
-{
- SPDocument * doc = SP_OBJECT_DOCUMENT(obj);
- gchar * id = SP_OBJECT_ID(obj);
-
-// g_message(" setting up to render '%s' as the icon", id );
-
- NRArenaItem *root = NULL;
-
- /* Create new arena */
- NRArena *arena = NRArena::create();
-
- /* Create ArenaItem and set transform */
- unsigned int visionkey = sp_item_display_key_new(1);
-
- root = sp_item_invoke_show ( SP_ITEM( SP_DOCUMENT_ROOT(doc) ),
- arena, visionkey, SP_ITEM_SHOW_DISPLAY );
-
- for ( int i = 0; i < numEntries; i++ ) {
- guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i] );
-// g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") );
- if ( px ) {
- memcpy( pixMem[i], px, sizes[i] * sizes[i] * 4 );
- g_free( px );
- px = 0;
- } else {
- memset( pixMem[i], 0, sizes[i] * sizes[i] * 4 );
- }
- images[i]->queue_draw();
- }
- updateMagnify();
-
- sp_item_invoke_hide(SP_ITEM(sp_document_root(doc)), visionkey);
- nr_object_unref((NRObject *) arena);
-}
-
-void IconPreviewPanel::updateMagnify()
-{
- Glib::RefPtr<Gdk::Pixbuf> buf = images[hot]->get_pixbuf()->scale_simple( 128, 128, Gdk::INTERP_NEAREST );
- magLabel.set_label( *labels[hot] );
- magnified.set( buf );
- magnified.queue_draw();
- magnified.get_parent()->queue_draw();
-}
-
-
-} //namespace Dialogs
-} //namespace UI
-} //namespace Inkscape
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/iconpreview.h b/src/dialogs/iconpreview.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/** @file
- * @brief A simple dialog for previewing icon representation.
- */
-/* Authors:
- * Jon A. Cruz
- * Bob Jamison
- * Other dudes from The Inkscape Organization
- *
- * Copyright (C) 2004,2005 The Inkscape Organization
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_ICON_PREVIEW_H
-#define SEEN_ICON_PREVIEW_H
-
-#include <gtkmm/box.h>
-#include <gtkmm/button.h>
-#include <gtkmm/label.h>
-#include <gtkmm/paned.h>
-#include <gtkmm/image.h>
-#include <gtkmm/togglebutton.h>
-#include <gtkmm/toggletoolbutton.h>
-
-#include "ui/widget/panel.h"
-
-struct SPObject;
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-
-/**
- * A panel that displays an icon preview
- */
-class IconPreviewPanel : public UI::Widget::Panel
-{
-public:
- IconPreviewPanel();
- //IconPreviewPanel(Glib::ustring const &label);
-
- static IconPreviewPanel& getInstance();
-
- void refreshPreview();
- void modeToggled();
-
-private:
- IconPreviewPanel(IconPreviewPanel const &); // no copy
- IconPreviewPanel &operator=(IconPreviewPanel const &); // no assign
-
-
- void on_button_clicked(int which);
- void renderPreview( SPObject* obj );
- void updateMagnify();
-
- Gtk::Tooltips tips;
-
- Gtk::VBox iconBox;
- Gtk::HPaned splitter;
-
- int hot;
- int numEntries;
- int* sizes;
-
- Gtk::Image magnified;
- Gtk::Label magLabel;
-
- Gtk::Button *refreshButton;
- Gtk::ToggleButton *selectionButton;
-
- guchar** pixMem;
- Gtk::Image** images;
- Glib::ustring** labels;
- Gtk::ToggleToolButton** buttons;
-};
-
-} //namespace Dialogs
-} //namespace UI
-} //namespace Inkscape
-
-
-
-#endif // SEEN_ICON_PREVIEW_H
diff --git a/src/dialogs/in-dt-coordsys.cpp b/src/dialogs/in-dt-coordsys.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#include "sp-root.h"
-
-/** Returns true iff \a item is suitable to be included in the selection, in particular
- whether it has a bounding box in the desktop coordinate system for rendering resize handles.
-
- Descendents of <defs> nodes (markers etc.) return false, for example.
-*/
-bool in_dt_coordsys(SPObject const &item)
-{
- /* Definition based on sp_item_i2doc_affine. */
- SPObject const *child = &item;
- g_return_val_if_fail(child != NULL, false);
- for(;;) {
- if (!SP_IS_ITEM(child)) {
- return false;
- }
- SPObject const * const parent = SP_OBJECT_PARENT(child);
- if (parent == NULL) {
- break;
- }
- child = parent;
- }
- g_assert(SP_IS_ROOT(child));
- /* Relevance: Otherwise, I'm not sure whether to return true or false. */
- return true;
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/in-dt-coordsys.h b/src/dialogs/in-dt-coordsys.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef SEEN_IN_DT_COORDSYS
-#define SEEN_IN_DT_COORDSYS
-#include "forward.h"
-
-bool in_dt_coordsys(SPObject const &item);
-
-#endif /* !SEEN_IN_DT_COORDSYS */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 076358082cd1a5ca1589c9c70ad22f134c89b9f5..44a479b6cafb67d223d1101d26b31b0bb9bcca40 100644 (file)
#include <gtk/gtktextview.h>
#include <gtk/gtktooltips.h>
+#include "../desktop-handles.h"
+#include "dialog-events.h"
+#include "../document.h"
#include <glibmm/i18n.h>
-#include "helper/window.h"
-#include "../widgets/sp-widget.h"
+#include "../helper/window.h"
#include "../inkscape.h"
-#include "../document.h"
-#include "../desktop-handles.h"
+#include "../interface.h"
+#include "../macros.h"
+#include "../preferences.h"
#include "../selection.h"
#include "../sp-item.h"
-#include "../macros.h"
#include "../verbs.h"
-#include "../interface.h"
-#include "sp-attribute-widget.h"
-
-#include "dialog-events.h"
-#include "../preferences.h"
+#include "../widgets/sp-attribute-widget.h"
+#include "../widgets/sp-widget.h"
#define MIN_ONSCREEN_DISTANCE 50
diff --git a/src/dialogs/layer-properties.cpp b/src/dialogs/layer-properties.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/** @file
- * @brief Dialog for renaming layers
- */
-/* Author:
- * Bryce W. Harrington <bryce@bryceharrington.com>
- * Andrius R. <knutux@gmail.com>
- *
- * Copyright (C) 2004 Bryce Harrington
- * Copyright (C) 2006 Andrius R.
- *
- * Released under GNU GPL. Read the file 'COPYING' for more information
- */
-
-#include <gtkmm/stock.h>
-#include <glibmm/i18n.h>
-#include "inkscape.h"
-#include "desktop.h"
-#include "document.h"
-#include "layer-manager.h"
-#include "message-stack.h"
-#include "desktop-handles.h"
-#include "sp-object.h"
-#include "sp-item.h"
-
-#include "layer-properties.h"
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-LayerPropertiesDialog::LayerPropertiesDialog()
-: _strategy(NULL), _desktop(NULL), _layer(NULL), _position_visible(false)
-{
- Gtk::VBox *mainVBox = get_vbox();
-
- _layout_table.set_spacings(4);
- _layout_table.resize (1, 2);
-
- // Layer name widgets
- _layer_name_entry.set_activates_default(true);
- _layer_name_label.set_label(_("Layer name:"));
- _layer_name_label.set_alignment(1.0, 0.5);
-
- _layout_table.attach(_layer_name_label,
- 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);
-
- // Buttons
- _close_button.set_use_stock(true);
- _close_button.set_label(Gtk::Stock::CANCEL.id);
- _close_button.set_flags(Gtk::CAN_DEFAULT);
-
- _apply_button.set_use_underline(true);
- _apply_button.set_flags(Gtk::CAN_DEFAULT);
-
- _close_button.signal_clicked()
- .connect(sigc::mem_fun(*this, &LayerPropertiesDialog::_close));
- _apply_button.signal_clicked()
- .connect(sigc::mem_fun(*this, &LayerPropertiesDialog::_apply));
-
- signal_delete_event().connect(
- sigc::bind_return(
- sigc::hide(sigc::mem_fun(*this, &LayerPropertiesDialog::_close)),
- true
- )
- );
-
- add_action_widget(_close_button, Gtk::RESPONSE_CLOSE);
- add_action_widget(_apply_button, Gtk::RESPONSE_APPLY);
-
- _apply_button.grab_default();
-
- show_all_children();
-}
-
-LayerPropertiesDialog::~LayerPropertiesDialog() {
- _setDesktop(NULL);
- _setLayer(NULL);
-}
-
-void LayerPropertiesDialog::_showDialog(LayerPropertiesDialog::Strategy &strategy,
- SPDesktop *desktop, SPObject *layer)
-{
- LayerPropertiesDialog *dialog = new LayerPropertiesDialog();
-
- dialog->_strategy = &strategy;
- dialog->_setDesktop(desktop);
- dialog->_setLayer(layer);
-
- dialog->_strategy->setup(*dialog);
-
- dialog->set_modal(true);
- desktop->setWindowTransient (dialog->gobj());
- dialog->property_destroy_with_parent() = true;
-
- dialog->show();
- dialog->present();
-}
-
-void
-LayerPropertiesDialog::_apply()
-{
- g_assert(_strategy != NULL);
-
- _strategy->perform(*this);
- sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_NONE,
- _("Add layer"));
-
- _close();
-}
-
-void
-LayerPropertiesDialog::_close()
-{
- _setLayer(NULL);
- _setDesktop(NULL);
- destroy_();
- Glib::signal_idle().connect(
- sigc::bind_return(
- sigc::bind(sigc::ptr_fun(&::operator delete), this),
- false
- )
- );
-}
-
-void
-LayerPropertiesDialog::_setup_position_controls() {
- if ( NULL == _layer || _desktop->currentRoot() == _layer ) {
- // no layers yet, so option above/below/sublayer is useless
- return;
- }
-
- _position_visible = true;
- _dropdown_list = Gtk::ListStore::create(_dropdown_columns);
- _layer_position_combo.set_model(_dropdown_list);
- _layer_position_combo.pack_start(_label_renderer);
- _layer_position_combo.set_cell_data_func(_label_renderer,
- sigc::mem_fun(*this, &LayerPropertiesDialog::_prepareLabelRenderer));
-
- _layout_table.resize (2, 2);
-
- Gtk::ListStore::iterator row;
- row = _dropdown_list->append();
- row->set_value(_dropdown_columns.position, LPOS_ABOVE);
- row->set_value(_dropdown_columns.name, Glib::ustring(_("Above current")));
- _layer_position_combo.set_active(row);
- row = _dropdown_list->append();
- row->set_value(_dropdown_columns.position, LPOS_BELOW);
- row->set_value(_dropdown_columns.name, Glib::ustring(_("Below current")));
- row = _dropdown_list->append();
- row->set_value(_dropdown_columns.position, LPOS_CHILD);
- row->set_value(_dropdown_columns.name, Glib::ustring(_("As sublayer of current")));
-
- _layout_table.attach(_layer_position_combo,
- 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
- _layer_position_label.set_label(_("Position:"));
- _layer_position_label.set_alignment(1.0, 0.5);
- _layout_table.attach(_layer_position_label,
- 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
- show_all_children();
-}
-
-/** Formats the label for a given layer row
- */
-void LayerPropertiesDialog::_prepareLabelRenderer(
- Gtk::TreeModel::const_iterator const &row
-) {
- Glib::ustring name=(*row)[_dropdown_columns.name];
- _label_renderer.property_markup() = name.c_str();
-}
-
-void LayerPropertiesDialog::Rename::setup(LayerPropertiesDialog &dialog) {
- SPDesktop *desktop=dialog._desktop;
- dialog.set_title(_("Rename Layer"));
- gchar const *name = desktop->currentLayer()->label();
- dialog._layer_name_entry.set_text(( name ? name : "" ));
- dialog._apply_button.set_label(_("_Rename"));
-}
-
-void LayerPropertiesDialog::Rename::perform(LayerPropertiesDialog &dialog) {
- SPDesktop *desktop=dialog._desktop;
- Glib::ustring name(dialog._layer_name_entry.get_text());
- desktop->layer_manager->renameLayer( desktop->currentLayer(),
- ( name.empty() ? NULL : (gchar *)name.c_str() )
- );
- sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE,
- _("Rename layer"));
- // TRANSLATORS: This means "The layer has been renamed"
- desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Renamed layer"));
-}
-
-void LayerPropertiesDialog::Create::setup(LayerPropertiesDialog &dialog) {
- dialog.set_title(_("Add Layer"));
- dialog._layer_name_entry.set_text("");
- dialog._apply_button.set_label(_("_Add"));
- dialog._setup_position_controls();
-}
-
-void LayerPropertiesDialog::Create::perform(LayerPropertiesDialog &dialog) {
- SPDesktop *desktop=dialog._desktop;
-
- LayerRelativePosition position = LPOS_ABOVE;
-
- if (dialog._position_visible) {
- Gtk::ListStore::iterator activeRow(dialog._layer_position_combo.get_active());
- position = activeRow->get_value(dialog._dropdown_columns.position);
- }
-
- SPObject *new_layer=Inkscape::create_layer(desktop->currentRoot(), dialog._layer, position);
-
- Glib::ustring name(dialog._layer_name_entry.get_text());
- if (!name.empty()) {
- desktop->layer_manager->renameLayer( new_layer, (gchar *)name.c_str() );
- }
- sp_desktop_selection(desktop)->clear();
- desktop->setCurrentLayer(new_layer);
- desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("New layer created."));
-}
-
-void LayerPropertiesDialog::_setDesktop(SPDesktop *desktop) {
- if (desktop) {
- Inkscape::GC::anchor (desktop);
- }
- if (_desktop) {
- Inkscape::GC::release (_desktop);
- }
- _desktop = desktop;
-}
-
-void LayerPropertiesDialog::_setLayer(SPObject *layer) {
- if (layer) {
- sp_object_ref(layer, NULL);
- }
- if (_layer) {
- sp_object_unref(_layer, NULL);
- }
- _layer = layer;
-}
-
-} // namespace
-} // namespace
-} // namespace
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/layer-properties.h b/src/dialogs/layer-properties.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/** @file
- * @brief Dialog for renaming layers
- */
-/* Author:
- * Bryce W. Harrington <bryce@bryceharrington.com>
- *
- * Copyright (C) 2004 Bryce Harrington
- *
- * Released under GNU GPL. Read the file 'COPYING' for more information
- */
-
-#ifndef INKSCAPE_DIALOG_LAYER_PROPERTIES_H
-#define INKSCAPE_DIALOG_LAYER_PROPERTIES_H
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/notebook.h>
-#include <gtkmm/separator.h>
-#include <gtkmm/frame.h>
-#include <gtkmm/entry.h>
-#include <gtkmm/label.h>
-#include <gtkmm/table.h>
-#include <gtkmm/combobox.h>
-#include <gtkmm/liststore.h>
-
-#include "selection.h"
-#include "layer-fns.h"
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-class LayerPropertiesDialog : public Gtk::Dialog {
- public:
- LayerPropertiesDialog();
- virtual ~LayerPropertiesDialog();
-
- Glib::ustring getName() const { return "LayerPropertiesDialog"; }
-
- static void showRename(SPDesktop *desktop, SPObject *layer) {
- _showDialog(Rename::instance(), desktop, layer);
- }
- static void showCreate(SPDesktop *desktop, SPObject *layer) {
- _showDialog(Create::instance(), desktop, layer);
- }
-
-protected:
- struct Strategy {
- virtual ~Strategy() {}
- virtual void setup(LayerPropertiesDialog &)=0;
- virtual void perform(LayerPropertiesDialog &)=0;
- };
- struct Rename : public Strategy {
- static Rename &instance() { static Rename instance; return instance; }
- void setup(LayerPropertiesDialog &dialog);
- void perform(LayerPropertiesDialog &dialog);
- };
- struct Create : public Strategy {
- static Create &instance() { static Create instance; return instance; }
- void setup(LayerPropertiesDialog &dialog);
- void perform(LayerPropertiesDialog &dialog);
- };
-
- friend class Rename;
- friend class Create;
-
- Strategy *_strategy;
- SPDesktop *_desktop;
- SPObject *_layer;
-
- class PositionDropdownColumns : public Gtk::TreeModel::ColumnRecord {
- public:
- Gtk::TreeModelColumn<LayerRelativePosition> position;
- Gtk::TreeModelColumn<Glib::ustring> name;
-
- PositionDropdownColumns() {
- add(position); add(name);
- }
- };
-
- Gtk::Label _layer_name_label;
- Gtk::Entry _layer_name_entry;
- Gtk::Label _layer_position_label;
- Gtk::ComboBox _layer_position_combo;
- Gtk::Table _layout_table;
- bool _position_visible;
-
- PositionDropdownColumns _dropdown_columns;
- Gtk::CellRendererText _label_renderer;
- Glib::RefPtr<Gtk::ListStore> _dropdown_list;
-
- Gtk::Button _close_button;
- Gtk::Button _apply_button;
-
- sigc::connection _destroy_connection;
-
- static LayerPropertiesDialog &_instance() {
- static LayerPropertiesDialog instance;
- return instance;
- }
-
- void _setDesktop(SPDesktop *desktop);
- void _setLayer(SPObject *layer);
-
- static void _showDialog(Strategy &strategy, SPDesktop *desktop, SPObject *layer);
- void _apply();
- void _close();
-
- void _setup_position_controls();
- void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row);
-
-private:
- LayerPropertiesDialog(LayerPropertiesDialog const &); // no copy
- LayerPropertiesDialog &operator=(LayerPropertiesDialog const &); // no assign
-};
-
-} // namespace
-} // namespace
-} // namespace
-
-
-#endif //INKSCAPE_DIALOG_LAYER_PROPERTIES_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/layers-panel.cpp b/src/dialogs/layers-panel.cpp
+++ /dev/null
@@ -1,810 +0,0 @@
-/*
- * A simple panel for layers
- *
- * Authors:
- * Jon A. Cruz
- *
- * Copyright (C) 2006 Jon A. Cruz
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <glibmm/i18n.h>
-
-#include <gtk/gtkstock.h>
-#include <gtk/gtkmain.h>
-
-#include <gtkmm/icontheme.h>
-
-#include "inkscape.h"
-
-#include "layers-panel.h"
-
-#include "layer-manager.h"
-#include "layer-fns.h"
-
-#include "verbs.h"
-#include "helper/action.h"
-
-#include "document.h"
-#include "desktop.h"
-#include "sp-object.h"
-#include "sp-item.h"
-#include "widgets/icon.h"
-#include "ui/widget/imagetoggler.h"
-#include <gtkmm/widget.h>
-#include "preferences.h"
-#include "xml/repr.h"
-#include "svg/css-ostringstream.h"
-#include "desktop-style.h"
-#include "ui/icon-names.h"
-
-//#define DUMP_LAYERS 1
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-LayersPanel&
-LayersPanel::getInstance()
-{
- return *new LayersPanel();
-}
-
-enum {
- COL_VISIBLE = 1,
- COL_LOCKED
-};
-
-enum {
- BUTTON_NEW = 0,
- BUTTON_RENAME,
- BUTTON_TOP,
- BUTTON_BOTTOM,
- BUTTON_UP,
- BUTTON_DOWN,
- BUTTON_DUPLICATE,
- BUTTON_DELETE,
- BUTTON_SOLO
-};
-
-class LayersPanel::InternalUIBounce
-{
-public:
- int _actionCode;
- SPObject* _target;
-};
-
-static gboolean layers_panel_activated( GtkObject */*object*/, GdkEvent * /*event*/, gpointer data )
-{
- if ( data )
- {
- LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
- panel->setDesktop(panel->getDesktop());
- }
-
- return FALSE;
-}
-
-static gboolean layers_panel_deactivated( GtkObject */*object*/, GdkEvent * /*event*/, gpointer data )
-{
- if ( data )
- {
- LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
- panel->setDesktop(NULL);
- }
-
- return FALSE;
-}
-
-
-void LayersPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback )
-{
- bool set = false;
-
- if ( iconName ) {
- GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
- gtk_widget_show( child );
- btn.add( *manage(Glib::wrap(child)) );
- set = true;
- }
-
- if ( desktop ) {
- Verb *verb = Verb::get( code );
- if ( verb ) {
- SPAction *action = verb->get_action(desktop);
- if ( !set && action && action->image ) {
- GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image );
- gtk_widget_show( child );
- btn.add( *manage(Glib::wrap(child)) );
- set = true;
- }
-
- if ( action && action->tip ) {
- _tips.set_tip( btn, action->tip );
- }
- }
- }
-
- if ( !set && fallback ) {
- btn.set_label( fallback );
- }
-}
-
-
-Gtk::MenuItem& LayersPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
-{
- GtkWidget* iconWidget = 0;
- const char* label = 0;
-
- if ( iconName ) {
- iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName );
- }
-
- if ( desktop ) {
- Verb *verb = Verb::get( code );
- if ( verb ) {
- SPAction *action = verb->get_action(desktop);
- if ( !iconWidget && action && action->image ) {
- iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image );
- }
-
- if ( action ) {
- label = action->name;
- }
- }
- }
-
- if ( !label && fallback ) {
- label = fallback;
- }
-
- Gtk::Widget* wrapped = 0;
- if ( iconWidget ) {
- wrapped = manage(Glib::wrap(iconWidget));
- wrapped->show();
- }
-
-
-
- Gtk::Menu::MenuList& menulist = _popupMenu.items();
-
- if ( wrapped ) {
- menulist.push_back( Gtk::Menu_Helpers::ImageMenuElem( label, *wrapped, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
- } else {
- menulist.push_back( Gtk::Menu_Helpers::MenuElem( label, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
- }
- return menulist.back();
-}
-
-void LayersPanel::_fireAction( unsigned int code )
-{
- if ( _desktop ) {
- Verb *verb = Verb::get( code );
- if ( verb ) {
- SPAction *action = verb->get_action(_desktop);
- if ( action ) {
- sp_action_perform( action, NULL );
-// } else {
-// g_message("no action");
- }
-// } else {
-// g_message("no verb for %u", code);
- }
-// } else {
-// g_message("no active desktop");
- }
-}
-
-// SP_VERB_LAYER_NEXT,
-// SP_VERB_LAYER_PREV,
-void LayersPanel::_takeAction( int val )
-{
- if ( !_pending ) {
- _pending = new InternalUIBounce();
- _pending->_actionCode = val;
- _pending->_target = _selectedLayer();
- Glib::signal_timeout().connect( sigc::mem_fun(*this, &LayersPanel::_executeAction), 0 );
- }
-}
-
-bool LayersPanel::_executeAction()
-{
- // Make sure selected layer hasn't changed since the action was triggered
- if ( _pending
- && (
- (_pending->_actionCode == BUTTON_NEW)
- || !( (_desktop && _desktop->currentLayer())
- && (_desktop->currentLayer() != _pending->_target)
- )
- )
- ) {
- int val = _pending->_actionCode;
-// SPObject* target = _pending->_target;
-
- switch ( val ) {
- case BUTTON_NEW:
- {
- _fireAction( SP_VERB_LAYER_NEW );
- }
- break;
- case BUTTON_RENAME:
- {
- _fireAction( SP_VERB_LAYER_RENAME );
- }
- break;
- case BUTTON_TOP:
- {
- _fireAction( SP_VERB_LAYER_TO_TOP );
- }
- break;
- case BUTTON_BOTTOM:
- {
- _fireAction( SP_VERB_LAYER_TO_BOTTOM );
- }
- break;
- case BUTTON_UP:
- {
- _fireAction( SP_VERB_LAYER_RAISE );
- }
- break;
- case BUTTON_DOWN:
- {
- _fireAction( SP_VERB_LAYER_LOWER );
- }
- break;
- case BUTTON_DUPLICATE:
- {
- _fireAction( SP_VERB_LAYER_DUPLICATE );
- }
- break;
- case BUTTON_DELETE:
- {
- _fireAction( SP_VERB_LAYER_DELETE );
- }
- case BUTTON_SOLO:
- {
- _fireAction( SP_VERB_LAYER_SOLO );
- }
- break;
- }
-
- delete _pending;
- _pending = 0;
- }
-
- return false;
-}
-
-class LayersPanel::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;
-};
-
-void LayersPanel::_updateLayer( SPObject *layer ) {
- _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForUpdated), layer) );
-}
-
-bool LayersPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* layer)
-{
- bool stopGoing = false;
- Gtk::TreeModel::Row row = *iter;
- Glib::ustring tmp = row[_model->_colLabel];
- if ( layer == row[_model->_colObject] )
- {
- row[_model->_colLabel] = layer->label() ? layer->label() : SP_OBJECT_ID(layer);
- row[_model->_colVisible] = SP_IS_ITEM(layer) ? !SP_ITEM(layer)->isHidden() : false;
- row[_model->_colLocked] = SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false;
-
- stopGoing = true;
- }
-
- return stopGoing;
-}
-
-void LayersPanel::_selectLayer( SPObject *layer ) {
- if ( !layer || (_desktop && _desktop->doc() && (layer == _desktop->doc()->root)) ) {
- if ( _tree.get_selection()->count_selected_rows() != 0 ) {
- _tree.get_selection()->unselect_all();
- }
- } else {
- _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForSelected), layer) );
- }
-
- _checkTreeSelection();
-}
-
-bool LayersPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer)
-{
- bool stopGoing = false;
-
- Gtk::TreeModel::Row row = *iter;
- if ( layer == row[_model->_colObject] )
- {
- _tree.expand_to_path( path );
-
- Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
-
- select->select(iter);
-
- stopGoing = true;
- }
-
- return stopGoing;
-}
-
-void LayersPanel::_layersChanged()
-{
-// g_message("_layersChanged()");
- SPDocument* document = _desktop->doc();
- SPObject* root = document->root;
- if ( root ) {
- _selectedConnection.block();
- if ( _mgr && _mgr->includes( root ) ) {
- SPObject* target = _desktop->currentLayer();
- _store->clear();
-
-#if DUMP_LAYERS
- g_message("root:%p {%s} [%s]", root, root->id, root->label() );
-#endif // DUMP_LAYERS
- _addLayer( document, root, 0, target, 0 );
- }
- _selectedConnection.unblock();
- }
-}
-
-void LayersPanel::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level )
-{
- if ( layer && (level < _maxNestDepth) ) {
- unsigned int counter = _mgr->childCount(layer);
- for ( unsigned int i = 0; i < counter; i++ ) {
- SPObject *child = _mgr->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() : SP_OBJECT_ID(child);
- 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* LayersPanel::_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;
-}
-
-void LayersPanel::_pushTreeSelectionToCurrent()
-{
- SPObject* inTree = _selectedLayer();
- // TODO hunt down the possible API abuse in getting NULL
- if ( _desktop->currentRoot() ) {
- if ( inTree ) {
- SPObject* curr = _desktop->currentLayer();
- if ( curr != inTree ) {
- _mgr->setCurrentLayer( inTree );
- }
- } else {
- _mgr->setCurrentLayer( _desktop->doc()->root );
- }
- }
-}
-
-void LayersPanel::_checkTreeSelection()
-{
- bool sensitive = false;
- bool sensitiveNonTop = false;
- bool sensitiveNonBottom = false;
- if ( _tree.get_selection()->count_selected_rows() > 0 ) {
- sensitive = true;
-
- SPObject* inTree = _selectedLayer();
- if ( inTree ) {
-
- sensitiveNonTop = (Inkscape::next_layer(inTree->parent, inTree) != 0);
- sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0);
-
- }
- }
-
-
- for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
- (*it)->set_sensitive( sensitive );
- }
- for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
- (*it)->set_sensitive( sensitiveNonTop );
- }
- for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
- (*it)->set_sensitive( sensitiveNonBottom );
- }
-}
-
-void LayersPanel::_preToggle( GdkEvent const *event )
-{
- if ( _toggleEvent ) {
- gdk_event_free(_toggleEvent);
- _toggleEvent = 0;
- }
-
- if ( event && (event->type == GDK_BUTTON_PRESS) ) {
- // Make a copy so we can keep it around.
- _toggleEvent = gdk_event_copy(const_cast<GdkEvent*>(event));
- }
-}
-
-void LayersPanel::_toggled( Glib::ustring const& str, int targetCol )
-{
- Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(str);
- Gtk::TreeModel::Row row = *iter;
-
- Glib::ustring tmp = row[_model->_colLabel];
-
- SPObject* obj = row[_model->_colObject];
- SPItem* item = ( obj && SP_IS_ITEM(obj) ) ? SP_ITEM(obj) : 0;
- if ( item ) {
- switch ( targetCol ) {
- case COL_VISIBLE:
- {
- bool newValue = !row[_model->_colVisible];
- row[_model->_colVisible] = newValue;
- item->setHidden( !newValue );
- item->updateRepr();
- sp_document_done( _desktop->doc() , SP_VERB_DIALOG_LAYERS,
- newValue? _("Unhide layer") : _("Hide layer"));
- }
- break;
-
- case COL_LOCKED:
- {
- bool newValue = !row[_model->_colLocked];
- row[_model->_colLocked] = newValue;
- item->setLocked( newValue );
- item->updateRepr();
- sp_document_done( _desktop->doc() , SP_VERB_DIALOG_LAYERS,
- newValue? _("Lock layer") : _("Unlock layer"));
- }
- break;
- }
- }
-}
-
-void LayersPanel::_handleButtonEvent(GdkEventButton* evt)
-{
- // TODO - fix to a better is-popup function
- if ( (evt->type == GDK_BUTTON_PRESS) && (evt->button == 3) ) {
-
-
- {
- Gtk::TreeModel::Path path;
- Gtk::TreeViewColumn* col = 0;
- int x = static_cast<int>(evt->x);
- int y = static_cast<int>(evt->y);
- int x2 = 0;
- int y2 = 0;
- if ( _tree.get_path_at_pos( x, y,
- path, col,
- x2, y2 ) ) {
- _checkTreeSelection();
- _popupMenu.popup(evt->button, evt->time);
- }
- }
-
- }
-}
-
-void LayersPanel::_handleRowChange( Gtk::TreeModel::Path const& /*path*/, Gtk::TreeModel::iterator const& iter )
-{
- Gtk::TreeModel::Row row = *iter;
- if ( row ) {
- SPObject* obj = row[_model->_colObject];
- if ( obj ) {
- gchar const* oldLabel = obj->label();
- Glib::ustring tmp = row[_model->_colLabel];
- if ( oldLabel && oldLabel[0] && !tmp.empty() && (tmp != oldLabel) ) {
- _mgr->renameLayer( obj, tmp.c_str() );
- row[_model->_colLabel] = obj->label();
- }
- }
- }
-}
-
-bool LayersPanel::_rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected )
-{
- bool val = true;
- if ( !currentlySelected && _toggleEvent )
- {
- GdkEvent* event = gtk_get_current_event();
- if ( event ) {
- // (keep these checks separate, so we know when to call gdk_event_free()
- if ( event->type == GDK_BUTTON_PRESS ) {
- GdkEventButton const* target = reinterpret_cast<GdkEventButton const*>(_toggleEvent);
- GdkEventButton const* evtb = reinterpret_cast<GdkEventButton const*>(event);
-
- if ( (evtb->window == target->window)
- && (evtb->send_event == target->send_event)
- && (evtb->time == target->time)
- && (evtb->state == target->state)
- )
- {
- // Ooooh! It's a magic one
- val = false;
- }
- }
- gdk_event_free(event);
- }
- }
- return val;
-}
-
-/**
- * Constructor
- */
-LayersPanel::LayersPanel() :
- UI::Widget::Panel("", "/dialogs/layers", SP_VERB_DIALOG_LAYERS),
- _maxNestDepth(20),
- _mgr(0),
- _desktop(0),
- _model(0),
- _pending(0),
- _toggleEvent(0),
- _compositeSettings(SP_VERB_DIALOG_LAYERS, "layers", UI::Widget::SimpleFilterModifier::BLEND)
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- _maxNestDepth = prefs->getIntLimited("/dialogs/layers/maxDepth", 20, 1, 1000);
-
- 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;
- eyeRenderer->signal_pre_toggle().connect( sigc::mem_fun(*this, &LayersPanel::_preToggle) );
- eyeRenderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_VISIBLE) );
- eyeRenderer->property_activatable() = true;
- 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;
- renderer->signal_pre_toggle().connect( sigc::mem_fun(*this, &LayersPanel::_preToggle) );
- renderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_LOCKED) );
- renderer->property_activatable() = true;
- col = _tree.get_column(lockedColNum);
- if ( col ) {
- col->add_attribute( renderer->property_active(), _model->_colLocked );
- }
-
- int nameColNum = _tree.append_column_editable("Name", _model->_colLabel) - 1;
-
- _tree.set_expander_column( *_tree.get_column(nameColNum) );
-
- _compositeSettings.setSubject(&_subject);
-
- _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &LayersPanel::_pushTreeSelectionToCurrent) );
- _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &LayersPanel::_rowSelectFunction) );
-
- _tree.get_model()->signal_row_changed().connect( sigc::mem_fun(*this, &LayersPanel::_handleRowChange) );
- _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent) );
-
- _scroller.add( _tree );
- _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
- _scroller.set_shadow_type(Gtk::SHADOW_IN);
-
- _watching.push_back( &_compositeSettings );
-
- _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET );
- _layersPage.pack_end(_compositeSettings, Gtk::PACK_SHRINK);
- _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK);
-
- _notebook.append_page(_layersPage, _("Layers"));
-
- _getContents()->pack_start(_notebook, Gtk::PACK_EXPAND_WIDGET);
-
- SPDesktop* targetDesktop = getDesktop();
-
- _buttonsRow.set_child_min_width( 16 );
-
- Gtk::Button* btn = manage( new Gtk::Button() );
- _styleButton( *btn, targetDesktop, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("New") );
- btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_NEW) );
- _buttonsRow.add( *btn );
-
- btn = manage( new Gtk::Button() );
- _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_TOP, GTK_STOCK_GOTO_TOP, _("Top") );
- btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_TOP) );
- _watchingNonTop.push_back( btn );
- _buttonsRow.add( *btn );
-
- btn = manage( new Gtk::Button() );
- _styleButton( *btn, targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, _("Up") );
- btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_UP) );
- _watchingNonTop.push_back( btn );
- _buttonsRow.add( *btn );
-
- btn = manage( new Gtk::Button() );
- _styleButton( *btn, targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, _("Dn") );
- btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DOWN) );
- _watchingNonBottom.push_back( btn );
- _buttonsRow.add( *btn );
-
- btn = manage( new Gtk::Button() );
- _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_BOTTOM, GTK_STOCK_GOTO_BOTTOM, _("Bot") );
- btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_BOTTOM) );
- _watchingNonBottom.push_back( btn );
- _buttonsRow.add( *btn );
-
-// btn = manage( new Gtk::Button("Dup") );
-// btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) );
-// _buttonsRow.add( *btn );
-
- btn = manage( new Gtk::Button() );
- _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("X") );
- btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DELETE) );
- _watching.push_back( btn );
- _buttonsRow.add( *btn );
-
-
-
-
- // -------------------------------------------------------
- {
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SOLO, 0, "Solo", (int)BUTTON_SOLO ) );
-
- _popupMenu.items().push_back( Gtk::Menu_Helpers::SeparatorElem() );
-
- _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) );
- _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) );
-
- _popupMenu.show_all_children();
- }
- // -------------------------------------------------------
-
-
-
- for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
- (*it)->set_sensitive( false );
- }
- for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
- (*it)->set_sensitive( false );
- }
- for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
- (*it)->set_sensitive( false );
- }
-
- g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK( layers_panel_activated ), this );
- g_signal_connect( G_OBJECT(INKSCAPE), "deactivate_desktop", G_CALLBACK( layers_panel_deactivated ), this );
- setDesktop( targetDesktop );
-
- show_all_children();
-
- // restorePanelPrefs();
-}
-
-LayersPanel::~LayersPanel()
-{
- setDesktop(NULL);
-
- _compositeSettings.setSubject(NULL);
-
- if ( _model )
- {
- delete _model;
- }
-
- if ( _toggleEvent )
- {
- gdk_event_free( _toggleEvent );
- _toggleEvent = 0;
- }
-}
-
-
-void LayersPanel::setDesktop( SPDesktop* desktop )
-{
- Panel::setDesktop(desktop);
-
- if ( desktop != _desktop ) {
- _layerChangedConnection.disconnect();
- _layerUpdatedConnection.disconnect();
- _changedConnection.disconnect();
- if ( _mgr ) {
- _mgr = 0;
- }
- if ( _desktop ) {
- _desktop = 0;
- }
-
- _desktop = getDesktop();
- if ( _desktop ) {
- //setLabel( _desktop->doc()->name );
-
- _mgr = _desktop->layer_manager;
- if ( _mgr ) {
- _layerChangedConnection = _mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayersPanel::_selectLayer) );
- _layerUpdatedConnection = _mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayersPanel::_updateLayer) );
- _changedConnection = _mgr->connectChanged( sigc::mem_fun(*this, &LayersPanel::_layersChanged) );
- }
-
- _layersChanged();
- }
- }
-/*
- GSList const *layers=sp_document_get_resource_list( _desktop->doc(), "layer" );
- g_message( "layers list starts at %p", layers );
- for ( GSList const *iter=layers ; iter ; iter = iter->next ) {
- SPObject *layer=static_cast<SPObject *>(iter->data);
- g_message(" {%s} [%s]", layer->id, layer->label() );
- }
-*/
-}
-
-
-
-} //namespace Dialogs
-} //namespace UI
-} //namespace Inkscape
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/layers-panel.h b/src/dialogs/layers-panel.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * A simple dialog for layer UI.
- *
- * Authors:
- * Jon A. Cruz
- *
- * Copyright (C) 2006 Jon A. Cruz
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_LAYERS_PANEL_H
-#define SEEN_LAYERS_PANEL_H
-
-#include <gtkmm/treeview.h>
-#include <gtkmm/treestore.h>
-#include <gtkmm/tooltips.h>
-#include <gtkmm/scale.h>
-#include <gtkmm/scrolledwindow.h>
-#include <gtkmm/box.h>
-#include <gtkmm/buttonbox.h>
-#include <gtkmm/spinbutton.h>
-#include <gtkmm/notebook.h>
-
-//#include "ui/previewholder.h"
-#include "ui/widget/panel.h"
-#include "ui/widget/object-composite-settings.h"
-
-class SPObject;
-
-namespace Inkscape {
-
-class LayerManager;
-
-namespace UI {
-namespace Dialogs {
-
-
-/**
- * A panel that displays layers.
- */
-class LayersPanel : public UI::Widget::Panel
-{
-public:
- LayersPanel();
- virtual ~LayersPanel();
-
- //virtual void setOrientation( Gtk::AnchorType how );
-
- static LayersPanel& getInstance();
-
- void setDesktop( SPDesktop* desktop );
-
-protected:
- //virtual void _handleAction( int setId, int itemId );
-
-private:
- class ModelColumns;
- class InternalUIBounce;
-
- LayersPanel(LayersPanel const &); // no copy
- LayersPanel &operator=(LayersPanel const &); // no assign
-
- void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback );
- void _fireAction( unsigned int code );
- Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id );
-
- void _preToggle( GdkEvent const *event );
- void _toggled( Glib::ustring const& str, int targetCol );
-
- void _handleButtonEvent(GdkEventButton* evt);
- void _handleRowChange( Gtk::TreeModel::Path const& path, Gtk::TreeModel::iterator const& iter );
-
- void _pushTreeSelectionToCurrent();
- void _checkTreeSelection();
-
- void _takeAction( int val );
- bool _executeAction();
-
- bool _rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & model, Gtk::TreeModel::Path const & path, bool b );
-
- void _updateLayer(SPObject *layer);
- bool _checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer);
-
- void _selectLayer(SPObject *layer);
- bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer);
-
- void _layersChanged();
- void _addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level );
-
- SPObject* _selectedLayer();
-
- // Hooked to the layer manager:
- sigc::connection _layerChangedConnection;
- sigc::connection _layerUpdatedConnection;
- sigc::connection _changedConnection;
- sigc::connection _addedConnection;
- sigc::connection _removedConnection;
-
- // Internal
- sigc::connection _selectedConnection;
-
- int _maxNestDepth;
- Inkscape::LayerManager* _mgr;
- SPDesktop* _desktop;
- ModelColumns* _model;
- InternalUIBounce* _pending;
- GdkEvent* _toggleEvent;
- Glib::RefPtr<Gtk::TreeStore> _store;
- std::vector<Gtk::Widget*> _watching;
- std::vector<Gtk::Widget*> _watchingNonTop;
- std::vector<Gtk::Widget*> _watchingNonBottom;
-
- Gtk::Tooltips _tips;
- Gtk::TreeView _tree;
- Gtk::HButtonBox _buttonsRow;
- Gtk::ScrolledWindow _scroller;
- Gtk::Menu _popupMenu;
- Gtk::SpinButton _spinBtn;
- Gtk::Notebook _notebook;
- Gtk::VBox _layersPage;
-
- UI::Widget::StyleSubject::CurrentLayer _subject;
- UI::Widget::ObjectCompositeSettings _compositeSettings;
-};
-
-
-
-} //namespace Dialogs
-} //namespace UI
-} //namespace Inkscape
-
-
-
-#endif // SEEN_LAYERS_PANEL_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index d9bcf148943efb75e9753f18778db5c95beab2c6..320840f76bc5387188c819367a6a9b0974c963c4 100644 (file)
#include <glibmm/i18n.h>
#include <string>
#include <cstring>
+#include <sigc++/connection.h>
+#include <sigc++/functors/ptr_fun.h>
+#include <sigc++/adaptors/bind.h>
#include "helper/window.h"
#include "macros.h"
#include "sp-anchor.h"
-#include "sp-attribute-widget.h"
+#include "widgets/sp-attribute-widget.h"
#include "../xml/repr.h"
-#include <sigc++/connection.h>
-#include <sigc++/functors/ptr_fun.h>
-#include <sigc++/adaptors/bind.h>
-
struct SPAttrDesc {
gchar const *label;
gchar const *attribute;
diff --git a/src/dialogs/rdf.cpp b/src/dialogs/rdf.cpp
--- a/src/dialogs/rdf.cpp
+++ /dev/null
@@ -1,1023 +0,0 @@
-/** @file
- * @brief RDF manipulation functions
- *
- * @todo move these to xml/ instead of dialogs/
- */
-/* Authors:
- * Kees Cook <kees@outflux.net>
- * Jon Phillips <jon@rejon.org>
- *
- * Copyright (C) 2004 Kees Cook <kees@outflux.net>
- * Copyright (C) 2006 Jon Phillips <jon@rejon.org>
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "xml/repr.h"
-#include "rdf.h"
-#include "sp-item-group.h"
-#include "inkscape.h"
-
-/*
- Example RDF XML from various places...
-
-<rdf:RDF xmlns="http://creativecommons.org/ns#"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
-<Work rdf:about="">
- <dc:title>title of work</dc:title>
- <dc:date>year</dc:date>
- <dc:description>description of work</dc:description>
- <dc:creator><Agent>
- <dc:title>creator</dc:title>
- </Agent></dc:creator>
- <dc:rights><Agent>
- <dc:title>holder</dc:title>
- </Agent></dc:rights>
- <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:source rdf:resource="source"/>
- <license rdf:resource="http://creativecommons.org/licenses/by/2.0/"
-/>
-</Work>
-
-
- <rdf:RDF xmlns="http://creativecommons.org/ns#"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
- <Work rdf:about="">
- <dc:title>SVG Road Signs</dc:title>
- <dc:rights><Agent>
- <dc:title>John Cliff</dc:title>
- </Agent></dc:rights>
- <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <license rdf:resource="http://creativecommons.org/ns#PublicDomain" />
- </Work>
-
- <License rdf:about="http://creativecommons.org/ns#PublicDomain">
- <permits rdf:resource="http://creativecommons.org/ns#Reproduction" />
- <permits rdf:resource="http://creativecommons.org/ns#Distribution" />
- <permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
- </License>
-
-</rdf:RDF>
-
-
-Bag example:
-
-<dc:subject>
-<rdf:Bag>
-<rdf:li>open clip art logo</rdf:li>
-<rdf:li>images</rdf:li>
-<rdf:li>logo</rdf:li>
-<rdf:li>clip art</rdf:li>
-<rdf:li>ocal</rdf:li>
-<rdf:li>logotype</rdf:li>
-<rdf:li>filetype</rdf:li>
-</rdf:Bag>
-</dc:subject>
-*/
-
-struct rdf_double_t rdf_license_empty [] = {
- { NULL, NULL }
-};
-
-struct rdf_double_t rdf_license_cc_a [] = {
- { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
- { "cc:permits", "http://creativecommons.org/ns#Distribution", },
- { "cc:requires", "http://creativecommons.org/ns#Notice", },
- { "cc:requires", "http://creativecommons.org/ns#Attribution", },
- { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
- { NULL, NULL }
-};
-
-struct rdf_double_t rdf_license_cc_a_sa [] = {
- { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
- { "cc:permits", "http://creativecommons.org/ns#Distribution", },
- { "cc:requires", "http://creativecommons.org/ns#Notice", },
- { "cc:requires", "http://creativecommons.org/ns#Attribution", },
- { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
- { "cc:requires", "http://creativecommons.org/ns#ShareAlike", },
- { NULL, NULL }
-};
-
-struct rdf_double_t rdf_license_cc_a_nd [] = {
- { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
- { "cc:permits", "http://creativecommons.org/ns#Distribution", },
- { "cc:requires", "http://creativecommons.org/ns#Notice", },
- { "cc:requires", "http://creativecommons.org/ns#Attribution", },
- { NULL, NULL }
-};
-
-struct rdf_double_t rdf_license_cc_a_nc [] = {
- { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
- { "cc:permits", "http://creativecommons.org/ns#Distribution", },
- { "cc:requires", "http://creativecommons.org/ns#Notice", },
- { "cc:requires", "http://creativecommons.org/ns#Attribution", },
- { "cc:prohibits", "http://creativecommons.org/ns#CommercialUse", },
- { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
- { NULL, NULL }
-};
-
-struct rdf_double_t rdf_license_cc_a_nc_sa [] = {
- { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
- { "cc:permits", "http://creativecommons.org/ns#Distribution", },
- { "cc:requires", "http://creativecommons.org/ns#Notice", },
- { "cc:requires", "http://creativecommons.org/ns#Attribution", },
- { "cc:prohibits", "http://creativecommons.org/ns#CommercialUse", },
- { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
- { "cc:requires", "http://creativecommons.org/ns#ShareAlike", },
- { NULL, NULL }
-};
-
-struct rdf_double_t rdf_license_cc_a_nc_nd [] = {
- { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
- { "cc:permits", "http://creativecommons.org/ns#Distribution", },
- { "cc:requires", "http://creativecommons.org/ns#Notice", },
- { "cc:requires", "http://creativecommons.org/ns#Attribution", },
- { "cc:prohibits", "http://creativecommons.org/ns#CommercialUse", },
- { NULL, NULL }
-};
-
-struct rdf_double_t rdf_license_pd [] = {
- { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
- { "cc:permits", "http://creativecommons.org/ns#Distribution", },
- { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
- { NULL, NULL }
-};
-
-struct rdf_double_t rdf_license_freeart [] = {
- { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
- { "cc:permits", "http://creativecommons.org/ns#Distribution", },
- { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
- { "cc:requires", "http://creativecommons.org/ns#ShareAlike", },
- { "cc:requires", "http://creativecommons.org/ns#Notice", },
- { "cc:requires", "http://creativecommons.org/ns#Attribution", },
- { NULL, NULL }
-};
-
-struct rdf_double_t rdf_license_ofl [] = {
- { "cc:permits", "http://scripts.sil.org/pub/OFL/Reproduction", },
- { "cc:permits", "http://scripts.sil.org/pub/OFL/Distribution", },
- { "cc:permits", "http://scripts.sil.org/pub/OFL/Embedding", },
- { "cc:permits", "http://scripts.sil.org/pub/OFL/DerivativeWorks", },
- { "cc:requires", "http://scripts.sil.org/pub/OFL/Notice", },
- { "cc:requires", "http://scripts.sil.org/pub/OFL/Attribution", },
- { "cc:requires", "http://scripts.sil.org/pub/OFL/ShareAlike", },
- { "cc:requires", "http://scripts.sil.org/pub/OFL/DerivativeRenaming", },
- { "cc:requires", "http://scripts.sil.org/pub/OFL/BundlingWhenSelling", },
- { NULL, NULL }
-};
-
-struct rdf_license_t rdf_licenses [] = {
- { N_("CC Attribution"),
- "http://creativecommons.org/licenses/by/3.0/",
- rdf_license_cc_a,
- },
-
- { N_("CC Attribution-ShareAlike"),
- "http://creativecommons.org/licenses/by-sa/3.0/",
- rdf_license_cc_a_sa,
- },
-
- { N_("CC Attribution-NoDerivs"),
- "http://creativecommons.org/licenses/by-nd/3.0/",
- rdf_license_cc_a_nd,
- },
-
- { N_("CC Attribution-NonCommercial"),
- "http://creativecommons.org/licenses/by-nc/3.0/",
- rdf_license_cc_a_nc,
- },
-
- { N_("CC Attribution-NonCommercial-ShareAlike"),
- "http://creativecommons.org/licenses/by-nc-sa/3.0/",
- rdf_license_cc_a_nc_sa,
- },
-
- { N_("CC Attribution-NonCommercial-NoDerivs"),
- "http://creativecommons.org/licenses/by-nc-nd/3.0/",
- rdf_license_cc_a_nc_nd,
- },
-
- { N_("Public Domain"),
- "http://creativecommons.org/licenses/publicdomain/",
- rdf_license_pd,
- },
-
- { N_("FreeArt"),
- "http://artlibre.org/licence.php/lalgb.html",
- rdf_license_freeart,
- },
-
- { N_("Open Font License"),
- "http://scripts.sil.org/OFL",
- rdf_license_ofl,
- },
-
- { NULL, NULL, rdf_license_empty, }
-};
-
-#define XML_TAG_NAME_SVG "svg:svg"
-#define XML_TAG_NAME_METADATA "svg:metadata"
-#define XML_TAG_NAME_RDF "rdf:RDF"
-#define XML_TAG_NAME_WORK "cc:Work"
-#define XML_TAG_NAME_LICENSE "cc:License"
-
-// Remember when using the "title" and "tip" elements to pass them through
-// the localization functions when you use them!
-struct rdf_work_entity_t rdf_work_entities [] = {
- { "title", N_("Title"), "dc:title", RDF_CONTENT,
- N_("Name by which this document is formally known."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
- { "date", N_("Date"), "dc:date", RDF_CONTENT,
- N_("Date associated with the creation of this document (YYYY-MM-DD)."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
- { "format", N_("Format"), "dc:format", RDF_CONTENT,
- N_("The physical or digital manifestation of this document (MIME type)."), RDF_FORMAT_LINE, RDF_EDIT_HARDCODED,
- },
- { "type", N_("Type"), "dc:type", RDF_RESOURCE,
- N_("Type of document (DCMI Type)."), RDF_FORMAT_LINE, RDF_EDIT_HARDCODED,
- },
-
- { "creator", N_("Creator"), "dc:creator", RDF_AGENT,
- N_("Name of entity primarily responsible for making the content of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
- { "rights", N_("Rights"), "dc:rights", RDF_AGENT,
- N_("Name of entity with rights to the Intellectual Property of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
- { "publisher", N_("Publisher"), "dc:publisher", RDF_AGENT,
- N_("Name of entity responsible for making this document available."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
-
- { "identifier", N_("Identifier"), "dc:identifier", RDF_CONTENT,
- N_("Unique URI to reference this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
- { "source", N_("Source"), "dc:source", RDF_CONTENT,
- N_("Unique URI to reference the source of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
- { "relation", N_("Relation"), "dc:relation", RDF_CONTENT,
- N_("Unique URI to a related document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
- { "language", N_("Language"), "dc:language", RDF_CONTENT,
- N_("Two-letter language tag with optional subtags for the language of this document. (e.g. 'en-GB')"), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
- { "subject", N_("Keywords"), "dc:subject", RDF_BAG,
- N_("The topic of this document as comma-separated key words, phrases, or classifications."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
- // TRANSLATORS: "Coverage": the spatial or temporal characteristics of the content.
- // For info, see Appendix D of http://www.w3.org/TR/1998/WD-rdf-schema-19980409/
- { "coverage", N_("Coverage"), "dc:coverage", RDF_CONTENT,
- N_("Extent or scope of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
- },
-
- { "description", N_("Description"), "dc:description", RDF_CONTENT,
- N_("A short account of the content of this document."), RDF_FORMAT_MULTILINE, RDF_EDIT_GENERIC,
- },
-
- // FIXME: need to handle 1 agent per line of input
- { "contributor", N_("Contributors"), "dc:contributor", RDF_AGENT,
- N_("Names of entities responsible for making contributions to the content of this document."), RDF_FORMAT_MULTILINE, RDF_EDIT_GENERIC,
- },
-
- // TRANSLATORS: URL to a page that defines the license for the document
- { "license_uri", N_("URI"), "cc:license", RDF_RESOURCE,
- // TRANSLATORS: this is where you put a URL to a page that defines the license
- N_("URI to this document's license's namespace definition."), RDF_FORMAT_LINE, RDF_EDIT_SPECIAL,
- },
-
- // TRANSLATORS: fragment of XML representing the license of the document
- { "license_fragment", N_("Fragment"), "License", RDF_XML,
- N_("XML fragment for the RDF 'License' section."), RDF_FORMAT_MULTILINE, RDF_EDIT_SPECIAL,
- },
-
- { NULL, NULL, NULL, RDF_CONTENT,
- NULL, RDF_FORMAT_LINE, RDF_EDIT_HARDCODED,
- }
-};
-
-/**
- * \brief Retrieves a known RDF/Work entity by name
- * \return A pointer to an RDF/Work entity
- * \param name The desired RDF/Work entity
- *
- */
-struct rdf_work_entity_t *
-rdf_find_entity(gchar const * name)
-{
- struct rdf_work_entity_t *entity;
- for (entity=rdf_work_entities; entity->name; entity++) {
- if (strcmp(entity->name,name)==0) break;
- }
- if (entity->name) return entity;
- return NULL;
-}
-
-/*
- * Takes the inkscape rdf struct and spits out a static RDF, which is only
- * useful for testing. We must merge the rdf struct into the XML DOM for
- * changes to be saved.
- */
-/*
-
- Since g_markup_printf_escaped doesn't exist for most people's glib
- right now, this function will remain commented out since it's only
- for generic debug anyway. --Kees
-
-gchar *
-rdf_string(struct rdf_t * rdf)
-{
- gulong overall=0;
- gchar *string=NULL;
-
- gchar *rdf_head="\
-<rdf:RDF xmlns=\"http://creativecommons.org/ns#\"\
- xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\
- xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\
-";
- gchar *work_head="\
-<Work rdf:about=\"\">\
- <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\
-";
- gchar *work_title=NULL;
- gchar *work_date=NULL;
- gchar *work_description=NULL;
- gchar *work_creator=NULL;
- gchar *work_owner=NULL;
- gchar *work_source=NULL;
- gchar *work_license=NULL;
- gchar *license_head=NULL;
- gchar *license=NULL;
- gchar *license_end="</License>\n";
- gchar *work_end="</Work>\n";
- gchar *rdf_end="</rdf:RDF>\n";
-
- if (rdf && rdf->work_title && rdf->work_title[0]) {
- work_title=g_markup_printf_escaped(" <dc:title>%s</dc:title>\n",
- rdf->work_title);
- overall+=strlen(work_title);
- }
- if (rdf && rdf->work_date && rdf->work_date[0]) {
- work_date=g_markup_printf_escaped(" <dc:date>%s</dc:date>\n",
- rdf->work_date);
- overall+=strlen(work_date);
- }
- if (rdf && rdf->work_description && rdf->work_description[0]) {
- work_description=g_markup_printf_escaped(" <dc:description>%s</dc:description>\n",
- rdf->work_description);
- overall+=strlen(work_description);
- }
- if (rdf && rdf->work_creator && rdf->work_creator[0]) {
- work_creator=g_markup_printf_escaped(" <dc:creator><Agent>\
- <dc:title>%s</dc:title>\
- </Agent></dc:creator>\n",
- rdf->work_creator);
- overall+=strlen(work_creator);
- }
- if (rdf && rdf->work_owner && rdf->work_owner[0]) {
- work_owner=g_markup_printf_escaped(" <dc:rights><Agent>\
- <dc:title>%s</dc:title>\
- </Agent></dc:rights>\n",
- rdf->work_owner);
- overall+=strlen(work_owner);
- }
- if (rdf && rdf->work_source && rdf->work_source[0]) {
- work_source=g_markup_printf_escaped(" <dc:source rdf:resource=\"%s\" />\n",
- rdf->work_source);
- overall+=strlen(work_source);
- }
- if (rdf && rdf->license && rdf->license->work_rdf && rdf->license->work_rdf[0]) {
- work_license=g_markup_printf_escaped(" <license rdf:resource=\"%s\" />\n",
- rdf->license->work_rdf);
- overall+=strlen(work_license);
-
- license_head=g_markup_printf_escaped("<License rdf:about=\"%s\">\n",
- rdf->license->work_rdf);
- overall+=strlen(license_head);
- overall+=strlen(rdf->license->license_rdf);
- overall+=strlen(license_end);
- }
-
- overall+=strlen(rdf_head)+strlen(rdf_end);
- overall+=strlen(work_head)+strlen(work_end);
-
- overall++; // NULL term
-
- if (!(string=(gchar*)g_malloc(overall))) {
- return NULL;
- }
-
- string[0]='\0';
- strcat(string,rdf_head);
- strcat(string,work_head);
-
- if (work_title) strcat(string,work_title);
- if (work_date) strcat(string,work_date);
- if (work_description) strcat(string,work_description);
- if (work_creator) strcat(string,work_creator);
- if (work_owner) strcat(string,work_owner);
- if (work_source) strcat(string,work_source);
- if (work_license) strcat(string,work_license);
-
- strcat(string,work_end);
- if (license_head) {
- strcat(string,license_head);
- strcat(string,rdf->license->license_rdf);
- strcat(string,license_end);
- }
- strcat(string,rdf_end);
-
- return string;
-}
-*/
-
-
-/**
- * \brief Pull the text out of an RDF entity, depends on how it's stored
- * \return A pointer to the entity's static contents as a string
- * \param repr The XML element to extract from
- * \param entity The desired RDF/Work entity
- *
- */
-const gchar *
-rdf_get_repr_text ( Inkscape::XML::Node * repr, struct rdf_work_entity_t * entity )
-{
- g_return_val_if_fail (repr != NULL, NULL);
- g_return_val_if_fail (entity != NULL, NULL);
- static gchar * bag = NULL;
- gchar * holder = NULL;
-
- Inkscape::XML::Node * temp=NULL;
- switch (entity->datatype) {
- case RDF_CONTENT:
- temp = sp_repr_children(repr);
- if ( temp == NULL ) return NULL;
-
- return temp->content();
-
- case RDF_AGENT:
- temp = sp_repr_lookup_name ( repr, "cc:Agent", 1 );
- if ( temp == NULL ) return NULL;
-
- temp = sp_repr_lookup_name ( temp, "dc:title", 1 );
- if ( temp == NULL ) return NULL;
-
- temp = sp_repr_children(temp);
- if ( temp == NULL ) return NULL;
-
- return temp->content();
-
- case RDF_RESOURCE:
- return repr->attribute("rdf:resource");
-
- case RDF_XML:
- return "xml goes here";
-
- case RDF_BAG:
- /* clear the static string. yucky. */
- if (bag) g_free(bag);
- bag = NULL;
-
- temp = sp_repr_lookup_name ( repr, "rdf:Bag", 1 );
- if ( temp == NULL ) {
- /* backwards compatible: read contents */
- temp = sp_repr_children(repr);
- if ( temp == NULL ) return NULL;
-
- return temp->content();
- }
-
- for ( temp = sp_repr_children(temp) ;
- temp ;
- temp = sp_repr_next(temp) ) {
- if (!strcmp(temp->name(),"rdf:li") &&
- temp->firstChild()) {
- const gchar * str = temp->firstChild()->content();
- if (bag) {
- holder = bag;
- bag = g_strconcat(holder, ", ", str, NULL);
- g_free(holder);
- }
- else {
- bag = g_strdup(str);
- }
- }
- }
- return bag;
-
- default:
- break;
- }
- return NULL;
-}
-
-unsigned int
-rdf_set_repr_text ( Inkscape::XML::Node * repr,
- struct rdf_work_entity_t * entity,
- gchar const * text )
-{
- g_return_val_if_fail ( repr != NULL, 0);
- g_return_val_if_fail ( entity != NULL, 0);
- g_return_val_if_fail ( text != NULL, 0);
- gchar * str = NULL;
- gchar** strlist = NULL;
- int i;
-
- Inkscape::XML::Node * temp=NULL;
- Inkscape::XML::Node * child=NULL;
- Inkscape::XML::Node * parent=repr;
-
- Inkscape::XML::Document * xmldoc = parent->document();
- g_return_val_if_fail (xmldoc != NULL, FALSE);
-
- // set document's title element to the RDF title
- if (!strcmp(entity->name, "title")) {
- SPDocument *doc = SP_ACTIVE_DOCUMENT;
- if(doc && doc->root) doc->root->setTitle(text);
- }
-
- switch (entity->datatype) {
- case RDF_CONTENT:
- temp = sp_repr_children(parent);
- if ( temp == NULL ) {
- temp = xmldoc->createTextNode( text );
- g_return_val_if_fail (temp != NULL, FALSE);
-
- parent->appendChild(temp);
- Inkscape::GC::release(temp);
-
- return TRUE;
- }
- else {
- temp->setContent(text);
- return TRUE;
- }
-
- case RDF_AGENT:
- temp = sp_repr_lookup_name ( parent, "cc:Agent", 1 );
- if ( temp == NULL ) {
- temp = xmldoc->createElement ( "cc:Agent" );
- g_return_val_if_fail (temp != NULL, FALSE);
-
- parent->appendChild(temp);
- Inkscape::GC::release(temp);
- }
- parent = temp;
-
- temp = sp_repr_lookup_name ( parent, "dc:title", 1 );
- if ( temp == NULL ) {
- temp = xmldoc->createElement ( "dc:title" );
- g_return_val_if_fail (temp != NULL, FALSE);
-
- parent->appendChild(temp);
- Inkscape::GC::release(temp);
- }
- parent = temp;
-
- temp = sp_repr_children(parent);
- if ( temp == NULL ) {
- temp = xmldoc->createTextNode( text );
- g_return_val_if_fail (temp != NULL, FALSE);
-
- parent->appendChild(temp);
- Inkscape::GC::release(temp);
-
- return TRUE;
- }
- else {
- temp->setContent(text);
- return TRUE;
- }
-
- case RDF_RESOURCE:
- parent->setAttribute("rdf:resource", text );
- return true;
-
- case RDF_XML:
- return 1;
-
- case RDF_BAG:
- /* find/create the rdf:Bag item */
- temp = sp_repr_lookup_name ( parent, "rdf:Bag", 1 );
- if ( temp == NULL ) {
- /* backward compatibility: drop the dc:subject contents */
- while ( (temp = sp_repr_children( parent )) ) {
- parent->removeChild(temp);
- }
-
- temp = xmldoc->createElement ( "rdf:Bag" );
- g_return_val_if_fail (temp != NULL, FALSE);
-
- parent->appendChild(temp);
- Inkscape::GC::release(temp);
- }
- parent = temp;
-
- /* toss all the old list items */
- while ( (temp = sp_repr_children( parent )) ) {
- parent->removeChild(temp);
- }
-
- /* chop our list up on commas */
- strlist = g_strsplit( text, ",", 0);
-
- for (i = 0; (str = strlist[i]); i++) {
- temp = xmldoc->createElement ( "rdf:li" );
- g_return_val_if_fail (temp != NULL, 0);
-
- parent->appendChild(temp);
- Inkscape::GC::release(temp);
-
- child = xmldoc->createTextNode( g_strstrip(str) );
- g_return_val_if_fail (child != NULL, 0);
-
- temp->appendChild(child);
- Inkscape::GC::release(child);
- }
- g_strfreev( strlist );
-
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-Inkscape::XML::Node *
-rdf_get_rdf_root_repr ( SPDocument * doc, bool build )
-{
- g_return_val_if_fail (doc != NULL, NULL);
- g_return_val_if_fail (doc->rroot != NULL, NULL);
-
- Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
- g_return_val_if_fail (xmldoc != NULL, NULL);
-
- Inkscape::XML::Node * rdf = sp_repr_lookup_name ( doc->rroot, XML_TAG_NAME_RDF );
-
- if (rdf == NULL) {
- //printf("missing XML '%s'\n",XML_TAG_NAME_RDF);
- if (!build) return NULL;
-
- Inkscape::XML::Node * svg = sp_repr_lookup_name ( doc->rroot, XML_TAG_NAME_SVG );
- g_return_val_if_fail ( svg != NULL, NULL );
-
- Inkscape::XML::Node * parent = sp_repr_lookup_name ( svg, XML_TAG_NAME_METADATA );
- if ( parent == NULL ) {
- parent = xmldoc->createElement( XML_TAG_NAME_METADATA );
- g_return_val_if_fail ( parent != NULL, NULL);
-
- svg->appendChild(parent);
- Inkscape::GC::release(parent);
- }
-
- Inkscape::XML::Document * xmldoc = parent->document();
- g_return_val_if_fail (xmldoc != NULL, FALSE);
-
- rdf = xmldoc->createElement( XML_TAG_NAME_RDF );
- g_return_val_if_fail (rdf != NULL, NULL);
-
- parent->appendChild(rdf);
- Inkscape::GC::release(rdf);
- }
-
- /*
- * some implementations do not put RDF stuff inside <metadata>,
- * so we need to check for it and add it if we don't see it
- */
- Inkscape::XML::Node * want_metadata = sp_repr_parent ( rdf );
- g_return_val_if_fail (want_metadata != NULL, NULL);
- if (strcmp( want_metadata->name(), XML_TAG_NAME_METADATA )) {
- Inkscape::XML::Node * metadata = xmldoc->createElement( XML_TAG_NAME_METADATA );
- g_return_val_if_fail (metadata != NULL, NULL);
-
- /* attach the metadata node */
- want_metadata->appendChild(metadata);
- Inkscape::GC::release(metadata);
-
- /* move the RDF into it */
- Inkscape::GC::anchor(rdf);
- sp_repr_unparent ( rdf );
- metadata->appendChild(rdf);
- Inkscape::GC::release(rdf);
- }
-
- return rdf;
-}
-
-Inkscape::XML::Node *
-rdf_get_xml_repr( SPDocument * doc, gchar const * name, bool build )
-{
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (doc != NULL, NULL);
- g_return_val_if_fail (doc->rroot != NULL, NULL);
-
- Inkscape::XML::Node * rdf = rdf_get_rdf_root_repr ( doc, build );
- if (!rdf) return NULL;
-
- Inkscape::XML::Node * xml = sp_repr_lookup_name ( rdf, name );
- if (xml == NULL) {
- //printf("missing XML '%s'\n",name);
- if (!build) return NULL;
-
- Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
- g_return_val_if_fail (xmldoc != NULL, NULL);
-
- xml = xmldoc->createElement( name );
- g_return_val_if_fail (xml != NULL, NULL);
-
- xml->setAttribute("rdf:about", "" );
-
- rdf->appendChild(xml);
- Inkscape::GC::release(xml);
- }
-
- return xml;
-}
-
-Inkscape::XML::Node *
-rdf_get_work_repr( SPDocument * doc, gchar const * name, bool build )
-{
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (doc != NULL, NULL);
- g_return_val_if_fail (doc->rroot != NULL, NULL);
-
- Inkscape::XML::Node * work = rdf_get_xml_repr ( doc, XML_TAG_NAME_WORK, build );
- if (!work) return NULL;
-
- Inkscape::XML::Node * item = sp_repr_lookup_name ( work, name, 1 );
- if (item == NULL) {
- //printf("missing XML '%s'\n",name);
- if (!build) return NULL;
-
- Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
- g_return_val_if_fail (xmldoc != NULL, NULL);
-
- item = xmldoc->createElement( name );
- g_return_val_if_fail (item != NULL, NULL);
-
- work->appendChild(item);
- Inkscape::GC::release(item);
- }
-
- return item;
-}
-
-
-
-/**
- * \brief Retrieves a known RDF/Work entity's contents from the document XML by name
- * \return A pointer to the entity's static contents as a string, or NULL if no entity exists
- * \param entity The desired RDF/Work entity
- *
- */
-const gchar *
-rdf_get_work_entity(SPDocument * doc, struct rdf_work_entity_t * entity)
-{
- g_return_val_if_fail (doc != NULL, NULL);
- if ( entity == NULL ) return NULL;
- //printf("want '%s'\n",entity->title);
- bool bIsTitle = !strcmp(entity->name, "title");
-
- Inkscape::XML::Node * item;
- if ( entity->datatype == RDF_XML ) {
- item = rdf_get_xml_repr ( doc, entity->tag, FALSE );
- }
- else {
- item = rdf_get_work_repr( doc, entity->tag, bIsTitle ); // build title if necessary
- }
- if ( item == NULL ) return NULL;
- const gchar * result = rdf_get_repr_text ( item, entity );
- if(!result && bIsTitle && doc->root) { // if RDF title not set
- result = doc->root->title(); // get the document's <title>
- rdf_set_work_entity(doc, entity, result); // and set the RDF
- }
- //printf("found '%s' == '%s'\n", entity->title, result );
- return result;
-}
-
-/**
- * \brief Stores a string into a named RDF/Work entity in the document XML
- * \param entity The desired RDF/Work entity to replace
- * \param string The string to replace the entity contents with
- *
- */
-unsigned int
-rdf_set_work_entity(SPDocument * doc, struct rdf_work_entity_t * entity,
- const gchar * text)
-{
- g_return_val_if_fail ( entity != NULL, 0 );
- if (text == NULL) {
- // FIXME: on a "NULL" text, delete the entity. For now, blank it.
- text="";
- }
-
- /*
- printf("changing '%s' (%s) to '%s'\n",
- entity->title,
- entity->tag,
- text);
- */
-
- Inkscape::XML::Node * item = rdf_get_work_repr( doc, entity->tag, TRUE );
- g_return_val_if_fail ( item != NULL, 0 );
-
- return rdf_set_repr_text ( item, entity, text );
-}
-
-#undef DEBUG_MATCH
-
-static bool
-rdf_match_license(Inkscape::XML::Node const *repr, struct rdf_license_t const *license)
-{
- g_assert ( repr != NULL );
- g_assert ( license != NULL );
-
- bool result=TRUE;
-#ifdef DEBUG_MATCH
- printf("checking against '%s'\n",license->name);
-#endif
-
- int count = 0;
- for (struct rdf_double_t const *details = license->details;
- details->name; details++ ) {
- count++;
- }
- bool * matched = (bool*)calloc(count,sizeof(bool));
-
- for (Inkscape::XML::Node const *current = sp_repr_children(repr);
- current;
- current = sp_repr_next ( current ) ) {
-
- gchar const * attr = current->attribute("rdf:resource");
- if ( attr == NULL ) continue;
-
-#ifdef DEBUG_MATCH
- printf("\texamining '%s' => '%s'\n", current->name(), attr);
-#endif
-
- bool found_match=FALSE;
- for (int i=0; i<count; i++) {
- // skip already matched items
- if (matched[i]) continue;
-
-#ifdef DEBUG_MATCH
- printf("\t\t'%s' vs '%s'\n", current->name(), license->details[i].name);
- printf("\t\t'%s' vs '%s'\n", attr, license->details[i].resource);
-#endif
-
- if (!strcmp( current->name(),
- license->details[i].name ) &&
- !strcmp( attr,
- license->details[i].resource )) {
- matched[i]=TRUE;
- found_match=TRUE;
-#ifdef DEBUG_MATCH
- printf("\t\tgood!\n");
-#endif
- break;
- }
- }
- if (!found_match) {
- // if we checked each known item of the license
- // and didn't find it, we must abort
- result=FALSE;
-#ifdef DEBUG_MATCH
- printf("\t\tno '%s' element matched XML (bong)!\n",license->name);
-#endif
- break;
- }
- }
-#ifdef DEBUG_MATCH
- if (result) printf("\t\tall XML found matching elements!\n");
-#endif
- for (int i=0; result && i<count; i++) {
- // scan looking for an unmatched item
- if (matched[i]==0) {
- result=FALSE;
-#ifdef DEBUG_MATCH
- printf("\t\tnot all '%s' elements used to match (bong)!\n", license->name);
-#endif
- }
- }
-
-#ifdef DEBUG_MATCH
- printf("\t\tall '%s' elements used to match!\n",license->name);
-#endif
-
- free(matched);
-
-#ifdef DEBUG_MATCH
- if (result) printf("matched '%s'\n",license->name);
-#endif
- return result;
-}
-
-/**
- * \brief Attempts to match and retrieve a known RDF/License from the document XML
- * \return A pointer to the static RDF license structure
- *
- */
-struct rdf_license_t *
-rdf_get_license(SPDocument * document)
-{
- Inkscape::XML::Node const *repr = rdf_get_xml_repr ( document, XML_TAG_NAME_LICENSE, FALSE );
- if (repr) {
- for (struct rdf_license_t * license = rdf_licenses;
- license->name; license++ ) {
- if ( rdf_match_license ( repr, license ) ) return license;
- }
- }
-#ifdef DEBUG_MATCH
- else {
- printf("no license XML\n");
- }
-#endif
- return NULL;
-}
-
-/**
- * \brief Stores an RDF/License XML in the document XML
- * \param document Which document to update
- * \param license The desired RDF/License structure to store; NULL drops old license, so can be used for proprietary license.
- *
- */
-void
-rdf_set_license(SPDocument * doc, struct rdf_license_t const * license)
-{
- // drop old license section
- Inkscape::XML::Node * repr = rdf_get_xml_repr ( doc, XML_TAG_NAME_LICENSE, FALSE );
- if (repr) sp_repr_unparent(repr);
-
- if (!license) return;
-
- // build new license section
- repr = rdf_get_xml_repr ( doc, XML_TAG_NAME_LICENSE, TRUE );
- g_assert ( repr );
-
- repr->setAttribute("rdf:about", license->uri );
-
- Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
- g_return_if_fail (xmldoc != NULL);
-
- for (struct rdf_double_t const * detail = license->details;
- detail->name; detail++) {
- Inkscape::XML::Node * child = xmldoc->createElement( detail->name );
- g_assert ( child != NULL );
-
- child->setAttribute("rdf:resource", detail->resource );
- repr->appendChild(child);
- Inkscape::GC::release(child);
- }
-}
-
-struct rdf_entity_default_t {
- gchar const * name;
- gchar const * text;
-};
-struct rdf_entity_default_t rdf_defaults[] = {
- { "format", "image/svg+xml", },
- { "type", "http://purl.org/dc/dcmitype/StillImage", },
- { NULL, NULL, }
-};
-
-void
-rdf_set_defaults ( SPDocument * doc )
-{
- g_assert ( doc != NULL );
-
- // Create metadata node if it doesn't already exist
- if (!sp_item_group_get_child_by_name ((SPGroup *) doc->root, NULL,
- XML_TAG_NAME_METADATA)) {
- // create repr
- Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
- g_return_if_fail (xmldoc != NULL);
- Inkscape::XML::Node * rnew = xmldoc->createElement (XML_TAG_NAME_METADATA);
- // insert into the document
- doc->rroot->addChild(rnew, NULL);
- // clean up
- Inkscape::GC::release(rnew);
- }
-
- /* install defaults */
- for ( struct rdf_entity_default_t * rdf_default = rdf_defaults;
- rdf_default->name;
- rdf_default++) {
- struct rdf_work_entity_t * entity = rdf_find_entity ( rdf_default->name );
- g_assert ( entity != NULL );
-
- if ( rdf_get_work_entity ( doc, entity ) == NULL ) {
- rdf_set_work_entity ( doc, entity, rdf_default->text );
- }
- }
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/rdf.h b/src/dialogs/rdf.h
--- a/src/dialogs/rdf.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/** @file
- * @brief headers for RDF types
- */
-/* Authors:
- * Kees Cook <kees@outflux.net>
- *
- * Copyright (C) 2004 Authors
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-#ifndef _RDF_H_
-#define _RDF_H_
-
-#include <glib.h>
-#include <glibmm/i18n.h>
-#include "document.h"
-
-// yeah, it's not a triple yet...
-/**
- * \brief Holds license name/resource doubles for rdf_license_t entries
- */
-struct rdf_double_t {
- gchar const *name;
- gchar const *resource;
-};
-
-/**
- * \brief Holds license name and RDF information
- */
-struct rdf_license_t {
- gchar const *name; /* localized name of this license */
- gchar const *uri; /* URL for the RDF/Work/license element */
- struct rdf_double_t *details; /* the license details */
-// gchar const *fragment; /* XML contents for the RDF/License tag */
-};
-
-extern rdf_license_t rdf_licenses [];
-
-/**
- * \brief Describes how a given RDF entity is stored in XML
- */
-enum RDFType {
- RDF_CONTENT, // direct between-XML-tags content
- RDF_AGENT, // requires the "Agent" hierarchy before doing content
- RDF_RESOURCE, // stored in "rdf:resource" element
- RDF_XML, // literal XML
- RDF_BAG // rdf:Bag resources
-};
-
-/**
- * \brief Describes how a given RDF entity should be edited
- */
-enum RDF_Format {
- RDF_FORMAT_LINE, // uses single line data (GtkEntry)
- RDF_FORMAT_MULTILINE, // uses multiline data (GtkTextView)
- RDF_FORMAT_SPECIAL // uses some other edit methods
-};
-
-enum RDF_Editable {
- RDF_EDIT_GENERIC, // editable via generic widgets
- RDF_EDIT_SPECIAL, // special widgets are needed
- RDF_EDIT_HARDCODED // isn't editable
-};
-
-/**
- * \brief Holds known RDF/Work tags
- */
-struct rdf_work_entity_t {
- char const *name; /* unique name of this entity for internal reference */
- gchar const *title; /* localized title of this entity for data entry */
- gchar const *tag; /* namespace tag for the RDF/Work element */
- RDFType datatype; /* how to extract/inject the RDF information */
- gchar const *tip; /* tool tip to explain the meaning of the entity */
- RDF_Format format; /* in what format is this data edited? */
- RDF_Editable editable;/* in what way is the data editable? */
-};
-
-extern rdf_work_entity_t rdf_work_entities [];
-
-/**
- * \brief Generic collection of RDF information for the RDF debug function
- */
-struct rdf_t {
- gchar* work_title;
- gchar* work_date;
- gchar* work_creator;
- gchar* work_owner;
- gchar* work_publisher;
- gchar* work_type;
- gchar* work_source;
- gchar* work_subject;
- gchar* work_description;
- struct rdf_license_t* license;
-};
-
-struct rdf_work_entity_t * rdf_find_entity(gchar const * name);
-
-const gchar * rdf_get_work_entity(SPDocument * doc,
- struct rdf_work_entity_t * entity);
-unsigned int rdf_set_work_entity(SPDocument * doc,
- struct rdf_work_entity_t * entity,
- const gchar * text);
-
-struct rdf_license_t * rdf_get_license(SPDocument * doc);
-void rdf_set_license(SPDocument * doc,
- struct rdf_license_t const * license);
-
-void rdf_set_defaults ( SPDocument * doc );
-
-#endif // _RDF_H_
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/sp-attribute-widget.cpp b/src/dialogs/sp-attribute-widget.cpp
+++ /dev/null
@@ -1,790 +0,0 @@
-/** @file
- * @brief Widget that listens and modifies repr attributes
- */
-/* Authors:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 2001 Ximian, Inc.
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <gtk/gtktable.h>
-#include <gtk/gtklabel.h>
-#include "xml/repr.h"
-#include "macros.h"
-#include "document.h"
-#include "sp-object.h"
-#include <glibmm/i18n.h>
-
-#include <sigc++/functors/ptr_fun.h>
-#include <sigc++/adaptors/bind.h>
-
-#include "sp-attribute-widget.h"
-
-static void sp_attribute_widget_class_init (SPAttributeWidgetClass *klass);
-static void sp_attribute_widget_init (SPAttributeWidget *widget);
-static void sp_attribute_widget_destroy (GtkObject *object);
-
-static void sp_attribute_widget_changed (GtkEditable *editable);
-
-static void sp_attribute_widget_object_modified ( SPObject *object,
- guint flags,
- SPAttributeWidget *spaw );
-static void sp_attribute_widget_object_release ( SPObject *object,
- SPAttributeWidget *spaw );
-
-static GtkEntryClass *parent_class;
-
-
-
-
-GType sp_attribute_widget_get_type(void)
-{
- static GtkType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPAttributeWidgetClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_attribute_widget_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(SPAttributeWidget),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_attribute_widget_init,
- 0 // value_table
- };
- type = g_type_register_static(GTK_TYPE_ENTRY, "SPAttributeWidget", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-} // end of sp_attribute_widget_get_type()
-
-
-
-static void
-sp_attribute_widget_class_init (SPAttributeWidgetClass *klass)
-{
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
- GtkEditableClass *editable_class;
-
- object_class = GTK_OBJECT_CLASS (klass);
- widget_class = GTK_WIDGET_CLASS (klass);
- editable_class = GTK_EDITABLE_CLASS (klass);
-
- parent_class = (GtkEntryClass*)gtk_type_class (GTK_TYPE_ENTRY);
-
- object_class->destroy = sp_attribute_widget_destroy;
-
- editable_class->changed = sp_attribute_widget_changed;
-
-} // end of sp_attribute_widget_class_init()
-
-
-
-static void
-sp_attribute_widget_init (SPAttributeWidget *spaw)
-{
- spaw->blocked = FALSE;
- spaw->hasobj = FALSE;
-
- spaw->src.object = NULL;
-
- spaw->attribute = NULL;
-
- new (&spaw->modified_connection) sigc::connection();
- new (&spaw->release_connection) sigc::connection();
-}
-
-
-
-static void
-sp_attribute_widget_destroy (GtkObject *object)
-{
-
- SPAttributeWidget *spaw;
-
- spaw = SP_ATTRIBUTE_WIDGET (object);
-
- if (spaw->attribute) {
- g_free (spaw->attribute);
- spaw->attribute = NULL;
- }
-
-
- if (spaw->hasobj) {
-
- if (spaw->src.object) {
- spaw->modified_connection.disconnect();
- spaw->release_connection.disconnect();
- spaw->src.object = NULL;
- }
- } else {
-
- if (spaw->src.repr) {
- spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
- }
- } // end of if()
-
- spaw->modified_connection.~connection();
- spaw->release_connection.~connection();
-
- ((GtkObjectClass *) parent_class)->destroy (object);
-
-}
-
-
-
-static void
-sp_attribute_widget_changed (GtkEditable *editable)
-{
-
- SPAttributeWidget *spaw;
-
- spaw = SP_ATTRIBUTE_WIDGET (editable);
-
- if (!spaw->blocked) {
-
- const gchar *text;
- spaw->blocked = TRUE;
- text = gtk_entry_get_text (GTK_ENTRY (spaw));
- if (!*text)
- text = NULL;
-
- if (spaw->hasobj && spaw->src.object) {
-
- SP_OBJECT_REPR (spaw->src.object)->setAttribute(spaw->attribute, text, false);
- sp_document_done (SP_OBJECT_DOCUMENT (spaw->src.object), SP_VERB_NONE,
- _("Set attribute"));
-
- } else if (spaw->src.repr) {
-
- spaw->src.repr->setAttribute(spaw->attribute, text, false);
- /* TODO: Warning! Undo will not be flushed in given case */
- }
- spaw->blocked = FALSE;
- }
-
-} // end of sp_attribute_widget_changed()
-
-
-
-GtkWidget *
-sp_attribute_widget_new ( SPObject *object, const gchar *attribute )
-{
- SPAttributeWidget *spaw;
-
- g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL);
- g_return_val_if_fail (!object || attribute, NULL);
-
- spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET);
-
- sp_attribute_widget_set_object (spaw, object, attribute);
-
- return GTK_WIDGET (spaw);
-
-} // end of sp_attribute_widget_new()
-
-
-
-GtkWidget *
-sp_attribute_widget_new_repr ( Inkscape::XML::Node *repr, const gchar *attribute )
-{
- SPAttributeWidget *spaw;
-
- spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET);
-
- sp_attribute_widget_set_repr (spaw, repr, attribute);
-
- return GTK_WIDGET (spaw);
-}
-
-
-
-void
-sp_attribute_widget_set_object ( SPAttributeWidget *spaw,
- SPObject *object,
- const gchar *attribute )
-{
-
- g_return_if_fail (spaw != NULL);
- g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw));
- g_return_if_fail (!object || SP_IS_OBJECT (object));
- g_return_if_fail (!object || attribute);
- g_return_if_fail (attribute != NULL);
-
- if (spaw->attribute) {
- g_free (spaw->attribute);
- spaw->attribute = NULL;
- }
-
- if (spaw->hasobj) {
-
- if (spaw->src.object) {
- spaw->modified_connection.disconnect();
- spaw->release_connection.disconnect();
- spaw->src.object = NULL;
- }
- } else {
-
- if (spaw->src.repr) {
- spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
- }
- }
-
- spaw->hasobj = TRUE;
-
- if (object) {
- const gchar *val;
-
- spaw->blocked = TRUE;
- spaw->src.object = object;
-
- spaw->modified_connection = object->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_attribute_widget_object_modified), spaw));
- spaw->release_connection = object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_attribute_widget_object_release), spaw));
-
- spaw->attribute = g_strdup (attribute);
-
- val = SP_OBJECT_REPR (object)->attribute(attribute);
- gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) "");
- spaw->blocked = FALSE;
- }
-
- gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.object != NULL));
-
-} // end of sp_attribute_widget_set_object()
-
-
-
-void
-sp_attribute_widget_set_repr ( SPAttributeWidget *spaw,
- Inkscape::XML::Node *repr,
- const gchar *attribute )
-{
-
- g_return_if_fail (spaw != NULL);
- g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw));
- g_return_if_fail (attribute != NULL);
-
- if (spaw->attribute) {
- g_free (spaw->attribute);
- spaw->attribute = NULL;
- }
-
- if (spaw->hasobj) {
-
- if (spaw->src.object) {
- spaw->modified_connection.disconnect();
- spaw->release_connection.disconnect();
- spaw->src.object = NULL;
- }
- } else {
-
- if (spaw->src.repr) {
- spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
- }
- }
-
- spaw->hasobj = FALSE;
-
- if (repr) {
- const gchar *val;
-
- spaw->blocked = TRUE;
- spaw->src.repr = Inkscape::GC::anchor(repr);
- spaw->attribute = g_strdup (attribute);
-
- val = repr->attribute(attribute);
- gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) "");
- spaw->blocked = FALSE;
- }
-
- gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.repr != NULL));
-
-} // end of sp_attribute_widget_set_repr()
-
-
-
-static void
-sp_attribute_widget_object_modified ( SPObject */*object*/,
- guint flags,
- SPAttributeWidget *spaw )
-{
-
- if (flags && SP_OBJECT_MODIFIED_FLAG) {
-
- const gchar *val, *text;
- val = SP_OBJECT_REPR (spaw->src.object)->attribute(spaw->attribute);
- text = gtk_entry_get_text (GTK_ENTRY (spaw));
-
- if (val || text) {
-
- if (!val || !text || strcmp (val, text)) {
- /* We are different */
- spaw->blocked = TRUE;
- gtk_entry_set_text ( GTK_ENTRY (spaw),
- val ? val : (const gchar *) "");
- spaw->blocked = FALSE;
- } // end of if()
-
- } // end of if()
-
- } //end of if()
-
-} // end of sp_attribute_widget_object_modified()
-
-
-
-static void
-sp_attribute_widget_object_release ( SPObject */*object*/,
- SPAttributeWidget *spaw )
-{
- sp_attribute_widget_set_object (spaw, NULL, NULL);
-}
-
-
-
-/* SPAttributeTable */
-
-static void sp_attribute_table_class_init (SPAttributeTableClass *klass);
-static void sp_attribute_table_init (SPAttributeTable *widget);
-static void sp_attribute_table_destroy (GtkObject *object);
-
-static void sp_attribute_table_object_modified (SPObject *object, guint flags, SPAttributeTable *spaw);
-static void sp_attribute_table_object_release (SPObject *object, SPAttributeTable *spaw);
-static void sp_attribute_table_entry_changed (GtkEditable *editable, SPAttributeTable *spat);
-
-static GtkVBoxClass *table_parent_class;
-
-
-
-
-GType sp_attribute_table_get_type(void)
-{
- static GtkType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof(SPAttributeTableClass),
- 0, // base_init
- 0, // base_finalize
- (GClassInitFunc)sp_attribute_table_class_init,
- 0, // class_finalize
- 0, // class_data
- sizeof(SPAttributeTable),
- 0, // n_preallocs
- (GInstanceInitFunc)sp_attribute_table_init,
- 0 // value_table
- };
- type = g_type_register_static(GTK_TYPE_VBOX, "SPAttributeTable", &info, static_cast<GTypeFlags>(0));
- }
- return type;
-} // end of sp_attribute_table_get_type()
-
-
-
-static void
-sp_attribute_table_class_init (SPAttributeTableClass *klass)
-{
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
-
- object_class = GTK_OBJECT_CLASS (klass);
- widget_class = GTK_WIDGET_CLASS (klass);
-
- table_parent_class = (GtkVBoxClass*)gtk_type_class (GTK_TYPE_VBOX);
-
- object_class->destroy = sp_attribute_table_destroy;
-
-} // end of sp_attribute_table_class_init()
-
-
-
-static void
-sp_attribute_table_init ( SPAttributeTable *spat )
-{
- spat->blocked = FALSE;
- spat->hasobj = FALSE;
- spat->table = NULL;
- spat->src.object = NULL;
- spat->num_attr = 0;
- spat->attributes = NULL;
- spat->entries = NULL;
-
- new (&spat->modified_connection) sigc::connection();
- new (&spat->release_connection) sigc::connection();
-}
-
-static void
-sp_attribute_table_destroy ( GtkObject *object )
-{
- SPAttributeTable *spat;
-
- spat = SP_ATTRIBUTE_TABLE (object);
-
- if (spat->attributes) {
- gint i;
- for (i = 0; i < spat->num_attr; i++) {
- g_free (spat->attributes[i]);
- }
- g_free (spat->attributes);
- spat->attributes = NULL;
- }
-
- if (spat->hasobj) {
-
- if (spat->src.object) {
- spat->modified_connection.disconnect();
- spat->release_connection.disconnect();
- spat->src.object = NULL;
- }
- } else {
- if (spat->src.repr) {
- spat->src.repr = Inkscape::GC::release(spat->src.repr);
- }
- } // end of if()
-
- spat->modified_connection.~connection();
- spat->release_connection.~connection();
-
- if (spat->entries) {
- g_free (spat->entries);
- spat->entries = NULL;
- }
-
- spat->table = NULL;
-
- if (((GtkObjectClass *) table_parent_class)->destroy) {
- (* ((GtkObjectClass *) table_parent_class)->destroy) (object);
- }
-
-} // end of sp_attribute_table_destroy()
-
-
-GtkWidget *
-sp_attribute_table_new ( SPObject *object,
- gint num_attr,
- const gchar **labels,
- const gchar **attributes )
-{
- SPAttributeTable *spat;
-
- g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL);
- g_return_val_if_fail (!object || (num_attr > 0), NULL);
- g_return_val_if_fail (!num_attr || (labels && attributes), NULL);
-
- spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE);
-
- sp_attribute_table_set_object (spat, object, num_attr, labels, attributes);
-
- return GTK_WIDGET (spat);
-
-} // end of sp_attribute_table_new()
-
-
-
-GtkWidget *
-sp_attribute_table_new_repr ( Inkscape::XML::Node *repr,
- gint num_attr,
- const gchar **labels,
- const gchar **attributes )
-{
- SPAttributeTable *spat;
-
- g_return_val_if_fail (!num_attr || (labels && attributes), NULL);
-
- spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE);
-
- sp_attribute_table_set_repr (spat, repr, num_attr, labels, attributes);
-
- return GTK_WIDGET (spat);
-
-} // end of sp_attribute_table_new_repr()
-
-
-
-#define XPAD 4
-#define YPAD 0
-
-void
-sp_attribute_table_set_object ( SPAttributeTable *spat,
- SPObject *object,
- gint num_attr,
- const gchar **labels,
- const gchar **attributes )
-{
-
- g_return_if_fail (spat != NULL);
- g_return_if_fail (SP_IS_ATTRIBUTE_TABLE (spat));
- g_return_if_fail (!object || SP_IS_OBJECT (object));
- g_return_if_fail (!object || (num_attr > 0));
- g_return_if_fail (!num_attr || (labels && attributes));
-
- if (spat->table) {
- gtk_widget_destroy (spat->table);
- spat->table = NULL;
- }
-
- if (spat->attributes) {
- gint i;
- for (i = 0; i < spat->num_attr; i++) {
- g_free (spat->attributes[i]);
- }
- g_free (spat->attributes);
- spat->attributes = NULL;
- }
-
- if (spat->entries) {
- g_free (spat->entries);
- spat->entries = NULL;
- }
-
- if (spat->hasobj) {
- if (spat->src.object) {
- spat->modified_connection.disconnect();
- spat->release_connection.disconnect();
- spat->src.object = NULL;
- }
- } else {
- if (spat->src.repr) {
- spat->src.repr = Inkscape::GC::release(spat->src.repr);
- }
- }
-
- spat->hasobj = TRUE;
-
- if (object) {
- gint i;
-
- spat->blocked = TRUE;
-
- /* Set up object */
- spat->src.object = object;
- spat->num_attr = num_attr;
-
- spat->modified_connection = object->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_attribute_table_object_modified), spat));
- spat->release_connection = object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_attribute_table_object_release), spat));
-
- /* Create table */
- spat->table = gtk_table_new (num_attr, 2, FALSE);
- gtk_container_add (GTK_CONTAINER (spat), spat->table);
- /* Arrays */
- spat->attributes = g_new0 (gchar *, num_attr);
- spat->entries = g_new0 (GtkWidget *, num_attr);
- /* Fill rows */
- for (i = 0; i < num_attr; i++) {
- GtkWidget *w;
- const gchar *val;
-
- spat->attributes[i] = g_strdup (attributes[i]);
- w = gtk_label_new (_(labels[i]));
- gtk_widget_show (w);
- gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
- gtk_table_attach ( GTK_TABLE (spat->table), w, 0, 1, i, i + 1,
- GTK_FILL,
- (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
- XPAD, YPAD );
- w = gtk_entry_new ();
- gtk_widget_show (w);
- val = SP_OBJECT_REPR (object)->attribute(attributes[i]);
- gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) "");
- gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1,
- (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
- XPAD, YPAD );
- spat->entries[i] = w;
- g_signal_connect ( G_OBJECT (w), "changed",
- G_CALLBACK (sp_attribute_table_entry_changed),
- spat );
- }
- /* Show table */
- gtk_widget_show (spat->table);
-
- spat->blocked = FALSE;
- }
-
- gtk_widget_set_sensitive ( GTK_WIDGET (spat),
- (spat->src.object != NULL) );
-
-} // end of sp_attribute_table_set_object()
-
-
-
-void
-sp_attribute_table_set_repr ( SPAttributeTable *spat,
- Inkscape::XML::Node *repr,
- gint num_attr,
- const gchar **labels,
- const gchar **attributes )
-{
- g_return_if_fail (spat != NULL);
- g_return_if_fail (SP_IS_ATTRIBUTE_TABLE (spat));
- g_return_if_fail (!num_attr || (labels && attributes));
-
- if (spat->table) {
- gtk_widget_destroy (spat->table);
- spat->table = NULL;
- }
-
- if (spat->attributes) {
- gint i;
- for (i = 0; i < spat->num_attr; i++) {
- g_free (spat->attributes[i]);
- }
- g_free (spat->attributes);
- spat->attributes = NULL;
- }
-
- if (spat->entries) {
- g_free (spat->entries);
- spat->entries = NULL;
- }
-
- if (spat->hasobj) {
- if (spat->src.object) {
- spat->modified_connection.disconnect();
- spat->release_connection.disconnect();
- spat->src.object = NULL;
- }
- } else {
- if (spat->src.repr) {
- spat->src.repr = Inkscape::GC::release(spat->src.repr);
- }
- }
-
- spat->hasobj = FALSE;
-
- if (repr) {
- gint i;
-
- spat->blocked = TRUE;
-
- /* Set up repr */
- spat->src.repr = Inkscape::GC::anchor(repr);
- spat->num_attr = num_attr;
- /* Create table */
- spat->table = gtk_table_new (num_attr, 2, FALSE);
- gtk_container_add (GTK_CONTAINER (spat), spat->table);
- /* Arrays */
- spat->attributes = g_new0 (gchar *, num_attr);
- spat->entries = g_new0 (GtkWidget *, num_attr);
-
- /* Fill rows */
- for (i = 0; i < num_attr; i++) {
- GtkWidget *w;
- const gchar *val;
-
- spat->attributes[i] = g_strdup (attributes[i]);
- w = gtk_label_new (labels[i]);
- gtk_widget_show (w);
- gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
- gtk_table_attach ( GTK_TABLE (spat->table), w, 0, 1, i, i + 1,
- GTK_FILL,
- (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
- XPAD, YPAD );
- w = gtk_entry_new ();
- gtk_widget_show (w);
- val = repr->attribute(attributes[i]);
- gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) "");
- gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1,
- (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
- XPAD, YPAD );
- spat->entries[i] = w;
- g_signal_connect ( G_OBJECT (w), "changed",
- G_CALLBACK (sp_attribute_table_entry_changed),
- spat );
- }
- /* Show table */
- gtk_widget_show (spat->table);
-
- spat->blocked = FALSE;
- }
-
- gtk_widget_set_sensitive (GTK_WIDGET (spat), (spat->src.repr != NULL));
-
-} // end of sp_attribute_table_set_repr()
-
-
-
-static void
-sp_attribute_table_object_modified ( SPObject */*object*/,
- guint flags,
- SPAttributeTable *spat )
-{
- if (flags && SP_OBJECT_MODIFIED_FLAG)
- {
- gint i;
- for (i = 0; i < spat->num_attr; i++) {
- const gchar *val, *text;
- val = SP_OBJECT_REPR (spat->src.object)->attribute(spat->attributes[i]);
- text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i]));
- if (val || text) {
- if (!val || !text || strcmp (val, text)) {
- /* We are different */
- spat->blocked = TRUE;
- gtk_entry_set_text ( GTK_ENTRY (spat->entries[i]),
- val ? val : (const gchar *) "");
- spat->blocked = FALSE;
- }
- }
- }
- } // end of if()
-
-} // end of sp_attribute_table_object_modified()
-
-
-
-static void
-sp_attribute_table_object_release (SPObject */*object*/, SPAttributeTable *spat)
-{
- sp_attribute_table_set_object (spat, NULL, 0, NULL, NULL);
-}
-
-
-
-static void
-sp_attribute_table_entry_changed ( GtkEditable *editable,
- SPAttributeTable *spat )
-{
- if (!spat->blocked)
- {
- gint i;
- for (i = 0; i < spat->num_attr; i++) {
-
- if (GTK_WIDGET (editable) == spat->entries[i]) {
- const gchar *text;
- spat->blocked = TRUE;
- text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i]));
-
- if (!*text)
- text = NULL;
-
- if (spat->hasobj && spat->src.object) {
- SP_OBJECT_REPR (spat->src.object)->setAttribute(spat->attributes[i], text, false);
- sp_document_done (SP_OBJECT_DOCUMENT (spat->src.object), SP_VERB_NONE,
- _("Set attribute"));
-
- } else if (spat->src.repr) {
-
- spat->src.repr->setAttribute(spat->attributes[i], text, false);
- /* TODO: Warning! Undo will not be flushed in given case */
- }
- spat->blocked = FALSE;
- return;
- }
- }
- g_warning ("file %s: line %d: Entry signalled change, but there is no such entry", __FILE__, __LINE__);
- } // end of if()
-
-} // end of sp_attribute_table_entry_changed()
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/sp-attribute-widget.h b/src/dialogs/sp-attribute-widget.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/** @file
- * @brief Widget that listens and modifies repr attributes
- */
-/* Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2002 authors
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Licensed under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_DIALOGS_SP_ATTRIBUTE_WIDGET_H
-#define SEEN_DIALOGS_SP_ATTRIBUTE_WIDGET_H
-
-#include <glib.h>
-#include <sigc++/connection.h>
-
-#define SP_TYPE_ATTRIBUTE_WIDGET (sp_attribute_widget_get_type ())
-#define SP_ATTRIBUTE_WIDGET(obj) (GTK_CHECK_CAST ((obj), SP_TYPE_ATTRIBUTE_WIDGET, SPAttributeWidget))
-#define SP_ATTRIBUTE_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), SP_TYPE_ATTRIBUTE_WIDGET, SPAttributeWidgetClass))
-#define SP_IS_ATTRIBUTE_WIDGET(obj) (GTK_CHECK_TYPE ((obj), SP_TYPE_ATTRIBUTE_WIDGET))
-#define SP_IS_ATTRIBUTE_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), SP_TYPE_ATTRIBUTE_WIDGET))
-
-#define SP_TYPE_ATTRIBUTE_TABLE (sp_attribute_table_get_type ())
-#define SP_ATTRIBUTE_TABLE(obj) (GTK_CHECK_CAST ((obj), SP_TYPE_ATTRIBUTE_TABLE, SPAttributeTable))
-#define SP_ATTRIBUTE_TABLE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), SP_TYPE_ATTRIBUTE_TABLE, SPAttributeTableClass))
-#define SP_IS_ATTRIBUTE_TABLE(obj) (GTK_CHECK_TYPE ((obj), SP_TYPE_ATTRIBUTE_TABLE))
-#define SP_IS_ATTRIBUTE_TABLE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), SP_TYPE_ATTRIBUTE_TABLE))
-
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-
-struct SPAttributeWidget;
-struct SPAttributeWidgetClass;
-
-struct SPAttributeTable;
-struct SPAttributeTableClass;
-
-#include <gtk/gtkentry.h>
-#include <gtk/gtkvbox.h>
-
-#include <forward.h>
-
-struct SPAttributeWidget {
- GtkEntry entry;
- guint blocked : 1;
- guint hasobj : 1;
- union {
- SPObject *object;
- Inkscape::XML::Node *repr;
- } src;
- gchar *attribute;
-
- sigc::connection modified_connection;
- sigc::connection release_connection;
-};
-
-struct SPAttributeWidgetClass {
- GtkEntryClass entry_class;
-};
-
-GtkType sp_attribute_widget_get_type (void);
-
-GtkWidget *sp_attribute_widget_new (SPObject *object, const gchar *attribute);
-GtkWidget *sp_attribute_widget_new_repr (Inkscape::XML::Node *repr, const gchar *attribute);
-
-void sp_attribute_widget_set_object ( SPAttributeWidget *spw,
- SPObject *object,
- const gchar *attribute );
-void sp_attribute_widget_set_repr ( SPAttributeWidget *spw,
- Inkscape::XML::Node *repr,
- const gchar *attribute );
-
-/* SPAttributeTable */
-
-struct SPAttributeTable {
- GtkVBox vbox;
- guint blocked : 1;
- guint hasobj : 1;
- GtkWidget *table;
- union {
- SPObject *object;
- Inkscape::XML::Node *repr;
- } src;
- gint num_attr;
- gchar **attributes;
- GtkWidget **entries;
-
- sigc::connection modified_connection;
- sigc::connection release_connection;
-};
-
-struct SPAttributeTableClass {
- GtkEntryClass entry_class;
-};
-
-GtkType sp_attribute_table_get_type (void);
-
-GtkWidget *sp_attribute_table_new ( SPObject *object, gint num_attr,
- const gchar **labels,
- const gchar **attributes );
-GtkWidget *sp_attribute_table_new_repr ( Inkscape::XML::Node *repr, gint num_attr,
- const gchar **labels,
- const gchar **attributes );
-void sp_attribute_table_set_object ( SPAttributeTable *spw,
- SPObject *object, gint num_attr,
- const gchar **labels,
- const gchar **attrs );
-void sp_attribute_table_set_repr ( SPAttributeTable *spw,
- Inkscape::XML::Node *repr, gint num_attr,
- const gchar **labels,
- const gchar **attrs );
-
-#endif
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/stroke-style.cpp b/src/dialogs/stroke-style.cpp
+++ /dev/null
@@ -1,1838 +0,0 @@
-/** @file
- * @brief Stroke style dialog
- */
-/* Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Bryce Harrington <brycehar@bryceharrington.org>
- * bulia byak <buliabyak@users.sf.net>
- * Maximilian Albert <maximilian.albert@gmail.com>
- * Josh Andler <scislac@users.sf.net>
- *
- * Copyright (C) 2001-2005 authors
- * Copyright (C) 2001 Ximian, Inc.
- * Copyright (C) 2004 John Cliff
- * Copyright (C) 2008 Maximilian Albert (gtkmm-ification)
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#define noSP_SS_VERBOSE
-
-#include <glib/gmem.h>
-#include <gtk/gtk.h>
-#include <glibmm/i18n.h>
-
-#include "desktop-handles.h"
-#include "desktop-style.h"
-#include "dialogs/dialog-events.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
-#include "document-private.h"
-#include "gradient-chemistry.h"
-#include "helper/stock-items.h"
-#include "helper/unit-menu.h"
-#include "helper/units.h"
-#include "inkscape.h"
-#include "io/sys.h"
-#include "marker.h"
-#include "path-prefix.h"
-#include "selection.h"
-#include "sp-linear-gradient.h"
-#include "sp-namedview.h"
-#include "sp-pattern.h"
-#include "sp-radial-gradient.h"
-#include "sp-rect.h"
-#include "sp-text.h"
-#include "style.h"
-#include "svg/css-ostringstream.h"
-#include "ui/cache/svg_preview_cache.h"
-#include "ui/icon-names.h"
-#include "widgets/dash-selector.h"
-#include "widgets/icon.h"
-#include "widgets/paint-selector.h"
-#include "widgets/sp-widget.h"
-#include "widgets/spw-utilities.h"
-#include "xml/repr.h"
-
-#include "dialogs/stroke-style.h"
-
-
-/* Paint */
-
-static void sp_stroke_style_paint_selection_modified (SPWidget *spw, Inkscape::Selection *selection, guint flags, SPPaintSelector *psel);
-static void sp_stroke_style_paint_selection_changed (SPWidget *spw, Inkscape::Selection *selection, SPPaintSelector *psel);
-static void sp_stroke_style_paint_update(SPWidget *spw);
-
-static void sp_stroke_style_paint_mode_changed(SPPaintSelector *psel, SPPaintSelectorMode mode, SPWidget *spw);
-static void sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw);
-static void sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw);
-
-static void sp_stroke_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw );
-static void sp_stroke_style_widget_transientize_callback(Inkscape::Application *inkscape,
- SPDesktop *desktop,
- SPWidget *spw );
-
-/** Marker selection option menus */
-static Gtk::OptionMenu * marker_start_menu = NULL;
-static Gtk::OptionMenu * marker_mid_menu = NULL;
-static Gtk::OptionMenu * marker_end_menu = NULL;
-
-sigc::connection marker_start_menu_connection;
-sigc::connection marker_mid_menu_connection;
-sigc::connection marker_end_menu_connection;
-
-static SPObject *ink_extract_marker_name(gchar const *n, SPDocument *doc);
-static void ink_markers_menu_update(Gtk::Container* spw, SPMarkerLoc const which);
-
-static Inkscape::UI::Cache::SvgPreview svg_preview_cache;
-
-/**
- * Create the stroke style widget, and hook up all the signals.
- */
-GtkWidget *
-sp_stroke_style_paint_widget_new(void)
-{
- GtkWidget *spw, *psel;
-
- spw = sp_widget_new_global(INKSCAPE);
-
- psel = sp_paint_selector_new(false); // without fillrule selector
- gtk_widget_show(psel);
- gtk_container_add(GTK_CONTAINER(spw), psel);
- gtk_object_set_data(GTK_OBJECT(spw), "paint-selector", psel);
-
- gtk_signal_connect(GTK_OBJECT(spw), "modify_selection",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_selection_modified),
- psel);
- gtk_signal_connect(GTK_OBJECT(spw), "change_selection",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_selection_changed),
- psel);
-
- g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_stroke_style_widget_change_subselection), spw);
-
- g_signal_connect (G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK (sp_stroke_style_widget_transientize_callback), spw );
-
- gtk_signal_connect(GTK_OBJECT(psel), "mode_changed",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_mode_changed),
- spw);
- gtk_signal_connect(GTK_OBJECT(psel), "dragged",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_dragged),
- spw);
- gtk_signal_connect(GTK_OBJECT(psel), "changed",
- GTK_SIGNAL_FUNC(sp_stroke_style_paint_changed),
- spw);
-
- sp_stroke_style_paint_update (SP_WIDGET(spw));
- return spw;
-}
-
-/**
- * On signal modified, invokes an update of the stroke style paint object.
- */
-static void
-sp_stroke_style_paint_selection_modified( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- guint flags,
- SPPaintSelector */*psel*/ )
-{
- if (flags & ( SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG |
- SP_OBJECT_STYLE_MODIFIED_FLAG) ) {
- sp_stroke_style_paint_update(spw);
- }
-}
-
-
-/**
- * On signal selection changed, invokes an update of the stroke style paint object.
- */
-static void
-sp_stroke_style_paint_selection_changed( SPWidget *spw,
- Inkscape::Selection */*selection*/,
- SPPaintSelector */*psel*/ )
-{
- sp_stroke_style_paint_update (spw);
-}
-
-
-/**
- * On signal change subselection, invoke an update of the stroke style widget.
- */
-static void
-sp_stroke_style_widget_change_subselection( Inkscape::Application */*inkscape*/,
- SPDesktop */*desktop*/,
- SPWidget *spw )
-{
- sp_stroke_style_paint_update (spw);
-}
-
-/**
- * Gets the active stroke style property, then sets the appropriate color, alpha, gradient,
- * pattern, etc. for the paint-selector.
- */
-static void
-sp_stroke_style_paint_update (SPWidget *spw)
-{
- if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
- return;
- }
-
- gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(TRUE));
-
- SPPaintSelector *psel = SP_PAINT_SELECTOR(gtk_object_get_data(GTK_OBJECT(spw), "paint-selector"));
-
- // create temporary style
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- // query into it
- int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKE);
-
- switch (result) {
- case QUERY_STYLE_NOTHING:
- {
- /* No paint at all */
- sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_EMPTY);
- break;
- }
-
- case QUERY_STYLE_SINGLE:
- case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector
- case QUERY_STYLE_MULTIPLE_SAME:
- {
- SPPaintSelectorMode pselmode = sp_style_determine_paint_selector_mode (query, false);
- sp_paint_selector_set_mode (psel, pselmode);
-
- if (query->stroke.set && query->stroke.isPaintserver()) {
-
- SPPaintServer *server = SP_STYLE_STROKE_SERVER (query);
-
- if (SP_IS_LINEARGRADIENT (server)) {
- SPGradient *vector = sp_gradient_get_vector (SP_GRADIENT (server), FALSE);
- sp_paint_selector_set_gradient_linear (psel, vector);
-
- SPLinearGradient *lg = SP_LINEARGRADIENT (server);
- sp_paint_selector_set_gradient_properties (psel,
- SP_GRADIENT_UNITS (lg),
- SP_GRADIENT_SPREAD (lg));
- } else if (SP_IS_RADIALGRADIENT (server)) {
- SPGradient *vector = sp_gradient_get_vector (SP_GRADIENT (server), FALSE);
- sp_paint_selector_set_gradient_radial (psel, vector);
-
- SPRadialGradient *rg = SP_RADIALGRADIENT (server);
- sp_paint_selector_set_gradient_properties (psel,
- SP_GRADIENT_UNITS (rg),
- SP_GRADIENT_SPREAD (rg));
- } else if (SP_IS_PATTERN (server)) {
- SPPattern *pat = pattern_getroot (SP_PATTERN (server));
- sp_update_pattern_list (psel, pat);
- }
- } else if (query->stroke.set && query->stroke.isColor()) {
- sp_paint_selector_set_color_alpha (psel, &query->stroke.value.color, SP_SCALE24_TO_FLOAT (query->stroke_opacity.value));
-
- }
- break;
- }
-
- case QUERY_STYLE_MULTIPLE_DIFFERENT:
- {
- sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_MULTIPLE);
- break;
- }
- }
-
- sp_style_unref(query);
-
- gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(FALSE));
-}
-
-/**
- * When the mode is changed, invoke a regular changed handler.
- */
-static void
-sp_stroke_style_paint_mode_changed( SPPaintSelector *psel,
- SPPaintSelectorMode /*mode*/,
- SPWidget *spw )
-{
- if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
- return;
- }
-
- /* TODO: Does this work?
- * Not really, here we have to get old color back from object
- * Instead of relying on paint widget having meaningful colors set
- */
- sp_stroke_style_paint_changed(psel, spw);
-}
-
-static gchar const *const undo_label_1 = "stroke:flatcolor:1";
-static gchar const *const undo_label_2 = "stroke:flatcolor:2";
-static gchar const *undo_label = undo_label_1;
-
-/**
- * When a drag callback occurs on a paint selector object, if it is a RGB or CMYK
- * color mode, then set the stroke opacity to psel's flat color.
- */
-static void
-sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw)
-{
- if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
- return;
- }
-
- switch (psel->mode) {
- case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
- case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
- {
- sp_paint_selector_set_flat_color (psel, SP_ACTIVE_DESKTOP, "stroke", "stroke-opacity");
- sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set stroke color"));
- break;
- }
-
- default:
- g_warning( "file %s: line %d: Paint %d should not emit 'dragged'",
- __FILE__, __LINE__, psel->mode);
- break;
- }
-}
-
-/**
- * When the stroke style's paint settings change, this handler updates the
- * repr's stroke css style and applies the style to relevant drawing items.
- */
-static void
-sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
-{
- if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
- return;
- }
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
-
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- SPDocument *document = sp_desktop_document (desktop);
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
-
- GSList const *items = selection->itemList();
-
- switch (psel->mode) {
- case SP_PAINT_SELECTOR_MODE_EMPTY:
- // This should not happen.
- g_warning ( "file %s: line %d: Paint %d should not emit 'changed'",
- __FILE__, __LINE__, psel->mode);
- break;
- case SP_PAINT_SELECTOR_MODE_MULTIPLE:
- // This happens when you switch multiple objects with different gradients to flat color;
- // nothing to do here.
- break;
-
- case SP_PAINT_SELECTOR_MODE_NONE:
- {
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property(css, "stroke", "none");
-
- sp_desktop_set_style (desktop, css);
-
- sp_repr_css_attr_unref(css);
-
- sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
- _("Remove stroke"));
- break;
- }
-
- case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
- case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
- {
- sp_paint_selector_set_flat_color (psel, desktop, "stroke", "stroke-opacity");
- sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE,
- _("Set stroke color"));
-
- // on release, toggle undo_label so that the next drag will not be lumped with this one
- if (undo_label == undo_label_1)
- undo_label = undo_label_2;
- else
- undo_label = undo_label_1;
-
- break;
- }
-
- case SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR:
- case SP_PAINT_SELECTOR_MODE_GRADIENT_RADIAL:
- if (items) {
- SPGradientType const gradient_type = ( psel->mode == SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR
- ? SP_GRADIENT_TYPE_LINEAR
- : SP_GRADIENT_TYPE_RADIAL );
- SPGradient *vector = sp_paint_selector_get_gradient_vector(psel);
- if (!vector) {
- /* No vector in paint selector should mean that we just changed mode */
-
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- int result = objects_query_fillstroke ((GSList *) items, query, false);
- guint32 common_rgb = 0;
- if (result == QUERY_STYLE_MULTIPLE_SAME) {
- if (!query->fill.isColor()) {
- common_rgb = sp_desktop_get_color(desktop, false);
- } else {
- common_rgb = query->stroke.value.color.toRGBA32( 0xff );
- }
- vector = sp_document_default_gradient_vector(document, common_rgb);
- }
- sp_style_unref(query);
-
- for (GSList const *i = items; i != NULL; i = i->next) {
- if (!vector) {
- sp_item_set_gradient(SP_ITEM(i->data),
- sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), false),
- gradient_type, false);
- } else {
- sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, false);
- }
- }
- } else {
- vector = sp_gradient_ensure_vector_normalized(vector);
- for (GSList const *i = items; i != NULL; i = i->next) {
- SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, false);
- sp_gradient_selector_attrs_to_gradient(gr, psel);
- }
- }
-
- sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set gradient on stroke"));
- }
- break;
-
- case SP_PAINT_SELECTOR_MODE_PATTERN:
-
- if (items) {
-
- SPPattern *pattern = sp_paint_selector_get_pattern (psel);
- if (!pattern) {
-
- /* No Pattern in paint selector should mean that we just
- * changed mode - dont do jack.
- */
-
- } else {
- Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern);
- SPCSSAttr *css = sp_repr_css_attr_new ();
- gchar *urltext = g_strdup_printf ("url(#%s)", patrepr->attribute("id"));
- sp_repr_css_set_property (css, "stroke", urltext);
-
- for (GSList const *i = items; i != NULL; i = i->next) {
- Inkscape::XML::Node *selrepr = SP_OBJECT_REPR (i->data);
- SPObject *selobj = SP_OBJECT (i->data);
- if (!selrepr)
- continue;
-
- SPStyle *style = SP_OBJECT_STYLE (selobj);
- if (style && style->stroke.isPaintserver()) {
- SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (selobj);
- if (SP_IS_PATTERN (server) && pattern_getroot (SP_PATTERN(server)) == pattern)
- // only if this object's pattern is not rooted in our selected pattern, apply
- continue;
- }
-
- sp_repr_css_change_recursive (selrepr, css, "style");
- }
-
- sp_repr_css_attr_unref (css);
- g_free (urltext);
-
- } // end if
-
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set pattern on stroke"));
- } // end if
-
- break;
-
- case SP_PAINT_SELECTOR_MODE_UNSET:
- if (items) {
- SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_unset_property (css, "stroke");
- sp_repr_css_unset_property (css, "stroke-opacity");
- sp_repr_css_unset_property (css, "stroke-width");
- sp_repr_css_unset_property (css, "stroke-miterlimit");
- sp_repr_css_unset_property (css, "stroke-linejoin");
- sp_repr_css_unset_property (css, "stroke-linecap");
- sp_repr_css_unset_property (css, "stroke-dashoffset");
- sp_repr_css_unset_property (css, "stroke-dasharray");
-
- sp_desktop_set_style (desktop, css);
- sp_repr_css_attr_unref (css);
-
- sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
- _("Unset stroke"));
- }
- break;
-
- default:
- g_warning( "file %s: line %d: Paint selector should not be in "
- "mode %d",
- __FILE__, __LINE__,
- psel->mode );
- break;
- }
-
- g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
-}
-
-
-
-
-
-/* Line */
-
-static void sp_stroke_style_line_selection_modified(SPWidget *spw, Inkscape::Selection *selection, guint flags, gpointer data);
-static void sp_stroke_style_line_selection_changed(SPWidget *spw, Inkscape::Selection *selection, gpointer data);
-
-static void sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel);
-
-static void sp_stroke_style_set_join_buttons(Gtk::Container *spw, Gtk::ToggleButton *active);
-
-static void sp_stroke_style_set_cap_buttons(Gtk::Container *spw, Gtk::ToggleButton *active);
-
-static void sp_stroke_style_width_changed(Gtk::Container *spw);
-static void sp_stroke_style_miterlimit_changed(Gtk::Container *spw);
-static void sp_stroke_style_any_toggled(Gtk::ToggleButton *tb, Gtk::Container *spw);
-static void sp_stroke_style_line_dash_changed(Gtk::Container *spw);
-
-static void sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects);
-
-
-/**
- * Helper function for creating radio buttons. This should probably be re-thought out
- * when reimplementing this with Gtkmm.
- */
-static Gtk::RadioButton *
-sp_stroke_radio_button(Gtk::RadioButton *tb, char const *icon,
- Gtk::HBox *hb, Gtk::Container *spw,
- gchar const *key, gchar const *data)
-{
- g_assert(icon != NULL);
- g_assert(hb != NULL);
- g_assert(spw != NULL);
-
- if (tb == NULL) {
- tb = new Gtk::RadioButton();
- } else {
- Gtk::RadioButtonGroup grp = tb->get_group();
- tb = new Gtk::RadioButton(grp);
- }
-
- tb->show();
- tb->set_mode(false);
- hb->pack_start(*tb, false, false, 0);
- spw->set_data(icon, tb);
- tb->set_data(key, (gpointer*)data);
- tb->signal_toggled().connect(sigc::bind<Gtk::RadioButton *, Gtk::Container *>(
- sigc::ptr_fun(&sp_stroke_style_any_toggled), tb, spw));
- Gtk::Widget *px = manage(Glib::wrap(sp_icon_new(Inkscape::ICON_SIZE_LARGE_TOOLBAR, icon)));
- g_assert(px != NULL);
- px->show();
- tb->add(*px);
-
- return tb;
-
-}
-
-static void
-sp_stroke_style_widget_transientize_callback(Inkscape::Application */*inkscape*/,
- SPDesktop */*desktop*/,
- SPWidget */*spw*/ )
-{
-// TODO: Either of these will cause crashes sometimes
-// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL);
-// ink_markers_menu_update(spw);
-}
-
-/**
- * Creates a copy of the marker named mname, determines its visible and renderable
- * area in menu_id's bounding box, and then renders it. This allows us to fill in
- * preview images of each marker in the marker menu.
- */
-static Gtk::Image *
-sp_marker_prev_new(unsigned psize, gchar const *mname,
- SPDocument *source, SPDocument *sandbox,
- gchar const *menu_id, NRArena const */*arena*/, unsigned /*visionkey*/, NRArenaItem *root)
-{
- // Retrieve the marker named 'mname' from the source SVG document
- SPObject const *marker = source->getObjectById(mname);
- if (marker == NULL)
- return NULL;
-
- // Create a copy repr of the marker with id="sample"
- Inkscape::XML::Document *xml_doc = sp_document_repr_doc(sandbox);
- Inkscape::XML::Node *mrepr = SP_OBJECT_REPR (marker)->duplicate(xml_doc);
- mrepr->setAttribute("id", "sample");
-
- // Replace the old sample in the sandbox by the new one
- Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (sandbox->getObjectById("defs"));
- SPObject *oldmarker = sandbox->getObjectById("sample");
- if (oldmarker)
- oldmarker->deleteObject(false);
- defsrepr->appendChild(mrepr);
- Inkscape::GC::release(mrepr);
-
-// Uncomment this to get the sandbox documents saved (useful for debugging)
- //FILE *fp = fopen (g_strconcat(menu_id, mname, ".svg", NULL), "w");
- //sp_repr_save_stream (sp_document_repr_doc (sandbox), fp);
- //fclose (fp);
-
- // object to render; note that the id is the same as that of the menu we're building
- SPObject *object = sandbox->getObjectById(menu_id);
- sp_document_root (sandbox)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- sp_document_ensure_up_to_date(sandbox);
-
- if (object == NULL || !SP_IS_ITEM(object))
- return NULL; // sandbox broken?
-
- // Find object's bbox in document
- Geom::Matrix const i2doc(sp_item_i2doc_affine(SP_ITEM(object)));
- Geom::OptRect dbox = SP_ITEM(object)->getBounds(i2doc);
-
- if (!dbox) {
- return NULL;
- }
-
- /* Update to renderable state */
- double sf = 0.8;
-
- gchar *cache_name = g_strconcat(menu_id, mname, NULL);
- Glib::ustring key = svg_preview_cache.cache_key(source->uri, cache_name, psize);
- g_free (cache_name);
- // TODO: is this correct?
- Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key));
-
- if (!pixbuf) {
- pixbuf = Glib::wrap(render_pixbuf(root, sf, *dbox, psize));
- svg_preview_cache.set_preview_in_cache(key, pixbuf->gobj());
- }
-
- // Create widget
- Gtk::Image *pb = new Gtk::Image(pixbuf);
-
- return pb;
-}
-
-/**
- * Returns a list of markers in the defs of the given source document as a GSList object
- * Returns NULL if there are no markers in the document.
- */
-GSList *
-ink_marker_list_get (SPDocument *source)
-{
- if (source == NULL)
- return NULL;
-
- GSList *ml = NULL;
- SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS (source);
- for ( SPObject *child = sp_object_first_child(SP_OBJECT(defs));
- child != NULL;
- child = SP_OBJECT_NEXT (child) )
- {
- if (SP_IS_MARKER(child)) {
- ml = g_slist_prepend (ml, child);
- }
- }
- return ml;
-}
-
-#define MARKER_ITEM_MARGIN 0
-
-/**
- * Adds previews of markers in marker_list to the given menu widget
- */
-static void
-sp_marker_menu_build (Gtk::Menu *m, GSList *marker_list, SPDocument *source, SPDocument *sandbox, gchar const *menu_id)
-{
- // Do this here, outside of loop, to speed up preview generation:
- NRArena const *arena = NRArena::create();
- unsigned const visionkey = sp_item_display_key_new(1);
- NRArenaItem *root = sp_item_invoke_show(SP_ITEM(SP_DOCUMENT_ROOT (sandbox)), (NRArena *) arena, visionkey, SP_ITEM_SHOW_DISPLAY);
-
- for (; marker_list != NULL; marker_list = marker_list->next) {
- Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) marker_list->data);
- Gtk::MenuItem *i = new Gtk::MenuItem();
- i->show();
-
- if (repr->attribute("inkscape:stockid"))
- i->set_data("stockid", (void *) "true");
- else
- i->set_data("stockid", (void *) "false");
-
- gchar const *markid = repr->attribute("id");
- i->set_data("marker", (void *) markid);
-
- Gtk::HBox *hb = new Gtk::HBox(false, MARKER_ITEM_MARGIN);
- hb->show();
-
- // generate preview
-
- Gtk::Image *prv = sp_marker_prev_new (22, markid, source, sandbox, menu_id, arena, visionkey, root);
- prv->show();
- hb->pack_start(*prv, false, false, 6);
-
- // create label
- Gtk::Label *l = new Gtk::Label(repr->attribute("id"));
- l->show();
- l->set_alignment(0.0, 0.5);
-
- hb->pack_start(*l, true, true, 0);
-
- hb->show();
- i->add(*hb);
-
- m->append(*i);
- }
-
- sp_item_invoke_hide(SP_ITEM(sp_document_root(sandbox)), visionkey);
- nr_object_unref((NRObject *) arena);
-}
-
-/**
- * sp_marker_list_from_doc()
- *
- * \brief Pick up all markers from source, except those that are in
- * current_doc (if non-NULL), and add items to the m menu
- *
- */
-static void
-sp_marker_list_from_doc (Gtk::Menu *m, SPDocument */*current_doc*/, SPDocument *source, SPDocument */*markers_doc*/, SPDocument *sandbox, gchar const *menu_id)
-{
- GSList *ml = ink_marker_list_get(source);
- GSList *clean_ml = NULL;
-
- for (; ml != NULL; ml = ml->next) {
- if (!SP_IS_MARKER(ml->data))
- continue;
-
- // Add to the list of markers we really do wish to show
- clean_ml = g_slist_prepend (clean_ml, ml->data);
- }
- sp_marker_menu_build(m, clean_ml, source, sandbox, menu_id);
-
- g_slist_free (ml);
- g_slist_free (clean_ml);
-}
-
-/**
- * Returns a new document containing default start, mid, and end markers.
- */
-SPDocument *
-ink_markers_preview_doc ()
-{
-gchar const *buffer = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
-" <defs id=\"defs\" />"
-
-" <g id=\"marker-start\">"
-" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:url(#sample);marker-mid:none;marker-end:none\""
-" d=\"M 12.5,13 L 25,13\" id=\"path1\" />"
-" <rect style=\"fill:none;stroke:none\" id=\"rect2\""
-" width=\"25\" height=\"25\" x=\"0\" y=\"0\" />"
-" </g>"
-
-" <g id=\"marker-mid\">"
-" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:none;marker-mid:url(#sample);marker-end:none\""
-" d=\"M 0,113 L 12.5,113 L 25,113\" id=\"path11\" />"
-" <rect style=\"fill:none;stroke:none\" id=\"rect22\""
-" width=\"25\" height=\"25\" x=\"0\" y=\"100\" />"
-" </g>"
-
-" <g id=\"marker-end\">"
-" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:none;marker-mid:none;marker-end:url(#sample)\""
-" d=\"M 0,213 L 12.5,213\" id=\"path111\" />"
-" <rect style=\"fill:none;stroke:none\" id=\"rect222\""
-" width=\"25\" height=\"25\" x=\"0\" y=\"200\" />"
-" </g>"
-
-"</svg>";
-
- return sp_document_new_from_mem (buffer, strlen(buffer), FALSE);
-}
-
-static void
-ink_marker_menu_create_menu(Gtk::Menu *m, gchar const *menu_id, SPDocument *doc, SPDocument *sandbox)
-{
- static SPDocument *markers_doc = NULL;
-
- // add "None"
- Gtk::MenuItem *i = new Gtk::MenuItem();
- i->show();
-
- i->set_data("marker", (void *) "none");
-
- Gtk::HBox *hb = new Gtk::HBox(false, MARKER_ITEM_MARGIN);
- hb->show();
-
- Gtk::Label *l = new Gtk::Label( _("None") );
- l->show();
- l->set_alignment(0.0, 0.5);
-
- hb->pack_start(*l, true, true, 0);
-
- hb->show();
- i->add(*hb);
- m->append(*i);
-
- // find and load markers.svg
- if (markers_doc == NULL) {
- char *markers_source = g_build_filename(INKSCAPE_MARKERSDIR, "markers.svg", NULL);
- if (Inkscape::IO::file_test(markers_source, G_FILE_TEST_IS_REGULAR)) {
- markers_doc = sp_document_new(markers_source, FALSE);
- }
- g_free(markers_source);
- }
-
- // suck in from current doc
- sp_marker_list_from_doc(m, NULL, doc, markers_doc, sandbox, menu_id);
-
- // add separator
- {
- //Gtk::Separator *i = gtk_separator_menu_item_new();
- Gtk::SeparatorMenuItem *i = new Gtk::SeparatorMenuItem();
- i->show();
- m->append(*i);
- }
-
- // suck in from markers.svg
- if (markers_doc) {
- sp_document_ensure_up_to_date(doc);
- sp_marker_list_from_doc(m, doc, markers_doc, NULL, sandbox, menu_id);
- }
-
-}
-
-/**
- * Creates a menu widget to display markers from markers.svg
- */
-static Gtk::OptionMenu *
-ink_marker_menu(Gtk::Widget */*tbl*/, gchar const *menu_id, SPDocument *sandbox)
-{
- SPDesktop *desktop = inkscape_active_desktop();
- SPDocument *doc = sp_desktop_document(desktop);
- Gtk::OptionMenu *mnu = new Gtk::OptionMenu();
-
- /* Create new menu widget */
- Gtk::Menu *m = new Gtk::Menu();
- m->show();
-
- mnu->set_data("updating", (gpointer) FALSE);
-
- if (!doc) {
- Gtk::MenuItem *i = new Gtk::MenuItem(_("No document selected"));
- i->show();
- m->append(*i);
- mnu->set_sensitive(false);
-
- } else {
- ink_marker_menu_create_menu(m, menu_id, doc, sandbox);
-
- mnu->set_sensitive(true);
- }
-
- mnu->set_data("menu_id", const_cast<gchar *>(menu_id));
- mnu->set_menu(*m);
-
- /* Set history */
- mnu->set_history(0);
-
- return mnu;
-}
-
-/**
- * Handles when user selects one of the markers from the marker menu.
- * Defines a uri string to refer to it, then applies it to all selected
- * items in the current desktop.
- */
-static void
-sp_marker_select(Gtk::OptionMenu *mnu, Gtk::Container *spw, SPMarkerLoc const which)
-{
- if (spw->get_data("update")) {
- return;
- }
-
- SPDesktop *desktop = inkscape_active_desktop();
- SPDocument *document = sp_desktop_document(desktop);
- if (!document) {
- return;
- }
-
- /* Get Marker */
- if (!mnu->get_menu()->get_active()->get_data("marker"))
- {
- return;
- }
- gchar *markid = static_cast<gchar *>(mnu->get_menu()->get_active()->get_data("marker"));
- gchar const *marker = "";
- if (strcmp(markid, "none")) {
- gchar *stockid = static_cast<gchar *>(mnu->get_menu()->get_active()->get_data("stockid"));
-
- gchar *markurn = markid;
- if (!strcmp(stockid,"true")) markurn = g_strconcat("urn:inkscape:marker:",markid,NULL);
- SPObject *mark = get_stock_item(markurn);
- if (mark) {
- Inkscape::XML::Node *repr = SP_OBJECT_REPR(mark);
- marker = g_strconcat("url(#", repr->attribute("id"), ")", NULL);
- }
- } else {
- marker = markid;
- }
- SPCSSAttr *css = sp_repr_css_attr_new();
- gchar const *menu_id = static_cast<gchar const *>(mnu->get_data("menu_id"));
- sp_repr_css_set_property(css, menu_id, marker);
-
- // Also update the marker dropdown menus, so the document's markers
- // show up at the top of the menu
-// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL);
- ink_markers_menu_update(spw, which);
-
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
- GSList const *items = selection->itemList();
- for (; items != NULL; items = items->next) {
- SPItem *item = (SPItem *) items->data;
- if (!SP_IS_SHAPE(item) || SP_IS_RECT(item)) // can't set marker to rect, until it's converted to using <path>
- continue;
- Inkscape::XML::Node *selrepr = SP_OBJECT_REPR((SPItem *) items->data);
- if (selrepr) {
- sp_repr_css_change_recursive(selrepr, css, "style");
- }
- SP_OBJECT(items->data)->requestModified(SP_OBJECT_MODIFIED_FLAG);
- SP_OBJECT(items->data)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
- }
-
- sp_repr_css_attr_unref(css);
-
- sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set markers"));
-
-};
-
-static unsigned int
-ink_marker_menu_get_pos(Gtk::Menu *mnu, gchar const *markname)
-{
- if (markname == NULL)
- markname = static_cast<gchar const *>(mnu->get_active()->get_data("marker"));
-
- if (markname == NULL)
- return 0;
-
- std::vector<Gtk::Widget *> kids = mnu->get_children();
- unsigned int i = 0;
- for (; i < kids.size();) {
- gchar const *mark = static_cast<gchar const *>(kids[i]->get_data("marker"));
- if (mark && strcmp(mark, markname) == 0) {
- break;
- }
- ++i;
- }
-
- return i;
-}
-
-static void
-ink_markers_menu_update(Gtk::Container* /*spw*/, SPMarkerLoc const which) {
- SPDesktop *desktop = inkscape_active_desktop();
- SPDocument *document = sp_desktop_document(desktop);
- SPDocument *sandbox = ink_markers_preview_doc ();
- Gtk::Menu *m;
- int pos;
-
- // TODO: this code can be shortened by abstracting out marker_(start|mid|end)_...
- switch (which) {
- case SP_MARKER_LOC_START:
- marker_start_menu_connection.block();
- pos = ink_marker_menu_get_pos(marker_start_menu->get_menu(), NULL);
- m = new Gtk::Menu();
- m->show();
- ink_marker_menu_create_menu(m, "marker-start", document, sandbox);
- marker_start_menu->remove_menu();
- marker_start_menu->set_menu(*m);
- marker_start_menu->set_history(pos);
- marker_start_menu_connection.unblock();
- break;
-
- case SP_MARKER_LOC_MID:
- marker_mid_menu_connection.block();
- pos = ink_marker_menu_get_pos(marker_mid_menu->get_menu(), NULL);
- m = new Gtk::Menu();
- m->show();
- ink_marker_menu_create_menu(m, "marker-mid", document, sandbox);
- marker_mid_menu->remove_menu();
- marker_mid_menu->set_menu(*m);
- marker_mid_menu->set_history(pos);
- marker_mid_menu_connection.unblock();
- break;
-
- case SP_MARKER_LOC_END:
- marker_end_menu_connection.block();
- pos = ink_marker_menu_get_pos(marker_end_menu->get_menu(), NULL);
- m = new Gtk::Menu();
- m->show();
- ink_marker_menu_create_menu(m, "marker-end", document, sandbox);
- marker_end_menu->remove_menu();
- marker_end_menu->set_menu(*m);
- marker_end_menu->set_history(pos);
- marker_end_menu_connection.unblock();
- break;
- default:
- g_assert_not_reached();
- }
-}
-
-/**
- * Sets the stroke width units for all selected items.
- * Also handles absolute and dimensionless units.
- */
-static gboolean stroke_width_set_unit(SPUnitSelector *,
- SPUnit const *old,
- SPUnit const *new_units,
- Gtk::Container *spw)
-{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
-
- if (!desktop) {
- return FALSE;
- }
-
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
-
- if (selection->isEmpty())
- return FALSE;
-
- GSList const *objects = selection->itemList();
-
- if ((old->base == SP_UNIT_ABSOLUTE || old->base == SP_UNIT_DEVICE) &&
- (new_units->base == SP_UNIT_DIMENSIONLESS)) {
-
- /* Absolute to percentage */
- spw->set_data ("update", GUINT_TO_POINTER (TRUE));
-
- Gtk::Adjustment *a = static_cast<Gtk::Adjustment *>(spw->get_data("width"));
- float w = sp_units_get_pixels (a->get_value(), *old);
-
- gdouble average = stroke_average_width (objects);
-
- if (average == NR_HUGE || average == 0)
- return FALSE;
-
- a->set_value (100.0 * w / average);
-
- spw->set_data ("update", GUINT_TO_POINTER (FALSE));
- return TRUE;
-
- } else if ((old->base == SP_UNIT_DIMENSIONLESS) &&
- (new_units->base == SP_UNIT_ABSOLUTE || new_units->base == SP_UNIT_DEVICE)) {
-
- /* Percentage to absolute */
- spw->set_data ("update", GUINT_TO_POINTER (TRUE));
-
- Gtk::Adjustment *a = static_cast<Gtk::Adjustment *>(spw->get_data ("width"));
-
- gdouble average = stroke_average_width (objects);
-
- a->set_value (sp_pixels_get_units (0.01 * a->get_value() * average, *new_units));
-
- spw->set_data ("update", GUINT_TO_POINTER (FALSE));
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/**
- * \brief Creates a new widget for the line stroke style.
- *
- */
-Gtk::Container *
-sp_stroke_style_line_widget_new(void)
-{
- Gtk::Widget *us;
- SPDashSelector *ds;
- GtkWidget *us_old, *spw_old;
- Gtk::Container *spw;
- Gtk::Table *t;
- Gtk::Adjustment *a;
- Gtk::SpinButton *sb;
- Gtk::RadioButton *tb;
- Gtk::HBox *f, *hb;
-
- Gtk::Tooltips *tt = new Gtk::Tooltips();
-
- spw_old = sp_widget_new_global(INKSCAPE);
- spw = dynamic_cast<Gtk::Container *>(manage(Glib::wrap(spw_old)));
-
- f = new Gtk::HBox(false, 0);
- f->show();
- spw->add(*f);
-
- t = new Gtk::Table(3, 6, false);
- t->show();
- t->set_border_width(4);
- t->set_row_spacings(4);
- f->add(*t);
- spw->set_data("stroke", t);
-
- gint i = 0;
-
- /* Stroke width */
- spw_label(t, Q_("StrokeWidth|Width:"), 0, i);
-
- hb = spw_hbox(t, 3, 1, i);
-
-// TODO: when this is gtkmmified, use an Inkscape::UI::Widget::ScalarUnit instead of the separate
-// spinbutton and unit selector for stroke width. In sp_stroke_style_line_update, use
-// setHundredPercent to remember the aeraged width corresponding to 100%. Then the
-// stroke_width_set_unit will be removed (because ScalarUnit takes care of conversions itself), and
-// with it, the two remaining calls of stroke_average_width, allowing us to get rid of that
-// function in desktop-style.
-
- a = new Gtk::Adjustment(1.0, 0.0, 1000.0, 0.1, 10.0, 10.0);
- spw->set_data("width", a);
- sb = new Gtk::SpinButton(*a, 0.1, 3);
- tt->set_tip(*sb, _("Stroke width"));
- sb->show();
-
- sp_dialog_defocus_on_enter_cpp(sb);
-
- hb->pack_start(*sb, false, false, 0);
- us_old = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
- us = manage(Glib::wrap(us_old));
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (desktop)
- sp_unit_selector_set_unit (SP_UNIT_SELECTOR(us_old), sp_desktop_namedview(desktop)->doc_units);
- sp_unit_selector_add_unit(SP_UNIT_SELECTOR(us_old), &sp_unit_get_by_id(SP_UNIT_PERCENT), 0);
- g_signal_connect ( G_OBJECT (us_old), "set_unit", G_CALLBACK (stroke_width_set_unit), spw );
- us->show();
- sp_unit_selector_add_adjustment( SP_UNIT_SELECTOR(us_old), GTK_ADJUSTMENT(a->gobj()) );
- hb->pack_start(*us, FALSE, FALSE, 0);
- spw->set_data("units", us_old);
-
- a->signal_value_changed().connect(sigc::bind(sigc::ptr_fun(&sp_stroke_style_width_changed), spw));
- i++;
-
- /* Join type */
- // TRANSLATORS: The line join style specifies the shape to be used at the
- // corners of paths. It can be "miter", "round" or "bevel".
- spw_label(t, _("Join:"), 0, i);
-
- hb = spw_hbox(t, 3, 1, i);
-
- tb = NULL;
-
- tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_JOIN_MITER,
- hb, spw, "join", "miter");
-
- // TRANSLATORS: Miter join: joining lines with a sharp (pointed) corner.
- // For an example, draw a triangle with a large stroke width and modify the
- // "Join" option (in the Fill and Stroke dialog).
- tt->set_tip(*tb, _("Miter join"));
-
- tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_JOIN_ROUND,
- hb, spw, "join", "round");
-
- // TRANSLATORS: Round join: joining lines with a rounded corner.
- // For an example, draw a triangle with a large stroke width and modify the
- // "Join" option (in the Fill and Stroke dialog).
- tt->set_tip(*tb, _("Round join"));
-
- tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_JOIN_BEVEL,
- hb, spw, "join", "bevel");
-
- // TRANSLATORS: Bevel join: joining lines with a blunted (flattened) corner.
- // For an example, draw a triangle with a large stroke width and modify the
- // "Join" option (in the Fill and Stroke dialog).
- tt->set_tip(*tb, _("Bevel join"));
-
- i++;
-
- /* Miterlimit */
- // TRANSLATORS: Miter limit: only for "miter join", this limits the length
- // of the sharp "spike" when the lines connect at too sharp an angle.
- // When two line segments meet at a sharp angle, a miter join results in a
- // spike that extends well beyond the connection point. The purpose of the
- // miter limit is to cut off such spikes (i.e. convert them into bevels)
- // when they become too long.
- spw_label(t, _("Miter limit:"), 0, i);
-
- hb = spw_hbox(t, 3, 1, i);
-
- a = new Gtk::Adjustment(4.0, 0.0, 100.0, 0.1, 10.0, 10.0);
- spw->set_data("miterlimit", a);
-
- sb = new Gtk::SpinButton(*a, 0.1, 2);
- tt->set_tip(*sb, _("Maximum length of the miter (in units of stroke width)"));
- sb->show();
- spw->set_data("miterlimit_sb", sb);
- sp_dialog_defocus_on_enter_cpp(sb);
-
- hb->pack_start(*sb, false, false, 0);
-
- a->signal_value_changed().connect(sigc::bind(sigc::ptr_fun(&sp_stroke_style_miterlimit_changed), spw));
- i++;
-
- /* Cap type */
- // TRANSLATORS: cap type specifies the shape for the ends of lines
- spw_label(t, _("Cap:"), 0, i);
-
- hb = spw_hbox(t, 3, 1, i);
-
- tb = NULL;
-
- tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_CAP_BUTT,
- hb, spw, "cap", "butt");
-
- // TRANSLATORS: Butt cap: the line shape does not extend beyond the end point
- // of the line; the ends of the line are square
- tt->set_tip(*tb, _("Butt cap"));
-
- tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_CAP_ROUND,
- hb, spw, "cap", "round");
-
- // TRANSLATORS: Round cap: the line shape extends beyond the end point of the
- // line; the ends of the line are rounded
- tt->set_tip(*tb, _("Round cap"));
-
- tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_CAP_SQUARE,
- hb, spw, "cap", "square");
-
- // TRANSLATORS: Square cap: the line shape extends beyond the end point of the
- // line; the ends of the line are square
- tt->set_tip(*tb, _("Square cap"));
-
- i++;
-
-
- /* Dash */
- spw_label(t, _("Dashes:"), 0, i);
- ds = manage(new SPDashSelector);
-
- ds->show();
- t->attach(*ds, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
- spw->set_data("dash", ds);
- ds->changed_signal.connect(sigc::bind(sigc::ptr_fun(&sp_stroke_style_line_dash_changed), spw));
- i++;
-
- /* Drop down marker selectors*/
- // TODO: this code can be shortened by iterating over the possible menus!
-
- // doing this here once, instead of for each preview, to speed things up
- SPDocument *sandbox = ink_markers_preview_doc ();
-
- // TRANSLATORS: Path markers are an SVG feature that allows you to attach arbitrary shapes
- // (arrowheads, bullets, faces, whatever) to the start, end, or middle nodes of a path.
- spw_label(t, _("Start Markers:"), 0, i);
- marker_start_menu = ink_marker_menu(spw ,"marker-start", sandbox);
- tt->set_tip(*marker_start_menu, _("Start Markers are drawn on the first node of a path or shape"));
- marker_start_menu_connection = marker_start_menu->signal_changed().connect(
- sigc::bind<Gtk::OptionMenu *, Gtk::Container *, SPMarkerLoc>(
- sigc::ptr_fun(&sp_marker_select), marker_start_menu, spw, SP_MARKER_LOC_START));
- marker_start_menu->show();
- t->attach(*marker_start_menu, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
- spw->set_data("start_mark_menu", marker_start_menu);
-
- i++;
- spw_label(t, _("Mid Markers:"), 0, i);
- marker_mid_menu = ink_marker_menu(spw ,"marker-mid", sandbox);
- tt->set_tip(*marker_mid_menu, _("Mid Markers are drawn on every node of a path or shape except the first and last nodes"));
- marker_mid_menu_connection = marker_mid_menu->signal_changed().connect(
- sigc::bind<Gtk::OptionMenu *, Gtk::Container *, SPMarkerLoc>(
- sigc::ptr_fun(&sp_marker_select), marker_mid_menu,spw, SP_MARKER_LOC_MID));
- marker_mid_menu->show();
- t->attach(*marker_mid_menu, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
- spw->set_data("mid_mark_menu", marker_mid_menu);
-
- i++;
- spw_label(t, _("End Markers:"), 0, i);
- marker_end_menu = ink_marker_menu(spw ,"marker-end", sandbox);
- tt->set_tip(*marker_end_menu, _("End Markers are drawn on the last node of a path or shape"));
- marker_end_menu_connection = marker_end_menu->signal_changed().connect(
- sigc::bind<Gtk::OptionMenu *, Gtk::Container *, SPMarkerLoc>(
- sigc::ptr_fun(&sp_marker_select), marker_end_menu, spw, SP_MARKER_LOC_END));
- marker_end_menu->show();
- t->attach(*marker_end_menu, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
- spw->set_data("end_mark_menu", marker_end_menu);
-
- i++;
-
- // FIXME: we cheat and still use gtk+ signals
-
- gtk_signal_connect(GTK_OBJECT(spw_old), "modify_selection",
- GTK_SIGNAL_FUNC(sp_stroke_style_line_selection_modified),
- spw);
- gtk_signal_connect(GTK_OBJECT(spw_old), "change_selection",
- GTK_SIGNAL_FUNC(sp_stroke_style_line_selection_changed),
- spw);
-
- sp_stroke_style_line_update(spw, desktop ? sp_desktop_selection(desktop) : NULL);
-
- return spw;
-}
-
-/**
- * Callback for when stroke style widget is modified.
- * Triggers update action.
- */
-static void
-sp_stroke_style_line_selection_modified(SPWidget *,
- Inkscape::Selection *selection,
- guint flags,
- gpointer data)
-{
- Gtk::Container *spw = static_cast<Gtk::Container *>(data);
- if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG)) {
- sp_stroke_style_line_update(spw, selection);
- }
-
-}
-
-/**
- * Callback for when stroke style widget is changed.
- * Triggers update action.
- */
-static void
-sp_stroke_style_line_selection_changed(SPWidget *,
- Inkscape::Selection *selection,
- gpointer data)
-{
- Gtk::Container *spw = static_cast<Gtk::Container *>(data);
- sp_stroke_style_line_update(spw, selection);
-}
-
-/**
- * Sets selector widgets' dash style from an SPStyle object.
- */
-static void
-sp_dash_selector_set_from_style(SPDashSelector *dsel, SPStyle *style)
-{
- if (style->stroke_dash.n_dash > 0) {
- double d[64];
- int len = MIN(style->stroke_dash.n_dash, 64);
- for (int i = 0; i < len; i++) {
- if (style->stroke_width.computed != 0)
- d[i] = style->stroke_dash.dash[i] / style->stroke_width.computed;
- else
- d[i] = style->stroke_dash.dash[i]; // is there a better thing to do for stroke_width==0?
- }
- dsel->set_dash(len, d, style->stroke_width.computed != 0 ?
- style->stroke_dash.offset / style->stroke_width.computed :
- style->stroke_dash.offset);
- } else {
- dsel->set_dash(0, NULL, 0.0);
- }
-}
-
-/**
- * Sets the join type for a line, and updates the stroke style widget's buttons
- */
-static void
-sp_jointype_set (Gtk::Container *spw, unsigned const jointype)
-{
- Gtk::RadioButton *tb = NULL;
- switch (jointype) {
- case SP_STROKE_LINEJOIN_MITER:
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_MITER));
- break;
- case SP_STROKE_LINEJOIN_ROUND:
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_ROUND));
- break;
- case SP_STROKE_LINEJOIN_BEVEL:
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_BEVEL));
- break;
- default:
- break;
- }
- sp_stroke_style_set_join_buttons(spw, tb);
-}
-
-/**
- * Sets the cap type for a line, and updates the stroke style widget's buttons
- */
-static void
-sp_captype_set (Gtk::Container *spw, unsigned const captype)
-{
- Gtk::RadioButton *tb = NULL;
- switch (captype) {
- case SP_STROKE_LINECAP_BUTT:
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_BUTT));
- break;
- case SP_STROKE_LINECAP_ROUND:
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_ROUND));
- break;
- case SP_STROKE_LINECAP_SQUARE:
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_SQUARE));
- break;
- default:
- break;
- }
- sp_stroke_style_set_cap_buttons(spw, tb);
-}
-
-/**
- * Callback for when stroke style widget is updated, including markers, cap type,
- * join type, etc.
- */
-static void
-sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel)
-{
- if (spw->get_data("update")) {
- return;
- }
-
- spw->set_data("update", GINT_TO_POINTER(TRUE));
-
- Gtk::Table *sset = static_cast<Gtk::Table *>(spw->get_data("stroke"));
- Gtk::Adjustment *width = static_cast<Gtk::Adjustment *>(spw->get_data("width"));
- Gtk::Adjustment *ml = static_cast<Gtk::Adjustment *>(spw->get_data("miterlimit"));
- SPUnitSelector *us = SP_UNIT_SELECTOR(spw->get_data("units"));
- SPDashSelector *dsel = static_cast<SPDashSelector *>(spw->get_data("dash"));
-
- // create temporary style
- SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
- // query into it
- int result_sw = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEWIDTH);
- int result_ml = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEMITERLIMIT);
- int result_cap = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKECAP);
- int result_join = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEJOIN);
-
- if (result_sw == QUERY_STYLE_NOTHING) {
- /* No objects stroked, set insensitive */
- sset->set_sensitive(false);
-
- spw->set_data("update", GINT_TO_POINTER(FALSE));
- return;
- } else {
- sset->set_sensitive(true);
-
- SPUnit const *unit = sp_unit_selector_get_unit(us);
-
- if (result_sw == QUERY_STYLE_MULTIPLE_AVERAGED) {
- sp_unit_selector_set_unit(us, &sp_unit_get_by_id(SP_UNIT_PERCENT));
- } else {
- // same width, or only one object; no sense to keep percent, switch to absolute
- if (unit->base != SP_UNIT_ABSOLUTE && unit->base != SP_UNIT_DEVICE) {
- sp_unit_selector_set_unit(us, sp_desktop_namedview(SP_ACTIVE_DESKTOP)->doc_units);
- }
- }
-
- unit = sp_unit_selector_get_unit(us);
-
- if (unit->base == SP_UNIT_ABSOLUTE || unit->base == SP_UNIT_DEVICE) {
- double avgwidth = sp_pixels_get_units (query->stroke_width.computed, *unit);
- width->set_value(avgwidth);
- } else {
- width->set_value(100);
- }
- }
-
- if (result_ml != QUERY_STYLE_NOTHING)
- ml->set_value(query->stroke_miterlimit.value); // TODO: reflect averagedness?
-
- if (result_join != QUERY_STYLE_MULTIPLE_DIFFERENT) {
- sp_jointype_set(spw, query->stroke_linejoin.value);
- } else {
- sp_stroke_style_set_join_buttons(spw, NULL);
- }
-
- if (result_cap != QUERY_STYLE_MULTIPLE_DIFFERENT) {
- sp_captype_set (spw, query->stroke_linecap.value);
- } else {
- sp_stroke_style_set_cap_buttons(spw, NULL);
- }
-
- sp_style_unref(query);
-
- if (!sel || sel->isEmpty())
- return;
-
- GSList const *objects = sel->itemList();
- SPObject * const object = SP_OBJECT(objects->data);
- SPStyle * const style = SP_OBJECT_STYLE(object);
-
- /* Markers */
- sp_stroke_style_update_marker_menus(spw, objects); // FIXME: make this desktop query too
-
- /* Dash */
- sp_dash_selector_set_from_style(dsel, style); // FIXME: make this desktop query too
-
- sset->set_sensitive(true);
-
- spw->set_data("update", GINT_TO_POINTER(FALSE));
-}
-
-/**
- * Sets a line's dash properties in a CSS style object.
- */
-static void
-sp_stroke_style_set_scaled_dash(SPCSSAttr *css,
- int ndash, double *dash, double offset,
- double scale)
-{
- if (ndash > 0) {
- Inkscape::CSSOStringStream osarray;
- for (int i = 0; i < ndash; i++) {
- osarray << dash[i] * scale;
- if (i < (ndash - 1)) {
- osarray << ",";
- }
- }
- sp_repr_css_set_property(css, "stroke-dasharray", osarray.str().c_str());
-
- Inkscape::CSSOStringStream osoffset;
- osoffset << offset * scale;
- sp_repr_css_set_property(css, "stroke-dashoffset", osoffset.str().c_str());
- } else {
- sp_repr_css_set_property(css, "stroke-dasharray", "none");
- sp_repr_css_set_property(css, "stroke-dashoffset", NULL);
- }
-}
-
-/**
- * Sets line properties like width, dashes, markers, etc. on all currently selected items.
- */
-static void
-sp_stroke_style_scale_line(Gtk::Container *spw)
-{
- if (spw->get_data("update")) {
- return;
- }
-
- spw->set_data("update", GINT_TO_POINTER(TRUE));
-
- Gtk::Adjustment *wadj = static_cast<Gtk::Adjustment *>(spw->get_data("width"));
- SPUnitSelector *us = SP_UNIT_SELECTOR(spw->get_data("units"));
- SPDashSelector *dsel = static_cast<SPDashSelector *>(spw->get_data("dash"));
- Gtk::Adjustment *ml = static_cast<Gtk::Adjustment *>(spw->get_data("miterlimit"));
-
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- SPDocument *document = sp_desktop_document (desktop);
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
-
- GSList const *items = selection->itemList();
-
- /* TODO: Create some standardized method */
- SPCSSAttr *css = sp_repr_css_attr_new();
-
- if (items) {
-
- double width_typed = wadj->get_value();
- double const miterlimit = ml->get_value();
-
- SPUnit const *const unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
-
- double *dash, offset;
- int ndash;
- dsel->get_dash(&ndash, &dash, &offset);
-
- for (GSList const *i = items; i != NULL; i = i->next) {
- /* Set stroke width */
- double width;
- if (unit->base == SP_UNIT_ABSOLUTE || unit->base == SP_UNIT_DEVICE) {
- width = sp_units_get_pixels (width_typed, *unit);
- } else { // percentage
- gdouble old_w = SP_OBJECT_STYLE (i->data)->stroke_width.computed;
- width = old_w * width_typed / 100;
- }
-
- {
- Inkscape::CSSOStringStream os_width;
- os_width << width;
- sp_repr_css_set_property(css, "stroke-width", os_width.str().c_str());
- }
-
- {
- Inkscape::CSSOStringStream os_ml;
- os_ml << miterlimit;
- sp_repr_css_set_property(css, "stroke-miterlimit", os_ml.str().c_str());
- }
-
- /* Set dash */
- sp_stroke_style_set_scaled_dash(css, ndash, dash, offset, width);
-
- sp_desktop_apply_css_recursive (SP_OBJECT(i->data), css, true);
- }
-
- g_free(dash);
-
- if (unit->base != SP_UNIT_ABSOLUTE && unit->base != SP_UNIT_DEVICE) {
- // reset to 100 percent
- wadj->set_value(100.0);
- }
-
- }
-
- // we have already changed the items, so set style without changing selection
- // FIXME: move the above stroke-setting stuff, including percentages, to desktop-style
- sp_desktop_set_style (desktop, css, false);
-
- sp_repr_css_attr_unref(css);
-
- sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
- _("Set stroke style"));
-
- spw->set_data("update", GINT_TO_POINTER(FALSE));
-}
-
-/**
- * Callback for when the stroke style's width changes.
- * Causes all line styles to be applied to all selected items.
- */
-static void
-sp_stroke_style_width_changed(Gtk::Container *spw)
-{
- if (spw->get_data("update")) {
- return;
- }
-
- sp_stroke_style_scale_line(spw);
-}
-
-/**
- * Callback for when the stroke style's miterlimit changes.
- * Causes all line styles to be applied to all selected items.
- */
-static void
-sp_stroke_style_miterlimit_changed(Gtk::Container *spw)
-{
- if (spw->get_data("update")) {
- return;
- }
-
- sp_stroke_style_scale_line(spw);
-}
-
-/**
- * Callback for when the stroke style's dash changes.
- * Causes all line styles to be applied to all selected items.
- */
-
-static void
-sp_stroke_style_line_dash_changed(Gtk::Container *spw)
-{
- if (spw->get_data("update")) {
- return;
- }
-
- sp_stroke_style_scale_line(spw);
-}
-
-/**
- * \brief This routine handles toggle events for buttons in the stroke style
- * dialog.
- * When activated, this routine gets the data for the various widgets, and then
- * calls the respective routines to update css properties, etc.
- *
- */
-static void
-sp_stroke_style_any_toggled(Gtk::ToggleButton *tb, Gtk::Container *spw)
-{
- if (spw->get_data("update")) {
- return;
- }
-
- if (tb->get_active()) {
-
- gchar const *join
- = static_cast<gchar const *>(tb->get_data("join"));
- gchar const *cap
- = static_cast<gchar const *>(tb->get_data("cap"));
-
- if (join) {
- Gtk::SpinButton *ml = static_cast<Gtk::SpinButton *>(spw->get_data("miterlimit_sb"));
- ml->set_sensitive(!strcmp(join, "miter"));
- }
-
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
-
- /* TODO: Create some standardized method */
- SPCSSAttr *css = sp_repr_css_attr_new();
-
- if (join) {
- sp_repr_css_set_property(css, "stroke-linejoin", join);
-
- sp_desktop_set_style (desktop, css);
-
- sp_stroke_style_set_join_buttons(spw, tb);
- } else if (cap) {
- sp_repr_css_set_property(css, "stroke-linecap", cap);
-
- sp_desktop_set_style (desktop, css);
-
- sp_stroke_style_set_cap_buttons(spw, tb);
- }
-
- sp_repr_css_attr_unref(css);
-
- sp_document_done(sp_desktop_document(desktop), SP_VERB_DIALOG_FILL_STROKE,
- _("Set stroke style"));
- }
-}
-
-/**
- * Updates the join style toggle buttons
- */
-static void
-sp_stroke_style_set_join_buttons(Gtk::Container *spw, Gtk::ToggleButton *active)
-{
- Gtk::RadioButton *tb;
-
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_MITER));
- tb->set_active(active == tb);
-
- Gtk::SpinButton *ml = static_cast<Gtk::SpinButton *>(spw->get_data("miterlimit_sb"));
- ml->set_sensitive(active == tb);
-
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_ROUND));
- tb->set_active(active == tb);
-
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_BEVEL));
- tb->set_active(active == tb);
-}
-
-/**
- * Updates the cap style toggle buttons
- */
-static void
-sp_stroke_style_set_cap_buttons(Gtk::Container *spw, Gtk::ToggleButton *active)
-{
- Gtk::RadioButton *tb;
-
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_BUTT));
- tb->set_active(active == tb);
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_ROUND));
- tb->set_active(active == tb);
- tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_SQUARE));
- tb->set_active(active == tb);
-}
-
-/**
- * Sets the current marker in the marker menu.
- */
-static void
-ink_marker_menu_set_current(SPObject *marker, Gtk::OptionMenu *mnu)
-{
- mnu->set_data("update", GINT_TO_POINTER(TRUE));
-
- Gtk::Menu *m = mnu->get_menu();
- if (marker != NULL) {
- bool mark_is_stock = false;
- if (SP_OBJECT_REPR(marker)->attribute("inkscape:stockid"))
- mark_is_stock = true;
-
- gchar *markname;
- if (mark_is_stock)
- markname = g_strdup(SP_OBJECT_REPR(marker)->attribute("inkscape:stockid"));
- else
- markname = g_strdup(SP_OBJECT_REPR(marker)->attribute("id"));
-
- int markpos = ink_marker_menu_get_pos(m, markname);
- mnu->set_history(markpos);
-
- g_free (markname);
- }
- else {
- mnu->set_history(0);
- }
- mnu->set_data("update", GINT_TO_POINTER(FALSE));
-}
-
-/**
- * Updates the marker menus to highlight the appropriate marker and scroll to
- * that marker.
- */
-static void
-sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects)
-{
- struct { char const *key; int loc; } const keyloc[] = {
- { "start_mark_menu", SP_MARKER_LOC_START },
- { "mid_mark_menu", SP_MARKER_LOC_MID },
- { "end_mark_menu", SP_MARKER_LOC_END }
- };
-
- bool all_texts = true;
- for (GSList *i = (GSList *) objects; i != NULL; i = i->next) {
- if (!SP_IS_TEXT (i->data)) {
- all_texts = false;
- }
- }
-
- for (unsigned i = 0; i < G_N_ELEMENTS(keyloc); ++i) {
- Gtk::OptionMenu *mnu = static_cast<Gtk::OptionMenu *>(spw->get_data(keyloc[i].key));
- // Per SVG spec, text objects cannot have markers; disable menus if only texts are selected
- mnu->set_sensitive(!all_texts);
- }
-
- // We show markers of the first object in the list only
- // FIXME: use the first in the list that has the marker of each type, if any
- SPObject *object = SP_OBJECT(objects->data);
-
- for (unsigned i = 0; i < G_N_ELEMENTS(keyloc); ++i) {
- // For all three marker types,
-
- // find the corresponding menu
- Gtk::OptionMenu *mnu = static_cast<Gtk::OptionMenu *>(spw->get_data(keyloc[i].key));
-
- // Quit if we're in update state
- if (mnu->get_data("update")) {
- return;
- }
-
- if (object->style->marker[keyloc[i].loc].value != NULL && !all_texts) {
- // If the object has this type of markers,
-
- // Extract the name of the marker that the object uses
- SPObject *marker = ink_extract_marker_name(object->style->marker[keyloc[i].loc].value, SP_OBJECT_DOCUMENT(object));
- // Scroll the menu to that marker
- ink_marker_menu_set_current(marker, mnu);
-
- } else {
- mnu->set_history(0);
- }
- }
-}
-
-
-/**
- * Extract the actual name of the link
- * e.g. get mTriangle from url(#mTriangle).
- * \return Buffer containing the actual name, allocated from GLib;
- * the caller should free the buffer when they no longer need it.
- */
-static SPObject*
-ink_extract_marker_name(gchar const *n, SPDocument *doc)
-{
- gchar const *p = n;
- while (*p != '\0' && *p != '#') {
- p++;
- }
-
- if (*p == '\0' || p[1] == '\0') {
- return NULL;
- }
-
- p++;
- int c = 0;
- while (p[c] != '\0' && p[c] != ')') {
- c++;
- }
-
- if (p[c] == '\0') {
- return NULL;
- }
-
- gchar* b = g_strdup(p);
- b[c] = '\0';
-
- // FIXME: get the document from the object and let the caller pass it in
- SPObject *marker = doc->getObjectById(b);
- return marker;
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/stroke-style.h b/src/dialogs/stroke-style.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/** @file
- * @brief Stroke style dialog
- */
-/* Author:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 2001 Ximian, Inc.
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_DIALOGS_STROKE_STYLE_H
-#define SEEN_DIALOGS_STROKE_STYLE_H
-
-#include <glib.h>
-
-#include <gtk/gtkwidget.h>
-
-#include "forward.h"
-#include "display/canvas-bpath.h"
-
-GtkWidget *sp_stroke_style_paint_widget_new (void);
-Gtk::Container *sp_stroke_style_line_widget_new (void);
-
-#endif
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/swatches.cpp b/src/dialogs/swatches.cpp
--- a/src/dialogs/swatches.cpp
+++ /dev/null
@@ -1,1213 +0,0 @@
-/** @file
- * @brief Color swatches dialog
- */
-/* Authors:
- * Jon A. Cruz
- * John Bintz
- *
- * Copyright (C) 2005 Jon A. Cruz
- * Copyright (C) 2008 John Bintz
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <errno.h>
-
-#include <gtk/gtkdialog.h> //for GTK_RESPONSE* types
-#include <gtk/gtkdnd.h>
-#include <gtk/gtkmenu.h>
-#include <gtk/gtkmenuitem.h>
-#include <gtk/gtkseparatormenuitem.h>
-
-#include <glibmm/i18n.h>
-#include <gdkmm/pixbuf.h>
-#include "inkscape.h"
-#include "desktop.h"
-#include "message-context.h"
-#include "document.h"
-#include "desktop-handles.h"
-#include "extension/db.h"
-#include "inkscape.h"
-#include "svg/svg-color.h"
-#include "desktop-style.h"
-#include "io/sys.h"
-#include "path-prefix.h"
-#include "swatches.h"
-#include "sp-item.h"
-#include "preferences.h"
-
-#include "eek-preview.h"
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-ColorItem::ColorItem() : _isRemove(true){};
-ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) :
- def( r, g, b, name ),
- _isRemove(false),
- _isLive(false),
- _linkIsTone(false),
- _linkPercent(0),
- _linkGray(0),
- _linkSrc(0)
-{
-}
-
-ColorItem::~ColorItem()
-{
-}
-
-ColorItem::ColorItem(ColorItem const &other) :
- Inkscape::UI::Previewable()
-{
- if ( this != &other ) {
- *this = other;
- }
-}
-
-ColorItem &ColorItem::operator=(ColorItem const &other)
-{
- if ( this != &other ) {
- def = other.def;
-
- // TODO - correct linkage
- _linkSrc = other._linkSrc;
- g_message("Erk!");
- }
- return *this;
-}
-
-
-class JustForNow
-{
-public:
- JustForNow() : _prefWidth(0) {}
-
- Glib::ustring _name;
- int _prefWidth;
- std::vector<ColorItem*> _colors;
-};
-
-static std::vector<JustForNow*> possible;
-
-
-
-typedef enum {
- APP_X_INKY_COLOR_ID = 0,
- APP_X_INKY_COLOR = 0,
- APP_X_COLOR,
- TEXT_DATA
-} colorFlavorType;
-
-//TODO: warning: deprecated conversion from string constant to ‘gchar*’
-//
-//Turn out to be warnings that we should probably leave in place. The
-// pointers/types used need to be read-only. So until we correct the using
-// code, those warnings are actually desired. They say "Hey! Fix this". We
-// definitely don't want to hide/ignore them. --JonCruz
-static const GtkTargetEntry sourceColorEntries[] = {
-#if ENABLE_MAGIC_COLORS
-// {"application/x-inkscape-color-id", GTK_TARGET_SAME_APP, APP_X_INKY_COLOR_ID},
- {"application/x-inkscape-color", 0, APP_X_INKY_COLOR},
-#endif // ENABLE_MAGIC_COLORS
- {"application/x-color", 0, APP_X_COLOR},
- {"text/plain", 0, TEXT_DATA},
-};
-
-void ColorItem::_dragGetColorData( GtkWidget *widget,
- GdkDragContext *drag_context,
- GtkSelectionData *data,
- guint info,
- guint time,
- gpointer user_data)
-{
- (void)widget;
- (void)drag_context;
- (void)time;
- static GdkAtom typeXColor = gdk_atom_intern("application/x-color", FALSE);
- static GdkAtom typeText = gdk_atom_intern("text/plain", FALSE);
-
- ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
- if ( info == TEXT_DATA ) {
- gchar* tmp = g_strdup_printf("#%02x%02x%02x", item->def.getR(), item->def.getG(), item->def.getB() );
-
- gtk_selection_data_set( data,
- typeText,
- 8, // format
- (guchar*)tmp,
- strlen((const char*)tmp) + 1);
- g_free(tmp);
- tmp = 0;
- } else if ( info == APP_X_INKY_COLOR ) {
- Glib::ustring paletteName;
-
- // Find where this thing came from
- bool found = false;
- int index = 0;
- for ( std::vector<JustForNow*>::iterator it = possible.begin(); it != possible.end() && !found; ++it ) {
- JustForNow* curr = *it;
- index = 0;
- for ( std::vector<ColorItem*>::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) {
- if ( item == *zz ) {
- found = true;
- paletteName = curr->_name;
- break;
- } else {
- index++;
- }
- }
- }
-
-// if ( found ) {
-// g_message("Found the color at entry %d in palette '%s'", index, paletteName.c_str() );
-// } else {
-// g_message("Unable to find the color");
-// }
- int itemCount = 4 + 2 + 1 + paletteName.length();
-
- guint16* tmp = new guint16[itemCount];
- tmp[0] = (item->def.getR() << 8) | item->def.getR();
- tmp[1] = (item->def.getG() << 8) | item->def.getG();
- tmp[2] = (item->def.getB() << 8) | item->def.getB();
- tmp[3] = 0xffff;
- tmp[4] = (item->_isLive || !item->_listeners.empty() || (item->_linkSrc != 0) ) ? 1 : 0;
-
- tmp[5] = index;
- tmp[6] = paletteName.length();
- for ( unsigned int i = 0; i < paletteName.length(); i++ ) {
- tmp[7 + i] = paletteName[i];
- }
- gtk_selection_data_set( data,
- typeXColor,
- 16, // format
- reinterpret_cast<const guchar*>(tmp),
- itemCount * 2);
- delete[] tmp;
- } else {
- guint16 tmp[4];
- tmp[0] = (item->def.getR() << 8) | item->def.getR();
- tmp[1] = (item->def.getG() << 8) | item->def.getG();
- tmp[2] = (item->def.getB() << 8) | item->def.getB();
- tmp[3] = 0xffff;
- gtk_selection_data_set( data,
- typeXColor,
- 16, // format
- reinterpret_cast<const guchar*>(tmp),
- (3+1) * 2);
- }
-}
-
-static void dragBegin( GtkWidget *widget, GdkDragContext* dc, gpointer data )
-{
- (void)widget;
- ColorItem* item = reinterpret_cast<ColorItem*>(data);
- if ( item )
- {
- if (item->isRemove()){
- GError *error = NULL;
- gchar *filepath = (gchar *) g_strdup_printf("%s/remove-color.png", INKSCAPE_PIXMAPDIR);
- gsize bytesRead = 0;
- gsize bytesWritten = 0;
- gchar *localFilename = g_filename_from_utf8( filepath,
- -1,
- &bytesRead,
- &bytesWritten,
- &error);
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, 32, 24, FALSE, &error);
- g_free(localFilename);
- g_free(filepath);
- gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 );
- return;
- }
-
- Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, 32, 24 );
- guint32 fillWith = (0xff000000 & (item->def.getR() << 24))
- | (0x00ff0000 & (item->def.getG() << 16))
- | (0x0000ff00 & (item->def.getB() << 8));
- thumb->fill( fillWith );
- gtk_drag_set_icon_pixbuf( dc, thumb->gobj(), 0, 0 );
- }
-
-}
-
-//"drag-drop"
-// gboolean dragDropColorData( GtkWidget *widget,
-// GdkDragContext *drag_context,
-// gint x,
-// gint y,
-// guint time,
-// gpointer user_data)
-// {
-// // TODO finish
-
-// return TRUE;
-// }
-
-static void handleClick( GtkWidget* widget, gpointer callback_data ) {
- (void)widget;
- ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
- if ( item ) {
- item->buttonClicked(false);
- }
-}
-
-static void handleSecondaryClick( GtkWidget* widget, gint arg1, gpointer callback_data ) {
- (void)widget;
- (void)arg1;
- ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
- if ( item ) {
- item->buttonClicked(true);
- }
-}
-
-static gboolean handleEnterNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) {
- ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
- if ( item ) {
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if ( desktop ) {
- gchar* msg = g_strdup_printf(_("Color: <b>%s</b>; <b>Click</b> to set fill, <b>Shift+click</b> to set stroke"),
- item->def.descr.c_str());
- desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg);
- g_free(msg);
- }
- }
- return FALSE;
-}
-
-static gboolean handleLeaveNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) {
- ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
- if ( item ) {
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if ( desktop ) {
- desktop->tipsMessageContext()->clear();
- }
- }
- return FALSE;
-}
-
-static GtkWidget* popupMenu = 0;
-static ColorItem* bounceTarget = 0;
-
-static void redirClick( GtkMenuItem *menuitem, gpointer user_data )
-{
- (void)user_data;
- if ( bounceTarget ) {
- handleClick( GTK_WIDGET(menuitem), bounceTarget );
- }
-}
-
-static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer user_data )
-{
- (void)user_data;
- if ( bounceTarget ) {
- handleSecondaryClick( GTK_WIDGET(menuitem), 0, bounceTarget );
- }
-}
-
-static gboolean handleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data)
-{
- (void)widget;
- gboolean handled = FALSE;
-
- if ( (event->button == 3) && (event->type == GDK_BUTTON_PRESS) ) {
- if ( !popupMenu ) {
- popupMenu = gtk_menu_new();
- GtkWidget* child = 0;
-
- //TRANSLATORS: An item in context menu on a colour in the swatches
- child = gtk_menu_item_new_with_label(_("Set fill"));
- g_signal_connect( G_OBJECT(child),
- "activate",
- G_CALLBACK(redirClick),
- user_data);
- gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
-
- //TRANSLATORS: An item in context menu on a colour in the swatches
- child = gtk_menu_item_new_with_label(_("Set stroke"));
-
- g_signal_connect( G_OBJECT(child),
- "activate",
- G_CALLBACK(redirSecondaryClick),
- user_data);
- gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
-
- gtk_widget_show_all(popupMenu);
- }
-
- ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
- if ( item ) {
- bounceTarget = item;
- if ( popupMenu ) {
- gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time);
- handled = TRUE;
- }
- }
- }
-
- return handled;
-}
-
-static void dieDieDie( GtkObject *obj, gpointer user_data )
-{
- g_message("die die die %p %p", obj, user_data );
-}
-
-//TODO: warning: deprecated conversion from string constant to ‘gchar*’
-//
-//Turn out to be warnings that we should probably leave in place. The
-// pointers/types used need to be read-only. So until we correct the using
-// code, those warnings are actually desired. They say "Hey! Fix this". We
-// definitely don't want to hide/ignore them. --JonCruz
-static const GtkTargetEntry destColorTargets[] = {
-#if ENABLE_MAGIC_COLORS
-// {"application/x-inkscape-color-id", GTK_TARGET_SAME_APP, APP_X_INKY_COLOR_ID},
- {"application/x-inkscape-color", 0, APP_X_INKY_COLOR},
-#endif // ENABLE_MAGIC_COLORS
- {"application/x-color", 0, APP_X_COLOR},
-};
-
-#include "color.h" // for SP_RGBA32_U_COMPOSE
-
-void ColorItem::_dropDataIn( GtkWidget *widget,
- GdkDragContext *drag_context,
- gint x, gint y,
- GtkSelectionData *data,
- guint info,
- guint event_time,
- gpointer user_data)
-{
- (void)widget;
- (void)drag_context;
- (void)x;
- (void)y;
- (void)event_time;
-// g_message(" droppy droppy %d", info);
- switch (info) {
- case APP_X_INKY_COLOR:
- {
- if ( data->length >= 8 ) {
- // Careful about endian issues.
- guint16* dataVals = (guint16*)data->data;
- if ( user_data ) {
- ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
- if ( item->def.isEditable() ) {
- // Shove on in the new value
- item->def.setRGB( 0x0ff & (dataVals[0] >> 8), 0x0ff & (dataVals[1] >> 8), 0x0ff & (dataVals[2] >> 8) );
- }
- }
- }
- break;
- }
- case APP_X_COLOR:
- {
- if ( data->length == 8 ) {
- // Careful about endian issues.
- guint16* dataVals = (guint16*)data->data;
-// {
-// gchar c[64] = {0};
-// sp_svg_write_color( c, 64,
-// SP_RGBA32_U_COMPOSE(
-// 0x0ff & (dataVals[0] >> 8),
-// 0x0ff & (dataVals[1] >> 8),
-// 0x0ff & (dataVals[2] >> 8),
-// 0xff // can't have transparency in the color itself
-// //0x0ff & (data->data[3] >> 8),
-// ));
-// }
- if ( user_data ) {
- ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
- if ( item->def.isEditable() ) {
- // Shove on in the new value
- item->def.setRGB( 0x0ff & (dataVals[0] >> 8), 0x0ff & (dataVals[1] >> 8), 0x0ff & (dataVals[2] >> 8) );
- }
- }
- }
- break;
- }
- default:
- g_message("unknown drop type");
- }
-
-}
-
-static bool bruteForce( SPDocument* document, Inkscape::XML::Node* node, Glib::ustring const& match, int r, int g, int b )
-{
- bool changed = false;
-
- if ( node ) {
- gchar const * val = node->attribute("inkscape:x-fill-tag");
- if ( val && (match == val) ) {
- SPObject *obj = document->getObjectByRepr( node );
-
- gchar c[64] = {0};
- sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) );
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property( css, "fill", c );
-
- sp_desktop_apply_css_recursive( (SPItem*)obj, css, true );
- ((SPItem*)obj)->updateRepr();
-
- changed = true;
- }
-
- val = node->attribute("inkscape:x-stroke-tag");
- if ( val && (match == val) ) {
- SPObject *obj = document->getObjectByRepr( node );
-
- gchar c[64] = {0};
- sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) );
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property( css, "stroke", c );
-
- sp_desktop_apply_css_recursive( (SPItem*)obj, css, true );
- ((SPItem*)obj)->updateRepr();
-
- changed = true;
- }
-
- Inkscape::XML::Node* first = node->firstChild();
- changed |= bruteForce( document, first, match, r, g, b );
-
- changed |= bruteForce( document, node->next(), match, r, g, b );
- }
-
- return changed;
-}
-
-void ColorItem::_colorDefChanged(void* data)
-{
- ColorItem* item = reinterpret_cast<ColorItem*>(data);
- if ( item ) {
- for ( std::vector<Gtk::Widget*>::iterator it = item->_previews.begin(); it != item->_previews.end(); ++it ) {
- Gtk::Widget* widget = *it;
- if ( IS_EEK_PREVIEW(widget->gobj()) ) {
- EekPreview * preview = EEK_PREVIEW(widget->gobj());
- eek_preview_set_color( preview,
- (item->def.getR() << 8) | item->def.getR(),
- (item->def.getG() << 8) | item->def.getG(),
- (item->def.getB() << 8) | item->def.getB() );
-
- eek_preview_set_linked( preview, (LinkType)((item->_linkSrc ? PREVIEW_LINK_IN:0)
- | (item->_listeners.empty() ? 0:PREVIEW_LINK_OUT)
- | (item->_isLive ? PREVIEW_LINK_OTHER:0)) );
-
- widget->queue_draw();
- }
- }
-
- for ( std::vector<ColorItem*>::iterator it = item->_listeners.begin(); it != item->_listeners.end(); ++it ) {
- guint r = item->def.getR();
- guint g = item->def.getG();
- guint b = item->def.getB();
-
- if ( (*it)->_linkIsTone ) {
- r = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * r) ) / 100;
- g = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * g) ) / 100;
- b = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * b) ) / 100;
- } else {
- r = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * r) ) / 100;
- g = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * g) ) / 100;
- b = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * b) ) / 100;
- }
-
- (*it)->def.setRGB( r, g, b );
- }
-
-
- // Look for objects using this color
- {
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if ( desktop ) {
- SPDocument* document = sp_desktop_document( desktop );
- Inkscape::XML::Node *rroot = sp_document_repr_root( document );
- if ( rroot ) {
-
- // Find where this thing came from
- Glib::ustring paletteName;
- bool found = false;
- int index = 0;
- for ( std::vector<JustForNow*>::iterator it2 = possible.begin(); it2 != possible.end() && !found; ++it2 ) {
- JustForNow* curr = *it2;
- index = 0;
- for ( std::vector<ColorItem*>::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) {
- if ( item == *zz ) {
- found = true;
- paletteName = curr->_name;
- break;
- } else {
- index++;
- }
- }
- }
-
- if ( !paletteName.empty() ) {
- gchar* str = g_strdup_printf("%d|", index);
- paletteName.insert( 0, str );
- g_free(str);
- str = 0;
-
- if ( bruteForce( document, rroot, paletteName, item->def.getR(), item->def.getG(), item->def.getB() ) ) {
- sp_document_done( document , SP_VERB_DIALOG_SWATCHES,
- _("Change color definition"));
- }
- }
- }
- }
- }
- }
-}
-
-
-Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio)
-{
- Gtk::Widget* widget = 0;
- if ( style == PREVIEW_STYLE_BLURB) {
- Gtk::Label *lbl = new Gtk::Label(def.descr);
- lbl->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER);
- widget = lbl;
- } else {
-// Glib::ustring blank(" ");
-// if ( size == Inkscape::ICON_SIZE_MENU || size == Inkscape::ICON_SIZE_DECORATION ) {
-// blank = " ";
-// }
-
- GtkWidget* eekWidget = eek_preview_new();
- EekPreview * preview = EEK_PREVIEW(eekWidget);
- Gtk::Widget* newBlot = Glib::wrap(eekWidget);
-
- eek_preview_set_color( preview, (def.getR() << 8) | def.getR(), (def.getG() << 8) | def.getG(), (def.getB() << 8) | def.getB());
- if ( _isRemove ) {
- GError *error = NULL;
- gchar *filepath = (gchar *) g_strdup_printf("%s/remove-color.png", INKSCAPE_PIXMAPDIR);
- gsize bytesRead = 0;
- gsize bytesWritten = 0;
- gchar *localFilename = g_filename_from_utf8( filepath,
- -1,
- &bytesRead,
- &bytesWritten,
- &error);
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(localFilename, &error);
- if (!pixbuf) {
- g_warning("Null pixbuf for %p [%s]", localFilename, localFilename );
- }
- g_free(localFilename);
- g_free(filepath);
-
- eek_preview_set_pixbuf( preview, pixbuf );
- }
-
- eek_preview_set_details( preview, (::PreviewStyle)style, (::ViewType)view, (::PreviewSize)size, ratio );
- eek_preview_set_linked( preview, (LinkType)((_linkSrc ? PREVIEW_LINK_IN:0)
- | (_listeners.empty() ? 0:PREVIEW_LINK_OUT)
- | (_isLive ? PREVIEW_LINK_OTHER:0)) );
-
- def.addCallback( _colorDefChanged, this );
-
- GValue val = {0, {{0}, {0}}};
- g_value_init( &val, G_TYPE_BOOLEAN );
- g_value_set_boolean( &val, FALSE );
- g_object_set_property( G_OBJECT(preview), "focus-on-click", &val );
-
-/*
- Gtk::Button *btn = new Gtk::Button(blank);
- Gdk::Color color;
- color.set_rgb((_r << 8)|_r, (_g << 8)|_g, (_b << 8)|_b);
- btn->modify_bg(Gtk::STATE_NORMAL, color);
- btn->modify_bg(Gtk::STATE_ACTIVE, color);
- btn->modify_bg(Gtk::STATE_PRELIGHT, color);
- btn->modify_bg(Gtk::STATE_SELECTED, color);
-
- Gtk::Widget* newBlot = btn;
-*/
-
- tips.set_tip((*newBlot), def.descr);
-
-/*
- newBlot->signal_clicked().connect( sigc::mem_fun(*this, &ColorItem::buttonClicked) );
-
- sigc::signal<void> type_signal_something;
-*/
-
- g_signal_connect( G_OBJECT(newBlot->gobj()),
- "clicked",
- G_CALLBACK(handleClick),
- this);
-
- g_signal_connect( G_OBJECT(newBlot->gobj()),
- "alt-clicked",
- G_CALLBACK(handleSecondaryClick),
- this);
-
- g_signal_connect( G_OBJECT(newBlot->gobj()),
- "button-press-event",
- G_CALLBACK(handleButtonPress),
- this);
-
- gtk_drag_source_set( GTK_WIDGET(newBlot->gobj()),
- GDK_BUTTON1_MASK,
- sourceColorEntries,
- G_N_ELEMENTS(sourceColorEntries),
- GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY) );
-
- g_signal_connect( G_OBJECT(newBlot->gobj()),
- "drag-data-get",
- G_CALLBACK(ColorItem::_dragGetColorData),
- this);
-
- g_signal_connect( G_OBJECT(newBlot->gobj()),
- "drag-begin",
- G_CALLBACK(dragBegin),
- this );
-
- g_signal_connect( G_OBJECT(newBlot->gobj()),
- "enter-notify-event",
- G_CALLBACK(handleEnterNotify),
- this);
-
- g_signal_connect( G_OBJECT(newBlot->gobj()),
- "leave-notify-event",
- G_CALLBACK(handleLeaveNotify),
- this);
-
-// g_signal_connect( G_OBJECT(newBlot->gobj()),
-// "drag-drop",
-// G_CALLBACK(dragDropColorData),
-// this);
-
- if ( def.isEditable() )
- {
- gtk_drag_dest_set( GTK_WIDGET(newBlot->gobj()),
- GTK_DEST_DEFAULT_ALL,
- destColorTargets,
- G_N_ELEMENTS(destColorTargets),
- GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE) );
-
-
- g_signal_connect( G_OBJECT(newBlot->gobj()),
- "drag-data-received",
- G_CALLBACK(_dropDataIn),
- this );
- }
-
- g_signal_connect( G_OBJECT(newBlot->gobj()),
- "destroy",
- G_CALLBACK(dieDieDie),
- this);
-
-
- widget = newBlot;
- }
-
- _previews.push_back( widget );
-
- return widget;
-}
-
-void ColorItem::buttonClicked(bool secondary)
-{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (!desktop) return;
- char const * attrName = secondary ? "stroke" : "fill";
-
- gchar c[64];
- if (!_isRemove){
- guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff;
- sp_svg_write_color(c, sizeof(c), rgba);
- }
-
- SPCSSAttr *css = sp_repr_css_attr_new();
- sp_repr_css_set_property( css, attrName, _isRemove ? "none" : c );
- sp_desktop_set_style(desktop, css);
- sp_repr_css_attr_unref(css);
-
- if (_isRemove){
- sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_SWATCHES,
- secondary? _("Remove stroke color") : _("Remove fill color"));
- } else {
- sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_SWATCHES,
- secondary? _("Set stroke color from swatch") : _("Set fill color from swatch"));
- }
-}
-
-static char* trim( char* str ) {
- char* ret = str;
- while ( *str && (*str == ' ' || *str == '\t') ) {
- str++;
- }
- ret = str;
- while ( *str ) {
- str++;
- }
- str--;
- while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) {
- *str-- = 0;
- }
- return ret;
-}
-
-void skipWhitespace( char*& str ) {
- while ( *str == ' ' || *str == '\t' ) {
- str++;
- }
-}
-
-bool parseNum( char*& str, int& val ) {
- val = 0;
- while ( '0' <= *str && *str <= '9' ) {
- val = val * 10 + (*str - '0');
- str++;
- }
- bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n');
- return retval;
-}
-
-
-static bool getBlock( std::string& dst, guchar ch, std::string const str )
-{
- bool good = false;
- std::string::size_type pos = str.find(ch);
- if ( pos != std::string::npos )
- {
- std::string::size_type pos2 = str.find( '(', pos );
- if ( pos2 != std::string::npos ) {
- std::string::size_type endPos = str.find( ')', pos2 );
- if ( endPos != std::string::npos ) {
- dst = str.substr( pos2 + 1, (endPos - pos2 - 1) );
- good = true;
- }
- }
- }
- return good;
-}
-
-static bool popVal( guint64& numVal, std::string& str )
-{
- bool good = false;
- std::string::size_type endPos = str.find(',');
- if ( endPos == std::string::npos ) {
- endPos = str.length();
- }
-
- if ( endPos != std::string::npos && endPos > 0 ) {
- std::string xxx = str.substr( 0, endPos );
- const gchar* ptr = xxx.c_str();
- gchar* endPtr = 0;
- numVal = g_ascii_strtoull( ptr, &endPtr, 10 );
- if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) {
- // overflow
- } else if ( (numVal == 0) && (endPtr == ptr) ) {
- // failed conversion
- } else {
- good = true;
- str.erase( 0, endPos + 1 );
- }
- }
-
- return good;
-}
-
-void ColorItem::_wireMagicColors( void* p )
-{
- JustForNow* onceMore = reinterpret_cast<JustForNow*>(p);
- if ( onceMore )
- {
- for ( std::vector<ColorItem*>::iterator it = onceMore->_colors.begin(); it != onceMore->_colors.end(); ++it )
- {
- std::string::size_type pos = (*it)->def.descr.find("*{");
- if ( pos != std::string::npos )
- {
- std::string subby = (*it)->def.descr.substr( pos + 2 );
- std::string::size_type endPos = subby.find("}*");
- if ( endPos != std::string::npos )
- {
- subby.erase( endPos );
- //g_message("FOUND MAGIC at '%s'", (*it)->def.descr.c_str());
- //g_message(" '%s'", subby.c_str());
-
- if ( subby.find('E') != std::string::npos )
- {
- (*it)->def.setEditable( true );
- }
-
- if ( subby.find('L') != std::string::npos )
- {
- (*it)->_isLive = true;
- }
-
- std::string part;
- // Tint. index + 1 more val.
- if ( getBlock( part, 'T', subby ) ) {
- guint64 colorIndex = 0;
- if ( popVal( colorIndex, part ) ) {
- guint64 percent = 0;
- if ( popVal( percent, part ) ) {
- (*it)->_linkTint( *(onceMore->_colors[colorIndex]), percent );
- }
- }
- }
-
- // Shade/tone. index + 1 or 2 more val.
- if ( getBlock( part, 'S', subby ) ) {
- guint64 colorIndex = 0;
- if ( popVal( colorIndex, part ) ) {
- guint64 percent = 0;
- if ( popVal( percent, part ) ) {
- guint64 grayLevel = 0;
- if ( !popVal( grayLevel, part ) ) {
- grayLevel = 0;
- }
- (*it)->_linkTone( *(onceMore->_colors[colorIndex]), percent, grayLevel );
- }
- }
- }
-
- }
- }
- }
- }
-}
-
-
-void ColorItem::_linkTint( ColorItem& other, int percent )
-{
- if ( !_linkSrc )
- {
- other._listeners.push_back(this);
- _linkIsTone = false;
- _linkPercent = percent;
- if ( _linkPercent > 100 )
- _linkPercent = 100;
- if ( _linkPercent < 0 )
- _linkPercent = 0;
- _linkGray = 0;
- _linkSrc = &other;
-
- ColorItem::_colorDefChanged(&other);
- }
-}
-
-void ColorItem::_linkTone( ColorItem& other, int percent, int grayLevel )
-{
- if ( !_linkSrc )
- {
- other._listeners.push_back(this);
- _linkIsTone = true;
- _linkPercent = percent;
- if ( _linkPercent > 100 )
- _linkPercent = 100;
- if ( _linkPercent < 0 )
- _linkPercent = 0;
- _linkGray = grayLevel;
- _linkSrc = &other;
-
- ColorItem::_colorDefChanged(&other);
- }
-}
-
-
-void _loadPaletteFile( gchar const *filename )
-{
- char block[1024];
- FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" );
- if ( f ) {
- char* result = fgets( block, sizeof(block), f );
- if ( result ) {
- if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) {
- bool inHeader = true;
- bool hasErr = false;
-
- JustForNow *onceMore = new JustForNow();
-
- do {
- result = fgets( block, sizeof(block), f );
- block[sizeof(block) - 1] = 0;
- if ( result ) {
- if ( block[0] == '#' ) {
- // ignore comment
- } else {
- char *ptr = block;
- // very simple check for header versus entry
- while ( *ptr == ' ' || *ptr == '\t' ) {
- ptr++;
- }
- if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) {
- // blank line. skip it.
- } else if ( '0' <= *ptr && *ptr <= '9' ) {
- // should be an entry link
- inHeader = false;
- ptr = block;
- Glib::ustring name("");
- int r = 0;
- int g = 0;
- int b = 0;
- skipWhitespace(ptr);
- if ( *ptr ) {
- hasErr = parseNum(ptr, r);
- if ( !hasErr ) {
- skipWhitespace(ptr);
- hasErr = parseNum(ptr, g);
- }
- if ( !hasErr ) {
- skipWhitespace(ptr);
- hasErr = parseNum(ptr, b);
- }
- if ( !hasErr && *ptr ) {
- char* n = trim(ptr);
- if (n != NULL) {
- name = n;
- }
- }
- if ( !hasErr ) {
- // Add the entry now
- Glib::ustring nameStr(name);
- ColorItem* item = new ColorItem( r, g, b, nameStr );
- onceMore->_colors.push_back(item);
- }
- } else {
- hasErr = true;
- }
- } else {
- if ( !inHeader ) {
- // Hmmm... probably bad. Not quite the format we want?
- hasErr = true;
- } else {
- char* sep = strchr(result, ':');
- if ( sep ) {
- *sep = 0;
- char* val = trim(sep + 1);
- char* name = trim(result);
- if ( *name ) {
- if ( strcmp( "Name", name ) == 0 )
- {
- onceMore->_name = val;
- }
- else if ( strcmp( "Columns", name ) == 0 )
- {
- gchar* endPtr = 0;
- guint64 numVal = g_ascii_strtoull( val, &endPtr, 10 );
- if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) {
- // overflow
- } else if ( (numVal == 0) && (endPtr == val) ) {
- // failed conversion
- } else {
- onceMore->_prefWidth = numVal;
- }
- }
- } else {
- // error
- hasErr = true;
- }
- } else {
- // error
- hasErr = true;
- }
- }
- }
- }
- }
- } while ( result && !hasErr );
- if ( !hasErr ) {
- possible.push_back(onceMore);
-#if ENABLE_MAGIC_COLORS
- ColorItem::_wireMagicColors( onceMore );
-#endif // ENABLE_MAGIC_COLORS
- } else {
- delete onceMore;
- }
- }
- }
-
- fclose(f);
- }
-}
-
-static void loadEmUp()
-{
- static bool beenHere = false;
- if ( !beenHere ) {
- beenHere = true;
-
- std::list<gchar *> sources;
- sources.push_back( profile_path("palettes") );
- sources.push_back( g_strdup(INKSCAPE_PALETTESDIR) );
- sources.push_back( g_strdup(CREATE_PALETTESDIR) );
-
- // Use this loop to iterate through a list of possible document locations.
- while (!sources.empty()) {
- gchar *dirname = sources.front();
-
- if ( Inkscape::IO::file_test( dirname, G_FILE_TEST_EXISTS )
- && Inkscape::IO::file_test( dirname, G_FILE_TEST_IS_DIR )) {
- GError *err = 0;
- GDir *directory = g_dir_open(dirname, 0, &err);
- if (!directory) {
- gchar *safeDir = Inkscape::IO::sanitizeString(dirname);
- g_warning(_("Palettes directory (%s) is unavailable."), safeDir);
- g_free(safeDir);
- } else {
- gchar *filename = 0;
- while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) {
- gchar* lower = g_ascii_strdown( filename, -1 );
-// if ( g_str_has_suffix(lower, ".gpl") ) {
- gchar* full = g_build_filename(dirname, filename, NULL);
- if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) {
- _loadPaletteFile(full);
- }
- g_free(full);
-// }
- g_free(lower);
- }
- g_dir_close(directory);
- }
- }
-
- // toss the dirname
- g_free(dirname);
- sources.pop_front();
- }
- }
-}
-
-
-
-
-
-
-
-
-
-SwatchesPanel& SwatchesPanel::getInstance()
-{
- return *new SwatchesPanel();
-}
-
-
-/**
- * Constructor
- */
-SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
- Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, "", true),
- _holder(0)
-{
- Gtk::RadioMenuItem* hotItem = 0;
- _holder = new PreviewHolder();
- _remove = new ColorItem();
- loadEmUp();
- if ( !possible.empty() ) {
- JustForNow* first = 0;
- Glib::ustring targetName;
- if ( !_prefs_path.empty() ) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- targetName = prefs->getString(_prefs_path + "/palette");
- if (!targetName.empty()) {
- for ( std::vector<JustForNow*>::iterator iter = possible.begin(); iter != possible.end(); ++iter ) {
- if ( (*iter)->_name == targetName ) {
- first = *iter;
- break;
- }
- }
- }
- }
-
- if ( !first ) {
- first = possible.front();
- }
-
- if ( first->_prefWidth > 0 ) {
- _holder->setColumnPref( first->_prefWidth );
- }
- _holder->freezeUpdates();
- _holder->addPreview(_remove);
- for ( std::vector<ColorItem*>::iterator it = first->_colors.begin(); it != first->_colors.end(); it++ ) {
- _holder->addPreview(*it);
- }
- _holder->thawUpdates();
-
- Gtk::RadioMenuItem::Group groupOne;
-
- int i = 0;
- for ( std::vector<JustForNow*>::iterator it = possible.begin(); it != possible.end(); it++ ) {
- JustForNow* curr = *it;
- Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, curr->_name));
- if ( curr == first ) {
- hotItem = single;
- }
- _regItem( single, 3, i );
- i++;
- }
- }
-
-
- _getContents()->pack_start(*_holder, Gtk::PACK_EXPAND_WIDGET);
- _setTargetFillable(_holder);
-
- show_all_children();
-
- restorePanelPrefs();
- if ( hotItem ) {
- hotItem->set_active();
- }
-}
-
-SwatchesPanel::~SwatchesPanel()
-{
- if (_remove) delete _remove;
- if (_holder) delete _holder;
-}
-
-void SwatchesPanel::setOrientation( Gtk::AnchorType how )
-{
- // Must call the parent class or bad things might happen
- Inkscape::UI::Widget::Panel::setOrientation( how );
-
- if ( _holder )
- {
- _holder->setOrientation( Gtk::ANCHOR_SOUTH );
- }
-}
-
-void SwatchesPanel::_handleAction( int setId, int itemId )
-{
- switch( setId ) {
- case 3:
- {
- if ( itemId >= 0 && itemId < static_cast<int>(possible.size()) ) {
- _holder->clear();
- JustForNow* curr = possible[itemId];
-
- if ( !_prefs_path.empty() ) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setString(_prefs_path + "/palette", curr->_name);
- }
-
- if ( curr->_prefWidth > 0 ) {
- _holder->setColumnPref( curr->_prefWidth );
- }
- _holder->freezeUpdates();
- _holder->addPreview(_remove);
- for ( std::vector<ColorItem*>::iterator it = curr->_colors.begin(); it != curr->_colors.end(); it++ ) {
- _holder->addPreview(*it);
- }
- _holder->thawUpdates();
- }
- }
- break;
- }
-}
-
-} //namespace Dialogs
-} //namespace UI
-} //namespace Inkscape
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/swatches.h b/src/dialogs/swatches.h
--- a/src/dialogs/swatches.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/** @file
- * @brief Color swatches dialog
- */
-/* Authors:
- * Jon A. Cruz
- *
- * Copyright (C) 2005 Jon A. Cruz
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-#ifndef SEEN_DIALOGS_SWATCHES_H
-#define SEEN_DIALOGS_SWATCHES_H
-
-#include <gtkmm/textview.h>
-#include <gtkmm/tooltips.h>
-
-#include "ui/widget/panel.h"
-#include "ui/previewholder.h"
-#include "dialogs/eek-color-def.h"
-
-using eek::ColorDef;
-
-namespace Inkscape {
-namespace UI {
-namespace Dialogs {
-
-
-void _loadPaletteFile( gchar const *filename );
-
-/**
- * The color swatch you see on screen as a clickable box.
- */
-class ColorItem : public Inkscape::UI::Previewable
-{
- friend void _loadPaletteFile( gchar const *filename );
-public:
- ColorItem();
- ColorItem( unsigned int r, unsigned int g, unsigned int b,
- Glib::ustring& name );
- virtual ~ColorItem();
- ColorItem(ColorItem const &other);
- virtual ColorItem &operator=(ColorItem const &other);
- virtual Gtk::Widget* getPreview(PreviewStyle style,
- ViewType view,
- ::PreviewSize size,
- guint ratio);
- void buttonClicked(bool secondary = false);
- bool isRemove(){ return _isRemove; }
- ColorDef def;
-
-private:
- static void _dropDataIn( GtkWidget *widget,
- GdkDragContext *drag_context,
- gint x, gint y,
- GtkSelectionData *data,
- guint info,
- guint event_time,
- gpointer user_data);
-
- static void _dragGetColorData( GtkWidget *widget,
- GdkDragContext *drag_context,
- GtkSelectionData *data,
- guint info,
- guint time,
- gpointer user_data);
-
- static void _wireMagicColors( void* p );
- static void _colorDefChanged(void* data);
-
- void _linkTint( ColorItem& other, int percent );
- void _linkTone( ColorItem& other, int percent, int grayLevel );
-
- Gtk::Tooltips tips;
- std::vector<Gtk::Widget*> _previews;
-
- bool _isRemove;
- bool _isLive;
- bool _linkIsTone;
- int _linkPercent;
- int _linkGray;
- ColorItem* _linkSrc;
- std::vector<ColorItem*> _listeners;
-};
-
-class RemoveColorItem;
-
-/**
- * A panel that displays color swatches.
- */
-class SwatchesPanel : public Inkscape::UI::Widget::Panel
-{
-public:
- SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches");
- virtual ~SwatchesPanel();
-
- static SwatchesPanel& getInstance();
- virtual void setOrientation( Gtk::AnchorType how );
-
-protected:
- virtual void _handleAction( int setId, int itemId );
-
-private:
- SwatchesPanel(SwatchesPanel const &); // no copy
- SwatchesPanel &operator=(SwatchesPanel const &); // no assign
-
- static SwatchesPanel* instance;
-
- PreviewHolder* _holder;
- ColorItem* _remove;
-};
-
-} //namespace Dialogs
-} //namespace UI
-} //namespace Inkscape
-
-
-
-#endif // SEEN_SWATCHES_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/unclump.cpp b/src/dialogs/unclump.cpp
--- a/src/dialogs/unclump.cpp
+++ /dev/null
@@ -1,388 +0,0 @@
-/** @file
- * @brief Unclumping objects
- */
-/* Authors:
- * bulia byak
- *
- * Copyright (C) 2005 Authors
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <algorithm>
-#include <map>
-#include "sp-item.h"
-
-
-// Taking bbox of an item is an expensive operation, and we need to do it many times, so here we
-// cache the centers, widths, and heights of items
-
-//FIXME: make a class with these cashes as members instead of globals
-std::map<const gchar *, Geom::Point> c_cache;
-std::map<const gchar *, Geom::Point> wh_cache;
-
-/**
-Center of bbox of item
-*/
-Geom::Point
-unclump_center (SPItem *item)
-{
- std::map<const gchar *, Geom::Point>::iterator i = c_cache.find(SP_OBJECT_ID(item));
- if ( i != c_cache.end() ) {
- return i->second;
- }
-
- Geom::OptRect r = item->getBounds(sp_item_i2d_affine(item));
- if (r) {
- Geom::Point const c = r->midpoint();
- c_cache[SP_OBJECT_ID(item)] = c;
- return c;
- } else {
- // FIXME
- return Geom::Point(0, 0);
- }
-}
-
-Geom::Point
-unclump_wh (SPItem *item)
-{
- Geom::Point wh;
- std::map<const gchar *, Geom::Point>::iterator i = wh_cache.find(SP_OBJECT_ID(item));
- if ( i != wh_cache.end() ) {
- wh = i->second;
- } else {
- Geom::OptRect r = item->getBounds(sp_item_i2d_affine(item));
- if (r) {
- wh = r->dimensions();
- wh_cache[SP_OBJECT_ID(item)] = wh;
- } else {
- wh = Geom::Point(0, 0);
- }
- }
-
- return wh;
-}
-
-/**
-Distance between "edges" of item1 and item2. An item is considered to be an ellipse inscribed into its w/h,
-so its radius (distance from center to edge) depends on the w/h and the angle towards the other item.
-May be negative if the edge of item1 is between the center and the edge of item2.
-*/
-double
-unclump_dist (SPItem *item1, SPItem *item2)
-{
- Geom::Point c1 = unclump_center (item1);
- Geom::Point c2 = unclump_center (item2);
-
- Geom::Point wh1 = unclump_wh (item1);
- Geom::Point wh2 = unclump_wh (item2);
-
- // angle from each item's center to the other's, unsqueezed by its w/h, normalized to 0..pi/2
- double a1 = atan2 ((c2 - c1)[Geom::Y], (c2 - c1)[Geom::X] * wh1[Geom::Y]/wh1[Geom::X]);
- a1 = fabs (a1);
- if (a1 > M_PI/2) a1 = M_PI - a1;
-
- double a2 = atan2 ((c1 - c2)[Geom::Y], (c1 - c2)[Geom::X] * wh2[Geom::Y]/wh2[Geom::X]);
- a2 = fabs (a2);
- if (a2 > M_PI/2) a2 = M_PI - a2;
-
- // get the radius of each item for the given angle
- double r1 = 0.5 * (wh1[Geom::X] + (wh1[Geom::Y] - wh1[Geom::X]) * (a1/(M_PI/2)));
- double r2 = 0.5 * (wh2[Geom::X] + (wh2[Geom::Y] - wh2[Geom::X]) * (a2/(M_PI/2)));
-
- // dist between centers minus angle-adjusted radii
- double dist_r = (Geom::L2 (c2 - c1) - r1 - r2);
-
- double stretch1 = wh1[Geom::Y]/wh1[Geom::X];
- double stretch2 = wh2[Geom::Y]/wh2[Geom::X];
-
- if ((stretch1 > 1.5 || stretch1 < 0.66) && (stretch2 > 1.5 || stretch2 < 0.66)) {
-
- std::vector<double> dists;
- dists.push_back (dist_r);
-
- // If both objects are not circle-like, find dists between four corners
- std::vector<Geom::Point> c1_points(2);
- {
- double y_closest;
- if (c2[Geom::Y] > c1[Geom::Y] + wh1[Geom::Y]/2) {
- y_closest = c1[Geom::Y] + wh1[Geom::Y]/2;
- } else if (c2[Geom::Y] < c1[Geom::Y] - wh1[Geom::Y]/2) {
- y_closest = c1[Geom::Y] - wh1[Geom::Y]/2;
- } else {
- y_closest = c2[Geom::Y];
- }
- c1_points[0] = Geom::Point (c1[Geom::X], y_closest);
- double x_closest;
- if (c2[Geom::X] > c1[Geom::X] + wh1[Geom::X]/2) {
- x_closest = c1[Geom::X] + wh1[Geom::X]/2;
- } else if (c2[Geom::X] < c1[Geom::X] - wh1[Geom::X]/2) {
- x_closest = c1[Geom::X] - wh1[Geom::X]/2;
- } else {
- x_closest = c2[Geom::X];
- }
- c1_points[1] = Geom::Point (x_closest, c1[Geom::Y]);
- }
-
-
- std::vector<Geom::Point> c2_points(2);
- {
- double y_closest;
- if (c1[Geom::Y] > c2[Geom::Y] + wh2[Geom::Y]/2) {
- y_closest = c2[Geom::Y] + wh2[Geom::Y]/2;
- } else if (c1[Geom::Y] < c2[Geom::Y] - wh2[Geom::Y]/2) {
- y_closest = c2[Geom::Y] - wh2[Geom::Y]/2;
- } else {
- y_closest = c1[Geom::Y];
- }
- c2_points[0] = Geom::Point (c2[Geom::X], y_closest);
- double x_closest;
- if (c1[Geom::X] > c2[Geom::X] + wh2[Geom::X]/2) {
- x_closest = c2[Geom::X] + wh2[Geom::X]/2;
- } else if (c1[Geom::X] < c2[Geom::X] - wh2[Geom::X]/2) {
- x_closest = c2[Geom::X] - wh2[Geom::X]/2;
- } else {
- x_closest = c1[Geom::X];
- }
- c2_points[1] = Geom::Point (x_closest, c2[Geom::Y]);
- }
-
- for (int i = 0; i < 2; i ++) {
- for (int j = 0; j < 2; j ++) {
- dists.push_back (Geom::L2 (c1_points[i] - c2_points[j]));
- }
- }
-
- // return the minimum of all dists
- return *std::min_element(dists.begin(), dists.end());
- } else {
- return dist_r;
- }
-}
-
-/**
-Average unclump_dist from item to others
-*/
-double unclump_average (SPItem *item, GSList *others)
-{
- int n = 0;
- double sum = 0;
-
- for (GSList *i = others; i != NULL; i = i->next) {
- SPItem *other = SP_ITEM (i->data);
-
- if (other == item)
- continue;
-
- n++;
- sum += unclump_dist (item, other);
- }
-
- if (n != 0)
- return sum/n;
- else
- return 0;
-}
-
-/**
-Closest to item among others
- */
-SPItem *unclump_closest (SPItem *item, GSList *others)
-{
- double min = HUGE_VAL;
- SPItem *closest = NULL;
-
- for (GSList *i = others; i != NULL; i = i->next) {
- SPItem *other = SP_ITEM (i->data);
-
- if (other == item)
- continue;
-
- double dist = unclump_dist (item, other);
- if (dist < min && fabs (dist) < 1e6) {
- min = dist;
- closest = other;
- }
- }
-
- return closest;
-}
-
-/**
-Most distant from item among others
- */
-SPItem *unclump_farest (SPItem *item, GSList *others)
-{
- double max = -HUGE_VAL;
- SPItem *farest = NULL;
-
- for (GSList *i = others; i != NULL; i = i->next) {
- SPItem *other = SP_ITEM (i->data);
-
- if (other == item)
- continue;
-
- double dist = unclump_dist (item, other);
- if (dist > max && fabs (dist) < 1e6) {
- max = dist;
- farest = other;
- }
- }
-
- return farest;
-}
-
-/**
-Removes from the \a rest list those items that are "behind" \a closest as seen from \a item,
-i.e. those on the other side of the line through \a closest perpendicular to the direction from \a
-item to \a closest. Returns a newly created list which must be freed.
- */
-GSList *
-unclump_remove_behind (SPItem *item, SPItem *closest, GSList *rest)
-{
- Geom::Point it = unclump_center (item);
- Geom::Point p1 = unclump_center (closest);
-
- // perpendicular through closest to the direction to item:
- Geom::Point perp = Geom::rot90(it - p1);
- Geom::Point p2 = p1 + perp;
-
- // get the standard Ax + By + C = 0 form for p1-p2:
- double A = p1[Geom::Y] - p2[Geom::Y];
- double B = p2[Geom::X] - p1[Geom::X];
- double C = p2[Geom::Y] * p1[Geom::X] - p1[Geom::Y] * p2[Geom::X];
-
- // substitute the item into it:
- double val_item = A * it[Geom::X] + B * it[Geom::Y] + C;
-
- GSList *out = NULL;
-
- for (GSList *i = rest; i != NULL; i = i->next) {
- SPItem *other = SP_ITEM (i->data);
-
- if (other == item)
- continue;
-
- Geom::Point o = unclump_center (other);
- double val_other = A * o[Geom::X] + B * o[Geom::Y] + C;
-
- if (val_item * val_other <= 1e-6) {
- // different signs, which means item and other are on the different sides of p1-p2 line; skip
- } else {
- out = g_slist_prepend (out, other);
- }
- }
-
- return out;
-}
-
-/**
-Moves \a what away from \a from by \a dist
- */
-void
-unclump_push (SPItem *from, SPItem *what, double dist)
-{
- Geom::Point it = unclump_center (what);
- Geom::Point p = unclump_center (from);
- Geom::Point by = dist * Geom::unit_vector (- (p - it));
-
- Geom::Matrix move = Geom::Translate (by);
-
- std::map<const gchar *, Geom::Point>::iterator i = c_cache.find(SP_OBJECT_ID(what));
- if ( i != c_cache.end() ) {
- i->second *= move;
- }
-
- //g_print ("push %s at %g,%g from %g,%g by %g,%g, dist %g\n", SP_OBJECT_ID(what), it[Geom::X],it[Geom::Y], p[Geom::X],p[Geom::Y], by[Geom::X],by[Geom::Y], dist);
-
- sp_item_set_i2d_affine(what, sp_item_i2d_affine(what) * move);
- sp_item_write_transform(what, SP_OBJECT_REPR(what), what->transform, NULL);
-}
-
-/**
-Moves \a what towards \a to by \a dist
- */
-void
-unclump_pull (SPItem *to, SPItem *what, double dist)
-{
- Geom::Point it = unclump_center (what);
- Geom::Point p = unclump_center (to);
- Geom::Point by = dist * Geom::unit_vector (p - it);
-
- Geom::Matrix move = Geom::Translate (by);
-
- std::map<const gchar *, Geom::Point>::iterator i = c_cache.find(SP_OBJECT_ID(what));
- if ( i != c_cache.end() ) {
- i->second *= move;
- }
-
- //g_print ("pull %s at %g,%g to %g,%g by %g,%g, dist %g\n", SP_OBJECT_ID(what), it[Geom::X],it[Geom::Y], p[Geom::X],p[Geom::Y], by[Geom::X],by[Geom::Y], dist);
-
- sp_item_set_i2d_affine(what, sp_item_i2d_affine(what) * move);
- sp_item_write_transform(what, SP_OBJECT_REPR(what), what->transform, NULL);
-}
-
-
-/**
-Unclumps the items in \a items, reducing local unevenness in their distribution. Produces an effect
-similar to "engraver dots". The only distribution which is unchanged by unclumping is a hexagonal
-grid. May be called repeatedly for stronger effect.
- */
-void
-unclump (GSList *items)
-{
- c_cache.clear();
- wh_cache.clear();
-
- for (GSList *i = items; i != NULL; i = i->next) { // for each original/clone x:
- SPItem *item = SP_ITEM (i->data);
-
- GSList *nei = NULL;
-
- GSList *rest = g_slist_copy (items);
- rest = g_slist_remove (rest, item);
-
- while (rest != NULL) {
- SPItem *closest = unclump_closest (item, rest);
- if (closest) {
- nei = g_slist_prepend (nei, closest);
- rest = g_slist_remove (rest, closest);
- GSList *new_rest = unclump_remove_behind (item, closest, rest);
- g_slist_free (rest);
- rest = new_rest;
- } else {
- g_slist_free (rest);
- break;
- }
- }
-
- if (g_slist_length (nei) >= 2) {
- double ave = unclump_average (item, nei);
-
- SPItem *closest = unclump_closest (item, nei);
- SPItem *farest = unclump_farest (item, nei);
-
- double dist_closest = unclump_dist (closest, item);
- double dist_farest = unclump_dist (farest, item);
-
- //g_print ("NEI %d for item %s closest %s at %g farest %s at %g ave %g\n", g_slist_length(nei), SP_OBJECT_ID(item), SP_OBJECT_ID(closest), dist_closest, SP_OBJECT_ID(farest), dist_farest, ave);
-
- if (fabs (ave) < 1e6 && fabs (dist_closest) < 1e6 && fabs (dist_farest) < 1e6) { // otherwise the items are bogus
- // increase these coefficients to make unclumping more aggressive and less stable
- // the pull coefficient is a bit bigger to counteract the long-term expansion trend
- unclump_push (closest, item, 0.3 * (ave - dist_closest));
- unclump_pull (farest, item, 0.35 * (dist_farest - ave));
- }
- }
- }
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/dialogs/unclump.h b/src/dialogs/unclump.h
--- a/src/dialogs/unclump.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/** @file
- * @brief Unclumping objects
- */
-/* Authors:
- * bulia byak
- *
- * Copyright (C) 2005 Authors
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_DIALOGS_UNCLUMP_H
-#define SEEN_DIALOGS_UNCLUMP_H
-
-#include <glib/gslist.h>
-
-void unclump(GSList *items);
-
-#endif /* !UNCLUMP_H_SEEN */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 65ae9a8a32c06253c095c8e3335e662d98f7360d..cf3599517b0318c44a9ade94a538ccb537bab0d4 100644 (file)
--- a/src/dialogs/xml-tree.cpp
+++ b/src/dialogs/xml-tree.cpp
#include "../document.h"
#include "../event-context.h"
#include "helper/window.h"
-#include "in-dt-coordsys.h"
#include "../inkscape.h"
#include "../interface.h"
#include "macros.h"
static gboolean sp_xml_tree_key_press(GtkWidget *widget, GdkEventKey *event);
+static bool in_dt_coordsys(SPObject const &item);
/*
* \brief Sets the XML status bar when the tree is selected.
} // end of cmd_unindent_node()
+/** Returns true iff \a item is suitable to be included in the selection, in particular
+ whether it has a bounding box in the desktop coordinate system for rendering resize handles.
+
+ Descendents of <defs> nodes (markers etc.) return false, for example.
+*/
+bool in_dt_coordsys(SPObject const &item)
+{
+ /* Definition based on sp_item_i2doc_affine. */
+ SPObject const *child = &item;
+ g_return_val_if_fail(child != NULL, false);
+ for(;;) {
+ if (!SP_IS_ITEM(child)) {
+ return false;
+ }
+ SPObject const * const parent = SP_OBJECT_PARENT(child);
+ if (parent == NULL) {
+ break;
+ }
+ child = parent;
+ }
+ g_assert(SP_IS_ROOT(child));
+ /* Relevance: Otherwise, I'm not sure whether to return true or false. */
+ return true;
+}
+
/*
Local Variables:
diff --git a/src/document.cpp b/src/document.cpp
index 4f54870324b9232fc972ff3897f0ac0b50124826..fe6ce011b9590291894f9c04155bd53385af969d 100644 (file)
--- a/src/document.cpp
+++ b/src/document.cpp
#include <gtk/gtkmain.h>
#include <string>
#include <cstring>
+
#include "application/application.h"
#include "application/editor.h"
-#include "xml/repr.h"
+#include "desktop.h"
+#include "dir-util.h"
+#include "display/nr-arena-item.h"
+#include "document-private.h"
#include "helper/units.h"
#include "inkscape-private.h"
#include "inkscape-version.h"
-#include "sp-object-repr.h"
-#include "sp-namedview.h"
-#include "desktop.h"
-#include "document-private.h"
-#include "dir-util.h"
-#include "unit-constants.h"
-#include "preferences.h"
#include "libavoid/router.h"
-#include "sp-item-group.h"
-#include "profile-manager.h"
#include "persp3d.h"
-
-#include "display/nr-arena-item.h"
-
-#include "dialogs/rdf.h"
-
+#include "preferences.h"
+#include "profile-manager.h"
+#include "rdf.h"
+#include "sp-item-group.h"
+#include "sp-namedview.h"
+#include "sp-object-repr.h"
#include "transf_mat_3x4.h"
+#include "unit-constants.h"
+#include "xml/repr.h"
#define SP_DOCUMENT_UPDATE_PRIORITY (G_PRIORITY_HIGH_IDLE - 1)
index 7e40522b36f77df193eed67f0b5044c9428549be..5a3f8dcd2030fe37f7dacf440d721cb309c046a1 100644 (file)
#include "inkscape.h"
#include "preferences.h"
-#include "dialogs/extensions.h"
+#include "ui/dialog/extensions.h"
#include "extension/extension.h"
#include "error-file.h"
diff --git a/src/file.cpp b/src/file.cpp
index 5c729eeeb65b1032a8c61cb0ca255d6bdbcad34a..396e9095f17b87673d3a12871cd2f1a54f741cd7 100644 (file)
--- a/src/file.cpp
+++ b/src/file.cpp
-#define __SP_FILE_C__
-
-/*
- * File/Print operations
- *
- * Authors:
+/** @file
+ * @brief File/Print operations
+ */
+/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Chema Celorio <chema@celorio.com>
* bulia byak <buliabyak@users.sf.net>
#include <gtk/gtk.h>
#include <glib/gmem.h>
+#include <glibmm/i18n.h>
#include <libnr/nr-pixops.h>
-#include "document-private.h"
-#include "selection-chemistry.h"
-#include "ui/view/view-widget.h"
+#include "application/application.h"
+#include "application/editor.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "dialogs/export.h"
#include "dir-util.h"
+#include "document-private.h"
+#include "extension/db.h"
+#include "extension/input.h"
+#include "extension/output.h"
+#include "extension/system.h"
+#include "file.h"
#include "helper/png-write.h"
-#include "dialogs/export.h"
-#include <glibmm/i18n.h>
+#include "id-clash.h"
+#include "inkscape.h"
#include "inkscape.h"
-#include "desktop.h"
-#include "selection.h"
#include "interface.h"
-#include "style.h"
-#include "print.h"
-#include "file.h"
+#include "io/sys.h"
#include "message.h"
#include "message-stack.h"
-#include "ui/dialog/filedialog.h"
-#include "ui/dialog/ocaldialogs.h"
-#include "preferences.h"
#include "path-prefix.h"
-
+#include "preferences.h"
+#include "print.h"
+#include "rdf.h"
+#include "selection-chemistry.h"
+#include "selection.h"
#include "sp-namedview.h"
-#include "desktop-handles.h"
-
-#include "extension/db.h"
-#include "extension/input.h"
-#include "extension/output.h"
-/* #include "extension/menu.h" */
-#include "extension/system.h"
-
-#include "io/sys.h"
-#include "application/application.h"
-#include "application/editor.h"
-#include "inkscape.h"
+#include "style.h"
+#include "ui/dialog/filedialog.h"
+#include "ui/dialog/ocaldialogs.h"
+#include "ui/view/view-widget.h"
#include "uri.h"
-#include "id-clash.h"
-#include "dialogs/rdf.h"
#ifdef WITH_GNOME_VFS
# include <libgnomevfs/gnome-vfs.h>
index 753b0df45ee1a684ad07e283663ee00cf9e93016..ee17e7079e639a724607ec37e2d45609f088a3c8 100644 (file)
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
#include <sp-root.h>
#include <sp-defs.h>
#include "preferences.h"
-#include "dialogs/rdf.h"
+#include "rdf.h"
/* This is an example of how to use libpng to read and write PNG files.
* The file libpng.txt is much more verbose then this. If you have not
diff --git a/src/rdf.cpp b/src/rdf.cpp
--- /dev/null
+++ b/src/rdf.cpp
@@ -0,0 +1,1023 @@
+/** @file
+ * @brief RDF manipulation functions
+ *
+ * @todo move these to xml/ instead of dialogs/
+ */
+/* Authors:
+ * Kees Cook <kees@outflux.net>
+ * Jon Phillips <jon@rejon.org>
+ *
+ * Copyright (C) 2004 Kees Cook <kees@outflux.net>
+ * Copyright (C) 2006 Jon Phillips <jon@rejon.org>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "xml/repr.h"
+#include "rdf.h"
+#include "sp-item-group.h"
+#include "inkscape.h"
+
+/*
+ Example RDF XML from various places...
+
+<rdf:RDF xmlns="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<Work rdf:about="">
+ <dc:title>title of work</dc:title>
+ <dc:date>year</dc:date>
+ <dc:description>description of work</dc:description>
+ <dc:creator><Agent>
+ <dc:title>creator</dc:title>
+ </Agent></dc:creator>
+ <dc:rights><Agent>
+ <dc:title>holder</dc:title>
+ </Agent></dc:rights>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:source rdf:resource="source"/>
+ <license rdf:resource="http://creativecommons.org/licenses/by/2.0/"
+/>
+</Work>
+
+
+ <rdf:RDF xmlns="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <Work rdf:about="">
+ <dc:title>SVG Road Signs</dc:title>
+ <dc:rights><Agent>
+ <dc:title>John Cliff</dc:title>
+ </Agent></dc:rights>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <license rdf:resource="http://creativecommons.org/ns#PublicDomain" />
+ </Work>
+
+ <License rdf:about="http://creativecommons.org/ns#PublicDomain">
+ <permits rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <permits rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ </License>
+
+</rdf:RDF>
+
+
+Bag example:
+
+<dc:subject>
+<rdf:Bag>
+<rdf:li>open clip art logo</rdf:li>
+<rdf:li>images</rdf:li>
+<rdf:li>logo</rdf:li>
+<rdf:li>clip art</rdf:li>
+<rdf:li>ocal</rdf:li>
+<rdf:li>logotype</rdf:li>
+<rdf:li>filetype</rdf:li>
+</rdf:Bag>
+</dc:subject>
+*/
+
+struct rdf_double_t rdf_license_empty [] = {
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a [] = {
+ { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
+ { "cc:permits", "http://creativecommons.org/ns#Distribution", },
+ { "cc:requires", "http://creativecommons.org/ns#Notice", },
+ { "cc:requires", "http://creativecommons.org/ns#Attribution", },
+ { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_sa [] = {
+ { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
+ { "cc:permits", "http://creativecommons.org/ns#Distribution", },
+ { "cc:requires", "http://creativecommons.org/ns#Notice", },
+ { "cc:requires", "http://creativecommons.org/ns#Attribution", },
+ { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
+ { "cc:requires", "http://creativecommons.org/ns#ShareAlike", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_nd [] = {
+ { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
+ { "cc:permits", "http://creativecommons.org/ns#Distribution", },
+ { "cc:requires", "http://creativecommons.org/ns#Notice", },
+ { "cc:requires", "http://creativecommons.org/ns#Attribution", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_nc [] = {
+ { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
+ { "cc:permits", "http://creativecommons.org/ns#Distribution", },
+ { "cc:requires", "http://creativecommons.org/ns#Notice", },
+ { "cc:requires", "http://creativecommons.org/ns#Attribution", },
+ { "cc:prohibits", "http://creativecommons.org/ns#CommercialUse", },
+ { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_nc_sa [] = {
+ { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
+ { "cc:permits", "http://creativecommons.org/ns#Distribution", },
+ { "cc:requires", "http://creativecommons.org/ns#Notice", },
+ { "cc:requires", "http://creativecommons.org/ns#Attribution", },
+ { "cc:prohibits", "http://creativecommons.org/ns#CommercialUse", },
+ { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
+ { "cc:requires", "http://creativecommons.org/ns#ShareAlike", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_nc_nd [] = {
+ { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
+ { "cc:permits", "http://creativecommons.org/ns#Distribution", },
+ { "cc:requires", "http://creativecommons.org/ns#Notice", },
+ { "cc:requires", "http://creativecommons.org/ns#Attribution", },
+ { "cc:prohibits", "http://creativecommons.org/ns#CommercialUse", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_pd [] = {
+ { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
+ { "cc:permits", "http://creativecommons.org/ns#Distribution", },
+ { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_freeart [] = {
+ { "cc:permits", "http://creativecommons.org/ns#Reproduction", },
+ { "cc:permits", "http://creativecommons.org/ns#Distribution", },
+ { "cc:permits", "http://creativecommons.org/ns#DerivativeWorks", },
+ { "cc:requires", "http://creativecommons.org/ns#ShareAlike", },
+ { "cc:requires", "http://creativecommons.org/ns#Notice", },
+ { "cc:requires", "http://creativecommons.org/ns#Attribution", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_ofl [] = {
+ { "cc:permits", "http://scripts.sil.org/pub/OFL/Reproduction", },
+ { "cc:permits", "http://scripts.sil.org/pub/OFL/Distribution", },
+ { "cc:permits", "http://scripts.sil.org/pub/OFL/Embedding", },
+ { "cc:permits", "http://scripts.sil.org/pub/OFL/DerivativeWorks", },
+ { "cc:requires", "http://scripts.sil.org/pub/OFL/Notice", },
+ { "cc:requires", "http://scripts.sil.org/pub/OFL/Attribution", },
+ { "cc:requires", "http://scripts.sil.org/pub/OFL/ShareAlike", },
+ { "cc:requires", "http://scripts.sil.org/pub/OFL/DerivativeRenaming", },
+ { "cc:requires", "http://scripts.sil.org/pub/OFL/BundlingWhenSelling", },
+ { NULL, NULL }
+};
+
+struct rdf_license_t rdf_licenses [] = {
+ { N_("CC Attribution"),
+ "http://creativecommons.org/licenses/by/3.0/",
+ rdf_license_cc_a,
+ },
+
+ { N_("CC Attribution-ShareAlike"),
+ "http://creativecommons.org/licenses/by-sa/3.0/",
+ rdf_license_cc_a_sa,
+ },
+
+ { N_("CC Attribution-NoDerivs"),
+ "http://creativecommons.org/licenses/by-nd/3.0/",
+ rdf_license_cc_a_nd,
+ },
+
+ { N_("CC Attribution-NonCommercial"),
+ "http://creativecommons.org/licenses/by-nc/3.0/",
+ rdf_license_cc_a_nc,
+ },
+
+ { N_("CC Attribution-NonCommercial-ShareAlike"),
+ "http://creativecommons.org/licenses/by-nc-sa/3.0/",
+ rdf_license_cc_a_nc_sa,
+ },
+
+ { N_("CC Attribution-NonCommercial-NoDerivs"),
+ "http://creativecommons.org/licenses/by-nc-nd/3.0/",
+ rdf_license_cc_a_nc_nd,
+ },
+
+ { N_("Public Domain"),
+ "http://creativecommons.org/licenses/publicdomain/",
+ rdf_license_pd,
+ },
+
+ { N_("FreeArt"),
+ "http://artlibre.org/licence.php/lalgb.html",
+ rdf_license_freeart,
+ },
+
+ { N_("Open Font License"),
+ "http://scripts.sil.org/OFL",
+ rdf_license_ofl,
+ },
+
+ { NULL, NULL, rdf_license_empty, }
+};
+
+#define XML_TAG_NAME_SVG "svg:svg"
+#define XML_TAG_NAME_METADATA "svg:metadata"
+#define XML_TAG_NAME_RDF "rdf:RDF"
+#define XML_TAG_NAME_WORK "cc:Work"
+#define XML_TAG_NAME_LICENSE "cc:License"
+
+// Remember when using the "title" and "tip" elements to pass them through
+// the localization functions when you use them!
+struct rdf_work_entity_t rdf_work_entities [] = {
+ { "title", N_("Title"), "dc:title", RDF_CONTENT,
+ N_("Name by which this document is formally known."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "date", N_("Date"), "dc:date", RDF_CONTENT,
+ N_("Date associated with the creation of this document (YYYY-MM-DD)."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "format", N_("Format"), "dc:format", RDF_CONTENT,
+ N_("The physical or digital manifestation of this document (MIME type)."), RDF_FORMAT_LINE, RDF_EDIT_HARDCODED,
+ },
+ { "type", N_("Type"), "dc:type", RDF_RESOURCE,
+ N_("Type of document (DCMI Type)."), RDF_FORMAT_LINE, RDF_EDIT_HARDCODED,
+ },
+
+ { "creator", N_("Creator"), "dc:creator", RDF_AGENT,
+ N_("Name of entity primarily responsible for making the content of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "rights", N_("Rights"), "dc:rights", RDF_AGENT,
+ N_("Name of entity with rights to the Intellectual Property of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "publisher", N_("Publisher"), "dc:publisher", RDF_AGENT,
+ N_("Name of entity responsible for making this document available."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+
+ { "identifier", N_("Identifier"), "dc:identifier", RDF_CONTENT,
+ N_("Unique URI to reference this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "source", N_("Source"), "dc:source", RDF_CONTENT,
+ N_("Unique URI to reference the source of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "relation", N_("Relation"), "dc:relation", RDF_CONTENT,
+ N_("Unique URI to a related document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "language", N_("Language"), "dc:language", RDF_CONTENT,
+ N_("Two-letter language tag with optional subtags for the language of this document. (e.g. 'en-GB')"), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "subject", N_("Keywords"), "dc:subject", RDF_BAG,
+ N_("The topic of this document as comma-separated key words, phrases, or classifications."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ // TRANSLATORS: "Coverage": the spatial or temporal characteristics of the content.
+ // For info, see Appendix D of http://www.w3.org/TR/1998/WD-rdf-schema-19980409/
+ { "coverage", N_("Coverage"), "dc:coverage", RDF_CONTENT,
+ N_("Extent or scope of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+
+ { "description", N_("Description"), "dc:description", RDF_CONTENT,
+ N_("A short account of the content of this document."), RDF_FORMAT_MULTILINE, RDF_EDIT_GENERIC,
+ },
+
+ // FIXME: need to handle 1 agent per line of input
+ { "contributor", N_("Contributors"), "dc:contributor", RDF_AGENT,
+ N_("Names of entities responsible for making contributions to the content of this document."), RDF_FORMAT_MULTILINE, RDF_EDIT_GENERIC,
+ },
+
+ // TRANSLATORS: URL to a page that defines the license for the document
+ { "license_uri", N_("URI"), "cc:license", RDF_RESOURCE,
+ // TRANSLATORS: this is where you put a URL to a page that defines the license
+ N_("URI to this document's license's namespace definition."), RDF_FORMAT_LINE, RDF_EDIT_SPECIAL,
+ },
+
+ // TRANSLATORS: fragment of XML representing the license of the document
+ { "license_fragment", N_("Fragment"), "License", RDF_XML,
+ N_("XML fragment for the RDF 'License' section."), RDF_FORMAT_MULTILINE, RDF_EDIT_SPECIAL,
+ },
+
+ { NULL, NULL, NULL, RDF_CONTENT,
+ NULL, RDF_FORMAT_LINE, RDF_EDIT_HARDCODED,
+ }
+};
+
+/**
+ * \brief Retrieves a known RDF/Work entity by name
+ * \return A pointer to an RDF/Work entity
+ * \param name The desired RDF/Work entity
+ *
+ */
+struct rdf_work_entity_t *
+rdf_find_entity(gchar const * name)
+{
+ struct rdf_work_entity_t *entity;
+ for (entity=rdf_work_entities; entity->name; entity++) {
+ if (strcmp(entity->name,name)==0) break;
+ }
+ if (entity->name) return entity;
+ return NULL;
+}
+
+/*
+ * Takes the inkscape rdf struct and spits out a static RDF, which is only
+ * useful for testing. We must merge the rdf struct into the XML DOM for
+ * changes to be saved.
+ */
+/*
+
+ Since g_markup_printf_escaped doesn't exist for most people's glib
+ right now, this function will remain commented out since it's only
+ for generic debug anyway. --Kees
+
+gchar *
+rdf_string(struct rdf_t * rdf)
+{
+ gulong overall=0;
+ gchar *string=NULL;
+
+ gchar *rdf_head="\
+<rdf:RDF xmlns=\"http://creativecommons.org/ns#\"\
+ xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\
+ xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\
+";
+ gchar *work_head="\
+<Work rdf:about=\"\">\
+ <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\
+";
+ gchar *work_title=NULL;
+ gchar *work_date=NULL;
+ gchar *work_description=NULL;
+ gchar *work_creator=NULL;
+ gchar *work_owner=NULL;
+ gchar *work_source=NULL;
+ gchar *work_license=NULL;
+ gchar *license_head=NULL;
+ gchar *license=NULL;
+ gchar *license_end="</License>\n";
+ gchar *work_end="</Work>\n";
+ gchar *rdf_end="</rdf:RDF>\n";
+
+ if (rdf && rdf->work_title && rdf->work_title[0]) {
+ work_title=g_markup_printf_escaped(" <dc:title>%s</dc:title>\n",
+ rdf->work_title);
+ overall+=strlen(work_title);
+ }
+ if (rdf && rdf->work_date && rdf->work_date[0]) {
+ work_date=g_markup_printf_escaped(" <dc:date>%s</dc:date>\n",
+ rdf->work_date);
+ overall+=strlen(work_date);
+ }
+ if (rdf && rdf->work_description && rdf->work_description[0]) {
+ work_description=g_markup_printf_escaped(" <dc:description>%s</dc:description>\n",
+ rdf->work_description);
+ overall+=strlen(work_description);
+ }
+ if (rdf && rdf->work_creator && rdf->work_creator[0]) {
+ work_creator=g_markup_printf_escaped(" <dc:creator><Agent>\
+ <dc:title>%s</dc:title>\
+ </Agent></dc:creator>\n",
+ rdf->work_creator);
+ overall+=strlen(work_creator);
+ }
+ if (rdf && rdf->work_owner && rdf->work_owner[0]) {
+ work_owner=g_markup_printf_escaped(" <dc:rights><Agent>\
+ <dc:title>%s</dc:title>\
+ </Agent></dc:rights>\n",
+ rdf->work_owner);
+ overall+=strlen(work_owner);
+ }
+ if (rdf && rdf->work_source && rdf->work_source[0]) {
+ work_source=g_markup_printf_escaped(" <dc:source rdf:resource=\"%s\" />\n",
+ rdf->work_source);
+ overall+=strlen(work_source);
+ }
+ if (rdf && rdf->license && rdf->license->work_rdf && rdf->license->work_rdf[0]) {
+ work_license=g_markup_printf_escaped(" <license rdf:resource=\"%s\" />\n",
+ rdf->license->work_rdf);
+ overall+=strlen(work_license);
+
+ license_head=g_markup_printf_escaped("<License rdf:about=\"%s\">\n",
+ rdf->license->work_rdf);
+ overall+=strlen(license_head);
+ overall+=strlen(rdf->license->license_rdf);
+ overall+=strlen(license_end);
+ }
+
+ overall+=strlen(rdf_head)+strlen(rdf_end);
+ overall+=strlen(work_head)+strlen(work_end);
+
+ overall++; // NULL term
+
+ if (!(string=(gchar*)g_malloc(overall))) {
+ return NULL;
+ }
+
+ string[0]='\0';
+ strcat(string,rdf_head);
+ strcat(string,work_head);
+
+ if (work_title) strcat(string,work_title);
+ if (work_date) strcat(string,work_date);
+ if (work_description) strcat(string,work_description);
+ if (work_creator) strcat(string,work_creator);
+ if (work_owner) strcat(string,work_owner);
+ if (work_source) strcat(string,work_source);
+ if (work_license) strcat(string,work_license);
+
+ strcat(string,work_end);
+ if (license_head) {
+ strcat(string,license_head);
+ strcat(string,rdf->license->license_rdf);
+ strcat(string,license_end);
+ }
+ strcat(string,rdf_end);
+
+ return string;
+}
+*/
+
+
+/**
+ * \brief Pull the text out of an RDF entity, depends on how it's stored
+ * \return A pointer to the entity's static contents as a string
+ * \param repr The XML element to extract from
+ * \param entity The desired RDF/Work entity
+ *
+ */
+const gchar *
+rdf_get_repr_text ( Inkscape::XML::Node * repr, struct rdf_work_entity_t * entity )
+{
+ g_return_val_if_fail (repr != NULL, NULL);
+ g_return_val_if_fail (entity != NULL, NULL);
+ static gchar * bag = NULL;
+ gchar * holder = NULL;
+
+ Inkscape::XML::Node * temp=NULL;
+ switch (entity->datatype) {
+ case RDF_CONTENT:
+ temp = sp_repr_children(repr);
+ if ( temp == NULL ) return NULL;
+
+ return temp->content();
+
+ case RDF_AGENT:
+ temp = sp_repr_lookup_name ( repr, "cc:Agent", 1 );
+ if ( temp == NULL ) return NULL;
+
+ temp = sp_repr_lookup_name ( temp, "dc:title", 1 );
+ if ( temp == NULL ) return NULL;
+
+ temp = sp_repr_children(temp);
+ if ( temp == NULL ) return NULL;
+
+ return temp->content();
+
+ case RDF_RESOURCE:
+ return repr->attribute("rdf:resource");
+
+ case RDF_XML:
+ return "xml goes here";
+
+ case RDF_BAG:
+ /* clear the static string. yucky. */
+ if (bag) g_free(bag);
+ bag = NULL;
+
+ temp = sp_repr_lookup_name ( repr, "rdf:Bag", 1 );
+ if ( temp == NULL ) {
+ /* backwards compatible: read contents */
+ temp = sp_repr_children(repr);
+ if ( temp == NULL ) return NULL;
+
+ return temp->content();
+ }
+
+ for ( temp = sp_repr_children(temp) ;
+ temp ;
+ temp = sp_repr_next(temp) ) {
+ if (!strcmp(temp->name(),"rdf:li") &&
+ temp->firstChild()) {
+ const gchar * str = temp->firstChild()->content();
+ if (bag) {
+ holder = bag;
+ bag = g_strconcat(holder, ", ", str, NULL);
+ g_free(holder);
+ }
+ else {
+ bag = g_strdup(str);
+ }
+ }
+ }
+ return bag;
+
+ default:
+ break;
+ }
+ return NULL;
+}
+
+unsigned int
+rdf_set_repr_text ( Inkscape::XML::Node * repr,
+ struct rdf_work_entity_t * entity,
+ gchar const * text )
+{
+ g_return_val_if_fail ( repr != NULL, 0);
+ g_return_val_if_fail ( entity != NULL, 0);
+ g_return_val_if_fail ( text != NULL, 0);
+ gchar * str = NULL;
+ gchar** strlist = NULL;
+ int i;
+
+ Inkscape::XML::Node * temp=NULL;
+ Inkscape::XML::Node * child=NULL;
+ Inkscape::XML::Node * parent=repr;
+
+ Inkscape::XML::Document * xmldoc = parent->document();
+ g_return_val_if_fail (xmldoc != NULL, FALSE);
+
+ // set document's title element to the RDF title
+ if (!strcmp(entity->name, "title")) {
+ SPDocument *doc = SP_ACTIVE_DOCUMENT;
+ if(doc && doc->root) doc->root->setTitle(text);
+ }
+
+ switch (entity->datatype) {
+ case RDF_CONTENT:
+ temp = sp_repr_children(parent);
+ if ( temp == NULL ) {
+ temp = xmldoc->createTextNode( text );
+ g_return_val_if_fail (temp != NULL, FALSE);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+
+ return TRUE;
+ }
+ else {
+ temp->setContent(text);
+ return TRUE;
+ }
+
+ case RDF_AGENT:
+ temp = sp_repr_lookup_name ( parent, "cc:Agent", 1 );
+ if ( temp == NULL ) {
+ temp = xmldoc->createElement ( "cc:Agent" );
+ g_return_val_if_fail (temp != NULL, FALSE);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+ }
+ parent = temp;
+
+ temp = sp_repr_lookup_name ( parent, "dc:title", 1 );
+ if ( temp == NULL ) {
+ temp = xmldoc->createElement ( "dc:title" );
+ g_return_val_if_fail (temp != NULL, FALSE);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+ }
+ parent = temp;
+
+ temp = sp_repr_children(parent);
+ if ( temp == NULL ) {
+ temp = xmldoc->createTextNode( text );
+ g_return_val_if_fail (temp != NULL, FALSE);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+
+ return TRUE;
+ }
+ else {
+ temp->setContent(text);
+ return TRUE;
+ }
+
+ case RDF_RESOURCE:
+ parent->setAttribute("rdf:resource", text );
+ return true;
+
+ case RDF_XML:
+ return 1;
+
+ case RDF_BAG:
+ /* find/create the rdf:Bag item */
+ temp = sp_repr_lookup_name ( parent, "rdf:Bag", 1 );
+ if ( temp == NULL ) {
+ /* backward compatibility: drop the dc:subject contents */
+ while ( (temp = sp_repr_children( parent )) ) {
+ parent->removeChild(temp);
+ }
+
+ temp = xmldoc->createElement ( "rdf:Bag" );
+ g_return_val_if_fail (temp != NULL, FALSE);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+ }
+ parent = temp;
+
+ /* toss all the old list items */
+ while ( (temp = sp_repr_children( parent )) ) {
+ parent->removeChild(temp);
+ }
+
+ /* chop our list up on commas */
+ strlist = g_strsplit( text, ",", 0);
+
+ for (i = 0; (str = strlist[i]); i++) {
+ temp = xmldoc->createElement ( "rdf:li" );
+ g_return_val_if_fail (temp != NULL, 0);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+
+ child = xmldoc->createTextNode( g_strstrip(str) );
+ g_return_val_if_fail (child != NULL, 0);
+
+ temp->appendChild(child);
+ Inkscape::GC::release(child);
+ }
+ g_strfreev( strlist );
+
+ return 1;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+Inkscape::XML::Node *
+rdf_get_rdf_root_repr ( SPDocument * doc, bool build )
+{
+ g_return_val_if_fail (doc != NULL, NULL);
+ g_return_val_if_fail (doc->rroot != NULL, NULL);
+
+ Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
+ g_return_val_if_fail (xmldoc != NULL, NULL);
+
+ Inkscape::XML::Node * rdf = sp_repr_lookup_name ( doc->rroot, XML_TAG_NAME_RDF );
+
+ if (rdf == NULL) {
+ //printf("missing XML '%s'\n",XML_TAG_NAME_RDF);
+ if (!build) return NULL;
+
+ Inkscape::XML::Node * svg = sp_repr_lookup_name ( doc->rroot, XML_TAG_NAME_SVG );
+ g_return_val_if_fail ( svg != NULL, NULL );
+
+ Inkscape::XML::Node * parent = sp_repr_lookup_name ( svg, XML_TAG_NAME_METADATA );
+ if ( parent == NULL ) {
+ parent = xmldoc->createElement( XML_TAG_NAME_METADATA );
+ g_return_val_if_fail ( parent != NULL, NULL);
+
+ svg->appendChild(parent);
+ Inkscape::GC::release(parent);
+ }
+
+ Inkscape::XML::Document * xmldoc = parent->document();
+ g_return_val_if_fail (xmldoc != NULL, FALSE);
+
+ rdf = xmldoc->createElement( XML_TAG_NAME_RDF );
+ g_return_val_if_fail (rdf != NULL, NULL);
+
+ parent->appendChild(rdf);
+ Inkscape::GC::release(rdf);
+ }
+
+ /*
+ * some implementations do not put RDF stuff inside <metadata>,
+ * so we need to check for it and add it if we don't see it
+ */
+ Inkscape::XML::Node * want_metadata = sp_repr_parent ( rdf );
+ g_return_val_if_fail (want_metadata != NULL, NULL);
+ if (strcmp( want_metadata->name(), XML_TAG_NAME_METADATA )) {
+ Inkscape::XML::Node * metadata = xmldoc->createElement( XML_TAG_NAME_METADATA );
+ g_return_val_if_fail (metadata != NULL, NULL);
+
+ /* attach the metadata node */
+ want_metadata->appendChild(metadata);
+ Inkscape::GC::release(metadata);
+
+ /* move the RDF into it */
+ Inkscape::GC::anchor(rdf);
+ sp_repr_unparent ( rdf );
+ metadata->appendChild(rdf);
+ Inkscape::GC::release(rdf);
+ }
+
+ return rdf;
+}
+
+Inkscape::XML::Node *
+rdf_get_xml_repr( SPDocument * doc, gchar const * name, bool build )
+{
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (doc != NULL, NULL);
+ g_return_val_if_fail (doc->rroot != NULL, NULL);
+
+ Inkscape::XML::Node * rdf = rdf_get_rdf_root_repr ( doc, build );
+ if (!rdf) return NULL;
+
+ Inkscape::XML::Node * xml = sp_repr_lookup_name ( rdf, name );
+ if (xml == NULL) {
+ //printf("missing XML '%s'\n",name);
+ if (!build) return NULL;
+
+ Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
+ g_return_val_if_fail (xmldoc != NULL, NULL);
+
+ xml = xmldoc->createElement( name );
+ g_return_val_if_fail (xml != NULL, NULL);
+
+ xml->setAttribute("rdf:about", "" );
+
+ rdf->appendChild(xml);
+ Inkscape::GC::release(xml);
+ }
+
+ return xml;
+}
+
+Inkscape::XML::Node *
+rdf_get_work_repr( SPDocument * doc, gchar const * name, bool build )
+{
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (doc != NULL, NULL);
+ g_return_val_if_fail (doc->rroot != NULL, NULL);
+
+ Inkscape::XML::Node * work = rdf_get_xml_repr ( doc, XML_TAG_NAME_WORK, build );
+ if (!work) return NULL;
+
+ Inkscape::XML::Node * item = sp_repr_lookup_name ( work, name, 1 );
+ if (item == NULL) {
+ //printf("missing XML '%s'\n",name);
+ if (!build) return NULL;
+
+ Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
+ g_return_val_if_fail (xmldoc != NULL, NULL);
+
+ item = xmldoc->createElement( name );
+ g_return_val_if_fail (item != NULL, NULL);
+
+ work->appendChild(item);
+ Inkscape::GC::release(item);
+ }
+
+ return item;
+}
+
+
+
+/**
+ * \brief Retrieves a known RDF/Work entity's contents from the document XML by name
+ * \return A pointer to the entity's static contents as a string, or NULL if no entity exists
+ * \param entity The desired RDF/Work entity
+ *
+ */
+const gchar *
+rdf_get_work_entity(SPDocument * doc, struct rdf_work_entity_t * entity)
+{
+ g_return_val_if_fail (doc != NULL, NULL);
+ if ( entity == NULL ) return NULL;
+ //printf("want '%s'\n",entity->title);
+ bool bIsTitle = !strcmp(entity->name, "title");
+
+ Inkscape::XML::Node * item;
+ if ( entity->datatype == RDF_XML ) {
+ item = rdf_get_xml_repr ( doc, entity->tag, FALSE );
+ }
+ else {
+ item = rdf_get_work_repr( doc, entity->tag, bIsTitle ); // build title if necessary
+ }
+ if ( item == NULL ) return NULL;
+ const gchar * result = rdf_get_repr_text ( item, entity );
+ if(!result && bIsTitle && doc->root) { // if RDF title not set
+ result = doc->root->title(); // get the document's <title>
+ rdf_set_work_entity(doc, entity, result); // and set the RDF
+ }
+ //printf("found '%s' == '%s'\n", entity->title, result );
+ return result;
+}
+
+/**
+ * \brief Stores a string into a named RDF/Work entity in the document XML
+ * \param entity The desired RDF/Work entity to replace
+ * \param string The string to replace the entity contents with
+ *
+ */
+unsigned int
+rdf_set_work_entity(SPDocument * doc, struct rdf_work_entity_t * entity,
+ const gchar * text)
+{
+ g_return_val_if_fail ( entity != NULL, 0 );
+ if (text == NULL) {
+ // FIXME: on a "NULL" text, delete the entity. For now, blank it.
+ text="";
+ }
+
+ /*
+ printf("changing '%s' (%s) to '%s'\n",
+ entity->title,
+ entity->tag,
+ text);
+ */
+
+ Inkscape::XML::Node * item = rdf_get_work_repr( doc, entity->tag, TRUE );
+ g_return_val_if_fail ( item != NULL, 0 );
+
+ return rdf_set_repr_text ( item, entity, text );
+}
+
+#undef DEBUG_MATCH
+
+static bool
+rdf_match_license(Inkscape::XML::Node const *repr, struct rdf_license_t const *license)
+{
+ g_assert ( repr != NULL );
+ g_assert ( license != NULL );
+
+ bool result=TRUE;
+#ifdef DEBUG_MATCH
+ printf("checking against '%s'\n",license->name);
+#endif
+
+ int count = 0;
+ for (struct rdf_double_t const *details = license->details;
+ details->name; details++ ) {
+ count++;
+ }
+ bool * matched = (bool*)calloc(count,sizeof(bool));
+
+ for (Inkscape::XML::Node const *current = sp_repr_children(repr);
+ current;
+ current = sp_repr_next ( current ) ) {
+
+ gchar const * attr = current->attribute("rdf:resource");
+ if ( attr == NULL ) continue;
+
+#ifdef DEBUG_MATCH
+ printf("\texamining '%s' => '%s'\n", current->name(), attr);
+#endif
+
+ bool found_match=FALSE;
+ for (int i=0; i<count; i++) {
+ // skip already matched items
+ if (matched[i]) continue;
+
+#ifdef DEBUG_MATCH
+ printf("\t\t'%s' vs '%s'\n", current->name(), license->details[i].name);
+ printf("\t\t'%s' vs '%s'\n", attr, license->details[i].resource);
+#endif
+
+ if (!strcmp( current->name(),
+ license->details[i].name ) &&
+ !strcmp( attr,
+ license->details[i].resource )) {
+ matched[i]=TRUE;
+ found_match=TRUE;
+#ifdef DEBUG_MATCH
+ printf("\t\tgood!\n");
+#endif
+ break;
+ }
+ }
+ if (!found_match) {
+ // if we checked each known item of the license
+ // and didn't find it, we must abort
+ result=FALSE;
+#ifdef DEBUG_MATCH
+ printf("\t\tno '%s' element matched XML (bong)!\n",license->name);
+#endif
+ break;
+ }
+ }
+#ifdef DEBUG_MATCH
+ if (result) printf("\t\tall XML found matching elements!\n");
+#endif
+ for (int i=0; result && i<count; i++) {
+ // scan looking for an unmatched item
+ if (matched[i]==0) {
+ result=FALSE;
+#ifdef DEBUG_MATCH
+ printf("\t\tnot all '%s' elements used to match (bong)!\n", license->name);
+#endif
+ }
+ }
+
+#ifdef DEBUG_MATCH
+ printf("\t\tall '%s' elements used to match!\n",license->name);
+#endif
+
+ free(matched);
+
+#ifdef DEBUG_MATCH
+ if (result) printf("matched '%s'\n",license->name);
+#endif
+ return result;
+}
+
+/**
+ * \brief Attempts to match and retrieve a known RDF/License from the document XML
+ * \return A pointer to the static RDF license structure
+ *
+ */
+struct rdf_license_t *
+rdf_get_license(SPDocument * document)
+{
+ Inkscape::XML::Node const *repr = rdf_get_xml_repr ( document, XML_TAG_NAME_LICENSE, FALSE );
+ if (repr) {
+ for (struct rdf_license_t * license = rdf_licenses;
+ license->name; license++ ) {
+ if ( rdf_match_license ( repr, license ) ) return license;
+ }
+ }
+#ifdef DEBUG_MATCH
+ else {
+ printf("no license XML\n");
+ }
+#endif
+ return NULL;
+}
+
+/**
+ * \brief Stores an RDF/License XML in the document XML
+ * \param document Which document to update
+ * \param license The desired RDF/License structure to store; NULL drops old license, so can be used for proprietary license.
+ *
+ */
+void
+rdf_set_license(SPDocument * doc, struct rdf_license_t const * license)
+{
+ // drop old license section
+ Inkscape::XML::Node * repr = rdf_get_xml_repr ( doc, XML_TAG_NAME_LICENSE, FALSE );
+ if (repr) sp_repr_unparent(repr);
+
+ if (!license) return;
+
+ // build new license section
+ repr = rdf_get_xml_repr ( doc, XML_TAG_NAME_LICENSE, TRUE );
+ g_assert ( repr );
+
+ repr->setAttribute("rdf:about", license->uri );
+
+ Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
+ g_return_if_fail (xmldoc != NULL);
+
+ for (struct rdf_double_t const * detail = license->details;
+ detail->name; detail++) {
+ Inkscape::XML::Node * child = xmldoc->createElement( detail->name );
+ g_assert ( child != NULL );
+
+ child->setAttribute("rdf:resource", detail->resource );
+ repr->appendChild(child);
+ Inkscape::GC::release(child);
+ }
+}
+
+struct rdf_entity_default_t {
+ gchar const * name;
+ gchar const * text;
+};
+struct rdf_entity_default_t rdf_defaults[] = {
+ { "format", "image/svg+xml", },
+ { "type", "http://purl.org/dc/dcmitype/StillImage", },
+ { NULL, NULL, }
+};
+
+void
+rdf_set_defaults ( SPDocument * doc )
+{
+ g_assert ( doc != NULL );
+
+ // Create metadata node if it doesn't already exist
+ if (!sp_item_group_get_child_by_name ((SPGroup *) doc->root, NULL,
+ XML_TAG_NAME_METADATA)) {
+ // create repr
+ Inkscape::XML::Document * xmldoc = sp_document_repr_doc(doc);
+ g_return_if_fail (xmldoc != NULL);
+ Inkscape::XML::Node * rnew = xmldoc->createElement (XML_TAG_NAME_METADATA);
+ // insert into the document
+ doc->rroot->addChild(rnew, NULL);
+ // clean up
+ Inkscape::GC::release(rnew);
+ }
+
+ /* install defaults */
+ for ( struct rdf_entity_default_t * rdf_default = rdf_defaults;
+ rdf_default->name;
+ rdf_default++) {
+ struct rdf_work_entity_t * entity = rdf_find_entity ( rdf_default->name );
+ g_assert ( entity != NULL );
+
+ if ( rdf_get_work_entity ( doc, entity ) == NULL ) {
+ rdf_set_work_entity ( doc, entity, rdf_default->text );
+ }
+ }
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/rdf.h b/src/rdf.h
--- /dev/null
+++ b/src/rdf.h
@@ -0,0 +1,120 @@
+/** @file
+ * @brief headers for RDF types
+ */
+/* Authors:
+ * Kees Cook <kees@outflux.net>
+ *
+ * Copyright (C) 2004 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifndef _RDF_H_
+#define _RDF_H_
+
+#include <glib.h>
+#include <glibmm/i18n.h>
+#include "document.h"
+
+// yeah, it's not a triple yet...
+/**
+ * \brief Holds license name/resource doubles for rdf_license_t entries
+ */
+struct rdf_double_t {
+ gchar const *name;
+ gchar const *resource;
+};
+
+/**
+ * \brief Holds license name and RDF information
+ */
+struct rdf_license_t {
+ gchar const *name; /* localized name of this license */
+ gchar const *uri; /* URL for the RDF/Work/license element */
+ struct rdf_double_t *details; /* the license details */
+// gchar const *fragment; /* XML contents for the RDF/License tag */
+};
+
+extern rdf_license_t rdf_licenses [];
+
+/**
+ * \brief Describes how a given RDF entity is stored in XML
+ */
+enum RDFType {
+ RDF_CONTENT, // direct between-XML-tags content
+ RDF_AGENT, // requires the "Agent" hierarchy before doing content
+ RDF_RESOURCE, // stored in "rdf:resource" element
+ RDF_XML, // literal XML
+ RDF_BAG // rdf:Bag resources
+};
+
+/**
+ * \brief Describes how a given RDF entity should be edited
+ */
+enum RDF_Format {
+ RDF_FORMAT_LINE, // uses single line data (GtkEntry)
+ RDF_FORMAT_MULTILINE, // uses multiline data (GtkTextView)
+ RDF_FORMAT_SPECIAL // uses some other edit methods
+};
+
+enum RDF_Editable {
+ RDF_EDIT_GENERIC, // editable via generic widgets
+ RDF_EDIT_SPECIAL, // special widgets are needed
+ RDF_EDIT_HARDCODED // isn't editable
+};
+
+/**
+ * \brief Holds known RDF/Work tags
+ */
+struct rdf_work_entity_t {
+ char const *name; /* unique name of this entity for internal reference */
+ gchar const *title; /* localized title of this entity for data entry */
+ gchar const *tag; /* namespace tag for the RDF/Work element */
+ RDFType datatype; /* how to extract/inject the RDF information */
+ gchar const *tip; /* tool tip to explain the meaning of the entity */
+ RDF_Format format; /* in what format is this data edited? */
+ RDF_Editable editable;/* in what way is the data editable? */
+};
+
+extern rdf_work_entity_t rdf_work_entities [];
+
+/**
+ * \brief Generic collection of RDF information for the RDF debug function
+ */
+struct rdf_t {
+ gchar* work_title;
+ gchar* work_date;
+ gchar* work_creator;
+ gchar* work_owner;
+ gchar* work_publisher;
+ gchar* work_type;
+ gchar* work_source;
+ gchar* work_subject;
+ gchar* work_description;
+ struct rdf_license_t* license;
+};
+
+struct rdf_work_entity_t * rdf_find_entity(gchar const * name);
+
+const gchar * rdf_get_work_entity(SPDocument * doc,
+ struct rdf_work_entity_t * entity);
+unsigned int rdf_set_work_entity(SPDocument * doc,
+ struct rdf_work_entity_t * entity,
+ const gchar * text);
+
+struct rdf_license_t * rdf_get_license(SPDocument * doc);
+void rdf_set_license(SPDocument * doc,
+ struct rdf_license_t const * license);
+
+void rdf_set_defaults ( SPDocument * doc );
+
+#endif // _RDF_H_
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/Makefile_insert b/src/ui/Makefile_insert
index e91c22025a9dcf45bb3ff3019d40c57d5303f1c4..3eb6c6b13c93cb29745fd91d297687ccdfc38454 100644 (file)
--- a/src/ui/Makefile_insert
+++ b/src/ui/Makefile_insert
## Makefile.am fragment sourced by src/Makefile.am.
ink_common_sources += \
- ui/clipboard.cpp \
- ui/clipboard.h \
- ui/icon-names.h \
+ ui/context-menu.cpp \
+ ui/context-menu.h \
+ ui/clipboard.cpp \
+ ui/clipboard.h \
+ ui/icon-names.h \
ui/previewable.h \
ui/previewfillable.h \
ui/previewholder.cpp \
index bf3b6baeb2d17f5b0305acce5bf98650602d9f4d..6a9ebf61ffac8529deb89636700f887f584b8c06 100644 (file)
## Makefile.am fragment sourced by src/Makefile.am.
+if WITH_INKBOARD
+inkboard_dialogs = \
+ whiteboard-connect.cpp \
+ whiteboard-connect.h \
+ whiteboard-sharewithchat.cpp \
+ whiteboard-sharewithchat.h \
+ whiteboard-sharewithuser.cpp \
+ whiteboard-sharewithuser.h
+endif
+
ink_common_sources += \
ui/dialog/aboutbox.cpp \
ui/dialog/aboutbox.h \
ui/dialog/align-and-distribute.cpp \
ui/dialog/align-and-distribute.h \
ui/dialog/behavior.h \
+ ui/dialog/calligraphic-profile-rename.h \
+ ui/dialog/calligraphic-profile-rename.cpp \
ui/dialog/debug.cpp \
ui/dialog/debug.h \
ui/dialog/dialog.cpp \
ui/dialog/document-properties.h \
ui/dialog/extension-editor.cpp \
ui/dialog/extension-editor.h \
+ ui/dialog/extensions.cpp \
+ ui/dialog/extensions.h \
ui/dialog/filedialog.cpp \
ui/dialog/filedialog.h \
ui/dialog/filedialogimpl-gtkmm.cpp \
ui/dialog/find.h \
ui/dialog/floating-behavior.cpp \
ui/dialog/floating-behavior.h \
+ ui/dialog/guides.cpp \
+ ui/dialog/guides.h \
+ ui/dialog/icon-preview.cpp \
+ ui/dialog/icon-preview.h \
ui/dialog/inkscape-preferences.cpp \
ui/dialog/inkscape-preferences.h \
ui/dialog/input.cpp \
ui/dialog/input.h \
+ ui/dialog/layer-properties.cpp \
+ ui/dialog/layer-properties.h \
+ ui/dialog/layers.cpp \
+ ui/dialog/layers.h \
ui/dialog/livepatheffect-editor.cpp \
ui/dialog/livepatheffect-editor.h \
ui/dialog/memory.cpp \
ui/dialog/scriptdialog.h \
ui/dialog/svg-fonts-dialog.cpp \
ui/dialog/svg-fonts-dialog.h \
+ ui/dialog/swatches.cpp \
+ ui/dialog/swatches.h \
ui/dialog/tile.cpp \
ui/dialog/tile.h \
ui/dialog/tracedialog.cpp \
index 0a59c004f3e0b4f181fa8e6ac0fa5a77e372beab..d8c4bc005606483457e09fdb8f8a6e8e42bb16df 100644 (file)
#include <gtkmm/spinbutton.h>
#include "desktop-handles.h"
-#include "dialogs/unclump.h"
+#include "unclump.h"
#include "document.h"
#include "enums.h"
#include "graphlayout/graphlayout.h"
diff --git a/src/ui/dialog/calligraphic-profile-rename.cpp b/src/ui/dialog/calligraphic-profile-rename.cpp
--- /dev/null
@@ -0,0 +1,108 @@
+/** @file
+ * @brief Dialog for naming calligraphic profiles
+ *
+ * @note This file is in the wrong directory because of link order issues -
+ * it is required by widgets/toolbox.cpp, and libspwidgets.a comes after
+ * libinkdialogs.a in the current link order.
+ */
+/* Author:
+ * Aubanel MONNIER
+ *
+ * Copyright (C) 2007 Authors
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glibmm/i18n.h>
+#include <gtkmm/stock.h>
+
+#include "desktop.h"
+#include "calligraphic-profile-rename.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+CalligraphicProfileRename::CalligraphicProfileRename() :
+ _applied(false)
+{
+ Gtk::VBox *mainVBox = get_vbox();
+ _layout_table.set_spacings(4);
+ _layout_table.resize (1, 2);
+
+ _profile_name_entry.set_activates_default(true);
+
+ _profile_name_label.set_label(_("Profile name:"));
+ _profile_name_label.set_alignment(1.0, 0.5);
+
+ _layout_table.attach(_profile_name_label,
+ 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(_profile_name_entry,
+ 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+ mainVBox->pack_start(_layout_table, false, false, 4);
+ // Buttons
+ _close_button.set_use_stock(true);
+ _close_button.set_label(Gtk::Stock::CANCEL.id);
+ _close_button.set_flags(Gtk::CAN_DEFAULT);
+
+ _apply_button.set_use_underline(true);
+ _apply_button.set_label(_("Save"));
+ _apply_button.set_flags(Gtk::CAN_DEFAULT);
+
+ _close_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &CalligraphicProfileRename::_close));
+ _apply_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &CalligraphicProfileRename::_apply));
+
+ signal_delete_event().connect( sigc::bind_return(
+ sigc::hide(sigc::mem_fun(*this, &CalligraphicProfileRename::_close)), true ) );
+
+ add_action_widget(_close_button, Gtk::RESPONSE_CLOSE);
+ add_action_widget(_apply_button, Gtk::RESPONSE_APPLY);
+
+ _apply_button.grab_default();
+
+ show_all_children();
+}
+
+void CalligraphicProfileRename::_apply()
+{
+ _profile_name = _profile_name_entry.get_text();
+ _applied = true;
+ _close();
+}
+
+void CalligraphicProfileRename::_close()
+{
+ this->Gtk::Dialog::hide();
+}
+
+void CalligraphicProfileRename::show(SPDesktop *desktop)
+{
+ CalligraphicProfileRename &dial = instance();
+ dial._applied=false;
+ dial.set_modal(true);
+ desktop->setWindowTransient (dial.gobj());
+ dial.property_destroy_with_parent() = true;
+ // dial.Gtk::Dialog::show();
+ //dial.present();
+ dial.run();
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/calligraphic-profile-rename.h b/src/ui/dialog/calligraphic-profile-rename.h
--- /dev/null
@@ -0,0 +1,75 @@
+/** @file
+ * @brief Dialog for naming calligraphic profiles
+ */
+/* Author:
+ * Aubanel MONNIER
+ *
+ * Copyright (C) 2007 Authors
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_DIALOG_CALLIGRAPHIC_PROFILE_H
+#define INKSCAPE_DIALOG_CALLIGRAPHIC_PROFILE_H
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/entry.h>
+#include <gtkmm/label.h>
+#include <gtkmm/table.h>
+struct SPDesktop;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class CalligraphicProfileRename : public Gtk::Dialog {
+public:
+ CalligraphicProfileRename();
+ virtual ~CalligraphicProfileRename() {}
+ Glib::ustring getName() const {
+ return "CalligraphicProfileRename";
+ }
+
+ static void show(SPDesktop *desktop);
+ static bool applied() {
+ return instance()._applied;
+ }
+ static Glib::ustring getProfileName() {
+ return instance()._profile_name;
+ }
+
+protected:
+ void _close();
+ void _apply();
+
+ Gtk::Label _profile_name_label;
+ Gtk::Entry _profile_name_entry;
+ Gtk::Table _layout_table;
+ Gtk::Button _close_button;
+ Gtk::Button _apply_button;
+ Glib::ustring _profile_name;
+ bool _applied;
+private:
+ static CalligraphicProfileRename &instance() {
+ static CalligraphicProfileRename instance_;
+ return instance_;
+ }
+ CalligraphicProfileRename(CalligraphicProfileRename const &); // no copy
+ CalligraphicProfileRename &operator=(CalligraphicProfileRename const &); // no assign
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_DIALOG_CALLIGRAPHIC_PROFILE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 7a8947adf7bc9315ee079b9baa9a92f897b11007..d1b818d236a781f6eacd8b1ca88b94bac2901367 100644 (file)
#include "ui/dialog/memory.h"
#include "ui/dialog/messages.h"
#include "ui/dialog/scriptdialog.h"
-#ifdef ENABLE_SVG_FONTS
-#include "ui/dialog/svg-fonts-dialog.h"
-#endif // ENABLE_SVG_FONTS
#include "ui/dialog/tile.h"
#include "ui/dialog/tracedialog.h"
#include "ui/dialog/transformation.h"
#include "ui/dialog/undo-history.h"
#include "ui/dialog/panel-dialog.h"
-
-#include "dialogs/layers-panel.h"
-#include "dialogs/iconpreview.h"
-
+#include "ui/dialog/layers.h"
+#include "ui/dialog/icon-preview.h"
#include "ui/dialog/floating-behavior.h"
#include "ui/dialog/dock-behavior.h"
#include "preferences.h"
+#ifdef ENABLE_SVG_FONTS
+#include "ui/dialog/svg-fonts-dialog.h"
+#endif // ENABLE_SVG_FONTS
+
namespace Inkscape {
namespace UI {
namespace Dialog {
index 32838309a4d678a078ba8900ab17cbdb2c9efc09..96cad1fbe6074596d9edfde15ba8a1b44c4f8cae 100644 (file)
# include <config.h>
#endif
-
-
-#include "ui/widget/entity-entry.h"
-
-#include "xml/node-event-vector.h"
-#include "dialogs/rdf.h"
-
-#include "inkscape.h"
-#include "verbs.h"
-#include "desktop-handles.h"
#include "desktop.h"
+#include "desktop-handles.h"
+#include "inkscape.h"
+#include "rdf.h"
#include "sp-namedview.h"
+#include "ui/widget/entity-entry.h"
+#include "verbs.h"
+#include "xml/node-event-vector.h"
#include "document-metadata.h"
diff --git a/src/ui/dialog/extensions.cpp b/src/ui/dialog/extensions.cpp
--- /dev/null
@@ -0,0 +1,129 @@
+/** @file
+ * @brief A simple dialog with information about extensions
+ */
+/* Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2005 Jon A. Cruz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtk/gtkdialog.h> //for GTK_RESPONSE* types
+#include <gtkmm/scrolledwindow.h>
+
+#include "extension/db.h"
+#include "extensions.h"
+
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+using Inkscape::Extension::Extension;
+
+ExtensionsPanel &ExtensionsPanel::getInstance()
+{
+ ExtensionsPanel &instance = *new ExtensionsPanel();
+
+ instance.rescan();
+
+ return instance;
+}
+
+
+
+/**
+ * Constructor
+ */
+ExtensionsPanel::ExtensionsPanel() :
+ _showAll(false)
+{
+ Gtk::ScrolledWindow* scroller = new Gtk::ScrolledWindow();
+
+ _view.set_editable(false);
+
+ scroller->add(_view);
+ add(*scroller);
+
+ rescan();
+
+ show_all_children();
+}
+
+void ExtensionsPanel::set_full(bool full)
+{
+ if ( full != _showAll ) {
+ _showAll = full;
+ rescan();
+ }
+}
+
+void ExtensionsPanel::listCB( Inkscape::Extension::Extension * in_plug, gpointer in_data )
+{
+ ExtensionsPanel * self = (ExtensionsPanel*)in_data;
+
+ const char* stateStr;
+ Extension::state_t state = in_plug->get_state();
+ switch ( state ) {
+ case Extension::STATE_LOADED:
+ {
+ stateStr = "loaded";
+ }
+ break;
+ case Extension::STATE_UNLOADED:
+ {
+ stateStr = "unloaded";
+ }
+ break;
+ case Extension::STATE_DEACTIVATED:
+ {
+ stateStr = "deactivated";
+ }
+ break;
+ default:
+ stateStr = "unknown";
+ }
+
+ if ( self->_showAll || in_plug->deactivated() ) {
+// gchar* line = g_strdup_printf( " extension %c %c %s |%s|%s|",
+// (in_plug->loaded() ? 'X' : '-'),
+// (in_plug->deactivated() ? 'X' : '-'),
+// stateStr, in_plug->get_id(),
+// in_plug->get_name() );
+ gchar* line = g_strdup_printf( "%s %s\n \"%s\"", stateStr, in_plug->get_name(), in_plug->get_id() );
+
+ self->_view.get_buffer()->insert( self->_view.get_buffer()->end(), line );
+ self->_view.get_buffer()->insert( self->_view.get_buffer()->end(), "\n" );
+ //g_message( "%s", line );
+ }
+
+
+
+ return;
+}
+
+void ExtensionsPanel::rescan()
+{
+ _view.get_buffer()->set_text("Extensions:\n");
+// g_message("/------------------");
+
+ Inkscape::Extension::db.foreach(listCB, (gpointer)this);
+
+// g_message("\\------------------");
+}
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/extensions.h b/src/ui/dialog/extensions.h
--- /dev/null
@@ -0,0 +1,56 @@
+/** @file
+ * A simple dialog with information about extensions
+ */
+/* Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2005 The Inkscape Organization
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_EXTENSIONS_H
+#define SEEN_EXTENSIONS_H
+
+#include <gtkmm/textview.h>
+#include "ui/widget/panel.h"
+
+namespace Inkscape {
+namespace Extension {
+class Extension;
+}
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+
+/**
+ * A panel that displays information about extensions.
+ */
+class ExtensionsPanel : public Inkscape::UI::Widget::Panel
+{
+public:
+ ExtensionsPanel();
+
+ static ExtensionsPanel &getInstance();
+
+ void set_full(bool full);
+
+private:
+ ExtensionsPanel(ExtensionsPanel const &); // no copy
+ ExtensionsPanel &operator=(ExtensionsPanel const &); // no assign
+
+ static void listCB(Inkscape::Extension::Extension *in_plug, gpointer in_data);
+
+ void rescan();
+
+ bool _showAll;
+ Gtk::TextView _view;
+};
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+#endif // SEEN_EXTENSIONS_H
index d28dc7955b20d03086f49cdeb344366f9adf1f5e..fe63c6e24e6fd9f15e4e2ff172d019bca906e5cc 100644 (file)
#include "selection.h"
#include "style.h"
#include "svg/css-ostringstream.h"
+#include "ui/icon-names.h"
#include "verbs.h"
-#include "xml/repr.h"
+#include "widgets/fill-style.h"
#include "widgets/icon.h"
-#include "ui/icon-names.h"
-
-#include "dialogs/fill-style.h"
-#include "dialogs/stroke-style.h"
-
-#include <widgets/paint-selector.h>
+#include "widgets/paint-selector.h"
+#include "widgets/stroke-style.h"
+#include "xml/repr.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/dialog/guides.cpp b/src/ui/dialog/guides.cpp
--- /dev/null
+++ b/src/ui/dialog/guides.cpp
@@ -0,0 +1,285 @@
+/** @file
+ * @brief Simple guideline dialog
+ */
+/* Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Andrius R. <knutux@gmail.com>
+ * Johan Engelen
+ *
+ * Copyright (C) 1999-2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "display/guideline.h"
+#include "helper/unit-menu.h"
+#include "helper/units.h"
+#include "desktop.h"
+#include "document.h"
+#include "sp-guide.h"
+#include "sp-namedview.h"
+#include "desktop-handles.h"
+#include "event-context.h"
+#include "widgets/desktop-widget.h"
+#include "sp-metrics.h"
+#include <glibmm/i18n.h>
+#include "dialogs/dialog-events.h"
+#include "message-context.h"
+#include "xml/repr.h"
+#include <2geom/point.h>
+#include <2geom/angle.h>
+#include "guides.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+GuidelinePropertiesDialog::GuidelinePropertiesDialog(SPGuide *guide, SPDesktop *desktop)
+: _desktop(desktop), _guide(guide),
+ _label_units(_("Unit:")),
+ _label_X(_("X:")),
+ _label_Y(_("Y:")),
+ _label_degrees(_("Angle (degrees):")),
+ _relative_toggle(_("Rela_tive change"), _("Move and/or rotate the guide relative to current settings")),
+ _adjustment_x(0.0, -1e6, 1e6, 1.0, 10.0, 10.0),
+ _adjustment_y(0.0, -1e6, 1e6, 1.0, 10.0, 10.0),
+ _adj_angle(0.0, -360, 360, 1.0, 10.0, 10.0),
+ _unit_selector(NULL), _mode(true), _oldpos(0.,0.), _oldangle(0.0)
+{
+}
+
+GuidelinePropertiesDialog::~GuidelinePropertiesDialog() {
+}
+
+void GuidelinePropertiesDialog::showDialog(SPGuide *guide, SPDesktop *desktop) {
+ GuidelinePropertiesDialog dialog(guide, desktop);
+ dialog._setup();
+ dialog.run();
+}
+
+void GuidelinePropertiesDialog::_modeChanged()
+{
+ _mode = !_relative_toggle.get_active();
+ if (!_mode) {
+ // relative
+ _spin_angle.set_value(0);
+
+ _spin_button_y.set_value(0);
+ _spin_button_x.set_value(0);
+ } else {
+ // absolute
+ _spin_angle.set_value(_oldangle);
+
+ SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(_unit_selector->gobj()));
+ gdouble const val_y = sp_pixels_get_units(_oldpos[Geom::Y], unit);
+ _spin_button_y.set_value(val_y);
+ gdouble const val_x = sp_pixels_get_units(_oldpos[Geom::X], unit);
+ _spin_button_x.set_value(val_x);
+ }
+}
+
+void GuidelinePropertiesDialog::_onApply()
+{
+ double deg_angle = _spin_angle.get_value();
+ if (!_mode)
+ deg_angle += _oldangle;
+ Geom::Point normal;
+ if ( deg_angle == 90. || deg_angle == 270. || deg_angle == -90. || deg_angle == -270.) {
+ normal = Geom::Point(1.,0.);
+ } else if ( deg_angle == 0. || deg_angle == 180. || deg_angle == -180.) {
+ normal = Geom::Point(0.,1.);
+ } else {
+ double rad_angle = Geom::deg_to_rad( deg_angle );
+ normal = Geom::rot90(Geom::Point::polar(rad_angle, 1.0));
+ }
+ sp_guide_set_normal(*_guide, normal, true);
+
+ SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(_unit_selector->gobj()));
+ gdouble const raw_dist_x = _spin_button_x.get_value();
+ gdouble const points_x = sp_units_get_pixels(raw_dist_x, unit);
+ gdouble const raw_dist_y = _spin_button_y.get_value();
+ gdouble const points_y = sp_units_get_pixels(raw_dist_y, unit);
+ Geom::Point newpos(points_x, points_y);
+ if (!_mode)
+ newpos += _oldpos;
+
+ sp_guide_moveto(*_guide, newpos, true);
+
+ sp_document_done(SP_OBJECT_DOCUMENT(_guide), SP_VERB_NONE,
+ _("Set guide properties"));
+}
+
+void GuidelinePropertiesDialog::_onOK()
+{
+ _onApply();
+}
+
+void GuidelinePropertiesDialog::_onDelete()
+{
+ SPDocument *doc = SP_OBJECT_DOCUMENT(_guide);
+ sp_guide_remove(_guide);
+ sp_document_done(doc, SP_VERB_NONE,
+ _("Delete guide"));
+}
+
+void GuidelinePropertiesDialog::_response(gint response)
+{
+ switch (response) {
+ case Gtk::RESPONSE_OK:
+ _onOK();
+ break;
+ case -12:
+ _onDelete();
+ break;
+ case Gtk::RESPONSE_CANCEL:
+ break;
+ case Gtk::RESPONSE_DELETE_EVENT:
+ break;
+/* case GTK_RESPONSE_APPLY:
+ _onApply();
+ break;
+*/
+ default:
+ g_assert_not_reached();
+ }
+}
+
+void GuidelinePropertiesDialog::_setup() {
+ set_title(_("Guideline"));
+ add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
+ add_button(Gtk::Stock::DELETE, -12);
+ add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+
+ Gtk::VBox *mainVBox = get_vbox();
+
+ _layout_table.set_spacings(4);
+ _layout_table.resize (3, 4);
+
+ mainVBox->pack_start(_layout_table, false, false, 0);
+
+ _label_name.set_label("foo0");
+ _layout_table.attach(_label_name,
+ 0, 3, 0, 1, Gtk::FILL, Gtk::FILL);
+ _label_name.set_alignment(0, 0.5);
+
+ _label_descr.set_label("foo1");
+ _layout_table.attach(_label_descr,
+ 0, 3, 1, 2, Gtk::FILL, Gtk::FILL);
+ _label_descr.set_alignment(0, 0.5);
+
+ // indent
+ _layout_table.attach(*manage(new Gtk::Label(" ")),
+ 0, 1, 2, 3, Gtk::FILL, Gtk::FILL, 10);
+
+ // mode radio button
+ _layout_table.attach(_relative_toggle,
+ 1, 3, 9, 10, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
+ _relative_toggle.signal_toggled().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_modeChanged));
+
+ // unitmenu
+ /* fixme: We should allow percents here too, as percents of the canvas size */
+ GtkWidget *unit_selector = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
+ sp_unit_selector_set_unit(SP_UNIT_SELECTOR(unit_selector), _desktop->namedview->doc_units);
+ _unit_selector = Gtk::manage(Glib::wrap(unit_selector));
+
+ // position spinbuttons
+ sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(unit_selector), GTK_ADJUSTMENT(_adjustment_x.gobj()));
+ sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(unit_selector), GTK_ADJUSTMENT(_adjustment_y.gobj()));
+ _spin_button_x.configure(_adjustment_x, 1.0 , 3);
+ _spin_button_x.set_numeric();
+ _spin_button_y.configure(_adjustment_y, 1.0 , 3);
+ _spin_button_y.set_numeric();
+ _layout_table.attach(_label_X,
+ 1, 2, 4, 5, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(_spin_button_x,
+ 2, 3, 4, 5, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(_label_Y,
+ 1, 2, 5, 6, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(_spin_button_y,
+ 2, 3, 5, 6, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
+ gtk_signal_connect_object(GTK_OBJECT(_spin_button_x.gobj()), "activate",
+ GTK_SIGNAL_FUNC(gtk_window_activate_default),
+ gobj());
+
+ _layout_table.attach(_label_units,
+ 1, 2, 6, 7, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(*_unit_selector,
+ 2, 3, 6, 7, Gtk::FILL, Gtk::FILL);
+
+ // angle spinbutton
+ _spin_angle.configure(_adj_angle, 5.0 , 3);
+ _spin_angle.set_numeric();
+ _spin_angle.show();
+ _layout_table.attach(_label_degrees,
+ 1, 2, 8, 9, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(_spin_angle,
+ 2, 3, 8, 9, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
+
+
+ // dialog
+ set_default_response(Gtk::RESPONSE_OK);
+ signal_response().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_response));
+
+ // initialize dialog
+ _oldpos = _guide->point_on_line;
+ if (_guide->is_vertical()) {
+ _oldangle = 90;
+ } else if (_guide->is_horizontal()) {
+ _oldangle = 0;
+ } else {
+ _oldangle = Geom::rad_to_deg( std::atan2( - _guide->normal_to_line[Geom::X], _guide->normal_to_line[Geom::Y] ) );
+ }
+
+ {
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (_guide);
+ const gchar *guide_id = repr->attribute("id");
+ gchar *label = g_strdup_printf(_("Guideline ID: %s"), guide_id);
+ _label_name.set_label(label);
+ g_free(label);
+ }
+ {
+ gchar *guide_description = sp_guide_description(_guide);
+ gchar *label = g_strdup_printf(_("Current: %s"), guide_description);
+ g_free(guide_description);
+ _label_descr.set_markup(label);
+ g_free(label);
+ }
+
+ _modeChanged(); // sets values of spinboxes.
+
+ if ( _oldangle == 90. || _oldangle == 270. || _oldangle == -90. || _oldangle == -270.) {
+ _spin_button_x.grab_focus();
+ _spin_button_x.select_region(0, 20);
+ } else if ( _oldangle == 0. || _oldangle == 180. || _oldangle == -180.) {
+ _spin_button_y.grab_focus();
+ _spin_button_y.select_region(0, 20);
+ } else {
+ _spin_angle.grab_focus();
+ _spin_angle.select_region(0, 20);
+ }
+
+ set_position(Gtk::WIN_POS_MOUSE);
+
+ show_all_children();
+ set_modal(true);
+ _desktop->setWindowTransient (gobj());
+ property_destroy_with_parent() = true;
+}
+
+}
+}
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/guides.h b/src/ui/dialog/guides.h
--- /dev/null
+++ b/src/ui/dialog/guides.h
@@ -0,0 +1,93 @@
+/**
+ *
+ * \brief Dialog for modifying guidelines
+ *
+ * Author:
+ * Andrius R. <knutux@gmail.com>
+ * Johan Engelen
+ *
+ * Copyright (C) 2006-2007 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_DIALOG_GUIDELINE_H
+#define INKSCAPE_DIALOG_GUIDELINE_H
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/table.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/label.h>
+#include <gtkmm/stock.h>
+#include <gtkmm/adjustment.h>
+#include "ui/widget/button.h"
+#include <2geom/point.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+class GuidelinePropertiesDialog : public Gtk::Dialog {
+public:
+ GuidelinePropertiesDialog(SPGuide *guide, SPDesktop *desktop);
+ virtual ~GuidelinePropertiesDialog();
+
+ Glib::ustring getName() const { return "GuidelinePropertiesDialog"; }
+
+ static void showDialog(SPGuide *guide, SPDesktop *desktop);
+
+protected:
+ void _setup();
+
+ void _onApply();
+ void _onOK();
+ void _onDelete();
+
+ void _response(gint response);
+ void _modeChanged();
+
+private:
+ GuidelinePropertiesDialog(GuidelinePropertiesDialog const &); // no copy
+ GuidelinePropertiesDialog &operator=(GuidelinePropertiesDialog const &); // no assign
+
+ SPDesktop *_desktop;
+ SPGuide *_guide;
+ Gtk::Table _layout_table;
+ Gtk::Label _label_name;
+ Gtk::Label _label_descr;
+ Gtk::Label _label_units;
+ Gtk::Label _label_X;
+ Gtk::Label _label_Y;
+ Gtk::Label _label_degrees;
+ Inkscape::UI::Widget::CheckButton _relative_toggle;
+ Gtk::Adjustment _adjustment_x;
+ Gtk::SpinButton _spin_button_x;
+ Gtk::Adjustment _adjustment_y;
+ Gtk::SpinButton _spin_button_y;
+
+ Gtk::Adjustment _adj_angle;
+ Gtk::SpinButton _spin_angle;
+
+ Gtk::Widget *_unit_selector;
+ bool _mode;
+ Geom::Point _oldpos;
+ gdouble _oldangle;
+};
+
+} // namespace
+} // namespace
+} // namespace
+
+
+#endif // INKSCAPE_DIALOG_GUIDELINE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp
--- /dev/null
@@ -0,0 +1,307 @@
+/** @file
+ * @brief A simple dialog for previewing icon representation.
+ */
+/* Authors:
+ * Jon A. Cruz
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004 Bob Jamison
+ * Copyright (C) 2005 Jon A. Cruz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <glib/gmem.h>
+#include <glibmm/i18n.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/stock.h>
+
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "display/nr-arena.h"
+#include "document.h"
+#include "inkscape.h"
+#include "preferences.h"
+#include "selection.h"
+#include "sp-root.h"
+#include "xml/repr.h"
+
+#include "icon-preview.h"
+
+extern "C" {
+// takes doc, root, icon, and icon name to produce pixels
+guchar *
+sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
+ const gchar *name, unsigned int psize );
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+
+IconPreviewPanel&
+IconPreviewPanel::getInstance()
+{
+ static IconPreviewPanel &instance = *new IconPreviewPanel();
+
+ instance.refreshPreview();
+
+ return instance;
+}
+
+//#########################################################################
+//## E V E N T S
+//#########################################################################
+
+void IconPreviewPanel::on_button_clicked(int which)
+{
+ if ( hot != which ) {
+ buttons[hot]->set_active( false );
+
+ hot = which;
+ updateMagnify();
+ _getContents()->queue_draw();
+ }
+}
+
+
+
+
+//#########################################################################
+//## C O N S T R U C T O R / D E S T R U C T O R
+//#########################################################################
+/**
+ * Constructor
+ */
+IconPreviewPanel::IconPreviewPanel() :
+ UI::Widget::Panel("", "/dialogs/iconpreview", SP_VERB_VIEW_ICON_PREVIEW),
+ hot(1),
+ refreshButton(0),
+ selectionButton(0)
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ numEntries = 0;
+
+ std::vector<Glib::ustring> pref_sizes = prefs->getAllDirs("/iconpreview/sizes/default");
+ std::vector<int> rawSizes;
+
+ for (std::vector<Glib::ustring>::iterator i = pref_sizes.begin(); i != pref_sizes.end(); ++i) {
+ if (prefs->getBool(*i + "/show", true)) {
+ int sizeVal = prefs->getInt(*i + "/value", -1);
+ if (sizeVal > 0) {
+ rawSizes.push_back(sizeVal);
+ }
+ }
+ }
+
+ if ( !rawSizes.empty() ) {
+ numEntries = rawSizes.size();
+ sizes = new int[numEntries];
+ int i = 0;
+ for ( std::vector<int>::iterator it = rawSizes.begin(); it != rawSizes.end(); ++it, ++i ) {
+ sizes[i] = *it;
+ }
+ }
+
+ if ( numEntries < 1 )
+ {
+ numEntries = 5;
+ sizes = new int[numEntries];
+ sizes[0] = 16;
+ sizes[1] = 24;
+ sizes[2] = 32;
+ sizes[3] = 48;
+ sizes[4] = 128;
+ }
+
+ pixMem = new guchar*[numEntries];
+ images = new Gtk::Image*[numEntries];
+ labels = new Glib::ustring*[numEntries];
+ buttons = new Gtk::ToggleToolButton*[numEntries];
+
+
+ for ( int i = 0; i < numEntries; i++ ) {
+ char *label = g_strdup_printf(_("%d x %d"), sizes[i], sizes[i]);
+ labels[i] = new Glib::ustring(label);
+ g_free(label);
+ pixMem[i] = 0;
+ images[i] = 0;
+ }
+
+
+ magLabel.set_label( *labels[hot] );
+
+ Gtk::VBox* magBox = new Gtk::VBox();
+
+ magBox->pack_start( magnified );
+ magBox->pack_start( magLabel, Gtk::PACK_SHRINK );
+
+
+ Gtk::VBox * verts = new Gtk::VBox();
+ for ( int i = 0; i < numEntries; i++ ) {
+ pixMem[i] = new guchar[4 * sizes[i] * sizes[i]];
+ memset( pixMem[i], 0x00, 4 * sizes[i] * sizes[i] );
+
+ GdkPixbuf *pb = gdk_pixbuf_new_from_data( pixMem[i], GDK_COLORSPACE_RGB, TRUE, 8, sizes[i], sizes[i], sizes[i] * 4, /*(GdkPixbufDestroyNotify)g_free*/NULL, NULL );
+ GtkImage* img = GTK_IMAGE( gtk_image_new_from_pixbuf( pb ) );
+ images[i] = Glib::wrap(img);
+ Glib::ustring label(*labels[i]);
+ buttons[i] = new Gtk::ToggleToolButton(label);
+ buttons[i]->set_active( i == hot );
+ buttons[i]->set_icon_widget(*images[i]);
+
+ tips.set_tip((*buttons[i]), label);
+
+ buttons[i]->signal_clicked().connect( sigc::bind<int>( sigc::mem_fun(*this, &IconPreviewPanel::on_button_clicked), i) );
+
+
+ verts->add(*buttons[i]);
+ }
+
+ iconBox.pack_start(splitter);
+ splitter.pack1( *magBox, true, true );
+ splitter.pack2( *verts, false, false );
+
+
+ //## The Refresh button
+
+
+ Gtk::HButtonBox* holder = new Gtk::HButtonBox( Gtk::BUTTONBOX_END );
+ _getContents()->pack_end(*holder, false, false);
+
+ selectionButton = new Gtk::ToggleButton(_("Selection")); // , GTK_RESPONSE_APPLY
+ holder->pack_start( *selectionButton, false, false );
+ tips.set_tip((*selectionButton), _("Selection only or whole document"));
+ selectionButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::modeToggled) );
+
+ gint val = prefs->getBool("/iconpreview/selectionOnly");
+ selectionButton->set_active( val != 0 );
+
+ refreshButton = new Gtk::Button(Gtk::Stock::REFRESH); // , GTK_RESPONSE_APPLY
+ holder->pack_end( *refreshButton, false, false );
+ tips.set_tip((*refreshButton), _("Refresh the icons"));
+ refreshButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::refreshPreview) );
+
+
+ _getContents()->pack_start(iconBox, Gtk::PACK_EXPAND_WIDGET);
+
+ show_all_children();
+}
+
+//#########################################################################
+//## M E T H O D S
+//#########################################################################
+
+
+void IconPreviewPanel::refreshPreview()
+{
+ SPDesktop *desktop = getDesktop();
+ if ( desktop ) {
+
+ if ( selectionButton && selectionButton->get_active() )
+ {
+ Inkscape::Selection * sel = sp_desktop_selection(desktop);
+ if ( sel ) {
+ //g_message("found a selection to play with");
+
+ GSList const *items = sel->itemList();
+ SPObject *target = 0;
+ while ( items && !target ) {
+ SPItem* item = SP_ITEM( items->data );
+ SPObject * obj = SP_OBJECT(item);
+ gchar const *id = SP_OBJECT_ID( obj );
+ if ( id ) {
+ target = obj;
+ }
+
+ items = g_slist_next(items);
+ }
+ if ( target ) {
+ renderPreview(target);
+ }
+ }
+ }
+ else
+ {
+ SPObject *target = desktop->currentRoot();
+ if ( target ) {
+ renderPreview(target);
+ }
+ }
+ }
+}
+
+void IconPreviewPanel::modeToggled()
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/iconpreview/selectionOnly", (selectionButton && selectionButton->get_active()));
+
+ refreshPreview();
+}
+
+void IconPreviewPanel::renderPreview( SPObject* obj )
+{
+ SPDocument * doc = SP_OBJECT_DOCUMENT(obj);
+ gchar * id = SP_OBJECT_ID(obj);
+
+// g_message(" setting up to render '%s' as the icon", id );
+
+ NRArenaItem *root = NULL;
+
+ /* Create new arena */
+ NRArena *arena = NRArena::create();
+
+ /* Create ArenaItem and set transform */
+ unsigned int visionkey = sp_item_display_key_new(1);
+
+ root = sp_item_invoke_show ( SP_ITEM( SP_DOCUMENT_ROOT(doc) ),
+ arena, visionkey, SP_ITEM_SHOW_DISPLAY );
+
+ for ( int i = 0; i < numEntries; i++ ) {
+ guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i] );
+// g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") );
+ if ( px ) {
+ memcpy( pixMem[i], px, sizes[i] * sizes[i] * 4 );
+ g_free( px );
+ px = 0;
+ } else {
+ memset( pixMem[i], 0, sizes[i] * sizes[i] * 4 );
+ }
+ images[i]->queue_draw();
+ }
+ updateMagnify();
+
+ sp_item_invoke_hide(SP_ITEM(sp_document_root(doc)), visionkey);
+ nr_object_unref((NRObject *) arena);
+}
+
+void IconPreviewPanel::updateMagnify()
+{
+ Glib::RefPtr<Gdk::Pixbuf> buf = images[hot]->get_pixbuf()->scale_simple( 128, 128, Gdk::INTERP_NEAREST );
+ magLabel.set_label( *labels[hot] );
+ magnified.set( buf );
+ magnified.queue_draw();
+ magnified.get_parent()->queue_draw();
+}
+
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/icon-preview.h b/src/ui/dialog/icon-preview.h
--- /dev/null
@@ -0,0 +1,84 @@
+/** @file
+ * @brief A simple dialog for previewing icon representation.
+ */
+/* Authors:
+ * Jon A. Cruz
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004,2005 The Inkscape Organization
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_ICON_PREVIEW_H
+#define SEEN_ICON_PREVIEW_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/button.h>
+#include <gtkmm/label.h>
+#include <gtkmm/paned.h>
+#include <gtkmm/image.h>
+#include <gtkmm/togglebutton.h>
+#include <gtkmm/toggletoolbutton.h>
+
+#include "ui/widget/panel.h"
+
+struct SPObject;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+
+/**
+ * A panel that displays an icon preview
+ */
+class IconPreviewPanel : public UI::Widget::Panel
+{
+public:
+ IconPreviewPanel();
+ //IconPreviewPanel(Glib::ustring const &label);
+
+ static IconPreviewPanel& getInstance();
+
+ void refreshPreview();
+ void modeToggled();
+
+private:
+ IconPreviewPanel(IconPreviewPanel const &); // no copy
+ IconPreviewPanel &operator=(IconPreviewPanel const &); // no assign
+
+
+ void on_button_clicked(int which);
+ void renderPreview( SPObject* obj );
+ void updateMagnify();
+
+ Gtk::Tooltips tips;
+
+ Gtk::VBox iconBox;
+ Gtk::HPaned splitter;
+
+ int hot;
+ int numEntries;
+ int* sizes;
+
+ Gtk::Image magnified;
+ Gtk::Label magLabel;
+
+ Gtk::Button *refreshButton;
+ Gtk::ToggleButton *selectionButton;
+
+ guchar** pixMem;
+ Gtk::Image** images;
+ Glib::ustring** labels;
+ Gtk::ToggleToolButton** buttons;
+};
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+
+#endif // SEEN_ICON_PREVIEW_H
diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp
--- /dev/null
@@ -0,0 +1,256 @@
+/** @file
+ * @brief Dialog for renaming layers
+ */
+/* Author:
+ * Bryce W. Harrington <bryce@bryceharrington.com>
+ * Andrius R. <knutux@gmail.com>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ * Copyright (C) 2006 Andrius R.
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/stock.h>
+#include <glibmm/i18n.h>
+#include "inkscape.h"
+#include "desktop.h"
+#include "document.h"
+#include "layer-manager.h"
+#include "message-stack.h"
+#include "desktop-handles.h"
+#include "sp-object.h"
+#include "sp-item.h"
+
+#include "layer-properties.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+LayerPropertiesDialog::LayerPropertiesDialog()
+: _strategy(NULL), _desktop(NULL), _layer(NULL), _position_visible(false)
+{
+ Gtk::VBox *mainVBox = get_vbox();
+
+ _layout_table.set_spacings(4);
+ _layout_table.resize (1, 2);
+
+ // Layer name widgets
+ _layer_name_entry.set_activates_default(true);
+ _layer_name_label.set_label(_("Layer name:"));
+ _layer_name_label.set_alignment(1.0, 0.5);
+
+ _layout_table.attach(_layer_name_label,
+ 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);
+
+ // Buttons
+ _close_button.set_use_stock(true);
+ _close_button.set_label(Gtk::Stock::CANCEL.id);
+ _close_button.set_flags(Gtk::CAN_DEFAULT);
+
+ _apply_button.set_use_underline(true);
+ _apply_button.set_flags(Gtk::CAN_DEFAULT);
+
+ _close_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &LayerPropertiesDialog::_close));
+ _apply_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &LayerPropertiesDialog::_apply));
+
+ signal_delete_event().connect(
+ sigc::bind_return(
+ sigc::hide(sigc::mem_fun(*this, &LayerPropertiesDialog::_close)),
+ true
+ )
+ );
+
+ add_action_widget(_close_button, Gtk::RESPONSE_CLOSE);
+ add_action_widget(_apply_button, Gtk::RESPONSE_APPLY);
+
+ _apply_button.grab_default();
+
+ show_all_children();
+}
+
+LayerPropertiesDialog::~LayerPropertiesDialog() {
+ _setDesktop(NULL);
+ _setLayer(NULL);
+}
+
+void LayerPropertiesDialog::_showDialog(LayerPropertiesDialog::Strategy &strategy,
+ SPDesktop *desktop, SPObject *layer)
+{
+ LayerPropertiesDialog *dialog = new LayerPropertiesDialog();
+
+ dialog->_strategy = &strategy;
+ dialog->_setDesktop(desktop);
+ dialog->_setLayer(layer);
+
+ dialog->_strategy->setup(*dialog);
+
+ dialog->set_modal(true);
+ desktop->setWindowTransient (dialog->gobj());
+ dialog->property_destroy_with_parent() = true;
+
+ dialog->show();
+ dialog->present();
+}
+
+void
+LayerPropertiesDialog::_apply()
+{
+ g_assert(_strategy != NULL);
+
+ _strategy->perform(*this);
+ sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_NONE,
+ _("Add layer"));
+
+ _close();
+}
+
+void
+LayerPropertiesDialog::_close()
+{
+ _setLayer(NULL);
+ _setDesktop(NULL);
+ destroy_();
+ Glib::signal_idle().connect(
+ sigc::bind_return(
+ sigc::bind(sigc::ptr_fun(&::operator delete), this),
+ false
+ )
+ );
+}
+
+void
+LayerPropertiesDialog::_setup_position_controls() {
+ if ( NULL == _layer || _desktop->currentRoot() == _layer ) {
+ // no layers yet, so option above/below/sublayer is useless
+ return;
+ }
+
+ _position_visible = true;
+ _dropdown_list = Gtk::ListStore::create(_dropdown_columns);
+ _layer_position_combo.set_model(_dropdown_list);
+ _layer_position_combo.pack_start(_label_renderer);
+ _layer_position_combo.set_cell_data_func(_label_renderer,
+ sigc::mem_fun(*this, &LayerPropertiesDialog::_prepareLabelRenderer));
+
+ _layout_table.resize (2, 2);
+
+ Gtk::ListStore::iterator row;
+ row = _dropdown_list->append();
+ row->set_value(_dropdown_columns.position, LPOS_ABOVE);
+ row->set_value(_dropdown_columns.name, Glib::ustring(_("Above current")));
+ _layer_position_combo.set_active(row);
+ row = _dropdown_list->append();
+ row->set_value(_dropdown_columns.position, LPOS_BELOW);
+ row->set_value(_dropdown_columns.name, Glib::ustring(_("Below current")));
+ row = _dropdown_list->append();
+ row->set_value(_dropdown_columns.position, LPOS_CHILD);
+ row->set_value(_dropdown_columns.name, Glib::ustring(_("As sublayer of current")));
+
+ _layout_table.attach(_layer_position_combo,
+ 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+ _layer_position_label.set_label(_("Position:"));
+ _layer_position_label.set_alignment(1.0, 0.5);
+ _layout_table.attach(_layer_position_label,
+ 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
+ show_all_children();
+}
+
+/** Formats the label for a given layer row
+ */
+void LayerPropertiesDialog::_prepareLabelRenderer(
+ Gtk::TreeModel::const_iterator const &row
+) {
+ Glib::ustring name=(*row)[_dropdown_columns.name];
+ _label_renderer.property_markup() = name.c_str();
+}
+
+void LayerPropertiesDialog::Rename::setup(LayerPropertiesDialog &dialog) {
+ SPDesktop *desktop=dialog._desktop;
+ dialog.set_title(_("Rename Layer"));
+ gchar const *name = desktop->currentLayer()->label();
+ dialog._layer_name_entry.set_text(( name ? name : "" ));
+ dialog._apply_button.set_label(_("_Rename"));
+}
+
+void LayerPropertiesDialog::Rename::perform(LayerPropertiesDialog &dialog) {
+ SPDesktop *desktop=dialog._desktop;
+ Glib::ustring name(dialog._layer_name_entry.get_text());
+ desktop->layer_manager->renameLayer( desktop->currentLayer(),
+ ( name.empty() ? NULL : (gchar *)name.c_str() )
+ );
+ sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE,
+ _("Rename layer"));
+ // TRANSLATORS: This means "The layer has been renamed"
+ desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Renamed layer"));
+}
+
+void LayerPropertiesDialog::Create::setup(LayerPropertiesDialog &dialog) {
+ dialog.set_title(_("Add Layer"));
+ dialog._layer_name_entry.set_text("");
+ dialog._apply_button.set_label(_("_Add"));
+ dialog._setup_position_controls();
+}
+
+void LayerPropertiesDialog::Create::perform(LayerPropertiesDialog &dialog) {
+ SPDesktop *desktop=dialog._desktop;
+
+ LayerRelativePosition position = LPOS_ABOVE;
+
+ if (dialog._position_visible) {
+ Gtk::ListStore::iterator activeRow(dialog._layer_position_combo.get_active());
+ position = activeRow->get_value(dialog._dropdown_columns.position);
+ }
+
+ SPObject *new_layer=Inkscape::create_layer(desktop->currentRoot(), dialog._layer, position);
+
+ Glib::ustring name(dialog._layer_name_entry.get_text());
+ if (!name.empty()) {
+ desktop->layer_manager->renameLayer( new_layer, (gchar *)name.c_str() );
+ }
+ sp_desktop_selection(desktop)->clear();
+ desktop->setCurrentLayer(new_layer);
+ desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("New layer created."));
+}
+
+void LayerPropertiesDialog::_setDesktop(SPDesktop *desktop) {
+ if (desktop) {
+ Inkscape::GC::anchor (desktop);
+ }
+ if (_desktop) {
+ Inkscape::GC::release (_desktop);
+ }
+ _desktop = desktop;
+}
+
+void LayerPropertiesDialog::_setLayer(SPObject *layer) {
+ if (layer) {
+ sp_object_ref(layer, NULL);
+ }
+ if (_layer) {
+ sp_object_unref(_layer, NULL);
+ }
+ _layer = layer;
+}
+
+} // namespace
+} // namespace
+} // namespace
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/layer-properties.h b/src/ui/dialog/layer-properties.h
--- /dev/null
@@ -0,0 +1,132 @@
+/** @file
+ * @brief Dialog for renaming layers
+ */
+/* Author:
+ * Bryce W. Harrington <bryce@bryceharrington.com>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_DIALOG_LAYER_PROPERTIES_H
+#define INKSCAPE_DIALOG_LAYER_PROPERTIES_H
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/notebook.h>
+#include <gtkmm/separator.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/entry.h>
+#include <gtkmm/label.h>
+#include <gtkmm/table.h>
+#include <gtkmm/combobox.h>
+#include <gtkmm/liststore.h>
+
+#include "selection.h"
+#include "layer-fns.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+class LayerPropertiesDialog : public Gtk::Dialog {
+ public:
+ LayerPropertiesDialog();
+ virtual ~LayerPropertiesDialog();
+
+ Glib::ustring getName() const { return "LayerPropertiesDialog"; }
+
+ static void showRename(SPDesktop *desktop, SPObject *layer) {
+ _showDialog(Rename::instance(), desktop, layer);
+ }
+ static void showCreate(SPDesktop *desktop, SPObject *layer) {
+ _showDialog(Create::instance(), desktop, layer);
+ }
+
+protected:
+ struct Strategy {
+ virtual ~Strategy() {}
+ virtual void setup(LayerPropertiesDialog &)=0;
+ virtual void perform(LayerPropertiesDialog &)=0;
+ };
+ struct Rename : public Strategy {
+ static Rename &instance() { static Rename instance; return instance; }
+ void setup(LayerPropertiesDialog &dialog);
+ void perform(LayerPropertiesDialog &dialog);
+ };
+ struct Create : public Strategy {
+ static Create &instance() { static Create instance; return instance; }
+ void setup(LayerPropertiesDialog &dialog);
+ void perform(LayerPropertiesDialog &dialog);
+ };
+
+ friend class Rename;
+ friend class Create;
+
+ Strategy *_strategy;
+ SPDesktop *_desktop;
+ SPObject *_layer;
+
+ class PositionDropdownColumns : public Gtk::TreeModel::ColumnRecord {
+ public:
+ Gtk::TreeModelColumn<LayerRelativePosition> position;
+ Gtk::TreeModelColumn<Glib::ustring> name;
+
+ PositionDropdownColumns() {
+ add(position); add(name);
+ }
+ };
+
+ Gtk::Label _layer_name_label;
+ Gtk::Entry _layer_name_entry;
+ Gtk::Label _layer_position_label;
+ Gtk::ComboBox _layer_position_combo;
+ Gtk::Table _layout_table;
+ bool _position_visible;
+
+ PositionDropdownColumns _dropdown_columns;
+ Gtk::CellRendererText _label_renderer;
+ Glib::RefPtr<Gtk::ListStore> _dropdown_list;
+
+ Gtk::Button _close_button;
+ Gtk::Button _apply_button;
+
+ sigc::connection _destroy_connection;
+
+ static LayerPropertiesDialog &_instance() {
+ static LayerPropertiesDialog instance;
+ return instance;
+ }
+
+ void _setDesktop(SPDesktop *desktop);
+ void _setLayer(SPObject *layer);
+
+ static void _showDialog(Strategy &strategy, SPDesktop *desktop, SPObject *layer);
+ void _apply();
+ void _close();
+
+ void _setup_position_controls();
+ void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row);
+
+private:
+ LayerPropertiesDialog(LayerPropertiesDialog const &); // no copy
+ LayerPropertiesDialog &operator=(LayerPropertiesDialog const &); // no assign
+};
+
+} // namespace
+} // namespace
+} // namespace
+
+
+#endif //INKSCAPE_DIALOG_LAYER_PROPERTIES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp
--- /dev/null
+++ b/src/ui/dialog/layers.cpp
@@ -0,0 +1,805 @@
+/*
+ * A simple panel for layers
+ *
+ * Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2006 Jon A. Cruz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtkstock.h>
+#include <gtk/gtkmain.h>
+#include <gtkmm/widget.h>
+#include <gtkmm/icontheme.h>
+#include <glibmm/i18n.h>
+
+#include "desktop.h"
+#include "desktop-style.h"
+#include "document.h"
+#include "helper/action.h"
+#include "inkscape.h"
+#include "layer-fns.h"
+#include "layer-manager.h"
+#include "preferences.h"
+#include "sp-item.h"
+#include "sp-object.h"
+#include "svg/css-ostringstream.h"
+#include "ui/icon-names.h"
+#include "ui/widget/imagetoggler.h"
+#include "verbs.h"
+#include "widgets/icon.h"
+#include "xml/repr.h"
+
+#include "layers.h"
+
+//#define DUMP_LAYERS 1
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+LayersPanel&
+LayersPanel::getInstance()
+{
+ return *new LayersPanel();
+}
+
+enum {
+ COL_VISIBLE = 1,
+ COL_LOCKED
+};
+
+enum {
+ BUTTON_NEW = 0,
+ BUTTON_RENAME,
+ BUTTON_TOP,
+ BUTTON_BOTTOM,
+ BUTTON_UP,
+ BUTTON_DOWN,
+ BUTTON_DUPLICATE,
+ BUTTON_DELETE,
+ BUTTON_SOLO
+};
+
+class LayersPanel::InternalUIBounce
+{
+public:
+ int _actionCode;
+ SPObject* _target;
+};
+
+static gboolean layers_panel_activated( GtkObject */*object*/, GdkEvent * /*event*/, gpointer data )
+{
+ if ( data )
+ {
+ LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
+ panel->setDesktop(panel->getDesktop());
+ }
+
+ return FALSE;
+}
+
+static gboolean layers_panel_deactivated( GtkObject */*object*/, GdkEvent * /*event*/, gpointer data )
+{
+ if ( data )
+ {
+ LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
+ panel->setDesktop(NULL);
+ }
+
+ return FALSE;
+}
+
+
+void LayersPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback )
+{
+ bool set = false;
+
+ if ( iconName ) {
+ GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
+ gtk_widget_show( child );
+ btn.add( *manage(Glib::wrap(child)) );
+ set = true;
+ }
+
+ if ( desktop ) {
+ Verb *verb = Verb::get( code );
+ if ( verb ) {
+ SPAction *action = verb->get_action(desktop);
+ if ( !set && action && action->image ) {
+ GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image );
+ gtk_widget_show( child );
+ btn.add( *manage(Glib::wrap(child)) );
+ set = true;
+ }
+
+ if ( action && action->tip ) {
+ _tips.set_tip( btn, action->tip );
+ }
+ }
+ }
+
+ if ( !set && fallback ) {
+ btn.set_label( fallback );
+ }
+}
+
+
+Gtk::MenuItem& LayersPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
+{
+ GtkWidget* iconWidget = 0;
+ const char* label = 0;
+
+ if ( iconName ) {
+ iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName );
+ }
+
+ if ( desktop ) {
+ Verb *verb = Verb::get( code );
+ if ( verb ) {
+ SPAction *action = verb->get_action(desktop);
+ if ( !iconWidget && action && action->image ) {
+ iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image );
+ }
+
+ if ( action ) {
+ label = action->name;
+ }
+ }
+ }
+
+ if ( !label && fallback ) {
+ label = fallback;
+ }
+
+ Gtk::Widget* wrapped = 0;
+ if ( iconWidget ) {
+ wrapped = manage(Glib::wrap(iconWidget));
+ wrapped->show();
+ }
+
+
+
+ Gtk::Menu::MenuList& menulist = _popupMenu.items();
+
+ if ( wrapped ) {
+ menulist.push_back( Gtk::Menu_Helpers::ImageMenuElem( label, *wrapped, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
+ } else {
+ menulist.push_back( Gtk::Menu_Helpers::MenuElem( label, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
+ }
+ return menulist.back();
+}
+
+void LayersPanel::_fireAction( unsigned int code )
+{
+ if ( _desktop ) {
+ Verb *verb = Verb::get( code );
+ if ( verb ) {
+ SPAction *action = verb->get_action(_desktop);
+ if ( action ) {
+ sp_action_perform( action, NULL );
+// } else {
+// g_message("no action");
+ }
+// } else {
+// g_message("no verb for %u", code);
+ }
+// } else {
+// g_message("no active desktop");
+ }
+}
+
+// SP_VERB_LAYER_NEXT,
+// SP_VERB_LAYER_PREV,
+void LayersPanel::_takeAction( int val )
+{
+ if ( !_pending ) {
+ _pending = new InternalUIBounce();
+ _pending->_actionCode = val;
+ _pending->_target = _selectedLayer();
+ Glib::signal_timeout().connect( sigc::mem_fun(*this, &LayersPanel::_executeAction), 0 );
+ }
+}
+
+bool LayersPanel::_executeAction()
+{
+ // Make sure selected layer hasn't changed since the action was triggered
+ if ( _pending
+ && (
+ (_pending->_actionCode == BUTTON_NEW)
+ || !( (_desktop && _desktop->currentLayer())
+ && (_desktop->currentLayer() != _pending->_target)
+ )
+ )
+ ) {
+ int val = _pending->_actionCode;
+// SPObject* target = _pending->_target;
+
+ switch ( val ) {
+ case BUTTON_NEW:
+ {
+ _fireAction( SP_VERB_LAYER_NEW );
+ }
+ break;
+ case BUTTON_RENAME:
+ {
+ _fireAction( SP_VERB_LAYER_RENAME );
+ }
+ break;
+ case BUTTON_TOP:
+ {
+ _fireAction( SP_VERB_LAYER_TO_TOP );
+ }
+ break;
+ case BUTTON_BOTTOM:
+ {
+ _fireAction( SP_VERB_LAYER_TO_BOTTOM );
+ }
+ break;
+ case BUTTON_UP:
+ {
+ _fireAction( SP_VERB_LAYER_RAISE );
+ }
+ break;
+ case BUTTON_DOWN:
+ {
+ _fireAction( SP_VERB_LAYER_LOWER );
+ }
+ break;
+ case BUTTON_DUPLICATE:
+ {
+ _fireAction( SP_VERB_LAYER_DUPLICATE );
+ }
+ break;
+ case BUTTON_DELETE:
+ {
+ _fireAction( SP_VERB_LAYER_DELETE );
+ }
+ case BUTTON_SOLO:
+ {
+ _fireAction( SP_VERB_LAYER_SOLO );
+ }
+ break;
+ }
+
+ delete _pending;
+ _pending = 0;
+ }
+
+ return false;
+}
+
+class LayersPanel::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;
+};
+
+void LayersPanel::_updateLayer( SPObject *layer ) {
+ _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForUpdated), layer) );
+}
+
+bool LayersPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* layer)
+{
+ bool stopGoing = false;
+ Gtk::TreeModel::Row row = *iter;
+ Glib::ustring tmp = row[_model->_colLabel];
+ if ( layer == row[_model->_colObject] )
+ {
+ row[_model->_colLabel] = layer->label() ? layer->label() : SP_OBJECT_ID(layer);
+ row[_model->_colVisible] = SP_IS_ITEM(layer) ? !SP_ITEM(layer)->isHidden() : false;
+ row[_model->_colLocked] = SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false;
+
+ stopGoing = true;
+ }
+
+ return stopGoing;
+}
+
+void LayersPanel::_selectLayer( SPObject *layer ) {
+ if ( !layer || (_desktop && _desktop->doc() && (layer == _desktop->doc()->root)) ) {
+ if ( _tree.get_selection()->count_selected_rows() != 0 ) {
+ _tree.get_selection()->unselect_all();
+ }
+ } else {
+ _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForSelected), layer) );
+ }
+
+ _checkTreeSelection();
+}
+
+bool LayersPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer)
+{
+ bool stopGoing = false;
+
+ Gtk::TreeModel::Row row = *iter;
+ if ( layer == row[_model->_colObject] )
+ {
+ _tree.expand_to_path( path );
+
+ Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
+
+ select->select(iter);
+
+ stopGoing = true;
+ }
+
+ return stopGoing;
+}
+
+void LayersPanel::_layersChanged()
+{
+// g_message("_layersChanged()");
+ SPDocument* document = _desktop->doc();
+ SPObject* root = document->root;
+ if ( root ) {
+ _selectedConnection.block();
+ if ( _mgr && _mgr->includes( root ) ) {
+ SPObject* target = _desktop->currentLayer();
+ _store->clear();
+
+#if DUMP_LAYERS
+ g_message("root:%p {%s} [%s]", root, root->id, root->label() );
+#endif // DUMP_LAYERS
+ _addLayer( document, root, 0, target, 0 );
+ }
+ _selectedConnection.unblock();
+ }
+}
+
+void LayersPanel::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level )
+{
+ if ( layer && (level < _maxNestDepth) ) {
+ unsigned int counter = _mgr->childCount(layer);
+ for ( unsigned int i = 0; i < counter; i++ ) {
+ SPObject *child = _mgr->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() : SP_OBJECT_ID(child);
+ 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* LayersPanel::_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;
+}
+
+void LayersPanel::_pushTreeSelectionToCurrent()
+{
+ SPObject* inTree = _selectedLayer();
+ // TODO hunt down the possible API abuse in getting NULL
+ if ( _desktop->currentRoot() ) {
+ if ( inTree ) {
+ SPObject* curr = _desktop->currentLayer();
+ if ( curr != inTree ) {
+ _mgr->setCurrentLayer( inTree );
+ }
+ } else {
+ _mgr->setCurrentLayer( _desktop->doc()->root );
+ }
+ }
+}
+
+void LayersPanel::_checkTreeSelection()
+{
+ bool sensitive = false;
+ bool sensitiveNonTop = false;
+ bool sensitiveNonBottom = false;
+ if ( _tree.get_selection()->count_selected_rows() > 0 ) {
+ sensitive = true;
+
+ SPObject* inTree = _selectedLayer();
+ if ( inTree ) {
+
+ sensitiveNonTop = (Inkscape::next_layer(inTree->parent, inTree) != 0);
+ sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0);
+
+ }
+ }
+
+
+ for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
+ (*it)->set_sensitive( sensitive );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
+ (*it)->set_sensitive( sensitiveNonTop );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
+ (*it)->set_sensitive( sensitiveNonBottom );
+ }
+}
+
+void LayersPanel::_preToggle( GdkEvent const *event )
+{
+ if ( _toggleEvent ) {
+ gdk_event_free(_toggleEvent);
+ _toggleEvent = 0;
+ }
+
+ if ( event && (event->type == GDK_BUTTON_PRESS) ) {
+ // Make a copy so we can keep it around.
+ _toggleEvent = gdk_event_copy(const_cast<GdkEvent*>(event));
+ }
+}
+
+void LayersPanel::_toggled( Glib::ustring const& str, int targetCol )
+{
+ Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(str);
+ Gtk::TreeModel::Row row = *iter;
+
+ Glib::ustring tmp = row[_model->_colLabel];
+
+ SPObject* obj = row[_model->_colObject];
+ SPItem* item = ( obj && SP_IS_ITEM(obj) ) ? SP_ITEM(obj) : 0;
+ if ( item ) {
+ switch ( targetCol ) {
+ case COL_VISIBLE:
+ {
+ bool newValue = !row[_model->_colVisible];
+ row[_model->_colVisible] = newValue;
+ item->setHidden( !newValue );
+ item->updateRepr();
+ sp_document_done( _desktop->doc() , SP_VERB_DIALOG_LAYERS,
+ newValue? _("Unhide layer") : _("Hide layer"));
+ }
+ break;
+
+ case COL_LOCKED:
+ {
+ bool newValue = !row[_model->_colLocked];
+ row[_model->_colLocked] = newValue;
+ item->setLocked( newValue );
+ item->updateRepr();
+ sp_document_done( _desktop->doc() , SP_VERB_DIALOG_LAYERS,
+ newValue? _("Lock layer") : _("Unlock layer"));
+ }
+ break;
+ }
+ }
+}
+
+void LayersPanel::_handleButtonEvent(GdkEventButton* evt)
+{
+ // TODO - fix to a better is-popup function
+ if ( (evt->type == GDK_BUTTON_PRESS) && (evt->button == 3) ) {
+
+
+ {
+ Gtk::TreeModel::Path path;
+ Gtk::TreeViewColumn* col = 0;
+ int x = static_cast<int>(evt->x);
+ int y = static_cast<int>(evt->y);
+ int x2 = 0;
+ int y2 = 0;
+ if ( _tree.get_path_at_pos( x, y,
+ path, col,
+ x2, y2 ) ) {
+ _checkTreeSelection();
+ _popupMenu.popup(evt->button, evt->time);
+ }
+ }
+
+ }
+}
+
+void LayersPanel::_handleRowChange( Gtk::TreeModel::Path const& /*path*/, Gtk::TreeModel::iterator const& iter )
+{
+ Gtk::TreeModel::Row row = *iter;
+ if ( row ) {
+ SPObject* obj = row[_model->_colObject];
+ if ( obj ) {
+ gchar const* oldLabel = obj->label();
+ Glib::ustring tmp = row[_model->_colLabel];
+ if ( oldLabel && oldLabel[0] && !tmp.empty() && (tmp != oldLabel) ) {
+ _mgr->renameLayer( obj, tmp.c_str() );
+ row[_model->_colLabel] = obj->label();
+ }
+ }
+ }
+}
+
+bool LayersPanel::_rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected )
+{
+ bool val = true;
+ if ( !currentlySelected && _toggleEvent )
+ {
+ GdkEvent* event = gtk_get_current_event();
+ if ( event ) {
+ // (keep these checks separate, so we know when to call gdk_event_free()
+ if ( event->type == GDK_BUTTON_PRESS ) {
+ GdkEventButton const* target = reinterpret_cast<GdkEventButton const*>(_toggleEvent);
+ GdkEventButton const* evtb = reinterpret_cast<GdkEventButton const*>(event);
+
+ if ( (evtb->window == target->window)
+ && (evtb->send_event == target->send_event)
+ && (evtb->time == target->time)
+ && (evtb->state == target->state)
+ )
+ {
+ // Ooooh! It's a magic one
+ val = false;
+ }
+ }
+ gdk_event_free(event);
+ }
+ }
+ return val;
+}
+
+/**
+ * Constructor
+ */
+LayersPanel::LayersPanel() :
+ UI::Widget::Panel("", "/dialogs/layers", SP_VERB_DIALOG_LAYERS),
+ _maxNestDepth(20),
+ _mgr(0),
+ _desktop(0),
+ _model(0),
+ _pending(0),
+ _toggleEvent(0),
+ _compositeSettings(SP_VERB_DIALOG_LAYERS, "layers", UI::Widget::SimpleFilterModifier::BLEND)
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ _maxNestDepth = prefs->getIntLimited("/dialogs/layers/maxDepth", 20, 1, 1000);
+
+ 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;
+ eyeRenderer->signal_pre_toggle().connect( sigc::mem_fun(*this, &LayersPanel::_preToggle) );
+ eyeRenderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_VISIBLE) );
+ eyeRenderer->property_activatable() = true;
+ 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;
+ renderer->signal_pre_toggle().connect( sigc::mem_fun(*this, &LayersPanel::_preToggle) );
+ renderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_LOCKED) );
+ renderer->property_activatable() = true;
+ col = _tree.get_column(lockedColNum);
+ if ( col ) {
+ col->add_attribute( renderer->property_active(), _model->_colLocked );
+ }
+
+ int nameColNum = _tree.append_column_editable("Name", _model->_colLabel) - 1;
+
+ _tree.set_expander_column( *_tree.get_column(nameColNum) );
+
+ _compositeSettings.setSubject(&_subject);
+
+ _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &LayersPanel::_pushTreeSelectionToCurrent) );
+ _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &LayersPanel::_rowSelectFunction) );
+
+ _tree.get_model()->signal_row_changed().connect( sigc::mem_fun(*this, &LayersPanel::_handleRowChange) );
+ _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent) );
+
+ _scroller.add( _tree );
+ _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
+ _scroller.set_shadow_type(Gtk::SHADOW_IN);
+
+ _watching.push_back( &_compositeSettings );
+
+ _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET );
+ _layersPage.pack_end(_compositeSettings, Gtk::PACK_SHRINK);
+ _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK);
+
+ _notebook.append_page(_layersPage, _("Layers"));
+
+ _getContents()->pack_start(_notebook, Gtk::PACK_EXPAND_WIDGET);
+
+ SPDesktop* targetDesktop = getDesktop();
+
+ _buttonsRow.set_child_min_width( 16 );
+
+ Gtk::Button* btn = manage( new Gtk::Button() );
+ _styleButton( *btn, targetDesktop, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("New") );
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_NEW) );
+ _buttonsRow.add( *btn );
+
+ btn = manage( new Gtk::Button() );
+ _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_TOP, GTK_STOCK_GOTO_TOP, _("Top") );
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_TOP) );
+ _watchingNonTop.push_back( btn );
+ _buttonsRow.add( *btn );
+
+ btn = manage( new Gtk::Button() );
+ _styleButton( *btn, targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, _("Up") );
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_UP) );
+ _watchingNonTop.push_back( btn );
+ _buttonsRow.add( *btn );
+
+ btn = manage( new Gtk::Button() );
+ _styleButton( *btn, targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, _("Dn") );
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DOWN) );
+ _watchingNonBottom.push_back( btn );
+ _buttonsRow.add( *btn );
+
+ btn = manage( new Gtk::Button() );
+ _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_BOTTOM, GTK_STOCK_GOTO_BOTTOM, _("Bot") );
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_BOTTOM) );
+ _watchingNonBottom.push_back( btn );
+ _buttonsRow.add( *btn );
+
+// btn = manage( new Gtk::Button("Dup") );
+// btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) );
+// _buttonsRow.add( *btn );
+
+ btn = manage( new Gtk::Button() );
+ _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("X") );
+ btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DELETE) );
+ _watching.push_back( btn );
+ _buttonsRow.add( *btn );
+
+
+
+
+ // -------------------------------------------------------
+ {
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SOLO, 0, "Solo", (int)BUTTON_SOLO ) );
+
+ _popupMenu.items().push_back( Gtk::Menu_Helpers::SeparatorElem() );
+
+ _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) );
+ _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) );
+
+ _popupMenu.show_all_children();
+ }
+ // -------------------------------------------------------
+
+
+
+ for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
+ (*it)->set_sensitive( false );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
+ (*it)->set_sensitive( false );
+ }
+ for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
+ (*it)->set_sensitive( false );
+ }
+
+ g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK( layers_panel_activated ), this );
+ g_signal_connect( G_OBJECT(INKSCAPE), "deactivate_desktop", G_CALLBACK( layers_panel_deactivated ), this );
+ setDesktop( targetDesktop );
+
+ show_all_children();
+
+ // restorePanelPrefs();
+}
+
+LayersPanel::~LayersPanel()
+{
+ setDesktop(NULL);
+
+ _compositeSettings.setSubject(NULL);
+
+ if ( _model )
+ {
+ delete _model;
+ }
+
+ if ( _toggleEvent )
+ {
+ gdk_event_free( _toggleEvent );
+ _toggleEvent = 0;
+ }
+}
+
+
+void LayersPanel::setDesktop( SPDesktop* desktop )
+{
+ Panel::setDesktop(desktop);
+
+ if ( desktop != _desktop ) {
+ _layerChangedConnection.disconnect();
+ _layerUpdatedConnection.disconnect();
+ _changedConnection.disconnect();
+ if ( _mgr ) {
+ _mgr = 0;
+ }
+ if ( _desktop ) {
+ _desktop = 0;
+ }
+
+ _desktop = getDesktop();
+ if ( _desktop ) {
+ //setLabel( _desktop->doc()->name );
+
+ _mgr = _desktop->layer_manager;
+ if ( _mgr ) {
+ _layerChangedConnection = _mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayersPanel::_selectLayer) );
+ _layerUpdatedConnection = _mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayersPanel::_updateLayer) );
+ _changedConnection = _mgr->connectChanged( sigc::mem_fun(*this, &LayersPanel::_layersChanged) );
+ }
+
+ _layersChanged();
+ }
+ }
+/*
+ GSList const *layers=sp_document_get_resource_list( _desktop->doc(), "layer" );
+ g_message( "layers list starts at %p", layers );
+ for ( GSList const *iter=layers ; iter ; iter = iter->next ) {
+ SPObject *layer=static_cast<SPObject *>(iter->data);
+ g_message(" {%s} [%s]", layer->id, layer->label() );
+ }
+*/
+}
+
+
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/layers.h b/src/ui/dialog/layers.h
--- /dev/null
+++ b/src/ui/dialog/layers.h
@@ -0,0 +1,146 @@
+/*
+ * A simple dialog for layer UI.
+ *
+ * Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2006 Jon A. Cruz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_LAYERS_PANEL_H
+#define SEEN_LAYERS_PANEL_H
+
+#include <gtkmm/treeview.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/scale.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/box.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/notebook.h>
+
+//#include "ui/previewholder.h"
+#include "ui/widget/panel.h"
+#include "ui/widget/object-composite-settings.h"
+
+class SPObject;
+
+namespace Inkscape {
+
+class LayerManager;
+
+namespace UI {
+namespace Dialogs {
+
+
+/**
+ * A panel that displays layers.
+ */
+class LayersPanel : public UI::Widget::Panel
+{
+public:
+ LayersPanel();
+ virtual ~LayersPanel();
+
+ //virtual void setOrientation( Gtk::AnchorType how );
+
+ static LayersPanel& getInstance();
+
+ void setDesktop( SPDesktop* desktop );
+
+protected:
+ //virtual void _handleAction( int setId, int itemId );
+
+private:
+ class ModelColumns;
+ class InternalUIBounce;
+
+ LayersPanel(LayersPanel const &); // no copy
+ LayersPanel &operator=(LayersPanel const &); // no assign
+
+ void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback );
+ void _fireAction( unsigned int code );
+ Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id );
+
+ void _preToggle( GdkEvent const *event );
+ void _toggled( Glib::ustring const& str, int targetCol );
+
+ void _handleButtonEvent(GdkEventButton* evt);
+ void _handleRowChange( Gtk::TreeModel::Path const& path, Gtk::TreeModel::iterator const& iter );
+
+ void _pushTreeSelectionToCurrent();
+ void _checkTreeSelection();
+
+ void _takeAction( int val );
+ bool _executeAction();
+
+ bool _rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & model, Gtk::TreeModel::Path const & path, bool b );
+
+ void _updateLayer(SPObject *layer);
+ bool _checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer);
+
+ void _selectLayer(SPObject *layer);
+ bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer);
+
+ void _layersChanged();
+ void _addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level );
+
+ SPObject* _selectedLayer();
+
+ // Hooked to the layer manager:
+ sigc::connection _layerChangedConnection;
+ sigc::connection _layerUpdatedConnection;
+ sigc::connection _changedConnection;
+ sigc::connection _addedConnection;
+ sigc::connection _removedConnection;
+
+ // Internal
+ sigc::connection _selectedConnection;
+
+ int _maxNestDepth;
+ Inkscape::LayerManager* _mgr;
+ SPDesktop* _desktop;
+ ModelColumns* _model;
+ InternalUIBounce* _pending;
+ GdkEvent* _toggleEvent;
+ Glib::RefPtr<Gtk::TreeStore> _store;
+ std::vector<Gtk::Widget*> _watching;
+ std::vector<Gtk::Widget*> _watchingNonTop;
+ std::vector<Gtk::Widget*> _watchingNonBottom;
+
+ Gtk::Tooltips _tips;
+ Gtk::TreeView _tree;
+ Gtk::HButtonBox _buttonsRow;
+ Gtk::ScrolledWindow _scroller;
+ Gtk::Menu _popupMenu;
+ Gtk::SpinButton _spinBtn;
+ Gtk::Notebook _notebook;
+ Gtk::VBox _layersPage;
+
+ UI::Widget::StyleSubject::CurrentLayer _subject;
+ UI::Widget::ObjectCompositeSettings _compositeSettings;
+};
+
+
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+
+#endif // SEEN_LAYERS_PANEL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index f087f40e49ea6ceb4a2e2565732c817a88669347..7dbb6dd4ac25477142a8deafc18809fc1df09360 100644 (file)
#include "verbs.h"
#include "dialog.h"
-#include "dialogs/swatches.h"
+#include "ui/dialog/swatches.h"
#include "ui/dialog/floating-behavior.h"
#include "ui/dialog/dock-behavior.h"
#include "preferences.h"
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
--- /dev/null
@@ -0,0 +1,1212 @@
+/** @file
+ * @brief Color swatches dialog
+ */
+/* Authors:
+ * Jon A. Cruz
+ * John Bintz
+ *
+ * Copyright (C) 2005 Jon A. Cruz
+ * Copyright (C) 2008 John Bintz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <errno.h>
+
+#include <gtk/gtkdialog.h> //for GTK_RESPONSE* types
+#include <gtk/gtkdnd.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkseparatormenuitem.h>
+#include <glibmm/i18n.h>
+#include <gdkmm/pixbuf.h>
+
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "desktop-style.h"
+#include "document.h"
+#include "extension/db.h"
+#include "inkscape.h"
+#include "inkscape.h"
+#include "io/sys.h"
+#include "message-context.h"
+#include "path-prefix.h"
+#include "preferences.h"
+#include "sp-item.h"
+#include "svg/svg-color.h"
+#include "swatches.h"
+#include "widgets/eek-preview.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+ColorItem::ColorItem() : _isRemove(true){};
+ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) :
+ def( r, g, b, name ),
+ _isRemove(false),
+ _isLive(false),
+ _linkIsTone(false),
+ _linkPercent(0),
+ _linkGray(0),
+ _linkSrc(0)
+{
+}
+
+ColorItem::~ColorItem()
+{
+}
+
+ColorItem::ColorItem(ColorItem const &other) :
+ Inkscape::UI::Previewable()
+{
+ if ( this != &other ) {
+ *this = other;
+ }
+}
+
+ColorItem &ColorItem::operator=(ColorItem const &other)
+{
+ if ( this != &other ) {
+ def = other.def;
+
+ // TODO - correct linkage
+ _linkSrc = other._linkSrc;
+ g_message("Erk!");
+ }
+ return *this;
+}
+
+
+class JustForNow
+{
+public:
+ JustForNow() : _prefWidth(0) {}
+
+ Glib::ustring _name;
+ int _prefWidth;
+ std::vector<ColorItem*> _colors;
+};
+
+static std::vector<JustForNow*> possible;
+
+
+
+typedef enum {
+ APP_X_INKY_COLOR_ID = 0,
+ APP_X_INKY_COLOR = 0,
+ APP_X_COLOR,
+ TEXT_DATA
+} colorFlavorType;
+
+//TODO: warning: deprecated conversion from string constant to ‘gchar*’
+//
+//Turn out to be warnings that we should probably leave in place. The
+// pointers/types used need to be read-only. So until we correct the using
+// code, those warnings are actually desired. They say "Hey! Fix this". We
+// definitely don't want to hide/ignore them. --JonCruz
+static const GtkTargetEntry sourceColorEntries[] = {
+#if ENABLE_MAGIC_COLORS
+// {"application/x-inkscape-color-id", GTK_TARGET_SAME_APP, APP_X_INKY_COLOR_ID},
+ {"application/x-inkscape-color", 0, APP_X_INKY_COLOR},
+#endif // ENABLE_MAGIC_COLORS
+ {"application/x-color", 0, APP_X_COLOR},
+ {"text/plain", 0, TEXT_DATA},
+};
+
+void ColorItem::_dragGetColorData( GtkWidget *widget,
+ GdkDragContext *drag_context,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ gpointer user_data)
+{
+ (void)widget;
+ (void)drag_context;
+ (void)time;
+ static GdkAtom typeXColor = gdk_atom_intern("application/x-color", FALSE);
+ static GdkAtom typeText = gdk_atom_intern("text/plain", FALSE);
+
+ ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
+ if ( info == TEXT_DATA ) {
+ gchar* tmp = g_strdup_printf("#%02x%02x%02x", item->def.getR(), item->def.getG(), item->def.getB() );
+
+ gtk_selection_data_set( data,
+ typeText,
+ 8, // format
+ (guchar*)tmp,
+ strlen((const char*)tmp) + 1);
+ g_free(tmp);
+ tmp = 0;
+ } else if ( info == APP_X_INKY_COLOR ) {
+ Glib::ustring paletteName;
+
+ // Find where this thing came from
+ bool found = false;
+ int index = 0;
+ for ( std::vector<JustForNow*>::iterator it = possible.begin(); it != possible.end() && !found; ++it ) {
+ JustForNow* curr = *it;
+ index = 0;
+ for ( std::vector<ColorItem*>::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) {
+ if ( item == *zz ) {
+ found = true;
+ paletteName = curr->_name;
+ break;
+ } else {
+ index++;
+ }
+ }
+ }
+
+// if ( found ) {
+// g_message("Found the color at entry %d in palette '%s'", index, paletteName.c_str() );
+// } else {
+// g_message("Unable to find the color");
+// }
+ int itemCount = 4 + 2 + 1 + paletteName.length();
+
+ guint16* tmp = new guint16[itemCount];
+ tmp[0] = (item->def.getR() << 8) | item->def.getR();
+ tmp[1] = (item->def.getG() << 8) | item->def.getG();
+ tmp[2] = (item->def.getB() << 8) | item->def.getB();
+ tmp[3] = 0xffff;
+ tmp[4] = (item->_isLive || !item->_listeners.empty() || (item->_linkSrc != 0) ) ? 1 : 0;
+
+ tmp[5] = index;
+ tmp[6] = paletteName.length();
+ for ( unsigned int i = 0; i < paletteName.length(); i++ ) {
+ tmp[7 + i] = paletteName[i];
+ }
+ gtk_selection_data_set( data,
+ typeXColor,
+ 16, // format
+ reinterpret_cast<const guchar*>(tmp),
+ itemCount * 2);
+ delete[] tmp;
+ } else {
+ guint16 tmp[4];
+ tmp[0] = (item->def.getR() << 8) | item->def.getR();
+ tmp[1] = (item->def.getG() << 8) | item->def.getG();
+ tmp[2] = (item->def.getB() << 8) | item->def.getB();
+ tmp[3] = 0xffff;
+ gtk_selection_data_set( data,
+ typeXColor,
+ 16, // format
+ reinterpret_cast<const guchar*>(tmp),
+ (3+1) * 2);
+ }
+}
+
+static void dragBegin( GtkWidget *widget, GdkDragContext* dc, gpointer data )
+{
+ (void)widget;
+ ColorItem* item = reinterpret_cast<ColorItem*>(data);
+ if ( item )
+ {
+ if (item->isRemove()){
+ GError *error = NULL;
+ gchar *filepath = (gchar *) g_strdup_printf("%s/remove-color.png", INKSCAPE_PIXMAPDIR);
+ gsize bytesRead = 0;
+ gsize bytesWritten = 0;
+ gchar *localFilename = g_filename_from_utf8( filepath,
+ -1,
+ &bytesRead,
+ &bytesWritten,
+ &error);
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, 32, 24, FALSE, &error);
+ g_free(localFilename);
+ g_free(filepath);
+ gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 );
+ return;
+ }
+
+ Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, 32, 24 );
+ guint32 fillWith = (0xff000000 & (item->def.getR() << 24))
+ | (0x00ff0000 & (item->def.getG() << 16))
+ | (0x0000ff00 & (item->def.getB() << 8));
+ thumb->fill( fillWith );
+ gtk_drag_set_icon_pixbuf( dc, thumb->gobj(), 0, 0 );
+ }
+
+}
+
+//"drag-drop"
+// gboolean dragDropColorData( GtkWidget *widget,
+// GdkDragContext *drag_context,
+// gint x,
+// gint y,
+// guint time,
+// gpointer user_data)
+// {
+// // TODO finish
+
+// return TRUE;
+// }
+
+static void handleClick( GtkWidget* widget, gpointer callback_data ) {
+ (void)widget;
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ item->buttonClicked(false);
+ }
+}
+
+static void handleSecondaryClick( GtkWidget* widget, gint arg1, gpointer callback_data ) {
+ (void)widget;
+ (void)arg1;
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ item->buttonClicked(true);
+ }
+}
+
+static gboolean handleEnterNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if ( desktop ) {
+ gchar* msg = g_strdup_printf(_("Color: <b>%s</b>; <b>Click</b> to set fill, <b>Shift+click</b> to set stroke"),
+ item->def.descr.c_str());
+ desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg);
+ g_free(msg);
+ }
+ }
+ return FALSE;
+}
+
+static gboolean handleLeaveNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
+ if ( item ) {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if ( desktop ) {
+ desktop->tipsMessageContext()->clear();
+ }
+ }
+ return FALSE;
+}
+
+static GtkWidget* popupMenu = 0;
+static ColorItem* bounceTarget = 0;
+
+static void redirClick( GtkMenuItem *menuitem, gpointer user_data )
+{
+ (void)user_data;
+ if ( bounceTarget ) {
+ handleClick( GTK_WIDGET(menuitem), bounceTarget );
+ }
+}
+
+static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer user_data )
+{
+ (void)user_data;
+ if ( bounceTarget ) {
+ handleSecondaryClick( GTK_WIDGET(menuitem), 0, bounceTarget );
+ }
+}
+
+static gboolean handleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data)
+{
+ (void)widget;
+ gboolean handled = FALSE;
+
+ if ( (event->button == 3) && (event->type == GDK_BUTTON_PRESS) ) {
+ if ( !popupMenu ) {
+ popupMenu = gtk_menu_new();
+ GtkWidget* child = 0;
+
+ //TRANSLATORS: An item in context menu on a colour in the swatches
+ child = gtk_menu_item_new_with_label(_("Set fill"));
+ g_signal_connect( G_OBJECT(child),
+ "activate",
+ G_CALLBACK(redirClick),
+ user_data);
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+
+ //TRANSLATORS: An item in context menu on a colour in the swatches
+ child = gtk_menu_item_new_with_label(_("Set stroke"));
+
+ g_signal_connect( G_OBJECT(child),
+ "activate",
+ G_CALLBACK(redirSecondaryClick),
+ user_data);
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+
+ gtk_widget_show_all(popupMenu);
+ }
+
+ ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
+ if ( item ) {
+ bounceTarget = item;
+ if ( popupMenu ) {
+ gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time);
+ handled = TRUE;
+ }
+ }
+ }
+
+ return handled;
+}
+
+static void dieDieDie( GtkObject *obj, gpointer user_data )
+{
+ g_message("die die die %p %p", obj, user_data );
+}
+
+//TODO: warning: deprecated conversion from string constant to ‘gchar*’
+//
+//Turn out to be warnings that we should probably leave in place. The
+// pointers/types used need to be read-only. So until we correct the using
+// code, those warnings are actually desired. They say "Hey! Fix this". We
+// definitely don't want to hide/ignore them. --JonCruz
+static const GtkTargetEntry destColorTargets[] = {
+#if ENABLE_MAGIC_COLORS
+// {"application/x-inkscape-color-id", GTK_TARGET_SAME_APP, APP_X_INKY_COLOR_ID},
+ {"application/x-inkscape-color", 0, APP_X_INKY_COLOR},
+#endif // ENABLE_MAGIC_COLORS
+ {"application/x-color", 0, APP_X_COLOR},
+};
+
+#include "color.h" // for SP_RGBA32_U_COMPOSE
+
+void ColorItem::_dropDataIn( GtkWidget *widget,
+ GdkDragContext *drag_context,
+ gint x, gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint event_time,
+ gpointer user_data)
+{
+ (void)widget;
+ (void)drag_context;
+ (void)x;
+ (void)y;
+ (void)event_time;
+// g_message(" droppy droppy %d", info);
+ switch (info) {
+ case APP_X_INKY_COLOR:
+ {
+ if ( data->length >= 8 ) {
+ // Careful about endian issues.
+ guint16* dataVals = (guint16*)data->data;
+ if ( user_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
+ if ( item->def.isEditable() ) {
+ // Shove on in the new value
+ item->def.setRGB( 0x0ff & (dataVals[0] >> 8), 0x0ff & (dataVals[1] >> 8), 0x0ff & (dataVals[2] >> 8) );
+ }
+ }
+ }
+ break;
+ }
+ case APP_X_COLOR:
+ {
+ if ( data->length == 8 ) {
+ // Careful about endian issues.
+ guint16* dataVals = (guint16*)data->data;
+// {
+// gchar c[64] = {0};
+// sp_svg_write_color( c, 64,
+// SP_RGBA32_U_COMPOSE(
+// 0x0ff & (dataVals[0] >> 8),
+// 0x0ff & (dataVals[1] >> 8),
+// 0x0ff & (dataVals[2] >> 8),
+// 0xff // can't have transparency in the color itself
+// //0x0ff & (data->data[3] >> 8),
+// ));
+// }
+ if ( user_data ) {
+ ColorItem* item = reinterpret_cast<ColorItem*>(user_data);
+ if ( item->def.isEditable() ) {
+ // Shove on in the new value
+ item->def.setRGB( 0x0ff & (dataVals[0] >> 8), 0x0ff & (dataVals[1] >> 8), 0x0ff & (dataVals[2] >> 8) );
+ }
+ }
+ }
+ break;
+ }
+ default:
+ g_message("unknown drop type");
+ }
+
+}
+
+static bool bruteForce( SPDocument* document, Inkscape::XML::Node* node, Glib::ustring const& match, int r, int g, int b )
+{
+ bool changed = false;
+
+ if ( node ) {
+ gchar const * val = node->attribute("inkscape:x-fill-tag");
+ if ( val && (match == val) ) {
+ SPObject *obj = document->getObjectByRepr( node );
+
+ gchar c[64] = {0};
+ sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) );
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property( css, "fill", c );
+
+ sp_desktop_apply_css_recursive( (SPItem*)obj, css, true );
+ ((SPItem*)obj)->updateRepr();
+
+ changed = true;
+ }
+
+ val = node->attribute("inkscape:x-stroke-tag");
+ if ( val && (match == val) ) {
+ SPObject *obj = document->getObjectByRepr( node );
+
+ gchar c[64] = {0};
+ sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) );
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property( css, "stroke", c );
+
+ sp_desktop_apply_css_recursive( (SPItem*)obj, css, true );
+ ((SPItem*)obj)->updateRepr();
+
+ changed = true;
+ }
+
+ Inkscape::XML::Node* first = node->firstChild();
+ changed |= bruteForce( document, first, match, r, g, b );
+
+ changed |= bruteForce( document, node->next(), match, r, g, b );
+ }
+
+ return changed;
+}
+
+void ColorItem::_colorDefChanged(void* data)
+{
+ ColorItem* item = reinterpret_cast<ColorItem*>(data);
+ if ( item ) {
+ for ( std::vector<Gtk::Widget*>::iterator it = item->_previews.begin(); it != item->_previews.end(); ++it ) {
+ Gtk::Widget* widget = *it;
+ if ( IS_EEK_PREVIEW(widget->gobj()) ) {
+ EekPreview * preview = EEK_PREVIEW(widget->gobj());
+ eek_preview_set_color( preview,
+ (item->def.getR() << 8) | item->def.getR(),
+ (item->def.getG() << 8) | item->def.getG(),
+ (item->def.getB() << 8) | item->def.getB() );
+
+ eek_preview_set_linked( preview, (LinkType)((item->_linkSrc ? PREVIEW_LINK_IN:0)
+ | (item->_listeners.empty() ? 0:PREVIEW_LINK_OUT)
+ | (item->_isLive ? PREVIEW_LINK_OTHER:0)) );
+
+ widget->queue_draw();
+ }
+ }
+
+ for ( std::vector<ColorItem*>::iterator it = item->_listeners.begin(); it != item->_listeners.end(); ++it ) {
+ guint r = item->def.getR();
+ guint g = item->def.getG();
+ guint b = item->def.getB();
+
+ if ( (*it)->_linkIsTone ) {
+ r = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * r) ) / 100;
+ g = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * g) ) / 100;
+ b = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * b) ) / 100;
+ } else {
+ r = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * r) ) / 100;
+ g = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * g) ) / 100;
+ b = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * b) ) / 100;
+ }
+
+ (*it)->def.setRGB( r, g, b );
+ }
+
+
+ // Look for objects using this color
+ {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if ( desktop ) {
+ SPDocument* document = sp_desktop_document( desktop );
+ Inkscape::XML::Node *rroot = sp_document_repr_root( document );
+ if ( rroot ) {
+
+ // Find where this thing came from
+ Glib::ustring paletteName;
+ bool found = false;
+ int index = 0;
+ for ( std::vector<JustForNow*>::iterator it2 = possible.begin(); it2 != possible.end() && !found; ++it2 ) {
+ JustForNow* curr = *it2;
+ index = 0;
+ for ( std::vector<ColorItem*>::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) {
+ if ( item == *zz ) {
+ found = true;
+ paletteName = curr->_name;
+ break;
+ } else {
+ index++;
+ }
+ }
+ }
+
+ if ( !paletteName.empty() ) {
+ gchar* str = g_strdup_printf("%d|", index);
+ paletteName.insert( 0, str );
+ g_free(str);
+ str = 0;
+
+ if ( bruteForce( document, rroot, paletteName, item->def.getR(), item->def.getG(), item->def.getB() ) ) {
+ sp_document_done( document , SP_VERB_DIALOG_SWATCHES,
+ _("Change color definition"));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio)
+{
+ Gtk::Widget* widget = 0;
+ if ( style == PREVIEW_STYLE_BLURB) {
+ Gtk::Label *lbl = new Gtk::Label(def.descr);
+ lbl->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER);
+ widget = lbl;
+ } else {
+// Glib::ustring blank(" ");
+// if ( size == Inkscape::ICON_SIZE_MENU || size == Inkscape::ICON_SIZE_DECORATION ) {
+// blank = " ";
+// }
+
+ GtkWidget* eekWidget = eek_preview_new();
+ EekPreview * preview = EEK_PREVIEW(eekWidget);
+ Gtk::Widget* newBlot = Glib::wrap(eekWidget);
+
+ eek_preview_set_color( preview, (def.getR() << 8) | def.getR(), (def.getG() << 8) | def.getG(), (def.getB() << 8) | def.getB());
+ if ( _isRemove ) {
+ GError *error = NULL;
+ gchar *filepath = (gchar *) g_strdup_printf("%s/remove-color.png", INKSCAPE_PIXMAPDIR);
+ gsize bytesRead = 0;
+ gsize bytesWritten = 0;
+ gchar *localFilename = g_filename_from_utf8( filepath,
+ -1,
+ &bytesRead,
+ &bytesWritten,
+ &error);
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(localFilename, &error);
+ if (!pixbuf) {
+ g_warning("Null pixbuf for %p [%s]", localFilename, localFilename );
+ }
+ g_free(localFilename);
+ g_free(filepath);
+
+ eek_preview_set_pixbuf( preview, pixbuf );
+ }
+
+ eek_preview_set_details( preview, (::PreviewStyle)style, (::ViewType)view, (::PreviewSize)size, ratio );
+ eek_preview_set_linked( preview, (LinkType)((_linkSrc ? PREVIEW_LINK_IN:0)
+ | (_listeners.empty() ? 0:PREVIEW_LINK_OUT)
+ | (_isLive ? PREVIEW_LINK_OTHER:0)) );
+
+ def.addCallback( _colorDefChanged, this );
+
+ GValue val = {0, {{0}, {0}}};
+ g_value_init( &val, G_TYPE_BOOLEAN );
+ g_value_set_boolean( &val, FALSE );
+ g_object_set_property( G_OBJECT(preview), "focus-on-click", &val );
+
+/*
+ Gtk::Button *btn = new Gtk::Button(blank);
+ Gdk::Color color;
+ color.set_rgb((_r << 8)|_r, (_g << 8)|_g, (_b << 8)|_b);
+ btn->modify_bg(Gtk::STATE_NORMAL, color);
+ btn->modify_bg(Gtk::STATE_ACTIVE, color);
+ btn->modify_bg(Gtk::STATE_PRELIGHT, color);
+ btn->modify_bg(Gtk::STATE_SELECTED, color);
+
+ Gtk::Widget* newBlot = btn;
+*/
+
+ tips.set_tip((*newBlot), def.descr);
+
+/*
+ newBlot->signal_clicked().connect( sigc::mem_fun(*this, &ColorItem::buttonClicked) );
+
+ sigc::signal<void> type_signal_something;
+*/
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "clicked",
+ G_CALLBACK(handleClick),
+ this);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "alt-clicked",
+ G_CALLBACK(handleSecondaryClick),
+ this);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "button-press-event",
+ G_CALLBACK(handleButtonPress),
+ this);
+
+ gtk_drag_source_set( GTK_WIDGET(newBlot->gobj()),
+ GDK_BUTTON1_MASK,
+ sourceColorEntries,
+ G_N_ELEMENTS(sourceColorEntries),
+ GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY) );
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "drag-data-get",
+ G_CALLBACK(ColorItem::_dragGetColorData),
+ this);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "drag-begin",
+ G_CALLBACK(dragBegin),
+ this );
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "enter-notify-event",
+ G_CALLBACK(handleEnterNotify),
+ this);
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "leave-notify-event",
+ G_CALLBACK(handleLeaveNotify),
+ this);
+
+// g_signal_connect( G_OBJECT(newBlot->gobj()),
+// "drag-drop",
+// G_CALLBACK(dragDropColorData),
+// this);
+
+ if ( def.isEditable() )
+ {
+ gtk_drag_dest_set( GTK_WIDGET(newBlot->gobj()),
+ GTK_DEST_DEFAULT_ALL,
+ destColorTargets,
+ G_N_ELEMENTS(destColorTargets),
+ GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE) );
+
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "drag-data-received",
+ G_CALLBACK(_dropDataIn),
+ this );
+ }
+
+ g_signal_connect( G_OBJECT(newBlot->gobj()),
+ "destroy",
+ G_CALLBACK(dieDieDie),
+ this);
+
+
+ widget = newBlot;
+ }
+
+ _previews.push_back( widget );
+
+ return widget;
+}
+
+void ColorItem::buttonClicked(bool secondary)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop) return;
+ char const * attrName = secondary ? "stroke" : "fill";
+
+ gchar c[64];
+ if (!_isRemove){
+ guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff;
+ sp_svg_write_color(c, sizeof(c), rgba);
+ }
+
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property( css, attrName, _isRemove ? "none" : c );
+ sp_desktop_set_style(desktop, css);
+ sp_repr_css_attr_unref(css);
+
+ if (_isRemove){
+ sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_SWATCHES,
+ secondary? _("Remove stroke color") : _("Remove fill color"));
+ } else {
+ sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_SWATCHES,
+ secondary? _("Set stroke color from swatch") : _("Set fill color from swatch"));
+ }
+}
+
+static char* trim( char* str ) {
+ char* ret = str;
+ while ( *str && (*str == ' ' || *str == '\t') ) {
+ str++;
+ }
+ ret = str;
+ while ( *str ) {
+ str++;
+ }
+ str--;
+ while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) {
+ *str-- = 0;
+ }
+ return ret;
+}
+
+void skipWhitespace( char*& str ) {
+ while ( *str == ' ' || *str == '\t' ) {
+ str++;
+ }
+}
+
+bool parseNum( char*& str, int& val ) {
+ val = 0;
+ while ( '0' <= *str && *str <= '9' ) {
+ val = val * 10 + (*str - '0');
+ str++;
+ }
+ bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n');
+ return retval;
+}
+
+
+static bool getBlock( std::string& dst, guchar ch, std::string const str )
+{
+ bool good = false;
+ std::string::size_type pos = str.find(ch);
+ if ( pos != std::string::npos )
+ {
+ std::string::size_type pos2 = str.find( '(', pos );
+ if ( pos2 != std::string::npos ) {
+ std::string::size_type endPos = str.find( ')', pos2 );
+ if ( endPos != std::string::npos ) {
+ dst = str.substr( pos2 + 1, (endPos - pos2 - 1) );
+ good = true;
+ }
+ }
+ }
+ return good;
+}
+
+static bool popVal( guint64& numVal, std::string& str )
+{
+ bool good = false;
+ std::string::size_type endPos = str.find(',');
+ if ( endPos == std::string::npos ) {
+ endPos = str.length();
+ }
+
+ if ( endPos != std::string::npos && endPos > 0 ) {
+ std::string xxx = str.substr( 0, endPos );
+ const gchar* ptr = xxx.c_str();
+ gchar* endPtr = 0;
+ numVal = g_ascii_strtoull( ptr, &endPtr, 10 );
+ if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) {
+ // overflow
+ } else if ( (numVal == 0) && (endPtr == ptr) ) {
+ // failed conversion
+ } else {
+ good = true;
+ str.erase( 0, endPos + 1 );
+ }
+ }
+
+ return good;
+}
+
+void ColorItem::_wireMagicColors( void* p )
+{
+ JustForNow* onceMore = reinterpret_cast<JustForNow*>(p);
+ if ( onceMore )
+ {
+ for ( std::vector<ColorItem*>::iterator it = onceMore->_colors.begin(); it != onceMore->_colors.end(); ++it )
+ {
+ std::string::size_type pos = (*it)->def.descr.find("*{");
+ if ( pos != std::string::npos )
+ {
+ std::string subby = (*it)->def.descr.substr( pos + 2 );
+ std::string::size_type endPos = subby.find("}*");
+ if ( endPos != std::string::npos )
+ {
+ subby.erase( endPos );
+ //g_message("FOUND MAGIC at '%s'", (*it)->def.descr.c_str());
+ //g_message(" '%s'", subby.c_str());
+
+ if ( subby.find('E') != std::string::npos )
+ {
+ (*it)->def.setEditable( true );
+ }
+
+ if ( subby.find('L') != std::string::npos )
+ {
+ (*it)->_isLive = true;
+ }
+
+ std::string part;
+ // Tint. index + 1 more val.
+ if ( getBlock( part, 'T', subby ) ) {
+ guint64 colorIndex = 0;
+ if ( popVal( colorIndex, part ) ) {
+ guint64 percent = 0;
+ if ( popVal( percent, part ) ) {
+ (*it)->_linkTint( *(onceMore->_colors[colorIndex]), percent );
+ }
+ }
+ }
+
+ // Shade/tone. index + 1 or 2 more val.
+ if ( getBlock( part, 'S', subby ) ) {
+ guint64 colorIndex = 0;
+ if ( popVal( colorIndex, part ) ) {
+ guint64 percent = 0;
+ if ( popVal( percent, part ) ) {
+ guint64 grayLevel = 0;
+ if ( !popVal( grayLevel, part ) ) {
+ grayLevel = 0;
+ }
+ (*it)->_linkTone( *(onceMore->_colors[colorIndex]), percent, grayLevel );
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+}
+
+
+void ColorItem::_linkTint( ColorItem& other, int percent )
+{
+ if ( !_linkSrc )
+ {
+ other._listeners.push_back(this);
+ _linkIsTone = false;
+ _linkPercent = percent;
+ if ( _linkPercent > 100 )
+ _linkPercent = 100;
+ if ( _linkPercent < 0 )
+ _linkPercent = 0;
+ _linkGray = 0;
+ _linkSrc = &other;
+
+ ColorItem::_colorDefChanged(&other);
+ }
+}
+
+void ColorItem::_linkTone( ColorItem& other, int percent, int grayLevel )
+{
+ if ( !_linkSrc )
+ {
+ other._listeners.push_back(this);
+ _linkIsTone = true;
+ _linkPercent = percent;
+ if ( _linkPercent > 100 )
+ _linkPercent = 100;
+ if ( _linkPercent < 0 )
+ _linkPercent = 0;
+ _linkGray = grayLevel;
+ _linkSrc = &other;
+
+ ColorItem::_colorDefChanged(&other);
+ }
+}
+
+
+void _loadPaletteFile( gchar const *filename )
+{
+ char block[1024];
+ FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" );
+ if ( f ) {
+ char* result = fgets( block, sizeof(block), f );
+ if ( result ) {
+ if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) {
+ bool inHeader = true;
+ bool hasErr = false;
+
+ JustForNow *onceMore = new JustForNow();
+
+ do {
+ result = fgets( block, sizeof(block), f );
+ block[sizeof(block) - 1] = 0;
+ if ( result ) {
+ if ( block[0] == '#' ) {
+ // ignore comment
+ } else {
+ char *ptr = block;
+ // very simple check for header versus entry
+ while ( *ptr == ' ' || *ptr == '\t' ) {
+ ptr++;
+ }
+ if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) {
+ // blank line. skip it.
+ } else if ( '0' <= *ptr && *ptr <= '9' ) {
+ // should be an entry link
+ inHeader = false;
+ ptr = block;
+ Glib::ustring name("");
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ skipWhitespace(ptr);
+ if ( *ptr ) {
+ hasErr = parseNum(ptr, r);
+ if ( !hasErr ) {
+ skipWhitespace(ptr);
+ hasErr = parseNum(ptr, g);
+ }
+ if ( !hasErr ) {
+ skipWhitespace(ptr);
+ hasErr = parseNum(ptr, b);
+ }
+ if ( !hasErr && *ptr ) {
+ char* n = trim(ptr);
+ if (n != NULL) {
+ name = n;
+ }
+ }
+ if ( !hasErr ) {
+ // Add the entry now
+ Glib::ustring nameStr(name);
+ ColorItem* item = new ColorItem( r, g, b, nameStr );
+ onceMore->_colors.push_back(item);
+ }
+ } else {
+ hasErr = true;
+ }
+ } else {
+ if ( !inHeader ) {
+ // Hmmm... probably bad. Not quite the format we want?
+ hasErr = true;
+ } else {
+ char* sep = strchr(result, ':');
+ if ( sep ) {
+ *sep = 0;
+ char* val = trim(sep + 1);
+ char* name = trim(result);
+ if ( *name ) {
+ if ( strcmp( "Name", name ) == 0 )
+ {
+ onceMore->_name = val;
+ }
+ else if ( strcmp( "Columns", name ) == 0 )
+ {
+ gchar* endPtr = 0;
+ guint64 numVal = g_ascii_strtoull( val, &endPtr, 10 );
+ if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) {
+ // overflow
+ } else if ( (numVal == 0) && (endPtr == val) ) {
+ // failed conversion
+ } else {
+ onceMore->_prefWidth = numVal;
+ }
+ }
+ } else {
+ // error
+ hasErr = true;
+ }
+ } else {
+ // error
+ hasErr = true;
+ }
+ }
+ }
+ }
+ }
+ } while ( result && !hasErr );
+ if ( !hasErr ) {
+ possible.push_back(onceMore);
+#if ENABLE_MAGIC_COLORS
+ ColorItem::_wireMagicColors( onceMore );
+#endif // ENABLE_MAGIC_COLORS
+ } else {
+ delete onceMore;
+ }
+ }
+ }
+
+ fclose(f);
+ }
+}
+
+static void loadEmUp()
+{
+ static bool beenHere = false;
+ if ( !beenHere ) {
+ beenHere = true;
+
+ std::list<gchar *> sources;
+ sources.push_back( profile_path("palettes") );
+ sources.push_back( g_strdup(INKSCAPE_PALETTESDIR) );
+ sources.push_back( g_strdup(CREATE_PALETTESDIR) );
+
+ // Use this loop to iterate through a list of possible document locations.
+ while (!sources.empty()) {
+ gchar *dirname = sources.front();
+
+ if ( Inkscape::IO::file_test( dirname, G_FILE_TEST_EXISTS )
+ && Inkscape::IO::file_test( dirname, G_FILE_TEST_IS_DIR )) {
+ GError *err = 0;
+ GDir *directory = g_dir_open(dirname, 0, &err);
+ if (!directory) {
+ gchar *safeDir = Inkscape::IO::sanitizeString(dirname);
+ g_warning(_("Palettes directory (%s) is unavailable."), safeDir);
+ g_free(safeDir);
+ } else {
+ gchar *filename = 0;
+ while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) {
+ gchar* lower = g_ascii_strdown( filename, -1 );
+// if ( g_str_has_suffix(lower, ".gpl") ) {
+ gchar* full = g_build_filename(dirname, filename, NULL);
+ if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) {
+ _loadPaletteFile(full);
+ }
+ g_free(full);
+// }
+ g_free(lower);
+ }
+ g_dir_close(directory);
+ }
+ }
+
+ // toss the dirname
+ g_free(dirname);
+ sources.pop_front();
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+SwatchesPanel& SwatchesPanel::getInstance()
+{
+ return *new SwatchesPanel();
+}
+
+
+/**
+ * Constructor
+ */
+SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
+ Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, "", true),
+ _holder(0)
+{
+ Gtk::RadioMenuItem* hotItem = 0;
+ _holder = new PreviewHolder();
+ _remove = new ColorItem();
+ loadEmUp();
+ if ( !possible.empty() ) {
+ JustForNow* first = 0;
+ Glib::ustring targetName;
+ if ( !_prefs_path.empty() ) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ targetName = prefs->getString(_prefs_path + "/palette");
+ if (!targetName.empty()) {
+ for ( std::vector<JustForNow*>::iterator iter = possible.begin(); iter != possible.end(); ++iter ) {
+ if ( (*iter)->_name == targetName ) {
+ first = *iter;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !first ) {
+ first = possible.front();
+ }
+
+ if ( first->_prefWidth > 0 ) {
+ _holder->setColumnPref( first->_prefWidth );
+ }
+ _holder->freezeUpdates();
+ _holder->addPreview(_remove);
+ for ( std::vector<ColorItem*>::iterator it = first->_colors.begin(); it != first->_colors.end(); it++ ) {
+ _holder->addPreview(*it);
+ }
+ _holder->thawUpdates();
+
+ Gtk::RadioMenuItem::Group groupOne;
+
+ int i = 0;
+ for ( std::vector<JustForNow*>::iterator it = possible.begin(); it != possible.end(); it++ ) {
+ JustForNow* curr = *it;
+ Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, curr->_name));
+ if ( curr == first ) {
+ hotItem = single;
+ }
+ _regItem( single, 3, i );
+ i++;
+ }
+ }
+
+
+ _getContents()->pack_start(*_holder, Gtk::PACK_EXPAND_WIDGET);
+ _setTargetFillable(_holder);
+
+ show_all_children();
+
+ restorePanelPrefs();
+ if ( hotItem ) {
+ hotItem->set_active();
+ }
+}
+
+SwatchesPanel::~SwatchesPanel()
+{
+ if (_remove) delete _remove;
+ if (_holder) delete _holder;
+}
+
+void SwatchesPanel::setOrientation( Gtk::AnchorType how )
+{
+ // Must call the parent class or bad things might happen
+ Inkscape::UI::Widget::Panel::setOrientation( how );
+
+ if ( _holder )
+ {
+ _holder->setOrientation( Gtk::ANCHOR_SOUTH );
+ }
+}
+
+void SwatchesPanel::_handleAction( int setId, int itemId )
+{
+ switch( setId ) {
+ case 3:
+ {
+ if ( itemId >= 0 && itemId < static_cast<int>(possible.size()) ) {
+ _holder->clear();
+ JustForNow* curr = possible[itemId];
+
+ if ( !_prefs_path.empty() ) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setString(_prefs_path + "/palette", curr->_name);
+ }
+
+ if ( curr->_prefWidth > 0 ) {
+ _holder->setColumnPref( curr->_prefWidth );
+ }
+ _holder->freezeUpdates();
+ _holder->addPreview(_remove);
+ for ( std::vector<ColorItem*>::iterator it = curr->_colors.begin(); it != curr->_colors.end(); it++ ) {
+ _holder->addPreview(*it);
+ }
+ _holder->thawUpdates();
+ }
+ }
+ break;
+ }
+}
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h
--- /dev/null
+++ b/src/ui/dialog/swatches.h
@@ -0,0 +1,128 @@
+/** @file
+ * @brief Color swatches dialog
+ */
+/* Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2005 Jon A. Cruz
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifndef SEEN_DIALOGS_SWATCHES_H
+#define SEEN_DIALOGS_SWATCHES_H
+
+#include <gtkmm/textview.h>
+#include <gtkmm/tooltips.h>
+
+#include "ui/widget/panel.h"
+#include "ui/previewholder.h"
+#include "widgets/eek-color-def.h"
+
+using eek::ColorDef;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+
+void _loadPaletteFile( gchar const *filename );
+
+/**
+ * The color swatch you see on screen as a clickable box.
+ */
+class ColorItem : public Inkscape::UI::Previewable
+{
+ friend void _loadPaletteFile( gchar const *filename );
+public:
+ ColorItem();
+ ColorItem( unsigned int r, unsigned int g, unsigned int b,
+ Glib::ustring& name );
+ virtual ~ColorItem();
+ ColorItem(ColorItem const &other);
+ virtual ColorItem &operator=(ColorItem const &other);
+ virtual Gtk::Widget* getPreview(PreviewStyle style,
+ ViewType view,
+ ::PreviewSize size,
+ guint ratio);
+ void buttonClicked(bool secondary = false);
+ bool isRemove(){ return _isRemove; }
+ ColorDef def;
+
+private:
+ static void _dropDataIn( GtkWidget *widget,
+ GdkDragContext *drag_context,
+ gint x, gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint event_time,
+ gpointer user_data);
+
+ static void _dragGetColorData( GtkWidget *widget,
+ GdkDragContext *drag_context,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ gpointer user_data);
+
+ static void _wireMagicColors( void* p );
+ static void _colorDefChanged(void* data);
+
+ void _linkTint( ColorItem& other, int percent );
+ void _linkTone( ColorItem& other, int percent, int grayLevel );
+
+ Gtk::Tooltips tips;
+ std::vector<Gtk::Widget*> _previews;
+
+ bool _isRemove;
+ bool _isLive;
+ bool _linkIsTone;
+ int _linkPercent;
+ int _linkGray;
+ ColorItem* _linkSrc;
+ std::vector<ColorItem*> _listeners;
+};
+
+class RemoveColorItem;
+
+/**
+ * A panel that displays color swatches.
+ */
+class SwatchesPanel : public Inkscape::UI::Widget::Panel
+{
+public:
+ SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches");
+ virtual ~SwatchesPanel();
+
+ static SwatchesPanel& getInstance();
+ virtual void setOrientation( Gtk::AnchorType how );
+
+protected:
+ virtual void _handleAction( int setId, int itemId );
+
+private:
+ SwatchesPanel(SwatchesPanel const &); // no copy
+ SwatchesPanel &operator=(SwatchesPanel const &); // no assign
+
+ static SwatchesPanel* instance;
+
+ PreviewHolder* _holder;
+ ColorItem* _remove;
+};
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+
+
+#endif // SEEN_SWATCHES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/previewable.h b/src/ui/previewable.h
index c517e4f28d1540443d34b0a9b47e4c87afaf9812..ef1ca3ce256898728e78cca7819e9e6e6f826cc5 100644 (file)
--- a/src/ui/previewable.h
+++ b/src/ui/previewable.h
#include <gtkmm/widget.h>
-#include "../dialogs/eek-preview.h"
+#include "../widgets/eek-preview.h"
namespace Inkscape {
namespace UI {
index 6f02b60a8235b5a42aaf52acc1bfee7f776eaede..f863af121969bf5a3d7752d69a3d0b78866c7363 100644 (file)
--- a/src/ui/previewfillable.h
+++ b/src/ui/previewfillable.h
#include "previewable.h"
-#include "../dialogs/eek-preview.h"
+#include "../widgets/eek-preview.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/previewholder.h b/src/ui/previewholder.h
index 812d4b27d0259d77008f3e50c47e11f20cfeef80..3c1a161955e9c5ef2a9916fbb12965a8a48d75dd 100644 (file)
--- a/src/ui/previewholder.h
+++ b/src/ui/previewholder.h
#include <gtkmm/bin.h>
#include <gtkmm/table.h>
#include "previewfillable.h"
-#include "../dialogs/eek-preview.h"
+#include "../widgets/eek-preview.h"
namespace Inkscape {
namespace UI {
index ea32056966bbb99f0743ebb36b049ac3128a68cb..2bb7083054f817c459662620a6338d42f0b32dc8 100644 (file)
#include "ui/dialog/dialog-manager.h"
#include "ui/view/edit-widget-interface.h"
#include "ui/widget/dock.h"
-#include "ui/widget/selected-style.h"
+#include "ui/widget/layer-selector.h"
#include "ui/widget/ruler.h"
-#include "ui/widget/toolbox.h"
+#include "ui/widget/selected-style.h"
#include "ui/widget/svg-canvas.h"
+#include "ui/widget/toolbox.h"
#include "ui/widget/zoom-status.h"
-#include "widgets/layer-selector.h"
struct SPDesktop;
struct SPDocument;
index 9b4048ea927b56ab347bef6d434679e07b64684b..b6069631bc4164371f004784d00dbe5e07af56bf 100644 (file)
ui/widget/imagetoggler.h \
ui/widget/labelled.cpp \
ui/widget/labelled.h \
+ ui/widget/layer-selector.cpp \
+ ui/widget/layer-selector.h \
ui/widget/licensor.cpp \
ui/widget/licensor.h \
ui/widget/notebook-page.cpp \
index 980d225b289151f7a614968dc350b2a392c85abd..e9f09f574c9deb5109f7967d3dd5cdcd05d06f81 100644 (file)
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/entry.h>
-#include "ui/widget/registry.h"
-
-#include "dialogs/rdf.h"
-
#include "inkscape.h"
+#include "rdf.h"
+#include "ui/widget/registry.h"
#include "entity-entry.h"
diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * Inkscape::Widgets::LayerSelector - layer selector widget
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ *
+ * Copyright (C) 2004 MenTaLguY
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <cstring>
+#include <string>
+#include <glibmm/i18n.h>
+
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "document.h"
+#include "layer-manager.h"
+#include "sp-item.h"
+#include "ui/dialog/layer-properties.h"
+#include "ui/widget/layer-selector.h"
+#include "util/filter-list.h"
+#include "util/reverse-list.h"
+#include "verbs.h"
+#include "widgets/icon.h"
+#include "widgets/shrink-wrap-button.h"
+#include "xml/node-event-vector.h"
+
+namespace Inkscape {
+namespace Widgets {
+
+namespace {
+
+class AlternateIcons : public Gtk::HBox {
+public:
+ AlternateIcons(Inkscape::IconSize size, gchar const *a, gchar const *b)
+ : _a(NULL), _b(NULL)
+ {
+ if (a) {
+ _a = Gtk::manage(sp_icon_get_icon(a, size));
+ _a->set_no_show_all(true);
+ add(*_a);
+ }
+ if (b) {
+ _b = Gtk::manage(sp_icon_get_icon(b, size));
+ _b->set_no_show_all(true);
+ add(*_b);
+ }
+ setState(false);
+ }
+
+ bool state() const { return _state; }
+ void setState(bool state) {
+ _state = state;
+ if (_state) {
+ if (_a) {
+ _a->hide();
+ }
+ if (_b) {
+ _b->show();
+ }
+ } else {
+ if (_a) {
+ _a->show();
+ }
+ if (_b) {
+ _b->hide();
+ }
+ }
+ }
+
+private:
+ Gtk::Widget *_a;
+ Gtk::Widget *_b;
+ bool _state;
+};
+
+}
+
+/** LayerSelector constructor. Creates lock and hide buttons,
+ * initalizes the layer dropdown selector with a label renderer,
+ * and hooks up signal for setting the desktop layer when the
+ * selector is changed.
+ */
+LayerSelector::LayerSelector(SPDesktop *desktop)
+: _desktop(NULL), _layer(NULL)
+{
+ AlternateIcons *label;
+
+ label = Gtk::manage(new AlternateIcons(Inkscape::ICON_SIZE_DECORATION, "visible", "hidden"));
+ _visibility_toggle.add(*label);
+ _visibility_toggle.signal_toggled().connect(
+ sigc::compose(
+ sigc::mem_fun(*label, &AlternateIcons::setState),
+ sigc::mem_fun(_visibility_toggle, &Gtk::ToggleButton::get_active)
+ )
+ );
+ _visibility_toggled_connection = _visibility_toggle.signal_toggled().connect(
+ sigc::compose(
+ sigc::mem_fun(*this, &LayerSelector::_hideLayer),
+ sigc::mem_fun(_visibility_toggle, &Gtk::ToggleButton::get_active)
+ )
+ );
+
+ _visibility_toggle.set_relief(Gtk::RELIEF_NONE);
+ shrink_wrap_button(_visibility_toggle);
+ _tooltips.set_tip(_visibility_toggle, _("Toggle current layer visibility"));
+ pack_start(_visibility_toggle, Gtk::PACK_EXPAND_PADDING);
+
+ label = Gtk::manage(new AlternateIcons(Inkscape::ICON_SIZE_DECORATION, "lock_unlocked", "width_height_lock"));
+ _lock_toggle.add(*label);
+ _lock_toggle.signal_toggled().connect(
+ sigc::compose(
+ sigc::mem_fun(*label, &AlternateIcons::setState),
+ sigc::mem_fun(_lock_toggle, &Gtk::ToggleButton::get_active)
+ )
+ );
+ _lock_toggled_connection = _lock_toggle.signal_toggled().connect(
+ sigc::compose(
+ sigc::mem_fun(*this, &LayerSelector::_lockLayer),
+ sigc::mem_fun(_lock_toggle, &Gtk::ToggleButton::get_active)
+ )
+ );
+
+ _lock_toggle.set_relief(Gtk::RELIEF_NONE);
+ shrink_wrap_button(_lock_toggle);
+ _tooltips.set_tip(_lock_toggle, _("Lock or unlock current layer"));
+ pack_start(_lock_toggle, Gtk::PACK_EXPAND_PADDING);
+
+ _tooltips.set_tip(_selector, _("Current layer"));
+ pack_start(_selector, Gtk::PACK_EXPAND_WIDGET);
+
+ _layer_model = Gtk::ListStore::create(_model_columns);
+ _selector.set_model(_layer_model);
+ _selector.pack_start(_label_renderer);
+ _selector.set_cell_data_func(
+ _label_renderer,
+ sigc::mem_fun(*this, &LayerSelector::_prepareLabelRenderer)
+ );
+
+ _selection_changed_connection = _selector.signal_changed().connect(
+ sigc::mem_fun(*this, &LayerSelector::_setDesktopLayer)
+ );
+ setDesktop(desktop);
+}
+
+/** Destructor - disconnects signal handler
+ */
+LayerSelector::~LayerSelector() {
+ setDesktop(NULL);
+ _selection_changed_connection.disconnect();
+}
+
+namespace {
+
+/** Helper function - detaches desktop from selector
+ */
+bool detach(LayerSelector *selector) {
+ selector->setDesktop(NULL);
+ return FALSE;
+}
+
+}
+
+/** Sets the desktop for the widget. First disconnects signals
+ * for the current desktop, then stores the pointer to the
+ * given \a desktop, and attaches its signals to this one.
+ * Then it selects the current layer for the desktop.
+ */
+void LayerSelector::setDesktop(SPDesktop *desktop) {
+ if ( desktop == _desktop ) {
+ return;
+ }
+
+ if (_desktop) {
+// _desktop_shutdown_connection.disconnect();
+ _layer_changed_connection.disconnect();
+// g_signal_handlers_disconnect_by_func(_desktop, (gpointer)&detach, this);
+ }
+ _desktop = desktop;
+ if (_desktop) {
+ // TODO we need a different signal for this, really..s
+// _desktop_shutdown_connection = _desktop->connectShutdown(
+// 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)
+ );
+ _selectLayer(_desktop->currentLayer());
+ }
+}
+
+namespace {
+
+class is_layer {
+public:
+ is_layer(SPDesktop *desktop) : _desktop(desktop) {}
+ bool operator()(SPObject &object) const {
+ return _desktop->isLayer(&object);
+ }
+private:
+ SPDesktop *_desktop;
+};
+
+class column_matches_object {
+public:
+ column_matches_object(Gtk::TreeModelColumn<SPObject *> const &column,
+ SPObject &object)
+ : _column(column), _object(object) {}
+ bool operator()(Gtk::TreeModel::const_iterator const &iter) const {
+ SPObject *current=(*iter)[_column];
+ return current == &_object;
+ }
+private:
+ Gtk::TreeModelColumn<SPObject *> const &_column;
+ SPObject &_object;
+};
+
+}
+
+/** Selects the given layer in the dropdown selector.
+ */
+void LayerSelector::_selectLayer(SPObject *layer) {
+ using Inkscape::Util::List;
+ using Inkscape::Util::cons;
+ using Inkscape::Util::reverse_list;
+
+ _selection_changed_connection.block();
+
+ while (!_layer_model->children().empty()) {
+ Gtk::ListStore::iterator first_row(_layer_model->children().begin());
+ _destroyEntry(first_row);
+ _layer_model->erase(first_row);
+ }
+
+ SPObject *root=_desktop->currentRoot();
+
+ if (_layer) {
+ sp_object_unref(_layer, NULL);
+ _layer = NULL;
+ }
+
+ if (layer) {
+ List<SPObject &> hierarchy=reverse_list<SPObject::ParentIterator>(layer, root);
+ if ( layer == root ) {
+ _buildEntries(0, cons(*root, hierarchy));
+ } else if (hierarchy) {
+ _buildSiblingEntries(0, *root, hierarchy);
+ }
+
+ Gtk::TreeIter row(
+ std::find_if(
+ _layer_model->children().begin(),
+ _layer_model->children().end(),
+ column_matches_object(_model_columns.object, *layer)
+ )
+ );
+ if ( row != _layer_model->children().end() ) {
+ _selector.set_active(row);
+ }
+
+ _layer = layer;
+ sp_object_ref(_layer, NULL);
+ }
+
+ if ( !layer || layer == root ) {
+ _visibility_toggle.set_sensitive(false);
+ _visibility_toggle.set_active(false);
+ _lock_toggle.set_sensitive(false);
+ _lock_toggle.set_active(false);
+ } else {
+ _visibility_toggle.set_sensitive(true);
+ _visibility_toggle.set_active(( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isHidden() : false ));
+ _lock_toggle.set_sensitive(true);
+ _lock_toggle.set_active(( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false ));
+ }
+
+ _selection_changed_connection.unblock();
+}
+
+/** Sets the current desktop layer to the actively selected layer.
+ */
+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();
+
+ _desktop->layer_manager->setCurrentLayer(layer);
+
+ _layer_changed_connection.unblock();
+
+ _selectLayer(_desktop->currentLayer());
+ }
+ if (_desktop && _desktop->canvas) {
+ gtk_widget_grab_focus (GTK_WIDGET(_desktop->canvas));
+ }
+}
+
+/** Creates rows in the _layer_model data structure for each item
+ * in \a hierarchy, to a given \a depth.
+ */
+void LayerSelector::_buildEntries(unsigned depth,
+ Inkscape::Util::List<SPObject &> hierarchy)
+{
+ using Inkscape::Util::List;
+ using Inkscape::Util::rest;
+
+ _buildEntry(depth, *hierarchy);
+
+ List<SPObject &> remainder=rest(hierarchy);
+ if (remainder) {
+ _buildEntries(depth+1, remainder);
+ } else {
+ _buildSiblingEntries(depth+1, *hierarchy, remainder);
+ }
+}
+
+/** Creates entries in the _layer_model data structure for
+ * all siblings of the first child in \a parent.
+ */
+void LayerSelector::_buildSiblingEntries(
+ unsigned depth, SPObject &parent,
+ Inkscape::Util::List<SPObject &> hierarchy
+) {
+ using Inkscape::Util::List;
+ using Inkscape::Util::rest;
+ using Inkscape::Util::reverse_list_in_place;
+ using Inkscape::Util::filter_list;
+
+ Inkscape::Util::List<SPObject &> siblings(
+ reverse_list_in_place(
+ filter_list<SPObject::SiblingIterator>(
+ is_layer(_desktop), parent.firstChild(), NULL
+ )
+ )
+ );
+
+ SPObject *layer( hierarchy ? &*hierarchy : NULL );
+
+ while (siblings) {
+ _buildEntry(depth, *siblings);
+ if ( &*siblings == layer ) {
+ _buildSiblingEntries(depth+1, *layer, rest(hierarchy));
+ }
+ ++siblings;
+ }
+}
+
+namespace {
+
+struct Callbacks {
+ sigc::slot<void> update_row;
+ sigc::slot<void> update_list;
+};
+
+void attribute_changed(Inkscape::XML::Node */*repr*/, gchar const *name,
+ gchar const */*old_value*/, gchar const */*new_value*/,
+ bool /*is_interactive*/, void *data)
+{
+ if ( !std::strcmp(name, "inkscape:groupmode") ) {
+ reinterpret_cast<Callbacks *>(data)->update_list();
+ } else {
+ reinterpret_cast<Callbacks *>(data)->update_row();
+ }
+}
+
+void node_added(Inkscape::XML::Node */*parent*/, Inkscape::XML::Node *child, Inkscape::XML::Node */*ref*/, void *data) {
+ gchar const *mode=child->attribute("inkscape:groupmode");
+ if ( mode && !std::strcmp(mode, "layer") ) {
+ reinterpret_cast<Callbacks *>(data)->update_list();
+ }
+}
+
+void node_removed(Inkscape::XML::Node */*parent*/, Inkscape::XML::Node *child, Inkscape::XML::Node */*ref*/, void *data) {
+ gchar const *mode=child->attribute("inkscape:groupmode");
+ if ( mode && !std::strcmp(mode, "layer") ) {
+ reinterpret_cast<Callbacks *>(data)->update_list();
+ }
+}
+
+void node_reordered(Inkscape::XML::Node */*parent*/, Inkscape::XML::Node *child,
+ Inkscape::XML::Node */*old_ref*/, Inkscape::XML::Node */*new_ref*/,
+ void *data)
+{
+ gchar const *mode=child->attribute("inkscape:groupmode");
+ if ( mode && !std::strcmp(mode, "layer") ) {
+ reinterpret_cast<Callbacks *>(data)->update_list();
+ }
+}
+
+void update_row_for_object(SPObject *object,
+ Gtk::TreeModelColumn<SPObject *> const &column,
+ Glib::RefPtr<Gtk::ListStore> const &model)
+{
+ Gtk::TreeIter row(
+ std::find_if(
+ model->children().begin(),
+ model->children().end(),
+ column_matches_object(column, *object)
+ )
+ );
+ if ( row != model->children().end() ) {
+ model->row_changed(model->get_path(row), row);
+ }
+}
+
+void rebuild_all_rows(sigc::slot<void, SPObject *> rebuild, SPDesktop *desktop)
+{
+ rebuild(desktop->currentLayer());
+}
+
+}
+
+void LayerSelector::_protectUpdate(sigc::slot<void> slot) {
+ bool visibility_blocked=_visibility_toggled_connection.blocked();
+ bool lock_blocked=_lock_toggled_connection.blocked();
+ _visibility_toggled_connection.block(true);
+ _lock_toggled_connection.block(true);
+ slot();
+
+ SPObject *layer = _desktop ? _desktop->currentLayer() : 0;
+ if ( layer ) {
+ bool wantedValue = ( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false );
+ if ( _lock_toggle.get_active() != wantedValue ) {
+ _lock_toggle.set_active( wantedValue );
+ }
+ wantedValue = ( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isHidden() : false );
+ if ( _visibility_toggle.get_active() != wantedValue ) {
+ _visibility_toggle.set_active( wantedValue );
+ }
+ }
+ _visibility_toggled_connection.block(visibility_blocked);
+ _lock_toggled_connection.block(lock_blocked);
+}
+
+/** Builds and appends a row in the layer model object.
+ */
+void LayerSelector::_buildEntry(unsigned depth, SPObject &object) {
+ Inkscape::XML::NodeEventVector *vector;
+
+ Callbacks *callbacks=new Callbacks();
+
+ callbacks->update_row = sigc::bind(
+ sigc::mem_fun(*this, &LayerSelector::_protectUpdate),
+ sigc::bind(
+ sigc::ptr_fun(&update_row_for_object),
+ &object, _model_columns.object, _layer_model
+ )
+ );
+
+ SPObject *layer=_desktop->currentLayer();
+ if ( &object == layer || &object == SP_OBJECT_PARENT(layer) ) {
+ callbacks->update_list = sigc::bind(
+ sigc::mem_fun(*this, &LayerSelector::_protectUpdate),
+ sigc::bind(
+ sigc::ptr_fun(&rebuild_all_rows),
+ sigc::mem_fun(*this, &LayerSelector::_selectLayer),
+ _desktop
+ )
+ );
+
+ Inkscape::XML::NodeEventVector events = {
+ &node_added,
+ &node_removed,
+ &attribute_changed,
+ NULL,
+ &node_reordered
+ };
+
+ vector = new Inkscape::XML::NodeEventVector(events);
+ } else {
+ Inkscape::XML::NodeEventVector events = {
+ NULL,
+ NULL,
+ &attribute_changed,
+ NULL,
+ NULL
+ };
+
+ vector = new Inkscape::XML::NodeEventVector(events);
+ }
+
+ Gtk::ListStore::iterator row(_layer_model->append());
+
+ row->set_value(_model_columns.depth, depth);
+
+ sp_object_ref(&object, NULL);
+ row->set_value(_model_columns.object, &object);
+
+ Inkscape::GC::anchor(SP_OBJECT_REPR(&object));
+ row->set_value(_model_columns.repr, SP_OBJECT_REPR(&object));
+
+ row->set_value(_model_columns.callbacks, reinterpret_cast<void *>(callbacks));
+
+ sp_repr_add_listener(SP_OBJECT_REPR(&object), vector, callbacks);
+}
+
+/** Removes a row from the _model_columns object, disconnecting listeners
+ * on the slot.
+ */
+void LayerSelector::_destroyEntry(Gtk::ListStore::iterator const &row) {
+ Callbacks *callbacks=reinterpret_cast<Callbacks *>(row->get_value(_model_columns.callbacks));
+ SPObject *object=row->get_value(_model_columns.object);
+ if (object) {
+ sp_object_unref(object, NULL);
+ }
+ Inkscape::XML::Node *repr=row->get_value(_model_columns.repr);
+ if (repr) {
+ sp_repr_remove_listener_by_data(repr, callbacks);
+ Inkscape::GC::release(repr);
+ }
+ delete callbacks;
+}
+
+/** Formats the label for a given layer row
+ */
+void LayerSelector::_prepareLabelRenderer(
+ Gtk::TreeModel::const_iterator const &row
+) {
+ unsigned depth=(*row)[_model_columns.depth];
+ SPObject *object=(*row)[_model_columns.object];
+ bool label_defaulted(false);
+
+ // TODO: when the currently selected row is removed,
+ // (or before one has been selected) something appears to
+ // "invent" an iterator with null data and try to render it;
+ // where does it come from, and how can we avoid it?
+ if ( object && SP_OBJECT_REPR(object) ) {
+ SPObject *layer=( _desktop ? _desktop->currentLayer() : NULL );
+ SPObject *root=( _desktop ? _desktop->currentRoot() : NULL );
+
+ bool isancestor = !( (layer && (SP_OBJECT_PARENT(object) == SP_OBJECT_PARENT(layer))) || ((layer == root) && (SP_OBJECT_PARENT(object) == root)));
+
+ bool iscurrent = ( object == layer && object != root );
+
+ gchar *format = g_strdup_printf (
+ "<span size=\"smaller\" %s><tt>%*s%s</tt>%s%s%s%%s%s%s%s</span>",
+ ( _desktop && _desktop->itemIsHidden (SP_ITEM(object)) ? "foreground=\"gray50\"" : "" ),
+ depth, "", ( iscurrent ? "•" : " " ),
+ ( iscurrent ? "<b>" : "" ),
+ ( SP_ITEM(object)->isLocked() ? "[" : "" ),
+ ( isancestor ? "<small>" : "" ),
+ ( isancestor ? "</small>" : "" ),
+ ( SP_ITEM(object)->isLocked() ? "]" : "" ),
+ ( iscurrent ? "</b>" : "" )
+ );
+
+ gchar const *label;
+ if ( object != root ) {
+ label = object->label();
+ if (!label) {
+ label = object->defaultLabel();
+ label_defaulted = true;
+ }
+ } else {
+ label = _("(root)");
+ }
+
+ gchar *text = g_markup_printf_escaped(format, label);
+ _label_renderer.property_markup() = text;
+ g_free(text);
+ g_free(format);
+ } else {
+ _label_renderer.property_markup() = "<small> </small>";
+ }
+
+ _label_renderer.property_ypad() = 1;
+ _label_renderer.property_style() = ( label_defaulted ?
+ Pango::STYLE_ITALIC :
+ Pango::STYLE_NORMAL );
+}
+
+void LayerSelector::_lockLayer(bool lock) {
+ if ( _layer && SP_IS_ITEM(_layer) ) {
+ SP_ITEM(_layer)->setLocked(lock);
+ sp_document_done(sp_desktop_document(_desktop), SP_VERB_NONE,
+ lock? _("Lock layer") : _("Unlock layer"));
+ }
+}
+
+void LayerSelector::_hideLayer(bool hide) {
+ if ( _layer && SP_IS_ITEM(_layer) ) {
+ SP_ITEM(_layer)->setHidden(hide);
+ sp_document_done(sp_desktop_document(_desktop), SP_VERB_NONE,
+ hide? _("Hide layer") : _("Unhide layer"));
+ }
+}
+
+}
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/layer-selector.h b/src/ui/widget/layer-selector.h
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Inkscape::Widgets::LayerSelector - layer selector widget
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ *
+ * Copyright (C) 2004 MenTaLguY
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_WIDGETS_LAYER_SELECTOR
+#define SEEN_INKSCAPE_WIDGETS_LAYER_SELECTOR
+
+#include <gtkmm/box.h>
+#include <gtkmm/combobox.h>
+#include <gtkmm/togglebutton.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/cellrenderertext.h>
+#include <gtkmm/treemodel.h>
+#include <gtkmm/liststore.h>
+#include <sigc++/slot.h>
+#include "util/list.h"
+
+class SPDesktop;
+class SPDocument;
+class SPObject;
+namespace Inkscape {
+namespace XML {
+class Node;
+}
+}
+
+
+namespace Inkscape {
+namespace Widgets {
+
+class DocumentTreeModel;
+
+class LayerSelector : public Gtk::HBox {
+public:
+ LayerSelector(SPDesktop *desktop = NULL);
+ ~LayerSelector();
+
+ SPDesktop *desktop() { return _desktop; }
+ void setDesktop(SPDesktop *desktop);
+
+private:
+ class LayerModelColumns : public Gtk::TreeModel::ColumnRecord {
+ public:
+ Gtk::TreeModelColumn<unsigned> depth;
+ Gtk::TreeModelColumn<SPObject *> object;
+ Gtk::TreeModelColumn<Inkscape::XML::Node *> repr;
+ Gtk::TreeModelColumn<void *> callbacks;
+
+ LayerModelColumns() {
+ add(depth); add(object); add(repr); add(callbacks);
+ }
+ };
+
+ SPDesktop *_desktop;
+
+ Gtk::Tooltips _tooltips;
+ Gtk::ComboBox _selector;
+ Gtk::ToggleButton _visibility_toggle;
+ Gtk::ToggleButton _lock_toggle;
+
+ LayerModelColumns _model_columns;
+ Gtk::CellRendererText _label_renderer;
+ Glib::RefPtr<Gtk::ListStore> _layer_model;
+
+// sigc::connection _desktop_shutdown_connection;
+ sigc::connection _layer_changed_connection;
+ sigc::connection _selection_changed_connection;
+ sigc::connection _visibility_toggled_connection;
+ sigc::connection _lock_toggled_connection;
+
+ SPObject *_layer;
+
+ void _selectLayer(SPObject *layer);
+ void _setDesktopLayer();
+
+ void _buildEntry(unsigned depth, SPObject &object);
+ void _buildEntries(unsigned depth,
+ Inkscape::Util::List<SPObject &> hierarchy);
+ void _buildSiblingEntries(unsigned depth,
+ SPObject &parent,
+ Inkscape::Util::List<SPObject &> hierarchy);
+ void _protectUpdate(sigc::slot<void> slot);
+ void _destroyEntry(Gtk::ListStore::iterator const &row);
+ void _hideLayer(bool hide);
+ void _lockLayer(bool lock);
+
+ void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row);
+};
+
+}
+}
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 24bd5595f54fd583a67f4fcbc9ecfb4f243e2054..05f00edfca11dbe9f5e291bb795225db04afddab 100644 (file)
#include "ui/widget/entity-entry.h"
#include "ui/widget/registry.h"
-#include "dialogs/rdf.h"
+#include "rdf.h"
#include "inkscape.h"
#include "licensor.h"
index 9811cc89c638fa16969a051471f5d5a1e5675243..82f75c3ff43810ced7cf17e2fac02b6a1bd915a1 100644 (file)
--- a/src/ui/widget/panel.cpp
+++ b/src/ui/widget/panel.cpp
#include "preferences.h"
#include "desktop-handles.h"
#include "inkscape.h"
-#include "dialogs/eek-preview.h"
+#include "widgets/eek-preview.h"
namespace Inkscape {
namespace UI {
diff --git a/src/unclump.cpp b/src/unclump.cpp
--- /dev/null
+++ b/src/unclump.cpp
@@ -0,0 +1,388 @@
+/** @file
+ * @brief Unclumping objects
+ */
+/* Authors:
+ * bulia byak
+ *
+ * Copyright (C) 2005 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <algorithm>
+#include <map>
+#include "sp-item.h"
+
+
+// Taking bbox of an item is an expensive operation, and we need to do it many times, so here we
+// cache the centers, widths, and heights of items
+
+//FIXME: make a class with these cashes as members instead of globals
+std::map<const gchar *, Geom::Point> c_cache;
+std::map<const gchar *, Geom::Point> wh_cache;
+
+/**
+Center of bbox of item
+*/
+Geom::Point
+unclump_center (SPItem *item)
+{
+ std::map<const gchar *, Geom::Point>::iterator i = c_cache.find(SP_OBJECT_ID(item));
+ if ( i != c_cache.end() ) {
+ return i->second;
+ }
+
+ Geom::OptRect r = item->getBounds(sp_item_i2d_affine(item));
+ if (r) {
+ Geom::Point const c = r->midpoint();
+ c_cache[SP_OBJECT_ID(item)] = c;
+ return c;
+ } else {
+ // FIXME
+ return Geom::Point(0, 0);
+ }
+}
+
+Geom::Point
+unclump_wh (SPItem *item)
+{
+ Geom::Point wh;
+ std::map<const gchar *, Geom::Point>::iterator i = wh_cache.find(SP_OBJECT_ID(item));
+ if ( i != wh_cache.end() ) {
+ wh = i->second;
+ } else {
+ Geom::OptRect r = item->getBounds(sp_item_i2d_affine(item));
+ if (r) {
+ wh = r->dimensions();
+ wh_cache[SP_OBJECT_ID(item)] = wh;
+ } else {
+ wh = Geom::Point(0, 0);
+ }
+ }
+
+ return wh;
+}
+
+/**
+Distance between "edges" of item1 and item2. An item is considered to be an ellipse inscribed into its w/h,
+so its radius (distance from center to edge) depends on the w/h and the angle towards the other item.
+May be negative if the edge of item1 is between the center and the edge of item2.
+*/
+double
+unclump_dist (SPItem *item1, SPItem *item2)
+{
+ Geom::Point c1 = unclump_center (item1);
+ Geom::Point c2 = unclump_center (item2);
+
+ Geom::Point wh1 = unclump_wh (item1);
+ Geom::Point wh2 = unclump_wh (item2);
+
+ // angle from each item's center to the other's, unsqueezed by its w/h, normalized to 0..pi/2
+ double a1 = atan2 ((c2 - c1)[Geom::Y], (c2 - c1)[Geom::X] * wh1[Geom::Y]/wh1[Geom::X]);
+ a1 = fabs (a1);
+ if (a1 > M_PI/2) a1 = M_PI - a1;
+
+ double a2 = atan2 ((c1 - c2)[Geom::Y], (c1 - c2)[Geom::X] * wh2[Geom::Y]/wh2[Geom::X]);
+ a2 = fabs (a2);
+ if (a2 > M_PI/2) a2 = M_PI - a2;
+
+ // get the radius of each item for the given angle
+ double r1 = 0.5 * (wh1[Geom::X] + (wh1[Geom::Y] - wh1[Geom::X]) * (a1/(M_PI/2)));
+ double r2 = 0.5 * (wh2[Geom::X] + (wh2[Geom::Y] - wh2[Geom::X]) * (a2/(M_PI/2)));
+
+ // dist between centers minus angle-adjusted radii
+ double dist_r = (Geom::L2 (c2 - c1) - r1 - r2);
+
+ double stretch1 = wh1[Geom::Y]/wh1[Geom::X];
+ double stretch2 = wh2[Geom::Y]/wh2[Geom::X];
+
+ if ((stretch1 > 1.5 || stretch1 < 0.66) && (stretch2 > 1.5 || stretch2 < 0.66)) {
+
+ std::vector<double> dists;
+ dists.push_back (dist_r);
+
+ // If both objects are not circle-like, find dists between four corners
+ std::vector<Geom::Point> c1_points(2);
+ {
+ double y_closest;
+ if (c2[Geom::Y] > c1[Geom::Y] + wh1[Geom::Y]/2) {
+ y_closest = c1[Geom::Y] + wh1[Geom::Y]/2;
+ } else if (c2[Geom::Y] < c1[Geom::Y] - wh1[Geom::Y]/2) {
+ y_closest = c1[Geom::Y] - wh1[Geom::Y]/2;
+ } else {
+ y_closest = c2[Geom::Y];
+ }
+ c1_points[0] = Geom::Point (c1[Geom::X], y_closest);
+ double x_closest;
+ if (c2[Geom::X] > c1[Geom::X] + wh1[Geom::X]/2) {
+ x_closest = c1[Geom::X] + wh1[Geom::X]/2;
+ } else if (c2[Geom::X] < c1[Geom::X] - wh1[Geom::X]/2) {
+ x_closest = c1[Geom::X] - wh1[Geom::X]/2;
+ } else {
+ x_closest = c2[Geom::X];
+ }
+ c1_points[1] = Geom::Point (x_closest, c1[Geom::Y]);
+ }
+
+
+ std::vector<Geom::Point> c2_points(2);
+ {
+ double y_closest;
+ if (c1[Geom::Y] > c2[Geom::Y] + wh2[Geom::Y]/2) {
+ y_closest = c2[Geom::Y] + wh2[Geom::Y]/2;
+ } else if (c1[Geom::Y] < c2[Geom::Y] - wh2[Geom::Y]/2) {
+ y_closest = c2[Geom::Y] - wh2[Geom::Y]/2;
+ } else {
+ y_closest = c1[Geom::Y];
+ }
+ c2_points[0] = Geom::Point (c2[Geom::X], y_closest);
+ double x_closest;
+ if (c1[Geom::X] > c2[Geom::X] + wh2[Geom::X]/2) {
+ x_closest = c2[Geom::X] + wh2[Geom::X]/2;
+ } else if (c1[Geom::X] < c2[Geom::X] - wh2[Geom::X]/2) {
+ x_closest = c2[Geom::X] - wh2[Geom::X]/2;
+ } else {
+ x_closest = c1[Geom::X];
+ }
+ c2_points[1] = Geom::Point (x_closest, c2[Geom::Y]);
+ }
+
+ for (int i = 0; i < 2; i ++) {
+ for (int j = 0; j < 2; j ++) {
+ dists.push_back (Geom::L2 (c1_points[i] - c2_points[j]));
+ }
+ }
+
+ // return the minimum of all dists
+ return *std::min_element(dists.begin(), dists.end());
+ } else {
+ return dist_r;
+ }
+}
+
+/**
+Average unclump_dist from item to others
+*/
+double unclump_average (SPItem *item, GSList *others)
+{
+ int n = 0;
+ double sum = 0;
+
+ for (GSList *i = others; i != NULL; i = i->next) {
+ SPItem *other = SP_ITEM (i->data);
+
+ if (other == item)
+ continue;
+
+ n++;
+ sum += unclump_dist (item, other);
+ }
+
+ if (n != 0)
+ return sum/n;
+ else
+ return 0;
+}
+
+/**
+Closest to item among others
+ */
+SPItem *unclump_closest (SPItem *item, GSList *others)
+{
+ double min = HUGE_VAL;
+ SPItem *closest = NULL;
+
+ for (GSList *i = others; i != NULL; i = i->next) {
+ SPItem *other = SP_ITEM (i->data);
+
+ if (other == item)
+ continue;
+
+ double dist = unclump_dist (item, other);
+ if (dist < min && fabs (dist) < 1e6) {
+ min = dist;
+ closest = other;
+ }
+ }
+
+ return closest;
+}
+
+/**
+Most distant from item among others
+ */
+SPItem *unclump_farest (SPItem *item, GSList *others)
+{
+ double max = -HUGE_VAL;
+ SPItem *farest = NULL;
+
+ for (GSList *i = others; i != NULL; i = i->next) {
+ SPItem *other = SP_ITEM (i->data);
+
+ if (other == item)
+ continue;
+
+ double dist = unclump_dist (item, other);
+ if (dist > max && fabs (dist) < 1e6) {
+ max = dist;
+ farest = other;
+ }
+ }
+
+ return farest;
+}
+
+/**
+Removes from the \a rest list those items that are "behind" \a closest as seen from \a item,
+i.e. those on the other side of the line through \a closest perpendicular to the direction from \a
+item to \a closest. Returns a newly created list which must be freed.
+ */
+GSList *
+unclump_remove_behind (SPItem *item, SPItem *closest, GSList *rest)
+{
+ Geom::Point it = unclump_center (item);
+ Geom::Point p1 = unclump_center (closest);
+
+ // perpendicular through closest to the direction to item:
+ Geom::Point perp = Geom::rot90(it - p1);
+ Geom::Point p2 = p1 + perp;
+
+ // get the standard Ax + By + C = 0 form for p1-p2:
+ double A = p1[Geom::Y] - p2[Geom::Y];
+ double B = p2[Geom::X] - p1[Geom::X];
+ double C = p2[Geom::Y] * p1[Geom::X] - p1[Geom::Y] * p2[Geom::X];
+
+ // substitute the item into it:
+ double val_item = A * it[Geom::X] + B * it[Geom::Y] + C;
+
+ GSList *out = NULL;
+
+ for (GSList *i = rest; i != NULL; i = i->next) {
+ SPItem *other = SP_ITEM (i->data);
+
+ if (other == item)
+ continue;
+
+ Geom::Point o = unclump_center (other);
+ double val_other = A * o[Geom::X] + B * o[Geom::Y] + C;
+
+ if (val_item * val_other <= 1e-6) {
+ // different signs, which means item and other are on the different sides of p1-p2 line; skip
+ } else {
+ out = g_slist_prepend (out, other);
+ }
+ }
+
+ return out;
+}
+
+/**
+Moves \a what away from \a from by \a dist
+ */
+void
+unclump_push (SPItem *from, SPItem *what, double dist)
+{
+ Geom::Point it = unclump_center (what);
+ Geom::Point p = unclump_center (from);
+ Geom::Point by = dist * Geom::unit_vector (- (p - it));
+
+ Geom::Matrix move = Geom::Translate (by);
+
+ std::map<const gchar *, Geom::Point>::iterator i = c_cache.find(SP_OBJECT_ID(what));
+ if ( i != c_cache.end() ) {
+ i->second *= move;
+ }
+
+ //g_print ("push %s at %g,%g from %g,%g by %g,%g, dist %g\n", SP_OBJECT_ID(what), it[Geom::X],it[Geom::Y], p[Geom::X],p[Geom::Y], by[Geom::X],by[Geom::Y], dist);
+
+ sp_item_set_i2d_affine(what, sp_item_i2d_affine(what) * move);
+ sp_item_write_transform(what, SP_OBJECT_REPR(what), what->transform, NULL);
+}
+
+/**
+Moves \a what towards \a to by \a dist
+ */
+void
+unclump_pull (SPItem *to, SPItem *what, double dist)
+{
+ Geom::Point it = unclump_center (what);
+ Geom::Point p = unclump_center (to);
+ Geom::Point by = dist * Geom::unit_vector (p - it);
+
+ Geom::Matrix move = Geom::Translate (by);
+
+ std::map<const gchar *, Geom::Point>::iterator i = c_cache.find(SP_OBJECT_ID(what));
+ if ( i != c_cache.end() ) {
+ i->second *= move;
+ }
+
+ //g_print ("pull %s at %g,%g to %g,%g by %g,%g, dist %g\n", SP_OBJECT_ID(what), it[Geom::X],it[Geom::Y], p[Geom::X],p[Geom::Y], by[Geom::X],by[Geom::Y], dist);
+
+ sp_item_set_i2d_affine(what, sp_item_i2d_affine(what) * move);
+ sp_item_write_transform(what, SP_OBJECT_REPR(what), what->transform, NULL);
+}
+
+
+/**
+Unclumps the items in \a items, reducing local unevenness in their distribution. Produces an effect
+similar to "engraver dots". The only distribution which is unchanged by unclumping is a hexagonal
+grid. May be called repeatedly for stronger effect.
+ */
+void
+unclump (GSList *items)
+{
+ c_cache.clear();
+ wh_cache.clear();
+
+ for (GSList *i = items; i != NULL; i = i->next) { // for each original/clone x:
+ SPItem *item = SP_ITEM (i->data);
+
+ GSList *nei = NULL;
+
+ GSList *rest = g_slist_copy (items);
+ rest = g_slist_remove (rest, item);
+
+ while (rest != NULL) {
+ SPItem *closest = unclump_closest (item, rest);
+ if (closest) {
+ nei = g_slist_prepend (nei, closest);
+ rest = g_slist_remove (rest, closest);
+ GSList *new_rest = unclump_remove_behind (item, closest, rest);
+ g_slist_free (rest);
+ rest = new_rest;
+ } else {
+ g_slist_free (rest);
+ break;
+ }
+ }
+
+ if (g_slist_length (nei) >= 2) {
+ double ave = unclump_average (item, nei);
+
+ SPItem *closest = unclump_closest (item, nei);
+ SPItem *farest = unclump_farest (item, nei);
+
+ double dist_closest = unclump_dist (closest, item);
+ double dist_farest = unclump_dist (farest, item);
+
+ //g_print ("NEI %d for item %s closest %s at %g farest %s at %g ave %g\n", g_slist_length(nei), SP_OBJECT_ID(item), SP_OBJECT_ID(closest), dist_closest, SP_OBJECT_ID(farest), dist_farest, ave);
+
+ if (fabs (ave) < 1e6 && fabs (dist_closest) < 1e6 && fabs (dist_farest) < 1e6) { // otherwise the items are bogus
+ // increase these coefficients to make unclumping more aggressive and less stable
+ // the pull coefficient is a bit bigger to counteract the long-term expansion trend
+ unclump_push (closest, item, 0.3 * (ave - dist_closest));
+ unclump_pull (farest, item, 0.35 * (dist_farest - ave));
+ }
+ }
+ }
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/unclump.h b/src/unclump.h
--- /dev/null
+++ b/src/unclump.h
@@ -0,0 +1,29 @@
+/** @file
+ * @brief Unclumping objects
+ */
+/* Authors:
+ * bulia byak
+ *
+ * Copyright (C) 2005 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_DIALOGS_UNCLUMP_H
+#define SEEN_DIALOGS_UNCLUMP_H
+
+#include <glib/gslist.h>
+
+void unclump(GSList *items);
+
+#endif /* !UNCLUMP_H_SEEN */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/verbs.cpp b/src/verbs.cpp
index ce624b14c2fd8aea2b9380d8da4fb369151d669e..834e1511d4bae4382fc481bba7027ca6a362f227 100644 (file)
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
#include "desktop.h"
#include "desktop-handles.h"
#include "dialogs/clonetiler.h"
-#include "dialogs/extensions.h"
#include "dialogs/find.h"
-#include "dialogs/iconpreview.h"
#include "dialogs/input.h"
#include "dialogs/item-properties.h"
-#include "dialogs/layer-properties.h"
-#include "dialogs/layers-panel.h"
#include "dialogs/spellcheck.h"
-#include "dialogs/swatches.h"
#include "dialogs/text-edit.h"
#include "dialogs/xml-tree.h"
#include "display/curve.h"
#include "tools-switch.h"
#include "ui/dialog/dialog-manager.h"
#include "ui/dialog/document-properties.h"
+#include "ui/dialog/extensions.h"
+#include "ui/dialog/icon-preview.h"
#include "ui/dialog/inkscape-preferences.h"
+#include "ui/dialog/layer-properties.h"
+#include "ui/dialog/layers.h"
+#include "ui/dialog/swatches.h"
#include "ui/icon-names.h"
#ifdef WITH_INKBOARD
index 32a8a71e5310acd2d0746424cf9995eb2fe5eb0c..13f2b33eb56c3e37e09d75e42b52405007f97125 100644 (file)
ink_common_sources += \
widgets/button.cpp \
widgets/button.h \
- widgets/calligraphic-profile-rename.cpp \
- widgets/calligraphic-profile-rename.h \
widgets/dash-selector.cpp \
widgets/dash-selector.h \
widgets/desktop-widget.cpp \
widgets/desktop-widget.h \
+ widgets/eek-color-def.cpp \
+ widgets/eek-color-def.h \
+ widgets/eek-preview.cpp \
+ widgets/eek-preview.h \
+ widgets/fill-style.cpp \
+ widgets/fill-style.h \
widgets/font-selector.cpp \
widgets/font-selector.h \
widgets/gradient-image.cpp \
widgets/gradient-vector.h \
widgets/icon.cpp \
widgets/icon.h \
- widgets/layer-selector.cpp \
- widgets/layer-selector.h \
widgets/paint-selector.cpp \
widgets/paint-selector.h \
widgets/ruler.cpp \
widgets/select-toolbar.h \
widgets/shrink-wrap-button.cpp \
widgets/shrink-wrap-button.h \
+ widgets/sp-attribute-widget.cpp \
+ widgets/sp-attribute-widget.h \
widgets/sp-color-gtkselector.cpp \
widgets/sp-color-gtkselector.h \
widgets/sp-color-icc-selector.cpp \
widgets/sp-xmlview-content.h \
widgets/sp-xmlview-tree.cpp \
widgets/sp-xmlview-tree.h \
+ widgets/stroke-style.cpp \
+ widgets/stroke-style.h \
widgets/toolbox.cpp \
widgets/toolbox.h \
widgets/widget-sizes.h
diff --git a/src/widgets/calligraphic-profile-rename.cpp b/src/widgets/calligraphic-profile-rename.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/** @file
- * @brief Dialog for naming calligraphic profiles
- *
- * @note This file is in the wrong directory because of link order issues -
- * it is required by widgets/toolbox.cpp, and libspwidgets.a comes after
- * libinkdialogs.a in the current link order.
- */
-/* Author:
- * Aubanel MONNIER
- *
- * Copyright (C) 2007 Authors
- * Released under GNU GPL. Read the file 'COPYING' for more information
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <glibmm/i18n.h>
-#include <gtkmm/stock.h>
-
-#include "desktop.h"
-#include "calligraphic-profile-rename.h"
-
-namespace Inkscape {
-namespace UI {
-namespace Dialog {
-
-CalligraphicProfileRename::CalligraphicProfileRename() :
- _applied(false)
-{
- Gtk::VBox *mainVBox = get_vbox();
- _layout_table.set_spacings(4);
- _layout_table.resize (1, 2);
-
- _profile_name_entry.set_activates_default(true);
-
- _profile_name_label.set_label(_("Profile name:"));
- _profile_name_label.set_alignment(1.0, 0.5);
-
- _layout_table.attach(_profile_name_label,
- 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
- _layout_table.attach(_profile_name_entry,
- 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
- mainVBox->pack_start(_layout_table, false, false, 4);
- // Buttons
- _close_button.set_use_stock(true);
- _close_button.set_label(Gtk::Stock::CANCEL.id);
- _close_button.set_flags(Gtk::CAN_DEFAULT);
-
- _apply_button.set_use_underline(true);
- _apply_button.set_label(_("Save"));
- _apply_button.set_flags(Gtk::CAN_DEFAULT);
-
- _close_button.signal_clicked()
- .connect(sigc::mem_fun(*this, &CalligraphicProfileRename::_close));
- _apply_button.signal_clicked()
- .connect(sigc::mem_fun(*this, &CalligraphicProfileRename::_apply));
-
- signal_delete_event().connect( sigc::bind_return(
- sigc::hide(sigc::mem_fun(*this, &CalligraphicProfileRename::_close)), true ) );
-
- add_action_widget(_close_button, Gtk::RESPONSE_CLOSE);
- add_action_widget(_apply_button, Gtk::RESPONSE_APPLY);
-
- _apply_button.grab_default();
-
- show_all_children();
-}
-
-void CalligraphicProfileRename::_apply()
-{
- _profile_name = _profile_name_entry.get_text();
- _applied = true;
- _close();
-}
-
-void CalligraphicProfileRename::_close()
-{
- this->Gtk::Dialog::hide();
-}
-
-void CalligraphicProfileRename::show(SPDesktop *desktop)
-{
- CalligraphicProfileRename &dial = instance();
- dial._applied=false;
- dial.set_modal(true);
- desktop->setWindowTransient (dial.gobj());
- dial.property_destroy_with_parent() = true;
- // dial.Gtk::Dialog::show();
- //dial.present();
- dial.run();
-}
-
-} // namespace Dialog
-} // namespace UI
-} // namespace Inkscape
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/calligraphic-profile-rename.h b/src/widgets/calligraphic-profile-rename.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/** @file
- * @brief Dialog for naming calligraphic profiles
- */
-/* Author:
- * Aubanel MONNIER
- *
- * Copyright (C) 2007 Authors
- * Released under GNU GPL. Read the file 'COPYING' for more information
- */
-
-#ifndef INKSCAPE_DIALOG_CALLIGRAPHIC_PROFILE_H
-#define INKSCAPE_DIALOG_CALLIGRAPHIC_PROFILE_H
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/entry.h>
-#include <gtkmm/label.h>
-#include <gtkmm/table.h>
-struct SPDesktop;
-
-namespace Inkscape {
-namespace UI {
-namespace Dialog {
-
-class CalligraphicProfileRename : public Gtk::Dialog {
-public:
- CalligraphicProfileRename();
- virtual ~CalligraphicProfileRename() {}
- Glib::ustring getName() const {
- return "CalligraphicProfileRename";
- }
-
- static void show(SPDesktop *desktop);
- static bool applied() {
- return instance()._applied;
- }
- static Glib::ustring getProfileName() {
- return instance()._profile_name;
- }
-
-protected:
- void _close();
- void _apply();
-
- Gtk::Label _profile_name_label;
- Gtk::Entry _profile_name_entry;
- Gtk::Table _layout_table;
- Gtk::Button _close_button;
- Gtk::Button _apply_button;
- Glib::ustring _profile_name;
- bool _applied;
-private:
- static CalligraphicProfileRename &instance() {
- static CalligraphicProfileRename instance_;
- return instance_;
- }
- CalligraphicProfileRename(CalligraphicProfileRename const &); // no copy
- CalligraphicProfileRename &operator=(CalligraphicProfileRename const &); // no assign
-};
-
-} // namespace Dialog
-} // namespace UI
-} // namespace Inkscape
-
-#endif // INKSCAPE_DIALOG_CALLIGRAPHIC_PROFILE_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 324e5b0087d1401b55198368d89f4efcedf91582..356a09418de9439c8661762afcec391cfb44d1d4 100644 (file)
#include <gtkmm/paned.h>
#include <gtk/gtk.h>
-#include "macros.h"
-#include "inkscape-private.h"
-#include "desktop-handles.h"
+#include "box3d-context.h"
+#include "color-profile-fns.h"
+#include "conn-avoid-ref.h"
#include "desktop-events.h"
-#include "document.h"
+#include "desktop-handles.h"
#include "desktop-widget.h"
-#include "sp-namedview.h"
-#include "interface.h"
-#include "toolbox.h"
-#include "preferences.h"
-#include "file.h"
#include "display/canvas-arena.h"
#include "display/nr-arena.h"
+#include "document.h"
+#include "ege-color-prof-tracker.h"
+#include "ege-select-one-action.h"
#include <extension/db.h>
+#include "file.h"
#include "helper/units.h"
+#include "inkscape-private.h"
+#include "interface.h"
+#include "macros.h"
+#include "preferences.h"
+#include "sp-image.h"
+#include "sp-item.h"
+#include "sp-namedview.h"
+#include "toolbox.h"
+#include "ui/dialog/dialog-manager.h"
+#include "ui/dialog/swatches.h"
+#include "ui/widget/dock.h"
+#include "ui/widget/layer-selector.h"
+#include "ui/widget/selected-style.h"
#include "widgets/button.h"
#include "widgets/ruler.h"
-#include "widgets/widget-sizes.h"
-#include "widgets/spw-utilities.h"
#include "widgets/spinbutton-events.h"
-#include "widgets/layer-selector.h"
+#include "widgets/spw-utilities.h"
#include "widgets/toolbox.h"
-#include "ui/dialog/dialog-manager.h"
-#include "ui/widget/dock.h"
-#include "ui/widget/selected-style.h"
-#include "sp-item.h"
-#include "dialogs/swatches.h"
-#include "conn-avoid-ref.h"
-#include "ege-select-one-action.h"
-#include "ege-color-prof-tracker.h"
-#include "color-profile-fns.h"
-#include "box3d-context.h"
-#include "sp-image.h"
+#include "widgets/widget-sizes.h"
#if defined (SOLARIS) && (SOLARIS == 8)
#include "round.h"
diff --git a/src/widgets/eek-color-def.cpp b/src/widgets/eek-color-def.cpp
--- /dev/null
@@ -0,0 +1,147 @@
+/** @file
+ * @brief EEK color definition
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Eek Color Definition.
+ *
+ * The Initial Developer of the Original Code is
+ * Jon A. Cruz.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "config.h"
+
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#endif
+
+#if !defined(_)
+#define _(s) gettext(s)
+#endif // !defined(_)
+
+#include "eek-color-def.h"
+
+namespace eek
+{
+
+ColorDef::ColorDef() :
+ descr(_("none")),
+ r(0),
+ g(0),
+ b(0),
+ none(true),
+ editable(false)
+{
+}
+
+ColorDef::ColorDef( unsigned int r, unsigned int g, unsigned int b, const std::string& description ) :
+ descr(description),
+ r(r),
+ g(g),
+ b(b),
+ none(false),
+ editable(false)
+{
+}
+
+ColorDef::~ColorDef()
+{
+}
+
+ColorDef::ColorDef( ColorDef const &other )
+{
+ if ( this != &other ) {
+ *this = other;
+ }
+}
+
+ColorDef& ColorDef::operator=( ColorDef const &other )
+{
+ if ( this != & other )
+ {
+ r = other.r;
+ g = other.g;
+ b = other.b;
+ descr = other.descr;
+ none = other.none;
+ editable = other.editable;
+ }
+ return *this;
+}
+
+class ColorDef::HookData {
+public:
+ HookData( ColorCallback cb, void* data ) {_cb = cb; _data = data;}
+ ColorCallback _cb;
+ void* _data;
+};
+
+void ColorDef::setRGB( unsigned int r, unsigned int g, unsigned int b )
+{
+ if ( r != this->r || g != this->g || b != this->b ) {
+ this->r = r;
+ this->g = g;
+ this->b = b;
+
+ // beware of callbacks changing things
+ for ( std::vector<HookData*>::iterator it = _listeners.begin(); it != _listeners.end(); ++it )
+ {
+ if ( (*it)->_cb )
+ {
+ (*it)->_cb( (*it)->_data );
+ }
+ }
+ }
+}
+
+void ColorDef::addCallback( ColorCallback cb, void* data )
+{
+ _listeners.push_back( new HookData(cb, data) );
+}
+
+void ColorDef::removeCallback( ColorCallback cb, void* data )
+{
+ (void)cb;
+ (void)data;
+}
+
+} // namespace eek
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/eek-color-def.h b/src/widgets/eek-color-def.h
--- /dev/null
@@ -0,0 +1,102 @@
+/** @file
+ * @brief EEK color definition
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Eek Color Definition.
+ *
+ * The Initial Developer of the Original Code is
+ * Jon A. Cruz.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef SEEN_EEK_COLOR_DEF_H
+#define SEEN_EEK_COLOR_DEF_H
+
+#include <string>
+#include <vector>
+
+namespace eek
+{
+
+typedef void (*ColorCallback)( void* data );
+
+
+class ColorDef
+{
+public:
+ ColorDef();
+ ColorDef( unsigned int r, unsigned int g, unsigned int b, const std::string& description );
+ virtual ~ColorDef();
+
+ ColorDef( ColorDef const &other );
+ virtual ColorDef& operator=( ColorDef const &other );
+
+ void setRGB( unsigned int r, unsigned int g, unsigned int b );
+ unsigned int getR() const { return r; }
+ unsigned int getG() const { return g; }
+ unsigned int getB() const { return b; }
+
+ void addCallback( ColorCallback cb, void* data );
+ void removeCallback( ColorCallback cb, void* data );
+
+ bool isEditable() const { return editable; }
+ void setEditable( bool edit ) { editable = edit; }
+
+ std::string descr;
+
+protected:
+ unsigned int r;
+ unsigned int g;
+ unsigned int b;
+ bool none;
+ bool editable;
+
+private:
+ class HookData;
+
+ std::vector<HookData*> _listeners;
+};
+
+
+} // namespace eek
+
+#endif // SEEN_EEK_COLOR_DEF_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/eek-preview.cpp b/src/widgets/eek-preview.cpp
--- /dev/null
@@ -0,0 +1,736 @@
+/** @file
+ * @brief EEK preview stuff
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Eek Preview Stuffs.
+ *
+ * The Initial Developer of the Original Code is
+ * Jon A. Cruz.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include "eek-preview.h"
+
+#define PRIME_BUTTON_MAGIC_NUMBER 1
+
+#define FOCUS_PROP_ID 1
+
+/* Keep in sycn with last value in eek-preview.h */
+#define PREVIEW_SIZE_LAST PREVIEW_SIZE_HUGE
+#define PREVIEW_SIZE_NEXTFREE (PREVIEW_SIZE_HUGE + 1)
+
+#define PREVIEW_MAX_RATIO 500
+
+static void eek_preview_class_init( EekPreviewClass *klass );
+static void eek_preview_init( EekPreview *preview );
+
+static GtkWidgetClass* parent_class = 0;
+
+void eek_preview_set_color( EekPreview* preview, int r, int g, int b )
+{
+ preview->_r = r;
+ preview->_g = g;
+ preview->_b = b;
+
+ gtk_widget_queue_draw(GTK_WIDGET(preview));
+}
+
+
+void eek_preview_set_pixbuf( EekPreview* preview, GdkPixbuf* pixbuf )
+{
+ preview->_previewPixbuf = pixbuf;
+
+ gtk_widget_queue_draw(GTK_WIDGET(preview));
+
+ if (preview->_scaled) {
+ g_object_unref(preview->_scaled);
+ preview->_scaled = 0;
+ }
+ preview->_scaledW = gdk_pixbuf_get_width(preview->_previewPixbuf);
+ preview->_scaledH = gdk_pixbuf_get_height(preview->_previewPixbuf);
+}
+
+
+GType eek_preview_get_type(void)
+{
+ static GType preview_type = 0;
+
+ if (!preview_type) {
+ static const GTypeInfo preview_info = {
+ sizeof( EekPreviewClass ),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc)eek_preview_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof( EekPreview ),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc)eek_preview_init,
+ NULL /* value_table */
+ };
+
+
+ preview_type = g_type_register_static( GTK_TYPE_DRAWING_AREA, "EekPreview", &preview_info, (GTypeFlags)0 );
+ }
+
+ return preview_type;
+}
+
+static gboolean setupDone = FALSE;
+static GtkRequisition sizeThings[PREVIEW_SIZE_NEXTFREE];
+
+void eek_preview_set_size_mappings( guint count, GtkIconSize const* sizes )
+{
+ gint width = 0;
+ gint height = 0;
+ gint smallest = 512;
+ gint largest = 0;
+ guint i = 0;
+ guint delta = 0;
+
+ for ( i = 0; i < count; ++i ) {
+ gboolean worked = gtk_icon_size_lookup( sizes[i], &width, &height );
+ if ( worked ) {
+ if ( width < smallest ) {
+ smallest = width;
+ }
+ if ( width > largest ) {
+ largest = width;
+ }
+ }
+ }
+
+ smallest = (smallest * 3) / 4;
+
+ delta = largest - smallest;
+
+ for ( i = 0; i < G_N_ELEMENTS(sizeThings); ++i ) {
+ guint val = smallest + ( (i * delta) / (G_N_ELEMENTS(sizeThings) - 1) );
+ sizeThings[i].width = val;
+ sizeThings[i].height = val;
+ }
+
+ setupDone = TRUE;
+}
+
+static void eek_preview_size_request( GtkWidget* widget, GtkRequisition* req )
+{
+ gint width = 0;
+ gint height = 0;
+ EekPreview* preview = EEK_PREVIEW(widget);
+
+ if ( !setupDone ) {
+ GtkIconSize sizes[] = {
+ GTK_ICON_SIZE_MENU,
+ GTK_ICON_SIZE_SMALL_TOOLBAR,
+ GTK_ICON_SIZE_LARGE_TOOLBAR,
+ GTK_ICON_SIZE_BUTTON,
+ GTK_ICON_SIZE_DIALOG
+ };
+ eek_preview_set_size_mappings( G_N_ELEMENTS(sizes), sizes );
+ }
+
+ width = sizeThings[preview->_size].width;
+ height = sizeThings[preview->_size].height;
+
+ if ( preview->_view == VIEW_TYPE_LIST ) {
+ width *= 3;
+ }
+
+ if ( preview->_ratio != 100 ) {
+ width = (width * preview->_ratio) / 100;
+ if ( width < 0 ) {
+ width = 1;
+ }
+ }
+
+ req->width = width;
+ req->height = height;
+}
+
+enum {
+ CLICKED_SIGNAL,
+ ALTCLICKED_SIGNAL,
+ LAST_SIGNAL
+};
+
+
+static guint eek_preview_signals[LAST_SIGNAL] = { 0 };
+
+
+gboolean eek_preview_expose_event( GtkWidget* widget, GdkEventExpose* event )
+{
+/* g_message("Exposed!!! %s", GTK_WIDGET_HAS_FOCUS(widget) ? "XXX" : "---" ); */
+ gint insetX = 0;
+ gint insetY = 0;
+
+ (void)event;
+/*
+ gint lower = widget->allocation.width;
+ lower = (widget->allocation.height < lower) ? widget->allocation.height : lower;
+ if ( lower > 16 ) {
+ insetX++;
+ if ( lower > 18 ) {
+ insetX++;
+ if ( lower > 22 ) {
+ insetX++;
+ if ( lower > 24 ) {
+ insetX++;
+ if ( lower > 32 ) {
+ insetX++;
+ }
+ }
+ }
+ }
+ insetY = insetX;
+ }
+*/
+
+ if ( GTK_WIDGET_DRAWABLE( widget ) ) {
+ GtkStyle* style = gtk_widget_get_style( widget );
+
+ if ( insetX > 0 || insetY > 0 ) {
+ gtk_paint_flat_box( style,
+ widget->window,
+ (GtkStateType)GTK_WIDGET_STATE(widget),
+ GTK_SHADOW_NONE,
+ NULL,
+ widget,
+ NULL,
+ 0, 0,
+ widget->allocation.width, widget->allocation.height);
+ }
+
+ GdkGC *gc = gdk_gc_new( widget->window );
+ EekPreview* preview = EEK_PREVIEW(widget);
+ GdkColor fg = {0, preview->_r, preview->_g, preview->_b};
+
+ gdk_colormap_alloc_color( gdk_colormap_get_system(), &fg, FALSE, TRUE );
+
+ gdk_gc_set_foreground( gc, &fg );
+
+ gdk_draw_rectangle( widget->window,
+ gc,
+ TRUE,
+ insetX, insetY,
+ widget->allocation.width - (insetX * 2), widget->allocation.height - (insetY * 2) );
+
+ if ( preview->_linked ) {
+ /* Draw arrow */
+ GdkRectangle possible = {insetX, insetY, (widget->allocation.width - (insetX * 2)), (widget->allocation.height - (insetY * 2)) };
+ GdkRectangle area = {possible.x, possible.y, possible.width / 2, possible.height / 2 };
+
+ /* Make it square */
+ if ( area.width > area.height )
+ area.width = area.height;
+ if ( area.height > area.width )
+ area.height = area.width;
+
+ /* Center it horizontally */
+ if ( area.width < possible.width ) {
+ int diff = (possible.width - area.width) / 2;
+ area.x += diff;
+ }
+
+
+ if ( preview->_linked & PREVIEW_LINK_IN ) {
+ gtk_paint_arrow( style,
+ widget->window,
+ (GtkStateType)widget->state,
+ GTK_SHADOW_ETCHED_IN,
+ NULL, /* clip area. &area, */
+ widget, /* may be NULL */
+ NULL, /* detail */
+ GTK_ARROW_DOWN,
+ FALSE,
+ area.x, area.y,
+ area.width, area.height
+ );
+ }
+
+ if ( preview->_linked & PREVIEW_LINK_OUT ) {
+ GdkRectangle otherArea = {area.x, area.y, area.width, area.height};
+ if ( otherArea.height < possible.height ) {
+ otherArea.y = possible.y + (possible.height - otherArea.height);
+ }
+
+ gtk_paint_arrow( style,
+ widget->window,
+ (GtkStateType)widget->state,
+ GTK_SHADOW_ETCHED_OUT,
+ NULL, /* clip area. &area, */
+ widget, /* may be NULL */
+ NULL, /* detail */
+ GTK_ARROW_UP,
+ FALSE,
+ otherArea.x, otherArea.y,
+ otherArea.width, otherArea.height
+ );
+ }
+
+ if ( preview->_linked & PREVIEW_LINK_OTHER ) {
+ GdkRectangle otherArea = {insetX, area.y, area.width, area.height};
+ if ( otherArea.height < possible.height ) {
+ otherArea.y = possible.y + (possible.height - otherArea.height) / 2;
+ }
+
+ gtk_paint_arrow( style,
+ widget->window,
+ (GtkStateType)widget->state,
+ GTK_SHADOW_ETCHED_OUT,
+ NULL, /* clip area. &area, */
+ widget, /* may be NULL */
+ NULL, /* detail */
+ GTK_ARROW_LEFT,
+ FALSE,
+ otherArea.x, otherArea.y,
+ otherArea.width, otherArea.height
+ );
+ }
+ }
+
+ if ( preview->_previewPixbuf ) {
+ GtkDrawingArea* da = &(preview->drawing);
+ GdkDrawable* drawable = (GdkDrawable*) (((GtkWidget*)da)->window);
+ gint w = 0;
+ gint h = 0;
+ gdk_drawable_get_size(drawable, &w, &h);
+ if ((w != preview->_scaledW) || (h != preview->_scaledH)) {
+ if (preview->_scaled) {
+ g_object_unref(preview->_scaled);
+ }
+ preview->_scaled = gdk_pixbuf_scale_simple(preview->_previewPixbuf, w, h, GDK_INTERP_BILINEAR);
+ preview->_scaledW = w;
+ preview->_scaledH = h;
+ }
+
+ GdkPixbuf* pix = (preview->_scaled) ? preview->_scaled : preview->_previewPixbuf;
+ gdk_draw_pixbuf( drawable, 0, pix, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0 );
+ }
+
+
+ if ( GTK_WIDGET_HAS_FOCUS(widget) ) {
+ gtk_paint_focus( style,
+ widget->window,
+ GTK_STATE_NORMAL,
+ NULL, /* GdkRectangle *area, */
+ widget,
+ NULL,
+ 0 + 1, 0 + 1,
+ widget->allocation.width - 2, widget->allocation.height - 2 );
+ }
+ }
+
+
+ return FALSE;
+}
+
+
+static gboolean eek_preview_enter_cb( GtkWidget* widget, GdkEventCrossing* event )
+{
+ if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
+ EekPreview* preview = EEK_PREVIEW(widget);
+ preview->_within = TRUE;
+ gtk_widget_set_state( widget, preview->_hot ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT );
+ }
+ return FALSE;
+}
+
+static gboolean eek_preview_leave_cb( GtkWidget* widget, GdkEventCrossing* event )
+{
+ if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
+ EekPreview* preview = EEK_PREVIEW(widget);
+ preview->_within = FALSE;
+ gtk_widget_set_state( widget, GTK_STATE_NORMAL );
+ }
+ return FALSE;
+}
+
+/*
+static gboolean eek_preview_focus_in_event( GtkWidget* widget, GdkEventFocus* event )
+{
+ g_message("focus IN");
+ gboolean blip = parent_class->focus_in_event ? parent_class->focus_in_event(widget, event) : FALSE;
+ return blip;
+}
+
+static gboolean eek_preview_focus_out_event( GtkWidget* widget, GdkEventFocus* event )
+{
+ g_message("focus OUT");
+ gboolean blip = parent_class->focus_out_event ? parent_class->focus_out_event(widget, event) : FALSE;
+ return blip;
+}
+*/
+
+static gboolean eek_preview_button_press_cb( GtkWidget* widget, GdkEventButton* event )
+{
+ if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
+ EekPreview* preview = EEK_PREVIEW(widget);
+
+ if ( preview->_takesFocus && !GTK_WIDGET_HAS_FOCUS(widget) ) {
+ gtk_widget_grab_focus(widget);
+ }
+
+ if ( event->button == PRIME_BUTTON_MAGIC_NUMBER ) {
+ preview->_hot = TRUE;
+ if ( preview->_within ) {
+ gtk_widget_set_state( widget, GTK_STATE_ACTIVE );
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean eek_preview_button_release_cb( GtkWidget* widget, GdkEventButton* event )
+{
+ if ( gtk_get_event_widget( (GdkEvent*)event ) == widget ) {
+ EekPreview* preview = EEK_PREVIEW(widget);
+ preview->_hot = FALSE;
+ gtk_widget_set_state( widget, GTK_STATE_NORMAL );
+ if ( preview->_within && event->button == PRIME_BUTTON_MAGIC_NUMBER ) {
+ gboolean isAlt = (event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK;
+
+ if ( isAlt ) {
+ g_signal_emit( widget, eek_preview_signals[ALTCLICKED_SIGNAL], 0, 2 );
+ } else {
+ g_signal_emit( widget, eek_preview_signals[CLICKED_SIGNAL], 0 );
+ }
+ }
+ }
+ return FALSE;
+}
+
+gboolean eek_preview_key_press_event( GtkWidget* widget, GdkEventKey* event)
+{
+ (void)widget;
+ (void)event;
+ g_message("TICK");
+ return FALSE;
+}
+
+gboolean eek_preview_key_release_event( GtkWidget* widget, GdkEventKey* event)
+{
+ (void)widget;
+ (void)event;
+ g_message("tock");
+ return FALSE;
+}
+
+static void eek_preview_get_property( GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GObjectClass* gobjClass = G_OBJECT_CLASS(parent_class);
+ switch ( property_id ) {
+ case FOCUS_PROP_ID:
+ {
+ EekPreview* preview = EEK_PREVIEW( object );
+ g_value_set_boolean( value, preview->_takesFocus );
+ }
+ break;
+ default:
+ {
+ if ( gobjClass->get_property ) {
+ gobjClass->get_property( object, property_id, value, pspec );
+ }
+ }
+ }
+}
+
+static void eek_preview_set_property( GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GObjectClass* gobjClass = G_OBJECT_CLASS(parent_class);
+ switch ( property_id ) {
+ case FOCUS_PROP_ID:
+ {
+ EekPreview* preview = EEK_PREVIEW( object );
+ gboolean val = g_value_get_boolean( value );
+ if ( val != preview->_takesFocus ) {
+ preview->_takesFocus = val;
+ }
+ }
+ break;
+ default:
+ {
+ if ( gobjClass->set_property ) {
+ gobjClass->set_property( object, property_id, value, pspec );
+ }
+ }
+ }
+}
+
+
+static gboolean eek_preview_popup_menu( GtkWidget* widget )
+{
+/* g_message("Do the popup!"); */
+ gboolean blip = parent_class->popup_menu ? parent_class->popup_menu(widget) : FALSE;
+ return blip;
+}
+
+
+static void eek_preview_class_init( EekPreviewClass *klass )
+{
+ GObjectClass* gobjClass = G_OBJECT_CLASS(klass);
+ /*GtkObjectClass* objectClass = (GtkObjectClass*)klass;*/
+ GtkWidgetClass* widgetClass = (GtkWidgetClass*)klass;
+
+ gobjClass->set_property = eek_preview_set_property;
+ gobjClass->get_property = eek_preview_get_property;
+
+ /*objectClass->destroy = eek_preview_destroy;*/
+
+ parent_class = (GtkWidgetClass*)g_type_class_peek_parent( klass );
+
+ /*widgetClass->map = ;*/
+ /*widgetClass->unmap = ;*/
+ /*widgetClass->realize = ;*/
+ /*widgetClass->unrealize = ;*/
+ widgetClass->size_request = eek_preview_size_request;
+ /*widgetClass->size_allocate = ;*/
+ /*widgetClass->state_changed = ;*/
+ /*widgetClass->style_set = ;*/
+ /*widgetClass->grab_notify = ;*/
+
+ widgetClass->button_press_event = eek_preview_button_press_cb;
+ widgetClass->button_release_event = eek_preview_button_release_cb;
+ /*widgetClass->delete_event = ;*/
+ /*widgetClass->destroy_event = ;*/
+ widgetClass->expose_event = eek_preview_expose_event;
+/* widgetClass->key_press_event = eek_preview_key_press_event; */
+/* widgetClass->key_release_event = eek_preview_key_release_event; */
+ widgetClass->enter_notify_event = eek_preview_enter_cb;
+ widgetClass->leave_notify_event = eek_preview_leave_cb;
+ /*widgetClass->configure_event = ;*/
+ /*widgetClass->focus_in_event = eek_preview_focus_in_event;*/
+ /*widgetClass->focus_out_event = eek_preview_focus_out_event;*/
+
+ /* selection */
+ /*widgetClass->selection_get = ;*/
+ /*widgetClass->selection_received = ;*/
+
+
+ /* drag source: */
+ /*widgetClass->drag_begin = ;*/
+ /*widgetClass->drag_end = ;*/
+ /*widgetClass->drag_data_get = ;*/
+ /*widgetClass->drag_data_delete = ;*/
+
+ /* drag target: */
+ /*widgetClass->drag_leave = ;*/
+ /*widgetClass->drag_motion = ;*/
+ /*widgetClass->drag_drop = ;*/
+ /*widgetClass->drag_data_received = ;*/
+
+ /* For keybindings: */
+ widgetClass->popup_menu = eek_preview_popup_menu;
+ /*widgetClass->show_help = ;*/
+
+ /* Accessibility support: */
+ /*widgetClass->get_accessible = ;*/
+ /*widgetClass->screen_changed = ;*/
+ /*widgetClass->can_activate_accel = ;*/
+
+
+ eek_preview_signals[CLICKED_SIGNAL] =
+ g_signal_new( "clicked",
+ G_TYPE_FROM_CLASS( klass ),
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
+ G_STRUCT_OFFSET( EekPreviewClass, clicked ),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 );
+
+ eek_preview_signals[ALTCLICKED_SIGNAL] =
+ g_signal_new( "alt-clicked",
+ G_TYPE_FROM_CLASS( klass ),
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
+ G_STRUCT_OFFSET( EekPreviewClass, clicked ),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
+ 1, G_TYPE_INT );
+
+
+ g_object_class_install_property( gobjClass,
+ FOCUS_PROP_ID,
+ g_param_spec_boolean(
+ "focus-on-click",
+ NULL,
+ "flag to grab focus when clicked",
+ TRUE,
+ (GParamFlags)(G_PARAM_READWRITE | G_PARAM_CONSTRUCT)
+ )
+ );
+}
+
+void eek_preview_set_linked( EekPreview* splat, LinkType link )
+{
+ link = (LinkType)(link & PREVIEW_LINK_ALL);
+ if ( link != (LinkType)splat->_linked ) {
+ splat->_linked = link;
+
+ gtk_widget_queue_draw( GTK_WIDGET(splat) );
+ }
+}
+
+LinkType eek_preview_get_linked( EekPreview* splat )
+{
+ return (LinkType)splat->_linked;
+}
+
+gboolean eek_preview_get_focus_on_click( EekPreview* preview )
+{
+ return preview->_takesFocus;
+}
+
+void eek_preview_set_focus_on_click( EekPreview* preview, gboolean focus_on_click )
+{
+ if ( focus_on_click != preview->_takesFocus ) {
+ preview->_takesFocus = focus_on_click;
+ }
+}
+
+void eek_preview_set_details( EekPreview* preview, PreviewStyle prevstyle, ViewType view, PreviewSize size, guint ratio )
+{
+ preview->_prevstyle = prevstyle;
+ preview->_view = view;
+
+ if ( size > PREVIEW_SIZE_LAST ) {
+ size = PREVIEW_SIZE_LAST;
+ }
+ preview->_size = size;
+
+ if ( ratio > PREVIEW_MAX_RATIO ) {
+ ratio = PREVIEW_MAX_RATIO;
+ }
+ preview->_ratio = ratio;
+
+ gtk_widget_queue_draw(GTK_WIDGET(preview));
+}
+
+static void eek_preview_init( EekPreview *preview )
+{
+ GtkWidget* widg = GTK_WIDGET(preview);
+ GTK_WIDGET_SET_FLAGS( widg, GTK_CAN_FOCUS );
+ GTK_WIDGET_SET_FLAGS( widg, GTK_RECEIVES_DEFAULT );
+
+ gtk_widget_set_sensitive( widg, TRUE );
+
+ gtk_widget_add_events(widg, GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_KEY_PRESS_MASK
+ | GDK_KEY_RELEASE_MASK
+ | GDK_FOCUS_CHANGE_MASK
+ | GDK_ENTER_NOTIFY_MASK
+ | GDK_LEAVE_NOTIFY_MASK );
+
+/* gtk_widget_add_events( widg, GDK_ALL_EVENTS_MASK );*/
+
+ preview->_r = 0x80;
+ preview->_g = 0x80;
+ preview->_b = 0xcc;
+ preview->_scaledW = 0;
+ preview->_scaledH = 0;
+
+ preview->_hot = FALSE;
+ preview->_within = FALSE;
+ preview->_takesFocus = FALSE;
+
+ preview->_prevstyle = PREVIEW_STYLE_ICON;
+ preview->_view = VIEW_TYPE_LIST;
+ preview->_size = PREVIEW_SIZE_SMALL;
+ preview->_ratio = 100;
+
+ preview->_previewPixbuf = 0;
+ preview->_scaled = 0;
+
+/*
+ GdkColor color = {0};
+ color.red = (255 << 8) | 255;
+
+ GdkColor whack = {0};
+ whack.green = (255 << 8) | 255;
+
+ gtk_widget_modify_bg( widg, GTK_STATE_NORMAL, &color );
+ gtk_widget_modify_bg( widg, GTK_STATE_PRELIGHT, &whack );
+*/
+
+/* GTK_STATE_ACTIVE, */
+/* GTK_STATE_PRELIGHT, */
+/* GTK_STATE_SELECTED, */
+/* GTK_STATE_INSENSITIVE */
+
+ if ( 0 ) {
+ GdkColor color = {0,0,0,0};
+
+ color.red = 0xffff;
+ color.green = 0;
+ color.blue = 0xffff;
+ gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE );
+ gtk_widget_modify_bg(widg, GTK_STATE_ACTIVE, &color);
+
+ color.red = 0;
+ color.green = 0xffff;
+ color.blue = 0;
+ gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE );
+ gtk_widget_modify_bg(widg, GTK_STATE_SELECTED, &color);
+
+ color.red = 0xffff;
+ color.green = 0;
+ color.blue = 0;
+ gdk_colormap_alloc_color( gdk_colormap_get_system(), &color, FALSE, TRUE );
+ gtk_widget_modify_bg( widg, GTK_STATE_PRELIGHT, &color );
+ }
+}
+
+
+GtkWidget* eek_preview_new(void)
+{
+ return GTK_WIDGET( g_object_new( EEK_PREVIEW_TYPE, NULL ) );
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/eek-preview.h b/src/widgets/eek-preview.h
--- /dev/null
@@ -0,0 +1,152 @@
+/** @file
+ * @brief EEK preview stuff
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Eek Preview Stuffs.
+ *
+ * The Initial Developer of the Original Code is
+ * Jon A. Cruz.
+ * Portions created by the Initial Developer are Copyright (C) 2005-2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef SEEN_EEK_PREVIEW_H
+#define SEEN_EEK_PREVIEW_H
+
+#include <gdk/gdkpixbuf.h>
+#include <gtk/gtkdrawingarea.h>
+
+G_BEGIN_DECLS
+
+
+#define EEK_PREVIEW_TYPE (eek_preview_get_type())
+#define EEK_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST( (obj), EEK_PREVIEW_TYPE, EekPreview))
+#define EEK_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST( (klass), EEK_PREVIEW_TYPE, EekPreviewClass))
+#define IS_EEK_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE( (obj), EEK_PREVIEW_TYPE))
+#define IS_EEK_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE( (klass), EEK_PREVIEW_TYPE))
+#define EEK_PREVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS( (obj), EEK_PREVIEW_TYPE, EekPreviewClass))
+
+typedef enum {
+ PREVIEW_STYLE_ICON = 0,
+ PREVIEW_STYLE_PREVIEW,
+ PREVIEW_STYLE_NAME,
+ PREVIEW_STYLE_BLURB,
+ PREVIEW_STYLE_ICON_NAME,
+ PREVIEW_STYLE_ICON_BLURB,
+ PREVIEW_STYLE_PREVIEW_NAME,
+ PREVIEW_STYLE_PREVIEW_BLURB
+} PreviewStyle;
+
+typedef enum {
+ VIEW_TYPE_LIST = 0,
+ VIEW_TYPE_GRID
+} ViewType;
+
+typedef enum {
+ PREVIEW_SIZE_TINY = 0,
+ PREVIEW_SIZE_SMALL,
+ PREVIEW_SIZE_MEDIUM,
+ PREVIEW_SIZE_BIG,
+ PREVIEW_SIZE_BIGGER,
+ PREVIEW_SIZE_HUGE
+} PreviewSize;
+
+typedef enum {
+ PREVIEW_LINK_NONE = 0,
+ PREVIEW_LINK_IN = 1,
+ PREVIEW_LINK_OUT = 2,
+ PREVIEW_LINK_OTHER = 4,
+ PREVIEW_LINK_ALL = 7
+} LinkType;
+
+typedef struct _EekPreview EekPreview;
+typedef struct _EekPreviewClass EekPreviewClass;
+
+
+struct _EekPreview
+{
+ GtkDrawingArea drawing;
+
+ int _r;
+ int _g;
+ int _b;
+ int _scaledW;
+ int _scaledH;
+
+ gboolean _hot;
+ gboolean _within;
+ gboolean _takesFocus;
+
+ PreviewStyle _prevstyle;
+ ViewType _view;
+ PreviewSize _size;
+ guint _ratio;
+ guint _linked;
+ GdkPixbuf* _previewPixbuf;
+ GdkPixbuf* _scaled;
+};
+
+struct _EekPreviewClass
+{
+ GtkDrawingAreaClass parent_class;
+
+ void (*clicked) (EekPreview* splat);
+};
+
+
+GType eek_preview_get_type(void) G_GNUC_CONST;
+GtkWidget* eek_preview_new(void);
+
+void eek_preview_set_details( EekPreview* splat, PreviewStyle prevstyle, ViewType view, PreviewSize size, guint ratio );
+void eek_preview_set_color( EekPreview* splat, int r, int g, int b );
+void eek_preview_set_pixbuf( EekPreview* splat, GdkPixbuf* pixbuf );
+
+void eek_preview_set_linked( EekPreview* splat, LinkType link );
+LinkType eek_preview_get_linked( EekPreview* splat );
+
+gboolean eek_preview_get_focus_on_click( EekPreview* preview );
+void eek_preview_set_focus_on_click( EekPreview* preview, gboolean focus_on_click );
+
+void eek_preview_set_size_mappings( guint count, GtkIconSize const* sizes );
+
+G_END_DECLS
+
+#endif /* SEEN_EEK_PREVIEW_H */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/fill-style.cpp b/src/widgets/fill-style.cpp
--- /dev/null
@@ -0,0 +1,552 @@
+/** @file
+ * @brief Fill style widget
+ */
+/* Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Frank Felfe <innerspace@iname.com>
+ * bulia byak <buliabyak@users.sf.net>
+ *
+ * Copyright (C) 1999-2005 authors
+ * Copyright (C) 2001-2002 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#define noSP_FS_VERBOSE
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glibmm/i18n.h>
+
+#include "desktop-handles.h"
+#include "desktop-style.h"
+#include "display/sp-canvas.h"
+#include "document-private.h"
+#include "gradient-chemistry.h"
+#include "inkscape.h"
+#include "selection.h"
+#include "sp-linear-gradient.h"
+#include "sp-pattern.h"
+#include "sp-radial-gradient.h"
+#include "style.h"
+#include "widgets/paint-selector.h"
+#include "widgets/sp-widget.h"
+#include "xml/repr.h"
+
+#include "widgets/fill-style.h"
+
+
+// These can be deleted once we sort out the libart dependence.
+
+#define ART_WIND_RULE_NONZERO 0
+
+static void sp_fill_style_widget_construct ( SPWidget *spw,
+ SPPaintSelector *psel );
+
+static void sp_fill_style_widget_modify_selection ( SPWidget *spw,
+ Inkscape::Selection *selection,
+ guint flags,
+ SPPaintSelector *psel );
+
+static void sp_fill_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw );
+
+static void sp_fill_style_widget_change_selection ( SPWidget *spw,
+ Inkscape::Selection *selection,
+ SPPaintSelector *psel );
+
+static void sp_fill_style_widget_update (SPWidget *spw);
+
+static void sp_fill_style_widget_paint_mode_changed ( SPPaintSelector *psel,
+ SPPaintSelectorMode mode,
+ SPWidget *spw );
+static void sp_fill_style_widget_fillrule_changed ( SPPaintSelector *psel,
+ SPPaintSelectorFillRule mode,
+ SPWidget *spw );
+
+static void sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw );
+static void sp_fill_style_widget_paint_changed (SPPaintSelector *psel, SPWidget *spw );
+
+GtkWidget *
+sp_fill_style_widget_new (void)
+{
+ GtkWidget *spw = sp_widget_new_global (INKSCAPE);
+
+ GtkWidget *vb = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vb);
+ gtk_container_add (GTK_CONTAINER (spw), vb);
+
+ GtkWidget *psel = sp_paint_selector_new (true); // with fillrule selector
+ gtk_widget_show (psel);
+ gtk_box_pack_start (GTK_BOX (vb), psel, TRUE, TRUE, 0);
+ g_object_set_data (G_OBJECT (spw), "paint-selector", psel);
+
+ g_signal_connect ( G_OBJECT (psel), "mode_changed",
+ G_CALLBACK (sp_fill_style_widget_paint_mode_changed),
+ spw );
+
+ g_signal_connect ( G_OBJECT (psel), "dragged",
+ G_CALLBACK (sp_fill_style_widget_paint_dragged),
+ spw );
+
+ g_signal_connect ( G_OBJECT (psel), "changed",
+ G_CALLBACK (sp_fill_style_widget_paint_changed),
+ spw );
+
+ g_signal_connect ( G_OBJECT (psel), "fillrule_changed",
+ G_CALLBACK (sp_fill_style_widget_fillrule_changed),
+ spw );
+
+
+ g_signal_connect ( G_OBJECT (spw), "construct",
+ G_CALLBACK (sp_fill_style_widget_construct), psel);
+
+//FIXME: switch these from spw signals to global inkscape object signals; spw just retranslates
+//those anyway; then eliminate spw
+ g_signal_connect ( G_OBJECT (spw), "modify_selection",
+ G_CALLBACK (sp_fill_style_widget_modify_selection), psel);
+
+ g_signal_connect ( G_OBJECT (spw), "change_selection",
+ G_CALLBACK (sp_fill_style_widget_change_selection), psel);
+
+ g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_fill_style_widget_change_subselection), spw);
+
+ sp_fill_style_widget_update (SP_WIDGET (spw));
+
+ return spw;
+
+} // end of sp_fill_style_widget_new()
+
+
+
+static void
+sp_fill_style_widget_construct( SPWidget *spw, SPPaintSelector */*psel*/ )
+{
+#ifdef SP_FS_VERBOSE
+ g_print ( "Fill style widget constructed: inkscape %p repr %p\n",
+ spw->inkscape, spw->repr );
+#endif
+ if (spw->inkscape) {
+ sp_fill_style_widget_update (spw);
+ }
+
+} // end of sp_fill_style_widget_construct()
+
+static void
+sp_fill_style_widget_modify_selection( SPWidget *spw,
+ Inkscape::Selection */*selection*/,
+ guint flags,
+ SPPaintSelector */*psel*/ )
+{
+ if (flags & ( SP_OBJECT_MODIFIED_FLAG |
+ SP_OBJECT_PARENT_MODIFIED_FLAG |
+ SP_OBJECT_STYLE_MODIFIED_FLAG) )
+ {
+ sp_fill_style_widget_update (spw);
+ }
+}
+
+static void
+sp_fill_style_widget_change_subselection( Inkscape::Application */*inkscape*/,
+ SPDesktop */*desktop*/,
+ SPWidget *spw )
+{
+ sp_fill_style_widget_update (spw);
+}
+
+static void
+sp_fill_style_widget_change_selection( SPWidget *spw,
+ Inkscape::Selection */*selection*/,
+ SPPaintSelector */*psel*/ )
+{
+ sp_fill_style_widget_update (spw);
+}
+
+/**
+* \param sel Selection to use, or NULL.
+*/
+static void
+sp_fill_style_widget_update (SPWidget *spw)
+{
+ if (g_object_get_data (G_OBJECT (spw), "update"))
+ return;
+
+ if (g_object_get_data (G_OBJECT (spw), "local")) {
+ g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (FALSE)); // local change; do nothing, but reset the flag
+ return;
+ }
+
+ g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
+
+ SPPaintSelector *psel = SP_PAINT_SELECTOR (g_object_get_data (G_OBJECT (spw), "paint-selector"));
+
+ // create temporary style
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ // query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection
+ int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FILL);
+
+ switch (result) {
+ case QUERY_STYLE_NOTHING:
+ {
+ /* No paint at all */
+ sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_EMPTY);
+ break;
+ }
+
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector
+ case QUERY_STYLE_MULTIPLE_SAME:
+ {
+ SPPaintSelectorMode pselmode = sp_style_determine_paint_selector_mode (query, true);
+ sp_paint_selector_set_mode (psel, pselmode);
+
+ sp_paint_selector_set_fillrule (psel, query->fill_rule.computed == ART_WIND_RULE_NONZERO?
+ SP_PAINT_SELECTOR_FILLRULE_NONZERO : SP_PAINT_SELECTOR_FILLRULE_EVENODD);
+
+ if (query->fill.set && query->fill.isColor()) {
+ sp_paint_selector_set_color_alpha (psel, &query->fill.value.color, SP_SCALE24_TO_FLOAT (query->fill_opacity.value));
+ } else if (query->fill.set && query->fill.isPaintserver()) {
+
+ SPPaintServer *server = SP_STYLE_FILL_SERVER (query);
+
+ if (SP_IS_LINEARGRADIENT (server)) {
+ SPGradient *vector = sp_gradient_get_vector (SP_GRADIENT (server), FALSE);
+ sp_paint_selector_set_gradient_linear (psel, vector);
+
+ SPLinearGradient *lg = SP_LINEARGRADIENT (server);
+ sp_paint_selector_set_gradient_properties (psel,
+ SP_GRADIENT_UNITS (lg),
+ SP_GRADIENT_SPREAD (lg));
+ } else if (SP_IS_RADIALGRADIENT (server)) {
+ SPGradient *vector = sp_gradient_get_vector (SP_GRADIENT (server), FALSE);
+ sp_paint_selector_set_gradient_radial (psel, vector);
+
+ SPRadialGradient *rg = SP_RADIALGRADIENT (server);
+ sp_paint_selector_set_gradient_properties (psel,
+ SP_GRADIENT_UNITS (rg),
+ SP_GRADIENT_SPREAD (rg));
+ } else if (SP_IS_PATTERN (server)) {
+ SPPattern *pat = pattern_getroot (SP_PATTERN (server));
+ sp_update_pattern_list (psel, pat);
+ }
+ }
+ break;
+ }
+
+ case QUERY_STYLE_MULTIPLE_DIFFERENT:
+ {
+ sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_MULTIPLE);
+ break;
+ }
+ }
+
+ sp_style_unref(query);
+
+ g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
+
+}
+
+
+static void
+sp_fill_style_widget_paint_mode_changed ( SPPaintSelector *psel,
+ SPPaintSelectorMode /*mode*/,
+ SPWidget *spw )
+{
+ if (g_object_get_data (G_OBJECT (spw), "update"))
+ return;
+
+ /* TODO: Does this work? */
+ /* TODO: Not really, here we have to get old color back from object */
+ /* Instead of relying on paint widget having meaningful colors set */
+ sp_fill_style_widget_paint_changed (psel, spw);
+}
+
+static void
+sp_fill_style_widget_fillrule_changed ( SPPaintSelector */*psel*/,
+ SPPaintSelectorFillRule mode,
+ SPWidget *spw )
+{
+ if (g_object_get_data (G_OBJECT (spw), "update"))
+ return;
+
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "fill-rule", mode == SP_PAINT_SELECTOR_FILLRULE_EVENODD? "evenodd":"nonzero");
+
+ sp_desktop_set_style (desktop, css);
+
+ sp_repr_css_attr_unref (css);
+
+ sp_document_done (SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_FILL_STROKE,
+ _("Change fill rule"));
+}
+
+static gchar const *undo_label_1 = "fill:flatcolor:1";
+static gchar const *undo_label_2 = "fill:flatcolor:2";
+static gchar const *undo_label = undo_label_1;
+
+/**
+This is called repeatedly while you are dragging a color slider, only for flat color
+modes. Previously it set the color in style but did not update the repr for efficiency, however
+this was flakey and didn't buy us almost anything. So now it does the same as _changed, except
+lumps all its changes for undo.
+ */
+static void
+sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw)
+{
+ if (!spw->inkscape) {
+ return;
+ }
+
+ if (g_object_get_data (G_OBJECT (spw), "update")) {
+ return;
+ }
+
+ if (g_object_get_data (G_OBJECT (spw), "local")) {
+ // previous local flag not cleared yet;
+ // this means dragged events come too fast, so we better skip this one to speed up display
+ // (it's safe to do this in any case)
+ return;
+ }
+
+ g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
+
+ switch (psel->mode) {
+
+ case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
+ case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
+ {
+ sp_paint_selector_set_flat_color (psel, SP_ACTIVE_DESKTOP, "fill", "fill-opacity");
+ sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set fill color"));
+ g_object_set_data (G_OBJECT (spw), "local", GINT_TO_POINTER (TRUE)); // local change, do not update from selection
+ break;
+ }
+
+ default:
+ g_warning ( "file %s: line %d: Paint %d should not emit 'dragged'",
+ __FILE__, __LINE__, psel->mode );
+ break;
+
+ }
+ g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
+}
+
+
+/**
+This is called (at least) when:
+1 paint selector mode is switched (e.g. flat color -> gradient)
+2 you finished dragging a gradient node and released mouse
+3 you changed a gradient selector parameter (e.g. spread)
+Must update repr.
+ */
+static void
+sp_fill_style_widget_paint_changed ( SPPaintSelector *psel,
+ SPWidget *spw )
+{
+ if (g_object_get_data (G_OBJECT (spw), "update")) {
+ return;
+ }
+ g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
+
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop) {
+ return;
+ }
+ SPDocument *document = sp_desktop_document (desktop);
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
+
+ GSList const *items = selection->itemList();
+
+ switch (psel->mode) {
+
+ case SP_PAINT_SELECTOR_MODE_EMPTY:
+ // This should not happen.
+ g_warning ( "file %s: line %d: Paint %d should not emit 'changed'",
+ __FILE__, __LINE__, psel->mode);
+ break;
+ case SP_PAINT_SELECTOR_MODE_MULTIPLE:
+ // This happens when you switch multiple objects with different gradients to flat color;
+ // nothing to do here.
+ break;
+
+ case SP_PAINT_SELECTOR_MODE_NONE:
+ {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "fill", "none");
+
+ sp_desktop_set_style (desktop, css);
+
+ sp_repr_css_attr_unref (css);
+
+ sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Remove fill"));
+ break;
+ }
+
+ case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
+ case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
+ {
+ // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in losing release events
+ sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0);
+
+ sp_paint_selector_set_flat_color (psel, desktop, "fill", "fill-opacity");
+ sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set fill color"));
+ // resume interruptibility
+ sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop));
+
+ // on release, toggle undo_label so that the next drag will not be lumped with this one
+ if (undo_label == undo_label_1)
+ undo_label = undo_label_2;
+ else
+ undo_label = undo_label_1;
+
+ break;
+ }
+
+ case SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR:
+ case SP_PAINT_SELECTOR_MODE_GRADIENT_RADIAL:
+ if (items) {
+ SPGradientType const gradient_type = ( psel->mode == SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR
+ ? SP_GRADIENT_TYPE_LINEAR
+ : SP_GRADIENT_TYPE_RADIAL );
+
+ // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, "fill-opacity", "1.0");
+
+ SPGradient *vector = sp_paint_selector_get_gradient_vector(psel);
+ if (!vector) {
+ /* No vector in paint selector should mean that we just changed mode */
+
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result = objects_query_fillstroke ((GSList *) items, query, true);
+ guint32 common_rgb = 0;
+ if (result == QUERY_STYLE_MULTIPLE_SAME) {
+ if (!query->fill.isColor()) {
+ common_rgb = sp_desktop_get_color(desktop, true);
+ } else {
+ common_rgb = query->fill.value.color.toRGBA32( 0xff );
+ }
+ vector = sp_document_default_gradient_vector(document, common_rgb);
+ }
+ sp_style_unref(query);
+
+ for (GSList const *i = items; i != NULL; i = i->next) {
+ //FIXME: see above
+ sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style");
+
+ if (!vector) {
+ sp_item_set_gradient(SP_ITEM(i->data),
+ sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), true),
+ gradient_type, true);
+ } else {
+ sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true);
+ }
+ }
+ } else {
+ /* We have changed from another gradient type, or modified spread/units within
+ * this gradient type. */
+ vector = sp_gradient_ensure_vector_normalized (vector);
+ for (GSList const *i = items; i != NULL; i = i->next) {
+ //FIXME: see above
+ sp_repr_css_change_recursive (SP_OBJECT_REPR (i->data), css, "style");
+
+ SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, true);
+ sp_gradient_selector_attrs_to_gradient (gr, psel);
+ }
+ }
+
+ sp_repr_css_attr_unref (css);
+
+ sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set gradient on fill"));
+ }
+ break;
+
+ case SP_PAINT_SELECTOR_MODE_PATTERN:
+
+ if (items) {
+
+ SPPattern *pattern = sp_paint_selector_get_pattern (psel);
+ if (!pattern) {
+
+ /* No Pattern in paint selector should mean that we just
+ * changed mode - dont do jack.
+ */
+
+ } else {
+ Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern);
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar *urltext = g_strdup_printf ("url(#%s)", patrepr->attribute("id"));
+ sp_repr_css_set_property (css, "fill", urltext);
+
+ // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs
+ sp_repr_css_set_property(css, "fill-opacity", "1.0");
+
+ // cannot just call sp_desktop_set_style, because we don't want to touch those
+ // objects who already have the same root pattern but through a different href
+ // chain. FIXME: move this to a sp_item_set_pattern
+ for (GSList const *i = items; i != NULL; i = i->next) {
+ SPObject *selobj = SP_OBJECT (i->data);
+
+ SPStyle *style = SP_OBJECT_STYLE (selobj);
+ if (style && style->fill.isPaintserver()) {
+ SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (selobj);
+ if (SP_IS_PATTERN (server) && pattern_getroot (SP_PATTERN(server)) == pattern)
+ // only if this object's pattern is not rooted in our selected pattern, apply
+ continue;
+ }
+
+ sp_desktop_apply_css_recursive (selobj, css, true);
+ }
+
+ sp_repr_css_attr_unref (css);
+ g_free (urltext);
+
+ } // end if
+
+ sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set pattern on fill"));
+
+ } // end if
+
+ break;
+
+ case SP_PAINT_SELECTOR_MODE_UNSET:
+ if (items) {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_unset_property (css, "fill");
+
+ sp_desktop_set_style (desktop, css);
+ sp_repr_css_attr_unref (css);
+
+ sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Unset fill"));
+ }
+ break;
+
+ default:
+ g_warning ( "file %s: line %d: Paint selector should not be in "
+ "mode %d",
+ __FILE__, __LINE__, psel->mode );
+ break;
+ }
+
+ g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/fill-style.h b/src/widgets/fill-style.h
--- /dev/null
+++ b/src/widgets/fill-style.h
@@ -0,0 +1,33 @@
+/** @file
+ * @brief Fill style configuration
+ */
+/* Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ *
+ * Copyright (C) 2002 Lauris Kaplinski
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_DIALOGS_SP_FILL_STYLE_H
+#define SEEN_DIALOGS_SP_FILL_STYLE_H
+
+#include <glib.h>
+#include <gtk/gtkwidget.h>
+#include "forward.h"
+
+
+GtkWidget *sp_fill_style_widget_new (void);
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/layer-selector.cpp b/src/widgets/layer-selector.cpp
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * Inkscape::Widgets::LayerSelector - layer selector widget
- *
- * Authors:
- * MenTaLguY <mental@rydia.net>
- *
- * Copyright (C) 2004 MenTaLguY
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <cstring>
-#include <string>
-#include <glibmm/i18n.h>
-
-#include "desktop-handles.h"
-
-#include "widgets/layer-selector.h"
-#include "widgets/shrink-wrap-button.h"
-#include "widgets/icon.h"
-
-#include "util/reverse-list.h"
-#include "util/filter-list.h"
-
-#include "sp-item.h"
-#include "desktop.h"
-#include "document.h"
-#include "dialogs/layer-properties.h"
-#include "layer-manager.h"
-#include "xml/node-event-vector.h"
-#include "verbs.h"
-
-namespace Inkscape {
-namespace Widgets {
-
-namespace {
-
-class AlternateIcons : public Gtk::HBox {
-public:
- AlternateIcons(Inkscape::IconSize size, gchar const *a, gchar const *b)
- : _a(NULL), _b(NULL)
- {
- if (a) {
- _a = Gtk::manage(sp_icon_get_icon(a, size));
- _a->set_no_show_all(true);
- add(*_a);
- }
- if (b) {
- _b = Gtk::manage(sp_icon_get_icon(b, size));
- _b->set_no_show_all(true);
- add(*_b);
- }
- setState(false);
- }
-
- bool state() const { return _state; }
- void setState(bool state) {
- _state = state;
- if (_state) {
- if (_a) {
- _a->hide();
- }
- if (_b) {
- _b->show();
- }
- } else {
- if (_a) {
- _a->show();
- }
- if (_b) {
- _b->hide();
- }
- }
- }
-
-private:
- Gtk::Widget *_a;
- Gtk::Widget *_b;
- bool _state;
-};
-
-}
-
-/** LayerSelector constructor. Creates lock and hide buttons,
- * initalizes the layer dropdown selector with a label renderer,
- * and hooks up signal for setting the desktop layer when the
- * selector is changed.
- */
-LayerSelector::LayerSelector(SPDesktop *desktop)
-: _desktop(NULL), _layer(NULL)
-{
- AlternateIcons *label;
-
- label = Gtk::manage(new AlternateIcons(Inkscape::ICON_SIZE_DECORATION, "visible", "hidden"));
- _visibility_toggle.add(*label);
- _visibility_toggle.signal_toggled().connect(
- sigc::compose(
- sigc::mem_fun(*label, &AlternateIcons::setState),
- sigc::mem_fun(_visibility_toggle, &Gtk::ToggleButton::get_active)
- )
- );
- _visibility_toggled_connection = _visibility_toggle.signal_toggled().connect(
- sigc::compose(
- sigc::mem_fun(*this, &LayerSelector::_hideLayer),
- sigc::mem_fun(_visibility_toggle, &Gtk::ToggleButton::get_active)
- )
- );
-
- _visibility_toggle.set_relief(Gtk::RELIEF_NONE);
- shrink_wrap_button(_visibility_toggle);
- _tooltips.set_tip(_visibility_toggle, _("Toggle current layer visibility"));
- pack_start(_visibility_toggle, Gtk::PACK_EXPAND_PADDING);
-
- label = Gtk::manage(new AlternateIcons(Inkscape::ICON_SIZE_DECORATION, "lock_unlocked", "width_height_lock"));
- _lock_toggle.add(*label);
- _lock_toggle.signal_toggled().connect(
- sigc::compose(
- sigc::mem_fun(*label, &AlternateIcons::setState),
- sigc::mem_fun(_lock_toggle, &Gtk::ToggleButton::get_active)
- )
- );
- _lock_toggled_connection = _lock_toggle.signal_toggled().connect(
- sigc::compose(
- sigc::mem_fun(*this, &LayerSelector::_lockLayer),
- sigc::mem_fun(_lock_toggle, &Gtk::ToggleButton::get_active)
- )
- );
-
- _lock_toggle.set_relief(Gtk::RELIEF_NONE);
- shrink_wrap_button(_lock_toggle);
- _tooltips.set_tip(_lock_toggle, _("Lock or unlock current layer"));
- pack_start(_lock_toggle, Gtk::PACK_EXPAND_PADDING);
-
- _tooltips.set_tip(_selector, _("Current layer"));
- pack_start(_selector, Gtk::PACK_EXPAND_WIDGET);
-
- _layer_model = Gtk::ListStore::create(_model_columns);
- _selector.set_model(_layer_model);
- _selector.pack_start(_label_renderer);
- _selector.set_cell_data_func(
- _label_renderer,
- sigc::mem_fun(*this, &LayerSelector::_prepareLabelRenderer)
- );
-
- _selection_changed_connection = _selector.signal_changed().connect(
- sigc::mem_fun(*this, &LayerSelector::_setDesktopLayer)
- );
- setDesktop(desktop);
-}
-
-/** Destructor - disconnects signal handler
- */
-LayerSelector::~LayerSelector() {
- setDesktop(NULL);
- _selection_changed_connection.disconnect();
-}
-
-namespace {
-
-/** Helper function - detaches desktop from selector
- */
-bool detach(LayerSelector *selector) {
- selector->setDesktop(NULL);
- return FALSE;
-}
-
-}
-
-/** Sets the desktop for the widget. First disconnects signals
- * for the current desktop, then stores the pointer to the
- * given \a desktop, and attaches its signals to this one.
- * Then it selects the current layer for the desktop.
- */
-void LayerSelector::setDesktop(SPDesktop *desktop) {
- if ( desktop == _desktop ) {
- return;
- }
-
- if (_desktop) {
-// _desktop_shutdown_connection.disconnect();
- _layer_changed_connection.disconnect();
-// g_signal_handlers_disconnect_by_func(_desktop, (gpointer)&detach, this);
- }
- _desktop = desktop;
- if (_desktop) {
- // TODO we need a different signal for this, really..s
-// _desktop_shutdown_connection = _desktop->connectShutdown(
-// 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)
- );
- _selectLayer(_desktop->currentLayer());
- }
-}
-
-namespace {
-
-class is_layer {
-public:
- is_layer(SPDesktop *desktop) : _desktop(desktop) {}
- bool operator()(SPObject &object) const {
- return _desktop->isLayer(&object);
- }
-private:
- SPDesktop *_desktop;
-};
-
-class column_matches_object {
-public:
- column_matches_object(Gtk::TreeModelColumn<SPObject *> const &column,
- SPObject &object)
- : _column(column), _object(object) {}
- bool operator()(Gtk::TreeModel::const_iterator const &iter) const {
- SPObject *current=(*iter)[_column];
- return current == &_object;
- }
-private:
- Gtk::TreeModelColumn<SPObject *> const &_column;
- SPObject &_object;
-};
-
-}
-
-/** Selects the given layer in the dropdown selector.
- */
-void LayerSelector::_selectLayer(SPObject *layer) {
- using Inkscape::Util::List;
- using Inkscape::Util::cons;
- using Inkscape::Util::reverse_list;
-
- _selection_changed_connection.block();
-
- while (!_layer_model->children().empty()) {
- Gtk::ListStore::iterator first_row(_layer_model->children().begin());
- _destroyEntry(first_row);
- _layer_model->erase(first_row);
- }
-
- SPObject *root=_desktop->currentRoot();
-
- if (_layer) {
- sp_object_unref(_layer, NULL);
- _layer = NULL;
- }
-
- if (layer) {
- List<SPObject &> hierarchy=reverse_list<SPObject::ParentIterator>(layer, root);
- if ( layer == root ) {
- _buildEntries(0, cons(*root, hierarchy));
- } else if (hierarchy) {
- _buildSiblingEntries(0, *root, hierarchy);
- }
-
- Gtk::TreeIter row(
- std::find_if(
- _layer_model->children().begin(),
- _layer_model->children().end(),
- column_matches_object(_model_columns.object, *layer)
- )
- );
- if ( row != _layer_model->children().end() ) {
- _selector.set_active(row);
- }
-
- _layer = layer;
- sp_object_ref(_layer, NULL);
- }
-
- if ( !layer || layer == root ) {
- _visibility_toggle.set_sensitive(false);
- _visibility_toggle.set_active(false);
- _lock_toggle.set_sensitive(false);
- _lock_toggle.set_active(false);
- } else {
- _visibility_toggle.set_sensitive(true);
- _visibility_toggle.set_active(( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isHidden() : false ));
- _lock_toggle.set_sensitive(true);
- _lock_toggle.set_active(( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false ));
- }
-
- _selection_changed_connection.unblock();
-}
-
-/** Sets the current desktop layer to the actively selected layer.
- */
-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();
-
- _desktop->layer_manager->setCurrentLayer(layer);
-
- _layer_changed_connection.unblock();
-
- _selectLayer(_desktop->currentLayer());
- }
- if (_desktop && _desktop->canvas) {
- gtk_widget_grab_focus (GTK_WIDGET(_desktop->canvas));
- }
-}
-
-/** Creates rows in the _layer_model data structure for each item
- * in \a hierarchy, to a given \a depth.
- */
-void LayerSelector::_buildEntries(unsigned depth,
- Inkscape::Util::List<SPObject &> hierarchy)
-{
- using Inkscape::Util::List;
- using Inkscape::Util::rest;
-
- _buildEntry(depth, *hierarchy);
-
- List<SPObject &> remainder=rest(hierarchy);
- if (remainder) {
- _buildEntries(depth+1, remainder);
- } else {
- _buildSiblingEntries(depth+1, *hierarchy, remainder);
- }
-}
-
-/** Creates entries in the _layer_model data structure for
- * all siblings of the first child in \a parent.
- */
-void LayerSelector::_buildSiblingEntries(
- unsigned depth, SPObject &parent,
- Inkscape::Util::List<SPObject &> hierarchy
-) {
- using Inkscape::Util::List;
- using Inkscape::Util::rest;
- using Inkscape::Util::reverse_list_in_place;
- using Inkscape::Util::filter_list;
-
- Inkscape::Util::List<SPObject &> siblings(
- reverse_list_in_place(
- filter_list<SPObject::SiblingIterator>(
- is_layer(_desktop), parent.firstChild(), NULL
- )
- )
- );
-
- SPObject *layer( hierarchy ? &*hierarchy : NULL );
-
- while (siblings) {
- _buildEntry(depth, *siblings);
- if ( &*siblings == layer ) {
- _buildSiblingEntries(depth+1, *layer, rest(hierarchy));
- }
- ++siblings;
- }
-}
-
-namespace {
-
-struct Callbacks {
- sigc::slot<void> update_row;
- sigc::slot<void> update_list;
-};
-
-void attribute_changed(Inkscape::XML::Node */*repr*/, gchar const *name,
- gchar const */*old_value*/, gchar const */*new_value*/,
- bool /*is_interactive*/, void *data)
-{
- if ( !std::strcmp(name, "inkscape:groupmode") ) {
- reinterpret_cast<Callbacks *>(data)->update_list();
- } else {
- reinterpret_cast<Callbacks *>(data)->update_row();
- }
-}
-
-void node_added(Inkscape::XML::Node */*parent*/, Inkscape::XML::Node *child, Inkscape::XML::Node */*ref*/, void *data) {
- gchar const *mode=child->attribute("inkscape:groupmode");
- if ( mode && !std::strcmp(mode, "layer") ) {
- reinterpret_cast<Callbacks *>(data)->update_list();
- }
-}
-
-void node_removed(Inkscape::XML::Node */*parent*/, Inkscape::XML::Node *child, Inkscape::XML::Node */*ref*/, void *data) {
- gchar const *mode=child->attribute("inkscape:groupmode");
- if ( mode && !std::strcmp(mode, "layer") ) {
- reinterpret_cast<Callbacks *>(data)->update_list();
- }
-}
-
-void node_reordered(Inkscape::XML::Node */*parent*/, Inkscape::XML::Node *child,
- Inkscape::XML::Node */*old_ref*/, Inkscape::XML::Node */*new_ref*/,
- void *data)
-{
- gchar const *mode=child->attribute("inkscape:groupmode");
- if ( mode && !std::strcmp(mode, "layer") ) {
- reinterpret_cast<Callbacks *>(data)->update_list();
- }
-}
-
-void update_row_for_object(SPObject *object,
- Gtk::TreeModelColumn<SPObject *> const &column,
- Glib::RefPtr<Gtk::ListStore> const &model)
-{
- Gtk::TreeIter row(
- std::find_if(
- model->children().begin(),
- model->children().end(),
- column_matches_object(column, *object)
- )
- );
- if ( row != model->children().end() ) {
- model->row_changed(model->get_path(row), row);
- }
-}
-
-void rebuild_all_rows(sigc::slot<void, SPObject *> rebuild, SPDesktop *desktop)
-{
- rebuild(desktop->currentLayer());
-}
-
-}
-
-void LayerSelector::_protectUpdate(sigc::slot<void> slot) {
- bool visibility_blocked=_visibility_toggled_connection.blocked();
- bool lock_blocked=_lock_toggled_connection.blocked();
- _visibility_toggled_connection.block(true);
- _lock_toggled_connection.block(true);
- slot();
-
- SPObject *layer = _desktop ? _desktop->currentLayer() : 0;
- if ( layer ) {
- bool wantedValue = ( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false );
- if ( _lock_toggle.get_active() != wantedValue ) {
- _lock_toggle.set_active( wantedValue );
- }
- wantedValue = ( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isHidden() : false );
- if ( _visibility_toggle.get_active() != wantedValue ) {
- _visibility_toggle.set_active( wantedValue );
- }
- }
- _visibility_toggled_connection.block(visibility_blocked);
- _lock_toggled_connection.block(lock_blocked);
-}
-
-/** Builds and appends a row in the layer model object.
- */
-void LayerSelector::_buildEntry(unsigned depth, SPObject &object) {
- Inkscape::XML::NodeEventVector *vector;
-
- Callbacks *callbacks=new Callbacks();
-
- callbacks->update_row = sigc::bind(
- sigc::mem_fun(*this, &LayerSelector::_protectUpdate),
- sigc::bind(
- sigc::ptr_fun(&update_row_for_object),
- &object, _model_columns.object, _layer_model
- )
- );
-
- SPObject *layer=_desktop->currentLayer();
- if ( &object == layer || &object == SP_OBJECT_PARENT(layer) ) {
- callbacks->update_list = sigc::bind(
- sigc::mem_fun(*this, &LayerSelector::_protectUpdate),
- sigc::bind(
- sigc::ptr_fun(&rebuild_all_rows),
- sigc::mem_fun(*this, &LayerSelector::_selectLayer),
- _desktop
- )
- );
-
- Inkscape::XML::NodeEventVector events = {
- &node_added,
- &node_removed,
- &attribute_changed,
- NULL,
- &node_reordered
- };
-
- vector = new Inkscape::XML::NodeEventVector(events);
- } else {
- Inkscape::XML::NodeEventVector events = {
- NULL,
- NULL,
- &attribute_changed,
- NULL,
- NULL
- };
-
- vector = new Inkscape::XML::NodeEventVector(events);
- }
-
- Gtk::ListStore::iterator row(_layer_model->append());
-
- row->set_value(_model_columns.depth, depth);
-
- sp_object_ref(&object, NULL);
- row->set_value(_model_columns.object, &object);
-
- Inkscape::GC::anchor(SP_OBJECT_REPR(&object));
- row->set_value(_model_columns.repr, SP_OBJECT_REPR(&object));
-
- row->set_value(_model_columns.callbacks, reinterpret_cast<void *>(callbacks));
-
- sp_repr_add_listener(SP_OBJECT_REPR(&object), vector, callbacks);
-}
-
-/** Removes a row from the _model_columns object, disconnecting listeners
- * on the slot.
- */
-void LayerSelector::_destroyEntry(Gtk::ListStore::iterator const &row) {
- Callbacks *callbacks=reinterpret_cast<Callbacks *>(row->get_value(_model_columns.callbacks));
- SPObject *object=row->get_value(_model_columns.object);
- if (object) {
- sp_object_unref(object, NULL);
- }
- Inkscape::XML::Node *repr=row->get_value(_model_columns.repr);
- if (repr) {
- sp_repr_remove_listener_by_data(repr, callbacks);
- Inkscape::GC::release(repr);
- }
- delete callbacks;
-}
-
-/** Formats the label for a given layer row
- */
-void LayerSelector::_prepareLabelRenderer(
- Gtk::TreeModel::const_iterator const &row
-) {
- unsigned depth=(*row)[_model_columns.depth];
- SPObject *object=(*row)[_model_columns.object];
- bool label_defaulted(false);
-
- // TODO: when the currently selected row is removed,
- // (or before one has been selected) something appears to
- // "invent" an iterator with null data and try to render it;
- // where does it come from, and how can we avoid it?
- if ( object && SP_OBJECT_REPR(object) ) {
- SPObject *layer=( _desktop ? _desktop->currentLayer() : NULL );
- SPObject *root=( _desktop ? _desktop->currentRoot() : NULL );
-
- bool isancestor = !( (layer && (SP_OBJECT_PARENT(object) == SP_OBJECT_PARENT(layer))) || ((layer == root) && (SP_OBJECT_PARENT(object) == root)));
-
- bool iscurrent = ( object == layer && object != root );
-
- gchar *format = g_strdup_printf (
- "<span size=\"smaller\" %s><tt>%*s%s</tt>%s%s%s%%s%s%s%s</span>",
- ( _desktop && _desktop->itemIsHidden (SP_ITEM(object)) ? "foreground=\"gray50\"" : "" ),
- depth, "", ( iscurrent ? "•" : " " ),
- ( iscurrent ? "<b>" : "" ),
- ( SP_ITEM(object)->isLocked() ? "[" : "" ),
- ( isancestor ? "<small>" : "" ),
- ( isancestor ? "</small>" : "" ),
- ( SP_ITEM(object)->isLocked() ? "]" : "" ),
- ( iscurrent ? "</b>" : "" )
- );
-
- gchar const *label;
- if ( object != root ) {
- label = object->label();
- if (!label) {
- label = object->defaultLabel();
- label_defaulted = true;
- }
- } else {
- label = _("(root)");
- }
-
- gchar *text = g_markup_printf_escaped(format, label);
- _label_renderer.property_markup() = text;
- g_free(text);
- g_free(format);
- } else {
- _label_renderer.property_markup() = "<small> </small>";
- }
-
- _label_renderer.property_ypad() = 1;
- _label_renderer.property_style() = ( label_defaulted ?
- Pango::STYLE_ITALIC :
- Pango::STYLE_NORMAL );
-}
-
-void LayerSelector::_lockLayer(bool lock) {
- if ( _layer && SP_IS_ITEM(_layer) ) {
- SP_ITEM(_layer)->setLocked(lock);
- sp_document_done(sp_desktop_document(_desktop), SP_VERB_NONE,
- lock? _("Lock layer") : _("Unlock layer"));
- }
-}
-
-void LayerSelector::_hideLayer(bool hide) {
- if ( _layer && SP_IS_ITEM(_layer) ) {
- SP_ITEM(_layer)->setHidden(hide);
- sp_document_done(sp_desktop_document(_desktop), SP_VERB_NONE,
- hide? _("Hide layer") : _("Unhide layer"));
- }
-}
-
-}
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/layer-selector.h b/src/widgets/layer-selector.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Inkscape::Widgets::LayerSelector - layer selector widget
- *
- * Authors:
- * MenTaLguY <mental@rydia.net>
- *
- * Copyright (C) 2004 MenTaLguY
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_INKSCAPE_WIDGETS_LAYER_SELECTOR
-#define SEEN_INKSCAPE_WIDGETS_LAYER_SELECTOR
-
-#include <gtkmm/box.h>
-#include <gtkmm/combobox.h>
-#include <gtkmm/togglebutton.h>
-#include <gtkmm/tooltips.h>
-#include <gtkmm/cellrenderertext.h>
-#include <gtkmm/treemodel.h>
-#include <gtkmm/liststore.h>
-#include <sigc++/slot.h>
-#include "util/list.h"
-
-class SPDesktop;
-class SPDocument;
-class SPObject;
-namespace Inkscape {
-namespace XML {
-class Node;
-}
-}
-
-
-namespace Inkscape {
-namespace Widgets {
-
-class DocumentTreeModel;
-
-class LayerSelector : public Gtk::HBox {
-public:
- LayerSelector(SPDesktop *desktop = NULL);
- ~LayerSelector();
-
- SPDesktop *desktop() { return _desktop; }
- void setDesktop(SPDesktop *desktop);
-
-private:
- class LayerModelColumns : public Gtk::TreeModel::ColumnRecord {
- public:
- Gtk::TreeModelColumn<unsigned> depth;
- Gtk::TreeModelColumn<SPObject *> object;
- Gtk::TreeModelColumn<Inkscape::XML::Node *> repr;
- Gtk::TreeModelColumn<void *> callbacks;
-
- LayerModelColumns() {
- add(depth); add(object); add(repr); add(callbacks);
- }
- };
-
- SPDesktop *_desktop;
-
- Gtk::Tooltips _tooltips;
- Gtk::ComboBox _selector;
- Gtk::ToggleButton _visibility_toggle;
- Gtk::ToggleButton _lock_toggle;
-
- LayerModelColumns _model_columns;
- Gtk::CellRendererText _label_renderer;
- Glib::RefPtr<Gtk::ListStore> _layer_model;
-
-// sigc::connection _desktop_shutdown_connection;
- sigc::connection _layer_changed_connection;
- sigc::connection _selection_changed_connection;
- sigc::connection _visibility_toggled_connection;
- sigc::connection _lock_toggled_connection;
-
- SPObject *_layer;
-
- void _selectLayer(SPObject *layer);
- void _setDesktopLayer();
-
- void _buildEntry(unsigned depth, SPObject &object);
- void _buildEntries(unsigned depth,
- Inkscape::Util::List<SPObject &> hierarchy);
- void _buildSiblingEntries(unsigned depth,
- SPObject &parent,
- Inkscape::Util::List<SPObject &> hierarchy);
- void _protectUpdate(sigc::slot<void> slot);
- void _destroyEntry(Gtk::ListStore::iterator const &row);
- void _hideLayer(bool hide);
- void _lockLayer(bool lock);
-
- void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row);
-};
-
-}
-}
-
-#endif
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/sp-attribute-widget.cpp b/src/widgets/sp-attribute-widget.cpp
--- /dev/null
@@ -0,0 +1,790 @@
+/** @file
+ * @brief Widget that listens and modifies repr attributes
+ */
+/* Authors:
+ * Lauris Kaplinski <lauris@ximian.com>
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtk/gtktable.h>
+#include <gtk/gtklabel.h>
+#include "xml/repr.h"
+#include "macros.h"
+#include "document.h"
+#include "sp-object.h"
+#include <glibmm/i18n.h>
+
+#include <sigc++/functors/ptr_fun.h>
+#include <sigc++/adaptors/bind.h>
+
+#include "sp-attribute-widget.h"
+
+static void sp_attribute_widget_class_init (SPAttributeWidgetClass *klass);
+static void sp_attribute_widget_init (SPAttributeWidget *widget);
+static void sp_attribute_widget_destroy (GtkObject *object);
+
+static void sp_attribute_widget_changed (GtkEditable *editable);
+
+static void sp_attribute_widget_object_modified ( SPObject *object,
+ guint flags,
+ SPAttributeWidget *spaw );
+static void sp_attribute_widget_object_release ( SPObject *object,
+ SPAttributeWidget *spaw );
+
+static GtkEntryClass *parent_class;
+
+
+
+
+GType sp_attribute_widget_get_type(void)
+{
+ static GtkType type = 0;
+ if (!type) {
+ GTypeInfo info = {
+ sizeof(SPAttributeWidgetClass),
+ 0, // base_init
+ 0, // base_finalize
+ (GClassInitFunc)sp_attribute_widget_class_init,
+ 0, // class_finalize
+ 0, // class_data
+ sizeof(SPAttributeWidget),
+ 0, // n_preallocs
+ (GInstanceInitFunc)sp_attribute_widget_init,
+ 0 // value_table
+ };
+ type = g_type_register_static(GTK_TYPE_ENTRY, "SPAttributeWidget", &info, static_cast<GTypeFlags>(0));
+ }
+ return type;
+} // end of sp_attribute_widget_get_type()
+
+
+
+static void
+sp_attribute_widget_class_init (SPAttributeWidgetClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkEditableClass *editable_class;
+
+ object_class = GTK_OBJECT_CLASS (klass);
+ widget_class = GTK_WIDGET_CLASS (klass);
+ editable_class = GTK_EDITABLE_CLASS (klass);
+
+ parent_class = (GtkEntryClass*)gtk_type_class (GTK_TYPE_ENTRY);
+
+ object_class->destroy = sp_attribute_widget_destroy;
+
+ editable_class->changed = sp_attribute_widget_changed;
+
+} // end of sp_attribute_widget_class_init()
+
+
+
+static void
+sp_attribute_widget_init (SPAttributeWidget *spaw)
+{
+ spaw->blocked = FALSE;
+ spaw->hasobj = FALSE;
+
+ spaw->src.object = NULL;
+
+ spaw->attribute = NULL;
+
+ new (&spaw->modified_connection) sigc::connection();
+ new (&spaw->release_connection) sigc::connection();
+}
+
+
+
+static void
+sp_attribute_widget_destroy (GtkObject *object)
+{
+
+ SPAttributeWidget *spaw;
+
+ spaw = SP_ATTRIBUTE_WIDGET (object);
+
+ if (spaw->attribute) {
+ g_free (spaw->attribute);
+ spaw->attribute = NULL;
+ }
+
+
+ if (spaw->hasobj) {
+
+ if (spaw->src.object) {
+ spaw->modified_connection.disconnect();
+ spaw->release_connection.disconnect();
+ spaw->src.object = NULL;
+ }
+ } else {
+
+ if (spaw->src.repr) {
+ spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
+ }
+ } // end of if()
+
+ spaw->modified_connection.~connection();
+ spaw->release_connection.~connection();
+
+ ((GtkObjectClass *) parent_class)->destroy (object);
+
+}
+
+
+
+static void
+sp_attribute_widget_changed (GtkEditable *editable)
+{
+
+ SPAttributeWidget *spaw;
+
+ spaw = SP_ATTRIBUTE_WIDGET (editable);
+
+ if (!spaw->blocked) {
+
+ const gchar *text;
+ spaw->blocked = TRUE;
+ text = gtk_entry_get_text (GTK_ENTRY (spaw));
+ if (!*text)
+ text = NULL;
+
+ if (spaw->hasobj && spaw->src.object) {
+
+ SP_OBJECT_REPR (spaw->src.object)->setAttribute(spaw->attribute, text, false);
+ sp_document_done (SP_OBJECT_DOCUMENT (spaw->src.object), SP_VERB_NONE,
+ _("Set attribute"));
+
+ } else if (spaw->src.repr) {
+
+ spaw->src.repr->setAttribute(spaw->attribute, text, false);
+ /* TODO: Warning! Undo will not be flushed in given case */
+ }
+ spaw->blocked = FALSE;
+ }
+
+} // end of sp_attribute_widget_changed()
+
+
+
+GtkWidget *
+sp_attribute_widget_new ( SPObject *object, const gchar *attribute )
+{
+ SPAttributeWidget *spaw;
+
+ g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL);
+ g_return_val_if_fail (!object || attribute, NULL);
+
+ spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET);
+
+ sp_attribute_widget_set_object (spaw, object, attribute);
+
+ return GTK_WIDGET (spaw);
+
+} // end of sp_attribute_widget_new()
+
+
+
+GtkWidget *
+sp_attribute_widget_new_repr ( Inkscape::XML::Node *repr, const gchar *attribute )
+{
+ SPAttributeWidget *spaw;
+
+ spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET);
+
+ sp_attribute_widget_set_repr (spaw, repr, attribute);
+
+ return GTK_WIDGET (spaw);
+}
+
+
+
+void
+sp_attribute_widget_set_object ( SPAttributeWidget *spaw,
+ SPObject *object,
+ const gchar *attribute )
+{
+
+ g_return_if_fail (spaw != NULL);
+ g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw));
+ g_return_if_fail (!object || SP_IS_OBJECT (object));
+ g_return_if_fail (!object || attribute);
+ g_return_if_fail (attribute != NULL);
+
+ if (spaw->attribute) {
+ g_free (spaw->attribute);
+ spaw->attribute = NULL;
+ }
+
+ if (spaw->hasobj) {
+
+ if (spaw->src.object) {
+ spaw->modified_connection.disconnect();
+ spaw->release_connection.disconnect();
+ spaw->src.object = NULL;
+ }
+ } else {
+
+ if (spaw->src.repr) {
+ spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
+ }
+ }
+
+ spaw->hasobj = TRUE;
+
+ if (object) {
+ const gchar *val;
+
+ spaw->blocked = TRUE;
+ spaw->src.object = object;
+
+ spaw->modified_connection = object->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_attribute_widget_object_modified), spaw));
+ spaw->release_connection = object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_attribute_widget_object_release), spaw));
+
+ spaw->attribute = g_strdup (attribute);
+
+ val = SP_OBJECT_REPR (object)->attribute(attribute);
+ gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) "");
+ spaw->blocked = FALSE;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.object != NULL));
+
+} // end of sp_attribute_widget_set_object()
+
+
+
+void
+sp_attribute_widget_set_repr ( SPAttributeWidget *spaw,
+ Inkscape::XML::Node *repr,
+ const gchar *attribute )
+{
+
+ g_return_if_fail (spaw != NULL);
+ g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw));
+ g_return_if_fail (attribute != NULL);
+
+ if (spaw->attribute) {
+ g_free (spaw->attribute);
+ spaw->attribute = NULL;
+ }
+
+ if (spaw->hasobj) {
+
+ if (spaw->src.object) {
+ spaw->modified_connection.disconnect();
+ spaw->release_connection.disconnect();
+ spaw->src.object = NULL;
+ }
+ } else {
+
+ if (spaw->src.repr) {
+ spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
+ }
+ }
+
+ spaw->hasobj = FALSE;
+
+ if (repr) {
+ const gchar *val;
+
+ spaw->blocked = TRUE;
+ spaw->src.repr = Inkscape::GC::anchor(repr);
+ spaw->attribute = g_strdup (attribute);
+
+ val = repr->attribute(attribute);
+ gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) "");
+ spaw->blocked = FALSE;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.repr != NULL));
+
+} // end of sp_attribute_widget_set_repr()
+
+
+
+static void
+sp_attribute_widget_object_modified ( SPObject */*object*/,
+ guint flags,
+ SPAttributeWidget *spaw )
+{
+
+ if (flags && SP_OBJECT_MODIFIED_FLAG) {
+
+ const gchar *val, *text;
+ val = SP_OBJECT_REPR (spaw->src.object)->attribute(spaw->attribute);
+ text = gtk_entry_get_text (GTK_ENTRY (spaw));
+
+ if (val || text) {
+
+ if (!val || !text || strcmp (val, text)) {
+ /* We are different */
+ spaw->blocked = TRUE;
+ gtk_entry_set_text ( GTK_ENTRY (spaw),
+ val ? val : (const gchar *) "");
+ spaw->blocked = FALSE;
+ } // end of if()
+
+ } // end of if()
+
+ } //end of if()
+
+} // end of sp_attribute_widget_object_modified()
+
+
+
+static void
+sp_attribute_widget_object_release ( SPObject */*object*/,
+ SPAttributeWidget *spaw )
+{
+ sp_attribute_widget_set_object (spaw, NULL, NULL);
+}
+
+
+
+/* SPAttributeTable */
+
+static void sp_attribute_table_class_init (SPAttributeTableClass *klass);
+static void sp_attribute_table_init (SPAttributeTable *widget);
+static void sp_attribute_table_destroy (GtkObject *object);
+
+static void sp_attribute_table_object_modified (SPObject *object, guint flags, SPAttributeTable *spaw);
+static void sp_attribute_table_object_release (SPObject *object, SPAttributeTable *spaw);
+static void sp_attribute_table_entry_changed (GtkEditable *editable, SPAttributeTable *spat);
+
+static GtkVBoxClass *table_parent_class;
+
+
+
+
+GType sp_attribute_table_get_type(void)
+{
+ static GtkType type = 0;
+ if (!type) {
+ GTypeInfo info = {
+ sizeof(SPAttributeTableClass),
+ 0, // base_init
+ 0, // base_finalize
+ (GClassInitFunc)sp_attribute_table_class_init,
+ 0, // class_finalize
+ 0, // class_data
+ sizeof(SPAttributeTable),
+ 0, // n_preallocs
+ (GInstanceInitFunc)sp_attribute_table_init,
+ 0 // value_table
+ };
+ type = g_type_register_static(GTK_TYPE_VBOX, "SPAttributeTable", &info, static_cast<GTypeFlags>(0));
+ }
+ return type;
+} // end of sp_attribute_table_get_type()
+
+
+
+static void
+sp_attribute_table_class_init (SPAttributeTableClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = GTK_OBJECT_CLASS (klass);
+ widget_class = GTK_WIDGET_CLASS (klass);
+
+ table_parent_class = (GtkVBoxClass*)gtk_type_class (GTK_TYPE_VBOX);
+
+ object_class->destroy = sp_attribute_table_destroy;
+
+} // end of sp_attribute_table_class_init()
+
+
+
+static void
+sp_attribute_table_init ( SPAttributeTable *spat )
+{
+ spat->blocked = FALSE;
+ spat->hasobj = FALSE;
+ spat->table = NULL;
+ spat->src.object = NULL;
+ spat->num_attr = 0;
+ spat->attributes = NULL;
+ spat->entries = NULL;
+
+ new (&spat->modified_connection) sigc::connection();
+ new (&spat->release_connection) sigc::connection();
+}
+
+static void
+sp_attribute_table_destroy ( GtkObject *object )
+{
+ SPAttributeTable *spat;
+
+ spat = SP_ATTRIBUTE_TABLE (object);
+
+ if (spat->attributes) {
+ gint i;
+ for (i = 0; i < spat->num_attr; i++) {
+ g_free (spat->attributes[i]);
+ }
+ g_free (spat->attributes);
+ spat->attributes = NULL;
+ }
+
+ if (spat->hasobj) {
+
+ if (spat->src.object) {
+ spat->modified_connection.disconnect();
+ spat->release_connection.disconnect();
+ spat->src.object = NULL;
+ }
+ } else {
+ if (spat->src.repr) {
+ spat->src.repr = Inkscape::GC::release(spat->src.repr);
+ }
+ } // end of if()
+
+ spat->modified_connection.~connection();
+ spat->release_connection.~connection();
+
+ if (spat->entries) {
+ g_free (spat->entries);
+ spat->entries = NULL;
+ }
+
+ spat->table = NULL;
+
+ if (((GtkObjectClass *) table_parent_class)->destroy) {
+ (* ((GtkObjectClass *) table_parent_class)->destroy) (object);
+ }
+
+} // end of sp_attribute_table_destroy()
+
+
+GtkWidget *
+sp_attribute_table_new ( SPObject *object,
+ gint num_attr,
+ const gchar **labels,
+ const gchar **attributes )
+{
+ SPAttributeTable *spat;
+
+ g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL);
+ g_return_val_if_fail (!object || (num_attr > 0), NULL);
+ g_return_val_if_fail (!num_attr || (labels && attributes), NULL);
+
+ spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE);
+
+ sp_attribute_table_set_object (spat, object, num_attr, labels, attributes);
+
+ return GTK_WIDGET (spat);
+
+} // end of sp_attribute_table_new()
+
+
+
+GtkWidget *
+sp_attribute_table_new_repr ( Inkscape::XML::Node *repr,
+ gint num_attr,
+ const gchar **labels,
+ const gchar **attributes )
+{
+ SPAttributeTable *spat;
+
+ g_return_val_if_fail (!num_attr || (labels && attributes), NULL);
+
+ spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE);
+
+ sp_attribute_table_set_repr (spat, repr, num_attr, labels, attributes);
+
+ return GTK_WIDGET (spat);
+
+} // end of sp_attribute_table_new_repr()
+
+
+
+#define XPAD 4
+#define YPAD 0
+
+void
+sp_attribute_table_set_object ( SPAttributeTable *spat,
+ SPObject *object,
+ gint num_attr,
+ const gchar **labels,
+ const gchar **attributes )
+{
+
+ g_return_if_fail (spat != NULL);
+ g_return_if_fail (SP_IS_ATTRIBUTE_TABLE (spat));
+ g_return_if_fail (!object || SP_IS_OBJECT (object));
+ g_return_if_fail (!object || (num_attr > 0));
+ g_return_if_fail (!num_attr || (labels && attributes));
+
+ if (spat->table) {
+ gtk_widget_destroy (spat->table);
+ spat->table = NULL;
+ }
+
+ if (spat->attributes) {
+ gint i;
+ for (i = 0; i < spat->num_attr; i++) {
+ g_free (spat->attributes[i]);
+ }
+ g_free (spat->attributes);
+ spat->attributes = NULL;
+ }
+
+ if (spat->entries) {
+ g_free (spat->entries);
+ spat->entries = NULL;
+ }
+
+ if (spat->hasobj) {
+ if (spat->src.object) {
+ spat->modified_connection.disconnect();
+ spat->release_connection.disconnect();
+ spat->src.object = NULL;
+ }
+ } else {
+ if (spat->src.repr) {
+ spat->src.repr = Inkscape::GC::release(spat->src.repr);
+ }
+ }
+
+ spat->hasobj = TRUE;
+
+ if (object) {
+ gint i;
+
+ spat->blocked = TRUE;
+
+ /* Set up object */
+ spat->src.object = object;
+ spat->num_attr = num_attr;
+
+ spat->modified_connection = object->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_attribute_table_object_modified), spat));
+ spat->release_connection = object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_attribute_table_object_release), spat));
+
+ /* Create table */
+ spat->table = gtk_table_new (num_attr, 2, FALSE);
+ gtk_container_add (GTK_CONTAINER (spat), spat->table);
+ /* Arrays */
+ spat->attributes = g_new0 (gchar *, num_attr);
+ spat->entries = g_new0 (GtkWidget *, num_attr);
+ /* Fill rows */
+ for (i = 0; i < num_attr; i++) {
+ GtkWidget *w;
+ const gchar *val;
+
+ spat->attributes[i] = g_strdup (attributes[i]);
+ w = gtk_label_new (_(labels[i]));
+ gtk_widget_show (w);
+ gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
+ gtk_table_attach ( GTK_TABLE (spat->table), w, 0, 1, i, i + 1,
+ GTK_FILL,
+ (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ XPAD, YPAD );
+ w = gtk_entry_new ();
+ gtk_widget_show (w);
+ val = SP_OBJECT_REPR (object)->attribute(attributes[i]);
+ gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) "");
+ gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1,
+ (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ XPAD, YPAD );
+ spat->entries[i] = w;
+ g_signal_connect ( G_OBJECT (w), "changed",
+ G_CALLBACK (sp_attribute_table_entry_changed),
+ spat );
+ }
+ /* Show table */
+ gtk_widget_show (spat->table);
+
+ spat->blocked = FALSE;
+ }
+
+ gtk_widget_set_sensitive ( GTK_WIDGET (spat),
+ (spat->src.object != NULL) );
+
+} // end of sp_attribute_table_set_object()
+
+
+
+void
+sp_attribute_table_set_repr ( SPAttributeTable *spat,
+ Inkscape::XML::Node *repr,
+ gint num_attr,
+ const gchar **labels,
+ const gchar **attributes )
+{
+ g_return_if_fail (spat != NULL);
+ g_return_if_fail (SP_IS_ATTRIBUTE_TABLE (spat));
+ g_return_if_fail (!num_attr || (labels && attributes));
+
+ if (spat->table) {
+ gtk_widget_destroy (spat->table);
+ spat->table = NULL;
+ }
+
+ if (spat->attributes) {
+ gint i;
+ for (i = 0; i < spat->num_attr; i++) {
+ g_free (spat->attributes[i]);
+ }
+ g_free (spat->attributes);
+ spat->attributes = NULL;
+ }
+
+ if (spat->entries) {
+ g_free (spat->entries);
+ spat->entries = NULL;
+ }
+
+ if (spat->hasobj) {
+ if (spat->src.object) {
+ spat->modified_connection.disconnect();
+ spat->release_connection.disconnect();
+ spat->src.object = NULL;
+ }
+ } else {
+ if (spat->src.repr) {
+ spat->src.repr = Inkscape::GC::release(spat->src.repr);
+ }
+ }
+
+ spat->hasobj = FALSE;
+
+ if (repr) {
+ gint i;
+
+ spat->blocked = TRUE;
+
+ /* Set up repr */
+ spat->src.repr = Inkscape::GC::anchor(repr);
+ spat->num_attr = num_attr;
+ /* Create table */
+ spat->table = gtk_table_new (num_attr, 2, FALSE);
+ gtk_container_add (GTK_CONTAINER (spat), spat->table);
+ /* Arrays */
+ spat->attributes = g_new0 (gchar *, num_attr);
+ spat->entries = g_new0 (GtkWidget *, num_attr);
+
+ /* Fill rows */
+ for (i = 0; i < num_attr; i++) {
+ GtkWidget *w;
+ const gchar *val;
+
+ spat->attributes[i] = g_strdup (attributes[i]);
+ w = gtk_label_new (labels[i]);
+ gtk_widget_show (w);
+ gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
+ gtk_table_attach ( GTK_TABLE (spat->table), w, 0, 1, i, i + 1,
+ GTK_FILL,
+ (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ XPAD, YPAD );
+ w = gtk_entry_new ();
+ gtk_widget_show (w);
+ val = repr->attribute(attributes[i]);
+ gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) "");
+ gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1,
+ (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ XPAD, YPAD );
+ spat->entries[i] = w;
+ g_signal_connect ( G_OBJECT (w), "changed",
+ G_CALLBACK (sp_attribute_table_entry_changed),
+ spat );
+ }
+ /* Show table */
+ gtk_widget_show (spat->table);
+
+ spat->blocked = FALSE;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (spat), (spat->src.repr != NULL));
+
+} // end of sp_attribute_table_set_repr()
+
+
+
+static void
+sp_attribute_table_object_modified ( SPObject */*object*/,
+ guint flags,
+ SPAttributeTable *spat )
+{
+ if (flags && SP_OBJECT_MODIFIED_FLAG)
+ {
+ gint i;
+ for (i = 0; i < spat->num_attr; i++) {
+ const gchar *val, *text;
+ val = SP_OBJECT_REPR (spat->src.object)->attribute(spat->attributes[i]);
+ text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i]));
+ if (val || text) {
+ if (!val || !text || strcmp (val, text)) {
+ /* We are different */
+ spat->blocked = TRUE;
+ gtk_entry_set_text ( GTK_ENTRY (spat->entries[i]),
+ val ? val : (const gchar *) "");
+ spat->blocked = FALSE;
+ }
+ }
+ }
+ } // end of if()
+
+} // end of sp_attribute_table_object_modified()
+
+
+
+static void
+sp_attribute_table_object_release (SPObject */*object*/, SPAttributeTable *spat)
+{
+ sp_attribute_table_set_object (spat, NULL, 0, NULL, NULL);
+}
+
+
+
+static void
+sp_attribute_table_entry_changed ( GtkEditable *editable,
+ SPAttributeTable *spat )
+{
+ if (!spat->blocked)
+ {
+ gint i;
+ for (i = 0; i < spat->num_attr; i++) {
+
+ if (GTK_WIDGET (editable) == spat->entries[i]) {
+ const gchar *text;
+ spat->blocked = TRUE;
+ text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i]));
+
+ if (!*text)
+ text = NULL;
+
+ if (spat->hasobj && spat->src.object) {
+ SP_OBJECT_REPR (spat->src.object)->setAttribute(spat->attributes[i], text, false);
+ sp_document_done (SP_OBJECT_DOCUMENT (spat->src.object), SP_VERB_NONE,
+ _("Set attribute"));
+
+ } else if (spat->src.repr) {
+
+ spat->src.repr->setAttribute(spat->attributes[i], text, false);
+ /* TODO: Warning! Undo will not be flushed in given case */
+ }
+ spat->blocked = FALSE;
+ return;
+ }
+ }
+ g_warning ("file %s: line %d: Entry signalled change, but there is no such entry", __FILE__, __LINE__);
+ } // end of if()
+
+} // end of sp_attribute_table_entry_changed()
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/sp-attribute-widget.h b/src/widgets/sp-attribute-widget.h
--- /dev/null
@@ -0,0 +1,130 @@
+/** @file
+ * @brief Widget that listens and modifies repr attributes
+ */
+/* Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ *
+ * Copyright (C) 2002 authors
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Licensed under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_DIALOGS_SP_ATTRIBUTE_WIDGET_H
+#define SEEN_DIALOGS_SP_ATTRIBUTE_WIDGET_H
+
+#include <glib.h>
+#include <sigc++/connection.h>
+
+#define SP_TYPE_ATTRIBUTE_WIDGET (sp_attribute_widget_get_type ())
+#define SP_ATTRIBUTE_WIDGET(obj) (GTK_CHECK_CAST ((obj), SP_TYPE_ATTRIBUTE_WIDGET, SPAttributeWidget))
+#define SP_ATTRIBUTE_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), SP_TYPE_ATTRIBUTE_WIDGET, SPAttributeWidgetClass))
+#define SP_IS_ATTRIBUTE_WIDGET(obj) (GTK_CHECK_TYPE ((obj), SP_TYPE_ATTRIBUTE_WIDGET))
+#define SP_IS_ATTRIBUTE_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), SP_TYPE_ATTRIBUTE_WIDGET))
+
+#define SP_TYPE_ATTRIBUTE_TABLE (sp_attribute_table_get_type ())
+#define SP_ATTRIBUTE_TABLE(obj) (GTK_CHECK_CAST ((obj), SP_TYPE_ATTRIBUTE_TABLE, SPAttributeTable))
+#define SP_ATTRIBUTE_TABLE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), SP_TYPE_ATTRIBUTE_TABLE, SPAttributeTableClass))
+#define SP_IS_ATTRIBUTE_TABLE(obj) (GTK_CHECK_TYPE ((obj), SP_TYPE_ATTRIBUTE_TABLE))
+#define SP_IS_ATTRIBUTE_TABLE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), SP_TYPE_ATTRIBUTE_TABLE))
+
+namespace Inkscape {
+namespace XML {
+class Node;
+}
+}
+
+
+struct SPAttributeWidget;
+struct SPAttributeWidgetClass;
+
+struct SPAttributeTable;
+struct SPAttributeTableClass;
+
+#include <gtk/gtkentry.h>
+#include <gtk/gtkvbox.h>
+
+#include <forward.h>
+
+struct SPAttributeWidget {
+ GtkEntry entry;
+ guint blocked : 1;
+ guint hasobj : 1;
+ union {
+ SPObject *object;
+ Inkscape::XML::Node *repr;
+ } src;
+ gchar *attribute;
+
+ sigc::connection modified_connection;
+ sigc::connection release_connection;
+};
+
+struct SPAttributeWidgetClass {
+ GtkEntryClass entry_class;
+};
+
+GtkType sp_attribute_widget_get_type (void);
+
+GtkWidget *sp_attribute_widget_new (SPObject *object, const gchar *attribute);
+GtkWidget *sp_attribute_widget_new_repr (Inkscape::XML::Node *repr, const gchar *attribute);
+
+void sp_attribute_widget_set_object ( SPAttributeWidget *spw,
+ SPObject *object,
+ const gchar *attribute );
+void sp_attribute_widget_set_repr ( SPAttributeWidget *spw,
+ Inkscape::XML::Node *repr,
+ const gchar *attribute );
+
+/* SPAttributeTable */
+
+struct SPAttributeTable {
+ GtkVBox vbox;
+ guint blocked : 1;
+ guint hasobj : 1;
+ GtkWidget *table;
+ union {
+ SPObject *object;
+ Inkscape::XML::Node *repr;
+ } src;
+ gint num_attr;
+ gchar **attributes;
+ GtkWidget **entries;
+
+ sigc::connection modified_connection;
+ sigc::connection release_connection;
+};
+
+struct SPAttributeTableClass {
+ GtkEntryClass entry_class;
+};
+
+GtkType sp_attribute_table_get_type (void);
+
+GtkWidget *sp_attribute_table_new ( SPObject *object, gint num_attr,
+ const gchar **labels,
+ const gchar **attributes );
+GtkWidget *sp_attribute_table_new_repr ( Inkscape::XML::Node *repr, gint num_attr,
+ const gchar **labels,
+ const gchar **attributes );
+void sp_attribute_table_set_object ( SPAttributeTable *spw,
+ SPObject *object, gint num_attr,
+ const gchar **labels,
+ const gchar **attrs );
+void sp_attribute_table_set_repr ( SPAttributeTable *spw,
+ Inkscape::XML::Node *repr, gint num_attr,
+ const gchar **labels,
+ const gchar **attrs );
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp
--- /dev/null
@@ -0,0 +1,1838 @@
+/** @file
+ * @brief Stroke style dialog
+ */
+/* Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Bryce Harrington <brycehar@bryceharrington.org>
+ * bulia byak <buliabyak@users.sf.net>
+ * Maximilian Albert <maximilian.albert@gmail.com>
+ * Josh Andler <scislac@users.sf.net>
+ *
+ * Copyright (C) 2001-2005 authors
+ * Copyright (C) 2001 Ximian, Inc.
+ * Copyright (C) 2004 John Cliff
+ * Copyright (C) 2008 Maximilian Albert (gtkmm-ification)
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#define noSP_SS_VERBOSE
+
+#include <glib/gmem.h>
+#include <gtk/gtk.h>
+#include <glibmm/i18n.h>
+
+#include "desktop-handles.h"
+#include "desktop-style.h"
+#include "dialogs/dialog-events.h"
+#include "display/nr-arena.h"
+#include "display/nr-arena-item.h"
+#include "document-private.h"
+#include "gradient-chemistry.h"
+#include "helper/stock-items.h"
+#include "helper/unit-menu.h"
+#include "helper/units.h"
+#include "inkscape.h"
+#include "io/sys.h"
+#include "marker.h"
+#include "path-prefix.h"
+#include "selection.h"
+#include "sp-linear-gradient.h"
+#include "sp-namedview.h"
+#include "sp-pattern.h"
+#include "sp-radial-gradient.h"
+#include "sp-rect.h"
+#include "sp-text.h"
+#include "style.h"
+#include "svg/css-ostringstream.h"
+#include "ui/cache/svg_preview_cache.h"
+#include "ui/icon-names.h"
+#include "widgets/dash-selector.h"
+#include "widgets/icon.h"
+#include "widgets/paint-selector.h"
+#include "widgets/sp-widget.h"
+#include "widgets/spw-utilities.h"
+#include "xml/repr.h"
+
+#include "widgets/stroke-style.h"
+
+
+/* Paint */
+
+static void sp_stroke_style_paint_selection_modified (SPWidget *spw, Inkscape::Selection *selection, guint flags, SPPaintSelector *psel);
+static void sp_stroke_style_paint_selection_changed (SPWidget *spw, Inkscape::Selection *selection, SPPaintSelector *psel);
+static void sp_stroke_style_paint_update(SPWidget *spw);
+
+static void sp_stroke_style_paint_mode_changed(SPPaintSelector *psel, SPPaintSelectorMode mode, SPWidget *spw);
+static void sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw);
+static void sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw);
+
+static void sp_stroke_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw );
+static void sp_stroke_style_widget_transientize_callback(Inkscape::Application *inkscape,
+ SPDesktop *desktop,
+ SPWidget *spw );
+
+/** Marker selection option menus */
+static Gtk::OptionMenu * marker_start_menu = NULL;
+static Gtk::OptionMenu * marker_mid_menu = NULL;
+static Gtk::OptionMenu * marker_end_menu = NULL;
+
+sigc::connection marker_start_menu_connection;
+sigc::connection marker_mid_menu_connection;
+sigc::connection marker_end_menu_connection;
+
+static SPObject *ink_extract_marker_name(gchar const *n, SPDocument *doc);
+static void ink_markers_menu_update(Gtk::Container* spw, SPMarkerLoc const which);
+
+static Inkscape::UI::Cache::SvgPreview svg_preview_cache;
+
+/**
+ * Create the stroke style widget, and hook up all the signals.
+ */
+GtkWidget *
+sp_stroke_style_paint_widget_new(void)
+{
+ GtkWidget *spw, *psel;
+
+ spw = sp_widget_new_global(INKSCAPE);
+
+ psel = sp_paint_selector_new(false); // without fillrule selector
+ gtk_widget_show(psel);
+ gtk_container_add(GTK_CONTAINER(spw), psel);
+ gtk_object_set_data(GTK_OBJECT(spw), "paint-selector", psel);
+
+ gtk_signal_connect(GTK_OBJECT(spw), "modify_selection",
+ GTK_SIGNAL_FUNC(sp_stroke_style_paint_selection_modified),
+ psel);
+ gtk_signal_connect(GTK_OBJECT(spw), "change_selection",
+ GTK_SIGNAL_FUNC(sp_stroke_style_paint_selection_changed),
+ psel);
+
+ g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_stroke_style_widget_change_subselection), spw);
+
+ g_signal_connect (G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK (sp_stroke_style_widget_transientize_callback), spw );
+
+ gtk_signal_connect(GTK_OBJECT(psel), "mode_changed",
+ GTK_SIGNAL_FUNC(sp_stroke_style_paint_mode_changed),
+ spw);
+ gtk_signal_connect(GTK_OBJECT(psel), "dragged",
+ GTK_SIGNAL_FUNC(sp_stroke_style_paint_dragged),
+ spw);
+ gtk_signal_connect(GTK_OBJECT(psel), "changed",
+ GTK_SIGNAL_FUNC(sp_stroke_style_paint_changed),
+ spw);
+
+ sp_stroke_style_paint_update (SP_WIDGET(spw));
+ return spw;
+}
+
+/**
+ * On signal modified, invokes an update of the stroke style paint object.
+ */
+static void
+sp_stroke_style_paint_selection_modified( SPWidget *spw,
+ Inkscape::Selection */*selection*/,
+ guint flags,
+ SPPaintSelector */*psel*/ )
+{
+ if (flags & ( SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG |
+ SP_OBJECT_STYLE_MODIFIED_FLAG) ) {
+ sp_stroke_style_paint_update(spw);
+ }
+}
+
+
+/**
+ * On signal selection changed, invokes an update of the stroke style paint object.
+ */
+static void
+sp_stroke_style_paint_selection_changed( SPWidget *spw,
+ Inkscape::Selection */*selection*/,
+ SPPaintSelector */*psel*/ )
+{
+ sp_stroke_style_paint_update (spw);
+}
+
+
+/**
+ * On signal change subselection, invoke an update of the stroke style widget.
+ */
+static void
+sp_stroke_style_widget_change_subselection( Inkscape::Application */*inkscape*/,
+ SPDesktop */*desktop*/,
+ SPWidget *spw )
+{
+ sp_stroke_style_paint_update (spw);
+}
+
+/**
+ * Gets the active stroke style property, then sets the appropriate color, alpha, gradient,
+ * pattern, etc. for the paint-selector.
+ */
+static void
+sp_stroke_style_paint_update (SPWidget *spw)
+{
+ if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
+ return;
+ }
+
+ gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(TRUE));
+
+ SPPaintSelector *psel = SP_PAINT_SELECTOR(gtk_object_get_data(GTK_OBJECT(spw), "paint-selector"));
+
+ // create temporary style
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ // query into it
+ int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKE);
+
+ switch (result) {
+ case QUERY_STYLE_NOTHING:
+ {
+ /* No paint at all */
+ sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_EMPTY);
+ break;
+ }
+
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere in paint selector
+ case QUERY_STYLE_MULTIPLE_SAME:
+ {
+ SPPaintSelectorMode pselmode = sp_style_determine_paint_selector_mode (query, false);
+ sp_paint_selector_set_mode (psel, pselmode);
+
+ if (query->stroke.set && query->stroke.isPaintserver()) {
+
+ SPPaintServer *server = SP_STYLE_STROKE_SERVER (query);
+
+ if (SP_IS_LINEARGRADIENT (server)) {
+ SPGradient *vector = sp_gradient_get_vector (SP_GRADIENT (server), FALSE);
+ sp_paint_selector_set_gradient_linear (psel, vector);
+
+ SPLinearGradient *lg = SP_LINEARGRADIENT (server);
+ sp_paint_selector_set_gradient_properties (psel,
+ SP_GRADIENT_UNITS (lg),
+ SP_GRADIENT_SPREAD (lg));
+ } else if (SP_IS_RADIALGRADIENT (server)) {
+ SPGradient *vector = sp_gradient_get_vector (SP_GRADIENT (server), FALSE);
+ sp_paint_selector_set_gradient_radial (psel, vector);
+
+ SPRadialGradient *rg = SP_RADIALGRADIENT (server);
+ sp_paint_selector_set_gradient_properties (psel,
+ SP_GRADIENT_UNITS (rg),
+ SP_GRADIENT_SPREAD (rg));
+ } else if (SP_IS_PATTERN (server)) {
+ SPPattern *pat = pattern_getroot (SP_PATTERN (server));
+ sp_update_pattern_list (psel, pat);
+ }
+ } else if (query->stroke.set && query->stroke.isColor()) {
+ sp_paint_selector_set_color_alpha (psel, &query->stroke.value.color, SP_SCALE24_TO_FLOAT (query->stroke_opacity.value));
+
+ }
+ break;
+ }
+
+ case QUERY_STYLE_MULTIPLE_DIFFERENT:
+ {
+ sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_MULTIPLE);
+ break;
+ }
+ }
+
+ sp_style_unref(query);
+
+ gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(FALSE));
+}
+
+/**
+ * When the mode is changed, invoke a regular changed handler.
+ */
+static void
+sp_stroke_style_paint_mode_changed( SPPaintSelector *psel,
+ SPPaintSelectorMode /*mode*/,
+ SPWidget *spw )
+{
+ if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
+ return;
+ }
+
+ /* TODO: Does this work?
+ * Not really, here we have to get old color back from object
+ * Instead of relying on paint widget having meaningful colors set
+ */
+ sp_stroke_style_paint_changed(psel, spw);
+}
+
+static gchar const *const undo_label_1 = "stroke:flatcolor:1";
+static gchar const *const undo_label_2 = "stroke:flatcolor:2";
+static gchar const *undo_label = undo_label_1;
+
+/**
+ * When a drag callback occurs on a paint selector object, if it is a RGB or CMYK
+ * color mode, then set the stroke opacity to psel's flat color.
+ */
+static void
+sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw)
+{
+ if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
+ return;
+ }
+
+ switch (psel->mode) {
+ case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
+ case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
+ {
+ sp_paint_selector_set_flat_color (psel, SP_ACTIVE_DESKTOP, "stroke", "stroke-opacity");
+ sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set stroke color"));
+ break;
+ }
+
+ default:
+ g_warning( "file %s: line %d: Paint %d should not emit 'dragged'",
+ __FILE__, __LINE__, psel->mode);
+ break;
+ }
+}
+
+/**
+ * When the stroke style's paint settings change, this handler updates the
+ * repr's stroke css style and applies the style to relevant drawing items.
+ */
+static void
+sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
+{
+ if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
+ return;
+ }
+ g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE));
+
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDocument *document = sp_desktop_document (desktop);
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
+
+ GSList const *items = selection->itemList();
+
+ switch (psel->mode) {
+ case SP_PAINT_SELECTOR_MODE_EMPTY:
+ // This should not happen.
+ g_warning ( "file %s: line %d: Paint %d should not emit 'changed'",
+ __FILE__, __LINE__, psel->mode);
+ break;
+ case SP_PAINT_SELECTOR_MODE_MULTIPLE:
+ // This happens when you switch multiple objects with different gradients to flat color;
+ // nothing to do here.
+ break;
+
+ case SP_PAINT_SELECTOR_MODE_NONE:
+ {
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, "stroke", "none");
+
+ sp_desktop_set_style (desktop, css);
+
+ sp_repr_css_attr_unref(css);
+
+ sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Remove stroke"));
+ break;
+ }
+
+ case SP_PAINT_SELECTOR_MODE_COLOR_RGB:
+ case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
+ {
+ sp_paint_selector_set_flat_color (psel, desktop, "stroke", "stroke-opacity");
+ sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set stroke color"));
+
+ // on release, toggle undo_label so that the next drag will not be lumped with this one
+ if (undo_label == undo_label_1)
+ undo_label = undo_label_2;
+ else
+ undo_label = undo_label_1;
+
+ break;
+ }
+
+ case SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR:
+ case SP_PAINT_SELECTOR_MODE_GRADIENT_RADIAL:
+ if (items) {
+ SPGradientType const gradient_type = ( psel->mode == SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR
+ ? SP_GRADIENT_TYPE_LINEAR
+ : SP_GRADIENT_TYPE_RADIAL );
+ SPGradient *vector = sp_paint_selector_get_gradient_vector(psel);
+ if (!vector) {
+ /* No vector in paint selector should mean that we just changed mode */
+
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result = objects_query_fillstroke ((GSList *) items, query, false);
+ guint32 common_rgb = 0;
+ if (result == QUERY_STYLE_MULTIPLE_SAME) {
+ if (!query->fill.isColor()) {
+ common_rgb = sp_desktop_get_color(desktop, false);
+ } else {
+ common_rgb = query->stroke.value.color.toRGBA32( 0xff );
+ }
+ vector = sp_document_default_gradient_vector(document, common_rgb);
+ }
+ sp_style_unref(query);
+
+ for (GSList const *i = items; i != NULL; i = i->next) {
+ if (!vector) {
+ sp_item_set_gradient(SP_ITEM(i->data),
+ sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), false),
+ gradient_type, false);
+ } else {
+ sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, false);
+ }
+ }
+ } else {
+ vector = sp_gradient_ensure_vector_normalized(vector);
+ for (GSList const *i = items; i != NULL; i = i->next) {
+ SPGradient *gr = sp_item_set_gradient(SP_ITEM(i->data), vector, gradient_type, false);
+ sp_gradient_selector_attrs_to_gradient(gr, psel);
+ }
+ }
+
+ sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set gradient on stroke"));
+ }
+ break;
+
+ case SP_PAINT_SELECTOR_MODE_PATTERN:
+
+ if (items) {
+
+ SPPattern *pattern = sp_paint_selector_get_pattern (psel);
+ if (!pattern) {
+
+ /* No Pattern in paint selector should mean that we just
+ * changed mode - dont do jack.
+ */
+
+ } else {
+ Inkscape::XML::Node *patrepr = SP_OBJECT_REPR(pattern);
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar *urltext = g_strdup_printf ("url(#%s)", patrepr->attribute("id"));
+ sp_repr_css_set_property (css, "stroke", urltext);
+
+ for (GSList const *i = items; i != NULL; i = i->next) {
+ Inkscape::XML::Node *selrepr = SP_OBJECT_REPR (i->data);
+ SPObject *selobj = SP_OBJECT (i->data);
+ if (!selrepr)
+ continue;
+
+ SPStyle *style = SP_OBJECT_STYLE (selobj);
+ if (style && style->stroke.isPaintserver()) {
+ SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (selobj);
+ if (SP_IS_PATTERN (server) && pattern_getroot (SP_PATTERN(server)) == pattern)
+ // only if this object's pattern is not rooted in our selected pattern, apply
+ continue;
+ }
+
+ sp_repr_css_change_recursive (selrepr, css, "style");
+ }
+
+ sp_repr_css_attr_unref (css);
+ g_free (urltext);
+
+ } // end if
+
+ sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set pattern on stroke"));
+ } // end if
+
+ break;
+
+ case SP_PAINT_SELECTOR_MODE_UNSET:
+ if (items) {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_unset_property (css, "stroke");
+ sp_repr_css_unset_property (css, "stroke-opacity");
+ sp_repr_css_unset_property (css, "stroke-width");
+ sp_repr_css_unset_property (css, "stroke-miterlimit");
+ sp_repr_css_unset_property (css, "stroke-linejoin");
+ sp_repr_css_unset_property (css, "stroke-linecap");
+ sp_repr_css_unset_property (css, "stroke-dashoffset");
+ sp_repr_css_unset_property (css, "stroke-dasharray");
+
+ sp_desktop_set_style (desktop, css);
+ sp_repr_css_attr_unref (css);
+
+ sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Unset stroke"));
+ }
+ break;
+
+ default:
+ g_warning( "file %s: line %d: Paint selector should not be in "
+ "mode %d",
+ __FILE__, __LINE__,
+ psel->mode );
+ break;
+ }
+
+ g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE));
+}
+
+
+
+
+
+/* Line */
+
+static void sp_stroke_style_line_selection_modified(SPWidget *spw, Inkscape::Selection *selection, guint flags, gpointer data);
+static void sp_stroke_style_line_selection_changed(SPWidget *spw, Inkscape::Selection *selection, gpointer data);
+
+static void sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel);
+
+static void sp_stroke_style_set_join_buttons(Gtk::Container *spw, Gtk::ToggleButton *active);
+
+static void sp_stroke_style_set_cap_buttons(Gtk::Container *spw, Gtk::ToggleButton *active);
+
+static void sp_stroke_style_width_changed(Gtk::Container *spw);
+static void sp_stroke_style_miterlimit_changed(Gtk::Container *spw);
+static void sp_stroke_style_any_toggled(Gtk::ToggleButton *tb, Gtk::Container *spw);
+static void sp_stroke_style_line_dash_changed(Gtk::Container *spw);
+
+static void sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects);
+
+
+/**
+ * Helper function for creating radio buttons. This should probably be re-thought out
+ * when reimplementing this with Gtkmm.
+ */
+static Gtk::RadioButton *
+sp_stroke_radio_button(Gtk::RadioButton *tb, char const *icon,
+ Gtk::HBox *hb, Gtk::Container *spw,
+ gchar const *key, gchar const *data)
+{
+ g_assert(icon != NULL);
+ g_assert(hb != NULL);
+ g_assert(spw != NULL);
+
+ if (tb == NULL) {
+ tb = new Gtk::RadioButton();
+ } else {
+ Gtk::RadioButtonGroup grp = tb->get_group();
+ tb = new Gtk::RadioButton(grp);
+ }
+
+ tb->show();
+ tb->set_mode(false);
+ hb->pack_start(*tb, false, false, 0);
+ spw->set_data(icon, tb);
+ tb->set_data(key, (gpointer*)data);
+ tb->signal_toggled().connect(sigc::bind<Gtk::RadioButton *, Gtk::Container *>(
+ sigc::ptr_fun(&sp_stroke_style_any_toggled), tb, spw));
+ Gtk::Widget *px = manage(Glib::wrap(sp_icon_new(Inkscape::ICON_SIZE_LARGE_TOOLBAR, icon)));
+ g_assert(px != NULL);
+ px->show();
+ tb->add(*px);
+
+ return tb;
+
+}
+
+static void
+sp_stroke_style_widget_transientize_callback(Inkscape::Application */*inkscape*/,
+ SPDesktop */*desktop*/,
+ SPWidget */*spw*/ )
+{
+// TODO: Either of these will cause crashes sometimes
+// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL);
+// ink_markers_menu_update(spw);
+}
+
+/**
+ * Creates a copy of the marker named mname, determines its visible and renderable
+ * area in menu_id's bounding box, and then renders it. This allows us to fill in
+ * preview images of each marker in the marker menu.
+ */
+static Gtk::Image *
+sp_marker_prev_new(unsigned psize, gchar const *mname,
+ SPDocument *source, SPDocument *sandbox,
+ gchar const *menu_id, NRArena const */*arena*/, unsigned /*visionkey*/, NRArenaItem *root)
+{
+ // Retrieve the marker named 'mname' from the source SVG document
+ SPObject const *marker = source->getObjectById(mname);
+ if (marker == NULL)
+ return NULL;
+
+ // Create a copy repr of the marker with id="sample"
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(sandbox);
+ Inkscape::XML::Node *mrepr = SP_OBJECT_REPR (marker)->duplicate(xml_doc);
+ mrepr->setAttribute("id", "sample");
+
+ // Replace the old sample in the sandbox by the new one
+ Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (sandbox->getObjectById("defs"));
+ SPObject *oldmarker = sandbox->getObjectById("sample");
+ if (oldmarker)
+ oldmarker->deleteObject(false);
+ defsrepr->appendChild(mrepr);
+ Inkscape::GC::release(mrepr);
+
+// Uncomment this to get the sandbox documents saved (useful for debugging)
+ //FILE *fp = fopen (g_strconcat(menu_id, mname, ".svg", NULL), "w");
+ //sp_repr_save_stream (sp_document_repr_doc (sandbox), fp);
+ //fclose (fp);
+
+ // object to render; note that the id is the same as that of the menu we're building
+ SPObject *object = sandbox->getObjectById(menu_id);
+ sp_document_root (sandbox)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ sp_document_ensure_up_to_date(sandbox);
+
+ if (object == NULL || !SP_IS_ITEM(object))
+ return NULL; // sandbox broken?
+
+ // Find object's bbox in document
+ Geom::Matrix const i2doc(sp_item_i2doc_affine(SP_ITEM(object)));
+ Geom::OptRect dbox = SP_ITEM(object)->getBounds(i2doc);
+
+ if (!dbox) {
+ return NULL;
+ }
+
+ /* Update to renderable state */
+ double sf = 0.8;
+
+ gchar *cache_name = g_strconcat(menu_id, mname, NULL);
+ Glib::ustring key = svg_preview_cache.cache_key(source->uri, cache_name, psize);
+ g_free (cache_name);
+ // TODO: is this correct?
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key));
+
+ if (!pixbuf) {
+ pixbuf = Glib::wrap(render_pixbuf(root, sf, *dbox, psize));
+ svg_preview_cache.set_preview_in_cache(key, pixbuf->gobj());
+ }
+
+ // Create widget
+ Gtk::Image *pb = new Gtk::Image(pixbuf);
+
+ return pb;
+}
+
+/**
+ * Returns a list of markers in the defs of the given source document as a GSList object
+ * Returns NULL if there are no markers in the document.
+ */
+GSList *
+ink_marker_list_get (SPDocument *source)
+{
+ if (source == NULL)
+ return NULL;
+
+ GSList *ml = NULL;
+ SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS (source);
+ for ( SPObject *child = sp_object_first_child(SP_OBJECT(defs));
+ child != NULL;
+ child = SP_OBJECT_NEXT (child) )
+ {
+ if (SP_IS_MARKER(child)) {
+ ml = g_slist_prepend (ml, child);
+ }
+ }
+ return ml;
+}
+
+#define MARKER_ITEM_MARGIN 0
+
+/**
+ * Adds previews of markers in marker_list to the given menu widget
+ */
+static void
+sp_marker_menu_build (Gtk::Menu *m, GSList *marker_list, SPDocument *source, SPDocument *sandbox, gchar const *menu_id)
+{
+ // Do this here, outside of loop, to speed up preview generation:
+ NRArena const *arena = NRArena::create();
+ unsigned const visionkey = sp_item_display_key_new(1);
+ NRArenaItem *root = sp_item_invoke_show(SP_ITEM(SP_DOCUMENT_ROOT (sandbox)), (NRArena *) arena, visionkey, SP_ITEM_SHOW_DISPLAY);
+
+ for (; marker_list != NULL; marker_list = marker_list->next) {
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) marker_list->data);
+ Gtk::MenuItem *i = new Gtk::MenuItem();
+ i->show();
+
+ if (repr->attribute("inkscape:stockid"))
+ i->set_data("stockid", (void *) "true");
+ else
+ i->set_data("stockid", (void *) "false");
+
+ gchar const *markid = repr->attribute("id");
+ i->set_data("marker", (void *) markid);
+
+ Gtk::HBox *hb = new Gtk::HBox(false, MARKER_ITEM_MARGIN);
+ hb->show();
+
+ // generate preview
+
+ Gtk::Image *prv = sp_marker_prev_new (22, markid, source, sandbox, menu_id, arena, visionkey, root);
+ prv->show();
+ hb->pack_start(*prv, false, false, 6);
+
+ // create label
+ Gtk::Label *l = new Gtk::Label(repr->attribute("id"));
+ l->show();
+ l->set_alignment(0.0, 0.5);
+
+ hb->pack_start(*l, true, true, 0);
+
+ hb->show();
+ i->add(*hb);
+
+ m->append(*i);
+ }
+
+ sp_item_invoke_hide(SP_ITEM(sp_document_root(sandbox)), visionkey);
+ nr_object_unref((NRObject *) arena);
+}
+
+/**
+ * sp_marker_list_from_doc()
+ *
+ * \brief Pick up all markers from source, except those that are in
+ * current_doc (if non-NULL), and add items to the m menu
+ *
+ */
+static void
+sp_marker_list_from_doc (Gtk::Menu *m, SPDocument */*current_doc*/, SPDocument *source, SPDocument */*markers_doc*/, SPDocument *sandbox, gchar const *menu_id)
+{
+ GSList *ml = ink_marker_list_get(source);
+ GSList *clean_ml = NULL;
+
+ for (; ml != NULL; ml = ml->next) {
+ if (!SP_IS_MARKER(ml->data))
+ continue;
+
+ // Add to the list of markers we really do wish to show
+ clean_ml = g_slist_prepend (clean_ml, ml->data);
+ }
+ sp_marker_menu_build(m, clean_ml, source, sandbox, menu_id);
+
+ g_slist_free (ml);
+ g_slist_free (clean_ml);
+}
+
+/**
+ * Returns a new document containing default start, mid, and end markers.
+ */
+SPDocument *
+ink_markers_preview_doc ()
+{
+gchar const *buffer = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
+" <defs id=\"defs\" />"
+
+" <g id=\"marker-start\">"
+" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:url(#sample);marker-mid:none;marker-end:none\""
+" d=\"M 12.5,13 L 25,13\" id=\"path1\" />"
+" <rect style=\"fill:none;stroke:none\" id=\"rect2\""
+" width=\"25\" height=\"25\" x=\"0\" y=\"0\" />"
+" </g>"
+
+" <g id=\"marker-mid\">"
+" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:none;marker-mid:url(#sample);marker-end:none\""
+" d=\"M 0,113 L 12.5,113 L 25,113\" id=\"path11\" />"
+" <rect style=\"fill:none;stroke:none\" id=\"rect22\""
+" width=\"25\" height=\"25\" x=\"0\" y=\"100\" />"
+" </g>"
+
+" <g id=\"marker-end\">"
+" <path style=\"fill:none;stroke:black;stroke-width:1.7;marker-start:none;marker-mid:none;marker-end:url(#sample)\""
+" d=\"M 0,213 L 12.5,213\" id=\"path111\" />"
+" <rect style=\"fill:none;stroke:none\" id=\"rect222\""
+" width=\"25\" height=\"25\" x=\"0\" y=\"200\" />"
+" </g>"
+
+"</svg>";
+
+ return sp_document_new_from_mem (buffer, strlen(buffer), FALSE);
+}
+
+static void
+ink_marker_menu_create_menu(Gtk::Menu *m, gchar const *menu_id, SPDocument *doc, SPDocument *sandbox)
+{
+ static SPDocument *markers_doc = NULL;
+
+ // add "None"
+ Gtk::MenuItem *i = new Gtk::MenuItem();
+ i->show();
+
+ i->set_data("marker", (void *) "none");
+
+ Gtk::HBox *hb = new Gtk::HBox(false, MARKER_ITEM_MARGIN);
+ hb->show();
+
+ Gtk::Label *l = new Gtk::Label( _("None") );
+ l->show();
+ l->set_alignment(0.0, 0.5);
+
+ hb->pack_start(*l, true, true, 0);
+
+ hb->show();
+ i->add(*hb);
+ m->append(*i);
+
+ // find and load markers.svg
+ if (markers_doc == NULL) {
+ char *markers_source = g_build_filename(INKSCAPE_MARKERSDIR, "markers.svg", NULL);
+ if (Inkscape::IO::file_test(markers_source, G_FILE_TEST_IS_REGULAR)) {
+ markers_doc = sp_document_new(markers_source, FALSE);
+ }
+ g_free(markers_source);
+ }
+
+ // suck in from current doc
+ sp_marker_list_from_doc(m, NULL, doc, markers_doc, sandbox, menu_id);
+
+ // add separator
+ {
+ //Gtk::Separator *i = gtk_separator_menu_item_new();
+ Gtk::SeparatorMenuItem *i = new Gtk::SeparatorMenuItem();
+ i->show();
+ m->append(*i);
+ }
+
+ // suck in from markers.svg
+ if (markers_doc) {
+ sp_document_ensure_up_to_date(doc);
+ sp_marker_list_from_doc(m, doc, markers_doc, NULL, sandbox, menu_id);
+ }
+
+}
+
+/**
+ * Creates a menu widget to display markers from markers.svg
+ */
+static Gtk::OptionMenu *
+ink_marker_menu(Gtk::Widget */*tbl*/, gchar const *menu_id, SPDocument *sandbox)
+{
+ SPDesktop *desktop = inkscape_active_desktop();
+ SPDocument *doc = sp_desktop_document(desktop);
+ Gtk::OptionMenu *mnu = new Gtk::OptionMenu();
+
+ /* Create new menu widget */
+ Gtk::Menu *m = new Gtk::Menu();
+ m->show();
+
+ mnu->set_data("updating", (gpointer) FALSE);
+
+ if (!doc) {
+ Gtk::MenuItem *i = new Gtk::MenuItem(_("No document selected"));
+ i->show();
+ m->append(*i);
+ mnu->set_sensitive(false);
+
+ } else {
+ ink_marker_menu_create_menu(m, menu_id, doc, sandbox);
+
+ mnu->set_sensitive(true);
+ }
+
+ mnu->set_data("menu_id", const_cast<gchar *>(menu_id));
+ mnu->set_menu(*m);
+
+ /* Set history */
+ mnu->set_history(0);
+
+ return mnu;
+}
+
+/**
+ * Handles when user selects one of the markers from the marker menu.
+ * Defines a uri string to refer to it, then applies it to all selected
+ * items in the current desktop.
+ */
+static void
+sp_marker_select(Gtk::OptionMenu *mnu, Gtk::Container *spw, SPMarkerLoc const which)
+{
+ if (spw->get_data("update")) {
+ return;
+ }
+
+ SPDesktop *desktop = inkscape_active_desktop();
+ SPDocument *document = sp_desktop_document(desktop);
+ if (!document) {
+ return;
+ }
+
+ /* Get Marker */
+ if (!mnu->get_menu()->get_active()->get_data("marker"))
+ {
+ return;
+ }
+ gchar *markid = static_cast<gchar *>(mnu->get_menu()->get_active()->get_data("marker"));
+ gchar const *marker = "";
+ if (strcmp(markid, "none")) {
+ gchar *stockid = static_cast<gchar *>(mnu->get_menu()->get_active()->get_data("stockid"));
+
+ gchar *markurn = markid;
+ if (!strcmp(stockid,"true")) markurn = g_strconcat("urn:inkscape:marker:",markid,NULL);
+ SPObject *mark = get_stock_item(markurn);
+ if (mark) {
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(mark);
+ marker = g_strconcat("url(#", repr->attribute("id"), ")", NULL);
+ }
+ } else {
+ marker = markid;
+ }
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ gchar const *menu_id = static_cast<gchar const *>(mnu->get_data("menu_id"));
+ sp_repr_css_set_property(css, menu_id, marker);
+
+ // Also update the marker dropdown menus, so the document's markers
+ // show up at the top of the menu
+// sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL);
+ ink_markers_menu_update(spw, which);
+
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
+ GSList const *items = selection->itemList();
+ for (; items != NULL; items = items->next) {
+ SPItem *item = (SPItem *) items->data;
+ if (!SP_IS_SHAPE(item) || SP_IS_RECT(item)) // can't set marker to rect, until it's converted to using <path>
+ continue;
+ Inkscape::XML::Node *selrepr = SP_OBJECT_REPR((SPItem *) items->data);
+ if (selrepr) {
+ sp_repr_css_change_recursive(selrepr, css, "style");
+ }
+ SP_OBJECT(items->data)->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ SP_OBJECT(items->data)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
+ }
+
+ sp_repr_css_attr_unref(css);
+
+ sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set markers"));
+
+};
+
+static unsigned int
+ink_marker_menu_get_pos(Gtk::Menu *mnu, gchar const *markname)
+{
+ if (markname == NULL)
+ markname = static_cast<gchar const *>(mnu->get_active()->get_data("marker"));
+
+ if (markname == NULL)
+ return 0;
+
+ std::vector<Gtk::Widget *> kids = mnu->get_children();
+ unsigned int i = 0;
+ for (; i < kids.size();) {
+ gchar const *mark = static_cast<gchar const *>(kids[i]->get_data("marker"));
+ if (mark && strcmp(mark, markname) == 0) {
+ break;
+ }
+ ++i;
+ }
+
+ return i;
+}
+
+static void
+ink_markers_menu_update(Gtk::Container* /*spw*/, SPMarkerLoc const which) {
+ SPDesktop *desktop = inkscape_active_desktop();
+ SPDocument *document = sp_desktop_document(desktop);
+ SPDocument *sandbox = ink_markers_preview_doc ();
+ Gtk::Menu *m;
+ int pos;
+
+ // TODO: this code can be shortened by abstracting out marker_(start|mid|end)_...
+ switch (which) {
+ case SP_MARKER_LOC_START:
+ marker_start_menu_connection.block();
+ pos = ink_marker_menu_get_pos(marker_start_menu->get_menu(), NULL);
+ m = new Gtk::Menu();
+ m->show();
+ ink_marker_menu_create_menu(m, "marker-start", document, sandbox);
+ marker_start_menu->remove_menu();
+ marker_start_menu->set_menu(*m);
+ marker_start_menu->set_history(pos);
+ marker_start_menu_connection.unblock();
+ break;
+
+ case SP_MARKER_LOC_MID:
+ marker_mid_menu_connection.block();
+ pos = ink_marker_menu_get_pos(marker_mid_menu->get_menu(), NULL);
+ m = new Gtk::Menu();
+ m->show();
+ ink_marker_menu_create_menu(m, "marker-mid", document, sandbox);
+ marker_mid_menu->remove_menu();
+ marker_mid_menu->set_menu(*m);
+ marker_mid_menu->set_history(pos);
+ marker_mid_menu_connection.unblock();
+ break;
+
+ case SP_MARKER_LOC_END:
+ marker_end_menu_connection.block();
+ pos = ink_marker_menu_get_pos(marker_end_menu->get_menu(), NULL);
+ m = new Gtk::Menu();
+ m->show();
+ ink_marker_menu_create_menu(m, "marker-end", document, sandbox);
+ marker_end_menu->remove_menu();
+ marker_end_menu->set_menu(*m);
+ marker_end_menu->set_history(pos);
+ marker_end_menu_connection.unblock();
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+/**
+ * Sets the stroke width units for all selected items.
+ * Also handles absolute and dimensionless units.
+ */
+static gboolean stroke_width_set_unit(SPUnitSelector *,
+ SPUnit const *old,
+ SPUnit const *new_units,
+ Gtk::Container *spw)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+
+ if (!desktop) {
+ return FALSE;
+ }
+
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
+
+ if (selection->isEmpty())
+ return FALSE;
+
+ GSList const *objects = selection->itemList();
+
+ if ((old->base == SP_UNIT_ABSOLUTE || old->base == SP_UNIT_DEVICE) &&
+ (new_units->base == SP_UNIT_DIMENSIONLESS)) {
+
+ /* Absolute to percentage */
+ spw->set_data ("update", GUINT_TO_POINTER (TRUE));
+
+ Gtk::Adjustment *a = static_cast<Gtk::Adjustment *>(spw->get_data("width"));
+ float w = sp_units_get_pixels (a->get_value(), *old);
+
+ gdouble average = stroke_average_width (objects);
+
+ if (average == NR_HUGE || average == 0)
+ return FALSE;
+
+ a->set_value (100.0 * w / average);
+
+ spw->set_data ("update", GUINT_TO_POINTER (FALSE));
+ return TRUE;
+
+ } else if ((old->base == SP_UNIT_DIMENSIONLESS) &&
+ (new_units->base == SP_UNIT_ABSOLUTE || new_units->base == SP_UNIT_DEVICE)) {
+
+ /* Percentage to absolute */
+ spw->set_data ("update", GUINT_TO_POINTER (TRUE));
+
+ Gtk::Adjustment *a = static_cast<Gtk::Adjustment *>(spw->get_data ("width"));
+
+ gdouble average = stroke_average_width (objects);
+
+ a->set_value (sp_pixels_get_units (0.01 * a->get_value() * average, *new_units));
+
+ spw->set_data ("update", GUINT_TO_POINTER (FALSE));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * \brief Creates a new widget for the line stroke style.
+ *
+ */
+Gtk::Container *
+sp_stroke_style_line_widget_new(void)
+{
+ Gtk::Widget *us;
+ SPDashSelector *ds;
+ GtkWidget *us_old, *spw_old;
+ Gtk::Container *spw;
+ Gtk::Table *t;
+ Gtk::Adjustment *a;
+ Gtk::SpinButton *sb;
+ Gtk::RadioButton *tb;
+ Gtk::HBox *f, *hb;
+
+ Gtk::Tooltips *tt = new Gtk::Tooltips();
+
+ spw_old = sp_widget_new_global(INKSCAPE);
+ spw = dynamic_cast<Gtk::Container *>(manage(Glib::wrap(spw_old)));
+
+ f = new Gtk::HBox(false, 0);
+ f->show();
+ spw->add(*f);
+
+ t = new Gtk::Table(3, 6, false);
+ t->show();
+ t->set_border_width(4);
+ t->set_row_spacings(4);
+ f->add(*t);
+ spw->set_data("stroke", t);
+
+ gint i = 0;
+
+ /* Stroke width */
+ spw_label(t, Q_("StrokeWidth|Width:"), 0, i);
+
+ hb = spw_hbox(t, 3, 1, i);
+
+// TODO: when this is gtkmmified, use an Inkscape::UI::Widget::ScalarUnit instead of the separate
+// spinbutton and unit selector for stroke width. In sp_stroke_style_line_update, use
+// setHundredPercent to remember the aeraged width corresponding to 100%. Then the
+// stroke_width_set_unit will be removed (because ScalarUnit takes care of conversions itself), and
+// with it, the two remaining calls of stroke_average_width, allowing us to get rid of that
+// function in desktop-style.
+
+ a = new Gtk::Adjustment(1.0, 0.0, 1000.0, 0.1, 10.0, 10.0);
+ spw->set_data("width", a);
+ sb = new Gtk::SpinButton(*a, 0.1, 3);
+ tt->set_tip(*sb, _("Stroke width"));
+ sb->show();
+
+ sp_dialog_defocus_on_enter_cpp(sb);
+
+ hb->pack_start(*sb, false, false, 0);
+ us_old = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE);
+ us = manage(Glib::wrap(us_old));
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (desktop)
+ sp_unit_selector_set_unit (SP_UNIT_SELECTOR(us_old), sp_desktop_namedview(desktop)->doc_units);
+ sp_unit_selector_add_unit(SP_UNIT_SELECTOR(us_old), &sp_unit_get_by_id(SP_UNIT_PERCENT), 0);
+ g_signal_connect ( G_OBJECT (us_old), "set_unit", G_CALLBACK (stroke_width_set_unit), spw );
+ us->show();
+ sp_unit_selector_add_adjustment( SP_UNIT_SELECTOR(us_old), GTK_ADJUSTMENT(a->gobj()) );
+ hb->pack_start(*us, FALSE, FALSE, 0);
+ spw->set_data("units", us_old);
+
+ a->signal_value_changed().connect(sigc::bind(sigc::ptr_fun(&sp_stroke_style_width_changed), spw));
+ i++;
+
+ /* Join type */
+ // TRANSLATORS: The line join style specifies the shape to be used at the
+ // corners of paths. It can be "miter", "round" or "bevel".
+ spw_label(t, _("Join:"), 0, i);
+
+ hb = spw_hbox(t, 3, 1, i);
+
+ tb = NULL;
+
+ tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_JOIN_MITER,
+ hb, spw, "join", "miter");
+
+ // TRANSLATORS: Miter join: joining lines with a sharp (pointed) corner.
+ // For an example, draw a triangle with a large stroke width and modify the
+ // "Join" option (in the Fill and Stroke dialog).
+ tt->set_tip(*tb, _("Miter join"));
+
+ tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_JOIN_ROUND,
+ hb, spw, "join", "round");
+
+ // TRANSLATORS: Round join: joining lines with a rounded corner.
+ // For an example, draw a triangle with a large stroke width and modify the
+ // "Join" option (in the Fill and Stroke dialog).
+ tt->set_tip(*tb, _("Round join"));
+
+ tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_JOIN_BEVEL,
+ hb, spw, "join", "bevel");
+
+ // TRANSLATORS: Bevel join: joining lines with a blunted (flattened) corner.
+ // For an example, draw a triangle with a large stroke width and modify the
+ // "Join" option (in the Fill and Stroke dialog).
+ tt->set_tip(*tb, _("Bevel join"));
+
+ i++;
+
+ /* Miterlimit */
+ // TRANSLATORS: Miter limit: only for "miter join", this limits the length
+ // of the sharp "spike" when the lines connect at too sharp an angle.
+ // When two line segments meet at a sharp angle, a miter join results in a
+ // spike that extends well beyond the connection point. The purpose of the
+ // miter limit is to cut off such spikes (i.e. convert them into bevels)
+ // when they become too long.
+ spw_label(t, _("Miter limit:"), 0, i);
+
+ hb = spw_hbox(t, 3, 1, i);
+
+ a = new Gtk::Adjustment(4.0, 0.0, 100.0, 0.1, 10.0, 10.0);
+ spw->set_data("miterlimit", a);
+
+ sb = new Gtk::SpinButton(*a, 0.1, 2);
+ tt->set_tip(*sb, _("Maximum length of the miter (in units of stroke width)"));
+ sb->show();
+ spw->set_data("miterlimit_sb", sb);
+ sp_dialog_defocus_on_enter_cpp(sb);
+
+ hb->pack_start(*sb, false, false, 0);
+
+ a->signal_value_changed().connect(sigc::bind(sigc::ptr_fun(&sp_stroke_style_miterlimit_changed), spw));
+ i++;
+
+ /* Cap type */
+ // TRANSLATORS: cap type specifies the shape for the ends of lines
+ spw_label(t, _("Cap:"), 0, i);
+
+ hb = spw_hbox(t, 3, 1, i);
+
+ tb = NULL;
+
+ tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_CAP_BUTT,
+ hb, spw, "cap", "butt");
+
+ // TRANSLATORS: Butt cap: the line shape does not extend beyond the end point
+ // of the line; the ends of the line are square
+ tt->set_tip(*tb, _("Butt cap"));
+
+ tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_CAP_ROUND,
+ hb, spw, "cap", "round");
+
+ // TRANSLATORS: Round cap: the line shape extends beyond the end point of the
+ // line; the ends of the line are rounded
+ tt->set_tip(*tb, _("Round cap"));
+
+ tb = sp_stroke_radio_button(tb, INKSCAPE_ICON_STROKE_CAP_SQUARE,
+ hb, spw, "cap", "square");
+
+ // TRANSLATORS: Square cap: the line shape extends beyond the end point of the
+ // line; the ends of the line are square
+ tt->set_tip(*tb, _("Square cap"));
+
+ i++;
+
+
+ /* Dash */
+ spw_label(t, _("Dashes:"), 0, i);
+ ds = manage(new SPDashSelector);
+
+ ds->show();
+ t->attach(*ds, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
+ spw->set_data("dash", ds);
+ ds->changed_signal.connect(sigc::bind(sigc::ptr_fun(&sp_stroke_style_line_dash_changed), spw));
+ i++;
+
+ /* Drop down marker selectors*/
+ // TODO: this code can be shortened by iterating over the possible menus!
+
+ // doing this here once, instead of for each preview, to speed things up
+ SPDocument *sandbox = ink_markers_preview_doc ();
+
+ // TRANSLATORS: Path markers are an SVG feature that allows you to attach arbitrary shapes
+ // (arrowheads, bullets, faces, whatever) to the start, end, or middle nodes of a path.
+ spw_label(t, _("Start Markers:"), 0, i);
+ marker_start_menu = ink_marker_menu(spw ,"marker-start", sandbox);
+ tt->set_tip(*marker_start_menu, _("Start Markers are drawn on the first node of a path or shape"));
+ marker_start_menu_connection = marker_start_menu->signal_changed().connect(
+ sigc::bind<Gtk::OptionMenu *, Gtk::Container *, SPMarkerLoc>(
+ sigc::ptr_fun(&sp_marker_select), marker_start_menu, spw, SP_MARKER_LOC_START));
+ marker_start_menu->show();
+ t->attach(*marker_start_menu, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
+ spw->set_data("start_mark_menu", marker_start_menu);
+
+ i++;
+ spw_label(t, _("Mid Markers:"), 0, i);
+ marker_mid_menu = ink_marker_menu(spw ,"marker-mid", sandbox);
+ tt->set_tip(*marker_mid_menu, _("Mid Markers are drawn on every node of a path or shape except the first and last nodes"));
+ marker_mid_menu_connection = marker_mid_menu->signal_changed().connect(
+ sigc::bind<Gtk::OptionMenu *, Gtk::Container *, SPMarkerLoc>(
+ sigc::ptr_fun(&sp_marker_select), marker_mid_menu,spw, SP_MARKER_LOC_MID));
+ marker_mid_menu->show();
+ t->attach(*marker_mid_menu, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
+ spw->set_data("mid_mark_menu", marker_mid_menu);
+
+ i++;
+ spw_label(t, _("End Markers:"), 0, i);
+ marker_end_menu = ink_marker_menu(spw ,"marker-end", sandbox);
+ tt->set_tip(*marker_end_menu, _("End Markers are drawn on the last node of a path or shape"));
+ marker_end_menu_connection = marker_end_menu->signal_changed().connect(
+ sigc::bind<Gtk::OptionMenu *, Gtk::Container *, SPMarkerLoc>(
+ sigc::ptr_fun(&sp_marker_select), marker_end_menu, spw, SP_MARKER_LOC_END));
+ marker_end_menu->show();
+ t->attach(*marker_end_menu, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0);
+ spw->set_data("end_mark_menu", marker_end_menu);
+
+ i++;
+
+ // FIXME: we cheat and still use gtk+ signals
+
+ gtk_signal_connect(GTK_OBJECT(spw_old), "modify_selection",
+ GTK_SIGNAL_FUNC(sp_stroke_style_line_selection_modified),
+ spw);
+ gtk_signal_connect(GTK_OBJECT(spw_old), "change_selection",
+ GTK_SIGNAL_FUNC(sp_stroke_style_line_selection_changed),
+ spw);
+
+ sp_stroke_style_line_update(spw, desktop ? sp_desktop_selection(desktop) : NULL);
+
+ return spw;
+}
+
+/**
+ * Callback for when stroke style widget is modified.
+ * Triggers update action.
+ */
+static void
+sp_stroke_style_line_selection_modified(SPWidget *,
+ Inkscape::Selection *selection,
+ guint flags,
+ gpointer data)
+{
+ Gtk::Container *spw = static_cast<Gtk::Container *>(data);
+ if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG)) {
+ sp_stroke_style_line_update(spw, selection);
+ }
+
+}
+
+/**
+ * Callback for when stroke style widget is changed.
+ * Triggers update action.
+ */
+static void
+sp_stroke_style_line_selection_changed(SPWidget *,
+ Inkscape::Selection *selection,
+ gpointer data)
+{
+ Gtk::Container *spw = static_cast<Gtk::Container *>(data);
+ sp_stroke_style_line_update(spw, selection);
+}
+
+/**
+ * Sets selector widgets' dash style from an SPStyle object.
+ */
+static void
+sp_dash_selector_set_from_style(SPDashSelector *dsel, SPStyle *style)
+{
+ if (style->stroke_dash.n_dash > 0) {
+ double d[64];
+ int len = MIN(style->stroke_dash.n_dash, 64);
+ for (int i = 0; i < len; i++) {
+ if (style->stroke_width.computed != 0)
+ d[i] = style->stroke_dash.dash[i] / style->stroke_width.computed;
+ else
+ d[i] = style->stroke_dash.dash[i]; // is there a better thing to do for stroke_width==0?
+ }
+ dsel->set_dash(len, d, style->stroke_width.computed != 0 ?
+ style->stroke_dash.offset / style->stroke_width.computed :
+ style->stroke_dash.offset);
+ } else {
+ dsel->set_dash(0, NULL, 0.0);
+ }
+}
+
+/**
+ * Sets the join type for a line, and updates the stroke style widget's buttons
+ */
+static void
+sp_jointype_set (Gtk::Container *spw, unsigned const jointype)
+{
+ Gtk::RadioButton *tb = NULL;
+ switch (jointype) {
+ case SP_STROKE_LINEJOIN_MITER:
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_MITER));
+ break;
+ case SP_STROKE_LINEJOIN_ROUND:
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_ROUND));
+ break;
+ case SP_STROKE_LINEJOIN_BEVEL:
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_BEVEL));
+ break;
+ default:
+ break;
+ }
+ sp_stroke_style_set_join_buttons(spw, tb);
+}
+
+/**
+ * Sets the cap type for a line, and updates the stroke style widget's buttons
+ */
+static void
+sp_captype_set (Gtk::Container *spw, unsigned const captype)
+{
+ Gtk::RadioButton *tb = NULL;
+ switch (captype) {
+ case SP_STROKE_LINECAP_BUTT:
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_BUTT));
+ break;
+ case SP_STROKE_LINECAP_ROUND:
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_ROUND));
+ break;
+ case SP_STROKE_LINECAP_SQUARE:
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_SQUARE));
+ break;
+ default:
+ break;
+ }
+ sp_stroke_style_set_cap_buttons(spw, tb);
+}
+
+/**
+ * Callback for when stroke style widget is updated, including markers, cap type,
+ * join type, etc.
+ */
+static void
+sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel)
+{
+ if (spw->get_data("update")) {
+ return;
+ }
+
+ spw->set_data("update", GINT_TO_POINTER(TRUE));
+
+ Gtk::Table *sset = static_cast<Gtk::Table *>(spw->get_data("stroke"));
+ Gtk::Adjustment *width = static_cast<Gtk::Adjustment *>(spw->get_data("width"));
+ Gtk::Adjustment *ml = static_cast<Gtk::Adjustment *>(spw->get_data("miterlimit"));
+ SPUnitSelector *us = SP_UNIT_SELECTOR(spw->get_data("units"));
+ SPDashSelector *dsel = static_cast<SPDashSelector *>(spw->get_data("dash"));
+
+ // create temporary style
+ SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+ // query into it
+ int result_sw = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEWIDTH);
+ int result_ml = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEMITERLIMIT);
+ int result_cap = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKECAP);
+ int result_join = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEJOIN);
+
+ if (result_sw == QUERY_STYLE_NOTHING) {
+ /* No objects stroked, set insensitive */
+ sset->set_sensitive(false);
+
+ spw->set_data("update", GINT_TO_POINTER(FALSE));
+ return;
+ } else {
+ sset->set_sensitive(true);
+
+ SPUnit const *unit = sp_unit_selector_get_unit(us);
+
+ if (result_sw == QUERY_STYLE_MULTIPLE_AVERAGED) {
+ sp_unit_selector_set_unit(us, &sp_unit_get_by_id(SP_UNIT_PERCENT));
+ } else {
+ // same width, or only one object; no sense to keep percent, switch to absolute
+ if (unit->base != SP_UNIT_ABSOLUTE && unit->base != SP_UNIT_DEVICE) {
+ sp_unit_selector_set_unit(us, sp_desktop_namedview(SP_ACTIVE_DESKTOP)->doc_units);
+ }
+ }
+
+ unit = sp_unit_selector_get_unit(us);
+
+ if (unit->base == SP_UNIT_ABSOLUTE || unit->base == SP_UNIT_DEVICE) {
+ double avgwidth = sp_pixels_get_units (query->stroke_width.computed, *unit);
+ width->set_value(avgwidth);
+ } else {
+ width->set_value(100);
+ }
+ }
+
+ if (result_ml != QUERY_STYLE_NOTHING)
+ ml->set_value(query->stroke_miterlimit.value); // TODO: reflect averagedness?
+
+ if (result_join != QUERY_STYLE_MULTIPLE_DIFFERENT) {
+ sp_jointype_set(spw, query->stroke_linejoin.value);
+ } else {
+ sp_stroke_style_set_join_buttons(spw, NULL);
+ }
+
+ if (result_cap != QUERY_STYLE_MULTIPLE_DIFFERENT) {
+ sp_captype_set (spw, query->stroke_linecap.value);
+ } else {
+ sp_stroke_style_set_cap_buttons(spw, NULL);
+ }
+
+ sp_style_unref(query);
+
+ if (!sel || sel->isEmpty())
+ return;
+
+ GSList const *objects = sel->itemList();
+ SPObject * const object = SP_OBJECT(objects->data);
+ SPStyle * const style = SP_OBJECT_STYLE(object);
+
+ /* Markers */
+ sp_stroke_style_update_marker_menus(spw, objects); // FIXME: make this desktop query too
+
+ /* Dash */
+ sp_dash_selector_set_from_style(dsel, style); // FIXME: make this desktop query too
+
+ sset->set_sensitive(true);
+
+ spw->set_data("update", GINT_TO_POINTER(FALSE));
+}
+
+/**
+ * Sets a line's dash properties in a CSS style object.
+ */
+static void
+sp_stroke_style_set_scaled_dash(SPCSSAttr *css,
+ int ndash, double *dash, double offset,
+ double scale)
+{
+ if (ndash > 0) {
+ Inkscape::CSSOStringStream osarray;
+ for (int i = 0; i < ndash; i++) {
+ osarray << dash[i] * scale;
+ if (i < (ndash - 1)) {
+ osarray << ",";
+ }
+ }
+ sp_repr_css_set_property(css, "stroke-dasharray", osarray.str().c_str());
+
+ Inkscape::CSSOStringStream osoffset;
+ osoffset << offset * scale;
+ sp_repr_css_set_property(css, "stroke-dashoffset", osoffset.str().c_str());
+ } else {
+ sp_repr_css_set_property(css, "stroke-dasharray", "none");
+ sp_repr_css_set_property(css, "stroke-dashoffset", NULL);
+ }
+}
+
+/**
+ * Sets line properties like width, dashes, markers, etc. on all currently selected items.
+ */
+static void
+sp_stroke_style_scale_line(Gtk::Container *spw)
+{
+ if (spw->get_data("update")) {
+ return;
+ }
+
+ spw->set_data("update", GINT_TO_POINTER(TRUE));
+
+ Gtk::Adjustment *wadj = static_cast<Gtk::Adjustment *>(spw->get_data("width"));
+ SPUnitSelector *us = SP_UNIT_SELECTOR(spw->get_data("units"));
+ SPDashSelector *dsel = static_cast<SPDashSelector *>(spw->get_data("dash"));
+ Gtk::Adjustment *ml = static_cast<Gtk::Adjustment *>(spw->get_data("miterlimit"));
+
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDocument *document = sp_desktop_document (desktop);
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
+
+ GSList const *items = selection->itemList();
+
+ /* TODO: Create some standardized method */
+ SPCSSAttr *css = sp_repr_css_attr_new();
+
+ if (items) {
+
+ double width_typed = wadj->get_value();
+ double const miterlimit = ml->get_value();
+
+ SPUnit const *const unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
+
+ double *dash, offset;
+ int ndash;
+ dsel->get_dash(&ndash, &dash, &offset);
+
+ for (GSList const *i = items; i != NULL; i = i->next) {
+ /* Set stroke width */
+ double width;
+ if (unit->base == SP_UNIT_ABSOLUTE || unit->base == SP_UNIT_DEVICE) {
+ width = sp_units_get_pixels (width_typed, *unit);
+ } else { // percentage
+ gdouble old_w = SP_OBJECT_STYLE (i->data)->stroke_width.computed;
+ width = old_w * width_typed / 100;
+ }
+
+ {
+ Inkscape::CSSOStringStream os_width;
+ os_width << width;
+ sp_repr_css_set_property(css, "stroke-width", os_width.str().c_str());
+ }
+
+ {
+ Inkscape::CSSOStringStream os_ml;
+ os_ml << miterlimit;
+ sp_repr_css_set_property(css, "stroke-miterlimit", os_ml.str().c_str());
+ }
+
+ /* Set dash */
+ sp_stroke_style_set_scaled_dash(css, ndash, dash, offset, width);
+
+ sp_desktop_apply_css_recursive (SP_OBJECT(i->data), css, true);
+ }
+
+ g_free(dash);
+
+ if (unit->base != SP_UNIT_ABSOLUTE && unit->base != SP_UNIT_DEVICE) {
+ // reset to 100 percent
+ wadj->set_value(100.0);
+ }
+
+ }
+
+ // we have already changed the items, so set style without changing selection
+ // FIXME: move the above stroke-setting stuff, including percentages, to desktop-style
+ sp_desktop_set_style (desktop, css, false);
+
+ sp_repr_css_attr_unref(css);
+
+ sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
+ _("Set stroke style"));
+
+ spw->set_data("update", GINT_TO_POINTER(FALSE));
+}
+
+/**
+ * Callback for when the stroke style's width changes.
+ * Causes all line styles to be applied to all selected items.
+ */
+static void
+sp_stroke_style_width_changed(Gtk::Container *spw)
+{
+ if (spw->get_data("update")) {
+ return;
+ }
+
+ sp_stroke_style_scale_line(spw);
+}
+
+/**
+ * Callback for when the stroke style's miterlimit changes.
+ * Causes all line styles to be applied to all selected items.
+ */
+static void
+sp_stroke_style_miterlimit_changed(Gtk::Container *spw)
+{
+ if (spw->get_data("update")) {
+ return;
+ }
+
+ sp_stroke_style_scale_line(spw);
+}
+
+/**
+ * Callback for when the stroke style's dash changes.
+ * Causes all line styles to be applied to all selected items.
+ */
+
+static void
+sp_stroke_style_line_dash_changed(Gtk::Container *spw)
+{
+ if (spw->get_data("update")) {
+ return;
+ }
+
+ sp_stroke_style_scale_line(spw);
+}
+
+/**
+ * \brief This routine handles toggle events for buttons in the stroke style
+ * dialog.
+ * When activated, this routine gets the data for the various widgets, and then
+ * calls the respective routines to update css properties, etc.
+ *
+ */
+static void
+sp_stroke_style_any_toggled(Gtk::ToggleButton *tb, Gtk::Container *spw)
+{
+ if (spw->get_data("update")) {
+ return;
+ }
+
+ if (tb->get_active()) {
+
+ gchar const *join
+ = static_cast<gchar const *>(tb->get_data("join"));
+ gchar const *cap
+ = static_cast<gchar const *>(tb->get_data("cap"));
+
+ if (join) {
+ Gtk::SpinButton *ml = static_cast<Gtk::SpinButton *>(spw->get_data("miterlimit_sb"));
+ ml->set_sensitive(!strcmp(join, "miter"));
+ }
+
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+
+ /* TODO: Create some standardized method */
+ SPCSSAttr *css = sp_repr_css_attr_new();
+
+ if (join) {
+ sp_repr_css_set_property(css, "stroke-linejoin", join);
+
+ sp_desktop_set_style (desktop, css);
+
+ sp_stroke_style_set_join_buttons(spw, tb);
+ } else if (cap) {
+ sp_repr_css_set_property(css, "stroke-linecap", cap);
+
+ sp_desktop_set_style (desktop, css);
+
+ sp_stroke_style_set_cap_buttons(spw, tb);
+ }
+
+ sp_repr_css_attr_unref(css);
+
+ sp_document_done(sp_desktop_document(desktop), SP_VERB_DIALOG_FILL_STROKE,
+ _("Set stroke style"));
+ }
+}
+
+/**
+ * Updates the join style toggle buttons
+ */
+static void
+sp_stroke_style_set_join_buttons(Gtk::Container *spw, Gtk::ToggleButton *active)
+{
+ Gtk::RadioButton *tb;
+
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_MITER));
+ tb->set_active(active == tb);
+
+ Gtk::SpinButton *ml = static_cast<Gtk::SpinButton *>(spw->get_data("miterlimit_sb"));
+ ml->set_sensitive(active == tb);
+
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_ROUND));
+ tb->set_active(active == tb);
+
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_JOIN_BEVEL));
+ tb->set_active(active == tb);
+}
+
+/**
+ * Updates the cap style toggle buttons
+ */
+static void
+sp_stroke_style_set_cap_buttons(Gtk::Container *spw, Gtk::ToggleButton *active)
+{
+ Gtk::RadioButton *tb;
+
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_BUTT));
+ tb->set_active(active == tb);
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_ROUND));
+ tb->set_active(active == tb);
+ tb = static_cast<Gtk::RadioButton *>(spw->get_data(INKSCAPE_ICON_STROKE_CAP_SQUARE));
+ tb->set_active(active == tb);
+}
+
+/**
+ * Sets the current marker in the marker menu.
+ */
+static void
+ink_marker_menu_set_current(SPObject *marker, Gtk::OptionMenu *mnu)
+{
+ mnu->set_data("update", GINT_TO_POINTER(TRUE));
+
+ Gtk::Menu *m = mnu->get_menu();
+ if (marker != NULL) {
+ bool mark_is_stock = false;
+ if (SP_OBJECT_REPR(marker)->attribute("inkscape:stockid"))
+ mark_is_stock = true;
+
+ gchar *markname;
+ if (mark_is_stock)
+ markname = g_strdup(SP_OBJECT_REPR(marker)->attribute("inkscape:stockid"));
+ else
+ markname = g_strdup(SP_OBJECT_REPR(marker)->attribute("id"));
+
+ int markpos = ink_marker_menu_get_pos(m, markname);
+ mnu->set_history(markpos);
+
+ g_free (markname);
+ }
+ else {
+ mnu->set_history(0);
+ }
+ mnu->set_data("update", GINT_TO_POINTER(FALSE));
+}
+
+/**
+ * Updates the marker menus to highlight the appropriate marker and scroll to
+ * that marker.
+ */
+static void
+sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects)
+{
+ struct { char const *key; int loc; } const keyloc[] = {
+ { "start_mark_menu", SP_MARKER_LOC_START },
+ { "mid_mark_menu", SP_MARKER_LOC_MID },
+ { "end_mark_menu", SP_MARKER_LOC_END }
+ };
+
+ bool all_texts = true;
+ for (GSList *i = (GSList *) objects; i != NULL; i = i->next) {
+ if (!SP_IS_TEXT (i->data)) {
+ all_texts = false;
+ }
+ }
+
+ for (unsigned i = 0; i < G_N_ELEMENTS(keyloc); ++i) {
+ Gtk::OptionMenu *mnu = static_cast<Gtk::OptionMenu *>(spw->get_data(keyloc[i].key));
+ // Per SVG spec, text objects cannot have markers; disable menus if only texts are selected
+ mnu->set_sensitive(!all_texts);
+ }
+
+ // We show markers of the first object in the list only
+ // FIXME: use the first in the list that has the marker of each type, if any
+ SPObject *object = SP_OBJECT(objects->data);
+
+ for (unsigned i = 0; i < G_N_ELEMENTS(keyloc); ++i) {
+ // For all three marker types,
+
+ // find the corresponding menu
+ Gtk::OptionMenu *mnu = static_cast<Gtk::OptionMenu *>(spw->get_data(keyloc[i].key));
+
+ // Quit if we're in update state
+ if (mnu->get_data("update")) {
+ return;
+ }
+
+ if (object->style->marker[keyloc[i].loc].value != NULL && !all_texts) {
+ // If the object has this type of markers,
+
+ // Extract the name of the marker that the object uses
+ SPObject *marker = ink_extract_marker_name(object->style->marker[keyloc[i].loc].value, SP_OBJECT_DOCUMENT(object));
+ // Scroll the menu to that marker
+ ink_marker_menu_set_current(marker, mnu);
+
+ } else {
+ mnu->set_history(0);
+ }
+ }
+}
+
+
+/**
+ * Extract the actual name of the link
+ * e.g. get mTriangle from url(#mTriangle).
+ * \return Buffer containing the actual name, allocated from GLib;
+ * the caller should free the buffer when they no longer need it.
+ */
+static SPObject*
+ink_extract_marker_name(gchar const *n, SPDocument *doc)
+{
+ gchar const *p = n;
+ while (*p != '\0' && *p != '#') {
+ p++;
+ }
+
+ if (*p == '\0' || p[1] == '\0') {
+ return NULL;
+ }
+
+ p++;
+ int c = 0;
+ while (p[c] != '\0' && p[c] != ')') {
+ c++;
+ }
+
+ if (p[c] == '\0') {
+ return NULL;
+ }
+
+ gchar* b = g_strdup(p);
+ b[c] = '\0';
+
+ // FIXME: get the document from the object and let the caller pass it in
+ SPObject *marker = doc->getObjectById(b);
+ return marker;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/widgets/stroke-style.h b/src/widgets/stroke-style.h
--- /dev/null
@@ -0,0 +1,35 @@
+/** @file
+ * @brief Stroke style dialog
+ */
+/* Author:
+ * Lauris Kaplinski <lauris@ximian.com>
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_DIALOGS_STROKE_STYLE_H
+#define SEEN_DIALOGS_STROKE_STYLE_H
+
+#include <glib.h>
+
+#include <gtk/gtkwidget.h>
+
+#include "forward.h"
+#include "display/canvas-bpath.h"
+
+GtkWidget *sp_stroke_style_paint_widget_new (void);
+Gtk::Container *sp_stroke_style_line_widget_new (void);
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 14acb188a1d02985b26a6e34346e68925d5865a0..e3dcbcc14a9ebfd3bd63ea2d879633c7e74f32e7 100644 (file)
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
#include "../box3d-context.h"
#include "../box3d.h"
-#include "calligraphic-profile-rename.h"
#include "../conn-avoid-ref.h"
#include "../connection-pool.h"
#include "../connector-context.h"
#include "../svg/css-ostringstream.h"
#include "../tools-switch.h"
#include "../tweak-context.h"
+#include "../ui/dialog/calligraphic-profile-rename.h"
#include "../ui/icon-names.h"
#include "../ui/widget/style-swatch.h"
#include "../verbs.h"