Code

Fix checkbuttons of LPEs. Should no longer crash, should no longer need clicking...
[inkscape.git] / src / ui / widget / registered-widget.cpp
1 /** \file
2  *
3  *
4  * Authors:
5  *   Johan Engelen <j.b.c.engelen@utwente.nl>
6  *   bulia byak <buliabyak@users.sf.net>
7  *   Bryce W. Harrington <bryce@bryceharrington.org>
8  *   Lauris Kaplinski <lauris@kaplinski.com>
9  *   Jon Phillips <jon@rejon.org>
10  *   Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
11  *
12  * Copyright (C) 2000 - 2007 Authors
13  *
14  * Released under GNU GPL.  Read the file 'COPYING' for more information
15  */
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
22 #include "ui/widget/color-picker.h"
23 #include "ui/widget/registry.h"
24 #include "ui/widget/scalar-unit.h"
25 #include "ui/widget/point.h"
26 #include "ui/widget/random.h"
27 #include "widgets/spinbutton-events.h"
29 #include "helper/units.h"
30 #include "xml/repr.h"
31 #include "svg/svg-color.h"
32 #include "svg/stringstream.h"
34 #include "inkscape.h"
35 #include "document.h"
36 #include "desktop-handles.h"
37 #include "sp-namedview.h"
39 #include "registered-widget.h"
40 #include "verbs.h"
42 // for interruptability bug:
43 #include "display/sp-canvas.h"
45 namespace Inkscape {
46 namespace UI {
47 namespace Widget {
49 //===================================================
51 //---------------------------------------------------
54 void
55 RegisteredWidget::write_to_xml(const char * svgstr)
56 {
57     // Use local repr here. When repr is specified, use that one, but
58     // if repr==NULL, get the repr of namedview of active desktop.
59     Inkscape::XML::Node *local_repr = repr;
60     SPDocument *local_doc = doc;
61     if (!local_repr) {
62         // no repr specified, use active desktop's namedview's repr
63         SPDesktop* dt = SP_ACTIVE_DESKTOP;
64         local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
65         local_doc = sp_desktop_document(dt);
66     }
68     bool saved = sp_document_get_undo_sensitive (local_doc);
69     sp_document_set_undo_sensitive (local_doc, false);
71     if (!write_undo) local_repr->setAttribute(_key.c_str(), svgstr);
72     local_doc->rroot->setAttribute("sodipodi:modified", "true");
74     sp_document_set_undo_sensitive (local_doc, saved);
75     if (write_undo) {
76         local_repr->setAttribute(_key.c_str(), svgstr);
77         sp_document_done (local_doc, event_type, event_description);
78     }
79 }
82 //====================================================
84 RegisteredCheckButton::RegisteredCheckButton()
85 : _button(0),
86    setProgrammatically(false)
87 {
88 }
90 RegisteredCheckButton::~RegisteredCheckButton()
91 {
92     _toggled_connection.disconnect();
93     if (_button) delete _button;
94 }
96 void
97 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)
98 {
99     init_parent(key, wr, repr_in, doc_in);
101     _button = new Gtk::CheckButton;
102     _tt.set_tip (*_button, tip);
103     Gtk::Label *l = new Gtk::Label (label);
104     l->set_use_underline (true);
105     _button->add (*manage (l));
106     _button->set_alignment (right? 1.0 : 0.0, 0.5);
107     _toggled_connection = _button->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
110 void
111 RegisteredCheckButton::setActive (bool b)
113     if (_wr->isUpdating())
114         return;
116     setProgrammatically = true;
117     _button->set_active (b);
118     //The slave button is greyed out if the master button is unchecked
119     for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
120         (*i)->set_sensitive(b);
121     }
122     setProgrammatically = false;
125 void
126 RegisteredCheckButton::on_toggled()
128     if (setProgrammatically) {
129         setProgrammatically = false;
130         return;
131     }
133     if (_wr->isUpdating())
134         return;
135     _wr->setUpdating (true);
137     write_to_xml(_button->get_active() ? "true" : "false");
138     //The slave button is greyed out if the master button is unchecked
139     for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
140         (*i)->set_sensitive(_button->get_active());
141     }
143     _wr->setUpdating (false);
146 RegisteredUnitMenu::RegisteredUnitMenu()
147 : _label(0), _sel(0)
151 RegisteredUnitMenu::~RegisteredUnitMenu()
153     _changed_connection.disconnect();
154     if (_label) delete _label;
155     if (_sel) delete _sel;
158 void
159 RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
161     init_parent(key, wr, repr_in, doc_in);
163     _label = new Gtk::Label (label, 1.0, 0.5);
164     _label->set_use_underline (true);
165     _sel = new UnitMenu ();
166     _label->set_mnemonic_widget (*_sel);
167     _sel->setUnitType (UNIT_TYPE_LINEAR);
168     _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
171 void
172 RegisteredUnitMenu::setUnit (const SPUnit* unit)
174     _sel->setUnit (sp_unit_get_abbreviation (unit));
177 void
178 RegisteredUnitMenu::on_changed()
180     if (_wr->isUpdating())
181         return;
183     Inkscape::SVGOStringStream os;
184     os << _sel->getUnitAbbr();
186     _wr->setUpdating (true);
188     write_to_xml(os.str().c_str());
190     _wr->setUpdating (false);
194 RegisteredScalarUnit::RegisteredScalarUnit()
195 : _widget(0), _um(0)
199 RegisteredScalarUnit::~RegisteredScalarUnit()
201     if (_widget) delete _widget;
202     _value_changed_connection.disconnect();
205 void
206 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)
208     init_parent(key, wr, repr_in, doc_in);
210     _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel);
211     _widget->initScalar (-1e6, 1e6);
212     _widget->setUnit (rum._sel->getUnitAbbr());
213     _widget->setDigits (2);
214     _um = rum._sel;
215     _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
218 ScalarUnit*
219 RegisteredScalarUnit::getSU()
221     return _widget;
224 void
225 RegisteredScalarUnit::setValue (double val)
227     if (_wr->isUpdating())
228         return;
230     _widget->setValue (val);
233 void
234 RegisteredScalarUnit::on_value_changed()
236     if (_widget->setProgrammatically) {
237         _widget->setProgrammatically = false;
238         return;
239     }
241     if (_wr->isUpdating())
242         return;
244     _wr->setUpdating (true);
246     Inkscape::SVGOStringStream os;
247     os << _widget->getValue("");
248     if (_um)
249         os << _um->getUnitAbbr();
251     write_to_xml(os.str().c_str());
253     _wr->setUpdating (false);
257 RegisteredScalar::RegisteredScalar()
259     _widget = NULL;
262 RegisteredScalar::~RegisteredScalar()
264     if (_widget) 
265         delete _widget;
267     _value_changed_connection.disconnect();
270 void
271 RegisteredScalar::init ( const Glib::ustring& label, const Glib::ustring& tip, 
272                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
273                          SPDocument * doc_in )
275     init_parent(key, wr, repr_in, doc_in);
277     _widget = new Scalar (label, tip);
278     _widget->setRange (-1e6, 1e6);
279     _widget->setDigits (2);
280     _widget->setIncrements(0.1, 1.0);
281     _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
284 Scalar*
285 RegisteredScalar::getS()
287     return _widget;
290 void
291 RegisteredScalar::setValue (double val)
293     if (_wr->isUpdating())
294         return;
296     _widget->setValue (val);
299 void
300 RegisteredScalar::on_value_changed()
302     if (_widget->setProgrammatically) {
303         _widget->setProgrammatically = false;
304         return;
305     }
307     if (_wr->isUpdating()) {
308         return;
309     }
310     _wr->setUpdating (true);
312     Inkscape::SVGOStringStream os;
313     os << _widget->getValue();
315     _widget->set_sensitive(false);
316     write_to_xml(os.str().c_str());
317     _widget->set_sensitive(true);
319     _wr->setUpdating (false);
323 RegisteredColorPicker::RegisteredColorPicker()
324 : _label(0), _cp(0)
328 RegisteredColorPicker::~RegisteredColorPicker()
330     _changed_connection.disconnect();
331     if (_cp) delete _cp;
332     if (_label) delete _label;
335 void
336 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)
338     init_parent("", wr, repr_in, doc_in);
340     _label = new Gtk::Label (label, 1.0, 0.5);
341     _label->set_use_underline (true);
342     _cp = new ColorPicker (title,tip,0,true);
343     _label->set_mnemonic_widget (*_cp);
344     _ckey = ckey;
345     _akey = akey;
346     _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
349 void
350 RegisteredColorPicker::setRgba32 (guint32 rgba)
352     if (_wr->isUpdating())
353         return;
355     _cp->setRgba32 (rgba);
358 void
359 RegisteredColorPicker::closeWindow()
361     _cp->closeWindow();
364 void
365 RegisteredColorPicker::on_changed (guint32 rgba)
367     if (_wr->isUpdating())
368         return;
370     _wr->setUpdating (true);
372     // Use local repr here. When repr is specified, use that one, but
373     // if repr==NULL, get the repr of namedview of active desktop.
374     Inkscape::XML::Node *local_repr = repr;
375     SPDocument *local_doc = doc;
376     if (!local_repr) {
377         // no repr specified, use active desktop's namedview's repr
378         SPDesktop *dt = SP_ACTIVE_DESKTOP;
379         if (!dt)
380             return;
381         local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
382         local_doc = sp_desktop_document(dt);
383     }
385     gchar c[32];
386     sp_svg_write_color(c, sizeof(c), rgba);
387     bool saved = sp_document_get_undo_sensitive (local_doc);
388     sp_document_set_undo_sensitive (local_doc, false);
389     local_repr->setAttribute(_ckey.c_str(), c);
390     sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
391     local_doc->rroot->setAttribute("sodipodi:modified", "true");
392     sp_document_set_undo_sensitive (local_doc, saved);
393     sp_document_done (local_doc, SP_VERB_NONE,
394                       /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
396     _wr->setUpdating (false);
399 RegisteredSuffixedInteger::RegisteredSuffixedInteger()
400 : _label(0),
401   setProgrammatically(false),
402   _sb(0),
403   _adj(0.0,0.0,100.0,1.0,1.0,1.0),
404   _suffix(0)
408 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
410     _changed_connection.disconnect();
411     if (_label) delete _label;
412     if (_suffix) delete _suffix;
413     if (_sb) delete _sb;
416 void
417 RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
419     init_parent(key, wr, repr_in, doc_in);
421     _label = new Gtk::Label (label);
422     _label->set_alignment (1.0, 0.5);
423     _label->set_use_underline();
424     _sb = new Gtk::SpinButton (_adj, 1.0, 0);
425     _label->set_mnemonic_widget (*_sb);
426     _suffix = new Gtk::Label (suffix);
427     _hbox.pack_start (*_sb, true, true, 0);
428     _hbox.pack_start (*_suffix, false, false, 0);
430     _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
433 void
434 RegisteredSuffixedInteger::setValue (int i)
436     if (_wr->isUpdating())
437         return;
439     setProgrammatically = true;
440     _adj.set_value (i);
443 void
444 RegisteredSuffixedInteger::on_value_changed()
446     if (setProgrammatically) {
447         setProgrammatically = false;
448         return;
449     }
451     if (_wr->isUpdating())
452         return;
454     _wr->setUpdating (true);
456     Inkscape::SVGOStringStream os;
457     int value = int(_adj.get_value());
458     os << value;
460     write_to_xml(os.str().c_str());
462     _wr->setUpdating (false);
465 RegisteredRadioButtonPair::RegisteredRadioButtonPair()
466 : _hbox(0),
467    setProgrammatically(false)
471 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
473     _changed_connection.disconnect();
476 void
477 RegisteredRadioButtonPair::init (const Glib::ustring& label,
478 const Glib::ustring& label1, const Glib::ustring& label2,
479 const Glib::ustring& tip1, const Glib::ustring& tip2,
480 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
482     init_parent(key, wr, repr_in, doc_in);
484     _hbox = new Gtk::HBox;
485     _hbox->add (*manage (new Gtk::Label (label)));
486     _rb1 = manage (new Gtk::RadioButton (label1, true));
487     _hbox->add (*_rb1);
488     Gtk::RadioButtonGroup group = _rb1->get_group();
489     _rb2 = manage (new Gtk::RadioButton (group, label2, true));
490     _hbox->add (*_rb2);
491     _rb2->set_active();
492     _tt.set_tip (*_rb1, tip1);
493     _tt.set_tip (*_rb2, tip2);
494     _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
497 void
498 RegisteredRadioButtonPair::setValue (bool second)
500     if (_wr->isUpdating())
501         return;
503     setProgrammatically = true;
504     if (second) _rb2->set_active();
505     else        _rb1->set_active();
508 void
509 RegisteredRadioButtonPair::on_value_changed()
511     if (setProgrammatically) {
512         setProgrammatically = false;
513         return;
514     }
516     if (_wr->isUpdating())
517         return;
519     _wr->setUpdating (true);
521     bool second = _rb2->get_active();
522     write_to_xml(second ? "true" : "false");
524     _wr->setUpdating (false);
527 /*#########################################
528  * Registered POINT
529  */
531 RegisteredPoint::RegisteredPoint()
533     _widget = NULL;
536 RegisteredPoint::~RegisteredPoint()
538     if (_widget) 
539         delete _widget;
541     _value_x_changed_connection.disconnect();
542     _value_y_changed_connection.disconnect();
545 void
546 RegisteredPoint::init ( const Glib::ustring& label, const Glib::ustring& tip, 
547                         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, 
548                         SPDocument* doc_in )
550     init_parent(key, wr, repr_in, doc_in);
552     _widget = new Point (label, tip);
553     _widget->setRange (-1e6, 1e6);
554     _widget->setDigits (2);
555     _widget->setIncrements(0.1, 1.0);
556     _value_x_changed_connection = _widget->signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
557     _value_y_changed_connection = _widget->signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
560 Point*
561 RegisteredPoint::getPoint()
563     return _widget;
566 void
567 RegisteredPoint::setValue (double xval, double yval)
569     if (_wr->isUpdating())
570         return;
572     _widget->setValue(xval, yval);
575 void
576 RegisteredPoint::on_value_changed()
578     if (_widget->setProgrammatically()) {
579         _widget->clearProgrammatically();
580         return;
581     }
583     if (_wr->isUpdating())
584         return;
586     _wr->setUpdating (true);
588     Inkscape::SVGOStringStream os;
589     os << _widget->getXValue() << "," << _widget->getYValue();
591     write_to_xml(os.str().c_str());
593     _wr->setUpdating (false);
596 /*#########################################
597  * Registered RANDOM
598  */
600 RegisteredRandom::RegisteredRandom()
602     _widget = NULL;
605 RegisteredRandom::~RegisteredRandom()
607     if (_widget) 
608         delete _widget;
610     _value_changed_connection.disconnect();
611     _reseeded_connection.disconnect();
614 void
615 RegisteredRandom::init ( const Glib::ustring& label, const Glib::ustring& tip, 
616                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
617                          SPDocument * doc_in )
619     init_parent(key, wr, repr_in, doc_in);
621     _widget = new Random (label, tip);
622     _widget->setRange (-1e6, 1e6);
623     _widget->setDigits (2);
624     _widget->setIncrements(0.1, 1.0);
625     _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
626     _reseeded_connection = _widget->signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
629 Random*
630 RegisteredRandom::getR()
632     return _widget;
635 void
636 RegisteredRandom::setValue (double val, long startseed)
638     if (_wr->isUpdating())
639         return;
641     _widget->setValue (val);
642     _widget->setStartSeed(startseed);
645 void
646 RegisteredRandom::on_value_changed()
648     if (_widget->setProgrammatically) {
649         _widget->setProgrammatically = false;
650         return;
651     }
653     if (_wr->isUpdating())
654         return;
655     _wr->setUpdating (true);
657     // FIXME:  gtk bug?
658     // disable interruptibility: see http://inkscape.svn.sourceforge.net/viewvc/inkscape/inkscape/trunk/src/ui/widget/selected-style.cpp?r1=13149&r2=13257&sortby=date
659     SPDesktop* dt = SP_ACTIVE_DESKTOP;
660     sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(dt), 0);
662     Inkscape::SVGOStringStream os;
663     os << _widget->getValue() << ';' << _widget->getStartSeed();
665     write_to_xml(os.str().c_str());
667     // resume interruptibility
668     sp_canvas_end_forced_full_redraws(sp_desktop_canvas(dt));
670     _wr->setUpdating (false);
674 } // namespace Dialog
675 } // namespace UI
676 } // namespace Inkscape
678 /*
679   Local Variables:
680   mode:c++
681   c-file-style:"stroustrup"
682   c-file-offsets:((innamespace . 0)(inline-open . 0))
683   indent-tabs-mode:nil
684   fill-column:99
685   End:
686 */
687 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :