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));
108 }
110 void
111 RegisteredCheckButton::setActive (bool b)
112 {
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;
123 }
125 void
126 RegisteredCheckButton::on_toggled()
127 {
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);
144 }
146 RegisteredUnitMenu::RegisteredUnitMenu()
147 : _label(0), _sel(0)
148 {
149 }
151 RegisteredUnitMenu::~RegisteredUnitMenu()
152 {
153 _changed_connection.disconnect();
154 if (_label) delete _label;
155 if (_sel) delete _sel;
156 }
158 void
159 RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
160 {
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));
169 }
171 void
172 RegisteredUnitMenu::setUnit (const SPUnit* unit)
173 {
174 _sel->setUnit (sp_unit_get_abbreviation (unit));
175 }
177 void
178 RegisteredUnitMenu::on_changed()
179 {
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);
191 }
194 RegisteredScalarUnit::RegisteredScalarUnit()
195 : _widget(0), _um(0)
196 {
197 }
199 RegisteredScalarUnit::~RegisteredScalarUnit()
200 {
201 if (_widget) delete _widget;
202 _value_changed_connection.disconnect();
203 }
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)
207 {
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));
216 }
218 ScalarUnit*
219 RegisteredScalarUnit::getSU()
220 {
221 return _widget;
222 }
224 void
225 RegisteredScalarUnit::setValue (double val)
226 {
227 if (_wr->isUpdating())
228 return;
230 _widget->setValue (val);
231 }
233 void
234 RegisteredScalarUnit::on_value_changed()
235 {
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);
254 }
257 RegisteredScalar::RegisteredScalar()
258 {
259 _widget = NULL;
260 }
262 RegisteredScalar::~RegisteredScalar()
263 {
264 if (_widget)
265 delete _widget;
267 _value_changed_connection.disconnect();
268 }
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 )
274 {
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));
282 }
284 Scalar*
285 RegisteredScalar::getS()
286 {
287 return _widget;
288 }
290 void
291 RegisteredScalar::setValue (double val)
292 {
293 if (_wr->isUpdating())
294 return;
296 _widget->setValue (val);
297 }
299 void
300 RegisteredScalar::on_value_changed()
301 {
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);
320 }
323 RegisteredColorPicker::RegisteredColorPicker()
324 : _label(0), _cp(0)
325 {
326 }
328 RegisteredColorPicker::~RegisteredColorPicker()
329 {
330 _changed_connection.disconnect();
331 if (_cp) delete _cp;
332 if (_label) delete _label;
333 }
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)
337 {
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));
347 }
349 void
350 RegisteredColorPicker::setRgba32 (guint32 rgba)
351 {
352 if (_wr->isUpdating())
353 return;
355 _cp->setRgba32 (rgba);
356 }
358 void
359 RegisteredColorPicker::closeWindow()
360 {
361 _cp->closeWindow();
362 }
364 void
365 RegisteredColorPicker::on_changed (guint32 rgba)
366 {
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);
397 }
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)
405 {
406 }
408 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
409 {
410 _changed_connection.disconnect();
411 if (_label) delete _label;
412 if (_suffix) delete _suffix;
413 if (_sb) delete _sb;
414 }
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)
418 {
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));
431 }
433 void
434 RegisteredSuffixedInteger::setValue (int i)
435 {
436 if (_wr->isUpdating())
437 return;
439 setProgrammatically = true;
440 _adj.set_value (i);
441 }
443 void
444 RegisteredSuffixedInteger::on_value_changed()
445 {
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);
463 }
465 RegisteredRadioButtonPair::RegisteredRadioButtonPair()
466 : _hbox(0),
467 setProgrammatically(false)
468 {
469 }
471 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
472 {
473 _changed_connection.disconnect();
474 }
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)
481 {
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));
495 }
497 void
498 RegisteredRadioButtonPair::setValue (bool second)
499 {
500 if (_wr->isUpdating())
501 return;
503 setProgrammatically = true;
504 if (second) _rb2->set_active();
505 else _rb1->set_active();
506 }
508 void
509 RegisteredRadioButtonPair::on_value_changed()
510 {
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);
525 }
527 /*#########################################
528 * Registered POINT
529 */
531 RegisteredPoint::RegisteredPoint()
532 {
533 _widget = NULL;
534 }
536 RegisteredPoint::~RegisteredPoint()
537 {
538 if (_widget)
539 delete _widget;
541 _value_x_changed_connection.disconnect();
542 _value_y_changed_connection.disconnect();
543 }
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 )
549 {
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));
558 }
560 Point*
561 RegisteredPoint::getPoint()
562 {
563 return _widget;
564 }
566 void
567 RegisteredPoint::setValue (double xval, double yval)
568 {
569 if (_wr->isUpdating())
570 return;
572 _widget->setValue(xval, yval);
573 }
575 void
576 RegisteredPoint::on_value_changed()
577 {
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);
594 }
596 /*#########################################
597 * Registered RANDOM
598 */
600 RegisteredRandom::RegisteredRandom()
601 {
602 _widget = NULL;
603 }
605 RegisteredRandom::~RegisteredRandom()
606 {
607 if (_widget)
608 delete _widget;
610 _value_changed_connection.disconnect();
611 _reseeded_connection.disconnect();
612 }
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 )
618 {
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));
627 }
629 Random*
630 RegisteredRandom::getR()
631 {
632 return _widget;
633 }
635 void
636 RegisteredRandom::setValue (double val, long startseed)
637 {
638 if (_wr->isUpdating())
639 return;
641 _widget->setValue (val);
642 _widget->setStartSeed(startseed);
643 }
645 void
646 RegisteredRandom::on_value_changed()
647 {
648 if (_widget->setProgrammatically) {
649 _widget->setProgrammatically = false;
650 return;
651 }
653 if (_wr->isUpdating()) {
654 return;
655 }
656 _wr->setUpdating (true);
658 Inkscape::SVGOStringStream os;
659 os << _widget->getValue() << ';' << _widget->getStartSeed();
661 _widget->set_sensitive(false);
662 write_to_xml(os.str().c_str());
663 _widget->set_sensitive(true);
665 _wr->setUpdating (false);
666 }
669 } // namespace Dialog
670 } // namespace UI
671 } // namespace Inkscape
673 /*
674 Local Variables:
675 mode:c++
676 c-file-style:"stroustrup"
677 c-file-offsets:((innamespace . 0)(inline-open . 0))
678 indent-tabs-mode:nil
679 fill-column:99
680 End:
681 */
682 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :