summaryrefslogtreecommitdiffstats
path: root/src/ui/dialog
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/dialog')
-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
51 files changed, 9163 insertions, 0 deletions
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 :