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 initScalar (-1e6, 1e6);
159 setUnit (rum.getUnitMenu()->getUnitAbbr());
160 setDigits (2);
161 _um = rum.getUnitMenu();
162 _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
163 }
166 void
167 RegisteredScalarUnit::on_value_changed()
168 {
169 if (setProgrammatically) {
170 setProgrammatically = false;
171 return;
172 }
174 if (_wr->isUpdating())
175 return;
177 _wr->setUpdating (true);
179 Inkscape::SVGOStringStream os;
180 os << getValue("");
181 if (_um)
182 os << _um->getUnitAbbr();
184 write_to_xml(os.str().c_str());
186 _wr->setUpdating (false);
187 }
190 /*#########################################
191 * Registered SCALAR
192 */
194 RegisteredScalar::~RegisteredScalar()
195 {
196 _value_changed_connection.disconnect();
197 }
199 RegisteredScalar::RegisteredScalar ( const Glib::ustring& label, const Glib::ustring& tip,
200 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
201 SPDocument * doc_in )
202 : RegisteredWidget<Scalar>(label, tip)
203 {
204 init_parent(key, wr, repr_in, doc_in);
206 setRange (-1e6, 1e6);
207 setDigits (2);
208 setIncrements(0.1, 1.0);
209 _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
210 }
212 void
213 RegisteredScalar::on_value_changed()
214 {
215 if (setProgrammatically) {
216 setProgrammatically = false;
217 return;
218 }
220 if (_wr->isUpdating()) {
221 return;
222 }
223 _wr->setUpdating (true);
225 Inkscape::SVGOStringStream os;
226 os << getValue();
228 set_sensitive(false);
229 write_to_xml(os.str().c_str());
230 set_sensitive(true);
232 _wr->setUpdating (false);
233 }
236 /*#########################################
237 * Registered COLORPICKER
238 */
240 RegisteredColorPicker::RegisteredColorPicker(const Glib::ustring& label,
241 const Glib::ustring& title,
242 const Glib::ustring& tip,
243 const Glib::ustring& ckey,
244 const Glib::ustring& akey,
245 Registry& wr,
246 Inkscape::XML::Node* repr_in,
247 SPDocument *doc_in)
248 : RegisteredWidget<ColorPicker> (title, tip, 0, true)
249 {
250 init_parent("", wr, repr_in, doc_in);
252 _label = new Gtk::Label (label, 1.0, 0.5);
253 _label->set_use_underline (true);
254 _label->set_mnemonic_widget (*this);
255 _ckey = ckey;
256 _akey = akey;
257 _changed_connection = connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
258 }
260 RegisteredColorPicker::~RegisteredColorPicker()
261 {
262 _changed_connection.disconnect();
263 }
265 void
266 RegisteredColorPicker::setRgba32 (guint32 rgba)
267 {
268 ColorPicker::setRgba32 (rgba);
269 }
271 void
272 RegisteredColorPicker::closeWindow()
273 {
274 ColorPicker::closeWindow();
275 }
277 void
278 RegisteredColorPicker::on_changed (guint32 rgba)
279 {
280 if (_wr->isUpdating())
281 return;
283 _wr->setUpdating (true);
285 // Use local repr here. When repr is specified, use that one, but
286 // if repr==NULL, get the repr of namedview of active desktop.
287 Inkscape::XML::Node *local_repr = repr;
288 SPDocument *local_doc = doc;
289 if (!local_repr) {
290 // no repr specified, use active desktop's namedview's repr
291 SPDesktop *dt = SP_ACTIVE_DESKTOP;
292 if (!dt)
293 return;
294 local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
295 local_doc = sp_desktop_document(dt);
296 }
298 gchar c[32];
299 sp_svg_write_color(c, sizeof(c), rgba);
300 bool saved = sp_document_get_undo_sensitive (local_doc);
301 sp_document_set_undo_sensitive (local_doc, false);
302 local_repr->setAttribute(_ckey.c_str(), c);
303 sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
304 sp_document_set_undo_sensitive (local_doc, saved);
306 local_doc->setModifiedSinceSave();
307 sp_document_done (local_doc, SP_VERB_NONE,
308 /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
310 _wr->setUpdating (false);
311 }
314 /*#########################################
315 * Registered SUFFIXEDINTEGER
316 */
318 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
319 {
320 _changed_connection.disconnect();
321 }
323 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)
324 : RegisteredWidget<Scalar>(label, tip, 0, suffix),
325 setProgrammatically(false)
326 {
327 init_parent(key, wr, repr_in, doc_in);
329 setRange (0, 1e6);
330 setDigits (0);
331 setIncrements(1, 10);
333 _changed_connection = signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
334 }
336 void
337 RegisteredSuffixedInteger::on_value_changed()
338 {
339 if (setProgrammatically) {
340 setProgrammatically = false;
341 return;
342 }
344 if (_wr->isUpdating())
345 return;
347 _wr->setUpdating (true);
349 Inkscape::SVGOStringStream os;
350 os << getValue();
352 write_to_xml(os.str().c_str());
354 _wr->setUpdating (false);
355 }
358 /*#########################################
359 * Registered RADIOBUTTONPAIR
360 */
362 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
363 {
364 _changed_connection.disconnect();
365 }
367 RegisteredRadioButtonPair::RegisteredRadioButtonPair (const Glib::ustring& label,
368 const Glib::ustring& label1, const Glib::ustring& label2,
369 const Glib::ustring& tip1, const Glib::ustring& tip2,
370 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
371 : RegisteredWidget<Gtk::HBox>(),
372 _rb1(NULL),
373 _rb2(NULL)
374 {
375 init_parent(key, wr, repr_in, doc_in);
377 setProgrammatically = false;
379 add (*manage (new Gtk::Label (label)));
380 _rb1 = manage (new Gtk::RadioButton (label1, true));
381 add (*_rb1);
382 Gtk::RadioButtonGroup group = _rb1->get_group();
383 _rb2 = manage (new Gtk::RadioButton (group, label2, true));
384 add (*_rb2);
385 _rb2->set_active();
386 _tt.set_tip (*_rb1, tip1);
387 _tt.set_tip (*_rb2, tip2);
388 _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
389 }
391 void
392 RegisteredRadioButtonPair::setValue (bool second)
393 {
394 if (!_rb1 || !_rb2)
395 return;
397 setProgrammatically = true;
398 if (second) {
399 _rb2->set_active();
400 } else {
401 _rb1->set_active();
402 }
403 }
405 void
406 RegisteredRadioButtonPair::on_value_changed()
407 {
408 if (setProgrammatically) {
409 setProgrammatically = false;
410 return;
411 }
413 if (_wr->isUpdating())
414 return;
416 _wr->setUpdating (true);
418 bool second = _rb2->get_active();
419 write_to_xml(second ? "true" : "false");
421 _wr->setUpdating (false);
422 }
425 /*#########################################
426 * Registered POINT
427 */
429 RegisteredPoint::~RegisteredPoint()
430 {
431 _value_x_changed_connection.disconnect();
432 _value_y_changed_connection.disconnect();
433 }
435 RegisteredPoint::RegisteredPoint ( const Glib::ustring& label, const Glib::ustring& tip,
436 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
437 SPDocument* doc_in )
438 : RegisteredWidget<Point> (label, tip)
439 {
440 init_parent(key, wr, repr_in, doc_in);
442 setRange (-1e6, 1e6);
443 setDigits (2);
444 setIncrements(0.1, 1.0);
445 _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
446 _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
447 }
449 void
450 RegisteredPoint::on_value_changed()
451 {
452 if (setProgrammatically()) {
453 clearProgrammatically();
454 return;
455 }
457 if (_wr->isUpdating())
458 return;
460 _wr->setUpdating (true);
462 Inkscape::SVGOStringStream os;
463 os << getXValue() << "," << getYValue();
465 write_to_xml(os.str().c_str());
467 _wr->setUpdating (false);
468 }
470 /*#########################################
471 * Registered TRANSFORMEDPOINT
472 */
474 RegisteredTransformedPoint::~RegisteredTransformedPoint()
475 {
476 _value_x_changed_connection.disconnect();
477 _value_y_changed_connection.disconnect();
478 }
480 RegisteredTransformedPoint::RegisteredTransformedPoint ( const Glib::ustring& label, const Glib::ustring& tip,
481 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
482 SPDocument* doc_in )
483 : RegisteredWidget<Point> (label, tip),
484 to_svg(Geom::identity())
485 {
486 init_parent(key, wr, repr_in, doc_in);
488 setRange (-1e6, 1e6);
489 setDigits (2);
490 setIncrements(0.1, 1.0);
491 _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredTransformedPoint::on_value_changed));
492 _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredTransformedPoint::on_value_changed));
493 }
495 void
496 RegisteredTransformedPoint::setValue(Geom::Point const & p)
497 {
498 Geom::Point new_p = p * to_svg.inverse();
499 Point::setValue(new_p); // the Point widget should display things in canvas coordinates
500 }
502 void
503 RegisteredTransformedPoint::setTransform(Geom::Matrix const & canvas_to_svg)
504 {
505 // check if matrix is singular / has inverse
506 if ( ! canvas_to_svg.isSingular() ) {
507 to_svg = canvas_to_svg;
508 } else {
509 // set back to default
510 to_svg = Geom::identity();
511 }
512 }
514 void
515 RegisteredTransformedPoint::on_value_changed()
516 {
517 if (setProgrammatically()) {
518 clearProgrammatically();
519 return;
520 }
522 if (_wr->isUpdating())
523 return;
525 _wr->setUpdating (true);
527 Geom::Point pos = getValue() * to_svg;
529 Inkscape::SVGOStringStream os;
530 os << pos;
532 write_to_xml(os.str().c_str());
534 _wr->setUpdating (false);
535 }
537 /*#########################################
538 * Registered RANDOM
539 */
541 RegisteredRandom::~RegisteredRandom()
542 {
543 _value_changed_connection.disconnect();
544 _reseeded_connection.disconnect();
545 }
547 RegisteredRandom::RegisteredRandom ( const Glib::ustring& label, const Glib::ustring& tip,
548 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
549 SPDocument * doc_in )
550 : RegisteredWidget<Random> (label, tip)
551 {
552 init_parent(key, wr, repr_in, doc_in);
554 setRange (-1e6, 1e6);
555 setDigits (2);
556 setIncrements(0.1, 1.0);
557 _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
558 _reseeded_connection = signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
559 }
561 void
562 RegisteredRandom::setValue (double val, long startseed)
563 {
564 Scalar::setValue (val);
565 setStartSeed(startseed);
566 }
568 void
569 RegisteredRandom::on_value_changed()
570 {
571 if (setProgrammatically) {
572 setProgrammatically = false;
573 return;
574 }
576 if (_wr->isUpdating()) {
577 return;
578 }
579 _wr->setUpdating (true);
581 Inkscape::SVGOStringStream os;
582 os << getValue() << ';' << getStartSeed();
584 set_sensitive(false);
585 write_to_xml(os.str().c_str());
586 set_sensitive(true);
588 _wr->setUpdating (false);
589 }
591 } // namespace Dialog
592 } // namespace UI
593 } // namespace Inkscape
595 /*
596 Local Variables:
597 mode:c++
598 c-file-style:"stroustrup"
599 c-file-offsets:((innamespace . 0)(inline-open . 0))
600 indent-tabs-mode:nil
601 fill-column:99
602 End:
603 */
604 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :