Code

46532d35848aa15bf60b058aefef51e511c8dac4
[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 // FIXME: for some reason, this function is also called when user clicks. then setProgrammatically should not be set!
114     setProgrammatically = true;
115     _button->set_active (b);
116     //The slave button is greyed out if the master button is unchecked
117     for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
118         (*i)->set_sensitive(b);
119     }
122 void
123 RegisteredCheckButton::on_toggled()
125     if (setProgrammatically) {
126         setProgrammatically = false;
127         return;
128     }
130     if (_wr->isUpdating())
131         return;
133     _wr->setUpdating (true);
135     write_to_xml(_button->get_active() ? "true" : "false");
136     //The slave button is greyed out if the master button is unchecked
137     for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
138         (*i)->set_sensitive(_button->get_active());
139     }
141     _wr->setUpdating (false);
144 RegisteredUnitMenu::RegisteredUnitMenu()
145 : _label(0), _sel(0)
149 RegisteredUnitMenu::~RegisteredUnitMenu()
151     _changed_connection.disconnect();
152     if (_label) delete _label;
153     if (_sel) delete _sel;
156 void
157 RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
159     init_parent(key, wr, repr_in, doc_in);
161     _label = new Gtk::Label (label, 1.0, 0.5);
162     _label->set_use_underline (true);
163     _sel = new UnitMenu ();
164     _label->set_mnemonic_widget (*_sel);
165     _sel->setUnitType (UNIT_TYPE_LINEAR);
166     _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
169 void
170 RegisteredUnitMenu::setUnit (const SPUnit* unit)
172     _sel->setUnit (sp_unit_get_abbreviation (unit));
175 void
176 RegisteredUnitMenu::on_changed()
178     if (_wr->isUpdating())
179         return;
181     Inkscape::SVGOStringStream os;
182     os << _sel->getUnitAbbr();
184     _wr->setUpdating (true);
186     write_to_xml(os.str().c_str());
188     _wr->setUpdating (false);
192 RegisteredScalarUnit::RegisteredScalarUnit()
193 : _widget(0), _um(0)
197 RegisteredScalarUnit::~RegisteredScalarUnit()
199     if (_widget) delete _widget;
200     _value_changed_connection.disconnect();
203 void
204 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)
206     init_parent(key, wr, repr_in, doc_in);
208     _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel);
209     _widget->initScalar (-1e6, 1e6);
210     _widget->setUnit (rum._sel->getUnitAbbr());
211     _widget->setDigits (2);
212     _um = rum._sel;
213     _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
216 ScalarUnit*
217 RegisteredScalarUnit::getSU()
219     return _widget;
222 void
223 RegisteredScalarUnit::setValue (double val)
225     _widget->setValue (val);
228 void
229 RegisteredScalarUnit::on_value_changed()
231     if (_widget->setProgrammatically) {
232         _widget->setProgrammatically = false;
233         return;
234     }
236     if (_wr->isUpdating())
237         return;
239     _wr->setUpdating (true);
241     Inkscape::SVGOStringStream os;
242     os << _widget->getValue("");
243     if (_um)
244         os << _um->getUnitAbbr();
246     write_to_xml(os.str().c_str());
248     _wr->setUpdating (false);
252 RegisteredScalar::RegisteredScalar()
254     _widget = NULL;
257 RegisteredScalar::~RegisteredScalar()
259     if (_widget) 
260         delete _widget;
262     _value_changed_connection.disconnect();
265 void
266 RegisteredScalar::init ( const Glib::ustring& label, const Glib::ustring& tip, 
267                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
268                          SPDocument * doc_in )
270     init_parent(key, wr, repr_in, doc_in);
272     _widget = new Scalar (label, tip);
273     _widget->setRange (-1e6, 1e6);
274     _widget->setDigits (2);
275     _widget->setIncrements(0.1, 1.0);
276     _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
279 Scalar*
280 RegisteredScalar::getS()
282     return _widget;
285 void
286 RegisteredScalar::setValue (double val)
288     _widget->setValue (val);
291 void
292 RegisteredScalar::on_value_changed()
294     if (_widget->setProgrammatically) {
295         _widget->setProgrammatically = false;
296         return;
297     }
299     if (_wr->isUpdating()) {
300         return;
301     }
302     _wr->setUpdating (true);
304     Inkscape::SVGOStringStream os;
305     os << _widget->getValue();
307     _widget->set_sensitive(false);
308     write_to_xml(os.str().c_str());
309     _widget->set_sensitive(true);
311     _wr->setUpdating (false);
315 RegisteredColorPicker::RegisteredColorPicker()
316 : _label(0), _cp(0)
320 RegisteredColorPicker::~RegisteredColorPicker()
322     _changed_connection.disconnect();
323     if (_cp) delete _cp;
324     if (_label) delete _label;
327 void
328 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)
330     init_parent("", wr, repr_in, doc_in);
332     _label = new Gtk::Label (label, 1.0, 0.5);
333     _label->set_use_underline (true);
334     _cp = new ColorPicker (title,tip,0,true);
335     _label->set_mnemonic_widget (*_cp);
336     _ckey = ckey;
337     _akey = akey;
338     _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
341 void
342 RegisteredColorPicker::setRgba32 (guint32 rgba)
344     _cp->setRgba32 (rgba);
347 void
348 RegisteredColorPicker::closeWindow()
350     _cp->closeWindow();
353 void
354 RegisteredColorPicker::on_changed (guint32 rgba)
356     if (_wr->isUpdating())
357         return;
359     _wr->setUpdating (true);
361     // Use local repr here. When repr is specified, use that one, but
362     // if repr==NULL, get the repr of namedview of active desktop.
363     Inkscape::XML::Node *local_repr = repr;
364     SPDocument *local_doc = doc;
365     if (!local_repr) {
366         // no repr specified, use active desktop's namedview's repr
367         SPDesktop *dt = SP_ACTIVE_DESKTOP;
368         if (!dt)
369             return;
370         local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
371         local_doc = sp_desktop_document(dt);
372     }
374     gchar c[32];
375     sp_svg_write_color(c, sizeof(c), rgba);
376     bool saved = sp_document_get_undo_sensitive (local_doc);
377     sp_document_set_undo_sensitive (local_doc, false);
378     local_repr->setAttribute(_ckey.c_str(), c);
379     sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
380     local_doc->rroot->setAttribute("sodipodi:modified", "true");
381     sp_document_set_undo_sensitive (local_doc, saved);
382     sp_document_done (local_doc, SP_VERB_NONE,
383                       /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
385     _wr->setUpdating (false);
388 RegisteredSuffixedInteger::RegisteredSuffixedInteger()
389 : _label(0),
390   setProgrammatically(false),
391   _sb(0),
392   _adj(0.0,0.0,100.0,1.0,1.0,1.0),
393   _suffix(0)
397 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
399     _changed_connection.disconnect();
400     if (_label) delete _label;
401     if (_suffix) delete _suffix;
402     if (_sb) delete _sb;
405 void
406 RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
408     init_parent(key, wr, repr_in, doc_in);
410     _label = new Gtk::Label (label);
411     _label->set_alignment (1.0, 0.5);
412     _label->set_use_underline();
413     _sb = new Gtk::SpinButton (_adj, 1.0, 0);
414     _label->set_mnemonic_widget (*_sb);
415     _suffix = new Gtk::Label (suffix);
416     _hbox.pack_start (*_sb, true, true, 0);
417     _hbox.pack_start (*_suffix, false, false, 0);
419     _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
422 void
423 RegisteredSuffixedInteger::setValue (int i)
425     setProgrammatically = true;
426     _adj.set_value (i);
429 void
430 RegisteredSuffixedInteger::on_value_changed()
432     if (setProgrammatically) {
433         setProgrammatically = false;
434         return;
435     }
437     if (_wr->isUpdating())
438         return;
440     _wr->setUpdating (true);
442     Inkscape::SVGOStringStream os;
443     int value = int(_adj.get_value());
444     os << value;
446     write_to_xml(os.str().c_str());
448     _wr->setUpdating (false);
451 RegisteredRadioButtonPair::RegisteredRadioButtonPair()
452 : _hbox(0),
453    setProgrammatically(false)
457 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
459     _changed_connection.disconnect();
462 void
463 RegisteredRadioButtonPair::init (const Glib::ustring& label,
464 const Glib::ustring& label1, const Glib::ustring& label2,
465 const Glib::ustring& tip1, const Glib::ustring& tip2,
466 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
468     init_parent(key, wr, repr_in, doc_in);
470     _hbox = new Gtk::HBox;
471     _hbox->add (*manage (new Gtk::Label (label)));
472     _rb1 = manage (new Gtk::RadioButton (label1, true));
473     _hbox->add (*_rb1);
474     Gtk::RadioButtonGroup group = _rb1->get_group();
475     _rb2 = manage (new Gtk::RadioButton (group, label2, true));
476     _hbox->add (*_rb2);
477     _rb2->set_active();
478     _tt.set_tip (*_rb1, tip1);
479     _tt.set_tip (*_rb2, tip2);
480     _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
483 void
484 RegisteredRadioButtonPair::setValue (bool second)
486     setProgrammatically = true;
487     if (second) _rb2->set_active();
488     else        _rb1->set_active();
491 void
492 RegisteredRadioButtonPair::on_value_changed()
494     if (setProgrammatically) {
495         setProgrammatically = false;
496         return;
497     }
499     if (_wr->isUpdating())
500         return;
502     _wr->setUpdating (true);
504     bool second = _rb2->get_active();
505     write_to_xml(second ? "true" : "false");
507     _wr->setUpdating (false);
510 /*#########################################
511  * Registered POINT
512  */
514 RegisteredPoint::RegisteredPoint()
516     _widget = NULL;
519 RegisteredPoint::~RegisteredPoint()
521     if (_widget) 
522         delete _widget;
524     _value_x_changed_connection.disconnect();
525     _value_y_changed_connection.disconnect();
528 void
529 RegisteredPoint::init ( const Glib::ustring& label, const Glib::ustring& tip, 
530                         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, 
531                         SPDocument* doc_in )
533     init_parent(key, wr, repr_in, doc_in);
535     _widget = new Point (label, tip);
536     _widget->setRange (-1e6, 1e6);
537     _widget->setDigits (2);
538     _widget->setIncrements(0.1, 1.0);
539     _value_x_changed_connection = _widget->signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
540     _value_y_changed_connection = _widget->signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
543 Point*
544 RegisteredPoint::getPoint()
546     return _widget;
549 void
550 RegisteredPoint::setValue (double xval, double yval)
552     _widget->setValue(xval, yval);
555 void
556 RegisteredPoint::on_value_changed()
558     if (_widget->setProgrammatically()) {
559         _widget->clearProgrammatically();
560         return;
561     }
563     if (_wr->isUpdating())
564         return;
566     _wr->setUpdating (true);
568     Inkscape::SVGOStringStream os;
569     os << _widget->getXValue() << "," << _widget->getYValue();
571     write_to_xml(os.str().c_str());
573     _wr->setUpdating (false);
576 /*#########################################
577  * Registered RANDOM
578  */
580 RegisteredRandom::RegisteredRandom()
582     _widget = NULL;
585 RegisteredRandom::~RegisteredRandom()
587     if (_widget) 
588         delete _widget;
590     _value_changed_connection.disconnect();
591     _reseeded_connection.disconnect();
594 void
595 RegisteredRandom::init ( const Glib::ustring& label, const Glib::ustring& tip, 
596                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
597                          SPDocument * doc_in )
599     init_parent(key, wr, repr_in, doc_in);
601     _widget = new Random (label, tip);
602     _widget->setRange (-1e6, 1e6);
603     _widget->setDigits (2);
604     _widget->setIncrements(0.1, 1.0);
605     _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
606     _reseeded_connection = _widget->signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
609 Random*
610 RegisteredRandom::getR()
612     return _widget;
615 void
616 RegisteredRandom::setValue (double val, long startseed)
618     _widget->setValue (val);
619     _widget->setStartSeed(startseed);
622 void
623 RegisteredRandom::on_value_changed()
625     if (_widget->setProgrammatically) {
626         _widget->setProgrammatically = false;
627         return;
628     }
630     if (_wr->isUpdating())
631         return;
632     _wr->setUpdating (true);
634     // FIXME:  gtk bug?
635     // disable interruptibility: see http://inkscape.svn.sourceforge.net/viewvc/inkscape/inkscape/trunk/src/ui/widget/selected-style.cpp?r1=13149&r2=13257&sortby=date
636     SPDesktop* dt = SP_ACTIVE_DESKTOP;
637     sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(dt), 0);
639     Inkscape::SVGOStringStream os;
640     os << _widget->getValue() << ';' << _widget->getStartSeed();
642     write_to_xml(os.str().c_str());
644     // resume interruptibility
645     sp_canvas_end_forced_full_redraws(sp_desktop_canvas(dt));
647     _wr->setUpdating (false);
651 } // namespace Dialog
652 } // namespace UI
653 } // namespace Inkscape
655 /*
656   Local Variables:
657   mode:c++
658   c-file-style:"stroustrup"
659   c-file-offsets:((innamespace . 0)(inline-open . 0))
660   indent-tabs-mode:nil
661   fill-column:99
662   End:
663 */
664 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :