Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / ui / widget / registered-widget.cpp
index 46532d35848aa15bf60b058aefef51e511c8dac4..04bd272856b2704feb2676071ad0fd97b5d8bcd7 100644 (file)
@@ -8,6 +8,7 @@
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *   Jon Phillips <jon@rejon.org>
  *   Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
+ *   Abhishek Sharma
  *
  * Copyright (C) 2000 - 2007 Authors
  *
@@ -18,6 +19,7 @@
 # include <config.h>
 #endif
 
+#include "registered-widget.h"
 
 #include "ui/widget/color-picker.h"
 #include "ui/widget/registry.h"
 #include "svg/svg-color.h"
 #include "svg/stringstream.h"
 
-#include "inkscape.h"
-#include "document.h"
-#include "desktop-handles.h"
-#include "sp-namedview.h"
-
-#include "registered-widget.h"
 #include "verbs.h"
 
 // for interruptability bug:
@@ -46,77 +42,40 @@ namespace Inkscape {
 namespace UI {
 namespace Widget {
 
-//===================================================
-
-//---------------------------------------------------
-
-
-void
-RegisteredWidget::write_to_xml(const char * svgstr)
-{
-    // Use local repr here. When repr is specified, use that one, but
-    // if repr==NULL, get the repr of namedview of active desktop.
-    Inkscape::XML::Node *local_repr = repr;
-    SPDocument *local_doc = doc;
-    if (!local_repr) {
-        // no repr specified, use active desktop's namedview's repr
-        SPDesktop* dt = SP_ACTIVE_DESKTOP;
-        local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
-        local_doc = sp_desktop_document(dt);
-    }
-
-    bool saved = sp_document_get_undo_sensitive (local_doc);
-    sp_document_set_undo_sensitive (local_doc, false);
-
-    if (!write_undo) local_repr->setAttribute(_key.c_str(), svgstr);
-    local_doc->rroot->setAttribute("sodipodi:modified", "true");
-
-    sp_document_set_undo_sensitive (local_doc, saved);
-    if (write_undo) {
-        local_repr->setAttribute(_key.c_str(), svgstr);
-        sp_document_done (local_doc, event_type, event_description);
-    }
-}
-
-
-//====================================================
-
-RegisteredCheckButton::RegisteredCheckButton()
-: _button(0),
-   setProgrammatically(false)
-{
-}
+/*#########################################
+ * Registered CHECKBUTTON
+ */
 
 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, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+RegisteredCheckButton::RegisteredCheckButton (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+    : RegisteredWidget<Gtk::CheckButton>()
 {
     init_parent(key, wr, repr_in, doc_in);
 
-    _button = new Gtk::CheckButton;
-    _tt.set_tip (*_button, tip);
+    setProgrammatically = false;
+
+    _tt.set_tip (*this, tip);
     Gtk::Label *l = new Gtk::Label (label);
     l->set_use_underline (true);
-    _button->add (*manage (l));
-    _button->set_alignment (right? 1.0 : 0.0, 0.5);
-    _toggled_connection = _button->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
+    add (*manage (l));
+    set_alignment (right? 1.0 : 0.0, 0.5);
+    _toggled_connection = signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
 }
 
 void
 RegisteredCheckButton::setActive (bool b)
 {
-// FIXME: for some reason, this function is also called when user clicks. then setProgrammatically should not be set!
     setProgrammatically = true;
-    _button->set_active (b);
+    set_active (b);
     //The slave button is greyed out if the master button is unchecked
-    for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
+    for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); i++) {
         (*i)->set_sensitive(b);
     }
+    setProgrammatically = false;
 }
 
 void
@@ -129,47 +88,40 @@ RegisteredCheckButton::on_toggled()
 
     if (_wr->isUpdating())
         return;
-
     _wr->setUpdating (true);
 
-    write_to_xml(_button->get_active() ? "true" : "false");
+    write_to_xml(get_active() ? "true" : "false");
     //The slave button is greyed out if the master button is unchecked
-    for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
-        (*i)->set_sensitive(_button->get_active());
+    for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); i++) {
+        (*i)->set_sensitive(get_active());
     }
 
     _wr->setUpdating (false);
 }
 
-RegisteredUnitMenu::RegisteredUnitMenu()
-: _label(0), _sel(0)
-{
-}
+
+/*#########################################
+ * Registered UNITMENU
+ */
 
 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, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+RegisteredUnitMenu::RegisteredUnitMenu (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+    :  RegisteredWidget<Labelled> (label, "" /*tooltip*/, new UnitMenu())
 {
     init_parent(key, wr, repr_in, doc_in);
 
-    _label = new Gtk::Label (label, 1.0, 0.5);
-    _label->set_use_underline (true);
-    _sel = new UnitMenu ();
-    _label->set_mnemonic_widget (*_sel);
-    _sel->setUnitType (UNIT_TYPE_LINEAR);
-    _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
+    getUnitMenu()->setUnitType (UNIT_TYPE_LINEAR);
+    _changed_connection = getUnitMenu()->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
 }
 
 void
 RegisteredUnitMenu::setUnit (const SPUnit* unit)
 {
-    _sel->setUnit (sp_unit_get_abbreviation (unit));
+    getUnitMenu()->setUnit (sp_unit_get_abbreviation (unit));
 }
 
 void
@@ -179,7 +131,7 @@ RegisteredUnitMenu::on_changed()
         return;
 
     Inkscape::SVGOStringStream os;
-    os << _sel->getUnitAbbr();
+    os << getUnitMenu()->getUnitAbbr();
 
     _wr->setUpdating (true);
 
@@ -189,47 +141,36 @@ RegisteredUnitMenu::on_changed()
 }
 
 
-RegisteredScalarUnit::RegisteredScalarUnit()
-: _widget(0), _um(0)
-{
-}
+/*#########################################
+ * Registered SCALARUNIT
+ */
 
 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, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+RegisteredScalarUnit::RegisteredScalarUnit (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, const RegisteredUnitMenu &rum, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+    : RegisteredWidget<ScalarUnit>(label, tip, UNIT_TYPE_LINEAR, "", "", rum.getUnitMenu()),
+      _um(0)
 {
     init_parent(key, wr, repr_in, doc_in);
 
-    _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel);
-    _widget->initScalar (-1e6, 1e6);
-    _widget->setUnit (rum._sel->getUnitAbbr());
-    _widget->setDigits (2);
-    _um = rum._sel;
-    _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
-}
+    setProgrammatically = false;
 
-ScalarUnit*
-RegisteredScalarUnit::getSU()
-{
-    return _widget;
+    initScalar (-1e6, 1e6);
+    setUnit (rum.getUnitMenu()->getUnitAbbr());
+    setDigits (2);
+    _um = rum.getUnitMenu();
+    _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
 }
 
-void
-RegisteredScalarUnit::setValue (double val)
-{
-    _widget->setValue (val);
-}
 
 void
 RegisteredScalarUnit::on_value_changed()
 {
-    if (_widget->setProgrammatically) {
-        _widget->setProgrammatically = false;
+    if (setProgrammatically) {
+        setProgrammatically = false;
         return;
     }
 
@@ -239,7 +180,7 @@ RegisteredScalarUnit::on_value_changed()
     _wr->setUpdating (true);
 
     Inkscape::SVGOStringStream os;
-    os << _widget->getValue("");
+    os << getValue("");
     if (_um)
         os << _um->getUnitAbbr();
 
@@ -249,50 +190,35 @@ RegisteredScalarUnit::on_value_changed()
 }
 
 
-RegisteredScalar::RegisteredScalar()
-{
-    _widget = NULL;
-}
+/*#########################################
+ * Registered SCALAR
+ */
 
 RegisteredScalar::~RegisteredScalar()
 {
-    if (_widget) 
-        delete _widget;
-
     _value_changed_connection.disconnect();
 }
 
-void
-RegisteredScalar::init ( const Glib::ustring& label, const Glib::ustring& tip, 
+RegisteredScalar::RegisteredScalar ( const Glib::ustring& label, const Glib::ustring& tip,
                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
                          SPDocument * doc_in )
+    : RegisteredWidget<Scalar>(label, tip)
 {
     init_parent(key, wr, repr_in, doc_in);
 
-    _widget = new Scalar (label, tip);
-    _widget->setRange (-1e6, 1e6);
-    _widget->setDigits (2);
-    _widget->setIncrements(0.1, 1.0);
-    _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
-}
-
-Scalar*
-RegisteredScalar::getS()
-{
-    return _widget;
-}
+    setProgrammatically = false;
 
-void
-RegisteredScalar::setValue (double val)
-{
-    _widget->setValue (val);
+    setRange (-1e6, 1e6);
+    setDigits (2);
+    setIncrements(0.1, 1.0);
+    _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
 }
 
 void
 RegisteredScalar::on_value_changed()
 {
-    if (_widget->setProgrammatically) {
-        _widget->setProgrammatically = false;
+    if (setProgrammatically) {
+        setProgrammatically = false;
         return;
     }
 
@@ -302,52 +228,103 @@ RegisteredScalar::on_value_changed()
     _wr->setUpdating (true);
 
     Inkscape::SVGOStringStream os;
-    os << _widget->getValue();
+    os << getValue();
 
-    _widget->set_sensitive(false);
+    set_sensitive(false);
     write_to_xml(os.str().c_str());
-    _widget->set_sensitive(true);
+    set_sensitive(true);
 
     _wr->setUpdating (false);
 }
 
 
-RegisteredColorPicker::RegisteredColorPicker()
-: _label(0), _cp(0)
+/*#########################################
+ * Registered TEXT
+ */
+
+RegisteredText::~RegisteredText()
 {
+    _activate_connection.disconnect();
 }
 
-RegisteredColorPicker::~RegisteredColorPicker()
+RegisteredText::RegisteredText ( const Glib::ustring& label, const Glib::ustring& tip,
+                         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
+                         SPDocument * doc_in )
+    : RegisteredWidget<Text>(label, tip)
 {
-    _changed_connection.disconnect();
-    if (_cp) delete _cp;
-    if (_label) delete _label;
+    init_parent(key, wr, repr_in, doc_in);
+
+    setProgrammatically = false;
+
+    setText("");
+    _activate_connection = signal_activate().connect (sigc::mem_fun (*this, &RegisteredText::on_activate));
 }
 
 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, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+RegisteredText::on_activate()
+{
+    if (setProgrammatically) {
+        setProgrammatically = false;
+        return;
+    }
+
+    if (_wr->isUpdating()) {
+        return;
+    }
+    _wr->setUpdating (true);
+
+    Inkscape::SVGOStringStream os;
+    os << getText();
+
+    set_sensitive(false);
+    write_to_xml(os.str().c_str());
+    set_sensitive(true);
+
+    setText(os.str().c_str());
+
+    _wr->setUpdating (false);
+}
+
+
+/*#########################################
+ * Registered COLORPICKER
+ */
+
+RegisteredColorPicker::RegisteredColorPicker(const Glib::ustring& label,
+                                             const Glib::ustring& title,
+                                             const Glib::ustring& tip,
+                                             const Glib::ustring& ckey,
+                                             const Glib::ustring& akey,
+                                             Registry& wr,
+                                             Inkscape::XML::Node* repr_in,
+                                             SPDocument *doc_in)
+    : RegisteredWidget<ColorPicker> (title, tip, 0, true)
 {
     init_parent("", wr, repr_in, doc_in);
 
     _label = new Gtk::Label (label, 1.0, 0.5);
     _label->set_use_underline (true);
-    _cp = new ColorPicker (title,tip,0,true);
-    _label->set_mnemonic_widget (*_cp);
+    _label->set_mnemonic_widget (*this);
     _ckey = ckey;
     _akey = akey;
-    _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
+    _changed_connection = connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
+}
+
+RegisteredColorPicker::~RegisteredColorPicker()
+{
+    _changed_connection.disconnect();
 }
 
 void
 RegisteredColorPicker::setRgba32 (guint32 rgba)
 {
-    _cp->setRgba32 (rgba);
+    ColorPicker::setRgba32 (rgba);
 }
 
 void
 RegisteredColorPicker::closeWindow()
 {
-    _cp->closeWindow();
+    ColorPicker::closeWindow();
 }
 
 void
@@ -373,57 +350,40 @@ RegisteredColorPicker::on_changed (guint32 rgba)
 
     gchar c[32];
     sp_svg_write_color(c, sizeof(c), rgba);
-    bool saved = sp_document_get_undo_sensitive (local_doc);
-    sp_document_set_undo_sensitive (local_doc, false);
+    bool saved = DocumentUndo::getUndoSensitive(local_doc);
+    DocumentUndo::setUndoSensitive(local_doc, false);
     local_repr->setAttribute(_ckey.c_str(), c);
     sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
-    local_doc->rroot->setAttribute("sodipodi:modified", "true");
-    sp_document_set_undo_sensitive (local_doc, saved);
-    sp_document_done (local_doc, SP_VERB_NONE,
-                      /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
+    DocumentUndo::setUndoSensitive(local_doc, saved);
+
+    local_doc->setModifiedSinceSave();
+    DocumentUndo::done(local_doc, SP_VERB_NONE,
+                       /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
 
     _wr->setUpdating (false);
 }
 
-RegisteredSuffixedInteger::RegisteredSuffixedInteger()
-: _label(0),
-  setProgrammatically(false),
-  _sb(0),
-  _adj(0.0,0.0,100.0,1.0,1.0,1.0),
-  _suffix(0)
-{
-}
+
+/*#########################################
+ * Registered SUFFIXEDINTEGER
+ */
 
 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, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+RegisteredSuffixedInteger::RegisteredSuffixedInteger (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+    : RegisteredWidget<Scalar>(label, tip, 0, suffix),
+      setProgrammatically(false)
 {
     init_parent(key, wr, repr_in, doc_in);
 
-    _label = new Gtk::Label (label);
-    _label->set_alignment (1.0, 0.5);
-    _label->set_use_underline();
-    _sb = new Gtk::SpinButton (_adj, 1.0, 0);
-    _label->set_mnemonic_widget (*_sb);
-    _suffix = new Gtk::Label (suffix);
-    _hbox.pack_start (*_sb, true, true, 0);
-    _hbox.pack_start (*_suffix, false, false, 0);
+    setRange (0, 1e6);
+    setDigits (0);
+    setIncrements(1, 10);
 
-    _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
-}
-
-void
-RegisteredSuffixedInteger::setValue (int i)
-{
-    setProgrammatically = true;
-    _adj.set_value (i);
+    _changed_connection = signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
 }
 
 void
@@ -440,40 +400,41 @@ RegisteredSuffixedInteger::on_value_changed()
     _wr->setUpdating (true);
 
     Inkscape::SVGOStringStream os;
-    int value = int(_adj.get_value());
-    os << value;
+    os << getValue();
 
     write_to_xml(os.str().c_str());
 
     _wr->setUpdating (false);
 }
 
-RegisteredRadioButtonPair::RegisteredRadioButtonPair()
-: _hbox(0),
-   setProgrammatically(false)
-{
-}
+
+/*#########################################
+ * Registered RADIOBUTTONPAIR
+ */
 
 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, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+RegisteredRadioButtonPair::RegisteredRadioButtonPair (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, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
+    : RegisteredWidget<Gtk::HBox>(),
+      _rb1(NULL),
+      _rb2(NULL)
 {
     init_parent(key, wr, repr_in, doc_in);
 
-    _hbox = new Gtk::HBox;
-    _hbox->add (*manage (new Gtk::Label (label)));
+    setProgrammatically = false;
+
+    add (*manage (new Gtk::Label (label)));
     _rb1 = manage (new Gtk::RadioButton (label1, true));
-    _hbox->add (*_rb1);
+    add (*_rb1);
     Gtk::RadioButtonGroup group = _rb1->get_group();
     _rb2 = manage (new Gtk::RadioButton (group, label2, true));
-    _hbox->add (*_rb2);
+    add (*_rb2);
     _rb2->set_active();
     _tt.set_tip (*_rb1, tip1);
     _tt.set_tip (*_rb2, tip2);
@@ -483,9 +444,15 @@ const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument
 void
 RegisteredRadioButtonPair::setValue (bool second)
 {
+    if (!_rb1 || !_rb2)
+        return;
+
     setProgrammatically = true;
-    if (second) _rb2->set_active();
-    else        _rb1->set_active();
+    if (second) {
+        _rb2->set_active();
+    } else {
+        _rb1->set_active();
+    }
 }
 
 void
@@ -507,56 +474,101 @@ RegisteredRadioButtonPair::on_value_changed()
     _wr->setUpdating (false);
 }
 
+
 /*#########################################
  * Registered POINT
  */
 
-RegisteredPoint::RegisteredPoint()
+RegisteredPoint::~RegisteredPoint()
 {
-    _widget = NULL;
+    _value_x_changed_connection.disconnect();
+    _value_y_changed_connection.disconnect();
 }
 
-RegisteredPoint::~RegisteredPoint()
+RegisteredPoint::RegisteredPoint ( const Glib::ustring& label, const Glib::ustring& tip,
+                        const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
+                        SPDocument* doc_in )
+    : RegisteredWidget<Point> (label, tip)
 {
-    if (_widget) 
-        delete _widget;
+    init_parent(key, wr, repr_in, doc_in);
+
+    setRange (-1e6, 1e6);
+    setDigits (2);
+    setIncrements(0.1, 1.0);
+    _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
+    _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
+}
 
+void
+RegisteredPoint::on_value_changed()
+{
+    if (setProgrammatically()) {
+        clearProgrammatically();
+        return;
+    }
+
+    if (_wr->isUpdating())
+        return;
+
+    _wr->setUpdating (true);
+
+    Inkscape::SVGOStringStream os;
+    os << getXValue() << "," << getYValue();
+
+    write_to_xml(os.str().c_str());
+
+    _wr->setUpdating (false);
+}
+
+/*#########################################
+ * Registered TRANSFORMEDPOINT
+ */
+
+RegisteredTransformedPoint::~RegisteredTransformedPoint()
+{
     _value_x_changed_connection.disconnect();
     _value_y_changed_connection.disconnect();
 }
 
-void
-RegisteredPoint::init ( const Glib::ustring& label, const Glib::ustring& tip, 
-                        const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, 
+RegisteredTransformedPoint::RegisteredTransformedPoint ( const Glib::ustring& label, const Glib::ustring& tip,
+                        const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
                         SPDocument* doc_in )
+    : RegisteredWidget<Point> (label, tip),
+      to_svg(Geom::identity())
 {
     init_parent(key, wr, repr_in, doc_in);
 
-    _widget = new Point (label, tip);
-    _widget->setRange (-1e6, 1e6);
-    _widget->setDigits (2);
-    _widget->setIncrements(0.1, 1.0);
-    _value_x_changed_connection = _widget->signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
-    _value_y_changed_connection = _widget->signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
+    setRange (-1e6, 1e6);
+    setDigits (2);
+    setIncrements(0.1, 1.0);
+    _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredTransformedPoint::on_value_changed));
+    _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredTransformedPoint::on_value_changed));
 }
 
-Point*
-RegisteredPoint::getPoint()
+void
+RegisteredTransformedPoint::setValue(Geom::Point const & p)
 {
-    return _widget;
+    Geom::Point new_p = p * to_svg.inverse();
+    Point::setValue(new_p);  // the Point widget should display things in canvas coordinates
 }
 
 void
-RegisteredPoint::setValue (double xval, double yval)
-{
-    _widget->setValue(xval, yval);
+RegisteredTransformedPoint::setTransform(Geom::Matrix const & canvas_to_svg)
+{
+    // check if matrix is singular / has inverse
+    if ( ! canvas_to_svg.isSingular() ) {
+        to_svg = canvas_to_svg;
+    } else {
+        // set back to default
+        to_svg = Geom::identity();
+    }
 }
 
 void
-RegisteredPoint::on_value_changed()
+RegisteredTransformedPoint::on_value_changed()
 {
-    if (_widget->setProgrammatically()) {
-        _widget->clearProgrammatically();
+    if (setProgrammatically()) {
+        clearProgrammatically();
         return;
     }
 
@@ -565,8 +577,10 @@ RegisteredPoint::on_value_changed()
 
     _wr->setUpdating (true);
 
+    Geom::Point pos = getValue() * to_svg;
+
     Inkscape::SVGOStringStream os;
-    os << _widget->getXValue() << "," << _widget->getYValue();
+    os << pos;
 
     write_to_xml(os.str().c_str());
 
@@ -574,80 +588,151 @@ RegisteredPoint::on_value_changed()
 }
 
 /*#########################################
- * Registered RANDOM
+ * Registered TRANSFORMEDPOINT
+ */
+
+RegisteredVector::~RegisteredVector()
+{
+    _value_x_changed_connection.disconnect();
+    _value_y_changed_connection.disconnect();
+}
+
+RegisteredVector::RegisteredVector ( const Glib::ustring& label, const Glib::ustring& tip,
+                        const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
+                        SPDocument* doc_in )
+    : RegisteredWidget<Point> (label, tip),
+      _polar_coords(false)
+{
+    init_parent(key, wr, repr_in, doc_in);
+
+    setRange (-1e6, 1e6);
+    setDigits (2);
+    setIncrements(0.1, 1.0);
+    _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredVector::on_value_changed));
+    _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredVector::on_value_changed));
+}
+
+void
+RegisteredVector::setValue(Geom::Point const & p)
+{
+    if (!_polar_coords) {
+        Point::setValue(p);
+    } else {
+        Geom::Point polar;
+        polar[Geom::X] = atan2(p) *180/M_PI;
+        polar[Geom::Y] = p.length();
+        Point::setValue(polar);
+    }
+}
+
+void
+RegisteredVector::setValue(Geom::Point const & p, Geom::Point const & origin)
+{
+    RegisteredVector::setValue(p);
+    _origin = origin;
+}
+
+/**
+ * Changes the widgets text to polar coordinates. The SVG output will still be a normal carthesian vector.
+ * Careful: when calling getValue(), the return value's X-coord will be the angle, Y-value will be the distance/length. 
+ * After changing the coords type (polar/non-polar), the value has to be reset (setValue).
  */
+void
+RegisteredVector::setPolarCoords(bool polar_coords)
+{
+    _polar_coords = polar_coords;
+    if (polar_coords) {
+        xwidget.setLabelText("Angle:");
+        ywidget.setLabelText("Distance:");
+    } else {
+        xwidget.setLabelText("X:");
+        ywidget.setLabelText("Y:");
+    }
+}
 
-RegisteredRandom::RegisteredRandom()
+void
+RegisteredVector::on_value_changed()
 {
-    _widget = NULL;
+    if (setProgrammatically()) {
+        clearProgrammatically();
+        return;
+    }
+
+    if (_wr->isUpdating())
+        return;
+
+    _wr->setUpdating (true);
+
+    Geom::Point origin = _origin;
+    Geom::Point vector = getValue();
+    if (_polar_coords) {
+        vector = Geom::Point::polar(vector[Geom::X]*M_PI/180, vector[Geom::Y]);
+    }
+
+    Inkscape::SVGOStringStream os;
+    os << origin << " , " << vector;
+
+    write_to_xml(os.str().c_str());
+
+    _wr->setUpdating (false);
 }
 
+/*#########################################
+ * Registered RANDOM
+ */
+
 RegisteredRandom::~RegisteredRandom()
 {
-    if (_widget) 
-        delete _widget;
-
     _value_changed_connection.disconnect();
     _reseeded_connection.disconnect();
 }
 
-void
-RegisteredRandom::init ( const Glib::ustring& label, const Glib::ustring& tip, 
+RegisteredRandom::RegisteredRandom ( const Glib::ustring& label, const Glib::ustring& tip,
                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
                          SPDocument * doc_in )
+    : RegisteredWidget<Random> (label, tip)
 {
     init_parent(key, wr, repr_in, doc_in);
 
-    _widget = new Random (label, tip);
-    _widget->setRange (-1e6, 1e6);
-    _widget->setDigits (2);
-    _widget->setIncrements(0.1, 1.0);
-    _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
-    _reseeded_connection = _widget->signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
-}
+    setProgrammatically = false;
 
-Random*
-RegisteredRandom::getR()
-{
-    return _widget;
+    setRange (-1e6, 1e6);
+    setDigits (2);
+    setIncrements(0.1, 1.0);
+    _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
+    _reseeded_connection = signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
 }
 
 void
 RegisteredRandom::setValue (double val, long startseed)
 {
-    _widget->setValue (val);
-    _widget->setStartSeed(startseed);
+    Scalar::setValue (val);
+    setStartSeed(startseed);
 }
 
 void
 RegisteredRandom::on_value_changed()
 {
-    if (_widget->setProgrammatically) {
-        _widget->setProgrammatically = false;
+    if (setProgrammatically) {
+        setProgrammatically = false;
         return;
     }
 
-    if (_wr->isUpdating())
+    if (_wr->isUpdating()) {
         return;
+    }
     _wr->setUpdating (true);
 
-    // FIXME:  gtk bug?
-    // disable interruptibility: see http://inkscape.svn.sourceforge.net/viewvc/inkscape/inkscape/trunk/src/ui/widget/selected-style.cpp?r1=13149&r2=13257&sortby=date
-    SPDesktop* dt = SP_ACTIVE_DESKTOP;
-    sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(dt), 0);
-
     Inkscape::SVGOStringStream os;
-    os << _widget->getValue() << ';' << _widget->getStartSeed();
+    os << getValue() << ';' << getStartSeed();
 
+    set_sensitive(false);
     write_to_xml(os.str().c_str());
-
-    // resume interruptibility
-    sp_canvas_end_forced_full_redraws(sp_desktop_canvas(dt));
+    set_sensitive(true);
 
     _wr->setUpdating (false);
 }
 
-
 } // namespace Dialog
 } // namespace UI
 } // namespace Inkscape