summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/.cvsignore3
-rw-r--r--src/ui/Makefile_insert18
-rw-r--r--src/ui/dialog/.cvsignore3
-rw-r--r--src/ui/dialog/Makefile_insert63
-rw-r--r--src/ui/dialog/aboutbox.cpp682
-rw-r--r--src/ui/dialog/aboutbox.h50
-rw-r--r--src/ui/dialog/align-and-distribute.cpp1051
-rw-r--r--src/ui/dialog/align-and-distribute.h120
-rw-r--r--src/ui/dialog/dialog-manager.cpp191
-rw-r--r--src/ui/dialog/dialog-manager.h72
-rw-r--r--src/ui/dialog/dialog.cpp359
-rw-r--r--src/ui/dialog/dialog.h94
-rw-r--r--src/ui/dialog/document-metadata.cpp306
-rw-r--r--src/ui/dialog/document-metadata.h84
-rw-r--r--src/ui/dialog/document-properties.cpp503
-rw-r--r--src/ui/dialog/document-properties.h103
-rw-r--r--src/ui/dialog/export.cpp58
-rw-r--r--src/ui/dialog/export.h59
-rw-r--r--src/ui/dialog/extension-editor.cpp48
-rw-r--r--src/ui/dialog/extension-editor.h52
-rw-r--r--src/ui/dialog/fill-and-stroke.cpp62
-rw-r--r--src/ui/dialog/fill-and-stroke.h61
-rw-r--r--src/ui/dialog/find.cpp58
-rw-r--r--src/ui/dialog/find.h59
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp525
-rw-r--r--src/ui/dialog/inkscape-preferences.h140
-rw-r--r--src/ui/dialog/layer-editor.cpp48
-rw-r--r--src/ui/dialog/layer-editor.h52
-rw-r--r--src/ui/dialog/makefile.in17
-rw-r--r--src/ui/dialog/memory.cpp244
-rw-r--r--src/ui/dialog/memory.h54
-rw-r--r--src/ui/dialog/messages.cpp185
-rw-r--r--src/ui/dialog/messages.h98
-rw-r--r--src/ui/dialog/scriptdialog.cpp248
-rw-r--r--src/ui/dialog/scriptdialog.h65
-rw-r--r--src/ui/dialog/session-player.cpp229
-rw-r--r--src/ui/dialog/session-player.h124
-rw-r--r--src/ui/dialog/text-properties.cpp59
-rw-r--r--src/ui/dialog/text-properties.h60
-rw-r--r--src/ui/dialog/tracedialog.cpp562
-rw-r--r--src/ui/dialog/tracedialog.h63
-rw-r--r--src/ui/dialog/transformation.cpp955
-rw-r--r--src/ui/dialog/transformation.h239
-rw-r--r--src/ui/dialog/tree-editor.cpp53
-rw-r--r--src/ui/dialog/tree-editor.h61
-rw-r--r--src/ui/dialog/whiteboard-connect.cpp192
-rw-r--r--src/ui/dialog/whiteboard-connect.h88
-rw-r--r--src/ui/dialog/whiteboard-sharewithchat.cpp147
-rw-r--r--src/ui/dialog/whiteboard-sharewithchat.h93
-rw-r--r--src/ui/dialog/whiteboard-sharewithuser.cpp214
-rw-r--r--src/ui/dialog/whiteboard-sharewithuser.h110
-rw-r--r--src/ui/dialog/xml-editor.cpp48
-rw-r--r--src/ui/dialog/xml-editor.h52
-rw-r--r--src/ui/icons.cpp696
-rw-r--r--src/ui/icons.h36
-rw-r--r--src/ui/makefile.in17
-rw-r--r--src/ui/previewable.h62
-rw-r--r--src/ui/previewfillable.h49
-rw-r--r--src/ui/previewholder.cpp153
-rw-r--r--src/ui/previewholder.h60
-rw-r--r--src/ui/stock-items.cpp215
-rw-r--r--src/ui/stock-items.h37
-rw-r--r--src/ui/stock.cpp187
-rw-r--r--src/ui/stock.h192
-rw-r--r--src/ui/view/.cvsignore3
-rw-r--r--src/ui/view/Makefile_insert27
-rw-r--r--src/ui/view/desktop-affine.cpp0
-rw-r--r--src/ui/view/desktop-affine.h0
-rw-r--r--src/ui/view/desktop-events.cpp0
-rw-r--r--src/ui/view/desktop-events.h0
-rw-r--r--src/ui/view/desktop-handles.cpp0
-rw-r--r--src/ui/view/desktop-handles.h0
-rw-r--r--src/ui/view/desktop-style.cpp0
-rw-r--r--src/ui/view/desktop-style.h0
-rw-r--r--src/ui/view/desktop.cpp0
-rw-r--r--src/ui/view/desktop.h0
-rw-r--r--src/ui/view/edit-widget-interface.h134
-rw-r--r--src/ui/view/edit-widget.cpp1701
-rw-r--r--src/ui/view/edit-widget.h211
-rw-r--r--src/ui/view/edit.cpp28
-rw-r--r--src/ui/view/edit.h27
-rw-r--r--src/ui/view/makefile.in17
-rw-r--r--src/ui/view/view-widget.cpp135
-rw-r--r--src/ui/view/view-widget.h97
-rw-r--r--src/ui/view/view.cpp163
-rw-r--r--src/ui/view/view.h148
-rw-r--r--src/ui/widget/.cvsignore3
-rw-r--r--src/ui/widget/Makefile_insert62
-rw-r--r--src/ui/widget/button.cpp51
-rw-r--r--src/ui/widget/button.h56
-rw-r--r--src/ui/widget/color-picker.cpp167
-rw-r--r--src/ui/widget/color-picker.h65
-rw-r--r--src/ui/widget/color-preview.cpp122
-rw-r--r--src/ui/widget/color-preview.h50
-rw-r--r--src/ui/widget/combo-text.cpp92
-rw-r--r--src/ui/widget/combo-text.h66
-rw-r--r--src/ui/widget/entity-entry.cpp161
-rw-r--r--src/ui/widget/entity-entry.h84
-rw-r--r--src/ui/widget/handlebox.cpp48
-rw-r--r--src/ui/widget/handlebox.h50
-rw-r--r--src/ui/widget/icon-widget.cpp165
-rw-r--r--src/ui/widget/icon-widget.h63
-rw-r--r--src/ui/widget/imageicon.cpp442
-rw-r--r--src/ui/widget/imageicon.h138
-rw-r--r--src/ui/widget/labelled.cpp102
-rw-r--r--src/ui/widget/labelled.h65
-rw-r--r--src/ui/widget/licensor.cpp146
-rw-r--r--src/ui/widget/licensor.h59
-rw-r--r--src/ui/widget/makefile.in17
-rw-r--r--src/ui/widget/notebook-page.cpp49
-rw-r--r--src/ui/widget/notebook-page.h50
-rw-r--r--src/ui/widget/page-sizer.cpp357
-rw-r--r--src/ui/widget/page-sizer.h67
-rw-r--r--src/ui/widget/panel.cpp248
-rw-r--r--src/ui/widget/panel.h80
-rw-r--r--src/ui/widget/preferences-widget.cpp278
-rw-r--r--src/ui/widget/preferences-widget.h117
-rw-r--r--src/ui/widget/registered-widget.cpp409
-rw-r--r--src/ui/widget/registered-widget.h175
-rw-r--r--src/ui/widget/registry.cpp58
-rw-r--r--src/ui/widget/registry.h54
-rw-r--r--src/ui/widget/ruler.cpp197
-rw-r--r--src/ui/widget/ruler.h88
-rw-r--r--src/ui/widget/scalar-unit.cpp252
-rw-r--r--src/ui/widget/scalar-unit.h85
-rw-r--r--src/ui/widget/scalar.cpp217
-rw-r--r--src/ui/widget/scalar.h86
-rw-r--r--src/ui/widget/selected-style.cpp977
-rw-r--r--src/ui/widget/selected-style.h212
-rw-r--r--src/ui/widget/style-swatch.cpp244
-rw-r--r--src/ui/widget/style-swatch.h88
-rw-r--r--src/ui/widget/svg-canvas.cpp92
-rw-r--r--src/ui/widget/svg-canvas.h56
-rw-r--r--src/ui/widget/tolerance-slider.cpp142
-rw-r--r--src/ui/widget/tolerance-slider.h61
-rw-r--r--src/ui/widget/toolbox.cpp269
-rw-r--r--src/ui/widget/toolbox.h73
-rw-r--r--src/ui/widget/unit-menu.cpp181
-rw-r--r--src/ui/widget/unit-menu.h70
-rw-r--r--src/ui/widget/zoom-status.cpp127
-rw-r--r--src/ui/widget/zoom-status.h61
141 files changed, 21373 insertions, 0 deletions
diff --git a/src/ui/.cvsignore b/src/ui/.cvsignore
new file mode 100644
index 000000000..38efca7bc
--- /dev/null
+++ b/src/ui/.cvsignore
@@ -0,0 +1,3 @@
+.deps
+.dirstamp
+makefile
diff --git a/src/ui/Makefile_insert b/src/ui/Makefile_insert
new file mode 100644
index 000000000..f3f24983d
--- /dev/null
+++ b/src/ui/Makefile_insert
@@ -0,0 +1,18 @@
+## Makefile.am fragment sourced by src/Makefile.am.
+
+ui/all: ui/libui.a ui/view/all ui/widget/all ui/dialog/all
+
+ui/clean: ui/widget/clean ui/dialog/clean
+ rm -f ui/libui.a $(ui_libui_a_OBJECTS)
+
+ui_libui_a_SOURCES = \
+ ui/icons.cpp \
+ ui/icons.h \
+ ui/previewable.h \
+ ui/previewfillable.h \
+ ui/previewholder.cpp \
+ ui/previewholder.h \
+ ui/stock-items.cpp \
+ ui/stock-items.h \
+ ui/stock.cpp \
+ ui/stock.h
diff --git a/src/ui/dialog/.cvsignore b/src/ui/dialog/.cvsignore
new file mode 100644
index 000000000..38efca7bc
--- /dev/null
+++ b/src/ui/dialog/.cvsignore
@@ -0,0 +1,3 @@
+.deps
+.dirstamp
+makefile
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert
new file mode 100644
index 000000000..7ab87c7d3
--- /dev/null
+++ b/src/ui/dialog/Makefile_insert
@@ -0,0 +1,63 @@
+## Makefile.am fragment sourced by src/Makefile.am.
+
+ui/dialog/all: ui/dialog/libuidialog.a
+
+ui/dialog/clean:
+ rm -f ui/dialog/libuidialog.a $(ui_libuidialog_a_OBJECTS)
+
+if WITH_INKBOARD
+inkboard_dialogs = \
+ ui/dialog/session-player.cpp \
+ ui/dialog/session-player.h \
+ ui/dialog/whiteboard-connect.cpp \
+ ui/dialog/whiteboard-connect.h \
+ ui/dialog/whiteboard-sharewithuser.cpp \
+ ui/dialog/whiteboard-sharewithuser.h \
+ ui/dialog/whiteboard-sharewithchat.cpp \
+ ui/dialog/whiteboard-sharewithchat.h
+endif
+
+ui_dialog_libuidialog_a_SOURCES = \
+ ui/dialog/dialog-manager.cpp \
+ ui/dialog/dialog-manager.h \
+ ui/dialog/dialog.cpp \
+ ui/dialog/dialog.h \
+ ui/dialog/align-and-distribute.cpp \
+ ui/dialog/align-and-distribute.h \
+ ui/dialog/document-metadata.cpp \
+ ui/dialog/document-metadata.h \
+ ui/dialog/document-properties.cpp \
+ ui/dialog/document-properties.h \
+ ui/dialog/export.cpp \
+ ui/dialog/export.h \
+ ui/dialog/extension-editor.cpp \
+ ui/dialog/extension-editor.h \
+ ui/dialog/fill-and-stroke.cpp \
+ ui/dialog/fill-and-stroke.h \
+ ui/dialog/find.cpp \
+ ui/dialog/find.h \
+ ui/dialog/inkscape-preferences.cpp \
+ ui/dialog/inkscape-preferences.h \
+ ui/dialog/layer-editor.cpp \
+ ui/dialog/layer-editor.h \
+ ui/dialog/memory.cpp \
+ ui/dialog/memory.h \
+ ui/dialog/messages.cpp \
+ ui/dialog/messages.h \
+ ui/dialog/scriptdialog.cpp \
+ ui/dialog/scriptdialog.h \
+ ui/dialog/text-properties.cpp \
+ ui/dialog/text-properties.h \
+ ui/dialog/tracedialog.cpp \
+ ui/dialog/tracedialog.h \
+ ui/dialog/transformation.cpp \
+ ui/dialog/transformation.h \
+ ui/dialog/tree-editor.cpp \
+ ui/dialog/tree-editor.h \
+ $(inkboard_dialogs) \
+ ui/dialog/xml-editor.cpp \
+ ui/dialog/xml-editor.h \
+ ui/dialog/aboutbox.cpp \
+ ui/dialog/aboutbox.h
+
+ui/dialog/aboutbox.$(OBJEXT): inkscape_version.h
diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp
new file mode 100644
index 000000000..4ad2413fc
--- /dev/null
+++ b/src/ui/dialog/aboutbox.cpp
@@ -0,0 +1,682 @@
+/**
+ * \brief AboutBox - the Inkscape about dialog
+ *
+ * Authors:
+ * Derek P. Moore <derekm@hackunix.org>
+ * MenTaLguY <mental@rydia.net>
+ * Kees Cook <kees@outflux.net>
+ * Jon Phillips <jon@rejon.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ * Copyright 2004 Kees Cook
+ * Copyright 2004 Jon Phillips
+ * Copyright 2005 MenTaLguY
+ *
+ * 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/notebook.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/aspectframe.h>
+#include <gtkmm/textview.h>
+#include <gtkmm/stock.h>
+
+#include "path-prefix.h"
+#include "document.h"
+#include "svg-view-widget.h"
+#include "sp-text.h"
+#include "text-editing.h"
+#include "ui/dialog/aboutbox.h"
+
+#include "inkscape_version.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+static Gtk::Widget *build_splash_widget();
+static gchar const *authors_text();
+static gchar const *translators_text();
+static gchar const *license_text();
+
+static Gtk::ScrolledWindow *make_scrolled_text(gchar const *contents);
+
+static AboutBox *window=NULL;
+
+void AboutBox::show_about() {
+ if (!window) {
+ window = new AboutBox();
+ }
+ window->show();
+}
+
+void AboutBox::hide_about() {
+ if (window) {
+ window->hide();
+ }
+}
+
+AboutBox::AboutBox() : Gtk::Dialog(_("About Inkscape")) {
+ Gtk::Notebook *tabs=new Gtk::Notebook();
+
+ tabs->set_scrollable();
+
+ Gtk::Widget *splash=build_splash_widget();
+ if (splash) {
+ tabs->append_page(*manage(splash), _("_Splash"), true);
+ }
+ tabs->append_page(*manage(make_scrolled_text(authors_text())), _("_Authors"), true);
+ tabs->append_page(*manage(make_scrolled_text(translators_text())), _("_Translators"), true);
+ tabs->append_page(*manage(make_scrolled_text(license_text())), _("_License"), true);
+
+ get_vbox()->pack_end(*manage(tabs), true, true);
+ tabs->show_all();
+
+ add_button(Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE);
+ set_default_response(Gtk::RESPONSE_CLOSE);
+
+ Gtk::Label *label=new Gtk::Label();
+ gchar *label_text=g_strdup_printf("<small><i>Inkscape %s, built %s</i></small>", INKSCAPE_VERSION, __DATE__);
+ label->set_markup(label_text);
+ label->set_alignment(Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
+ g_free(label_text);
+ label->set_selectable(true);
+ label->show();
+
+ get_vbox()->pack_start(*manage(label), false, false);
+
+ Gtk::Requisition requisition;
+ gtk_widget_size_request (reinterpret_cast<GtkWidget*>(gobj()), &requisition);
+ // allow window to shrink
+ set_size_request(0, 0);
+ set_default_size(requisition.width, requisition.height);
+}
+
+void AboutBox::on_response(int response_id) {
+ if ( response_id == Gtk::RESPONSE_CLOSE ) {
+ AboutBox::hide_about();
+ }
+}
+
+Gtk::Widget *build_splash_widget() {
+ /* TRANSLATORS: This is the filename of the `About Inkscape' picture in
+ the `screens' directory. Thus the translation of "about.svg" should be
+ the filename of its translated version, e.g. about.zh.svg for Chinese.
+
+ N.B. about.svg changes once per release. (We should probably rename
+ the original to about-0.40.svg etc. as soon as we have a translation.
+ If we do so, then add an item to release-checklist saying that the
+ string here should be changed.) */
+
+ // FIXME? INKSCAPE_SCREENSDIR and "about.svg" are in UTF-8, not the
+ // native filename encoding... and the filename passed to sp_document_new
+ // should be in UTF-*8..
+
+ char *about=g_build_filename(INKSCAPE_SCREENSDIR, _("about.svg"), NULL);
+ SPDocument *doc=sp_document_new (about, TRUE);
+ g_free(about);
+ g_return_val_if_fail(doc != NULL, NULL);
+
+ SPObject *version = doc->getObjectById("version");
+ if ( version && SP_IS_TEXT(version) ) {
+ sp_te_set_repr_text_multiline (SP_TEXT (version), INKSCAPE_VERSION);
+ }
+ sp_document_ensure_up_to_date(doc);
+
+ GtkWidget *v=sp_svg_view_widget_new(doc);
+
+ double width=sp_document_width(doc);
+ double height=sp_document_height(doc);
+
+ sp_document_unref(doc);
+
+ sp_svg_view_widget_set_resize(SP_SVG_VIEW_WIDGET(v), FALSE, (int)width, (int)height);
+
+ Gtk::AspectFrame *frame=new Gtk::AspectFrame();
+ frame->unset_label();
+ frame->set_shadow_type(Gtk::SHADOW_NONE);
+ frame->property_ratio() = width / height;
+ frame->add(*manage(Glib::wrap(v)));
+
+ return frame;
+}
+
+static Gtk::ScrolledWindow *make_scrolled_text(gchar const *contents) {
+ // This attempts to emulate the AboutDialog child dialog settings as
+ // closely as possible. Mostly, that's margin widths and shadows. Size
+ // is probably set in some other way, but this looked close enough.
+ Gtk::ScrolledWindow *scrolled=new Gtk::ScrolledWindow();
+
+ scrolled->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ scrolled->set_shadow_type(Gtk::SHADOW_IN);
+
+ Gtk::TextView *textview=manage(new Gtk::TextView());
+ textview->set_editable(false);
+ textview->set_left_margin(10);
+ textview->set_right_margin(10);
+ textview->get_buffer()->set_text(contents);
+ scrolled->add(*textview);
+
+ return scrolled;
+}
+
+gchar const *authors_text() {
+ static gchar const text[]=
+ "Josh Andler\n"
+ "John Bintz\n"
+ "Arpad Biro\n"
+ "Daniel Borgmann\n"
+ "Hans Breuer\n"
+ "Nicu Buculei\n"
+ "Bulia Byak\n"
+ "Chema Celorio\n"
+ "Johan Ceuppens\n"
+ "Zbigniew Chyla\n"
+ "Alexander Clausen\n"
+ "John Cliff\n"
+ "Kees Cook\n"
+ "Ben Cromwell\n"
+ "Robert Crosbie\n"
+ "Jon Cruz\n"
+ "Daniel Díaz\n"
+ "Larry Doolittle\n"
+ "Tim Dwyer\n"
+ "Maxim V. Dziumanenko\n"
+ "Danilo Egan\n"
+ "Frank Felfe\n"
+ "Andrew Fitzsimon\n"
+ "Edward Flick\n"
+ "Fred\n"
+ "Ben Fowler\n"
+ "Ted Gould\n"
+ "Bryce Harrington\n"
+ "Carl Hetherington\n"
+ "Karl Ove Hufthammer\n"
+ "Richard Hughes\n"
+ "Nathan Hurst\n"
+ "Thomas Ingham\n"
+ "Bob Jamison\n"
+ "Lauris Kaplinski\n"
+ "Lynn Kerby\n"
+ "Petr Kovar\n"
+ "Raph Levien\n"
+ "Nicklas Lindgren\n"
+ "Vitaly Lipatov\n"
+ "Colin Marquardt\n"
+ "Dmitry G. Mastrukov\n"
+ "Matiphas\n"
+ "Michael Meeks\n"
+ "Federico Mena\n"
+ "MenTaLguY\n"
+ "Aubanel Monnier\n"
+ "Derek P. Moore\n"
+ "Peter Moulder\n"
+ "Jörg Müller\n"
+ "Yukihiro Nakai\n"
+ "Christian Neumair\n"
+ "Andreas Nilsson\n"
+ "Mitsuru Oka\n"
+ "Jon Phillips\n"
+ "Zdenko Podobny\n"
+ "Alexandre Prokoudine\n"
+ "Alexey Remizov\n"
+ "Frederic Rodrigo\n"
+ "Juarez Rudsatz\n"
+ "Xavier Conde Rueda\n"
+ "Christian Schaller\n"
+ "Tom von Schwerdtner\n"
+ "Shivaken\n"
+ "Boštjan Špetič\n"
+ "Aaron Spike\n"
+ "Kaushik Sridharan\n"
+ "Ralf Stephan\n"
+ "Dariusz Stojek\n"
+ "Pat Suwalski\n"
+ "Adib Taraben\n"
+ "David Turner\n"
+ "Aleksandar Urosevic\n"
+ "Lucas Vieites\n"
+ "Michael Wybrow\n"
+ "Daniel Yacob\n"
+ "David Yip\n"
+ "Masatake Yamato";
+
+ return text;
+}
+
+gchar const *translators_text() {
+ static char const text[]=
+ "Adib Taraben <theadib@yahoo.com>, 2004.\n"
+ "Alastair McKinstry <mckinstry@computer.org>, 2000.\n"
+ "Aleksandar Urošević <urke@users.sourceforge.net>\n"
+ "Alessio Frusciante <algol@firenze.linux.it>, 2002, 2003.\n"
+ "Alexandre Prokoudine <alexandre.prokoudine@gmail.com>, 2005.\n"
+ "Alexey Remizov <alexey@remizov.pp.ru>, 2004.\n"
+ "Álvaro Lopes <alvieboy@alvie.com>, 2001, 2002\n"
+ "Andreas Hyden <a.hyden@cyberpoint.se>, 2000.\n"
+ "Arman Aksoy <armish@linux-sevenler.de>, 2003.\n"
+ "Arpad Biro <biro_arpad@yahoo.com>, 2004, 2005.\n"
+ "Benedikt Roth <Benedikt.Roth@gmx.net>, 2000\n"
+ "Boštjan Špetič <igzebedze@cyberpipe.org>, 2004, 2005.\n"
+ "Brisa Francesco <fbrisa@yahoo.it>, 2000.\n"
+ "bulia byak <buliabyak@users.sf.net>, 2004.\n"
+ "Christian Meyer <chrisime@gnome.org>, 2000-2002.\n"
+ "Christian Neumair <chris@gnome-de.org>, 2002, 2003.\n"
+ "Christian Rose <menthos@menthos.com>, 2000, 2001, 2002, 2003.\n"
+ "Christophe Merlet (RedFox) <redfox@redfoxcenter.org>, 2000-2002.\n"
+ "Colin Marquardt <colin@marquardt-home.de>, 2004, 2005.\n"
+ "Daniel Díaz <yosoy@danieldiaz.org>, 2004\n"
+ "Александар Урошевић <urke@users.sourceforge.net>\n"
+ "Didier Conchaudron <conchaudron@free.fr>, 2003.\n"
+ "Duarte Loreto <happyguy_pt@hotmail.com> 2002,2003 (Maintainer)\n"
+ "Fatih Demir <kabalak@gtranslator.org>, 2000.\n"
+ "Francesc Dorca <f.dorca@filnet.es>, 2003. Traducció sodipodi.\n"
+ "Francisco Javier F. Serrador <serrador@arrakis.es>, 2003.\n"
+ "Francisco Xosé Vázquez Grandal <fxvazquez@arrakis.es>, 2001.\n"
+ "Frederic Rodrigo <f.rodrigo free.fr>, 2004-2005.\n"
+ "Ge'ez Frontier Foundation <locales@geez.org>, 2002.\n"
+ "Jörg Müller <jfm@ram-brand.de>, 2005.\n"
+ "Jeroen van der Vegt <ajvdvegt (at) 123mail.org>, 2003, 2005.\n"
+ "Jose Antonio Salgueiro Aquino <developer@telefonica.net>, 2003.\n"
+ "Josef Vybiral <josef.vybiral@gmail.com>, 2005.\n"
+ "Juarez Rudsatz <juarez@correio.com>, 2004\n"
+ "Junichi Uekawa <dancer@debian.org>, 2002.\n"
+ "Kai Lahmann <kailahmann@01019freenet.de>, 2000\n"
+ "Karl Ove Hufthammer <karl@huftis.org>, 2004, 2005.\n"
+ "Keld Simonsen <keld@dkuug.dk>, 2000-2001.\n"
+ "Kjartan Maraas <kmaraas@gnome.org>, 2000-2002.\n"
+ "Lauris Kaplinski <lauris@ariman.ee>, 2000.\n"
+ "Luca Bruno <luca.br@uno.it>, 2005.\n"
+ "Lucas Vieites Fariña<lucas@asixinformatica.com>, 2003-2005.\n"
+ "Martin Srebotnjak, <miles@filmsi.net>, 2005.\n"
+ "Masatake YAMATO <jet@gyve.org>, 2002.\n"
+ "Matiphas <matiphas _a_ free _point_ fr>, 2004.\n"
+ "Mattias Hultgren <mattias_hultgren@tele2.se>, 2005.\n"
+ "Maxim Dziumanenko <mvd@mylinux.com.ua>, 2004\n"
+ "Mitsuru Oka <oka326@parkcity.ne.jp>, 2001-2002.\n"
+ "Mufit Eribol <meribol@ere.com.tr>, 2000.\n"
+ "Quico Llach <quico@softcatala.org>, 2000. Traducció sodipodi.\n"
+ "Raymond Ostertag <raymond@linuxgraphic.org>, 2002-2003.\n"
+ "shivaken <shivaken@owls-nest.net>, 2004.\n"
+ "Simos Xenitellis <simos@hellug.gr>, 2001.\n"
+ "Takeshi Aihana <aihana@muc.biglobe.ne.jp>, 2000-2001.\n"
+ "Jose Antonio Salgueiro <developer@telefonica.net>.\n"
+ "Valek Filippov <frob@df.ru>, 2000, 2003.\n"
+ "Vincent van Adrighem <V.vanAdrighem@dirck.mine.nu>, 2003.\n"
+ "Vital Khilko <dojlid@mova.org>, 2003\n"
+ "Vitaly Lipatov <lav@altlinux.ru>, 2002, 2004.\n"
+ "Wang Li <charlesw1234@163.com>, 2002\n"
+ "Xavier Conde Rueda <xavi.conde@gmail.com>, 2004, 2005\n"
+ "Yukihiro Nakai <nakai@gnome.gr.jp>, 2000, 2003.\n"
+ "Yuri Syrota <rasta@renome.rovno.ua>, 2000.\n"
+ "Zdenko Podobný <zdpo@mailbox.sk>, 2003, 2004.";
+
+ return text;
+}
+
+gchar const *license_text() {
+ static gchar const text[]=
+" GNU GENERAL PUBLIC LICENSE\n\
+ Version 2, June 1991\n\
+\n\
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n\
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\
+ Everyone is permitted to copy and distribute verbatim copies\n\
+ of this license document, but changing it is not allowed.\n\
+\n\
+ Preamble\n\
+\n\
+ The licenses for most software are designed to take away your\n\
+freedom to share and change it. By contrast, the GNU General Public\n\
+License is intended to guarantee your freedom to share and change free\n\
+software--to make sure the software is free for all its users. This\n\
+General Public License applies to most of the Free Software\n\
+Foundation's software and to any other program whose authors commit to\n\
+using it. (Some other Free Software Foundation software is covered by\n\
+the GNU Library General Public License instead.) You can apply it to\n\
+your programs, too.\n\
+\n\
+ When we speak of free software, we are referring to freedom, not\n\
+price. Our General Public Licenses are designed to make sure that you\n\
+have the freedom to distribute copies of free software (and charge for\n\
+this service if you wish), that you receive source code or can get it\n\
+if you want it, that you can change the software or use pieces of it\n\
+in new free programs; and that you know you can do these things.\n\
+\n\
+ To protect your rights, we need to make restrictions that forbid\n\
+anyone to deny you these rights or to ask you to surrender the rights.\n\
+These restrictions translate to certain responsibilities for you if you\n\
+distribute copies of the software, or if you modify it.\n\
+\n\
+ For example, if you distribute copies of such a program, whether\n\
+gratis or for a fee, you must give the recipients all the rights that\n\
+you have. You must make sure that they, too, receive or can get the\n\
+source code. And you must show them these terms so they know their\n\
+rights.\n\
+\n\
+ We protect your rights with two steps: (1) copyright the software, and\n\
+(2) offer you this license which gives you legal permission to copy,\n\
+distribute and/or modify the software.\n\
+\n\
+ Also, for each author's protection and ours, we want to make certain\n\
+that everyone understands that there is no warranty for this free\n\
+software. If the software is modified by someone else and passed on, we\n\
+want its recipients to know that what they have is not the original, so\n\
+that any problems introduced by others will not reflect on the original\n\
+authors' reputations.\n\
+\n\
+ Finally, any free program is threatened constantly by software\n\
+patents. We wish to avoid the danger that redistributors of a free\n\
+program will individually obtain patent licenses, in effect making the\n\
+program proprietary. To prevent this, we have made it clear that any\n\
+patent must be licensed for everyone's free use or not licensed at all.\n\
+\n\
+ The precise terms and conditions for copying, distribution and\n\
+modification follow.\n\
+\n\
+ GNU GENERAL PUBLIC LICENSE\n\
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\
+\n\
+ 0. This License applies to any program or other work which contains\n\
+a notice placed by the copyright holder saying it may be distributed\n\
+under the terms of this General Public License. The \"Program\", below,\n\
+refers to any such program or work, and a \"work based on the Program\"\n\
+means either the Program or any derivative work under copyright law:\n\
+that is to say, a work containing the Program or a portion of it,\n\
+either verbatim or with modifications and/or translated into another\n\
+language. (Hereinafter, translation is included without limitation in\n\
+the term \"modification\".) Each licensee is addressed as \"you\".\n\
+\n\
+Activities other than copying, distribution and modification are not\n\
+covered by this License; they are outside its scope. The act of\n\
+running the Program is not restricted, and the output from the Program\n\
+is covered only if its contents constitute a work based on the\n\
+Program (independent of having been made by running the Program).\n\
+Whether that is true depends on what the Program does.\n\
+\n\
+ 1. You may copy and distribute verbatim copies of the Program's\n\
+source code as you receive it, in any medium, provided that you\n\
+conspicuously and appropriately publish on each copy an appropriate\n\
+copyright notice and disclaimer of warranty; keep intact all the\n\
+notices that refer to this License and to the absence of any warranty;\n\
+and give any other recipients of the Program a copy of this License\n\
+along with the Program.\n\
+\n\
+You may charge a fee for the physical act of transferring a copy, and\n\
+you may at your option offer warranty protection in exchange for a fee.\n\
+\n\
+ 2. You may modify your copy or copies of the Program or any portion\n\
+of it, thus forming a work based on the Program, and copy and\n\
+distribute such modifications or work under the terms of Section 1\n\
+above, provided that you also meet all of these conditions:\n\
+\n\
+ a) You must cause the modified files to carry prominent notices\n\
+ stating that you changed the files and the date of any change.\n\
+\n\
+ b) You must cause any work that you distribute or publish, that in\n\
+ whole or in part contains or is derived from the Program or any\n\
+ part thereof, to be licensed as a whole at no charge to all third\n\
+ parties under the terms of this License.\n\
+\n\
+ c) If the modified program normally reads commands interactively\n\
+ when run, you must cause it, when started running for such\n\
+ interactive use in the most ordinary way, to print or display an\n\
+ announcement including an appropriate copyright notice and a\n\
+ notice that there is no warranty (or else, saying that you provide\n\
+ a warranty) and that users may redistribute the program under\n\
+ these conditions, and telling the user how to view a copy of this\n\
+ License. (Exception: if the Program itself is interactive but\n\
+ does not normally print such an announcement, your work based on\n\
+ the Program is not required to print an announcement.)\n\
+\n\
+These requirements apply to the modified work as a whole. If\n\
+identifiable sections of that work are not derived from the Program,\n\
+and can be reasonably considered independent and separate works in\n\
+themselves, then this License, and its terms, do not apply to those\n\
+sections when you distribute them as separate works. But when you\n\
+distribute the same sections as part of a whole which is a work based\n\
+on the Program, the distribution of the whole must be on the terms of\n\
+this License, whose permissions for other licensees extend to the\n\
+entire whole, and thus to each and every part regardless of who wrote it.\n\
+\n\
+Thus, it is not the intent of this section to claim rights or contest\n\
+your rights to work written entirely by you; rather, the intent is to\n\
+exercise the right to control the distribution of derivative or\n\
+collective works based on the Program.\n\
+\n\
+In addition, mere aggregation of another work not based on the Program\n\
+with the Program (or with a work based on the Program) on a volume of\n\
+a storage or distribution medium does not bring the other work under\n\
+the scope of this License.\n\
+\n\
+ 3. You may copy and distribute the Program (or a work based on it,\n\
+under Section 2) in object code or executable form under the terms of\n\
+Sections 1 and 2 above provided that you also do one of the following:\n\
+\n\
+ a) Accompany it with the complete corresponding machine-readable\n\
+ source code, which must be distributed under the terms of Sections\n\
+ 1 and 2 above on a medium customarily used for software interchange; or,\n\
+\n\
+ b) Accompany it with a written offer, valid for at least three\n\
+ years, to give any third party, for a charge no more than your\n\
+ cost of physically performing source distribution, a complete\n\
+ machine-readable copy of the corresponding source code, to be\n\
+ distributed under the terms of Sections 1 and 2 above on a medium\n\
+ customarily used for software interchange; or,\n\
+\n\
+ c) Accompany it with the information you received as to the offer\n\
+ to distribute corresponding source code. (This alternative is\n\
+ allowed only for noncommercial distribution and only if you\n\
+ received the program in object code or executable form with such\n\
+ an offer, in accord with Subsection b above.)\n\
+\n\
+The source code for a work means the preferred form of the work for\n\
+making modifications to it. For an executable work, complete source\n\
+code means all the source code for all modules it contains, plus any\n\
+associated interface definition files, plus the scripts used to\n\
+control compilation and installation of the executable. However, as a\n\
+special exception, the source code distributed need not include\n\
+anything that is normally distributed (in either source or binary\n\
+form) with the major components (compiler, kernel, and so on) of the\n\
+operating system on which the executable runs, unless that component\n\
+itself accompanies the executable.\n\
+\n\
+If distribution of executable or object code is made by offering\n\
+access to copy from a designated place, then offering equivalent\n\
+access to copy the source code from the same place counts as\n\
+distribution of the source code, even though third parties are not\n\
+compelled to copy the source along with the object code.\n\
+\n\
+ 4. You may not copy, modify, sublicense, or distribute the Program\n\
+except as expressly provided under this License. Any attempt\n\
+otherwise to copy, modify, sublicense or distribute the Program is\n\
+void, and will automatically terminate your rights under this License.\n\
+However, parties who have received copies, or rights, from you under\n\
+this License will not have their licenses terminated so long as such\n\
+parties remain in full compliance.\n\
+\n\
+ 5. You are not required to accept this License, since you have not\n\
+signed it. However, nothing else grants you permission to modify or\n\
+distribute the Program or its derivative works. These actions are\n\
+prohibited by law if you do not accept this License. Therefore, by\n\
+modifying or distributing the Program (or any work based on the\n\
+Program), you indicate your acceptance of this License to do so, and\n\
+all its terms and conditions for copying, distributing or modifying\n\
+the Program or works based on it.\n\
+\n\
+ 6. Each time you redistribute the Program (or any work based on the\n\
+Program), the recipient automatically receives a license from the\n\
+original licensor to copy, distribute or modify the Program subject to\n\
+these terms and conditions. You may not impose any further\n\
+restrictions on the recipients' exercise of the rights granted herein.\n\
+You are not responsible for enforcing compliance by third parties to\n\
+this License.\n\
+\n\
+ 7. If, as a consequence of a court judgment or allegation of patent\n\
+infringement or for any other reason (not limited to patent issues),\n\
+conditions are imposed on you (whether by court order, agreement or\n\
+otherwise) that contradict the conditions of this License, they do not\n\
+excuse you from the conditions of this License. If you cannot\n\
+distribute so as to satisfy simultaneously your obligations under this\n\
+License and any other pertinent obligations, then as a consequence you\n\
+may not distribute the Program at all. For example, if a patent\n\
+license would not permit royalty-free redistribution of the Program by\n\
+all those who receive copies directly or indirectly through you, then\n\
+the only way you could satisfy both it and this License would be to\n\
+refrain entirely from distribution of the Program.\n\
+\n\
+If any portion of this section is held invalid or unenforceable under\n\
+any particular circumstance, the balance of the section is intended to\n\
+apply and the section as a whole is intended to apply in other\n\
+circumstances.\n\
+\n\
+It is not the purpose of this section to induce you to infringe any\n\
+patents or other property right claims or to contest validity of any\n\
+such claims; this section has the sole purpose of protecting the\n\
+integrity of the free software distribution system, which is\n\
+implemented by public license practices. Many people have made\n\
+generous contributions to the wide range of software distributed\n\
+through that system in reliance on consistent application of that\n\
+system; it is up to the author/donor to decide if he or she is willing\n\
+to distribute software through any other system and a licensee cannot\n\
+impose that choice.\n\
+\n\
+This section is intended to make thoroughly clear what is believed to\n\
+be a consequence of the rest of this License.\n\
+\n\
+ 8. If the distribution and/or use of the Program is restricted in\n\
+certain countries either by patents or by copyrighted interfaces, the\n\
+original copyright holder who places the Program under this License\n\
+may add an explicit geographical distribution limitation excluding\n\
+those countries, so that distribution is permitted only in or among\n\
+countries not thus excluded. In such case, this License incorporates\n\
+the limitation as if written in the body of this License.\n\
+\n\
+ 9. The Free Software Foundation may publish revised and/or new versions\n\
+of the General Public License from time to time. Such new versions will\n\
+be similar in spirit to the present version, but may differ in detail to\n\
+address new problems or concerns.\n\
+\n\
+Each version is given a distinguishing version number. If the Program\n\
+specifies a version number of this License which applies to it and \"any\n\
+later version\", you have the option of following the terms and conditions\n\
+either of that version or of any later version published by the Free\n\
+Software Foundation. If the Program does not specify a version number of\n\
+this License, you may choose any version ever published by the Free Software\n\
+Foundation.\n\
+\n\
+ 10. If you wish to incorporate parts of the Program into other free\n\
+programs whose distribution conditions are different, write to the author\n\
+to ask for permission. For software which is copyrighted by the Free\n\
+Software Foundation, write to the Free Software Foundation; we sometimes\n\
+make exceptions for this. Our decision will be guided by the two goals\n\
+of preserving the free status of all derivatives of our free software and\n\
+of promoting the sharing and reuse of software generally.\n\
+\n\
+ NO WARRANTY\n\
+\n\
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n\
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n\
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n\
+PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n\
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n\
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n\
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n\
+REPAIR OR CORRECTION.\n\
+\n\
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n\
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n\
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n\
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n\
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n\
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n\
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n\
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n\
+POSSIBILITY OF SUCH DAMAGES.\n\
+\n\
+ END OF TERMS AND CONDITIONS\n\
+\n\
+ How to Apply These Terms to Your New Programs\n\
+\n\
+ If you develop a new program, and you want it to be of the greatest\n\
+possible use to the public, the best way to achieve this is to make it\n\
+free software which everyone can redistribute and change under these terms.\n\
+\n\
+ To do so, attach the following notices to the program. It is safest\n\
+to attach them to the start of each source file to most effectively\n\
+convey the exclusion of warranty; and each file should have at least\n\
+the \"copyright\" line and a pointer to where the full notice is found.\n\
+\n\
+ <one line to give the program's name and a brief idea of what it does.>\n\
+ Copyright (C) <year> <name of author>\n\
+\n\
+ This program is free software; you can redistribute it and/or modify\n\
+ it under the terms of the GNU General Public License as published by\n\
+ the Free Software Foundation; either version 2 of the License, or\n\
+ (at your option) any later version.\n\
+\n\
+ This program is distributed in the hope that it will be useful,\n\
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
+ GNU General Public License for more details.\n\
+\n\
+ You should have received a copy of the GNU General Public License\n\
+ along with this program; if not, write to the Free Software\n\
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\
+\n\
+\n\
+Also add information on how to contact you by electronic and paper mail.\n\
+\n\
+If the program is interactive, make it output a short notice like this\n\
+when it starts in an interactive mode:\n\
+\n\
+ Gnomovision version 69, Copyright (C) year name of author\n\
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n\
+ This is free software, and you are welcome to redistribute it\n\
+ under certain conditions; type `show c' for details.\n\
+\n\
+The hypothetical commands `show w' and `show c' should show the appropriate\n\
+parts of the General Public License. Of course, the commands you use may\n\
+be called something other than `show w' and `show c'; they could even be\n\
+mouse-clicks or menu items--whatever suits your program.\n\
+\n\
+You should also get your employer (if you work as a programmer) or your\n\
+school, if any, to sign a \"copyright disclaimer\" for the program, if\n\
+necessary. Here is a sample; alter the names:\n\
+\n\
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n\
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\
+\n\
+ <signature of Ty Coon>, 1 April 1989\n\
+ Ty Coon, President of Vice\n\
+\n\
+This General Public License does not permit incorporating your program into\n\
+proprietary programs. If your program is a subroutine library, you may\n\
+consider it more useful to permit linking proprietary applications with the\n\
+library. If this is what you want to do, use the GNU Library General\n\
+Public License instead of this License.";
+
+ return text;
+}
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/dialog/aboutbox.h b/src/ui/dialog/aboutbox.h
new file mode 100644
index 000000000..50627b57d
--- /dev/null
+++ b/src/ui/dialog/aboutbox.h
@@ -0,0 +1,50 @@
+/**
+ * \brief About Widget - Adds the "about" doc to the Gnome::UI::About Class
+ *
+ * The standard Gnome::UI::About class doesn't include a place to stuff
+ * a renderable View that holds the classic Inkscape "about.svg".
+ *
+ * Author:
+ * Kees Cook <kees@outflux.net>
+ *
+ * Copyright (C) 2005 Kees Cook
+ *
+ * Released under GNU GPL v2+. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_ABOUTBOX_H
+#define INKSCAPE_UI_DIALOG_ABOUTBOX_H
+
+#include <gtkmm/dialog.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class AboutBox : public Gtk::Dialog {
+public:
+ static void show_about();
+ static void hide_about();
+
+private:
+ AboutBox();
+
+ virtual void on_response(int response_id);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_ABOUTBOX_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
new file mode 100644
index 000000000..262aa690b
--- /dev/null
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -0,0 +1,1051 @@
+/**
+ * \brief Align and Distribute dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Aubanel MONNIER <aubi@libertysurf.fr>
+ * Frank Felfe <innerspace@iname.com>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Tim Dwyer <tgdwyer@gmail.com>
+ *
+ * Copyright (C) 1999-2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "verbs.h"
+
+#include "dialogs/unclump.h"
+#include "removeoverlap/removeoverlap.h"
+
+#include <gtkmm/spinbutton.h>
+
+
+
+
+#include "util/glib-list-iterators.h"
+
+#include "widgets/icon.h"
+
+#include "inkscape.h"
+#include "document.h"
+#include "selection.h"
+#include "desktop-handles.h"
+#include "macros.h"
+#include "sp-item-transform.h"
+#include "prefs-utils.h"
+#include "enums.h"
+
+#include "sp-text.h"
+#include "sp-flowtext.h"
+#include "text-editing.h"
+
+#include "node-context.h" //For node align/distribute function
+
+#include "tools-switch.h"
+
+#include "align-and-distribute.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+/////////helper classes//////////////////////////////////
+
+class Action {
+public :
+ Action(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row, guint column,
+ Gtk::Table &parent,
+ Gtk::Tooltips &tooltips,
+ AlignAndDistribute &dialog):
+ _dialog(dialog),
+ _id(id),
+ _parent(parent)
+ {
+ Gtk::Widget* pIcon = Gtk::manage( sp_icon_get_icon( _id, GTK_ICON_SIZE_LARGE_TOOLBAR) );
+ Gtk::Button * pButton = Gtk::manage(new Gtk::Button());
+ pButton->set_relief(Gtk::RELIEF_NONE);
+ pIcon->show();
+ pButton->add(*pIcon);
+ pButton->show();
+
+ pButton->signal_clicked()
+ .connect(sigc::mem_fun(*this, &Action::on_button_click));
+ tooltips.set_tip(*pButton, tiptext);
+ parent.attach(*pButton, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL);
+ }
+ virtual ~Action(){}
+
+ AlignAndDistribute &_dialog;
+
+private :
+ virtual void on_button_click(){}
+
+ Glib::ustring _id;
+ Gtk::Table &_parent;
+};
+
+
+class ActionAlign : public Action {
+public :
+ struct Coeffs {
+ double mx0, mx1, my0, my1;
+ double sx0, sx1, sy0, sy1;
+ };
+ ActionAlign(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row, guint column,
+ AlignAndDistribute &dialog,
+ guint coeffIndex):
+ Action(id, tiptext, row, column,
+ dialog.align_table(), dialog.tooltips(), dialog),
+ _index(coeffIndex),
+ _dialog(dialog)
+ {}
+
+private :
+
+ virtual void on_button_click() {
+ //Retreive selected objects
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop) return;
+
+ Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+ if (!selection) return;
+
+ using Inkscape::Util::GSListConstIterator;
+ std::list<SPItem *> selected;
+ selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ if (selected.empty()) return;
+
+ NR::Point mp; //Anchor point
+ AlignAndDistribute::AlignTarget target = _dialog.getAlignTarget();
+ const Coeffs &a= _allCoeffs[_index];
+ switch (target)
+ {
+ case AlignAndDistribute::LAST:
+ case AlignAndDistribute::FIRST:
+ case AlignAndDistribute::BIGGEST:
+ case AlignAndDistribute::SMALLEST:
+ {
+ //Check 2 or more selected objects
+ std::list<SPItem *>::iterator second(selected.begin());
+ ++second;
+ if (second == selected.end())
+ return;
+ //Find the master (anchor on which the other objects are aligned)
+ std::list<SPItem *>::iterator master(
+ _dialog.find_master (
+ selected,
+ (a.mx0 != 0.0) ||
+ (a.mx1 != 0.0) )
+ );
+ //remove the master from the selection
+ SPItem * thing = *master;
+ selected.erase(master);
+ //Compute the anchor point
+ NR::Rect b = sp_item_bbox_desktop (thing);
+ mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X],
+ a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]);
+ break;
+ }
+
+ case AlignAndDistribute::PAGE:
+ mp = NR::Point(a.mx1 * sp_document_width(SP_DT_DOCUMENT(desktop)),
+ a.my1 * sp_document_height(SP_DT_DOCUMENT(desktop)));
+ break;
+
+ case AlignAndDistribute::DRAWING:
+ {
+ NR::Rect b = sp_item_bbox_desktop
+ ( (SPItem *) sp_document_root (SP_DT_DOCUMENT (desktop)) );
+ mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X],
+ a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]);
+ break;
+ }
+
+ case AlignAndDistribute::SELECTION:
+ {
+ NR::Rect b = selection->bounds();
+ mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X],
+ a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]);
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }; // end of switch
+
+ // Top hack: temporarily set clone compensation to unmoved, so that we can align/distribute
+ // clones with their original (and the move of the original does not disturb the
+ // clones). The only problem with this is that if there are outside-of-selection clones of
+ // a selected original, they will be unmoved too, possibly contrary to user's
+ // expecation. However this is a minor point compared to making align/distribute always
+ // work as expected, and "unmoved" is the default option anyway.
+ int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+
+ bool changed = false;
+ //Move each item in the selected list
+ for (std::list<SPItem *>::iterator it(selected.begin());
+ it != selected.end();
+ it++)
+ {
+ sp_document_ensure_up_to_date(SP_DT_DOCUMENT (desktop));
+ NR::Rect b = sp_item_bbox_desktop (*it);
+ NR::Point const sp(a.sx0 * b.min()[NR::X] + a.sx1 * b.max()[NR::X],
+ a.sy0 * b.min()[NR::Y] + a.sy1 * b.max()[NR::Y]);
+ NR::Point const mp_rel( mp - sp );
+ if (LInfty(mp_rel) > 1e-9) {
+ sp_item_move_rel(*it, NR::translate(mp_rel));
+ changed = true;
+ }
+ }
+
+ // restore compensation setting
+ prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+
+ if (changed) {
+ sp_document_done ( SP_DT_DOCUMENT (desktop) );
+ }
+
+
+ }
+ guint _index;
+ AlignAndDistribute &_dialog;
+
+ static const Coeffs _allCoeffs[10];
+
+};
+ActionAlign::Coeffs const ActionAlign::_allCoeffs[10] = {
+ {1., 0., 0., 0., 0., 1., 0., 0.},
+ {1., 0., 0., 0., 1., 0., 0., 0.},
+ {.5, .5, 0., 0., .5, .5, 0., 0.},
+ {0., 1., 0., 0., 0., 1., 0., 0.},
+ {0., 1., 0., 0., 1., 0., 0., 0.},
+ {0., 0., 0., 1., 0., 0., 1., 0.},
+ {0., 0., 0., 1., 0., 0., 0., 1.},
+ {0., 0., .5, .5, 0., 0., .5, .5},
+ {0., 0., 1., 0., 0., 0., 1., 0.},
+ {0., 0., 1., 0., 0., 0., 0., 1.}
+};
+
+struct BBoxSort
+{
+ SPItem *item;
+ float anchor;
+ NR::Rect bbox;
+ BBoxSort(SPItem *pItem, NR::Dim2 orientation, double kBegin, double kEnd) :
+ item(pItem),
+ bbox (sp_item_bbox_desktop (pItem))
+ {
+ anchor = kBegin * bbox.min()[orientation] + kEnd * bbox.max()[orientation];
+ }
+ BBoxSort(const BBoxSort &rhs):
+ //NOTE : this copy ctor is called O(sort) when sorting the vector
+ //this is bad. The vector should be a vector of pointers.
+ //But I'll wait the bohem GC before doing that
+ item(rhs.item), anchor(rhs.anchor), bbox(rhs.bbox) {
+ }
+};
+bool operator< (const BBoxSort &a, const BBoxSort &b)
+{
+ return (a.anchor < b.anchor);
+}
+
+class ActionDistribute : public Action {
+public :
+ ActionDistribute(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row, guint column,
+ AlignAndDistribute &dialog,
+ bool onInterSpace,
+ NR::Dim2 orientation,
+ double kBegin, double kEnd
+ ):
+ Action(id, tiptext, row, column,
+ dialog.distribute_table(), dialog.tooltips(), dialog),
+ _dialog(dialog),
+ _onInterSpace(onInterSpace),
+ _orientation(orientation),
+ _kBegin(kBegin),
+ _kEnd( kEnd)
+ {}
+
+private :
+ virtual void on_button_click() {
+ //Retreive selected objects
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop) return;
+
+ Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+ if (!selection) return;
+
+ using Inkscape::Util::GSListConstIterator;
+ std::list<SPItem *> selected;
+ selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ if (selected.empty()) return;
+
+ //Check 2 or more selected objects
+ std::list<SPItem *>::iterator second(selected.begin());
+ ++second;
+ if (second == selected.end()) return;
+
+
+ std::vector< BBoxSort > sorted;
+ for (std::list<SPItem *>::iterator it(selected.begin());
+ it != selected.end();
+ ++it)
+ {
+ BBoxSort b (*it, _orientation, _kBegin, _kEnd);
+ sorted.push_back(b);
+ }
+ //sort bbox by anchors
+ std::sort(sorted.begin(), sorted.end());
+
+ // see comment in ActionAlign above
+ int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+
+ unsigned int len = sorted.size();
+ bool changed = false;
+ if (_onInterSpace)
+ {
+ //overall bboxes span
+ float dist = (sorted.back().bbox.max()[_orientation] -
+ sorted.front().bbox.min()[_orientation]);
+ //space eaten by bboxes
+ float span = 0;
+ for (unsigned int i = 0; i < len; i++)
+ {
+ span += sorted[i].bbox.extent(_orientation);
+ }
+ //new distance between each bbox
+ float step = (dist - span) / (len - 1);
+ float pos = sorted.front().bbox.min()[_orientation];
+ for ( std::vector<BBoxSort> ::iterator it (sorted.begin());
+ it < sorted.end();
+ it ++ )
+ {
+ if (!NR_DF_TEST_CLOSE (pos, it->bbox.min()[_orientation], 1e-6)) {
+ NR::Point t(0.0, 0.0);
+ t[_orientation] = pos - it->bbox.min()[_orientation];
+ sp_item_move_rel(it->item, NR::translate(t));
+ changed = true;
+ }
+ pos += it->bbox.extent(_orientation);
+ pos += step;
+ }
+ }
+ else
+ {
+ //overall anchor span
+ float dist = sorted.back().anchor - sorted.front().anchor;
+ //distance between anchors
+ float step = dist / (len - 1);
+
+ for ( unsigned int i = 0; i < len ; i ++ )
+ {
+ BBoxSort & it(sorted[i]);
+ //new anchor position
+ float pos = sorted.front().anchor + i * step;
+ //Don't move if we are really close
+ if (!NR_DF_TEST_CLOSE (pos, it.anchor, 1e-6)) {
+ //Compute translation
+ NR::Point t(0.0, 0.0);
+ t[_orientation] = pos - it.anchor;
+ //translate
+ sp_item_move_rel(it.item, NR::translate(t));
+ changed = true;
+ }
+ }
+ }
+
+ // restore compensation setting
+ prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+
+ if (changed) {
+ sp_document_done ( SP_DT_DOCUMENT (desktop) );
+ }
+ }
+ guint _index;
+ AlignAndDistribute &_dialog;
+ bool _onInterSpace;
+ NR::Dim2 _orientation;
+
+ double _kBegin;
+ double _kEnd;
+
+};
+
+
+class ActionNode : public Action {
+public :
+ ActionNode(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint column,
+ AlignAndDistribute &dialog,
+ NR::Dim2 orientation, bool distribute):
+ Action(id, tiptext, 0, column,
+ dialog.nodes_table(), dialog.tooltips(), dialog),
+ _orientation(orientation),
+ _distribute(distribute)
+ {}
+
+private :
+ NR::Dim2 _orientation;
+ bool _distribute;
+ virtual void on_button_click()
+ {
+
+ if (!SP_ACTIVE_DESKTOP) return;
+ SPEventContext *event_context = SP_DT_EVENTCONTEXT(SP_ACTIVE_DESKTOP);
+ if (!SP_IS_NODE_CONTEXT (event_context)) return ;
+
+ Inkscape::NodePath::Path *nodepath = SP_NODE_CONTEXT (event_context)->nodepath;
+ if (!nodepath) return;
+ if (_distribute)
+ sp_nodepath_selected_distribute(nodepath, _orientation);
+ else
+ sp_nodepath_selected_align(nodepath, _orientation);
+
+ }
+};
+
+class ActionRemoveOverlaps : public Action {
+private:
+ Gtk::Label removeOverlapXGapLabel;
+ Gtk::Label removeOverlapYGapLabel;
+ Gtk::SpinButton removeOverlapXGap;
+ Gtk::SpinButton removeOverlapYGap;
+
+public:
+ ActionRemoveOverlaps(Glib::ustring const &id,
+ Glib::ustring const &tiptext,
+ guint row,
+ guint column,
+ AlignAndDistribute &dialog) :
+ Action(id, tiptext, row, column + 4,
+ dialog.removeOverlap_table(), dialog.tooltips(), dialog)
+ {
+ dialog.removeOverlap_table().set_col_spacings(3);
+
+ removeOverlapXGap.set_digits(1);
+ removeOverlapXGap.set_size_request(60, -1);
+ removeOverlapXGap.set_increments(1.0, 5.0);
+ removeOverlapXGap.set_range(-1000.0, 1000.0);
+ removeOverlapXGap.set_value(0);
+ dialog.tooltips().set_tip(removeOverlapXGap,
+ _("Minimum horizontal gap (in px units) between bounding boxes"));
+ /* TRANSLATORS: Horizontal gap */
+ removeOverlapXGapLabel.set_label(_("H:"));
+
+ removeOverlapYGap.set_digits(1);
+ removeOverlapYGap.set_size_request(60, -1);
+ removeOverlapYGap.set_increments(1.0, 5.0);
+ removeOverlapYGap.set_range(-1000.0, 1000.0);
+ removeOverlapYGap.set_value(0);
+ dialog.tooltips().set_tip(removeOverlapYGap,
+ _("Minimum vertical gap (in px units) between bounding boxes"));
+ /* TRANSLATORS: Vertical gap */
+ removeOverlapYGapLabel.set_label(_("V:"));
+
+ dialog.removeOverlap_table().attach(removeOverlapXGapLabel, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL);
+ dialog.removeOverlap_table().attach(removeOverlapXGap, column+1, column+2, row, row+1, Gtk::FILL, Gtk::FILL);
+ dialog.removeOverlap_table().attach(removeOverlapYGapLabel, column+2, column+3, row, row+1, Gtk::FILL, Gtk::FILL);
+ dialog.removeOverlap_table().attach(removeOverlapYGap, column+3, column+4, row, row+1, Gtk::FILL, Gtk::FILL);
+
+ }
+
+private :
+ virtual void on_button_click()
+ {
+ if (!SP_ACTIVE_DESKTOP) return;
+
+ // see comment in ActionAlign above
+ int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+
+ // xGap and yGap are the minimum space required between bounding rectangles.
+ double const xGap = removeOverlapXGap.get_value();
+ double const yGap = removeOverlapYGap.get_value();
+ removeoverlap(SP_DT_SELECTION(SP_ACTIVE_DESKTOP)->itemList(),
+ xGap, yGap);
+
+ // restore compensation setting
+ prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+
+ sp_document_done(SP_DT_DOCUMENT(SP_ACTIVE_DESKTOP));
+ }
+};
+
+class ActionUnclump : public Action {
+public :
+ ActionUnclump(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row,
+ guint column,
+ AlignAndDistribute &dialog):
+ Action(id, tiptext, row, column,
+ dialog.distribute_table(), dialog.tooltips(), dialog)
+ {}
+
+private :
+ virtual void on_button_click()
+ {
+ if (!SP_ACTIVE_DESKTOP) return;
+
+ // see comment in ActionAlign above
+ int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+
+ unclump ((GSList *) SP_DT_SELECTION(SP_ACTIVE_DESKTOP)->itemList());
+
+ // restore compensation setting
+ prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+
+ sp_document_done (SP_DT_DOCUMENT (SP_ACTIVE_DESKTOP));
+ }
+};
+
+class ActionRandomize : public Action {
+public :
+ ActionRandomize(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row,
+ guint column,
+ AlignAndDistribute &dialog):
+ Action(id, tiptext, row, column,
+ dialog.distribute_table(), dialog.tooltips(), dialog)
+ {}
+
+private :
+ virtual void on_button_click()
+ {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop) return;
+
+ Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+ if (!selection) return;
+
+ using Inkscape::Util::GSListConstIterator;
+ std::list<SPItem *> selected;
+ selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ if (selected.empty()) return;
+
+ //Check 2 or more selected objects
+ if (selected.size() < 2) return;
+
+ // This bbox is cached between calls to randomize, so that there's no growth nor shrink
+ // nor drift on sequential randomizations. Discard cache on global (or better active
+ // desktop's) selection_change signal.
+ if (!_dialog.randomize_bbox_set) {
+ _dialog.randomize_bbox = selection->bounds();
+ _dialog.randomize_bbox_set = true;
+ }
+
+ // see comment in ActionAlign above
+ int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+
+ for (std::list<SPItem *>::iterator it(selected.begin());
+ it != selected.end();
+ ++it)
+ {
+ sp_document_ensure_up_to_date(SP_DT_DOCUMENT (desktop));
+ NR::Rect item_box = sp_item_bbox_desktop (*it);
+ // find new center, staying within bbox
+ double x = _dialog.randomize_bbox.min()[NR::X] + item_box.extent(NR::X)/2 +
+ g_random_double_range (0, _dialog.randomize_bbox.extent(NR::X) - item_box.extent(NR::X));
+ double y = _dialog.randomize_bbox.min()[NR::Y] + item_box.extent(NR::Y)/2 +
+ g_random_double_range (0, _dialog.randomize_bbox.extent(NR::Y) - item_box.extent(NR::Y));
+ // displacement is the new center minus old:
+ NR::Point t = NR::Point (x, y) - 0.5*(item_box.max() + item_box.min());
+ sp_item_move_rel(*it, NR::translate(t));
+ }
+
+ // restore compensation setting
+ prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+
+ sp_document_done (SP_DT_DOCUMENT (SP_ACTIVE_DESKTOP));
+ }
+};
+
+struct Baselines
+{
+ SPItem *_item;
+ NR::Point _base;
+ NR::Dim2 _orientation;
+ Baselines(SPItem *item, NR::Point base, NR::Dim2 orientation) :
+ _item (item),
+ _base (base),
+ _orientation (orientation)
+ {}
+};
+
+bool operator< (const Baselines &a, const Baselines &b)
+{
+ return (a._base[a._orientation] < b._base[b._orientation]);
+}
+
+class ActionBaseline : public Action {
+public :
+ ActionBaseline(const Glib::ustring &id,
+ const Glib::ustring &tiptext,
+ guint row,
+ guint column,
+ AlignAndDistribute &dialog,
+ Gtk::Table &table,
+ NR::Dim2 orientation, bool distribute):
+ Action(id, tiptext, row, column,
+ table, dialog.tooltips(), dialog),
+ _orientation(orientation),
+ _distribute(distribute)
+ {}
+
+private :
+ NR::Dim2 _orientation;
+ bool _distribute;
+ virtual void on_button_click()
+ {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop) return;
+
+ Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+ if (!selection) return;
+
+ using Inkscape::Util::GSListConstIterator;
+ std::list<SPItem *> selected;
+ selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ if (selected.empty()) return;
+
+ //Check 2 or more selected objects
+ if (selected.size() < 2) return;
+
+ NR::Point b_min = NR::Point (HUGE_VAL, HUGE_VAL);
+ NR::Point b_max = NR::Point (-HUGE_VAL, -HUGE_VAL);
+
+ std::vector<Baselines> sorted;
+
+ for (std::list<SPItem *>::iterator it(selected.begin());
+ it != selected.end();
+ ++it)
+ {
+ if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
+ Inkscape::Text::Layout const *layout = te_get_layout(*it);
+ NR::Point base = layout->characterAnchorPoint(layout->begin()) * sp_item_i2d_affine(*it);
+ if (base[NR::X] < b_min[NR::X]) b_min[NR::X] = base[NR::X];
+ if (base[NR::Y] < b_min[NR::Y]) b_min[NR::Y] = base[NR::Y];
+ if (base[NR::X] > b_max[NR::X]) b_max[NR::X] = base[NR::X];
+ if (base[NR::Y] > b_max[NR::Y]) b_max[NR::Y] = base[NR::Y];
+
+ Baselines b (*it, base, _orientation);
+ sorted.push_back(b);
+ }
+ }
+
+ if (sorted.size() <= 1) return;
+
+ //sort baselines
+ std::sort(sorted.begin(), sorted.end());
+
+ bool changed = false;
+
+ if (_distribute) {
+ double step = (b_max[_orientation] - b_min[_orientation])/(sorted.size() - 1);
+ for (unsigned int i = 0; i < sorted.size(); i++) {
+ SPItem *item = sorted[i]._item;
+ NR::Point base = sorted[i]._base;
+ NR::Point t(0.0, 0.0);
+ t[_orientation] = b_min[_orientation] + step * i - base[_orientation];
+ sp_item_move_rel(item, NR::translate(t));
+ changed = true;
+ }
+
+ } else {
+ for (std::list<SPItem *>::iterator it(selected.begin());
+ it != selected.end();
+ ++it)
+ {
+ if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
+ Inkscape::Text::Layout const *layout = te_get_layout(*it);
+ NR::Point base = layout->characterAnchorPoint(layout->begin()) * sp_item_i2d_affine(*it);
+ NR::Point t(0.0, 0.0);
+ t[_orientation] = b_min[_orientation] - base[_orientation];
+ sp_item_move_rel(*it, NR::translate(t));
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ sp_document_done (SP_DT_DOCUMENT (SP_ACTIVE_DESKTOP));
+ }
+ }
+};
+
+
+
+void on_tool_changed(Inkscape::Application *inkscape, SPEventContext *context, AlignAndDistribute *daad)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (desktop && SP_DT_EVENTCONTEXT(desktop))
+ daad->setMode(tools_active(desktop) == TOOLS_NODES);
+}
+
+void on_selection_changed(Inkscape::Application *inkscape, Inkscape::Selection *selection, AlignAndDistribute *daad)
+{
+ daad->randomize_bbox_set = false;
+}
+
+/////////////////////////////////////////////////////////
+
+
+
+
+AlignAndDistribute::AlignAndDistribute()
+ : Dialog ("dialogs.align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE),
+ randomize_bbox (NR::Point (0, 0), NR::Point (0, 0)),
+ _alignFrame(_("Align")),
+ _distributeFrame(_("Distribute")),
+ _removeOverlapFrame(_("Remove overlaps")),
+ _nodesFrame(_("Nodes")),
+ _alignTable(2, 6, true),
+ _distributeTable(3, 6, true),
+ _removeOverlapTable(1, 5, false),
+ _nodesTable(1, 4, true),
+ _anchorLabel(_("Relative to: "))
+{
+
+ //Instanciate the align buttons
+ addAlignButton("al_left_out",
+ _("Align right sides of objects to left side of anchor"),
+ 0, 0);
+ addAlignButton("al_left_in",
+ _("Align left sides"),
+ 0, 1);
+ addAlignButton("al_center_hor",
+ _("Center on vertical axis"),
+ 0, 2);
+ addAlignButton("al_right_in",
+ _("Align right sides"),
+ 0, 3);
+ addAlignButton("al_right_out",
+ _("Align left sides of objects to right side of anchor"),
+ 0, 4);
+ addAlignButton("al_top_out",
+ _("Align bottoms of objects to top of anchor"),
+ 1, 0);
+ addAlignButton("al_top_in",
+ _("Align tops"),
+ 1, 1);
+ addAlignButton("al_center_ver",
+ _("Center on horizontal axis"),
+ 1, 2);
+ addAlignButton("al_bottom_in",
+ _("Align bottoms"),
+ 1, 3);
+ addAlignButton("al_bottom_out",
+ _("Align tops of objects to bottom of anchor"),
+ 1, 4);
+
+ //Baseline aligns
+ addBaselineButton("al_baselines_vert",
+ _("Align baseline anchors of texts vertically"),
+ 0, 5, this->align_table(), NR::X, false);
+ addBaselineButton("al_baselines_hor",
+ _("Align baseline anchors of texts horizontally"),
+ 1, 5, this->align_table(), NR::Y, false);
+
+ //The distribute buttons
+ addDistributeButton("distribute_hdist",
+ _("Make horizontal gaps between objects equal"),
+ 0, 4, true, NR::X, .5, .5);
+
+ addDistributeButton("distribute_left",
+ _("Distribute left sides equidistantly"),
+ 0, 1, false, NR::X, 1., 0.);
+ addDistributeButton("distribute_hcentre",
+ _("Distribute centers equidistantly horizontally"),
+ 0, 2, false, NR::X, .5, .5);
+ addDistributeButton("distribute_right",
+ _("Distribute right sides equidistantly"),
+ 0, 3, false, NR::X, 0., 1.);
+
+ addDistributeButton("distribute_vdist",
+ _("Make vertical gaps between objects equal"),
+ 1, 4, true, NR::Y, .5, .5);
+
+ addDistributeButton("distribute_top",
+ _("Distribute tops equidistantly"),
+ 1, 1, false, NR::Y, 0, 1);
+ addDistributeButton("distribute_vcentre",
+ _("Distribute centers equidistantly vertically"),
+ 1, 2, false, NR::Y, .5, .5);
+ addDistributeButton("distribute_bottom",
+ _("Distribute bottoms equidistantly"),
+ 1, 3, false, NR::Y, 1., 0.);
+
+ //Baseline distribs
+ addBaselineButton("distribute_baselines_hor",
+ _("Distribute baseline anchors of texts horizontally"),
+ 0, 5, this->distribute_table(), NR::X, true);
+ addBaselineButton("distribute_baselines_vert",
+ _("Distribute baseline anchors of texts vertically"),
+ 1, 5, this->distribute_table(), NR::Y, true);
+
+ //Randomize & Unclump
+ addRandomizeButton("distribute_randomize",
+ _("Randomize centers in both dimensions"),
+ 2, 2);
+ addUnclumpButton("unclump",
+ _("Unclump objects: try to equalize edge-to-edge distances"),
+ 2, 4);
+
+ //Remove overlaps
+ addRemoveOverlapsButton("remove_overlaps",
+ _("Move objects as little as possible so that their bounding boxes do not overlap"),
+ 0, 0);
+
+ //Node Mode buttons
+ addNodeButton("node_halign",
+ _("Align selected nodes horizontally"),
+ 0, NR::X, false);
+ addNodeButton("node_valign",
+ _("Align selected nodes vertically"),
+ 1, NR::Y, false);
+ addNodeButton("node_hdistribute",
+ _("Distribute selected nodes horizontally"),
+ 2, NR::X, true);
+ addNodeButton("node_vdistribute",
+ _("Distribute selected nodes vertically"),
+ 3, NR::Y, true);
+
+ //Rest of the widgetry
+
+ _combo.append_text(_("Last selected"));
+ _combo.append_text(_("First selected"));
+ _combo.append_text(_("Biggest item"));
+ _combo.append_text(_("Smallest item"));
+ _combo.append_text(_("Page"));
+ _combo.append_text(_("Drawing"));
+ _combo.append_text(_("Selection"));
+
+ _combo.set_active(6);
+ _combo.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_ref_change));
+
+ _anchorBox.pack_start(_anchorLabel);
+ _anchorBox.pack_start(_combo);
+
+ _alignBox.pack_start(_anchorBox);
+ _alignBox.pack_start(_alignTable);
+
+ _alignFrame.add(_alignBox);
+ _distributeFrame.add(_distributeTable);
+ _removeOverlapFrame.add(_removeOverlapTable);
+ _nodesFrame.add(_nodesTable);
+
+ // Top level vbox
+ Gtk::VBox *vbox = get_vbox();
+ vbox->set_spacing(4);
+
+ // Notebook for individual transformations
+
+ vbox->pack_start(_alignFrame, true, true);
+ vbox->pack_start(_distributeFrame, true, true);
+ vbox->pack_start(_removeOverlapFrame, true, true);
+ vbox->pack_start(_nodesFrame, true, true);
+
+ //Connect to the global tool change signal
+ g_signal_connect (G_OBJECT (INKSCAPE), "set_eventcontext", G_CALLBACK (on_tool_changed), this);
+
+ // Connect to the global selection change, to invalidate cached randomize_bbox
+ g_signal_connect (G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (on_selection_changed), this);
+ randomize_bbox = NR::Rect (NR::Point (0, 0), NR::Point (0, 0));
+ randomize_bbox_set = false;
+
+ show_all_children();
+
+ on_tool_changed (NULL, NULL, this); // set current mode
+}
+
+AlignAndDistribute::~AlignAndDistribute()
+{
+ sp_signal_disconnect_by_data (G_OBJECT (INKSCAPE), this);
+
+ for (std::list<Action *>::iterator it = _actionList.begin();
+ it != _actionList.end();
+ it ++)
+ delete *it;
+}
+
+void AlignAndDistribute::on_ref_change(){
+//Make blink the master
+}
+
+
+
+
+void AlignAndDistribute::setMode(bool nodeEdit)
+{
+ //Act on widgets used in node mode
+ void ( Gtk::Widget::*mNode) () = nodeEdit ?
+ &Gtk::Widget::show_all : &Gtk::Widget::hide_all;
+
+ //Act on widgets used in selection mode
+ void ( Gtk::Widget::*mSel) () = nodeEdit ?
+ &Gtk::Widget::hide_all : &Gtk::Widget::show_all;
+
+
+ ((_alignFrame).*(mSel))();
+ ((_distributeFrame).*(mSel))();
+ ((_removeOverlapFrame).*(mSel))();
+ ((_nodesFrame).*(mNode))();
+
+}
+void AlignAndDistribute::addAlignButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col)
+{
+ _actionList.push_back(
+ new ActionAlign(
+ id, tiptext, row, col,
+ *this , col + row * 5));
+}
+void AlignAndDistribute::addDistributeButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col, bool onInterSpace,
+ NR::Dim2 orientation, float kBegin, float kEnd)
+{
+ _actionList.push_back(
+ new ActionDistribute(
+ id, tiptext, row, col, *this ,
+ onInterSpace, orientation,
+ kBegin, kEnd
+ )
+ );
+}
+
+void AlignAndDistribute::addNodeButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint col, NR::Dim2 orientation, bool distribute)
+{
+ _actionList.push_back(
+ new ActionNode(
+ id, tiptext, col,
+ *this, orientation, distribute));
+}
+
+void AlignAndDistribute::addRemoveOverlapsButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col)
+{
+ _actionList.push_back(
+ new ActionRemoveOverlaps(
+ id, tiptext, row, col, *this)
+ );
+}
+
+void AlignAndDistribute::addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col)
+{
+ _actionList.push_back(
+ new ActionUnclump(
+ id, tiptext, row, col, *this)
+ );
+}
+
+void AlignAndDistribute::addRandomizeButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col)
+{
+ _actionList.push_back(
+ new ActionRandomize(
+ id, tiptext, row, col, *this)
+ );
+}
+
+void AlignAndDistribute::addBaselineButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col, Gtk::Table &table, NR::Dim2 orientation, bool distribute)
+{
+ _actionList.push_back(
+ new ActionBaseline(
+ id, tiptext, row, col,
+ *this, table, orientation, distribute));
+}
+
+
+
+
+std::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem *> &list, bool horizontal){
+ std::list<SPItem *>::iterator master = list.end();
+ switch (getAlignTarget()) {
+ case LAST:
+ return list.begin();
+ break;
+
+ case FIRST:
+ return --(list.end());
+ break;
+
+ case BIGGEST:
+ {
+ gdouble max = -1e18;
+ for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
+ NR::Rect b = sp_item_bbox_desktop (*it);
+ gdouble dim = b.extent(horizontal ? NR::X : NR::Y);
+ if (dim > max) {
+ max = dim;
+ master = it;
+ }
+ }
+ return master;
+ break;
+ }
+
+ case SMALLEST:
+ {
+ gdouble max = 1e18;
+ for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
+ NR::Rect b = sp_item_bbox_desktop (*it);
+ gdouble dim = b.extent(horizontal ? NR::X : NR::Y);
+ if (dim < max) {
+ max = dim;
+ master = it;
+ }
+ }
+ return master;
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ break;
+
+ } // end of switch statement
+ return NULL;
+}
+
+AlignAndDistribute::AlignTarget AlignAndDistribute::getAlignTarget()const {
+ return AlignTarget(_combo.get_active_row_number());
+}
+
+
+
+} // 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/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h
new file mode 100644
index 000000000..35ca3c7c3
--- /dev/null
+++ b/src/ui/dialog/align-and-distribute.h
@@ -0,0 +1,120 @@
+/**
+ * \brief Align and Distribute dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Aubanel MONNIER <aubi@libertysurf.fr>
+ * Frank Felfe <innerspace@iname.com>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ *
+ * Copyright (C) 1999-2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_ALIGN_AND_DISTRIBUTE_H
+#define INKSCAPE_UI_DIALOG_ALIGN_AND_DISTRIBUTE_H
+
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+#include <list>
+#include <gtkmm/frame.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/table.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/label.h>
+#include "libnr/nr-dim2.h"
+#include "libnr/nr-rect.h"
+
+
+#include "dialog.h"
+#include "ui/widget/notebook-page.h"
+
+using namespace Inkscape::UI::Widget;
+
+
+class SPItem;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class Action;
+
+
+class AlignAndDistribute : public Dialog {
+public:
+ AlignAndDistribute();
+ virtual ~AlignAndDistribute();
+
+ static AlignAndDistribute *create() { return new AlignAndDistribute(); }
+
+ enum AlignTarget { LAST=0, FIRST, BIGGEST, SMALLEST, PAGE, DRAWING, SELECTION };
+
+ AlignTarget getAlignTarget() const;
+
+ Gtk::Table &align_table(){return _alignTable;}
+ Gtk::Table &distribute_table(){return _distributeTable;}
+ Gtk::Table &removeOverlap_table(){return _removeOverlapTable;}
+ Gtk::Table &nodes_table(){return _nodesTable;}
+ Gtk::Tooltips &tooltips(){return _tooltips;}
+
+ std::list<SPItem *>::iterator find_master(std::list <SPItem *> &list, bool horizontal);
+ void setMode(bool nodeEdit);
+
+ NR::Rect randomize_bbox;
+ bool randomize_bbox_set;
+
+
+protected:
+
+ void on_ref_change();
+ void addDistributeButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col, bool onInterSpace,
+ NR::Dim2 orientation, float kBegin, float kEnd);
+ void addAlignButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col);
+ void addNodeButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint col, NR::Dim2 orientation, bool distribute);
+ void addRemoveOverlapsButton(const Glib::ustring &id,
+ const Glib::ustring tiptext,
+ guint row, guint col);
+ void addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col);
+ void addRandomizeButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col);
+ void addBaselineButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col, Gtk::Table &table, NR::Dim2 orientation, bool distribute);
+
+ std::list<Action *> _actionList;
+ Gtk::Frame _alignFrame, _distributeFrame, _removeOverlapFrame, _nodesFrame;
+ Gtk::Table _alignTable, _distributeTable, _removeOverlapTable, _nodesTable;
+ Gtk::HBox _anchorBox;
+ Gtk::VBox _alignBox;
+ Gtk::Label _anchorLabel;
+ Gtk::ComboBoxText _combo;
+ Gtk::Tooltips _tooltips;
+
+private:
+ AlignAndDistribute(AlignAndDistribute const &d);
+ AlignAndDistribute& operator=(AlignAndDistribute const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_ALIGN_AND_DISTRIBUTE_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
new file mode 100644
index 000000000..80fae2c92
--- /dev/null
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -0,0 +1,191 @@
+/**
+ * \brief Object for managing a set of dialogs, including their signals and
+ * construction/caching/destruction of them.
+ *
+ * Author:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Jon Phillips <jon@rejon.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ui/dialog/dialog-manager.h"
+
+#include "ui/dialog/align-and-distribute.h"
+#include "ui/dialog/document-metadata.h"
+#include "ui/dialog/document-properties.h"
+#include "ui/dialog/export.h"
+#include "ui/dialog/extension-editor.h"
+#include "ui/dialog/fill-and-stroke.h"
+#include "ui/dialog/find.h"
+#include "ui/dialog/inkscape-preferences.h"
+#include "ui/dialog/layer-editor.h"
+#include "ui/dialog/memory.h"
+#include "ui/dialog/messages.h"
+#include "ui/dialog/scriptdialog.h"
+#include "ui/dialog/text-properties.h"
+#include "ui/dialog/tracedialog.h"
+#include "ui/dialog/transformation.h"
+
+#ifdef WITH_INKBOARD
+#include "ui/dialog/whiteboard-sharewithchat.h"
+#include "ui/dialog/whiteboard-sharewithuser.h"
+#include "ui/dialog/whiteboard-connect.h"
+#include "ui/dialog/session-player.h"
+#endif
+
+#include "ui/dialog/xml-editor.h"
+
+#include "dialogs/tiledialog.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+namespace {
+
+template <typename T>
+Dialog *create() { return T::create(); }
+
+}
+
+/**
+ * This class is provided as a container for Inkscape's various
+ * dialogs. This allows Inkscape::Application to treat the various
+ * dialogs it invokes, as abstractions.
+ *
+ * DialogManager is essentially a cache of dialogs. It lets us
+ * initialize dialogs lazily - instead of constructing them during
+ * application startup, they're constructed the first time they're
+ * actually invoked by Inkscape::Application. The constructed
+ * dialog is held here after that, so future invokations of the
+ * dialog don't need to get re-constructed each time. The memory for
+ * the dialogs are then reclaimed when the DialogManager is destroyed.
+ *
+ * In addition, DialogManager also serves as a signal manager for
+ * dialogs. It provides a set of signals that can be sent to all
+ * dialogs for doing things such as hiding/unhiding them, etc.
+ * DialogManager ensures that every dialog it handles will listen
+ * to these signals.
+ *
+ */
+DialogManager::DialogManager() {
+ registerFactory("AlignAndDistribute", &create<AlignAndDistribute>);
+ registerFactory("DocumentMetadata", &create<DocumentMetadata>);
+ registerFactory("DocumentProperties", &create<DocumentProperties>);
+ registerFactory("Export", &create<Export>);
+ registerFactory("ExtensionEditor", &create<ExtensionEditor>);
+ registerFactory("FillAndStroke", &create<FillAndStroke>);
+ registerFactory("Find", &create<Find>);
+ registerFactory("InkscapePreferences", &create<InkscapePreferences>);
+ registerFactory("LayerEditor", &create<LayerEditor>);
+ registerFactory("Memory", &create<Memory>);
+ registerFactory("Messages", &create<Messages>);
+ registerFactory("Script", &create<ScriptDialog>);
+ registerFactory("TextProperties", &create<TextProperties>);
+ registerFactory("TileDialog", &create<TileDialog>);
+ registerFactory("Trace", &create<TraceDialog>);
+ registerFactory("Transformation", &create<Transformation>);
+#ifdef WITH_INKBOARD
+ registerFactory("SessionPlayer", &create<SessionPlaybackDialog>);
+ registerFactory("WhiteboardConnect", &create<WhiteboardConnectDialog>);
+ registerFactory("WhiteboardShareWithUser", &create<WhiteboardShareWithUserDialog>);
+ registerFactory("WhiteboardShareWithChat", &create<WhiteboardShareWithChatroomDialog>);
+#endif
+ registerFactory("XmlEditor", &create<XmlEditor>);
+}
+
+DialogManager::~DialogManager() {
+ // TODO: Disconnect the signals
+ // TODO: Do we need to explicitly delete the dialogs?
+ // Appears to cause a segfault if we do
+}
+
+/**
+ * Registers a dialog factory function used to create the named dialog.
+ */
+void DialogManager::registerFactory(gchar const *name,
+ DialogManager::DialogFactory factory)
+{
+ registerFactory(g_quark_from_string(name), factory);
+}
+
+/**
+ * Registers a dialog factory function used to create the named dialog.
+ */
+void DialogManager::registerFactory(GQuark name,
+ DialogManager::DialogFactory factory)
+{
+ _factory_map[name] = factory;
+}
+
+/**
+ * Fetches the named dialog, creating it if it has not already been
+ * created (assuming a factory has been registered for it).
+ */
+Dialog *DialogManager::getDialog(gchar const *name) {
+ return getDialog(g_quark_from_string(name));
+}
+
+/**
+ * Fetches the named dialog, creating it if it has not already been
+ * created (assuming a factory has been registered for it).
+ */
+Dialog *DialogManager::getDialog(GQuark name) {
+ DialogMap::iterator dialog_found;
+ dialog_found = _dialog_map.find(name);
+
+ Dialog *dialog=NULL;
+ if ( dialog_found != _dialog_map.end() ) {
+ dialog = dialog_found->second;
+ } else {
+ FactoryMap::iterator factory_found;
+ factory_found = _factory_map.find(name);
+
+ if ( factory_found != _factory_map.end() ) {
+ dialog = factory_found->second();
+ _dialog_map[name] = dialog;
+ }
+ }
+
+ return dialog;
+}
+
+/**
+ * Shows the named dialog, creating it if necessary.
+ */
+void DialogManager::showDialog(gchar const *name) {
+ showDialog(g_quark_from_string(name));
+}
+
+/**
+ * Shows the named dialog, creating it if necessary.
+ */
+void DialogManager::showDialog(GQuark name) {
+ Dialog *dialog=getDialog(name);
+ if (dialog) {
+ dialog->present();
+ dialog->read_geometry();
+ }
+}
+
+} // 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/dialog-manager.h b/src/ui/dialog/dialog-manager.h
new file mode 100644
index 000000000..cf5a23712
--- /dev/null
+++ b/src/ui/dialog/dialog-manager.h
@@ -0,0 +1,72 @@
+/**
+ * \brief Object for managing a set of dialogs, including their signals and
+ * construction/caching/destruction of them.
+ *
+ * Author:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Jon Phillips <jon@rejon.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_MANAGER_H
+#define INKSCAPE_UI_DIALOG_MANAGER_H
+
+#include <glib/gquark.h>
+#include "dialog.h"
+#include <map>
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class DialogManager {
+public:
+ typedef Dialog *(*DialogFactory)();
+
+ DialogManager();
+ virtual ~DialogManager();
+
+ sigc::signal<void> show_dialogs;
+ sigc::signal<void> show_f12;
+ sigc::signal<void> hide_dialogs;
+ sigc::signal<void> hide_f12;
+ sigc::signal<void> transientize;
+
+ /* generic dialog management start */
+ typedef std::map<GQuark, DialogFactory> FactoryMap;
+ typedef std::map<GQuark, Dialog*> DialogMap;
+
+ void registerFactory(gchar const *name, DialogFactory factory);
+ void registerFactory(GQuark name, DialogFactory factory);
+ Dialog *getDialog(gchar const* dlgName);
+ Dialog *getDialog(GQuark dlgName);
+ void showDialog(gchar const *name);
+ void showDialog(GQuark name);
+
+protected:
+ DialogManager(DialogManager const &d); // no copy
+ DialogManager& operator=(DialogManager const &d); // no assign
+
+ FactoryMap _factory_map; //< factories to create dialogs
+ DialogMap _dialog_map; //< map of already created dialogs
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif //INKSCAPE_UI_DIALOG_MANAGER_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.cpp b/src/ui/dialog/dialog.cpp
new file mode 100644
index 000000000..47cb4eb73
--- /dev/null
+++ b/src/ui/dialog/dialog.cpp
@@ -0,0 +1,359 @@
+/**
+ * \brief Base class for dialogs in Inkscape. This class provides certain
+ * common behaviors and styles wanted of all dialogs in the application.
+ *
+ * Author:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/stock.h>
+#include <gtk/gtk.h>
+
+#include "application/application.h"
+#include "application/editor.h"
+#include "inkscape.h"
+#include "event-context.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "dialog-manager.h"
+#include "dialogs/dialog-events.h"
+#include "shortcuts.h"
+#include "prefs-utils.h"
+#include "interface.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+#ifndef WIN32
+static gboolean
+sp_retransientize_again (gpointer dlgPtr)
+{
+ Dialog *dlg = (Dialog *)dlgPtr;
+ dlg->retransientize_suppress = false;
+ return FALSE; // so that it is only called once
+}
+#endif
+
+static void
+sp_retransientize (Inkscape::Application *inkscape, SPDesktop *desktop, gpointer dlgPtr)
+{
+ Dialog *dlg = (Dialog *)dlgPtr;
+ dlg->onDesktopActivated (desktop);
+}
+
+static void
+sp_dialog_shutdown (GtkObject *object, gpointer dlgPtr)
+{
+ Dialog *dlg = (Dialog *)dlgPtr;
+ dlg->onShutdown();
+}
+
+void
+Dialog::save_geometry()
+{
+ int y, x, w, h;
+
+ get_position(x, y);
+ get_size(w, h);
+
+// g_print ("write %d %d %d %d\n", x, y, w, h);
+
+ prefs_set_int_attribute (_prefs_path, "x", x);
+ prefs_set_int_attribute (_prefs_path, "y", y);
+ prefs_set_int_attribute (_prefs_path, "w", w);
+ prefs_set_int_attribute (_prefs_path, "h", h);
+}
+
+void
+Dialog::read_geometry()
+{
+ _user_hidden = false;
+
+ int x = prefs_get_int_attribute (_prefs_path, "x", -1000);
+ int y = prefs_get_int_attribute (_prefs_path, "y", -1000);
+ int w = prefs_get_int_attribute (_prefs_path, "w", 0);
+ int h = prefs_get_int_attribute (_prefs_path, "h", 0);
+
+// g_print ("read %d %d %d %d\n", x, y, w, h);
+
+ // If there are stored height and width values for the dialog,
+ // resize the window to match; otherwise we leave it at its default
+ if (w != 0 && h != 0) {
+ resize (w, h);
+ }
+
+ // If there are stored values for where the dialog should be
+ // located, then restore the dialog to that position.
+ if (x != -1000 && y != -1000) {
+ move(x, y);
+ } else {
+ // ...otherwise just put it in the middle of the screen
+ set_position(Gtk::WIN_POS_CENTER);
+ }
+}
+
+void hideCallback(GtkObject *object, gpointer dlgPtr)
+{
+ Dialog *dlg = (Dialog *)dlgPtr;
+ dlg->onHideF12();
+}
+
+void unhideCallback(GtkObject *object, gpointer dlgPtr)
+{
+ Dialog *dlg = (Dialog *)dlgPtr;
+ dlg->onShowF12();
+}
+
+//=====================================================================
+
+/**
+ * UI::Dialog::Dialog is a base class for all dialogs in Inkscape. The
+ * purpose of this class is to provide a unified place for ensuring
+ * style and behavior. Specifically, this class provides functionality
+ * for saving and restoring the size and position of dialogs (through
+ * the user's preferences file).
+ *
+ * It also provides some general purpose signal handlers for things like
+ * showing and hiding all dialogs.
+ */
+Dialog::Dialog(const char *prefs_path, int verb_num, const char *apply_label)
+{
+ hide();
+ set_has_separator(false);
+
+ _prefs_path = prefs_path;
+
+ if (prefs_get_int_attribute ("dialogs", "showclose", 0) || apply_label) {
+ // TODO: make the order of buttons obey the global preference
+ if (apply_label) {
+ add_button(Glib::ustring(apply_label), Gtk::RESPONSE_APPLY);
+ set_default_response(Gtk::RESPONSE_APPLY);
+ }
+ add_button(Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE);
+ }
+
+ GtkWidget *dlg = GTK_WIDGET(gobj());
+
+ if (verb_num)
+ {
+ gchar title[500];
+ sp_ui_dialog_title_string (Inkscape::Verb::get(verb_num), title);
+ set_title(title);
+ }
+
+ sp_transientize(dlg);
+ retransientize_suppress = false;
+
+ gtk_signal_connect( GTK_OBJECT (dlg), "event", GTK_SIGNAL_FUNC(sp_dialog_event_handler), dlg );
+
+ _hiddenF12 = false;
+ if (Inkscape::NSApplication::Application::getNewGui())
+ {
+ _desktop_activated_connection = Inkscape::NSApplication::Editor::connectDesktopActivated (sigc::mem_fun (*this, &Dialog::onDesktopActivated));
+ _dialogs_hidden_connection = Inkscape::NSApplication::Editor::connectDialogsHidden (sigc::mem_fun (*this, &Dialog::onHideF12));
+ _dialogs_unhidden_connection = Inkscape::NSApplication::Editor::connectDialogsUnhidden (sigc::mem_fun (*this, &Dialog::onShowF12));
+ _shutdown_connection = Inkscape::NSApplication::Editor::connectShutdown (sigc::mem_fun (*this, &Dialog::onShutdown));
+ }
+ else
+ {
+ g_signal_connect (G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (sp_retransientize), (void *)this);
+ g_signal_connect( G_OBJECT(INKSCAPE), "dialogs_hide", G_CALLBACK(hideCallback), (void *)this );
+ g_signal_connect( G_OBJECT(INKSCAPE), "dialogs_unhide", G_CALLBACK(unhideCallback), (void *)this );
+ g_signal_connect (G_OBJECT (INKSCAPE), "shut_down", G_CALLBACK (sp_dialog_shutdown), (void *)this);
+ }
+
+ g_signal_connect_after( gobj(), "key_press_event", (GCallback)windowKeyPress, NULL );
+
+ read_geometry();
+ present();
+}
+
+Dialog::Dialog(BaseObjectType *gobj)
+ : Gtk::Dialog(gobj)
+{
+}
+
+Dialog::~Dialog()
+{
+ if (Inkscape::NSApplication::Application::getNewGui())
+ {
+ _desktop_activated_connection.disconnect();
+ _dialogs_hidden_connection.disconnect();
+ _dialogs_unhidden_connection.disconnect();
+ _shutdown_connection.disconnect();
+ }
+
+ save_geometry();
+}
+
+
+bool Dialog::windowKeyPress( GtkWidget *widget, GdkEventKey *event )
+{
+ unsigned int shortcut = 0;
+ shortcut = get_group0_keyval (event) |
+ ( event->state & GDK_SHIFT_MASK ?
+ SP_SHORTCUT_SHIFT_MASK : 0 ) |
+ ( event->state & GDK_CONTROL_MASK ?
+ SP_SHORTCUT_CONTROL_MASK : 0 ) |
+ ( event->state & GDK_MOD1_MASK ?
+ SP_SHORTCUT_ALT_MASK : 0 );
+ return sp_shortcut_invoke( shortcut, SP_ACTIVE_DESKTOP );
+}
+
+//---------------------------------------------------------------------
+
+void
+Dialog::on_response(int response_id)
+{
+ switch (response_id) {
+ case Gtk::RESPONSE_APPLY: {
+ _apply();
+ break;
+ }
+ case Gtk::RESPONSE_CLOSE: {
+ _close();
+ break;
+ }
+ }
+}
+
+bool
+Dialog::on_delete_event (GdkEventAny *event)
+{
+ save_geometry();
+ _user_hidden = true;
+
+ return false;
+}
+
+void
+Dialog::onHideF12()
+{
+ _hiddenF12 = true;
+ save_geometry();
+ hide();
+}
+
+void
+Dialog::onShowF12()
+{
+ if (_user_hidden)
+ return;
+
+ if (_hiddenF12) {
+ show();
+ read_geometry();
+ }
+
+ _hiddenF12 = false;
+}
+
+void
+Dialog::onShutdown()
+{
+ save_geometry();
+ _user_hidden = true;
+}
+
+void
+Dialog::onDesktopActivated (SPDesktop *desktop)
+{
+ gint transient_policy = prefs_get_int_attribute_limited ( "options.transientpolicy", "value", 1, 0, 2);
+
+ if (!transient_policy)
+ return;
+
+#ifndef WIN32
+ GtkWindow *dialog_win = GTK_WINDOW(gobj());
+
+ if (retransientize_suppress) {
+ /* if retransientizing of this dialog is still forbidden after
+ * previous call warning turned off because it was confusingly fired
+ * when loading many files from command line
+ */
+
+ // g_warning("Retranzientize aborted! You're switching windows too fast!");
+ return;
+ }
+
+ if (dialog_win)
+ {
+ retransientize_suppress = true; // disallow other attempts to retranzientize this dialog
+
+ desktop->setWindowTransient (dialog_win);
+
+ /*
+ * This enables "aggressive" transientization,
+ * i.e. dialogs always emerging on top when you switch documents. Note
+ * however that this breaks "click to raise" policy of a window
+ * manager because the switched-to document will be raised at once
+ * (so that its transients also could raise)
+ */
+ if (transient_policy == 2 && !_hiddenF12 && !_user_hidden) {
+ // without this, a transient window not always emerges on top
+ gtk_window_present (dialog_win);
+ }
+ }
+
+ // we're done, allow next retransientizing not sooner than after 120 msec
+ gtk_timeout_add (120, (GtkFunction) sp_retransientize_again, (gpointer) this);
+#endif
+}
+
+
+Inkscape::Selection*
+Dialog::_getSelection()
+{
+ return SP_DT_SELECTION(SP_ACTIVE_DESKTOP);
+}
+
+void
+Dialog::_apply()
+{
+ g_warning("Apply button clicked for dialog [Dialog::_apply()]");
+}
+
+void
+Dialog::_close()
+{
+ GtkWidget *dlg = GTK_WIDGET(gobj());
+
+ /* this code sends a delete_event to the dialog,
+ * instead of just destroying it, so that the
+ * dialog can do some housekeeping, such as remember
+ * its position.
+ */
+ GdkEventAny event;
+ event.type = GDK_DELETE;
+ event.window = dlg->window;
+ event.send_event = TRUE;
+ g_object_ref (G_OBJECT (event.window));
+ gtk_main_do_event ((GdkEvent*)&event);
+ g_object_unref (G_OBJECT (event.window));
+}
+
+} // 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/dialog.h b/src/ui/dialog/dialog.h
new file mode 100644
index 000000000..d01cdb048
--- /dev/null
+++ b/src/ui/dialog/dialog.h
@@ -0,0 +1,94 @@
+/**
+ * \brief Base class for dialogs in Inkscape. This class provides certain
+ * common behaviors and styles wanted of all dialogs in the application.
+ *
+ * Author:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_DIALOG_H
+#define INKSCAPE_DIALOG_H
+
+#include <gtkmm/dialog.h>
+#include <gtkmm/tooltips.h>
+
+namespace Inkscape { class Selection; }
+class SPDesktop;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class Dialog : public Gtk::Dialog {
+public:
+ Dialog(BaseObjectType *gobj); // fixme: remove this
+
+ Dialog(const char *prefs_path, int verb_num = 0, const char *apply_label = NULL);
+
+ virtual ~Dialog();
+
+ virtual void onDesktopActivated (SPDesktop*);
+ virtual void onShutdown();
+
+ /** Hide and show dialogs */
+ virtual void onHideF12();
+ virtual void onShowF12();
+
+ bool _hiddenF12;
+ bool _user_hidden; // when it is closed by the user, to prevent repopping on f12
+
+ void read_geometry();
+ void save_geometry();
+
+ const char *_prefs_path;
+
+ bool retransientize_suppress; // when true, do not retransientize (prevents races when switching new windows too fast)
+
+protected:
+
+ /**
+ * Tooltips object for all descendants to use
+ */
+ Gtk::Tooltips tooltips;
+
+ virtual void on_response(int response_id);
+ virtual bool on_delete_event (GdkEventAny*);
+ virtual void _apply();
+ virtual void _close();
+
+ static bool windowKeyPress( GtkWidget *widget, GdkEventKey *event );
+
+ Inkscape::Selection* _getSelection();
+
+ sigc::connection _desktop_activated_connection;
+ sigc::connection _dialogs_hidden_connection;
+ sigc::connection _dialogs_unhidden_connection;
+ sigc::connection _shutdown_connection;
+
+private:
+ Dialog(); // no constructor without params
+
+ Dialog(Dialog const &d); // no copy
+ Dialog& operator=(Dialog const &d); // no assign
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif //INKSCAPE_DIALOG_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/document-metadata.cpp b/src/ui/dialog/document-metadata.cpp
new file mode 100644
index 000000000..bbe64b201
--- /dev/null
+++ b/src/ui/dialog/document-metadata.cpp
@@ -0,0 +1,306 @@
+/** \file
+ *
+ * Document metadata dialog, Gtkmm-style
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# 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 "sp-namedview.h"
+
+#include "document-metadata.h"
+
+//using std::pair;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+#define SPACE_SIZE_X 15
+#define SPACE_SIZE_Y 15
+
+//===================================================
+
+//---------------------------------------------------
+
+static DocumentMetadata *_instance = 0;
+
+static void on_repr_attr_changed (Inkscape::XML::Node *, gchar const *, gchar const *, gchar const *, bool, gpointer);
+static void on_doc_replaced (SPDesktop* dt, SPDocument* doc);
+static void on_activate_desktop (Inkscape::Application *, SPDesktop* dt, void*);
+static void on_deactivate_desktop (Inkscape::Application *, SPDesktop* dt, void*);
+
+static Inkscape::XML::NodeEventVector const _repr_events = {
+ NULL, /* child_added */
+ NULL, /* child_removed */
+ on_repr_attr_changed,
+ NULL, /* content_changed */
+ NULL /* order_changed */
+};
+
+
+DocumentMetadata*
+DocumentMetadata::create()
+{
+ if (_instance) return _instance;
+ _instance = new DocumentMetadata;
+ _instance->init();
+ return _instance;
+}
+
+void
+DocumentMetadata::destroy()
+{
+ if (_instance)
+ {
+ delete _instance;
+ _instance = 0;
+ }
+}
+
+DocumentMetadata::DocumentMetadata()
+ : Dialog ("dialogs.documentmetadata", SP_VERB_DIALOG_METADATA),
+ _page_metadata1(1, 1), _page_metadata2(1, 1),
+ _prefs_path("dialogs.documentmetadata")
+{
+ hide();
+ set_resizable (false);
+ _tt.enable();
+ get_vbox()->set_spacing (4);
+ get_vbox()->pack_start (_notebook, true, true);
+
+ _notebook.append_page(_page_metadata1, _("Metadata"));
+ _notebook.append_page(_page_metadata2, _("License"));
+
+ build_metadata();
+}
+
+void
+DocumentMetadata::init()
+{
+ update();
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ repr->addListener (&_repr_events, this);
+
+ _doc_replaced_connection = SP_ACTIVE_DESKTOP->connectDocumentReplaced (sigc::ptr_fun (on_doc_replaced));
+
+ g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop",
+ G_CALLBACK(on_activate_desktop), 0);
+
+ g_signal_connect(G_OBJECT(INKSCAPE), "deactivate_desktop",
+ G_CALLBACK(on_deactivate_desktop), 0);
+
+ show_all_children();
+ present();
+}
+
+DocumentMetadata::~DocumentMetadata()
+{
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ repr->removeListenerByData (this);
+ _doc_replaced_connection.disconnect();
+
+ for (RDElist::iterator it = _rdflist.begin(); it != _rdflist.end(); it++)
+ delete (*it);
+}
+
+//========================================================================
+
+/**
+ * Helper function that attachs widgets in a 3xn table. The widgets come in an
+ * array that has two entries per table row. The two entries code for four
+ * possible cases: (0,0) means insert space in first column; (0, non-0) means
+ * widget in columns 2-3; (non-0, 0) means label in columns 1-3; and
+ * (non-0, non-0) means two widgets in columns 2 and 3.
+**/
+inline void
+attach_all (Gtk::Table &table, const Gtk::Widget *arr[], unsigned size, int start = 0)
+{
+ for (unsigned i=0, r=start; i<size/sizeof(Gtk::Widget*); i+=2)
+ {
+ if (arr[i] && arr[i+1])
+ {
+ table.attach (const_cast<Gtk::Widget&>(*arr[i]), 1, 2, r, r+1,
+ Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 2, 3, r, r+1,
+ Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ }
+ else
+ {
+ if (arr[i+1])
+ table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 1, 3, r, r+1,
+ Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ else if (arr[i])
+ {
+ Gtk::Label& label = reinterpret_cast<Gtk::Label&> (const_cast<Gtk::Widget&>(*arr[i]));
+ label.set_alignment (0.0);
+ table.attach (label, 0, 3, r, r+1,
+ Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ }
+ else
+ {
+ Gtk::HBox *space = manage (new Gtk::HBox);
+ space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y);
+ table.attach (*space, 0, 1, r, r+1,
+ (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0);
+ }
+ }
+ ++r;
+ }
+}
+
+void
+DocumentMetadata::build_metadata()
+{
+ _page_metadata1.show();
+
+ Gtk::Label *label = manage (new Gtk::Label);
+ label->set_markup (_("<b>Dublin Core Entities</b>"));
+ label->set_alignment (0.0);
+ _page_metadata1.table().attach (*label, 0,3,0,1, Gtk::FILL, (Gtk::AttachOptions)0,0,0);
+ /* add generic metadata entry areas */
+ struct rdf_work_entity_t * entity;
+ int row = 1;
+ for (entity = rdf_work_entities; entity && entity->name; entity++, row++) {
+ if ( entity->editable == RDF_EDIT_GENERIC ) {
+ EntityEntry *w = EntityEntry::create (entity, _tt, _wr);
+ _rdflist.push_back (w);
+ Gtk::HBox *space = manage (new Gtk::HBox);
+ space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y);
+ _page_metadata1.table().attach (*space, 0,1, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0);
+ _page_metadata1.table().attach (w->_label, 1,2, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0);
+ _page_metadata1.table().attach (*w->_packable, 2,3, row, row+1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ }
+ }
+
+ _page_metadata2.show();
+
+ row = 0;
+ Gtk::Label *llabel = manage (new Gtk::Label);
+ llabel->set_markup (_("<b>License</b>"));
+ llabel->set_alignment (0.0);
+ _page_metadata2.table().attach (*llabel, 0,3, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0);
+ /* add license selector pull-down and URI */
+ ++row;
+ _licensor.init (_tt, _wr);
+ Gtk::HBox *space = manage (new Gtk::HBox);
+ space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y);
+ _page_metadata2.table().attach (*space, 0,1, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0);
+ _page_metadata2.table().attach (_licensor, 1,3, row, row+1, Gtk::EXPAND|Gtk::FILL, (Gtk::AttachOptions)0,0,0);
+}
+
+/**
+ * Update dialog widgets from desktop.
+ */
+void
+DocumentMetadata::update()
+{
+ if (_wr.isUpdating()) return;
+
+ _wr.setUpdating (true);
+ set_sensitive (true);
+
+ //-----------------------------------------------------------meta pages
+ /* update the RDF entities */
+ for (RDElist::iterator it = _rdflist.begin(); it != _rdflist.end(); it++)
+ (*it)->update (SP_ACTIVE_DOCUMENT);
+
+ _licensor.update (SP_ACTIVE_DOCUMENT);
+
+ _wr.setUpdating (false);
+}
+
+//--------------------------------------------------------------------
+
+void
+DocumentMetadata::on_response (int id)
+{
+ if (id == Gtk::RESPONSE_CLOSE)
+ hide();
+}
+
+/**
+ * Called when XML node attribute changed; updates dialog widgets.
+ */
+static void
+on_repr_attr_changed (Inkscape::XML::Node *, gchar const *, gchar const *, gchar const *, bool, gpointer)
+{
+ if (!_instance)
+ return;
+
+ _instance->update();
+}
+
+static void
+on_activate_desktop (Inkscape::Application *, SPDesktop* dt, void*)
+{
+ if (!_instance)
+ return;
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ repr->addListener (&_repr_events, _instance);
+ _instance->_doc_replaced_connection = SP_ACTIVE_DESKTOP->connectDocumentReplaced (sigc::ptr_fun (on_doc_replaced));
+ _instance->update();
+}
+
+static void
+on_deactivate_desktop (Inkscape::Application *, SPDesktop* dt, void*)
+{
+ if (!_instance)
+ return;
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ repr->removeListenerByData (_instance);
+ _instance->_doc_replaced_connection.disconnect();
+}
+
+static void
+on_doc_replaced (SPDesktop* dt, SPDocument* doc)
+{
+ if (!_instance)
+ return;
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(dt));
+ repr->addListener (&_repr_events, _instance);
+ _instance->update();
+}
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/dialog/document-metadata.h b/src/ui/dialog/document-metadata.h
new file mode 100644
index 000000000..c3cba2d34
--- /dev/null
+++ b/src/ui/dialog/document-metadata.h
@@ -0,0 +1,84 @@
+/** \file
+ * \brief Document Metadata dialog
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005, 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_DOCUMENT_METADATA_H
+#define INKSCAPE_UI_DIALOG_DOCUMENT_METADATA_H
+
+#include <list>
+#include <sigc++/sigc++.h>
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+#include "ui/widget/licensor.h"
+#include "ui/widget/notebook-page.h"
+#include "ui/widget/registry.h"
+#include "dialog.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+ namespace XML {
+ class Node;
+ }
+ namespace UI {
+ namespace Widget {
+ class EntityEntry;
+ }
+ namespace Dialog {
+
+typedef std::list<EntityEntry*> RDElist;
+
+class DocumentMetadata : public Inkscape::UI::Dialog::Dialog {
+public:
+ void update();
+ static DocumentMetadata *create();
+ static void destroy();
+ sigc::connection _doc_replaced_connection;
+
+protected:
+ void build_metadata();
+ void init();
+ virtual void on_response (int);
+
+ Gtk::Tooltips _tt;
+ Gtk::Notebook _notebook;
+
+ NotebookPage _page_metadata1, _page_metadata2;
+
+ //---------------------------------------------------------------
+ RDElist _rdflist;
+ Licensor _licensor;
+
+ gchar * _prefs_path;
+ Registry _wr;
+
+private:
+ DocumentMetadata();
+ virtual ~DocumentMetadata();
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_DOCUMENT_METADATA_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
new file mode 100644
index 000000000..875e7d9f7
--- /dev/null
+++ b/src/ui/dialog/document-properties.cpp
@@ -0,0 +1,503 @@
+/** \file
+ *
+ * Document properties dialog, Gtkmm-style
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+
+#include "ui/widget/color-picker.h"
+#include "ui/widget/scalar-unit.h"
+
+#include "xml/node-event-vector.h"
+#include "helper/units.h"
+
+#include "inkscape.h"
+#include "verbs.h"
+#include "document.h"
+#include "desktop-handles.h"
+#include "desktop.h"
+#include "sp-namedview.h"
+
+#include "document-properties.h"
+
+using std::pair;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+#define SPACE_SIZE_X 15
+#define SPACE_SIZE_Y 10
+
+//===================================================
+
+//---------------------------------------------------
+
+static DocumentProperties *_instance = 0;
+
+static void on_repr_attr_changed (Inkscape::XML::Node *, gchar const *, gchar const *, gchar const *, bool, gpointer);
+static void on_doc_replaced (SPDesktop* dt, SPDocument* doc);
+static void on_activate_desktop (Inkscape::Application *, SPDesktop* dt, void*);
+static void on_deactivate_desktop (Inkscape::Application *, SPDesktop* dt, void*);
+
+static Inkscape::XML::NodeEventVector const _repr_events = {
+ NULL, /* child_added */
+ NULL, /* child_removed */
+ on_repr_attr_changed,
+ NULL, /* content_changed */
+ NULL /* order_changed */
+};
+
+
+DocumentProperties*
+DocumentProperties::create()
+{
+ if (_instance) return _instance;
+ _instance = new DocumentProperties;
+ _instance->init();
+ return _instance;
+}
+
+void
+DocumentProperties::destroy()
+{
+ if (_instance)
+ {
+ delete _instance;
+ _instance = 0;
+ }
+}
+
+DocumentProperties::DocumentProperties()
+ : Dialog ("dialogs.documentoptions", SP_VERB_DIALOG_NAMEDVIEW),
+ _page_page(1, 1), _page_grid(1, 1), _page_guides(1, 1),
+ _page_snap(1, 1),
+ _prefs_path("dialogs.documentoptions")
+{
+ hide();
+ set_resizable (false);
+ _tt.enable();
+ get_vbox()->set_spacing (4);
+ get_vbox()->pack_start (_notebook, true, true);
+
+ _notebook.append_page(_page_page, _("Page"));
+ _notebook.append_page(_page_grid, _("Grid/Guides"));
+ _notebook.append_page(_page_snap, _("Snap"));
+
+ build_page();
+ build_grid();
+ build_snap();
+}
+
+void
+DocumentProperties::init()
+{
+ update();
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ repr->addListener (&_repr_events, this);
+
+ _doc_replaced_connection = SP_ACTIVE_DESKTOP->connectDocumentReplaced (sigc::ptr_fun (on_doc_replaced));
+
+ g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop",
+ G_CALLBACK(on_activate_desktop), 0);
+
+ g_signal_connect(G_OBJECT(INKSCAPE), "deactivate_desktop",
+ G_CALLBACK(on_deactivate_desktop), 0);
+
+ show_all_children();
+ present();
+}
+
+DocumentProperties::~DocumentProperties()
+{
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ repr->removeListenerByData (this);
+ _doc_replaced_connection.disconnect();
+}
+
+//========================================================================
+
+/**
+ * Helper function that attachs widgets in a 3xn table. The widgets come in an
+ * array that has two entries per table row. The two entries code for four
+ * possible cases: (0,0) means insert space in first column; (0, non-0) means
+ * widget in columns 2-3; (non-0, 0) means label in columns 1-3; and
+ * (non-0, non-0) means two widgets in columns 2 and 3.
+**/
+inline void
+attach_all (Gtk::Table &table, const Gtk::Widget *arr[], unsigned size, int start = 0)
+{
+ for (unsigned i=0, r=start; i<size/sizeof(Gtk::Widget*); i+=2)
+ {
+ if (arr[i] && arr[i+1])
+ {
+ table.attach (const_cast<Gtk::Widget&>(*arr[i]), 1, 2, r, r+1,
+ Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 2, 3, r, r+1,
+ Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ }
+ else
+ {
+ if (arr[i+1])
+ table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 1, 3, r, r+1,
+ Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ else if (arr[i])
+ {
+ Gtk::Label& label = reinterpret_cast<Gtk::Label&> (const_cast<Gtk::Widget&>(*arr[i]));
+ label.set_alignment (0.0);
+ table.attach (label, 0, 3, r, r+1,
+ Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ }
+ else
+ {
+ Gtk::HBox *space = manage (new Gtk::HBox);
+ space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y);
+ table.attach (*space, 0, 1, r, r+1,
+ (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0);
+ }
+ }
+ ++r;
+ }
+}
+
+void
+DocumentProperties::build_page()
+{
+ _page_page.show();
+
+ _rcp_bg.init (_("Background:"), _("Background color"), _("Color and transparency of the page background (also used for bitmap export)"),
+ "pagecolor", "inkscape:pageopacity", _wr);
+ _rcb_canb.init (_("Show page border"), _("If set, rectangular page border is shown"), "showborder", _wr, false);
+ _rcb_bord.init (_("Border on top of drawing"), _("If set, border is always on top of the drawing"), "borderlayer", _wr, false);
+ _rcp_bord.init (_("Border color:"), _("Page border color"),
+ _("Color of the page border"),
+ "bordercolor", "borderopacity", _wr);
+ _rcb_shad.init (_("Show border shadow"), "If set, page border shows a shadow on its right and lower side", "inkscape:showpageshadow", _wr, false);
+ _rum_deflt.init (_("Default units:"), "inkscape:document-units", _wr);
+ Gtk::Label* label_gen = manage (new Gtk::Label);
+ label_gen->set_markup (_("<b>General</b>"));
+ Gtk::Label* label_bor = manage (new Gtk::Label);
+ label_bor->set_markup (_("<b>Border</b>"));
+ Gtk::Label *label_for = manage (new Gtk::Label);
+ label_for->set_markup (_("<b>Format</b>"));
+ _page_sizer.init (_wr);
+
+ const Gtk::Widget* widget_array[] =
+ {
+ label_gen, 0,
+ _rum_deflt._label, _rum_deflt._sel,
+ _rcp_bg._label, _rcp_bg._cp,
+ 0, 0,
+ label_for, 0,
+ 0, &_page_sizer,
+ 0, 0,
+ label_bor, 0,
+ 0, _rcb_canb._button,
+ 0, _rcb_bord._button,
+ 0, _rcb_shad._button,
+ _rcp_bord._label, _rcp_bord._cp,
+ };
+
+ attach_all (_page_page.table(), widget_array, sizeof(widget_array));
+}
+
+void
+DocumentProperties::build_grid()
+{
+ _page_grid.show();
+
+ /// \todo FIXME: gray out snapping when grid is off.
+ /// Dissenting view: you want snapping without grid.
+
+ _rcbgrid.init (_("Show grid"), _("Show or hide grid"), "showgrid", _wr);
+ _rumg.init (_("Grid units:"), "grid_units", _wr);
+ _rsu_ox.init (_("Origin X:"), _("X coordinate of grid origin"),
+ "gridoriginx", _rumg, _wr);
+ _rsu_oy.init (_("Origin Y:"), _("Y coordinate of grid origin"),
+ "gridoriginy", _rumg, _wr);
+ _rsu_sx.init (_("Spacing X:"), _("Distance of vertical grid lines"),
+ "gridspacingx", _rumg, _wr);
+ _rsu_sy.init (_("Spacing Y:"), _("Distance of horizontal grid lines"),
+ "gridspacingy", _rumg, _wr);
+ _rcp_gcol.init (_("Grid line color:"), _("Grid line color"),
+ _("Color of grid lines"), "gridcolor", "gridopacity", _wr);
+ _rcp_gmcol.init (_("Major grid line color:"), _("Major grid line color"),
+ _("Color of the major (highlighted) grid lines"),
+ "gridempcolor", "gridempopacity", _wr);
+ _rsi.init (_("Major grid line every:"), _("lines"), "gridempspacing", _wr);
+ _rcb_sgui.init (_("Show guides"), _("Show or hide guides"), "showguides", _wr);
+ _rcp_gui.init (_("Guide color:"), _("Guideline color"),
+ _("Color of guidelines"), "guidecolor", "guideopacity", _wr);
+ _rcp_hgui.init (_("Highlight color:"), _("Highlighted guideline color"),
+ _("Color of a guideline when it is under mouse"),
+ "guidehicolor", "guidehiopacity", _wr);
+ Gtk::Label *label_grid = manage (new Gtk::Label);
+ label_grid->set_markup (_("<b>Grid</b>"));
+ Gtk::Label *label_gui = manage (new Gtk::Label);
+ label_gui->set_markup (_("<b>Guides</b>"));
+
+ const Gtk::Widget* widget_array[] =
+ {
+ label_grid, 0,
+ 0, _rcbgrid._button,
+ _rumg._label, _rumg._sel,
+ 0, _rsu_ox.getSU(),
+ 0, _rsu_oy.getSU(),
+ 0, _rsu_sx.getSU(),
+ 0, _rsu_sy.getSU(),
+ _rcp_gcol._label, _rcp_gcol._cp,
+ 0, 0,
+ _rcp_gmcol._label, _rcp_gmcol._cp,
+ _rsi._label, &_rsi._hbox,
+ 0, 0,
+ label_gui, 0,
+ 0, _rcb_sgui._button,
+ _rcp_gui._label, _rcp_gui._cp,
+ _rcp_hgui._label, _rcp_hgui._cp,
+ };
+
+ attach_all (_page_grid.table(), widget_array, sizeof(widget_array));
+}
+
+void
+DocumentProperties::build_snap()
+{
+ _page_snap.show();
+
+ _rcbsnbo.init (_("Snap bounding boxes to objects"),
+ _("Snap the edges of the object bounding boxes to other objects"),
+ "inkscape:object-bbox", _wr);
+ _rcbsnnob.init (_("Snap nodes to objects"),
+ _("Snap the nodes of objects to other objects"),
+ "inkscape:object-points", _wr);
+ _rcbsnop.init (_("Snap to object paths"),
+ _("Snap to other object paths"),
+ "inkscape:object-paths", _wr);
+ _rcbsnon.init (_("Snap to object nodes"),
+ _("Snap to other object nodes"),
+ "inkscape:object-nodes", _wr);
+ _rsu_sno.init (_("Snap sensitivity:"), _(""),
+ _("Controls max. snapping distance from object"),
+ "objecttolerance", _wr);
+ _rcbsnbb.init (_("Snap bounding boxes to grid"),
+ _("Snap the edges of the object bounding boxes"),
+ "inkscape:grid-bbox", _wr);
+ _rcbsnnod.init (_("Snap nodes to grid"),
+ _("Snap path nodes, text baselines, ellipse centers, etc."),
+ "inkscape:grid-points", _wr);
+ _rsu_sn.init (_("Snap sensitivity:"), _(""),
+ _("Controls max. snapping distance from grid"),
+ "gridtolerance", _wr);
+ _rcb_snpgui.init (_("Snap bounding boxes to guides"),
+ _("Snap the edges of the object bounding boxes"),
+ "inkscape:guide-bbox", _wr);
+ _rcb_snbgui.init (_("Snap points to guides"),
+ _("Snap path nodes, text baselines, ellipse centers, etc."),
+ "inkscape:guide-points", _wr);
+ _rsu_gusn.init (_("Snap sensitivity:"), _(""),
+ _("Controls max. snapping distance from guides"), "guidetolerance", _wr);
+ _rrb_pix.init (_("Sensitivity:"), _("Screen pixels"), _("px units"),
+ _("Sensitivity is always the same, regardless of zoom."),
+ _("Sensitivity changes with zoom; zooming in will enlarge max. snapping distance."),
+ _("inkscape:has_abs_tolerance"), _wr);
+ Gtk::Label *label_o = manage (new Gtk::Label);
+ label_o->set_markup (_("<b>Object Snapping</b>"));
+ Gtk::Label *label_gr = manage (new Gtk::Label);
+ label_gr->set_markup (_("<b>Grid Snapping</b>"));
+ Gtk::Label *label_gu = manage (new Gtk::Label);
+ label_gu->set_markup (_("<b>Guide Snapping</b>"));
+
+ const Gtk::Widget* array[] =
+ {
+ label_o, 0,
+ 0, _rcbsnbo._button,
+ 0, _rcbsnnob._button,
+ 0, _rcbsnop._button,
+ 0, _rcbsnon._button,
+ 0, _rsu_sno._hbox,
+ 0, 0,
+ label_gr, 0,
+ 0, _rcbsnbb._button,
+ 0, _rcbsnnod._button,
+ 0, _rsu_sn._hbox,
+ 0, 0,
+ label_gu, 0,
+ 0, _rcb_snpgui._button,
+ 0, _rcb_snbgui._button,
+ 0, _rsu_gusn._hbox,
+ 0, 0,
+ 0, _rrb_pix._hbox,
+ };
+
+ attach_all (_page_snap.table(), array, sizeof(array));
+ }
+
+/**
+ * Update dialog widgets from desktop.
+ */
+void
+DocumentProperties::update()
+{
+ if (_wr.isUpdating()) return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ SPNamedView *nv = SP_DT_NAMEDVIEW(dt);
+ _wr.setUpdating (true);
+ set_sensitive (true);
+
+ //-----------------------------------------------------------page page
+ _rcp_bg.setRgba32 (nv->pagecolor);
+ _rcb_canb.setActive (nv->showborder);
+ _rcb_bord.setActive (nv->borderlayer == SP_BORDER_LAYER_TOP);
+ _rcp_bord.setRgba32 (nv->bordercolor);
+ _rcb_shad.setActive (nv->showpageshadow);
+
+ if (nv->doc_units)
+ _rum_deflt.setUnit (nv->doc_units);
+
+ double const doc_w_px = sp_document_width(SP_DT_DOCUMENT(dt));
+ double const doc_h_px = sp_document_height(SP_DT_DOCUMENT(dt));
+ _page_sizer.setDim (doc_w_px, doc_h_px);
+
+ //-----------------------------------------------------------grid page
+ _rcbgrid.setActive (nv->showgrid);
+ _rumg.setUnit (nv->gridunit);
+
+ gdouble val;
+ val = nv->gridorigin[NR::X];
+ val = sp_pixels_get_units (val, *(nv->gridunit));
+ _rsu_ox.setValue (val);
+ val = nv->gridorigin[NR::Y];
+ val = sp_pixels_get_units (val, *(nv->gridunit));
+ _rsu_oy.setValue (val);
+ val = nv->gridspacing[NR::X];
+ double gridx = sp_pixels_get_units (val, *(nv->gridunit));
+ _rsu_sx.setValue (gridx);
+ val = nv->gridspacing[NR::Y];
+ double gridy = sp_pixels_get_units (val, *(nv->gridunit));
+ _rsu_sy.setValue (gridy);
+
+ _rcp_gcol.setRgba32 (nv->gridcolor);
+ _rcp_gmcol.setRgba32 (nv->gridempcolor);
+ _rsi.setValue (nv->gridempspacing);
+
+ //-----------------------------------------------------------guide
+ _rcb_sgui.setActive (nv->showguides);
+ _rcp_gui.setRgba32 (nv->guidecolor);
+ _rcp_hgui.setRgba32 (nv->guidehicolor);
+
+ //-----------------------------------------------------------snap
+ _rcbsnbo.setActive (nv->object_snapper.getSnapTo(Inkscape::Snapper::BBOX_POINT));
+ _rcbsnnob.setActive (nv->object_snapper.getSnapTo(Inkscape::Snapper::SNAP_POINT));
+ _rcbsnop.setActive (nv->object_snapper.getSnapToPaths());
+ _rcbsnop.setActive (nv->object_snapper.getSnapToNodes());
+ _rsu_sno.setValue (nv->objecttolerance, nv->has_abs_tolerance);
+
+ _rcbsnbb.setActive (nv->grid_snapper.getSnapTo(Inkscape::Snapper::BBOX_POINT));
+ _rcbsnnod.setActive (nv->grid_snapper.getSnapTo(Inkscape::Snapper::SNAP_POINT));
+ _rsu_sn.setValue (nv->gridtolerance, nv->has_abs_tolerance);
+
+ _rcb_snpgui.setActive (nv->guide_snapper.getSnapTo(Inkscape::Snapper::BBOX_POINT));
+ _rcb_snbgui.setActive (nv->guide_snapper.getSnapTo(Inkscape::Snapper::SNAP_POINT));
+ _rsu_gusn.setValue (nv->guidetolerance, nv->has_abs_tolerance);
+ _rrb_pix.setValue (true);
+
+ _wr.setUpdating (false);
+}
+
+//--------------------------------------------------------------------
+
+void
+DocumentProperties::on_response (int id)
+{
+ if (id == Gtk::RESPONSE_DELETE_EVENT || id == Gtk::RESPONSE_CLOSE)
+ {
+ _rcp_bg.closeWindow();
+ _rcp_bord.closeWindow();
+ _rcp_gcol.closeWindow();
+ _rcp_gmcol.closeWindow();
+ _rcp_gui.closeWindow();
+ _rcp_hgui.closeWindow();
+ }
+
+ if (id == Gtk::RESPONSE_CLOSE)
+ hide();
+}
+
+/**
+ * Called when XML node attribute changed; updates dialog widgets.
+ */
+static void
+on_repr_attr_changed (Inkscape::XML::Node *, gchar const *, gchar const *, gchar const *, bool, gpointer)
+{
+ if (!_instance)
+ return;
+
+ _instance->update();
+}
+
+static void
+on_activate_desktop (Inkscape::Application *, SPDesktop* dt, void*)
+{
+ if (!_instance)
+ return;
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ repr->addListener (&_repr_events, _instance);
+ _instance->_doc_replaced_connection = SP_ACTIVE_DESKTOP->connectDocumentReplaced (sigc::ptr_fun (on_doc_replaced));
+ _instance->update();
+}
+
+static void
+on_deactivate_desktop (Inkscape::Application *, SPDesktop* dt, void*)
+{
+ if (!_instance)
+ return;
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ repr->removeListenerByData (_instance);
+ _instance->_doc_replaced_connection.disconnect();
+}
+
+static void
+on_doc_replaced (SPDesktop* dt, SPDocument* doc)
+{
+ if (!_instance)
+ return;
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(dt));
+ repr->addListener (&_repr_events, _instance);
+ _instance->update();
+}
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h
new file mode 100644
index 000000000..ae2c30cbf
--- /dev/null
+++ b/src/ui/dialog/document-properties.h
@@ -0,0 +1,103 @@
+/** \file
+ * \brief Document Properties dialog
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_DOCUMENT_PREFERENCES_H
+#define INKSCAPE_UI_DIALOG_DOCUMENT_PREFERENCES_H
+
+#include <list>
+#include <sigc++/sigc++.h>
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+#include "ui/widget/notebook-page.h"
+#include "ui/widget/page-sizer.h"
+#include "ui/widget/registered-widget.h"
+#include "ui/widget/registry.h"
+#include "ui/widget/tolerance-slider.h"
+#include "dialog.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+ namespace XML {
+ class Node;
+ }
+ namespace UI {
+ namespace Dialog {
+
+class DocumentProperties : public Inkscape::UI::Dialog::Dialog {
+public:
+ void update();
+ static DocumentProperties *create();
+ static void destroy();
+ sigc::connection _doc_replaced_connection;
+
+protected:
+ void build_page();
+ void build_grid();
+ void build_guides();
+ void build_snap();
+ void init();
+ virtual void on_response (int);
+
+ Gtk::Tooltips _tt;
+ Gtk::Notebook _notebook;
+
+ NotebookPage _page_page, _page_grid, _page_guides;
+ NotebookPage _page_snap;
+
+ RegisteredCheckButton _rcb_canb, _rcb_bord, _rcb_shad;
+ RegisteredColorPicker _rcp_bg, _rcp_bord;
+ RegisteredUnitMenu _rum_deflt;
+ PageSizer _page_sizer;
+ //---------------------------------------------------------------
+ RegisteredCheckButton _rcbgrid, _rcbsnbb, _rcbsnnod;
+ RegisteredUnitMenu _rumg, _rums;
+ RegisteredScalarUnit _rsu_ox, _rsu_oy, _rsu_sx, _rsu_sy;
+ RegisteredColorPicker _rcp_gcol, _rcp_gmcol;
+ RegisteredSuffixedInteger _rsi;
+ //---------------------------------------------------------------
+ RegisteredCheckButton _rcb_sgui, _rcb_snpgui, _rcb_snbgui;
+ RegisteredUnitMenu _rum_gusn;
+ ToleranceSlider _rsu_sn, _rsu_gusn;
+ RegisteredColorPicker _rcp_gui, _rcp_hgui;
+ //---------------------------------------------------------------
+ RegisteredCheckButton _rcbsnbo, _rcbsnnob, _rcbsnop, _rcbsnon;
+ RegisteredUnitMenu _rumso;
+ ToleranceSlider _rsu_sno;
+ RegisteredRadioButtonPair _rrb_pix;
+ //---------------------------------------------------------------
+
+ gchar * _prefs_path;
+ Registry _wr;
+
+private:
+ DocumentProperties();
+ virtual ~DocumentProperties();
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_DOCUMENT_PREFERENCES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp
new file mode 100644
index 000000000..d9ea2d25d
--- /dev/null
+++ b/src/ui/dialog/export.cpp
@@ -0,0 +1,58 @@
+/**
+ * \brief Export dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "export.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+Export::Export()
+ : Dialog ("dialogs.export", SP_VERB_FILE_EXPORT),
+ _page_export(1, 1)
+{
+ // Top level vbox
+ Gtk::VBox *vbox = get_vbox();
+ vbox->set_spacing(4);
+
+ // Notebook for individual transformations
+ vbox->pack_start(_notebook, true, true);
+
+ _notebook.append_page(_page_export, _("Export"));
+
+ // TODO: Insert widgets
+
+ show_all_children();
+}
+
+Export::~Export()
+{
+}
+
+} // 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/export.h b/src/ui/dialog/export.h
new file mode 100644
index 000000000..567eae10d
--- /dev/null
+++ b/src/ui/dialog/export.h
@@ -0,0 +1,59 @@
+/**
+ * \brief Export dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_EXPORT_H
+#define INKSCAPE_UI_DIALOG_EXPORT_H
+
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+#include "dialog.h"
+#include "ui/widget/notebook-page.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class Export : public Dialog {
+public:
+ Export();
+ virtual ~Export();
+
+ static Export *create() { return new Export(); }
+
+protected:
+ Gtk::Notebook _notebook;
+
+ NotebookPage _page_export;
+
+private:
+ Export(Export const &d);
+ Export& operator=(Export const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_EXPORT_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/extension-editor.cpp b/src/ui/dialog/extension-editor.cpp
new file mode 100644
index 000000000..2b17983ce
--- /dev/null
+++ b/src/ui/dialog/extension-editor.cpp
@@ -0,0 +1,48 @@
+/**
+ * \brief Extension editor
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "extension-editor.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+ExtensionEditor::ExtensionEditor()
+ : Dialog ("dialogs.extensioneditor", SP_VERB_NONE /*FIXME*/)
+{
+ // TODO: Insert widgets
+
+ show_all_children();
+}
+
+ExtensionEditor::~ExtensionEditor()
+{
+}
+
+} // 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/extension-editor.h b/src/ui/dialog/extension-editor.h
new file mode 100644
index 000000000..4c6beb7f7
--- /dev/null
+++ b/src/ui/dialog/extension-editor.h
@@ -0,0 +1,52 @@
+/**
+ * \brief Extension editor
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_EXTENSION_EDITOR_H
+#define INKSCAPE_UI_DIALOG_EXTENSION_EDITOR_H
+
+#include "dialog.h"
+
+#include <glibmm/i18n.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class ExtensionEditor : public Dialog {
+public:
+ ExtensionEditor();
+ virtual ~ExtensionEditor();
+
+ static ExtensionEditor *create() { return new ExtensionEditor(); }
+
+protected:
+
+private:
+ ExtensionEditor(ExtensionEditor const &d);
+ ExtensionEditor& operator=(ExtensionEditor const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_EXTENSION_EDITOR_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/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp
new file mode 100644
index 000000000..ae48fc1ab
--- /dev/null
+++ b/src/ui/dialog/fill-and-stroke.cpp
@@ -0,0 +1,62 @@
+/**
+ * \brief Fill and Stroke dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "fill-and-stroke.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+FillAndStroke::FillAndStroke()
+ : Dialog ("dialogs.fillstroke", SP_VERB_DIALOG_FILL_STROKE),
+ _page_fill(1, 1),
+ _page_stroke_paint(1, 1),
+ _page_stroke_style(1, 1)
+{
+ // Top level vbox
+ Gtk::VBox *vbox = get_vbox();
+ vbox->set_spacing(4);
+
+ // Notebook for individual transformations
+ vbox->pack_start(_notebook, true, true);
+
+ _notebook.append_page(_page_fill, _("Fill"));
+ _notebook.append_page(_page_stroke_paint, _("Stroke Paint"));
+ _notebook.append_page(_page_stroke_style, _("Stroke Style"));
+
+ // TODO: Insert widgets
+
+ show_all_children();
+}
+
+FillAndStroke::~FillAndStroke()
+{
+}
+
+} // 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/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h
new file mode 100644
index 000000000..0e63ef1c3
--- /dev/null
+++ b/src/ui/dialog/fill-and-stroke.h
@@ -0,0 +1,61 @@
+/**
+ * \brief Fill and Stroke dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_FILL_AND_STROKE_H
+#define INKSCAPE_UI_DIALOG_FILL_AND_STROKE_H
+
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+#include "dialog.h"
+#include "ui/widget/notebook-page.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class FillAndStroke : public Dialog {
+public:
+ FillAndStroke();
+ virtual ~FillAndStroke();
+
+ static FillAndStroke *create() { return new FillAndStroke(); }
+
+protected:
+ Gtk::Notebook _notebook;
+
+ NotebookPage _page_fill;
+ NotebookPage _page_stroke_paint;
+ NotebookPage _page_stroke_style;
+
+private:
+ FillAndStroke(FillAndStroke const &d);
+ FillAndStroke& operator=(FillAndStroke const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_FILL_AND_STROKE_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/find.cpp b/src/ui/dialog/find.cpp
new file mode 100644
index 000000000..5d559261f
--- /dev/null
+++ b/src/ui/dialog/find.cpp
@@ -0,0 +1,58 @@
+/**
+ * \brief Find dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "find.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+Find::Find()
+ : Dialog ("dialogs.find", SP_VERB_DIALOG_FIND),
+ _page_find(1, 1)
+{
+ // Top level vbox
+ Gtk::VBox *vbox = get_vbox();
+ vbox->set_spacing(4);
+
+ // Notebook for individual transformations
+ vbox->pack_start(_notebook, true, true);
+
+ _notebook.append_page(_page_find, _("Find"));
+
+ // TODO: Insert widgets
+
+ show_all_children();
+}
+
+Find::~Find()
+{
+}
+
+} // 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/find.h b/src/ui/dialog/find.h
new file mode 100644
index 000000000..6d019b765
--- /dev/null
+++ b/src/ui/dialog/find.h
@@ -0,0 +1,59 @@
+/**
+ * \brief Find dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_FIND_H
+#define INKSCAPE_UI_DIALOG_FIND_H
+
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+#include "dialog.h"
+#include "ui/widget/notebook-page.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class Find : public Dialog {
+public:
+ Find();
+ virtual ~Find();
+
+ static Find *create() { return new Find(); }
+
+protected:
+ Gtk::Notebook _notebook;
+
+ NotebookPage _page_find;
+
+private:
+ Find(Find const &d);
+ Find& operator=(Find const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_FIND_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/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
new file mode 100644
index 000000000..1fa2049d2
--- /dev/null
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -0,0 +1,525 @@
+/**
+ * \brief Inkscape Preferences dialog
+ *
+ * Authors:
+ * Carl Hetherington
+ * Marco Scholten
+ *
+ * Copyright (C) 2004, 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/frame.h>
+#include <gtkmm/scrolledwindow.h>
+
+#include "prefs-utils.h"
+#include "inkscape-preferences.h"
+#include "verbs.h"
+#include "selcue.h"
+#include <iostream>
+#include "enums.h"
+#include "inkscape.h"
+#include "desktop-handles.h"
+#include "message-stack.h"
+#include "style.h"
+#include "selection.h"
+#include "selection-chemistry.h"
+#include "xml/repr.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+InkscapePreferences::InkscapePreferences()
+ : Dialog ("dialogs.preferences", SP_VERB_DIALOG_DISPLAY),
+ _max_dialog_width(0),
+ _max_dialog_height(0),
+ _current_page(0)
+{
+ //get the width of a spinbutton
+ Gtk::SpinButton* sb = new Gtk::SpinButton;
+ sb->set_width_chars(6);
+ this->get_vbox()->add(*sb);
+ this->show_all_children();
+ _sb_width = sb->size_request().width;
+ this->get_vbox()->remove(*sb);
+ delete sb;
+
+ //Main HBox
+ Gtk::HBox* hbox_list_page = Gtk::manage(new Gtk::HBox());
+ hbox_list_page->set_border_width(12);
+ hbox_list_page->set_spacing(12);
+ this->get_vbox()->add(*hbox_list_page);
+
+
+ //Pagelist
+ Gtk::Frame* list_frame = Gtk::manage(new Gtk::Frame());
+ Gtk::ScrolledWindow* scrolled_window = Gtk::manage(new Gtk::ScrolledWindow());
+ hbox_list_page->pack_start(*list_frame, false, true, 0);
+ _page_list.set_headers_visible(false);
+ scrolled_window->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+ scrolled_window->add(_page_list);
+ list_frame->set_shadow_type(Gtk::SHADOW_IN);
+ list_frame->add(*scrolled_window);
+ _page_list_model = Gtk::TreeStore::create(_page_list_columns);
+ _page_list.set_model(_page_list_model);
+ _page_list.append_column("id",_page_list_columns._col_id);
+ Glib::RefPtr<Gtk::TreeSelection> _page_list_selection = _page_list.get_selection();
+ _page_list_selection->signal_changed().connect(sigc::mem_fun(*this, &InkscapePreferences::on_pagelist_selection_changed));
+ _page_list_selection->set_mode(Gtk::SELECTION_BROWSE);
+
+ //Pages
+ Gtk::VBox* vbox_page = Gtk::manage(new Gtk::VBox());
+ Gtk::Frame* title_frame = Gtk::manage(new Gtk::Frame());
+ hbox_list_page->pack_start(*vbox_page, true, true, 0);
+ title_frame->add(_page_title);
+ vbox_page->pack_start(*title_frame, false, false, 0);
+ vbox_page->pack_start(_page_frame, true, true, 0);
+ _page_frame.set_shadow_type(Gtk::SHADOW_IN);
+ title_frame->set_shadow_type(Gtk::SHADOW_IN);
+
+ initPageMouse();
+ initPageScrolling();
+ initPageSteps();
+ initPageTools();
+ initPageWindows();
+ initPageClones();
+ initPageTransforms();
+ initPageSelecting();
+ initPageMisc();
+
+ //calculate the size request for this dialog
+ this->show_all_children();
+ _page_list.expand_all();
+ _page_list_model->foreach_iter(sigc::mem_fun(*this, &InkscapePreferences::SetMaxDialogSize));
+ this->set_size_request(_max_dialog_width, _max_dialog_height);
+ _page_list.collapse_all();
+
+ //Select page todo: select last
+ Gtk::TreeModel::iterator iter = _page_list_model->children().begin();
+ if(iter)
+ _page_list_selection->select(iter);
+}
+
+InkscapePreferences::~InkscapePreferences()
+{
+}
+
+Gtk::TreeModel::iterator InkscapePreferences::AddPage(DialogPage& p, Glib::ustring title)
+{
+ Gtk::TreeModel::iterator iter = _page_list_model->append();
+ Gtk::TreeModel::Row row = *iter;
+ row[_page_list_columns._col_id] = title;
+ row[_page_list_columns._col_page] = &p;
+ return iter;
+}
+
+Gtk::TreeModel::iterator InkscapePreferences::AddPage(DialogPage& p, Glib::ustring title, Gtk::TreeModel::iterator parent)
+{
+ Gtk::TreeModel::iterator iter = _page_list_model->append((*parent).children());
+ Gtk::TreeModel::Row row = *iter;
+ row[_page_list_columns._col_id] = title;
+ row[_page_list_columns._col_page] = &p;
+ return iter;
+}
+
+void InkscapePreferences::initPageMouse()
+{
+ this->AddPage(_page_mouse, _("Mouse"));
+ _mouse_sens.init ( "options.cursortolerance", "value", 0.0, 30.0, 1.0, 1.0, 8.0, true, false);
+ _page_mouse.add_line( false, _("Grab sensitivity:"), _mouse_sens, _("pixels"),
+ _("How close on the screen you need to be to an object to be able to grab it with mouse (in screen pixels)"), false);
+ _mouse_thres.init ( "options.dragtolerance", "value", 0.0, 20.0, 1.0, 1.0, 4.0, true, false);
+ _page_mouse.add_line( false, _("Click/drag threshold:"), _mouse_thres, _("pixels"),
+ _("Maximum mouse drag (in screen pixels) which is considered a click, not a drag"), false);
+}
+
+void InkscapePreferences::initPageScrolling()
+{
+ this->AddPage(_page_scrolling, _("Scrolling"));
+ _scroll_wheel.init ( "options.wheelscroll", "value", 0.0, 1000.0, 1.0, 1.0, 40.0, true, false);
+ _page_scrolling.add_line( false, _("Mouse wheel scrolls by:"), _scroll_wheel, _("pixels"),
+ _("One mouse wheel notch scrolls by this distance in screen pixels (horizontally with Shift)"), false);
+ _page_scrolling.add_group_header( _("Ctrl+arrows"));
+ _scroll_arrow_px.init ( "options.keyscroll", "value", 0.0, 1000.0, 1.0, 1.0, 10.0, true, false);
+ _page_scrolling.add_line( true, _("Scroll by:"), _scroll_arrow_px, _("pixels"),
+ _("Pressing Ctrl+arrow key scrolls by this distance (in screen pixels)"), false);
+ _scroll_arrow_acc.init ( "options.scrollingacceleration", "value", 0.0, 5.0, 0.01, 1.0, 0.35, false, false);
+ _page_scrolling.add_line( true, _("Acceleration:"), _scroll_arrow_acc, "",
+ _("Pressing and holding Ctrl+arrow will gradually speed up scrolling (0 for no acceleration)"), false);
+ _page_scrolling.add_group_header( _("Autoscrolling"));
+ _scroll_auto_speed.init ( "options.autoscrollspeed", "value", 0.0, 5.0, 0.01, 1.0, 0.7, false, false);
+ _page_scrolling.add_line( true, _("Speed:"), _scroll_auto_speed, "",
+ _("How fast the canvas autoscrolls when you drag beyond canvas edge (0 to turn autoscroll off)"), false);
+ _scroll_auto_thres.init ( "options.autoscrolldistance", "value", -600.0, 600.0, 1.0, 1.0, -10.0, true, false);
+ _page_scrolling.add_line( true, _("Threshold:"), _scroll_auto_thres, _("pixels"),
+ _("How far (in screen pixels) you need to be from the canvas edge to trigger autoscroll; positive is outside the canvas, negative is within the canvas"), false);
+}
+
+void InkscapePreferences::initPageSteps()
+{
+ this->AddPage(_page_steps, _("Steps"));
+
+ _steps_arrow.init ( "options.nudgedistance", "value", 0.0, 3000.0, 0.01, 1.0, 2.0, false, false);
+ _page_steps.add_line( false, _("Arrow keys move by:"), _steps_arrow, _("px"),
+ _("Pressing an arrow key moves selected object(s) or node(s) by this distance (in px units)"), false);
+ _steps_scale.init ( "options.defaultscale", "value", 0.0, 3000.0, 0.01, 1.0, 2.0, false, false);
+ _page_steps.add_line( false, _("> and < scale by:"), _steps_scale, _("px"),
+ _("Pressing > or < scales selection up or down by this increment (in px units)"), false);
+ _steps_inset.init ( "options.defaultoffsetwidth", "value", 0.0, 3000.0, 0.01, 1.0, 2.0, false, false);
+ _page_steps.add_line( false, _("Inset/Outset by:"), _steps_inset, _("px"),
+ _("Inset and Outset commands displace the path by this distance (in px units)"), false);
+ _steps_compass.init ( _("Compass-like display of angles"), "options.compassangledisplay", "value", true);
+ _page_windows.add_line( false, "", _steps_compass, "",
+ _("When on, angles are displayed with 0 at north, 0 to 360 range, positive clockwise; otherwise with 0 at east, -180 to 180 range, positive counterclockwise"));
+ int const num_items = 12;
+ Glib::ustring labels[num_items] = {"90", "60", "45", "30", "15", "10", "7.5", "6", "3", "2", "1", _("None")};
+ int values[num_items] = {2, 3, 4, 6, 12, 18, 24, 30, 60, 90, 180, 0};
+ _steps_rot_snap.set_size_request(_sb_width);
+ _steps_rot_snap.init("options.rotationsnapsperpi", "value", labels, values, num_items, 12);
+ _page_steps.add_line( false, _("Rotation snaps every:"), _steps_rot_snap, _("degrees"),
+ _("Rotating with Ctrl pressed snaps every that much degrees; also, pressing [ or ] rotates by this amount"), false);
+ _steps_zoom.init ( "options.zoomincrement", "value", 101.0, 500.0, 1.0, 1.0, 1.414213562, true, true);
+ _page_steps.add_line( false, _("Zoom in/out by:"), _steps_zoom, _("%"),
+ _("Zoom tool click, +/- keys, and middle click zoom in and out by this multiplier"), false);
+}
+
+void InkscapePreferences::AddSelcueCheckbox(DialogPage& p, const std::string& prefs_path, bool def_value)
+{
+ PrefCheckButton* cb = Gtk::manage( new PrefCheckButton);
+ cb->init ( _("Show selection cue"), prefs_path, "selcue", def_value);
+ p.add_line( false, "", *cb, "", _("Whether selected objects display a selection cue (the same as in selector)"));
+}
+
+void InkscapePreferences::AddGradientCheckbox(DialogPage& p, const std::string& prefs_path, bool def_value)
+{
+ PrefCheckButton* cb = Gtk::manage( new PrefCheckButton);
+ cb->init ( _("Enable gradient editing"), prefs_path, "gradientdrag", def_value);
+ p.add_line( false, "", *cb, "", _("Whether selected objects display gradient editing controls"));
+}
+
+void InkscapePreferences::AddNewObjectsStyle(DialogPage& p, const std::string& prefs_path)
+{
+ PrefRadioButton* current = Gtk::manage( new PrefRadioButton);
+ PrefRadioButton* own = Gtk::manage( new PrefRadioButton);
+ Gtk::Button* button = Gtk::manage( new Gtk::Button(_("Take from selection"),true));
+
+ own->changed_signal.connect( sigc::mem_fun(*button, &Gtk::Button::set_sensitive) );
+ button->signal_clicked().connect(sigc::bind( sigc::ptr_fun(InkscapePreferences::StyleFromSelectionToTool), prefs_path.c_str() ) );
+
+ current->init ( _("Last used style"), prefs_path, "usecurrent", 1, true, 0);
+ own->init ( _("This tool's own style:"), prefs_path, "usecurrent", 0, false, current);
+
+ p.add_group_header( _("Create new objects with:"));
+ p.add_line( true, "", *current, "",
+ _("Apply the style you last set on an object"));
+ p.add_line( true, "", *own, "",
+ _("Each tool may store its own style to apply to the newly created objects. Use the button below to set it."));
+ p.add_line( true, "", *button, "",
+ _("Remember the style of the (first) selected object as this tool's style"));
+}
+
+void InkscapePreferences::StyleFromSelectionToTool(gchar const *prefs_path)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (desktop == NULL)
+ return;
+
+ Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+
+ if (selection->isEmpty()) {
+ SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE,
+ _("<b>No objects selected</b> to take the style from."));
+ return;
+ }
+ SPItem *item = selection->singleItem();
+ if (!item) {
+ /* TODO: If each item in the selection has the same style then don't consider it an error.
+ * Maybe we should try to handle multiple selections anyway, e.g. the intersection of the
+ * style attributes for the selected items. */
+ SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE,
+ _("<b>More than one object selected.</b> Cannot take style from multiple objects."));
+ return;
+ }
+
+ SPCSSAttr *css = take_style_from_item (item);
+
+ if (!css) return;
+
+ // only store text style for the text tool
+ if (!g_strrstr ((const gchar *) prefs_path, "text")) {
+ css = sp_css_attr_unset_text (css);
+ }
+
+ // we cannot store properties with uris - they will be invalid in other documents
+ css = sp_css_attr_unset_uris (css);
+
+ sp_repr_css_change (inkscape_get_repr (INKSCAPE, prefs_path), css, "style");
+ sp_repr_css_attr_unref (css);
+}
+
+void InkscapePreferences::initPageTools()
+{
+ Gtk::TreeModel::iterator iter_tools = this->AddPage(_page_tools, _("Tools"));
+
+ //Selector
+ this->AddPage(_page_selector, _("Selector"), iter_tools);
+
+ AddSelcueCheckbox(_page_selector, "tools.select", false);
+ _page_selector.add_group_header( _("When transforming, show:"));
+ _t_sel_trans_obj.init ( _("Objects"), "tools.select", "show", "content", true, 0);
+ _page_selector.add_line( true, "", _t_sel_trans_obj, "",
+ _("Show the actual objects when moving or transforming"));
+ _t_sel_trans_outl.init ( _("Box outline"), "tools.select", "show", "outline", false, &_t_sel_trans_obj);
+ _page_selector.add_line( true, "", _t_sel_trans_outl, "",
+ _("Show only a box outline of the objects when moving or transforming"));
+ _page_selector.add_group_header( _("Per-object selection cue:"));
+ _t_sel_cue_none.init ( _("None"), "options.selcue", "value", Inkscape::SelCue::NONE, false, 0);
+ _page_selector.add_line( true, "", _t_sel_cue_none, "",
+ _("No per-object selection indication"));
+ _t_sel_cue_mark.init ( _("Mark"), "options.selcue", "value", Inkscape::SelCue::MARK, true, &_t_sel_cue_none);
+ _page_selector.add_line( true, "", _t_sel_cue_mark, "",
+ _("Each selected object has a diamond mark in the top left corner"));
+ _t_sel_cue_box.init ( _("Box"), "options.selcue", "value", Inkscape::SelCue::BBOX, false, &_t_sel_cue_none);
+ _page_selector.add_line( true, "", _t_sel_cue_box, "",
+ _("Each selected object displays its bounding box"));
+ _page_selector.add_group_header( _("Default scale origin:"));
+ _t_sel_org_edge.init ( _("Opposite bounding box edge"), "tools.select", "scale_origin", "bbox", true, 0);
+ _page_selector.add_line( true, "", _t_sel_org_edge, "",
+ _("Default scale origin will be on the bounding box of the item"));
+ _t_sel_org_node.init ( _("Farthest opposite node"), "tools.select", "scale_origin", "points", false, &_t_sel_org_edge);
+ _page_selector.add_line( true, "", _t_sel_org_node, "",
+ _("Default scale origin will be on the bounding box of the item's points"));
+ //Node
+ this->AddPage(_page_node, _("Node"), iter_tools);
+ AddSelcueCheckbox(_page_node, "tools.nodes", true);
+ AddGradientCheckbox(_page_node, "tools.nodes", true);
+ //Zoom
+ this->AddPage(_page_zoom, _("Zoom"), iter_tools);
+ AddSelcueCheckbox(_page_zoom, "tools.zoom", true);
+ AddGradientCheckbox(_page_zoom, "tools.zoom", false);
+ //Shapes
+ Gtk::TreeModel::iterator iter_shapes = this->AddPage(_page_shapes, _("Shapes"), iter_tools);
+ this->AddSelcueCheckbox(_page_shapes, "tools.shapes", true);
+ this->AddGradientCheckbox(_page_shapes, "tools.shapes", true);
+ //Rectangle
+ this->AddPage(_page_rectangle, _("Rectangle"), iter_shapes);
+ this->AddNewObjectsStyle(_page_rectangle, "tools.shapes.rect");
+ //ellipse
+ this->AddPage(_page_ellipse, _("Ellipse"), iter_shapes);
+ this->AddNewObjectsStyle(_page_ellipse, "tools.shapes.arc");
+ //star
+ this->AddPage(_page_star, _("Star"), iter_shapes);
+ this->AddNewObjectsStyle(_page_star, "tools.shapes.star");
+ //spiral
+ this->AddPage(_page_spiral, _("Spiral"), iter_shapes);
+ this->AddNewObjectsStyle(_page_spiral, "tools.shapes.spiral");
+ //Pencil
+ this->AddPage(_page_pencil, _("Pencil"), iter_tools);
+ this->AddSelcueCheckbox(_page_pencil, "tools.freehand.pencil", true);
+ _t_pencil_tolerance.init ( "tools.freehand.pencil", "tolerance", 0.0, 100.0, 0.5, 1.0, 10.0, false, false);
+ _page_pencil.add_line( false, _("Tolerance:"), _t_pencil_tolerance, "",
+ _("This value affects the amount of smoothing applied to freehand lines; lower values produce more uneven paths with more nodes"),
+ false );
+ this->AddNewObjectsStyle(_page_pencil, "tools.freehand.pencil");
+ //Pen
+ this->AddPage(_page_pen, _("Pen"), iter_tools);
+ this->AddSelcueCheckbox(_page_pen, "tools.freehand.pen", true);
+ this->AddNewObjectsStyle(_page_pen, "tools.freehand.pen");
+ //Calligraphy
+ this->AddPage(_page_calligraphy, _("Calligraphy"), iter_tools);
+ this->AddNewObjectsStyle(_page_calligraphy, "tools.calligraphic");
+ //Text
+ this->AddPage(_page_text, _("Text"), iter_tools);
+ this->AddSelcueCheckbox(_page_text, "tools.text", true);
+ this->AddGradientCheckbox(_page_text, "tools.text", true);
+ this->AddNewObjectsStyle(_page_text, "tools.text");
+ //Gradient
+ this->AddPage(_page_gradient, _("Gradient"), iter_tools);
+ this->AddSelcueCheckbox(_page_gradient, "tools.gradient", true);
+ //Connector
+ this->AddPage(_page_connector, _("Connector"), iter_tools);
+ this->AddSelcueCheckbox(_page_connector, "tools.connector", true);
+ //Dropper
+ this->AddPage(_page_dropper, _("Dropper"), iter_tools);
+ this->AddSelcueCheckbox(_page_dropper, "tools.dropper", true);
+ this->AddGradientCheckbox(_page_dropper, "tools.dropper", true);
+}
+
+void InkscapePreferences::initPageWindows()
+{
+ _win_save_geom.init ( _("Save window geometry"), "options.savewindowgeometry", "value", true);
+ _win_hide_task.init ( _("Dialogs are hidden in taskbar"), "options.dialogsskiptaskbar", "value", true);
+ _win_zoom_resize.init ( _("Zoom when window is resized"), "options.stickyzoom", "value", false);
+ _win_ontop_none.init ( _("None"), "options.transientpolicy", "value", 0, false, 0);
+ _win_ontop_normal.init ( _("Normal"), "options.transientpolicy", "value", 1, true, &_win_ontop_none);
+ _win_ontop_agressive.init ( _("Aggressive"), "options.transientpolicy", "value", 2, false, &_win_ontop_none);
+
+ _page_windows.add_line( false, "", _win_save_geom, "",
+ _("Save the window size and position with each document (only for Inkscape SVG format)"));
+ _page_windows.add_line( false, "", _win_hide_task, "",
+ _("Whether dialog windows are to be hidden in the window manager taskbar"));
+ _page_windows.add_line( false, "", _win_zoom_resize, "",
+ _("Zoom drawing when document window is resized, to keep the same area visible (this is the default which can be changed in any window using the button above the right scrollbar)"));
+ _page_windows.add_group_header( _("Dialogs on top:"));
+ _page_windows.add_line( true, "", _win_ontop_none, "",
+ _("Dialogs are treated as regular windows"));
+ _page_windows.add_line( true, "", _win_ontop_normal, "",
+ _("Dialogs stay on top of document windows"));
+ _page_windows.add_line( true, "", _win_ontop_agressive, "",
+ _("Same as Normal but may work better with some window managers"));
+
+ this->AddPage(_page_windows, _("Windows"));
+}
+
+void InkscapePreferences::initPageClones()
+{
+ _clone_option_parallel.init ( _("Move in parallel"), "options.clonecompensation", "value",
+ SP_CLONE_COMPENSATION_PARALLEL, true, 0);
+ _clone_option_stay.init ( _("Stay unmoved"), "options.clonecompensation", "value",
+ SP_CLONE_COMPENSATION_UNMOVED, false, &_clone_option_parallel);
+ _clone_option_transform.init ( _("Move according to transform"), "options.clonecompensation", "value",
+ SP_CLONE_COMPENSATION_NONE, false, &_clone_option_parallel);
+ _clone_option_unlink.init ( _("Are unlinked"), "options.cloneorphans", "value",
+ SP_CLONE_ORPHANS_UNLINK, true, 0);
+ _clone_option_delete.init ( _("Are deleted"), "options.cloneorphans", "value",
+ SP_CLONE_ORPHANS_DELETE, false, &_clone_option_unlink);
+
+ _page_clones.add_group_header( _("When the original moves, its clones and linked offsets:"));
+ _page_clones.add_line( true, "", _clone_option_parallel, "",
+ _("Clones are translated by the same vector as their original."));
+ _page_clones.add_line( true, "", _clone_option_stay, "",
+ _("Clones preserve their positions when their original is moved."));
+ _page_clones.add_line( true, "", _clone_option_transform, "",
+ _("Each clone moves according to the value of its transform= attribute. For example, a rotated clone will move in a different direction than its original."));
+ _page_clones.add_group_header( _("When the original is deleted, its clones:"));
+ _page_clones.add_line( true, "", _clone_option_unlink, "",
+ _("Orphaned clones are converted to regular objects."));
+ _page_clones.add_line( true, "", _clone_option_delete, "",
+ _("Orphaned clones are deleted along with their original."));
+
+ this->AddPage(_page_clones, _("Clones"));
+}
+
+void InkscapePreferences::initPageTransforms()
+{
+ _trans_scale_stroke.init ( _("Scale stroke width"), "options.transform", "stroke", true);
+ _trans_scale_corner.init ( _("Scale rounded corners in rectangles"), "options.transform", "rectcorners", false);
+ _trans_gradient.init ( _("Transform gradients"), "options.transform", "gradient", true);
+ _trans_pattern.init ( _("Transform patterns"), "options.transform", "pattern", false);
+ _trans_optimized.init ( _("Normal"), "options.preservetransform", "value", 0, true, 0);
+ _trans_preserved.init ( _("Aggressive"), "options.preservetransform", "value", 1, false, &_trans_optimized);
+
+ _page_transforms.add_line( false, "", _trans_scale_stroke, "",
+ _("When scaling objects, scale the stroke width by the same proportion"));
+ _page_transforms.add_line( false, "", _trans_scale_corner, "",
+ _("When scaling rectangles, scale the radii of rounded corners"));
+ _page_transforms.add_line( false, "", _trans_gradient, "",
+ _("Transform gradients (in fill or stroke) along with the objects"));
+ _page_transforms.add_line( false, "", _trans_pattern, "",
+ _("Transform patterns (in fill or stroke) along with the objects"));
+ _page_transforms.add_group_header( _("Store transformation:"));
+ _page_transforms.add_line( true, "", _trans_optimized, "",
+ _("If possible, apply transformation to objects without adding a transform= attribute"));
+ _page_transforms.add_line( true, "", _trans_preserved, "",
+ _("Always store transformation as a transform= attribute on objects"));
+
+ this->AddPage(_page_transforms, _("Transforms"));
+}
+
+void InkscapePreferences::initPageSelecting()
+{
+ _sel_current.init ( _("Select only within current layer"), "options.kbselection", "inlayer", true);
+ _sel_hidden.init ( _("Ignore hidden objects"), "options.kbselection", "onlyvisible", true);
+ _sel_locked.init ( _("Ignore locked objects"), "options.kbselection", "onlysensitive", true);
+
+ _page_select.add_group_header( _("Ctrl+A, Tab, Shift+Tab:"));
+ _page_select.add_line( true, "", _sel_current, "",
+ _("Uncheck this to make keyboard selection commands work on objects in all layers"));
+ _page_select.add_line( true, "", _sel_hidden, "",
+ _("Uncheck this to be able to select objects that are hidden (either by themselves or by being in a hidden group or layer)"));
+ _page_select.add_line( true, "", _sel_locked, "",
+ _("Uncheck this to be able to select objects that are locked (either by themselves or by being in a locked group or layer)"));
+
+ this->AddPage(_page_select, _("Selecting"));
+}
+
+
+void InkscapePreferences::initPageMisc()
+{
+ _misc_export.init("dialogs.export.defaultxdpi", "value", 0.0, 6000.0, 1.0, 1.0, 1.0, true, false);
+ _page_misc.add_line( false, _("Default export resolution:"), _misc_export, _("dpi"),
+ _("Default bitmap resolution (in dots per inch) in the Export dialog"), false);
+ _misc_imp_bitmap.init( _("Import bitmap as <image>"), "options.importbitmapsasimages", "value", true);
+ _page_misc.add_line( false, "", _misc_imp_bitmap, "",
+ _("When on, an imported bitmap creates an <image> element; otherwise it is a rectangle with bitmap fill"), true);
+ _misc_comment.init( _("Add label comments to printing output"), "printing.debug", "show-label-comments", false);
+ _page_misc.add_line( false, "", _misc_comment, "",
+ _("When on, a comment will be added to the raw print output, marking the rendered output for an object with its label"), true);
+ _misc_scripts.init( _("Enable script effects (requires restart) - EXPERIMENTAL"), "extensions", "show-effects-menu", false);
+ _page_misc.add_line( false, "", _misc_scripts, "",
+ _("When on, the effects menu is enabled, allowing external effect scripts to be called, requires restart before effective - EXPERIMENTAL"), true);
+ _misc_recent.init("options.maxrecentdocuments", "value", 0.0, 1000.0, 1.0, 1.0, 1.0, true, false);
+ _page_misc.add_line( false, _("Max recent documents:"), _misc_recent, "",
+ _("The maximum length of the Open Recent list in the File menu"), false);
+ _misc_simpl.init("options.simplifythreshold", "value", 0.0, 1.0, 0.001, 0.01, 0.002, false, false);
+ _page_misc.add_line( false, _("Simplification threshold:"), _misc_simpl, "",
+ _("How strong is the Simplify command by default. If you invoke this command several times in quick succession, it will act more and more aggressively; invoking it again after a pause restores the default threshold."), false);
+ int const num_items = 5;
+ Glib::ustring labels[num_items] = {_("None"), _("2x2"), _("4x4"), _("8x8"), _("16x16")};
+ int values[num_items] = {0, 1, 2, 3, 4};
+ _misc_overs_bitmap.set_size_request(_sb_width);
+ _misc_overs_bitmap.init("options.bitmapoversample", "value", labels, values, num_items, 1);
+ _page_misc.add_line( false, _("Oversample bitmaps:"), _misc_overs_bitmap, "", "", false);
+
+ this->AddPage(_page_misc, _("Misc"));
+}
+
+bool InkscapePreferences::SetMaxDialogSize(const Gtk::TreeModel::iterator& iter)
+{
+ Gtk::TreeModel::Row row = *iter;
+ DialogPage* page = row[_page_list_columns._col_page];
+ _page_frame.add(*page);
+ this->show_all_children();
+ _max_dialog_width=std::max(_max_dialog_width, this->size_request().width);
+ _max_dialog_height=std::max(_max_dialog_height, this->size_request().height);
+ _page_frame.remove();
+ return false;
+}
+
+void InkscapePreferences::on_pagelist_selection_changed()
+{
+ // show new selection
+ Glib::RefPtr<Gtk::TreeSelection> selection = _page_list.get_selection();
+ Gtk::TreeModel::iterator iter = selection->get_selected();
+ if(iter)
+ {
+ if (_current_page)
+ _page_frame.remove();
+ Gtk::TreeModel::Row row = *iter;
+ _current_page = row[_page_list_columns._col_page];
+ _page_title.set_markup("<span size='large'><b>" + row[_page_list_columns._col_id] + "</b></span>");
+ _page_frame.add(*_current_page);
+ _current_page->show();
+ }
+}
+
+} // 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/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
new file mode 100644
index 000000000..269bce7f0
--- /dev/null
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -0,0 +1,140 @@
+/**
+ * \brief Inkscape Preferences dialog
+ *
+ * Authors:
+ * Carl Hetherington
+ * Marco Scholten
+ *
+ * Copyright (C) 2004, 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_INKSCAPE_PREFERENCES_H
+#define INKSCAPE_UI_DIALOG_INKSCAPE_PREFERENCES_H
+
+#include <iostream>
+#include <vector>
+#include <gtkmm/table.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/radiobutton.h>
+#include <gtkmm/frame.h>
+#include "ui/widget/preferences-widget.h"
+#include <sigc++/sigc++.h>
+#include <glibmm/i18n.h>
+
+#include "dialog.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class InkscapePreferences : public Dialog {
+public:
+ virtual ~InkscapePreferences();
+
+ static InkscapePreferences *create() {return new InkscapePreferences(); }
+
+protected:
+ Gtk::Frame _page_frame;
+ Gtk::Label _page_title;
+ Gtk::TreeView _page_list;
+ Glib::RefPtr<Gtk::TreeStore> _page_list_model;
+
+ //Pagelist model columns:
+ class PageListModelColumns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ PageListModelColumns()
+ { Gtk::TreeModelColumnRecord::add(_col_id); Gtk::TreeModelColumnRecord::add(_col_page); }
+ Gtk::TreeModelColumn<Glib::ustring> _col_id;
+ Gtk::TreeModelColumn<DialogPage*> _col_page;
+ };
+ PageListModelColumns _page_list_columns;
+
+ DialogPage _page_mouse, _page_scrolling, _page_steps, _page_tools, _page_windows,
+ _page_clones, _page_transforms, _page_select, _page_misc;
+ DialogPage _page_selector, _page_node, _page_zoom, _page_shapes, _page_pencil, _page_pen,
+ _page_calligraphy, _page_text, _page_gradient, _page_connector, _page_dropper;
+ DialogPage _page_rectangle, _page_ellipse, _page_star, _page_spiral;
+
+ PrefSpinButton _mouse_sens, _mouse_thres;
+
+ PrefSpinButton _scroll_wheel, _scroll_arrow_px, _scroll_arrow_acc, _scroll_auto_speed, _scroll_auto_thres;
+
+ PrefCombo _steps_rot_snap;
+ PrefCheckButton _steps_compass;
+ PrefSpinButton _steps_arrow, _steps_scale, _steps_inset, _steps_zoom;
+
+ PrefRadioButton _t_sel_trans_obj, _t_sel_trans_outl, _t_sel_cue_none, _t_sel_cue_mark,
+ _t_sel_cue_box, _t_sel_org_edge, _t_sel_org_node;
+
+ PrefSpinButton _t_pencil_tolerance;
+
+ PrefRadioButton _win_ontop_none, _win_ontop_normal, _win_ontop_agressive;
+ PrefCheckButton _win_save_geom, _win_hide_task, _win_zoom_resize;
+
+ PrefRadioButton _clone_option_parallel, _clone_option_stay, _clone_option_transform,
+ _clone_option_unlink, _clone_option_delete;
+
+ PrefCheckButton _trans_scale_stroke, _trans_scale_corner, _trans_gradient,_trans_pattern;
+ PrefRadioButton _trans_optimized, _trans_preserved;
+
+ PrefCheckButton _sel_current, _sel_hidden, _sel_locked;
+
+ PrefSpinButton _misc_export, _misc_recent, _misc_simpl;
+ PrefCheckButton _misc_imp_bitmap, _misc_comment, _misc_scripts;
+ PrefCombo _misc_overs_bitmap;
+
+ int _max_dialog_width;
+ int _max_dialog_height;
+ int _sb_width;
+ DialogPage* _current_page;
+
+ Gtk::TreeModel::iterator AddPage(DialogPage& p, Glib::ustring title);
+ Gtk::TreeModel::iterator AddPage(DialogPage& p, Glib::ustring title, Gtk::TreeModel::iterator parent);
+ bool SetMaxDialogSize(const Gtk::TreeModel::iterator& iter);
+
+ static void AddSelcueCheckbox(DialogPage& p, const std::string& prefs_path, bool def_value);
+ static void AddGradientCheckbox(DialogPage& p, const std::string& prefs_path, bool def_value);
+ static void AddNewObjectsStyle(DialogPage& p, const std::string& prefs_path);
+ static void StyleFromSelectionToTool(gchar const *prefs_path);
+
+ void on_pagelist_selection_changed();
+ void initPageMouse();
+ void initPageScrolling();
+ void initPageSteps();
+ void initPageTools();
+ void initPageWindows();
+ void initPageClones();
+ void initPageTransforms();
+ void initPageSelecting();
+ void initPageMisc();
+
+private:
+ InkscapePreferences();
+ InkscapePreferences(InkscapePreferences const &d);
+ InkscapePreferences operator=(InkscapePreferences const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif //INKSCAPE_UI_DIALOG_INKSCAPE_PREFERENCES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/dialog/layer-editor.cpp b/src/ui/dialog/layer-editor.cpp
new file mode 100644
index 000000000..03a546a89
--- /dev/null
+++ b/src/ui/dialog/layer-editor.cpp
@@ -0,0 +1,48 @@
+/**
+ * \brief Layer Editor dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "layer-editor.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+LayerEditor::LayerEditor()
+ : Dialog ("dialogs.layereditor", SP_VERB_NONE /*FIXME*/)
+{
+ // TODO: Insert widgets
+
+ show_all_children();
+}
+
+LayerEditor::~LayerEditor()
+{
+}
+
+} // 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/layer-editor.h b/src/ui/dialog/layer-editor.h
new file mode 100644
index 000000000..3d68a7fcf
--- /dev/null
+++ b/src/ui/dialog/layer-editor.h
@@ -0,0 +1,52 @@
+/**
+ * \brief Layer Editor dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_LAYER_EDITOR_H
+#define INKSCAPE_UI_DIALOG_LAYER_EDITOR_H
+
+#include "dialog.h"
+
+#include <glibmm/i18n.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class LayerEditor : public Dialog {
+public:
+ LayerEditor();
+ virtual ~LayerEditor();
+
+ static LayerEditor *create() { return new LayerEditor(); }
+
+protected:
+
+private:
+ LayerEditor(LayerEditor const &d);
+ LayerEditor& operator=(LayerEditor const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_LAYER_EDITOR_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/makefile.in b/src/ui/dialog/makefile.in
new file mode 100644
index 000000000..c99e72597
--- /dev/null
+++ b/src/ui/dialog/makefile.in
@@ -0,0 +1,17 @@
+# Convenience stub makefile to call the real Makefile.
+
+@SET_MAKE@
+
+# Explicit so that it's the default rule.
+all:
+ cd ../.. && $(MAKE) ui/dialog/all
+
+clean %.a %.o:
+ cd ../.. && $(MAKE) ui/dialog/$@
+
+.PHONY: all clean
+
+OBJEXT = @OBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .a .$(OBJEXT)
diff --git a/src/ui/dialog/memory.cpp b/src/ui/dialog/memory.cpp
new file mode 100644
index 000000000..e81db17d8
--- /dev/null
+++ b/src/ui/dialog/memory.cpp
@@ -0,0 +1,244 @@
+/**
+ * \brief Memory statistics dialog
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ *
+ * Copyright (C) 2005
+ *
+ * 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/liststore.h>
+#include <gtkmm/treeview.h>
+
+#include "gc-core.h"
+#include "ui/dialog/memory.h"
+#include "debug/heap.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+namespace {
+
+Glib::ustring format_size(std::size_t value) {
+ if (!value) {
+ return Glib::ustring("0");
+ }
+
+ typedef std::vector<char> Digits;
+ typedef std::vector<Digits *> Groups;
+
+ Groups groups;
+
+ Digits *digits;
+
+ while (value) {
+ unsigned places=3;
+ digits = new Digits();
+ digits->reserve(places);
+
+ while ( value && places ) {
+ digits->push_back('0' + (char)( value % 10 ));
+ value /= 10;
+ --places;
+ }
+
+ groups.push_back(digits);
+ }
+
+ Glib::ustring temp;
+
+ while (true) {
+ digits = groups.back();
+ while (!digits->empty()) {
+ temp.append(1, digits->back());
+ digits->pop_back();
+ }
+ delete digits;
+
+ groups.pop_back();
+ if (groups.empty()) {
+ break;
+ }
+
+ temp.append(",");
+ }
+
+ return temp;
+}
+
+}
+
+struct Memory::Private {
+ class ModelColumns : public Gtk::TreeModel::ColumnRecord {
+ public:
+ Gtk::TreeModelColumn<Glib::ustring> name;
+ Gtk::TreeModelColumn<Glib::ustring> used;
+ Gtk::TreeModelColumn<Glib::ustring> slack;
+ Gtk::TreeModelColumn<Glib::ustring> total;
+
+ ModelColumns() { add(name); add(used); add(slack); add(total); }
+ };
+
+ Private() {
+ model = Gtk::ListStore::create(columns);
+ view.set_model(model);
+ view.append_column(_("Heap"), columns.name);
+ view.append_column(_("In Use"), columns.used);
+ // TRANSLATORS: "Slack" refers to memory which is in the heap but currently unused.
+ // More typical usage is to call this memory "free" rather than "slack".
+ view.append_column(_("Slack"), columns.slack);
+ view.append_column(_("Total"), columns.total);
+ }
+
+ void update();
+
+ void start_update_task();
+ void stop_update_task();
+
+ ModelColumns columns;
+ Glib::RefPtr<Gtk::ListStore> model;
+ Gtk::TreeView view;
+
+ sigc::connection update_task;
+};
+
+void Memory::Private::update() {
+ Debug::Heap::Stats total = { 0, 0 };
+
+ int aggregate_features = Debug::Heap::SIZE_AVAILABLE | Debug::Heap::USED_AVAILABLE;
+ Gtk::ListStore::iterator row;
+
+ row = model->children().begin();
+
+ for ( unsigned i = 0 ; i < Debug::heap_count() ; i++ ) {
+ Debug::Heap *heap=Debug::get_heap(i);
+ if (heap) {
+ Debug::Heap::Stats stats=heap->stats();
+ int features=heap->features();
+
+ aggregate_features &= features;
+
+ if ( row == model->children().end() ) {
+ row = model->append();
+ }
+
+ row->set_value(columns.name, Glib::ustring(heap->name()));
+ if ( features & Debug::Heap::SIZE_AVAILABLE ) {
+ row->set_value(columns.total, format_size(stats.size));
+ total.size += stats.size;
+ } else {
+ row->set_value(columns.total, Glib::ustring(_("Unknown")));
+ }
+ if ( features & Debug::Heap::USED_AVAILABLE ) {
+ row->set_value(columns.used, format_size(stats.bytes_used));
+ total.bytes_used += stats.bytes_used;
+ } else {
+ row->set_value(columns.used, Glib::ustring(_("Unknown")));
+ }
+ if ( features & Debug::Heap::SIZE_AVAILABLE &&
+ features & Debug::Heap::USED_AVAILABLE )
+ {
+ row->set_value(columns.slack, format_size(stats.size - stats.bytes_used));
+ } else {
+ row->set_value(columns.slack, Glib::ustring(_("Unknown")));
+ }
+
+ ++row;
+ }
+ }
+
+ if ( row == model->children().end() ) {
+ row = model->append();
+ }
+
+ Glib::ustring value;
+
+ row->set_value(columns.name, Glib::ustring(_("Combined")));
+
+ if ( aggregate_features & Debug::Heap::SIZE_AVAILABLE ) {
+ row->set_value(columns.total, format_size(total.size));
+ } else {
+ row->set_value(columns.total, Glib::ustring("> ") + format_size(total.size));
+ }
+
+ if ( aggregate_features & Debug::Heap::USED_AVAILABLE ) {
+ row->set_value(columns.used, format_size(total.bytes_used));
+ } else {
+ row->set_value(columns.used, Glib::ustring("> ") + format_size(total.bytes_used));
+ }
+
+ if ( aggregate_features & Debug::Heap::SIZE_AVAILABLE &&
+ aggregate_features & Debug::Heap::USED_AVAILABLE )
+ {
+ row->set_value(columns.slack, format_size(total.size - total.bytes_used));
+ } else {
+ row->set_value(columns.slack, Glib::ustring(_("Unknown")));
+ }
+
+ ++row;
+
+ while ( row != model->children().end() ) {
+ row = model->erase(row);
+ }
+}
+
+void Memory::Private::start_update_task() {
+ update_task.disconnect();
+ update_task = Glib::signal_timeout().connect(
+ sigc::bind_return(sigc::mem_fun(*this, &Private::update), true),
+ 500
+ );
+}
+
+void Memory::Private::stop_update_task() {
+ update_task.disconnect();
+}
+
+Memory::Memory()
+ : Dialog ("dialogs.memory", SP_VERB_HELP_MEMORY, _("Recalculate")),
+ _private(*(new Memory::Private()))
+{
+ get_vbox()->add(_private.view);
+
+ _private.update();
+
+ show_all_children();
+
+ signal_show().connect(sigc::mem_fun(_private, &Private::start_update_task));
+ signal_hide().connect(sigc::mem_fun(_private, &Private::stop_update_task));
+
+ _private.start_update_task();
+}
+
+Memory::~Memory() {
+ delete &_private;
+}
+
+void Memory::_apply() {
+ GC::Core::gcollect();
+ _private.update();
+}
+
+} // 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/memory.h b/src/ui/dialog/memory.h
new file mode 100644
index 000000000..bec6c8fd0
--- /dev/null
+++ b/src/ui/dialog/memory.h
@@ -0,0 +1,54 @@
+/**
+ * \brief Memory statistics dialog
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ *
+ * Copyright 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef SEEN_INKSCAPE_UI_DIALOG_MEMORY_H
+#define SEEN_INKSCAPE_UI_DIALOG_MEMORY_H
+
+#include "dialog.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class Memory : public Dialog {
+public:
+ Memory();
+ ~Memory();
+
+ static Memory *create() { return new Memory(); }
+
+protected:
+ void _apply();
+
+private:
+ Memory(Memory const &d); // no copy
+ void operator=(Memory const &d); // no assign
+
+ struct Private;
+ Private &_private;
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#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/dialog/messages.cpp b/src/ui/dialog/messages.cpp
new file mode 100644
index 000000000..9228273d0
--- /dev/null
+++ b/src/ui/dialog/messages.cpp
@@ -0,0 +1,185 @@
+/*
+ * A very simple dialog for displaying Inkscape messages. Messages
+ * sent to g_log(), g_warning(), g_message(), ets, are routed here,
+ * in order to avoid messing with the startup console.
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "messages.h"
+
+
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+//#########################################################################
+//## E V E N T S
+//#########################################################################
+
+/**
+ * Also a public method. Remove all text from the dialog
+ */
+void Messages::clear()
+{
+ Glib::RefPtr<Gtk::TextBuffer> buffer = messageText.get_buffer();
+ buffer->erase(buffer->begin(), buffer->end());
+}
+
+
+//#########################################################################
+//## C O N S T R U C T O R / D E S T R U C T O R
+//#########################################################################
+/**
+ * Constructor
+ */
+Messages::Messages()
+ : Dialog ("dialogs.messages", SP_VERB_DIALOG_DEBUG)
+{
+ Gtk::VBox *mainVBox = get_vbox();
+
+ //## Add a menu for clear()
+ menuBar.items().push_back( Gtk::Menu_Helpers::MenuElem(_("_File"), fileMenu) );
+ fileMenu.items().push_back( Gtk::Menu_Helpers::MenuElem(_("_Clear"),
+ sigc::mem_fun(*this, &Messages::clear) ) );
+ fileMenu.items().push_back( Gtk::Menu_Helpers::MenuElem(_("Capture log messages"),
+ sigc::mem_fun(*this, &Messages::captureLogMessages) ) );
+ fileMenu.items().push_back( Gtk::Menu_Helpers::MenuElem(_("Release log messages"),
+ sigc::mem_fun(*this, &Messages::releaseLogMessages) ) );
+ mainVBox->pack_start(menuBar, Gtk::PACK_SHRINK);
+
+
+ //### Set up the text widget
+ messageText.set_editable(false);
+ textScroll.add(messageText);
+ textScroll.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS);
+ mainVBox->pack_start(textScroll);
+
+ show_all_children();
+
+ message(_("Ready."));
+ message(_("Enable log display by setting dialogs.debug 'redirect' attribute to 1 in preferences.xml"));
+
+ handlerDefault = 0;
+ handlerGlibmm = 0;
+ handlerAtkmm = 0;
+ handlerPangomm = 0;
+ handlerGdkmm = 0;
+ handlerGtkmm = 0;
+}
+
+Messages::~Messages()
+{
+}
+
+
+//#########################################################################
+//## M E T H O D S
+//#########################################################################
+
+void Messages::message(char *msg)
+{
+ Glib::RefPtr<Gtk::TextBuffer> buffer = messageText.get_buffer();
+ Glib::ustring uMsg = msg;
+ if (uMsg[uMsg.length()-1] != '\n')
+ uMsg += '\n';
+ buffer->insert (buffer->end(), uMsg);
+}
+
+
+void dialogLoggingFunction(const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *messageText,
+ gpointer user_data)
+{
+ Messages *dlg = (Messages *)user_data;
+
+ dlg->message((char *)messageText);
+
+}
+
+
+void Messages::captureLogMessages()
+{
+ /*
+ This might likely need more code, to capture Gtkmm
+ and Glibmm warnings, or maybe just simply grab stdout/stderr
+ */
+ GLogLevelFlags flags = (GLogLevelFlags) (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL |
+ G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE |
+ G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG);
+ if ( !handlerDefault ) {
+ handlerDefault = g_log_set_handler(NULL, flags,
+ dialogLoggingFunction, (gpointer)this);
+ }
+ if ( !handlerGlibmm ) {
+ handlerGlibmm = g_log_set_handler("glibmm", flags,
+ dialogLoggingFunction, (gpointer)this);
+ }
+ if ( !handlerAtkmm ) {
+ handlerAtkmm = g_log_set_handler("atkmm", flags,
+ dialogLoggingFunction, (gpointer)this);
+ }
+ if ( !handlerPangomm ) {
+ handlerPangomm = g_log_set_handler("pangomm", flags,
+ dialogLoggingFunction, (gpointer)this);
+ }
+ if ( !handlerGdkmm ) {
+ handlerGdkmm = g_log_set_handler("gdkmm", flags,
+ dialogLoggingFunction, (gpointer)this);
+ }
+ if ( !handlerGtkmm ) {
+ handlerGtkmm = g_log_set_handler("gtkmm", flags,
+ dialogLoggingFunction, (gpointer)this);
+ }
+ message("log capture started");
+}
+
+void Messages::releaseLogMessages()
+{
+ if ( handlerDefault ) {
+ g_log_remove_handler(NULL, handlerDefault);
+ handlerDefault = 0;
+ }
+ if ( handlerGlibmm ) {
+ g_log_remove_handler("glibmm", handlerGlibmm);
+ handlerGlibmm = 0;
+ }
+ if ( handlerAtkmm ) {
+ g_log_remove_handler("atkmm", handlerAtkmm);
+ handlerAtkmm = 0;
+ }
+ if ( handlerPangomm ) {
+ g_log_remove_handler("pangomm", handlerPangomm);
+ handlerPangomm = 0;
+ }
+ if ( handlerGdkmm ) {
+ g_log_remove_handler("gdkmm", handlerGdkmm);
+ handlerGdkmm = 0;
+ }
+ if ( handlerGtkmm ) {
+ g_log_remove_handler("gtkmm", handlerGtkmm);
+ handlerGtkmm = 0;
+ }
+ message("log capture discontinued");
+}
+
+} //namespace Dialog
+} //namespace UI
+} //namespace Inkscape
+
+//#########################################################################
+//## E N D O F F I L E
+//#########################################################################
diff --git a/src/ui/dialog/messages.h b/src/ui/dialog/messages.h
new file mode 100644
index 000000000..3ce7b5a87
--- /dev/null
+++ b/src/ui/dialog/messages.h
@@ -0,0 +1,98 @@
+/*
+ * \brief Messages Dialog
+ *
+ * A very simple dialog for displaying Inkscape messages. Messages
+ * sent to g_log(), g_warning(), g_message(), ets, are routed here,
+ * in order to avoid messing with the startup console.
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_MESSAGES_H
+#define INKSCAPE_UI_DIALOG_MESSAGES_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/dialog.h>
+#include <gtkmm/textview.h>
+#include <gtkmm/button.h>
+#include <gtkmm/menubar.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/scrolledwindow.h>
+
+#include <glibmm/i18n.h>
+
+#include "dialog.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class Messages : public Dialog {
+public:
+ Messages();
+ virtual ~Messages();
+
+ static Messages *create() { return new Messages(); }
+
+ /**
+ * Clear all information from the dialog
+ */
+ void clear();
+
+ /**
+ * Display a message
+ */
+ void message(char *msg);
+
+ /**
+ * Redirect g_log() messages to this widget
+ */
+ void captureLogMessages();
+
+ /**
+ * Return g_log() messages to normal handling
+ */
+ void releaseLogMessages();
+
+protected:
+ Gtk::MenuBar menuBar;
+ Gtk::Menu fileMenu;
+ Gtk::ScrolledWindow textScroll;
+ Gtk::TextView messageText;
+
+ //Handler ID's
+ guint handlerDefault;
+ guint handlerGlibmm;
+ guint handlerAtkmm;
+ guint handlerPangomm;
+ guint handlerGdkmm;
+ guint handlerGtkmm;
+
+private:
+ Messages(Messages const &d);
+ Messages operator=(Messages const &d);
+};
+
+
+} //namespace Dialog
+} //namespace UI
+} //namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_MESSAGES_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/scriptdialog.cpp b/src/ui/dialog/scriptdialog.cpp
new file mode 100644
index 000000000..a0f7f4337
--- /dev/null
+++ b/src/ui/dialog/scriptdialog.cpp
@@ -0,0 +1,248 @@
+/*
+ * This dialog is for launching scripts whose main purpose if
+ * the scripting of Inkscape itself.
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004, 2005 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/menubar.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/textview.h>
+
+#include "scriptdialog.h"
+#include <extension/script/InkscapeScript.h>
+
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+//#########################################################################
+//## I M P L E M E N T A T I O N
+//#########################################################################
+
+/**
+ * A script editor/executor
+ */
+class ScriptDialogImpl : public ScriptDialog
+{
+
+ public:
+
+
+ /**
+ * Constructor
+ */
+ ScriptDialogImpl();
+
+ /**
+ * Destructor
+ */
+ ~ScriptDialogImpl()
+ {}
+
+
+ /**
+ * Clear the text
+ */
+ void clear();
+
+ /**
+ * Execute the script
+ */
+ void execute(Inkscape::Extension::Script::InkscapeScript::ScriptLanguage lang);
+
+ /**
+ * Execute a Python script
+ */
+ void executePython();
+
+ /**
+ * Execute a Perl script
+ */
+ void executePerl();
+
+
+
+ private:
+
+
+ Gtk::MenuBar menuBar;
+
+ Gtk::Menu fileMenu;
+
+ //## Script text
+ Gtk::Frame scriptTextFrame;
+ Gtk::ScrolledWindow scriptTextScroll;
+ Gtk::TextView scriptText;
+
+ //## Output text
+ Gtk::Frame outputTextFrame;
+ Gtk::ScrolledWindow outputTextScroll;
+ Gtk::TextView outputText;
+
+ //## Error text
+ Gtk::Frame errorTextFrame;
+ Gtk::ScrolledWindow errorTextScroll;
+ Gtk::TextView errorText;
+
+
+
+};
+
+static char *defaultPythonCodeStr =
+ "# This is a sample Python script.\n"
+ "# To run it, select 'Execute Python' from the File menu above.\n"
+ "desktop = inkscape.getDesktop()\n"
+ "dialogmanager = inkscape.getDialogManager()\n"
+ "document = desktop.getDocument()\n"
+ "document.hello()\n"
+ "dialogmanager.showAbout()\n"
+ "";
+
+
+
+//#########################################################################
+//## E V E N T S
+//#########################################################################
+
+static void textViewClear(Gtk::TextView &view)
+{
+ Glib::RefPtr<Gtk::TextBuffer> buffer = view.get_buffer();
+ buffer->erase(buffer->begin(), buffer->end());
+}
+
+
+/**
+ * Also a public method. Remove all text from the dialog
+ */
+void ScriptDialogImpl::clear()
+{
+ textViewClear(scriptText);
+ textViewClear(outputText);
+ textViewClear(errorText);
+}
+
+/**
+ * Execute the script in the dialog
+ */
+void
+ScriptDialogImpl::execute(Inkscape::Extension::Script::InkscapeScript::ScriptLanguage
+lang)
+{
+ Glib::ustring script = scriptText.get_buffer()->get_text(true);
+ Glib::ustring output;
+ Glib::ustring error;
+ Inkscape::Extension::Script::InkscapeScript engine;
+ engine.interpretScript(script, output, error, lang);
+ outputText.get_buffer()->set_text(output);
+ errorText.get_buffer()->set_text(error);
+}
+
+/**
+ * Execute the script in the dialog
+ */
+void ScriptDialogImpl::executePython()
+{
+ execute(Inkscape::Extension::Script::InkscapeScript::PYTHON);
+}
+
+/**
+ * Execute the script in the dialog
+ */
+void ScriptDialogImpl::executePerl()
+{
+ execute(Inkscape::Extension::Script::InkscapeScript::PERL);
+}
+
+
+//#########################################################################
+//## C O N S T R U C T O R / D E S T R U C T O R
+//#########################################################################
+/**
+ * Constructor
+ */
+ScriptDialogImpl::ScriptDialogImpl()
+{
+ Gtk::VBox *mainVBox = get_vbox();
+
+ //## Add a menu for clear()
+ menuBar.items().push_back( Gtk::Menu_Helpers::MenuElem(_("_File"), fileMenu) );
+ fileMenu.items().push_back( Gtk::Menu_Helpers::MenuElem(_("_Clear"),
+ sigc::mem_fun(*this, &ScriptDialogImpl::clear) ) );
+ fileMenu.items().push_back( Gtk::Menu_Helpers::MenuElem(_("_Execute Python"),
+ sigc::mem_fun(*this, &ScriptDialogImpl::executePython) ) );
+ fileMenu.items().push_back( Gtk::Menu_Helpers::MenuElem(_("_Execute Perl"),
+ sigc::mem_fun(*this, &ScriptDialogImpl::executePerl) ) );
+ mainVBox->pack_start(menuBar, Gtk::PACK_SHRINK);
+
+ //### Set up the script field
+ scriptText.set_editable(true);
+ scriptText.get_buffer()->set_text(defaultPythonCodeStr);
+ scriptTextScroll.add(scriptText);
+ scriptTextScroll.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS);
+ scriptTextFrame.set_label(_("Script"));
+ scriptTextFrame.set_shadow_type(Gtk::SHADOW_NONE);
+ scriptTextFrame.add(scriptTextScroll);
+ mainVBox->pack_start(scriptTextFrame);
+
+ //### Set up the output field
+ outputText.set_editable(true);
+ outputText.get_buffer()->set_text("");
+ outputTextScroll.add(outputText);
+ outputTextScroll.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS);
+ outputTextFrame.set_label(_("Output"));
+ outputTextFrame.set_shadow_type(Gtk::SHADOW_NONE);
+ outputTextFrame.add(outputTextScroll);
+ mainVBox->pack_start(outputTextFrame);
+
+ //### Set up the error field
+ errorText.set_editable(true);
+ errorText.get_buffer()->set_text("");
+ errorTextScroll.add(errorText);
+ errorTextScroll.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS);
+ errorTextFrame.set_label(_("Errors"));
+ errorTextFrame.set_shadow_type(Gtk::SHADOW_NONE);
+ errorTextFrame.add(errorTextScroll);
+ mainVBox->pack_start(errorTextFrame);
+
+ show_all_children();
+
+}
+
+/**
+ * Factory method. Use this to create a new ScriptDialog
+ */
+ScriptDialog *ScriptDialog::create()
+{
+ ScriptDialog *dialog = new ScriptDialogImpl();
+ return dialog;
+}
+
+
+
+
+
+
+} //namespace Dialogs
+} //namespace UI
+} //namespace Inkscape
+
+//#########################################################################
+//## E N D O F F I L E
+//#########################################################################
+
+
+
diff --git a/src/ui/dialog/scriptdialog.h b/src/ui/dialog/scriptdialog.h
new file mode 100644
index 000000000..74bc5d007
--- /dev/null
+++ b/src/ui/dialog/scriptdialog.h
@@ -0,0 +1,65 @@
+#ifndef __SCRIPTDIALOG_H__
+#define __SCRIPTDIALOG_H__
+/*
+ * This dialog is for launching scripts whose main purpose if
+ * the scripting of Inkscape itself.
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include "dialog.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+/**
+ * A script editor, loader, and executor
+ */
+class ScriptDialog : public Dialog
+{
+
+ public:
+
+
+ /**
+ * Constructor
+ */
+ ScriptDialog() : Dialog ("dialogs.script", SP_VERB_DIALOG_SCRIPT)
+ {}
+
+
+ /**
+ * Factory method
+ */
+ static ScriptDialog *create();
+
+ /**
+ * Destructor
+ */
+ virtual ~ScriptDialog() {};
+
+
+
+
+}; // class ScriptDialog
+
+
+} //namespace Dialog
+} //namespace UI
+} //namespace Inkscape
+
+
+
+
+#endif /* __DEBUGDIALOG_H__ */
+
diff --git a/src/ui/dialog/session-player.cpp b/src/ui/dialog/session-player.cpp
new file mode 100644
index 000000000..48c3ff5ef
--- /dev/null
+++ b/src/ui/dialog/session-player.cpp
@@ -0,0 +1,229 @@
+/**
+ * Whiteboard session playback control dialog
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ *
+ * Copyright (c) 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glibmm.h>
+#include <glibmm/i18n.h>
+#include <gtk/gtkdialog.h>
+#include <gtkmm.h>
+
+#include "inkscape.h"
+#include "path-prefix.h"
+
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "document.h"
+
+#include "ui/stock.h"
+
+#include "jabber_whiteboard/node-tracker.h"
+#include "jabber_whiteboard/session-manager.h"
+#include "jabber_whiteboard/session-file-player.h"
+
+#include "ui/dialog/session-player.h"
+
+#include "util/ucompose.hpp"
+
+namespace Inkscape {
+
+namespace UI {
+
+namespace Dialog {
+
+SessionPlaybackDialog*
+SessionPlaybackDialog::create()
+{
+ return new SessionPlaybackDialogImpl();
+}
+
+SessionPlaybackDialogImpl::SessionPlaybackDialogImpl()
+ : _delay(100, 1, 5000, 10, 100), _delayentry(_delay)
+{
+ this->_desktop = SP_ACTIVE_DESKTOP;
+ this->_sm = this->_desktop->whiteboard_session_manager();
+ this->_sfp = this->_sm->session_player();
+ this->_openfile.set_text(this->_sfp->filename());
+
+ this->_construct();
+ this->get_vbox()->show_all_children();
+}
+
+SessionPlaybackDialogImpl::~SessionPlaybackDialogImpl()
+{
+
+}
+
+void
+SessionPlaybackDialogImpl::_construct()
+{
+ Gtk::VBox* main = this->get_vbox();
+
+ // Dialog organization
+ this->_filemanager.set_label(_("Session file"));
+ this->_playback.set_label(_("Playback controls"));
+ this->_currentmsgbox.set_label(_("Message information"));
+
+ this->_filemanager.set_border_width(4);
+ this->_playback.set_border_width(4);
+ this->_fm.set_border_width(4);
+ this->_toolbarbox.set_border_width(4);
+
+ // Active session file display
+ // fixme: Does this mean the active file for the session, or the file for the active session?
+ // Please indicate which with a TRANSLATORS comment.
+ this->_labels[0].set_text(_("Active session file:"));
+ this->_labels[1].set_text(_("Delay (milliseconds):"));
+
+ this->_openfile.set_editable(false);
+
+ this->_filebox.pack_start(this->_labels[0], true, false, 8);
+ this->_filebox.pack_end(this->_openfile, true, true, 0);
+
+ // Unload/load buttons
+ this->_close.set_label(_("Close file"));
+ this->_open.set_label(_("Open new file"));
+ this->_setdelay.set_label(_("Set delay"));
+
+ // Attach callbacks
+ this->_close.signal_clicked().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &SessionPlaybackDialogImpl::_respCallback), CLOSE_FILE));
+ this->_open.signal_clicked().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &SessionPlaybackDialogImpl::_respCallback), OPEN_FILE));
+ this->_setdelay.signal_clicked().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &SessionPlaybackDialogImpl::_respCallback), RESET_DELAY));
+
+ // Button box
+ this->_filebuttons.pack_start(this->_close, true, false, 0);
+ this->_filebuttons.pack_start(this->_open, true, false, 0);
+
+ // Message information box
+ this->_currentmsgbuffer = Gtk::TextBuffer::create();
+ this->_currentmsgview.set_buffer(this->_currentmsgbuffer);
+ this->_currentmsgview.set_editable(false);
+ this->_currentmsgview.set_cursor_visible(false);
+ this->_currentmsgview.set_wrap_mode(Gtk::WRAP_WORD);
+ this->_currentmsgscroller.add(this->_currentmsgview);
+ this->_currentmsgbox.add(this->_currentmsgscroller);
+ this->_sfp->setMessageOutputWidget(this->_currentmsgbuffer);
+
+ // Delay setting
+ // parameters: initial lower upper single-incr page-incr
+ this->_delayentry.set_numeric(true);
+
+ // Playback controls
+ this->_playbackcontrols.set_show_arrow(false);
+
+ /* these are waiting for the Gtkmm conversion
+ this->_controls[0].set_stock_id(Stock::SESSION_PLAYBACK_REW);
+ this->_controls[1].set_stock_id(Stock::SESSION_PLAYBACK_STEPBACK);
+ this->_controls[2].set_stock_id(Stock::SESSION_PLAYBACK_PAUSE);
+ this->_controls[3].set_stock_id(Stock::SESSION_PLAYBACK_STEPFORWARD);
+ this->_controls[4].set_stock_id(Stock::SESSION_PLAYBACK_PLAY);
+ */
+
+ this->_controls[0].set_label("Rewind");
+ this->_controls[1].set_label("Go back one");
+ this->_controls[2].set_label("Pause");
+ this->_controls[3].set_label("Go forward one");
+ this->_controls[4].set_label("Play");
+
+ this->_controls[0].set_tooltip(this->_tooltips, _("Rewind"));
+ this->_controls[1].set_tooltip(this->_tooltips, _("Go back one change"));
+ this->_controls[2].set_tooltip(this->_tooltips, _("Pause"));
+ this->_controls[3].set_tooltip(this->_tooltips, _("Go forward one change"));
+ this->_controls[4].set_tooltip(this->_tooltips, _("Play"));
+
+ for(int i = 0; i < 5; i++) {
+ this->_playbackcontrols.append(this->_controls[i], sigc::bind< 0 >(sigc::mem_fun(*this, &SessionPlaybackDialogImpl::_respCallback), TOOLBAR_BASE + i));
+ }
+
+ this->_delaybox.pack_start(this->_labels[1]);
+ this->_delaybox.pack_start(this->_delayentry);
+ this->_delaybox.pack_end(this->_setdelay);
+
+ this->_toolbarbox.pack_start(this->_delaybox);
+ this->_toolbarbox.pack_end(this->_playbackcontrols);
+
+ // Pack widgets into frames
+ this->_fm.pack_start(this->_filebox);
+ this->_fm.pack_end(this->_filebuttons);
+
+ this->_filemanager.add(this->_fm);
+ this->_playback.add(this->_toolbarbox);
+
+ // Pack widgets into main vbox
+ main->pack_start(this->_filemanager);
+ main->pack_start(this->_playback);
+ main->pack_end(this->_currentmsgbox);
+}
+
+void
+SessionPlaybackDialogImpl::_respCallback(int resp)
+{
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "_respCallback: %u", resp);
+ switch(resp) {
+ case CLOSE_FILE:
+ this->_sfp->unload();
+ break;
+ case OPEN_FILE: {
+ Gtk::FileChooserDialog sessionfiledlg(_("Open session file"), Gtk::FILE_CHOOSER_ACTION_OPEN);
+ sessionfiledlg.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ sessionfiledlg.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
+
+ int result = sessionfiledlg.run();
+ switch (result) {
+ case Gtk::RESPONSE_OK:
+ this->_sm->clearDocument();
+ sp_document_done(SP_DT_DOCUMENT(this->_desktop));
+ this->_sm->loadSessionFile(sessionfiledlg.get_filename());
+ this->_openfile.set_text(this->_sfp->filename());
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case RESET_DELAY:
+ this->_sfp->setDelay(this->_delayentry.get_value_as_int());
+ break;
+ case REWIND:
+ if (this->_sfp->_playing) {
+ this->_sfp->stop();
+ }
+ this->_sfp->_curdir = Whiteboard::SessionFilePlayer::BACKWARD;
+ this->_sfp->start();
+ break;
+ case STEP_REWIND:
+ this->_sfp->step(Whiteboard::SessionFilePlayer::BACKWARD);
+ break;
+ case PAUSE:
+ this->_sfp->stop();
+ break;
+ case STEP_PLAY:
+ this->_sfp->step(Whiteboard::SessionFilePlayer::FORWARD);
+ break;
+ case PLAY:
+ if (this->_sfp->_playing) {
+ this->_sfp->stop();
+ }
+ this->_sfp->_curdir = Whiteboard::SessionFilePlayer::FORWARD;
+ this->_sfp->start();
+ break;
+ default:
+ break;
+ }
+}
+
+}
+
+}
+
+}
diff --git a/src/ui/dialog/session-player.h b/src/ui/dialog/session-player.h
new file mode 100644
index 000000000..fd2945bb0
--- /dev/null
+++ b/src/ui/dialog/session-player.h
@@ -0,0 +1,124 @@
+/**
+ * Whiteboard session playback control dialog
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ *
+ * Copyright (c) 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef __SESSION_PLAYBACK_DIALOG_H__
+#define __SESSION_PLAYBACK_DIALOG_H__
+
+#include "verbs.h"
+#include "dialog.h"
+
+#include "gtkmm/toolbutton.h"
+#include "gtkmm/toolbar.h"
+#include "gtkmm/expander.h"
+
+#include "ui/widget/icon-widget.h"
+
+struct SPDesktop;
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+class SessionManager;
+class SessionFilePlayer;
+
+}
+
+namespace UI {
+
+namespace Dialog {
+
+class SessionPlaybackDialog : public Dialog {
+public:
+ SessionPlaybackDialog() : Dialog("dialogs.session_playback", SP_VERB_DIALOG_WHITEBOARD_SESSIONPLAYBACK)
+ {
+
+ }
+
+ static SessionPlaybackDialog* create();
+
+ virtual ~SessionPlaybackDialog()
+ {
+
+ }
+private:
+ SessionPlaybackDialog(SessionPlaybackDialog const& dlg); // no copy
+ void operator=(SessionPlaybackDialog const& dlg); // no assign
+};
+
+class SessionPlaybackDialogImpl : public SessionPlaybackDialog {
+public:
+ SessionPlaybackDialogImpl();
+ ~SessionPlaybackDialogImpl();
+
+private:
+ // GTK+ widgets
+ Gtk::HBox _filebox;
+ Gtk::HBox _filebuttons;
+ Gtk::HBox _toolbarbox;
+ Gtk::HBox _delaybox;
+
+ Gtk::Entry _openfile;
+
+ Gtk::Label _labels[2];
+ Gtk::ToolButton _controls[5];
+
+ Gtk::Button _close, _open, _setdelay;
+
+ Gtk::Tooltips _tooltips;
+ Gtk::Toolbar _playbackcontrols;
+ Gtk::Adjustment _delay;
+ Gtk::SpinButton _delayentry;
+
+ Gtk::Frame _filemanager;
+ Gtk::VBox _fm;
+
+ Gtk::Frame _playback;
+
+ Gtk::Expander _currentmsgbox;
+ Glib::RefPtr<Gtk::TextBuffer> _currentmsgbuffer;
+ Gtk::TextView _currentmsgview;
+ Gtk::ScrolledWindow _currentmsgscroller;
+
+ // Construction and callback
+ void _construct();
+ void _respCallback(int resp);
+
+ // SessionManager and SPDesktop pointers
+ ::SPDesktop* _desktop;
+ Whiteboard::SessionManager* _sm;
+ Whiteboard::SessionFilePlayer* _sfp;
+
+ // button values
+ static unsigned short const CLOSE_FILE = 0;
+ static unsigned short const OPEN_FILE = 1;
+ static unsigned short const RESET_DELAY = 2;
+
+ static unsigned short const TOOLBAR_BASE = 10;
+ static unsigned short const REWIND = TOOLBAR_BASE + 0;
+ static unsigned short const STEP_REWIND = TOOLBAR_BASE + 1;
+ static unsigned short const PAUSE = TOOLBAR_BASE + 2;
+ static unsigned short const STEP_PLAY = TOOLBAR_BASE + 3;
+ static unsigned short const PLAY = TOOLBAR_BASE + 4;
+
+
+ // noncopyable
+ SessionPlaybackDialogImpl(SessionPlaybackDialogImpl const& dlg); // no copy
+ void operator=(SessionPlaybackDialogImpl const& dlg); // no assign
+};
+
+}
+
+}
+
+}
+
+#endif
diff --git a/src/ui/dialog/text-properties.cpp b/src/ui/dialog/text-properties.cpp
new file mode 100644
index 000000000..c4a95f014
--- /dev/null
+++ b/src/ui/dialog/text-properties.cpp
@@ -0,0 +1,59 @@
+/**
+ * \brief Text Properties dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "text-properties.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+TextProperties::TextProperties()
+ : Dialog ("dialogs.textandfont", SP_VERB_DIALOG_TEXT),
+ _page_font(1, 1),
+ _page_text(1, 1)
+{
+ // Top level vbox
+ Gtk::VBox *vbox = get_vbox();
+ vbox->set_spacing(4);
+
+ // Notebook for individual transformations
+ vbox->pack_start(_notebook, true, true);
+
+ // TODO: Insert widgets
+ _notebook.append_page(_page_font, _("Font"));
+ _notebook.append_page(_page_text, _("Text"));
+
+ show_all_children();
+}
+
+TextProperties::~TextProperties()
+{
+}
+
+} // 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/text-properties.h b/src/ui/dialog/text-properties.h
new file mode 100644
index 000000000..2d5a03b9e
--- /dev/null
+++ b/src/ui/dialog/text-properties.h
@@ -0,0 +1,60 @@
+/**
+ * \brief Text Properties dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_TEXT_PROPERTIES_H
+#define INKSCAPE_UI_DIALOG_TEXT_PROPERTIES_H
+
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+#include "dialog.h"
+#include "ui/widget/notebook-page.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class TextProperties : public Dialog {
+public:
+ TextProperties();
+ virtual ~TextProperties();
+
+ static TextProperties *create() { return new TextProperties(); }
+
+protected:
+ Gtk::Notebook _notebook;
+
+ NotebookPage _page_font;
+ NotebookPage _page_text;
+
+private:
+ TextProperties(TextProperties const &d);
+ TextProperties& operator=(TextProperties const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_TEXT_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/tracedialog.cpp b/src/ui/dialog/tracedialog.cpp
new file mode 100644
index 000000000..fad7cb315
--- /dev/null
+++ b/src/ui/dialog/tracedialog.cpp
@@ -0,0 +1,562 @@
+/*
+ * A simple dialog for setting the parameters for autotracing a
+ * bitmap <image> into an svg <path>
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/notebook.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/stock.h>
+
+#include <gtk/gtkdialog.h> //for GTK_RESPONSE* types
+#include <glibmm/i18n.h>
+
+
+
+#include "tracedialog.h"
+#include "trace/potrace/inkscape-potrace.h"
+
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+//#########################################################################
+//## I M P L E M E N T A T I O N
+//#########################################################################
+
+/**
+ * A dialog for adjusting bitmap->vector tracing parameters
+ */
+class TraceDialogImpl : public TraceDialog
+{
+
+ public:
+
+
+ /**
+ * Constructor
+ */
+ TraceDialogImpl();
+
+ /**
+ * Destructor
+ */
+ ~TraceDialogImpl();
+
+ /**
+ * Callback from OK or Cancel
+ */
+ void responseCallback(int response_id);
+
+ private:
+
+ /**
+ * This is the big almighty McGuffin
+ */
+ Inkscape::Trace::Tracer tracer;
+
+ /**
+ * This does potrace processing
+ * Only preview if do_i_trace is false
+ */
+ void potraceProcess(bool do_i_trace);
+
+ /**
+ * Abort processing
+ */
+ void abort();
+
+ void potracePreviewCallback();
+
+ Gtk::Notebook notebook;
+ Gtk::Tooltips tips;
+
+ //########## Potrace items
+ Gtk::VBox potraceBox;
+ Gtk::RadioButtonGroup potraceGroup;
+ Gtk::CheckButton potraceInvertButton;
+ Gtk::HBox potraceInvertBox;
+ Gtk::Button *potraceOkButton;
+ Gtk::Button *potraceCancelButton;
+
+ //brightness
+ Gtk::Frame potraceBrightnessFrame;
+ Gtk::VBox potraceBrightnessVBox;
+ Gtk::HBox potraceBrightnessBox;
+ Gtk::RadioButton potraceBrightnessRadioButton;
+ Gtk::Label potraceBrightnessSpinnerLabel;
+ Gtk::SpinButton potraceBrightnessSpinner;
+
+
+ //edge detection
+ Gtk::Frame potraceCannyFrame;
+ Gtk::HBox potraceCannyBox;
+ Gtk::VBox potraceCannyVBox;
+ Gtk::RadioButton potraceCannyRadioButton;
+ //Gtk::HSeparator potraceCannySeparator;
+ //Gtk::Label potraceCannyLoSpinnerLabel;
+ //Gtk::SpinButton potraceCannyLoSpinner;
+ Gtk::Label potraceCannyHiSpinnerLabel;
+ Gtk::SpinButton potraceCannyHiSpinner;
+
+ //quantization
+ Gtk::Frame potraceQuantFrame;
+ Gtk::HBox potraceQuantBox;
+ Gtk::VBox potraceQuantVBox;
+ Gtk::RadioButton potraceQuantRadioButton;
+ Gtk::Label potraceQuantNrColorLabel;
+ Gtk::SpinButton potraceQuantNrColorSpinner;
+
+ //multiple path scanning
+ Gtk::Frame potraceMultiScanFrame;
+ Gtk::VBox potraceMultiScanVBox;
+
+ Gtk::HBox potraceMultiScanHBox1;
+ Gtk::RadioButton potraceMultiScanBrightnessRadioButton;
+ Gtk::SpinButton potraceMultiScanNrColorSpinner;
+
+ Gtk::HBox potraceMultiScanHBox2;
+ Gtk::RadioButton potraceMultiScanColorRadioButton;
+ Gtk::CheckButton potraceMultiScanStackButton;
+
+ Gtk::HBox potraceMultiScanHBox3;
+ Gtk::RadioButton potraceMultiScanMonoRadioButton;
+ Gtk::Label potraceMultiScanNrColorLabel;
+
+ Gtk::CheckButton potraceMultiScanSmoothButton;
+
+
+ //preview
+ Gtk::Frame potracePreviewFrame;
+ Gtk::HBox potracePreviewBox;
+ Gtk::Button potracePreviewButton;
+ Gtk::Image potracePreviewImage;
+
+ //credits
+ Gtk::Frame potraceCreditsFrame;
+ Gtk::VBox potraceCreditsVBox;
+ Gtk::Label potraceCreditsLabel;
+
+ //########## Other items
+ Gtk::VBox otherBox;
+
+
+
+};
+
+
+
+
+//#########################################################################
+//## E V E N T S
+//#########################################################################
+
+/**
+ * This does potrace processing
+ * Only preview if do_i_trace is false
+ */
+void TraceDialogImpl::potraceProcess(bool do_i_trace)
+{
+ //##### Get the tracer and engine
+ Inkscape::Trace::Potrace::PotraceTracingEngine pte;
+
+ /* inversion */
+ bool invert = potraceInvertButton.get_active();
+ pte.setInvert(invert);
+
+ //##### Get the single-scan settings
+ /* which one? */
+ if (potraceBrightnessRadioButton.get_active())
+ pte.setTraceType(Inkscape::Trace::Potrace::TRACE_BRIGHTNESS);
+ else if (potraceMultiScanBrightnessRadioButton.get_active())
+ pte.setTraceType(Inkscape::Trace::Potrace::TRACE_BRIGHTNESS_MULTI);
+ else if (potraceCannyRadioButton.get_active())
+ pte.setTraceType(Inkscape::Trace::Potrace::TRACE_CANNY);
+ else if (potraceQuantRadioButton.get_active())
+ pte.setTraceType(Inkscape::Trace::Potrace::TRACE_QUANT);
+ else if (potraceMultiScanColorRadioButton.get_active())
+ {
+ pte.setTraceType(Inkscape::Trace::Potrace::TRACE_QUANT_COLOR);
+ pte.setInvert(false);
+ }
+ else if (potraceMultiScanMonoRadioButton.get_active())
+ {
+ pte.setTraceType(Inkscape::Trace::Potrace::TRACE_QUANT_MONO);
+ pte.setInvert(false);
+ }
+
+ /* brightness */
+ double brightnessThreshold = potraceBrightnessSpinner.get_value();
+ pte.setBrightnessThreshold(brightnessThreshold);
+
+ /* canny */
+ double cannyHighThreshold = potraceCannyHiSpinner.get_value();
+ pte.setCannyHighThreshold(cannyHighThreshold);
+
+ /* quantization */
+ int quantNrColors = potraceQuantNrColorSpinner.get_value_as_int();
+ pte.setQuantizationNrColors(quantNrColors);
+
+ //##### Get multiple-scan settings
+ int multiScanNrColors = potraceMultiScanNrColorSpinner.get_value_as_int();
+ pte.setMultiScanNrColors(multiScanNrColors);
+ bool do_i_stack = potraceMultiScanStackButton.get_active();
+ pte.setMultiScanStack(do_i_stack);
+ bool do_i_smooth = potraceMultiScanSmoothButton.get_active();
+ pte.setMultiScanSmooth(do_i_smooth);
+
+ //##### Get intermediate bitmap image
+ GdkPixbuf *pixbuf = tracer.getSelectedImage();
+ if (pixbuf)
+ {
+ GdkPixbuf *preview = pte.preview(pixbuf);
+ if (preview)
+ {
+ Glib::RefPtr<Gdk::Pixbuf> thePreview = Glib::wrap(preview);
+ int width = thePreview->get_width();
+ int height = thePreview->get_height();
+ double scaleFactor = 100.0 / (double)height;
+ int newWidth = (int) (((double)width) * scaleFactor);
+ int newHeight = (int) (((double)height) * scaleFactor);
+ Glib::RefPtr<Gdk::Pixbuf> scaledPreview =
+ thePreview->scale_simple(newWidth, newHeight,
+ Gdk::INTERP_NEAREST);
+ //g_object_unref(preview);
+ potracePreviewImage.set(scaledPreview);
+ }
+ }
+
+ //##### Convert
+ if (do_i_trace)
+ {
+ if (potraceCancelButton)
+ potraceCancelButton->set_sensitive(true);
+ if (potraceOkButton)
+ potraceOkButton->set_sensitive(false);
+ tracer.trace(&pte);
+ if (potraceCancelButton)
+ potraceCancelButton->set_sensitive(false);
+ if (potraceOkButton)
+ potraceOkButton->set_sensitive(true);
+ }
+
+}
+
+
+/**
+ * Abort processing
+ */
+void TraceDialogImpl::abort()
+{
+ //### Do some GUI thing
+
+ //### Make the abort() call to the tracer
+ tracer.abort();
+
+}
+
+
+
+//#########################################################################
+//## E V E N T S
+//#########################################################################
+
+/**
+ * Callback from the Preview button. Can be called from elsewhere.
+ */
+void TraceDialogImpl::potracePreviewCallback()
+{
+ potraceProcess(false);
+}
+
+/**
+ * Default response from the dialog. Let's intercept it
+ */
+void TraceDialogImpl::responseCallback(int response_id)
+{
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ int panelNr = notebook.get_current_page();
+ //g_message("selected panel:%d\n", panelNr);
+
+ if (panelNr == 0)
+ {
+ potraceProcess(true);
+ }
+ }
+ else if (response_id == GTK_RESPONSE_CANCEL)
+ {
+ abort();
+ }
+ else
+ {
+ hide();
+ return;
+ }
+
+
+
+}
+
+
+
+
+//#########################################################################
+//## C O N S T R U C T O R / D E S T R U C T O R
+//#########################################################################
+/**
+ * Constructor
+ */
+TraceDialogImpl::TraceDialogImpl()
+{
+
+ Gtk::VBox *mainVBox = get_vbox();
+
+#define MARGIN 4
+
+ //##Set up the Potrace panel
+
+ /*#### brightness ####*/
+ potraceBrightnessRadioButton.set_label(_("Brightness"));
+ potraceGroup = potraceBrightnessRadioButton.get_group();
+ potraceBrightnessBox.pack_start(potraceBrightnessRadioButton, false, false, MARGIN);
+ tips.set_tip(potraceBrightnessRadioButton, _("Trace by a given brightness level"));
+
+ potraceBrightnessSpinner.set_digits(3);
+ potraceBrightnessSpinner.set_increments(0.01, 0.1);
+ potraceBrightnessSpinner.set_range(0.0, 1.0);
+ potraceBrightnessSpinner.set_value(0.45);
+ potraceBrightnessBox.pack_end(potraceBrightnessSpinner, false, false, MARGIN);
+ tips.set_tip(potraceBrightnessSpinner, _("Brightness cutoff for black/white"));
+
+ potraceBrightnessSpinnerLabel.set_label(_("Threshold:"));
+ potraceBrightnessBox.pack_end(potraceBrightnessSpinnerLabel, false, false, MARGIN);
+
+ potraceBrightnessVBox.pack_start(potraceBrightnessBox, false, false, MARGIN);
+
+ potraceBrightnessFrame.set_label(_("Image Brightness"));
+ //potraceBrightnessFrame.set_shadow_type(Gtk::SHADOW_NONE);
+ potraceBrightnessFrame.add(potraceBrightnessVBox);
+ potraceBox.pack_start(potraceBrightnessFrame, false, false, 0);
+
+ /*#### canny edge detection ####*/
+ // TRANSLATORS: "Canny" is the name of the inventor of this edge detection method
+ potraceCannyRadioButton.set_label(_("Optimal Edge Detection (Canny)"));
+ potraceCannyRadioButton.set_group(potraceGroup);
+ potraceCannyBox.pack_start(potraceCannyRadioButton, false, false, MARGIN);
+ tips.set_tip(potraceCannyRadioButton, _("Trace with edge detection by J. Canny's algorithm"));
+ /*
+ potraceCannyBox.pack_start(potraceCannySeparator);
+ potraceCannyLoSpinnerLabel.set_label(_("Low"));
+ potraceCannyBox.pack_start(potraceCannyLoSpinnerLabel);
+ potraceCannyLoSpinner.set_digits(5);
+ potraceCannyLoSpinner.set_increments(0.01, 0.1);
+ potraceCannyLoSpinner.set_range(0.0, 1.0);
+ potraceCannyLoSpinner.set_value(0.1);
+ potraceCannyBox.pack_start(potraceCannyLoSpinner);
+ */
+ potraceCannyHiSpinner.set_digits(3);
+ potraceCannyHiSpinner.set_increments(0.01, 0.1);
+ potraceCannyHiSpinner.set_range(0.0, 1.0);
+ potraceCannyHiSpinner.set_value(0.65);
+ potraceCannyBox.pack_end(potraceCannyHiSpinner, false, false, MARGIN);
+ tips.set_tip(potraceCannyHiSpinner, _("Brightness cutoff for adjacent pixels (determines edge thickness)"));
+
+ potraceCannyHiSpinnerLabel.set_label(_("Threshold:"));
+ potraceCannyBox.pack_end(potraceCannyHiSpinnerLabel, false, false, MARGIN);
+
+ potraceCannyVBox.pack_start(potraceCannyBox, false, false, MARGIN);
+
+ potraceCannyFrame.set_label(_("Edge Detection"));
+ //potraceCannyFrame.set_shadow_type(Gtk::SHADOW_NONE);
+ potraceCannyFrame.add(potraceCannyVBox);
+ potraceBox.pack_start(potraceCannyFrame, false, false, 0);
+
+ /*#### quantization ####*/
+ // TRANSLATORS: Color Quantization: the process of reducing the number of colors
+ // in an image by selecting an optimized set of representative colors and then
+ // re-applying this reduced set to the original image.
+ potraceQuantRadioButton.set_label(_("Color Quantization"));
+ potraceQuantRadioButton.set_group(potraceGroup);
+ potraceQuantBox.pack_start(potraceQuantRadioButton, false, false, MARGIN);
+ tips.set_tip(potraceQuantRadioButton, _("Trace along the boundaries of reduced colors"));
+
+ potraceQuantNrColorSpinner.set_digits(2);
+ potraceQuantNrColorSpinner.set_increments(1.0, 4.0);
+ potraceQuantNrColorSpinner.set_range(2.0, 64.0);
+ potraceQuantNrColorSpinner.set_value(8.0);
+ potraceQuantBox.pack_end(potraceQuantNrColorSpinner, false, false, MARGIN);
+ tips.set_tip(potraceQuantNrColorSpinner, _("The number of reduced colors"));
+
+ potraceQuantNrColorLabel.set_label(_("Colors:"));
+ potraceQuantBox.pack_end(potraceQuantNrColorLabel, false, false, MARGIN);
+
+ potraceQuantVBox.pack_start(potraceQuantBox, false, false, MARGIN);
+
+ potraceQuantFrame.set_label(_("Quantization / Reduction"));
+ //potraceQuantFrame.set_shadow_type(Gtk::SHADOW_NONE);
+ potraceQuantFrame.add(potraceQuantVBox);
+ potraceBox.pack_start(potraceQuantFrame, false, false, 0);
+
+ /*#### Multiple scanning####*/
+ //----Hbox1
+ potraceMultiScanBrightnessRadioButton.set_label(_("Brightness"));
+ potraceMultiScanBrightnessRadioButton.set_group(potraceGroup);
+ potraceMultiScanHBox1.pack_start(potraceMultiScanBrightnessRadioButton, false, false, MARGIN);
+ tips.set_tip(potraceMultiScanBrightnessRadioButton, _("Trace the given number of brightness levels"));
+
+ potraceMultiScanNrColorSpinner.set_digits(2);
+ potraceMultiScanNrColorSpinner.set_increments(1.0, 4.0);
+ potraceMultiScanNrColorSpinner.set_range(2.0, 256.0);
+ potraceMultiScanNrColorSpinner.set_value(8.0);
+ potraceMultiScanHBox1.pack_end(potraceMultiScanNrColorSpinner, false, false, MARGIN);
+ potraceMultiScanNrColorLabel.set_label(_("Scans:"));
+ potraceMultiScanHBox1.pack_end(potraceMultiScanNrColorLabel, false, false, MARGIN);
+ tips.set_tip(potraceMultiScanNrColorSpinner, _("The desired number of scans"));
+
+ potraceMultiScanVBox.pack_start(potraceMultiScanHBox1, false, false, MARGIN);
+
+ //----Hbox2
+ potraceMultiScanColorRadioButton.set_label(_("Color"));
+ potraceMultiScanColorRadioButton.set_group(potraceGroup);
+ potraceMultiScanHBox2.pack_start(potraceMultiScanColorRadioButton, false, false, MARGIN);
+ tips.set_tip(potraceMultiScanColorRadioButton, _("Trace the given number of reduced colors"));
+
+
+ potraceMultiScanVBox.pack_start(potraceMultiScanHBox2, false, false, MARGIN);
+
+ //---Hbox3
+ potraceMultiScanMonoRadioButton.set_label(_("Monochrome"));
+ potraceMultiScanMonoRadioButton.set_group(potraceGroup);
+ potraceMultiScanHBox3.pack_start(potraceMultiScanMonoRadioButton, false, false, MARGIN);
+ tips.set_tip(potraceMultiScanMonoRadioButton, _("Same as Color, but convert result to grayscale"));
+
+ // TRANSLATORS: "Stack" is a verb here
+ potraceMultiScanStackButton.set_label(_("Stack"));
+ potraceMultiScanStackButton.set_active(true);
+ potraceMultiScanHBox3.pack_end(potraceMultiScanStackButton, false, false, MARGIN);
+ tips.set_tip(potraceMultiScanStackButton, _("Stack scans vertically (no gaps) or tile horizontally (usually with gaps)"));
+
+ // TRANSLATORS: "Smooth" is a verb here
+ potraceMultiScanSmoothButton.set_label(_("Smooth"));
+ potraceMultiScanSmoothButton.set_active(true);
+ potraceMultiScanHBox3.pack_end(potraceMultiScanSmoothButton, false, false, MARGIN);
+ tips.set_tip(potraceMultiScanSmoothButton, _("Apply Gaussian blur to the bitmap before tracing"));
+
+ potraceMultiScanVBox.pack_start(potraceMultiScanHBox3, false, false, MARGIN);
+
+ potraceMultiScanFrame.set_label(_("Multiple Scanning"));
+ //potraceQuantFrame.set_shadow_type(Gtk::SHADOW_NONE);
+ potraceMultiScanFrame.add(potraceMultiScanVBox);
+ potraceBox.pack_start(potraceMultiScanFrame, false, false, 0);
+
+ /*#### Preview ####*/
+ potracePreviewButton.set_label(_("Preview"));
+ potracePreviewButton.signal_clicked().connect(
+ sigc::mem_fun(*this, &TraceDialogImpl::potracePreviewCallback) );
+ potracePreviewBox.pack_end(potracePreviewButton, false, false, 0);//do not expand
+ tips.set_tip(potracePreviewButton, _("Preview the result without actual tracing"));
+
+
+ potracePreviewImage.set_size_request(100,100);
+ //potracePreviewImage.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
+ potracePreviewBox.pack_start(potracePreviewImage, true, true, 0);
+ potracePreviewFrame.set_label(_("Preview")); // I guess it's correct to call the "intermediate bitmap" a preview of the trace
+ //potracePreviewFrame.set_shadow_type(Gtk::SHADOW_NONE);
+ potracePreviewFrame.add(potracePreviewBox);
+ potraceBox.pack_start(potracePreviewFrame, true, true, 0);
+
+ /*#### swap black and white ####*/
+ potraceInvertButton.set_label(_("Invert"));
+ potraceInvertButton.set_active(false);
+ potraceInvertBox.pack_end(potraceInvertButton, false, false, MARGIN);
+ potraceBox.pack_start(potraceInvertBox, false, false, MARGIN);
+ tips.set_tip(potraceInvertButton, _("Invert black and white regions for single traces"));
+
+ /*#### Credits ####*/
+ potraceCreditsLabel.set_text(
+ _("Thanks to Peter Selinger, http://potrace.sourceforge.net")
+ );
+ potraceCreditsVBox.pack_start(potraceCreditsLabel, false, false, MARGIN);
+ potraceCreditsFrame.set_label(_("Credits"));
+ potraceCreditsFrame.set_shadow_type(Gtk::SHADOW_NONE);
+ potraceCreditsFrame.add(potraceCreditsVBox);
+ potraceBox.pack_start(potraceCreditsFrame, false, false, 0);
+
+ /*done */
+ // TRANSLATORS: Potrace is an application for transforming bitmaps into
+ // vector graphics (http://potrace.sourceforge.net/)
+ notebook.append_page(potraceBox, _("Potrace"));
+
+ //##Set up the Other panel
+ // This may be reenabled when we have another tracer; now an empty tab is confusing so I'm disabling it
+ // notebook.append_page(otherBox, _("Other"));
+
+ //##Put the notebook on the dialog
+ mainVBox->pack_start(notebook);
+
+ //## The OK button
+ potraceCancelButton = add_button(Gtk::Stock::STOP, GTK_RESPONSE_CANCEL);
+ if (potraceCancelButton)
+ {
+ tips.set_tip((*potraceCancelButton), _("Abort a trace in progress"));
+ potraceCancelButton->set_sensitive(false);
+ }
+ potraceOkButton = add_button(Gtk::Stock::OK, GTK_RESPONSE_OK);
+ tips.set_tip((*potraceOkButton), _("Execute the trace"));
+
+ show_all_children();
+
+ //## Connect the signal
+ signal_response().connect(
+ sigc::mem_fun(*this, &TraceDialogImpl::responseCallback) );
+}
+
+/**
+ * Factory method. Use this to create a new TraceDialog
+ */
+TraceDialog *TraceDialog::create()
+{
+ TraceDialog *dialog = new TraceDialogImpl();
+ return dialog;
+}
+
+
+/**
+ * Constructor
+ */
+TraceDialogImpl::~TraceDialogImpl()
+{
+
+
+}
+
+
+
+
+
+
+} //namespace Dialog
+} //namespace UI
+} //namespace Inkscape
+
+//#########################################################################
+//## E N D O F F I L E
+//#########################################################################
+
+
+
diff --git a/src/ui/dialog/tracedialog.h b/src/ui/dialog/tracedialog.h
new file mode 100644
index 000000000..80311bb15
--- /dev/null
+++ b/src/ui/dialog/tracedialog.h
@@ -0,0 +1,63 @@
+#ifndef __TRACEDIALOG_H__
+#define __TRACEDIALOG_H__
+/*
+ * A simple dialog for setting the parameters for autotracing a
+ * bitmap <image> into an svg <path>
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include "verbs.h"
+#include "dialog.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+/**
+ * A dialog that displays log messages
+ */
+class TraceDialog : public Dialog
+{
+
+public:
+
+
+ /**
+ * Constructor
+ */
+ TraceDialog() : Dialog ("dialogs.trace", SP_VERB_SELECTION_TRACE)
+ {}
+
+
+ /**
+ * Factory method
+ */
+ static TraceDialog *create();
+
+ /**
+ * Destructor
+ */
+ virtual ~TraceDialog() {};
+
+
+};
+
+
+} //namespace Dialog
+} //namespace UI
+} //namespace Inkscape
+
+
+
+
+#endif /* __TRACEDIALOG_H__ */
+
diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp
new file mode 100644
index 000000000..9182209f5
--- /dev/null
+++ b/src/ui/dialog/transformation.cpp
@@ -0,0 +1,955 @@
+/**
+ * \brief Object Transformation dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/stock.h>
+
+#include "document.h"
+#include "desktop-handles.h"
+#include "transformation.h"
+#include "libnr/nr-matrix-ops.h"
+#include "inkscape.h"
+#include "selection.h"
+#include "selection-chemistry.h"
+#include "verbs.h"
+#include "prefs-utils.h"
+#include "sp-item-transform.h"
+#include "macros.h"
+#include "sp-item.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+void on_selection_changed(Inkscape::Application *inkscape, Inkscape::Selection *selection, Transformation *daad)
+{
+ int page = daad->getCurrentPage();
+ daad->updateSelection((Inkscape::UI::Dialog::Transformation::PageType)page, selection);
+}
+
+void on_selection_modified ( Inkscape::Application *inkscape,
+ Inkscape::Selection *selection,
+ guint flags,
+ Transformation *daad )
+{
+ int page = daad->getCurrentPage();
+ daad->updateSelection((Inkscape::UI::Dialog::Transformation::PageType)page, selection);
+}
+
+/*########################################################################
+# C O N S T R U C T O R
+########################################################################*/
+
+/**
+ * Constructor for Transformation. This does the initialization
+ * and layout of the dialog used for transforming SVG objects. It
+ * consists of 5 pages for the 5 operations it handles:
+ * 'Move' allows x,y translation of SVG objects
+ * 'Scale' allows linear resizing of SVG objects
+ * 'Rotate' allows rotating SVG objects by a degree
+ * 'Skew' allows skewing SVG objects
+ * 'Matrix' allows applying a generic affine transform on SVG objects,
+ * with the user specifying the 6 degrees of freedom manually.
+ *
+ * The dialog is implemented as a Gtk::Notebook with five pages.
+ * The pages are implemented using Inkscape's NotebookPage which
+ * is used to help make sure all of Inkscape's notebooks follow
+ * the same style. We then populate the pages with our widgets,
+ * we use the ScalarUnit class for this.
+ *
+ */
+Transformation::Transformation()
+ : Dialog ("dialogs.transformation", SP_VERB_DIALOG_TRANSFORM),
+ _page_move (4, 2),
+ _page_scale (4, 2),
+ _page_rotate (4, 2),
+ _page_skew (4, 2),
+ _page_transform (3, 3),
+ _scalar_move_horizontal (_("_Horizontal"), _("Horizontal displacement (relative) or position (absolute)"), UNIT_TYPE_LINEAR,
+ "", "arrows_hor", &_units_move),
+ _scalar_move_vertical (_("_Vertical"), _("Vertical displacement (relative) or position (absolute)"), UNIT_TYPE_LINEAR,
+ "", "arrows_ver", &_units_move),
+ _scalar_scale_horizontal(_("_Width"), _("Horizontal size increment (absolute or percentage)"), UNIT_TYPE_DIMENSIONLESS,
+ "", "transform_scale_hor", &_units_scale),
+ _scalar_scale_vertical (_("_Height"), _("Vertical size increment (absolute or percentage)"), UNIT_TYPE_DIMENSIONLESS,
+ "", "transform_scale_ver", &_units_scale),
+ _scalar_rotate (_("A_ngle"), _("Rotation angle (positive = counterclockwise)"), UNIT_TYPE_RADIAL,
+ "", "transform_rotate", &_units_rotate),
+ _scalar_skew_horizontal (_("_Horizontal"), _("Horizontal skew angle (positive = counterclockwise), or absolute displacement, or percentage displacement"), UNIT_TYPE_LINEAR,
+ "", "arrows_hor", &_units_skew),
+ _scalar_skew_vertical (_("_Vertical"), _("Vertical skew angle (positive = counterclockwise), or absolute displacement, or percentage displacement"), UNIT_TYPE_LINEAR,
+ "", "arrows_ver", &_units_skew),
+
+ _scalar_transform_a ("_A", _("Transformation matrix element A")),
+ _scalar_transform_b ("_B", _("Transformation matrix element B")),
+ _scalar_transform_c ("_C", _("Transformation matrix element C")),
+ _scalar_transform_d ("_D", _("Transformation matrix element D")),
+ _scalar_transform_e ("_E", _("Transformation matrix element E")),
+ _scalar_transform_f ("_F", _("Transformation matrix element F")),
+
+ _check_move_relative (_("Rela_tive move"), _("Add the specified relative displacement to the current position; otherwise, edit the current absolute position directly")),
+ _check_scale_proportional (_("Scale proportionally"), _("Preserve the width/height ratio of the scaled objects")),
+ _check_apply_separately (_("Apply to each _object separately"), _("Apply the scale/rotate/skew to each selected object separately; otherwise, transform the selection as a whole")),
+ _check_replace_matrix (_("Edit c_urrent matrix"), _("Edit the current transform= matrix; otherwise, post-multiply transform= by this matrix"))
+
+{
+ // Top level vbox
+ Gtk::VBox *vbox = get_vbox();
+ vbox->set_spacing(0);
+
+ // Notebook for individual transformations
+ vbox->pack_start(_notebook, true, true);
+
+ _notebook.append_page(_page_move, _("_Move"), true);
+ layoutPageMove();
+
+ _notebook.append_page(_page_scale, _("_Scale"), true);
+ layoutPageScale();
+
+ _notebook.append_page(_page_rotate, _("_Rotate"), true);
+ layoutPageRotate();
+
+ _notebook.append_page(_page_skew, _("Ske_w"), true);
+ layoutPageSkew();
+
+ _notebook.append_page(_page_transform, _("Matri_x"), true);
+ layoutPageTransform();
+
+ _notebook.signal_switch_page().connect(sigc::mem_fun(*this, &Transformation::onSwitchPage));
+
+ // Apply separately
+ vbox->pack_start(_check_apply_separately, true, true);
+ _check_apply_separately.set_active(prefs_get_int_attribute_limited ("dialogs.transformation", "applyseparately", 0, 0, 1));
+ _check_apply_separately.signal_toggled().connect(sigc::mem_fun(*this, &Transformation::onApplySeparatelyToggled));
+
+ updateSelection(PAGE_MOVE, _getSelection());
+
+ resetButton = add_button(Gtk::Stock::CLEAR, 0);
+ if (resetButton) {
+ tooltips.set_tip((*resetButton), _("Reset the values on the current tab to defaults"));
+ resetButton->set_sensitive(true);
+ resetButton->signal_clicked().connect(sigc::mem_fun(*this, &Transformation::onClear));
+ }
+
+ applyButton = add_button(Gtk::Stock::APPLY, Gtk::RESPONSE_APPLY);
+ if (applyButton) {
+ tooltips.set_tip((*applyButton), _("Apply transformation to selection"));
+ applyButton->set_sensitive(false);
+ }
+
+ // Connect to the global selection changed & modified signals
+ g_signal_connect (G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (on_selection_changed), this);
+ g_signal_connect (G_OBJECT (INKSCAPE), "modify_selection", G_CALLBACK (on_selection_modified), this);
+
+ show_all_children();
+}
+
+Transformation::~Transformation()
+{
+ sp_signal_disconnect_by_data (G_OBJECT (INKSCAPE), this);
+}
+
+
+
+/*########################################################################
+# U T I L I T Y
+########################################################################*/
+
+void
+Transformation::present(Transformation::PageType page)
+{
+ _notebook.set_current_page(page);
+ Gtk::Dialog::show();
+ Gtk::Dialog::present();
+}
+
+
+
+
+/*########################################################################
+# S E T U P L A Y O U T
+########################################################################*/
+
+
+void
+Transformation::layoutPageMove()
+{
+ _units_move.setUnitType(UNIT_TYPE_LINEAR);
+ _scalar_move_horizontal.initScalar(-1e6, 1e6);
+ _scalar_move_horizontal.setDigits(3);
+ _scalar_move_horizontal.setIncrements(0.1, 1.0);
+
+ _scalar_move_vertical.initScalar(-1e6, 1e6);
+ _scalar_move_vertical.setDigits(3);
+ _scalar_move_vertical.setIncrements(0.1, 1.0);
+
+ //_scalar_move_vertical.set_label_image( INKSCAPE_STOCK_ARROWS_HOR );
+ _page_move.table()
+ .attach(_scalar_move_horizontal, 0, 2, 0, 1, Gtk::FILL, Gtk::SHRINK);
+
+ _page_move.table()
+ .attach(_units_move, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+
+ _scalar_move_horizontal.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onMoveValueChanged));
+
+ //_scalar_move_vertical.set_label_image( INKSCAPE_STOCK_ARROWS_VER );
+ _page_move.table()
+ .attach(_scalar_move_vertical, 0, 2, 1, 2, Gtk::FILL, Gtk::SHRINK);
+
+ _scalar_move_vertical.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onMoveValueChanged));
+
+ // Relative moves
+ _page_move.table()
+ .attach(_check_move_relative, 0, 2, 2, 3, Gtk::FILL, Gtk::SHRINK);
+ _check_move_relative.set_active(true);
+ _check_move_relative.signal_toggled()
+ .connect(sigc::mem_fun(*this, &Transformation::onMoveRelativeToggled));
+}
+
+void
+Transformation::layoutPageScale()
+{
+ _units_scale.setUnitType(UNIT_TYPE_DIMENSIONLESS);
+ _units_scale.setUnitType(UNIT_TYPE_LINEAR);
+
+ _scalar_scale_horizontal.initScalar(-1e6, 1e6);
+ _scalar_scale_horizontal.setValue(0.0, "%");
+ _scalar_scale_horizontal.setDigits(3);
+ _scalar_scale_horizontal.setIncrements(0.1, 1.0);
+ _scalar_scale_horizontal.setAbsoluteIsIncrement(true);
+ _scalar_scale_horizontal.setPercentageIsIncrement(true);
+
+ _scalar_scale_vertical.initScalar(-1e6, 1e6);
+ _scalar_scale_vertical.setValue(0.0, "%");
+ _scalar_scale_vertical.setDigits(3);
+ _scalar_scale_vertical.setIncrements(0.1, 1.0);
+ _scalar_scale_vertical.setAbsoluteIsIncrement(true);
+ _scalar_scale_vertical.setPercentageIsIncrement(true);
+
+ _page_scale.table()
+ .attach(_scalar_scale_horizontal, 0, 2, 0, 1, Gtk::FILL, Gtk::SHRINK);
+ _scalar_scale_horizontal.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onScaleXValueChanged));
+
+ _page_scale.table()
+ .attach(_units_scale, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+
+ _page_scale.table()
+ .attach(_scalar_scale_vertical, 0, 2, 1, 2, Gtk::FILL, Gtk::SHRINK);
+ _scalar_scale_vertical.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onScaleYValueChanged));
+
+ _page_scale.table()
+ .attach(_check_scale_proportional, 0, 2, 2, 3, Gtk::FILL, Gtk::SHRINK);
+ _check_scale_proportional.set_active(false);
+ _check_scale_proportional.signal_toggled()
+ .connect(sigc::mem_fun(*this, &Transformation::onScaleProportionalToggled));
+
+ //TODO: add a widget for selecting the fixed point in scaling, or honour rotation center?
+}
+
+void
+Transformation::layoutPageRotate()
+{
+ _units_rotate.setUnitType(UNIT_TYPE_RADIAL);
+
+ _scalar_rotate.initScalar(-360.0, 360.0);
+ _scalar_rotate.setDigits(3);
+ _scalar_rotate.setIncrements(0.1, 1.0);
+
+ _page_rotate.table()
+ .attach(_scalar_rotate, 0, 2, 0, 1, Gtk::FILL, Gtk::SHRINK);
+
+ _page_rotate.table()
+ .attach(_units_rotate, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+
+ _scalar_rotate.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onRotateValueChanged));
+
+ //TODO: honour rotation center?
+}
+
+void
+Transformation::layoutPageSkew()
+{
+ _units_skew.setUnitType(UNIT_TYPE_LINEAR);
+ _units_skew.setUnitType(UNIT_TYPE_DIMENSIONLESS);
+ _units_skew.setUnitType(UNIT_TYPE_RADIAL);
+
+ _scalar_skew_horizontal.initScalar(-1e6, 1e6);
+ _scalar_skew_horizontal.setDigits(3);
+ _scalar_skew_horizontal.setIncrements(0.1, 1.0);
+
+ _scalar_skew_vertical.initScalar(-1e6, 1e6);
+ _scalar_skew_vertical.setDigits(3);
+ _scalar_skew_vertical.setIncrements(0.1, 1.0);
+
+ _page_skew.table()
+ .attach(_scalar_skew_horizontal, 0, 2, 0, 1, Gtk::FILL, Gtk::SHRINK);
+ _scalar_skew_horizontal.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onSkewValueChanged));
+
+ _page_skew.table()
+ .attach(_units_skew, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+
+ _page_skew.table()
+ .attach(_scalar_skew_vertical, 0, 2, 1, 2, Gtk::FILL, Gtk::SHRINK);
+ _scalar_skew_vertical.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onSkewValueChanged));
+
+ //TODO: honour rotation center?
+}
+
+
+
+void
+Transformation::layoutPageTransform()
+{
+ _scalar_transform_a.setWidgetSizeRequest(65, -1);
+ _scalar_transform_a.setRange(-1e10, 1e10);
+ _scalar_transform_a.setDigits(3);
+ _scalar_transform_a.setIncrements(0.1, 1.0);
+ _scalar_transform_a.setValue(1.0);
+ _page_transform.table()
+ .attach(_scalar_transform_a, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+ _scalar_transform_a.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onTransformValueChanged));
+
+
+ _scalar_transform_b.setWidgetSizeRequest(65, -1);
+ _scalar_transform_b.setRange(-1e10, 1e10);
+ _scalar_transform_b.setDigits(3);
+ _scalar_transform_b.setIncrements(0.1, 1.0);
+ _scalar_transform_b.setValue(0.0);
+ _page_transform.table()
+ .attach(_scalar_transform_b, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
+ _scalar_transform_b.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onTransformValueChanged));
+
+
+ _scalar_transform_c.setWidgetSizeRequest(65, -1);
+ _scalar_transform_c.setRange(-1e10, 1e10);
+ _scalar_transform_c.setDigits(3);
+ _scalar_transform_c.setIncrements(0.1, 1.0);
+ _scalar_transform_c.setValue(0.0);
+ _page_transform.table()
+ .attach(_scalar_transform_c, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+ _scalar_transform_c.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onTransformValueChanged));
+
+
+ _scalar_transform_d.setWidgetSizeRequest(65, -1);
+ _scalar_transform_d.setRange(-1e10, 1e10);
+ _scalar_transform_d.setDigits(3);
+ _scalar_transform_d.setIncrements(0.1, 1.0);
+ _scalar_transform_d.setValue(1.0);
+ _page_transform.table()
+ .attach(_scalar_transform_d, 1, 2, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
+ _scalar_transform_d.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onTransformValueChanged));
+
+
+ _scalar_transform_e.setWidgetSizeRequest(65, -1);
+ _scalar_transform_e.setRange(-1e10, 1e10);
+ _scalar_transform_e.setDigits(3);
+ _scalar_transform_e.setIncrements(0.1, 1.0);
+ _scalar_transform_e.setValue(0.0);
+ _page_transform.table()
+ .attach(_scalar_transform_e, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+ _scalar_transform_e.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onTransformValueChanged));
+
+
+ _scalar_transform_f.setWidgetSizeRequest(65, -1);
+ _scalar_transform_f.setRange(-1e10, 1e10);
+ _scalar_transform_f.setDigits(3);
+ _scalar_transform_f.setIncrements(0.1, 1.0);
+ _scalar_transform_f.setValue(0.0);
+ _page_transform.table()
+ .attach(_scalar_transform_f, 2, 3, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
+ _scalar_transform_f.signal_value_changed()
+ .connect(sigc::mem_fun(*this, &Transformation::onTransformValueChanged));
+
+ // Edit existing matrix
+ _page_transform.table()
+ .attach(_check_replace_matrix, 0, 2, 2, 3, Gtk::FILL, Gtk::SHRINK);
+ _check_replace_matrix.set_active(false);
+ _check_replace_matrix.signal_toggled()
+ .connect(sigc::mem_fun(*this, &Transformation::onReplaceMatrixToggled));
+}
+
+
+/*########################################################################
+# U P D A T E
+########################################################################*/
+
+void
+Transformation::updateSelection(PageType page, Inkscape::Selection *selection)
+{
+ if (!selection || selection->isEmpty())
+ return;
+
+ switch (page) {
+ case PAGE_MOVE: {
+ updatePageMove(selection);
+ break;
+ }
+ case PAGE_SCALE: {
+ updatePageScale(selection);
+ break;
+ }
+ case PAGE_ROTATE: {
+ updatePageRotate(selection);
+ break;
+ }
+ case PAGE_SKEW: {
+ updatePageSkew(selection);
+ break;
+ }
+ case PAGE_TRANSFORM: {
+ updatePageTransform(selection);
+ break;
+ }
+ case PAGE_QTY: {
+ break;
+ }
+ }
+
+ set_response_sensitive(Gtk::RESPONSE_APPLY,
+ selection && !selection->isEmpty());
+}
+
+void
+Transformation::onSwitchPage(GtkNotebookPage *page,
+ guint pagenum)
+{
+ updateSelection((PageType)pagenum, SP_DT_SELECTION(SP_ACTIVE_DESKTOP));
+}
+
+void
+Transformation::updatePageMove(Inkscape::Selection *selection)
+{
+ if (selection && !selection->isEmpty()) {
+ if (!_check_move_relative.get_active()) {
+
+ NR::Rect bbox = selection->bounds();
+ double x = bbox.min()[NR::X];
+ double y = bbox.min()[NR::Y];
+
+ _scalar_move_horizontal.setValue(x, "px");
+ _scalar_move_vertical.setValue(y, "px");
+ } else {
+ // do nothing, so you can apply the same relative move to many objects in turn
+ }
+ _page_move.set_sensitive(true);
+ } else {
+ _page_move.set_sensitive(false);
+ }
+}
+
+void
+Transformation::updatePageScale(Inkscape::Selection *selection)
+{
+ if (selection && !selection->isEmpty()) {
+ NR::Rect bbox = selection->bounds();
+ double w = bbox.extent(NR::X);
+ double h = bbox.extent(NR::Y);
+ _scalar_scale_horizontal.setHundredPercent(w);
+ _scalar_scale_vertical.setHundredPercent(h);
+ onScaleXValueChanged(); // to update x/y proportionality if switch is on
+ _page_scale.set_sensitive(true);
+ } else {
+ _page_scale.set_sensitive(false);
+ }
+}
+
+void
+Transformation::updatePageRotate(Inkscape::Selection *selection)
+{
+ if (selection && !selection->isEmpty()) {
+ _page_rotate.set_sensitive(true);
+ } else {
+ _page_rotate.set_sensitive(false);
+ }
+}
+
+void
+Transformation::updatePageSkew(Inkscape::Selection *selection)
+{
+ if (selection && !selection->isEmpty()) {
+ _page_skew.set_sensitive(true);
+ } else {
+ _page_skew.set_sensitive(false);
+ }
+}
+
+void
+Transformation::updatePageTransform(Inkscape::Selection *selection)
+{
+ if (selection && !selection->isEmpty()) {
+ if (_check_replace_matrix.get_active()) {
+ NR::Matrix current (SP_ITEM(selection->itemList()->data)->transform); // take from the first item in selection
+
+ NR::Matrix new_displayed = current;
+
+ _scalar_transform_a.setValue(new_displayed[0]);
+ _scalar_transform_b.setValue(new_displayed[1]);
+ _scalar_transform_c.setValue(new_displayed[2]);
+ _scalar_transform_d.setValue(new_displayed[3]);
+ _scalar_transform_e.setValue(new_displayed[4]);
+ _scalar_transform_f.setValue(new_displayed[5]);
+ } else {
+ // do nothing, so you can apply the same matrix to many objects in turn
+ }
+ _page_transform.set_sensitive(true);
+ } else {
+ _page_transform.set_sensitive(false);
+ }
+}
+
+
+
+
+
+/*########################################################################
+# A P P L Y
+########################################################################*/
+
+
+
+void
+Transformation::_apply()
+{
+ Inkscape::Selection * const selection = _getSelection();
+ if (!selection || selection->isEmpty())
+ return;
+
+ int const page = _notebook.get_current_page();
+
+ switch (page) {
+ case PAGE_MOVE: {
+ applyPageMove(selection);
+ break;
+ }
+ case PAGE_ROTATE: {
+ applyPageRotate(selection);
+ break;
+ }
+ case PAGE_SCALE: {
+ applyPageScale(selection);
+ break;
+ }
+ case PAGE_SKEW: {
+ applyPageSkew(selection);
+ break;
+ }
+ case PAGE_TRANSFORM: {
+ applyPageTransform(selection);
+ break;
+ }
+ }
+
+ //Let's play with never turning this off
+ //set_response_sensitive(Gtk::RESPONSE_APPLY, false);
+}
+
+void
+Transformation::applyPageMove(Inkscape::Selection *selection)
+{
+ double x = _scalar_move_horizontal.getValue("px");
+ double y = _scalar_move_vertical.getValue("px");
+
+ if (_check_move_relative.get_active()) {
+ sp_selection_move_relative(selection, x, y);
+ } else {
+ NR::Rect bbox = selection->bounds();
+ sp_selection_move_relative(selection,
+ x - bbox.min()[NR::X], y - bbox.min()[NR::Y]);
+ }
+
+ sp_document_done ( SP_DT_DOCUMENT (selection->desktop()) );
+}
+
+void
+Transformation::applyPageScale(Inkscape::Selection *selection)
+{
+ double scaleX = _scalar_scale_horizontal.getValue("px");
+ double scaleY = _scalar_scale_vertical.getValue("px");
+
+ if (prefs_get_int_attribute_limited ("dialogs.transformation", "applyseparately", 0, 0, 1) == 1) {
+ for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
+ SPItem *item = SP_ITEM(l->data);
+ NR::Rect bbox (sp_item_bbox_desktop(item));
+ NR::scale scale (0,0);
+ // the values are increments!
+ if (_units_scale.isAbsolute()) {
+ double new_width = bbox.extent(NR::X) + scaleX;
+ if (new_width < 1e-6) new_width = 1e-6; // not 0, as this would result in a nasty no-bbox object
+ double new_height = bbox.extent(NR::Y) + scaleY;
+ if (new_height < 1e-6) new_height = 1e-6;
+ scale = NR::scale(new_width / bbox.extent(NR::X), new_height / bbox.extent(NR::Y));
+ } else {
+ double new_width = 100 + scaleX;
+ if (new_width < 1e-6) new_width = 1e-6;
+ double new_height = 100 + scaleY;
+ if (new_height < 1e-6) new_height = 1e-6;
+ scale = NR::scale(new_width / 100.0, new_height / 100.0);
+ }
+ sp_item_scale_rel (item, scale);
+ }
+ } else {
+ NR::Rect bbox(selection->bounds());
+ NR::Point center(bbox.midpoint());
+ NR::scale scale (0,0);
+ // the values are increments!
+ if (_units_scale.isAbsolute()) {
+ double new_width = bbox.extent(NR::X) + scaleX;
+ if (new_width < 1e-6) new_width = 1e-6;
+ double new_height = bbox.extent(NR::Y) + scaleY;
+ if (new_height < 1e-6) new_height = 1e-6;
+ scale = NR::scale(new_width / bbox.extent(NR::X), new_height / bbox.extent(NR::Y));
+ } else {
+ double new_width = 100 + scaleX;
+ if (new_width < 1e-6) new_width = 1e-6;
+ double new_height = 100 + scaleY;
+ if (new_height < 1e-6) new_height = 1e-6;
+ scale = NR::scale(new_width / 100.0, new_height / 100.0);
+ }
+ sp_selection_scale_relative(selection, center, scale);
+ }
+
+ sp_document_done(SP_DT_DOCUMENT(selection->desktop()));
+}
+
+void
+Transformation::applyPageRotate(Inkscape::Selection *selection)
+{
+ double angle = _scalar_rotate.getValue("deg");
+
+ if (prefs_get_int_attribute_limited ("dialogs.transformation", "applyseparately", 0, 0, 1) == 1) {
+ for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
+ SPItem *item = SP_ITEM(l->data);
+ sp_item_rotate_rel(item, NR::rotate (angle*M_PI/180.0));
+ }
+ } else {
+ NR::Rect bbox = selection->bounds();
+ NR::Point center = bbox.midpoint();
+ sp_selection_rotate_relative(selection, center, angle);
+ }
+
+ sp_document_done(SP_DT_DOCUMENT(selection->desktop()));
+
+}
+
+void
+Transformation::applyPageSkew(Inkscape::Selection *selection)
+{
+ if (prefs_get_int_attribute_limited ("dialogs.transformation", "applyseparately", 0, 0, 1) == 1) {
+ for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
+ SPItem *item = SP_ITEM(l->data);
+
+ if (!_units_skew.isAbsolute()) { // percentage
+ double skewX = _scalar_skew_horizontal.getValue("%");
+ double skewY = _scalar_skew_vertical.getValue("%");
+ sp_item_skew_rel (item, 0.01*skewX, 0.01*skewY);
+ } else if (_units_skew.isRadial()) { //deg or rad
+ double angleX = _scalar_skew_horizontal.getValue("rad");
+ double angleY = _scalar_skew_vertical.getValue("rad");
+ double skewX = tan(-angleX);
+ double skewY = tan(angleY);
+ sp_item_skew_rel (item, skewX, skewY);
+ } else { // absolute displacement
+ double skewX = _scalar_skew_horizontal.getValue("px");
+ double skewY = _scalar_skew_vertical.getValue("px");
+ NR::Rect bbox(sp_item_bbox_desktop(item));
+ double width = bbox.dimensions()[NR::X];
+ double height = bbox.dimensions()[NR::Y];
+ sp_item_skew_rel (item, skewX/height, skewY/width);
+ }
+ }
+ } else { // transform whole selection
+ NR::Rect bbox = selection->bounds();
+ double width = bbox.max()[NR::X] - bbox.min()[NR::X];
+ double height = bbox.max()[NR::Y] - bbox.min()[NR::Y];
+ NR::Point center = bbox.midpoint();
+
+ if (!_units_skew.isAbsolute()) { // percentage
+ double skewX = _scalar_skew_horizontal.getValue("%");
+ double skewY = _scalar_skew_vertical.getValue("%");
+ sp_selection_skew_relative(selection, center, 0.01*skewX, 0.01*skewY);
+ } else if (_units_skew.isRadial()) { //deg or rad
+ double angleX = _scalar_skew_horizontal.getValue("rad");
+ double angleY = _scalar_skew_vertical.getValue("rad");
+ double skewX = tan(-angleX);
+ double skewY = tan(angleY);
+ sp_selection_skew_relative(selection, center, skewX, skewY);
+ } else { // absolute displacement
+ double skewX = _scalar_skew_horizontal.getValue("px");
+ double skewY = _scalar_skew_vertical.getValue("px");
+ sp_selection_skew_relative(selection, center, skewX/height, skewY/width);
+ }
+ }
+
+ sp_document_done(SP_DT_DOCUMENT(selection->desktop()));
+}
+
+
+void
+Transformation::applyPageTransform(Inkscape::Selection *selection)
+{
+ double a = _scalar_transform_a.getValue();
+ double b = _scalar_transform_b.getValue();
+ double c = _scalar_transform_c.getValue();
+ double d = _scalar_transform_d.getValue();
+ double e = _scalar_transform_e.getValue();
+ double f = _scalar_transform_f.getValue();
+
+ NR::Matrix displayed(a, b, c, d, e, f);
+
+ if (_check_replace_matrix.get_active()) {
+ for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
+ SPItem *item = SP_ITEM(l->data);
+ sp_item_set_item_transform(item, displayed);
+ }
+ } else {
+ sp_selection_apply_affine(selection, displayed); // post-multiply each object's transform
+ }
+
+ sp_document_done(SP_DT_DOCUMENT(selection->desktop()));
+}
+
+
+
+
+
+/*########################################################################
+# V A L U E - C H A N G E D C A L L B A C K S
+########################################################################*/
+
+void
+Transformation::onMoveValueChanged()
+{
+ set_response_sensitive(Gtk::RESPONSE_APPLY, true);
+}
+
+void
+Transformation::onMoveRelativeToggled()
+{
+ Inkscape::Selection *selection = _getSelection();
+
+ if (!selection || selection->isEmpty())
+ return;
+
+ double x = _scalar_move_horizontal.getValue("px");
+ double y = _scalar_move_vertical.getValue("px");
+
+ //g_message("onMoveRelativeToggled: %f, %f px\n", x, y);
+
+ NR::Rect bbox = selection->bounds();
+
+ if (_check_move_relative.get_active()) {
+ // From absolute to relative
+ _scalar_move_horizontal.setValue(x - bbox.min()[NR::X], "px");
+ _scalar_move_vertical.setValue( y - bbox.min()[NR::Y], "px");
+ } else {
+ // From relative to absolute
+ _scalar_move_horizontal.setValue(bbox.min()[NR::X] + x, "px");
+ _scalar_move_vertical.setValue( bbox.min()[NR::Y] + y, "px");
+ }
+
+
+ set_response_sensitive(Gtk::RESPONSE_APPLY, true);
+}
+
+void
+Transformation::onScaleXValueChanged()
+{
+ if (_scalar_scale_horizontal.setProgrammatically) {
+ _scalar_scale_horizontal.setProgrammatically = false;
+ return;
+ }
+
+ set_response_sensitive(Gtk::RESPONSE_APPLY, true);
+
+ if (_check_scale_proportional.get_active()) {
+ if (!_units_scale.isAbsolute()) { // percentage, just copy over
+ _scalar_scale_vertical.setValue(_scalar_scale_horizontal.getValue("%"));
+ } else {
+ double scaleXPercentage = _scalar_scale_horizontal.getAsPercentage();
+ _scalar_scale_vertical.setFromPercentage (scaleXPercentage);
+ }
+ }
+}
+
+void
+Transformation::onScaleYValueChanged()
+{
+ if (_scalar_scale_vertical.setProgrammatically) {
+ _scalar_scale_vertical.setProgrammatically = false;
+ return;
+ }
+
+ set_response_sensitive(Gtk::RESPONSE_APPLY, true);
+
+ if (_check_scale_proportional.get_active()) {
+ if (!_units_scale.isAbsolute()) { // percentage, just copy over
+ _scalar_scale_horizontal.setValue(_scalar_scale_vertical.getValue("%"));
+ } else {
+ double scaleYPercentage = _scalar_scale_vertical.getAsPercentage();
+ _scalar_scale_horizontal.setFromPercentage (scaleYPercentage);
+ }
+ }
+}
+
+void
+Transformation::onRotateValueChanged()
+{
+ set_response_sensitive(Gtk::RESPONSE_APPLY, true);
+}
+
+void
+Transformation::onSkewValueChanged()
+{
+ set_response_sensitive(Gtk::RESPONSE_APPLY, true);
+}
+
+void
+Transformation::onTransformValueChanged()
+{
+
+ /*
+ double a = _scalar_transform_a.getValue();
+ double b = _scalar_transform_b.getValue();
+ double c = _scalar_transform_c.getValue();
+ double d = _scalar_transform_d.getValue();
+ double e = _scalar_transform_e.getValue();
+ double f = _scalar_transform_f.getValue();
+
+ //g_message("onTransformValueChanged: (%f, %f, %f, %f, %f, %f)\n",
+ // a, b, c, d, e ,f);
+ */
+
+ set_response_sensitive(Gtk::RESPONSE_APPLY, true);
+}
+
+void
+Transformation::onReplaceMatrixToggled()
+{
+ Inkscape::Selection *selection = _getSelection();
+
+ if (!selection || selection->isEmpty())
+ return;
+
+ double a = _scalar_transform_a.getValue();
+ double b = _scalar_transform_b.getValue();
+ double c = _scalar_transform_c.getValue();
+ double d = _scalar_transform_d.getValue();
+ double e = _scalar_transform_e.getValue();
+ double f = _scalar_transform_f.getValue();
+
+ NR::Matrix displayed (a, b, c, d, e, f);
+ NR::Matrix current (SP_ITEM(selection->itemList()->data)->transform); // take from the first item in selection
+
+ NR::Matrix new_displayed;
+ if (_check_replace_matrix.get_active()) {
+ new_displayed = current;
+ } else {
+ new_displayed = current.inverse() * displayed;
+ }
+
+ _scalar_transform_a.setValue(new_displayed[0]);
+ _scalar_transform_b.setValue(new_displayed[1]);
+ _scalar_transform_c.setValue(new_displayed[2]);
+ _scalar_transform_d.setValue(new_displayed[3]);
+ _scalar_transform_e.setValue(new_displayed[4]);
+ _scalar_transform_f.setValue(new_displayed[5]);
+}
+
+void
+Transformation::onScaleProportionalToggled()
+{
+ onScaleXValueChanged();
+}
+
+
+void
+Transformation::onClear()
+{
+ int const page = _notebook.get_current_page();
+
+ switch (page) {
+ case PAGE_MOVE: {
+ Inkscape::Selection *selection = _getSelection();
+ if (!selection || selection->isEmpty() || _check_move_relative.get_active()) {
+ _scalar_move_horizontal.setValue(0);
+ _scalar_move_vertical.setValue(0);
+ } else {
+ NR::Rect bbox = selection->bounds();
+ _scalar_move_horizontal.setValue(bbox.min()[NR::X], "px");
+ _scalar_move_vertical.setValue(bbox.min()[NR::Y], "px");
+ }
+ break;
+ }
+ case PAGE_ROTATE: {
+ _scalar_rotate.setValue(0);
+ break;
+ }
+ case PAGE_SCALE: {
+ _scalar_scale_horizontal.setValue(0);
+ _scalar_scale_vertical.setValue(0);
+ break;
+ }
+ case PAGE_SKEW: {
+ _scalar_skew_horizontal.setValue(0);
+ _scalar_skew_vertical.setValue(0);
+ break;
+ }
+ case PAGE_TRANSFORM: {
+ _scalar_transform_a.setValue(1);
+ _scalar_transform_b.setValue(0);
+ _scalar_transform_c.setValue(0);
+ _scalar_transform_d.setValue(1);
+ _scalar_transform_e.setValue(0);
+ _scalar_transform_f.setValue(0);
+ break;
+ }
+ }
+}
+
+void
+Transformation::onApplySeparatelyToggled()
+{
+ prefs_set_int_attribute ("dialogs.transformation", "applyseparately", _check_apply_separately.get_active()? 1 : 0);
+}
+
+
+} // 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/transformation.h b/src/ui/dialog/transformation.h
new file mode 100644
index 000000000..68faeb45a
--- /dev/null
+++ b/src/ui/dialog/transformation.h
@@ -0,0 +1,239 @@
+/**
+ * \brief Object Transformation dialog
+ *
+ * Author:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_TRANSFORMATION_H
+#define INKSCAPE_UI_DIALOG_TRANSFORMATION_H
+
+
+
+#include <gtkmm/notebook.h>
+#include <glibmm/i18n.h>
+
+
+
+#include "dialog.h"
+#include "application/application.h"
+#include "ui/widget/notebook-page.h"
+#include "ui/widget/scalar-unit.h"
+#include "ui/widget/imageicon.h"
+#include "ui/widget/button.h"
+
+
+using namespace Inkscape::UI::Widget;
+
+
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+
+
+class Transformation : public Dialog
+{
+
+public:
+
+ /**
+ * Create a new transform
+ */
+ Transformation();
+
+ /**
+ * Cleanup
+ */
+ virtual ~Transformation();
+
+
+ /**
+ * Factory method. Create an instance of this class/interface
+ */
+ static Transformation *create()
+ { return new Transformation(); }
+
+
+ /**
+ * Show the Move panel
+ */
+ void setPageMove()
+ { present(PAGE_MOVE); }
+
+
+ /**
+ * Show the Scale panel
+ */
+ void setPageScale()
+ { present(PAGE_SCALE); }
+
+
+ /**
+ * Show the Rotate panel
+ */
+ void setPageRotate()
+ { present(PAGE_ROTATE); }
+
+ /**
+ * Show the Skew panel
+ */
+ void setPageSkew()
+ { present(PAGE_SKEW); }
+
+ /**
+ * Show the Transform panel
+ */
+ void setPageTransform()
+ { present(PAGE_TRANSFORM); }
+
+
+ int getCurrentPage()
+ { return _notebook.get_current_page(); }
+
+ typedef enum {
+ PAGE_MOVE, PAGE_SCALE, PAGE_ROTATE, PAGE_SKEW, PAGE_TRANSFORM, PAGE_QTY
+ } PageType;
+
+ void updateSelection(PageType page, Inkscape::Selection *selection);
+
+protected:
+
+ Gtk::Notebook _notebook;
+
+ NotebookPage _page_move;
+ NotebookPage _page_scale;
+ NotebookPage _page_rotate;
+ NotebookPage _page_skew;
+ NotebookPage _page_transform;
+
+ UnitMenu _units_move;
+ UnitMenu _units_scale;
+ UnitMenu _units_rotate;
+ UnitMenu _units_skew;
+
+ ScalarUnit _scalar_move_horizontal;
+ ScalarUnit _scalar_move_vertical;
+ ScalarUnit _scalar_scale_horizontal;
+ ScalarUnit _scalar_scale_vertical;
+ ScalarUnit _scalar_rotate;
+ ScalarUnit _scalar_skew_horizontal;
+ ScalarUnit _scalar_skew_vertical;
+
+ Scalar _scalar_transform_a;
+ Scalar _scalar_transform_b;
+ Scalar _scalar_transform_c;
+ Scalar _scalar_transform_d;
+ Scalar _scalar_transform_e;
+ Scalar _scalar_transform_f;
+
+ CheckButton _check_move_relative;
+ CheckButton _check_scale_proportional;
+ CheckButton _check_apply_separately;
+ CheckButton _check_replace_matrix;
+
+ /**
+ * Layout the GUI components, and prepare for use
+ */
+ void layoutPageMove();
+ void layoutPageScale();
+ void layoutPageRotate();
+ void layoutPageSkew();
+ void layoutPageTransform();
+
+ virtual void _apply();
+ void present(PageType page);
+
+ void onSelectionChanged(Inkscape::NSApplication::Application *inkscape,
+ Inkscape::Selection *selection);
+ void onSelectionModified(Inkscape::NSApplication::Application *inkscape,
+ Inkscape::Selection *selection,
+ int unsigned flags);
+ void onSwitchPage(GtkNotebookPage *page,
+ guint pagenum);
+
+ /**
+ * Callbacks for when a user changes values on the panels
+ */
+ void onMoveValueChanged();
+ void onMoveRelativeToggled();
+ void onScaleXValueChanged();
+ void onScaleYValueChanged();
+ void onRotateValueChanged();
+ void onSkewValueChanged();
+ void onTransformValueChanged();
+ void onReplaceMatrixToggled();
+ void onScaleProportionalToggled();
+
+ void onClear();
+
+ void onApplySeparatelyToggled();
+
+ /**
+ * Called when the selection is updated, to make
+ * the panel(s) show the new values.
+ * Editor---->dialog
+ */
+ void updatePageMove(Inkscape::Selection *);
+ void updatePageScale(Inkscape::Selection *);
+ void updatePageRotate(Inkscape::Selection *);
+ void updatePageSkew(Inkscape::Selection *);
+ void updatePageTransform(Inkscape::Selection *);
+
+ /**
+ * Called when the Apply button is pushed
+ * Dialog---->editor
+ */
+ void applyPageMove(Inkscape::Selection *);
+ void applyPageScale(Inkscape::Selection *);
+ void applyPageRotate(Inkscape::Selection *);
+ void applyPageSkew(Inkscape::Selection *);
+ void applyPageTransform(Inkscape::Selection *);
+
+private:
+
+ /**
+ * Copy constructor
+ */
+ Transformation(Transformation const &d);
+
+ /**
+ * Assignment operator
+ */
+ Transformation operator=(Transformation const &d);
+
+ Gtk::Button *applyButton;
+ Gtk::Button *resetButton;
+ Gtk::Button *cancelButton;
+};
+
+
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+
+
+#endif //INKSCAPE_UI_DIALOG_TRANSFORMATION_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/tree-editor.cpp b/src/ui/dialog/tree-editor.cpp
new file mode 100644
index 000000000..4d982d3e3
--- /dev/null
+++ b/src/ui/dialog/tree-editor.cpp
@@ -0,0 +1,53 @@
+/*
+ * \brief Tree Editor - Abstract base class for dialogs that allow
+ * editing properties of tree-organized data.
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "tree-editor.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+TreeEditor::TreeEditor()
+ : Dialog ("dialogs.treeeditor", SP_VERB_NONE /*FIXME*/)
+{
+ get_vbox()->pack_start(_hbox);
+
+ _hbox.add(_leftWin);
+ _leftWin.add(_leftTree);
+
+ // Only show the scrollbars when they are necessary
+ _leftWin.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+
+ // TODO: Create the tree model
+
+ show_all_children();
+}
+
+} // 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/tree-editor.h b/src/ui/dialog/tree-editor.h
new file mode 100644
index 000000000..9355e04d7
--- /dev/null
+++ b/src/ui/dialog/tree-editor.h
@@ -0,0 +1,61 @@
+/*
+ * \brief Tree Editor - Abstract base class for dialogs that allow
+ * editing properties of tree-organized data.
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_DIALOG_TREE_EDITOR_H
+#define INKSCAPE_DIALOG_TREE_EDITOR_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/treeview.h>
+#include <glibmm/i18n.h>
+
+#include "dialog.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class TreeEditor : public Dialog {
+public:
+ TreeEditor();
+ virtual ~TreeEditor();
+
+protected:
+
+ Gtk::HBox _hbox;
+ Gtk::ScrolledWindow _leftWin;
+ Gtk::TreeView _leftTree;
+
+ // TODO: Add the tree model
+ // Glib::RefPtr<ExampleTreeModel> _refTreeModel;
+
+private:
+ TreeEditor(TreeEditor const &d);
+ TreeEditor& operator=(TreeEditor const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_TREE_EDITOR_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/whiteboard-connect.cpp b/src/ui/dialog/whiteboard-connect.cpp
new file mode 100644
index 000000000..173e9a794
--- /dev/null
+++ b/src/ui/dialog/whiteboard-connect.cpp
@@ -0,0 +1,192 @@
+/**
+ * Whiteboard connection establishment dialog
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ * Jason Segal, Jonas Collaros, Stephen Montgomery, Brandi Soggs, Matthew Weinstock (original C/Gtk version)
+ *
+ * Copyright (c) 2004-2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm/i18n.h>
+#include <gtk/gtkdialog.h>
+#include <gtkmm/entry.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/table.h>
+
+#include "inkscape.h"
+#include "desktop.h"
+#include "message-stack.h"
+#include "prefs-utils.h"
+
+#include "jabber_whiteboard/session-manager.h"
+
+#include "message-context.h"
+#include "ui/dialog/whiteboard-connect.h"
+
+#include "util/ucompose.hpp"
+
+namespace Inkscape {
+
+namespace UI {
+
+namespace Dialog {
+
+WhiteboardConnectDialog*
+WhiteboardConnectDialog::create()
+{
+ return new WhiteboardConnectDialogImpl();
+}
+
+WhiteboardConnectDialogImpl::WhiteboardConnectDialogImpl() :
+ _layout(4, 4, false), _usessl(_("_Use SSL"), true)
+{
+ this->setSessionManager();
+ this->_construct();
+ this->get_vbox()->show_all_children();
+}
+
+WhiteboardConnectDialogImpl::~WhiteboardConnectDialogImpl()
+{
+}
+
+void
+WhiteboardConnectDialogImpl::setSessionManager()
+{
+ this->_desktop = SP_ACTIVE_DESKTOP;
+ this->_sm = SP_ACTIVE_DESKTOP->whiteboard_session_manager();
+
+}
+
+void
+WhiteboardConnectDialogImpl::_construct()
+{
+ Gtk::VBox* main = this->get_vbox();
+
+ // Construct dialog interface
+ this->_labels[0].set_markup_with_mnemonic(_("_Server:"));
+ this->_labels[1].set_markup_with_mnemonic(_("_Username:"));
+ this->_labels[2].set_markup_with_mnemonic(_("_Password:"));
+ this->_labels[3].set_markup_with_mnemonic(_("P_ort:"));
+
+ this->_labels[0].set_mnemonic_widget(this->_server);
+ this->_labels[1].set_mnemonic_widget(this->_username);
+ this->_labels[2].set_mnemonic_widget(this->_password);
+ this->_labels[3].set_mnemonic_widget(this->_port);
+
+ this->_port.set_text("5222");
+
+ this->_layout.attach(this->_labels[0], 0, 1, 0, 1);
+ this->_layout.attach(this->_labels[3], 2, 3, 0, 1);
+ this->_layout.attach(this->_labels[1], 0, 1, 1, 2);
+ this->_layout.attach(this->_labels[2], 0, 1, 2, 3);
+
+ this->_layout.attach(this->_server, 1, 2, 0, 1);
+ this->_layout.attach(this->_port, 3, 4, 0, 1);
+ this->_layout.attach(this->_username, 1, 4, 1, 2);
+ this->_layout.attach(this->_password, 1, 4, 2, 3);
+
+ this->_layout.attach(this->_usessl, 1, 4, 3, 4);
+
+ this->_layout.set_col_spacings(1);
+ this->_layout.set_row_spacings(1);
+
+ this->_password.set_visibility(false);
+ this->_password.set_invisible_char('*');
+
+ // Buttons
+ this->_ok.set_label(_("Connect"));
+ this->_cancel.set_label(_("Cancel"));
+ this->_ok.signal_clicked().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &WhiteboardConnectDialogImpl::_respCallback), GTK_RESPONSE_OK));
+ this->_cancel.signal_clicked().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &WhiteboardConnectDialogImpl::_respCallback), GTK_RESPONSE_CANCEL));
+ this->_usessl.signal_clicked().connect(sigc::mem_fun(*this, &WhiteboardConnectDialogImpl::_useSSLClickedCallback));
+
+ this->_buttons.pack_start(this->_cancel, true, true, 0);
+ this->_buttons.pack_end(this->_ok, true, true, 0);
+
+ // Pack widgets into main vbox
+ main->pack_start(this->_layout);
+ main->pack_end(this->_buttons);
+}
+
+void
+WhiteboardConnectDialogImpl::_respCallback(int resp)
+{
+ if (resp == GTK_RESPONSE_OK) {
+ Glib::ustring server, port, username, password;
+ bool usessl;
+
+ server = this->_server.get_text();
+ port = this->_port.get_text();
+ username = this->_username.get_text();
+ password = this->_password.get_text();
+ usessl = this->_usessl.get_active();
+
+ Glib::ustring msg = String::ucompose(_("Establishing connection to Jabber server <b>%1</b> as user <b>%2</b>"), server, username);
+ this->_desktop->messageStack()->flash(INFORMATION_MESSAGE, msg.data());
+
+ switch (this->_sm->connectToServer(server, port, username, password, usessl)) {
+ case FAILED_TO_CONNECT:
+ msg = String::ucompose(_("Failed to establish connection to Jabber server <b>%1</b>"), server);
+ this->_desktop->messageStack()->flash(WARNING_MESSAGE, msg.data());
+ this->_sm->connectionError(msg);
+ break;
+ case INVALID_AUTH:
+ msg = String::ucompose(_("Authentication failed on Jabber server <b>%1</b> as <b>%2</b>"), server, username);
+ this->_desktop->messageStack()->flash(WARNING_MESSAGE, msg.data());
+ this->_sm->connectionError(msg);
+ break;
+ case SSL_INITIALIZATION_ERROR:
+ msg = String::ucompose(_("SSL initialization failed when connecting to Jabber server <b>%1</b>"), server);
+ this->_desktop->messageStack()->flash(WARNING_MESSAGE, msg.data());
+ this->_sm->connectionError(msg);
+ break;
+
+ case CONNECT_SUCCESS:
+ msg = String::ucompose(_("Connected to Jabber server <b>%1</b> as <b>%2</b>"), server, username);
+ this->_desktop->messageStack()->flash(INFORMATION_MESSAGE, msg.data());
+
+ // Save preferences
+ prefs_set_string_attribute(this->_prefs_path, "server", this->_server.get_text().c_str());
+ break;
+ default:
+ break;
+ }
+ }
+
+ this->_password.set_text("");
+ this->hide();
+}
+
+void
+WhiteboardConnectDialogImpl::_useSSLClickedCallback()
+{
+ if (this->_usessl.get_active()) {
+ this->_port.set_text("5223");
+
+ // String::ucompose seems to format numbers according to locale; unfortunately,
+ // I'm not yet sure how to turn that off
+ //this->_port.set_text(String::ucompose("%1", LM_CONNECTION_DEFAULT_PORT_SSL));
+ } else {
+ this->_port.set_text("5222");
+ }
+}
+
+}
+
+}
+
+}
+
+/*
+ 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/whiteboard-connect.h b/src/ui/dialog/whiteboard-connect.h
new file mode 100644
index 000000000..3eb86b540
--- /dev/null
+++ b/src/ui/dialog/whiteboard-connect.h
@@ -0,0 +1,88 @@
+/**
+ * Whiteboard connection establishment dialog
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ * Jason Segal, Jonas Collaros, Stephen Montgomery, Brandi Soggs, Matthew Weinstock (original C/Gtk version)
+ *
+ * Copyright (c) 2004-2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef __WHITEBOARD_CONNECT_DIALOG_H__
+#define __WHITEBOARD_CONNECT_DIALOG_H__
+
+#include "verbs.h"
+#include "dialog.h"
+
+struct SPDesktop;
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+class SessionManager;
+
+}
+
+namespace UI {
+
+namespace Dialog {
+
+class WhiteboardConnectDialog : public Dialog {
+public:
+ WhiteboardConnectDialog() : Dialog("dialogs.whiteboard_connect", SP_VERB_DIALOG_WHITEBOARD_CONNECT)
+ {
+
+ }
+
+ static WhiteboardConnectDialog* create();
+
+ virtual ~WhiteboardConnectDialog()
+ {
+
+ }
+};
+
+class WhiteboardConnectDialogImpl : public WhiteboardConnectDialog {
+public:
+ WhiteboardConnectDialogImpl();
+ ~WhiteboardConnectDialogImpl();
+ void present();
+ void setSessionManager();
+
+private:
+ // GTK+ widgets
+ Gtk::Table _layout;
+ Gtk::HBox _buttons;
+
+ Gtk::Entry _server;
+ Gtk::Entry _username;
+ Gtk::Entry _password;
+ Gtk::Entry _port;
+
+ Gtk::Label _labels[4];
+
+ Gtk::CheckButton _usessl;
+
+ Gtk::Button _ok, _cancel;
+
+ // Construction and callbacks
+ void _construct();
+ void _respCallback(int resp);
+ void _useSSLClickedCallback();
+
+ // SessionManager and SPDesktop pointers
+ ::SPDesktop* _desktop;
+ Whiteboard::SessionManager* _sm;
+};
+
+
+}
+
+}
+
+}
+
+#endif
diff --git a/src/ui/dialog/whiteboard-sharewithchat.cpp b/src/ui/dialog/whiteboard-sharewithchat.cpp
new file mode 100644
index 000000000..4c86b0dfa
--- /dev/null
+++ b/src/ui/dialog/whiteboard-sharewithchat.cpp
@@ -0,0 +1,147 @@
+/**
+ * Whiteboard share with chatroom dialog
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ * Jason Segal, Jonas Collaros, Stephen Montgomery, Brandi Soggs, Matthew Weinstock (original C/Gtk version)
+ *
+ * Copyright (c) 2004-2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm/i18n.h>
+
+#include <sigc++/sigc++.h>
+#include <gtk/gtkdialog.h>
+
+#include "message-stack.h"
+#include "message-context.h"
+#include "inkscape.h"
+#include "desktop.h"
+
+#include "jabber_whiteboard/typedefs.h"
+#include "jabber_whiteboard/session-manager.h"
+#include "jabber_whiteboard/buddy-list-manager.h"
+
+#include "jabber_whiteboard/session-file-selector.h"
+
+#include "ui/dialog/whiteboard-sharewithchat.h"
+
+#include "util/ucompose.hpp"
+
+namespace Inkscape {
+
+namespace UI {
+
+namespace Dialog {
+
+WhiteboardShareWithChatroomDialog*
+WhiteboardShareWithChatroomDialog::create()
+{
+ return new WhiteboardShareWithChatroomDialogImpl();
+}
+
+WhiteboardShareWithChatroomDialogImpl::WhiteboardShareWithChatroomDialogImpl() :
+ _layout(4, 2, false)
+{
+ this->setSessionManager();
+ this->_construct();
+ this->get_vbox()->show_all_children();
+}
+
+WhiteboardShareWithChatroomDialogImpl::~WhiteboardShareWithChatroomDialogImpl()
+{
+
+}
+
+void
+WhiteboardShareWithChatroomDialogImpl::setSessionManager()
+{
+ this->_desktop = SP_ACTIVE_DESKTOP;
+ this->_sm = SP_ACTIVE_DESKTOP->whiteboard_session_manager();
+
+}
+
+
+void
+WhiteboardShareWithChatroomDialogImpl::_construct()
+{
+ Gtk::VBox* main = this->get_vbox();
+
+ // Construct labels
+ this->_labels[0].set_markup_with_mnemonic(_("Chatroom _name:"));
+ this->_labels[1].set_markup_with_mnemonic(_("Chatroom _server:"));
+ this->_labels[2].set_markup_with_mnemonic(_("Chatroom _password:"));
+ this->_labels[3].set_markup_with_mnemonic(_("Chatroom _handle:"));
+
+ this->_labels[0].set_mnemonic_widget(this->_roomname);
+ this->_labels[1].set_mnemonic_widget(this->_confserver);
+ this->_labels[2].set_mnemonic_widget(this->_roompass);
+ this->_labels[3].set_mnemonic_widget(this->_handle);
+
+ // Pack table
+ this->_layout.attach(this->_labels[0], 0, 1, 0, 1);
+ this->_layout.attach(this->_labels[1], 0, 1, 1, 2);
+ this->_layout.attach(this->_labels[2], 0, 1, 2, 3);
+ this->_layout.attach(this->_labels[3], 0, 1, 3, 4);
+
+ this->_layout.attach(this->_roomname, 1, 2, 0, 1);
+ this->_layout.attach(this->_confserver, 1, 2, 1, 2);
+ this->_layout.attach(this->_roompass, 1, 2, 2, 3);
+ this->_layout.attach(this->_handle, 1, 2, 3, 4);
+
+ // Button setup and callback registration
+ this->_share.set_label(_("Connect to chatroom"));
+ this->_cancel.set_label(_("Cancel"));
+ this->_share.set_use_underline(true);
+ this->_cancel.set_use_underline(true);
+
+ this->_share.signal_clicked().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &WhiteboardShareWithChatroomDialogImpl::_respCallback), WhiteboardShareWithChatroomDialogImpl::SHARE));
+ this->_cancel.signal_clicked().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &WhiteboardShareWithChatroomDialogImpl::_respCallback), WhiteboardShareWithChatroomDialogImpl::CANCEL));
+
+ // Pack buttons
+ this->_buttonsbox.pack_start(this->_cancel);
+ this->_buttonsbox.pack_start(this->_share);
+
+ // Set default values
+ Glib::ustring jid = lm_connection_get_jid(this->_sm->session_data->connection);
+ Glib::ustring nick = jid.substr(0, jid.find_first_of('@'));
+ this->_handle.set_text(nick);
+ this->_roomname.set_text("inkboard");
+
+ // Pack into main box
+ main->pack_start(this->_layout);
+ main->pack_end(this->_buttonsbox);
+}
+
+void
+WhiteboardShareWithChatroomDialogImpl::_respCallback(int resp)
+{
+ switch (resp) {
+ case SHARE:
+ {
+ Glib::ustring chatroom, server, handle, password;
+ chatroom = this->_roomname.get_text();
+ server = this->_confserver.get_text();
+ password = this->_roompass.get_text();
+ handle = this->_handle.get_text();
+
+ Glib::ustring msg = String::ucompose(_("Synchronizing with chatroom <b>%1@%2</b> using the handle <b>%3</b>"), chatroom, server, handle);
+
+ this->_desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, msg.data());
+
+ this->_desktop->whiteboard_session_manager()->sendRequestToChatroom(server, chatroom, handle, password);
+ }
+ case CANCEL:
+ default:
+ this->hide();
+ break;
+ }
+}
+
+}
+
+}
+
+}
diff --git a/src/ui/dialog/whiteboard-sharewithchat.h b/src/ui/dialog/whiteboard-sharewithchat.h
new file mode 100644
index 000000000..898f8da26
--- /dev/null
+++ b/src/ui/dialog/whiteboard-sharewithchat.h
@@ -0,0 +1,93 @@
+/**
+ * Whiteboard share with chatroom dialog
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ * Jason Segal, Jonas Collaros, Stephen Montgomery, Brandi Soggs, Matthew Weinstock (original C/Gtk version)
+ *
+ * Copyright (c) 2004-2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef __WHITEBOARD_SHAREWITHCHAT_DIALOG_H__
+#define __WHITEBOARD_SHAREWITHCHAT_DIALOG_H__
+
+#include "verbs.h"
+#include "dialog.h"
+
+#include <gtkmm/table.h>
+#include "jabber_whiteboard/session-file-selector.h"
+
+struct SPDesktop;
+
+namespace Inkscape {
+
+namespace Whiteboard {
+
+class SessionManager;
+
+}
+
+namespace UI {
+
+namespace Dialog {
+
+class WhiteboardShareWithChatroomDialog : public Dialog {
+public:
+ WhiteboardShareWithChatroomDialog() : Dialog("dialogs.whiteboard_sharewithuser", SP_VERB_DIALOG_WHITEBOARD_SHAREWITHUSER)
+ {
+
+ }
+
+ static WhiteboardShareWithChatroomDialog* create();
+
+ virtual ~WhiteboardShareWithChatroomDialog()
+ {
+
+ }
+};
+
+
+class WhiteboardShareWithChatroomDialogImpl : public WhiteboardShareWithChatroomDialog {
+public:
+ WhiteboardShareWithChatroomDialogImpl();
+ ~WhiteboardShareWithChatroomDialogImpl();
+ void setSessionManager();
+
+private:
+ // Response flags
+ static unsigned int const SHARE = 0;
+ static unsigned int const CANCEL = 2;
+
+ // GTK+ widgets
+ Gtk::Table _layout;
+
+ Gtk::HBox _buttonsbox;
+ Whiteboard::SessionFileSelectorBox _sfsbox;
+
+ Gtk::Entry _roomname;
+ Gtk::Entry _roompass;
+ Gtk::Entry _confserver;
+ Gtk::Entry _handle;
+
+ Gtk::Label _labels[4];
+
+ Gtk::Button _share, _cancel;
+
+ // Construction and callback
+ void _construct();
+ void _respCallback(int resp);
+
+ // SessionManager and SPDesktop pointers
+ ::SPDesktop* _desktop;
+ Whiteboard::SessionManager* _sm;
+};
+
+}
+
+}
+
+}
+
+#endif
diff --git a/src/ui/dialog/whiteboard-sharewithuser.cpp b/src/ui/dialog/whiteboard-sharewithuser.cpp
new file mode 100644
index 000000000..13dc61a5e
--- /dev/null
+++ b/src/ui/dialog/whiteboard-sharewithuser.cpp
@@ -0,0 +1,214 @@
+/**
+ * Whiteboard share with user dialog
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ * Jason Segal, Jonas Collaros, Stephen Montgomery, Brandi Soggs, Matthew Weinstock (original C/Gtk version)
+ *
+ * Copyright (c) 2004-2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm/i18n.h>
+
+#include <sigc++/sigc++.h>
+#include <gtk/gtkdialog.h>
+
+#include "message-stack.h"
+#include "message-context.h"
+#include "inkscape.h"
+#include "desktop.h"
+
+#include "jabber_whiteboard/typedefs.h"
+#include "jabber_whiteboard/session-manager.h"
+#include "jabber_whiteboard/buddy-list-manager.h"
+
+#include "jabber_whiteboard/session-file-selector.h"
+
+#include "ui/dialog/whiteboard-sharewithuser.h"
+
+#include "util/ucompose.hpp"
+
+namespace Inkscape {
+
+namespace UI {
+
+namespace Dialog {
+
+WhiteboardShareWithUserDialog*
+WhiteboardShareWithUserDialog::create()
+{
+ return new WhiteboardShareWithUserDialogImpl();
+}
+
+WhiteboardShareWithUserDialogImpl::WhiteboardShareWithUserDialogImpl()
+{
+ this->setSessionManager();
+ this->_construct();
+ this->get_vbox()->show_all_children();
+
+ this->_sm->session_data->buddyList.addInsertListener(sigc::mem_fun(this, &WhiteboardShareWithUserDialogImpl::_insertBuddy));
+ this->_sm->session_data->buddyList.addEraseListener(sigc::mem_fun(this, &WhiteboardShareWithUserDialogImpl::_eraseBuddy));
+
+}
+
+WhiteboardShareWithUserDialogImpl::~WhiteboardShareWithUserDialogImpl()
+{
+
+}
+
+void
+WhiteboardShareWithUserDialogImpl::setSessionManager()
+{
+ this->_desktop = SP_ACTIVE_DESKTOP;
+ this->_sm = SP_ACTIVE_DESKTOP->whiteboard_session_manager();
+
+}
+
+
+void
+WhiteboardShareWithUserDialogImpl::_construct()
+{
+ Gtk::VBox* main = this->get_vbox();
+
+ // Construct dialog interface
+ this->_labels[0].set_markup_with_mnemonic(_("_User's Jabber ID:"));
+ this->_labels[0].set_mnemonic_widget(this->_jid);
+
+ // Buttons
+ this->_share.set_label(_("_Invite user"));
+ this->_cancel.set_label(_("_Cancel"));
+ this->_share.set_use_underline(true);
+ this->_cancel.set_use_underline(true);
+
+ // Button callbacks
+ this->_share.signal_clicked().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &WhiteboardShareWithUserDialogImpl::_respCallback), SHARE));
+ this->_cancel.signal_clicked().connect(sigc::bind< 0 >(sigc::mem_fun(*this, &WhiteboardShareWithUserDialogImpl::_respCallback), CANCEL));
+
+ // Construct ListStore for buddy list information
+ this->_buddylistdata = Gtk::ListStore::create(this->_blm);
+ this->_buddylist.set_model(this->_buddylistdata);
+ this->_buddylist.append_column(_("Buddy List"), this->_blm.jid);
+
+ // Fill buddy list
+ this->_fillBuddyList();
+
+ // Buddy list onclick callback
+ this->_buddylist.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &WhiteboardShareWithUserDialogImpl::_listCallback));
+
+ // Pack widgets into boxes
+ this->_listwindow.add(this->_buddylist);
+ this->_listwindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ this->_buddylistbox.pack_start(this->_listwindow);
+
+ this->_connecttojidbox.pack_start(this->_labels[0]);
+ this->_connecttojidbox.pack_end(this->_jid);
+
+ this->_buttons.pack_start(this->_cancel);
+ this->_buttons.pack_end(this->_share);
+
+ // Pack boxes into main box
+ main->pack_start(this->_buddylistbox);
+ main->pack_start(this->_connecttojidbox);
+ main->pack_start(this->_sfsbox);
+ main->pack_end(this->_buttons);
+}
+
+
+void
+WhiteboardShareWithUserDialogImpl::_fillBuddyList()
+{
+ Whiteboard::BuddyList& bl = this->_sm->session_data->buddyList.getList();
+
+ for(Whiteboard::BuddyList::iterator i = bl.begin(); i != bl.end(); i++) {
+ this->_insertBuddy(*i);
+ }
+// std::for_each(bl.begin(), bl.end(), std::mem_fun(&WhiteboardShareWithUserDialogImpl::_insertBuddy));
+}
+
+void
+WhiteboardShareWithUserDialogImpl::_insertBuddy(std::string const& jid)
+{
+ // FIXME: need a better way to avoid inserting duplicate rows in the case
+ // of duplicate Jabber presence messages
+ typedef Gtk::TreeModel::Children type_children;
+ type_children children = this->_buddylistdata->children();
+ for(type_children::iterator i = children.begin(); i != children.end(); i++) {
+ if ((*i).get_value(this->_blm.jid) == jid) {
+ return;
+ }
+ }
+
+ Gtk::TreeModel::Row row = *(this->_buddylistdata->append());
+ row[this->_blm.jid] = jid;
+}
+
+void
+WhiteboardShareWithUserDialogImpl::_eraseBuddy(std::string const& jid)
+{
+ // FIXME: Doesn't gtkmm provide a better way to erase rows from a ListStore?
+ typedef Gtk::TreeModel::Children type_children;
+ type_children children = this->_buddylistdata->children();
+ for(type_children::iterator i = children.begin(); i != children.end(); i++) {
+ if ((*i).get_value(this->_blm.jid) == jid) {
+ this->_buddylistdata->erase(i);
+ return;
+ }
+ }
+}
+
+void
+WhiteboardShareWithUserDialogImpl::_respCallback(int resp)
+{
+ switch (resp) {
+ case SHARE:
+ {
+ Glib::ustring jid = this->_jid.get_text();
+ Glib::ustring msg = String::ucompose(_("Sending whiteboard invitation to <b>%1</b>"), jid);
+ this->_sm->desktop()->messageStack()->flash(Inkscape::NORMAL_MESSAGE, msg.data());
+ if (this->_sfsbox.isSelected()) {
+ this->_sm->session_data->sessionFile = this->_sfsbox.getFilename();
+ } else {
+ this->_sm->session_data->sessionFile.clear();
+ }
+ this->_sm->sendRequestToUser(jid);
+ this->hide();
+ break;
+ }
+
+ case CANCEL:
+ this->hide();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+WhiteboardShareWithUserDialogImpl::_listCallback()
+{
+ Glib::RefPtr< Gtk::TreeSelection > sel = this->_buddylist.get_selection();
+
+ typedef Gtk::TreeModel::Children type_children;
+ type_children::iterator row = sel->get_selected();
+ this->_jid.set_text((*row).get_value(this->_blm.jid));
+}
+
+}
+
+}
+
+}
+
+/*
+ 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/whiteboard-sharewithuser.h b/src/ui/dialog/whiteboard-sharewithuser.h
new file mode 100644
index 000000000..ad0870707
--- /dev/null
+++ b/src/ui/dialog/whiteboard-sharewithuser.h
@@ -0,0 +1,110 @@
+/**
+ * Whiteboard share with user dialog
+ *
+ * Authors:
+ * David Yip <yipdw@rose-hulman.edu>
+ * Jason Segal, Jonas Collaros, Stephen Montgomery, Brandi Soggs, Matthew Weinstock (original C/Gtk version)
+ *
+ * Copyright (c) 2004-2005 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef __WHITEBOARD_SHAREWITHUSER_DIALOG_H__
+#define __WHITEBOARD_SHAREWITHUSER_DIALOG_H__
+
+#include <gtkmm/liststore.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/scrolledwindow.h>
+
+#include "verbs.h"
+#include "ui/dialog/dialog.h"
+#include "jabber_whiteboard/session-file-selector.h"
+
+
+struct SPDesktop;
+
+namespace Inkscape {
+ namespace Whiteboard {
+ class SessionManager;
+ }
+ namespace UI {
+ namespace Dialog {
+
+class WhiteboardShareWithUserDialog : public Dialog {
+public:
+ WhiteboardShareWithUserDialog() : Dialog("dialogs.whiteboard_sharewithuser", SP_VERB_DIALOG_WHITEBOARD_SHAREWITHUSER)
+ {
+
+ }
+
+ static WhiteboardShareWithUserDialog* create();
+
+ virtual ~WhiteboardShareWithUserDialog()
+ {
+
+ }
+};
+
+class WhiteboardShareWithUserDialogImpl : public WhiteboardShareWithUserDialog {
+public:
+ WhiteboardShareWithUserDialogImpl();
+ ~WhiteboardShareWithUserDialogImpl();
+ void setSessionManager();
+
+private:
+ // Response flags
+ static unsigned int const SHARE = 0;
+ static unsigned int const CANCEL = 2;
+
+ // GTK+ widgets
+ Gtk::HBox _connecttojidbox;
+ Gtk::HBox _buddylistbox;
+ Gtk::HBox _buttons;
+
+ Whiteboard::SessionFileSelectorBox _sfsbox;
+
+ Gtk::Entry _jid;
+
+ // more or less shamelessly stolen from gtkmm tutorial book
+ Glib::RefPtr< Gtk::ListStore > _buddylistdata;
+ Gtk::TreeView _buddylist;
+ class BuddyListModel : public Gtk::TreeModel::ColumnRecord {
+ public:
+ BuddyListModel()
+ {
+ add(jid);
+ }
+
+ Gtk::TreeModelColumn< std::string > jid;
+ };
+ BuddyListModel _blm;
+
+ Gtk::Label _labels[2];
+ Gtk::ScrolledWindow _listwindow;
+
+ Gtk::Button _share, _cancel;
+
+ // Construction and callback
+ void _construct();
+ void _respCallback(int resp);
+ void _listCallback();
+
+ // Buddy list management
+ void _fillBuddyList();
+ void _insertBuddy(std::string const& jid);
+ void _eraseBuddy(std::string const& jid);
+
+ // SessionManager and SPDesktop pointers
+ ::SPDesktop* _desktop;
+ Whiteboard::SessionManager* _sm;
+};
+
+
+}
+
+}
+
+}
+
+#endif
diff --git a/src/ui/dialog/xml-editor.cpp b/src/ui/dialog/xml-editor.cpp
new file mode 100644
index 000000000..b8abf8bfd
--- /dev/null
+++ b/src/ui/dialog/xml-editor.cpp
@@ -0,0 +1,48 @@
+/**
+ * \brief XML Editor dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "xml-editor.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+XmlEditor::XmlEditor()
+ : Dialog ("dialogs.xml", SP_VERB_DIALOG_XML_EDITOR)
+{
+ // TODO: Insert widgets
+
+ show_all_children();
+}
+
+XmlEditor::~XmlEditor()
+{
+}
+
+} // 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/xml-editor.h b/src/ui/dialog/xml-editor.h
new file mode 100644
index 000000000..b494ade1f
--- /dev/null
+++ b/src/ui/dialog/xml-editor.h
@@ -0,0 +1,52 @@
+/**
+ * \brief XML Editor dialog
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004, 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_DIALOG_XML_EDITOR_H
+#define INKSCAPE_DIALOG_XML_EDITOR_H
+
+#include "dialog.h"
+
+#include <glibmm/i18n.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class XmlEditor : public Dialog {
+public:
+ XmlEditor();
+ virtual ~XmlEditor();
+
+ static XmlEditor *create() { return new XmlEditor(); }
+
+protected:
+
+private:
+ XmlEditor(XmlEditor const &d);
+ XmlEditor& operator=(XmlEditor const &d);
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_DIALOG_XML_EDITOR_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/icons.cpp b/src/ui/icons.cpp
new file mode 100644
index 000000000..aa8c5d53c
--- /dev/null
+++ b/src/ui/icons.cpp
@@ -0,0 +1,696 @@
+/**
+ * \brief Stock icons for Inkscape-specific menu items and buttons.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtkmm/iconfactory.h>
+#include <gtkmm/stock.h>
+
+#include "stock.h"
+#include "path-prefix.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Icons {
+
+static Glib::ustring const get_icon_path(char const *utf8_basename);
+
+void
+init()
+{
+ Glib::RefPtr<Gtk::IconFactory> icons = Gtk::IconFactory::create();
+ Gtk::IconSource src;
+
+ // repeat, for every Inkscape stock.h entry that needs an icon.
+ //Gtk::IconSet ;
+ //src.set_icon_name("");
+ //src.set_filename(get_icon_path(".svg"));
+ //.add_source(src);
+ //icons->add(Stock::, );
+
+ // File menu
+ // Open Recent
+ Gtk::IconSet _open_recent;
+ src.set_icon_name("OpenRecent");
+ src.set_filename(get_icon_path("open-recent.svg"));
+ _open_recent.add_source(src);
+ icons->add(Stock::OPEN_RECENT, _open_recent);
+ // Import
+ Gtk::IconSet _import;
+ src.set_icon_name("Import");
+ src.set_filename(get_icon_path("import.svg"));
+ _import.add_source(src);
+ icons->add(Stock::IMPORT, _import);
+ // Export
+ Gtk::IconSet _export;
+ src.set_icon_name("Export");
+ src.set_filename(get_icon_path("export.svg"));
+ _export.add_source(src);
+ icons->add(Stock::EXPORT, _export);
+ // Vacuum Defs
+ Gtk::IconSet _vacuum_defs;
+ src.set_icon_name("VacuumDefs");
+ src.set_filename(get_icon_path("vacuum-defs.svg"));
+ _vacuum_defs.add_source(src);
+ icons->add(Stock::VACUUM_DEFS, _vacuum_defs);
+
+ // Edit menu
+ // Paste In Place
+ Gtk::IconSet _paste_in_place;
+ src.set_icon_name("PasteInPlace");
+ src.set_filename(get_icon_path("paste-in-place.svg"));
+ _paste_in_place.add_source(src);
+ icons->add(Stock::PASTE_IN_PLACE, _paste_in_place);
+ // Paste Style
+ Gtk::IconSet _paste_style;
+ src.set_icon_name("PasteStyle");
+ src.set_filename(get_icon_path("paste-style.svg"));
+ _paste_style.add_source(src);
+ icons->add(Stock::PASTE_STYLE, _paste_style);
+ // Duplicate
+ Gtk::IconSet _duplicate;
+ src.set_icon_name("Duplicate");
+ src.set_filename(get_icon_path("duplicate.svg"));
+ _duplicate.add_source(src);
+ icons->add(Stock::DUPLICATE, _duplicate);
+ // Clone
+ Gtk::IconSet _clone;
+ src.set_icon_name("Clone");
+ src.set_filename(get_icon_path("clone.svg"));
+ _clone.add_source(src);
+ icons->add(Stock::CLONE, _clone);
+ // Unlink Clone
+ Gtk::IconSet _clone_unlink;
+ src.set_icon_name("CloneUnlink");
+ src.set_filename(get_icon_path("clone-unlink.svg"));
+ _clone_unlink.add_source(src);
+ icons->add(Stock::CLONE_UNLINK, _clone_unlink);
+ // Make Bitmap
+ Gtk::IconSet _make_bitmap;
+ src.set_icon_name("MakeBitmap");
+ src.set_filename(get_icon_path("make-bitmap.svg"));
+ _make_bitmap.add_source(src);
+ icons->add(Stock::MAKE_BITMAP, _make_bitmap);
+ // Select All
+ Gtk::IconSet _select_all;
+ src.set_icon_name("SelectAll");
+ src.set_filename(get_icon_path("select-all.svg"));
+ _select_all.add_source(src);
+ icons->add(Stock::SELECT_ALL, _select_all);
+ // XML Editor
+ Gtk::IconSet _xml_editor;
+ src.set_icon_name("XmlEditor");
+ src.set_filename(get_icon_path("xml-editor.svg"));
+ _xml_editor.add_source(src);
+ icons->add(Stock::XML_EDITOR, _xml_editor);
+
+ // View menu
+ // Zoom
+ Gtk::IconSet _zoom;
+ src.set_icon_name("Zoom");
+ src.set_filename(get_icon_path("zoom.svg"));
+ _zoom.add_source(src);
+ icons->add(Stock::ZOOM, _zoom);
+ // Zoom In (use Inkscape icon for consistency over Gtk::Stock::ZOOM_IN)
+ Gtk::IconSet _zoom_in;
+ src.set_icon_name("ZoomIn");
+ src.set_filename(get_icon_path("zoom-in.svg"));
+ _zoom_in.add_source(src);
+ icons->add(Stock::ZOOM_IN, _zoom_in);
+ // Zoom Out (use Inkscape icon for consistency over Gtk::Stock::ZOOM_OUT)
+ Gtk::IconSet _zoom_out;
+ src.set_icon_name("ZoomOut");
+ src.set_filename(get_icon_path("zoom-out.svg"));
+ _zoom_out.add_source(src);
+ icons->add(Stock::ZOOM_OUT, _zoom_out);
+ // Zoom 100% (use Inkscape icon for consistency over Gtk::Stock::ZOOM_100)
+ Gtk::IconSet _zoom_100;
+ src.set_icon_name("Zoom100");
+ src.set_filename(get_icon_path("zoom-100.svg"));
+ _zoom_100.add_source(src);
+ icons->add(Stock::ZOOM_100, _zoom_100);
+ // Zoom 50%
+ Gtk::IconSet _zoom_50;
+ src.set_icon_name("Zoom50");
+ src.set_filename(get_icon_path("zoom-50.svg"));
+ _zoom_50.add_source(src);
+ icons->add(Stock::ZOOM_50, _zoom_50);
+ // Zoom 200%
+ Gtk::IconSet _zoom_200;
+ src.set_icon_name("Zoom200");
+ src.set_filename(get_icon_path("zoom-200.svg"));
+ _zoom_200.add_source(src);
+ icons->add(Stock::ZOOM_200, _zoom_200);
+ // Zoom Selection
+ Gtk::IconSet _zoom_selection;
+ src.set_icon_name("ZoomSelection");
+ src.set_filename(get_icon_path("zoom-selection.svg"));
+ _zoom_selection.add_source(src);
+ icons->add(Stock::ZOOM_SELECTION, _zoom_selection);
+ // Zoom Drawing
+ Gtk::IconSet _zoom_drawing;
+ src.set_icon_name("ZoomDrawing");
+ src.set_filename(get_icon_path("zoom-drawing.svg"));
+ _zoom_drawing.add_source(src);
+ icons->add(Stock::ZOOM_DRAWING, _zoom_drawing);
+ // Zoom Page (use Inkscape icon for consistency over Gtk::Stock::ZOOM_FIT)
+ Gtk::IconSet _zoom_page;
+ src.set_icon_name("ZoomPage");
+ src.set_filename(get_icon_path("zoom-page.svg"));
+ _zoom_page.add_source(src);
+ icons->add(Stock::ZOOM_PAGE, _zoom_page);
+ // Zoom Width
+ Gtk::IconSet _zoom_width;
+ src.set_icon_name("ZoomWidth");
+ src.set_filename(get_icon_path("zoom-width.svg"));
+ _zoom_width.add_source(src);
+ icons->add(Stock::ZOOM_WIDTH, _zoom_width);
+ // Zoom Previous
+ Gtk::IconSet _zoom_prev;
+ src.set_icon_name("ZoomPrev");
+ src.set_filename(get_icon_path("zoom-prev.svg"));
+ _zoom_prev.add_source(src);
+ icons->add(Stock::ZOOM_PREV, _zoom_prev);
+ // Zoom Next
+ Gtk::IconSet _zoom_next;
+ src.set_icon_name("ZoomNext");
+ src.set_filename(get_icon_path("zoom-next.svg"));
+ _zoom_next.add_source(src);
+ icons->add(Stock::ZOOM_NEXT, _zoom_next);
+ // Show/Hide Dialogs
+ Gtk::IconSet _show_hide_dialogs;
+ src.set_icon_name("ShowHideDialogs");
+ src.set_filename(get_icon_path("show-hide-dialogs.svg"));
+ _show_hide_dialogs.add_source(src);
+ icons->add(Stock::SHOW_HIDE_DIALOGS, _show_hide_dialogs);
+ // Grid
+ Gtk::IconSet _grid;
+ src.set_icon_name("Grid");
+ src.set_filename(get_icon_path("grid.svg"));
+ _grid.add_source(src);
+ icons->add(Stock::GRID, _grid);
+ // Guides
+ Gtk::IconSet _guides;
+ src.set_icon_name("Guides");
+ src.set_filename(get_icon_path("guides.svg"));
+ _guides.add_source(src);
+ icons->add(Stock::GUIDES, _guides);
+ // Fullscreen
+ Gtk::IconSet _fullscreen;
+ src.set_icon_name("Fullscreen");
+ src.set_filename(get_icon_path("fullscreen.svg"));
+ _fullscreen.add_source(src);
+ icons->add(Stock::FULLSCREEN, _fullscreen);
+ // Previous Window
+ Gtk::IconSet _window_prev;
+ src.set_icon_name("WindowPrev");
+ src.set_filename(get_icon_path("window-prev.svg"));
+ _window_prev.add_source(src);
+ icons->add(Stock::WINDOW_PREV, _window_prev);
+ // Next Window
+ Gtk::IconSet _window_next;
+ src.set_icon_name("WindowNext");
+ src.set_filename(get_icon_path("window-next.svg"));
+ _window_next.add_source(src);
+ icons->add(Stock::WINDOW_NEXT, _window_next);
+ // Duplicate Window
+ Gtk::IconSet _window_duplicate;
+ src.set_icon_name("WindowDuplicate");
+ src.set_filename(get_icon_path("window-duplicate.svg"));
+ _window_duplicate.add_source(src);
+ icons->add(Stock::WINDOW_DUPLICATE, _window_duplicate);
+
+ // Layer menu
+ // New Layer
+ icons->add(Stock::LAYER_NEW,
+ Gtk::IconSet::lookup_default(Gtk::Stock::NEW));
+ // Delete Layer
+ icons->add(Stock::LAYER_DELETE,
+ Gtk::IconSet::lookup_default(Gtk::Stock::DELETE));
+ // Raise Layer
+ icons->add(Stock::LAYER_RAISE,
+ Gtk::IconSet::lookup_default(Gtk::Stock::GO_UP));
+ // Lower Layer
+ icons->add(Stock::LAYER_LOWER,
+ Gtk::IconSet::lookup_default(Gtk::Stock::GO_DOWN));
+ // Layer to Top
+ icons->add(Stock::LAYER_TO_TOP,
+ Gtk::IconSet::lookup_default(Gtk::Stock::GOTO_TOP));
+ // Layer to Bottom
+ icons->add(Stock::LAYER_TO_BOTTOM,
+ Gtk::IconSet::lookup_default(Gtk::Stock::GOTO_BOTTOM));
+
+ // Object menu
+ // Fill and Stoke
+ Gtk::IconSet _fill_stroke;
+ src.set_icon_name("FillAndStroke");
+ src.set_filename(get_icon_path("fill-stroke.svg"));
+ _fill_stroke.add_source(src);
+ icons->add(Stock::FILL_STROKE, _fill_stroke);
+ // Object Properties
+ Gtk::IconSet _object_properties;
+ src.set_icon_name("ObjectProperties");
+ src.set_filename(get_icon_path("object-properties.svg"));
+ _object_properties.add_source(src);
+ icons->add(Stock::OBJECT_PROPERTIES, _object_properties);
+ // Group
+ Gtk::IconSet _group;
+ src.set_icon_name("Group");
+ src.set_filename(get_icon_path("group.svg"));
+ _group.add_source(src);
+ icons->add(Stock::GROUP, _group);
+ // Ungroup
+ Gtk::IconSet _ungroup;
+ src.set_icon_name("Ungroup");
+ src.set_filename(get_icon_path("ungroup.svg"));
+ _ungroup.add_source(src);
+ icons->add(Stock::UNGROUP, _ungroup);
+ // Raise
+ Gtk::IconSet _raise;
+ src.set_icon_name("Raise");
+ src.set_filename(get_icon_path("raise.svg"));
+ _raise.add_source(src);
+ icons->add(Stock::RAISE, _raise);
+ // Lower
+ Gtk::IconSet _lower;
+ src.set_icon_name("Lower");
+ src.set_filename(get_icon_path("lower.svg"));
+ _lower.add_source(src);
+ icons->add(Stock::LOWER, _lower);
+ // Raise to Top
+ Gtk::IconSet _raise_to_top;
+ src.set_icon_name("RaiseToTop");
+ src.set_filename(get_icon_path("raise-to-top.svg"));
+ _raise_to_top.add_source(src);
+ icons->add(Stock::RAISE_TO_TOP, _raise_to_top);
+ // Lower to Bottom
+ Gtk::IconSet _lower_to_bottom;
+ src.set_icon_name("LowerToBottom");
+ src.set_filename(get_icon_path("lower-to-bottom.svg"));
+ _lower_to_bottom.add_source(src);
+ icons->add(Stock::LOWER_TO_BOTTOM, _lower_to_bottom);
+ // Move to Next Layer
+ Gtk::IconSet _move_to_next_layer;
+ src.set_icon_name("MoveToNextLayer");
+ src.set_filename(get_icon_path("move-to-next-layer.svg"));
+ _move_to_next_layer.add_source(src);
+ icons->add(Stock::MOVE_TO_NEXT_LAYER, _move_to_next_layer);
+ // Move to Previous Layer
+ Gtk::IconSet _move_to_prev_layer;
+ src.set_icon_name("MoveToPrevLayer");
+ src.set_filename(get_icon_path("move-to-prev-layer.svg"));
+ _move_to_prev_layer.add_source(src);
+ icons->add(Stock::MOVE_TO_PREV_LAYER, _move_to_prev_layer);
+ // Move to Top Layer
+ Gtk::IconSet _move_to_top_layer;
+ src.set_icon_name("MoveToTopLayer");
+ src.set_filename(get_icon_path("move-to-top-layer.svg"));
+ _move_to_top_layer.add_source(src);
+ icons->add(Stock::MOVE_TO_TOP_LAYER, _move_to_top_layer);
+ // Move to Bottom Layer
+ Gtk::IconSet _move_to_bottom_layer;
+ src.set_icon_name("MoveToBottomLayer");
+ src.set_filename(get_icon_path("move-to-bottom-layer.svg"));
+ _move_to_bottom_layer.add_source(src);
+ icons->add(Stock::MOVE_TO_BOTTOM_LAYER, _move_to_bottom_layer);
+ // Rotate 90 CW
+ Gtk::IconSet _rotate_90_cw;
+ src.set_icon_name("Rotate90CW");
+ src.set_filename(get_icon_path("rotate-90-cw.svg"));
+ _rotate_90_cw.add_source(src);
+ icons->add(Stock::ROTATE_90_CW, _rotate_90_cw);
+ // Rotate 90 CCW
+ Gtk::IconSet _rotate_90_ccw;
+ src.set_icon_name("Rotate90CCW");
+ src.set_filename(get_icon_path("rotate-90-ccw.svg"));
+ _rotate_90_ccw.add_source(src);
+ icons->add(Stock::ROTATE_90_CCW, _rotate_90_ccw);
+ // Flip Horizontal
+ Gtk::IconSet _flip_horiz;
+ src.set_icon_name("FlipHoriz");
+ src.set_filename(get_icon_path("flip-horiz.svg"));
+ _flip_horiz.add_source(src);
+ icons->add(Stock::FLIP_HORIZ, _flip_horiz);
+ // Flip Vertical
+ Gtk::IconSet _flip_vert;
+ src.set_icon_name("FlipVert");
+ src.set_filename(get_icon_path("flip-vert.svg"));
+ _flip_vert.add_source(src);
+ icons->add(Stock::FLIP_VERT, _flip_vert);
+ // Transform
+ Gtk::IconSet _transform;
+ src.set_icon_name("Transform");
+ src.set_filename(get_icon_path("transform.svg"));
+ _transform.add_source(src);
+ icons->add(Stock::TRANSFORM, _transform);
+ // Transformation
+ Gtk::IconSet _transformation;
+ src.set_icon_name("Transformation");
+ src.set_filename(get_icon_path("transform.svg"));
+ _transformation.add_source(src);
+ icons->add(Stock::TRANSFORMATION, _transformation);
+ // Align and Distribute
+ Gtk::IconSet _align_distribute;
+ src.set_icon_name("AlignAndDistribute");
+ src.set_filename(get_icon_path("align-distribute.svg"));
+ _align_distribute.add_source(src);
+ icons->add(Stock::ALIGN_DISTRIBUTE, _align_distribute);
+
+ // Path menu
+ // Object to Path
+ Gtk::IconSet _object_to_path;
+ src.set_icon_name("ObjectToPath");
+ src.set_filename(get_icon_path("object-to-path.svg"));
+ _object_to_path.add_source(src);
+ icons->add(Stock::OBJECT_TO_PATH, _object_to_path);
+ // Stroke to Path
+ Gtk::IconSet _stroke_to_path;
+ src.set_icon_name("StrokeToPath");
+ src.set_filename(get_icon_path("stroke-to-path.svg"));
+ _stroke_to_path.add_source(src);
+ icons->add(Stock::STROKE_TO_PATH, _stroke_to_path);
+ // Trace
+ Gtk::IconSet _trace;
+ src.set_icon_name("Trace");
+ src.set_filename(get_icon_path("trace.svg"));
+ _trace.add_source(src);
+ icons->add(Stock::TRACE, _trace);
+ // Union
+ Gtk::IconSet _union;
+ src.set_icon_name("Union");
+ src.set_filename(get_icon_path("union.svg"));
+ _union.add_source(src);
+ icons->add(Stock::UNION, _union);
+ // Difference
+ Gtk::IconSet _difference;
+ src.set_icon_name("Difference");
+ src.set_filename(get_icon_path("difference.svg"));
+ _difference.add_source(src);
+ icons->add(Stock::DIFFERENCE, _difference);
+ // Intersection
+ Gtk::IconSet _intersection;
+ src.set_icon_name("Intersection");
+ src.set_filename(get_icon_path("intersection.svg"));
+ _intersection.add_source(src);
+ icons->add(Stock::INTERSECTION, _intersection);
+ // Exclusion
+ Gtk::IconSet _exclusion;
+ src.set_icon_name("Exclusion");
+ src.set_filename(get_icon_path("exclusion.svg"));
+ _exclusion.add_source(src);
+ icons->add(Stock::EXCLUSION, _exclusion);
+ // Division
+ Gtk::IconSet _division;
+ src.set_icon_name("Division");
+ src.set_filename(get_icon_path("division.svg"));
+ _division.add_source(src);
+ icons->add(Stock::DIVISION, _division);
+ // Cut Path
+ Gtk::IconSet _cut_path;
+ src.set_icon_name("CutPath");
+ src.set_filename(get_icon_path("cut-path.svg"));
+ _cut_path.add_source(src);
+ icons->add(Stock::CUT_PATH, _cut_path);
+ // Combine
+ Gtk::IconSet _combine;
+ src.set_icon_name("Combine");
+ src.set_filename(get_icon_path("combine.svg"));
+ _combine.add_source(src);
+ icons->add(Stock::COMBINE, _combine);
+ // Break Apart
+ Gtk::IconSet _break_apart;
+ src.set_icon_name("BreakApart");
+ src.set_filename(get_icon_path("break-apart.svg"));
+ _break_apart.add_source(src);
+ icons->add(Stock::BREAK_APART, _break_apart);
+ // Inset
+ Gtk::IconSet _inset;
+ src.set_icon_name("Inset");
+ src.set_filename(get_icon_path("inset.svg"));
+ _inset.add_source(src);
+ icons->add(Stock::INSET, _inset);
+ // Outset
+ Gtk::IconSet _outset;
+ src.set_icon_name("Outset");
+ src.set_filename(get_icon_path("outset.svg"));
+ _outset.add_source(src);
+ icons->add(Stock::OUTSET, _outset);
+ // Dynamic Offset
+ Gtk::IconSet _offset_dynamic;
+ src.set_icon_name("OffsetDynamic");
+ src.set_filename(get_icon_path("offset-dynamic.svg"));
+ _offset_dynamic.add_source(src);
+ icons->add(Stock::OFFSET_DYNAMIC, _offset_dynamic);
+ // Linked Offset
+ Gtk::IconSet _offset_linked;
+ src.set_icon_name("OffsetLinked");
+ src.set_filename(get_icon_path("offset-linked.svg"));
+ _offset_linked.add_source(src);
+ icons->add(Stock::OFFSET_LINKED, _offset_linked);
+ // Simplify
+ Gtk::IconSet _simplify;
+ src.set_icon_name("Simplify");
+ src.set_filename(get_icon_path("simplify.svg"));
+ _simplify.add_source(src);
+ icons->add(Stock::SIMPLIFY, _simplify);
+ // Reverse
+ Gtk::IconSet _reverse;
+ src.set_icon_name("Reverse");
+ src.set_filename(get_icon_path("reverse.svg"));
+ _reverse.add_source(src);
+ icons->add(Stock::REVERSE, _reverse);
+
+ // Help menu
+ // Keys and Mouse
+ Gtk::IconSet _keys_mouse;
+ src.set_icon_name("KeysAndMouse");
+ src.set_filename(get_icon_path("keys-mouse.svg"));
+ _keys_mouse.add_source(src);
+ icons->add(Stock::KEYS_MOUSE, _keys_mouse);
+ // Tutorials
+ Gtk::IconSet _tutorials;
+ src.set_icon_name("Tutorials");
+ src.set_filename(get_icon_path("tutorials.svg"));
+ _tutorials.add_source(src);
+ icons->add(Stock::TUTORIALS, _tutorials);
+ // About Inkscape
+ Gtk::IconSet _about;
+ src.set_icon_name("About");
+ src.set_filename(get_icon_path("inkscape.svg"));
+ _about.add_source(src);
+ icons->add(Stock::ABOUT, _about);
+ // About Splash
+ Gtk::IconSet _about_splash;
+ src.set_filename(get_icon_path("about41.svg"));
+ src.set_size(Gtk::IconSize::register_new("about", 750, 625));
+ _about_splash.add_source(src);
+ icons->add(Stock::ABOUT_SPLASH, _about_splash);
+ // 42 Don't Panic!
+ Gtk::IconSet _about_42;
+ src.set_filename(get_icon_path("dontpanic.svg"));
+ src.set_size(Gtk::IconSize::register_new("dontpanic", 250, 172));
+ _about_42.add_source(src);
+ icons->add(Stock::ABOUT_42, _about_42);
+ // Quick Help
+ Gtk::IconSet _about_quick_help;
+ src.set_filename(get_icon_path("quick-help.svg"));
+ src.set_size(Gtk::IconSize::from_name("about"));
+ _about_quick_help.add_source(src);
+ icons->add(Stock::ABOUT_QUICK_HELP, _about_quick_help);
+
+ // Tools toolbar
+ // Select tool
+ Gtk::IconSet _tool_select;
+ src.set_icon_name("ToolSelect");
+ src.set_filename(get_icon_path("tool-select.svg"));
+ _tool_select.add_source(src);
+ icons->add(Stock::TOOL_SELECT, _tool_select);
+ // Node tool
+ Gtk::IconSet _tool_node;
+ src.set_icon_name("ToolNode");
+ src.set_filename(get_icon_path("tool-node.svg"));
+ _tool_node.add_source(src);
+ icons->add(Stock::TOOL_NODE, _tool_node);
+ // Zoom tool
+ Gtk::IconSet _tool_zoom;
+ src.set_icon_name("ToolZoom");
+ src.set_filename(get_icon_path("tool-zoom.svg"));
+ _tool_zoom.add_source(src);
+ icons->add(Stock::TOOL_ZOOM, _tool_zoom);
+ // Rect tool
+ Gtk::IconSet _tool_rect;
+ src.set_icon_name("ToolRect");
+ src.set_filename(get_icon_path("tool-rect.svg"));
+ _tool_rect.add_source(src);
+ icons->add(Stock::TOOL_RECT, _tool_rect);
+ // Arc tool
+ Gtk::IconSet _tool_arc;
+ src.set_icon_name("ToolArc");
+ src.set_filename(get_icon_path("tool-arc.svg"));
+ _tool_arc.add_source(src);
+ icons->add(Stock::TOOL_ARC, _tool_arc);
+ // Star tool
+ Gtk::IconSet _tool_star;
+ src.set_icon_name("ToolStar");
+ src.set_filename(get_icon_path("tool-star.svg"));
+ _tool_star.add_source(src);
+ icons->add(Stock::TOOL_STAR, _tool_star);
+ // Spiral tool
+ Gtk::IconSet _tool_spiral;
+ src.set_icon_name("ToolSpiral");
+ src.set_filename(get_icon_path("tool-spiral.svg"));
+ _tool_spiral.add_source(src);
+ icons->add(Stock::TOOL_SPIRAL, _tool_spiral);
+ // Freehand tool
+ Gtk::IconSet _tool_freehand;
+ src.set_icon_name("ToolFreehand");
+ src.set_filename(get_icon_path("tool-freehand.svg"));
+ _tool_freehand.add_source(src);
+ icons->add(Stock::TOOL_FREEHAND, _tool_freehand);
+ // Pen tool
+ Gtk::IconSet _tool_pen;
+ src.set_icon_name("ToolPen");
+ src.set_filename(get_icon_path("tool-pen.svg"));
+ _tool_pen.add_source(src);
+ icons->add(Stock::TOOL_PEN, _tool_pen);
+ // DynaDraw tool
+ Gtk::IconSet _tool_dynadraw;
+ src.set_icon_name("ToolDynaDraw");
+ src.set_filename(get_icon_path("tool-dynadraw.svg"));
+ _tool_dynadraw.add_source(src);
+ icons->add(Stock::TOOL_DYNADRAW, _tool_dynadraw);
+ // Text tool
+ Gtk::IconSet _tool_text;
+ src.set_icon_name("ToolText");
+ src.set_filename(get_icon_path("tool-text.svg"));
+ _tool_text.add_source(src);
+ icons->add(Stock::TOOL_TEXT, _tool_text);
+ // Dropper tool
+ Gtk::IconSet _tool_dropper;
+ src.set_icon_name("ToolDropper");
+ src.set_filename(get_icon_path("tool-dropper.svg"));
+ _tool_dropper.add_source(src);
+ icons->add(Stock::TOOL_DROPPER, _tool_dropper);
+
+ // Select Tool controls
+ Gtk::IconSource small;
+ small.set_size(Gtk::ICON_SIZE_SMALL_TOOLBAR);
+ // Transform Stroke
+ Gtk::IconSet _transform_stroke;
+ small.set_icon_name("TransformStroke");
+ small.set_filename(get_icon_path("transform-stroke.svg"));
+ _transform_stroke.add_source(small);
+ icons->add(Stock::TRANSFORM_STROKE, _transform_stroke);
+ // Transform Corners
+ Gtk::IconSet _transform_corners;
+ small.set_icon_name("TransformCorners");
+ small.set_filename(get_icon_path("transform-corners.svg"));
+ _transform_corners.add_source(small);
+ icons->add(Stock::TRANSFORM_CORNERS, _transform_corners);
+ // Transform Grandient
+ Gtk::IconSet _transform_gradient;
+ small.set_icon_name("TransformGrandient");
+ small.set_filename(get_icon_path("transform-gradient.svg"));
+ _transform_gradient.add_source(small);
+ icons->add(Stock::TRANSFORM_GRADIENT, _transform_gradient);
+ // Transform Pattern
+ Gtk::IconSet _transform_pattern;
+ small.set_icon_name("TransformPattern");
+ small.set_filename(get_icon_path("transform-pattern.svg"));
+ _transform_pattern.add_source(small);
+ icons->add(Stock::TRANSFORM_PATTERN, _transform_pattern);
+
+ // Calligraphy Tool controls
+ // Use Pressure
+ Gtk::IconSet _use_pressure;
+ small.set_icon_name("UsePressure");
+ small.set_filename(get_icon_path("use-pressure.svg"));
+ _use_pressure.add_source(small);
+ icons->add(Stock::USE_PRESSURE, _use_pressure);
+ // Use Tilt
+ Gtk::IconSet _use_tilt;
+ small.set_icon_name("UseTilt");
+ small.set_filename(get_icon_path("use-tilt.svg"));
+ _use_tilt.add_source(small);
+ icons->add(Stock::USE_TILT, _use_tilt);
+
+ // Session playback dialog
+ // Rewind
+ Gtk::IconSet _session_rewind;
+ src.set_icon_name("Rewind");
+ src.set_filename(get_icon_path("session-rew.svg"));
+ _session_rewind.add_source(src);
+ icons->add(Stock::SESSION_PLAYBACK_REW, _session_rewind);
+ // Step backwards
+ Gtk::IconSet _session_stepback;
+ src.set_icon_name("StepBackward");
+ src.set_filename(get_icon_path("session-back1.svg"));
+ _session_stepback.add_source(src);
+ icons->add(Stock::SESSION_PLAYBACK_STEPBACK, _session_stepback);
+ // Pause
+ Gtk::IconSet _session_pause;
+ src.set_icon_name("Pause");
+ src.set_filename(get_icon_path("session-pause.svg"));
+ _session_pause.add_source(src);
+ icons->add(Stock::SESSION_PLAYBACK_PAUSE, _session_pause);
+ // Step forwards
+ Gtk::IconSet _session_stepforward;
+ src.set_icon_name("StepForward");
+ src.set_filename(get_icon_path("session-adv1.svg"));
+ _session_stepforward.add_source(src);
+ icons->add(Stock::SESSION_PLAYBACK_STEPFORWARD, _session_stepforward);
+ // Play
+ Gtk::IconSet _session_play;
+ src.set_icon_name("Play");
+ src.set_filename(get_icon_path("session-play.svg"));
+ _session_play.add_source(src);
+ icons->add(Stock::SESSION_PLAYBACK_PLAY, _session_play);
+
+ icons->add_default();
+}
+
+/** Returns the icon filename (in the operating system encoding used for filenames) whose basename
+ in utf8 encoding is \a utf8_basename.
+**/
+static Glib::ustring const
+get_icon_path(char const *const utf8_basename)
+{
+ /* Given that INKSCAPE_PIXMAPDIR is often a compiled constant, I suppose we should
+ interpret it as utf8: under windows, the encoding for filenames can change from
+ day to day even for a given file. */
+ static char *const opsys_iconsdir = g_filename_from_utf8(INKSCAPE_PIXMAPDIR, -1,
+ NULL, NULL, NULL);
+
+ g_assert(g_utf8_validate(utf8_basename, -1, NULL));
+ char *const opsys_basename = g_filename_from_utf8(utf8_basename, -1, NULL, NULL, NULL);
+ char *const ret_cstr = g_build_filename(opsys_iconsdir, opsys_basename, NULL);
+ Glib::ustring const ret(ret_cstr);
+ g_free(ret_cstr);
+ g_free(opsys_basename);
+ return ret;
+}
+
+} // namespace Icon
+} // 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/icons.h b/src/ui/icons.h
new file mode 100644
index 000000000..382dee693
--- /dev/null
+++ b/src/ui/icons.h
@@ -0,0 +1,36 @@
+/**
+ * \brief Stock icons for Inkscape-specific menu items and buttons.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_ICONS_H
+#define INKSCAPE_UI_ICONS_H
+
+namespace Inkscape {
+namespace UI {
+namespace Icons {
+
+void init();
+
+} // namespace Icons
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_ICONS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/makefile.in b/src/ui/makefile.in
new file mode 100644
index 000000000..11422bd6e
--- /dev/null
+++ b/src/ui/makefile.in
@@ -0,0 +1,17 @@
+# Convenience stub makefile to call the real Makefile.
+
+@SET_MAKE@
+
+# Explicit so that it's the default rule.
+all:
+ cd .. && $(MAKE) ui/all
+
+clean %.a %.o:
+ cd .. && $(MAKE) ui/$@
+
+.PHONY: all clean
+
+OBJEXT = @OBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .a .$(OBJEXT)
diff --git a/src/ui/previewable.h b/src/ui/previewable.h
new file mode 100644
index 000000000..86ee71ca5
--- /dev/null
+++ b/src/ui/previewable.h
@@ -0,0 +1,62 @@
+
+#ifndef SEEN_PREVIEWABLE_H
+#define SEEN_PREVIEWABLE_H
+/*
+ * A simple interface for previewing representations.
+ *
+ * Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2005 Jon A. Cruz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include <gtkmm/widget.h>
+
+
+namespace Inkscape {
+namespace UI {
+
+typedef enum {
+ PREVIEW_STYLE_ICON = 0,
+ PREVIEW_STYLE_PREVIEW,
+ PREVIEW_STYLE_NAME,
+ PREVIEW_STYLE_BLURB,
+ PREVIEW_STYLE_ICON_NAME,
+ PREVIEW_STYLE_ICON_BLURB,
+ PREVIEW_STYLE_PREVIEW_NAME,
+ PREVIEW_STYLE_PREVIEW_BLURB
+} PreviewStyle;
+
+typedef enum {
+ VIEW_TYPE_LIST = 0,
+ VIEW_TYPE_GRID
+} ViewType;
+
+class Previewable
+{
+public:
+// TODO need to add some nice parameters
+ virtual ~Previewable() {}
+ virtual Gtk::Widget* getPreview( PreviewStyle style, ViewType view, Gtk::BuiltinIconSize size ) = 0;
+};
+
+
+} //namespace UI
+} //namespace Inkscape
+
+
+#endif // SEEN_PREVIEWABLE_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/previewfillable.h b/src/ui/previewfillable.h
new file mode 100644
index 000000000..106eda7ea
--- /dev/null
+++ b/src/ui/previewfillable.h
@@ -0,0 +1,49 @@
+
+#ifndef SEEN_PREVIEWFILLABLE_H
+#define SEEN_PREVIEWFILLABLE_H
+/*
+ * A simple interface for previewing representations.
+ *
+ * Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2005 Jon A. Cruz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include "previewable.h"
+
+
+namespace Inkscape {
+namespace UI {
+
+class PreviewFillable
+{
+public:
+ virtual ~PreviewFillable() {}
+ virtual void clear() = 0;
+ virtual void addPreview( Previewable* preview ) = 0;
+ virtual void setStyle(Gtk::BuiltinIconSize size, ViewType type) = 0;
+ virtual Gtk::BuiltinIconSize getPreviewSize() const = 0;
+ virtual ViewType getPreviewType() const = 0;
+};
+
+
+} //namespace UI
+} //namespace Inkscape
+
+
+#endif // SEEN_PREVIEWFILLABLE_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/previewholder.cpp b/src/ui/previewholder.cpp
new file mode 100644
index 000000000..e73cd7407
--- /dev/null
+++ b/src/ui/previewholder.cpp
@@ -0,0 +1,153 @@
+
+/*
+ * A simple interface for previewing representations.
+ *
+ * Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2005 Jon A. Cruz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include "previewholder.h"
+
+#include <gtkmm/scrolledwindow.h>
+
+
+namespace Inkscape {
+namespace UI {
+
+
+PreviewHolder::PreviewHolder() :
+ VBox(),
+ PreviewFillable(),
+ _scroller(0),
+ _baseSize(Gtk::ICON_SIZE_MENU),
+ _view(VIEW_TYPE_LIST)
+{
+ _scroller = manage(new Gtk::ScrolledWindow());
+ Gtk::Table* stuff = manage(new Gtk::Table( 1, 2 ));
+ stuff->set_col_spacings( 8 );
+ _insides = stuff;
+ _scroller->add(*stuff);
+
+ pack_start(*_scroller, Gtk::PACK_EXPAND_WIDGET);
+}
+
+PreviewHolder::~PreviewHolder()
+{
+}
+
+
+
+void PreviewHolder::clear()
+{
+ items.clear();
+ rebuildUI();
+}
+
+void PreviewHolder::addPreview( Previewable* preview )
+{
+ items.push_back(preview);
+
+ int i = items.size() - 1;
+ if ( _view == VIEW_TYPE_LIST ) {
+ Gtk::Widget* label = manage(preview->getPreview(PREVIEW_STYLE_BLURB, VIEW_TYPE_LIST, _baseSize));
+ Gtk::Widget* thing = manage(preview->getPreview(PREVIEW_STYLE_PREVIEW, VIEW_TYPE_LIST, _baseSize));
+
+ _insides->attach( *thing, 0, 1, i, i+1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND );
+ _insides->attach( *label, 1, 2, i, i+1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK );
+ } else {
+ Gtk::Widget* thing = manage(items[i]->getPreview(PREVIEW_STYLE_PREVIEW, VIEW_TYPE_GRID, _baseSize));
+ int width = _baseSize == Gtk::ICON_SIZE_MENU ? 16 : 8;
+ int col = i % width;
+ int row = i / width;
+ if ( col == 0 ) {
+ // we just started a new row
+ _insides->resize( row + 1, width );
+ }
+ _insides->attach( *thing, col, col+1, row, row+1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND );
+ }
+
+ _scroller->show_all_children();
+ _scroller->queue_draw();
+}
+
+void PreviewHolder::setStyle(Gtk::BuiltinIconSize size, ViewType view)
+{
+ if ( size != _baseSize || view != _view ) {
+ _baseSize = size;
+ _view = view;
+ rebuildUI();
+ }
+}
+
+
+void PreviewHolder::rebuildUI()
+{
+ _scroller->remove();
+
+ if ( _view == VIEW_TYPE_LIST ) {
+ Gtk::Table* stuff = manage(new Gtk::Table( 1, 2 ));
+ _insides = stuff;
+ stuff->set_col_spacings( 8 );
+
+ for ( unsigned int i = 0; i < items.size(); i++ ) {
+ Gtk::Widget* label = manage(items[i]->getPreview(PREVIEW_STYLE_BLURB, _view, _baseSize));
+ //label->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER);
+
+ Gtk::Widget* thing = manage(items[i]->getPreview(PREVIEW_STYLE_PREVIEW, _view, _baseSize));
+
+ stuff->attach( *thing, 0, 1, i, i+1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND );
+ stuff->attach( *label, 1, 2, i, i+1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK );
+ }
+ _scroller->add(*stuff);
+ } else {
+ int width = _baseSize == Gtk::ICON_SIZE_MENU ? 16 : 8;
+ int height = (items.size() + (width - 1)) / width;
+ if ( height < 1 ) {
+ height = 1;
+ }
+
+ Gtk::Table* stuff = manage(new Gtk::Table( height, width ));
+ _insides = stuff;
+ int col = 0;
+ int row = 0;
+
+ for ( unsigned int i = 0; i < items.size(); i++ ) {
+ Gtk::Widget* thing = manage(items[i]->getPreview(PREVIEW_STYLE_PREVIEW, _view, _baseSize));
+
+ stuff->attach( *thing, col, col+1, row, row+1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND );
+ col++;
+ if ( col >= width ) {
+ col = 0;
+ row++;
+ }
+ }
+ _scroller->add(*stuff);
+ }
+
+ _scroller->show_all_children();
+ _scroller->queue_draw();
+}
+
+
+
+
+
+} //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/previewholder.h b/src/ui/previewholder.h
new file mode 100644
index 000000000..96d9b8228
--- /dev/null
+++ b/src/ui/previewholder.h
@@ -0,0 +1,60 @@
+
+#ifndef SEEN_PREVIEW_HOLDER_H
+#define SEEN_PREVIEW_HOLDER_H
+/*
+ * A simple interface for previewing representations.
+ *
+ * Authors:
+ * Jon A. Cruz
+ *
+ * Copyright (C) 2005 Jon A. Cruz
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include <gtkmm/box.h>
+#include <gtkmm/bin.h>
+#include <gtkmm/table.h>
+#include "previewfillable.h"
+
+namespace Inkscape {
+namespace UI {
+
+class PreviewHolder : public Gtk::VBox, public PreviewFillable
+{
+public:
+ PreviewHolder();
+ virtual ~PreviewHolder();
+
+ virtual void clear();
+ virtual void addPreview( Previewable* preview );
+ virtual void setStyle(Gtk::BuiltinIconSize size, ViewType view);
+ virtual Gtk::BuiltinIconSize getPreviewSize() const { return _baseSize; }
+ virtual ViewType getPreviewType() const { return _view; }
+
+private:
+ void rebuildUI();
+
+ std::vector<Previewable*> items;
+ Gtk::Bin *_scroller;
+ Gtk::Table *_insides;
+ Gtk::BuiltinIconSize _baseSize;
+ ViewType _view;
+};
+
+} //namespace UI
+} //namespace Inkscape
+
+#endif // SEEN_PREVIEW_HOLDER_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/stock-items.cpp b/src/ui/stock-items.cpp
new file mode 100644
index 000000000..09e2a894d
--- /dev/null
+++ b/src/ui/stock-items.cpp
@@ -0,0 +1,215 @@
+/**
+ * \brief StockItems for Inkscape-specific menu/button labels and key
+ * accelerators.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#include <gtkmm/stock.h>
+#include <glibmm/i18n.h>
+
+#include "stock.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Stock {
+
+void
+init()
+{
+ using namespace Gtk::Stock;
+
+// FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
+// See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
+
+ // File menu
+ add(Gtk::StockItem(OPEN, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(OPEN_RECENT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SAVE_AS, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(IMPORT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(EXPORT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(PRINT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(PRINT_PREVIEW, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(VACUUM_DEFS, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(PROPERTIES, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(PREFERENCES, _("PLACEHOLDER, do not translate")));
+
+ // Edit menu
+ add(Gtk::StockItem(PASTE_IN_PLACE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(PASTE_STYLE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(DUPLICATE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(CLONE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(CLONE_UNLINK, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(CLONE_SELECT_ORIG, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(MAKE_BITMAP, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TILE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(UNTILE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SELECT_ALL, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SELECT_ALL_IN_ALL_LAYERS, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SELECT_INVERT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SELECT_NONE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(XML_EDITOR, _("PLACEHOLDER, do not translate")));
+
+ // View menu
+ add(Gtk::StockItem(ZOOM, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_IN, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_OUT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_100, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_50, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_200, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_SELECTION, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_DRAWING, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_PAGE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_WIDTH, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_PREV, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ZOOM_NEXT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SHOW_HIDE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SHOW_HIDE_COMMANDS_BAR, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SHOW_HIDE_TOOL_CONTROLS_BAR, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SHOW_HIDE_TOOLS_BAR, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SHOW_HIDE_RULERS, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SHOW_HIDE_SCROLLBARS, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SHOW_HIDE_STATUSBAR, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SHOW_HIDE_DIALOGS, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(GRID, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(GUIDES, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(FULLSCREEN, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(MESSAGES, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SCRIPTS, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(WINDOW_PREV, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(WINDOW_NEXT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(WINDOW_DUPLICATE, _("PLACEHOLDER, do not translate")));
+
+ // Layer menu
+ add(Gtk::StockItem(LAYER_NEW, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_RENAME, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_DUPLICATE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_ANCHOR, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_MERGE_DOWN, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_DELETE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_SELECT_NEXT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_SELECT_PREV, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_SELECT_TOP, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_SELECT_BOTTOM, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_RAISE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_LOWER, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_TO_TOP, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LAYER_TO_BOTTOM, _("PLACEHOLDER, do not translate")));
+
+ // Object menu
+ add(Gtk::StockItem(FILL_STROKE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(OBJECT_PROPERTIES, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(GROUP, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(UNGROUP, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(RAISE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LOWER, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(RAISE_TO_TOP, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(LOWER_TO_BOTTOM, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(MOVE_TO_NEW_LAYER, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(MOVE_TO_NEXT_LAYER, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(MOVE_TO_PREV_LAYER, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(MOVE_TO_TOP_LAYER, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(MOVE_TO_BOTTOM_LAYER, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ROTATE_90_CW, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ROTATE_90_CCW, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(FLIP_HORIZ, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(FLIP_VERT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TRANSFORM, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TRANSFORMATION, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ALIGN_DISTRIBUTE, _("PLACEHOLDER, do not translate")));
+
+ // Path menu
+ add(Gtk::StockItem(OBJECT_TO_PATH, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(STROKE_TO_PATH, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TRACE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(UNION, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(DIFFERENCE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(INTERSECTION, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(EXCLUSION, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(DIVISION, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(CUT_PATH, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(COMBINE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(BREAK_APART, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(INSET, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(OUTSET, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(OFFSET_DYNAMIC, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(OFFSET_LINKED, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SIMPLIFY, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(REVERSE, _("PLACEHOLDER, do not translate")));
+ //add(Gtk::StockItem(CLEANUP, _("PLACEHOLDER, do not translate"))); (using Gtk::Stock::CLEAR)
+
+ // Text menu
+ add(Gtk::StockItem(SELECT_FONT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(PUT_ON_PATH, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(REMOVE_FROM_PATH, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(REMOVE_MANUAL_KERNS, _("PLACEHOLDER, do not translate")));
+
+ // About menu
+ add(Gtk::StockItem(KEYS_MOUSE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TUTORIALS, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(ABOUT, _("PLACEHOLDER, do not translate")));
+
+ // Tools toolbox
+ add(Gtk::StockItem(TOOL_SELECT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_NODE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_ZOOM, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_RECT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_ARC, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_STAR, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_SPIRAL, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_FREEHAND, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_PEN, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_DYNADRAW, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_TEXT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TOOL_DROPPER, _("PLACEHOLDER, do not translate")));
+
+ // Select Tool controls
+ add(Gtk::StockItem(TRANSFORM_STROKE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TRANSFORM_CORNERS, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TRANSFORM_GRADIENT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(TRANSFORM_PATTERN, _("PLACEHOLDER, do not translate")));
+
+ // Node Tool controls
+ add(Gtk::StockItem(NODE_INSERT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_DELETE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_JOIN, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_JOIN_SEGMENT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_DELETE_SEGMENT, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_BREAK, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_CORNER, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_SMOOTH, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_SYMMETRIC, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_LINE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(NODE_CURVE, _("PLACEHOLDER, do not translate")));
+
+ // Calligraphy Tool controls
+ add(Gtk::StockItem(USE_PRESSURE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(USE_TILT, _("PLACEHOLDER, do not translate")));
+
+ // Session playback controls
+ add(Gtk::StockItem(SESSION_PLAYBACK_REW, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SESSION_PLAYBACK_STEPBACK, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SESSION_PLAYBACK_PAUSE, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SESSION_PLAYBACK_STEPFORWARD, _("PLACEHOLDER, do not translate")));
+ add(Gtk::StockItem(SESSION_PLAYBACK_PLAY, _("PLACEHOLDER, do not translate")));
+}
+
+} // namespace Stock
+} // 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/stock-items.h b/src/ui/stock-items.h
new file mode 100644
index 000000000..a109c2960
--- /dev/null
+++ b/src/ui/stock-items.h
@@ -0,0 +1,37 @@
+/**
+ * \brief StockItems for Inkscape-specific menu and button labels and key
+ * accelerators.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_STOCK_ITEMS_H
+#define INKSCAPE_UI_STOCK_ITEMS_H
+
+namespace Inkscape {
+namespace UI {
+namespace Stock {
+
+void init();
+
+} // namespace Stock
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_STOCK_ITEMS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/stock.cpp b/src/ui/stock.cpp
new file mode 100644
index 000000000..b7dbddcc9
--- /dev/null
+++ b/src/ui/stock.cpp
@@ -0,0 +1,187 @@
+/**
+ * \brief StockIDs for Inkscape-specific stock menu/toolbar items and icons.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#include "stock.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Stock {
+
+// File menu
+Gtk::StockID const OPEN_RECENT("open-recent");
+Gtk::StockID const IMPORT("import");
+Gtk::StockID const EXPORT("export");
+Gtk::StockID const VACUUM_DEFS("vacuum-defs");
+// Edit menu
+Gtk::StockID const PASTE_IN_PLACE("paste-in-place");
+Gtk::StockID const PASTE_STYLE("paste-style");
+Gtk::StockID const DUPLICATE("duplicate");
+Gtk::StockID const CLONE("clone");
+Gtk::StockID const CLONE_UNLINK("clone-unlink");
+Gtk::StockID const CLONE_SELECT_ORIG("clone-select-orig");
+Gtk::StockID const MAKE_BITMAP("make-bitmap");
+Gtk::StockID const TILE("tile");
+Gtk::StockID const UNTILE("untile");
+Gtk::StockID const SELECT_ALL("select-all");
+Gtk::StockID const SELECT_ALL_IN_ALL_LAYERS("select-all-in-all-layers");
+Gtk::StockID const SELECT_INVERT("select-invert");
+Gtk::StockID const SELECT_NONE("select-none");
+Gtk::StockID const XML_EDITOR("xml-editor");
+// View menu
+Gtk::StockID const ZOOM("zoom");
+Gtk::StockID const ZOOM_IN("zoom-in");
+Gtk::StockID const ZOOM_OUT("zoom-out");
+Gtk::StockID const ZOOM_100("zoom-100");
+Gtk::StockID const ZOOM_50("zoom-50");
+Gtk::StockID const ZOOM_200("zoom-200");
+Gtk::StockID const ZOOM_SELECTION("zoom-selection");
+Gtk::StockID const ZOOM_DRAWING("zoom-drawing");
+Gtk::StockID const ZOOM_PAGE("zoom-page");
+Gtk::StockID const ZOOM_WIDTH("zoom-width");
+Gtk::StockID const ZOOM_PREV("zoom-prev");
+Gtk::StockID const ZOOM_NEXT("zoom-next");
+Gtk::StockID const SHOW_HIDE("show-hide");
+Gtk::StockID const SHOW_HIDE_COMMANDS_BAR("show-hide-commands-bar");
+Gtk::StockID const SHOW_HIDE_TOOL_CONTROLS_BAR("show-hide-tool-controls-bar");
+Gtk::StockID const SHOW_HIDE_TOOLS_BAR("show-hide-tools-bar");
+Gtk::StockID const SHOW_HIDE_RULERS("show-hide-rulers");
+Gtk::StockID const SHOW_HIDE_SCROLLBARS("show-hide-scrollbars");
+Gtk::StockID const SHOW_HIDE_STATUSBAR("show-hide-statusbar");
+Gtk::StockID const SHOW_HIDE_DIALOGS("show-hide-dialogs");
+Gtk::StockID const GRID("grid");
+Gtk::StockID const GUIDES("guides");
+Gtk::StockID const FULLSCREEN("fullscreen");
+Gtk::StockID const MESSAGES("messages");
+Gtk::StockID const SCRIPTS("scripts");
+Gtk::StockID const WINDOW_PREV("window-prev");
+Gtk::StockID const WINDOW_NEXT("window-next");
+Gtk::StockID const WINDOW_DUPLICATE("window-duplicate");
+// Layer menu
+Gtk::StockID const LAYER_NEW("layer-new");
+Gtk::StockID const LAYER_RENAME("layer-rename");
+Gtk::StockID const LAYER_DUPLICATE("layer-duplicate");
+Gtk::StockID const LAYER_ANCHOR("layer-anchor");
+Gtk::StockID const LAYER_MERGE_DOWN("layer-merge-down");
+Gtk::StockID const LAYER_DELETE("layer-delete");
+Gtk::StockID const LAYER_SELECT_NEXT("layer-select-next");
+Gtk::StockID const LAYER_SELECT_PREV("layer-select-prev");
+Gtk::StockID const LAYER_SELECT_TOP("layer-select-top");
+Gtk::StockID const LAYER_SELECT_BOTTOM("layer-select-bottom");
+Gtk::StockID const LAYER_RAISE("layer-raise");
+Gtk::StockID const LAYER_LOWER("layer-lower");
+Gtk::StockID const LAYER_TO_TOP("layer-to-top");
+Gtk::StockID const LAYER_TO_BOTTOM("layer-to-bottom");
+// Object menu
+Gtk::StockID const FILL_STROKE("fill-stroke");
+Gtk::StockID const OBJECT_PROPERTIES("object-properties");
+Gtk::StockID const GROUP("group");
+Gtk::StockID const UNGROUP("upgroup");
+Gtk::StockID const RAISE("raise");
+Gtk::StockID const LOWER("lower");
+Gtk::StockID const RAISE_TO_TOP("raise-to-top");
+Gtk::StockID const LOWER_TO_BOTTOM("lower-to-bottom");
+Gtk::StockID const MOVE_TO_NEW_LAYER("move-to-new-layer");
+Gtk::StockID const MOVE_TO_NEXT_LAYER("move-to-next-layer");
+Gtk::StockID const MOVE_TO_PREV_LAYER("move-to-prev-layer");
+Gtk::StockID const MOVE_TO_TOP_LAYER("move-to-top-layer");
+Gtk::StockID const MOVE_TO_BOTTOM_LAYER("move-to-bottom-layer");
+Gtk::StockID const ROTATE_90_CW("rotate-90-cw");
+Gtk::StockID const ROTATE_90_CCW("rotate-90-ccw");
+Gtk::StockID const FLIP_HORIZ("flip-horiz");
+Gtk::StockID const FLIP_VERT("flip-vert");
+Gtk::StockID const TRANSFORM("transform");
+Gtk::StockID const TRANSFORMATION("transformation");
+Gtk::StockID const ALIGN_DISTRIBUTE("align-distribute");
+// Path menu
+Gtk::StockID const OBJECT_TO_PATH("object-to-path");
+Gtk::StockID const STROKE_TO_PATH("stroke-to-path");
+Gtk::StockID const TRACE("trace");
+Gtk::StockID const UNION("union");
+Gtk::StockID const DIFFERENCE("difference");
+Gtk::StockID const INTERSECTION("intersection");
+Gtk::StockID const EXCLUSION("exclusion");
+Gtk::StockID const DIVISION("division");
+Gtk::StockID const CUT_PATH("cut-path");
+Gtk::StockID const COMBINE("combine");
+Gtk::StockID const BREAK_APART("break-apart");
+Gtk::StockID const INSET("inset");
+Gtk::StockID const OUTSET("outset");
+Gtk::StockID const OFFSET_DYNAMIC("offset-dynamic");
+Gtk::StockID const OFFSET_LINKED("offset-linked");
+Gtk::StockID const SIMPLIFY("simplify");
+Gtk::StockID const REVERSE("reverse");
+//Gtk::StockID const CLEANUP("cleanup"); (using Gtk::Stock::CLEAR)
+// Text menu
+Gtk::StockID const TEXT_PROPERTIES("text-properties");
+Gtk::StockID const PUT_ON_PATH("put-on-path");
+Gtk::StockID const REMOVE_FROM_PATH("remove-from-path");
+Gtk::StockID const REMOVE_MANUAL_KERNS("remove-manual-kerns");
+// About menu
+Gtk::StockID const KEYS_MOUSE("keys-mouse");
+Gtk::StockID const TUTORIALS("tutorials");
+Gtk::StockID const ABOUT("about");
+Gtk::StockID const ABOUT_SPLASH("about-splash");
+Gtk::StockID const ABOUT_42("about-42");
+Gtk::StockID const ABOUT_QUICK_HELP("about-quick-help");
+// Tools bar
+Gtk::StockID const TOOL_SELECT("tool-select");
+Gtk::StockID const TOOL_NODE("tool-node");
+Gtk::StockID const TOOL_ZOOM("tool-zoom");
+Gtk::StockID const TOOL_RECT("tool-rect");
+Gtk::StockID const TOOL_ARC("tool-arc");
+Gtk::StockID const TOOL_STAR("tool-star");
+Gtk::StockID const TOOL_SPIRAL("tool-spiral");
+Gtk::StockID const TOOL_FREEHAND("tool-freehand");
+Gtk::StockID const TOOL_PEN("tool-pen");
+Gtk::StockID const TOOL_DYNADRAW("tool-dynadraw");
+Gtk::StockID const TOOL_TEXT("tool-text");
+Gtk::StockID const TOOL_DROPPER("tool-dropper");
+// Select Tool controls
+Gtk::StockID const TRANSFORM_STROKE("transform-stroke");
+Gtk::StockID const TRANSFORM_CORNERS("transform-corners");
+Gtk::StockID const TRANSFORM_GRADIENT("transform-gradient");
+Gtk::StockID const TRANSFORM_PATTERN("transform-pattern");
+// Node Tool controls
+Gtk::StockID const NODE_INSERT("node-insert");
+Gtk::StockID const NODE_DELETE("node-delete");
+Gtk::StockID const NODE_JOIN("node-join");
+Gtk::StockID const NODE_JOIN_SEGMENT("node-join-segment");
+Gtk::StockID const NODE_DELETE_SEGMENT("node-delete-segment");
+Gtk::StockID const NODE_BREAK("node-break");
+Gtk::StockID const NODE_CORNER("node-corner");
+Gtk::StockID const NODE_SMOOTH("node-smooth");
+Gtk::StockID const NODE_SYMMETRIC("node-symmetric");
+Gtk::StockID const NODE_LINE("node-line");
+Gtk::StockID const NODE_CURVE("node-curve");
+// Calligraphy Tool controls
+Gtk::StockID const USE_PRESSURE("use-pressure");
+Gtk::StockID const USE_TILT("use-tilt");
+
+Gtk::StockID const SESSION_PLAYBACK_REW("session-rewind");
+Gtk::StockID const SESSION_PLAYBACK_STEPBACK("session-stepback");
+Gtk::StockID const SESSION_PLAYBACK_PAUSE("session-pause");
+Gtk::StockID const SESSION_PLAYBACK_STEPFORWARD("session-stepforward");
+Gtk::StockID const SESSION_PLAYBACK_PLAY("session-play");
+
+} // namespace Stock
+} // 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/stock.h b/src/ui/stock.h
new file mode 100644
index 000000000..d990186cb
--- /dev/null
+++ b/src/ui/stock.h
@@ -0,0 +1,192 @@
+/**
+ * \brief StockIDs for Inkscape-specific stock items and icons.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_STOCK_H
+#define INKSCAPE_UI_STOCK_H
+
+#include <gtkmm/stockid.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Stock {
+
+// File menu
+extern Gtk::StockID const OPEN_RECENT;
+extern Gtk::StockID const IMPORT;
+extern Gtk::StockID const EXPORT;
+extern Gtk::StockID const VACUUM_DEFS;
+// Edit menu
+extern Gtk::StockID const PASTE_IN_PLACE;
+extern Gtk::StockID const PASTE_STYLE;
+extern Gtk::StockID const DUPLICATE;
+extern Gtk::StockID const CLONE;
+extern Gtk::StockID const CLONE_UNLINK;
+extern Gtk::StockID const CLONE_SELECT_ORIG;
+extern Gtk::StockID const MAKE_BITMAP;
+extern Gtk::StockID const TILE;
+extern Gtk::StockID const UNTILE;
+extern Gtk::StockID const SELECT_ALL;
+extern Gtk::StockID const SELECT_ALL_IN_ALL_LAYERS;
+extern Gtk::StockID const SELECT_INVERT;
+extern Gtk::StockID const SELECT_NONE;
+extern Gtk::StockID const XML_EDITOR;
+// View menu
+extern Gtk::StockID const ZOOM;
+extern Gtk::StockID const ZOOM_IN;
+extern Gtk::StockID const ZOOM_OUT;
+extern Gtk::StockID const ZOOM_100;
+extern Gtk::StockID const ZOOM_50;
+extern Gtk::StockID const ZOOM_200;
+extern Gtk::StockID const ZOOM_SELECTION;
+extern Gtk::StockID const ZOOM_DRAWING;
+extern Gtk::StockID const ZOOM_PAGE;
+extern Gtk::StockID const ZOOM_WIDTH;
+extern Gtk::StockID const ZOOM_PREV;
+extern Gtk::StockID const ZOOM_NEXT;
+extern Gtk::StockID const SHOW_HIDE;
+extern Gtk::StockID const SHOW_HIDE_COMMANDS_BAR;
+extern Gtk::StockID const SHOW_HIDE_TOOL_CONTROLS_BAR;
+extern Gtk::StockID const SHOW_HIDE_TOOLS_BAR;
+extern Gtk::StockID const SHOW_HIDE_RULERS;
+extern Gtk::StockID const SHOW_HIDE_SCROLLBARS;
+extern Gtk::StockID const SHOW_HIDE_STATUSBAR;
+extern Gtk::StockID const SHOW_HIDE_DIALOGS;
+extern Gtk::StockID const GRID;
+extern Gtk::StockID const GUIDES;
+extern Gtk::StockID const FULLSCREEN;
+extern Gtk::StockID const MESSAGES;
+extern Gtk::StockID const SCRIPTS;
+extern Gtk::StockID const WINDOW_PREV;
+extern Gtk::StockID const WINDOW_NEXT;
+extern Gtk::StockID const WINDOW_DUPLICATE;
+// Layer menu
+extern Gtk::StockID const LAYER_NEW;
+extern Gtk::StockID const LAYER_RENAME;
+extern Gtk::StockID const LAYER_DUPLICATE;
+extern Gtk::StockID const LAYER_ANCHOR;
+extern Gtk::StockID const LAYER_MERGE_DOWN;
+extern Gtk::StockID const LAYER_DELETE;
+extern Gtk::StockID const LAYER_SELECT_NEXT;
+extern Gtk::StockID const LAYER_SELECT_PREV;
+extern Gtk::StockID const LAYER_SELECT_TOP;
+extern Gtk::StockID const LAYER_SELECT_BOTTOM;
+extern Gtk::StockID const LAYER_RAISE;
+extern Gtk::StockID const LAYER_LOWER;
+extern Gtk::StockID const LAYER_TO_TOP;
+extern Gtk::StockID const LAYER_TO_BOTTOM;
+// Object menu
+extern Gtk::StockID const FILL_STROKE;
+extern Gtk::StockID const OBJECT_PROPERTIES;
+extern Gtk::StockID const GROUP;
+extern Gtk::StockID const UNGROUP;
+extern Gtk::StockID const RAISE;
+extern Gtk::StockID const LOWER;
+extern Gtk::StockID const RAISE_TO_TOP;
+extern Gtk::StockID const LOWER_TO_BOTTOM;
+extern Gtk::StockID const MOVE_TO_NEW_LAYER;
+extern Gtk::StockID const MOVE_TO_NEXT_LAYER;
+extern Gtk::StockID const MOVE_TO_PREV_LAYER;
+extern Gtk::StockID const MOVE_TO_TOP_LAYER;
+extern Gtk::StockID const MOVE_TO_BOTTOM_LAYER;
+extern Gtk::StockID const ROTATE_90_CW;
+extern Gtk::StockID const ROTATE_90_CCW;
+extern Gtk::StockID const FLIP_HORIZ;
+extern Gtk::StockID const FLIP_VERT;
+extern Gtk::StockID const TRANSFORM;
+extern Gtk::StockID const TRANSFORMATION;
+extern Gtk::StockID const ALIGN_DISTRIBUTE;
+// Path menu
+extern Gtk::StockID const OBJECT_TO_PATH;
+extern Gtk::StockID const STROKE_TO_PATH;
+extern Gtk::StockID const TRACE;
+extern Gtk::StockID const UNION;
+extern Gtk::StockID const DIFFERENCE;
+extern Gtk::StockID const INTERSECTION;
+extern Gtk::StockID const EXCLUSION;
+extern Gtk::StockID const DIVISION;
+extern Gtk::StockID const CUT_PATH;
+extern Gtk::StockID const COMBINE;
+extern Gtk::StockID const BREAK_APART;
+extern Gtk::StockID const INSET;
+extern Gtk::StockID const OUTSET;
+extern Gtk::StockID const OFFSET_DYNAMIC;
+extern Gtk::StockID const OFFSET_LINKED;
+extern Gtk::StockID const SIMPLIFY;
+extern Gtk::StockID const REVERSE;
+//extern Gtk::StockID const CLEANUP; (using Gtk::Stock::CLEAR)
+// Text menu
+extern Gtk::StockID const TEXT_PROPERTIES;
+extern Gtk::StockID const PUT_ON_PATH;
+extern Gtk::StockID const REMOVE_FROM_PATH;
+extern Gtk::StockID const REMOVE_MANUAL_KERNS;
+// About menu
+extern Gtk::StockID const KEYS_MOUSE;
+extern Gtk::StockID const TUTORIALS;
+extern Gtk::StockID const ABOUT;
+extern Gtk::StockID const ABOUT_SPLASH;
+extern Gtk::StockID const ABOUT_42;
+extern Gtk::StockID const ABOUT_QUICK_HELP;
+// Tools bar
+extern Gtk::StockID const TOOL_SELECT;
+extern Gtk::StockID const TOOL_NODE;
+extern Gtk::StockID const TOOL_ZOOM;
+extern Gtk::StockID const TOOL_RECT;
+extern Gtk::StockID const TOOL_ARC;
+extern Gtk::StockID const TOOL_STAR;
+extern Gtk::StockID const TOOL_SPIRAL;
+extern Gtk::StockID const TOOL_FREEHAND;
+extern Gtk::StockID const TOOL_PEN;
+extern Gtk::StockID const TOOL_DYNADRAW;
+extern Gtk::StockID const TOOL_TEXT;
+extern Gtk::StockID const TOOL_DROPPER;
+// Select Tool controls
+extern Gtk::StockID const TRANSFORM_STROKE;
+extern Gtk::StockID const TRANSFORM_CORNERS;
+extern Gtk::StockID const TRANSFORM_GRADIENT;
+extern Gtk::StockID const TRANSFORM_PATTERN;
+// Node Tool controls
+extern Gtk::StockID const NODE_INSERT;
+extern Gtk::StockID const NODE_DELETE;
+extern Gtk::StockID const NODE_JOIN;
+extern Gtk::StockID const NODE_JOIN_SEGMENT;
+extern Gtk::StockID const NODE_DELETE_SEGMENT;
+extern Gtk::StockID const NODE_BREAK;
+extern Gtk::StockID const NODE_CORNER;
+extern Gtk::StockID const NODE_SMOOTH;
+extern Gtk::StockID const NODE_SYMMETRIC;
+extern Gtk::StockID const NODE_LINE;
+extern Gtk::StockID const NODE_CURVE;
+// Calligraphy Tool controls
+extern Gtk::StockID const USE_PRESSURE;
+extern Gtk::StockID const USE_TILT;
+// Session playback dialog controls
+extern Gtk::StockID const SESSION_PLAYBACK_REW;
+extern Gtk::StockID const SESSION_PLAYBACK_STEPBACK;
+extern Gtk::StockID const SESSION_PLAYBACK_PAUSE;
+extern Gtk::StockID const SESSION_PLAYBACK_STEPFORWARD;
+extern Gtk::StockID const SESSION_PLAYBACK_PLAY;
+
+} // namespace Stock
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_STOCK_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/view/.cvsignore b/src/ui/view/.cvsignore
new file mode 100644
index 000000000..38efca7bc
--- /dev/null
+++ b/src/ui/view/.cvsignore
@@ -0,0 +1,3 @@
+.deps
+.dirstamp
+makefile
diff --git a/src/ui/view/Makefile_insert b/src/ui/view/Makefile_insert
new file mode 100644
index 000000000..1b8c57630
--- /dev/null
+++ b/src/ui/view/Makefile_insert
@@ -0,0 +1,27 @@
+## Makefile.am fragment sourced by src/Makefile.am.
+
+ui/view/all: ui/view/libuiview.a
+
+ui/view/clean:
+ rm -f ui/view/libuiview.a $(ui_libuiview_a_OBJECTS)
+
+ui_view_libuiview_a_SOURCES = \
+ ui/view/edit.h \
+ ui/view/edit.cpp \
+ ui/view/edit-widget.h \
+ ui/view/edit-widget.cpp \
+ ui/view/edit-widget-interface.h \
+ ui/view/view.h \
+ ui/view/view.cpp \
+ ui/view/view-widget.cpp \
+ ui/view/view-widget.h \
+ ui/view/desktop.h \
+ ui/view/desktop.cpp \
+ ui/view/desktop-affine.h \
+ ui/view/desktop-affine.cpp \
+ ui/view/desktop-events.h \
+ ui/view/desktop-events.cpp \
+ ui/view/desktop-handles.h \
+ ui/view/desktop-handles.cpp \
+ ui/view/desktop-style.h \
+ ui/view/desktop-style.cpp
diff --git a/src/ui/view/desktop-affine.cpp b/src/ui/view/desktop-affine.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop-affine.cpp
diff --git a/src/ui/view/desktop-affine.h b/src/ui/view/desktop-affine.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop-affine.h
diff --git a/src/ui/view/desktop-events.cpp b/src/ui/view/desktop-events.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop-events.cpp
diff --git a/src/ui/view/desktop-events.h b/src/ui/view/desktop-events.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop-events.h
diff --git a/src/ui/view/desktop-handles.cpp b/src/ui/view/desktop-handles.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop-handles.cpp
diff --git a/src/ui/view/desktop-handles.h b/src/ui/view/desktop-handles.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop-handles.h
diff --git a/src/ui/view/desktop-style.cpp b/src/ui/view/desktop-style.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop-style.cpp
diff --git a/src/ui/view/desktop-style.h b/src/ui/view/desktop-style.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop-style.h
diff --git a/src/ui/view/desktop.cpp b/src/ui/view/desktop.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop.cpp
diff --git a/src/ui/view/desktop.h b/src/ui/view/desktop.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/ui/view/desktop.h
diff --git a/src/ui/view/edit-widget-interface.h b/src/ui/view/edit-widget-interface.h
new file mode 100644
index 000000000..689eff4a7
--- /dev/null
+++ b/src/ui/view/edit-widget-interface.h
@@ -0,0 +1,134 @@
+/**
+ * \file
+ *
+ * Abstract base class for all EditWidget implementations.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Ralf Stephan
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_H
+#define INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_H
+
+#include "gdk/gdktypes.h"
+#include "libnr/nr-point.h"
+#include "message.h"
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+struct EditWidgetInterface
+{
+ EditWidgetInterface() {}
+ virtual ~EditWidgetInterface() {}
+
+ /// Returns pointer to window UI object as void*
+ virtual void *getWindow() = 0;
+
+ /// Set the widget's title
+ virtual void setTitle (gchar const*) = 0;
+
+ /// Show all parts of widget the user wants to see.
+ virtual void layout() = 0;
+
+ /// Present widget to user
+ virtual void present() = 0;
+
+ /// Returns geometry of widget
+ virtual void getGeometry (gint &x, gint &y, gint &w, gint &h) = 0;
+
+ /// Change the widget's size
+ virtual void setSize (gint w, gint h) = 0;
+
+ /// Move widget to specified position
+ virtual void setPosition (NR::Point p) = 0;
+
+ /// Transientize widget
+ virtual void setTransient (void*, int) = 0;
+
+ /// Return mouse position in widget
+ virtual NR::Point getPointer() = 0;
+
+ /// Make widget fill screen and show it if possible.
+ virtual void setFullscreen() = 0;
+
+ /// Shuts down the desktop object for the view being closed. It checks
+ /// to see if the document has been edited, and if so prompts the user
+ /// to save, discard, or cancel. Returns TRUE if the shutdown operation
+ /// is cancelled or if the save is cancelled or fails, FALSE otherwise.
+ virtual bool shutdown() = 0;
+
+ /// Destroy and delete widget.
+ virtual void destroy() = 0;
+
+
+ /// Queue a redraw request with the canvas
+ virtual void requestCanvasUpdate() = 0;
+
+ /// Update the "active desktop" indicator
+ virtual void activateDesktop() = 0;
+
+ /// Update the "inactive desktop" indicator
+ virtual void deactivateDesktop() = 0;
+
+ /// Set rulers to position
+ virtual void viewSetPosition (NR::Point p) = 0;
+
+ /// Update rulers from current values
+ virtual void updateRulers() = 0;
+
+ /// Update scrollbars from current values
+ virtual void updateScrollbars (double scale) = 0;
+
+ /// Toggle rulers on/off and set preference value accordingly
+ virtual void toggleRulers() = 0;
+
+ /// Toggle scrollbars on/off and set preference value accordingly
+ virtual void toggleScrollbars() = 0;
+
+ /// Temporarily block signals and update zoom display
+ virtual void updateZoom() = 0;
+
+ /// The zoom display will get the keyboard focus.
+ virtual void letZoomGrabFocus() = 0;
+
+ /// In auxiliary toolbox, set focus to widget having specific id
+ virtual void setToolboxFocusTo (const gchar *) = 0;
+
+ /// In auxiliary toolbox, set value of adjustment with specific id
+ virtual void setToolboxAdjustmentValue (const gchar *, double) = 0;
+
+ /// In auxiliary toolbox, return true if specific togglebutton is active
+ virtual bool isToolboxButtonActive (gchar const*) = 0;
+
+ /// Set the coordinate display
+ virtual void setCoordinateStatus (NR::Point p) = 0;
+
+ /// Message widget will get no content
+ virtual void setMessage (Inkscape::MessageType type, gchar const* msg) = 0;
+
+ /// Open yes/no dialog with warning text and confirmation question.
+ virtual bool warnDialog (gchar*) = 0;
+};
+
+} // namespace View
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_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/view/edit-widget.cpp b/src/ui/view/edit-widget.cpp
new file mode 100644
index 000000000..5139f8ebf
--- /dev/null
+++ b/src/ui/view/edit-widget.cpp
@@ -0,0 +1,1701 @@
+/**
+ * \brief This class implements the functionality of the window layout, menus,
+ * and signals.
+ *
+ * This is a reimplementation into C++/Gtkmm of Sodipodi's SPDesktopWidget class.
+ * Both SPDesktopWidget and EditWidget adhere to the EditWidgetInterface, so
+ * they both can serve as widget for the same SPDesktop/Edit class.
+ *
+ * Ideally, this class should only contain the handling of the Window (i.e.,
+ * content construction and window signals) and implement its
+ * EditWidgetInterface.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Derek P. Moore <derekm@hackunix.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Frank Felfe <innerspace@iname.com>
+ *
+ * Copyright (C) 1999-2005 Authors
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtkwindow.h>
+#include <gtkmm/radioaction.h>
+#include <gtkmm/menubar.h>
+#include <gtkmm/messagedialog.h>
+#include <gtkmm/stock.h>
+#include <gtkmm/accelmap.h>
+#include <gtkmm/separator.h>
+
+#include "macros.h"
+#include "path-prefix.h"
+#include "prefs-utils.h"
+#include "file.h"
+#include "application/editor.h"
+#include "edit-widget.h"
+#include "ui/stock.h"
+#include "ui/stock-items.h"
+#include "ui/icons.h"
+
+#include "display/sodipodi-ctrlrect.h"
+#include "helper/units.h"
+#include "shortcuts.h"
+#include "widgets/spw-utilities.h"
+#include "event-context.h"
+#include "document.h"
+#include "sp-namedview.h"
+#include "sp-item.h"
+#include "interface.h"
+#include "extension/db.h"
+
+#ifdef WITH_INKBOARD
+#include "ui/dialog/whiteboard-connect.h"
+#include "ui/dialog/whiteboard-sharewithuser.h"
+#include "ui/dialog/whiteboard-sharewithchat.h"
+#endif
+
+using namespace Inkscape::UI;
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+EditWidget::EditWidget (SPDocument *doc)
+ : _main_window_table(4),
+ _viewport_table(3,3),
+ _act_grp(Gtk::ActionGroup::create()),
+ _ui_mgr(Gtk::UIManager::create()),
+ _update_s_f(false),
+ _update_a_f(false)
+{
+ g_warning("Creating new EditWidget");
+
+ _desktop = 0;
+ Icons::init();
+ Stock::init();
+ initActions();
+ initAccelMap();
+ initUIManager();
+ initLayout();
+ initEdit (doc);
+ g_warning("Done creating new EditWidget");
+}
+
+EditWidget::~EditWidget()
+{
+ destroyEdit();
+}
+
+void
+EditWidget::initActions()
+{
+ initMenuActions();
+ initToolbarActions();
+}
+
+void
+EditWidget::initUIManager()
+{
+ _ui_mgr->insert_action_group(_act_grp);
+ add_accel_group(_ui_mgr->get_accel_group());
+
+ gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL);
+ if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) {
+ g_warning("Error merging ui from file '%s'", filename_utf8);
+ // fixme-charset: What charset should we pass to g_warning?
+ }
+ g_free(filename_utf8);
+}
+
+void
+EditWidget::initLayout()
+{
+ set_title("New document 1 - Inkscape");
+ set_resizable();
+ set_default_size(640, 480);
+
+ // top level window into which all other portions of the UI get inserted
+ add(_main_window_table);
+ // attach box for horizontal toolbars
+ _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
+ // attach sub-window for viewport and vertical toolbars
+ _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3);
+ // viewport table with 3 rows by 3 columns
+ _sub_window_hbox.pack_end(_viewport_table);
+
+ // Menus and Bars
+ initMenuBar();
+ initCommandsBar();
+ initToolControlsBar();
+ initUriBar();
+ initToolsBar();
+
+ // Canvas Viewport
+ initLeftRuler();
+ initTopRuler();
+ initStickyZoom();
+ initBottomScrollbar();
+ initRightScrollbar();
+ _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+ _svg_canvas.widget().show_all();
+
+
+ // The statusbar comes last and appears at the bottom of _main_window_table
+ initStatusbar();
+
+ signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
+ signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
+ show_all_children();
+}
+
+void
+EditWidget::onMenuItem()
+{
+ g_warning("onMenuItem called");
+}
+
+void
+EditWidget::onActionFileNew()
+{
+// g_warning("onActionFileNew called");
+ sp_file_new_default();
+}
+
+void
+EditWidget::onActionFileOpen()
+{
+// g_warning("onActionFileOpen called");
+ sp_file_open_dialog (NULL, NULL);
+}
+
+void
+EditWidget::onActionFileQuit()
+{
+ g_warning("onActionFileQuit");
+ sp_ui_close_all();
+}
+
+void
+EditWidget::onActionFilePrint()
+{
+ g_warning("onActionFilePrint");
+}
+
+void
+EditWidget::onToolbarItem()
+{
+ g_warning("onToolbarItem called");
+}
+
+void
+EditWidget::onSelectTool()
+{
+ _tool_ctrl->remove();
+ _tool_ctrl->add(*_select_ctrl);
+}
+
+void
+EditWidget::onNodeTool()
+{
+ _tool_ctrl->remove();
+ _tool_ctrl->add(*_node_ctrl);
+}
+
+void
+EditWidget::onDialogInkscapePreferences()
+{
+ _dlg_mgr.showDialog("InkscapePreferences");
+}
+
+void
+EditWidget::onDialogAbout()
+{
+}
+
+void
+EditWidget::onDialogAlignAndDistribute()
+{
+ _dlg_mgr.showDialog("AlignAndDistribute");
+}
+
+void
+EditWidget::onDialogDocumentProperties()
+{
+// manage (Inkscape::UI::Dialog::DocumentPreferences::create());
+ _dlg_mgr.showDialog("DocumentPreferences");
+}
+
+void
+EditWidget::onDialogExport()
+{
+ _dlg_mgr.showDialog("Export");
+}
+
+void
+EditWidget::onDialogExtensionEditor()
+{
+ _dlg_mgr.showDialog("ExtensionEditor");
+}
+
+void
+EditWidget::onDialogFillAndStroke()
+{
+ _dlg_mgr.showDialog("FillAndStroke");
+}
+
+void
+EditWidget::onDialogFind()
+{
+ _dlg_mgr.showDialog("Find");
+}
+
+void
+EditWidget::onDialogLayerEditor()
+{
+ _dlg_mgr.showDialog("LayerEditor");
+}
+
+void
+EditWidget::onDialogMessages()
+{
+ _dlg_mgr.showDialog("Messages");
+}
+
+void
+EditWidget::onDialogObjectProperties()
+{
+ _dlg_mgr.showDialog("ObjectProperties");
+}
+
+void
+EditWidget::onDialogTextProperties()
+{
+ _dlg_mgr.showDialog("TextProperties");
+}
+
+void
+EditWidget::onDialogTrace()
+{
+}
+
+void
+EditWidget::onDialogTransformation()
+{
+ _dlg_mgr.showDialog("Transformation");
+}
+
+void
+EditWidget::onDialogXmlEditor()
+{
+ _dlg_mgr.showDialog("XmlEditor");
+}
+
+#ifdef WITH_INKBOARD
+void
+EditWidget::onDialogWhiteboardConnect()
+{
+ Dialog::WhiteboardConnectDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardConnectDialogImpl* >(_dlg_mgr.getDialog("WhiteboardConnect"));
+ dlg->setSessionManager();
+ _dlg_mgr.showDialog("WhiteboardConnect");
+}
+
+void
+EditWidget::onDialogWhiteboardShareWithUser()
+{
+ Dialog::WhiteboardShareWithUserDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithUserDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithUser"));
+ dlg->setSessionManager();
+ _dlg_mgr.showDialog("WhiteboardShareWithUser");
+}
+
+void
+EditWidget::onDialogWhiteboardShareWithChat()
+{
+ Dialog::WhiteboardShareWithChatroomDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithChatroomDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithChat"));
+ dlg->setSessionManager();
+ _dlg_mgr.showDialog("WhiteboardShareWithChat");
+}
+
+void
+EditWidget::onDialogOpenSessionFile()
+{
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet");
+}
+
+void
+EditWidget::onDumpXMLTracker()
+{
+ g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet");
+}
+
+#endif
+
+void
+EditWidget::onUriChanged()
+{
+ g_message("onUriChanged called");
+
+}
+
+// FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
+// See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
+
+void
+EditWidget::initMenuActions()
+{
+// _act_grp->add(Gtk::Action::create("MenuFile", _("PLACEHOLDER, do not translate")));
+// _act_grp->add(Gtk::Action::create("MenuEdit", _("PLACEHOLDER, do not translate")));
+// _act_grp->add(Gtk::Action::create("MenuView", _("PLACEHOLDER, do not translate")));
+// _act_grp->add(Gtk::Action::create("MenuLayer", _("PLACEHOLDER, do not translate")));
+// _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
+// _act_grp->add(Gtk::Action::create("MenuPath", _("PLACEHOLDER, do not translate")));
+// _act_grp->add(Gtk::Action::create("MenuText", _("PLACEHOLDER, do not translate")));
+#ifdef WITH_INKBOARD
+// _act_grp->add(Gtk::Action::create("MenuWhiteboard", _("PLACEHOLDER, do not translate")));
+#endif
+// _act_grp->add(Gtk::Action::create("MenuHelp", _("PLACEHOLDER, do not translate")));
+// temporarily replaced with non-gettext version to have a well-sized menu
+// for testing:
+
+ _act_grp->add(Gtk::Action::create("MenuFile", "File"));
+ _act_grp->add(Gtk::Action::create("MenuEdit", "Edit"));
+ _act_grp->add(Gtk::Action::create("MenuView", "View"));
+ _act_grp->add(Gtk::Action::create("MenuLayer", "Layer"));
+ _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
+ _act_grp->add(Gtk::Action::create("MenuPath", "Path"));
+ _act_grp->add(Gtk::Action::create("MenuText", "Text"));
+#ifdef WITH_INKBOARD
+ _act_grp->add(Gtk::Action::create("MenuWhiteboard", "Whiteboard"));
+#endif
+ _act_grp->add(Gtk::Action::create("MenuHelp", "Help"));
+
+ // File menu
+ _act_grp->add(Gtk::Action::create("New",
+ Gtk::Stock::NEW, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onActionFileNew));
+
+ _act_grp->add(Gtk::Action::create("Open",
+ Gtk::Stock::OPEN, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
+
+ _act_grp->add(Gtk::Action::create("OpenRecent",
+ Stock::OPEN_RECENT));
+
+ _act_grp->add(Gtk::Action::create("Revert",
+ Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
+
+ _act_grp->add(Gtk::Action::create("Save",
+ Gtk::Stock::SAVE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
+
+ _act_grp->add(Gtk::Action::create("SaveAs",
+ Gtk::Stock::SAVE_AS, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
+
+ _act_grp->add(Gtk::Action::create("Import",
+ Stock::IMPORT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
+
+ _act_grp->add(Gtk::Action::create("Export",
+ Stock::EXPORT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogExport));
+
+ _act_grp->add(Gtk::Action::create("Print",
+ Gtk::Stock::PRINT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
+
+ _act_grp->add(Gtk::Action::create("PrintPreview",
+ Gtk::Stock::PRINT_PREVIEW),
+ sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
+
+ _act_grp->add(Gtk::Action::create("VacuumDefs",
+ Stock::VACUUM_DEFS),
+ sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
+
+ _act_grp->add(Gtk::Action::create("DocumentProperties",
+ Gtk::Stock::PROPERTIES, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
+
+ _act_grp->add(Gtk::Action::create("InkscapePreferences",
+ Gtk::Stock::PREFERENCES, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
+
+ _act_grp->add(Gtk::Action::create("Close",
+ Gtk::Stock::CLOSE),
+ sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
+
+ _act_grp->add(Gtk::Action::create("Quit",
+ Gtk::Stock::QUIT),
+ sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
+
+ // EditWidget menu
+ _act_grp->add(Gtk::Action::create("Undo",
+ Gtk::Stock::UNDO, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Redo",
+ Gtk::Stock::REDO, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Cut",
+ Gtk::Stock::CUT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Copy",
+ Gtk::Stock::COPY, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Paste",
+ Gtk::Stock::PASTE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("PasteInPlace",
+ Stock::PASTE_IN_PLACE));
+
+ _act_grp->add(Gtk::Action::create("PasteStyle",
+ Stock::PASTE_STYLE));
+
+ _act_grp->add(Gtk::Action::create("Find",
+ Gtk::Stock::FIND),
+ sigc::mem_fun(*this, &EditWidget::onDialogFind));
+
+ _act_grp->add(Gtk::Action::create("Duplicate",
+ Stock::DUPLICATE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Clone",
+ Stock::CLONE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("CloneUnlink",
+ Stock::CLONE_UNLINK, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("CloneSelectOrig",
+ Stock::CLONE_SELECT_ORIG));
+
+ _act_grp->add(Gtk::Action::create("MakeBitmap",
+ Stock::MAKE_BITMAP));
+
+ _act_grp->add(Gtk::Action::create("Tile",
+ Stock::TILE));
+
+ _act_grp->add(Gtk::Action::create("Untile",
+ Stock::UNTILE));
+
+ _act_grp->add(Gtk::Action::create("Delete",
+ Gtk::Stock::DELETE));
+
+ _act_grp->add(Gtk::Action::create("SelectAll",
+ Stock::SELECT_ALL));
+
+ _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
+ Stock::SELECT_ALL_IN_ALL_LAYERS));
+
+ _act_grp->add(Gtk::Action::create("SelectInvert",
+ Stock::SELECT_INVERT));
+
+ _act_grp->add(Gtk::Action::create("SelectNone",
+ Stock::SELECT_NONE));
+
+ _act_grp->add(Gtk::Action::create("XmlEditor",
+ Stock::XML_EDITOR, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
+
+ // View menu
+ _act_grp->add(Gtk::Action::create("Zoom",
+ Stock::ZOOM));
+
+ _act_grp->add(Gtk::Action::create("ZoomIn",
+ Stock::ZOOM_IN, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("ZoomOut",
+ Stock::ZOOM_OUT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Zoom100",
+ Stock::ZOOM_100, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Zoom50",
+ Stock::ZOOM_50, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Zoom200",
+ Stock::ZOOM_200, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("ZoomSelection",
+ Stock::ZOOM_SELECTION, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("ZoomDrawing",
+ Stock::ZOOM_DRAWING, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("ZoomPage",
+ Stock::ZOOM_PAGE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("ZoomWidth",
+ Stock::ZOOM_WIDTH, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("ZoomPrev",
+ Stock::ZOOM_PREV, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("ZoomNext",
+ Stock::ZOOM_NEXT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("ShowHide",
+ Stock::SHOW_HIDE));
+
+ _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
+ Stock::SHOW_HIDE_COMMANDS_BAR));
+
+ _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
+ Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
+
+ _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
+ Stock::SHOW_HIDE_TOOLS_BAR));
+
+ _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
+ Stock::SHOW_HIDE_RULERS));
+
+ _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
+ Stock::SHOW_HIDE_SCROLLBARS));
+
+ _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
+ Stock::SHOW_HIDE_STATUSBAR));
+
+ _act_grp->add(Gtk::Action::create("ShowHideDialogs",
+ Stock::SHOW_HIDE_DIALOGS));
+
+ _act_grp->add(Gtk::Action::create("Grid",
+ Stock::GRID));
+
+ _act_grp->add(Gtk::Action::create("Guides",
+ Stock::GUIDES));
+
+ _act_grp->add(Gtk::Action::create("Fullscreen",
+ Stock::FULLSCREEN));
+
+ _act_grp->add(Gtk::Action::create("Messages",
+ Stock::MESSAGES),
+ sigc::mem_fun(*this, &EditWidget::onDialogMessages));
+
+ _act_grp->add(Gtk::Action::create("Scripts",
+ Stock::SCRIPTS));
+
+ _act_grp->add(Gtk::Action::create("WindowPrev",
+ Stock::WINDOW_PREV));
+
+ _act_grp->add(Gtk::Action::create("WindowNext",
+ Stock::WINDOW_NEXT));
+
+ _act_grp->add(Gtk::Action::create("WindowDuplicate",
+ Stock::WINDOW_DUPLICATE));
+
+ // Layer menu
+ _act_grp->add(Gtk::Action::create("LayerNew",
+ Stock::LAYER_NEW));
+
+ _act_grp->add(Gtk::Action::create("LayerRename",
+ Stock::LAYER_RENAME));
+
+ _act_grp->add(Gtk::Action::create("LayerDuplicate",
+ Stock::LAYER_DUPLICATE));
+
+ _act_grp->add(Gtk::Action::create("LayerAnchor",
+ Stock::LAYER_ANCHOR));
+
+ _act_grp->add(Gtk::Action::create("LayerMergeDown",
+ Stock::LAYER_MERGE_DOWN));
+
+ _act_grp->add(Gtk::Action::create("LayerDelete",
+ Stock::LAYER_DELETE));
+
+ _act_grp->add(Gtk::Action::create("LayerSelectNext",
+ Stock::LAYER_SELECT_NEXT));
+
+ _act_grp->add(Gtk::Action::create("LayerSelectPrev",
+ Stock::LAYER_SELECT_PREV));
+
+ _act_grp->add(Gtk::Action::create("LayerSelectTop",
+ Stock::LAYER_SELECT_TOP));
+
+ _act_grp->add(Gtk::Action::create("LayerSelectBottom",
+ Stock::LAYER_SELECT_BOTTOM));
+
+ _act_grp->add(Gtk::Action::create("LayerRaise",
+ Stock::LAYER_RAISE));
+
+ _act_grp->add(Gtk::Action::create("LayerLower",
+ Stock::LAYER_LOWER));
+
+ _act_grp->add(Gtk::Action::create("LayerToTop",
+ Stock::LAYER_TO_TOP));
+
+ _act_grp->add(Gtk::Action::create("LayerToBottom",
+ Stock::LAYER_TO_BOTTOM));
+
+ // Object menu
+ _act_grp->add(Gtk::Action::create("FillAndStroke",
+ Stock::FILL_STROKE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
+
+ _act_grp->add(Gtk::Action::create("ObjectProperties",
+ Stock::OBJECT_PROPERTIES),
+ sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
+
+ _act_grp->add(Gtk::Action::create("Group",
+ Stock::GROUP, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Ungroup",
+ Stock::UNGROUP, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Raise",
+ Stock::RAISE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Lower",
+ Stock::LOWER, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("RaiseToTop",
+ Stock::RAISE_TO_TOP, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("LowerToBottom",
+ Stock::LOWER_TO_BOTTOM, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("MoveToNewLayer",
+ Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("MoveToNextLayer",
+ Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
+ Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("MoveToTopLayer",
+ Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
+ Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Rotate90CW",
+ Stock::ROTATE_90_CW, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Rotate90CCW",
+ Stock::ROTATE_90_CCW, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("FlipHoriz",
+ Stock::FLIP_HORIZ, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("FlipVert",
+ Stock::FLIP_VERT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Transformation",
+ Stock::TRANSFORMATION, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
+
+ _act_grp->add(Gtk::Action::create("AlignAndDistribute",
+ Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
+
+ // Path menu
+ _act_grp->add(Gtk::Action::create("ObjectToPath",
+ Stock::OBJECT_TO_PATH, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("StrokeToPath",
+ Stock::STROKE_TO_PATH, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("Trace",
+ Stock::TRACE),
+ sigc::mem_fun(*this, &EditWidget::onDialogTrace));
+
+ _act_grp->add(Gtk::Action::create("Union",
+ Stock::UNION));
+
+ _act_grp->add(Gtk::Action::create("Difference",
+ Stock::DIFFERENCE));
+
+ _act_grp->add(Gtk::Action::create("Intersection",
+ Stock::INTERSECTION));
+
+ _act_grp->add(Gtk::Action::create("Exclusion",
+ Stock::EXCLUSION));
+
+ _act_grp->add(Gtk::Action::create("Division",
+ Stock::DIVISION));
+
+ _act_grp->add(Gtk::Action::create("CutPath",
+ Stock::CUT_PATH));
+
+ _act_grp->add(Gtk::Action::create("Combine",
+ Stock::COMBINE));
+
+ _act_grp->add(Gtk::Action::create("BreakApart",
+ Stock::BREAK_APART));
+
+ _act_grp->add(Gtk::Action::create("Inset",
+ Stock::INSET));
+
+ _act_grp->add(Gtk::Action::create("Outset",
+ Stock::OUTSET));
+
+ _act_grp->add(Gtk::Action::create("OffsetDynamic",
+ Stock::OFFSET_DYNAMIC));
+
+ _act_grp->add(Gtk::Action::create("OffsetLinked",
+ Stock::OFFSET_LINKED));
+
+ _act_grp->add(Gtk::Action::create("Simplify",
+ Stock::SIMPLIFY));
+
+ _act_grp->add(Gtk::Action::create("Reverse",
+ Stock::REVERSE));
+
+ _act_grp->add(Gtk::Action::create("Cleanup",
+ Gtk::Stock::CLEAR,
+ _("PLACEHOLDER, do not translate")));
+
+ // Text menu
+ _act_grp->add(Gtk::Action::create("TextProperties",
+ Gtk::Stock::SELECT_FONT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
+
+ _act_grp->add(Gtk::Action::create("PutOnPath",
+ Stock::PUT_ON_PATH));
+
+ _act_grp->add(Gtk::Action::create("RemoveFromPath",
+ Stock::REMOVE_FROM_PATH));
+
+ _act_grp->add(Gtk::Action::create("RemoveManualKerns",
+ Stock::REMOVE_MANUAL_KERNS));
+
+ // Whiteboard menu
+#ifdef WITH_INKBOARD
+ _act_grp->add(Gtk::Action::create("DialogWhiteboardConnect",
+ Gtk::Stock::CLEAR, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardConnect));
+
+ _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithUser",
+ Gtk::Stock::CLEAR, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithUser));
+
+ _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithChat",
+ Gtk::Stock::CLEAR, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithChat));
+
+ _act_grp->add(Gtk::Action::create("WhiteboardOpenSessionFile",
+ Gtk::Stock::CLEAR, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDialogOpenSessionFile));
+
+ _act_grp->add(Gtk::Action::create("WhiteboardDumpXMLTracker",
+ Gtk::Stock::CLEAR, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onDumpXMLTracker));
+#endif
+
+ // About menu
+ _act_grp->add(Gtk::Action::create("KeysAndMouse",
+ Stock::KEYS_MOUSE));
+
+ _act_grp->add(Gtk::Action::create("Tutorials",
+ Stock::TUTORIALS));
+
+ _act_grp->add(Gtk::Action::create("About",
+ Stock::ABOUT),
+ sigc::mem_fun(*this, &EditWidget::onDialogAbout));
+}
+
+void
+EditWidget::initToolbarActions()
+{
+ // Tools bar
+ Gtk::RadioAction::Group tools;
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
+ Stock::TOOL_SELECT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onSelectTool));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
+ Stock::TOOL_NODE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")),
+ sigc::mem_fun(*this, &EditWidget::onNodeTool));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
+ Stock::TOOL_ZOOM, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
+ Stock::TOOL_RECT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
+ Stock::TOOL_ARC, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
+ Stock::TOOL_STAR, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
+ Stock::TOOL_SPIRAL, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
+ Stock::TOOL_FREEHAND, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
+ Stock::TOOL_PEN, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
+ Stock::TOOL_DYNADRAW, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
+ Stock::TOOL_TEXT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
+ Stock::TOOL_DROPPER, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ // Select Controls bar
+ _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
+ Stock::TRANSFORM_STROKE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
+ Stock::TRANSFORM_CORNERS, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
+ Stock::TRANSFORM_GRADIENT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
+ Stock::TRANSFORM_PATTERN, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ // Node Controls bar
+ _act_grp->add(Gtk::Action::create("NodeInsert",
+ Gtk::Stock::ADD, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeDelete",
+ Gtk::Stock::REMOVE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeJoin",
+ Stock::NODE_JOIN, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeJoinSegment",
+ Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
+ Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeBreak",
+ Stock::NODE_BREAK, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeCorner",
+ Stock::NODE_CORNER, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeSmooth",
+ Stock::NODE_SMOOTH, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeSymmetric",
+ Stock::NODE_SYMMETRIC, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeLine",
+ Stock::NODE_LINE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+
+ _act_grp->add(Gtk::Action::create("NodeCurve",
+ Stock::NODE_CURVE, Glib::ustring(),
+ _("PLACEHOLDER, do not translate")));
+}
+
+void
+EditWidget::initAccelMap()
+{
+ gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
+ Gtk::AccelMap::load(filename);
+ g_free(filename);
+
+ // One problem is that the keys 1-6 are zoom accelerators which get
+ // caught as accelerator _before_ any Entry input handler receives them,
+ // for example the zoom status. At the moment, the best way seems to
+ // disable them as accelerators when the Entry gets focus, and enable
+ // them when focus goes elsewhere. The code for this belongs here,
+ // and not in zoom-status.cpp .
+
+ _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
+ _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
+}
+
+bool
+EditWidget::onEntryFocusIn (GdkEventFocus* ev)
+{
+ Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
+ Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
+ return false;
+}
+
+bool
+EditWidget::onEntryFocusOut (GdkEventFocus* ev)
+{
+ Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
+ Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
+ Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
+ return false;
+}
+
+void
+EditWidget::initMenuBar()
+{
+ g_assert(_ui_mgr);
+ Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
+ g_assert(menu != NULL);
+ _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
+}
+
+void
+EditWidget::initCommandsBar()
+{
+ g_assert(_ui_mgr);
+ Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
+ Gtk::TOOLBAR_ICONS);
+ g_assert(bar != NULL);
+ _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
+}
+
+void
+EditWidget::initToolControlsBar()
+{
+ // TODO: Do UIManager controlled widgets need to be deleted?
+ _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
+ _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
+
+ _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
+
+ _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
+}
+
+void
+EditWidget::initUriBar()
+{
+ /// \todo Create an Inkscape::UI::Widget::UriBar class (?)
+
+ _uri_ctrl = new Gtk::Toolbar();
+
+ _uri_label.set_label(_("PLACEHOLDER, DO NOT TRANSLATE"));
+ _uri_ctrl->add(_uri_label);
+ _uri_ctrl->add(_uri_entry);
+
+ _uri_entry.signal_activate()
+ .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
+
+ _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
+}
+
+void
+EditWidget::initToolsBar()
+{
+ Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
+ Gtk::TOOLBAR_ICONS,
+ Gtk::ORIENTATION_VERTICAL);
+ g_assert(bar != NULL);
+ _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
+}
+
+void
+EditWidget::initTopRuler()
+{
+ _viewport_table.attach(_top_ruler, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
+
+ _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
+}
+
+void
+EditWidget::initLeftRuler()
+{
+ _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
+
+ _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
+}
+
+void
+EditWidget::initBottomScrollbar()
+{
+ _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
+ _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
+ _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
+}
+
+void
+EditWidget::initRightScrollbar()
+{
+ _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
+
+ _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
+ _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
+}
+
+void
+EditWidget::initStickyZoom()
+{
+ _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+
+ _sticky_zoom.set_active (prefs_get_int_attribute ("options.stickyzoom", "value", 0) != 0);
+ _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
+
+ /// \todo icon not implemented
+}
+
+void
+EditWidget::initStatusbar()
+{
+ _statusbar.pack_start (_selected_style_status, false, false, 1);
+ _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
+
+ _tooltips.set_tip (_zoom_status, _("Zoom"));
+
+ _layer_selector.reference();
+ _statusbar.pack_start (_layer_selector, false, false, 1);
+
+ _coord_status.property_n_rows() = 2;
+ _coord_status.property_n_columns() = 5;
+ _coord_status.property_row_spacing() = 0;
+ _coord_status.property_column_spacing() = 2;
+ _coord_eventbox.add (_coord_status);
+ _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
+ _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
+ _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
+ _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
+ _coord_status_x.set_text ("0.0");
+ _coord_status_x.set_alignment (0.0, 0.5);
+ _coord_status_y.set_text ("0.0");
+ _coord_status_y.set_alignment (0.0, 0.5);
+ _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
+ _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
+ _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
+ _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
+ sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
+ _statusbar.pack_end (_coord_eventbox, false, false, 1);
+
+ _select_status.property_xalign() = 0.0;
+ _select_status.property_yalign() = 0.5;
+ _select_status.set_markup (_("<b>Welcome to Inkscape!</b> Use shape or freehand tools to create objects; use selector (arrow) to move or transform them."));
+ // include this again with Gtk+-2.6
+ //_select_status.property_ellipsize() = Pango::ELLIPSIZE_END;
+ _select_status.set_size_request (1, -1);
+ _statusbar.pack_start (_select_status, true, true, 0);
+
+ _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
+}
+
+//========================================
+//----------implements EditWidgetInterface
+
+void *
+EditWidget::getWindow()
+{
+ return this;
+}
+
+void
+EditWidget::setTitle (gchar const* new_title)
+{
+ set_title (new_title);
+}
+
+void
+EditWidget::layout()
+{
+ show_all_children();
+}
+
+void
+EditWidget::present()
+{
+ this->Gtk::Window::present();
+}
+
+void
+EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
+{
+ get_position (x, y);
+ get_size (w, h);
+}
+
+void
+EditWidget::setSize (gint w, gint h)
+{
+ resize (w, h);
+}
+
+void
+EditWidget::setPosition (NR::Point p)
+{
+ move (int(p[NR::X]), int(p[NR::Y]));
+}
+
+/// \param p is already gobj()!
+void
+EditWidget::setTransient (void* p, int i)
+{
+#ifndef WIN32
+ gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
+ if (i==2)
+ this->Gtk::Window::present();
+#endif
+}
+
+NR::Point
+EditWidget::getPointer()
+{
+ int x, y;
+ get_pointer (x, y);
+ return NR::Point (x, y);
+}
+
+void
+EditWidget::setFullscreen()
+{
+ fullscreen();
+}
+
+/**
+ * Shuts down the desktop object for the view being closed. It checks
+ * to see if the document has been edited, and if so prompts the user
+ * to save, discard, or cancel. Returns TRUE if the shutdown operation
+ * is cancelled or if the save is cancelled or fails, FALSE otherwise.
+ */
+bool
+EditWidget::shutdown()
+{
+ g_assert (_desktop != NULL);
+ if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
+ return false;
+
+ SPDocument *doc = _desktop->doc();
+ if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL)
+ {
+ gchar *markup;
+ /// \todo FIXME !!! obviously this will have problems if the document
+ /// name contains markup characters
+ markup = g_strdup_printf(
+ _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
+ "If you close without saving, your changes will be discarded."),
+ SP_DOCUMENT_NAME(doc));
+
+ Gtk::MessageDialog dlg (*this,
+ markup,
+ true,
+ Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_NONE,
+ true);
+ g_free(markup);
+ Gtk::Button close_button (_("Close _without saving"), true);
+ dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
+ close_button.show();
+ dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
+ dlg.set_default_response (Gtk::RESPONSE_YES);
+
+ int response = dlg.run();
+ switch (response)
+ {
+ case Gtk::RESPONSE_YES:
+ sp_document_ref(doc);
+ if (sp_file_save_document(doc)) {
+ sp_document_unref(doc);
+ } else { // save dialog cancelled or save failed
+ sp_document_unref(doc);
+ return TRUE;
+ }
+ break;
+ case Gtk::RESPONSE_NO:
+ break;
+ default: // cancel pressed, or dialog was closed
+ return TRUE;
+ break;
+ }
+ }
+
+ /* Code to check data loss */
+ bool allow_data_loss = FALSE;
+ while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
+ {
+ gchar *markup;
+ /// \todo FIXME !!! obviously this will have problems if the document
+ /// name contains markup characters
+ markup = g_strdup_printf(
+ _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
+ "Do you want to save this file in another format?"),
+ SP_DOCUMENT_NAME(doc),
+ Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
+
+ Gtk::MessageDialog dlg (*this,
+ markup,
+ true,
+ Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_NONE,
+ true);
+ g_free(markup);
+ Gtk::Button close_button (_("Close _without saving"), true);
+ dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
+ close_button.show();
+ dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
+ dlg.set_default_response (Gtk::RESPONSE_YES);
+
+ int response = dlg.run();
+
+ switch (response)
+ {
+ case Gtk::RESPONSE_YES:
+ sp_document_ref(doc);
+ if (sp_file_save_document(doc)) {
+ sp_document_unref(doc);
+ } else { // save dialog cancelled or save failed
+ sp_document_unref(doc);
+ return TRUE;
+ }
+ break;
+ case Gtk::RESPONSE_NO:
+ allow_data_loss = TRUE;
+ break;
+ default: // cancel pressed, or dialog was closed
+ return TRUE;
+ break;
+ }
+ }
+
+ return false;
+}
+
+
+void
+EditWidget::destroy()
+{
+ delete this;
+}
+
+void
+EditWidget::requestCanvasUpdate()
+{
+ _svg_canvas.widget().queue_draw();
+}
+
+void
+EditWidget::activateDesktop()
+{
+ /// \todo active_desktop_indicator not implemented
+}
+
+void
+EditWidget::deactivateDesktop()
+{
+ /// \todo active_desktop_indicator not implemented
+}
+
+void
+EditWidget::viewSetPosition (NR::Point p)
+{
+ p -= _namedview->gridorigin;
+ double lo, up, pos, max;
+ _top_ruler.get_range (lo, up, pos, max);
+ _top_ruler.set_range (lo, up, p[NR::X], max);
+ _left_ruler.get_range (lo, up, pos, max);
+ _left_ruler.set_range (lo, up, p[NR::Y], max);
+}
+
+void
+EditWidget::updateRulers()
+{
+ NR::Point origin = _namedview->gridorigin;
+
+ NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
+ double lo, up, pos, max;
+ double const scale = _desktop->current_zoom();
+ double s = viewbox.min()[NR::X] / scale - origin[NR::X];
+ double e = viewbox.max()[NR::X] / scale - origin[NR::X];
+ _top_ruler.get_range(lo, up, pos, max);
+ _top_ruler.set_range(s, e, pos, e);
+ s = viewbox.min()[NR::Y] / -scale - origin[NR::Y];
+ e = viewbox.max()[NR::Y] / -scale - origin[NR::Y];
+ _left_ruler.set_range(s, e, origin[NR::Y], e);
+ /// \todo is that correct?
+}
+
+void
+EditWidget::updateScrollbars (double scale)
+{
+ // do not call this function before canvas has its size allocated
+ if (!is_realized() || _update_s_f) {
+ return;
+ }
+
+ _update_s_f = true;
+
+ /* The desktop region we always show unconditionally */
+ SPDocument *doc = _desktop->doc();
+ NR::Rect const r = sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc)));
+ NR::Rect darea(NR::Point(MIN(r.min()[NR::X], -sp_document_width(doc)),
+ MIN(r.min()[NR::Y], -sp_document_height(doc))),
+ NR::Point(MAX(r.max()[NR::X], 2 * sp_document_width(doc)),
+ MAX(r.max()[NR::Y], 2 * sp_document_height(doc))));
+
+ /* Canvas region we always show unconditionally */
+ NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64,
+ darea.max()[NR::Y] * -scale - 64),
+ NR::Point(darea.max()[NR::X] * scale + 64,
+ darea.min()[NR::Y] * -scale + 64));
+
+ NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
+
+ /* Viewbox is always included into scrollable region */
+ carea = NR::Rect::union_bounds(carea, viewbox);
+
+ Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
+ adj->set_value(viewbox.min()[NR::X]);
+ adj->set_lower(carea.min()[NR::X]);
+ adj->set_upper(carea.max()[NR::X]);
+ adj->set_page_increment(viewbox.dimensions()[NR::X]);
+ adj->set_step_increment(0.1 * (viewbox.dimensions()[NR::X]));
+ adj->set_page_size(viewbox.dimensions()[NR::X]);
+
+ adj = _right_scrollbar.get_adjustment();
+ adj->set_value(viewbox.min()[NR::Y]);
+ adj->set_lower(carea.min()[NR::Y]);
+ adj->set_upper(carea.max()[NR::Y]);
+ adj->set_page_increment(viewbox.dimensions()[NR::Y]);
+ adj->set_step_increment(0.1 * viewbox.dimensions()[NR::Y]);
+ adj->set_page_size(viewbox.dimensions()[NR::Y]);
+
+ _update_s_f = false;
+}
+
+void
+EditWidget::toggleRulers()
+{
+ if (_top_ruler.is_visible())
+ {
+ _top_ruler.hide_all();
+ _left_ruler.hide_all();
+ prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 0);
+ } else {
+ _top_ruler.show_all();
+ _left_ruler.show_all();
+ prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1);
+ }
+}
+
+void
+EditWidget::toggleScrollbars()
+{
+ if (_bottom_scrollbar.is_visible())
+ {
+ _bottom_scrollbar.hide_all();
+ _right_scrollbar.hide_all();
+ prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
+ } else {
+ _bottom_scrollbar.show_all();
+ _right_scrollbar.show_all();
+ prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
+ }
+}
+
+void
+EditWidget::updateZoom()
+{
+ _zoom_status.update();
+}
+
+void
+EditWidget::letZoomGrabFocus()
+{
+ _zoom_status.grab_focus();
+}
+
+void
+EditWidget::setToolboxFocusTo (const gchar *)
+{
+ /// \todo not implemented
+}
+
+void
+EditWidget::setToolboxAdjustmentValue (const gchar *, double)
+{
+ /// \todo not implemented
+}
+
+bool
+EditWidget::isToolboxButtonActive (gchar const*)
+{
+ /// \todo not implemented
+ return true;
+}
+
+void
+EditWidget::setCoordinateStatus (NR::Point p)
+{
+ gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::X]);
+ _coord_status_x.property_label() = cstr;
+ g_free (cstr);
+ cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::Y]);
+ _coord_status_y.property_label() = cstr;
+ g_free (cstr);
+}
+
+void
+EditWidget::setMessage (Inkscape::MessageType type, gchar const* msg)
+{
+ _select_status.set_markup (msg? msg : "");
+}
+
+bool
+EditWidget::warnDialog (gchar* msg)
+{
+ Gtk::MessageDialog dlg (*this,
+ msg,
+ true,
+ Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_YES_NO,
+ true);
+ int r = dlg.run();
+ return r == Gtk::RESPONSE_YES;
+}
+
+
+void
+EditWidget::initEdit (SPDocument *doc)
+{
+ _desktop = new SPDesktop();
+ _desktop->registerEditWidget (this);
+
+ _namedview = sp_document_namedview (doc, 0);
+ _svg_canvas.init (_desktop);
+ _desktop->init (_namedview, _svg_canvas.spobj());
+ sp_namedview_window_from_document (_desktop);
+ _dt2r = 1.0 / _namedview->doc_units->unittobase;
+
+ /// \todo convert to sigc++ when SPObject hierarchy gets converted
+ /* Listen on namedview modification */
+ g_signal_connect (G_OBJECT (_desktop->namedview), "modified", G_CALLBACK (_namedview_modified), this);
+ _layer_selector.setDesktop (_desktop);
+ _selected_style_status.setDesktop (_desktop);
+
+ Inkscape::NSApplication::Editor::addDesktop (_desktop);
+
+ _zoom_status.init (_desktop);
+ _top_ruler.init (_desktop, _svg_canvas.widget());
+ _left_ruler.init (_desktop, _svg_canvas.widget());
+ updateRulers();
+}
+
+void
+EditWidget::destroyEdit()
+{
+ if (_desktop) {
+ _layer_selector.unreference();
+ Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
+ sp_signal_disconnect_by_data (G_OBJECT (_desktop->namedview), this);
+ _desktop->destroy();
+ Inkscape::GC::release (_desktop);
+ _desktop = 0;
+ }
+}
+
+//----------end of EditWidgetInterface implementation
+
+//----------start of other callbacks
+
+bool
+EditWidget::on_key_press_event (GdkEventKey* event)
+{
+ // this is the original code from helper/window.cpp
+
+ unsigned int shortcut;
+ shortcut = get_group0_keyval (event) |
+ ( event->state & GDK_SHIFT_MASK ?
+ SP_SHORTCUT_SHIFT_MASK : 0 ) |
+ ( event->state & GDK_CONTROL_MASK ?
+ SP_SHORTCUT_CONTROL_MASK : 0 ) |
+ ( event->state & GDK_MOD1_MASK ?
+ SP_SHORTCUT_ALT_MASK : 0 );
+ return sp_shortcut_invoke (shortcut,
+ Inkscape::NSApplication::Editor::getActiveDesktop());
+}
+
+bool
+EditWidget::on_delete_event (GdkEventAny*)
+{
+ return shutdown();
+}
+
+bool
+EditWidget::on_focus_in_event (GdkEventFocus*)
+{
+ Inkscape::NSApplication::Editor::activateDesktop (_desktop);
+ _svg_canvas.widget().grab_focus();
+
+ return false;
+}
+
+void
+EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
+{
+ if (!is_realized()) return;
+
+ const Gtk::Allocation& all = get_allocation();
+ if ((newall.get_x() == all.get_x()) &&
+ (newall.get_y() == all.get_y()) &&
+ (newall.get_width() == all.get_width()) &&
+ (newall.get_height() == all.get_height())) {
+ return;
+ }
+
+ NR::Rect const area = _desktop->get_display_area();
+ double zoom = _desktop->current_zoom();
+
+ if (_sticky_zoom.get_active()) {
+ /* Calculate zoom per pixel */
+ double const zpsp = zoom / hypot(area.dimensions()[NR::X], area.dimensions()[NR::Y]);
+ /* Find new visible area */
+ NR::Rect const newarea = _desktop->get_display_area();
+ /* Calculate adjusted zoom */
+ zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]);
+ }
+
+ _desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom);
+}
+
+void
+EditWidget::onWindowRealize()
+{
+ NR::Rect d(NR::Point(0, 0),
+ NR::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())));
+
+ if (fabs(d.dimensions()[NR::X]) < 1.0 || fabs(d.dimensions()[NR::Y]) < 1.0) {
+ return;
+ }
+
+ _desktop->set_display_area(d.min()[NR::X], d.min()[NR::Y], d.max()[NR::X], d.max()[NR::Y], 10);
+ _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG, this);
+ setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
+}
+
+void
+EditWidget::onAdjValueChanged()
+{
+ if (_update_a_f) return;
+ _update_a_f = true;
+
+ sp_canvas_scroll_to (_svg_canvas.spobj(),
+ _bottom_scrollbar.get_value(),
+ _right_scrollbar.get_value(),
+ false);
+ updateRulers();
+
+ _update_a_f = false;
+}
+
+/// \todo make this a member function when the signal is a sigc++ signal
+void _namedview_modified (SPNamedView* nv, guint flags, EditWidget* ew)
+{
+ if (flags & SP_OBJECT_MODIFIED_FLAG)
+ {
+ ew->_dt2r = 1.0 / nv->doc_units->unittobase;
+ ew->_top_ruler.update_metric();
+ ew->_left_ruler.update_metric();
+ ew->_tooltips.set_tip (ew->_top_ruler, ew->_top_ruler.get_tip());
+ ew->_tooltips.set_tip (ew->_left_ruler, ew->_left_ruler.get_tip());
+ ew->updateRulers();
+ }
+}
+
+} // namespace View
+} // 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/view/edit-widget.h b/src/ui/view/edit-widget.h
new file mode 100644
index 000000000..73e6f048e
--- /dev/null
+++ b/src/ui/view/edit-widget.h
@@ -0,0 +1,211 @@
+/**
+ * \brief This class implements the functionality of the window layout, menus,
+ * and signals.
+ *
+ * Authors:
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Derek P. Moore <derekm@hackunix.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_VIEW_EDIT_WIDGET_H
+#define INKSCAPE_UI_VIEW_EDIT_WIDGET_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/table.h>
+#include <gtkmm/entry.h>
+#include <gtkmm/scrollbar.h>
+#include <gtkmm/actiongroup.h>
+#include <gtkmm/uimanager.h>
+#include <gtkmm/togglebutton.h>
+
+#include "ui/dialog/dialog-manager.h"
+#include "ui/view/edit-widget-interface.h"
+#include "ui/widget/selected-style.h"
+#include "ui/widget/ruler.h"
+#include "ui/widget/toolbox.h"
+#include "ui/widget/svg-canvas.h"
+#include "ui/widget/zoom-status.h"
+#include "widgets/layer-selector.h"
+
+struct SPDesktop;
+struct SPDocument;
+struct SPNamedView;
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+class EditWidget : public Gtk::Window,
+ public EditWidgetInterface {
+public:
+ EditWidget (SPDocument*);
+ ~EditWidget();
+
+ // Initialization
+ void initActions();
+ void initUIManager();
+ void initLayout();
+ void initEdit (SPDocument*);
+ void destroyEdit();
+
+ // Actions
+ void onActionFileNew();
+ void onActionFileOpen();
+ void onActionFilePrint();
+ void onActionFileQuit();
+ void onToolbarItem();
+ void onSelectTool();
+ void onNodeTool();
+
+ // Menus
+ void onMenuItem();
+
+ void onDialogAbout();
+ void onDialogAlignAndDistribute();
+ void onDialogInkscapePreferences();
+ void onDialogDialog();
+ void onDialogDocumentProperties();
+ void onDialogExport();
+ void onDialogExtensionEditor();
+ void onDialogFillAndStroke();
+ void onDialogFind();
+ void onDialogLayerEditor();
+ void onDialogMessages();
+ void onDialogObjectProperties();
+ void onDialogTextProperties();
+ void onDialogTransform();
+ void onDialogTransformation();
+ void onDialogTrace();
+ void onDialogXmlEditor();
+
+ // Whiteboard (Inkboard)
+#ifdef WITH_INKBOARD
+ void onDialogWhiteboardConnect();
+ void onDialogWhiteboardShareWithUser();
+ void onDialogWhiteboardShareWithChat();
+ void onDialogOpenSessionFile();
+ void onDumpXMLTracker();
+#endif
+
+ void onUriChanged();
+
+ // from EditWidgetInterface
+ virtual void *getWindow();
+ virtual void setTitle (gchar const*);
+ virtual void layout();
+ virtual void present();
+ virtual void getGeometry (gint &x, gint &y, gint &w, gint &h);
+ virtual void setSize (gint w, gint h);
+ virtual void setPosition (NR::Point p);
+ virtual void setTransient (void*, int);
+ virtual NR::Point getPointer();
+ virtual void setFullscreen();
+ virtual bool shutdown();
+ virtual void destroy();
+ virtual void requestCanvasUpdate();
+ virtual void activateDesktop();
+ virtual void deactivateDesktop();
+ virtual void viewSetPosition (NR::Point p);
+ virtual void updateRulers();
+ virtual void updateScrollbars (double scale);
+ virtual void toggleRulers();
+ virtual void toggleScrollbars();
+ virtual void updateZoom();
+ virtual void letZoomGrabFocus();
+ virtual void setToolboxFocusTo (const gchar *);
+ virtual void setToolboxAdjustmentValue (const gchar *, double);
+ virtual bool isToolboxButtonActive (gchar const*);
+ virtual void setCoordinateStatus (NR::Point p);
+ virtual void setMessage (Inkscape::MessageType type, gchar const* msg);
+ virtual bool warnDialog (gchar*);
+
+protected:
+ friend void _namedview_modified (SPNamedView*, guint, EditWidget*);
+
+ Gtk::Tooltips _tooltips;
+
+ // Child widgets:
+ Gtk::Table _main_window_table;
+ Gtk::VBox _toolbars_vbox;
+ Gtk::HBox _sub_window_hbox;
+ Gtk::Table _viewport_table;
+
+ UI::Widget::Toolbox *_tool_ctrl;
+ Gtk::Toolbar *_select_ctrl;
+ Gtk::Toolbar *_uri_ctrl;
+ Gtk::Label _uri_label;
+ Gtk::Entry _uri_entry;
+ Gtk::Toolbar *_node_ctrl;
+
+ UI::Widget::HRuler _top_ruler;
+ UI::Widget::VRuler _left_ruler;
+ Gtk::HScrollbar _bottom_scrollbar;
+ Gtk::VScrollbar _right_scrollbar;
+ Gtk::ToggleButton _sticky_zoom;
+ UI::Widget::SVGCanvas _svg_canvas;
+ Gtk::HBox _statusbar;
+ UI::Widget::SelectedStyle _selected_style_status;
+ UI::Widget::ZoomStatus _zoom_status;
+ Inkscape::Widgets::LayerSelector _layer_selector;
+ Gtk::EventBox _coord_eventbox;
+ Gtk::Table _coord_status;
+ Gtk::Label _coord_status_x, _coord_status_y;
+ Gtk::Label _select_status;
+
+ SPDesktop* _desktop;
+ SPNamedView* _namedview;
+ double _dt2r;
+
+ Glib::RefPtr<Gtk::ActionGroup> _act_grp;
+ Glib::RefPtr<Gtk::UIManager> _ui_mgr;
+ UI::Dialog::DialogManager _dlg_mgr;
+
+ void initMenuActions();
+ void initToolbarActions();
+ void initAccelMap();
+ void initMenuBar();
+ void initCommandsBar();
+ void initToolControlsBar();
+ void initUriBar();
+ void initToolsBar();
+ void initBottomScrollbar();
+ void initRightScrollbar();
+ void initLeftRuler();
+ void initTopRuler();
+ void initStickyZoom();
+ void initStatusbar();
+
+ virtual bool on_key_press_event (GdkEventKey*);
+ virtual bool on_delete_event (GdkEventAny*);
+ virtual bool on_focus_in_event (GdkEventFocus*);
+
+private:
+ bool onEntryFocusIn (GdkEventFocus*);
+ bool onEntryFocusOut (GdkEventFocus*);
+ void onWindowSizeAllocate (Gtk::Allocation&);
+ void onWindowRealize();
+ void onAdjValueChanged();
+
+ bool _update_s_f, _update_a_f;
+};
+} // namespace View
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_VIEW_EDIT_WIDGET_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/view/edit.cpp b/src/ui/view/edit.cpp
new file mode 100644
index 000000000..87bbc241c
--- /dev/null
+++ b/src/ui/view/edit.cpp
@@ -0,0 +1,28 @@
+/**
+ * \brief Empty file left in repo for current desktop.cpp
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+
+} // namespace View
+} // 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/view/edit.h b/src/ui/view/edit.h
new file mode 100644
index 000000000..76c2b5942
--- /dev/null
+++ b/src/ui/view/edit.h
@@ -0,0 +1,27 @@
+/**
+ * \brief empty file left in repo for current desktop.h
+ */
+
+#ifndef INKSCAPE_UI_VIEW_EDIT_H
+#define INKSCAPE_UI_VIEW_EDIT_H
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+} // namespace View
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_VIEW_EDIT_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/view/makefile.in b/src/ui/view/makefile.in
new file mode 100644
index 000000000..00aaffe5a
--- /dev/null
+++ b/src/ui/view/makefile.in
@@ -0,0 +1,17 @@
+# Convenience stub makefile to call the real Makefile.
+
+@SET_MAKE@
+
+# Explicit so that it's the default rule.
+all:
+ cd ../.. && $(MAKE) ui/view/all
+
+clean %.a %.o:
+ cd ../.. && $(MAKE) ui/view/$@
+
+.PHONY: all clean
+
+OBJEXT = @OBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .a .$(OBJEXT)
diff --git a/src/ui/view/view-widget.cpp b/src/ui/view/view-widget.cpp
new file mode 100644
index 000000000..6e60a9dfe
--- /dev/null
+++ b/src/ui/view/view-widget.cpp
@@ -0,0 +1,135 @@
+/** \file
+ * SPViewWidget implementation.
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "view.h"
+#include "view-widget.h"
+
+//using namespace Inkscape::UI::View;
+
+/* SPViewWidget */
+
+static void sp_view_widget_class_init(SPViewWidgetClass *vwc);
+static void sp_view_widget_init(SPViewWidget *widget);
+static void sp_view_widget_destroy(GtkObject *object);
+
+static GtkEventBoxClass *widget_parent_class;
+
+/**
+ * Registers the SPViewWidget class with Glib and returns its type number.
+ */
+GtkType sp_view_widget_get_type(void)
+{
+ static GtkType type = 0;
+
+ if (!type) {
+ GtkTypeInfo info = {
+ "SPViewWidget",
+ sizeof(SPViewWidget),
+ sizeof(SPViewWidgetClass),
+ (GtkClassInitFunc) sp_view_widget_class_init,
+ (GtkObjectInitFunc) sp_view_widget_init,
+ NULL, NULL, NULL
+ };
+ type = gtk_type_unique(GTK_TYPE_EVENT_BOX, &info);
+ }
+
+ return type;
+}
+
+/**
+ * Callback to initialize the SPViewWidget vtable.
+ */
+static void sp_view_widget_class_init(SPViewWidgetClass *vwc)
+{
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS(vwc);
+
+ widget_parent_class = (GtkEventBoxClass*) gtk_type_class(GTK_TYPE_EVENT_BOX);
+
+ object_class->destroy = sp_view_widget_destroy;
+}
+
+/**
+ * Callback to initialize the SPViewWidget.
+ */
+static void sp_view_widget_init(SPViewWidget *vw)
+{
+ vw->view = NULL;
+}
+
+/**
+ * Callback to disconnect from view and destroy SPViewWidget.
+ *
+ * Apparently, this gets only called when a desktop is closed, but then twice!
+ */
+static void sp_view_widget_destroy(GtkObject *object)
+{
+ SPViewWidget *vw = SP_VIEW_WIDGET(object);
+
+ if (vw->view) {
+ vw->view->close();
+ Inkscape::GC::release(vw->view);
+ vw->view = NULL;
+ }
+
+ if (((GtkObjectClass *) (widget_parent_class))->destroy) {
+ (* ((GtkObjectClass *) (widget_parent_class))->destroy)(object);
+ }
+}
+
+/**
+ * Connects widget to view's 'resized' signal and calls virtual set_view()
+ * function.
+ */
+void sp_view_widget_set_view(SPViewWidget *vw, Inkscape::UI::View::View *view)
+{
+ g_return_if_fail(vw != NULL);
+ g_return_if_fail(SP_IS_VIEW_WIDGET(vw));
+ g_return_if_fail(view != NULL);
+
+ g_return_if_fail(vw->view == NULL);
+
+ vw->view = view;
+ Inkscape::GC::anchor(view);
+
+ if (((SPViewWidgetClass *) G_OBJECT_GET_CLASS(vw))->set_view) {
+ ((SPViewWidgetClass *) G_OBJECT_GET_CLASS(vw))->set_view(vw, view);
+ }
+}
+
+/**
+ * Calls the virtual shutdown() function of the SPViewWidget.
+ */
+bool sp_view_widget_shutdown(SPViewWidget *vw)
+{
+ g_return_val_if_fail(vw != NULL, TRUE);
+ g_return_val_if_fail(SP_IS_VIEW_WIDGET(vw), TRUE);
+
+ if (((SPViewWidgetClass *) G_OBJECT_GET_CLASS(vw))->shutdown) {
+ return ((SPViewWidgetClass *) G_OBJECT_GET_CLASS(vw))->shutdown(vw);
+ }
+
+ return FALSE;
+}
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/view/view-widget.h b/src/ui/view/view-widget.h
new file mode 100644
index 000000000..9b5e9c4a8
--- /dev/null
+++ b/src/ui/view/view-widget.h
@@ -0,0 +1,97 @@
+#ifndef INKSCAPE_UI_VIEW_VIEWWIDGET_H
+#define INKSCAPE_UI_VIEW_VIEWWIDGET_H
+
+/** \file
+ * A widget is the UI context for a document view.
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtk/gtkeventbox.h>
+
+namespace Inkscape {
+ namespace UI {
+ namespace View {
+ class View;
+ }}}
+class SPViewWidget;
+class SPNamedView;
+
+#define SP_TYPE_VIEW_WIDGET (sp_view_widget_get_type ())
+#define SP_VIEW_WIDGET(obj) (GTK_CHECK_CAST ((obj), SP_TYPE_VIEW_WIDGET, SPViewWidget))
+#define SP_VIEW_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), SP_TYPE_VIEW_WIDGET, SPViewWidgetClass))
+#define SP_IS_VIEW_WIDGET(obj) (GTK_CHECK_TYPE ((obj), SP_TYPE_VIEW_WIDGET))
+#define SP_IS_VIEW_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), SP_TYPE_VIEW_WIDGET))
+#define SP_VIEW_WIDGET_VIEW(w) (SP_VIEW_WIDGET (w)->view)
+#define SP_VIEW_WIDGET_DOCUMENT(w) (SP_VIEW_WIDGET (w)->view ? ((SPViewWidget *) (w))->view->doc : NULL)
+
+GType sp_view_widget_get_type (void);
+
+void sp_view_widget_set_view (SPViewWidget *vw, Inkscape::UI::View::View *view);
+
+/// Allows presenting 'save changes' dialog, FALSE - continue, TRUE - cancel
+bool sp_view_widget_shutdown (SPViewWidget *vw);
+
+/// Create a new SPViewWidget (which happens to be a SPDesktopWidget).
+SPViewWidget *sp_desktop_widget_new (SPNamedView *namedview);
+
+/**
+ * SPViewWidget is a GUI widget that contain a single View. It is also
+ * an abstract base class with little functionality of its own.
+ */
+class SPViewWidget {
+ public:
+ GtkEventBox eventbox;
+
+ Inkscape::UI::View::View *view;
+
+ // C++ Wrappers
+ GType getType() const {
+ return sp_view_widget_get_type();
+ }
+
+ void setView(Inkscape::UI::View::View *view) {
+ sp_view_widget_set_view(this, view);
+ }
+
+ gboolean shutdown() {
+ return sp_view_widget_shutdown(this);
+ }
+
+// void resized (double x, double y) = 0;
+};
+
+/**
+ * The Glib-style vtable for the SPViewWidget class.
+ */
+class SPViewWidgetClass {
+ public:
+ GtkEventBoxClass parent_class;
+
+ /* Virtual method to set/change/remove view */
+ void (* set_view) (SPViewWidget *vw, Inkscape::UI::View::View *view);
+ /// Virtual method about view size change
+ void (* view_resized) (SPViewWidget *vw, Inkscape::UI::View::View *view, gdouble width, gdouble height);
+
+ gboolean (* shutdown) (SPViewWidget *vw);
+};
+
+#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 :
diff --git a/src/ui/view/view.cpp b/src/ui/view/view.cpp
new file mode 100644
index 000000000..0f7fd9195
--- /dev/null
+++ b/src/ui/view/view.cpp
@@ -0,0 +1,163 @@
+#define __SP_VIEW_C__
+
+/** \file
+ * View implementation
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "libnr/nr-point.h"
+#include "document.h"
+#include "view.h"
+#include "message-stack.h"
+#include "message-context.h"
+#include "verbs.h"
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+static void
+_onPositionSet (double x, double y, View* v)
+{
+ v->onPositionSet (x,y);
+}
+
+static void
+_onResized (double x, double y, View* v)
+{
+ v->onResized (x,y);
+}
+
+static void
+_onRedrawRequested (View* v)
+{
+ v->onRedrawRequested();
+}
+
+static void
+_onStatusMessage (Inkscape::MessageType type, gchar const *message, View* v)
+{
+ v->onStatusMessage (type, message);
+}
+
+static void
+_onDocumentURISet (gchar const* uri, View* v)
+{
+ v->onDocumentURISet (uri);
+}
+
+static void
+_onDocumentResized (double x, double y, View* v)
+{
+ v->onDocumentResized (x,y);
+}
+
+//--------------------------------------------------------------------
+View::View()
+: _doc(0)
+{
+ _message_stack = GC::release(new Inkscape::MessageStack());
+ _tips_message_context = new Inkscape::MessageContext(_message_stack);
+
+ _position_set_connection = _position_set_signal.connect (sigc::bind (sigc::ptr_fun (&_onPositionSet), this));
+ _resized_connection = _resized_signal.connect (sigc::bind (sigc::ptr_fun (&_onResized), this));
+ _redraw_requested_connection = _redraw_requested_signal.connect (sigc::bind (sigc::ptr_fun (&_onRedrawRequested), this));
+
+ _message_changed_connection = _message_stack->connectChanged (sigc::bind (sigc::ptr_fun (&_onStatusMessage), this));
+}
+
+/**
+ * Deletes and nulls all View message stacks and disconnects it from signals.
+ */
+View::~View()
+{
+ _close();
+}
+
+void View::_close() {
+ _message_changed_connection.disconnect();
+
+ delete _tips_message_context;
+ _tips_message_context = 0;
+
+ _message_stack = 0;
+
+ if (_doc) {
+ _document_uri_set_connection.disconnect();
+ _document_resized_connection.disconnect();
+ _doc = 0;
+ }
+
+ Inkscape::Verb::delete_all_view (this);
+}
+
+void View::setPosition (double x, double y)
+{
+ _position_set_signal.emit (x,y);
+}
+
+void View::setPosition(NR::Point const &p)
+{
+ setPosition (double(p[NR::X]), double(p[NR::Y]));
+}
+
+void View::emitResized (double width, double height)
+{
+ _resized_signal.emit (width, height);
+}
+
+void View::requestRedraw()
+{
+ _redraw_requested_signal.emit();
+}
+
+/**
+ * Disconnects the view from the document signals, connects the view
+ * to a new one, and emits the _document_set_signal on the view.
+ *
+ * This is code comon to all subclasses and called from their
+ * setDocument() methods after they are done.
+ *
+ * \param doc The new document to connect the view to.
+ */
+void View::setDocument(SPDocument *doc) {
+ g_return_if_fail(doc != NULL);
+
+ if (_doc) {
+ _document_uri_set_connection.disconnect();
+ _document_resized_connection.disconnect();
+ sp_document_unref (_doc);
+ }
+
+ _doc = sp_document_ref (doc);
+ _document_uri_set_connection =
+ _doc->connectURISet(sigc::bind(sigc::ptr_fun(&_onDocumentURISet), this));
+ _document_resized_connection =
+ _doc->connectResized(sigc::bind(sigc::ptr_fun(&_onDocumentResized), this));
+ _document_uri_set_signal.emit (SP_DOCUMENT_URI(_doc));
+}
+
+}}}
+
+/*
+ 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 :
diff --git a/src/ui/view/view.h b/src/ui/view/view.h
new file mode 100644
index 000000000..6f0a29543
--- /dev/null
+++ b/src/ui/view/view.h
@@ -0,0 +1,148 @@
+#ifndef INKSCAPE_UI_VIEW_VIEW_H
+#define INKSCAPE_UI_VIEW_VIEW_H
+
+/** \file
+ * Abstract base class for all SVG document views
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gdk/gdktypes.h>
+#include <sigc++/connection.h>
+#include "message.h"
+#include "gc-managed.h"
+#include "gc-finalized.h"
+#include "gc-anchored.h"
+
+
+/**
+ * Iterates until true or returns false.
+ * When used as signal accumulator, stops emission if one slot returns true.
+ */
+struct StopOnTrue {
+ typedef bool result_type;
+
+ template<typename T_iterator>
+ result_type operator()(T_iterator first, T_iterator last) const{
+ for (; first != last; ++first)
+ if (*first) return true;
+ return false;
+ }
+};
+
+/**
+ * Iterates until nonzero or returns 0.
+ * When used as signal accumulator, stops emission if one slot returns nonzero.
+ */
+struct StopOnNonZero {
+ typedef int result_type;
+
+ template<typename T_iterator>
+ result_type operator()(T_iterator first, T_iterator last) const{
+ for (; first != last; ++first)
+ if (*first) return *first;
+ return 0;
+ }
+};
+
+
+namespace NR {
+ class Point;
+}
+class SPDocument;
+
+namespace Inkscape {
+ class MessageContext;
+ class MessageStack;
+ namespace UI {
+ namespace View {
+
+/**
+ * View is an abstract base class of all UI document views. This
+ * includes both the editing window and the SVG preview, but does not
+ * include the non-UI RGBA buffer-based NRArena nor the XML editor or
+ * similar views. The View base class has very little functionality of
+ * its own.
+ */
+class View : public GC::Managed<>,
+ public GC::Finalized,
+ public GC::Anchored
+{
+public:
+
+ View();
+ virtual ~View();
+
+ void close() { _close(); }
+
+ /// Returns a pointer to the view's document.
+ SPDocument *doc() const
+ { return _doc; }
+ /// Returns a pointer to the view's message stack.
+ Inkscape::MessageStack *messageStack() const
+ { return _message_stack; }
+ /// Returns a pointer to the view's tipsMessageContext.
+ Inkscape::MessageContext *tipsMessageContext() const
+ { return _tips_message_context; }
+
+ void setPosition(gdouble x, gdouble y);
+ void setPosition(NR::Point const &p);
+ void emitResized(gdouble width, gdouble height);
+ void requestRedraw();
+
+ // view subclasses must give implementations of these methods
+
+ virtual bool shutdown() = 0;
+ virtual void mouseover() = 0;
+ virtual void mouseout() = 0;
+
+ virtual void onPositionSet (double, double) = 0;
+ virtual void onResized (double, double) = 0;
+ virtual void onRedrawRequested() = 0;
+ virtual void onStatusMessage (Inkscape::MessageType type, gchar const *message) = 0;
+ virtual void onDocumentURISet (gchar const* uri) = 0;
+ virtual void onDocumentResized (double, double) = 0;
+
+protected:
+ SPDocument *_doc;
+ Inkscape::MessageStack *_message_stack;
+ Inkscape::MessageContext *_tips_message_context;
+
+ virtual void _close();
+ virtual void setDocument(SPDocument *doc);
+
+ sigc::signal<void,double,double> _position_set_signal;
+ sigc::signal<void,double,double> _resized_signal;
+ sigc::signal<void,gchar const*> _document_uri_set_signal;
+ sigc::signal<void> _redraw_requested_signal;
+
+private:
+ sigc::connection _position_set_connection;
+ sigc::connection _resized_connection;
+ sigc::connection _redraw_requested_connection;
+ sigc::connection _message_changed_connection; // foreign
+ sigc::connection _document_uri_set_connection; // foreign
+ sigc::connection _document_resized_connection; // foreign
+};
+
+}}}
+
+#endif // INKSCAPE_UI_VIEW_VIEW_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 :
diff --git a/src/ui/widget/.cvsignore b/src/ui/widget/.cvsignore
new file mode 100644
index 000000000..38efca7bc
--- /dev/null
+++ b/src/ui/widget/.cvsignore
@@ -0,0 +1,3 @@
+.deps
+.dirstamp
+makefile
diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert
new file mode 100644
index 000000000..2ef0f8f41
--- /dev/null
+++ b/src/ui/widget/Makefile_insert
@@ -0,0 +1,62 @@
+## Makefile.am fragment sourced by src/Makefile.am.
+
+ui/widget/all: ui/widget/libuiwidget.a
+
+ui/widget/clean:
+ rm -f ui/widget/libuiwidget.a $(ui_libuiwidget_a_OBJECTS)
+
+ui_widget_libuiwidget_a_SOURCES = \
+ ui/widget/button.h \
+ ui/widget/button.cpp \
+ ui/widget/color-picker.cpp \
+ ui/widget/color-picker.h \
+ ui/widget/color-preview.cpp \
+ ui/widget/color-preview.h \
+ ui/widget/combo-text.cpp \
+ ui/widget/combo-text.h \
+ ui/widget/entity-entry.cpp \
+ ui/widget/entity-entry.h \
+ ui/widget/handlebox.cpp \
+ ui/widget/handlebox.h \
+ ui/widget/icon-widget.cpp \
+ ui/widget/icon-widget.h \
+ ui/widget/imageicon.cpp \
+ ui/widget/imageicon.h \
+ ui/widget/labelled.cpp \
+ ui/widget/labelled.h \
+ ui/widget/licensor.cpp \
+ ui/widget/licensor.h \
+ ui/widget/notebook-page.cpp \
+ ui/widget/notebook-page.h \
+ ui/widget/page-sizer.cpp \
+ ui/widget/page-sizer.h \
+ ui/widget/panel.cpp \
+ ui/widget/panel.cpp \
+ ui/widget/panel.h \
+ ui/widget/preferences-widget.cpp \
+ ui/widget/preferences-widget.h \
+ ui/widget/registered-widget.cpp \
+ ui/widget/registered-widget.h \
+ ui/widget/registry.cpp \
+ ui/widget/registry.h \
+ ui/widget/ruler.cpp \
+ ui/widget/ruler.h \
+ ui/widget/scalar-unit.cpp \
+ ui/widget/scalar-unit.h \
+ ui/widget/scalar.cpp \
+ ui/widget/scalar.h \
+ ui/widget/selected-style.h \
+ ui/widget/selected-style.cpp \
+ ui/widget/style-swatch.h \
+ ui/widget/style-swatch.cpp \
+ ui/widget/svg-canvas.cpp \
+ ui/widget/svg-canvas.h \
+ ui/widget/tolerance-slider.cpp \
+ ui/widget/tolerance-slider.h \
+ ui/widget/toolbox.cpp \
+ ui/widget/toolbox.h \
+ ui/widget/unit-menu.cpp \
+ ui/widget/unit-menu.h \
+ ui/widget/zoom-status.h \
+ ui/widget/zoom-status.cpp
+
diff --git a/src/ui/widget/button.cpp b/src/ui/widget/button.cpp
new file mode 100644
index 000000000..19c69ba44
--- /dev/null
+++ b/src/ui/widget/button.cpp
@@ -0,0 +1,51 @@
+/**
+ * \brief Button and CheckButton widgets
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "button.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+Button::Button(Glib::ustring const &label, Glib::ustring const &tooltip)
+ : _tooltips()
+{
+ set_use_underline (true);
+ set_label (label);
+ _tooltips.set_tip(*this, tooltip);
+}
+
+CheckButton::CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip)
+ : _tooltips()
+{
+ set_use_underline (true);
+ set_label (label);
+ _tooltips.set_tip(*this, tooltip);
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/button.h b/src/ui/widget/button.h
new file mode 100644
index 000000000..7e942b324
--- /dev/null
+++ b/src/ui/widget/button.h
@@ -0,0 +1,56 @@
+/**
+ * \brief Button and CheckButton widgets
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_BUTTON_H
+#define INKSCAPE_UI_WIDGET_BUTTON_H
+
+#include <gtkmm/button.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/tooltips.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Button : public Gtk::Button
+{
+public:
+ Button();
+ Button(Glib::ustring const &label, Glib::ustring const &tooltip);
+protected:
+ Gtk::Tooltips _tooltips;
+};
+
+class CheckButton : public Gtk::CheckButton
+{
+public:
+ CheckButton();
+ CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip);
+protected:
+ Gtk::Tooltips _tooltips;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_BUTTON_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/color-picker.cpp b/src/ui/widget/color-picker.cpp
new file mode 100644
index 000000000..9bc79ddc1
--- /dev/null
+++ b/src/ui/widget/color-picker.cpp
@@ -0,0 +1,167 @@
+#define __COLOR_PICKER_C__
+
+/** \file
+ * \brief Color picker button & window
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * bulia byak <buliabyak@users.sf.net>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) Authors 2000-2005
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "inkscape.h"
+#include "desktop-handles.h"
+#include "document.h"
+
+#include "ui/dialog/dialog.h"
+
+#include "widgets/sp-color-notebook.h"
+
+#include "color-picker.h"
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+struct CPPointer {
+ ColorPicker *ptr;
+};
+
+class ColorPickerWindow : public Inkscape::UI::Dialog::Dialog {
+public:
+ ColorPickerWindow (ColorPicker* cp, const Glib::ustring &title);
+ virtual ~ColorPickerWindow();
+ void setRgba32 (guint32);
+
+ SPColorSelector *_csel;
+ CPPointer _cpp;
+};
+
+ColorPicker::ColorPicker (const Glib::ustring& title, const Glib::ustring& tip,
+ guint32 rgba, bool undo)
+: _preview(rgba), _window(0),
+ _title(title), _rgba(rgba), _undo(undo)
+{
+ set_relief (Gtk::RELIEF_NONE);
+ _preview.show();
+ add (_preview);
+ _tt.set_tip (*this, tip);
+}
+
+ColorPicker::~ColorPicker()
+{
+ closeWindow();
+}
+
+void
+ColorPicker::setRgba32 (guint32 rgba)
+{
+ _preview.setRgba32 (rgba);
+ _rgba = rgba;
+ if (_window)
+ _window->setRgba32 (rgba);
+}
+
+void
+ColorPicker::closeWindow()
+{
+ if (_window)
+ {
+ delete _window;
+ _window = 0;
+ }
+}
+
+void
+ColorPicker::on_clicked()
+{
+ static int _x, _y;
+ if (_window)
+ {
+ _window->move(_x,_y);
+ _window->present();
+ return;
+ }
+
+ _window =new ColorPickerWindow (this, _title);
+ _window->setRgba32 (_rgba);
+ _window->show_all();
+ _window->get_position (_x, _y);
+}
+
+void
+ColorPicker::on_changed (guint32)
+{
+}
+
+void
+sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp)
+{
+ SPColor color;
+ float alpha;
+ csel->base->getColorAlpha(color, &alpha);
+ guint32 rgba = sp_color_get_rgba32_falpha(&color, alpha);
+
+ ColorPicker *ptr = static_cast<CPPointer*>((void*)cp)->ptr;
+
+ (ptr->_preview).setRgba32 (rgba);
+
+ if (ptr->_undo && SP_ACTIVE_DESKTOP)
+ sp_document_done(SP_DT_DOCUMENT(SP_ACTIVE_DESKTOP));
+
+ ptr->on_changed (rgba);
+ ptr->_changed_signal.emit (rgba);
+}
+
+//==============================================================
+
+ColorPickerWindow::ColorPickerWindow (ColorPicker *cp, const Glib::ustring &title)
+ : Dialog("dialogs.colorpickerwindow")
+{
+ set_title (title);
+ set_border_width (4);
+ _csel = (SPColorSelector*)sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK,
+ SP_COLORSPACE_TYPE_UNKNOWN);
+ get_vbox()->pack_start (*Glib::wrap(&_csel->vbox), true, true, 0);
+
+ _cpp.ptr = cp;
+ g_signal_connect(G_OBJECT(_csel), "dragged",
+ G_CALLBACK(sp_color_picker_color_mod), &_cpp);
+ g_signal_connect(G_OBJECT(_csel), "changed",
+ G_CALLBACK(sp_color_picker_color_mod), &_cpp);
+
+ show();
+}
+
+ColorPickerWindow::~ColorPickerWindow()
+{
+ _csel = 0;
+}
+
+void
+ColorPickerWindow::setRgba32 (guint32 rgba)
+{
+ if (_csel)
+ {
+ SPColor color;
+ sp_color_set_rgb_rgba32(&color, rgba);
+ _csel->base->setColorAlpha(color, SP_RGBA32_A_F(rgba));
+ }
+}
+
+}}}
+
+/*
+ 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/color-picker.h b/src/ui/widget/color-picker.h
new file mode 100644
index 000000000..adff8181a
--- /dev/null
+++ b/src/ui/widget/color-picker.h
@@ -0,0 +1,65 @@
+#ifndef __COLOR_PICKER_H__
+#define __COLOR_PICKER_H__
+
+/**
+ * \file Color picker button \& window.
+ */
+/*
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) Authors 2000-2005
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <sigc++/sigc++.h>
+#include <gtkmm/button.h>
+#include <gtkmm/tooltips.h>
+#include "ui/widget/color-preview.h"
+
+class SPColorSelector;
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+ class ColorPickerWindow;
+
+class ColorPicker : public Gtk::Button {
+public:
+ ColorPicker (const Glib::ustring& title, const Glib::ustring& tip, const guint32 rgba, bool undo);
+ virtual ~ColorPicker();
+ void setRgba32 (guint32 rgba);
+ void closeWindow();
+ sigc::connection connectChanged (const sigc::slot<void,guint>& slot)
+ { return _changed_signal.connect (slot); }
+
+protected:
+ friend void sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp);
+ virtual void on_clicked();
+ virtual void on_changed (guint32);
+
+ ColorPreview _preview;
+ Gtk::Tooltips _tt;
+ ColorPickerWindow *_window;
+
+ const Glib::ustring _title;
+ sigc::signal<void,guint32> _changed_signal;
+ guint32 _rgba;
+ bool _undo;
+};
+
+}}}
+
+#endif /* !__COLOR_PICKER_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/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp
new file mode 100644
index 000000000..6e9f9ff4a
--- /dev/null
+++ b/src/ui/widget/color-preview.cpp
@@ -0,0 +1,122 @@
+/** \file
+ * Implemenmtation of a simple color preview widget
+ *
+ * Author:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2001-2005 Authors
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/nr-plain-stuff-gdk.h"
+#include "color-preview.h"
+
+#define SPCP_DEFAULT_WIDTH 32
+#define SPCP_DEFAULT_HEIGHT 11
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+ColorPreview::ColorPreview (guint32 rgba)
+{
+ _rgba = rgba;
+ set_flags (Gtk::NO_WINDOW);
+}
+
+void
+ColorPreview::on_size_request (Gtk::Requisition *req)
+{
+ req->width = SPCP_DEFAULT_WIDTH;
+ req->height = SPCP_DEFAULT_HEIGHT;
+}
+
+void
+ColorPreview::on_size_allocate (Gtk::Allocation &all)
+{
+ set_allocation (all);
+ if (is_drawable())
+ queue_draw();
+}
+
+bool
+ColorPreview::on_expose_event (GdkEventExpose *event)
+{
+ if (is_drawable())
+ paint (&event->area);
+
+ return true;
+}
+
+void
+ColorPreview::setRgba32 (guint32 rgba)
+{
+ _rgba = rgba;
+
+ if (is_drawable())
+ queue_draw();
+}
+
+void
+ColorPreview::paint (GdkRectangle *area)
+{
+ GdkRectangle warea, carea;
+ GdkRectangle wpaint, cpaint;
+ gint w2;
+
+ const Gtk::Allocation& allocation = get_allocation();
+ warea.x = allocation.get_x();
+ warea.y = allocation.get_y();
+ warea.width = allocation.get_width();
+ warea.height = allocation.get_height();
+
+ if (!gdk_rectangle_intersect (area, &warea, &wpaint))
+ return;
+
+ /* Transparent area */
+
+ w2 = warea.width / 2;
+
+ carea.x = warea.x;
+ carea.y = warea.y;
+ carea.width = w2;
+ carea.height = warea.height;
+
+ if (gdk_rectangle_intersect (area, &carea, &cpaint)) {
+ nr_gdk_draw_rgba32_solid (get_window()->gobj(),
+ get_style()->get_black_gc()->gobj(),
+ cpaint.x, cpaint.y,
+ cpaint.width, cpaint.height,
+ _rgba);
+ }
+
+ /* Solid area */
+
+ carea.x = warea.x + w2;
+ carea.y = warea.y;
+ carea.width = warea.width - w2;
+ carea.height = warea.height;
+
+ if (gdk_rectangle_intersect (area, &carea, &cpaint)) {
+ nr_gdk_draw_rgba32_solid (get_window()->gobj(),
+ get_style()->get_black_gc()->gobj(),
+ cpaint.x, cpaint.y,
+ cpaint.width, cpaint.height,
+ _rgba | 0xff);
+ }
+}
+
+}}}
+
+/*
+ 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:
+*/
diff --git a/src/ui/widget/color-preview.h b/src/ui/widget/color-preview.h
new file mode 100644
index 000000000..424c58665
--- /dev/null
+++ b/src/ui/widget/color-preview.h
@@ -0,0 +1,50 @@
+#ifndef __COLOR_PREVIEW_H__
+#define __COLOR_PREVIEW_H__
+
+/** \file
+ * A simple color preview widget, mainly used within a picker button.
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2001-2005 Authors
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/eventbox.h>
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class ColorPreview : public Gtk::Widget {
+public:
+ ColorPreview (guint32 rgba);
+ void setRgba32 (guint32 rgba);
+
+protected:
+ virtual void on_size_request (Gtk::Requisition *req);
+ virtual void on_size_allocate (Gtk::Allocation &all);
+ virtual bool on_expose_event (GdkEventExpose *event);
+ void paint (GdkRectangle *area);
+
+ guint32 _rgba;
+};
+
+}}}
+
+#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 :
diff --git a/src/ui/widget/combo-text.cpp b/src/ui/widget/combo-text.cpp
new file mode 100644
index 000000000..7706f7c29
--- /dev/null
+++ b/src/ui/widget/combo-text.cpp
@@ -0,0 +1,92 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "combo-text.h"
+#include <gtk/gtkcombobox.h>
+
+ComboText::ComboText()
+ : Gtk::ComboBox()
+{
+ m_model = Gtk::ListStore::create(m_text_columns);
+ set_model(m_model);
+ pack_start(m_text_columns.m_column);
+}
+
+
+ComboText::~ComboText()
+{
+
+}
+
+void ComboText::append_text(const Glib::ustring& text)
+{
+ gtk_combo_box_append_text(gobj(), text.c_str());
+}
+
+void ComboText::insert_text(int position, const Glib::ustring& text)
+{
+ gtk_combo_box_insert_text(gobj(), position, text.c_str());
+}
+
+void ComboText::prepend_text(const Glib::ustring& text)
+{
+ gtk_combo_box_prepend_text(gobj(), text.c_str());
+}
+
+Glib::ustring ComboText::get_active_text() const
+{
+ Glib::ustring result;
+
+ //Get the active row:
+ Gtk::TreeModel::iterator active_row = get_active();
+ if(active_row)
+ {
+ Gtk::TreeModel::Row row = *active_row;
+ result = row[m_text_columns.m_column];
+ }
+
+ return result;
+}
+
+void ComboText::clear_text()
+{
+ m_model->clear();
+}
+
+void ComboText::set_active_text(const Glib::ustring& text)
+{
+ for(Gtk::TreeModel::iterator iter = m_model->children().begin(); iter != m_model->children().end(); ++iter)
+ {
+ Glib::ustring this_text = (*iter)[m_text_columns.m_column];
+
+ if(this_text == text)
+ {
+ set_active(iter);
+ return; //success
+ }
+ }
+
+ //Not found, so mark it as blank:
+ unset_active();
+}
diff --git a/src/ui/widget/combo-text.h b/src/ui/widget/combo-text.h
new file mode 100644
index 000000000..382414fb0
--- /dev/null
+++ b/src/ui/widget/combo-text.h
@@ -0,0 +1,66 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GLOM_MODE_DESIGN_COMBO_TEXTGLADE_HH
+#define GLOM_MODE_DESIGN_COMBO_TEXTGLADE_HH
+
+#include <gtkmm/combobox.h>
+
+#include <gtkmm/liststore.h>
+
+/** This class should just derive from Gtk::ComboBoxText and provide a
+ * constuctor suitable for libglade's get_widget_derived() template.
+ * However, I have reimplemented Gtk::ComboBoxText here temporarily,
+ * until the fixes in gtkmm 2.4.3 are widely available.
+ */
+class ComboText : public Gtk::ComboBox
+{
+ public:
+ ComboText();
+ virtual ~ComboText();
+
+ void append_text(const Glib::ustring& text);
+ void insert_text(int position, const Glib::ustring& text);
+ void prepend_text(const Glib::ustring& text);
+ Glib::ustring get_active_text() const;
+
+ //This is not part of ComboBoxText:
+ void clear_text();
+ void set_active_text(const Glib::ustring& text);
+
+ protected:
+
+ //Tree model columns:
+ //These columns are used by the model that is created by the default constructor
+ class TextModelColumns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ TextModelColumns()
+ { add(m_column); }
+
+ Gtk::TreeModelColumn<Glib::ustring> m_column;
+ };
+
+ TextModelColumns m_text_columns;
+ Glib::RefPtr<Gtk::ListStore> m_model;
+
+};
+
+#endif //GLOM_MODE_DESIGN_COMBO_TEXTGLADE_HH
diff --git a/src/ui/widget/entity-entry.cpp b/src/ui/widget/entity-entry.cpp
new file mode 100644
index 000000000..1b4048ab0
--- /dev/null
+++ b/src/ui/widget/entity-entry.cpp
@@ -0,0 +1,161 @@
+/** \file
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/entry.h>
+
+#include "ui/widget/registry.h"
+
+#include "dialogs/rdf.h"
+
+#include "inkscape.h"
+
+#include "entity-entry.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+//---------------------------------------------------
+
+EntityEntry*
+EntityEntry::create (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr)
+{
+ g_assert (ent);
+ EntityEntry* obj = 0;
+ switch (ent->format)
+ {
+ case RDF_FORMAT_LINE:
+ obj = new EntityLineEntry (ent, tt, wr);
+ break;
+ case RDF_FORMAT_MULTILINE:
+ obj = new EntityMultiLineEntry (ent, tt, wr);
+ break;
+ default:
+ g_warning ("Can't happen.");
+ }
+
+ obj->_label.show();
+ return obj;
+}
+
+EntityEntry::EntityEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr)
+: _label(Glib::ustring(_(ent->title))+":", 1.0, 0.5), _packable(0),
+ _entity(ent), _tt(&tt), _wr(&wr)
+{
+}
+
+EntityEntry::~EntityEntry()
+{
+ _changed_connection.disconnect();
+}
+
+EntityLineEntry::EntityLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr)
+: EntityEntry (ent, tt, wr)
+{
+ Gtk::Entry *e = new Gtk::Entry;
+ tt.set_tip (*e, _(ent->tip));
+ _packable = e;
+ _changed_connection = e->signal_changed().connect (sigc::mem_fun (*this, &EntityLineEntry::on_changed));
+}
+
+EntityLineEntry::~EntityLineEntry()
+{
+ delete reinterpret_cast<Gtk::Entry*>(_packable);
+}
+
+void
+EntityLineEntry::update (SPDocument *doc)
+{
+ const char *text = rdf_get_work_entity (doc, _entity);
+ reinterpret_cast<Gtk::Entry*>(_packable)->set_text (text ? text : "");
+}
+
+void
+EntityLineEntry::on_changed()
+{
+ if (_wr->isUpdating()) return;
+
+ _wr->setUpdating (true);
+ SPDocument *doc = SP_ACTIVE_DOCUMENT;
+ char const *text = reinterpret_cast<Gtk::Entry*>(_packable)->get_text().c_str();
+ if (rdf_set_work_entity (doc, _entity, text))
+ sp_document_done (doc);
+ _wr->setUpdating (false);
+}
+
+EntityMultiLineEntry::EntityMultiLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr)
+: EntityEntry (ent, tt, wr)
+{
+ Gtk::ScrolledWindow *s = new Gtk::ScrolledWindow;
+ s->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ s->set_shadow_type (Gtk::SHADOW_IN);
+ _packable = s;
+ _v.set_size_request (-1, 5);
+ _v.set_wrap_mode (Gtk::WRAP_WORD);
+ _v.set_accepts_tab (false);
+ s->add (_v);
+ tt.set_tip (_v, _(ent->tip));
+ _changed_connection = _v.get_buffer()->signal_changed().connect (sigc::mem_fun (*this, &EntityMultiLineEntry::on_changed));
+}
+
+EntityMultiLineEntry::~EntityMultiLineEntry()
+{
+ delete reinterpret_cast<Gtk::ScrolledWindow*>(_packable);
+}
+
+void
+EntityMultiLineEntry::update (SPDocument *doc)
+{
+ const char *text = rdf_get_work_entity (doc, _entity);
+ Gtk::ScrolledWindow *s = reinterpret_cast<Gtk::ScrolledWindow*>(_packable);
+ Gtk::TextView *tv = reinterpret_cast<Gtk::TextView*>(s->get_child());
+ tv->get_buffer()->set_text (text ? text : "");
+}
+
+void
+EntityMultiLineEntry::on_changed()
+{
+ if (_wr->isUpdating()) return;
+
+ _wr->setUpdating (true);
+ SPDocument *doc = SP_ACTIVE_DOCUMENT;
+ Gtk::ScrolledWindow *s = reinterpret_cast<Gtk::ScrolledWindow*>(_packable);
+ Gtk::TextView *tv = reinterpret_cast<Gtk::TextView*>(s->get_child());
+ char const *text = tv->get_buffer()->get_text().c_str();
+ if (rdf_set_work_entity (doc, _entity, text))
+ sp_document_done (doc);
+ _wr->setUpdating (false);
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/entity-entry.h b/src/ui/widget/entity-entry.h
new file mode 100644
index 000000000..5bdee9a90
--- /dev/null
+++ b/src/ui/widget/entity-entry.h
@@ -0,0 +1,84 @@
+/** \file
+ * \brief
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_ENTITY_ENTRY__H
+#define INKSCAPE_UI_WIDGET_ENTITY_ENTRY__H
+
+#include <gtkmm/textview.h>
+#include <gtkmm/tooltips.h>
+
+struct rdf_work_entity_t;
+class SPDocument;
+
+namespace Gtk {
+class TextBuffer;
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Registry;
+
+class EntityEntry {
+public:
+ static EntityEntry* create (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr);
+ virtual ~EntityEntry() = 0;
+ virtual void update (SPDocument *doc) = 0;
+ virtual void on_changed() = 0;
+ Gtk::Label _label;
+ Gtk::Widget *_packable;
+
+protected:
+ EntityEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr);
+ sigc::connection _changed_connection;
+ rdf_work_entity_t *_entity;
+ Gtk::Tooltips *_tt;
+ Registry *_wr;
+};
+
+class EntityLineEntry : public EntityEntry {
+public:
+ EntityLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr);
+ ~EntityLineEntry();
+ void update (SPDocument *doc);
+
+protected:
+ virtual void on_changed();
+};
+
+class EntityMultiLineEntry : public EntityEntry {
+public:
+ EntityMultiLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr);
+ ~EntityMultiLineEntry();
+ void update (SPDocument *doc);
+
+protected:
+ virtual void on_changed();
+ Gtk::TextView _v;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_ENTITY_ENTRY__H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/handlebox.cpp b/src/ui/widget/handlebox.cpp
new file mode 100644
index 000000000..b82b715bb
--- /dev/null
+++ b/src/ui/widget/handlebox.cpp
@@ -0,0 +1,48 @@
+/**
+ * \brief HandleBox Widget - Adds a detachment handle to another widget.
+ *
+ * This work really doesn't amount to much more than a convenience constructor
+ * for Gtk::HandleBox. Maybe this could be contributed back to Gtkmm, as
+ * Gtkmm provides several convenience constructors for other widgets as well.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "handlebox.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+HandleBox::HandleBox(Gtk::Widget *widget,
+ Gtk::PositionType position)
+ : _widget(widget)
+{
+ g_assert(_widget != NULL);
+ add(*Gtk::manage(_widget));
+ set_handle_position(position);
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/handlebox.h b/src/ui/widget/handlebox.h
new file mode 100644
index 000000000..41a993e9d
--- /dev/null
+++ b/src/ui/widget/handlebox.h
@@ -0,0 +1,50 @@
+/**
+ * \brief HandleBox Widget - Adds a detachment handle to another widget.
+ *
+ * This work really doesn't amount to much more than a convenience constructor
+ * for Gtk::HandleBox. Maybe this could be contributed back to Gtkmm, as
+ * Gtkmm provides several convenience constructors for other widgets as well.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_HANDLEBOX_H
+#define INKSCAPE_UI_WIDGET_HANDLEBOX_H
+
+#include <gtkmm/handlebox.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class HandleBox : public Gtk::HandleBox
+{
+public:
+ HandleBox(Gtk::Widget *widget,
+ Gtk::PositionType position = Gtk::POS_LEFT);
+
+protected:
+ Gtk::Widget *_widget;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_HANDLEBOX_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/icon-widget.cpp b/src/ui/widget/icon-widget.cpp
new file mode 100644
index 000000000..c456778b6
--- /dev/null
+++ b/src/ui/widget/icon-widget.cpp
@@ -0,0 +1,165 @@
+/**
+ * \brief Icon Widget
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ * based on work by Lauris Kaplinski in 2002 released under GPL
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "icon-widget.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * General purpose icon widget, supporting SVG, etc. icon loading
+ *
+ * \param ...
+ *
+ * An icon widget is a ...
+ */
+
+IconWidget::IconWidget()
+{
+ _pb = NULL;
+ _size = 0;
+}
+
+IconWidget::IconWidget(int unsigned size, int unsigned scale, gchar const *name)
+{
+ _size = std::max((int unsigned)128, std::min(size, (int unsigned)1));
+
+ char c[256];
+ g_snprintf (c, 256, "%d:%d:%s", _size, scale, name);
+ guchar *pixels = image_load_gtk(name, _size, scale);
+
+ if (pixels == NULL) {
+ g_warning("Couldn't find matching icon for %s - has this application been installed?", name);
+ _pb = NULL;
+ } else {
+ /* TODO
+ _pb = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB,
+ TRUE, 8, _size, _size, _size * 4,
+ (GdkPixbufDestroyNotify)nr_free, NULL);
+ */
+ }
+}
+
+IconWidget::IconWidget(int unsigned size, guchar const *px)
+{
+ _size = std::max((int unsigned)128, std::min(size, (int unsigned)1));
+
+ /*
+ _pb = gdk_pixbuf_new_from_data((guchar *)px, GDK_COLORSPACE_RGB,
+ TRUE, 8, _size, _size, _size * 4, NULL, NULL);
+ */
+}
+
+IconWidget::~IconWidget() {
+}
+
+void IconWidget::size_request(Gtk::Requisition &requisition)
+{
+ requisition.width = _size;
+ requisition.height = _size;
+}
+
+void IconWidget::size_allocate(Gtk::Allocation const &allocation)
+{
+ Gtk::Widget::size_allocate(allocation);
+
+ if (this->is_drawable()) {
+ this->queue_draw();
+ }
+}
+
+int IconWidget::expose(GdkEventExpose *event)
+{
+ if (this->is_drawable()) {
+ paint(&(event->area));
+ }
+ return true;
+}
+
+void IconWidget::paint(GdkRectangle const *area)
+{
+ Gtk::Allocation allocation = get_allocation();
+ int const x_pad = std::max(0, (allocation.get_width() - _size)/2);
+ int const y_pad = std::max(0, (allocation.get_height() - _size)/2);
+
+ int const x_max = std::max(area->x, allocation.get_x() + x_pad);
+ int const y_max = std::max(area->y, allocation.get_y() + y_pad);
+ int const x_min = std::min(area->x + area->width,
+ allocation.get_x() + x_pad + _size);
+ int const y_min = std::min(area->y + area->height,
+ allocation.get_y() + y_pad + _size);
+
+ if (_pb) {
+ gdk_draw_pixbuf(this->get_window()->gobj(), NULL, _pb,
+ x_max - allocation.get_x() - x_pad,
+ y_max - allocation.get_y() - y_pad,
+ x_max, y_max,
+ x_min - x_max, y_min - y_max,
+ GDK_RGB_DITHER_NORMAL, x_max, y_max);
+ }
+}
+
+guchar* IconWidget::image_load(gchar const *name, int unsigned size, int unsigned scale)
+{
+ guchar *px;
+
+ if (_do_bitmap_icons) {
+ px = image_load_pixmap(name, size, scale);
+ if (!px) {
+ px = image_load_svg(name, size, scale);
+ }
+ } else {
+ px = image_load_svg(name, size, scale);
+ if (!px) {
+ px = image_load_pixmap(name, size, scale);
+ }
+ }
+ return px;
+}
+
+guchar* IconWidget::image_load_pixmap(gchar const *name, int unsigned size, int unsigned scale)
+{
+ // TODO
+ return NULL;
+}
+
+guchar* IconWidget::image_load_svg(gchar const *name, int unsigned size, int unsigned scale)
+{
+ // TODO
+ return NULL;
+}
+
+guchar* IconWidget::image_load_gtk(gchar const *name, int unsigned size, int unsigned scale)
+{
+ // TODO
+ return NULL;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/icon-widget.h b/src/ui/widget/icon-widget.h
new file mode 100644
index 000000000..3ca461b33
--- /dev/null
+++ b/src/ui/widget/icon-widget.h
@@ -0,0 +1,63 @@
+/**
+ * \brief Icon Widget - General image widget (including SVG icons)
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_ICON_H
+#define INKSCAPE_UI_WIDGET_ICON_H
+
+#include <gtkmm/image.h>
+#include <gdkmm/rectangle.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class IconWidget : public Gtk::Widget
+{
+public:
+ IconWidget();
+ IconWidget(int unsigned size, int unsigned scale, gchar const *name);
+ IconWidget(int unsigned size, guchar const *px);
+ virtual ~IconWidget();
+
+ // Overrides of Gtk::Widget functions
+ void size_request(Gtk::Requisition &requisition);
+ void size_allocate(Gtk::Allocation const &allocation);
+
+ int expose(GdkEventExpose *event);
+ void paint(GdkRectangle const *area);
+ guchar* image_load(gchar const *name, int unsigned size, int unsigned scale);
+ guchar* image_load_pixmap(gchar const *name, int unsigned size, int unsigned scale);
+ guchar* image_load_svg(gchar const *name, int unsigned size, int unsigned scale);
+ guchar* image_load_gtk(gchar const *name, int unsigned size, int unsigned scale);
+
+protected:
+ int _size;
+ GdkPixbuf *_pb;
+ bool _do_bitmap_icons;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_ICON_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/imageicon.cpp b/src/ui/widget/imageicon.cpp
new file mode 100644
index 000000000..6a817e30d
--- /dev/null
+++ b/src/ui/widget/imageicon.cpp
@@ -0,0 +1,442 @@
+/*
+ * A simple image display widget, using Inkscape's own rendering engine
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004 The Inkscape Organization
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+
+
+#include "imageicon.h"
+#include <sys/stat.h>
+#include "svg-view-widget.h"
+#include "document.h"
+#include "inkscape.h"
+
+
+namespace Inkscape
+{
+namespace UI
+{
+namespace Widget
+{
+
+
+
+typedef enum {
+ SVG_TYPES,
+ IMPORT_TYPES,
+ EXPORT_TYPES
+ } FileDialogType;
+
+
+/*#########################################################################
+### ImageIcon widget
+#########################################################################*/
+
+
+/**
+ * Constructor
+ */
+ImageIcon::ImageIcon()
+{
+ init();
+}
+
+/**
+ * Construct from a file name
+ */
+ImageIcon::ImageIcon(const Glib::ustring &fileName)
+{
+ init();
+ showSvgFile(fileName);
+}
+
+/**
+ * Copy Constructor
+ */
+ImageIcon::ImageIcon(const ImageIcon &other)
+ : sigc::trackable(), Glib::ObjectBase(), Gtk::VBox()
+{
+ init();
+ document = other.document;
+ viewerGtkmm = other.viewerGtkmm;
+ showingBrokenImage = other.showingBrokenImage;
+}
+
+/**
+ * Destructor
+ */
+ImageIcon::~ImageIcon()
+{
+ if (document)
+ sp_document_unref(document);
+}
+
+
+/**
+ * basic initialization, called by the various constructors
+ */
+void ImageIcon::init()
+{
+ if (!INKSCAPE)
+ inkscape_application_init("",false);
+ document = NULL;
+ viewerGtkmm = NULL;
+ //set_size_request(150,150);
+ showingBrokenImage = false;
+}
+
+
+bool ImageIcon::showSvgDocument(const SPDocument *docArg)
+{
+
+ if (document)
+ sp_document_unref(document);
+
+ SPDocument *doc = (SPDocument *)docArg;
+
+ sp_document_ref(doc);
+ document = doc;
+
+ //This should remove it from the box, and free resources
+ //if (viewerGtkmm)
+ // viewerGtkmm->destroy();
+
+ GtkWidget *viewerGtk = sp_svg_view_widget_new(doc);
+ viewerGtkmm = Glib::wrap(viewerGtk);
+
+ viewerGtkmm->show();
+ pack_start(*viewerGtkmm, TRUE, TRUE, 0);
+
+ //GtkWidget *vbox = (GtkWidget *)gobj();
+ //gtk_box_pack_start(GTK_BOX(vbox), viewerGtk, TRUE, TRUE, 0);
+
+ return true;
+}
+
+bool ImageIcon::showSvgFile(const Glib::ustring &theFileName)
+{
+ Glib::ustring fileName = theFileName;
+
+ fileName = Glib::filename_to_utf8(fileName);
+
+ SPDocument *doc = sp_document_new (fileName.c_str(), 0);
+ if (!doc) {
+ g_warning("SVGView: error loading document '%s'\n", fileName.c_str());
+ return false;
+ }
+
+ showSvgDocument(doc);
+
+ sp_document_unref(doc);
+
+ return true;
+}
+
+
+
+bool ImageIcon::showSvgFromMemory(const char *xmlBuffer)
+{
+ if (!xmlBuffer)
+ return false;
+
+ gint len = (gint)strlen(xmlBuffer);
+ SPDocument *doc = sp_document_new_from_mem(xmlBuffer, len, 0);
+ if (!doc) {
+ g_warning("SVGView: error loading buffer '%s'\n",xmlBuffer);
+ return false;
+ }
+
+ showSvgDocument(doc);
+
+ sp_document_unref(doc);
+
+ return true;
+}
+
+
+
+bool ImageIcon::showBitmap(const Glib::ustring &theFileName)
+{
+ Glib::ustring fileName = theFileName;
+
+
+ /*#####################################
+ # LET'S HAVE SOME FUN WITH SVG!
+ # Instead of just loading an image, why
+ # don't we make a lovely little svg and
+ # display it nicely?
+ #####################################*/
+
+ //Arbitrary size of svg doc -- rather 'portrait' shaped
+ gint previewWidth = 400;
+ gint previewHeight = 600;
+
+ //Get some image info. Smart pointer does not need to be deleted
+ Glib::RefPtr<Gdk::Pixbuf> img = Gdk::Pixbuf::create_from_file(fileName);
+ gint imgWidth = img->get_width();
+ gint imgHeight = img->get_height();
+
+ //Find the minimum scale to fit the image inside the preview area
+ double scaleFactorX = (0.9 *(double)previewWidth) / ((double)imgWidth);
+ double scaleFactorY = (0.9 *(double)previewHeight) / ((double)imgHeight);
+ double scaleFactor = scaleFactorX;
+ if (scaleFactorX > scaleFactorY)
+ scaleFactor = scaleFactorY;
+
+ //Now get the resized values
+ gint scaledImgWidth = (int) (scaleFactor * (double)imgWidth);
+ gint scaledImgHeight = (int) (scaleFactor * (double)imgHeight);
+
+ //center the image on the area
+ gint imgX = (previewWidth - scaledImgWidth) / 2;
+ gint imgY = (previewHeight - scaledImgHeight) / 2;
+
+ //wrap a rectangle around the image
+ gint rectX = imgX-1;
+ gint rectY = imgY-1;
+ gint rectWidth = scaledImgWidth +2;
+ gint rectHeight = scaledImgHeight+2;
+
+ //Our template. Modify to taste
+ gchar const *xformat =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<svg\n"
+ "xmlns=\"http://www.w3.org/2000/svg\"\n"
+ "xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
+ "width=\"%d\" height=\"%d\">\n"
+ "<rect\n"
+ " style=\"fill:#eeeeee;stroke:none\"\n"
+ " x=\"-100\" y=\"-100\" width=\"4000\" height=\"4000\"/>\n"
+ "<image x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"\n"
+ "xlink:href=\"%s\"/>\n"
+ "<rect\n"
+ " style=\"fill:none;"
+ " stroke:#000000;stroke-width:1.0;"
+ " stroke-linejoin:miter;stroke-opacity:1.0000000;"
+ " stroke-miterlimit:4.0000000;stroke-dasharray:none\"\n"
+ " x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"/>\n"
+ "</svg>\n\n";
+
+ //if (!Glib::get_charset()) //If we are not utf8
+ fileName = Glib::filename_to_utf8(fileName);
+
+ //Fill in the template
+ /* FIXME: Do proper XML quoting for fileName. */
+ gchar *xmlBuffer = g_strdup_printf(xformat,
+ previewWidth, previewHeight,
+ imgX, imgY, scaledImgWidth, scaledImgHeight,
+ fileName.c_str(),
+ rectX, rectY, rectWidth, rectHeight);
+
+ //g_message("%s\n", xmlBuffer);
+
+ //now show it!
+ showSvgFromMemory(xmlBuffer);
+ g_free(xmlBuffer);
+
+ return true;
+}
+
+
+
+void ImageIcon::showBrokenImage(const Glib::ustring &errorMessage)
+{
+ //Are we already showing it?
+ if (showingBrokenImage)
+ return;
+
+ //Our template. Modify to taste
+ gchar const *xformat =
+ "<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
+ "<!-- Created with Inkscape (http://www.inkscape.org/) -->"
+ "<svg"
+ " xmlns:xml='http://www.w3.org/XML/1998/namespace'"
+ " xmlns:svg='http://www.w3.org/2000/svg'"
+ " xmlns='http://www.w3.org/2000/svg'"
+ " id='svg2'"
+ " height='64.000000'"
+ " width='64.000000'"
+ " y='0.00000000'"
+ " x='0.00000000'"
+ " version='1.0'>"
+ " <defs"
+ " id='defs3' />"
+ " <rect"
+ " id='rect1723'"
+ " style='fill:#fefefe;fill-opacity:1.0000000;stroke:#fe0101;stroke-opacity:1.0000000'"
+ " y='0.74437392'"
+ " x='0.52374262'"
+ " height='62.698864'"
+ " width='62.701584' />"
+ " <path"
+ " id='path1725'"
+ " style='fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#fe0101;stroke-width:0.99443889px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000'"
+ " d='M 0.35436684,0.57368969 L 62.861950,63.081272' />"
+ " <path"
+ " id='path1727'"
+ " style='fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#fe0101;stroke-width:0.99443889px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000'"
+ " d='M 0.53194379,63.258849 L 63.217104,0.92884358' />"
+ " <path"
+ " id='text1729'"
+ " style='font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial Black'"
+ " d='M 11.027113,15.116791 L 13.421921,15.116791 L 13.421921,18.076798 C 13.658875,17.828198 13.926907,17.641741 14.226014,17.517426 C 14.529009,17.393131 14.863071,17.330979 15.228229,17.330969 C 15.981815,17.330979 16.605278,17.602888 17.098629,18.146717 C 17.591951,18.686677 17.838621,19.463583 17.838631,20.477433 C 17.838621,21.153343 17.725971,21.749619 17.500671,22.266259 C 17.275361,22.779022 16.962660,23.163581 16.562557,23.419968 C 16.166333,23.672456 15.725439,23.798710 15.239874,23.798710 C 14.824228,23.798710 14.443547,23.709359 14.097831,23.530668 C 13.837556,23.390830 13.553992,23.128627 13.247118,22.744057 L 13.247118,23.658862 L 11.027113,23.658862 L 11.027113,15.116791 M 13.404438,20.547352 C 13.404438,21.079536 13.503494,21.466054 13.701606,21.706887 C 13.903597,21.943842 14.158034,22.062320 14.464918,22.062320 C 14.748482,22.062320 14.985437,21.945791 15.175782,21.712715 C 15.370006,21.475760 15.467113,21.079536 15.467123,20.524052 C 15.467113,20.034599 15.371945,19.675289 15.181610,19.446090 C 14.995153,19.216912 14.767903,19.102313 14.499872,19.102313 C 14.177455,19.102313 13.913313,19.222739 13.707434,19.463573 C 13.505433,19.700537 13.404438,20.061797 13.404438,20.547352 M 18.986502,17.470807 L 21.206507,17.470807 L 21.206507,18.484677 C 21.420152,18.045732 21.639635,17.744675 21.864935,17.581518 C 22.094123,17.414492 22.375749,17.330979 22.709820,17.330969 C 23.059425,17.330979 23.442055,17.439740 23.857701,17.657264 L 23.123527,19.347034 C 22.843831,19.230506 22.622419,19.172242 22.459271,19.172232 C 22.148509,19.172242 21.907666,19.300425 21.736752,19.556801 C 21.492021,19.918071 21.369655,20.593971 21.369665,21.584522 L 21.369665,23.658862 L 18.986502,23.658862 L 18.986502,17.470807 M 24.149042,20.582316 C 24.149042,19.638385 24.467571,18.861480 25.104638,18.251600 C 25.741695,17.637853 26.602114,17.330979 27.685903,17.330969 C 28.925063,17.330979 29.861228,17.690289 30.494417,18.408921 C 31.003281,18.987724 31.257718,19.700537 31.257728,20.547352 C 31.257718,21.499070 30.941129,22.279853 30.307960,22.889723 C 29.678659,23.495714 28.806586,23.798710 27.691730,23.798710 C 26.697291,23.798710 25.893188,23.546212 25.279440,23.041226 C 24.525835,22.415813 24.149042,21.596177 24.149042,20.582316 M 26.526367,20.576489 C 26.526367,21.128094 26.637078,21.535973 26.858500,21.800116 C 27.083800,22.064269 27.365425,22.196340 27.703385,22.196340 C 28.045214,22.196340 28.324899,22.066208 28.542443,21.805944 C 28.763855,21.545679 28.874566,21.128094 28.874566,20.553179 C 28.874566,20.017127 28.763855,19.618964 28.542443,19.358689 C 28.321021,19.094546 28.047163,18.962475 27.720867,18.962465 C 27.375141,18.962475 27.089627,19.096485 26.864327,19.364517 C 26.639017,19.628669 26.526367,20.032660 26.526367,20.576489 M 32.388127,15.116791 L 34.812072,15.116791 L 34.812072,19.521837 L 36.583416,17.470807 L 39.502631,17.470807 L 37.282626,19.638375 L 39.630824,23.658862 L 36.956330,23.658862 L 35.703566,21.176653 L 34.812072,22.050665 L 34.812072,23.658862 L 32.388127,23.658862 L 32.388127,15.116791 M 46.832739,21.153343 L 42.078078,21.153343 C 42.120799,21.534024 42.223744,21.817598 42.386891,22.004056 C 42.616080,22.272087 42.915187,22.406107 43.284223,22.406107 C 43.517290,22.406107 43.738702,22.347833 43.948479,22.231295 C 44.076662,22.157498 44.214561,22.027365 44.362175,21.840908 L 46.698719,22.056492 C 46.341337,22.678017 45.910148,23.124739 45.405172,23.396658 C 44.900176,23.664689 44.175718,23.798710 43.231777,23.798710 C 42.412140,23.798710 41.767306,23.684110 41.297285,23.454922 C 40.827253,23.221855 40.436856,22.854768 40.126104,22.353661 C 39.819220,21.848675 39.665779,21.256287 39.665779,20.576489 C 39.665779,19.609248 39.974601,18.826515 40.592247,18.228291 C 41.213762,17.630086 42.070302,17.330979 43.161858,17.330969 C 44.047525,17.330979 44.746735,17.464989 45.259497,17.733020 C 45.772250,18.001051 46.162646,18.389509 46.430688,18.898373 C 46.698709,19.407248 46.832729,20.069564 46.832739,20.885312 L 46.832739,21.153343 M 44.420439,20.017117 C 44.373820,19.558750 44.249515,19.230506 44.047525,19.032394 C 43.849413,18.834282 43.587209,18.735226 43.260914,18.735226 C 42.884111,18.735226 42.583054,18.884779 42.357764,19.183887 C 42.214028,19.370354 42.122739,19.648091 42.083906,20.017117 L 44.420439,20.017117 M 47.934001,17.470807 L 50.142351,17.470807 L 50.142351,18.478849 C 50.472535,18.067092 50.806606,17.773812 51.144556,17.599000 C 51.482507,17.420319 51.894264,17.330979 52.379838,17.330969 C 53.036317,17.330979 53.549080,17.527142 53.918116,17.919478 C 54.291021,18.307935 54.477478,18.910038 54.477488,19.725776 L 54.477488,23.658862 L 52.094325,23.658862 L 52.094325,20.256021 C 52.094325,19.867563 52.022457,19.593705 51.878731,19.434436 C 51.735004,19.271298 51.533004,19.189714 51.272750,19.189714 C 50.985287,19.189714 50.752220,19.298486 50.573530,19.516019 C 50.394839,19.733553 50.305499,20.123950 50.305499,20.687200 L 50.305499,23.658862 L 47.934001,23.658862 L 47.934001,17.470807' />"
+ " <path"
+ " id='text1733'"
+ " style='font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial Black'"
+ " d='M 13.747801,34.415696 L 16.119299,34.415696 L 16.119299,36.029710 L 13.747801,36.029710 L 13.747801,34.415696 M 13.747801,36.769712 L 16.119299,36.769712 L 16.119299,42.957766 L 13.747801,42.957766 L 13.747801,36.769712 M 17.640095,36.769712 L 19.854272,36.769712 L 19.854272,37.672871 C 20.172801,37.296078 20.493269,37.028047 20.815696,36.868768 C 21.141991,36.709508 21.534327,36.629883 21.992704,36.629874 C 22.486035,36.629883 22.876432,36.717285 23.163894,36.892077 C 23.451337,37.066890 23.686352,37.327154 23.868931,37.672871 C 24.241836,37.268880 24.581735,36.995022 24.888619,36.851295 C 25.195493,36.703681 25.574225,36.629883 26.024845,36.629874 C 26.689090,36.629883 27.207670,36.827986 27.580595,37.224210 C 27.953500,37.616546 28.139957,38.232243 28.139967,39.071300 L 28.139967,42.957766 L 25.762641,42.957766 L 25.762641,39.432560 C 25.762631,39.152874 25.708246,38.945056 25.599484,38.809097 C 25.440214,38.595452 25.242102,38.488619 25.005157,38.488619 C 24.725462,38.488619 24.500161,38.589624 24.329247,38.791615 C 24.158323,38.993615 24.072861,39.317971 24.072871,39.764683 L 24.072871,42.957766 L 21.695536,42.957766 L 21.695536,39.549099 C 21.695536,39.277179 21.679993,39.092671 21.648926,38.995554 C 21.598419,38.840173 21.511017,38.715868 21.386723,38.622640 C 21.262408,38.525523 21.116742,38.476974 20.949706,38.476964 C 20.677787,38.476974 20.454426,38.579908 20.279624,38.785787 C 20.104821,38.991666 20.017420,39.329626 20.017420,39.799647 L 20.017420,42.957766 L 17.640095,42.957766 L 17.640095,36.769712 M 31.717620,38.774132 L 29.450995,38.535238 C 29.536457,38.139014 29.658813,37.828252 29.818082,37.602952 C 29.981230,37.373764 30.214307,37.175651 30.517302,37.008616 C 30.734826,36.888199 31.033943,36.794970 31.414624,36.728930 C 31.795305,36.662899 32.207063,36.629883 32.649906,36.629874 C 33.360771,36.629883 33.931797,36.670665 34.362976,36.752239 C 34.794155,36.829935 35.153476,36.995022 35.440938,37.247510 C 35.642928,37.422322 35.802188,37.670932 35.918736,37.993339 C 36.035264,38.311877 36.093529,38.616812 36.093538,38.908153 L 36.093538,41.640911 C 36.093529,41.932251 36.111011,42.161440 36.145975,42.328476 C 36.184818,42.491623 36.266392,42.701390 36.390707,42.957766 L 34.164874,42.957766 C 34.075524,42.798497 34.017250,42.678081 33.990062,42.596507 C 33.962874,42.511045 33.935676,42.378973 33.908488,42.200282 C 33.597726,42.499390 33.288903,42.713045 32.982029,42.841228 C 32.562495,43.012152 32.074991,43.097614 31.519508,43.097614 C 30.781445,43.097614 30.220134,42.926690 29.835565,42.584852 C 29.454883,42.243014 29.264538,41.821540 29.264538,41.320443 C 29.264538,40.850411 29.402437,40.463903 29.678244,40.160907 C 29.954042,39.857922 30.462916,39.632612 31.204857,39.484997 C 32.094413,39.306316 32.671267,39.182011 32.935419,39.112082 C 33.199562,39.038285 33.479248,38.943117 33.774477,38.826569 C 33.774467,38.535238 33.714264,38.331299 33.593847,38.214760 C 33.473421,38.098232 33.261715,38.039958 32.958719,38.039958 C 32.570271,38.039958 32.278931,38.102110 32.084707,38.226415 C 31.933204,38.323532 31.810838,38.506101 31.717620,38.774132 M 33.774477,40.021069 C 33.448172,40.137607 33.108273,40.240542 32.754790,40.329882 C 32.273103,40.458075 31.968169,40.584319 31.839975,40.708624 C 31.707904,40.836817 31.641863,40.982483 31.641873,41.145640 C 31.641863,41.332098 31.705965,41.485530 31.834158,41.605956 C 31.966219,41.722484 32.158504,41.780759 32.411002,41.780759 C 32.675145,41.780759 32.919876,41.716667 33.145176,41.588474 C 33.374365,41.460281 33.535573,41.304900 33.628802,41.122331 C 33.725909,40.935873 33.774467,40.695030 33.774477,40.399811 L 33.774477,40.021069 M 41.996080,36.769712 L 44.216085,36.769712 L 44.216085,42.613989 L 44.221913,42.887847 C 44.221903,43.276295 44.138390,43.645331 43.971354,43.994936 C 43.808196,44.348430 43.588724,44.633943 43.312926,44.851476 C 43.041007,45.069010 42.693341,45.226330 42.269939,45.323447 C 41.850405,45.420554 41.368718,45.469112 40.824890,45.469112 C 39.581841,45.469112 38.727240,45.282655 38.261107,44.909741 C 37.798842,44.536826 37.567715,44.037667 37.567715,43.412255 C 37.567715,43.334569 37.571603,43.229686 37.579369,43.097614 L 39.880948,43.359818 C 39.939213,43.573463 40.028563,43.721078 40.148979,43.802652 C 40.323782,43.923068 40.543255,43.983282 40.807407,43.983282 C 41.149246,43.983282 41.403683,43.891992 41.570719,43.709423 C 41.741633,43.526854 41.827095,43.208315 41.827095,42.753827 L 41.827095,41.815713 C 41.594018,42.091521 41.360952,42.291572 41.127885,42.415877 C 40.762737,42.610101 40.368452,42.707218 39.945050,42.707218 C 39.117637,42.707218 38.449503,42.345958 37.940629,41.623428 C 37.579369,41.110676 37.398739,40.432827 37.398739,39.589880 C 37.398739,38.626528 37.631806,37.892353 38.097949,37.387358 C 38.564093,36.882372 39.173962,36.629883 39.927568,36.629874 C 40.409244,36.629883 40.805468,36.711457 41.116230,36.874595 C 41.430871,37.037753 41.724151,37.307733 41.996080,37.684526 L 41.996080,36.769712 M 39.764410,39.770510 C 39.764410,40.217232 39.859578,40.549365 40.049923,40.766898 C 40.240269,40.980544 40.490818,41.087366 40.801580,41.087366 C 41.096799,41.087366 41.343470,40.976665 41.541582,40.755243 C 41.743572,40.529943 41.844577,40.191983 41.844577,39.741383 C 41.844577,39.290773 41.739694,38.946996 41.529937,38.710041 C 41.320160,38.469198 41.063784,38.348781 40.760798,38.348781 C 40.457802,38.348781 40.215020,38.459492 40.032451,38.680904 C 39.853760,38.898437 39.764410,39.261646 39.764410,39.770510 M 52.507607,40.452248 L 47.752946,40.452248 C 47.795667,40.832929 47.898612,41.116503 48.061759,41.302961 C 48.290948,41.570992 48.590055,41.705012 48.959091,41.705012 C 49.192158,41.705012 49.413580,41.646738 49.623347,41.530200 C 49.751530,41.456402 49.889429,41.326270 50.037043,41.139813 L 52.373587,41.355397 C 52.016205,41.976922 51.585026,42.423643 51.080040,42.695563 C 50.575044,42.963594 49.850586,43.097614 48.906644,43.097614 C 48.087008,43.097614 47.442184,42.983015 46.972153,42.753827 C 46.502121,42.520760 46.111734,42.153673 45.800972,41.652565 C 45.494088,41.147579 45.340656,40.555192 45.340656,39.875394 C 45.340656,38.908153 45.649469,38.125420 46.267115,37.527195 C 46.888640,36.928991 47.745170,36.629883 48.836725,36.629874 C 49.722393,36.629883 50.421612,36.763894 50.934375,37.031925 C 51.447127,37.299956 51.837514,37.688414 52.105555,38.197278 C 52.373577,38.706152 52.507597,39.368469 52.507607,40.184217 L 52.507607,40.452248 M 50.095317,39.316022 C 50.048698,38.857655 49.924393,38.529411 49.722403,38.331299 C 49.524281,38.133187 49.262077,38.034131 48.935782,38.034131 C 48.558979,38.034131 48.257932,38.183684 48.032632,38.482792 C 47.888896,38.669259 47.797616,38.946996 47.758774,39.316022 L 50.095317,39.316022' />"
+ " <text"
+ " xml:space='preserve'"
+ " id='text1644'"
+ " style='font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans'"
+ " y='59.288345'"
+ " x='12.760736'><tspan"
+ " id='tspan1646'"
+ " y='59.288345'"
+ " x='12.760736'>%s</tspan></text>"
+ "</svg>";
+
+ //Fill in the template
+ char *cErrorMessage = (char *)errorMessage.c_str();
+ gchar *xmlBuffer = g_strdup_printf(xformat, cErrorMessage);
+
+ //g_message("%s\n", xmlBuffer);
+
+ //now show it!
+ showSvgFromMemory(xmlBuffer);
+ g_free(xmlBuffer);
+ showingBrokenImage = true;
+
+}
+
+
+
+static bool
+hasSuffix(const Glib::ustring &str, Glib::ustring &ext)
+{
+ int strLen = str.length();
+ int extLen = ext.length();
+ if (extLen > strLen)
+ {
+ return false;
+ }
+ int strpos = strLen-1;
+ for (int extpos = extLen-1 ; extpos>=0 ; extpos--, strpos--)
+ {
+ Glib::ustring::value_type ch = str[strpos];
+ if (ch != ext[extpos])
+ {
+ if ( ((ch & 0xff80) != 0) ||
+ static_cast<Glib::ustring::value_type>( g_ascii_tolower( static_cast<gchar>(0x07f & ch) ) ) != ext[extpos] )
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
+/**
+ * Return true if the image is loadable by Gdk, else false
+ */
+static bool
+isValidImageIconFile(const Glib::ustring &fileName)
+{
+ std::vector<Gdk::PixbufFormat>formats = Gdk::Pixbuf::get_formats();
+ for (unsigned int i=0; i<formats.size(); i++)
+ {
+ Gdk::PixbufFormat format = formats[i];
+ std::vector<Glib::ustring>extensions = format.get_extensions();
+ for (unsigned int j=0; j<extensions.size(); j++)
+ {
+ Glib::ustring ext = extensions[j];
+ if (hasSuffix(fileName, ext))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool ImageIcon::show(const Glib::ustring &fileName)
+{
+
+ if (!Glib::file_test(fileName, Glib::FILE_TEST_EXISTS))
+ return false;
+
+ gchar *fName = (gchar *)fileName.c_str();
+ //g_message("fname:%s\n", fName);
+
+
+ if (Glib::file_test(fileName, Glib::FILE_TEST_IS_REGULAR))
+ {
+ struct stat info;
+ if (stat(fName, &info))
+ {
+ Glib::ustring err = "cannot get file info";
+ showBrokenImage(err);
+ return false;
+ }
+ long fileLen = info.st_size;
+ if (fileLen > 0x150000L)
+ {
+ Glib::ustring err = "File too large";
+ showBrokenImage(err);
+ return false;
+ }
+ }
+
+ Glib::ustring svg = ".svg";
+ Glib::ustring svgz = ".svgz";
+
+ if (hasSuffix(fileName, svg) || hasSuffix(fileName, svgz) )
+ {
+ if (!showSvgFile(fileName))
+ {
+ showBrokenImage(bitmapError);
+ return false;
+ }
+ return true;
+ }
+ else if (isValidImageIconFile(fileName))
+ {
+ if (!showBitmap(fileName))
+ {
+ showBrokenImage(bitmapError);
+ return false;
+ }
+ return true;
+ }
+ else
+ {
+ showBrokenImage("unsupported file type");
+ return false;
+ }
+}
+
+
+
+
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+/*#########################################################################
+### E N D O F F I L E
+#########################################################################*/
+
+
+
diff --git a/src/ui/widget/imageicon.h b/src/ui/widget/imageicon.h
new file mode 100644
index 000000000..803b2f53f
--- /dev/null
+++ b/src/ui/widget/imageicon.h
@@ -0,0 +1,138 @@
+#ifndef __UI_DIALOG_IMAGE_H__
+#define __UI_DIALOG_IMAGE_H__
+/*
+ * A simple image display widget, using Inkscape's own rendering engine
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004 The Inkscape Organization
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm/ustring.h>
+#include <gtkmm/box.h>
+
+
+class SPDocument;
+
+namespace Inkscape
+{
+namespace UI
+{
+namespace Widget
+{
+
+
+/*#########################################################################
+### ImageIcon widget
+#########################################################################*/
+
+/**
+ * This class is evolved from the SVGPreview widget of the FileChooser
+ * This uses Inkscape's renderer to show images in a variety of formats,
+ * including SVG
+ */
+class ImageIcon : public Gtk::VBox
+{
+public:
+
+ /**
+ * Constructor
+ */
+ ImageIcon();
+
+ /**
+ * Construct from a file name
+ */
+ ImageIcon(const Glib::ustring &fileName);
+
+ /**
+ * Copy Constructor
+ */
+ ImageIcon(const ImageIcon &other);
+
+ /**
+ * Destructor
+ */
+ ~ImageIcon();
+
+ /**
+ *
+ */
+ bool showSvgDocument(const SPDocument *doc);
+
+ /**
+ *
+ */
+ bool showSvgFile(const Glib::ustring &fileName);
+
+ /**
+ *
+ */
+ bool showSvgFromMemory(const char *xmlBuffer);
+
+ /**
+ * Show image embedded in SVG
+ */
+ bool showBitmap(const Glib::ustring &fileName);
+
+ /**
+ * Show the "Too large" image
+ */
+ void showBrokenImage(const Glib::ustring &reason);
+
+ /**
+ *
+ */
+ bool show(const Glib::ustring &fileName);
+
+private:
+
+ /**
+ * basic initialization, called by the various constructors
+ */
+ void init();
+
+ /**
+ * The svg document we are currently showing
+ */
+ SPDocument *document;
+
+ /**
+ * The sp_svg_view widget
+ */
+ Gtk::Widget *viewerGtkmm;
+
+ /**
+ * are we currently showing the "broken image" image?
+ */
+ bool showingBrokenImage;
+
+
+ /**
+ * will be set by showImageIcon as a side-effect of an error
+ */
+ Glib::ustring bitmapError;
+
+
+ /**
+ * will be set by showImageIcon as a side-effect of an error
+ */
+ Glib::ustring svgError;
+
+};
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif /* __UI_DIALOG_IMAGE_H__ */
+/*#########################################################################
+### E N D O F F I L E
+#########################################################################*/
diff --git a/src/ui/widget/labelled.cpp b/src/ui/widget/labelled.cpp
new file mode 100644
index 000000000..64f9aef83
--- /dev/null
+++ b/src/ui/widget/labelled.cpp
@@ -0,0 +1,102 @@
+/**
+ * \brief Labelled Widget - Adds a label with optional icon or suffix to
+ * another widget.
+ *
+ * Authors:
+ * Carl Hetherington <inkscape@carlh.net>
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Carl Hetherington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* For getting the Gtkmmified Icon manager */
+#include "widgets/icon.h"
+
+#include "labelled.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a Labelled Widget.
+ *
+ * \param label Label.
+ * \param widget Widget to label; should be allocated with new, as it will
+ * be passed to Gtk::manage().
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the text
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to true).
+ */
+Labelled::Labelled(Glib::ustring const &label, Glib::ustring const &tooltip,
+ Gtk::Widget *widget,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ bool mnemonic)
+ : _widget(widget),
+ _label(new Gtk::Label(label, 1.0, 0.5, mnemonic)),
+ _suffix(new Gtk::Label(suffix, 0.0, 0.5)),
+ _tooltips()
+{
+ g_assert(g_utf8_validate(icon.c_str(), -1, NULL));
+ if (icon != "") {
+ _icon = sp_icon_get_icon(icon.c_str(), GTK_ICON_SIZE_LARGE_TOOLBAR);
+ pack_start(*Gtk::manage(_icon), Gtk::PACK_SHRINK);
+ }
+ pack_start(*Gtk::manage(_label), Gtk::PACK_EXPAND_WIDGET, 6);
+ pack_start(*Gtk::manage(_widget), Gtk::PACK_SHRINK, 6);
+ if (mnemonic) {
+ _label->set_mnemonic_widget(*_widget);
+ }
+ _tooltips.set_tip(*_widget, tooltip);
+}
+
+
+/**
+ * Allow the setting of the width of the labelled widget
+ */
+void Labelled::setWidgetSizeRequest(int width, int height)
+{
+ if (_widget)
+ _widget->set_size_request(width, height);
+
+
+}
+
+const Gtk::Widget* const
+Labelled::getWidget() const
+{
+ return _widget;
+}
+
+const Gtk::Label* const
+Labelled::getLabel() const
+{
+ return _label;
+}
+
+
+
+
+} // namespace Widget
+} // 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/widget/labelled.h b/src/ui/widget/labelled.h
new file mode 100644
index 000000000..1823aeef2
--- /dev/null
+++ b/src/ui/widget/labelled.h
@@ -0,0 +1,65 @@
+/**
+ * \brief Labelled Widget - Adds a label with optional icon or suffix to
+ * another widget.
+ *
+ * Authors:
+ * Carl Hetherington <inkscape@carlh.net>
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Carl Hetherington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_LABELLED_H
+#define INKSCAPE_UI_WIDGET_LABELLED_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/label.h>
+#include <gtkmm/image.h>
+#include <gtkmm/tooltips.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Labelled : public Gtk::HBox
+{
+public:
+ Labelled(Glib::ustring const &label, Glib::ustring const &tooltip,
+ Gtk::Widget *widget,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ bool mnemonic = true);
+
+ /**
+ * Allow the setting of the width of the labelled widget
+ */
+ void setWidgetSizeRequest(int width, int height);
+ const Gtk::Widget* const getWidget() const;
+ const Gtk::Label* const getLabel() const;
+
+protected:
+ Gtk::Widget *_widget;
+ Gtk::Label *_label;
+ Gtk::Label *_suffix;
+ Gtk::Widget *_icon;
+ Gtk::Tooltips _tooltips;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_LABELLED_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/widget/licensor.cpp b/src/ui/widget/licensor.cpp
new file mode 100644
index 000000000..9a5713220
--- /dev/null
+++ b/src/ui/widget/licensor.cpp
@@ -0,0 +1,146 @@
+/** \file
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/entry.h>
+
+#include "ui/widget/entity-entry.h"
+#include "ui/widget/registry.h"
+#include "dialogs/rdf.h"
+#include "inkscape.h"
+
+#include "licensor.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+const struct rdf_license_t _proprietary_license =
+ {_("Proprietary"), "", 0};
+
+class LicenseItem : public Gtk::RadioButton {
+public:
+ LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr);
+protected:
+ void on_toggled();
+ struct rdf_license_t const *_lic;
+ EntityEntry *_eep;
+ Registry &_wr;
+};
+
+LicenseItem::LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr)
+: Gtk::RadioButton(license->name), _lic(license), _eep(entity), _wr(wr)
+{
+ static Gtk::RadioButtonGroup group = get_group();
+ static bool first = true;
+ if (first) first = false;
+ else set_group (group);
+}
+
+/// \pre it is assumed that the license URI entry is a Gtk::Entry
+void
+LicenseItem::on_toggled()
+{
+ if (_wr.isUpdating()) return;
+
+ _wr.setUpdating (true);
+ rdf_set_license (SP_ACTIVE_DOCUMENT, _lic->details ? _lic : 0);
+ sp_document_done (SP_ACTIVE_DOCUMENT);
+ _wr.setUpdating (false);
+ reinterpret_cast<Gtk::Entry*>(_eep->_packable)->set_text (_lic->uri);
+ _eep->on_changed();
+}
+
+//---------------------------------------------------
+
+Licensor::Licensor()
+: Gtk::VBox(false,4)
+{
+}
+
+Licensor::~Licensor()
+{
+ if (_eentry) delete _eentry;
+}
+
+void
+Licensor::init (Gtk::Tooltips& tt, Registry& wr)
+{
+ /* add license-specific metadata entry areas */
+ rdf_work_entity_t* entity = rdf_find_entity ( "license_uri" );
+ _eentry = EntityEntry::create (entity, tt, wr);
+
+ LicenseItem *i;
+ wr.setUpdating (true);
+ i = manage (new LicenseItem (&_proprietary_license, _eentry, wr));
+ add (*i);
+ LicenseItem *pd = i;
+ for (struct rdf_license_t * license = rdf_licenses;
+ license && license->name;
+ license++) {
+ i = manage (new LicenseItem (license, _eentry, wr));
+ add(*i);
+ }
+ pd->set_active();
+ wr.setUpdating (false);
+
+ Gtk::HBox *box = manage (new Gtk::HBox);
+ pack_start (*box, true, true, 0);
+
+ box->pack_start (_eentry->_label, false, false, 5);
+ box->pack_start (*_eentry->_packable, true, true, 0);
+
+ show_all_children();
+}
+
+void
+Licensor::update (SPDocument *doc)
+{
+ /* identify the license info */
+ struct rdf_license_t * license = rdf_get_license (doc);
+
+ if (license) {
+ int i;
+ for (i=0; rdf_licenses[i].name; i++)
+ if (license == &rdf_licenses[i])
+ break;
+ reinterpret_cast<LicenseItem*>(children()[i+1].get_widget())->set_active();
+ }
+ else {
+ reinterpret_cast<LicenseItem*>(children()[0].get_widget())->set_active();
+ }
+
+ /* update the URI */
+ _eentry->update (doc);
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/licensor.h b/src/ui/widget/licensor.h
new file mode 100644
index 000000000..9f41a6d0d
--- /dev/null
+++ b/src/ui/widget/licensor.h
@@ -0,0 +1,59 @@
+/** \file
+ * \brief Widget for specifying a document's license; part of document
+ * preferences dialog.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_LICENSOR__H
+#define INKSCAPE_UI_WIDGET_LICENSOR__H
+
+#include <gtkmm/box.h>
+
+class SPDocument;
+
+namespace Gtk {
+ class Tooltips;
+}
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class EntityEntry;
+class Registry;
+
+
+class Licensor : public Gtk::VBox {
+public:
+ Licensor();
+ virtual ~Licensor();
+ void init (Gtk::Tooltips&, Registry&);
+ void update (SPDocument *doc);
+
+protected:
+ EntityEntry *_eentry;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_LICENSOR__H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/makefile.in b/src/ui/widget/makefile.in
new file mode 100644
index 000000000..2dfa00344
--- /dev/null
+++ b/src/ui/widget/makefile.in
@@ -0,0 +1,17 @@
+# Convenience stub makefile to call the real Makefile.
+
+@SET_MAKE@
+
+# Explicit so that it's the default rule.
+all:
+ cd ../.. && $(MAKE) ui/widget/all
+
+clean %.a %.o:
+ cd ../.. && $(MAKE) ui/widget/$@
+
+.PHONY: all clean
+
+OBJEXT = @OBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .a .$(OBJEXT)
diff --git a/src/ui/widget/notebook-page.cpp b/src/ui/widget/notebook-page.cpp
new file mode 100644
index 000000000..83be16a43
--- /dev/null
+++ b/src/ui/widget/notebook-page.cpp
@@ -0,0 +1,49 @@
+/**
+ * \brief Notebook page widget
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "notebook-page.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a NotebookPage
+ *
+ * \param label Label.
+ */
+
+NotebookPage::NotebookPage(int n_rows, int n_columns)
+ :_table(n_rows, n_columns)
+{
+ set_border_width(2);
+ _table.set_spacings(2);
+ pack_start(_table, false, false, 0);
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/notebook-page.h b/src/ui/widget/notebook-page.h
new file mode 100644
index 000000000..0341cb659
--- /dev/null
+++ b/src/ui/widget/notebook-page.h
@@ -0,0 +1,50 @@
+/**
+ * \brief Notebook Page Widget - A tabbed notebook page for dialogs.
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H
+#define INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/table.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class NotebookPage : public Gtk::VBox
+{
+public:
+ NotebookPage();
+ NotebookPage(int n_rows, int n_columns);
+
+ Gtk::Table& table() { return _table; }
+
+protected:
+ Gtk::Table _table;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp
new file mode 100644
index 000000000..ea0efeb2d
--- /dev/null
+++ b/src/ui/widget/page-sizer.cpp
@@ -0,0 +1,357 @@
+/** \file
+ *
+ * Paper-size widget and helper functions
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <cmath>
+#include <gtkmm/optionmenu.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/table.h>
+
+#include "ui/widget/scalar-unit.h"
+
+#include "helper/units.h"
+#include "inkscape.h"
+#include "desktop-handles.h"
+#include "document.h"
+#include "page-sizer.h"
+
+using std::pair;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+struct PaperSize {
+ char const * const name;
+ double const smaller;
+ double const larger;
+ SPUnitId const unit;
+};
+
+ /** \note
+ * The ISO page sizes in the table below differ from ghostscript's idea of page sizes (by
+ * less than 1pt). Being off by <1pt should be OK for most purposes, but may cause fuzziness
+ * (antialiasing) problems when printing to 72dpi or 144dpi printers or bitmap files due to
+ * postscript's different coordinate system (y=0 meaning bottom of page in postscript and top
+ * of page in SVG). I haven't looked into whether this does in fact cause fuzziness, I merely
+ * note the possibility. Rounding done by extension/internal/ps.cpp (e.g. floor/ceil calls)
+ * will also affect whether fuzziness occurs.
+ *
+ * The remainder of this comment discusses the origin of the numbers used for ISO page sizes in
+ * this table and in ghostscript.
+ *
+ * The versions here, in mm, are the official sizes according to
+ * <a href="http://en.wikipedia.org/wiki/Paper_sizes">http://en.wikipedia.org/wiki/Paper_sizes</a>
+ * at 2005-01-25. (The ISO entries in the below table
+ * were produced mechanically from the table on that page.)
+ *
+ * (The rule seems to be that A0, B0, ..., D0. sizes are rounded to the nearest number of mm
+ * from the "theoretical size" (i.e. 1000 * sqrt(2) or pow(2.0, .25) or the like), whereas
+ * going from e.g. A0 to A1 always take the floor of halving -- which by chance coincides
+ * exactly with flooring the "theoretical size" for n != 0 instead of the rounding to nearest
+ * done for n==0.)
+ *
+ * Ghostscript paper sizes are given in gs_statd.ps according to gs(1). gs_statd.ps always
+ * uses an integer number of pt: sometimes gs_statd.ps rounds to nearest (e.g. a1), sometimes
+ * floors (e.g. a10), sometimes ceils (e.g. a8).
+ *
+ * I'm not sure how ghostscript's gs_statd.ps was calculated: it isn't just rounding the
+ * "theoretical size" of each page to pt (see a0), nor is it rounding the a0 size times an
+ * appropriate power of two (see a1). Possibly it was prepared manually, with a human applying
+ * inconsistent rounding rules when converting from mm to pt.
+ */
+ /** \todo
+ * Should we include the JIS B series (used in Japan)
+ * (JIS B0 is sometimes called JB0, and similarly for JB1 etc)?
+ * Should we exclude B7--B10 and A7--10 to make the list smaller ?
+ * Should we include any of the ISO C, D and E series (see below) ?
+ */
+
+static PaperSize const inkscape_papers[] = {
+ { "A4", 210, 297, SP_UNIT_MM },
+ { "US Letter", 8.5, 11, SP_UNIT_IN },
+ { "US Legal", 8.5, 14, SP_UNIT_IN },
+ { "US Executive", 7.25, 10.5, SP_UNIT_IN },
+ { "A0", 841, 1189, SP_UNIT_MM },
+ { "A1", 594, 841, SP_UNIT_MM },
+ { "A2", 420, 594, SP_UNIT_MM },
+ { "A3", 297, 420, SP_UNIT_MM },
+ { "A5", 148, 210, SP_UNIT_MM },
+ { "A6", 105, 148, SP_UNIT_MM },
+ { "A7", 74, 105, SP_UNIT_MM },
+ { "A8", 52, 74, SP_UNIT_MM },
+ { "A9", 37, 52, SP_UNIT_MM },
+ { "A10", 26, 37, SP_UNIT_MM },
+ { "B0", 1000, 1414, SP_UNIT_MM },
+ { "B1", 707, 1000, SP_UNIT_MM },
+ { "B2", 500, 707, SP_UNIT_MM },
+ { "B3", 353, 500, SP_UNIT_MM },
+ { "B4", 250, 353, SP_UNIT_MM },
+ { "B5", 176, 250, SP_UNIT_MM },
+ { "B6", 125, 176, SP_UNIT_MM },
+ { "B7", 88, 125, SP_UNIT_MM },
+ { "B8", 62, 88, SP_UNIT_MM },
+ { "B9", 44, 62, SP_UNIT_MM },
+ { "B10", 31, 44, SP_UNIT_MM },
+
+#if 0 /* Whether to include or exclude these depends on how big we mind our page size menu
+ becoming. C series is used for envelopes; don't know what D and E series are used for. */
+ { "C0", 917, 1297, SP_UNIT_MM },
+ { "C1", 648, 917, SP_UNIT_MM },
+ { "C2", 458, 648, SP_UNIT_MM },
+ { "C3", 324, 458, SP_UNIT_MM },
+ { "C4", 229, 324, SP_UNIT_MM },
+ { "C5", 162, 229, SP_UNIT_MM },
+ { "C6", 114, 162, SP_UNIT_MM },
+ { "C7", 81, 114, SP_UNIT_MM },
+ { "C8", 57, 81, SP_UNIT_MM },
+ { "C9", 40, 57, SP_UNIT_MM },
+ { "C10", 28, 40, SP_UNIT_MM },
+ { "D1", 545, 771, SP_UNIT_MM },
+ { "D2", 385, 545, SP_UNIT_MM },
+ { "D3", 272, 385, SP_UNIT_MM },
+ { "D4", 192, 272, SP_UNIT_MM },
+ { "D5", 136, 192, SP_UNIT_MM },
+ { "D6", 96, 136, SP_UNIT_MM },
+ { "D7", 68, 96, SP_UNIT_MM },
+ { "E3", 400, 560, SP_UNIT_MM },
+ { "E4", 280, 400, SP_UNIT_MM },
+ { "E5", 200, 280, SP_UNIT_MM },
+ { "E6", 140, 200, SP_UNIT_MM },
+#endif
+
+ { "CSE", 462, 649, SP_UNIT_PT },
+ { "US #10 Envelope", 4.125, 9.5, SP_UNIT_IN }, // TODO: Select landscape by default.
+ /* See http://www.hbp.com/content/PCR_envelopes.cfm for a much larger list of US envelope
+ sizes. */
+ { "DL Envelope", 110, 220, SP_UNIT_MM }, // TODO: Select landscape by default.
+ { "Ledger/Tabloid", 11, 17, SP_UNIT_IN },
+ /* Note that `Folio' (used in QPrinter/KPrinter) is deliberately absent from this list, as it
+ means different sizes to different people: different people may expect the width to be
+ either 8, 8.25 or 8.5 inches, and the height to be either 13 or 13.5 inches, even
+ restricting our interpretation to foolscap folio. If you wish to introduce a folio-like
+ page size to the list, then please consider using a name more specific than just `Folio' or
+ `Foolscap Folio'. */
+ { "Banner 468x60", 60, 468, SP_UNIT_PX }, // TODO: Select landscape by default.
+ { "Icon 16x16", 16, 16, SP_UNIT_PX },
+ { "Icon 32x32", 32, 32, SP_UNIT_PX },
+ { NULL, 0, 0, SP_UNIT_PX },
+};
+
+//===================================================
+static const SPUnit _px_unit = sp_unit_get_by_id (SP_UNIT_PX);
+
+class SizeMenuItem : public Gtk::MenuItem {
+public:
+ SizeMenuItem (PaperSize const * paper, PageSizer * widget)
+ : Gtk::MenuItem (paper ? paper->name : _("Custom")),
+ _paper(paper), _parent(widget) {}
+protected:
+ PaperSize const * _paper;
+ PageSizer *_parent;
+ void on_activate();
+};
+
+void
+SizeMenuItem::on_activate()
+{
+ if (_parent == 0) // handle Custom entry
+ return;
+
+ double w = _paper->smaller, h = _paper->larger;
+ SPUnit const &src_unit = sp_unit_get_by_id (_paper->unit);
+ sp_convert_distance (&w, &src_unit, &_px_unit);
+ sp_convert_distance (&h, &src_unit, &_px_unit);
+ if (_parent->_landscape)
+ _parent->setDim (h, w, true);
+ else
+ _parent->setDim (w, h, true);
+}
+
+//---------------------------------------------------
+
+PageSizer::PageSizer()
+: Gtk::VBox(false,4)
+{
+ Gtk::HBox *hbox_size = manage (new Gtk::HBox (false, 4));
+ pack_start (*hbox_size, false, false, 0);
+ Gtk::Label *label_size = manage (new Gtk::Label (_("Page size:"), 1.0, 0.5));
+ hbox_size->pack_start (*label_size, false, false, 0);
+ _omenu_size = manage (new Gtk::OptionMenu);
+ hbox_size->pack_start (*_omenu_size, true, true, 0);
+ Gtk::Menu *menu_size = manage (new Gtk::Menu);
+
+ for (PaperSize const *paper = inkscape_papers; paper->name; paper++) {
+ SizeMenuItem *item = manage (new SizeMenuItem (paper, this));
+ menu_size->append (*item);
+ }
+ SizeMenuItem *item = manage (new SizeMenuItem (0, 0));
+ menu_size->prepend (*item);
+ _omenu_size->set_menu (*menu_size);
+}
+
+PageSizer::~PageSizer()
+{
+ _portrait_connection.disconnect();
+ _landscape_connection.disconnect();
+ _changedw_connection.disconnect();
+ _changedh_connection.disconnect();
+}
+
+void
+PageSizer::init (Registry& reg)
+{
+ Gtk::HBox *hbox_ori = manage (new Gtk::HBox);
+ pack_start (*hbox_ori, false, false, 0);
+ Gtk::Label *label_ori = manage (new Gtk::Label (_("Page orientation:"), 0.0, 0.5));
+ hbox_ori->pack_start (*label_ori, false, false, 0);
+ _rb_land = manage (new Gtk::RadioButton (_("Landscape")));
+ Gtk::RadioButton::Group group = _rb_land->get_group();
+ hbox_ori->pack_end (*_rb_land, false, false, 5);
+ _rb_port = manage (new Gtk::RadioButton (_("Portrait")));
+ hbox_ori->pack_end (*_rb_port, false, false, 5);
+ _rb_port->set_group (group);
+ _rb_port->set_active (true);
+
+ /* Custom paper frame */
+ Gtk::Frame *frame = manage (new Gtk::Frame(_("Custom size")));
+ pack_start (*frame, false, false, 0);
+ Gtk::Table *table = manage (new Gtk::Table (4, 2, false));
+ table->set_border_width (4);
+ table->set_row_spacings (4);
+ table->set_col_spacings (4);
+ frame->add (*table);
+
+ _wr = &reg;
+
+ _rum.init (_("Units:"), "units", *_wr);
+ _rusw.init (_("Width:"), _("Width of paper"), "width", _rum, *_wr);
+ _rush.init (_("Height:"), _("Height of paper"), "height", _rum, *_wr);
+
+ table->attach (*_rum._label, 0,1,0,1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ table->attach (*_rum._sel, 1,2,0,1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ table->attach (*_rusw.getSU(), 0,2,1,2, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ table->attach (*_rush.getSU(), 0,2,2,3, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+
+ _landscape_connection = _rb_land->signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_landscape));
+ _portrait_connection = _rb_port->signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_portrait));
+ _changedw_connection = _rusw.getSU()->signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed));
+ _changedh_connection = _rush.getSU()->signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed));
+
+ show_all_children();
+}
+
+/**
+ * \param w, h given in px
+ */
+void
+PageSizer::setDim (double w, double h, bool update)
+{
+ _landscape = w>h;
+ _rb_land->set_active (_landscape ? true : false);
+ _rb_port->set_active (_landscape ? false : true);
+ _omenu_size->set_history (1 + find_paper_size (w, h));
+
+ Unit const& unit = _rum._sel->getUnit();
+ if (!update) _changedw_connection.block();
+ _rusw.setValue (w / unit.factor);
+ if (!update) _changedw_connection.unblock();
+ if (!update) _changedh_connection.block();
+ _rush.setValue (h / unit.factor);
+ if (!update) _changedh_connection.unblock();
+}
+
+void
+PageSizer::setDoc (double w, double h)
+{
+ setDim (w, h);
+ if (!SP_ACTIVE_DESKTOP || _wr->isUpdating())
+ return;
+
+ SPDocument *doc = SP_DT_DOCUMENT(SP_ACTIVE_DESKTOP);
+ sp_document_set_width (doc, _rusw.getSU()->getValue("px"), &_px_unit);
+ sp_document_set_height (doc, _rush.getSU()->getValue("px"), &_px_unit);
+ sp_document_done (doc);
+}
+
+/**
+ * Returns an index into inkscape_papers of a paper of the specified
+ * size (specified in px), or -1 if there's no such paper.
+ */
+int
+PageSizer::find_paper_size (double w, double h) const
+{
+ double given[2];
+ if ( w < h ) {
+ given[0] = w; given[1] = h;
+ } else {
+ given[0] = h; given[1] = w;
+ }
+ g_return_val_if_fail(given[0] <= given[1], -1);
+ for (unsigned i = 0; i < G_N_ELEMENTS(inkscape_papers) - 1; ++i) {
+ SPUnit const &i_unit = sp_unit_get_by_id(inkscape_papers[i].unit);
+ double const i_sizes[2] = { sp_units_get_pixels(inkscape_papers[i].smaller, i_unit),
+ sp_units_get_pixels(inkscape_papers[i].larger, i_unit) };
+ g_return_val_if_fail(i_sizes[0] <= i_sizes[1], -1);
+ if ((std::abs(given[0] - i_sizes[0]) <= .1) &&
+ (std::abs(given[1] - i_sizes[1]) <= .1) )
+ {
+ return (int) i;
+ }
+ }
+ return -1;
+}
+
+void
+PageSizer::on_portrait()
+{
+ double w = _rusw.getSU()->getValue ("px");
+ double h = _rush.getSU()->getValue ("px");
+ if (h<w) setDoc (h, w);
+}
+
+void
+PageSizer::on_landscape()
+{
+ double w = _rusw.getSU()->getValue ("px");
+ double h = _rush.getSU()->getValue ("px");
+ if (w<h) setDoc (h, w);
+}
+
+void
+PageSizer::on_value_changed()
+{
+ if (_wr->isUpdating()) return;
+
+ setDoc (_rusw.getSU()->getValue("px"), _rush.getSU()->getValue("px"));
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h
new file mode 100644
index 000000000..e17628c76
--- /dev/null
+++ b/src/ui/widget/page-sizer.h
@@ -0,0 +1,67 @@
+/** \file
+ * \brief Widget for specifying page size; part of Document Preferences dialog.
+ *
+ * Author:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_PAGE_SIZER__H
+#define INKSCAPE_UI_WIDGET_PAGE_SIZER__H
+
+#include <sigc++/sigc++.h>
+#include <gtkmm/box.h>
+#include "ui/widget/registry.h"
+#include "ui/widget/registered-widget.h"
+
+namespace Gtk {
+ class OptionMenu;
+ class RadioButton;
+}
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+/// Widget containing all widgets for specifying page size.
+class PageSizer : public Gtk::VBox {
+public:
+ PageSizer();
+ virtual ~PageSizer();
+ void init (Registry& reg);
+ void setDim (double w, double h, bool update = false);
+ bool _landscape;
+
+protected:
+ void setDoc (double w, double h);
+ int find_paper_size (double w, double h) const;
+ void on_portrait();
+ void on_landscape();
+ void on_value_changed();
+
+ RegisteredUnitMenu _rum;
+ RegisteredScalarUnit _rusw, _rush;
+ Gtk::OptionMenu *_omenu_size;
+ Gtk::RadioButton *_rb_port, *_rb_land;
+ sigc::connection _portrait_connection, _landscape_connection;
+ sigc::connection _changedw_connection, _changedh_connection;
+ Registry *_wr;
+};
+
+}}}
+
+#endif /* INKSCAPE_UI_WIDGET_PAGE_SIZER__H */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp
new file mode 100644
index 000000000..67aca690a
--- /dev/null
+++ b/src/ui/widget/panel.cpp
@@ -0,0 +1,248 @@
+/**
+ * \brief Panel widget
+ *
+ * Authors:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ * 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 <glibmm/i18n.h>
+
+#include "panel.h"
+#include "../../prefs-utils.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a Panel
+ *
+ * \param label Label.
+ */
+
+Panel::Panel(const gchar *prefs_path) :
+ _prefs_path(NULL),
+ _fillable(0)
+{
+ _prefs_path = prefs_path;
+ init();
+}
+
+Panel::Panel() :
+ _prefs_path(NULL),
+ _fillable(0)
+{
+ init();
+}
+
+Panel::Panel(Glib::ustring const &label) :
+ _prefs_path(NULL),
+ _fillable(0)
+{
+ this->label = label;
+ init();
+}
+
+Panel::~Panel()
+{
+}
+
+void Panel::init()
+{
+ Glib::ustring tmp("<");
+ tabTitle.set_label(this->label);
+
+ guint panel_size = 0;
+ if (_prefs_path) {
+ panel_size = prefs_get_int_attribute_limited (_prefs_path, "panel_size", 1, 0, 10);
+ }
+
+ guint panel_mode = 0;
+ if (_prefs_path) {
+ panel_mode = prefs_get_int_attribute_limited (_prefs_path, "panel_mode", 1, 0, 10);
+ }
+
+ tabButton.set_menu(menu);
+ Gtk::MenuItem* dummy = manage(new Gtk::MenuItem(tmp));
+ menu.append( *dummy );
+ menu.append( *manage(new Gtk::SeparatorMenuItem()) );
+ {
+ const char *things[] = {
+ N_("small"),
+ N_("medium"),
+ N_("large"),
+ N_("huge")
+ };
+ Gtk::RadioMenuItem::Group groupOne;
+ for ( unsigned int i = 0; i < G_N_ELEMENTS(things); i++ ) {
+ Glib::ustring foo(gettext(things[i]));
+ Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, foo));
+ menu.append(*single);
+ if ( i == panel_size ) {
+ single->set_active(true);
+ }
+ single->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), 0, i) );
+ }
+ }
+ menu.append( *manage(new Gtk::SeparatorMenuItem()) );
+ Gtk::RadioMenuItem::Group group;
+ Glib::ustring oneLab(_("List"));
+ Glib::ustring twoLab(_("Grid"));
+ Gtk::RadioMenuItem *one = manage(new Gtk::RadioMenuItem(group, oneLab));
+ Gtk::RadioMenuItem *two = manage(new Gtk::RadioMenuItem(group, twoLab));
+
+ if (panel_mode == 0) {
+ one->set_active(true);
+ } else if (panel_mode == 1) {
+ two->set_active(true);
+ }
+
+ menu.append( *one );
+ menu.append( *two );
+ menu.append( *manage(new Gtk::SeparatorMenuItem()) );
+ one->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), 1, 0) );
+ two->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), 1, 1) );
+
+ closeButton.set_label("X");
+
+ topBar.pack_start(tabTitle);
+
+ topBar.pack_end(closeButton, false, false);
+ topBar.pack_end(tabButton, false, false);
+
+ pack_start( topBar, false, false );
+
+ show_all_children();
+
+ bounceCall (0, panel_size);
+ bounceCall (1, panel_mode);
+}
+
+void Panel::setLabel(Glib::ustring const &label)
+{
+ this->label = label;
+ tabTitle.set_label(this->label);
+}
+
+void Panel::_regItem( Gtk::MenuItem* item, int group, int id )
+{
+ menu.append( *item );
+ item->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), group + 2, id) );
+}
+
+void Panel::restorePanelPrefs()
+{
+ guint panel_size = 0;
+ if (_prefs_path) {
+ panel_size = prefs_get_int_attribute_limited (_prefs_path, "panel_size", 1, 0, 10);
+ }
+ guint panel_mode = 0;
+ if (_prefs_path) {
+ panel_mode = prefs_get_int_attribute_limited (_prefs_path, "panel_mode", 1, 0, 10);
+ }
+ bounceCall (0, panel_size);
+ bounceCall (1, panel_mode);
+}
+
+void Panel::bounceCall(int i, int j)
+{
+ menu.set_active(0);
+ switch ( i ) {
+ case 0:
+ if (_prefs_path) prefs_set_int_attribute (_prefs_path, "panel_size", j);
+ if ( _fillable ) {
+ ViewType currType = _fillable->getPreviewType();
+ switch ( j ) {
+ case 0:
+ {
+ _fillable->setStyle(Gtk::ICON_SIZE_MENU, currType);
+ }
+ break;
+ case 1:
+ {
+ _fillable->setStyle(Gtk::ICON_SIZE_SMALL_TOOLBAR, currType);
+ }
+ break;
+ case 2:
+ {
+ _fillable->setStyle(Gtk::ICON_SIZE_BUTTON, currType);
+ }
+ break;
+ case 3:
+ {
+ _fillable->setStyle(Gtk::ICON_SIZE_DIALOG, currType);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ break;
+ case 1:
+ if (_prefs_path) prefs_set_int_attribute (_prefs_path, "panel_mode", j);
+ if ( _fillable ) {
+ Gtk::BuiltinIconSize currSize = _fillable->getPreviewSize();
+ switch ( j ) {
+ case 0:
+ {
+ _fillable->setStyle(currSize, VIEW_TYPE_LIST);
+ }
+ break;
+ case 1:
+ {
+ _fillable->setStyle(currSize, VIEW_TYPE_GRID);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ _handleAction( i - 2, j );
+ }
+}
+
+
+
+
+
+Glib::ustring const &Panel::getLabel() const
+{
+ return label;
+}
+
+void Panel::_setTargetFillable( PreviewFillable *target )
+{
+ _fillable = target;
+}
+
+void Panel::_handleAction( int setId, int itemId )
+{
+// for subclasses to override
+}
+
+} // namespace Widget
+} // 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/widget/panel.h b/src/ui/widget/panel.h
new file mode 100644
index 000000000..07225b8ce
--- /dev/null
+++ b/src/ui/widget/panel.h
@@ -0,0 +1,80 @@
+/**
+ * \brief Generic Panel widget - A generic dockable container.
+ *
+ * Authors:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ * Copyright (C) 2005 Jon A. Cruz
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef SEEN_INKSCAPE_UI_WIDGET_PANEL_H
+#define SEEN_INKSCAPE_UI_WIDGET_PANEL_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/table.h>
+#include <gtkmm/button.h>
+#include <gtkmm/label.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/optionmenu.h>
+#include "../previewfillable.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Panel : public Gtk::VBox
+{
+public:
+ Panel();
+ virtual ~Panel();
+ Panel(Glib::ustring const &label);
+ Panel(const gchar *prefs_path);
+
+ void setLabel(Glib::ustring const &label);
+ Glib::ustring const &getLabel() const;
+
+ const gchar *_prefs_path;
+ void restorePanelPrefs();
+
+protected:
+ void _setTargetFillable( PreviewFillable *target );
+ void _regItem( Gtk::MenuItem* item, int group, int id );
+
+ virtual void _handleAction( int setId, int itemId );
+
+
+private:
+ void init();
+ void bounceCall(int i, int j);
+
+ Glib::ustring label;
+
+ Gtk::HBox topBar;
+ Gtk::Label tabTitle;
+ Gtk::OptionMenu tabButton;
+ Gtk::Menu menu;
+ Gtk::Button closeButton;
+ PreviewFillable *_fillable;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // SEEN_INKSCAPE_UI_WIDGET_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/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp
new file mode 100644
index 000000000..cc389c611
--- /dev/null
+++ b/src/ui/widget/preferences-widget.cpp
@@ -0,0 +1,278 @@
+/**
+ * \brief Inkscape Preferences dialog
+ *
+ * Authors:
+ * Marco Scholten
+ *
+ * Copyright (C) 2004, 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/frame.h>
+#include <gtkmm/alignment.h>
+#include <gtkmm/box.h>
+
+#include "prefs-utils.h"
+#include "ui/widget/preferences-widget.h"
+#include "verbs.h"
+#include "selcue.h"
+#include <iostream>
+#include "enums.h"
+#include "inkscape.h"
+#include "desktop-handles.h"
+#include "message-stack.h"
+#include "style.h"
+#include "selection.h"
+#include "selection-chemistry.h"
+#include "xml/repr.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+DialogPage::DialogPage()
+{
+ this->set_border_width(12);
+ this->set_col_spacings(12);
+ this->set_row_spacings(6);
+}
+
+void DialogPage::add_line(bool indent, const Glib::ustring label, Gtk::Widget& widget, const Glib::ustring suffix, const Glib::ustring& tip, bool expand_widget)
+{
+ int start_col;
+ int row = this->property_n_rows();
+ Gtk::Widget* w;
+ if (expand_widget)
+ {
+ w = &widget;
+ }
+ else
+ {
+ Gtk::HBox* hb = Gtk::manage(new Gtk::HBox());
+ hb->set_spacing(12);
+ hb->pack_start(widget,false,false);
+ w = (Gtk::Widget*) hb;
+ }
+ if (label != "")
+ {
+ Gtk::Label* label_widget;
+ label_widget = Gtk::manage(new Gtk::Label(label , Gtk::ALIGN_LEFT , Gtk::ALIGN_CENTER, true));
+ label_widget->set_mnemonic_widget(widget);
+ if (indent)
+ {
+ Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment());
+ alignment->set_padding(0, 0, 12, 0);
+ alignment->add(*label_widget);
+ this->attach(*alignment , 0, 1, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0);
+ }
+ else
+ this->attach(*label_widget , 0, 1, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0);
+ start_col = 1;
+ }
+ else
+ start_col = 0;
+
+ if (start_col == 0 && indent) //indent this widget
+ {
+ Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment());
+ alignment->set_padding(0, 0, 12, 0);
+ alignment->add(*w);
+ this->attach(*alignment, start_col, 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::AttachOptions(), 0, 0);
+ }
+ else
+ {
+ this->attach(*w, start_col, 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::AttachOptions(), 0, 0);
+ }
+
+ if (suffix != "")
+ {
+ Gtk::Label* suffix_widget = Gtk::manage(new Gtk::Label(suffix , Gtk::ALIGN_LEFT , Gtk::ALIGN_CENTER, true));
+ if (expand_widget)
+ this->attach(*suffix_widget, 2, 3, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0);
+ else
+ ((Gtk::HBox*)w)->pack_start(*suffix_widget,false,false);
+ }
+
+ if (tip != "")
+ {
+ _tooltips.set_tip (widget, tip);
+ }
+
+}
+
+void DialogPage::add_group_header(Glib::ustring name)
+{
+ int row = this->property_n_rows();
+ if (name != "")
+ {
+ Gtk::Label* label_widget = Gtk::manage(new Gtk::Label(Glib::ustring(/*"<span size='large'>*/"<b>") + name +
+ Glib::ustring("</b>"/*</span>"*/) , Gtk::ALIGN_LEFT , Gtk::ALIGN_CENTER, true));
+ label_widget->set_use_markup(true);
+ this->attach(*label_widget , 0, 4, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0);
+ if (row != 1)
+ this->set_row_spacing(row - 1, 18);
+ }
+}
+
+void PrefCheckButton::init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ bool default_value)
+{
+ _prefs_path = prefs_path;
+ _attr = attr;
+ this->set_label(label);
+ this->set_active( prefs_get_int_attribute (_prefs_path.c_str(), _attr.c_str(), (int)default_value) );
+}
+
+void PrefCheckButton::on_toggled()
+{
+ if (this->is_visible()) //only take action if the user toggled it
+ {
+ prefs_set_int_attribute (_prefs_path.c_str(), _attr.c_str(), (int) this->get_active());
+ }
+}
+
+void PrefRadioButton::init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ const std::string& string_value, bool default_value, PrefRadioButton* group_member)
+{
+ _value_type = VAL_STRING;
+ _prefs_path = prefs_path;
+ _attr = attr;
+ _string_value = string_value;
+ this->set_label(label);
+ if (group_member)
+ {
+ Gtk::RadioButtonGroup rbg = group_member->get_group();
+ this->set_group(rbg);
+ }
+ const gchar* val = prefs_get_string_attribute( _prefs_path.c_str(), _attr.c_str() );
+ if ( val )
+ this->set_active( std::string( val ) == _string_value);
+ else
+ this->set_active( false );
+}
+
+void PrefRadioButton::init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ int int_value, bool default_value, PrefRadioButton* group_member)
+{
+ _value_type = VAL_INT;
+ _prefs_path = prefs_path;
+ _attr = attr;
+ _int_value = int_value;
+ this->set_label(label);
+ if (group_member)
+ {
+ Gtk::RadioButtonGroup rbg = group_member->get_group();
+ this->set_group(rbg);
+ }
+ if (default_value)
+ this->set_active( prefs_get_int_attribute( _prefs_path.c_str(), _attr.c_str(), int_value ) == _int_value);
+ else
+ this->set_active( prefs_get_int_attribute( _prefs_path.c_str(), _attr.c_str(), int_value + 1 )== _int_value);
+}
+
+void PrefRadioButton::on_toggled()
+{
+ this->changed_signal.emit(this->get_active());
+ if (this->is_visible() && this->get_active() ) //only take action if toggled by user (to active)
+ {
+ if ( _value_type == VAL_STRING )
+ prefs_set_string_attribute ( _prefs_path.c_str(), _attr.c_str(), _string_value.c_str());
+ else if ( _value_type == VAL_INT )
+ prefs_set_int_attribute ( _prefs_path.c_str(), _attr.c_str(), _int_value);
+ }
+}
+
+void PrefSpinButton::init(const std::string& prefs_path, const std::string& attr,
+ double lower, double upper, double step_increment, double page_increment,
+ double default_value, bool is_int, bool is_percent)
+{
+ _prefs_path = prefs_path;
+ _attr = attr;
+ _is_int = is_int;
+ _is_percent = is_percent;
+
+ double value;
+ if (is_int)
+ if (is_percent)
+ value = 100 * prefs_get_double_attribute_limited (prefs_path.c_str(), attr.c_str(), default_value, lower/100.0, upper/100.0);
+ else
+ value = (double) prefs_get_int_attribute_limited (prefs_path.c_str(), attr.c_str(), (int) default_value, (int) lower, (int) upper);
+ else
+ value = prefs_get_double_attribute_limited (prefs_path.c_str(), attr.c_str(), default_value, lower, upper);
+
+ this->set_range (lower, upper);
+ this->set_increments (step_increment, page_increment);
+ this->set_numeric();
+ this->set_value (value);
+ this->set_width_chars(6);
+ if (is_int)
+ this->set_digits(0);
+ else if (step_increment < 0.1)
+ this->set_digits(3);
+ else
+ this->set_digits(2);
+
+}
+
+void PrefSpinButton::on_value_changed()
+{
+ if (this->is_visible()) //only take action if user changed value
+ {
+ if (_is_int)
+ if (_is_percent)
+ prefs_set_double_attribute(_prefs_path.c_str(), _attr.c_str(), this->get_value()/100.0);
+ else
+ prefs_set_int_attribute(_prefs_path.c_str(), _attr.c_str(), (int) this->get_value());
+ else
+ prefs_set_double_attribute (_prefs_path.c_str(), _attr.c_str(), this->get_value());
+ }
+}
+
+void PrefCombo::init(const std::string& prefs_path, const std::string& attr,
+ Glib::ustring labels[], int values[], int num_items, int default_value)
+{
+ _prefs_path = prefs_path;
+ _attr = attr;
+ int row = 0;
+ int value = prefs_get_int_attribute (_prefs_path.c_str(), _attr.c_str(), default_value);
+
+ for (int i = 0 ; i < num_items; ++i)
+ {
+ this->append_text(labels[i]);
+ _values.push_back(values[i]);
+ if (value == values[i])
+ row = i;
+ }
+ this->set_active(row);
+}
+
+void PrefCombo::on_changed()
+{
+ if (this->is_visible()) //only take action if user changed value
+ {
+ prefs_set_int_attribute (_prefs_path.c_str(), _attr.c_str(), _values[this->get_active_row_number()]);
+ std::cout << "combo set: " << _prefs_path << " " << _attr << " " << _values[this->get_active_row_number()] << std::endl;
+ }
+}
+
+} // namespace Widget
+} // 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/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h
new file mode 100644
index 000000000..a5a594114
--- /dev/null
+++ b/src/ui/widget/preferences-widget.h
@@ -0,0 +1,117 @@
+/**
+ * \brief Inkscape Preferences dialog
+ *
+ * Authors:
+ * Marco Scholten
+ *
+ * Copyright (C) 2004, 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_INKSCAPE_PREFERENCES_H
+#define INKSCAPE_UI_WIDGET_INKSCAPE_PREFERENCES_H
+
+#include <iostream>
+#include <vector>
+#include <gtkmm/table.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/radiobutton.h>
+#include <gtkmm/frame.h>
+#include <sigc++/sigc++.h>
+//#include <glibmm/i18n.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class PrefCheckButton : public Gtk::CheckButton
+{
+public:
+ void init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ bool default_value);
+protected:
+ std::string _prefs_path;
+ std::string _attr;
+ bool _int_value;
+ void on_toggled();
+};
+
+class PrefRadioButton : public Gtk::RadioButton
+{
+public:
+ void init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ int int_value, bool default_value, PrefRadioButton* group_member);
+ void init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ const std::string& string_value, bool default_value, PrefRadioButton* group_member);
+ sigc::signal<void, bool> changed_signal;
+protected:
+ std::string _prefs_path;
+ std::string _attr;
+ std::string _string_value;
+ int _value_type;
+ enum
+ {
+ VAL_INT,
+ VAL_STRING
+ };
+ int _int_value;
+ void on_toggled();
+};
+
+class PrefSpinButton : public Gtk::SpinButton
+{
+public:
+ void init(const std::string& prefs_path, const std::string& attr,
+ double lower, double upper, double step_increment, double page_increment,
+ double default_value, bool is_int, bool is_percent);
+protected:
+ std::string _prefs_path;
+ std::string _attr;
+ bool _is_int;
+ bool _is_percent;
+ void on_value_changed();
+};
+
+class PrefCombo : public Gtk::ComboBoxText
+{
+public:
+ void init(const std::string& prefs_path, const std::string& attr,
+ Glib::ustring labels[], int values[], int num_items, int default_value);
+protected:
+ std::string _prefs_path;
+ std::string _attr;
+ std::vector<int> _values;
+ void on_changed();
+};
+
+class DialogPage : public Gtk::Table
+{
+public:
+ DialogPage();
+ void add_line(bool indent, const Glib::ustring label, Gtk::Widget& widget, const Glib::ustring suffix, const Glib::ustring& tip, bool expand = true);
+ void add_group_header(Glib::ustring name);
+protected:
+ Gtk::Tooltips _tooltips;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif //INKSCAPE_UI_WIDGET_INKSCAPE_PREFERENCES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp
new file mode 100644
index 000000000..918742e75
--- /dev/null
+++ b/src/ui/widget/registered-widget.cpp
@@ -0,0 +1,409 @@
+/** \file
+ *
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include "ui/widget/color-picker.h"
+#include "ui/widget/registry.h"
+#include "ui/widget/scalar-unit.h"
+
+#include "helper/units.h"
+#include "xml/repr.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+
+#include "inkscape.h"
+#include "document.h"
+#include "desktop-handles.h"
+#include "sp-namedview.h"
+
+#include "registered-widget.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+//---------------------------------------------------
+
+
+
+//====================================================
+
+RegisteredCheckButton::RegisteredCheckButton()
+: _button(0)
+{
+}
+
+RegisteredCheckButton::~RegisteredCheckButton()
+{
+ _toggled_connection.disconnect();
+ if (_button) delete _button;
+}
+
+void
+RegisteredCheckButton::init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right)
+{
+ _button = new Gtk::CheckButton;
+ _tt.set_tip (*_button, tip);
+ _button->add (*manage (new Gtk::Label (label)));
+ _button->set_alignment (right? 1.0 : 0.0, 0.5);
+ _key = key;
+ _wr = &wr;
+ _toggled_connection = _button->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
+}
+
+void
+RegisteredCheckButton::setActive (bool b)
+{
+ _button->set_active (b);
+}
+
+void
+RegisteredCheckButton::on_toggled()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt) {
+ return;
+ }
+
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ _wr->setUpdating (true);
+
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ sp_repr_set_boolean(repr, _key.c_str(), _button->get_active());
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+RegisteredUnitMenu::RegisteredUnitMenu()
+: _label(0), _sel(0)
+{
+}
+
+RegisteredUnitMenu::~RegisteredUnitMenu()
+{
+ _changed_connection.disconnect();
+ if (_label) delete _label;
+ if (_sel) delete _sel;
+}
+
+void
+RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr)
+{
+ _label = new Gtk::Label (label, 1.0, 0.5);
+ _sel = new UnitMenu ();
+ _sel->setUnitType (UNIT_TYPE_LINEAR);
+ _wr = &wr;
+ _key = key;
+ _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
+}
+
+void
+RegisteredUnitMenu::setUnit (const SPUnit* unit)
+{
+ _sel->setUnit (sp_unit_get_abbreviation (unit));
+}
+
+void
+RegisteredUnitMenu::on_changed()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt)
+ return;
+
+ Inkscape::SVGOStringStream os;
+ os << _sel->getUnitAbbr();
+
+ _wr->setUpdating (true);
+
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ repr->setAttribute(_key.c_str(), os.str().c_str());
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+
+RegisteredScalarUnit::RegisteredScalarUnit()
+: _widget(0), _um(0)
+{
+}
+
+RegisteredScalarUnit::~RegisteredScalarUnit()
+{
+ if (_widget) delete _widget;
+ _value_changed_connection.disconnect();
+}
+
+void
+RegisteredScalarUnit::init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, const RegisteredUnitMenu &rum, Registry& wr)
+{
+ _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel);
+ _widget->initScalar (-1e6, 1e6);
+ _widget->setUnit (rum._sel->getUnitAbbr());
+ _widget->setDigits (2);
+ _key = key;
+ _um = rum._sel;
+ _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
+ _wr = &wr;
+}
+
+ScalarUnit*
+RegisteredScalarUnit::getSU()
+{
+ return _widget;
+}
+
+void
+RegisteredScalarUnit::setValue (double val)
+{
+ _widget->setValue (val);
+ on_value_changed();
+}
+
+void
+RegisteredScalarUnit::on_value_changed()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt)
+ return;
+
+ Inkscape::SVGOStringStream os;
+ os << _widget->getValue("");
+ if (_um)
+ os << _um->getUnitAbbr();
+
+ _wr->setUpdating (true);
+
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ repr->setAttribute(_key.c_str(), os.str().c_str());
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+RegisteredColorPicker::RegisteredColorPicker()
+: _label(0), _cp(0)
+{
+}
+
+RegisteredColorPicker::~RegisteredColorPicker()
+{
+ _changed_connection.disconnect();
+ if (_cp) delete _cp;
+ if (_label) delete _label;
+}
+
+void
+RegisteredColorPicker::init (const Glib::ustring& label, const Glib::ustring& title, const Glib::ustring& tip, const Glib::ustring& ckey, const Glib::ustring& akey, Registry& wr)
+{
+ _label = new Gtk::Label (label, 1.0, 0.5);
+ _cp = new ColorPicker (title,tip,0,true);
+ _ckey = ckey;
+ _akey = akey;
+ _wr = &wr;
+ _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
+}
+
+void
+RegisteredColorPicker::setRgba32 (guint32 rgba)
+{
+ _cp->setRgba32 (rgba);
+}
+
+void
+RegisteredColorPicker::closeWindow()
+{
+ _cp->closeWindow();
+}
+
+void
+RegisteredColorPicker::on_changed (guint32 rgba)
+{
+ if (_wr->isUpdating() || !SP_ACTIVE_DESKTOP)
+ return;
+
+ _wr->setUpdating (true);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ gchar c[32];
+ sp_svg_write_color(c, 32, rgba);
+ repr->setAttribute(_ckey.c_str(), c);
+ sp_repr_set_css_double(repr, _akey.c_str(), (rgba & 0xff) / 255.0);
+ _wr->setUpdating (false);
+}
+
+RegisteredSuffixedInteger::RegisteredSuffixedInteger()
+: _label(0), _sb(0),
+ _adj(0.0,0.0,100.0,1.0,1.0,1.0),
+ _suffix(0)
+{
+}
+
+RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
+{
+ _changed_connection.disconnect();
+ if (_label) delete _label;
+ if (_suffix) delete _suffix;
+ if (_sb) delete _sb;
+}
+
+void
+RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr)
+{
+ _key = key;
+ _label = new Gtk::Label (label);
+ _label->set_alignment (1.0, 0.5);
+ _sb = new Gtk::SpinButton (_adj, 1.0, 0);
+ _suffix = new Gtk::Label (suffix);
+ _hbox.pack_start (*_sb, true, true, 0);
+ _hbox.pack_start (*_suffix, false, false, 0);
+
+ _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
+ _wr = &wr;
+}
+
+void
+RegisteredSuffixedInteger::setValue (int i)
+{
+ _adj.set_value (i);
+}
+
+void
+RegisteredSuffixedInteger::on_value_changed()
+{
+ if (_wr->isUpdating() || !SP_ACTIVE_DESKTOP)
+ return;
+
+ _wr->setUpdating (true);
+
+ SPDesktop* dt = SP_ACTIVE_DESKTOP;
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(dt));
+ Inkscape::SVGOStringStream os;
+ int value = int(_adj.get_value());
+ os << value;
+
+ repr->setAttribute(_key.c_str(), os.str().c_str());
+ sp_document_done(SP_DT_DOCUMENT(dt));
+
+ _wr->setUpdating (false);
+}
+
+RegisteredRadioButtonPair::RegisteredRadioButtonPair()
+: _hbox(0)
+{
+}
+
+RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
+{
+ _changed_connection.disconnect();
+}
+
+void
+RegisteredRadioButtonPair::init (const Glib::ustring& label,
+const Glib::ustring& label1, const Glib::ustring& label2,
+const Glib::ustring& tip1, const Glib::ustring& tip2,
+const Glib::ustring& key, Registry& wr)
+{
+ _hbox = new Gtk::HBox;
+ _hbox->add (*manage (new Gtk::Label (label)));
+ _rb1 = manage (new Gtk::RadioButton (label1));
+ _hbox->add (*_rb1);
+ Gtk::RadioButtonGroup group = _rb1->get_group();
+ _rb2 = manage (new Gtk::RadioButton (group, label2, false));
+ _hbox->add (*_rb2);
+ _rb2->set_active();
+ _tt.set_tip (*_rb1, tip1);
+ _tt.set_tip (*_rb2, tip2);
+ _key = key;
+ _wr = &wr;
+ _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
+}
+
+void
+RegisteredRadioButtonPair::setValue (bool second)
+{
+ if (second) _rb2->set_active();
+ else _rb1->set_active();
+}
+
+void
+RegisteredRadioButtonPair::on_value_changed()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt)
+ return;
+
+ _wr->setUpdating (true);
+
+ bool second = _rb2->get_active();
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ repr->setAttribute(_key.c_str(), second ? "true" : "false");
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h
new file mode 100644
index 000000000..7138f4640
--- /dev/null
+++ b/src/ui/widget/registered-widget.h
@@ -0,0 +1,175 @@
+/** \file
+ * \brief
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_REGISTERED_WIDGET__H_
+#define INKSCAPE_UI_WIDGET_REGISTERED_WIDGET__H_
+
+#include <gtkmm/box.h>
+#include <gtkmm/adjustment.h>
+
+class SPUnit;
+
+namespace Gtk {
+ class HScale;
+ class RadioButton;
+ class SpinButton;
+ class ToggleButton;
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class ColorPicker;
+class Registry;
+class ScalarUnit;
+class UnitMenu;
+
+class RegisteredCheckButton {
+public:
+ RegisteredCheckButton();
+ ~RegisteredCheckButton();
+ void init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right=true);
+ void setActive (bool);
+
+ Gtk::ToggleButton *_button;
+
+protected:
+ Gtk::Tooltips _tt;
+ sigc::connection _toggled_connection;
+ Registry *_wr;
+ Glib::ustring _key;
+ void on_toggled();
+};
+
+class RegisteredUnitMenu {
+public:
+ RegisteredUnitMenu();
+ ~RegisteredUnitMenu();
+ void init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr);
+ void setUnit (const SPUnit*);
+ Gtk::Label *_label;
+ UnitMenu *_sel;
+ sigc::connection _changed_connection;
+
+protected:
+ void on_changed();
+ Registry *_wr;
+ Glib::ustring _key;
+};
+
+class RegisteredScalarUnit {
+public:
+ RegisteredScalarUnit();
+ ~RegisteredScalarUnit();
+ void init (const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ const RegisteredUnitMenu &rum,
+ Registry& wr);
+ ScalarUnit* getSU();
+ void setValue (double);
+
+protected:
+ ScalarUnit *_widget;
+ sigc::connection _value_changed_connection;
+ UnitMenu *_um;
+ Registry *_wr;
+ Glib::ustring _key;
+ void on_value_changed();
+};
+
+class RegisteredColorPicker {
+public:
+ RegisteredColorPicker();
+ ~RegisteredColorPicker();
+ void init (const Glib::ustring& label,
+ const Glib::ustring& title,
+ const Glib::ustring& tip,
+ const Glib::ustring& ckey,
+ const Glib::ustring& akey,
+ Registry& wr);
+ void setRgba32 (guint32);
+ void closeWindow();
+
+ Gtk::Label *_label;
+ ColorPicker *_cp;
+
+protected:
+ Glib::ustring _ckey, _akey;
+ Registry *_wr;
+ void on_changed (guint32);
+ sigc::connection _changed_connection;
+};
+
+class RegisteredSuffixedInteger {
+public:
+ RegisteredSuffixedInteger();
+ ~RegisteredSuffixedInteger();
+ void init (const Glib::ustring& label1,
+ const Glib::ustring& label2,
+ const Glib::ustring& key,
+ Registry& wr);
+ void setValue (int);
+ Gtk::Label *_label;
+ Gtk::HBox _hbox;
+
+protected:
+ Gtk::SpinButton *_sb;
+ Gtk::Adjustment _adj;
+ Gtk::Label *_suffix;
+ Glib::ustring _key;
+ Registry *_wr;
+ sigc::connection _changed_connection;
+ void on_value_changed();
+};
+
+class RegisteredRadioButtonPair {
+public:
+ RegisteredRadioButtonPair();
+ ~RegisteredRadioButtonPair();
+ void init (const Glib::ustring& label,
+ const Glib::ustring& label1,
+ const Glib::ustring& label2,
+ const Glib::ustring& tip1,
+ const Glib::ustring& tip2,
+ const Glib::ustring& key,
+ Registry& wr);
+ void setValue (bool second);
+ Gtk::HBox *_hbox;
+
+protected:
+ Gtk::RadioButton *_rb1, *_rb2;
+ Gtk::Tooltips _tt;
+ Glib::ustring _key;
+ Registry *_wr;
+ sigc::connection _changed_connection;
+ void on_value_changed();
+};
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_REGISTERED_WIDGET__H_
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/registry.cpp b/src/ui/widget/registry.cpp
new file mode 100644
index 000000000..aa92e6ecb
--- /dev/null
+++ b/src/ui/widget/registry.cpp
@@ -0,0 +1,58 @@
+/** \file
+ *
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "registry.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+//---------------------------------------------------
+
+Registry::Registry() : _updating(false) {}
+
+Registry::~Registry() {}
+
+bool
+Registry::isUpdating()
+{
+ return _updating;
+}
+
+void
+Registry::setUpdating (bool upd)
+{
+ _updating = upd;
+}
+
+//====================================================
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/registry.h b/src/ui/widget/registry.h
new file mode 100644
index 000000000..4d7ad3068
--- /dev/null
+++ b/src/ui/widget/registry.h
@@ -0,0 +1,54 @@
+/** \file
+ * \brief
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_REGISTRY__H
+#define INKSCAPE_UI_WIDGET_REGISTRY__H
+
+#include <map>
+#include <glibmm/i18n.h>
+#include <glibmm/ustring.h>
+
+namespace Gtk {
+ class Object;
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Registry {
+public:
+ Registry();
+ ~Registry();
+
+ bool isUpdating();
+ void setUpdating (bool);
+
+protected:
+ bool _updating;
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Widget
+
+#endif // INKSCAPE_UI_WIDGET_REGISTRY__H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/ruler.cpp b/src/ui/widget/ruler.cpp
new file mode 100644
index 000000000..f2a59338d
--- /dev/null
+++ b/src/ui/widget/ruler.cpp
@@ -0,0 +1,197 @@
+/** \file
+ * Gtkmm facade/wrapper around SPRuler code that formerly lived
+ * in desktop-events.cpp
+ */
+/*
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * Lauris Kaplinski
+ *
+ * Copyright (C) 2005 Ralf Stephan
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#if defined(WIN32) || defined(__APPLE__)
+# include <glibmm/i18n.h>
+#endif
+
+#include <gtkmm/ruler.h>
+#include "helper/units.h"
+#include "widgets/ruler.h"
+#include "ui/widget/ruler.h"
+
+#include "xml/repr.h"
+#include "display/guideline.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "document.h"
+#include "sp-namedview.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+void
+Ruler::init(SPDesktop *dt, Gtk::Widget &w)
+{
+ _dt = dt;
+ _canvas_widget = &w;
+ _dragging = false;
+ _guide = 0;
+ sp_ruler_set_metric(GTK_RULER(_r->gobj()), SP_PT);
+ _r->set_range(-500, 500, 0, 1000);
+}
+
+void
+Ruler::get_range(double &lo, double &up, double &pos, double &max)
+{
+ _r->get_range(lo, up, pos, max);
+}
+
+void
+Ruler::set_range(double lo, double up, double pos, double max)
+{
+ _r->set_range(lo, up, pos, max);
+}
+
+/// Set metric from namedview
+void
+Ruler::update_metric()
+{
+ if (!_dt) return;
+ sp_ruler_set_metric(GTK_RULER(_r->gobj()), _dt->namedview->getDefaultMetric());
+}
+
+/// Returns text to be used for tooltip for ruler.
+/// \todo incorrect
+Glib::ustring
+Ruler::get_tip()
+{
+ return gettext(sp_unit_get_plural( _dt
+ ? _dt->namedview->doc_units
+ : &sp_unit_get_by_id(SP_UNIT_PT) ));
+}
+
+/// Helper that gets mouse coordinates relative to canvas widget.
+void
+Ruler::canvas_get_pointer(int &x, int &y)
+{
+ Gdk::ModifierType mask;
+ (void) _canvas_widget->get_window()->get_pointer(x, y, mask);
+}
+
+NR::Point
+Ruler::get_event_dt()
+{
+ int wx, wy;
+ canvas_get_pointer(wx, wy);
+ NR::Point const event_win(wx, wy);
+ NR::Point const event_w(sp_canvas_window_to_world(_dt->canvas, event_win));
+ return _dt->w2d(event_w);
+}
+
+bool
+Ruler::on_button_press_event(GdkEventButton *evb)
+{
+ g_assert(_dt);
+ NR::Point const &event_dt = get_event_dt();
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(_dt->namedview);
+
+ if (evb->button == 1) {
+ _dragging = true;
+ sp_repr_set_boolean(repr, "showguides", TRUE);
+ sp_repr_set_boolean(repr, "inkscape:guide-bbox", TRUE);
+ double const guide_pos_dt = event_dt[ _horiz_f ? NR::Y : NR::X ];
+ _guide = sp_guideline_new(_dt->guides, guide_pos_dt, !_horiz_f);
+ sp_guideline_set_color(SP_GUIDELINE(_guide), _dt->namedview->guidehicolor);
+ (void) get_window()->pointer_grab(false,
+ Gdk::BUTTON_RELEASE_MASK |
+ Gdk::POINTER_MOTION_MASK |
+ Gdk::POINTER_MOTION_HINT_MASK,
+ evb->time);
+ }
+ return false;
+}
+
+bool
+Ruler::on_motion_notify_event(GdkEventMotion *)
+{
+ g_assert(_dt);
+ NR::Point const &event_dt = get_event_dt();
+
+ if (_dragging) {
+ double const guide_pos_dt = event_dt[ _horiz_f ? NR::Y : NR::X ];
+ sp_guideline_set_position(SP_GUIDELINE(_guide), guide_pos_dt);
+ _dt->set_coordinate_status(event_dt);
+ _dt->setPosition(event_dt);
+ }
+ return false;
+}
+
+bool
+Ruler::on_button_release_event(GdkEventButton *evb)
+{
+ g_assert(_dt);
+ int wx, wy;
+ canvas_get_pointer(wx, wy);
+ NR::Point const &event_dt = get_event_dt();
+
+ if (_dragging && evb->button == 1) {
+ Gdk::Window::pointer_ungrab(evb->time);
+ gtk_object_destroy(GTK_OBJECT(_guide));
+ _guide = 0;
+ _dragging = false;
+
+ if ( (_horiz_f ? wy : wx ) >= 0 ) {
+ Inkscape::XML::Node *repr = sp_repr_new("sodipodi:guide");
+ repr->setAttribute("orientation", _horiz_f ? "horizontal" : "vertical");
+ double const guide_pos_dt = event_dt[ _horiz_f ? NR::Y : NR::X ];
+ sp_repr_set_svg_double(repr, "position", guide_pos_dt);
+ SP_OBJECT_REPR(_dt->namedview)->appendChild(repr);
+ Inkscape::GC::release(repr);
+ sp_document_done(SP_DT_DOCUMENT(_dt));
+ }
+ _dt->set_coordinate_status(event_dt);
+ }
+ return false;
+}
+
+//------------------------------------------------------------
+HRuler::HRuler()
+{
+ _dt = 0;
+ _r = static_cast<Gtk::HRuler*>(Glib::wrap(static_cast<GtkWidget*> (sp_hruler_new())));
+ add(*_r);
+ _horiz_f = true;
+}
+
+HRuler::~HRuler()
+{
+}
+
+
+VRuler::VRuler()
+{
+ _dt = 0;
+ _r = static_cast<Gtk::VRuler*>(Glib::wrap(static_cast<GtkWidget*> (sp_vruler_new())));
+ add(*_r);
+ _horiz_f = false;
+}
+
+VRuler::~VRuler()
+{
+}
+
+}}}
+
+/*
+ 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/ruler.h b/src/ui/widget/ruler.h
new file mode 100644
index 000000000..74dbf028c
--- /dev/null
+++ b/src/ui/widget/ruler.h
@@ -0,0 +1,88 @@
+#ifndef __UI_WIDGET_RULER_H__
+#define __UI_WIDGET_RULER_H__
+
+/** \file
+ * Gtkmm facade/wrapper around sp_rulers.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 The Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/eventbox.h>
+#include "libnr/nr-point.h"
+
+struct SPCanvasItem;
+struct SPDesktop;
+namespace Glib {
+ class ustring;
+}
+namespace Gtk {
+ class Ruler;
+}
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class Ruler : public Gtk::EventBox
+{
+public:
+ void init (SPDesktop*, Gtk::Widget&);
+ void get_range (double&, double&, double&, double&);
+ void set_range (double, double, double, double);
+ void update_metric();
+ Glib::ustring get_tip();
+
+protected:
+ SPDesktop *_dt;
+ SPCanvasItem *_guide;
+ Gtk::Widget *_canvas_widget;
+ Gtk::Ruler *_r;
+ bool _horiz_f, _dragging;
+
+ virtual bool on_button_press_event (GdkEventButton *);
+ virtual bool on_motion_notify_event (GdkEventMotion *);
+ virtual bool on_button_release_event (GdkEventButton *);
+
+private:
+ void canvas_get_pointer (int&, int&);
+ NR::Point get_event_dt();
+};
+
+/// Horizontal ruler
+class HRuler : public Ruler
+{
+public:
+ HRuler();
+ ~HRuler();
+};
+
+/// Vertical ruler
+class VRuler : public Ruler
+{
+public:
+ VRuler();
+ ~VRuler();
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#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 :
diff --git a/src/ui/widget/scalar-unit.cpp b/src/ui/widget/scalar-unit.cpp
new file mode 100644
index 000000000..8727ed052
--- /dev/null
+++ b/src/ui/widget/scalar-unit.cpp
@@ -0,0 +1,252 @@
+/**
+ * \brief Scalar Unit Widget - A labelled text box, with spin buttons and
+ * optional icon or suffix, for entering the values of various unit
+ * types.
+ *
+ * A ScalarUnit is a control for entering, viewing, or manipulating
+ * numbers with units. This differs from ordinary numbers like 2 or
+ * 3.14 because the number portion of a scalar *only* has meaning
+ * when considered with its unit type. For instance, 12 m and 12 in
+ * have very different actual values, but 1 m and 100 cm have the same
+ * value. The ScalarUnit allows us to abstract the presentation of
+ * the scalar to the user from the internal representations used by
+ * the program.
+ *
+ * Authors:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ * Derek P. Moore <derekm@hackunix.org>
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2004-2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "scalar-unit.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a ScalarUnit
+ *
+ * \param label Label.
+ * \param unit_type Unit type (defaults to UNIT_TYPE_LINEAR).
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param unit_menu UnitMenu drop down; if not specified, one will be created
+ * and displayed after the widget (defaults to NULL).
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to true).
+ */
+ScalarUnit::ScalarUnit(Glib::ustring const &label, Glib::ustring const &tooltip,
+ UnitType unit_type,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ UnitMenu *unit_menu,
+ bool mnemonic)
+ : Scalar(label, tooltip, suffix, icon, mnemonic),
+ _unit_menu(unit_menu),
+ _hundred_percent(0),
+ _absolute_is_increment(false),
+ _percentage_is_increment(false)
+{
+ if (_unit_menu == NULL) {
+ _unit_menu = new UnitMenu();
+ g_assert(_unit_menu);
+ _unit_menu->setUnitType(unit_type);
+ pack_start(*Gtk::manage(_unit_menu), false, false, 4);
+ }
+ _unit_menu->signal_changed()
+ .connect_notify(sigc::mem_fun(*this, &ScalarUnit::on_unit_changed));
+}
+
+/**
+ * Initializes the scalar based on the settings in _unit_menu.
+ * Requires that _unit_menu has already been initialized.
+ */
+void
+ScalarUnit::initScalar(double min_value, double max_value)
+{
+ g_assert(_unit_menu != NULL);
+ Scalar::setDigits(_unit_menu->getDefaultDigits());
+ Scalar::setIncrements(_unit_menu->getDefaultStep(),
+ _unit_menu->getDefaultPage());
+ Scalar::setRange(min_value, max_value);
+}
+
+/** Sets the unit for the ScalarUnit widget */
+bool
+ScalarUnit::setUnit(Glib::ustring const &unit) {
+ g_assert(_unit_menu != NULL);
+ // First set the unit
+ if (!_unit_menu->setUnit(unit)) {
+ return false;
+ }
+ lastUnits = unit;
+ return true;
+}
+
+/** Gets the object for the currently selected unit */
+Unit
+ScalarUnit::getUnit() const {
+ g_assert(_unit_menu != NULL);
+ return _unit_menu->getUnit();
+}
+
+/** Gets the UnitType ID for the unit */
+UnitType
+ScalarUnit::getUnitType() const {
+ g_assert(_unit_menu);
+ return _unit_menu->getUnitType();
+}
+
+/** Sets the number and unit system */
+void
+ScalarUnit::setValue(double number, Glib::ustring const &units) {
+ g_assert(_unit_menu != NULL);
+ _unit_menu->setUnit(units);
+ Scalar::setValue(number);
+}
+
+/** Sets the number only */
+void
+ScalarUnit::setValue(double number) {
+ Scalar::setValue(number);
+}
+
+/** Returns the value in the given unit system */
+double
+ScalarUnit::getValue(Glib::ustring const &unit_name) const {
+ g_assert(_unit_menu != NULL);
+ if (unit_name == "") {
+ // Return the value in the default units
+ return Scalar::getValue();
+ } else {
+ double conversion = _unit_menu->getConversion(unit_name);
+ return conversion * Scalar::getValue();
+ }
+}
+
+void
+ScalarUnit::setHundredPercent(double number)
+{
+ _hundred_percent = number;
+}
+
+void
+ScalarUnit::setAbsoluteIsIncrement(bool value)
+{
+ _absolute_is_increment = value;
+}
+
+void
+ScalarUnit::setPercentageIsIncrement(bool value)
+{
+ _percentage_is_increment = value;
+}
+
+/** Convert value from % to absolute, using _hundred_percent and *_is_increment flags */
+double
+ScalarUnit::PercentageToAbsolute(double value)
+{
+ // convert from percent to absolute
+ double convertedVal = 0;
+ double hundred_converted = _hundred_percent / _unit_menu->getConversion("px"); // _hundred_percent is in px
+ if (_percentage_is_increment)
+ value += 100;
+ convertedVal = 0.01 * hundred_converted * value;
+ if (_absolute_is_increment)
+ convertedVal -= hundred_converted;
+
+ return convertedVal;
+}
+
+/** Convert value from absolute to %, using _hundred_percent and *_is_increment flags */
+double
+ScalarUnit::AbsoluteToPercentage(double value)
+{
+ double convertedVal = 0;
+ // convert from absolute to percent
+ if (_hundred_percent == 0) {
+ if (_percentage_is_increment)
+ convertedVal = 0;
+ else
+ convertedVal = 100;
+ } else {
+ double hundred_converted = _hundred_percent / _unit_menu->getConversion("px", lastUnits); // _hundred_percent is in px
+ if (_absolute_is_increment)
+ value += hundred_converted;
+ convertedVal = 100 * value / hundred_converted;
+ if (_percentage_is_increment)
+ convertedVal -= 100;
+ }
+
+ return convertedVal;
+}
+
+/** Assuming the current unit is absolute, get the corresponding % value */
+double
+ScalarUnit::getAsPercentage()
+{
+ double convertedVal = AbsoluteToPercentage(Scalar::getValue());
+ return convertedVal;
+}
+
+
+/** Assuming the current unit is absolute, set the value corresponding to a given % */
+void
+ScalarUnit::setFromPercentage(double value)
+{
+ double absolute = PercentageToAbsolute(value);
+ Scalar::setValue(absolute);
+}
+
+
+/** Signal handler for updating the value and suffix label when unit is changed */
+void
+ScalarUnit::on_unit_changed()
+{
+ g_assert(_unit_menu != NULL);
+
+ Glib::ustring abbr = _unit_menu->getUnitAbbr();
+ _suffix->set_label(abbr);
+
+ Inkscape::Util::UnitTable &table = _unit_menu->getUnitTable();
+ Inkscape::Util::Unit new_unit = (table.getUnit(abbr));
+ Inkscape::Util::Unit old_unit = (table.getUnit(lastUnits));
+
+ double convertedVal = 0;
+ if (old_unit.type == UNIT_TYPE_DIMENSIONLESS && new_unit.type == UNIT_TYPE_LINEAR) {
+ convertedVal = PercentageToAbsolute(Scalar::getValue());
+ } else if (old_unit.type == UNIT_TYPE_LINEAR && new_unit.type == UNIT_TYPE_DIMENSIONLESS) {
+ convertedVal = AbsoluteToPercentage(Scalar::getValue());
+ } else {
+ double conversion = _unit_menu->getConversion(lastUnits);
+ convertedVal = Scalar::getValue() / conversion;
+ }
+ Scalar::setValue(convertedVal);
+
+ lastUnits = abbr;
+}
+
+} // namespace Widget
+} // 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/widget/scalar-unit.h b/src/ui/widget/scalar-unit.h
new file mode 100644
index 000000000..c99161dad
--- /dev/null
+++ b/src/ui/widget/scalar-unit.h
@@ -0,0 +1,85 @@
+/**
+ * \brief Scalar Unit Widget - A labelled text box, with spin buttons and
+ * optional icon or suffix, for entering the values of various unit
+ * types.
+ *
+ * Authors:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ * Derek P. Moore <derekm@hackunix.org>
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2004-2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_SCALAR_UNIT_H
+#define INKSCAPE_UI_WIDGET_SCALAR_UNIT_H
+
+#include "scalar.h"
+#include "unit-menu.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class ScalarUnit : public Scalar
+{
+public:
+ ScalarUnit(Glib::ustring const &label, Glib::ustring const &tooltip,
+ UnitType unit_type = UNIT_TYPE_LINEAR,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ UnitMenu *unit_menu = NULL,
+ bool mnemonic = true);
+
+ void initScalar(double min_value, double max_value);
+
+ Unit getUnit() const;
+ UnitType getUnitType() const;
+ double getValue(Glib::ustring const &units) const;
+
+ bool setUnit(Glib::ustring const &units);
+ void setValue(double number, Glib::ustring const &units);
+ void setValue(double number);
+
+ void setHundredPercent(double number);
+ void setAbsoluteIsIncrement(bool value);
+ void setPercentageIsIncrement(bool value);
+
+ double PercentageToAbsolute(double value);
+ double AbsoluteToPercentage(double value);
+
+ double getAsPercentage();
+ void setFromPercentage(double value);
+
+ void on_unit_changed();
+
+protected:
+ UnitMenu *_unit_menu;
+
+ double _hundred_percent; // the length that corresponds to 100%, in px, for %-to/from-absolute conversions
+
+ bool _absolute_is_increment; // if true, 120% with _hundred_percent=100px gets converted to/from 20px; otherwise, to/from 120px
+ bool _percentage_is_increment; // if true, 120px with _hundred_percent=100px gets converted to/from 20%; otherwise, to/from 120%
+ // if both are true, 20px is converted to/from 20% if _hundred_percent=100px
+
+ Glib::ustring lastUnits; // previously selected unit, for conversions
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_SCALAR_UNIT_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/widget/scalar.cpp b/src/ui/widget/scalar.cpp
new file mode 100644
index 000000000..ae90e4a0f
--- /dev/null
+++ b/src/ui/widget/scalar.cpp
@@ -0,0 +1,217 @@
+/**
+ * \brief Scalar Widget - A labelled text box, with spin buttons and optional
+ * icon or suffix, for entering arbitrary number values.
+ *
+ * Authors:
+ * Carl Hetherington <inkscape@carlh.net>
+ * Derek P. Moore <derekm@hackunix.org>
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Carl Hetherington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include "scalar.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a Scalar Widget.
+ *
+ * \param label Label.
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to false).
+ */
+Scalar::Scalar(Glib::ustring const &label, Glib::ustring const &tooltip,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ bool mnemonic)
+ : Labelled(label, tooltip, new Gtk::SpinButton(), suffix, icon, mnemonic),
+ setProgrammatically(false)
+{
+}
+
+/**
+ * Construct a Scalar Widget.
+ *
+ * \param label Label.
+ * \param digits Number of decimal digits to display.
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to false).
+ */
+Scalar::Scalar(Glib::ustring const &label, Glib::ustring const &tooltip,
+ unsigned digits,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ bool mnemonic)
+ : Labelled(label, tooltip, new Gtk::SpinButton(0.0, digits), suffix, icon, mnemonic),
+ setProgrammatically(false)
+{
+}
+
+/**
+ * Construct a Scalar Widget.
+ *
+ * \param label Label.
+ * \param adjust Adjustment to use for the SpinButton.
+ * \param digits Number of decimal digits to display (defaults to 0).
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to true).
+ */
+Scalar::Scalar(Glib::ustring const &label, Glib::ustring const &tooltip,
+ Gtk::Adjustment &adjust,
+ unsigned digits,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ bool mnemonic)
+ : Labelled(label, tooltip, new Gtk::SpinButton(adjust, 0.0, digits), suffix, icon, mnemonic),
+ setProgrammatically(false)
+{
+}
+
+/** Fetches the precision of the spin buton */
+unsigned
+Scalar::getDigits() const
+{
+ g_assert(_widget != NULL);
+ return static_cast<Gtk::SpinButton*>(_widget)->get_digits();
+}
+
+/** Gets the current step ingrement used by the spin button */
+double
+Scalar::getStep() const
+{
+ g_assert(_widget != NULL);
+ double step, page;
+ static_cast<Gtk::SpinButton*>(_widget)->get_increments(step, page);
+ return step;
+}
+
+/** Gets the current page increment used by the spin button */
+double
+Scalar::getPage() const
+{
+ g_assert(_widget != NULL);
+ double step, page;
+ static_cast<Gtk::SpinButton*>(_widget)->get_increments(step, page);
+ return page;
+}
+
+/** Gets the minimum range value allowed for the spin button */
+double
+Scalar::getRangeMin() const
+{
+ g_assert(_widget != NULL);
+ double min, max;
+ static_cast<Gtk::SpinButton*>(_widget)->get_range(min, max);
+ return min;
+}
+
+/** Gets the maximum range value allowed for the spin button */
+double
+Scalar::getRangeMax() const
+{
+ g_assert(_widget != NULL);
+ double min, max;
+ static_cast<Gtk::SpinButton*>(_widget)->get_range(min, max);
+ return max;
+}
+
+/** Get the value in the spin_button . */
+double
+Scalar::getValue() const
+{
+ g_assert(_widget != NULL);
+ return static_cast<Gtk::SpinButton*>(_widget)->get_value();
+}
+
+/** Get the value spin_button represented as an integer. */
+int
+Scalar::getValueAsInt() const
+{
+ g_assert(_widget != NULL);
+ return static_cast<Gtk::SpinButton*>(_widget)->get_value_as_int();
+}
+
+
+/** Sets the precision to be displayed by the spin button */
+void
+Scalar::setDigits(unsigned digits)
+{
+ g_assert(_widget != NULL);
+ static_cast<Gtk::SpinButton*>(_widget)->set_digits(digits);
+}
+
+/** Sets the step and page increments for the spin button */
+void
+Scalar::setIncrements(double step, double page)
+{
+ g_assert(_widget != NULL);
+ static_cast<Gtk::SpinButton*>(_widget)->set_increments(step, page);
+}
+
+/** Sets the minimum and maximum range allowed for the spin button */
+void
+Scalar::setRange(double min, double max)
+{
+ g_assert(_widget != NULL);
+ static_cast<Gtk::SpinButton*>(_widget)->set_range(min, max);
+}
+
+/** Sets the value of the spin button */
+void
+Scalar::setValue(double value)
+{
+ g_assert(_widget != NULL);
+ setProgrammatically = true; // callback is supposed to reset back, if it cares
+ static_cast<Gtk::SpinButton*>(_widget)->set_value(value);
+}
+
+/** Manually forces an update of the spin button */
+void
+Scalar::update() {
+ g_assert(_widget != NULL);
+ static_cast<Gtk::SpinButton*>(_widget)->update();
+}
+
+
+
+/** Signal raised when the spin button's value changes */
+Glib::SignalProxy0<void>
+Scalar::signal_value_changed()
+{
+ return static_cast<Gtk::SpinButton*>(_widget)->signal_value_changed();
+}
+
+
+} // namespace Widget
+} // 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/widget/scalar.h b/src/ui/widget/scalar.h
new file mode 100644
index 000000000..8ce72d949
--- /dev/null
+++ b/src/ui/widget/scalar.h
@@ -0,0 +1,86 @@
+/**
+ * \brief Scalar Widget - A labelled text box, with spin buttons and optional
+ * icon or suffix, for entering arbitrary number values.
+ *
+ * Authors:
+ * Carl Hetherington <inkscape@carlh.net>
+ * Derek P. Moore <derekm@hackunix.org>
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Carl Hetherington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_SCALAR_H
+#define INKSCAPE_UI_WIDGET_SCALAR_H
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/spinbutton.h>
+
+#include "labelled.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Scalar : public Labelled
+{
+public:
+ Scalar(Glib::ustring const &label,
+ Glib::ustring const &tooltip,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ bool mnemonic = true);
+ Scalar(Glib::ustring const &label,
+ Glib::ustring const &tooltip,
+ unsigned digits,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ bool mnemonic = true);
+ Scalar(Glib::ustring const &label,
+ Glib::ustring const &tooltip,
+ Gtk::Adjustment &adjust,
+ unsigned digits = 0,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ bool mnemonic = true);
+
+ unsigned getDigits() const;
+ double getStep() const;
+ double getPage() const;
+ double getRangeMin() const;
+ double getRangeMax() const;
+ bool getSnapToTicks() const;
+ double getValue() const;
+ int getValueAsInt() const;
+
+ void setDigits(unsigned digits);
+ void setIncrements(double step, double page);
+ void setRange(double min, double max);
+ void setValue(double value);
+
+ void update();
+
+ Glib::SignalProxy0<void> signal_value_changed();
+
+ bool setProgrammatically; // true if the value was set by setValue, not changed by the user;
+ // if a callback checks it, it must reset it back to false
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_SCALAR_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/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp
new file mode 100644
index 000000000..c808289b2
--- /dev/null
+++ b/src/ui/widget/selected-style.cpp
@@ -0,0 +1,977 @@
+/**
+ * \brief Selected style indicator (fill, stroke, opacity)
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include "selected-style.h"
+
+#include "widgets/spw-utilities.h"
+#include "ui/widget/color-preview.h"
+
+#include "selection.h"
+#include "desktop-handles.h"
+#include "style.h"
+#include "desktop-style.h"
+#include "sp-linear-gradient-fns.h"
+#include "sp-radial-gradient-fns.h"
+#include "sp-pattern.h"
+#include "dialogs/object-properties.h"
+#include "xml/repr.h"
+#include "document.h"
+#include "widgets/widget-sizes.h"
+#include "widgets/spinbutton-events.h"
+#include "svg/svg.h"
+#include "svg/css-ostringstream.h"
+#include "helper/units.h"
+
+static gdouble const _sw_presets[] = { 32 , 16 , 10 , 8 , 6 , 4 , 3 , 2 , 1.5 , 1 , 0.75 , 0.5 , 0.25 , 0.1 };
+static gchar* const _sw_presets_str[] = {"32", "16", "10", "8", "6", "4", "3", "2", "1.5", "1", "0.75", "0.5", "0.25", "0.1"};
+
+static void
+ss_selection_changed (Inkscape::Selection *, gpointer data)
+{
+ Inkscape::UI::Widget::SelectedStyle *ss = (Inkscape::UI::Widget::SelectedStyle *) data;
+ ss->update();
+}
+
+static void
+ss_selection_modified (Inkscape::Selection *selection, guint flags, gpointer data)
+{
+ ss_selection_changed (selection, data);
+}
+
+static void
+ss_subselection_changed (gpointer dragger, gpointer data)
+{
+ ss_selection_changed (NULL, data);
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+SelectedStyle::SelectedStyle(bool layout)
+ : _desktop (NULL),
+
+ _table(2, 6),
+ _fill_label (_("F:")),
+ _stroke_label (_("S:")),
+ _opacity_label (_("O:")),
+ _fill_place (),
+ _stroke_place (),
+
+ _fill_flag_place (),
+ _stroke_flag_place (),
+
+ _opacity_place (),
+ _opacity_adjustment (1.0, 0.0, 1.0, 0.01, 0.1),
+ _opacity_sb (0.02, 2),
+
+ _stroke (),
+ _stroke_width (""),
+
+ _opacity_blocked (false),
+
+ _popup_px(_sw_group),
+ _popup_pt(_sw_group),
+ _popup_mm(_sw_group),
+
+ _sw_unit(NULL),
+
+ _tooltips ()
+{
+ _fill_label.set_alignment(0.0, 0.5);
+ _fill_label.set_padding(0, 0);
+ _stroke_label.set_alignment(0.0, 0.5);
+ _stroke_label.set_padding(0, 0);
+ _opacity_label.set_alignment(0.0, 0.5);
+ _opacity_label.set_padding(0, 0);
+
+ _table.set_col_spacings (2);
+ _table.set_row_spacings (0);
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+
+ _na[i].set_markup (_("N/A"));
+ sp_set_font_size_smaller (GTK_WIDGET(_na[i].gobj()));
+ _na[i].show_all();
+ __na[i] = (_("Nothing selected"));
+
+ _none[i].set_markup (_("None"));
+ sp_set_font_size_smaller (GTK_WIDGET(_none[i].gobj()));
+ _none[i].show_all();
+ __none[i] = (i == SS_FILL)? (_("No fill")) : (_("No stroke"));
+
+ _pattern[i].set_markup (_("Pattern"));
+ sp_set_font_size_smaller (GTK_WIDGET(_pattern[i].gobj()));
+ _pattern[i].show_all();
+ __pattern[i] = (i == SS_FILL)? (_("Pattern fill")) : (_("Pattern stroke"));
+
+ _lgradient[i].set_markup (_("L Gradient"));
+ sp_set_font_size_smaller (GTK_WIDGET(_lgradient[i].gobj()));
+ _lgradient[i].show_all();
+ __lgradient[i] = (i == SS_FILL)? (_("Linear gradient fill")) : (_("Linear gradient stroke"));
+
+ _rgradient[i].set_markup (_("R Gradient"));
+ sp_set_font_size_smaller (GTK_WIDGET(_rgradient[i].gobj()));
+ _rgradient[i].show_all();
+ __rgradient[i] = (i == SS_FILL)? (_("Radial gradient fill")) : (_("Radial gradient stroke"));
+
+ _many[i].set_markup (_("Different"));
+ sp_set_font_size_smaller (GTK_WIDGET(_many[i].gobj()));
+ _many[i].show_all();
+ __many[i] = (i == SS_FILL)? (_("Different fills")) : (_("Different strokes"));
+
+ _unset[i].set_markup (_("Unset"));
+ sp_set_font_size_smaller (GTK_WIDGET(_unset[i].gobj()));
+ _unset[i].show_all();
+ __unset[i] = (i == SS_FILL)? (_("Unset fill")) : (_("Unset stroke"));
+
+ _color_preview[i] = new Inkscape::UI::Widget::ColorPreview (0);
+ __color[i] = (i == SS_FILL)? (_("Flat color fill")) : (_("Flat color stroke"));
+
+ // TRANSLATOR COMMENT: A means "Averaged"
+ _averaged[i].set_markup (_("<b>a</b>"));
+ sp_set_font_size_smaller (GTK_WIDGET(_averaged[i].gobj()));
+ _averaged[i].show_all();
+ __averaged[i] = (i == SS_FILL)? (_("Fill is averaged over selected objects")) : (_("Stroke is averaged over selected objects"));
+
+ // TRANSLATOR COMMENT: M means "Multiple"
+ _multiple[i].set_markup (_("<b>m</b>"));
+ sp_set_font_size_smaller (GTK_WIDGET(_multiple[i].gobj()));
+ _multiple[i].show_all();
+ __multiple[i] = (i == SS_FILL)? (_("Multiple selected objects have the same fill")) : (_("Multiple selected objects have the same stroke"));
+
+ _popup_edit[i].add(*(new Gtk::Label((i == SS_FILL)? _("Edit fill...") : _("Edit stroke..."), 0.0, 0.5)));
+ _popup_edit[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_edit : &SelectedStyle::on_stroke_edit ));
+
+ _popup_lastused[i].add(*(new Gtk::Label(_("Last set color"), 0.0, 0.5)));
+ _popup_lastused[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_lastused : &SelectedStyle::on_stroke_lastused ));
+
+ _popup_lastselected[i].add(*(new Gtk::Label(_("Last selected color"), 0.0, 0.5)));
+ _popup_lastselected[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_lastselected : &SelectedStyle::on_stroke_lastselected ));
+
+ _popup_invert[i].add(*(new Gtk::Label(_("Invert"), 0.0, 0.5)));
+ _popup_invert[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_invert : &SelectedStyle::on_stroke_invert ));
+
+ _popup_white[i].add(*(new Gtk::Label(_("White"), 0.0, 0.5)));
+ _popup_white[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_white : &SelectedStyle::on_stroke_white ));
+
+ _popup_black[i].add(*(new Gtk::Label(_("Black"), 0.0, 0.5)));
+ _popup_black[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_black : &SelectedStyle::on_stroke_black ));
+
+ _popup_copy[i].add(*(new Gtk::Label(_("Copy color"), 0.0, 0.5)));
+ _popup_copy[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_copy : &SelectedStyle::on_stroke_copy ));
+
+ _popup_paste[i].add(*(new Gtk::Label(_("Paste color"), 0.0, 0.5)));
+ _popup_paste[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_paste : &SelectedStyle::on_stroke_paste ));
+
+ _popup_swap[i].add(*(new Gtk::Label(_("Swap fill and stroke"), 0.0, 0.5)));
+ _popup_swap[i].signal_activate().connect(sigc::mem_fun(*this,
+ &SelectedStyle::on_fillstroke_swap));
+
+ _popup_opaque[i].add(*(new Gtk::Label((i == SS_FILL)? _("Make fill opaque") : _("Make stroke opaque"), 0.0, 0.5)));
+ _popup_opaque[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_opaque : &SelectedStyle::on_stroke_opaque ));
+
+ //TRANSLATORS COMMENT: unset is a verb here
+ _popup_unset[i].add(*(new Gtk::Label((i == SS_FILL)? _("Unset fill") : _("Unset stroke"), 0.0, 0.5)));
+ _popup_unset[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_unset : &SelectedStyle::on_stroke_unset ));
+
+ _popup_remove[i].add(*(new Gtk::Label((i == SS_FILL)? _("Remove fill") : _("Remove stroke"), 0.0, 0.5)));
+ _popup_remove[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_remove : &SelectedStyle::on_stroke_remove ));
+
+ _popup[i].attach(_popup_edit[i], 0,1, 0,1);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 1,2);
+ _popup[i].attach(_popup_lastused[i], 0,1, 2,3);
+ _popup[i].attach(_popup_lastselected[i], 0,1, 3,4);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 4,5);
+ _popup[i].attach(_popup_invert[i], 0,1, 5,6);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 6,7);
+ _popup[i].attach(_popup_white[i], 0,1, 7,8);
+ _popup[i].attach(_popup_black[i], 0,1, 8,9);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 9,10);
+ _popup[i].attach(_popup_copy[i], 0,1, 10,11);
+ _popup_copy[i].set_sensitive(false);
+ _popup[i].attach(_popup_paste[i], 0,1, 11,12);
+ _popup[i].attach(_popup_swap[i], 0,1, 12,13);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 13,14);
+ _popup[i].attach(_popup_opaque[i], 0,1, 14,15);
+ _popup[i].attach(_popup_unset[i], 0,1, 15,16);
+ _popup[i].attach(_popup_remove[i], 0,1, 16,17);
+ _popup[i].show_all();
+
+ _mode[i] = SS_NA;
+ }
+
+ {
+ _popup_px.add(*(new Gtk::Label(_("px"), 0.0, 0.5)));
+ _popup_px.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_px));
+ _popup_sw.attach(_popup_px, 0,1, 0,1);
+
+ _popup_pt.add(*(new Gtk::Label(_("pt"), 0.0, 0.5)));
+ _popup_pt.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_pt));
+ _popup_sw.attach(_popup_pt, 0,1, 1,2);
+
+ _popup_mm.add(*(new Gtk::Label(_("mm"), 0.0, 0.5)));
+ _popup_mm.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_mm));
+ _popup_sw.attach(_popup_mm, 0,1, 2,3);
+
+ _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, 3,4);
+
+ for (guint i = 0; i < G_N_ELEMENTS(_sw_presets_str); ++i) {
+ Gtk::MenuItem *mi = Gtk::manage(new Gtk::MenuItem());
+ mi->add(*(new Gtk::Label(_sw_presets_str[i], 0.0, 0.5)));
+ mi->signal_activate().connect(sigc::bind<int>(sigc::mem_fun(*this, &SelectedStyle::on_popup_preset), i));
+ _popup_sw.attach(*mi, 0,1, 4+i, 5+i);
+ }
+
+ guint i = G_N_ELEMENTS(_sw_presets_str) + 5;
+
+ _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, i,i+1);
+
+ _popup_sw_remove.add(*(new Gtk::Label(_("Remove"), 0.0, 0.5)));
+ _popup_sw_remove.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_stroke_remove));
+ _popup_sw.attach(_popup_sw_remove, 0,1, i+1,i+2);
+
+ _popup_sw.show_all();
+ }
+
+ _fill_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_fill_click));
+ _stroke_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_stroke_click));
+ _opacity_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_click));
+ _stroke_width_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_sw_click));
+
+ _opacity_sb.signal_populate_popup().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_menu));
+ _opacity_sb.signal_value_changed().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_changed));
+
+ _fill_place.add(_na[SS_FILL]);
+ _tooltips.set_tip(_fill_place, __na[SS_FILL]);
+
+ _stroke_place.add(_na[SS_STROKE]);
+ _tooltips.set_tip(_stroke_place, __na[SS_STROKE]);
+
+ _stroke.pack_start(_stroke_place);
+ _stroke_width_place.add(_stroke_width);
+ _stroke.pack_start(_stroke_width_place, Gtk::PACK_SHRINK);
+
+ _opacity_sb.set_adjustment(_opacity_adjustment);
+ sp_set_font_size_smaller (GTK_WIDGET(_opacity_sb.gobj()));
+ _opacity_sb.set_size_request (SELECTED_STYLE_SB_WIDTH, -1);
+ _opacity_sb.set_sensitive (false);
+
+ _table.attach(_fill_label, 0,1, 0,1, Gtk::SHRINK, Gtk::SHRINK);
+ _table.attach(_stroke_label, 0,1, 1,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ _table.attach(_fill_flag_place, 1,2, 0,1, Gtk::SHRINK, Gtk::SHRINK);
+ _table.attach(_stroke_flag_place, 1,2, 1,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ _table.attach(_fill_place, 2,3, 0,1);
+ _table.attach(_stroke, 2,3, 1,2);
+
+ _opacity_place.add(_opacity_label);
+ _table.attach(_opacity_place, 4,5, 0,2, Gtk::SHRINK, Gtk::SHRINK);
+ _table.attach(_opacity_sb, 5,6, 0,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ pack_start(_table, true, true, 2);
+
+ set_size_request (SELECTED_STYLE_WIDTH, -1);
+
+ sp_set_font_size_smaller (GTK_WIDGET(_opacity_label.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_opacity_sb.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_fill_place.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_fill_flag_place.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_place.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_flag_place.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_width.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_fill_label.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_label.gobj()));
+}
+
+SelectedStyle::~SelectedStyle()
+{
+ selection_changed_connection->disconnect();
+ delete selection_changed_connection;
+ selection_modified_connection->disconnect();
+ delete selection_modified_connection;
+ subselection_changed_connection->disconnect();
+ delete subselection_changed_connection;
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ delete _color_preview[i];
+ }
+}
+
+void
+SelectedStyle::setDesktop(SPDesktop *desktop)
+{
+ _desktop = desktop;
+ gtk_object_set_data (GTK_OBJECT(_opacity_sb.gobj()), "dtw", _desktop->canvas);
+
+ Inkscape::Selection *selection = SP_DT_SELECTION (desktop);
+
+ selection_changed_connection = new sigc::connection (selection->connectChanged(
+ sigc::bind (
+ sigc::ptr_fun(&ss_selection_changed),
+ this )
+ ));
+ selection_modified_connection = new sigc::connection (selection->connectModified(
+ sigc::bind (
+ sigc::ptr_fun(&ss_selection_modified),
+ this )
+ ));
+ subselection_changed_connection = new sigc::connection (desktop->connectToolSubselectionChanged(
+ sigc::bind (
+ sigc::ptr_fun(&ss_subselection_changed),
+ this )
+ ));
+
+ //_sw_unit = (SPUnit *) SP_DT_NAMEDVIEW(desktop)->doc_units;
+}
+
+void SelectedStyle::on_fill_remove() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "fill", "none");
+ sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_remove() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "stroke", "none");
+ sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_unset() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_unset_property (css, "fill");
+ sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_unset() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_unset_property (css, "stroke");
+ sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_opaque() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "fill-opacity", "1");
+ sp_desktop_set_style (_desktop, css, true);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_opaque() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "stroke-opacity", "1");
+ sp_desktop_set_style (_desktop, css, true);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_lastused() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ guint32 color = sp_desktop_get_color(_desktop, true);
+ gchar c[64];
+ sp_svg_write_color (c, 64, color);
+ sp_repr_css_set_property (css, "fill", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_lastused() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ guint32 color = sp_desktop_get_color(_desktop, false);
+ gchar c[64];
+ sp_svg_write_color (c, 64, color);
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_lastselected() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, _lastselected[SS_FILL]);
+ sp_repr_css_set_property (css, "fill", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_lastselected() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, _lastselected[SS_STROKE]);
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_invert() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ guint32 color = _thisselected[SS_FILL];
+ gchar c[64];
+ if (_mode[SS_FILL] != SS_COLOR) return;
+ sp_svg_write_color (c, 64,
+ SP_RGBA32_U_COMPOSE(
+ (255 - SP_RGBA32_R_U(color)),
+ (255 - SP_RGBA32_G_U(color)),
+ (255 - SP_RGBA32_B_U(color)),
+ SP_RGBA32_A_U(color)
+ )
+ );
+ sp_repr_css_set_property (css, "fill", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_invert() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ guint32 color = _thisselected[SS_STROKE];
+ gchar c[64];
+ if (_mode[SS_STROKE] != SS_COLOR) return;
+ sp_svg_write_color (c, 64,
+ SP_RGBA32_U_COMPOSE(
+ (255 - SP_RGBA32_R_U(color)),
+ (255 - SP_RGBA32_G_U(color)),
+ (255 - SP_RGBA32_B_U(color)),
+ SP_RGBA32_A_U(color)
+ )
+ );
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_white() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, 0xffffffff);
+ sp_repr_css_set_property (css, "fill", c);
+ sp_repr_css_set_property (css, "fill-opacity", "1");
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_white() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, 0xffffffff);
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_repr_css_set_property (css, "stroke-opacity", "1");
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_black() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, 0x000000ff);
+ sp_repr_css_set_property (css, "fill", c);
+ sp_repr_css_set_property (css, "fill-opacity", "1.0");
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_black() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, 0x000000ff);
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_repr_css_set_property (css, "stroke-opacity", "1.0");
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_copy() {
+ if (_mode[SS_FILL] == SS_COLOR) {
+ gchar c[64];
+ sp_svg_write_color (c, 64, _thisselected[SS_FILL]);
+ Glib::ustring text;
+ text += c;
+ if (!text.empty()) {
+ Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
+ refClipboard->set_text(text);
+ }
+ }
+}
+
+void SelectedStyle::on_stroke_copy() {
+ if (_mode[SS_STROKE] == SS_COLOR) {
+ gchar c[64];
+ sp_svg_write_color (c, 64, _thisselected[SS_STROKE]);
+ Glib::ustring text;
+ text += c;
+ if (!text.empty()) {
+ Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
+ refClipboard->set_text(text);
+ }
+ }
+}
+
+void SelectedStyle::on_fill_paste() {
+ Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
+ Glib::ustring const text = refClipboard->wait_for_text();
+
+ if (!text.empty()) {
+ guint32 color = sp_svg_read_color(text.c_str(), 0x000000ff); // impossible value, as SVG color cannot have opacity
+ if (color == 0x000000ff) // failed to parse color string
+ return;
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "fill", text.c_str());
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+ }
+}
+
+void SelectedStyle::on_stroke_paste() {
+ Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
+ Glib::ustring const text = refClipboard->wait_for_text();
+
+ if (!text.empty()) {
+ guint32 color = sp_svg_read_color(text.c_str(), 0x000000ff); // impossible value, as SVG color cannot have opacity
+ if (color == 0x000000ff) // failed to parse color string
+ return;
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "stroke", text.c_str());
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+ }
+}
+
+void SelectedStyle::on_fillstroke_swap() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+
+ switch (_mode[SS_FILL]) {
+ case SS_NA:
+ case SS_MANY:
+ break;
+ case SS_NONE:
+ sp_repr_css_set_property (css, "stroke", "none");
+ break;
+ case SS_UNSET:
+ sp_repr_css_unset_property (css, "stroke");
+ break;
+ case SS_COLOR:
+ gchar c[64];
+ sp_svg_write_color (c, 64, _thisselected[SS_FILL]);
+ sp_repr_css_set_property (css, "stroke", c);
+ break;
+ case SS_LGRADIENT:
+ case SS_RGRADIENT:
+ case SS_PATTERN:
+ sp_repr_css_set_property (css, "stroke", _paintserver_id[SS_FILL].c_str());
+ break;
+ }
+
+ switch (_mode[SS_STROKE]) {
+ case SS_NA:
+ case SS_MANY:
+ break;
+ case SS_NONE:
+ sp_repr_css_set_property (css, "fill", "none");
+ break;
+ case SS_UNSET:
+ sp_repr_css_unset_property (css, "fill");
+ break;
+ case SS_COLOR:
+ gchar c[64];
+ sp_svg_write_color (c, 64, _thisselected[SS_STROKE]);
+ sp_repr_css_set_property (css, "fill", c);
+ break;
+ case SS_LGRADIENT:
+ case SS_RGRADIENT:
+ case SS_PATTERN:
+ sp_repr_css_set_property (css, "fill", _paintserver_id[SS_STROKE].c_str());
+ break;
+ }
+
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_edit() {
+ sp_object_properties_fill();
+}
+
+void SelectedStyle::on_stroke_edit() {
+ sp_object_properties_stroke();
+}
+
+bool
+SelectedStyle::on_fill_click(GdkEventButton *event)
+{
+ if (event->button == 1) { // click, open fill&stroke
+ sp_object_properties_fill();
+ } else if (event->button == 3) { // right-click, popup menu
+ _popup[SS_FILL].popup(event->button, event->time);
+ } else if (event->button == 2) { // middle click, toggle none/lastcolor
+ if (_mode[SS_FILL] == SS_NONE) {
+ on_fill_lastused();
+ } else {
+ on_fill_remove();
+ }
+ }
+ return true;
+}
+
+bool
+SelectedStyle::on_stroke_click(GdkEventButton *event)
+{
+ if (event->button == 1) { // click, open fill&stroke
+ sp_object_properties_stroke();
+ } else if (event->button == 3) { // right-click, popup menu
+ _popup[SS_STROKE].popup(event->button, event->time);
+ } else if (event->button == 2) { // middle click, toggle none/lastcolor
+ if (_mode[SS_STROKE] == SS_NONE) {
+ on_stroke_lastused();
+ } else {
+ on_stroke_remove();
+ }
+ }
+ return true;
+}
+
+bool
+SelectedStyle::on_sw_click(GdkEventButton *event)
+{
+ if (event->button == 1) { // click, open fill&stroke
+ sp_object_properties_stroke_style ();
+ } else if (event->button == 3) { // right-click, popup menu
+ _popup_sw.popup(event->button, event->time);
+ } else if (event->button == 2) { // middle click, toggle none/lastwidth?
+ //
+ }
+ return true;
+}
+
+bool
+SelectedStyle::on_opacity_click(GdkEventButton *event)
+{
+ if (event->button == 2) { // middle click
+ const char* opacity = _opacity_sb.get_value() < 0.5? "0.5" : (_opacity_sb.get_value() == 1? "0" : "1");
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "opacity", opacity);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT (_desktop));
+ return true;
+ }
+
+ return false;
+}
+
+void SelectedStyle::on_popup_px() {
+ _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_PX));
+ update();
+}
+void SelectedStyle::on_popup_pt() {
+ _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_PT));
+ update();
+}
+void SelectedStyle::on_popup_mm() {
+ _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_MM));
+ update();
+}
+
+void SelectedStyle::on_popup_preset(int i) {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gdouble w;
+ if (_sw_unit) {
+ w = sp_units_get_pixels (_sw_presets[i], *_sw_unit);
+ } else {
+ w = _sw_presets[i];
+ }
+ Inkscape::CSSOStringStream os;
+ os << w;
+ sp_repr_css_set_property (css, "stroke-width", os.str().c_str());
+ sp_desktop_set_style (_desktop, css, true);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void
+SelectedStyle::update()
+{
+ if (_desktop == NULL)
+ return;
+
+ // create temporary style
+ SPStyle *query = sp_style_new ();
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ Gtk::EventBox *place = (i == SS_FILL)? &_fill_place : &_stroke_place;
+ Gtk::EventBox *flag_place = (i == SS_FILL)? &_fill_flag_place : &_stroke_flag_place;
+
+ place->remove();
+ flag_place->remove();
+
+ _tooltips.unset_tip(*place);
+ _tooltips.unset_tip(*flag_place);
+
+ _mode[i] = SS_NA;
+ _paintserver_id[i].clear();
+
+ _popup_copy[i].set_sensitive(false);
+
+ // query style from desktop. This returns a result flag and fills query with the style of subselection, if any, or selection
+ int result = sp_desktop_query_style (_desktop, query,
+ (i == SS_FILL)? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE);
+ switch (result) {
+ case QUERY_STYLE_NOTHING:
+ place->add(_na[i]);
+ _tooltips.set_tip(*place, __na[i]);
+ _mode[i] = SS_NA;
+ break;
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ SPIPaint *paint;
+ if (i == SS_FILL) {
+ paint = &(query->fill);
+ } else {
+ paint = &(query->stroke);
+ }
+ if (paint->set && paint->type == SP_PAINT_TYPE_COLOR) {
+ guint32 color = sp_color_get_rgba32_falpha (&(paint->value.color),
+ SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value));
+ _lastselected[i] = _thisselected[i];
+ _thisselected[i] = color | 0xff; // only color, opacity === 1
+ ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color);
+ _color_preview[i]->show_all();
+ place->add(*_color_preview[i]);
+ gchar c_string[64];
+ g_snprintf (c_string, 64, "%06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
+ _tooltips.set_tip(*place, __color[i] + ": " + c_string);
+ _mode[i] = SS_COLOR;
+ _popup_copy[i].set_sensitive(true);
+
+ } else if (paint->set && paint->type == SP_PAINT_TYPE_PAINTSERVER) {
+ SPPaintServer *server = (i == SS_FILL)? SP_STYLE_FILL_SERVER (query) : SP_STYLE_STROKE_SERVER (query);
+
+ Inkscape::XML::Node *srepr = SP_OBJECT_REPR(server);
+ _paintserver_id[i] += "url(#";
+ _paintserver_id[i] += srepr->attribute("id");
+ _paintserver_id[i] += ")";
+
+ if (SP_IS_LINEARGRADIENT (server)) {
+ place->add(_lgradient[i]);
+ _tooltips.set_tip(*place, __lgradient[i]);
+ _mode[i] = SS_LGRADIENT;
+ } else if (SP_IS_RADIALGRADIENT (server)) {
+ place->add(_rgradient[i]);
+ _tooltips.set_tip(*place, __rgradient[i]);
+ _mode[i] = SS_RGRADIENT;
+ } else if (SP_IS_PATTERN (server)) {
+ place->add(_pattern[i]);
+ _tooltips.set_tip(*place, __pattern[i]);
+ _mode[i] = SS_PATTERN;
+ }
+
+ } else if (paint->set && paint->type == SP_PAINT_TYPE_NONE) {
+ place->add(_none[i]);
+ _tooltips.set_tip(*place, __none[i]);
+ _mode[i] = SS_NONE;
+ } else if (!paint->set) {
+ place->add(_unset[i]);
+ _tooltips.set_tip(*place, __unset[i]);
+ _mode[i] = SS_UNSET;
+ }
+ if (result == QUERY_STYLE_MULTIPLE_AVERAGED) {
+ flag_place->add(_averaged[i]);
+ _tooltips.set_tip(*flag_place, __averaged[i]);
+ } else if (result == QUERY_STYLE_MULTIPLE_SAME) {
+ flag_place->add(_multiple[i]);
+ _tooltips.set_tip(*flag_place, __multiple[i]);
+ }
+ break;
+ case QUERY_STYLE_MULTIPLE_DIFFERENT:
+ place->add(_many[i]);
+ _tooltips.set_tip(*place, __many[i]);
+ _mode[i] = SS_MANY;
+ break;
+ default:
+ break;
+ }
+ }
+
+// Now query opacity
+ _tooltips.unset_tip(_opacity_place);
+
+ int result = sp_desktop_query_style (_desktop, query, QUERY_STYLE_PROPERTY_MASTEROPACITY);
+
+ switch (result) {
+ case QUERY_STYLE_NOTHING:
+ _tooltips.set_tip(_opacity_place, _("Nothing selected"));
+ _opacity_sb.set_sensitive(false);
+ break;
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ _tooltips.set_tip(_opacity_place, _("Master opacity"));
+ _opacity_blocked = true;
+ _opacity_sb.set_sensitive(true);
+ _opacity_adjustment.set_value(SP_SCALE24_TO_FLOAT(query->opacity.value));
+ _opacity_blocked = false;
+ break;
+ }
+
+// Now query stroke_width
+ int result_sw = sp_desktop_query_style (_desktop, query, QUERY_STYLE_PROPERTY_STROKEWIDTH);
+ switch (result_sw) {
+ case QUERY_STYLE_NOTHING:
+ _stroke_width.set_markup("");
+ break;
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ {
+ double w;
+ if (_sw_unit) {
+ w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit);
+ } else {
+ w = query->stroke_width.computed;
+ }
+ {
+ gchar *str = g_strdup_printf(" %.3g", w);
+ _stroke_width.set_markup(str);
+ g_free (str);
+ }
+ {
+ gchar *str = g_strdup_printf(_("Stroke width: %.5g%s%s"),
+ w,
+ _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px",
+ (result_sw == QUERY_STYLE_MULTIPLE_AVERAGED)?
+ _(" (averaged)") : "");
+ _tooltips.set_tip(_stroke_width_place, str);
+ g_free (str);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ g_free (query);
+}
+
+void SelectedStyle::opacity_0(void) {_opacity_sb.set_value(0);}
+void SelectedStyle::opacity_025(void) {_opacity_sb.set_value(0.25);}
+void SelectedStyle::opacity_05(void) {_opacity_sb.set_value(0.5);}
+void SelectedStyle::opacity_075(void) {_opacity_sb.set_value(0.75);}
+void SelectedStyle::opacity_1(void) {_opacity_sb.set_value(1.0);}
+
+void SelectedStyle::on_opacity_menu (Gtk::Menu *menu) {
+
+ Glib::ListHandle<Gtk::Widget *> children = menu->get_children();
+ for (Glib::ListHandle<Gtk::Widget *>::iterator iter = children.begin(); iter != children.end(); iter++) {
+ menu->remove(*(*iter));
+ }
+
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label(_("0 (transparent)"), 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_0 ));
+ menu->add(*item);
+ }
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label("0.25", 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_025 ));
+ menu->add(*item);
+ }
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label("0.5", 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_05 ));
+ menu->add(*item);
+ }
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label("0.75", 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_075 ));
+ menu->add(*item);
+ }
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label(_("1.0 (opaque)"), 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_1 ));
+ menu->add(*item);
+ }
+
+ menu->show_all();
+}
+
+void SelectedStyle::on_opacity_changed () {
+ if (_opacity_blocked)
+ return;
+ _opacity_blocked = true;
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ Inkscape::CSSOStringStream os;
+ os << CLAMP (_opacity_adjustment.get_value(), 0.0, 1.0);
+ sp_repr_css_set_property (css, "opacity", os.str().c_str());
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_maybe_done (SP_DT_DOCUMENT (_desktop), "fillstroke:opacity");
+ spinbutton_defocus(GTK_OBJECT(_opacity_sb.gobj()));
+ _opacity_blocked = false;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/selected-style.h b/src/ui/widget/selected-style.h
new file mode 100644
index 000000000..8f9c0fbf6
--- /dev/null
+++ b/src/ui/widget/selected-style.h
@@ -0,0 +1,212 @@
+/**
+ * \brief Selected style indicator (fill, stroke, opacity)
+ *
+ * Authors:
+ * buliabyak@gmail.com
+ * scislac@users.sf.net
+ *
+ * Copyright (C) 2005 authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_CURRENT_STYLE_H
+#define INKSCAPE_UI_CURRENT_STYLE_H
+
+#include <gtkmm/table.h>
+#include <gtkmm/label.h>
+#include <gtkmm/box.h>
+#include <gtkmm/eventbox.h>
+#include <gtkmm/enums.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/menuitem.h>
+#include <gtkmm/adjustment.h>
+#include <gtkmm/spinbutton.h>
+
+#include <sigc++/sigc++.h>
+
+#include <glibmm/i18n.h>
+
+#include <desktop.h>
+
+#include "button.h"
+
+class SPUnit;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+enum {
+ SS_NA,
+ SS_NONE,
+ SS_UNSET,
+ SS_PATTERN,
+ SS_LGRADIENT,
+ SS_RGRADIENT,
+ SS_MANY,
+ SS_COLOR
+};
+
+enum {
+ SS_FILL,
+ SS_STROKE
+};
+
+class SelectedStyle : public Gtk::HBox
+{
+public:
+ SelectedStyle(bool layout = true);
+
+ ~SelectedStyle();
+
+ void setDesktop(SPDesktop *desktop);
+ void update();
+
+protected:
+ SPDesktop *_desktop;
+
+ Gtk::Table _table;
+
+ Gtk::Label _fill_label;
+ Gtk::Label _stroke_label;
+ Gtk::Label _opacity_label;
+
+ Gtk::EventBox _fill_place;
+ Gtk::EventBox _stroke_place;
+
+ Gtk::EventBox _fill_flag_place;
+ Gtk::EventBox _stroke_flag_place;
+
+ Gtk::EventBox _opacity_place;
+ Gtk::Adjustment _opacity_adjustment;
+ Gtk::SpinButton _opacity_sb;
+
+ Gtk::Label _na[2];
+ Glib::ustring __na[2];
+
+ Gtk::Label _none[2];
+ Glib::ustring __none[2];
+
+ Gtk::Label _pattern[2];
+ Glib::ustring __pattern[2];
+
+ Gtk::Label _lgradient[2];
+ Glib::ustring __lgradient[2];
+
+ Gtk::Label _rgradient[2];
+ Glib::ustring __rgradient[2];
+
+ Gtk::Label _many[2];
+ Glib::ustring __many[2];
+
+ Gtk::Label _unset[2];
+ Glib::ustring __unset[2];
+
+ Gtk::Widget *_color_preview[2];
+ Glib::ustring __color[2];
+
+ Gtk::Label _averaged[2];
+ Glib::ustring __averaged[2];
+ Gtk::Label _multiple[2];
+ Glib::ustring __multiple[2];
+
+ Gtk::HBox _stroke;
+ Gtk::EventBox _stroke_width_place;
+ Gtk::Label _stroke_width;
+
+ guint32 _lastselected[2];
+ guint32 _thisselected[2];
+ Glib::ustring _paintserver_id[2];
+
+ guint _mode[2];
+
+ sigc::connection *selection_changed_connection;
+ sigc::connection *selection_modified_connection;
+ sigc::connection *subselection_changed_connection;
+
+ bool on_fill_click(GdkEventButton *event);
+ bool on_stroke_click(GdkEventButton *event);
+ bool on_opacity_click(GdkEventButton *event);
+ bool on_sw_click(GdkEventButton *event);
+
+ bool _opacity_blocked;
+ void on_opacity_changed();
+ void on_opacity_menu(Gtk::Menu *menu);
+ void opacity_0();
+ void opacity_025();
+ void opacity_05();
+ void opacity_075();
+ void opacity_1();
+
+ void on_fill_remove();
+ void on_stroke_remove();
+ void on_fill_lastused();
+ void on_stroke_lastused();
+ void on_fill_lastselected();
+ void on_stroke_lastselected();
+ void on_fill_unset();
+ void on_stroke_unset();
+ void on_fill_edit();
+ void on_stroke_edit();
+ void on_fillstroke_swap();
+ void on_fill_invert();
+ void on_stroke_invert();
+ void on_fill_white();
+ void on_stroke_white();
+ void on_fill_black();
+ void on_stroke_black();
+ void on_fill_copy();
+ void on_stroke_copy();
+ void on_fill_paste();
+ void on_stroke_paste();
+ void on_fill_opaque();
+ void on_stroke_opaque();
+
+ Gtk::Menu _popup[2];
+ Gtk::MenuItem _popup_edit[2];
+ Gtk::MenuItem _popup_lastused[2];
+ Gtk::MenuItem _popup_lastselected[2];
+ Gtk::MenuItem _popup_invert[2];
+ Gtk::MenuItem _popup_white[2];
+ Gtk::MenuItem _popup_black[2];
+ Gtk::MenuItem _popup_copy[2];
+ Gtk::MenuItem _popup_paste[2];
+ Gtk::MenuItem _popup_swap[2];
+ Gtk::MenuItem _popup_opaque[2];
+ Gtk::MenuItem _popup_unset[2];
+ Gtk::MenuItem _popup_remove[2];
+
+ Gtk::Menu _popup_sw;
+ Gtk::RadioButtonGroup _sw_group;
+ Gtk::RadioMenuItem _popup_px;
+ void on_popup_px();
+ Gtk::RadioMenuItem _popup_pt;
+ void on_popup_pt();
+ Gtk::RadioMenuItem _popup_mm;
+ void on_popup_mm();
+ void on_popup_preset(int i);
+ Gtk::MenuItem _popup_sw_remove;
+
+ SPUnit *_sw_unit;
+
+ Gtk::Tooltips _tooltips;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_BUTTON_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp
new file mode 100644
index 000000000..5d4623c19
--- /dev/null
+++ b/src/ui/widget/style-swatch.cpp
@@ -0,0 +1,244 @@
+/**
+ * \brief Static style swatch (fill, stroke, opacity)
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "style-swatch.h"
+
+#include "widgets/spw-utilities.h"
+#include "ui/widget/color-preview.h"
+
+#include "style.h"
+#include "sp-linear-gradient-fns.h"
+#include "sp-radial-gradient-fns.h"
+#include "sp-pattern.h"
+#include "xml/repr.h"
+#include "widgets/widget-sizes.h"
+#include "helper/units.h"
+
+enum {
+ SS_FILL,
+ SS_STROKE
+};
+
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+StyleSwatch::StyleSwatch(SPCSSAttr *css)
+ : _css (NULL),
+
+ _table(2, 6),
+
+ _sw_unit(NULL),
+
+ _tooltips ()
+{
+ _label[SS_FILL].set_markup(_("F:"));
+ _label[SS_STROKE].set_markup(_("S:"));
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ _label[i].set_alignment(0.0, 0.5);
+ _label[i].set_padding(0, 0);
+
+ _color_preview[i] = new Inkscape::UI::Widget::ColorPreview (0);
+ }
+
+ _opacity_value.set_alignment(0.0, 0.5);
+ _opacity_value.set_padding(0, 0);
+
+ _table.set_col_spacings (2);
+ _table.set_row_spacings (0);
+
+ _stroke.pack_start(_place[SS_STROKE]);
+ _stroke_width_place.add(_stroke_width);
+ _stroke.pack_start(_stroke_width_place, Gtk::PACK_SHRINK);
+
+ _table.attach(_label[SS_FILL], 0,1, 0,1, Gtk::SHRINK, Gtk::SHRINK);
+ _table.attach(_label[SS_STROKE], 0,1, 1,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ _table.attach(_place[SS_FILL], 1,2, 0,1);
+ _table.attach(_stroke, 1,2, 1,2);
+
+ _opacity_place.add(_opacity_value);
+ _table.attach(_opacity_place, 2,3, 0,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ pack_start(_table, true, true, 0);
+
+ set_size_request (STYLE_SWATCH_WIDTH, -1);
+
+ sp_set_font_size_smaller (GTK_WIDGET(_opacity_value.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_width.gobj()));
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ sp_set_font_size_smaller (GTK_WIDGET(_value[i].gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_place[i].gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_label[i].gobj()));
+ }
+
+ setStyle (css);
+}
+
+StyleSwatch::~StyleSwatch()
+{
+ if (_css)
+ sp_repr_css_attr_unref (_css);
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ delete _color_preview[i];
+ }
+}
+
+void
+StyleSwatch::setStyle(SPCSSAttr *css)
+{
+ if (_css)
+ sp_repr_css_attr_unref (_css);
+ _css = sp_repr_css_attr_new();
+ sp_repr_css_merge(_css, css);
+
+ gchar const *css_string = sp_repr_css_write_string (_css);
+ SPStyle *temp_spstyle = sp_style_new();
+ sp_style_merge_from_style_string (temp_spstyle, css_string);
+
+ setStyle (temp_spstyle);
+
+ sp_style_unref (temp_spstyle);
+}
+
+void
+StyleSwatch::setStyle(SPStyle *query)
+{
+ _place[SS_FILL].remove();
+ _place[SS_STROKE].remove();
+
+ bool has_stroke = true;
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ Gtk::EventBox *place = &(_place[i]);
+
+ SPIPaint *paint;
+ if (i == SS_FILL) {
+ paint = &(query->fill);
+ } else {
+ paint = &(query->stroke);
+ }
+
+ if (paint->set && paint->type == SP_PAINT_TYPE_COLOR) {
+ guint32 color = sp_color_get_rgba32_falpha (&(paint->value.color),
+ SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value));
+ ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color);
+ _color_preview[i]->show_all();
+ place->add(*_color_preview[i]);
+ gchar *tip;
+ if (i == SS_FILL) {
+ tip = g_strdup_printf ("Fill: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
+ } else {
+ tip = g_strdup_printf ("Stroke: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
+ }
+ _tooltips.set_tip(*place, tip);
+ g_free (tip);
+ } else if (paint->set && paint->type == SP_PAINT_TYPE_PAINTSERVER) {
+ SPPaintServer *server = (i == SS_FILL)? SP_STYLE_FILL_SERVER (query) : SP_STYLE_STROKE_SERVER (query);
+
+ if (SP_IS_LINEARGRADIENT (server)) {
+ _value[i].set_markup(_("L Gradient"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("Linear gradient fill")) : (_("Linear gradient stroke")));
+ } else if (SP_IS_RADIALGRADIENT (server)) {
+ _value[i].set_markup(_("R Gradient"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("Radial gradient fill")) : (_("Radial gradient stroke")));
+ } else if (SP_IS_PATTERN (server)) {
+ _value[i].set_markup(_("Pattern"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("Pattern fill")) : (_("Pattern stroke")));
+ }
+
+ } else if (paint->set && paint->type == SP_PAINT_TYPE_NONE) {
+ _value[i].set_markup(_("None"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("No fill")) : (_("No stroke")));
+ if (i == SS_STROKE) has_stroke = false;
+ } else if (!paint->set) {
+ _value[i].set_markup(_("Unset"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("Unset fill")) : (_("Unset stroke")));
+ if (i == SS_STROKE) has_stroke = false;
+ }
+ }
+
+// Now query stroke_width
+ if (has_stroke) {
+ double w;
+ if (_sw_unit) {
+ w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit);
+ } else {
+ w = query->stroke_width.computed;
+ }
+
+ {
+ gchar *str = g_strdup_printf(" %.3g", w);
+ _stroke_width.set_markup(str);
+ g_free (str);
+ }
+ {
+ gchar *str = g_strdup_printf(_("Stroke width: %.5g%s"),
+ w,
+ _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px");
+ _tooltips.set_tip(_stroke_width_place, str);
+ g_free (str);
+ }
+ } else {
+ _tooltips.unset_tip(_stroke_width_place);
+ _stroke_width.set_markup ("");
+ }
+
+ gdouble op = SP_SCALE24_TO_FLOAT(query->opacity.value);
+ if (op != 1) {
+ {
+ gchar *str;
+ if (op == 0)
+ str = g_strdup_printf(_("0:%.3g"), op);
+ else
+ str = g_strdup_printf(_("0:.%d"), (int) (op*10));
+ _opacity_value.set_markup (str);
+ g_free (str);
+ }
+ {
+ gchar *str = g_strdup_printf(_("Opacity: %.3g"), op);
+ _tooltips.set_tip(_opacity_place, str);
+ g_free (str);
+ }
+ } else {
+ _tooltips.unset_tip(_opacity_place);
+ _opacity_value.set_markup ("");
+ }
+
+ show_all();
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/style-swatch.h b/src/ui/widget/style-swatch.h
new file mode 100644
index 000000000..d78b3d64e
--- /dev/null
+++ b/src/ui/widget/style-swatch.h
@@ -0,0 +1,88 @@
+/**
+ * \brief Static style swatch (fill, stroke, opacity)
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_CURRENT_STYLE_H
+#define INKSCAPE_UI_CURRENT_STYLE_H
+
+#include <gtkmm/table.h>
+#include <gtkmm/label.h>
+#include <gtkmm/box.h>
+#include <gtkmm/eventbox.h>
+#include <gtkmm/enums.h>
+
+#include <glibmm/i18n.h>
+
+#include <desktop.h>
+
+#include "button.h"
+
+class SPUnit;
+class SPStyle;
+class SPCSSAttr;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class StyleSwatch : public Gtk::HBox
+{
+public:
+ StyleSwatch (SPStyle *style);
+ StyleSwatch (SPCSSAttr *attr);
+
+ ~StyleSwatch();
+
+ void setStyle(SPStyle *style);
+ void setStyle(SPCSSAttr *attr);
+ SPCSSAttr *getStyle();
+
+protected:
+ SPCSSAttr *_css;
+
+ Gtk::Table _table;
+
+ Gtk::Label _label[2];
+
+ Gtk::EventBox _place[2];
+ Gtk::EventBox _opacity_place;
+
+ Gtk::Label _value[2];
+ Gtk::Label _opacity_value;
+
+ Gtk::Widget *_color_preview[2];
+ Glib::ustring __color[2];
+
+ Gtk::HBox _stroke;
+ Gtk::EventBox _stroke_width_place;
+ Gtk::Label _stroke_width;
+
+ SPUnit *_sw_unit;
+
+ Gtk::Tooltips _tooltips;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_BUTTON_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/svg-canvas.cpp b/src/ui/widget/svg-canvas.cpp
new file mode 100644
index 000000000..1ba49b7ec
--- /dev/null
+++ b/src/ui/widget/svg-canvas.cpp
@@ -0,0 +1,92 @@
+/** \file
+ * Gtkmm facade/wrapper around SPCanvas.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 The Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/widget.h>
+#include "desktop.h"
+#include "desktop-events.h"
+#include "display/canvas-arena.h"
+#include "display/display-forward.h"
+#include "ui/widget/svg-canvas.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+SVGCanvas::SVGCanvas()
+{
+ void *canvas = gtk_type_new (sp_canvas_get_type ());
+ _spcanvas = static_cast<SPCanvas*>(canvas);
+ _widget = Glib::wrap (static_cast<GtkWidget*> (canvas));
+ _dt = 0;
+}
+
+SVGCanvas::~SVGCanvas()
+{
+}
+
+void
+SVGCanvas::init (SPDesktop *dt)
+{
+ _dt = dt;
+ _widget->set_flags(Gtk::CAN_FOCUS);
+
+ // Set background to white
+ Glib::RefPtr<Gtk::Style> style = _widget->get_style();
+ style->set_bg(Gtk::STATE_NORMAL, style->get_white());
+ _widget->set_style(style);
+ _widget->set_extension_events(Gdk::EXTENSION_EVENTS_ALL);
+ _widget->signal_event().connect(sigc::mem_fun(*this, &SVGCanvas::onEvent));
+}
+
+bool
+SVGCanvas::onEvent (GdkEvent * ev) const
+{
+ g_assert (_dt);
+
+ // Gdk::Event doesn't appear to be fully usable for this atm
+ if (ev->type == GDK_BUTTON_PRESS) {
+ // defocus any spinbuttons
+ _widget->grab_focus();
+ }
+
+ if ((ev->type == GDK_BUTTON_PRESS) && (ev->button.button == 3)) {
+ if (ev->button.state & GDK_SHIFT_MASK) {
+ sp_canvas_arena_set_sticky(SP_CANVAS_ARENA(_dt->drawing), true);
+ } else {
+ sp_canvas_arena_set_sticky(SP_CANVAS_ARENA(_dt->drawing), false);
+ }
+ }
+
+ // The keypress events need to be passed to desktop handler explicitly,
+ // because otherwise the event contexts only receive keypresses when the mouse cursor
+ // is over the canvas. This redirection is only done for keypresses and only if there's no
+ // current item on the canvas, because item events and all mouse events are caught
+ // and passed on by the canvas acetate (I think). --bb
+
+ if (ev->type == GDK_KEY_PRESS && !_spcanvas->current_item) {
+ return sp_desktop_root_handler(0, ev, _dt);
+ }
+
+ return false;
+}
+
+}}}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/svg-canvas.h b/src/ui/widget/svg-canvas.h
new file mode 100644
index 000000000..cb8dc4013
--- /dev/null
+++ b/src/ui/widget/svg-canvas.h
@@ -0,0 +1,56 @@
+#ifndef __UI_WIDGET_SVGCANVAS_H__
+#define __UI_WIDGET_SVGCANVAS_H__
+
+/** \file
+ * Gtkmm facade/wrapper around SPCanvas.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 The Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+struct SPCanvas;
+struct SPDesktop;
+namespace Gtk { class Widget; }
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class SVGCanvas
+{
+public:
+ SVGCanvas();
+ ~SVGCanvas();
+ void init (SPDesktop*);
+ Gtk::Widget& widget() const { return *_widget; }
+ SPCanvas* spobj() const { return _spcanvas; }
+
+protected:
+ Gtk::Widget *_widget;
+ SPCanvas *_spcanvas;
+ SPDesktop *_dt;
+
+ bool onEvent (GdkEvent *) const;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#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 :
diff --git a/src/ui/widget/tolerance-slider.cpp b/src/ui/widget/tolerance-slider.cpp
new file mode 100644
index 000000000..dbef74eaf
--- /dev/null
+++ b/src/ui/widget/tolerance-slider.cpp
@@ -0,0 +1,142 @@
+/** \file
+ *
+ Implementation of tolerance slider widget.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/box.h>
+#include <gtkmm/label.h>
+#include <gtkmm/scale.h>
+
+#include "xml/repr.h"
+#include "svg/stringstream.h"
+
+#include "inkscape.h"
+#include "document.h"
+#include "desktop-handles.h"
+#include "sp-namedview.h"
+
+#include "registry.h"
+#include "tolerance-slider.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+//---------------------------------------------------
+
+
+
+//====================================================
+
+ToleranceSlider::ToleranceSlider()
+: _hbox(0)
+{
+}
+
+ToleranceSlider::~ToleranceSlider()
+{
+ if (_hbox) delete _hbox;
+ _scale_changed_connection.disconnect();
+}
+
+void
+ToleranceSlider::init (const Glib::ustring& label1, const Glib::ustring& label2, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr)
+{
+ _hbox = new Gtk::HBox;
+ Gtk::Label *theLabel1 = manage (new Gtk::Label (label1));
+ _hbox->add (*theLabel1);
+ _hscale = manage (new Gtk::HScale (0.4, 50.1, 0.1));
+ _hscale->set_draw_value (true);
+ _hscale->set_value_pos (Gtk::POS_RIGHT);
+ _hscale->set_size_request (100, -1);
+ _hbox->add (*_hscale);
+ Gtk::Label *theLabel2 = manage (new Gtk::Label (label2));
+ _hbox->add (*theLabel2);
+ _key = key;
+ _scale_changed_connection = _hscale->signal_value_changed().connect (sigc::mem_fun (*this, &ToleranceSlider::update));
+ _wr = &wr;
+}
+
+void
+ToleranceSlider::setValue (double val, bool is_absolute)
+{
+ _hscale->set_value (val);
+ Gtk::Adjustment *adj = _hscale->get_adjustment();
+ if (is_absolute)
+ {
+ adj->set_lower (0.4);
+ adj->set_upper (50.1);
+ adj->set_step_increment (0.1);
+ }
+ else
+ {
+ adj->set_lower (1.0);
+ adj->set_upper (51.0);
+ adj->set_step_increment (1.0);
+ }
+ update();
+}
+
+void
+ToleranceSlider::setLimits (double theMin, double theMax)
+{
+ _hscale->set_range (theMin, theMax);
+ _hscale->get_adjustment()->set_step_increment (1);
+}
+
+void
+ToleranceSlider::update()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt)
+ return;
+
+ Inkscape::SVGOStringStream os;
+ os << _hscale->get_value();
+
+ _wr->setUpdating (true);
+
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ repr->setAttribute(_key.c_str(), os.str().c_str());
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/tolerance-slider.h b/src/ui/widget/tolerance-slider.h
new file mode 100644
index 000000000..2eeacb403
--- /dev/null
+++ b/src/ui/widget/tolerance-slider.h
@@ -0,0 +1,61 @@
+/** \file
+ * \brief
+ *
+ * This widget is part of the Document properties dialog.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_TOLERANCE_SLIDER__H_
+#define INKSCAPE_UI_WIDGET_TOLERANCE_SLIDER__H_
+
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Registry;
+class ToleranceSlider {
+public:
+ ToleranceSlider();
+ ~ToleranceSlider();
+ void init (const Glib::ustring& label1,
+ const Glib::ustring& label2,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Registry& wr);
+ void setValue (double, bool);
+ void setLimits (double, double);
+ Gtk::HBox* _hbox;
+
+protected:
+ void on_scale_changed();
+ void update();
+ sigc::connection _scale_changed_connection;
+ Gtk::HScale *_hscale;
+ Registry *_wr;
+ Glib::ustring _key;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_TOLERANCE_SLIDER__H_
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/toolbox.cpp b/src/ui/widget/toolbox.cpp
new file mode 100644
index 000000000..e90a58b6e
--- /dev/null
+++ b/src/ui/widget/toolbox.cpp
@@ -0,0 +1,269 @@
+/**
+ * \brief Toolbox Widget - A detachable toolbar for buttons and other widgets.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/radioaction.h>
+#include <gtk/gtkmain.h>
+#include "ui/widget/toolbox.h"
+#include "path-prefix.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+Toolbox::Toolbox(Gtk::Toolbar *toolbar,
+ Gtk::Orientation orientation)
+ : HandleBox(toolbar)
+{
+ init_actions();
+ init_orientation(orientation);
+ init_style(toolbar->get_toolbar_style());
+}
+
+Toolbox::Toolbox(Gtk::Toolbar *toolbar,
+ Gtk::ToolbarStyle style,
+ Gtk::Orientation orientation)
+ : HandleBox(toolbar)
+{
+ init_actions();
+ init_orientation(orientation);
+ init_style(style);
+}
+
+Gtk::Toolbar&
+Toolbox::get_toolbar()
+{
+ return static_cast<Gtk::Toolbar&>(*_widget);
+}
+
+static Glib::ustring
+get_uidir_filename(char const *basename_utf8)
+{
+ char *const ret_str = g_build_filename(INKSCAPE_UIDIR, basename_utf8, NULL);
+ Glib::ustring const ret(ret_str);
+ g_free(ret_str);
+ return ret;
+}
+
+void
+Toolbox::init_actions()
+{
+ _action_grp = Gtk::ActionGroup::create();
+
+ Gtk::RadioAction::Group icons;
+ _action_grp->add(Gtk::RadioAction::create(icons, "Icons", "Icons Only"),
+ sigc::mem_fun(*this, &Toolbox::on_change_style_icons));
+ _action_grp->add(Gtk::RadioAction::create(icons, "Text", "Text Only"),
+ sigc::mem_fun(*this, &Toolbox::on_change_style_text));
+ _action_grp->add(Gtk::RadioAction::create(icons, "Both", "Text Below Icons"),
+ sigc::mem_fun(*this, &Toolbox::on_change_style_both));
+ _action_grp->add(Gtk::RadioAction::create(icons, "BothHoriz", "Text Beside Icons"),
+ sigc::mem_fun(*this, &Toolbox::on_change_style_both_horiz));
+
+ _detach_grp = Gtk::ActionGroup::create();
+
+ Gtk::RadioAction::Group orient;
+ _detach_grp->add(Gtk::RadioAction::create(orient, "OrientHoriz", "Horizontal"),
+ sigc::mem_fun(*this, &Toolbox::on_change_orient_horiz));
+ _detach_grp->add(Gtk::RadioAction::create(orient, "OrientVert", "Vertical"),
+ sigc::mem_fun(*this, &Toolbox::on_change_orient_vert));
+
+ _detach_grp->add(Gtk::ToggleAction::create("ShowArrow", "Show Arrow",
+ Glib::ustring(), true),
+ sigc::mem_fun(*this, &Toolbox::on_show_arrow));
+
+ _ui_mgr = Gtk::UIManager::create();
+ _ui_mgr->insert_action_group(_action_grp);
+ _ui_mgr->insert_action_group(_detach_grp);
+ _ui_mgr->add_ui_from_file(get_uidir_filename("toolbox.xml"));
+
+ _context_menu = static_cast<Gtk::Menu*>(_ui_mgr->get_widget("/ToolboxMenu"));
+
+ static_cast<Gtk::Toolbar*>(_widget)->signal_popup_context_menu()
+ .connect(sigc::mem_fun(*this, &Toolbox::on_popup_context_menu));
+
+ _detach_grp->set_sensitive(false);
+}
+
+void
+Toolbox::init_orientation(Gtk::Orientation const &orientation)
+{
+ static_cast<Gtk::Toolbar*>(_widget)->set_orientation(orientation);
+ if (orientation == Gtk::ORIENTATION_VERTICAL) {
+ set_handle_position(Gtk::POS_TOP);
+ }
+ switch (orientation) {
+ case Gtk::ORIENTATION_HORIZONTAL: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientHoriz"))
+ ->set_active();
+ break;
+ }
+ case Gtk::ORIENTATION_VERTICAL: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientVert"))
+ ->set_active();
+ break;
+ }
+ }
+}
+
+void
+Toolbox::init_style(Gtk::ToolbarStyle const &style)
+{
+ switch (style) {
+ case Gtk::TOOLBAR_ICONS: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Icons"))
+ ->activate();
+ break;
+ }
+ case Gtk::TOOLBAR_TEXT: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Text"))
+ ->activate();
+ break;
+ }
+ case Gtk::TOOLBAR_BOTH: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Both"))
+ ->activate();
+ break;
+ }
+ case Gtk::TOOLBAR_BOTH_HORIZ: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("BothHoriz"))
+ ->activate();
+ break;
+ }
+ }
+}
+
+bool
+Toolbox::on_popup_context_menu(int x, int y, int button)
+{
+ (void)x;
+ (void)y;
+ _context_menu->popup(button, gtk_get_current_event_time());
+ return true;
+}
+
+void
+Toolbox::on_child_attached(Gtk::Widget *widget)
+{
+ (void)widget;
+ Gtk::Toolbar *toolbar = static_cast<Gtk::Toolbar*>(_widget);
+
+ if (!(toolbar->get_show_arrow())) {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("ShowArrow"))
+ ->activate();
+ }
+
+ if (get_handle_position() == Gtk::POS_LEFT
+ && toolbar->get_orientation() != Gtk::ORIENTATION_HORIZONTAL) {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientHoriz"))
+ ->activate();
+ } else if (get_handle_position() == Gtk::POS_TOP
+ && toolbar->get_orientation() != Gtk::ORIENTATION_VERTICAL) {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientVert"))
+ ->activate();
+ }
+
+ _detach_grp->set_sensitive(false);
+}
+
+void
+Toolbox::on_child_detached(Gtk::Widget *widget)
+{
+ (void)widget;
+ _detach_grp->set_sensitive(true);
+
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("ShowArrow"))
+ ->set_active(false);
+}
+
+void
+Toolbox::on_change_style_icons()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Icons"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_ICONS);
+ }
+}
+
+void
+Toolbox::on_change_style_text()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Text"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_TEXT);
+ }
+}
+
+void
+Toolbox::on_change_style_both()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Both"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_BOTH);
+ }
+}
+
+void
+Toolbox::on_change_style_both_horiz()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("BothHoriz"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_BOTH_HORIZ);
+ }
+}
+
+void
+Toolbox::on_change_orient_horiz()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientHoriz"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
+ }
+}
+
+void
+Toolbox::on_change_orient_vert()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientVert"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_orientation(Gtk::ORIENTATION_VERTICAL);
+ }
+}
+
+void
+Toolbox::on_show_arrow()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("ShowArrow"));
+ Gtk::Toolbar *toolbar = static_cast<Gtk::Toolbar*>(_widget);
+ if (action->get_active()) {
+ toolbar->set_show_arrow(true);
+ } else {
+ toolbar->set_show_arrow(false);
+ }
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/toolbox.h b/src/ui/widget/toolbox.h
new file mode 100644
index 000000000..9c4e18909
--- /dev/null
+++ b/src/ui/widget/toolbox.h
@@ -0,0 +1,73 @@
+/**
+ * \brief Toolbox Widget - A detachable toolbar for buttons and other widgets.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_TOOLBOX_H
+#define INKSCAPE_UI_WIDGET_TOOLBOX_H
+
+#include <gtkmm/toolbar.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/action.h>
+#include <gtkmm/uimanager.h>
+#include "handlebox.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Toolbox : public HandleBox
+{
+public:
+ Toolbox(Gtk::Toolbar *toolbar,
+ Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL);
+ Toolbox(Gtk::Toolbar *toolbar,
+ Gtk::ToolbarStyle style,
+ Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL);
+
+ Gtk::Toolbar& get_toolbar();
+
+protected:
+ Gtk::Menu *_context_menu;
+
+ Glib::RefPtr<Gtk::ActionGroup> _action_grp;
+ Glib::RefPtr<Gtk::ActionGroup> _detach_grp;
+ Glib::RefPtr<Gtk::UIManager> _ui_mgr;
+
+ void init_actions();
+ void init_orientation(Gtk::Orientation const &orientation);
+ void init_style(Gtk::ToolbarStyle const &style);
+ bool on_popup_context_menu(int x, int y, int button);
+ void on_child_attached(Gtk::Widget *widget);
+ void on_child_detached(Gtk::Widget *widget);
+ void on_change_style_icons();
+ void on_change_style_text();
+ void on_change_style_both();
+ void on_change_style_both_horiz();
+ void on_change_orient_horiz();
+ void on_change_orient_vert();
+ void on_show_arrow();
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_TOOLBOX_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/unit-menu.cpp b/src/ui/widget/unit-menu.cpp
new file mode 100644
index 000000000..b4271762c
--- /dev/null
+++ b/src/ui/widget/unit-menu.cpp
@@ -0,0 +1,181 @@
+/**
+ * \brief Unit Menu Widget - A drop down menu for choosing unit types.
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <cmath>
+
+#include "unit-menu.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a UnitMenu
+ *
+ */
+UnitMenu::UnitMenu() : _type(UNIT_TYPE_NONE)
+{
+ set_active(0);
+}
+
+UnitMenu::~UnitMenu() {
+}
+
+/** Adds the unit type to the widget. This extracts the corresponding
+ units from the unit map matching the given type, and appends them
+ to the dropdown widget. It causes the primary unit for the given
+ unit_type to be selected. */
+bool
+UnitMenu::setUnitType(UnitType unit_type)
+{
+ /* Expand the unit widget with unit entries from the unit table */
+ UnitTable::UnitMap m = _unit_table.units(unit_type);
+ UnitTable::UnitMap::iterator iter = m.begin();
+ while(iter != m.end()) {
+ Glib::ustring text = (*iter).first;
+ append_text(text);
+ ++iter;
+ }
+ _type = unit_type;
+ set_active_text(_unit_table.primary(unit_type));
+
+ return true;
+}
+
+/** Returns the Unit object corresponding to the current selection
+ in the dropdown widget */
+Unit
+UnitMenu::getUnit() const {
+ if (get_active_text() == "") {
+ g_assert(_type != UNIT_TYPE_NONE);
+ return _unit_table.getUnit(_unit_table.primary(_type));
+ }
+ return _unit_table.getUnit(get_active_text());
+}
+
+/** Sets the dropdown widget to the given unit abbreviation.
+ Returns true if the unit was selectable, false if not
+ (i.e., if the unit was not present in the widget) */
+bool
+UnitMenu::setUnit(Glib::ustring const & unit) {
+ // TODO: Determine if 'unit' is available in the dropdown.
+ // If not, return false
+
+ set_active_text(unit);
+ return true;
+}
+
+/** Returns the abbreviated unit name of the selected unit */
+Glib::ustring
+UnitMenu::getUnitAbbr() const {
+ if (get_active_text() == "") {
+ return "";
+ }
+ return getUnit().abbr;
+}
+
+/** Returns the UnitType of the selected unit */
+UnitType
+UnitMenu::getUnitType() const {
+ return getUnit().type;
+}
+
+/** Returns the unit factor for the selected unit */
+double
+UnitMenu::getUnitFactor() const
+{
+ return getUnit().factor;
+}
+
+/** Returns the recommended number of digits for displaying
+ * numbers of this unit type.
+ */
+int
+UnitMenu::getDefaultDigits() const
+{
+ return getUnit().defaultDigits();
+}
+
+/** Returns the recommended step size in spin buttons
+ * displaying units of this type
+ */
+double
+UnitMenu::getDefaultStep() const
+{
+ int factor_digits = -1*int(log10(getUnit().factor));
+ return pow(10.0, factor_digits);
+}
+
+/** Returns the recommended page size (when hitting pgup/pgdn)
+ * in spin buttons displaying units of this type
+ */
+double
+UnitMenu::getDefaultPage() const
+{
+ return 10 * getDefaultStep();
+}
+
+/**
+ * Returns the conversion factor required to convert values
+ * of the currently selected unit into units of type
+ * new_unit_abbr.
+ */
+double
+UnitMenu::getConversion(Glib::ustring const &new_unit_abbr, Glib::ustring const &old_unit_abbr) const
+{
+ double old_factor = getUnit().factor;
+ if (old_unit_abbr != "no_unit")
+ old_factor = _unit_table.getUnit(old_unit_abbr).factor;
+ Unit new_unit = _unit_table.getUnit(new_unit_abbr);
+
+ // Catch the case of zero or negative unit factors (error!)
+ if (old_factor < 0.0000001 ||
+ new_unit.factor < 0.0000001) {
+ // TODO: Should we assert here?
+ return 0.00;
+ }
+
+ return old_factor / new_unit.factor;
+}
+
+/** Returns true if the selected unit is not dimensionless
+ * (false for %, true for px, pt, cm, etc)
+ */
+bool
+UnitMenu::isAbsolute() const {
+ return getUnitType() != UNIT_TYPE_DIMENSIONLESS;
+}
+
+/** Returns true if the selected unit is radial (deg or rad)
+ */
+bool
+UnitMenu::isRadial() const {
+ return getUnitType() == UNIT_TYPE_RADIAL;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/unit-menu.h b/src/ui/widget/unit-menu.h
new file mode 100644
index 000000000..60a9702b4
--- /dev/null
+++ b/src/ui/widget/unit-menu.h
@@ -0,0 +1,70 @@
+/**
+ * \brief Unit Menu Widget - A drop down menu for choosing unit types.
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_UNIT_H
+#define INKSCAPE_UI_WIDGET_UNIT_H
+
+#include "combo-text.h"
+#include "util/units.h"
+
+using namespace Inkscape::Util;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class UnitMenu : public ComboText
+{
+public:
+ UnitMenu();
+ virtual ~UnitMenu();
+
+ bool setUnitType(UnitType unit_type);
+
+ bool setUnit(Glib::ustring const &unit);
+
+ Unit getUnit() const;
+ Glib::ustring getUnitAbbr() const;
+ UnitType getUnitType() const;
+ double getUnitFactor() const;
+
+ int getDefaultDigits() const;
+ double getDefaultStep() const;
+ double getDefaultPage() const;
+
+ double getConversion(Glib::ustring const &new_unit_abbr, Glib::ustring const &old_unit_abbr = "no_unit") const;
+
+ bool isAbsolute() const;
+ bool isRadial() const;
+
+ UnitTable &getUnitTable() {return _unit_table;}
+
+protected:
+ UnitTable _unit_table;
+ UnitType _type;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_UNIT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/zoom-status.cpp b/src/ui/widget/zoom-status.cpp
new file mode 100644
index 000000000..e7320102c
--- /dev/null
+++ b/src/ui/widget/zoom-status.cpp
@@ -0,0 +1,127 @@
+/** \file
+ * Gtkmm facade/wrapper around zoom_status code that formerly lived
+ * in desktop-widget.cpp
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * MenTaLguY <mental@rydia.net>
+ * bulia byak <buliabyak@users.sf.net>
+ *
+ * Copyright (C) 2005 Ralf Stephan
+ * Copyright (C) 2004 MenTaLguY
+ * Copyright (C) 1999-2002 Lauris Kaplinski
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/widget/zoom-status.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "widgets/spw-utilities.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+ZoomStatus::ZoomStatus()
+ : _adj(0.0, -1.0, 1.0, 0.1, 0.1)
+{
+ _dt = 0;
+ _upd_f = false;
+
+ property_numeric() = false;
+ property_update_policy() = Gtk::UPDATE_ALWAYS;
+ sp_set_font_size_smaller(static_cast<GtkWidget*>((void*)gobj()));
+}
+
+ZoomStatus::~ZoomStatus()
+{
+ _dt = 0;
+}
+
+void
+ZoomStatus::init(SPDesktop *dt)
+{
+ _dt = dt;
+ property_digits() = 4;
+ _adj.set_value(0.0);
+ _adj.set_lower(log(SP_DESKTOP_ZOOM_MIN)/log(2.0));
+ _adj.set_upper(log(SP_DESKTOP_ZOOM_MAX)/log(2.0));
+ _adj.set_step_increment(0.1);
+ _adj.set_page_increment(0.1);
+ set_adjustment(_adj);
+}
+
+void
+ZoomStatus::update()
+{
+ if (!_dt) return;
+ _upd_f = true;
+ set_value(log(_dt->current_zoom())/log(2.0));
+ _upd_f = false;
+}
+
+inline double
+value_to_display(double value)
+{
+ return floor(pow(2, value) * 100.0 + 0.5);
+}
+
+inline double
+display_to_value(double value)
+{
+ return log(value / 100.0) / log(2.0);
+}
+
+int
+ZoomStatus::on_input(double *new_val)
+{
+ double new_scrolled = get_value();
+ double new_typed = atof(get_text().c_str());
+
+ if (value_to_display(new_scrolled) == new_typed)
+ { // the new value is set by scrolling
+ *new_val = new_scrolled;
+ } else { // the new value is typed in
+ *new_val = display_to_value(new_typed);
+ }
+
+ return true;
+}
+
+bool
+ZoomStatus::on_output()
+{
+ gchar b[64];
+ g_snprintf(b, 64, "%4.0f%%", value_to_display(get_value()));
+ set_text(b);
+ return true;
+}
+
+void
+ZoomStatus::on_value_changed()
+{
+ if (_upd_f) return;
+ _upd_f = true;
+ g_assert(_dt);
+ double zoom_factor = pow(2, get_value());
+ NR::Rect const d =_dt->get_display_area();
+ _dt->zoom_absolute(d.midpoint()[NR::X], d.midpoint()[NR::Y], zoom_factor);
+ gtk_widget_grab_focus(static_cast<GtkWidget*>((void*)_dt->canvas)); /// \todo this no love song
+ _upd_f = false;
+}
+
+}}}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/zoom-status.h b/src/ui/widget/zoom-status.h
new file mode 100644
index 000000000..58d595329
--- /dev/null
+++ b/src/ui/widget/zoom-status.h
@@ -0,0 +1,61 @@
+#ifndef __UI_WIDGET_ZOOMSTATUS_H__
+#define __UI_WIDGET_ZOOMSTATUS_H__
+
+/** \file
+ * Enhanced spinbutton.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 The Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/spinbutton.h>
+
+struct SPDesktop;
+
+namespace Gtk { class Widget; }
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class ZoomStatus : public Gtk::SpinButton
+{
+public:
+ ZoomStatus();
+ ~ZoomStatus();
+
+ void init (SPDesktop*);
+ void update();
+
+protected:
+ Gtk::Adjustment _adj;
+ SPDesktop *_dt;
+ bool _upd_f;
+
+ virtual int on_input (double*);
+ virtual bool on_output();
+ virtual void on_value_changed();
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#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 :