Code

first crack at enabling blend for layers dialog
[inkscape.git] / src / ui / widget / registered-widget.cpp
index 1bfcb1f8465ead4dd15ff062e910e744bcb277c1..aac9ff25ce8c47b50f5ed310a65aa90c569bde89 100644 (file)
@@ -2,13 +2,14 @@
  *
  *
  * Authors:
+ *   Johan Engelen <j.b.c.engelen@utwente.nl>
  *   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
+ * Copyright (C) 2000 - 2007 Authors
  *
  * Released under GNU GPL.  Read the file 'COPYING' for more information
  */
@@ -21,6 +22,9 @@
 #include "ui/widget/color-picker.h"
 #include "ui/widget/registry.h"
 #include "ui/widget/scalar-unit.h"
+#include "ui/widget/point.h"
+#include "ui/widget/random.h"
+#include "widgets/spinbutton-events.h"
 
 #include "helper/units.h"
 #include "xml/repr.h"
 #include "sp-namedview.h"
 
 #include "registered-widget.h"
+#include "verbs.h"
+
+// for interruptability bug:
+#include "display/sp-canvas.h"
 
 namespace Inkscape {
 namespace UI {
@@ -43,11 +51,39 @@ 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)
+: _button(0),
+   setProgrammatically(false)
 {
 }
 
@@ -58,48 +94,49 @@ RegisteredCheckButton::~RegisteredCheckButton()
 }
 
 void
-RegisteredCheckButton::init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right)
+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)
 {
+    init_parent(key, wr, repr_in, doc_in);
+
     _button = new Gtk::CheckButton;
     _tt.set_tip (*_button, 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);
-    _key = key;
-    _wr = &wr;
     _toggled_connection = _button->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
 }
 
 void
 RegisteredCheckButton::setActive (bool b)
 {
+    setProgrammatically = true;
     _button->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++) {
+        (*i)->set_sensitive(b);
+    }
+    setProgrammatically = false;
 }
 
 void
 RegisteredCheckButton::on_toggled()
 {
-    if (_wr->isUpdating())
-        return;
-
-    SPDesktop *dt = SP_ACTIVE_DESKTOP;
-    if (!dt) {
+    if (setProgrammatically) {
+        setProgrammatically = false;
         return;
     }
 
-    SPDocument *doc = sp_desktop_document(dt);
-
-    Inkscape::XML::Node *repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
+    if (_wr->isUpdating())
+        return;
     _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);
-    
+    write_to_xml(_button->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());
+    }
+
     _wr->setUpdating (false);
 }
 
@@ -116,19 +153,19 @@ RegisteredUnitMenu::~RegisteredUnitMenu()
 }
 
 void
-RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr)
+RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
 {
+    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);
-    _wr = &wr;
-    _key = key;
     _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
 }
 
-void 
+void
 RegisteredUnitMenu::setUnit (const SPUnit* unit)
 {
     _sel->setUnit (sp_unit_get_abbreviation (unit));
@@ -140,24 +177,13 @@ 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_desktop_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_desktop_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);
-    
+    write_to_xml(os.str().c_str());
+
     _wr->setUpdating (false);
 }
 
@@ -174,16 +200,16 @@ RegisteredScalarUnit::~RegisteredScalarUnit()
 }
 
 void
-RegisteredScalarUnit::init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, const RegisteredUnitMenu &rum, Registry& wr)
+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)
 {
+    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);
-    _key = key;
     _um = rum._sel;
     _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
-    _wr = &wr;
 }
 
 ScalarUnit*
@@ -192,42 +218,101 @@ RegisteredScalarUnit::getSU()
     return _widget;
 }
 
-void 
+void
 RegisteredScalarUnit::setValue (double val)
 {
-    _widget->setValue (val);
-    on_value_changed();
+    if (_widget)
+        _widget->setValue (val);
 }
 
 void
 RegisteredScalarUnit::on_value_changed()
 {
-    if (_wr->isUpdating())
+    if (_widget->setProgrammatically) {
+        _widget->setProgrammatically = false;
         return;
+    }
 
-    SPDesktop *dt = SP_ACTIVE_DESKTOP;
-    if (!dt) 
+    if (_wr->isUpdating())
         return;
 
+    _wr->setUpdating (true);
+
     Inkscape::SVGOStringStream os;
     os << _widget->getValue("");
     if (_um)
         os << _um->getUnitAbbr();
 
+    write_to_xml(os.str().c_str());
+
+    _wr->setUpdating (false);
+}
+
+
+RegisteredScalar::RegisteredScalar()
+{
+    _widget = NULL;
+}
+
+RegisteredScalar::~RegisteredScalar()
+{
+    if (_widget)
+        delete _widget;
+
+    _value_changed_connection.disconnect();
+}
+
+void
+RegisteredScalar::init ( const Glib::ustring& label, const Glib::ustring& tip,
+                         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
+                         SPDocument * doc_in )
+{
+    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;
+}
+
+void
+RegisteredScalar::setValue (double val)
+{
+    if (_widget)
+        _widget->setValue (val);
+}
+
+void
+RegisteredScalar::on_value_changed()
+{
+    if (_widget->setProgrammatically) {
+        _widget->setProgrammatically = false;
+        return;
+    }
+
+    if (_wr->isUpdating()) {
+        return;
+    }
     _wr->setUpdating (true);
 
-    SPDocument *doc = sp_desktop_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_desktop_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);
-    
+    Inkscape::SVGOStringStream os;
+    os << _widget->getValue();
+
+    _widget->set_sensitive(false);
+    write_to_xml(os.str().c_str());
+    _widget->set_sensitive(true);
+
     _wr->setUpdating (false);
 }
 
+
 RegisteredColorPicker::RegisteredColorPicker()
 : _label(0), _cp(0)
 {
@@ -241,19 +326,20 @@ RegisteredColorPicker::~RegisteredColorPicker()
 }
 
 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)
+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)
 {
+    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);
     _ckey = ckey;
     _akey = akey;
-    _wr = &wr;
     _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
 }
 
-void 
+void
 RegisteredColorPicker::setRgba32 (guint32 rgba)
 {
     _cp->setRgba32 (rgba);
@@ -268,21 +354,43 @@ RegisteredColorPicker::closeWindow()
 void
 RegisteredColorPicker::on_changed (guint32 rgba)
 {
-    if (_wr->isUpdating() || !SP_ACTIVE_DESKTOP)
+    if (_wr->isUpdating())
         return;
 
     _wr->setUpdating (true);
-    Inkscape::XML::Node *repr = SP_OBJECT_REPR(sp_desktop_namedview(SP_ACTIVE_DESKTOP));
+
+    // 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;
+        if (!dt)
+            return;
+        local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
+        local_doc = sp_desktop_document(dt);
+    }
+
     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);
+    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);
+    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");
+
     _wr->setUpdating (false);
 }
 
 RegisteredSuffixedInteger::RegisteredSuffixedInteger()
-: _label(0), _sb(0),
-  _adj(0.0,0.0,100.0,1.0,1.0,1.0), 
+: _label(0),
+  setProgrammatically(false),
+  _sb(0),
+  _adj(0.0,0.0,100.0,1.0,1.0,1.0),
   _suffix(0)
 {
 }
@@ -296,50 +404,55 @@ RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
 }
 
 void
-RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr)
+RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
 {
-    _key = key;
+    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);
+    _sb->set_numeric();
     _label->set_mnemonic_widget (*_sb);
     _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 
+void
 RegisteredSuffixedInteger::setValue (int i)
 {
+    setProgrammatically = true;
     _adj.set_value (i);
 }
 
 void
 RegisteredSuffixedInteger::on_value_changed()
 {
-    if (_wr->isUpdating() || !SP_ACTIVE_DESKTOP)
+    if (setProgrammatically) {
+        setProgrammatically = false;
+        return;
+    }
+
+    if (_wr->isUpdating())
         return;
 
     _wr->setUpdating (true);
-    
-    SPDesktop* dt = SP_ACTIVE_DESKTOP;
-    Inkscape::XML::Node *repr = SP_OBJECT_REPR(sp_desktop_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_desktop_document(dt));
-    
+    write_to_xml(os.str().c_str());
+
     _wr->setUpdating (false);
 }
 
 RegisteredRadioButtonPair::RegisteredRadioButtonPair()
-: _hbox(0)
+: _hbox(0),
+   setProgrammatically(false)
 {
 }
 
@@ -349,11 +462,13 @@ RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
 }
 
 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)
+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)
 {
+    init_parent(key, wr, repr_in, doc_in);
+
     _hbox = new Gtk::HBox;
     _hbox->add (*manage (new Gtk::Label (label)));
     _rb1 = manage (new Gtk::RadioButton (label1, true));
@@ -364,43 +479,182 @@ const Glib::ustring& key, Registry& wr)
     _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 
+void
 RegisteredRadioButtonPair::setValue (bool second)
 {
-    if (second) _rb2->set_active();
-    else        _rb1->set_active();
+    if (!_rb1 || !_rb2)
+        return;
+
+    setProgrammatically = true;
+    if (second) {
+        _rb2->set_active();
+    } else {
+        _rb1->set_active();
+    }
 }
 
 void
 RegisteredRadioButtonPair::on_value_changed()
 {
-    if (_wr->isUpdating())
+    if (setProgrammatically) {
+        setProgrammatically = false;
         return;
+    }
 
-    SPDesktop *dt = SP_ACTIVE_DESKTOP;
-    if (!dt) 
+    if (_wr->isUpdating())
         return;
 
     _wr->setUpdating (true);
-    
+
     bool second = _rb2->get_active();
-    SPDocument *doc = sp_desktop_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_desktop_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);
-    
+    write_to_xml(second ? "true" : "false");
+
+    _wr->setUpdating (false);
+}
+
+/*#########################################
+ * Registered POINT
+ */
+
+RegisteredPoint::RegisteredPoint()
+{
+    _widget = NULL;
+}
+
+RegisteredPoint::~RegisteredPoint()
+{
+    if (_widget) 
+        delete _widget;
+
+    _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, 
+                        SPDocument* doc_in )
+{
+    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));
+}
+
+Point*
+RegisteredPoint::getPoint()
+{
+    return _widget;
+}
+
+void
+RegisteredPoint::setValue (double xval, double yval)
+{
+    if (_widget)
+        _widget->setValue(xval, yval);
+}
+
+void
+RegisteredPoint::on_value_changed()
+{
+    if (_widget->setProgrammatically()) {
+        _widget->clearProgrammatically();
+        return;
+    }
+
+    if (_wr->isUpdating())
+        return;
+
+    _wr->setUpdating (true);
+
+    Inkscape::SVGOStringStream os;
+    os << _widget->getXValue() << "," << _widget->getYValue();
+
+    write_to_xml(os.str().c_str());
+
+    _wr->setUpdating (false);
+}
+
+/*#########################################
+ * Registered RANDOM
+ */
+
+RegisteredRandom::RegisteredRandom()
+{
+    _widget = NULL;
+}
+
+RegisteredRandom::~RegisteredRandom()
+{
+    if (_widget) 
+        delete _widget;
+
+    _value_changed_connection.disconnect();
+    _reseeded_connection.disconnect();
+}
+
+void
+RegisteredRandom::init ( const Glib::ustring& label, const Glib::ustring& tip, 
+                         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
+                         SPDocument * doc_in )
+{
+    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));
+}
+
+Random*
+RegisteredRandom::getR()
+{
+    return _widget;
+}
+
+void
+RegisteredRandom::setValue (double val, long startseed)
+{
+    if (!_widget)
+        return;
+
+    _widget->setValue (val);
+    _widget->setStartSeed(startseed);
+}
+
+void
+RegisteredRandom::on_value_changed()
+{
+    if (_widget->setProgrammatically) {
+        _widget->setProgrammatically = false;
+        return;
+    }
+
+    if (_wr->isUpdating()) {
+        return;
+    }
+    _wr->setUpdating (true);
+
+    Inkscape::SVGOStringStream os;
+    os << _widget->getValue() << ';' << _widget->getStartSeed();
+
+    _widget->set_sensitive(false);
+    write_to_xml(os.str().c_str());
+    _widget->set_sensitive(true);
+
     _wr->setUpdating (false);
 }
 
+
 } // namespace Dialog
 } // namespace UI
 } // namespace Inkscape