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
21 #include "registered-widget.h"
23 #include "ui/widget/color-picker.h"
24 #include "ui/widget/registry.h"
25 #include "ui/widget/scalar-unit.h"
26 #include "ui/widget/point.h"
27 #include "ui/widget/random.h"
28 #include "widgets/spinbutton-events.h"
30 #include "helper/units.h"
31 #include "xml/repr.h"
32 #include "svg/svg-color.h"
33 #include "svg/stringstream.h"
35 #include "verbs.h"
37 // for interruptability bug:
38 #include "display/sp-canvas.h"
40 namespace Inkscape {
41 namespace UI {
42 namespace Widget {
44 /*#########################################
45 * Registered CHECKBUTTON
46 */
48 RegisteredCheckButton::~RegisteredCheckButton()
49 {
50 _toggled_connection.disconnect();
51 }
53 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)
54 : RegisteredWidget<Gtk::CheckButton>()
55 {
56 init_parent(key, wr, repr_in, doc_in);
58 setProgrammatically = false;
60 _tt.set_tip (*this, tip);
61 Gtk::Label *l = new Gtk::Label (label);
62 l->set_use_underline (true);
63 add (*manage (l));
64 set_alignment (right? 1.0 : 0.0, 0.5);
65 _toggled_connection = signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
66 }
68 void
69 RegisteredCheckButton::setActive (bool b)
70 {
71 setProgrammatically = true;
72 set_active (b);
73 //The slave button is greyed out if the master button is unchecked
74 for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); i++) {
75 (*i)->set_sensitive(b);
76 }
77 setProgrammatically = false;
78 }
80 void
81 RegisteredCheckButton::on_toggled()
82 {
83 if (setProgrammatically) {
84 setProgrammatically = false;
85 return;
86 }
88 if (_wr->isUpdating())
89 return;
90 _wr->setUpdating (true);
92 write_to_xml(get_active() ? "true" : "false");
93 //The slave button is greyed out if the master button is unchecked
94 for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); i++) {
95 (*i)->set_sensitive(get_active());
96 }
98 _wr->setUpdating (false);
99 }
102 /*#########################################
103 * Registered UNITMENU
104 */
106 RegisteredUnitMenu::~RegisteredUnitMenu()
107 {
108 _changed_connection.disconnect();
109 }
111 RegisteredUnitMenu::RegisteredUnitMenu (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
112 : RegisteredWidget<Labelled> (label, "" /*tooltip*/, new UnitMenu())
113 {
114 init_parent(key, wr, repr_in, doc_in);
116 getUnitMenu()->setUnitType (UNIT_TYPE_LINEAR);
117 _changed_connection = getUnitMenu()->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
118 }
120 void
121 RegisteredUnitMenu::setUnit (const SPUnit* unit)
122 {
123 getUnitMenu()->setUnit (sp_unit_get_abbreviation (unit));
124 }
126 void
127 RegisteredUnitMenu::on_changed()
128 {
129 if (_wr->isUpdating())
130 return;
132 Inkscape::SVGOStringStream os;
133 os << getUnitMenu()->getUnitAbbr();
135 _wr->setUpdating (true);
137 write_to_xml(os.str().c_str());
139 _wr->setUpdating (false);
140 }
143 /*#########################################
144 * Registered SCALARUNIT
145 */
147 RegisteredScalarUnit::~RegisteredScalarUnit()
148 {
149 _value_changed_connection.disconnect();
150 }
152 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)
153 : RegisteredWidget<ScalarUnit>(label, tip, UNIT_TYPE_LINEAR, "", "", rum.getUnitMenu()),
154 _um(0)
155 {
156 init_parent(key, wr, repr_in, doc_in);
158 setProgrammatically = false;
160 initScalar (-1e6, 1e6);
161 setUnit (rum.getUnitMenu()->getUnitAbbr());
162 setDigits (2);
163 _um = rum.getUnitMenu();
164 _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
165 }
168 void
169 RegisteredScalarUnit::on_value_changed()
170 {
171 if (setProgrammatically) {
172 setProgrammatically = false;
173 return;
174 }
176 if (_wr->isUpdating())
177 return;
179 _wr->setUpdating (true);
181 Inkscape::SVGOStringStream os;
182 os << getValue("");
183 if (_um)
184 os << _um->getUnitAbbr();
186 write_to_xml(os.str().c_str());
188 _wr->setUpdating (false);
189 }
192 /*#########################################
193 * Registered SCALAR
194 */
196 RegisteredScalar::~RegisteredScalar()
197 {
198 _value_changed_connection.disconnect();
199 }
201 RegisteredScalar::RegisteredScalar ( const Glib::ustring& label, const Glib::ustring& tip,
202 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
203 SPDocument * doc_in )
204 : RegisteredWidget<Scalar>(label, tip)
205 {
206 init_parent(key, wr, repr_in, doc_in);
208 setProgrammatically = false;
210 setRange (-1e6, 1e6);
211 setDigits (2);
212 setIncrements(0.1, 1.0);
213 _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
214 }
216 void
217 RegisteredScalar::on_value_changed()
218 {
219 if (setProgrammatically) {
220 setProgrammatically = false;
221 return;
222 }
224 if (_wr->isUpdating()) {
225 return;
226 }
227 _wr->setUpdating (true);
229 Inkscape::SVGOStringStream os;
230 os << getValue();
232 set_sensitive(false);
233 write_to_xml(os.str().c_str());
234 set_sensitive(true);
236 _wr->setUpdating (false);
237 }
240 /*#########################################
241 * Registered TEXT
242 */
244 RegisteredText::~RegisteredText()
245 {
246 _activate_connection.disconnect();
247 }
249 RegisteredText::RegisteredText ( const Glib::ustring& label, const Glib::ustring& tip,
250 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
251 SPDocument * doc_in )
252 : RegisteredWidget<Text>(label, tip)
253 {
254 init_parent(key, wr, repr_in, doc_in);
256 setProgrammatically = false;
258 setText("");
259 _activate_connection = signal_activate().connect (sigc::mem_fun (*this, &RegisteredText::on_activate));
260 }
262 void
263 RegisteredText::on_activate()
264 {
265 if (setProgrammatically) {
266 setProgrammatically = false;
267 return;
268 }
270 if (_wr->isUpdating()) {
271 return;
272 }
273 _wr->setUpdating (true);
275 Inkscape::SVGOStringStream os;
276 os << getText();
278 set_sensitive(false);
279 write_to_xml(os.str().c_str());
280 set_sensitive(true);
282 setText(os.str().c_str());
284 _wr->setUpdating (false);
285 }
288 /*#########################################
289 * Registered COLORPICKER
290 */
292 RegisteredColorPicker::RegisteredColorPicker(const Glib::ustring& label,
293 const Glib::ustring& title,
294 const Glib::ustring& tip,
295 const Glib::ustring& ckey,
296 const Glib::ustring& akey,
297 Registry& wr,
298 Inkscape::XML::Node* repr_in,
299 SPDocument *doc_in)
300 : RegisteredWidget<ColorPicker> (title, tip, 0, true)
301 {
302 init_parent("", wr, repr_in, doc_in);
304 _label = new Gtk::Label (label, 1.0, 0.5);
305 _label->set_use_underline (true);
306 _label->set_mnemonic_widget (*this);
307 _ckey = ckey;
308 _akey = akey;
309 _changed_connection = connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
310 }
312 RegisteredColorPicker::~RegisteredColorPicker()
313 {
314 _changed_connection.disconnect();
315 }
317 void
318 RegisteredColorPicker::setRgba32 (guint32 rgba)
319 {
320 ColorPicker::setRgba32 (rgba);
321 }
323 void
324 RegisteredColorPicker::closeWindow()
325 {
326 ColorPicker::closeWindow();
327 }
329 void
330 RegisteredColorPicker::on_changed (guint32 rgba)
331 {
332 if (_wr->isUpdating())
333 return;
335 _wr->setUpdating (true);
337 // Use local repr here. When repr is specified, use that one, but
338 // if repr==NULL, get the repr of namedview of active desktop.
339 Inkscape::XML::Node *local_repr = repr;
340 SPDocument *local_doc = doc;
341 if (!local_repr) {
342 // no repr specified, use active desktop's namedview's repr
343 SPDesktop *dt = SP_ACTIVE_DESKTOP;
344 if (!dt)
345 return;
346 local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
347 local_doc = sp_desktop_document(dt);
348 }
350 gchar c[32];
351 sp_svg_write_color(c, sizeof(c), rgba);
352 bool saved = sp_document_get_undo_sensitive (local_doc);
353 sp_document_set_undo_sensitive (local_doc, false);
354 local_repr->setAttribute(_ckey.c_str(), c);
355 sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
356 sp_document_set_undo_sensitive (local_doc, saved);
358 local_doc->setModifiedSinceSave();
359 sp_document_done (local_doc, SP_VERB_NONE,
360 /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
362 _wr->setUpdating (false);
363 }
366 /*#########################################
367 * Registered SUFFIXEDINTEGER
368 */
370 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
371 {
372 _changed_connection.disconnect();
373 }
375 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)
376 : RegisteredWidget<Scalar>(label, tip, 0, suffix),
377 setProgrammatically(false)
378 {
379 init_parent(key, wr, repr_in, doc_in);
381 setRange (0, 1e6);
382 setDigits (0);
383 setIncrements(1, 10);
385 _changed_connection = signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
386 }
388 void
389 RegisteredSuffixedInteger::on_value_changed()
390 {
391 if (setProgrammatically) {
392 setProgrammatically = false;
393 return;
394 }
396 if (_wr->isUpdating())
397 return;
399 _wr->setUpdating (true);
401 Inkscape::SVGOStringStream os;
402 os << getValue();
404 write_to_xml(os.str().c_str());
406 _wr->setUpdating (false);
407 }
410 /*#########################################
411 * Registered RADIOBUTTONPAIR
412 */
414 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
415 {
416 _changed_connection.disconnect();
417 }
419 RegisteredRadioButtonPair::RegisteredRadioButtonPair (const Glib::ustring& label,
420 const Glib::ustring& label1, const Glib::ustring& label2,
421 const Glib::ustring& tip1, const Glib::ustring& tip2,
422 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
423 : RegisteredWidget<Gtk::HBox>(),
424 _rb1(NULL),
425 _rb2(NULL)
426 {
427 init_parent(key, wr, repr_in, doc_in);
429 setProgrammatically = false;
431 add (*manage (new Gtk::Label (label)));
432 _rb1 = manage (new Gtk::RadioButton (label1, true));
433 add (*_rb1);
434 Gtk::RadioButtonGroup group = _rb1->get_group();
435 _rb2 = manage (new Gtk::RadioButton (group, label2, true));
436 add (*_rb2);
437 _rb2->set_active();
438 _tt.set_tip (*_rb1, tip1);
439 _tt.set_tip (*_rb2, tip2);
440 _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
441 }
443 void
444 RegisteredRadioButtonPair::setValue (bool second)
445 {
446 if (!_rb1 || !_rb2)
447 return;
449 setProgrammatically = true;
450 if (second) {
451 _rb2->set_active();
452 } else {
453 _rb1->set_active();
454 }
455 }
457 void
458 RegisteredRadioButtonPair::on_value_changed()
459 {
460 if (setProgrammatically) {
461 setProgrammatically = false;
462 return;
463 }
465 if (_wr->isUpdating())
466 return;
468 _wr->setUpdating (true);
470 bool second = _rb2->get_active();
471 write_to_xml(second ? "true" : "false");
473 _wr->setUpdating (false);
474 }
477 /*#########################################
478 * Registered POINT
479 */
481 RegisteredPoint::~RegisteredPoint()
482 {
483 _value_x_changed_connection.disconnect();
484 _value_y_changed_connection.disconnect();
485 }
487 RegisteredPoint::RegisteredPoint ( const Glib::ustring& label, const Glib::ustring& tip,
488 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
489 SPDocument* doc_in )
490 : RegisteredWidget<Point> (label, tip)
491 {
492 init_parent(key, wr, repr_in, doc_in);
494 setRange (-1e6, 1e6);
495 setDigits (2);
496 setIncrements(0.1, 1.0);
497 _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
498 _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
499 }
501 void
502 RegisteredPoint::on_value_changed()
503 {
504 if (setProgrammatically()) {
505 clearProgrammatically();
506 return;
507 }
509 if (_wr->isUpdating())
510 return;
512 _wr->setUpdating (true);
514 Inkscape::SVGOStringStream os;
515 os << getXValue() << "," << getYValue();
517 write_to_xml(os.str().c_str());
519 _wr->setUpdating (false);
520 }
522 /*#########################################
523 * Registered TRANSFORMEDPOINT
524 */
526 RegisteredTransformedPoint::~RegisteredTransformedPoint()
527 {
528 _value_x_changed_connection.disconnect();
529 _value_y_changed_connection.disconnect();
530 }
532 RegisteredTransformedPoint::RegisteredTransformedPoint ( const Glib::ustring& label, const Glib::ustring& tip,
533 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
534 SPDocument* doc_in )
535 : RegisteredWidget<Point> (label, tip),
536 to_svg(Geom::identity())
537 {
538 init_parent(key, wr, repr_in, doc_in);
540 setRange (-1e6, 1e6);
541 setDigits (2);
542 setIncrements(0.1, 1.0);
543 _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredTransformedPoint::on_value_changed));
544 _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredTransformedPoint::on_value_changed));
545 }
547 void
548 RegisteredTransformedPoint::setValue(Geom::Point const & p)
549 {
550 Geom::Point new_p = p * to_svg.inverse();
551 Point::setValue(new_p); // the Point widget should display things in canvas coordinates
552 }
554 void
555 RegisteredTransformedPoint::setTransform(Geom::Matrix const & canvas_to_svg)
556 {
557 // check if matrix is singular / has inverse
558 if ( ! canvas_to_svg.isSingular() ) {
559 to_svg = canvas_to_svg;
560 } else {
561 // set back to default
562 to_svg = Geom::identity();
563 }
564 }
566 void
567 RegisteredTransformedPoint::on_value_changed()
568 {
569 if (setProgrammatically()) {
570 clearProgrammatically();
571 return;
572 }
574 if (_wr->isUpdating())
575 return;
577 _wr->setUpdating (true);
579 Geom::Point pos = getValue() * to_svg;
581 Inkscape::SVGOStringStream os;
582 os << pos;
584 write_to_xml(os.str().c_str());
586 _wr->setUpdating (false);
587 }
589 /*#########################################
590 * Registered RANDOM
591 */
593 RegisteredRandom::~RegisteredRandom()
594 {
595 _value_changed_connection.disconnect();
596 _reseeded_connection.disconnect();
597 }
599 RegisteredRandom::RegisteredRandom ( const Glib::ustring& label, const Glib::ustring& tip,
600 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
601 SPDocument * doc_in )
602 : RegisteredWidget<Random> (label, tip)
603 {
604 init_parent(key, wr, repr_in, doc_in);
606 setProgrammatically = false;
608 setRange (-1e6, 1e6);
609 setDigits (2);
610 setIncrements(0.1, 1.0);
611 _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
612 _reseeded_connection = signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
613 }
615 void
616 RegisteredRandom::setValue (double val, long startseed)
617 {
618 Scalar::setValue (val);
619 setStartSeed(startseed);
620 }
622 void
623 RegisteredRandom::on_value_changed()
624 {
625 if (setProgrammatically) {
626 setProgrammatically = false;
627 return;
628 }
630 if (_wr->isUpdating()) {
631 return;
632 }
633 _wr->setUpdating (true);
635 Inkscape::SVGOStringStream os;
636 os << getValue() << ';' << getStartSeed();
638 set_sensitive(false);
639 write_to_xml(os.str().c_str());
640 set_sensitive(true);
642 _wr->setUpdating (false);
643 }
645 } // namespace Dialog
646 } // namespace UI
647 } // namespace Inkscape
649 /*
650 Local Variables:
651 mode:c++
652 c-file-style:"stroustrup"
653 c-file-offsets:((innamespace . 0)(inline-open . 0))
654 indent-tabs-mode:nil
655 fill-column:99
656 End:
657 */
658 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :