Code

Merge and cleanup of GSoC C++-ification project.
[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  *   Abhishek Sharma
12  *
13  * Copyright (C) 2000 - 2007 Authors
14  *
15  * Released under GNU GPL.  Read the file 'COPYING' for more information
16  */
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
22 #include "registered-widget.h"
24 #include "ui/widget/color-picker.h"
25 #include "ui/widget/registry.h"
26 #include "ui/widget/scalar-unit.h"
27 #include "ui/widget/point.h"
28 #include "ui/widget/random.h"
29 #include "widgets/spinbutton-events.h"
31 #include "helper/units.h"
32 #include "xml/repr.h"
33 #include "svg/svg-color.h"
34 #include "svg/stringstream.h"
36 #include "verbs.h"
38 // for interruptability bug:
39 #include "display/sp-canvas.h"
41 namespace Inkscape {
42 namespace UI {
43 namespace Widget {
45 /*#########################################
46  * Registered CHECKBUTTON
47  */
49 RegisteredCheckButton::~RegisteredCheckButton()
50 {
51     _toggled_connection.disconnect();
52 }
54 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)
55     : RegisteredWidget<Gtk::CheckButton>()
56 {
57     init_parent(key, wr, repr_in, doc_in);
59     setProgrammatically = false;
61     _tt.set_tip (*this, tip);
62     Gtk::Label *l = new Gtk::Label (label);
63     l->set_use_underline (true);
64     add (*manage (l));
65     set_alignment (right? 1.0 : 0.0, 0.5);
66     _toggled_connection = signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
67 }
69 void
70 RegisteredCheckButton::setActive (bool b)
71 {
72     setProgrammatically = true;
73     set_active (b);
74     //The slave button is greyed out if the master button is unchecked
75     for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); i++) {
76         (*i)->set_sensitive(b);
77     }
78     setProgrammatically = false;
79 }
81 void
82 RegisteredCheckButton::on_toggled()
83 {
84     if (setProgrammatically) {
85         setProgrammatically = false;
86         return;
87     }
89     if (_wr->isUpdating())
90         return;
91     _wr->setUpdating (true);
93     write_to_xml(get_active() ? "true" : "false");
94     //The slave button is greyed out if the master button is unchecked
95     for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); i++) {
96         (*i)->set_sensitive(get_active());
97     }
99     _wr->setUpdating (false);
103 /*#########################################
104  * Registered UNITMENU
105  */
107 RegisteredUnitMenu::~RegisteredUnitMenu()
109     _changed_connection.disconnect();
112 RegisteredUnitMenu::RegisteredUnitMenu (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
113     :  RegisteredWidget<Labelled> (label, "" /*tooltip*/, new UnitMenu())
115     init_parent(key, wr, repr_in, doc_in);
117     getUnitMenu()->setUnitType (UNIT_TYPE_LINEAR);
118     _changed_connection = getUnitMenu()->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
121 void
122 RegisteredUnitMenu::setUnit (const SPUnit* unit)
124     getUnitMenu()->setUnit (sp_unit_get_abbreviation (unit));
127 void
128 RegisteredUnitMenu::on_changed()
130     if (_wr->isUpdating())
131         return;
133     Inkscape::SVGOStringStream os;
134     os << getUnitMenu()->getUnitAbbr();
136     _wr->setUpdating (true);
138     write_to_xml(os.str().c_str());
140     _wr->setUpdating (false);
144 /*#########################################
145  * Registered SCALARUNIT
146  */
148 RegisteredScalarUnit::~RegisteredScalarUnit()
150     _value_changed_connection.disconnect();
153 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)
154     : RegisteredWidget<ScalarUnit>(label, tip, UNIT_TYPE_LINEAR, "", "", rum.getUnitMenu()),
155       _um(0)
157     init_parent(key, wr, repr_in, doc_in);
159     setProgrammatically = false;
161     initScalar (-1e6, 1e6);
162     setUnit (rum.getUnitMenu()->getUnitAbbr());
163     setDigits (2);
164     _um = rum.getUnitMenu();
165     _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
169 void
170 RegisteredScalarUnit::on_value_changed()
172     if (setProgrammatically) {
173         setProgrammatically = false;
174         return;
175     }
177     if (_wr->isUpdating())
178         return;
180     _wr->setUpdating (true);
182     Inkscape::SVGOStringStream os;
183     os << getValue("");
184     if (_um)
185         os << _um->getUnitAbbr();
187     write_to_xml(os.str().c_str());
189     _wr->setUpdating (false);
193 /*#########################################
194  * Registered SCALAR
195  */
197 RegisteredScalar::~RegisteredScalar()
199     _value_changed_connection.disconnect();
202 RegisteredScalar::RegisteredScalar ( const Glib::ustring& label, const Glib::ustring& tip,
203                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
204                          SPDocument * doc_in )
205     : RegisteredWidget<Scalar>(label, tip)
207     init_parent(key, wr, repr_in, doc_in);
209     setProgrammatically = false;
211     setRange (-1e6, 1e6);
212     setDigits (2);
213     setIncrements(0.1, 1.0);
214     _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
217 void
218 RegisteredScalar::on_value_changed()
220     if (setProgrammatically) {
221         setProgrammatically = false;
222         return;
223     }
225     if (_wr->isUpdating()) {
226         return;
227     }
228     _wr->setUpdating (true);
230     Inkscape::SVGOStringStream os;
231     os << getValue();
233     set_sensitive(false);
234     write_to_xml(os.str().c_str());
235     set_sensitive(true);
237     _wr->setUpdating (false);
241 /*#########################################
242  * Registered TEXT
243  */
245 RegisteredText::~RegisteredText()
247     _activate_connection.disconnect();
250 RegisteredText::RegisteredText ( const Glib::ustring& label, const Glib::ustring& tip,
251                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
252                          SPDocument * doc_in )
253     : RegisteredWidget<Text>(label, tip)
255     init_parent(key, wr, repr_in, doc_in);
257     setProgrammatically = false;
259     setText("");
260     _activate_connection = signal_activate().connect (sigc::mem_fun (*this, &RegisteredText::on_activate));
263 void
264 RegisteredText::on_activate()
266     if (setProgrammatically) {
267         setProgrammatically = false;
268         return;
269     }
271     if (_wr->isUpdating()) {
272         return;
273     }
274     _wr->setUpdating (true);
276     Inkscape::SVGOStringStream os;
277     os << getText();
279     set_sensitive(false);
280     write_to_xml(os.str().c_str());
281     set_sensitive(true);
283     setText(os.str().c_str());
285     _wr->setUpdating (false);
289 /*#########################################
290  * Registered COLORPICKER
291  */
293 RegisteredColorPicker::RegisteredColorPicker(const Glib::ustring& label,
294                                              const Glib::ustring& title,
295                                              const Glib::ustring& tip,
296                                              const Glib::ustring& ckey,
297                                              const Glib::ustring& akey,
298                                              Registry& wr,
299                                              Inkscape::XML::Node* repr_in,
300                                              SPDocument *doc_in)
301     : RegisteredWidget<ColorPicker> (title, tip, 0, true)
303     init_parent("", wr, repr_in, doc_in);
305     _label = new Gtk::Label (label, 1.0, 0.5);
306     _label->set_use_underline (true);
307     _label->set_mnemonic_widget (*this);
308     _ckey = ckey;
309     _akey = akey;
310     _changed_connection = connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
313 RegisteredColorPicker::~RegisteredColorPicker()
315     _changed_connection.disconnect();
318 void
319 RegisteredColorPicker::setRgba32 (guint32 rgba)
321     ColorPicker::setRgba32 (rgba);
324 void
325 RegisteredColorPicker::closeWindow()
327     ColorPicker::closeWindow();
330 void
331 RegisteredColorPicker::on_changed (guint32 rgba)
333     if (_wr->isUpdating())
334         return;
336     _wr->setUpdating (true);
338     // Use local repr here. When repr is specified, use that one, but
339     // if repr==NULL, get the repr of namedview of active desktop.
340     Inkscape::XML::Node *local_repr = repr;
341     SPDocument *local_doc = doc;
342     if (!local_repr) {
343         // no repr specified, use active desktop's namedview's repr
344         SPDesktop *dt = SP_ACTIVE_DESKTOP;
345         if (!dt)
346             return;
347         local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
348         local_doc = sp_desktop_document(dt);
349     }
351     gchar c[32];
352     sp_svg_write_color(c, sizeof(c), rgba);
353     bool saved = DocumentUndo::getUndoSensitive(local_doc);
354     DocumentUndo::setUndoSensitive(local_doc, false);
355     local_repr->setAttribute(_ckey.c_str(), c);
356     sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
357     DocumentUndo::setUndoSensitive(local_doc, saved);
359     local_doc->setModifiedSinceSave();
360     DocumentUndo::done(local_doc, SP_VERB_NONE,
361                        /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
363     _wr->setUpdating (false);
367 /*#########################################
368  * Registered SUFFIXEDINTEGER
369  */
371 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
373     _changed_connection.disconnect();
376 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)
377     : RegisteredWidget<Scalar>(label, tip, 0, suffix),
378       setProgrammatically(false)
380     init_parent(key, wr, repr_in, doc_in);
382     setRange (0, 1e6);
383     setDigits (0);
384     setIncrements(1, 10);
386     _changed_connection = signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
389 void
390 RegisteredSuffixedInteger::on_value_changed()
392     if (setProgrammatically) {
393         setProgrammatically = false;
394         return;
395     }
397     if (_wr->isUpdating())
398         return;
400     _wr->setUpdating (true);
402     Inkscape::SVGOStringStream os;
403     os << getValue();
405     write_to_xml(os.str().c_str());
407     _wr->setUpdating (false);
411 /*#########################################
412  * Registered RADIOBUTTONPAIR
413  */
415 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
417     _changed_connection.disconnect();
420 RegisteredRadioButtonPair::RegisteredRadioButtonPair (const Glib::ustring& label,
421         const Glib::ustring& label1, const Glib::ustring& label2,
422         const Glib::ustring& tip1, const Glib::ustring& tip2,
423         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
424     : RegisteredWidget<Gtk::HBox>(),
425       _rb1(NULL),
426       _rb2(NULL)
428     init_parent(key, wr, repr_in, doc_in);
430     setProgrammatically = false;
432     add (*manage (new Gtk::Label (label)));
433     _rb1 = manage (new Gtk::RadioButton (label1, true));
434     add (*_rb1);
435     Gtk::RadioButtonGroup group = _rb1->get_group();
436     _rb2 = manage (new Gtk::RadioButton (group, label2, true));
437     add (*_rb2);
438     _rb2->set_active();
439     _tt.set_tip (*_rb1, tip1);
440     _tt.set_tip (*_rb2, tip2);
441     _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
444 void
445 RegisteredRadioButtonPair::setValue (bool second)
447     if (!_rb1 || !_rb2)
448         return;
450     setProgrammatically = true;
451     if (second) {
452         _rb2->set_active();
453     } else {
454         _rb1->set_active();
455     }
458 void
459 RegisteredRadioButtonPair::on_value_changed()
461     if (setProgrammatically) {
462         setProgrammatically = false;
463         return;
464     }
466     if (_wr->isUpdating())
467         return;
469     _wr->setUpdating (true);
471     bool second = _rb2->get_active();
472     write_to_xml(second ? "true" : "false");
474     _wr->setUpdating (false);
478 /*#########################################
479  * Registered POINT
480  */
482 RegisteredPoint::~RegisteredPoint()
484     _value_x_changed_connection.disconnect();
485     _value_y_changed_connection.disconnect();
488 RegisteredPoint::RegisteredPoint ( const Glib::ustring& label, const Glib::ustring& tip,
489                         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
490                         SPDocument* doc_in )
491     : RegisteredWidget<Point> (label, tip)
493     init_parent(key, wr, repr_in, doc_in);
495     setRange (-1e6, 1e6);
496     setDigits (2);
497     setIncrements(0.1, 1.0);
498     _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
499     _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
502 void
503 RegisteredPoint::on_value_changed()
505     if (setProgrammatically()) {
506         clearProgrammatically();
507         return;
508     }
510     if (_wr->isUpdating())
511         return;
513     _wr->setUpdating (true);
515     Inkscape::SVGOStringStream os;
516     os << getXValue() << "," << getYValue();
518     write_to_xml(os.str().c_str());
520     _wr->setUpdating (false);
523 /*#########################################
524  * Registered TRANSFORMEDPOINT
525  */
527 RegisteredTransformedPoint::~RegisteredTransformedPoint()
529     _value_x_changed_connection.disconnect();
530     _value_y_changed_connection.disconnect();
533 RegisteredTransformedPoint::RegisteredTransformedPoint ( const Glib::ustring& label, const Glib::ustring& tip,
534                         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
535                         SPDocument* doc_in )
536     : RegisteredWidget<Point> (label, tip),
537       to_svg(Geom::identity())
539     init_parent(key, wr, repr_in, doc_in);
541     setRange (-1e6, 1e6);
542     setDigits (2);
543     setIncrements(0.1, 1.0);
544     _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredTransformedPoint::on_value_changed));
545     _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredTransformedPoint::on_value_changed));
548 void
549 RegisteredTransformedPoint::setValue(Geom::Point const & p)
551     Geom::Point new_p = p * to_svg.inverse();
552     Point::setValue(new_p);  // the Point widget should display things in canvas coordinates
555 void
556 RegisteredTransformedPoint::setTransform(Geom::Matrix const & canvas_to_svg)
558     // check if matrix is singular / has inverse
559     if ( ! canvas_to_svg.isSingular() ) {
560         to_svg = canvas_to_svg;
561     } else {
562         // set back to default
563         to_svg = Geom::identity();
564     }
567 void
568 RegisteredTransformedPoint::on_value_changed()
570     if (setProgrammatically()) {
571         clearProgrammatically();
572         return;
573     }
575     if (_wr->isUpdating())
576         return;
578     _wr->setUpdating (true);
580     Geom::Point pos = getValue() * to_svg;
582     Inkscape::SVGOStringStream os;
583     os << pos;
585     write_to_xml(os.str().c_str());
587     _wr->setUpdating (false);
590 /*#########################################
591  * Registered TRANSFORMEDPOINT
592  */
594 RegisteredVector::~RegisteredVector()
596     _value_x_changed_connection.disconnect();
597     _value_y_changed_connection.disconnect();
600 RegisteredVector::RegisteredVector ( const Glib::ustring& label, const Glib::ustring& tip,
601                         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
602                         SPDocument* doc_in )
603     : RegisteredWidget<Point> (label, tip),
604       _polar_coords(false)
606     init_parent(key, wr, repr_in, doc_in);
608     setRange (-1e6, 1e6);
609     setDigits (2);
610     setIncrements(0.1, 1.0);
611     _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredVector::on_value_changed));
612     _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredVector::on_value_changed));
615 void
616 RegisteredVector::setValue(Geom::Point const & p)
618     if (!_polar_coords) {
619         Point::setValue(p);
620     } else {
621         Geom::Point polar;
622         polar[Geom::X] = atan2(p) *180/M_PI;
623         polar[Geom::Y] = p.length();
624         Point::setValue(polar);
625     }
628 void
629 RegisteredVector::setValue(Geom::Point const & p, Geom::Point const & origin)
631     RegisteredVector::setValue(p);
632     _origin = origin;
635 /**
636  * Changes the widgets text to polar coordinates. The SVG output will still be a normal carthesian vector.
637  * Careful: when calling getValue(), the return value's X-coord will be the angle, Y-value will be the distance/length. 
638  * After changing the coords type (polar/non-polar), the value has to be reset (setValue).
639  */
640 void
641 RegisteredVector::setPolarCoords(bool polar_coords)
643     _polar_coords = polar_coords;
644     if (polar_coords) {
645         xwidget.setLabelText("Angle:");
646         ywidget.setLabelText("Distance:");
647     } else {
648         xwidget.setLabelText("X:");
649         ywidget.setLabelText("Y:");
650     }
653 void
654 RegisteredVector::on_value_changed()
656     if (setProgrammatically()) {
657         clearProgrammatically();
658         return;
659     }
661     if (_wr->isUpdating())
662         return;
664     _wr->setUpdating (true);
666     Geom::Point origin = _origin;
667     Geom::Point vector = getValue();
668     if (_polar_coords) {
669         vector = Geom::Point::polar(vector[Geom::X]*M_PI/180, vector[Geom::Y]);
670     }
672     Inkscape::SVGOStringStream os;
673     os << origin << " , " << vector;
675     write_to_xml(os.str().c_str());
677     _wr->setUpdating (false);
680 /*#########################################
681  * Registered RANDOM
682  */
684 RegisteredRandom::~RegisteredRandom()
686     _value_changed_connection.disconnect();
687     _reseeded_connection.disconnect();
690 RegisteredRandom::RegisteredRandom ( const Glib::ustring& label, const Glib::ustring& tip,
691                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
692                          SPDocument * doc_in )
693     : RegisteredWidget<Random> (label, tip)
695     init_parent(key, wr, repr_in, doc_in);
697     setProgrammatically = false;
699     setRange (-1e6, 1e6);
700     setDigits (2);
701     setIncrements(0.1, 1.0);
702     _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
703     _reseeded_connection = signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
706 void
707 RegisteredRandom::setValue (double val, long startseed)
709     Scalar::setValue (val);
710     setStartSeed(startseed);
713 void
714 RegisteredRandom::on_value_changed()
716     if (setProgrammatically) {
717         setProgrammatically = false;
718         return;
719     }
721     if (_wr->isUpdating()) {
722         return;
723     }
724     _wr->setUpdating (true);
726     Inkscape::SVGOStringStream os;
727     os << getValue() << ';' << getStartSeed();
729     set_sensitive(false);
730     write_to_xml(os.str().c_str());
731     set_sensitive(true);
733     _wr->setUpdating (false);
736 } // namespace Dialog
737 } // namespace UI
738 } // namespace Inkscape
740 /*
741   Local Variables:
742   mode:c++
743   c-file-style:"stroustrup"
744   c-file-offsets:((innamespace . 0)(inline-open . 0))
745   indent-tabs-mode:nil
746   fill-column:99
747   End:
748 */
749 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :