summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/Makefile_insert8
-rw-r--r--src/ui/dialog/Makefile_insert24
-rw-r--r--src/ui/dialog/align-and-distribute.cpp2
-rw-r--r--src/ui/dialog/calligraphic-profile-rename.cpp108
-rw-r--r--src/ui/dialog/calligraphic-profile-rename.h75
-rw-r--r--src/ui/dialog/dialog-manager.cpp13
-rw-r--r--src/ui/dialog/document-metadata.cpp16
-rw-r--r--src/ui/dialog/extensions.cpp129
-rw-r--r--src/ui/dialog/extensions.h56
-rw-r--r--src/ui/dialog/fill-and-stroke.cpp12
-rw-r--r--src/ui/dialog/guides.cpp285
-rw-r--r--src/ui/dialog/guides.h93
-rw-r--r--src/ui/dialog/icon-preview.cpp307
-rw-r--r--src/ui/dialog/icon-preview.h84
-rw-r--r--src/ui/dialog/layer-properties.cpp256
-rw-r--r--src/ui/dialog/layer-properties.h132
-rw-r--r--src/ui/dialog/layers.cpp805
-rw-r--r--src/ui/dialog/layers.h146
-rw-r--r--src/ui/dialog/panel-dialog.h2
-rw-r--r--src/ui/dialog/swatches.cpp1212
-rw-r--r--src/ui/dialog/swatches.h128
-rw-r--r--src/ui/previewable.h2
-rw-r--r--src/ui/previewfillable.h2
-rw-r--r--src/ui/previewholder.h2
-rw-r--r--src/ui/view/edit-widget.h6
-rw-r--r--src/ui/widget/Makefile_insert2
-rw-r--r--src/ui/widget/entity-entry.cpp6
-rw-r--r--src/ui/widget/layer-selector.cpp608
-rw-r--r--src/ui/widget/layer-selector.h110
-rw-r--r--src/ui/widget/licensor.cpp2
-rw-r--r--src/ui/widget/panel.cpp2
31 files changed, 4594 insertions, 41 deletions
diff --git a/src/ui/Makefile_insert b/src/ui/Makefile_insert
index e91c22025..3eb6c6b13 100644
--- a/src/ui/Makefile_insert
+++ b/src/ui/Makefile_insert
@@ -1,9 +1,11 @@
## 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 \
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert
index bf3b6baeb..6a9ebf61f 100644
--- a/src/ui/dialog/Makefile_insert
+++ b/src/ui/dialog/Makefile_insert
@@ -1,11 +1,23 @@
## 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 \
@@ -20,6 +32,8 @@ ink_common_sources += \
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 \
@@ -34,10 +48,18 @@ ink_common_sources += \
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 \
@@ -53,6 +75,8 @@ ink_common_sources += \
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 \
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
index 0a59c004f..d8c4bc005 100644
--- a/src/ui/dialog/align-and-distribute.cpp
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -21,7 +21,7 @@
#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
new file mode 100644
index 000000000..888b327f4
--- /dev/null
+++ b/src/ui/dialog/calligraphic-profile-rename.cpp
@@ -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
new file mode 100644
index 000000000..53ce907ed
--- /dev/null
+++ b/src/ui/dialog/calligraphic-profile-rename.h
@@ -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 :
diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
index 7a8947adf..d1b818d23 100644
--- a/src/ui/dialog/dialog-manager.cpp
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -31,22 +31,21 @@
#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 {
diff --git a/src/ui/dialog/document-metadata.cpp b/src/ui/dialog/document-metadata.cpp
index 32838309a..96cad1fbe 100644
--- a/src/ui/dialog/document-metadata.cpp
+++ b/src/ui/dialog/document-metadata.cpp
@@ -17,18 +17,14 @@
# 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
new file mode 100644
index 000000000..f168da33a
--- /dev/null
+++ b/src/ui/dialog/extensions.cpp
@@ -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
new file mode 100644
index 000000000..8b0fc2780
--- /dev/null
+++ b/src/ui/dialog/extensions.h
@@ -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
diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp
index d28dc7955..fe63c6e24 100644
--- a/src/ui/dialog/fill-and-stroke.cpp
+++ b/src/ui/dialog/fill-and-stroke.cpp
@@ -21,15 +21,13 @@
#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
new file mode 100644
index 000000000..c5d2ae488
--- /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
new file mode 100644
index 000000000..49f94deea
--- /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
new file mode 100644
index 000000000..336afc3c5
--- /dev/null
+++ b/src/ui/dialog/icon-preview.cpp
@@ -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
new file mode 100644
index 000000000..8f143725d
--- /dev/null
+++ b/src/ui/dialog/icon-preview.h
@@ -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
new file mode 100644
index 000000000..ccd91fa2e
--- /dev/null
+++ b/src/ui/dialog/layer-properties.cpp
@@ -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
new file mode 100644
index 000000000..807967e8d
--- /dev/null
+++ b/src/ui/dialog/layer-properties.h
@@ -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
new file mode 100644
index 000000000..0e75401ab
--- /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
new file mode 100644
index 000000000..1f593b9c6
--- /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 :
diff --git a/src/ui/dialog/panel-dialog.h b/src/ui/dialog/panel-dialog.h
index f087f40e4..7dbb6dd4a 100644
--- a/src/ui/dialog/panel-dialog.h
+++ b/src/ui/dialog/panel-dialog.h
@@ -19,7 +19,7 @@
#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
new file mode 100644
index 000000000..dfb60c04e
--- /dev/null
+++ b/src/ui/dialog/swatches.cpp
@@ -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
new file mode 100644
index 000000000..08fc9f79b
--- /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 c517e4f28..ef1ca3ce2 100644
--- a/src/ui/previewable.h
+++ b/src/ui/previewable.h
@@ -14,7 +14,7 @@
#include <gtkmm/widget.h>
-#include "../dialogs/eek-preview.h"
+#include "../widgets/eek-preview.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/previewfillable.h b/src/ui/previewfillable.h
index 6f02b60a8..f863af121 100644
--- a/src/ui/previewfillable.h
+++ b/src/ui/previewfillable.h
@@ -14,7 +14,7 @@
#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 812d4b27d..3c1a16195 100644
--- a/src/ui/previewholder.h
+++ b/src/ui/previewholder.h
@@ -17,7 +17,7 @@
#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 {
diff --git a/src/ui/view/edit-widget.h b/src/ui/view/edit-widget.h
index ea3205696..2bb708305 100644
--- a/src/ui/view/edit-widget.h
+++ b/src/ui/view/edit-widget.h
@@ -28,12 +28,12 @@
#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;
diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert
index 9b4048ea9..b6069631b 100644
--- a/src/ui/widget/Makefile_insert
+++ b/src/ui/widget/Makefile_insert
@@ -31,6 +31,8 @@ ink_common_sources += \
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 \
diff --git a/src/ui/widget/entity-entry.cpp b/src/ui/widget/entity-entry.cpp
index 980d225b2..e9f09f574 100644
--- a/src/ui/widget/entity-entry.cpp
+++ b/src/ui/widget/entity-entry.cpp
@@ -19,11 +19,9 @@
#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
new file mode 100644
index 000000000..51084b127
--- /dev/null
+++ b/src/ui/widget/layer-selector.cpp
@@ -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 ? "&#8226;" : " " ),
+ ( 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
new file mode 100644
index 000000000..0b5300272
--- /dev/null
+++ b/src/ui/widget/layer-selector.h
@@ -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 :
diff --git a/src/ui/widget/licensor.cpp b/src/ui/widget/licensor.cpp
index 24bd5595f..05f00edfc 100644
--- a/src/ui/widget/licensor.cpp
+++ b/src/ui/widget/licensor.cpp
@@ -20,7 +20,7 @@
#include "ui/widget/entity-entry.h"
#include "ui/widget/registry.h"
-#include "dialogs/rdf.h"
+#include "rdf.h"
#include "inkscape.h"
#include "licensor.h"
diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp
index 9811cc89c..82f75c3ff 100644
--- a/src/ui/widget/panel.cpp
+++ b/src/ui/widget/panel.cpp
@@ -29,7 +29,7 @@
#include "preferences.h"
#include "desktop-handles.h"
#include "inkscape.h"
-#include "dialogs/eek-preview.h"
+#include "widgets/eek-preview.h"
namespace Inkscape {
namespace UI {