summaryrefslogtreecommitdiffstats
path: root/src/ui/widget
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/ui/widget
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/ui/widget')
-rw-r--r--src/ui/widget/.cvsignore3
-rw-r--r--src/ui/widget/Makefile_insert62
-rw-r--r--src/ui/widget/button.cpp51
-rw-r--r--src/ui/widget/button.h56
-rw-r--r--src/ui/widget/color-picker.cpp167
-rw-r--r--src/ui/widget/color-picker.h65
-rw-r--r--src/ui/widget/color-preview.cpp122
-rw-r--r--src/ui/widget/color-preview.h50
-rw-r--r--src/ui/widget/combo-text.cpp92
-rw-r--r--src/ui/widget/combo-text.h66
-rw-r--r--src/ui/widget/entity-entry.cpp161
-rw-r--r--src/ui/widget/entity-entry.h84
-rw-r--r--src/ui/widget/handlebox.cpp48
-rw-r--r--src/ui/widget/handlebox.h50
-rw-r--r--src/ui/widget/icon-widget.cpp165
-rw-r--r--src/ui/widget/icon-widget.h63
-rw-r--r--src/ui/widget/imageicon.cpp442
-rw-r--r--src/ui/widget/imageicon.h138
-rw-r--r--src/ui/widget/labelled.cpp102
-rw-r--r--src/ui/widget/labelled.h65
-rw-r--r--src/ui/widget/licensor.cpp146
-rw-r--r--src/ui/widget/licensor.h59
-rw-r--r--src/ui/widget/makefile.in17
-rw-r--r--src/ui/widget/notebook-page.cpp49
-rw-r--r--src/ui/widget/notebook-page.h50
-rw-r--r--src/ui/widget/page-sizer.cpp357
-rw-r--r--src/ui/widget/page-sizer.h67
-rw-r--r--src/ui/widget/panel.cpp248
-rw-r--r--src/ui/widget/panel.h80
-rw-r--r--src/ui/widget/preferences-widget.cpp278
-rw-r--r--src/ui/widget/preferences-widget.h117
-rw-r--r--src/ui/widget/registered-widget.cpp409
-rw-r--r--src/ui/widget/registered-widget.h175
-rw-r--r--src/ui/widget/registry.cpp58
-rw-r--r--src/ui/widget/registry.h54
-rw-r--r--src/ui/widget/ruler.cpp197
-rw-r--r--src/ui/widget/ruler.h88
-rw-r--r--src/ui/widget/scalar-unit.cpp252
-rw-r--r--src/ui/widget/scalar-unit.h85
-rw-r--r--src/ui/widget/scalar.cpp217
-rw-r--r--src/ui/widget/scalar.h86
-rw-r--r--src/ui/widget/selected-style.cpp977
-rw-r--r--src/ui/widget/selected-style.h212
-rw-r--r--src/ui/widget/style-swatch.cpp244
-rw-r--r--src/ui/widget/style-swatch.h88
-rw-r--r--src/ui/widget/svg-canvas.cpp92
-rw-r--r--src/ui/widget/svg-canvas.h56
-rw-r--r--src/ui/widget/tolerance-slider.cpp142
-rw-r--r--src/ui/widget/tolerance-slider.h61
-rw-r--r--src/ui/widget/toolbox.cpp269
-rw-r--r--src/ui/widget/toolbox.h73
-rw-r--r--src/ui/widget/unit-menu.cpp181
-rw-r--r--src/ui/widget/unit-menu.h70
-rw-r--r--src/ui/widget/zoom-status.cpp127
-rw-r--r--src/ui/widget/zoom-status.h61
55 files changed, 7794 insertions, 0 deletions
diff --git a/src/ui/widget/.cvsignore b/src/ui/widget/.cvsignore
new file mode 100644
index 000000000..38efca7bc
--- /dev/null
+++ b/src/ui/widget/.cvsignore
@@ -0,0 +1,3 @@
+.deps
+.dirstamp
+makefile
diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert
new file mode 100644
index 000000000..2ef0f8f41
--- /dev/null
+++ b/src/ui/widget/Makefile_insert
@@ -0,0 +1,62 @@
+## Makefile.am fragment sourced by src/Makefile.am.
+
+ui/widget/all: ui/widget/libuiwidget.a
+
+ui/widget/clean:
+ rm -f ui/widget/libuiwidget.a $(ui_libuiwidget_a_OBJECTS)
+
+ui_widget_libuiwidget_a_SOURCES = \
+ ui/widget/button.h \
+ ui/widget/button.cpp \
+ ui/widget/color-picker.cpp \
+ ui/widget/color-picker.h \
+ ui/widget/color-preview.cpp \
+ ui/widget/color-preview.h \
+ ui/widget/combo-text.cpp \
+ ui/widget/combo-text.h \
+ ui/widget/entity-entry.cpp \
+ ui/widget/entity-entry.h \
+ ui/widget/handlebox.cpp \
+ ui/widget/handlebox.h \
+ ui/widget/icon-widget.cpp \
+ ui/widget/icon-widget.h \
+ ui/widget/imageicon.cpp \
+ ui/widget/imageicon.h \
+ ui/widget/labelled.cpp \
+ ui/widget/labelled.h \
+ ui/widget/licensor.cpp \
+ ui/widget/licensor.h \
+ ui/widget/notebook-page.cpp \
+ ui/widget/notebook-page.h \
+ ui/widget/page-sizer.cpp \
+ ui/widget/page-sizer.h \
+ ui/widget/panel.cpp \
+ ui/widget/panel.cpp \
+ ui/widget/panel.h \
+ ui/widget/preferences-widget.cpp \
+ ui/widget/preferences-widget.h \
+ ui/widget/registered-widget.cpp \
+ ui/widget/registered-widget.h \
+ ui/widget/registry.cpp \
+ ui/widget/registry.h \
+ ui/widget/ruler.cpp \
+ ui/widget/ruler.h \
+ ui/widget/scalar-unit.cpp \
+ ui/widget/scalar-unit.h \
+ ui/widget/scalar.cpp \
+ ui/widget/scalar.h \
+ ui/widget/selected-style.h \
+ ui/widget/selected-style.cpp \
+ ui/widget/style-swatch.h \
+ ui/widget/style-swatch.cpp \
+ ui/widget/svg-canvas.cpp \
+ ui/widget/svg-canvas.h \
+ ui/widget/tolerance-slider.cpp \
+ ui/widget/tolerance-slider.h \
+ ui/widget/toolbox.cpp \
+ ui/widget/toolbox.h \
+ ui/widget/unit-menu.cpp \
+ ui/widget/unit-menu.h \
+ ui/widget/zoom-status.h \
+ ui/widget/zoom-status.cpp
+
diff --git a/src/ui/widget/button.cpp b/src/ui/widget/button.cpp
new file mode 100644
index 000000000..19c69ba44
--- /dev/null
+++ b/src/ui/widget/button.cpp
@@ -0,0 +1,51 @@
+/**
+ * \brief Button and CheckButton widgets
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "button.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+Button::Button(Glib::ustring const &label, Glib::ustring const &tooltip)
+ : _tooltips()
+{
+ set_use_underline (true);
+ set_label (label);
+ _tooltips.set_tip(*this, tooltip);
+}
+
+CheckButton::CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip)
+ : _tooltips()
+{
+ set_use_underline (true);
+ set_label (label);
+ _tooltips.set_tip(*this, tooltip);
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/button.h b/src/ui/widget/button.h
new file mode 100644
index 000000000..7e942b324
--- /dev/null
+++ b/src/ui/widget/button.h
@@ -0,0 +1,56 @@
+/**
+ * \brief Button and CheckButton widgets
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_BUTTON_H
+#define INKSCAPE_UI_WIDGET_BUTTON_H
+
+#include <gtkmm/button.h>
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/tooltips.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Button : public Gtk::Button
+{
+public:
+ Button();
+ Button(Glib::ustring const &label, Glib::ustring const &tooltip);
+protected:
+ Gtk::Tooltips _tooltips;
+};
+
+class CheckButton : public Gtk::CheckButton
+{
+public:
+ CheckButton();
+ CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip);
+protected:
+ Gtk::Tooltips _tooltips;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_BUTTON_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/color-picker.cpp b/src/ui/widget/color-picker.cpp
new file mode 100644
index 000000000..9bc79ddc1
--- /dev/null
+++ b/src/ui/widget/color-picker.cpp
@@ -0,0 +1,167 @@
+#define __COLOR_PICKER_C__
+
+/** \file
+ * \brief Color picker button & window
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * bulia byak <buliabyak@users.sf.net>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) Authors 2000-2005
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "inkscape.h"
+#include "desktop-handles.h"
+#include "document.h"
+
+#include "ui/dialog/dialog.h"
+
+#include "widgets/sp-color-notebook.h"
+
+#include "color-picker.h"
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+struct CPPointer {
+ ColorPicker *ptr;
+};
+
+class ColorPickerWindow : public Inkscape::UI::Dialog::Dialog {
+public:
+ ColorPickerWindow (ColorPicker* cp, const Glib::ustring &title);
+ virtual ~ColorPickerWindow();
+ void setRgba32 (guint32);
+
+ SPColorSelector *_csel;
+ CPPointer _cpp;
+};
+
+ColorPicker::ColorPicker (const Glib::ustring& title, const Glib::ustring& tip,
+ guint32 rgba, bool undo)
+: _preview(rgba), _window(0),
+ _title(title), _rgba(rgba), _undo(undo)
+{
+ set_relief (Gtk::RELIEF_NONE);
+ _preview.show();
+ add (_preview);
+ _tt.set_tip (*this, tip);
+}
+
+ColorPicker::~ColorPicker()
+{
+ closeWindow();
+}
+
+void
+ColorPicker::setRgba32 (guint32 rgba)
+{
+ _preview.setRgba32 (rgba);
+ _rgba = rgba;
+ if (_window)
+ _window->setRgba32 (rgba);
+}
+
+void
+ColorPicker::closeWindow()
+{
+ if (_window)
+ {
+ delete _window;
+ _window = 0;
+ }
+}
+
+void
+ColorPicker::on_clicked()
+{
+ static int _x, _y;
+ if (_window)
+ {
+ _window->move(_x,_y);
+ _window->present();
+ return;
+ }
+
+ _window =new ColorPickerWindow (this, _title);
+ _window->setRgba32 (_rgba);
+ _window->show_all();
+ _window->get_position (_x, _y);
+}
+
+void
+ColorPicker::on_changed (guint32)
+{
+}
+
+void
+sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp)
+{
+ SPColor color;
+ float alpha;
+ csel->base->getColorAlpha(color, &alpha);
+ guint32 rgba = sp_color_get_rgba32_falpha(&color, alpha);
+
+ ColorPicker *ptr = static_cast<CPPointer*>((void*)cp)->ptr;
+
+ (ptr->_preview).setRgba32 (rgba);
+
+ if (ptr->_undo && SP_ACTIVE_DESKTOP)
+ sp_document_done(SP_DT_DOCUMENT(SP_ACTIVE_DESKTOP));
+
+ ptr->on_changed (rgba);
+ ptr->_changed_signal.emit (rgba);
+}
+
+//==============================================================
+
+ColorPickerWindow::ColorPickerWindow (ColorPicker *cp, const Glib::ustring &title)
+ : Dialog("dialogs.colorpickerwindow")
+{
+ set_title (title);
+ set_border_width (4);
+ _csel = (SPColorSelector*)sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK,
+ SP_COLORSPACE_TYPE_UNKNOWN);
+ get_vbox()->pack_start (*Glib::wrap(&_csel->vbox), true, true, 0);
+
+ _cpp.ptr = cp;
+ g_signal_connect(G_OBJECT(_csel), "dragged",
+ G_CALLBACK(sp_color_picker_color_mod), &_cpp);
+ g_signal_connect(G_OBJECT(_csel), "changed",
+ G_CALLBACK(sp_color_picker_color_mod), &_cpp);
+
+ show();
+}
+
+ColorPickerWindow::~ColorPickerWindow()
+{
+ _csel = 0;
+}
+
+void
+ColorPickerWindow::setRgba32 (guint32 rgba)
+{
+ if (_csel)
+ {
+ SPColor color;
+ sp_color_set_rgb_rgba32(&color, rgba);
+ _csel->base->setColorAlpha(color, SP_RGBA32_A_F(rgba));
+ }
+}
+
+}}}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/color-picker.h b/src/ui/widget/color-picker.h
new file mode 100644
index 000000000..adff8181a
--- /dev/null
+++ b/src/ui/widget/color-picker.h
@@ -0,0 +1,65 @@
+#ifndef __COLOR_PICKER_H__
+#define __COLOR_PICKER_H__
+
+/**
+ * \file Color picker button \& window.
+ */
+/*
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) Authors 2000-2005
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <sigc++/sigc++.h>
+#include <gtkmm/button.h>
+#include <gtkmm/tooltips.h>
+#include "ui/widget/color-preview.h"
+
+class SPColorSelector;
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+ class ColorPickerWindow;
+
+class ColorPicker : public Gtk::Button {
+public:
+ ColorPicker (const Glib::ustring& title, const Glib::ustring& tip, const guint32 rgba, bool undo);
+ virtual ~ColorPicker();
+ void setRgba32 (guint32 rgba);
+ void closeWindow();
+ sigc::connection connectChanged (const sigc::slot<void,guint>& slot)
+ { return _changed_signal.connect (slot); }
+
+protected:
+ friend void sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp);
+ virtual void on_clicked();
+ virtual void on_changed (guint32);
+
+ ColorPreview _preview;
+ Gtk::Tooltips _tt;
+ ColorPickerWindow *_window;
+
+ const Glib::ustring _title;
+ sigc::signal<void,guint32> _changed_signal;
+ guint32 _rgba;
+ bool _undo;
+};
+
+}}}
+
+#endif /* !__COLOR_PICKER_H__ */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp
new file mode 100644
index 000000000..6e9f9ff4a
--- /dev/null
+++ b/src/ui/widget/color-preview.cpp
@@ -0,0 +1,122 @@
+/** \file
+ * Implemenmtation of a simple color preview widget
+ *
+ * Author:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2001-2005 Authors
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/nr-plain-stuff-gdk.h"
+#include "color-preview.h"
+
+#define SPCP_DEFAULT_WIDTH 32
+#define SPCP_DEFAULT_HEIGHT 11
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+ColorPreview::ColorPreview (guint32 rgba)
+{
+ _rgba = rgba;
+ set_flags (Gtk::NO_WINDOW);
+}
+
+void
+ColorPreview::on_size_request (Gtk::Requisition *req)
+{
+ req->width = SPCP_DEFAULT_WIDTH;
+ req->height = SPCP_DEFAULT_HEIGHT;
+}
+
+void
+ColorPreview::on_size_allocate (Gtk::Allocation &all)
+{
+ set_allocation (all);
+ if (is_drawable())
+ queue_draw();
+}
+
+bool
+ColorPreview::on_expose_event (GdkEventExpose *event)
+{
+ if (is_drawable())
+ paint (&event->area);
+
+ return true;
+}
+
+void
+ColorPreview::setRgba32 (guint32 rgba)
+{
+ _rgba = rgba;
+
+ if (is_drawable())
+ queue_draw();
+}
+
+void
+ColorPreview::paint (GdkRectangle *area)
+{
+ GdkRectangle warea, carea;
+ GdkRectangle wpaint, cpaint;
+ gint w2;
+
+ const Gtk::Allocation& allocation = get_allocation();
+ warea.x = allocation.get_x();
+ warea.y = allocation.get_y();
+ warea.width = allocation.get_width();
+ warea.height = allocation.get_height();
+
+ if (!gdk_rectangle_intersect (area, &warea, &wpaint))
+ return;
+
+ /* Transparent area */
+
+ w2 = warea.width / 2;
+
+ carea.x = warea.x;
+ carea.y = warea.y;
+ carea.width = w2;
+ carea.height = warea.height;
+
+ if (gdk_rectangle_intersect (area, &carea, &cpaint)) {
+ nr_gdk_draw_rgba32_solid (get_window()->gobj(),
+ get_style()->get_black_gc()->gobj(),
+ cpaint.x, cpaint.y,
+ cpaint.width, cpaint.height,
+ _rgba);
+ }
+
+ /* Solid area */
+
+ carea.x = warea.x + w2;
+ carea.y = warea.y;
+ carea.width = warea.width - w2;
+ carea.height = warea.height;
+
+ if (gdk_rectangle_intersect (area, &carea, &cpaint)) {
+ nr_gdk_draw_rgba32_solid (get_window()->gobj(),
+ get_style()->get_black_gc()->gobj(),
+ cpaint.x, cpaint.y,
+ cpaint.width, cpaint.height,
+ _rgba | 0xff);
+ }
+}
+
+}}}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
diff --git a/src/ui/widget/color-preview.h b/src/ui/widget/color-preview.h
new file mode 100644
index 000000000..424c58665
--- /dev/null
+++ b/src/ui/widget/color-preview.h
@@ -0,0 +1,50 @@
+#ifndef __COLOR_PREVIEW_H__
+#define __COLOR_PREVIEW_H__
+
+/** \file
+ * A simple color preview widget, mainly used within a picker button.
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2001-2005 Authors
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/eventbox.h>
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class ColorPreview : public Gtk::Widget {
+public:
+ ColorPreview (guint32 rgba);
+ void setRgba32 (guint32 rgba);
+
+protected:
+ virtual void on_size_request (Gtk::Requisition *req);
+ virtual void on_size_allocate (Gtk::Allocation &all);
+ virtual bool on_expose_event (GdkEventExpose *event);
+ void paint (GdkRectangle *area);
+
+ guint32 _rgba;
+};
+
+}}}
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/combo-text.cpp b/src/ui/widget/combo-text.cpp
new file mode 100644
index 000000000..7706f7c29
--- /dev/null
+++ b/src/ui/widget/combo-text.cpp
@@ -0,0 +1,92 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "combo-text.h"
+#include <gtk/gtkcombobox.h>
+
+ComboText::ComboText()
+ : Gtk::ComboBox()
+{
+ m_model = Gtk::ListStore::create(m_text_columns);
+ set_model(m_model);
+ pack_start(m_text_columns.m_column);
+}
+
+
+ComboText::~ComboText()
+{
+
+}
+
+void ComboText::append_text(const Glib::ustring& text)
+{
+ gtk_combo_box_append_text(gobj(), text.c_str());
+}
+
+void ComboText::insert_text(int position, const Glib::ustring& text)
+{
+ gtk_combo_box_insert_text(gobj(), position, text.c_str());
+}
+
+void ComboText::prepend_text(const Glib::ustring& text)
+{
+ gtk_combo_box_prepend_text(gobj(), text.c_str());
+}
+
+Glib::ustring ComboText::get_active_text() const
+{
+ Glib::ustring result;
+
+ //Get the active row:
+ Gtk::TreeModel::iterator active_row = get_active();
+ if(active_row)
+ {
+ Gtk::TreeModel::Row row = *active_row;
+ result = row[m_text_columns.m_column];
+ }
+
+ return result;
+}
+
+void ComboText::clear_text()
+{
+ m_model->clear();
+}
+
+void ComboText::set_active_text(const Glib::ustring& text)
+{
+ for(Gtk::TreeModel::iterator iter = m_model->children().begin(); iter != m_model->children().end(); ++iter)
+ {
+ Glib::ustring this_text = (*iter)[m_text_columns.m_column];
+
+ if(this_text == text)
+ {
+ set_active(iter);
+ return; //success
+ }
+ }
+
+ //Not found, so mark it as blank:
+ unset_active();
+}
diff --git a/src/ui/widget/combo-text.h b/src/ui/widget/combo-text.h
new file mode 100644
index 000000000..382414fb0
--- /dev/null
+++ b/src/ui/widget/combo-text.h
@@ -0,0 +1,66 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GLOM_MODE_DESIGN_COMBO_TEXTGLADE_HH
+#define GLOM_MODE_DESIGN_COMBO_TEXTGLADE_HH
+
+#include <gtkmm/combobox.h>
+
+#include <gtkmm/liststore.h>
+
+/** This class should just derive from Gtk::ComboBoxText and provide a
+ * constuctor suitable for libglade's get_widget_derived() template.
+ * However, I have reimplemented Gtk::ComboBoxText here temporarily,
+ * until the fixes in gtkmm 2.4.3 are widely available.
+ */
+class ComboText : public Gtk::ComboBox
+{
+ public:
+ ComboText();
+ virtual ~ComboText();
+
+ void append_text(const Glib::ustring& text);
+ void insert_text(int position, const Glib::ustring& text);
+ void prepend_text(const Glib::ustring& text);
+ Glib::ustring get_active_text() const;
+
+ //This is not part of ComboBoxText:
+ void clear_text();
+ void set_active_text(const Glib::ustring& text);
+
+ protected:
+
+ //Tree model columns:
+ //These columns are used by the model that is created by the default constructor
+ class TextModelColumns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ TextModelColumns()
+ { add(m_column); }
+
+ Gtk::TreeModelColumn<Glib::ustring> m_column;
+ };
+
+ TextModelColumns m_text_columns;
+ Glib::RefPtr<Gtk::ListStore> m_model;
+
+};
+
+#endif //GLOM_MODE_DESIGN_COMBO_TEXTGLADE_HH
diff --git a/src/ui/widget/entity-entry.cpp b/src/ui/widget/entity-entry.cpp
new file mode 100644
index 000000000..1b4048ab0
--- /dev/null
+++ b/src/ui/widget/entity-entry.cpp
@@ -0,0 +1,161 @@
+/** \file
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/entry.h>
+
+#include "ui/widget/registry.h"
+
+#include "dialogs/rdf.h"
+
+#include "inkscape.h"
+
+#include "entity-entry.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+//---------------------------------------------------
+
+EntityEntry*
+EntityEntry::create (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr)
+{
+ g_assert (ent);
+ EntityEntry* obj = 0;
+ switch (ent->format)
+ {
+ case RDF_FORMAT_LINE:
+ obj = new EntityLineEntry (ent, tt, wr);
+ break;
+ case RDF_FORMAT_MULTILINE:
+ obj = new EntityMultiLineEntry (ent, tt, wr);
+ break;
+ default:
+ g_warning ("Can't happen.");
+ }
+
+ obj->_label.show();
+ return obj;
+}
+
+EntityEntry::EntityEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr)
+: _label(Glib::ustring(_(ent->title))+":", 1.0, 0.5), _packable(0),
+ _entity(ent), _tt(&tt), _wr(&wr)
+{
+}
+
+EntityEntry::~EntityEntry()
+{
+ _changed_connection.disconnect();
+}
+
+EntityLineEntry::EntityLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr)
+: EntityEntry (ent, tt, wr)
+{
+ Gtk::Entry *e = new Gtk::Entry;
+ tt.set_tip (*e, _(ent->tip));
+ _packable = e;
+ _changed_connection = e->signal_changed().connect (sigc::mem_fun (*this, &EntityLineEntry::on_changed));
+}
+
+EntityLineEntry::~EntityLineEntry()
+{
+ delete reinterpret_cast<Gtk::Entry*>(_packable);
+}
+
+void
+EntityLineEntry::update (SPDocument *doc)
+{
+ const char *text = rdf_get_work_entity (doc, _entity);
+ reinterpret_cast<Gtk::Entry*>(_packable)->set_text (text ? text : "");
+}
+
+void
+EntityLineEntry::on_changed()
+{
+ if (_wr->isUpdating()) return;
+
+ _wr->setUpdating (true);
+ SPDocument *doc = SP_ACTIVE_DOCUMENT;
+ char const *text = reinterpret_cast<Gtk::Entry*>(_packable)->get_text().c_str();
+ if (rdf_set_work_entity (doc, _entity, text))
+ sp_document_done (doc);
+ _wr->setUpdating (false);
+}
+
+EntityMultiLineEntry::EntityMultiLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr)
+: EntityEntry (ent, tt, wr)
+{
+ Gtk::ScrolledWindow *s = new Gtk::ScrolledWindow;
+ s->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ s->set_shadow_type (Gtk::SHADOW_IN);
+ _packable = s;
+ _v.set_size_request (-1, 5);
+ _v.set_wrap_mode (Gtk::WRAP_WORD);
+ _v.set_accepts_tab (false);
+ s->add (_v);
+ tt.set_tip (_v, _(ent->tip));
+ _changed_connection = _v.get_buffer()->signal_changed().connect (sigc::mem_fun (*this, &EntityMultiLineEntry::on_changed));
+}
+
+EntityMultiLineEntry::~EntityMultiLineEntry()
+{
+ delete reinterpret_cast<Gtk::ScrolledWindow*>(_packable);
+}
+
+void
+EntityMultiLineEntry::update (SPDocument *doc)
+{
+ const char *text = rdf_get_work_entity (doc, _entity);
+ Gtk::ScrolledWindow *s = reinterpret_cast<Gtk::ScrolledWindow*>(_packable);
+ Gtk::TextView *tv = reinterpret_cast<Gtk::TextView*>(s->get_child());
+ tv->get_buffer()->set_text (text ? text : "");
+}
+
+void
+EntityMultiLineEntry::on_changed()
+{
+ if (_wr->isUpdating()) return;
+
+ _wr->setUpdating (true);
+ SPDocument *doc = SP_ACTIVE_DOCUMENT;
+ Gtk::ScrolledWindow *s = reinterpret_cast<Gtk::ScrolledWindow*>(_packable);
+ Gtk::TextView *tv = reinterpret_cast<Gtk::TextView*>(s->get_child());
+ char const *text = tv->get_buffer()->get_text().c_str();
+ if (rdf_set_work_entity (doc, _entity, text))
+ sp_document_done (doc);
+ _wr->setUpdating (false);
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/entity-entry.h b/src/ui/widget/entity-entry.h
new file mode 100644
index 000000000..5bdee9a90
--- /dev/null
+++ b/src/ui/widget/entity-entry.h
@@ -0,0 +1,84 @@
+/** \file
+ * \brief
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_ENTITY_ENTRY__H
+#define INKSCAPE_UI_WIDGET_ENTITY_ENTRY__H
+
+#include <gtkmm/textview.h>
+#include <gtkmm/tooltips.h>
+
+struct rdf_work_entity_t;
+class SPDocument;
+
+namespace Gtk {
+class TextBuffer;
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Registry;
+
+class EntityEntry {
+public:
+ static EntityEntry* create (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr);
+ virtual ~EntityEntry() = 0;
+ virtual void update (SPDocument *doc) = 0;
+ virtual void on_changed() = 0;
+ Gtk::Label _label;
+ Gtk::Widget *_packable;
+
+protected:
+ EntityEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr);
+ sigc::connection _changed_connection;
+ rdf_work_entity_t *_entity;
+ Gtk::Tooltips *_tt;
+ Registry *_wr;
+};
+
+class EntityLineEntry : public EntityEntry {
+public:
+ EntityLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr);
+ ~EntityLineEntry();
+ void update (SPDocument *doc);
+
+protected:
+ virtual void on_changed();
+};
+
+class EntityMultiLineEntry : public EntityEntry {
+public:
+ EntityMultiLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr);
+ ~EntityMultiLineEntry();
+ void update (SPDocument *doc);
+
+protected:
+ virtual void on_changed();
+ Gtk::TextView _v;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_ENTITY_ENTRY__H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/handlebox.cpp b/src/ui/widget/handlebox.cpp
new file mode 100644
index 000000000..b82b715bb
--- /dev/null
+++ b/src/ui/widget/handlebox.cpp
@@ -0,0 +1,48 @@
+/**
+ * \brief HandleBox Widget - Adds a detachment handle to another widget.
+ *
+ * This work really doesn't amount to much more than a convenience constructor
+ * for Gtk::HandleBox. Maybe this could be contributed back to Gtkmm, as
+ * Gtkmm provides several convenience constructors for other widgets as well.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "handlebox.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+HandleBox::HandleBox(Gtk::Widget *widget,
+ Gtk::PositionType position)
+ : _widget(widget)
+{
+ g_assert(_widget != NULL);
+ add(*Gtk::manage(_widget));
+ set_handle_position(position);
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/handlebox.h b/src/ui/widget/handlebox.h
new file mode 100644
index 000000000..41a993e9d
--- /dev/null
+++ b/src/ui/widget/handlebox.h
@@ -0,0 +1,50 @@
+/**
+ * \brief HandleBox Widget - Adds a detachment handle to another widget.
+ *
+ * This work really doesn't amount to much more than a convenience constructor
+ * for Gtk::HandleBox. Maybe this could be contributed back to Gtkmm, as
+ * Gtkmm provides several convenience constructors for other widgets as well.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_HANDLEBOX_H
+#define INKSCAPE_UI_WIDGET_HANDLEBOX_H
+
+#include <gtkmm/handlebox.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class HandleBox : public Gtk::HandleBox
+{
+public:
+ HandleBox(Gtk::Widget *widget,
+ Gtk::PositionType position = Gtk::POS_LEFT);
+
+protected:
+ Gtk::Widget *_widget;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_HANDLEBOX_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/icon-widget.cpp b/src/ui/widget/icon-widget.cpp
new file mode 100644
index 000000000..c456778b6
--- /dev/null
+++ b/src/ui/widget/icon-widget.cpp
@@ -0,0 +1,165 @@
+/**
+ * \brief Icon Widget
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ * based on work by Lauris Kaplinski in 2002 released under GPL
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "icon-widget.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * General purpose icon widget, supporting SVG, etc. icon loading
+ *
+ * \param ...
+ *
+ * An icon widget is a ...
+ */
+
+IconWidget::IconWidget()
+{
+ _pb = NULL;
+ _size = 0;
+}
+
+IconWidget::IconWidget(int unsigned size, int unsigned scale, gchar const *name)
+{
+ _size = std::max((int unsigned)128, std::min(size, (int unsigned)1));
+
+ char c[256];
+ g_snprintf (c, 256, "%d:%d:%s", _size, scale, name);
+ guchar *pixels = image_load_gtk(name, _size, scale);
+
+ if (pixels == NULL) {
+ g_warning("Couldn't find matching icon for %s - has this application been installed?", name);
+ _pb = NULL;
+ } else {
+ /* TODO
+ _pb = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB,
+ TRUE, 8, _size, _size, _size * 4,
+ (GdkPixbufDestroyNotify)nr_free, NULL);
+ */
+ }
+}
+
+IconWidget::IconWidget(int unsigned size, guchar const *px)
+{
+ _size = std::max((int unsigned)128, std::min(size, (int unsigned)1));
+
+ /*
+ _pb = gdk_pixbuf_new_from_data((guchar *)px, GDK_COLORSPACE_RGB,
+ TRUE, 8, _size, _size, _size * 4, NULL, NULL);
+ */
+}
+
+IconWidget::~IconWidget() {
+}
+
+void IconWidget::size_request(Gtk::Requisition &requisition)
+{
+ requisition.width = _size;
+ requisition.height = _size;
+}
+
+void IconWidget::size_allocate(Gtk::Allocation const &allocation)
+{
+ Gtk::Widget::size_allocate(allocation);
+
+ if (this->is_drawable()) {
+ this->queue_draw();
+ }
+}
+
+int IconWidget::expose(GdkEventExpose *event)
+{
+ if (this->is_drawable()) {
+ paint(&(event->area));
+ }
+ return true;
+}
+
+void IconWidget::paint(GdkRectangle const *area)
+{
+ Gtk::Allocation allocation = get_allocation();
+ int const x_pad = std::max(0, (allocation.get_width() - _size)/2);
+ int const y_pad = std::max(0, (allocation.get_height() - _size)/2);
+
+ int const x_max = std::max(area->x, allocation.get_x() + x_pad);
+ int const y_max = std::max(area->y, allocation.get_y() + y_pad);
+ int const x_min = std::min(area->x + area->width,
+ allocation.get_x() + x_pad + _size);
+ int const y_min = std::min(area->y + area->height,
+ allocation.get_y() + y_pad + _size);
+
+ if (_pb) {
+ gdk_draw_pixbuf(this->get_window()->gobj(), NULL, _pb,
+ x_max - allocation.get_x() - x_pad,
+ y_max - allocation.get_y() - y_pad,
+ x_max, y_max,
+ x_min - x_max, y_min - y_max,
+ GDK_RGB_DITHER_NORMAL, x_max, y_max);
+ }
+}
+
+guchar* IconWidget::image_load(gchar const *name, int unsigned size, int unsigned scale)
+{
+ guchar *px;
+
+ if (_do_bitmap_icons) {
+ px = image_load_pixmap(name, size, scale);
+ if (!px) {
+ px = image_load_svg(name, size, scale);
+ }
+ } else {
+ px = image_load_svg(name, size, scale);
+ if (!px) {
+ px = image_load_pixmap(name, size, scale);
+ }
+ }
+ return px;
+}
+
+guchar* IconWidget::image_load_pixmap(gchar const *name, int unsigned size, int unsigned scale)
+{
+ // TODO
+ return NULL;
+}
+
+guchar* IconWidget::image_load_svg(gchar const *name, int unsigned size, int unsigned scale)
+{
+ // TODO
+ return NULL;
+}
+
+guchar* IconWidget::image_load_gtk(gchar const *name, int unsigned size, int unsigned scale)
+{
+ // TODO
+ return NULL;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/icon-widget.h b/src/ui/widget/icon-widget.h
new file mode 100644
index 000000000..3ca461b33
--- /dev/null
+++ b/src/ui/widget/icon-widget.h
@@ -0,0 +1,63 @@
+/**
+ * \brief Icon Widget - General image widget (including SVG icons)
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_ICON_H
+#define INKSCAPE_UI_WIDGET_ICON_H
+
+#include <gtkmm/image.h>
+#include <gdkmm/rectangle.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class IconWidget : public Gtk::Widget
+{
+public:
+ IconWidget();
+ IconWidget(int unsigned size, int unsigned scale, gchar const *name);
+ IconWidget(int unsigned size, guchar const *px);
+ virtual ~IconWidget();
+
+ // Overrides of Gtk::Widget functions
+ void size_request(Gtk::Requisition &requisition);
+ void size_allocate(Gtk::Allocation const &allocation);
+
+ int expose(GdkEventExpose *event);
+ void paint(GdkRectangle const *area);
+ guchar* image_load(gchar const *name, int unsigned size, int unsigned scale);
+ guchar* image_load_pixmap(gchar const *name, int unsigned size, int unsigned scale);
+ guchar* image_load_svg(gchar const *name, int unsigned size, int unsigned scale);
+ guchar* image_load_gtk(gchar const *name, int unsigned size, int unsigned scale);
+
+protected:
+ int _size;
+ GdkPixbuf *_pb;
+ bool _do_bitmap_icons;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_ICON_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/imageicon.cpp b/src/ui/widget/imageicon.cpp
new file mode 100644
index 000000000..6a817e30d
--- /dev/null
+++ b/src/ui/widget/imageicon.cpp
@@ -0,0 +1,442 @@
+/*
+ * A simple image display widget, using Inkscape's own rendering engine
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004 The Inkscape Organization
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+
+
+#include "imageicon.h"
+#include <sys/stat.h>
+#include "svg-view-widget.h"
+#include "document.h"
+#include "inkscape.h"
+
+
+namespace Inkscape
+{
+namespace UI
+{
+namespace Widget
+{
+
+
+
+typedef enum {
+ SVG_TYPES,
+ IMPORT_TYPES,
+ EXPORT_TYPES
+ } FileDialogType;
+
+
+/*#########################################################################
+### ImageIcon widget
+#########################################################################*/
+
+
+/**
+ * Constructor
+ */
+ImageIcon::ImageIcon()
+{
+ init();
+}
+
+/**
+ * Construct from a file name
+ */
+ImageIcon::ImageIcon(const Glib::ustring &fileName)
+{
+ init();
+ showSvgFile(fileName);
+}
+
+/**
+ * Copy Constructor
+ */
+ImageIcon::ImageIcon(const ImageIcon &other)
+ : sigc::trackable(), Glib::ObjectBase(), Gtk::VBox()
+{
+ init();
+ document = other.document;
+ viewerGtkmm = other.viewerGtkmm;
+ showingBrokenImage = other.showingBrokenImage;
+}
+
+/**
+ * Destructor
+ */
+ImageIcon::~ImageIcon()
+{
+ if (document)
+ sp_document_unref(document);
+}
+
+
+/**
+ * basic initialization, called by the various constructors
+ */
+void ImageIcon::init()
+{
+ if (!INKSCAPE)
+ inkscape_application_init("",false);
+ document = NULL;
+ viewerGtkmm = NULL;
+ //set_size_request(150,150);
+ showingBrokenImage = false;
+}
+
+
+bool ImageIcon::showSvgDocument(const SPDocument *docArg)
+{
+
+ if (document)
+ sp_document_unref(document);
+
+ SPDocument *doc = (SPDocument *)docArg;
+
+ sp_document_ref(doc);
+ document = doc;
+
+ //This should remove it from the box, and free resources
+ //if (viewerGtkmm)
+ // viewerGtkmm->destroy();
+
+ GtkWidget *viewerGtk = sp_svg_view_widget_new(doc);
+ viewerGtkmm = Glib::wrap(viewerGtk);
+
+ viewerGtkmm->show();
+ pack_start(*viewerGtkmm, TRUE, TRUE, 0);
+
+ //GtkWidget *vbox = (GtkWidget *)gobj();
+ //gtk_box_pack_start(GTK_BOX(vbox), viewerGtk, TRUE, TRUE, 0);
+
+ return true;
+}
+
+bool ImageIcon::showSvgFile(const Glib::ustring &theFileName)
+{
+ Glib::ustring fileName = theFileName;
+
+ fileName = Glib::filename_to_utf8(fileName);
+
+ SPDocument *doc = sp_document_new (fileName.c_str(), 0);
+ if (!doc) {
+ g_warning("SVGView: error loading document '%s'\n", fileName.c_str());
+ return false;
+ }
+
+ showSvgDocument(doc);
+
+ sp_document_unref(doc);
+
+ return true;
+}
+
+
+
+bool ImageIcon::showSvgFromMemory(const char *xmlBuffer)
+{
+ if (!xmlBuffer)
+ return false;
+
+ gint len = (gint)strlen(xmlBuffer);
+ SPDocument *doc = sp_document_new_from_mem(xmlBuffer, len, 0);
+ if (!doc) {
+ g_warning("SVGView: error loading buffer '%s'\n",xmlBuffer);
+ return false;
+ }
+
+ showSvgDocument(doc);
+
+ sp_document_unref(doc);
+
+ return true;
+}
+
+
+
+bool ImageIcon::showBitmap(const Glib::ustring &theFileName)
+{
+ Glib::ustring fileName = theFileName;
+
+
+ /*#####################################
+ # LET'S HAVE SOME FUN WITH SVG!
+ # Instead of just loading an image, why
+ # don't we make a lovely little svg and
+ # display it nicely?
+ #####################################*/
+
+ //Arbitrary size of svg doc -- rather 'portrait' shaped
+ gint previewWidth = 400;
+ gint previewHeight = 600;
+
+ //Get some image info. Smart pointer does not need to be deleted
+ Glib::RefPtr<Gdk::Pixbuf> img = Gdk::Pixbuf::create_from_file(fileName);
+ gint imgWidth = img->get_width();
+ gint imgHeight = img->get_height();
+
+ //Find the minimum scale to fit the image inside the preview area
+ double scaleFactorX = (0.9 *(double)previewWidth) / ((double)imgWidth);
+ double scaleFactorY = (0.9 *(double)previewHeight) / ((double)imgHeight);
+ double scaleFactor = scaleFactorX;
+ if (scaleFactorX > scaleFactorY)
+ scaleFactor = scaleFactorY;
+
+ //Now get the resized values
+ gint scaledImgWidth = (int) (scaleFactor * (double)imgWidth);
+ gint scaledImgHeight = (int) (scaleFactor * (double)imgHeight);
+
+ //center the image on the area
+ gint imgX = (previewWidth - scaledImgWidth) / 2;
+ gint imgY = (previewHeight - scaledImgHeight) / 2;
+
+ //wrap a rectangle around the image
+ gint rectX = imgX-1;
+ gint rectY = imgY-1;
+ gint rectWidth = scaledImgWidth +2;
+ gint rectHeight = scaledImgHeight+2;
+
+ //Our template. Modify to taste
+ gchar const *xformat =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<svg\n"
+ "xmlns=\"http://www.w3.org/2000/svg\"\n"
+ "xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
+ "width=\"%d\" height=\"%d\">\n"
+ "<rect\n"
+ " style=\"fill:#eeeeee;stroke:none\"\n"
+ " x=\"-100\" y=\"-100\" width=\"4000\" height=\"4000\"/>\n"
+ "<image x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"\n"
+ "xlink:href=\"%s\"/>\n"
+ "<rect\n"
+ " style=\"fill:none;"
+ " stroke:#000000;stroke-width:1.0;"
+ " stroke-linejoin:miter;stroke-opacity:1.0000000;"
+ " stroke-miterlimit:4.0000000;stroke-dasharray:none\"\n"
+ " x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"/>\n"
+ "</svg>\n\n";
+
+ //if (!Glib::get_charset()) //If we are not utf8
+ fileName = Glib::filename_to_utf8(fileName);
+
+ //Fill in the template
+ /* FIXME: Do proper XML quoting for fileName. */
+ gchar *xmlBuffer = g_strdup_printf(xformat,
+ previewWidth, previewHeight,
+ imgX, imgY, scaledImgWidth, scaledImgHeight,
+ fileName.c_str(),
+ rectX, rectY, rectWidth, rectHeight);
+
+ //g_message("%s\n", xmlBuffer);
+
+ //now show it!
+ showSvgFromMemory(xmlBuffer);
+ g_free(xmlBuffer);
+
+ return true;
+}
+
+
+
+void ImageIcon::showBrokenImage(const Glib::ustring &errorMessage)
+{
+ //Are we already showing it?
+ if (showingBrokenImage)
+ return;
+
+ //Our template. Modify to taste
+ gchar const *xformat =
+ "<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
+ "<!-- Created with Inkscape (http://www.inkscape.org/) -->"
+ "<svg"
+ " xmlns:xml='http://www.w3.org/XML/1998/namespace'"
+ " xmlns:svg='http://www.w3.org/2000/svg'"
+ " xmlns='http://www.w3.org/2000/svg'"
+ " id='svg2'"
+ " height='64.000000'"
+ " width='64.000000'"
+ " y='0.00000000'"
+ " x='0.00000000'"
+ " version='1.0'>"
+ " <defs"
+ " id='defs3' />"
+ " <rect"
+ " id='rect1723'"
+ " style='fill:#fefefe;fill-opacity:1.0000000;stroke:#fe0101;stroke-opacity:1.0000000'"
+ " y='0.74437392'"
+ " x='0.52374262'"
+ " height='62.698864'"
+ " width='62.701584' />"
+ " <path"
+ " id='path1725'"
+ " style='fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#fe0101;stroke-width:0.99443889px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000'"
+ " d='M 0.35436684,0.57368969 L 62.861950,63.081272' />"
+ " <path"
+ " id='path1727'"
+ " style='fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#fe0101;stroke-width:0.99443889px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000'"
+ " d='M 0.53194379,63.258849 L 63.217104,0.92884358' />"
+ " <path"
+ " id='text1729'"
+ " style='font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial Black'"
+ " d='M 11.027113,15.116791 L 13.421921,15.116791 L 13.421921,18.076798 C 13.658875,17.828198 13.926907,17.641741 14.226014,17.517426 C 14.529009,17.393131 14.863071,17.330979 15.228229,17.330969 C 15.981815,17.330979 16.605278,17.602888 17.098629,18.146717 C 17.591951,18.686677 17.838621,19.463583 17.838631,20.477433 C 17.838621,21.153343 17.725971,21.749619 17.500671,22.266259 C 17.275361,22.779022 16.962660,23.163581 16.562557,23.419968 C 16.166333,23.672456 15.725439,23.798710 15.239874,23.798710 C 14.824228,23.798710 14.443547,23.709359 14.097831,23.530668 C 13.837556,23.390830 13.553992,23.128627 13.247118,22.744057 L 13.247118,23.658862 L 11.027113,23.658862 L 11.027113,15.116791 M 13.404438,20.547352 C 13.404438,21.079536 13.503494,21.466054 13.701606,21.706887 C 13.903597,21.943842 14.158034,22.062320 14.464918,22.062320 C 14.748482,22.062320 14.985437,21.945791 15.175782,21.712715 C 15.370006,21.475760 15.467113,21.079536 15.467123,20.524052 C 15.467113,20.034599 15.371945,19.675289 15.181610,19.446090 C 14.995153,19.216912 14.767903,19.102313 14.499872,19.102313 C 14.177455,19.102313 13.913313,19.222739 13.707434,19.463573 C 13.505433,19.700537 13.404438,20.061797 13.404438,20.547352 M 18.986502,17.470807 L 21.206507,17.470807 L 21.206507,18.484677 C 21.420152,18.045732 21.639635,17.744675 21.864935,17.581518 C 22.094123,17.414492 22.375749,17.330979 22.709820,17.330969 C 23.059425,17.330979 23.442055,17.439740 23.857701,17.657264 L 23.123527,19.347034 C 22.843831,19.230506 22.622419,19.172242 22.459271,19.172232 C 22.148509,19.172242 21.907666,19.300425 21.736752,19.556801 C 21.492021,19.918071 21.369655,20.593971 21.369665,21.584522 L 21.369665,23.658862 L 18.986502,23.658862 L 18.986502,17.470807 M 24.149042,20.582316 C 24.149042,19.638385 24.467571,18.861480 25.104638,18.251600 C 25.741695,17.637853 26.602114,17.330979 27.685903,17.330969 C 28.925063,17.330979 29.861228,17.690289 30.494417,18.408921 C 31.003281,18.987724 31.257718,19.700537 31.257728,20.547352 C 31.257718,21.499070 30.941129,22.279853 30.307960,22.889723 C 29.678659,23.495714 28.806586,23.798710 27.691730,23.798710 C 26.697291,23.798710 25.893188,23.546212 25.279440,23.041226 C 24.525835,22.415813 24.149042,21.596177 24.149042,20.582316 M 26.526367,20.576489 C 26.526367,21.128094 26.637078,21.535973 26.858500,21.800116 C 27.083800,22.064269 27.365425,22.196340 27.703385,22.196340 C 28.045214,22.196340 28.324899,22.066208 28.542443,21.805944 C 28.763855,21.545679 28.874566,21.128094 28.874566,20.553179 C 28.874566,20.017127 28.763855,19.618964 28.542443,19.358689 C 28.321021,19.094546 28.047163,18.962475 27.720867,18.962465 C 27.375141,18.962475 27.089627,19.096485 26.864327,19.364517 C 26.639017,19.628669 26.526367,20.032660 26.526367,20.576489 M 32.388127,15.116791 L 34.812072,15.116791 L 34.812072,19.521837 L 36.583416,17.470807 L 39.502631,17.470807 L 37.282626,19.638375 L 39.630824,23.658862 L 36.956330,23.658862 L 35.703566,21.176653 L 34.812072,22.050665 L 34.812072,23.658862 L 32.388127,23.658862 L 32.388127,15.116791 M 46.832739,21.153343 L 42.078078,21.153343 C 42.120799,21.534024 42.223744,21.817598 42.386891,22.004056 C 42.616080,22.272087 42.915187,22.406107 43.284223,22.406107 C 43.517290,22.406107 43.738702,22.347833 43.948479,22.231295 C 44.076662,22.157498 44.214561,22.027365 44.362175,21.840908 L 46.698719,22.056492 C 46.341337,22.678017 45.910148,23.124739 45.405172,23.396658 C 44.900176,23.664689 44.175718,23.798710 43.231777,23.798710 C 42.412140,23.798710 41.767306,23.684110 41.297285,23.454922 C 40.827253,23.221855 40.436856,22.854768 40.126104,22.353661 C 39.819220,21.848675 39.665779,21.256287 39.665779,20.576489 C 39.665779,19.609248 39.974601,18.826515 40.592247,18.228291 C 41.213762,17.630086 42.070302,17.330979 43.161858,17.330969 C 44.047525,17.330979 44.746735,17.464989 45.259497,17.733020 C 45.772250,18.001051 46.162646,18.389509 46.430688,18.898373 C 46.698709,19.407248 46.832729,20.069564 46.832739,20.885312 L 46.832739,21.153343 M 44.420439,20.017117 C 44.373820,19.558750 44.249515,19.230506 44.047525,19.032394 C 43.849413,18.834282 43.587209,18.735226 43.260914,18.735226 C 42.884111,18.735226 42.583054,18.884779 42.357764,19.183887 C 42.214028,19.370354 42.122739,19.648091 42.083906,20.017117 L 44.420439,20.017117 M 47.934001,17.470807 L 50.142351,17.470807 L 50.142351,18.478849 C 50.472535,18.067092 50.806606,17.773812 51.144556,17.599000 C 51.482507,17.420319 51.894264,17.330979 52.379838,17.330969 C 53.036317,17.330979 53.549080,17.527142 53.918116,17.919478 C 54.291021,18.307935 54.477478,18.910038 54.477488,19.725776 L 54.477488,23.658862 L 52.094325,23.658862 L 52.094325,20.256021 C 52.094325,19.867563 52.022457,19.593705 51.878731,19.434436 C 51.735004,19.271298 51.533004,19.189714 51.272750,19.189714 C 50.985287,19.189714 50.752220,19.298486 50.573530,19.516019 C 50.394839,19.733553 50.305499,20.123950 50.305499,20.687200 L 50.305499,23.658862 L 47.934001,23.658862 L 47.934001,17.470807' />"
+ " <path"
+ " id='text1733'"
+ " style='font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial Black'"
+ " d='M 13.747801,34.415696 L 16.119299,34.415696 L 16.119299,36.029710 L 13.747801,36.029710 L 13.747801,34.415696 M 13.747801,36.769712 L 16.119299,36.769712 L 16.119299,42.957766 L 13.747801,42.957766 L 13.747801,36.769712 M 17.640095,36.769712 L 19.854272,36.769712 L 19.854272,37.672871 C 20.172801,37.296078 20.493269,37.028047 20.815696,36.868768 C 21.141991,36.709508 21.534327,36.629883 21.992704,36.629874 C 22.486035,36.629883 22.876432,36.717285 23.163894,36.892077 C 23.451337,37.066890 23.686352,37.327154 23.868931,37.672871 C 24.241836,37.268880 24.581735,36.995022 24.888619,36.851295 C 25.195493,36.703681 25.574225,36.629883 26.024845,36.629874 C 26.689090,36.629883 27.207670,36.827986 27.580595,37.224210 C 27.953500,37.616546 28.139957,38.232243 28.139967,39.071300 L 28.139967,42.957766 L 25.762641,42.957766 L 25.762641,39.432560 C 25.762631,39.152874 25.708246,38.945056 25.599484,38.809097 C 25.440214,38.595452 25.242102,38.488619 25.005157,38.488619 C 24.725462,38.488619 24.500161,38.589624 24.329247,38.791615 C 24.158323,38.993615 24.072861,39.317971 24.072871,39.764683 L 24.072871,42.957766 L 21.695536,42.957766 L 21.695536,39.549099 C 21.695536,39.277179 21.679993,39.092671 21.648926,38.995554 C 21.598419,38.840173 21.511017,38.715868 21.386723,38.622640 C 21.262408,38.525523 21.116742,38.476974 20.949706,38.476964 C 20.677787,38.476974 20.454426,38.579908 20.279624,38.785787 C 20.104821,38.991666 20.017420,39.329626 20.017420,39.799647 L 20.017420,42.957766 L 17.640095,42.957766 L 17.640095,36.769712 M 31.717620,38.774132 L 29.450995,38.535238 C 29.536457,38.139014 29.658813,37.828252 29.818082,37.602952 C 29.981230,37.373764 30.214307,37.175651 30.517302,37.008616 C 30.734826,36.888199 31.033943,36.794970 31.414624,36.728930 C 31.795305,36.662899 32.207063,36.629883 32.649906,36.629874 C 33.360771,36.629883 33.931797,36.670665 34.362976,36.752239 C 34.794155,36.829935 35.153476,36.995022 35.440938,37.247510 C 35.642928,37.422322 35.802188,37.670932 35.918736,37.993339 C 36.035264,38.311877 36.093529,38.616812 36.093538,38.908153 L 36.093538,41.640911 C 36.093529,41.932251 36.111011,42.161440 36.145975,42.328476 C 36.184818,42.491623 36.266392,42.701390 36.390707,42.957766 L 34.164874,42.957766 C 34.075524,42.798497 34.017250,42.678081 33.990062,42.596507 C 33.962874,42.511045 33.935676,42.378973 33.908488,42.200282 C 33.597726,42.499390 33.288903,42.713045 32.982029,42.841228 C 32.562495,43.012152 32.074991,43.097614 31.519508,43.097614 C 30.781445,43.097614 30.220134,42.926690 29.835565,42.584852 C 29.454883,42.243014 29.264538,41.821540 29.264538,41.320443 C 29.264538,40.850411 29.402437,40.463903 29.678244,40.160907 C 29.954042,39.857922 30.462916,39.632612 31.204857,39.484997 C 32.094413,39.306316 32.671267,39.182011 32.935419,39.112082 C 33.199562,39.038285 33.479248,38.943117 33.774477,38.826569 C 33.774467,38.535238 33.714264,38.331299 33.593847,38.214760 C 33.473421,38.098232 33.261715,38.039958 32.958719,38.039958 C 32.570271,38.039958 32.278931,38.102110 32.084707,38.226415 C 31.933204,38.323532 31.810838,38.506101 31.717620,38.774132 M 33.774477,40.021069 C 33.448172,40.137607 33.108273,40.240542 32.754790,40.329882 C 32.273103,40.458075 31.968169,40.584319 31.839975,40.708624 C 31.707904,40.836817 31.641863,40.982483 31.641873,41.145640 C 31.641863,41.332098 31.705965,41.485530 31.834158,41.605956 C 31.966219,41.722484 32.158504,41.780759 32.411002,41.780759 C 32.675145,41.780759 32.919876,41.716667 33.145176,41.588474 C 33.374365,41.460281 33.535573,41.304900 33.628802,41.122331 C 33.725909,40.935873 33.774467,40.695030 33.774477,40.399811 L 33.774477,40.021069 M 41.996080,36.769712 L 44.216085,36.769712 L 44.216085,42.613989 L 44.221913,42.887847 C 44.221903,43.276295 44.138390,43.645331 43.971354,43.994936 C 43.808196,44.348430 43.588724,44.633943 43.312926,44.851476 C 43.041007,45.069010 42.693341,45.226330 42.269939,45.323447 C 41.850405,45.420554 41.368718,45.469112 40.824890,45.469112 C 39.581841,45.469112 38.727240,45.282655 38.261107,44.909741 C 37.798842,44.536826 37.567715,44.037667 37.567715,43.412255 C 37.567715,43.334569 37.571603,43.229686 37.579369,43.097614 L 39.880948,43.359818 C 39.939213,43.573463 40.028563,43.721078 40.148979,43.802652 C 40.323782,43.923068 40.543255,43.983282 40.807407,43.983282 C 41.149246,43.983282 41.403683,43.891992 41.570719,43.709423 C 41.741633,43.526854 41.827095,43.208315 41.827095,42.753827 L 41.827095,41.815713 C 41.594018,42.091521 41.360952,42.291572 41.127885,42.415877 C 40.762737,42.610101 40.368452,42.707218 39.945050,42.707218 C 39.117637,42.707218 38.449503,42.345958 37.940629,41.623428 C 37.579369,41.110676 37.398739,40.432827 37.398739,39.589880 C 37.398739,38.626528 37.631806,37.892353 38.097949,37.387358 C 38.564093,36.882372 39.173962,36.629883 39.927568,36.629874 C 40.409244,36.629883 40.805468,36.711457 41.116230,36.874595 C 41.430871,37.037753 41.724151,37.307733 41.996080,37.684526 L 41.996080,36.769712 M 39.764410,39.770510 C 39.764410,40.217232 39.859578,40.549365 40.049923,40.766898 C 40.240269,40.980544 40.490818,41.087366 40.801580,41.087366 C 41.096799,41.087366 41.343470,40.976665 41.541582,40.755243 C 41.743572,40.529943 41.844577,40.191983 41.844577,39.741383 C 41.844577,39.290773 41.739694,38.946996 41.529937,38.710041 C 41.320160,38.469198 41.063784,38.348781 40.760798,38.348781 C 40.457802,38.348781 40.215020,38.459492 40.032451,38.680904 C 39.853760,38.898437 39.764410,39.261646 39.764410,39.770510 M 52.507607,40.452248 L 47.752946,40.452248 C 47.795667,40.832929 47.898612,41.116503 48.061759,41.302961 C 48.290948,41.570992 48.590055,41.705012 48.959091,41.705012 C 49.192158,41.705012 49.413580,41.646738 49.623347,41.530200 C 49.751530,41.456402 49.889429,41.326270 50.037043,41.139813 L 52.373587,41.355397 C 52.016205,41.976922 51.585026,42.423643 51.080040,42.695563 C 50.575044,42.963594 49.850586,43.097614 48.906644,43.097614 C 48.087008,43.097614 47.442184,42.983015 46.972153,42.753827 C 46.502121,42.520760 46.111734,42.153673 45.800972,41.652565 C 45.494088,41.147579 45.340656,40.555192 45.340656,39.875394 C 45.340656,38.908153 45.649469,38.125420 46.267115,37.527195 C 46.888640,36.928991 47.745170,36.629883 48.836725,36.629874 C 49.722393,36.629883 50.421612,36.763894 50.934375,37.031925 C 51.447127,37.299956 51.837514,37.688414 52.105555,38.197278 C 52.373577,38.706152 52.507597,39.368469 52.507607,40.184217 L 52.507607,40.452248 M 50.095317,39.316022 C 50.048698,38.857655 49.924393,38.529411 49.722403,38.331299 C 49.524281,38.133187 49.262077,38.034131 48.935782,38.034131 C 48.558979,38.034131 48.257932,38.183684 48.032632,38.482792 C 47.888896,38.669259 47.797616,38.946996 47.758774,39.316022 L 50.095317,39.316022' />"
+ " <text"
+ " xml:space='preserve'"
+ " id='text1644'"
+ " style='font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans'"
+ " y='59.288345'"
+ " x='12.760736'><tspan"
+ " id='tspan1646'"
+ " y='59.288345'"
+ " x='12.760736'>%s</tspan></text>"
+ "</svg>";
+
+ //Fill in the template
+ char *cErrorMessage = (char *)errorMessage.c_str();
+ gchar *xmlBuffer = g_strdup_printf(xformat, cErrorMessage);
+
+ //g_message("%s\n", xmlBuffer);
+
+ //now show it!
+ showSvgFromMemory(xmlBuffer);
+ g_free(xmlBuffer);
+ showingBrokenImage = true;
+
+}
+
+
+
+static bool
+hasSuffix(const Glib::ustring &str, Glib::ustring &ext)
+{
+ int strLen = str.length();
+ int extLen = ext.length();
+ if (extLen > strLen)
+ {
+ return false;
+ }
+ int strpos = strLen-1;
+ for (int extpos = extLen-1 ; extpos>=0 ; extpos--, strpos--)
+ {
+ Glib::ustring::value_type ch = str[strpos];
+ if (ch != ext[extpos])
+ {
+ if ( ((ch & 0xff80) != 0) ||
+ static_cast<Glib::ustring::value_type>( g_ascii_tolower( static_cast<gchar>(0x07f & ch) ) ) != ext[extpos] )
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
+/**
+ * Return true if the image is loadable by Gdk, else false
+ */
+static bool
+isValidImageIconFile(const Glib::ustring &fileName)
+{
+ std::vector<Gdk::PixbufFormat>formats = Gdk::Pixbuf::get_formats();
+ for (unsigned int i=0; i<formats.size(); i++)
+ {
+ Gdk::PixbufFormat format = formats[i];
+ std::vector<Glib::ustring>extensions = format.get_extensions();
+ for (unsigned int j=0; j<extensions.size(); j++)
+ {
+ Glib::ustring ext = extensions[j];
+ if (hasSuffix(fileName, ext))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool ImageIcon::show(const Glib::ustring &fileName)
+{
+
+ if (!Glib::file_test(fileName, Glib::FILE_TEST_EXISTS))
+ return false;
+
+ gchar *fName = (gchar *)fileName.c_str();
+ //g_message("fname:%s\n", fName);
+
+
+ if (Glib::file_test(fileName, Glib::FILE_TEST_IS_REGULAR))
+ {
+ struct stat info;
+ if (stat(fName, &info))
+ {
+ Glib::ustring err = "cannot get file info";
+ showBrokenImage(err);
+ return false;
+ }
+ long fileLen = info.st_size;
+ if (fileLen > 0x150000L)
+ {
+ Glib::ustring err = "File too large";
+ showBrokenImage(err);
+ return false;
+ }
+ }
+
+ Glib::ustring svg = ".svg";
+ Glib::ustring svgz = ".svgz";
+
+ if (hasSuffix(fileName, svg) || hasSuffix(fileName, svgz) )
+ {
+ if (!showSvgFile(fileName))
+ {
+ showBrokenImage(bitmapError);
+ return false;
+ }
+ return true;
+ }
+ else if (isValidImageIconFile(fileName))
+ {
+ if (!showBitmap(fileName))
+ {
+ showBrokenImage(bitmapError);
+ return false;
+ }
+ return true;
+ }
+ else
+ {
+ showBrokenImage("unsupported file type");
+ return false;
+ }
+}
+
+
+
+
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+/*#########################################################################
+### E N D O F F I L E
+#########################################################################*/
+
+
+
diff --git a/src/ui/widget/imageicon.h b/src/ui/widget/imageicon.h
new file mode 100644
index 000000000..803b2f53f
--- /dev/null
+++ b/src/ui/widget/imageicon.h
@@ -0,0 +1,138 @@
+#ifndef __UI_DIALOG_IMAGE_H__
+#define __UI_DIALOG_IMAGE_H__
+/*
+ * A simple image display widget, using Inkscape's own rendering engine
+ *
+ * Authors:
+ * Bob Jamison
+ * Other dudes from The Inkscape Organization
+ *
+ * Copyright (C) 2004 The Inkscape Organization
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glibmm/ustring.h>
+#include <gtkmm/box.h>
+
+
+class SPDocument;
+
+namespace Inkscape
+{
+namespace UI
+{
+namespace Widget
+{
+
+
+/*#########################################################################
+### ImageIcon widget
+#########################################################################*/
+
+/**
+ * This class is evolved from the SVGPreview widget of the FileChooser
+ * This uses Inkscape's renderer to show images in a variety of formats,
+ * including SVG
+ */
+class ImageIcon : public Gtk::VBox
+{
+public:
+
+ /**
+ * Constructor
+ */
+ ImageIcon();
+
+ /**
+ * Construct from a file name
+ */
+ ImageIcon(const Glib::ustring &fileName);
+
+ /**
+ * Copy Constructor
+ */
+ ImageIcon(const ImageIcon &other);
+
+ /**
+ * Destructor
+ */
+ ~ImageIcon();
+
+ /**
+ *
+ */
+ bool showSvgDocument(const SPDocument *doc);
+
+ /**
+ *
+ */
+ bool showSvgFile(const Glib::ustring &fileName);
+
+ /**
+ *
+ */
+ bool showSvgFromMemory(const char *xmlBuffer);
+
+ /**
+ * Show image embedded in SVG
+ */
+ bool showBitmap(const Glib::ustring &fileName);
+
+ /**
+ * Show the "Too large" image
+ */
+ void showBrokenImage(const Glib::ustring &reason);
+
+ /**
+ *
+ */
+ bool show(const Glib::ustring &fileName);
+
+private:
+
+ /**
+ * basic initialization, called by the various constructors
+ */
+ void init();
+
+ /**
+ * The svg document we are currently showing
+ */
+ SPDocument *document;
+
+ /**
+ * The sp_svg_view widget
+ */
+ Gtk::Widget *viewerGtkmm;
+
+ /**
+ * are we currently showing the "broken image" image?
+ */
+ bool showingBrokenImage;
+
+
+ /**
+ * will be set by showImageIcon as a side-effect of an error
+ */
+ Glib::ustring bitmapError;
+
+
+ /**
+ * will be set by showImageIcon as a side-effect of an error
+ */
+ Glib::ustring svgError;
+
+};
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif /* __UI_DIALOG_IMAGE_H__ */
+/*#########################################################################
+### E N D O F F I L E
+#########################################################################*/
diff --git a/src/ui/widget/labelled.cpp b/src/ui/widget/labelled.cpp
new file mode 100644
index 000000000..64f9aef83
--- /dev/null
+++ b/src/ui/widget/labelled.cpp
@@ -0,0 +1,102 @@
+/**
+ * \brief Labelled Widget - Adds a label with optional icon or suffix to
+ * another widget.
+ *
+ * Authors:
+ * Carl Hetherington <inkscape@carlh.net>
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Carl Hetherington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* For getting the Gtkmmified Icon manager */
+#include "widgets/icon.h"
+
+#include "labelled.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a Labelled Widget.
+ *
+ * \param label Label.
+ * \param widget Widget to label; should be allocated with new, as it will
+ * be passed to Gtk::manage().
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the text
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to true).
+ */
+Labelled::Labelled(Glib::ustring const &label, Glib::ustring const &tooltip,
+ Gtk::Widget *widget,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ bool mnemonic)
+ : _widget(widget),
+ _label(new Gtk::Label(label, 1.0, 0.5, mnemonic)),
+ _suffix(new Gtk::Label(suffix, 0.0, 0.5)),
+ _tooltips()
+{
+ g_assert(g_utf8_validate(icon.c_str(), -1, NULL));
+ if (icon != "") {
+ _icon = sp_icon_get_icon(icon.c_str(), GTK_ICON_SIZE_LARGE_TOOLBAR);
+ pack_start(*Gtk::manage(_icon), Gtk::PACK_SHRINK);
+ }
+ pack_start(*Gtk::manage(_label), Gtk::PACK_EXPAND_WIDGET, 6);
+ pack_start(*Gtk::manage(_widget), Gtk::PACK_SHRINK, 6);
+ if (mnemonic) {
+ _label->set_mnemonic_widget(*_widget);
+ }
+ _tooltips.set_tip(*_widget, tooltip);
+}
+
+
+/**
+ * Allow the setting of the width of the labelled widget
+ */
+void Labelled::setWidgetSizeRequest(int width, int height)
+{
+ if (_widget)
+ _widget->set_size_request(width, height);
+
+
+}
+
+const Gtk::Widget* const
+Labelled::getWidget() const
+{
+ return _widget;
+}
+
+const Gtk::Label* const
+Labelled::getLabel() const
+{
+ return _label;
+}
+
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/labelled.h b/src/ui/widget/labelled.h
new file mode 100644
index 000000000..1823aeef2
--- /dev/null
+++ b/src/ui/widget/labelled.h
@@ -0,0 +1,65 @@
+/**
+ * \brief Labelled Widget - Adds a label with optional icon or suffix to
+ * another widget.
+ *
+ * Authors:
+ * Carl Hetherington <inkscape@carlh.net>
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Carl Hetherington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_LABELLED_H
+#define INKSCAPE_UI_WIDGET_LABELLED_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/label.h>
+#include <gtkmm/image.h>
+#include <gtkmm/tooltips.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Labelled : public Gtk::HBox
+{
+public:
+ Labelled(Glib::ustring const &label, Glib::ustring const &tooltip,
+ Gtk::Widget *widget,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ bool mnemonic = true);
+
+ /**
+ * Allow the setting of the width of the labelled widget
+ */
+ void setWidgetSizeRequest(int width, int height);
+ const Gtk::Widget* const getWidget() const;
+ const Gtk::Label* const getLabel() const;
+
+protected:
+ Gtk::Widget *_widget;
+ Gtk::Label *_label;
+ Gtk::Label *_suffix;
+ Gtk::Widget *_icon;
+ Gtk::Tooltips _tooltips;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_LABELLED_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/licensor.cpp b/src/ui/widget/licensor.cpp
new file mode 100644
index 000000000..9a5713220
--- /dev/null
+++ b/src/ui/widget/licensor.cpp
@@ -0,0 +1,146 @@
+/** \file
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/entry.h>
+
+#include "ui/widget/entity-entry.h"
+#include "ui/widget/registry.h"
+#include "dialogs/rdf.h"
+#include "inkscape.h"
+
+#include "licensor.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+const struct rdf_license_t _proprietary_license =
+ {_("Proprietary"), "", 0};
+
+class LicenseItem : public Gtk::RadioButton {
+public:
+ LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr);
+protected:
+ void on_toggled();
+ struct rdf_license_t const *_lic;
+ EntityEntry *_eep;
+ Registry &_wr;
+};
+
+LicenseItem::LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr)
+: Gtk::RadioButton(license->name), _lic(license), _eep(entity), _wr(wr)
+{
+ static Gtk::RadioButtonGroup group = get_group();
+ static bool first = true;
+ if (first) first = false;
+ else set_group (group);
+}
+
+/// \pre it is assumed that the license URI entry is a Gtk::Entry
+void
+LicenseItem::on_toggled()
+{
+ if (_wr.isUpdating()) return;
+
+ _wr.setUpdating (true);
+ rdf_set_license (SP_ACTIVE_DOCUMENT, _lic->details ? _lic : 0);
+ sp_document_done (SP_ACTIVE_DOCUMENT);
+ _wr.setUpdating (false);
+ reinterpret_cast<Gtk::Entry*>(_eep->_packable)->set_text (_lic->uri);
+ _eep->on_changed();
+}
+
+//---------------------------------------------------
+
+Licensor::Licensor()
+: Gtk::VBox(false,4)
+{
+}
+
+Licensor::~Licensor()
+{
+ if (_eentry) delete _eentry;
+}
+
+void
+Licensor::init (Gtk::Tooltips& tt, Registry& wr)
+{
+ /* add license-specific metadata entry areas */
+ rdf_work_entity_t* entity = rdf_find_entity ( "license_uri" );
+ _eentry = EntityEntry::create (entity, tt, wr);
+
+ LicenseItem *i;
+ wr.setUpdating (true);
+ i = manage (new LicenseItem (&_proprietary_license, _eentry, wr));
+ add (*i);
+ LicenseItem *pd = i;
+ for (struct rdf_license_t * license = rdf_licenses;
+ license && license->name;
+ license++) {
+ i = manage (new LicenseItem (license, _eentry, wr));
+ add(*i);
+ }
+ pd->set_active();
+ wr.setUpdating (false);
+
+ Gtk::HBox *box = manage (new Gtk::HBox);
+ pack_start (*box, true, true, 0);
+
+ box->pack_start (_eentry->_label, false, false, 5);
+ box->pack_start (*_eentry->_packable, true, true, 0);
+
+ show_all_children();
+}
+
+void
+Licensor::update (SPDocument *doc)
+{
+ /* identify the license info */
+ struct rdf_license_t * license = rdf_get_license (doc);
+
+ if (license) {
+ int i;
+ for (i=0; rdf_licenses[i].name; i++)
+ if (license == &rdf_licenses[i])
+ break;
+ reinterpret_cast<LicenseItem*>(children()[i+1].get_widget())->set_active();
+ }
+ else {
+ reinterpret_cast<LicenseItem*>(children()[0].get_widget())->set_active();
+ }
+
+ /* update the URI */
+ _eentry->update (doc);
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/licensor.h b/src/ui/widget/licensor.h
new file mode 100644
index 000000000..9f41a6d0d
--- /dev/null
+++ b/src/ui/widget/licensor.h
@@ -0,0 +1,59 @@
+/** \file
+ * \brief Widget for specifying a document's license; part of document
+ * preferences dialog.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_LICENSOR__H
+#define INKSCAPE_UI_WIDGET_LICENSOR__H
+
+#include <gtkmm/box.h>
+
+class SPDocument;
+
+namespace Gtk {
+ class Tooltips;
+}
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class EntityEntry;
+class Registry;
+
+
+class Licensor : public Gtk::VBox {
+public:
+ Licensor();
+ virtual ~Licensor();
+ void init (Gtk::Tooltips&, Registry&);
+ void update (SPDocument *doc);
+
+protected:
+ EntityEntry *_eentry;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_LICENSOR__H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/makefile.in b/src/ui/widget/makefile.in
new file mode 100644
index 000000000..2dfa00344
--- /dev/null
+++ b/src/ui/widget/makefile.in
@@ -0,0 +1,17 @@
+# Convenience stub makefile to call the real Makefile.
+
+@SET_MAKE@
+
+# Explicit so that it's the default rule.
+all:
+ cd ../.. && $(MAKE) ui/widget/all
+
+clean %.a %.o:
+ cd ../.. && $(MAKE) ui/widget/$@
+
+.PHONY: all clean
+
+OBJEXT = @OBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .a .$(OBJEXT)
diff --git a/src/ui/widget/notebook-page.cpp b/src/ui/widget/notebook-page.cpp
new file mode 100644
index 000000000..83be16a43
--- /dev/null
+++ b/src/ui/widget/notebook-page.cpp
@@ -0,0 +1,49 @@
+/**
+ * \brief Notebook page widget
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "notebook-page.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a NotebookPage
+ *
+ * \param label Label.
+ */
+
+NotebookPage::NotebookPage(int n_rows, int n_columns)
+ :_table(n_rows, n_columns)
+{
+ set_border_width(2);
+ _table.set_spacings(2);
+ pack_start(_table, false, false, 0);
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/notebook-page.h b/src/ui/widget/notebook-page.h
new file mode 100644
index 000000000..0341cb659
--- /dev/null
+++ b/src/ui/widget/notebook-page.h
@@ -0,0 +1,50 @@
+/**
+ * \brief Notebook Page Widget - A tabbed notebook page for dialogs.
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H
+#define INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/table.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class NotebookPage : public Gtk::VBox
+{
+public:
+ NotebookPage();
+ NotebookPage(int n_rows, int n_columns);
+
+ Gtk::Table& table() { return _table; }
+
+protected:
+ Gtk::Table _table;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp
new file mode 100644
index 000000000..ea0efeb2d
--- /dev/null
+++ b/src/ui/widget/page-sizer.cpp
@@ -0,0 +1,357 @@
+/** \file
+ *
+ * Paper-size widget and helper functions
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <cmath>
+#include <gtkmm/optionmenu.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/table.h>
+
+#include "ui/widget/scalar-unit.h"
+
+#include "helper/units.h"
+#include "inkscape.h"
+#include "desktop-handles.h"
+#include "document.h"
+#include "page-sizer.h"
+
+using std::pair;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+struct PaperSize {
+ char const * const name;
+ double const smaller;
+ double const larger;
+ SPUnitId const unit;
+};
+
+ /** \note
+ * The ISO page sizes in the table below differ from ghostscript's idea of page sizes (by
+ * less than 1pt). Being off by <1pt should be OK for most purposes, but may cause fuzziness
+ * (antialiasing) problems when printing to 72dpi or 144dpi printers or bitmap files due to
+ * postscript's different coordinate system (y=0 meaning bottom of page in postscript and top
+ * of page in SVG). I haven't looked into whether this does in fact cause fuzziness, I merely
+ * note the possibility. Rounding done by extension/internal/ps.cpp (e.g. floor/ceil calls)
+ * will also affect whether fuzziness occurs.
+ *
+ * The remainder of this comment discusses the origin of the numbers used for ISO page sizes in
+ * this table and in ghostscript.
+ *
+ * The versions here, in mm, are the official sizes according to
+ * <a href="http://en.wikipedia.org/wiki/Paper_sizes">http://en.wikipedia.org/wiki/Paper_sizes</a>
+ * at 2005-01-25. (The ISO entries in the below table
+ * were produced mechanically from the table on that page.)
+ *
+ * (The rule seems to be that A0, B0, ..., D0. sizes are rounded to the nearest number of mm
+ * from the "theoretical size" (i.e. 1000 * sqrt(2) or pow(2.0, .25) or the like), whereas
+ * going from e.g. A0 to A1 always take the floor of halving -- which by chance coincides
+ * exactly with flooring the "theoretical size" for n != 0 instead of the rounding to nearest
+ * done for n==0.)
+ *
+ * Ghostscript paper sizes are given in gs_statd.ps according to gs(1). gs_statd.ps always
+ * uses an integer number of pt: sometimes gs_statd.ps rounds to nearest (e.g. a1), sometimes
+ * floors (e.g. a10), sometimes ceils (e.g. a8).
+ *
+ * I'm not sure how ghostscript's gs_statd.ps was calculated: it isn't just rounding the
+ * "theoretical size" of each page to pt (see a0), nor is it rounding the a0 size times an
+ * appropriate power of two (see a1). Possibly it was prepared manually, with a human applying
+ * inconsistent rounding rules when converting from mm to pt.
+ */
+ /** \todo
+ * Should we include the JIS B series (used in Japan)
+ * (JIS B0 is sometimes called JB0, and similarly for JB1 etc)?
+ * Should we exclude B7--B10 and A7--10 to make the list smaller ?
+ * Should we include any of the ISO C, D and E series (see below) ?
+ */
+
+static PaperSize const inkscape_papers[] = {
+ { "A4", 210, 297, SP_UNIT_MM },
+ { "US Letter", 8.5, 11, SP_UNIT_IN },
+ { "US Legal", 8.5, 14, SP_UNIT_IN },
+ { "US Executive", 7.25, 10.5, SP_UNIT_IN },
+ { "A0", 841, 1189, SP_UNIT_MM },
+ { "A1", 594, 841, SP_UNIT_MM },
+ { "A2", 420, 594, SP_UNIT_MM },
+ { "A3", 297, 420, SP_UNIT_MM },
+ { "A5", 148, 210, SP_UNIT_MM },
+ { "A6", 105, 148, SP_UNIT_MM },
+ { "A7", 74, 105, SP_UNIT_MM },
+ { "A8", 52, 74, SP_UNIT_MM },
+ { "A9", 37, 52, SP_UNIT_MM },
+ { "A10", 26, 37, SP_UNIT_MM },
+ { "B0", 1000, 1414, SP_UNIT_MM },
+ { "B1", 707, 1000, SP_UNIT_MM },
+ { "B2", 500, 707, SP_UNIT_MM },
+ { "B3", 353, 500, SP_UNIT_MM },
+ { "B4", 250, 353, SP_UNIT_MM },
+ { "B5", 176, 250, SP_UNIT_MM },
+ { "B6", 125, 176, SP_UNIT_MM },
+ { "B7", 88, 125, SP_UNIT_MM },
+ { "B8", 62, 88, SP_UNIT_MM },
+ { "B9", 44, 62, SP_UNIT_MM },
+ { "B10", 31, 44, SP_UNIT_MM },
+
+#if 0 /* Whether to include or exclude these depends on how big we mind our page size menu
+ becoming. C series is used for envelopes; don't know what D and E series are used for. */
+ { "C0", 917, 1297, SP_UNIT_MM },
+ { "C1", 648, 917, SP_UNIT_MM },
+ { "C2", 458, 648, SP_UNIT_MM },
+ { "C3", 324, 458, SP_UNIT_MM },
+ { "C4", 229, 324, SP_UNIT_MM },
+ { "C5", 162, 229, SP_UNIT_MM },
+ { "C6", 114, 162, SP_UNIT_MM },
+ { "C7", 81, 114, SP_UNIT_MM },
+ { "C8", 57, 81, SP_UNIT_MM },
+ { "C9", 40, 57, SP_UNIT_MM },
+ { "C10", 28, 40, SP_UNIT_MM },
+ { "D1", 545, 771, SP_UNIT_MM },
+ { "D2", 385, 545, SP_UNIT_MM },
+ { "D3", 272, 385, SP_UNIT_MM },
+ { "D4", 192, 272, SP_UNIT_MM },
+ { "D5", 136, 192, SP_UNIT_MM },
+ { "D6", 96, 136, SP_UNIT_MM },
+ { "D7", 68, 96, SP_UNIT_MM },
+ { "E3", 400, 560, SP_UNIT_MM },
+ { "E4", 280, 400, SP_UNIT_MM },
+ { "E5", 200, 280, SP_UNIT_MM },
+ { "E6", 140, 200, SP_UNIT_MM },
+#endif
+
+ { "CSE", 462, 649, SP_UNIT_PT },
+ { "US #10 Envelope", 4.125, 9.5, SP_UNIT_IN }, // TODO: Select landscape by default.
+ /* See http://www.hbp.com/content/PCR_envelopes.cfm for a much larger list of US envelope
+ sizes. */
+ { "DL Envelope", 110, 220, SP_UNIT_MM }, // TODO: Select landscape by default.
+ { "Ledger/Tabloid", 11, 17, SP_UNIT_IN },
+ /* Note that `Folio' (used in QPrinter/KPrinter) is deliberately absent from this list, as it
+ means different sizes to different people: different people may expect the width to be
+ either 8, 8.25 or 8.5 inches, and the height to be either 13 or 13.5 inches, even
+ restricting our interpretation to foolscap folio. If you wish to introduce a folio-like
+ page size to the list, then please consider using a name more specific than just `Folio' or
+ `Foolscap Folio'. */
+ { "Banner 468x60", 60, 468, SP_UNIT_PX }, // TODO: Select landscape by default.
+ { "Icon 16x16", 16, 16, SP_UNIT_PX },
+ { "Icon 32x32", 32, 32, SP_UNIT_PX },
+ { NULL, 0, 0, SP_UNIT_PX },
+};
+
+//===================================================
+static const SPUnit _px_unit = sp_unit_get_by_id (SP_UNIT_PX);
+
+class SizeMenuItem : public Gtk::MenuItem {
+public:
+ SizeMenuItem (PaperSize const * paper, PageSizer * widget)
+ : Gtk::MenuItem (paper ? paper->name : _("Custom")),
+ _paper(paper), _parent(widget) {}
+protected:
+ PaperSize const * _paper;
+ PageSizer *_parent;
+ void on_activate();
+};
+
+void
+SizeMenuItem::on_activate()
+{
+ if (_parent == 0) // handle Custom entry
+ return;
+
+ double w = _paper->smaller, h = _paper->larger;
+ SPUnit const &src_unit = sp_unit_get_by_id (_paper->unit);
+ sp_convert_distance (&w, &src_unit, &_px_unit);
+ sp_convert_distance (&h, &src_unit, &_px_unit);
+ if (_parent->_landscape)
+ _parent->setDim (h, w, true);
+ else
+ _parent->setDim (w, h, true);
+}
+
+//---------------------------------------------------
+
+PageSizer::PageSizer()
+: Gtk::VBox(false,4)
+{
+ Gtk::HBox *hbox_size = manage (new Gtk::HBox (false, 4));
+ pack_start (*hbox_size, false, false, 0);
+ Gtk::Label *label_size = manage (new Gtk::Label (_("Page size:"), 1.0, 0.5));
+ hbox_size->pack_start (*label_size, false, false, 0);
+ _omenu_size = manage (new Gtk::OptionMenu);
+ hbox_size->pack_start (*_omenu_size, true, true, 0);
+ Gtk::Menu *menu_size = manage (new Gtk::Menu);
+
+ for (PaperSize const *paper = inkscape_papers; paper->name; paper++) {
+ SizeMenuItem *item = manage (new SizeMenuItem (paper, this));
+ menu_size->append (*item);
+ }
+ SizeMenuItem *item = manage (new SizeMenuItem (0, 0));
+ menu_size->prepend (*item);
+ _omenu_size->set_menu (*menu_size);
+}
+
+PageSizer::~PageSizer()
+{
+ _portrait_connection.disconnect();
+ _landscape_connection.disconnect();
+ _changedw_connection.disconnect();
+ _changedh_connection.disconnect();
+}
+
+void
+PageSizer::init (Registry& reg)
+{
+ Gtk::HBox *hbox_ori = manage (new Gtk::HBox);
+ pack_start (*hbox_ori, false, false, 0);
+ Gtk::Label *label_ori = manage (new Gtk::Label (_("Page orientation:"), 0.0, 0.5));
+ hbox_ori->pack_start (*label_ori, false, false, 0);
+ _rb_land = manage (new Gtk::RadioButton (_("Landscape")));
+ Gtk::RadioButton::Group group = _rb_land->get_group();
+ hbox_ori->pack_end (*_rb_land, false, false, 5);
+ _rb_port = manage (new Gtk::RadioButton (_("Portrait")));
+ hbox_ori->pack_end (*_rb_port, false, false, 5);
+ _rb_port->set_group (group);
+ _rb_port->set_active (true);
+
+ /* Custom paper frame */
+ Gtk::Frame *frame = manage (new Gtk::Frame(_("Custom size")));
+ pack_start (*frame, false, false, 0);
+ Gtk::Table *table = manage (new Gtk::Table (4, 2, false));
+ table->set_border_width (4);
+ table->set_row_spacings (4);
+ table->set_col_spacings (4);
+ frame->add (*table);
+
+ _wr = &reg;
+
+ _rum.init (_("Units:"), "units", *_wr);
+ _rusw.init (_("Width:"), _("Width of paper"), "width", _rum, *_wr);
+ _rush.init (_("Height:"), _("Height of paper"), "height", _rum, *_wr);
+
+ table->attach (*_rum._label, 0,1,0,1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ table->attach (*_rum._sel, 1,2,0,1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ table->attach (*_rusw.getSU(), 0,2,1,2, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+ table->attach (*_rush.getSU(), 0,2,2,3, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
+
+ _landscape_connection = _rb_land->signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_landscape));
+ _portrait_connection = _rb_port->signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_portrait));
+ _changedw_connection = _rusw.getSU()->signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed));
+ _changedh_connection = _rush.getSU()->signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed));
+
+ show_all_children();
+}
+
+/**
+ * \param w, h given in px
+ */
+void
+PageSizer::setDim (double w, double h, bool update)
+{
+ _landscape = w>h;
+ _rb_land->set_active (_landscape ? true : false);
+ _rb_port->set_active (_landscape ? false : true);
+ _omenu_size->set_history (1 + find_paper_size (w, h));
+
+ Unit const& unit = _rum._sel->getUnit();
+ if (!update) _changedw_connection.block();
+ _rusw.setValue (w / unit.factor);
+ if (!update) _changedw_connection.unblock();
+ if (!update) _changedh_connection.block();
+ _rush.setValue (h / unit.factor);
+ if (!update) _changedh_connection.unblock();
+}
+
+void
+PageSizer::setDoc (double w, double h)
+{
+ setDim (w, h);
+ if (!SP_ACTIVE_DESKTOP || _wr->isUpdating())
+ return;
+
+ SPDocument *doc = SP_DT_DOCUMENT(SP_ACTIVE_DESKTOP);
+ sp_document_set_width (doc, _rusw.getSU()->getValue("px"), &_px_unit);
+ sp_document_set_height (doc, _rush.getSU()->getValue("px"), &_px_unit);
+ sp_document_done (doc);
+}
+
+/**
+ * Returns an index into inkscape_papers of a paper of the specified
+ * size (specified in px), or -1 if there's no such paper.
+ */
+int
+PageSizer::find_paper_size (double w, double h) const
+{
+ double given[2];
+ if ( w < h ) {
+ given[0] = w; given[1] = h;
+ } else {
+ given[0] = h; given[1] = w;
+ }
+ g_return_val_if_fail(given[0] <= given[1], -1);
+ for (unsigned i = 0; i < G_N_ELEMENTS(inkscape_papers) - 1; ++i) {
+ SPUnit const &i_unit = sp_unit_get_by_id(inkscape_papers[i].unit);
+ double const i_sizes[2] = { sp_units_get_pixels(inkscape_papers[i].smaller, i_unit),
+ sp_units_get_pixels(inkscape_papers[i].larger, i_unit) };
+ g_return_val_if_fail(i_sizes[0] <= i_sizes[1], -1);
+ if ((std::abs(given[0] - i_sizes[0]) <= .1) &&
+ (std::abs(given[1] - i_sizes[1]) <= .1) )
+ {
+ return (int) i;
+ }
+ }
+ return -1;
+}
+
+void
+PageSizer::on_portrait()
+{
+ double w = _rusw.getSU()->getValue ("px");
+ double h = _rush.getSU()->getValue ("px");
+ if (h<w) setDoc (h, w);
+}
+
+void
+PageSizer::on_landscape()
+{
+ double w = _rusw.getSU()->getValue ("px");
+ double h = _rush.getSU()->getValue ("px");
+ if (w<h) setDoc (h, w);
+}
+
+void
+PageSizer::on_value_changed()
+{
+ if (_wr->isUpdating()) return;
+
+ setDoc (_rusw.getSU()->getValue("px"), _rush.getSU()->getValue("px"));
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h
new file mode 100644
index 000000000..e17628c76
--- /dev/null
+++ b/src/ui/widget/page-sizer.h
@@ -0,0 +1,67 @@
+/** \file
+ * \brief Widget for specifying page size; part of Document Preferences dialog.
+ *
+ * Author:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_PAGE_SIZER__H
+#define INKSCAPE_UI_WIDGET_PAGE_SIZER__H
+
+#include <sigc++/sigc++.h>
+#include <gtkmm/box.h>
+#include "ui/widget/registry.h"
+#include "ui/widget/registered-widget.h"
+
+namespace Gtk {
+ class OptionMenu;
+ class RadioButton;
+}
+
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+/// Widget containing all widgets for specifying page size.
+class PageSizer : public Gtk::VBox {
+public:
+ PageSizer();
+ virtual ~PageSizer();
+ void init (Registry& reg);
+ void setDim (double w, double h, bool update = false);
+ bool _landscape;
+
+protected:
+ void setDoc (double w, double h);
+ int find_paper_size (double w, double h) const;
+ void on_portrait();
+ void on_landscape();
+ void on_value_changed();
+
+ RegisteredUnitMenu _rum;
+ RegisteredScalarUnit _rusw, _rush;
+ Gtk::OptionMenu *_omenu_size;
+ Gtk::RadioButton *_rb_port, *_rb_land;
+ sigc::connection _portrait_connection, _landscape_connection;
+ sigc::connection _changedw_connection, _changedh_connection;
+ Registry *_wr;
+};
+
+}}}
+
+#endif /* INKSCAPE_UI_WIDGET_PAGE_SIZER__H */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp
new file mode 100644
index 000000000..67aca690a
--- /dev/null
+++ b/src/ui/widget/panel.cpp
@@ -0,0 +1,248 @@
+/**
+ * \brief Panel widget
+ *
+ * Authors:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ * Copyright (C) 2005 Jon A. Cruz
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glibmm/i18n.h>
+
+#include "panel.h"
+#include "../../prefs-utils.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a Panel
+ *
+ * \param label Label.
+ */
+
+Panel::Panel(const gchar *prefs_path) :
+ _prefs_path(NULL),
+ _fillable(0)
+{
+ _prefs_path = prefs_path;
+ init();
+}
+
+Panel::Panel() :
+ _prefs_path(NULL),
+ _fillable(0)
+{
+ init();
+}
+
+Panel::Panel(Glib::ustring const &label) :
+ _prefs_path(NULL),
+ _fillable(0)
+{
+ this->label = label;
+ init();
+}
+
+Panel::~Panel()
+{
+}
+
+void Panel::init()
+{
+ Glib::ustring tmp("<");
+ tabTitle.set_label(this->label);
+
+ guint panel_size = 0;
+ if (_prefs_path) {
+ panel_size = prefs_get_int_attribute_limited (_prefs_path, "panel_size", 1, 0, 10);
+ }
+
+ guint panel_mode = 0;
+ if (_prefs_path) {
+ panel_mode = prefs_get_int_attribute_limited (_prefs_path, "panel_mode", 1, 0, 10);
+ }
+
+ tabButton.set_menu(menu);
+ Gtk::MenuItem* dummy = manage(new Gtk::MenuItem(tmp));
+ menu.append( *dummy );
+ menu.append( *manage(new Gtk::SeparatorMenuItem()) );
+ {
+ const char *things[] = {
+ N_("small"),
+ N_("medium"),
+ N_("large"),
+ N_("huge")
+ };
+ Gtk::RadioMenuItem::Group groupOne;
+ for ( unsigned int i = 0; i < G_N_ELEMENTS(things); i++ ) {
+ Glib::ustring foo(gettext(things[i]));
+ Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, foo));
+ menu.append(*single);
+ if ( i == panel_size ) {
+ single->set_active(true);
+ }
+ single->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), 0, i) );
+ }
+ }
+ menu.append( *manage(new Gtk::SeparatorMenuItem()) );
+ Gtk::RadioMenuItem::Group group;
+ Glib::ustring oneLab(_("List"));
+ Glib::ustring twoLab(_("Grid"));
+ Gtk::RadioMenuItem *one = manage(new Gtk::RadioMenuItem(group, oneLab));
+ Gtk::RadioMenuItem *two = manage(new Gtk::RadioMenuItem(group, twoLab));
+
+ if (panel_mode == 0) {
+ one->set_active(true);
+ } else if (panel_mode == 1) {
+ two->set_active(true);
+ }
+
+ menu.append( *one );
+ menu.append( *two );
+ menu.append( *manage(new Gtk::SeparatorMenuItem()) );
+ one->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), 1, 0) );
+ two->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), 1, 1) );
+
+ closeButton.set_label("X");
+
+ topBar.pack_start(tabTitle);
+
+ topBar.pack_end(closeButton, false, false);
+ topBar.pack_end(tabButton, false, false);
+
+ pack_start( topBar, false, false );
+
+ show_all_children();
+
+ bounceCall (0, panel_size);
+ bounceCall (1, panel_mode);
+}
+
+void Panel::setLabel(Glib::ustring const &label)
+{
+ this->label = label;
+ tabTitle.set_label(this->label);
+}
+
+void Panel::_regItem( Gtk::MenuItem* item, int group, int id )
+{
+ menu.append( *item );
+ item->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), group + 2, id) );
+}
+
+void Panel::restorePanelPrefs()
+{
+ guint panel_size = 0;
+ if (_prefs_path) {
+ panel_size = prefs_get_int_attribute_limited (_prefs_path, "panel_size", 1, 0, 10);
+ }
+ guint panel_mode = 0;
+ if (_prefs_path) {
+ panel_mode = prefs_get_int_attribute_limited (_prefs_path, "panel_mode", 1, 0, 10);
+ }
+ bounceCall (0, panel_size);
+ bounceCall (1, panel_mode);
+}
+
+void Panel::bounceCall(int i, int j)
+{
+ menu.set_active(0);
+ switch ( i ) {
+ case 0:
+ if (_prefs_path) prefs_set_int_attribute (_prefs_path, "panel_size", j);
+ if ( _fillable ) {
+ ViewType currType = _fillable->getPreviewType();
+ switch ( j ) {
+ case 0:
+ {
+ _fillable->setStyle(Gtk::ICON_SIZE_MENU, currType);
+ }
+ break;
+ case 1:
+ {
+ _fillable->setStyle(Gtk::ICON_SIZE_SMALL_TOOLBAR, currType);
+ }
+ break;
+ case 2:
+ {
+ _fillable->setStyle(Gtk::ICON_SIZE_BUTTON, currType);
+ }
+ break;
+ case 3:
+ {
+ _fillable->setStyle(Gtk::ICON_SIZE_DIALOG, currType);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ break;
+ case 1:
+ if (_prefs_path) prefs_set_int_attribute (_prefs_path, "panel_mode", j);
+ if ( _fillable ) {
+ Gtk::BuiltinIconSize currSize = _fillable->getPreviewSize();
+ switch ( j ) {
+ case 0:
+ {
+ _fillable->setStyle(currSize, VIEW_TYPE_LIST);
+ }
+ break;
+ case 1:
+ {
+ _fillable->setStyle(currSize, VIEW_TYPE_GRID);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ _handleAction( i - 2, j );
+ }
+}
+
+
+
+
+
+Glib::ustring const &Panel::getLabel() const
+{
+ return label;
+}
+
+void Panel::_setTargetFillable( PreviewFillable *target )
+{
+ _fillable = target;
+}
+
+void Panel::_handleAction( int setId, int itemId )
+{
+// for subclasses to override
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/panel.h b/src/ui/widget/panel.h
new file mode 100644
index 000000000..07225b8ce
--- /dev/null
+++ b/src/ui/widget/panel.h
@@ -0,0 +1,80 @@
+/**
+ * \brief Generic Panel widget - A generic dockable container.
+ *
+ * Authors:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ * Copyright (C) 2005 Jon A. Cruz
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef SEEN_INKSCAPE_UI_WIDGET_PANEL_H
+#define SEEN_INKSCAPE_UI_WIDGET_PANEL_H
+
+#include <gtkmm/box.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/table.h>
+#include <gtkmm/button.h>
+#include <gtkmm/label.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/optionmenu.h>
+#include "../previewfillable.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Panel : public Gtk::VBox
+{
+public:
+ Panel();
+ virtual ~Panel();
+ Panel(Glib::ustring const &label);
+ Panel(const gchar *prefs_path);
+
+ void setLabel(Glib::ustring const &label);
+ Glib::ustring const &getLabel() const;
+
+ const gchar *_prefs_path;
+ void restorePanelPrefs();
+
+protected:
+ void _setTargetFillable( PreviewFillable *target );
+ void _regItem( Gtk::MenuItem* item, int group, int id );
+
+ virtual void _handleAction( int setId, int itemId );
+
+
+private:
+ void init();
+ void bounceCall(int i, int j);
+
+ Glib::ustring label;
+
+ Gtk::HBox topBar;
+ Gtk::Label tabTitle;
+ Gtk::OptionMenu tabButton;
+ Gtk::Menu menu;
+ Gtk::Button closeButton;
+ PreviewFillable *_fillable;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // SEEN_INKSCAPE_UI_WIDGET_PANEL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp
new file mode 100644
index 000000000..cc389c611
--- /dev/null
+++ b/src/ui/widget/preferences-widget.cpp
@@ -0,0 +1,278 @@
+/**
+ * \brief Inkscape Preferences dialog
+ *
+ * Authors:
+ * Marco Scholten
+ *
+ * Copyright (C) 2004, 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/frame.h>
+#include <gtkmm/alignment.h>
+#include <gtkmm/box.h>
+
+#include "prefs-utils.h"
+#include "ui/widget/preferences-widget.h"
+#include "verbs.h"
+#include "selcue.h"
+#include <iostream>
+#include "enums.h"
+#include "inkscape.h"
+#include "desktop-handles.h"
+#include "message-stack.h"
+#include "style.h"
+#include "selection.h"
+#include "selection-chemistry.h"
+#include "xml/repr.h"
+
+using namespace Inkscape::UI::Widget;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+DialogPage::DialogPage()
+{
+ this->set_border_width(12);
+ this->set_col_spacings(12);
+ this->set_row_spacings(6);
+}
+
+void DialogPage::add_line(bool indent, const Glib::ustring label, Gtk::Widget& widget, const Glib::ustring suffix, const Glib::ustring& tip, bool expand_widget)
+{
+ int start_col;
+ int row = this->property_n_rows();
+ Gtk::Widget* w;
+ if (expand_widget)
+ {
+ w = &widget;
+ }
+ else
+ {
+ Gtk::HBox* hb = Gtk::manage(new Gtk::HBox());
+ hb->set_spacing(12);
+ hb->pack_start(widget,false,false);
+ w = (Gtk::Widget*) hb;
+ }
+ if (label != "")
+ {
+ Gtk::Label* label_widget;
+ label_widget = Gtk::manage(new Gtk::Label(label , Gtk::ALIGN_LEFT , Gtk::ALIGN_CENTER, true));
+ label_widget->set_mnemonic_widget(widget);
+ if (indent)
+ {
+ Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment());
+ alignment->set_padding(0, 0, 12, 0);
+ alignment->add(*label_widget);
+ this->attach(*alignment , 0, 1, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0);
+ }
+ else
+ this->attach(*label_widget , 0, 1, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0);
+ start_col = 1;
+ }
+ else
+ start_col = 0;
+
+ if (start_col == 0 && indent) //indent this widget
+ {
+ Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment());
+ alignment->set_padding(0, 0, 12, 0);
+ alignment->add(*w);
+ this->attach(*alignment, start_col, 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::AttachOptions(), 0, 0);
+ }
+ else
+ {
+ this->attach(*w, start_col, 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::AttachOptions(), 0, 0);
+ }
+
+ if (suffix != "")
+ {
+ Gtk::Label* suffix_widget = Gtk::manage(new Gtk::Label(suffix , Gtk::ALIGN_LEFT , Gtk::ALIGN_CENTER, true));
+ if (expand_widget)
+ this->attach(*suffix_widget, 2, 3, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0);
+ else
+ ((Gtk::HBox*)w)->pack_start(*suffix_widget,false,false);
+ }
+
+ if (tip != "")
+ {
+ _tooltips.set_tip (widget, tip);
+ }
+
+}
+
+void DialogPage::add_group_header(Glib::ustring name)
+{
+ int row = this->property_n_rows();
+ if (name != "")
+ {
+ Gtk::Label* label_widget = Gtk::manage(new Gtk::Label(Glib::ustring(/*"<span size='large'>*/"<b>") + name +
+ Glib::ustring("</b>"/*</span>"*/) , Gtk::ALIGN_LEFT , Gtk::ALIGN_CENTER, true));
+ label_widget->set_use_markup(true);
+ this->attach(*label_widget , 0, 4, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0);
+ if (row != 1)
+ this->set_row_spacing(row - 1, 18);
+ }
+}
+
+void PrefCheckButton::init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ bool default_value)
+{
+ _prefs_path = prefs_path;
+ _attr = attr;
+ this->set_label(label);
+ this->set_active( prefs_get_int_attribute (_prefs_path.c_str(), _attr.c_str(), (int)default_value) );
+}
+
+void PrefCheckButton::on_toggled()
+{
+ if (this->is_visible()) //only take action if the user toggled it
+ {
+ prefs_set_int_attribute (_prefs_path.c_str(), _attr.c_str(), (int) this->get_active());
+ }
+}
+
+void PrefRadioButton::init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ const std::string& string_value, bool default_value, PrefRadioButton* group_member)
+{
+ _value_type = VAL_STRING;
+ _prefs_path = prefs_path;
+ _attr = attr;
+ _string_value = string_value;
+ this->set_label(label);
+ if (group_member)
+ {
+ Gtk::RadioButtonGroup rbg = group_member->get_group();
+ this->set_group(rbg);
+ }
+ const gchar* val = prefs_get_string_attribute( _prefs_path.c_str(), _attr.c_str() );
+ if ( val )
+ this->set_active( std::string( val ) == _string_value);
+ else
+ this->set_active( false );
+}
+
+void PrefRadioButton::init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ int int_value, bool default_value, PrefRadioButton* group_member)
+{
+ _value_type = VAL_INT;
+ _prefs_path = prefs_path;
+ _attr = attr;
+ _int_value = int_value;
+ this->set_label(label);
+ if (group_member)
+ {
+ Gtk::RadioButtonGroup rbg = group_member->get_group();
+ this->set_group(rbg);
+ }
+ if (default_value)
+ this->set_active( prefs_get_int_attribute( _prefs_path.c_str(), _attr.c_str(), int_value ) == _int_value);
+ else
+ this->set_active( prefs_get_int_attribute( _prefs_path.c_str(), _attr.c_str(), int_value + 1 )== _int_value);
+}
+
+void PrefRadioButton::on_toggled()
+{
+ this->changed_signal.emit(this->get_active());
+ if (this->is_visible() && this->get_active() ) //only take action if toggled by user (to active)
+ {
+ if ( _value_type == VAL_STRING )
+ prefs_set_string_attribute ( _prefs_path.c_str(), _attr.c_str(), _string_value.c_str());
+ else if ( _value_type == VAL_INT )
+ prefs_set_int_attribute ( _prefs_path.c_str(), _attr.c_str(), _int_value);
+ }
+}
+
+void PrefSpinButton::init(const std::string& prefs_path, const std::string& attr,
+ double lower, double upper, double step_increment, double page_increment,
+ double default_value, bool is_int, bool is_percent)
+{
+ _prefs_path = prefs_path;
+ _attr = attr;
+ _is_int = is_int;
+ _is_percent = is_percent;
+
+ double value;
+ if (is_int)
+ if (is_percent)
+ value = 100 * prefs_get_double_attribute_limited (prefs_path.c_str(), attr.c_str(), default_value, lower/100.0, upper/100.0);
+ else
+ value = (double) prefs_get_int_attribute_limited (prefs_path.c_str(), attr.c_str(), (int) default_value, (int) lower, (int) upper);
+ else
+ value = prefs_get_double_attribute_limited (prefs_path.c_str(), attr.c_str(), default_value, lower, upper);
+
+ this->set_range (lower, upper);
+ this->set_increments (step_increment, page_increment);
+ this->set_numeric();
+ this->set_value (value);
+ this->set_width_chars(6);
+ if (is_int)
+ this->set_digits(0);
+ else if (step_increment < 0.1)
+ this->set_digits(3);
+ else
+ this->set_digits(2);
+
+}
+
+void PrefSpinButton::on_value_changed()
+{
+ if (this->is_visible()) //only take action if user changed value
+ {
+ if (_is_int)
+ if (_is_percent)
+ prefs_set_double_attribute(_prefs_path.c_str(), _attr.c_str(), this->get_value()/100.0);
+ else
+ prefs_set_int_attribute(_prefs_path.c_str(), _attr.c_str(), (int) this->get_value());
+ else
+ prefs_set_double_attribute (_prefs_path.c_str(), _attr.c_str(), this->get_value());
+ }
+}
+
+void PrefCombo::init(const std::string& prefs_path, const std::string& attr,
+ Glib::ustring labels[], int values[], int num_items, int default_value)
+{
+ _prefs_path = prefs_path;
+ _attr = attr;
+ int row = 0;
+ int value = prefs_get_int_attribute (_prefs_path.c_str(), _attr.c_str(), default_value);
+
+ for (int i = 0 ; i < num_items; ++i)
+ {
+ this->append_text(labels[i]);
+ _values.push_back(values[i]);
+ if (value == values[i])
+ row = i;
+ }
+ this->set_active(row);
+}
+
+void PrefCombo::on_changed()
+{
+ if (this->is_visible()) //only take action if user changed value
+ {
+ prefs_set_int_attribute (_prefs_path.c_str(), _attr.c_str(), _values[this->get_active_row_number()]);
+ std::cout << "combo set: " << _prefs_path << " " << _attr << " " << _values[this->get_active_row_number()] << std::endl;
+ }
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h
new file mode 100644
index 000000000..a5a594114
--- /dev/null
+++ b/src/ui/widget/preferences-widget.h
@@ -0,0 +1,117 @@
+/**
+ * \brief Inkscape Preferences dialog
+ *
+ * Authors:
+ * Marco Scholten
+ *
+ * Copyright (C) 2004, 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_INKSCAPE_PREFERENCES_H
+#define INKSCAPE_UI_WIDGET_INKSCAPE_PREFERENCES_H
+
+#include <iostream>
+#include <vector>
+#include <gtkmm/table.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/tooltips.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/radiobutton.h>
+#include <gtkmm/frame.h>
+#include <sigc++/sigc++.h>
+//#include <glibmm/i18n.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class PrefCheckButton : public Gtk::CheckButton
+{
+public:
+ void init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ bool default_value);
+protected:
+ std::string _prefs_path;
+ std::string _attr;
+ bool _int_value;
+ void on_toggled();
+};
+
+class PrefRadioButton : public Gtk::RadioButton
+{
+public:
+ void init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ int int_value, bool default_value, PrefRadioButton* group_member);
+ void init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr,
+ const std::string& string_value, bool default_value, PrefRadioButton* group_member);
+ sigc::signal<void, bool> changed_signal;
+protected:
+ std::string _prefs_path;
+ std::string _attr;
+ std::string _string_value;
+ int _value_type;
+ enum
+ {
+ VAL_INT,
+ VAL_STRING
+ };
+ int _int_value;
+ void on_toggled();
+};
+
+class PrefSpinButton : public Gtk::SpinButton
+{
+public:
+ void init(const std::string& prefs_path, const std::string& attr,
+ double lower, double upper, double step_increment, double page_increment,
+ double default_value, bool is_int, bool is_percent);
+protected:
+ std::string _prefs_path;
+ std::string _attr;
+ bool _is_int;
+ bool _is_percent;
+ void on_value_changed();
+};
+
+class PrefCombo : public Gtk::ComboBoxText
+{
+public:
+ void init(const std::string& prefs_path, const std::string& attr,
+ Glib::ustring labels[], int values[], int num_items, int default_value);
+protected:
+ std::string _prefs_path;
+ std::string _attr;
+ std::vector<int> _values;
+ void on_changed();
+};
+
+class DialogPage : public Gtk::Table
+{
+public:
+ DialogPage();
+ void add_line(bool indent, const Glib::ustring label, Gtk::Widget& widget, const Glib::ustring suffix, const Glib::ustring& tip, bool expand = true);
+ void add_group_header(Glib::ustring name);
+protected:
+ Gtk::Tooltips _tooltips;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif //INKSCAPE_UI_WIDGET_INKSCAPE_PREFERENCES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp
new file mode 100644
index 000000000..918742e75
--- /dev/null
+++ b/src/ui/widget/registered-widget.cpp
@@ -0,0 +1,409 @@
+/** \file
+ *
+ *
+ * Authors:
+ * bulia byak <buliabyak@users.sf.net>
+ * Bryce W. Harrington <bryce@bryceharrington.org>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Jon Phillips <jon@rejon.org>
+ * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *
+ * Copyright (C) 2000 - 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include "ui/widget/color-picker.h"
+#include "ui/widget/registry.h"
+#include "ui/widget/scalar-unit.h"
+
+#include "helper/units.h"
+#include "xml/repr.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+
+#include "inkscape.h"
+#include "document.h"
+#include "desktop-handles.h"
+#include "sp-namedview.h"
+
+#include "registered-widget.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+//---------------------------------------------------
+
+
+
+//====================================================
+
+RegisteredCheckButton::RegisteredCheckButton()
+: _button(0)
+{
+}
+
+RegisteredCheckButton::~RegisteredCheckButton()
+{
+ _toggled_connection.disconnect();
+ if (_button) delete _button;
+}
+
+void
+RegisteredCheckButton::init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right)
+{
+ _button = new Gtk::CheckButton;
+ _tt.set_tip (*_button, tip);
+ _button->add (*manage (new Gtk::Label (label)));
+ _button->set_alignment (right? 1.0 : 0.0, 0.5);
+ _key = key;
+ _wr = &wr;
+ _toggled_connection = _button->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
+}
+
+void
+RegisteredCheckButton::setActive (bool b)
+{
+ _button->set_active (b);
+}
+
+void
+RegisteredCheckButton::on_toggled()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt) {
+ return;
+ }
+
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ _wr->setUpdating (true);
+
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ sp_repr_set_boolean(repr, _key.c_str(), _button->get_active());
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+RegisteredUnitMenu::RegisteredUnitMenu()
+: _label(0), _sel(0)
+{
+}
+
+RegisteredUnitMenu::~RegisteredUnitMenu()
+{
+ _changed_connection.disconnect();
+ if (_label) delete _label;
+ if (_sel) delete _sel;
+}
+
+void
+RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr)
+{
+ _label = new Gtk::Label (label, 1.0, 0.5);
+ _sel = new UnitMenu ();
+ _sel->setUnitType (UNIT_TYPE_LINEAR);
+ _wr = &wr;
+ _key = key;
+ _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
+}
+
+void
+RegisteredUnitMenu::setUnit (const SPUnit* unit)
+{
+ _sel->setUnit (sp_unit_get_abbreviation (unit));
+}
+
+void
+RegisteredUnitMenu::on_changed()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt)
+ return;
+
+ Inkscape::SVGOStringStream os;
+ os << _sel->getUnitAbbr();
+
+ _wr->setUpdating (true);
+
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ repr->setAttribute(_key.c_str(), os.str().c_str());
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+
+RegisteredScalarUnit::RegisteredScalarUnit()
+: _widget(0), _um(0)
+{
+}
+
+RegisteredScalarUnit::~RegisteredScalarUnit()
+{
+ if (_widget) delete _widget;
+ _value_changed_connection.disconnect();
+}
+
+void
+RegisteredScalarUnit::init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, const RegisteredUnitMenu &rum, Registry& wr)
+{
+ _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel);
+ _widget->initScalar (-1e6, 1e6);
+ _widget->setUnit (rum._sel->getUnitAbbr());
+ _widget->setDigits (2);
+ _key = key;
+ _um = rum._sel;
+ _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
+ _wr = &wr;
+}
+
+ScalarUnit*
+RegisteredScalarUnit::getSU()
+{
+ return _widget;
+}
+
+void
+RegisteredScalarUnit::setValue (double val)
+{
+ _widget->setValue (val);
+ on_value_changed();
+}
+
+void
+RegisteredScalarUnit::on_value_changed()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt)
+ return;
+
+ Inkscape::SVGOStringStream os;
+ os << _widget->getValue("");
+ if (_um)
+ os << _um->getUnitAbbr();
+
+ _wr->setUpdating (true);
+
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ repr->setAttribute(_key.c_str(), os.str().c_str());
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+RegisteredColorPicker::RegisteredColorPicker()
+: _label(0), _cp(0)
+{
+}
+
+RegisteredColorPicker::~RegisteredColorPicker()
+{
+ _changed_connection.disconnect();
+ if (_cp) delete _cp;
+ if (_label) delete _label;
+}
+
+void
+RegisteredColorPicker::init (const Glib::ustring& label, const Glib::ustring& title, const Glib::ustring& tip, const Glib::ustring& ckey, const Glib::ustring& akey, Registry& wr)
+{
+ _label = new Gtk::Label (label, 1.0, 0.5);
+ _cp = new ColorPicker (title,tip,0,true);
+ _ckey = ckey;
+ _akey = akey;
+ _wr = &wr;
+ _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
+}
+
+void
+RegisteredColorPicker::setRgba32 (guint32 rgba)
+{
+ _cp->setRgba32 (rgba);
+}
+
+void
+RegisteredColorPicker::closeWindow()
+{
+ _cp->closeWindow();
+}
+
+void
+RegisteredColorPicker::on_changed (guint32 rgba)
+{
+ if (_wr->isUpdating() || !SP_ACTIVE_DESKTOP)
+ return;
+
+ _wr->setUpdating (true);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP));
+ gchar c[32];
+ sp_svg_write_color(c, 32, rgba);
+ repr->setAttribute(_ckey.c_str(), c);
+ sp_repr_set_css_double(repr, _akey.c_str(), (rgba & 0xff) / 255.0);
+ _wr->setUpdating (false);
+}
+
+RegisteredSuffixedInteger::RegisteredSuffixedInteger()
+: _label(0), _sb(0),
+ _adj(0.0,0.0,100.0,1.0,1.0,1.0),
+ _suffix(0)
+{
+}
+
+RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
+{
+ _changed_connection.disconnect();
+ if (_label) delete _label;
+ if (_suffix) delete _suffix;
+ if (_sb) delete _sb;
+}
+
+void
+RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr)
+{
+ _key = key;
+ _label = new Gtk::Label (label);
+ _label->set_alignment (1.0, 0.5);
+ _sb = new Gtk::SpinButton (_adj, 1.0, 0);
+ _suffix = new Gtk::Label (suffix);
+ _hbox.pack_start (*_sb, true, true, 0);
+ _hbox.pack_start (*_suffix, false, false, 0);
+
+ _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
+ _wr = &wr;
+}
+
+void
+RegisteredSuffixedInteger::setValue (int i)
+{
+ _adj.set_value (i);
+}
+
+void
+RegisteredSuffixedInteger::on_value_changed()
+{
+ if (_wr->isUpdating() || !SP_ACTIVE_DESKTOP)
+ return;
+
+ _wr->setUpdating (true);
+
+ SPDesktop* dt = SP_ACTIVE_DESKTOP;
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(dt));
+ Inkscape::SVGOStringStream os;
+ int value = int(_adj.get_value());
+ os << value;
+
+ repr->setAttribute(_key.c_str(), os.str().c_str());
+ sp_document_done(SP_DT_DOCUMENT(dt));
+
+ _wr->setUpdating (false);
+}
+
+RegisteredRadioButtonPair::RegisteredRadioButtonPair()
+: _hbox(0)
+{
+}
+
+RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
+{
+ _changed_connection.disconnect();
+}
+
+void
+RegisteredRadioButtonPair::init (const Glib::ustring& label,
+const Glib::ustring& label1, const Glib::ustring& label2,
+const Glib::ustring& tip1, const Glib::ustring& tip2,
+const Glib::ustring& key, Registry& wr)
+{
+ _hbox = new Gtk::HBox;
+ _hbox->add (*manage (new Gtk::Label (label)));
+ _rb1 = manage (new Gtk::RadioButton (label1));
+ _hbox->add (*_rb1);
+ Gtk::RadioButtonGroup group = _rb1->get_group();
+ _rb2 = manage (new Gtk::RadioButton (group, label2, false));
+ _hbox->add (*_rb2);
+ _rb2->set_active();
+ _tt.set_tip (*_rb1, tip1);
+ _tt.set_tip (*_rb2, tip2);
+ _key = key;
+ _wr = &wr;
+ _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
+}
+
+void
+RegisteredRadioButtonPair::setValue (bool second)
+{
+ if (second) _rb2->set_active();
+ else _rb1->set_active();
+}
+
+void
+RegisteredRadioButtonPair::on_value_changed()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt)
+ return;
+
+ _wr->setUpdating (true);
+
+ bool second = _rb2->get_active();
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ repr->setAttribute(_key.c_str(), second ? "true" : "false");
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h
new file mode 100644
index 000000000..7138f4640
--- /dev/null
+++ b/src/ui/widget/registered-widget.h
@@ -0,0 +1,175 @@
+/** \file
+ * \brief
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_REGISTERED_WIDGET__H_
+#define INKSCAPE_UI_WIDGET_REGISTERED_WIDGET__H_
+
+#include <gtkmm/box.h>
+#include <gtkmm/adjustment.h>
+
+class SPUnit;
+
+namespace Gtk {
+ class HScale;
+ class RadioButton;
+ class SpinButton;
+ class ToggleButton;
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class ColorPicker;
+class Registry;
+class ScalarUnit;
+class UnitMenu;
+
+class RegisteredCheckButton {
+public:
+ RegisteredCheckButton();
+ ~RegisteredCheckButton();
+ void init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right=true);
+ void setActive (bool);
+
+ Gtk::ToggleButton *_button;
+
+protected:
+ Gtk::Tooltips _tt;
+ sigc::connection _toggled_connection;
+ Registry *_wr;
+ Glib::ustring _key;
+ void on_toggled();
+};
+
+class RegisteredUnitMenu {
+public:
+ RegisteredUnitMenu();
+ ~RegisteredUnitMenu();
+ void init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr);
+ void setUnit (const SPUnit*);
+ Gtk::Label *_label;
+ UnitMenu *_sel;
+ sigc::connection _changed_connection;
+
+protected:
+ void on_changed();
+ Registry *_wr;
+ Glib::ustring _key;
+};
+
+class RegisteredScalarUnit {
+public:
+ RegisteredScalarUnit();
+ ~RegisteredScalarUnit();
+ void init (const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ const RegisteredUnitMenu &rum,
+ Registry& wr);
+ ScalarUnit* getSU();
+ void setValue (double);
+
+protected:
+ ScalarUnit *_widget;
+ sigc::connection _value_changed_connection;
+ UnitMenu *_um;
+ Registry *_wr;
+ Glib::ustring _key;
+ void on_value_changed();
+};
+
+class RegisteredColorPicker {
+public:
+ RegisteredColorPicker();
+ ~RegisteredColorPicker();
+ void init (const Glib::ustring& label,
+ const Glib::ustring& title,
+ const Glib::ustring& tip,
+ const Glib::ustring& ckey,
+ const Glib::ustring& akey,
+ Registry& wr);
+ void setRgba32 (guint32);
+ void closeWindow();
+
+ Gtk::Label *_label;
+ ColorPicker *_cp;
+
+protected:
+ Glib::ustring _ckey, _akey;
+ Registry *_wr;
+ void on_changed (guint32);
+ sigc::connection _changed_connection;
+};
+
+class RegisteredSuffixedInteger {
+public:
+ RegisteredSuffixedInteger();
+ ~RegisteredSuffixedInteger();
+ void init (const Glib::ustring& label1,
+ const Glib::ustring& label2,
+ const Glib::ustring& key,
+ Registry& wr);
+ void setValue (int);
+ Gtk::Label *_label;
+ Gtk::HBox _hbox;
+
+protected:
+ Gtk::SpinButton *_sb;
+ Gtk::Adjustment _adj;
+ Gtk::Label *_suffix;
+ Glib::ustring _key;
+ Registry *_wr;
+ sigc::connection _changed_connection;
+ void on_value_changed();
+};
+
+class RegisteredRadioButtonPair {
+public:
+ RegisteredRadioButtonPair();
+ ~RegisteredRadioButtonPair();
+ void init (const Glib::ustring& label,
+ const Glib::ustring& label1,
+ const Glib::ustring& label2,
+ const Glib::ustring& tip1,
+ const Glib::ustring& tip2,
+ const Glib::ustring& key,
+ Registry& wr);
+ void setValue (bool second);
+ Gtk::HBox *_hbox;
+
+protected:
+ Gtk::RadioButton *_rb1, *_rb2;
+ Gtk::Tooltips _tt;
+ Glib::ustring _key;
+ Registry *_wr;
+ sigc::connection _changed_connection;
+ void on_value_changed();
+};
+
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_REGISTERED_WIDGET__H_
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/registry.cpp b/src/ui/widget/registry.cpp
new file mode 100644
index 000000000..aa92e6ecb
--- /dev/null
+++ b/src/ui/widget/registry.cpp
@@ -0,0 +1,58 @@
+/** \file
+ *
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "registry.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+//---------------------------------------------------
+
+Registry::Registry() : _updating(false) {}
+
+Registry::~Registry() {}
+
+bool
+Registry::isUpdating()
+{
+ return _updating;
+}
+
+void
+Registry::setUpdating (bool upd)
+{
+ _updating = upd;
+}
+
+//====================================================
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/registry.h b/src/ui/widget/registry.h
new file mode 100644
index 000000000..4d7ad3068
--- /dev/null
+++ b/src/ui/widget/registry.h
@@ -0,0 +1,54 @@
+/** \file
+ * \brief
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_REGISTRY__H
+#define INKSCAPE_UI_WIDGET_REGISTRY__H
+
+#include <map>
+#include <glibmm/i18n.h>
+#include <glibmm/ustring.h>
+
+namespace Gtk {
+ class Object;
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Registry {
+public:
+ Registry();
+ ~Registry();
+
+ bool isUpdating();
+ void setUpdating (bool);
+
+protected:
+ bool _updating;
+};
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Widget
+
+#endif // INKSCAPE_UI_WIDGET_REGISTRY__H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/ruler.cpp b/src/ui/widget/ruler.cpp
new file mode 100644
index 000000000..f2a59338d
--- /dev/null
+++ b/src/ui/widget/ruler.cpp
@@ -0,0 +1,197 @@
+/** \file
+ * Gtkmm facade/wrapper around SPRuler code that formerly lived
+ * in desktop-events.cpp
+ */
+/*
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * Lauris Kaplinski
+ *
+ * Copyright (C) 2005 Ralf Stephan
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#if defined(WIN32) || defined(__APPLE__)
+# include <glibmm/i18n.h>
+#endif
+
+#include <gtkmm/ruler.h>
+#include "helper/units.h"
+#include "widgets/ruler.h"
+#include "ui/widget/ruler.h"
+
+#include "xml/repr.h"
+#include "display/guideline.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "document.h"
+#include "sp-namedview.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+void
+Ruler::init(SPDesktop *dt, Gtk::Widget &w)
+{
+ _dt = dt;
+ _canvas_widget = &w;
+ _dragging = false;
+ _guide = 0;
+ sp_ruler_set_metric(GTK_RULER(_r->gobj()), SP_PT);
+ _r->set_range(-500, 500, 0, 1000);
+}
+
+void
+Ruler::get_range(double &lo, double &up, double &pos, double &max)
+{
+ _r->get_range(lo, up, pos, max);
+}
+
+void
+Ruler::set_range(double lo, double up, double pos, double max)
+{
+ _r->set_range(lo, up, pos, max);
+}
+
+/// Set metric from namedview
+void
+Ruler::update_metric()
+{
+ if (!_dt) return;
+ sp_ruler_set_metric(GTK_RULER(_r->gobj()), _dt->namedview->getDefaultMetric());
+}
+
+/// Returns text to be used for tooltip for ruler.
+/// \todo incorrect
+Glib::ustring
+Ruler::get_tip()
+{
+ return gettext(sp_unit_get_plural( _dt
+ ? _dt->namedview->doc_units
+ : &sp_unit_get_by_id(SP_UNIT_PT) ));
+}
+
+/// Helper that gets mouse coordinates relative to canvas widget.
+void
+Ruler::canvas_get_pointer(int &x, int &y)
+{
+ Gdk::ModifierType mask;
+ (void) _canvas_widget->get_window()->get_pointer(x, y, mask);
+}
+
+NR::Point
+Ruler::get_event_dt()
+{
+ int wx, wy;
+ canvas_get_pointer(wx, wy);
+ NR::Point const event_win(wx, wy);
+ NR::Point const event_w(sp_canvas_window_to_world(_dt->canvas, event_win));
+ return _dt->w2d(event_w);
+}
+
+bool
+Ruler::on_button_press_event(GdkEventButton *evb)
+{
+ g_assert(_dt);
+ NR::Point const &event_dt = get_event_dt();
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(_dt->namedview);
+
+ if (evb->button == 1) {
+ _dragging = true;
+ sp_repr_set_boolean(repr, "showguides", TRUE);
+ sp_repr_set_boolean(repr, "inkscape:guide-bbox", TRUE);
+ double const guide_pos_dt = event_dt[ _horiz_f ? NR::Y : NR::X ];
+ _guide = sp_guideline_new(_dt->guides, guide_pos_dt, !_horiz_f);
+ sp_guideline_set_color(SP_GUIDELINE(_guide), _dt->namedview->guidehicolor);
+ (void) get_window()->pointer_grab(false,
+ Gdk::BUTTON_RELEASE_MASK |
+ Gdk::POINTER_MOTION_MASK |
+ Gdk::POINTER_MOTION_HINT_MASK,
+ evb->time);
+ }
+ return false;
+}
+
+bool
+Ruler::on_motion_notify_event(GdkEventMotion *)
+{
+ g_assert(_dt);
+ NR::Point const &event_dt = get_event_dt();
+
+ if (_dragging) {
+ double const guide_pos_dt = event_dt[ _horiz_f ? NR::Y : NR::X ];
+ sp_guideline_set_position(SP_GUIDELINE(_guide), guide_pos_dt);
+ _dt->set_coordinate_status(event_dt);
+ _dt->setPosition(event_dt);
+ }
+ return false;
+}
+
+bool
+Ruler::on_button_release_event(GdkEventButton *evb)
+{
+ g_assert(_dt);
+ int wx, wy;
+ canvas_get_pointer(wx, wy);
+ NR::Point const &event_dt = get_event_dt();
+
+ if (_dragging && evb->button == 1) {
+ Gdk::Window::pointer_ungrab(evb->time);
+ gtk_object_destroy(GTK_OBJECT(_guide));
+ _guide = 0;
+ _dragging = false;
+
+ if ( (_horiz_f ? wy : wx ) >= 0 ) {
+ Inkscape::XML::Node *repr = sp_repr_new("sodipodi:guide");
+ repr->setAttribute("orientation", _horiz_f ? "horizontal" : "vertical");
+ double const guide_pos_dt = event_dt[ _horiz_f ? NR::Y : NR::X ];
+ sp_repr_set_svg_double(repr, "position", guide_pos_dt);
+ SP_OBJECT_REPR(_dt->namedview)->appendChild(repr);
+ Inkscape::GC::release(repr);
+ sp_document_done(SP_DT_DOCUMENT(_dt));
+ }
+ _dt->set_coordinate_status(event_dt);
+ }
+ return false;
+}
+
+//------------------------------------------------------------
+HRuler::HRuler()
+{
+ _dt = 0;
+ _r = static_cast<Gtk::HRuler*>(Glib::wrap(static_cast<GtkWidget*> (sp_hruler_new())));
+ add(*_r);
+ _horiz_f = true;
+}
+
+HRuler::~HRuler()
+{
+}
+
+
+VRuler::VRuler()
+{
+ _dt = 0;
+ _r = static_cast<Gtk::VRuler*>(Glib::wrap(static_cast<GtkWidget*> (sp_vruler_new())));
+ add(*_r);
+ _horiz_f = false;
+}
+
+VRuler::~VRuler()
+{
+}
+
+}}}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/ruler.h b/src/ui/widget/ruler.h
new file mode 100644
index 000000000..74dbf028c
--- /dev/null
+++ b/src/ui/widget/ruler.h
@@ -0,0 +1,88 @@
+#ifndef __UI_WIDGET_RULER_H__
+#define __UI_WIDGET_RULER_H__
+
+/** \file
+ * Gtkmm facade/wrapper around sp_rulers.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 The Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/eventbox.h>
+#include "libnr/nr-point.h"
+
+struct SPCanvasItem;
+struct SPDesktop;
+namespace Glib {
+ class ustring;
+}
+namespace Gtk {
+ class Ruler;
+}
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class Ruler : public Gtk::EventBox
+{
+public:
+ void init (SPDesktop*, Gtk::Widget&);
+ void get_range (double&, double&, double&, double&);
+ void set_range (double, double, double, double);
+ void update_metric();
+ Glib::ustring get_tip();
+
+protected:
+ SPDesktop *_dt;
+ SPCanvasItem *_guide;
+ Gtk::Widget *_canvas_widget;
+ Gtk::Ruler *_r;
+ bool _horiz_f, _dragging;
+
+ virtual bool on_button_press_event (GdkEventButton *);
+ virtual bool on_motion_notify_event (GdkEventMotion *);
+ virtual bool on_button_release_event (GdkEventButton *);
+
+private:
+ void canvas_get_pointer (int&, int&);
+ NR::Point get_event_dt();
+};
+
+/// Horizontal ruler
+class HRuler : public Ruler
+{
+public:
+ HRuler();
+ ~HRuler();
+};
+
+/// Vertical ruler
+class VRuler : public Ruler
+{
+public:
+ VRuler();
+ ~VRuler();
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/scalar-unit.cpp b/src/ui/widget/scalar-unit.cpp
new file mode 100644
index 000000000..8727ed052
--- /dev/null
+++ b/src/ui/widget/scalar-unit.cpp
@@ -0,0 +1,252 @@
+/**
+ * \brief Scalar Unit Widget - A labelled text box, with spin buttons and
+ * optional icon or suffix, for entering the values of various unit
+ * types.
+ *
+ * A ScalarUnit is a control for entering, viewing, or manipulating
+ * numbers with units. This differs from ordinary numbers like 2 or
+ * 3.14 because the number portion of a scalar *only* has meaning
+ * when considered with its unit type. For instance, 12 m and 12 in
+ * have very different actual values, but 1 m and 100 cm have the same
+ * value. The ScalarUnit allows us to abstract the presentation of
+ * the scalar to the user from the internal representations used by
+ * the program.
+ *
+ * Authors:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ * Derek P. Moore <derekm@hackunix.org>
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2004-2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "scalar-unit.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a ScalarUnit
+ *
+ * \param label Label.
+ * \param unit_type Unit type (defaults to UNIT_TYPE_LINEAR).
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param unit_menu UnitMenu drop down; if not specified, one will be created
+ * and displayed after the widget (defaults to NULL).
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to true).
+ */
+ScalarUnit::ScalarUnit(Glib::ustring const &label, Glib::ustring const &tooltip,
+ UnitType unit_type,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ UnitMenu *unit_menu,
+ bool mnemonic)
+ : Scalar(label, tooltip, suffix, icon, mnemonic),
+ _unit_menu(unit_menu),
+ _hundred_percent(0),
+ _absolute_is_increment(false),
+ _percentage_is_increment(false)
+{
+ if (_unit_menu == NULL) {
+ _unit_menu = new UnitMenu();
+ g_assert(_unit_menu);
+ _unit_menu->setUnitType(unit_type);
+ pack_start(*Gtk::manage(_unit_menu), false, false, 4);
+ }
+ _unit_menu->signal_changed()
+ .connect_notify(sigc::mem_fun(*this, &ScalarUnit::on_unit_changed));
+}
+
+/**
+ * Initializes the scalar based on the settings in _unit_menu.
+ * Requires that _unit_menu has already been initialized.
+ */
+void
+ScalarUnit::initScalar(double min_value, double max_value)
+{
+ g_assert(_unit_menu != NULL);
+ Scalar::setDigits(_unit_menu->getDefaultDigits());
+ Scalar::setIncrements(_unit_menu->getDefaultStep(),
+ _unit_menu->getDefaultPage());
+ Scalar::setRange(min_value, max_value);
+}
+
+/** Sets the unit for the ScalarUnit widget */
+bool
+ScalarUnit::setUnit(Glib::ustring const &unit) {
+ g_assert(_unit_menu != NULL);
+ // First set the unit
+ if (!_unit_menu->setUnit(unit)) {
+ return false;
+ }
+ lastUnits = unit;
+ return true;
+}
+
+/** Gets the object for the currently selected unit */
+Unit
+ScalarUnit::getUnit() const {
+ g_assert(_unit_menu != NULL);
+ return _unit_menu->getUnit();
+}
+
+/** Gets the UnitType ID for the unit */
+UnitType
+ScalarUnit::getUnitType() const {
+ g_assert(_unit_menu);
+ return _unit_menu->getUnitType();
+}
+
+/** Sets the number and unit system */
+void
+ScalarUnit::setValue(double number, Glib::ustring const &units) {
+ g_assert(_unit_menu != NULL);
+ _unit_menu->setUnit(units);
+ Scalar::setValue(number);
+}
+
+/** Sets the number only */
+void
+ScalarUnit::setValue(double number) {
+ Scalar::setValue(number);
+}
+
+/** Returns the value in the given unit system */
+double
+ScalarUnit::getValue(Glib::ustring const &unit_name) const {
+ g_assert(_unit_menu != NULL);
+ if (unit_name == "") {
+ // Return the value in the default units
+ return Scalar::getValue();
+ } else {
+ double conversion = _unit_menu->getConversion(unit_name);
+ return conversion * Scalar::getValue();
+ }
+}
+
+void
+ScalarUnit::setHundredPercent(double number)
+{
+ _hundred_percent = number;
+}
+
+void
+ScalarUnit::setAbsoluteIsIncrement(bool value)
+{
+ _absolute_is_increment = value;
+}
+
+void
+ScalarUnit::setPercentageIsIncrement(bool value)
+{
+ _percentage_is_increment = value;
+}
+
+/** Convert value from % to absolute, using _hundred_percent and *_is_increment flags */
+double
+ScalarUnit::PercentageToAbsolute(double value)
+{
+ // convert from percent to absolute
+ double convertedVal = 0;
+ double hundred_converted = _hundred_percent / _unit_menu->getConversion("px"); // _hundred_percent is in px
+ if (_percentage_is_increment)
+ value += 100;
+ convertedVal = 0.01 * hundred_converted * value;
+ if (_absolute_is_increment)
+ convertedVal -= hundred_converted;
+
+ return convertedVal;
+}
+
+/** Convert value from absolute to %, using _hundred_percent and *_is_increment flags */
+double
+ScalarUnit::AbsoluteToPercentage(double value)
+{
+ double convertedVal = 0;
+ // convert from absolute to percent
+ if (_hundred_percent == 0) {
+ if (_percentage_is_increment)
+ convertedVal = 0;
+ else
+ convertedVal = 100;
+ } else {
+ double hundred_converted = _hundred_percent / _unit_menu->getConversion("px", lastUnits); // _hundred_percent is in px
+ if (_absolute_is_increment)
+ value += hundred_converted;
+ convertedVal = 100 * value / hundred_converted;
+ if (_percentage_is_increment)
+ convertedVal -= 100;
+ }
+
+ return convertedVal;
+}
+
+/** Assuming the current unit is absolute, get the corresponding % value */
+double
+ScalarUnit::getAsPercentage()
+{
+ double convertedVal = AbsoluteToPercentage(Scalar::getValue());
+ return convertedVal;
+}
+
+
+/** Assuming the current unit is absolute, set the value corresponding to a given % */
+void
+ScalarUnit::setFromPercentage(double value)
+{
+ double absolute = PercentageToAbsolute(value);
+ Scalar::setValue(absolute);
+}
+
+
+/** Signal handler for updating the value and suffix label when unit is changed */
+void
+ScalarUnit::on_unit_changed()
+{
+ g_assert(_unit_menu != NULL);
+
+ Glib::ustring abbr = _unit_menu->getUnitAbbr();
+ _suffix->set_label(abbr);
+
+ Inkscape::Util::UnitTable &table = _unit_menu->getUnitTable();
+ Inkscape::Util::Unit new_unit = (table.getUnit(abbr));
+ Inkscape::Util::Unit old_unit = (table.getUnit(lastUnits));
+
+ double convertedVal = 0;
+ if (old_unit.type == UNIT_TYPE_DIMENSIONLESS && new_unit.type == UNIT_TYPE_LINEAR) {
+ convertedVal = PercentageToAbsolute(Scalar::getValue());
+ } else if (old_unit.type == UNIT_TYPE_LINEAR && new_unit.type == UNIT_TYPE_DIMENSIONLESS) {
+ convertedVal = AbsoluteToPercentage(Scalar::getValue());
+ } else {
+ double conversion = _unit_menu->getConversion(lastUnits);
+ convertedVal = Scalar::getValue() / conversion;
+ }
+ Scalar::setValue(convertedVal);
+
+ lastUnits = abbr;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/scalar-unit.h b/src/ui/widget/scalar-unit.h
new file mode 100644
index 000000000..c99161dad
--- /dev/null
+++ b/src/ui/widget/scalar-unit.h
@@ -0,0 +1,85 @@
+/**
+ * \brief Scalar Unit Widget - A labelled text box, with spin buttons and
+ * optional icon or suffix, for entering the values of various unit
+ * types.
+ *
+ * Authors:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ * Derek P. Moore <derekm@hackunix.org>
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2004-2005 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_SCALAR_UNIT_H
+#define INKSCAPE_UI_WIDGET_SCALAR_UNIT_H
+
+#include "scalar.h"
+#include "unit-menu.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class ScalarUnit : public Scalar
+{
+public:
+ ScalarUnit(Glib::ustring const &label, Glib::ustring const &tooltip,
+ UnitType unit_type = UNIT_TYPE_LINEAR,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ UnitMenu *unit_menu = NULL,
+ bool mnemonic = true);
+
+ void initScalar(double min_value, double max_value);
+
+ Unit getUnit() const;
+ UnitType getUnitType() const;
+ double getValue(Glib::ustring const &units) const;
+
+ bool setUnit(Glib::ustring const &units);
+ void setValue(double number, Glib::ustring const &units);
+ void setValue(double number);
+
+ void setHundredPercent(double number);
+ void setAbsoluteIsIncrement(bool value);
+ void setPercentageIsIncrement(bool value);
+
+ double PercentageToAbsolute(double value);
+ double AbsoluteToPercentage(double value);
+
+ double getAsPercentage();
+ void setFromPercentage(double value);
+
+ void on_unit_changed();
+
+protected:
+ UnitMenu *_unit_menu;
+
+ double _hundred_percent; // the length that corresponds to 100%, in px, for %-to/from-absolute conversions
+
+ bool _absolute_is_increment; // if true, 120% with _hundred_percent=100px gets converted to/from 20px; otherwise, to/from 120px
+ bool _percentage_is_increment; // if true, 120px with _hundred_percent=100px gets converted to/from 20%; otherwise, to/from 120%
+ // if both are true, 20px is converted to/from 20% if _hundred_percent=100px
+
+ Glib::ustring lastUnits; // previously selected unit, for conversions
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_SCALAR_UNIT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/scalar.cpp b/src/ui/widget/scalar.cpp
new file mode 100644
index 000000000..ae90e4a0f
--- /dev/null
+++ b/src/ui/widget/scalar.cpp
@@ -0,0 +1,217 @@
+/**
+ * \brief Scalar Widget - A labelled text box, with spin buttons and optional
+ * icon or suffix, for entering arbitrary number values.
+ *
+ * Authors:
+ * Carl Hetherington <inkscape@carlh.net>
+ * Derek P. Moore <derekm@hackunix.org>
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Carl Hetherington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include "scalar.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a Scalar Widget.
+ *
+ * \param label Label.
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to false).
+ */
+Scalar::Scalar(Glib::ustring const &label, Glib::ustring const &tooltip,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ bool mnemonic)
+ : Labelled(label, tooltip, new Gtk::SpinButton(), suffix, icon, mnemonic),
+ setProgrammatically(false)
+{
+}
+
+/**
+ * Construct a Scalar Widget.
+ *
+ * \param label Label.
+ * \param digits Number of decimal digits to display.
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to false).
+ */
+Scalar::Scalar(Glib::ustring const &label, Glib::ustring const &tooltip,
+ unsigned digits,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ bool mnemonic)
+ : Labelled(label, tooltip, new Gtk::SpinButton(0.0, digits), suffix, icon, mnemonic),
+ setProgrammatically(false)
+{
+}
+
+/**
+ * Construct a Scalar Widget.
+ *
+ * \param label Label.
+ * \param adjust Adjustment to use for the SpinButton.
+ * \param digits Number of decimal digits to display (defaults to 0).
+ * \param suffix Suffix, placed after the widget (defaults to "").
+ * \param icon Icon filename, placed before the label (defaults to "").
+ * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label
+ * indicates the next character should be used for the
+ * mnemonic accelerator key (defaults to true).
+ */
+Scalar::Scalar(Glib::ustring const &label, Glib::ustring const &tooltip,
+ Gtk::Adjustment &adjust,
+ unsigned digits,
+ Glib::ustring const &suffix,
+ Glib::ustring const &icon,
+ bool mnemonic)
+ : Labelled(label, tooltip, new Gtk::SpinButton(adjust, 0.0, digits), suffix, icon, mnemonic),
+ setProgrammatically(false)
+{
+}
+
+/** Fetches the precision of the spin buton */
+unsigned
+Scalar::getDigits() const
+{
+ g_assert(_widget != NULL);
+ return static_cast<Gtk::SpinButton*>(_widget)->get_digits();
+}
+
+/** Gets the current step ingrement used by the spin button */
+double
+Scalar::getStep() const
+{
+ g_assert(_widget != NULL);
+ double step, page;
+ static_cast<Gtk::SpinButton*>(_widget)->get_increments(step, page);
+ return step;
+}
+
+/** Gets the current page increment used by the spin button */
+double
+Scalar::getPage() const
+{
+ g_assert(_widget != NULL);
+ double step, page;
+ static_cast<Gtk::SpinButton*>(_widget)->get_increments(step, page);
+ return page;
+}
+
+/** Gets the minimum range value allowed for the spin button */
+double
+Scalar::getRangeMin() const
+{
+ g_assert(_widget != NULL);
+ double min, max;
+ static_cast<Gtk::SpinButton*>(_widget)->get_range(min, max);
+ return min;
+}
+
+/** Gets the maximum range value allowed for the spin button */
+double
+Scalar::getRangeMax() const
+{
+ g_assert(_widget != NULL);
+ double min, max;
+ static_cast<Gtk::SpinButton*>(_widget)->get_range(min, max);
+ return max;
+}
+
+/** Get the value in the spin_button . */
+double
+Scalar::getValue() const
+{
+ g_assert(_widget != NULL);
+ return static_cast<Gtk::SpinButton*>(_widget)->get_value();
+}
+
+/** Get the value spin_button represented as an integer. */
+int
+Scalar::getValueAsInt() const
+{
+ g_assert(_widget != NULL);
+ return static_cast<Gtk::SpinButton*>(_widget)->get_value_as_int();
+}
+
+
+/** Sets the precision to be displayed by the spin button */
+void
+Scalar::setDigits(unsigned digits)
+{
+ g_assert(_widget != NULL);
+ static_cast<Gtk::SpinButton*>(_widget)->set_digits(digits);
+}
+
+/** Sets the step and page increments for the spin button */
+void
+Scalar::setIncrements(double step, double page)
+{
+ g_assert(_widget != NULL);
+ static_cast<Gtk::SpinButton*>(_widget)->set_increments(step, page);
+}
+
+/** Sets the minimum and maximum range allowed for the spin button */
+void
+Scalar::setRange(double min, double max)
+{
+ g_assert(_widget != NULL);
+ static_cast<Gtk::SpinButton*>(_widget)->set_range(min, max);
+}
+
+/** Sets the value of the spin button */
+void
+Scalar::setValue(double value)
+{
+ g_assert(_widget != NULL);
+ setProgrammatically = true; // callback is supposed to reset back, if it cares
+ static_cast<Gtk::SpinButton*>(_widget)->set_value(value);
+}
+
+/** Manually forces an update of the spin button */
+void
+Scalar::update() {
+ g_assert(_widget != NULL);
+ static_cast<Gtk::SpinButton*>(_widget)->update();
+}
+
+
+
+/** Signal raised when the spin button's value changes */
+Glib::SignalProxy0<void>
+Scalar::signal_value_changed()
+{
+ return static_cast<Gtk::SpinButton*>(_widget)->signal_value_changed();
+}
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/scalar.h b/src/ui/widget/scalar.h
new file mode 100644
index 000000000..8ce72d949
--- /dev/null
+++ b/src/ui/widget/scalar.h
@@ -0,0 +1,86 @@
+/**
+ * \brief Scalar Widget - A labelled text box, with spin buttons and optional
+ * icon or suffix, for entering arbitrary number values.
+ *
+ * Authors:
+ * Carl Hetherington <inkscape@carlh.net>
+ * Derek P. Moore <derekm@hackunix.org>
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Carl Hetherington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_SCALAR_H
+#define INKSCAPE_UI_WIDGET_SCALAR_H
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/spinbutton.h>
+
+#include "labelled.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Scalar : public Labelled
+{
+public:
+ Scalar(Glib::ustring const &label,
+ Glib::ustring const &tooltip,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ bool mnemonic = true);
+ Scalar(Glib::ustring const &label,
+ Glib::ustring const &tooltip,
+ unsigned digits,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ bool mnemonic = true);
+ Scalar(Glib::ustring const &label,
+ Glib::ustring const &tooltip,
+ Gtk::Adjustment &adjust,
+ unsigned digits = 0,
+ Glib::ustring const &suffix = "",
+ Glib::ustring const &icon = "",
+ bool mnemonic = true);
+
+ unsigned getDigits() const;
+ double getStep() const;
+ double getPage() const;
+ double getRangeMin() const;
+ double getRangeMax() const;
+ bool getSnapToTicks() const;
+ double getValue() const;
+ int getValueAsInt() const;
+
+ void setDigits(unsigned digits);
+ void setIncrements(double step, double page);
+ void setRange(double min, double max);
+ void setValue(double value);
+
+ void update();
+
+ Glib::SignalProxy0<void> signal_value_changed();
+
+ bool setProgrammatically; // true if the value was set by setValue, not changed by the user;
+ // if a callback checks it, it must reset it back to false
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_SCALAR_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp
new file mode 100644
index 000000000..c808289b2
--- /dev/null
+++ b/src/ui/widget/selected-style.cpp
@@ -0,0 +1,977 @@
+/**
+ * \brief Selected style indicator (fill, stroke, opacity)
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include "selected-style.h"
+
+#include "widgets/spw-utilities.h"
+#include "ui/widget/color-preview.h"
+
+#include "selection.h"
+#include "desktop-handles.h"
+#include "style.h"
+#include "desktop-style.h"
+#include "sp-linear-gradient-fns.h"
+#include "sp-radial-gradient-fns.h"
+#include "sp-pattern.h"
+#include "dialogs/object-properties.h"
+#include "xml/repr.h"
+#include "document.h"
+#include "widgets/widget-sizes.h"
+#include "widgets/spinbutton-events.h"
+#include "svg/svg.h"
+#include "svg/css-ostringstream.h"
+#include "helper/units.h"
+
+static gdouble const _sw_presets[] = { 32 , 16 , 10 , 8 , 6 , 4 , 3 , 2 , 1.5 , 1 , 0.75 , 0.5 , 0.25 , 0.1 };
+static gchar* const _sw_presets_str[] = {"32", "16", "10", "8", "6", "4", "3", "2", "1.5", "1", "0.75", "0.5", "0.25", "0.1"};
+
+static void
+ss_selection_changed (Inkscape::Selection *, gpointer data)
+{
+ Inkscape::UI::Widget::SelectedStyle *ss = (Inkscape::UI::Widget::SelectedStyle *) data;
+ ss->update();
+}
+
+static void
+ss_selection_modified (Inkscape::Selection *selection, guint flags, gpointer data)
+{
+ ss_selection_changed (selection, data);
+}
+
+static void
+ss_subselection_changed (gpointer dragger, gpointer data)
+{
+ ss_selection_changed (NULL, data);
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+SelectedStyle::SelectedStyle(bool layout)
+ : _desktop (NULL),
+
+ _table(2, 6),
+ _fill_label (_("F:")),
+ _stroke_label (_("S:")),
+ _opacity_label (_("O:")),
+ _fill_place (),
+ _stroke_place (),
+
+ _fill_flag_place (),
+ _stroke_flag_place (),
+
+ _opacity_place (),
+ _opacity_adjustment (1.0, 0.0, 1.0, 0.01, 0.1),
+ _opacity_sb (0.02, 2),
+
+ _stroke (),
+ _stroke_width (""),
+
+ _opacity_blocked (false),
+
+ _popup_px(_sw_group),
+ _popup_pt(_sw_group),
+ _popup_mm(_sw_group),
+
+ _sw_unit(NULL),
+
+ _tooltips ()
+{
+ _fill_label.set_alignment(0.0, 0.5);
+ _fill_label.set_padding(0, 0);
+ _stroke_label.set_alignment(0.0, 0.5);
+ _stroke_label.set_padding(0, 0);
+ _opacity_label.set_alignment(0.0, 0.5);
+ _opacity_label.set_padding(0, 0);
+
+ _table.set_col_spacings (2);
+ _table.set_row_spacings (0);
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+
+ _na[i].set_markup (_("N/A"));
+ sp_set_font_size_smaller (GTK_WIDGET(_na[i].gobj()));
+ _na[i].show_all();
+ __na[i] = (_("Nothing selected"));
+
+ _none[i].set_markup (_("None"));
+ sp_set_font_size_smaller (GTK_WIDGET(_none[i].gobj()));
+ _none[i].show_all();
+ __none[i] = (i == SS_FILL)? (_("No fill")) : (_("No stroke"));
+
+ _pattern[i].set_markup (_("Pattern"));
+ sp_set_font_size_smaller (GTK_WIDGET(_pattern[i].gobj()));
+ _pattern[i].show_all();
+ __pattern[i] = (i == SS_FILL)? (_("Pattern fill")) : (_("Pattern stroke"));
+
+ _lgradient[i].set_markup (_("L Gradient"));
+ sp_set_font_size_smaller (GTK_WIDGET(_lgradient[i].gobj()));
+ _lgradient[i].show_all();
+ __lgradient[i] = (i == SS_FILL)? (_("Linear gradient fill")) : (_("Linear gradient stroke"));
+
+ _rgradient[i].set_markup (_("R Gradient"));
+ sp_set_font_size_smaller (GTK_WIDGET(_rgradient[i].gobj()));
+ _rgradient[i].show_all();
+ __rgradient[i] = (i == SS_FILL)? (_("Radial gradient fill")) : (_("Radial gradient stroke"));
+
+ _many[i].set_markup (_("Different"));
+ sp_set_font_size_smaller (GTK_WIDGET(_many[i].gobj()));
+ _many[i].show_all();
+ __many[i] = (i == SS_FILL)? (_("Different fills")) : (_("Different strokes"));
+
+ _unset[i].set_markup (_("Unset"));
+ sp_set_font_size_smaller (GTK_WIDGET(_unset[i].gobj()));
+ _unset[i].show_all();
+ __unset[i] = (i == SS_FILL)? (_("Unset fill")) : (_("Unset stroke"));
+
+ _color_preview[i] = new Inkscape::UI::Widget::ColorPreview (0);
+ __color[i] = (i == SS_FILL)? (_("Flat color fill")) : (_("Flat color stroke"));
+
+ // TRANSLATOR COMMENT: A means "Averaged"
+ _averaged[i].set_markup (_("<b>a</b>"));
+ sp_set_font_size_smaller (GTK_WIDGET(_averaged[i].gobj()));
+ _averaged[i].show_all();
+ __averaged[i] = (i == SS_FILL)? (_("Fill is averaged over selected objects")) : (_("Stroke is averaged over selected objects"));
+
+ // TRANSLATOR COMMENT: M means "Multiple"
+ _multiple[i].set_markup (_("<b>m</b>"));
+ sp_set_font_size_smaller (GTK_WIDGET(_multiple[i].gobj()));
+ _multiple[i].show_all();
+ __multiple[i] = (i == SS_FILL)? (_("Multiple selected objects have the same fill")) : (_("Multiple selected objects have the same stroke"));
+
+ _popup_edit[i].add(*(new Gtk::Label((i == SS_FILL)? _("Edit fill...") : _("Edit stroke..."), 0.0, 0.5)));
+ _popup_edit[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_edit : &SelectedStyle::on_stroke_edit ));
+
+ _popup_lastused[i].add(*(new Gtk::Label(_("Last set color"), 0.0, 0.5)));
+ _popup_lastused[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_lastused : &SelectedStyle::on_stroke_lastused ));
+
+ _popup_lastselected[i].add(*(new Gtk::Label(_("Last selected color"), 0.0, 0.5)));
+ _popup_lastselected[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_lastselected : &SelectedStyle::on_stroke_lastselected ));
+
+ _popup_invert[i].add(*(new Gtk::Label(_("Invert"), 0.0, 0.5)));
+ _popup_invert[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_invert : &SelectedStyle::on_stroke_invert ));
+
+ _popup_white[i].add(*(new Gtk::Label(_("White"), 0.0, 0.5)));
+ _popup_white[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_white : &SelectedStyle::on_stroke_white ));
+
+ _popup_black[i].add(*(new Gtk::Label(_("Black"), 0.0, 0.5)));
+ _popup_black[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_black : &SelectedStyle::on_stroke_black ));
+
+ _popup_copy[i].add(*(new Gtk::Label(_("Copy color"), 0.0, 0.5)));
+ _popup_copy[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_copy : &SelectedStyle::on_stroke_copy ));
+
+ _popup_paste[i].add(*(new Gtk::Label(_("Paste color"), 0.0, 0.5)));
+ _popup_paste[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_paste : &SelectedStyle::on_stroke_paste ));
+
+ _popup_swap[i].add(*(new Gtk::Label(_("Swap fill and stroke"), 0.0, 0.5)));
+ _popup_swap[i].signal_activate().connect(sigc::mem_fun(*this,
+ &SelectedStyle::on_fillstroke_swap));
+
+ _popup_opaque[i].add(*(new Gtk::Label((i == SS_FILL)? _("Make fill opaque") : _("Make stroke opaque"), 0.0, 0.5)));
+ _popup_opaque[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_opaque : &SelectedStyle::on_stroke_opaque ));
+
+ //TRANSLATORS COMMENT: unset is a verb here
+ _popup_unset[i].add(*(new Gtk::Label((i == SS_FILL)? _("Unset fill") : _("Unset stroke"), 0.0, 0.5)));
+ _popup_unset[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_unset : &SelectedStyle::on_stroke_unset ));
+
+ _popup_remove[i].add(*(new Gtk::Label((i == SS_FILL)? _("Remove fill") : _("Remove stroke"), 0.0, 0.5)));
+ _popup_remove[i].signal_activate().connect(sigc::mem_fun(*this,
+ (i == SS_FILL)? &SelectedStyle::on_fill_remove : &SelectedStyle::on_stroke_remove ));
+
+ _popup[i].attach(_popup_edit[i], 0,1, 0,1);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 1,2);
+ _popup[i].attach(_popup_lastused[i], 0,1, 2,3);
+ _popup[i].attach(_popup_lastselected[i], 0,1, 3,4);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 4,5);
+ _popup[i].attach(_popup_invert[i], 0,1, 5,6);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 6,7);
+ _popup[i].attach(_popup_white[i], 0,1, 7,8);
+ _popup[i].attach(_popup_black[i], 0,1, 8,9);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 9,10);
+ _popup[i].attach(_popup_copy[i], 0,1, 10,11);
+ _popup_copy[i].set_sensitive(false);
+ _popup[i].attach(_popup_paste[i], 0,1, 11,12);
+ _popup[i].attach(_popup_swap[i], 0,1, 12,13);
+ _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 13,14);
+ _popup[i].attach(_popup_opaque[i], 0,1, 14,15);
+ _popup[i].attach(_popup_unset[i], 0,1, 15,16);
+ _popup[i].attach(_popup_remove[i], 0,1, 16,17);
+ _popup[i].show_all();
+
+ _mode[i] = SS_NA;
+ }
+
+ {
+ _popup_px.add(*(new Gtk::Label(_("px"), 0.0, 0.5)));
+ _popup_px.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_px));
+ _popup_sw.attach(_popup_px, 0,1, 0,1);
+
+ _popup_pt.add(*(new Gtk::Label(_("pt"), 0.0, 0.5)));
+ _popup_pt.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_pt));
+ _popup_sw.attach(_popup_pt, 0,1, 1,2);
+
+ _popup_mm.add(*(new Gtk::Label(_("mm"), 0.0, 0.5)));
+ _popup_mm.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_mm));
+ _popup_sw.attach(_popup_mm, 0,1, 2,3);
+
+ _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, 3,4);
+
+ for (guint i = 0; i < G_N_ELEMENTS(_sw_presets_str); ++i) {
+ Gtk::MenuItem *mi = Gtk::manage(new Gtk::MenuItem());
+ mi->add(*(new Gtk::Label(_sw_presets_str[i], 0.0, 0.5)));
+ mi->signal_activate().connect(sigc::bind<int>(sigc::mem_fun(*this, &SelectedStyle::on_popup_preset), i));
+ _popup_sw.attach(*mi, 0,1, 4+i, 5+i);
+ }
+
+ guint i = G_N_ELEMENTS(_sw_presets_str) + 5;
+
+ _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, i,i+1);
+
+ _popup_sw_remove.add(*(new Gtk::Label(_("Remove"), 0.0, 0.5)));
+ _popup_sw_remove.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_stroke_remove));
+ _popup_sw.attach(_popup_sw_remove, 0,1, i+1,i+2);
+
+ _popup_sw.show_all();
+ }
+
+ _fill_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_fill_click));
+ _stroke_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_stroke_click));
+ _opacity_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_click));
+ _stroke_width_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_sw_click));
+
+ _opacity_sb.signal_populate_popup().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_menu));
+ _opacity_sb.signal_value_changed().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_changed));
+
+ _fill_place.add(_na[SS_FILL]);
+ _tooltips.set_tip(_fill_place, __na[SS_FILL]);
+
+ _stroke_place.add(_na[SS_STROKE]);
+ _tooltips.set_tip(_stroke_place, __na[SS_STROKE]);
+
+ _stroke.pack_start(_stroke_place);
+ _stroke_width_place.add(_stroke_width);
+ _stroke.pack_start(_stroke_width_place, Gtk::PACK_SHRINK);
+
+ _opacity_sb.set_adjustment(_opacity_adjustment);
+ sp_set_font_size_smaller (GTK_WIDGET(_opacity_sb.gobj()));
+ _opacity_sb.set_size_request (SELECTED_STYLE_SB_WIDTH, -1);
+ _opacity_sb.set_sensitive (false);
+
+ _table.attach(_fill_label, 0,1, 0,1, Gtk::SHRINK, Gtk::SHRINK);
+ _table.attach(_stroke_label, 0,1, 1,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ _table.attach(_fill_flag_place, 1,2, 0,1, Gtk::SHRINK, Gtk::SHRINK);
+ _table.attach(_stroke_flag_place, 1,2, 1,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ _table.attach(_fill_place, 2,3, 0,1);
+ _table.attach(_stroke, 2,3, 1,2);
+
+ _opacity_place.add(_opacity_label);
+ _table.attach(_opacity_place, 4,5, 0,2, Gtk::SHRINK, Gtk::SHRINK);
+ _table.attach(_opacity_sb, 5,6, 0,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ pack_start(_table, true, true, 2);
+
+ set_size_request (SELECTED_STYLE_WIDTH, -1);
+
+ sp_set_font_size_smaller (GTK_WIDGET(_opacity_label.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_opacity_sb.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_fill_place.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_fill_flag_place.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_place.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_flag_place.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_width.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_fill_label.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_label.gobj()));
+}
+
+SelectedStyle::~SelectedStyle()
+{
+ selection_changed_connection->disconnect();
+ delete selection_changed_connection;
+ selection_modified_connection->disconnect();
+ delete selection_modified_connection;
+ subselection_changed_connection->disconnect();
+ delete subselection_changed_connection;
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ delete _color_preview[i];
+ }
+}
+
+void
+SelectedStyle::setDesktop(SPDesktop *desktop)
+{
+ _desktop = desktop;
+ gtk_object_set_data (GTK_OBJECT(_opacity_sb.gobj()), "dtw", _desktop->canvas);
+
+ Inkscape::Selection *selection = SP_DT_SELECTION (desktop);
+
+ selection_changed_connection = new sigc::connection (selection->connectChanged(
+ sigc::bind (
+ sigc::ptr_fun(&ss_selection_changed),
+ this )
+ ));
+ selection_modified_connection = new sigc::connection (selection->connectModified(
+ sigc::bind (
+ sigc::ptr_fun(&ss_selection_modified),
+ this )
+ ));
+ subselection_changed_connection = new sigc::connection (desktop->connectToolSubselectionChanged(
+ sigc::bind (
+ sigc::ptr_fun(&ss_subselection_changed),
+ this )
+ ));
+
+ //_sw_unit = (SPUnit *) SP_DT_NAMEDVIEW(desktop)->doc_units;
+}
+
+void SelectedStyle::on_fill_remove() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "fill", "none");
+ sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_remove() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "stroke", "none");
+ sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_unset() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_unset_property (css, "fill");
+ sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_unset() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_unset_property (css, "stroke");
+ sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_opaque() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "fill-opacity", "1");
+ sp_desktop_set_style (_desktop, css, true);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_opaque() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "stroke-opacity", "1");
+ sp_desktop_set_style (_desktop, css, true);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_lastused() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ guint32 color = sp_desktop_get_color(_desktop, true);
+ gchar c[64];
+ sp_svg_write_color (c, 64, color);
+ sp_repr_css_set_property (css, "fill", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_lastused() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ guint32 color = sp_desktop_get_color(_desktop, false);
+ gchar c[64];
+ sp_svg_write_color (c, 64, color);
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_lastselected() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, _lastselected[SS_FILL]);
+ sp_repr_css_set_property (css, "fill", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_lastselected() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, _lastselected[SS_STROKE]);
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_invert() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ guint32 color = _thisselected[SS_FILL];
+ gchar c[64];
+ if (_mode[SS_FILL] != SS_COLOR) return;
+ sp_svg_write_color (c, 64,
+ SP_RGBA32_U_COMPOSE(
+ (255 - SP_RGBA32_R_U(color)),
+ (255 - SP_RGBA32_G_U(color)),
+ (255 - SP_RGBA32_B_U(color)),
+ SP_RGBA32_A_U(color)
+ )
+ );
+ sp_repr_css_set_property (css, "fill", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_invert() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ guint32 color = _thisselected[SS_STROKE];
+ gchar c[64];
+ if (_mode[SS_STROKE] != SS_COLOR) return;
+ sp_svg_write_color (c, 64,
+ SP_RGBA32_U_COMPOSE(
+ (255 - SP_RGBA32_R_U(color)),
+ (255 - SP_RGBA32_G_U(color)),
+ (255 - SP_RGBA32_B_U(color)),
+ SP_RGBA32_A_U(color)
+ )
+ );
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_white() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, 0xffffffff);
+ sp_repr_css_set_property (css, "fill", c);
+ sp_repr_css_set_property (css, "fill-opacity", "1");
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_white() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, 0xffffffff);
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_repr_css_set_property (css, "stroke-opacity", "1");
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_black() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, 0x000000ff);
+ sp_repr_css_set_property (css, "fill", c);
+ sp_repr_css_set_property (css, "fill-opacity", "1.0");
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_stroke_black() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar c[64];
+ sp_svg_write_color (c, 64, 0x000000ff);
+ sp_repr_css_set_property (css, "stroke", c);
+ sp_repr_css_set_property (css, "stroke-opacity", "1.0");
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_copy() {
+ if (_mode[SS_FILL] == SS_COLOR) {
+ gchar c[64];
+ sp_svg_write_color (c, 64, _thisselected[SS_FILL]);
+ Glib::ustring text;
+ text += c;
+ if (!text.empty()) {
+ Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
+ refClipboard->set_text(text);
+ }
+ }
+}
+
+void SelectedStyle::on_stroke_copy() {
+ if (_mode[SS_STROKE] == SS_COLOR) {
+ gchar c[64];
+ sp_svg_write_color (c, 64, _thisselected[SS_STROKE]);
+ Glib::ustring text;
+ text += c;
+ if (!text.empty()) {
+ Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
+ refClipboard->set_text(text);
+ }
+ }
+}
+
+void SelectedStyle::on_fill_paste() {
+ Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
+ Glib::ustring const text = refClipboard->wait_for_text();
+
+ if (!text.empty()) {
+ guint32 color = sp_svg_read_color(text.c_str(), 0x000000ff); // impossible value, as SVG color cannot have opacity
+ if (color == 0x000000ff) // failed to parse color string
+ return;
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "fill", text.c_str());
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+ }
+}
+
+void SelectedStyle::on_stroke_paste() {
+ Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
+ Glib::ustring const text = refClipboard->wait_for_text();
+
+ if (!text.empty()) {
+ guint32 color = sp_svg_read_color(text.c_str(), 0x000000ff); // impossible value, as SVG color cannot have opacity
+ if (color == 0x000000ff) // failed to parse color string
+ return;
+
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "stroke", text.c_str());
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+ }
+}
+
+void SelectedStyle::on_fillstroke_swap() {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+
+ switch (_mode[SS_FILL]) {
+ case SS_NA:
+ case SS_MANY:
+ break;
+ case SS_NONE:
+ sp_repr_css_set_property (css, "stroke", "none");
+ break;
+ case SS_UNSET:
+ sp_repr_css_unset_property (css, "stroke");
+ break;
+ case SS_COLOR:
+ gchar c[64];
+ sp_svg_write_color (c, 64, _thisselected[SS_FILL]);
+ sp_repr_css_set_property (css, "stroke", c);
+ break;
+ case SS_LGRADIENT:
+ case SS_RGRADIENT:
+ case SS_PATTERN:
+ sp_repr_css_set_property (css, "stroke", _paintserver_id[SS_FILL].c_str());
+ break;
+ }
+
+ switch (_mode[SS_STROKE]) {
+ case SS_NA:
+ case SS_MANY:
+ break;
+ case SS_NONE:
+ sp_repr_css_set_property (css, "fill", "none");
+ break;
+ case SS_UNSET:
+ sp_repr_css_unset_property (css, "fill");
+ break;
+ case SS_COLOR:
+ gchar c[64];
+ sp_svg_write_color (c, 64, _thisselected[SS_STROKE]);
+ sp_repr_css_set_property (css, "fill", c);
+ break;
+ case SS_LGRADIENT:
+ case SS_RGRADIENT:
+ case SS_PATTERN:
+ sp_repr_css_set_property (css, "fill", _paintserver_id[SS_STROKE].c_str());
+ break;
+ }
+
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void SelectedStyle::on_fill_edit() {
+ sp_object_properties_fill();
+}
+
+void SelectedStyle::on_stroke_edit() {
+ sp_object_properties_stroke();
+}
+
+bool
+SelectedStyle::on_fill_click(GdkEventButton *event)
+{
+ if (event->button == 1) { // click, open fill&stroke
+ sp_object_properties_fill();
+ } else if (event->button == 3) { // right-click, popup menu
+ _popup[SS_FILL].popup(event->button, event->time);
+ } else if (event->button == 2) { // middle click, toggle none/lastcolor
+ if (_mode[SS_FILL] == SS_NONE) {
+ on_fill_lastused();
+ } else {
+ on_fill_remove();
+ }
+ }
+ return true;
+}
+
+bool
+SelectedStyle::on_stroke_click(GdkEventButton *event)
+{
+ if (event->button == 1) { // click, open fill&stroke
+ sp_object_properties_stroke();
+ } else if (event->button == 3) { // right-click, popup menu
+ _popup[SS_STROKE].popup(event->button, event->time);
+ } else if (event->button == 2) { // middle click, toggle none/lastcolor
+ if (_mode[SS_STROKE] == SS_NONE) {
+ on_stroke_lastused();
+ } else {
+ on_stroke_remove();
+ }
+ }
+ return true;
+}
+
+bool
+SelectedStyle::on_sw_click(GdkEventButton *event)
+{
+ if (event->button == 1) { // click, open fill&stroke
+ sp_object_properties_stroke_style ();
+ } else if (event->button == 3) { // right-click, popup menu
+ _popup_sw.popup(event->button, event->time);
+ } else if (event->button == 2) { // middle click, toggle none/lastwidth?
+ //
+ }
+ return true;
+}
+
+bool
+SelectedStyle::on_opacity_click(GdkEventButton *event)
+{
+ if (event->button == 2) { // middle click
+ const char* opacity = _opacity_sb.get_value() < 0.5? "0.5" : (_opacity_sb.get_value() == 1? "0" : "1");
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ sp_repr_css_set_property (css, "opacity", opacity);
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT (_desktop));
+ return true;
+ }
+
+ return false;
+}
+
+void SelectedStyle::on_popup_px() {
+ _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_PX));
+ update();
+}
+void SelectedStyle::on_popup_pt() {
+ _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_PT));
+ update();
+}
+void SelectedStyle::on_popup_mm() {
+ _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_MM));
+ update();
+}
+
+void SelectedStyle::on_popup_preset(int i) {
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gdouble w;
+ if (_sw_unit) {
+ w = sp_units_get_pixels (_sw_presets[i], *_sw_unit);
+ } else {
+ w = _sw_presets[i];
+ }
+ Inkscape::CSSOStringStream os;
+ os << w;
+ sp_repr_css_set_property (css, "stroke-width", os.str().c_str());
+ sp_desktop_set_style (_desktop, css, true);
+ sp_repr_css_attr_unref (css);
+ sp_document_done (SP_DT_DOCUMENT(_desktop));
+}
+
+void
+SelectedStyle::update()
+{
+ if (_desktop == NULL)
+ return;
+
+ // create temporary style
+ SPStyle *query = sp_style_new ();
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ Gtk::EventBox *place = (i == SS_FILL)? &_fill_place : &_stroke_place;
+ Gtk::EventBox *flag_place = (i == SS_FILL)? &_fill_flag_place : &_stroke_flag_place;
+
+ place->remove();
+ flag_place->remove();
+
+ _tooltips.unset_tip(*place);
+ _tooltips.unset_tip(*flag_place);
+
+ _mode[i] = SS_NA;
+ _paintserver_id[i].clear();
+
+ _popup_copy[i].set_sensitive(false);
+
+ // query style from desktop. This returns a result flag and fills query with the style of subselection, if any, or selection
+ int result = sp_desktop_query_style (_desktop, query,
+ (i == SS_FILL)? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE);
+ switch (result) {
+ case QUERY_STYLE_NOTHING:
+ place->add(_na[i]);
+ _tooltips.set_tip(*place, __na[i]);
+ _mode[i] = SS_NA;
+ break;
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ SPIPaint *paint;
+ if (i == SS_FILL) {
+ paint = &(query->fill);
+ } else {
+ paint = &(query->stroke);
+ }
+ if (paint->set && paint->type == SP_PAINT_TYPE_COLOR) {
+ guint32 color = sp_color_get_rgba32_falpha (&(paint->value.color),
+ SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value));
+ _lastselected[i] = _thisselected[i];
+ _thisselected[i] = color | 0xff; // only color, opacity === 1
+ ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color);
+ _color_preview[i]->show_all();
+ place->add(*_color_preview[i]);
+ gchar c_string[64];
+ g_snprintf (c_string, 64, "%06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
+ _tooltips.set_tip(*place, __color[i] + ": " + c_string);
+ _mode[i] = SS_COLOR;
+ _popup_copy[i].set_sensitive(true);
+
+ } else if (paint->set && paint->type == SP_PAINT_TYPE_PAINTSERVER) {
+ SPPaintServer *server = (i == SS_FILL)? SP_STYLE_FILL_SERVER (query) : SP_STYLE_STROKE_SERVER (query);
+
+ Inkscape::XML::Node *srepr = SP_OBJECT_REPR(server);
+ _paintserver_id[i] += "url(#";
+ _paintserver_id[i] += srepr->attribute("id");
+ _paintserver_id[i] += ")";
+
+ if (SP_IS_LINEARGRADIENT (server)) {
+ place->add(_lgradient[i]);
+ _tooltips.set_tip(*place, __lgradient[i]);
+ _mode[i] = SS_LGRADIENT;
+ } else if (SP_IS_RADIALGRADIENT (server)) {
+ place->add(_rgradient[i]);
+ _tooltips.set_tip(*place, __rgradient[i]);
+ _mode[i] = SS_RGRADIENT;
+ } else if (SP_IS_PATTERN (server)) {
+ place->add(_pattern[i]);
+ _tooltips.set_tip(*place, __pattern[i]);
+ _mode[i] = SS_PATTERN;
+ }
+
+ } else if (paint->set && paint->type == SP_PAINT_TYPE_NONE) {
+ place->add(_none[i]);
+ _tooltips.set_tip(*place, __none[i]);
+ _mode[i] = SS_NONE;
+ } else if (!paint->set) {
+ place->add(_unset[i]);
+ _tooltips.set_tip(*place, __unset[i]);
+ _mode[i] = SS_UNSET;
+ }
+ if (result == QUERY_STYLE_MULTIPLE_AVERAGED) {
+ flag_place->add(_averaged[i]);
+ _tooltips.set_tip(*flag_place, __averaged[i]);
+ } else if (result == QUERY_STYLE_MULTIPLE_SAME) {
+ flag_place->add(_multiple[i]);
+ _tooltips.set_tip(*flag_place, __multiple[i]);
+ }
+ break;
+ case QUERY_STYLE_MULTIPLE_DIFFERENT:
+ place->add(_many[i]);
+ _tooltips.set_tip(*place, __many[i]);
+ _mode[i] = SS_MANY;
+ break;
+ default:
+ break;
+ }
+ }
+
+// Now query opacity
+ _tooltips.unset_tip(_opacity_place);
+
+ int result = sp_desktop_query_style (_desktop, query, QUERY_STYLE_PROPERTY_MASTEROPACITY);
+
+ switch (result) {
+ case QUERY_STYLE_NOTHING:
+ _tooltips.set_tip(_opacity_place, _("Nothing selected"));
+ _opacity_sb.set_sensitive(false);
+ break;
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ _tooltips.set_tip(_opacity_place, _("Master opacity"));
+ _opacity_blocked = true;
+ _opacity_sb.set_sensitive(true);
+ _opacity_adjustment.set_value(SP_SCALE24_TO_FLOAT(query->opacity.value));
+ _opacity_blocked = false;
+ break;
+ }
+
+// Now query stroke_width
+ int result_sw = sp_desktop_query_style (_desktop, query, QUERY_STYLE_PROPERTY_STROKEWIDTH);
+ switch (result_sw) {
+ case QUERY_STYLE_NOTHING:
+ _stroke_width.set_markup("");
+ break;
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ {
+ double w;
+ if (_sw_unit) {
+ w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit);
+ } else {
+ w = query->stroke_width.computed;
+ }
+ {
+ gchar *str = g_strdup_printf(" %.3g", w);
+ _stroke_width.set_markup(str);
+ g_free (str);
+ }
+ {
+ gchar *str = g_strdup_printf(_("Stroke width: %.5g%s%s"),
+ w,
+ _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px",
+ (result_sw == QUERY_STYLE_MULTIPLE_AVERAGED)?
+ _(" (averaged)") : "");
+ _tooltips.set_tip(_stroke_width_place, str);
+ g_free (str);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ g_free (query);
+}
+
+void SelectedStyle::opacity_0(void) {_opacity_sb.set_value(0);}
+void SelectedStyle::opacity_025(void) {_opacity_sb.set_value(0.25);}
+void SelectedStyle::opacity_05(void) {_opacity_sb.set_value(0.5);}
+void SelectedStyle::opacity_075(void) {_opacity_sb.set_value(0.75);}
+void SelectedStyle::opacity_1(void) {_opacity_sb.set_value(1.0);}
+
+void SelectedStyle::on_opacity_menu (Gtk::Menu *menu) {
+
+ Glib::ListHandle<Gtk::Widget *> children = menu->get_children();
+ for (Glib::ListHandle<Gtk::Widget *>::iterator iter = children.begin(); iter != children.end(); iter++) {
+ menu->remove(*(*iter));
+ }
+
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label(_("0 (transparent)"), 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_0 ));
+ menu->add(*item);
+ }
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label("0.25", 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_025 ));
+ menu->add(*item);
+ }
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label("0.5", 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_05 ));
+ menu->add(*item);
+ }
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label("0.75", 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_075 ));
+ menu->add(*item);
+ }
+ {
+ Gtk::MenuItem *item = new Gtk::MenuItem;
+ item->add(*(new Gtk::Label(_("1.0 (opaque)"), 0, 0)));
+ item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_1 ));
+ menu->add(*item);
+ }
+
+ menu->show_all();
+}
+
+void SelectedStyle::on_opacity_changed () {
+ if (_opacity_blocked)
+ return;
+ _opacity_blocked = true;
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ Inkscape::CSSOStringStream os;
+ os << CLAMP (_opacity_adjustment.get_value(), 0.0, 1.0);
+ sp_repr_css_set_property (css, "opacity", os.str().c_str());
+ sp_desktop_set_style (_desktop, css);
+ sp_repr_css_attr_unref (css);
+ sp_document_maybe_done (SP_DT_DOCUMENT (_desktop), "fillstroke:opacity");
+ spinbutton_defocus(GTK_OBJECT(_opacity_sb.gobj()));
+ _opacity_blocked = false;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/selected-style.h b/src/ui/widget/selected-style.h
new file mode 100644
index 000000000..8f9c0fbf6
--- /dev/null
+++ b/src/ui/widget/selected-style.h
@@ -0,0 +1,212 @@
+/**
+ * \brief Selected style indicator (fill, stroke, opacity)
+ *
+ * Authors:
+ * buliabyak@gmail.com
+ * scislac@users.sf.net
+ *
+ * Copyright (C) 2005 authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_CURRENT_STYLE_H
+#define INKSCAPE_UI_CURRENT_STYLE_H
+
+#include <gtkmm/table.h>
+#include <gtkmm/label.h>
+#include <gtkmm/box.h>
+#include <gtkmm/eventbox.h>
+#include <gtkmm/enums.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/menuitem.h>
+#include <gtkmm/adjustment.h>
+#include <gtkmm/spinbutton.h>
+
+#include <sigc++/sigc++.h>
+
+#include <glibmm/i18n.h>
+
+#include <desktop.h>
+
+#include "button.h"
+
+class SPUnit;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+enum {
+ SS_NA,
+ SS_NONE,
+ SS_UNSET,
+ SS_PATTERN,
+ SS_LGRADIENT,
+ SS_RGRADIENT,
+ SS_MANY,
+ SS_COLOR
+};
+
+enum {
+ SS_FILL,
+ SS_STROKE
+};
+
+class SelectedStyle : public Gtk::HBox
+{
+public:
+ SelectedStyle(bool layout = true);
+
+ ~SelectedStyle();
+
+ void setDesktop(SPDesktop *desktop);
+ void update();
+
+protected:
+ SPDesktop *_desktop;
+
+ Gtk::Table _table;
+
+ Gtk::Label _fill_label;
+ Gtk::Label _stroke_label;
+ Gtk::Label _opacity_label;
+
+ Gtk::EventBox _fill_place;
+ Gtk::EventBox _stroke_place;
+
+ Gtk::EventBox _fill_flag_place;
+ Gtk::EventBox _stroke_flag_place;
+
+ Gtk::EventBox _opacity_place;
+ Gtk::Adjustment _opacity_adjustment;
+ Gtk::SpinButton _opacity_sb;
+
+ Gtk::Label _na[2];
+ Glib::ustring __na[2];
+
+ Gtk::Label _none[2];
+ Glib::ustring __none[2];
+
+ Gtk::Label _pattern[2];
+ Glib::ustring __pattern[2];
+
+ Gtk::Label _lgradient[2];
+ Glib::ustring __lgradient[2];
+
+ Gtk::Label _rgradient[2];
+ Glib::ustring __rgradient[2];
+
+ Gtk::Label _many[2];
+ Glib::ustring __many[2];
+
+ Gtk::Label _unset[2];
+ Glib::ustring __unset[2];
+
+ Gtk::Widget *_color_preview[2];
+ Glib::ustring __color[2];
+
+ Gtk::Label _averaged[2];
+ Glib::ustring __averaged[2];
+ Gtk::Label _multiple[2];
+ Glib::ustring __multiple[2];
+
+ Gtk::HBox _stroke;
+ Gtk::EventBox _stroke_width_place;
+ Gtk::Label _stroke_width;
+
+ guint32 _lastselected[2];
+ guint32 _thisselected[2];
+ Glib::ustring _paintserver_id[2];
+
+ guint _mode[2];
+
+ sigc::connection *selection_changed_connection;
+ sigc::connection *selection_modified_connection;
+ sigc::connection *subselection_changed_connection;
+
+ bool on_fill_click(GdkEventButton *event);
+ bool on_stroke_click(GdkEventButton *event);
+ bool on_opacity_click(GdkEventButton *event);
+ bool on_sw_click(GdkEventButton *event);
+
+ bool _opacity_blocked;
+ void on_opacity_changed();
+ void on_opacity_menu(Gtk::Menu *menu);
+ void opacity_0();
+ void opacity_025();
+ void opacity_05();
+ void opacity_075();
+ void opacity_1();
+
+ void on_fill_remove();
+ void on_stroke_remove();
+ void on_fill_lastused();
+ void on_stroke_lastused();
+ void on_fill_lastselected();
+ void on_stroke_lastselected();
+ void on_fill_unset();
+ void on_stroke_unset();
+ void on_fill_edit();
+ void on_stroke_edit();
+ void on_fillstroke_swap();
+ void on_fill_invert();
+ void on_stroke_invert();
+ void on_fill_white();
+ void on_stroke_white();
+ void on_fill_black();
+ void on_stroke_black();
+ void on_fill_copy();
+ void on_stroke_copy();
+ void on_fill_paste();
+ void on_stroke_paste();
+ void on_fill_opaque();
+ void on_stroke_opaque();
+
+ Gtk::Menu _popup[2];
+ Gtk::MenuItem _popup_edit[2];
+ Gtk::MenuItem _popup_lastused[2];
+ Gtk::MenuItem _popup_lastselected[2];
+ Gtk::MenuItem _popup_invert[2];
+ Gtk::MenuItem _popup_white[2];
+ Gtk::MenuItem _popup_black[2];
+ Gtk::MenuItem _popup_copy[2];
+ Gtk::MenuItem _popup_paste[2];
+ Gtk::MenuItem _popup_swap[2];
+ Gtk::MenuItem _popup_opaque[2];
+ Gtk::MenuItem _popup_unset[2];
+ Gtk::MenuItem _popup_remove[2];
+
+ Gtk::Menu _popup_sw;
+ Gtk::RadioButtonGroup _sw_group;
+ Gtk::RadioMenuItem _popup_px;
+ void on_popup_px();
+ Gtk::RadioMenuItem _popup_pt;
+ void on_popup_pt();
+ Gtk::RadioMenuItem _popup_mm;
+ void on_popup_mm();
+ void on_popup_preset(int i);
+ Gtk::MenuItem _popup_sw_remove;
+
+ SPUnit *_sw_unit;
+
+ Gtk::Tooltips _tooltips;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_BUTTON_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp
new file mode 100644
index 000000000..5d4623c19
--- /dev/null
+++ b/src/ui/widget/style-swatch.cpp
@@ -0,0 +1,244 @@
+/**
+ * \brief Static style swatch (fill, stroke, opacity)
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "style-swatch.h"
+
+#include "widgets/spw-utilities.h"
+#include "ui/widget/color-preview.h"
+
+#include "style.h"
+#include "sp-linear-gradient-fns.h"
+#include "sp-radial-gradient-fns.h"
+#include "sp-pattern.h"
+#include "xml/repr.h"
+#include "widgets/widget-sizes.h"
+#include "helper/units.h"
+
+enum {
+ SS_FILL,
+ SS_STROKE
+};
+
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+StyleSwatch::StyleSwatch(SPCSSAttr *css)
+ : _css (NULL),
+
+ _table(2, 6),
+
+ _sw_unit(NULL),
+
+ _tooltips ()
+{
+ _label[SS_FILL].set_markup(_("F:"));
+ _label[SS_STROKE].set_markup(_("S:"));
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ _label[i].set_alignment(0.0, 0.5);
+ _label[i].set_padding(0, 0);
+
+ _color_preview[i] = new Inkscape::UI::Widget::ColorPreview (0);
+ }
+
+ _opacity_value.set_alignment(0.0, 0.5);
+ _opacity_value.set_padding(0, 0);
+
+ _table.set_col_spacings (2);
+ _table.set_row_spacings (0);
+
+ _stroke.pack_start(_place[SS_STROKE]);
+ _stroke_width_place.add(_stroke_width);
+ _stroke.pack_start(_stroke_width_place, Gtk::PACK_SHRINK);
+
+ _table.attach(_label[SS_FILL], 0,1, 0,1, Gtk::SHRINK, Gtk::SHRINK);
+ _table.attach(_label[SS_STROKE], 0,1, 1,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ _table.attach(_place[SS_FILL], 1,2, 0,1);
+ _table.attach(_stroke, 1,2, 1,2);
+
+ _opacity_place.add(_opacity_value);
+ _table.attach(_opacity_place, 2,3, 0,2, Gtk::SHRINK, Gtk::SHRINK);
+
+ pack_start(_table, true, true, 0);
+
+ set_size_request (STYLE_SWATCH_WIDTH, -1);
+
+ sp_set_font_size_smaller (GTK_WIDGET(_opacity_value.gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_stroke_width.gobj()));
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ sp_set_font_size_smaller (GTK_WIDGET(_value[i].gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_place[i].gobj()));
+ sp_set_font_size_smaller (GTK_WIDGET(_label[i].gobj()));
+ }
+
+ setStyle (css);
+}
+
+StyleSwatch::~StyleSwatch()
+{
+ if (_css)
+ sp_repr_css_attr_unref (_css);
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ delete _color_preview[i];
+ }
+}
+
+void
+StyleSwatch::setStyle(SPCSSAttr *css)
+{
+ if (_css)
+ sp_repr_css_attr_unref (_css);
+ _css = sp_repr_css_attr_new();
+ sp_repr_css_merge(_css, css);
+
+ gchar const *css_string = sp_repr_css_write_string (_css);
+ SPStyle *temp_spstyle = sp_style_new();
+ sp_style_merge_from_style_string (temp_spstyle, css_string);
+
+ setStyle (temp_spstyle);
+
+ sp_style_unref (temp_spstyle);
+}
+
+void
+StyleSwatch::setStyle(SPStyle *query)
+{
+ _place[SS_FILL].remove();
+ _place[SS_STROKE].remove();
+
+ bool has_stroke = true;
+
+ for (int i = SS_FILL; i <= SS_STROKE; i++) {
+ Gtk::EventBox *place = &(_place[i]);
+
+ SPIPaint *paint;
+ if (i == SS_FILL) {
+ paint = &(query->fill);
+ } else {
+ paint = &(query->stroke);
+ }
+
+ if (paint->set && paint->type == SP_PAINT_TYPE_COLOR) {
+ guint32 color = sp_color_get_rgba32_falpha (&(paint->value.color),
+ SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value));
+ ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color);
+ _color_preview[i]->show_all();
+ place->add(*_color_preview[i]);
+ gchar *tip;
+ if (i == SS_FILL) {
+ tip = g_strdup_printf ("Fill: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
+ } else {
+ tip = g_strdup_printf ("Stroke: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
+ }
+ _tooltips.set_tip(*place, tip);
+ g_free (tip);
+ } else if (paint->set && paint->type == SP_PAINT_TYPE_PAINTSERVER) {
+ SPPaintServer *server = (i == SS_FILL)? SP_STYLE_FILL_SERVER (query) : SP_STYLE_STROKE_SERVER (query);
+
+ if (SP_IS_LINEARGRADIENT (server)) {
+ _value[i].set_markup(_("L Gradient"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("Linear gradient fill")) : (_("Linear gradient stroke")));
+ } else if (SP_IS_RADIALGRADIENT (server)) {
+ _value[i].set_markup(_("R Gradient"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("Radial gradient fill")) : (_("Radial gradient stroke")));
+ } else if (SP_IS_PATTERN (server)) {
+ _value[i].set_markup(_("Pattern"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("Pattern fill")) : (_("Pattern stroke")));
+ }
+
+ } else if (paint->set && paint->type == SP_PAINT_TYPE_NONE) {
+ _value[i].set_markup(_("None"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("No fill")) : (_("No stroke")));
+ if (i == SS_STROKE) has_stroke = false;
+ } else if (!paint->set) {
+ _value[i].set_markup(_("Unset"));
+ place->add(_value[i]);
+ _tooltips.set_tip(*place, (i == SS_FILL)? (_("Unset fill")) : (_("Unset stroke")));
+ if (i == SS_STROKE) has_stroke = false;
+ }
+ }
+
+// Now query stroke_width
+ if (has_stroke) {
+ double w;
+ if (_sw_unit) {
+ w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit);
+ } else {
+ w = query->stroke_width.computed;
+ }
+
+ {
+ gchar *str = g_strdup_printf(" %.3g", w);
+ _stroke_width.set_markup(str);
+ g_free (str);
+ }
+ {
+ gchar *str = g_strdup_printf(_("Stroke width: %.5g%s"),
+ w,
+ _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px");
+ _tooltips.set_tip(_stroke_width_place, str);
+ g_free (str);
+ }
+ } else {
+ _tooltips.unset_tip(_stroke_width_place);
+ _stroke_width.set_markup ("");
+ }
+
+ gdouble op = SP_SCALE24_TO_FLOAT(query->opacity.value);
+ if (op != 1) {
+ {
+ gchar *str;
+ if (op == 0)
+ str = g_strdup_printf(_("0:%.3g"), op);
+ else
+ str = g_strdup_printf(_("0:.%d"), (int) (op*10));
+ _opacity_value.set_markup (str);
+ g_free (str);
+ }
+ {
+ gchar *str = g_strdup_printf(_("Opacity: %.3g"), op);
+ _tooltips.set_tip(_opacity_place, str);
+ g_free (str);
+ }
+ } else {
+ _tooltips.unset_tip(_opacity_place);
+ _opacity_value.set_markup ("");
+ }
+
+ show_all();
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/style-swatch.h b/src/ui/widget/style-swatch.h
new file mode 100644
index 000000000..d78b3d64e
--- /dev/null
+++ b/src/ui/widget/style-swatch.h
@@ -0,0 +1,88 @@
+/**
+ * \brief Static style swatch (fill, stroke, opacity)
+ *
+ * Author:
+ * buliabyak@gmail.com
+ *
+ * Copyright (C) 2005 author
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_CURRENT_STYLE_H
+#define INKSCAPE_UI_CURRENT_STYLE_H
+
+#include <gtkmm/table.h>
+#include <gtkmm/label.h>
+#include <gtkmm/box.h>
+#include <gtkmm/eventbox.h>
+#include <gtkmm/enums.h>
+
+#include <glibmm/i18n.h>
+
+#include <desktop.h>
+
+#include "button.h"
+
+class SPUnit;
+class SPStyle;
+class SPCSSAttr;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class StyleSwatch : public Gtk::HBox
+{
+public:
+ StyleSwatch (SPStyle *style);
+ StyleSwatch (SPCSSAttr *attr);
+
+ ~StyleSwatch();
+
+ void setStyle(SPStyle *style);
+ void setStyle(SPCSSAttr *attr);
+ SPCSSAttr *getStyle();
+
+protected:
+ SPCSSAttr *_css;
+
+ Gtk::Table _table;
+
+ Gtk::Label _label[2];
+
+ Gtk::EventBox _place[2];
+ Gtk::EventBox _opacity_place;
+
+ Gtk::Label _value[2];
+ Gtk::Label _opacity_value;
+
+ Gtk::Widget *_color_preview[2];
+ Glib::ustring __color[2];
+
+ Gtk::HBox _stroke;
+ Gtk::EventBox _stroke_width_place;
+ Gtk::Label _stroke_width;
+
+ SPUnit *_sw_unit;
+
+ Gtk::Tooltips _tooltips;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_BUTTON_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/svg-canvas.cpp b/src/ui/widget/svg-canvas.cpp
new file mode 100644
index 000000000..1ba49b7ec
--- /dev/null
+++ b/src/ui/widget/svg-canvas.cpp
@@ -0,0 +1,92 @@
+/** \file
+ * Gtkmm facade/wrapper around SPCanvas.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 The Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/widget.h>
+#include "desktop.h"
+#include "desktop-events.h"
+#include "display/canvas-arena.h"
+#include "display/display-forward.h"
+#include "ui/widget/svg-canvas.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+SVGCanvas::SVGCanvas()
+{
+ void *canvas = gtk_type_new (sp_canvas_get_type ());
+ _spcanvas = static_cast<SPCanvas*>(canvas);
+ _widget = Glib::wrap (static_cast<GtkWidget*> (canvas));
+ _dt = 0;
+}
+
+SVGCanvas::~SVGCanvas()
+{
+}
+
+void
+SVGCanvas::init (SPDesktop *dt)
+{
+ _dt = dt;
+ _widget->set_flags(Gtk::CAN_FOCUS);
+
+ // Set background to white
+ Glib::RefPtr<Gtk::Style> style = _widget->get_style();
+ style->set_bg(Gtk::STATE_NORMAL, style->get_white());
+ _widget->set_style(style);
+ _widget->set_extension_events(Gdk::EXTENSION_EVENTS_ALL);
+ _widget->signal_event().connect(sigc::mem_fun(*this, &SVGCanvas::onEvent));
+}
+
+bool
+SVGCanvas::onEvent (GdkEvent * ev) const
+{
+ g_assert (_dt);
+
+ // Gdk::Event doesn't appear to be fully usable for this atm
+ if (ev->type == GDK_BUTTON_PRESS) {
+ // defocus any spinbuttons
+ _widget->grab_focus();
+ }
+
+ if ((ev->type == GDK_BUTTON_PRESS) && (ev->button.button == 3)) {
+ if (ev->button.state & GDK_SHIFT_MASK) {
+ sp_canvas_arena_set_sticky(SP_CANVAS_ARENA(_dt->drawing), true);
+ } else {
+ sp_canvas_arena_set_sticky(SP_CANVAS_ARENA(_dt->drawing), false);
+ }
+ }
+
+ // The keypress events need to be passed to desktop handler explicitly,
+ // because otherwise the event contexts only receive keypresses when the mouse cursor
+ // is over the canvas. This redirection is only done for keypresses and only if there's no
+ // current item on the canvas, because item events and all mouse events are caught
+ // and passed on by the canvas acetate (I think). --bb
+
+ if (ev->type == GDK_KEY_PRESS && !_spcanvas->current_item) {
+ return sp_desktop_root_handler(0, ev, _dt);
+ }
+
+ return false;
+}
+
+}}}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/svg-canvas.h b/src/ui/widget/svg-canvas.h
new file mode 100644
index 000000000..cb8dc4013
--- /dev/null
+++ b/src/ui/widget/svg-canvas.h
@@ -0,0 +1,56 @@
+#ifndef __UI_WIDGET_SVGCANVAS_H__
+#define __UI_WIDGET_SVGCANVAS_H__
+
+/** \file
+ * Gtkmm facade/wrapper around SPCanvas.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 The Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+struct SPCanvas;
+struct SPDesktop;
+namespace Gtk { class Widget; }
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class SVGCanvas
+{
+public:
+ SVGCanvas();
+ ~SVGCanvas();
+ void init (SPDesktop*);
+ Gtk::Widget& widget() const { return *_widget; }
+ SPCanvas* spobj() const { return _spcanvas; }
+
+protected:
+ Gtk::Widget *_widget;
+ SPCanvas *_spcanvas;
+ SPDesktop *_dt;
+
+ bool onEvent (GdkEvent *) const;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/tolerance-slider.cpp b/src/ui/widget/tolerance-slider.cpp
new file mode 100644
index 000000000..dbef74eaf
--- /dev/null
+++ b/src/ui/widget/tolerance-slider.cpp
@@ -0,0 +1,142 @@
+/** \file
+ *
+ Implementation of tolerance slider widget.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/box.h>
+#include <gtkmm/label.h>
+#include <gtkmm/scale.h>
+
+#include "xml/repr.h"
+#include "svg/stringstream.h"
+
+#include "inkscape.h"
+#include "document.h"
+#include "desktop-handles.h"
+#include "sp-namedview.h"
+
+#include "registry.h"
+#include "tolerance-slider.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+//===================================================
+
+//---------------------------------------------------
+
+
+
+//====================================================
+
+ToleranceSlider::ToleranceSlider()
+: _hbox(0)
+{
+}
+
+ToleranceSlider::~ToleranceSlider()
+{
+ if (_hbox) delete _hbox;
+ _scale_changed_connection.disconnect();
+}
+
+void
+ToleranceSlider::init (const Glib::ustring& label1, const Glib::ustring& label2, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr)
+{
+ _hbox = new Gtk::HBox;
+ Gtk::Label *theLabel1 = manage (new Gtk::Label (label1));
+ _hbox->add (*theLabel1);
+ _hscale = manage (new Gtk::HScale (0.4, 50.1, 0.1));
+ _hscale->set_draw_value (true);
+ _hscale->set_value_pos (Gtk::POS_RIGHT);
+ _hscale->set_size_request (100, -1);
+ _hbox->add (*_hscale);
+ Gtk::Label *theLabel2 = manage (new Gtk::Label (label2));
+ _hbox->add (*theLabel2);
+ _key = key;
+ _scale_changed_connection = _hscale->signal_value_changed().connect (sigc::mem_fun (*this, &ToleranceSlider::update));
+ _wr = &wr;
+}
+
+void
+ToleranceSlider::setValue (double val, bool is_absolute)
+{
+ _hscale->set_value (val);
+ Gtk::Adjustment *adj = _hscale->get_adjustment();
+ if (is_absolute)
+ {
+ adj->set_lower (0.4);
+ adj->set_upper (50.1);
+ adj->set_step_increment (0.1);
+ }
+ else
+ {
+ adj->set_lower (1.0);
+ adj->set_upper (51.0);
+ adj->set_step_increment (1.0);
+ }
+ update();
+}
+
+void
+ToleranceSlider::setLimits (double theMin, double theMax)
+{
+ _hscale->set_range (theMin, theMax);
+ _hscale->get_adjustment()->set_step_increment (1);
+}
+
+void
+ToleranceSlider::update()
+{
+ if (_wr->isUpdating())
+ return;
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (!dt)
+ return;
+
+ Inkscape::SVGOStringStream os;
+ os << _hscale->get_value();
+
+ _wr->setUpdating (true);
+
+ SPDocument *doc = SP_DT_DOCUMENT(dt);
+ gboolean saved = sp_document_get_undo_sensitive (doc);
+ sp_document_set_undo_sensitive (doc, FALSE);
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt));
+ repr->setAttribute(_key.c_str(), os.str().c_str());
+ doc->rroot->setAttribute("sodipodi:modified", "true");
+ sp_document_set_undo_sensitive (doc, saved);
+ sp_document_done (doc);
+
+ _wr->setUpdating (false);
+}
+
+
+} // namespace Dialog
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/tolerance-slider.h b/src/ui/widget/tolerance-slider.h
new file mode 100644
index 000000000..2eeacb403
--- /dev/null
+++ b/src/ui/widget/tolerance-slider.h
@@ -0,0 +1,61 @@
+/** \file
+ * \brief
+ *
+ * This widget is part of the Document properties dialog.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2006 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_TOLERANCE_SLIDER__H_
+#define INKSCAPE_UI_WIDGET_TOLERANCE_SLIDER__H_
+
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Registry;
+class ToleranceSlider {
+public:
+ ToleranceSlider();
+ ~ToleranceSlider();
+ void init (const Glib::ustring& label1,
+ const Glib::ustring& label2,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Registry& wr);
+ void setValue (double, bool);
+ void setLimits (double, double);
+ Gtk::HBox* _hbox;
+
+protected:
+ void on_scale_changed();
+ void update();
+ sigc::connection _scale_changed_connection;
+ Gtk::HScale *_hscale;
+ Registry *_wr;
+ Glib::ustring _key;
+};
+
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_TOLERANCE_SLIDER__H_
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/toolbox.cpp b/src/ui/widget/toolbox.cpp
new file mode 100644
index 000000000..e90a58b6e
--- /dev/null
+++ b/src/ui/widget/toolbox.cpp
@@ -0,0 +1,269 @@
+/**
+ * \brief Toolbox Widget - A detachable toolbar for buttons and other widgets.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm/radioaction.h>
+#include <gtk/gtkmain.h>
+#include "ui/widget/toolbox.h"
+#include "path-prefix.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+Toolbox::Toolbox(Gtk::Toolbar *toolbar,
+ Gtk::Orientation orientation)
+ : HandleBox(toolbar)
+{
+ init_actions();
+ init_orientation(orientation);
+ init_style(toolbar->get_toolbar_style());
+}
+
+Toolbox::Toolbox(Gtk::Toolbar *toolbar,
+ Gtk::ToolbarStyle style,
+ Gtk::Orientation orientation)
+ : HandleBox(toolbar)
+{
+ init_actions();
+ init_orientation(orientation);
+ init_style(style);
+}
+
+Gtk::Toolbar&
+Toolbox::get_toolbar()
+{
+ return static_cast<Gtk::Toolbar&>(*_widget);
+}
+
+static Glib::ustring
+get_uidir_filename(char const *basename_utf8)
+{
+ char *const ret_str = g_build_filename(INKSCAPE_UIDIR, basename_utf8, NULL);
+ Glib::ustring const ret(ret_str);
+ g_free(ret_str);
+ return ret;
+}
+
+void
+Toolbox::init_actions()
+{
+ _action_grp = Gtk::ActionGroup::create();
+
+ Gtk::RadioAction::Group icons;
+ _action_grp->add(Gtk::RadioAction::create(icons, "Icons", "Icons Only"),
+ sigc::mem_fun(*this, &Toolbox::on_change_style_icons));
+ _action_grp->add(Gtk::RadioAction::create(icons, "Text", "Text Only"),
+ sigc::mem_fun(*this, &Toolbox::on_change_style_text));
+ _action_grp->add(Gtk::RadioAction::create(icons, "Both", "Text Below Icons"),
+ sigc::mem_fun(*this, &Toolbox::on_change_style_both));
+ _action_grp->add(Gtk::RadioAction::create(icons, "BothHoriz", "Text Beside Icons"),
+ sigc::mem_fun(*this, &Toolbox::on_change_style_both_horiz));
+
+ _detach_grp = Gtk::ActionGroup::create();
+
+ Gtk::RadioAction::Group orient;
+ _detach_grp->add(Gtk::RadioAction::create(orient, "OrientHoriz", "Horizontal"),
+ sigc::mem_fun(*this, &Toolbox::on_change_orient_horiz));
+ _detach_grp->add(Gtk::RadioAction::create(orient, "OrientVert", "Vertical"),
+ sigc::mem_fun(*this, &Toolbox::on_change_orient_vert));
+
+ _detach_grp->add(Gtk::ToggleAction::create("ShowArrow", "Show Arrow",
+ Glib::ustring(), true),
+ sigc::mem_fun(*this, &Toolbox::on_show_arrow));
+
+ _ui_mgr = Gtk::UIManager::create();
+ _ui_mgr->insert_action_group(_action_grp);
+ _ui_mgr->insert_action_group(_detach_grp);
+ _ui_mgr->add_ui_from_file(get_uidir_filename("toolbox.xml"));
+
+ _context_menu = static_cast<Gtk::Menu*>(_ui_mgr->get_widget("/ToolboxMenu"));
+
+ static_cast<Gtk::Toolbar*>(_widget)->signal_popup_context_menu()
+ .connect(sigc::mem_fun(*this, &Toolbox::on_popup_context_menu));
+
+ _detach_grp->set_sensitive(false);
+}
+
+void
+Toolbox::init_orientation(Gtk::Orientation const &orientation)
+{
+ static_cast<Gtk::Toolbar*>(_widget)->set_orientation(orientation);
+ if (orientation == Gtk::ORIENTATION_VERTICAL) {
+ set_handle_position(Gtk::POS_TOP);
+ }
+ switch (orientation) {
+ case Gtk::ORIENTATION_HORIZONTAL: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientHoriz"))
+ ->set_active();
+ break;
+ }
+ case Gtk::ORIENTATION_VERTICAL: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientVert"))
+ ->set_active();
+ break;
+ }
+ }
+}
+
+void
+Toolbox::init_style(Gtk::ToolbarStyle const &style)
+{
+ switch (style) {
+ case Gtk::TOOLBAR_ICONS: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Icons"))
+ ->activate();
+ break;
+ }
+ case Gtk::TOOLBAR_TEXT: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Text"))
+ ->activate();
+ break;
+ }
+ case Gtk::TOOLBAR_BOTH: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Both"))
+ ->activate();
+ break;
+ }
+ case Gtk::TOOLBAR_BOTH_HORIZ: {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("BothHoriz"))
+ ->activate();
+ break;
+ }
+ }
+}
+
+bool
+Toolbox::on_popup_context_menu(int x, int y, int button)
+{
+ (void)x;
+ (void)y;
+ _context_menu->popup(button, gtk_get_current_event_time());
+ return true;
+}
+
+void
+Toolbox::on_child_attached(Gtk::Widget *widget)
+{
+ (void)widget;
+ Gtk::Toolbar *toolbar = static_cast<Gtk::Toolbar*>(_widget);
+
+ if (!(toolbar->get_show_arrow())) {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("ShowArrow"))
+ ->activate();
+ }
+
+ if (get_handle_position() == Gtk::POS_LEFT
+ && toolbar->get_orientation() != Gtk::ORIENTATION_HORIZONTAL) {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientHoriz"))
+ ->activate();
+ } else if (get_handle_position() == Gtk::POS_TOP
+ && toolbar->get_orientation() != Gtk::ORIENTATION_VERTICAL) {
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientVert"))
+ ->activate();
+ }
+
+ _detach_grp->set_sensitive(false);
+}
+
+void
+Toolbox::on_child_detached(Gtk::Widget *widget)
+{
+ (void)widget;
+ _detach_grp->set_sensitive(true);
+
+ Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("ShowArrow"))
+ ->set_active(false);
+}
+
+void
+Toolbox::on_change_style_icons()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Icons"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_ICONS);
+ }
+}
+
+void
+Toolbox::on_change_style_text()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Text"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_TEXT);
+ }
+}
+
+void
+Toolbox::on_change_style_both()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Both"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_BOTH);
+ }
+}
+
+void
+Toolbox::on_change_style_both_horiz()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("BothHoriz"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_BOTH_HORIZ);
+ }
+}
+
+void
+Toolbox::on_change_orient_horiz()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientHoriz"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
+ }
+}
+
+void
+Toolbox::on_change_orient_vert()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientVert"));
+ if (action->get_active()) {
+ static_cast<Gtk::Toolbar*>(_widget)->set_orientation(Gtk::ORIENTATION_VERTICAL);
+ }
+}
+
+void
+Toolbox::on_show_arrow()
+{
+ Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("ShowArrow"));
+ Gtk::Toolbar *toolbar = static_cast<Gtk::Toolbar*>(_widget);
+ if (action->get_active()) {
+ toolbar->set_show_arrow(true);
+ } else {
+ toolbar->set_show_arrow(false);
+ }
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/toolbox.h b/src/ui/widget/toolbox.h
new file mode 100644
index 000000000..9c4e18909
--- /dev/null
+++ b/src/ui/widget/toolbox.h
@@ -0,0 +1,73 @@
+/**
+ * \brief Toolbox Widget - A detachable toolbar for buttons and other widgets.
+ *
+ * Author:
+ * Derek P. Moore <derekm@hackunix.org>
+ *
+ * Copyright (C) 2004 Derek P. Moore
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_TOOLBOX_H
+#define INKSCAPE_UI_WIDGET_TOOLBOX_H
+
+#include <gtkmm/toolbar.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/action.h>
+#include <gtkmm/uimanager.h>
+#include "handlebox.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class Toolbox : public HandleBox
+{
+public:
+ Toolbox(Gtk::Toolbar *toolbar,
+ Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL);
+ Toolbox(Gtk::Toolbar *toolbar,
+ Gtk::ToolbarStyle style,
+ Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL);
+
+ Gtk::Toolbar& get_toolbar();
+
+protected:
+ Gtk::Menu *_context_menu;
+
+ Glib::RefPtr<Gtk::ActionGroup> _action_grp;
+ Glib::RefPtr<Gtk::ActionGroup> _detach_grp;
+ Glib::RefPtr<Gtk::UIManager> _ui_mgr;
+
+ void init_actions();
+ void init_orientation(Gtk::Orientation const &orientation);
+ void init_style(Gtk::ToolbarStyle const &style);
+ bool on_popup_context_menu(int x, int y, int button);
+ void on_child_attached(Gtk::Widget *widget);
+ void on_child_detached(Gtk::Widget *widget);
+ void on_change_style_icons();
+ void on_change_style_text();
+ void on_change_style_both();
+ void on_change_style_both_horiz();
+ void on_change_orient_horiz();
+ void on_change_orient_vert();
+ void on_show_arrow();
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_TOOLBOX_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/unit-menu.cpp b/src/ui/widget/unit-menu.cpp
new file mode 100644
index 000000000..b4271762c
--- /dev/null
+++ b/src/ui/widget/unit-menu.cpp
@@ -0,0 +1,181 @@
+/**
+ * \brief Unit Menu Widget - A drop down menu for choosing unit types.
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <cmath>
+
+#include "unit-menu.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+/**
+ * Construct a UnitMenu
+ *
+ */
+UnitMenu::UnitMenu() : _type(UNIT_TYPE_NONE)
+{
+ set_active(0);
+}
+
+UnitMenu::~UnitMenu() {
+}
+
+/** Adds the unit type to the widget. This extracts the corresponding
+ units from the unit map matching the given type, and appends them
+ to the dropdown widget. It causes the primary unit for the given
+ unit_type to be selected. */
+bool
+UnitMenu::setUnitType(UnitType unit_type)
+{
+ /* Expand the unit widget with unit entries from the unit table */
+ UnitTable::UnitMap m = _unit_table.units(unit_type);
+ UnitTable::UnitMap::iterator iter = m.begin();
+ while(iter != m.end()) {
+ Glib::ustring text = (*iter).first;
+ append_text(text);
+ ++iter;
+ }
+ _type = unit_type;
+ set_active_text(_unit_table.primary(unit_type));
+
+ return true;
+}
+
+/** Returns the Unit object corresponding to the current selection
+ in the dropdown widget */
+Unit
+UnitMenu::getUnit() const {
+ if (get_active_text() == "") {
+ g_assert(_type != UNIT_TYPE_NONE);
+ return _unit_table.getUnit(_unit_table.primary(_type));
+ }
+ return _unit_table.getUnit(get_active_text());
+}
+
+/** Sets the dropdown widget to the given unit abbreviation.
+ Returns true if the unit was selectable, false if not
+ (i.e., if the unit was not present in the widget) */
+bool
+UnitMenu::setUnit(Glib::ustring const & unit) {
+ // TODO: Determine if 'unit' is available in the dropdown.
+ // If not, return false
+
+ set_active_text(unit);
+ return true;
+}
+
+/** Returns the abbreviated unit name of the selected unit */
+Glib::ustring
+UnitMenu::getUnitAbbr() const {
+ if (get_active_text() == "") {
+ return "";
+ }
+ return getUnit().abbr;
+}
+
+/** Returns the UnitType of the selected unit */
+UnitType
+UnitMenu::getUnitType() const {
+ return getUnit().type;
+}
+
+/** Returns the unit factor for the selected unit */
+double
+UnitMenu::getUnitFactor() const
+{
+ return getUnit().factor;
+}
+
+/** Returns the recommended number of digits for displaying
+ * numbers of this unit type.
+ */
+int
+UnitMenu::getDefaultDigits() const
+{
+ return getUnit().defaultDigits();
+}
+
+/** Returns the recommended step size in spin buttons
+ * displaying units of this type
+ */
+double
+UnitMenu::getDefaultStep() const
+{
+ int factor_digits = -1*int(log10(getUnit().factor));
+ return pow(10.0, factor_digits);
+}
+
+/** Returns the recommended page size (when hitting pgup/pgdn)
+ * in spin buttons displaying units of this type
+ */
+double
+UnitMenu::getDefaultPage() const
+{
+ return 10 * getDefaultStep();
+}
+
+/**
+ * Returns the conversion factor required to convert values
+ * of the currently selected unit into units of type
+ * new_unit_abbr.
+ */
+double
+UnitMenu::getConversion(Glib::ustring const &new_unit_abbr, Glib::ustring const &old_unit_abbr) const
+{
+ double old_factor = getUnit().factor;
+ if (old_unit_abbr != "no_unit")
+ old_factor = _unit_table.getUnit(old_unit_abbr).factor;
+ Unit new_unit = _unit_table.getUnit(new_unit_abbr);
+
+ // Catch the case of zero or negative unit factors (error!)
+ if (old_factor < 0.0000001 ||
+ new_unit.factor < 0.0000001) {
+ // TODO: Should we assert here?
+ return 0.00;
+ }
+
+ return old_factor / new_unit.factor;
+}
+
+/** Returns true if the selected unit is not dimensionless
+ * (false for %, true for px, pt, cm, etc)
+ */
+bool
+UnitMenu::isAbsolute() const {
+ return getUnitType() != UNIT_TYPE_DIMENSIONLESS;
+}
+
+/** Returns true if the selected unit is radial (deg or rad)
+ */
+bool
+UnitMenu::isRadial() const {
+ return getUnitType() == UNIT_TYPE_RADIAL;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/unit-menu.h b/src/ui/widget/unit-menu.h
new file mode 100644
index 000000000..60a9702b4
--- /dev/null
+++ b/src/ui/widget/unit-menu.h
@@ -0,0 +1,70 @@
+/**
+ * \brief Unit Menu Widget - A drop down menu for choosing unit types.
+ *
+ * Author:
+ * Bryce Harrington <bryce@bryceharrington.org>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_WIDGET_UNIT_H
+#define INKSCAPE_UI_WIDGET_UNIT_H
+
+#include "combo-text.h"
+#include "util/units.h"
+
+using namespace Inkscape::Util;
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class UnitMenu : public ComboText
+{
+public:
+ UnitMenu();
+ virtual ~UnitMenu();
+
+ bool setUnitType(UnitType unit_type);
+
+ bool setUnit(Glib::ustring const &unit);
+
+ Unit getUnit() const;
+ Glib::ustring getUnitAbbr() const;
+ UnitType getUnitType() const;
+ double getUnitFactor() const;
+
+ int getDefaultDigits() const;
+ double getDefaultStep() const;
+ double getDefaultPage() const;
+
+ double getConversion(Glib::ustring const &new_unit_abbr, Glib::ustring const &old_unit_abbr = "no_unit") const;
+
+ bool isAbsolute() const;
+ bool isRadial() const;
+
+ UnitTable &getUnitTable() {return _unit_table;}
+
+protected:
+ UnitTable _unit_table;
+ UnitType _type;
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // INKSCAPE_UI_WIDGET_UNIT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/ui/widget/zoom-status.cpp b/src/ui/widget/zoom-status.cpp
new file mode 100644
index 000000000..e7320102c
--- /dev/null
+++ b/src/ui/widget/zoom-status.cpp
@@ -0,0 +1,127 @@
+/** \file
+ * Gtkmm facade/wrapper around zoom_status code that formerly lived
+ * in desktop-widget.cpp
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * MenTaLguY <mental@rydia.net>
+ * bulia byak <buliabyak@users.sf.net>
+ *
+ * Copyright (C) 2005 Ralf Stephan
+ * Copyright (C) 2004 MenTaLguY
+ * Copyright (C) 1999-2002 Lauris Kaplinski
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/widget/zoom-status.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "widgets/spw-utilities.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+ZoomStatus::ZoomStatus()
+ : _adj(0.0, -1.0, 1.0, 0.1, 0.1)
+{
+ _dt = 0;
+ _upd_f = false;
+
+ property_numeric() = false;
+ property_update_policy() = Gtk::UPDATE_ALWAYS;
+ sp_set_font_size_smaller(static_cast<GtkWidget*>((void*)gobj()));
+}
+
+ZoomStatus::~ZoomStatus()
+{
+ _dt = 0;
+}
+
+void
+ZoomStatus::init(SPDesktop *dt)
+{
+ _dt = dt;
+ property_digits() = 4;
+ _adj.set_value(0.0);
+ _adj.set_lower(log(SP_DESKTOP_ZOOM_MIN)/log(2.0));
+ _adj.set_upper(log(SP_DESKTOP_ZOOM_MAX)/log(2.0));
+ _adj.set_step_increment(0.1);
+ _adj.set_page_increment(0.1);
+ set_adjustment(_adj);
+}
+
+void
+ZoomStatus::update()
+{
+ if (!_dt) return;
+ _upd_f = true;
+ set_value(log(_dt->current_zoom())/log(2.0));
+ _upd_f = false;
+}
+
+inline double
+value_to_display(double value)
+{
+ return floor(pow(2, value) * 100.0 + 0.5);
+}
+
+inline double
+display_to_value(double value)
+{
+ return log(value / 100.0) / log(2.0);
+}
+
+int
+ZoomStatus::on_input(double *new_val)
+{
+ double new_scrolled = get_value();
+ double new_typed = atof(get_text().c_str());
+
+ if (value_to_display(new_scrolled) == new_typed)
+ { // the new value is set by scrolling
+ *new_val = new_scrolled;
+ } else { // the new value is typed in
+ *new_val = display_to_value(new_typed);
+ }
+
+ return true;
+}
+
+bool
+ZoomStatus::on_output()
+{
+ gchar b[64];
+ g_snprintf(b, 64, "%4.0f%%", value_to_display(get_value()));
+ set_text(b);
+ return true;
+}
+
+void
+ZoomStatus::on_value_changed()
+{
+ if (_upd_f) return;
+ _upd_f = true;
+ g_assert(_dt);
+ double zoom_factor = pow(2, get_value());
+ NR::Rect const d =_dt->get_display_area();
+ _dt->zoom_absolute(d.midpoint()[NR::X], d.midpoint()[NR::Y], zoom_factor);
+ gtk_widget_grab_focus(static_cast<GtkWidget*>((void*)_dt->canvas)); /// \todo this no love song
+ _upd_f = false;
+}
+
+}}}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/ui/widget/zoom-status.h b/src/ui/widget/zoom-status.h
new file mode 100644
index 000000000..58d595329
--- /dev/null
+++ b/src/ui/widget/zoom-status.h
@@ -0,0 +1,61 @@
+#ifndef __UI_WIDGET_ZOOMSTATUS_H__
+#define __UI_WIDGET_ZOOMSTATUS_H__
+
+/** \file
+ * Enhanced spinbutton.
+ *
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ *
+ * Copyright (C) 2005 The Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/spinbutton.h>
+
+struct SPDesktop;
+
+namespace Gtk { class Widget; }
+namespace Inkscape {
+ namespace UI {
+ namespace Widget {
+
+class ZoomStatus : public Gtk::SpinButton
+{
+public:
+ ZoomStatus();
+ ~ZoomStatus();
+
+ void init (SPDesktop*);
+ void update();
+
+protected:
+ Gtk::Adjustment _adj;
+ SPDesktop *_dt;
+ bool _upd_f;
+
+ virtual int on_input (double*);
+ virtual bool on_output();
+ virtual void on_value_changed();
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+
+#endif
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :