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 void
45 RegisteredWdg::write_to_xml(const char * svgstr)
46 {
47 // Use local repr here. When repr is specified, use that one, but
48 // if repr==NULL, get the repr of namedview of active desktop.
49 Inkscape::XML::Node *local_repr = repr;
50 SPDocument *local_doc = doc;
51 if (!local_repr) {
52 // no repr specified, use active desktop's namedview's repr
53 SPDesktop* dt = SP_ACTIVE_DESKTOP;
54 local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
55 local_doc = sp_desktop_document(dt);
56 }
58 bool saved = sp_document_get_undo_sensitive (local_doc);
59 sp_document_set_undo_sensitive (local_doc, false);
60 if (!write_undo) local_repr->setAttribute(_key.c_str(), svgstr);
61 sp_document_set_undo_sensitive (local_doc, saved);
63 local_doc->setModifiedSinceSave();
64 if (write_undo) {
65 local_repr->setAttribute(_key.c_str(), svgstr);
66 sp_document_done (local_doc, event_type, event_description);
67 }
68 }
71 /*#########################################
72 * Registered CHECKBUTTON
73 */
75 RegisteredCheckButton::~RegisteredCheckButton()
76 {
77 _toggled_connection.disconnect();
78 }
80 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)
81 : RegisteredWidget<Gtk::CheckButton>()
82 {
83 init_parent(key, wr, repr_in, doc_in);
85 setProgrammatically = false;
87 _tt.set_tip (*this, tip);
88 Gtk::Label *l = new Gtk::Label (label);
89 l->set_use_underline (true);
90 add (*manage (l));
91 set_alignment (right? 1.0 : 0.0, 0.5);
92 _toggled_connection = signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
93 }
95 void
96 RegisteredCheckButton::setActive (bool b)
97 {
98 setProgrammatically = true;
99 set_active (b);
100 //The slave button is greyed out if the master button is unchecked
101 for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); i++) {
102 (*i)->set_sensitive(b);
103 }
104 setProgrammatically = false;
105 }
107 void
108 RegisteredCheckButton::on_toggled()
109 {
110 if (setProgrammatically) {
111 setProgrammatically = false;
112 return;
113 }
115 if (_wr->isUpdating())
116 return;
117 _wr->setUpdating (true);
119 write_to_xml(get_active() ? "true" : "false");
120 //The slave button is greyed out if the master button is unchecked
121 for (std::list<Gtk::Widget*>::const_iterator i = _slavewidgets.begin(); i != _slavewidgets.end(); i++) {
122 (*i)->set_sensitive(get_active());
123 }
125 _wr->setUpdating (false);
126 }
129 /*#########################################
130 * Registered UNITMENU
131 */
133 RegisteredUnitMenu::RegisteredUnitMenu()
134 : _label(0), _sel(0)
135 {
136 }
138 RegisteredUnitMenu::~RegisteredUnitMenu()
139 {
140 _changed_connection.disconnect();
141 if (_label) delete _label;
142 if (_sel) delete _sel;
143 }
145 void
146 RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
147 {
148 init_parent(key, wr, repr_in, doc_in);
150 _label = new Gtk::Label (label, 1.0, 0.5);
151 _label->set_use_underline (true);
152 _sel = new UnitMenu ();
153 _label->set_mnemonic_widget (*_sel);
154 _sel->setUnitType (UNIT_TYPE_LINEAR);
155 _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
156 }
158 void
159 RegisteredUnitMenu::setUnit (const SPUnit* unit)
160 {
161 _sel->setUnit (sp_unit_get_abbreviation (unit));
162 }
164 void
165 RegisteredUnitMenu::on_changed()
166 {
167 if (_wr->isUpdating())
168 return;
170 Inkscape::SVGOStringStream os;
171 os << _sel->getUnitAbbr();
173 _wr->setUpdating (true);
175 write_to_xml(os.str().c_str());
177 _wr->setUpdating (false);
178 }
181 /*#########################################
182 * Registered SCALARUNIT
183 */
185 RegisteredScalarUnit::RegisteredScalarUnit()
186 : _widget(0), _um(0)
187 {
188 }
190 RegisteredScalarUnit::~RegisteredScalarUnit()
191 {
192 if (_widget) delete _widget;
193 _value_changed_connection.disconnect();
194 }
196 void
197 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)
198 {
199 init_parent(key, wr, repr_in, doc_in);
201 _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel);
202 _widget->initScalar (-1e6, 1e6);
203 _widget->setUnit (rum._sel->getUnitAbbr());
204 _widget->setDigits (2);
205 _um = rum._sel;
206 _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
207 }
209 ScalarUnit*
210 RegisteredScalarUnit::getSU()
211 {
212 return _widget;
213 }
215 void
216 RegisteredScalarUnit::setValue (double val)
217 {
218 if (_widget)
219 _widget->setValue (val);
220 }
222 void
223 RegisteredScalarUnit::on_value_changed()
224 {
225 if (_widget->setProgrammatically) {
226 _widget->setProgrammatically = false;
227 return;
228 }
230 if (_wr->isUpdating())
231 return;
233 _wr->setUpdating (true);
235 Inkscape::SVGOStringStream os;
236 os << _widget->getValue("");
237 if (_um)
238 os << _um->getUnitAbbr();
240 write_to_xml(os.str().c_str());
242 _wr->setUpdating (false);
243 }
246 /*#########################################
247 * Registered SCALAR
248 */
250 RegisteredScalar::~RegisteredScalar()
251 {
252 _value_changed_connection.disconnect();
253 }
255 RegisteredScalar::RegisteredScalar ( const Glib::ustring& label, const Glib::ustring& tip,
256 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
257 SPDocument * doc_in )
258 : RegisteredWidget<Scalar>(label, tip)
259 {
260 init_parent(key, wr, repr_in, doc_in);
262 setRange (-1e6, 1e6);
263 setDigits (2);
264 setIncrements(0.1, 1.0);
265 _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
266 }
268 void
269 RegisteredScalar::on_value_changed()
270 {
271 if (setProgrammatically) {
272 setProgrammatically = false;
273 return;
274 }
276 if (_wr->isUpdating()) {
277 return;
278 }
279 _wr->setUpdating (true);
281 Inkscape::SVGOStringStream os;
282 os << getValue();
284 set_sensitive(false);
285 write_to_xml(os.str().c_str());
286 set_sensitive(true);
288 _wr->setUpdating (false);
289 }
292 /*#########################################
293 * Registered COLORPICKER
294 */
296 RegisteredColorPicker::RegisteredColorPicker(const Glib::ustring& label,
297 const Glib::ustring& title,
298 const Glib::ustring& tip,
299 const Glib::ustring& ckey,
300 const Glib::ustring& akey,
301 Registry& wr,
302 Inkscape::XML::Node* repr_in,
303 SPDocument *doc_in)
304 : RegisteredWidget<ColorPicker> (title, tip, 0, true)
305 {
306 init_parent("", wr, repr_in, doc_in);
308 _label = new Gtk::Label (label, 1.0, 0.5);
309 _label->set_use_underline (true);
310 _label->set_mnemonic_widget (*this);
311 _ckey = ckey;
312 _akey = akey;
313 _changed_connection = connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
314 }
316 RegisteredColorPicker::~RegisteredColorPicker()
317 {
318 _changed_connection.disconnect();
319 }
321 void
322 RegisteredColorPicker::setRgba32 (guint32 rgba)
323 {
324 ColorPicker::setRgba32 (rgba);
325 }
327 void
328 RegisteredColorPicker::closeWindow()
329 {
330 ColorPicker::closeWindow();
331 }
333 void
334 RegisteredColorPicker::on_changed (guint32 rgba)
335 {
336 if (_wr->isUpdating())
337 return;
339 _wr->setUpdating (true);
341 // Use local repr here. When repr is specified, use that one, but
342 // if repr==NULL, get the repr of namedview of active desktop.
343 Inkscape::XML::Node *local_repr = repr;
344 SPDocument *local_doc = doc;
345 if (!local_repr) {
346 // no repr specified, use active desktop's namedview's repr
347 SPDesktop *dt = SP_ACTIVE_DESKTOP;
348 if (!dt)
349 return;
350 local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
351 local_doc = sp_desktop_document(dt);
352 }
354 gchar c[32];
355 sp_svg_write_color(c, sizeof(c), rgba);
356 bool saved = sp_document_get_undo_sensitive (local_doc);
357 sp_document_set_undo_sensitive (local_doc, false);
358 local_repr->setAttribute(_ckey.c_str(), c);
359 sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
360 sp_document_set_undo_sensitive (local_doc, saved);
362 local_doc->setModifiedSinceSave();
363 sp_document_done (local_doc, SP_VERB_NONE,
364 /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
366 _wr->setUpdating (false);
367 }
370 /*#########################################
371 * Registered SUFFIXEDINTEGER
372 */
374 RegisteredSuffixedInteger::RegisteredSuffixedInteger()
375 : _label(0),
376 setProgrammatically(false),
377 _sb(0),
378 _adj(0.0,0.0,100.0,1.0,1.0,1.0),
379 _suffix(0)
380 {
381 }
383 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
384 {
385 _changed_connection.disconnect();
386 if (_label) delete _label;
387 if (_suffix) delete _suffix;
388 if (_sb) delete _sb;
389 }
391 void
392 RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
393 {
394 init_parent(key, wr, repr_in, doc_in);
396 _label = new Gtk::Label (label);
397 _label->set_alignment (1.0, 0.5);
398 _label->set_use_underline();
399 _sb = new Gtk::SpinButton (_adj, 1.0, 0);
400 _sb->set_numeric();
401 _label->set_mnemonic_widget (*_sb);
402 _suffix = new Gtk::Label (suffix);
403 _hbox.pack_start (*_sb, true, true, 0);
404 _hbox.pack_start (*_suffix, false, false, 0);
406 _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
407 }
409 void
410 RegisteredSuffixedInteger::setValue (int i)
411 {
412 setProgrammatically = true;
413 _adj.set_value (i);
414 }
416 void
417 RegisteredSuffixedInteger::on_value_changed()
418 {
419 if (setProgrammatically) {
420 setProgrammatically = false;
421 return;
422 }
424 if (_wr->isUpdating())
425 return;
427 _wr->setUpdating (true);
429 Inkscape::SVGOStringStream os;
430 int value = int(_adj.get_value());
431 os << value;
433 write_to_xml(os.str().c_str());
435 _wr->setUpdating (false);
436 }
439 /*#########################################
440 * Registered RADIOBUTTONPAIR
441 */
443 RegisteredRadioButtonPair::RegisteredRadioButtonPair()
444 : _hbox(0),
445 setProgrammatically(false)
446 {
447 }
449 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
450 {
451 _changed_connection.disconnect();
452 }
454 void
455 RegisteredRadioButtonPair::init (const Glib::ustring& label,
456 const Glib::ustring& label1, const Glib::ustring& label2,
457 const Glib::ustring& tip1, const Glib::ustring& tip2,
458 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
459 {
460 init_parent(key, wr, repr_in, doc_in);
462 _hbox = new Gtk::HBox;
463 _hbox->add (*manage (new Gtk::Label (label)));
464 _rb1 = manage (new Gtk::RadioButton (label1, true));
465 _hbox->add (*_rb1);
466 Gtk::RadioButtonGroup group = _rb1->get_group();
467 _rb2 = manage (new Gtk::RadioButton (group, label2, true));
468 _hbox->add (*_rb2);
469 _rb2->set_active();
470 _tt.set_tip (*_rb1, tip1);
471 _tt.set_tip (*_rb2, tip2);
472 _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
473 }
475 void
476 RegisteredRadioButtonPair::setValue (bool second)
477 {
478 if (!_rb1 || !_rb2)
479 return;
481 setProgrammatically = true;
482 if (second) {
483 _rb2->set_active();
484 } else {
485 _rb1->set_active();
486 }
487 }
489 void
490 RegisteredRadioButtonPair::on_value_changed()
491 {
492 if (setProgrammatically) {
493 setProgrammatically = false;
494 return;
495 }
497 if (_wr->isUpdating())
498 return;
500 _wr->setUpdating (true);
502 bool second = _rb2->get_active();
503 write_to_xml(second ? "true" : "false");
505 _wr->setUpdating (false);
506 }
509 /*#########################################
510 * Registered POINT
511 */
513 RegisteredPoint::~RegisteredPoint()
514 {
515 _value_x_changed_connection.disconnect();
516 _value_y_changed_connection.disconnect();
517 }
519 RegisteredPoint::RegisteredPoint ( const Glib::ustring& label, const Glib::ustring& tip,
520 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
521 SPDocument* doc_in )
522 : RegisteredWidget<Point> (label, tip)
523 {
524 init_parent(key, wr, repr_in, doc_in);
526 setRange (-1e6, 1e6);
527 setDigits (2);
528 setIncrements(0.1, 1.0);
529 _value_x_changed_connection = signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
530 _value_y_changed_connection = signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
531 }
533 void
534 RegisteredPoint::on_value_changed()
535 {
536 if (setProgrammatically()) {
537 clearProgrammatically();
538 return;
539 }
541 if (_wr->isUpdating())
542 return;
544 _wr->setUpdating (true);
546 Inkscape::SVGOStringStream os;
547 os << getXValue() << "," << getYValue();
549 write_to_xml(os.str().c_str());
551 _wr->setUpdating (false);
552 }
555 /*#########################################
556 * Registered RANDOM
557 */
559 RegisteredRandom::~RegisteredRandom()
560 {
561 _value_changed_connection.disconnect();
562 _reseeded_connection.disconnect();
563 }
565 RegisteredRandom::RegisteredRandom ( const Glib::ustring& label, const Glib::ustring& tip,
566 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
567 SPDocument * doc_in )
568 : RegisteredWidget<Random> (label, tip)
569 {
570 init_parent(key, wr, repr_in, doc_in);
572 setRange (-1e6, 1e6);
573 setDigits (2);
574 setIncrements(0.1, 1.0);
575 _value_changed_connection = signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
576 _reseeded_connection = signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
577 }
579 void
580 RegisteredRandom::setValue (double val, long startseed)
581 {
582 Scalar::setValue (val);
583 setStartSeed(startseed);
584 }
586 void
587 RegisteredRandom::on_value_changed()
588 {
589 if (setProgrammatically) {
590 setProgrammatically = false;
591 return;
592 }
594 if (_wr->isUpdating()) {
595 return;
596 }
597 _wr->setUpdating (true);
599 Inkscape::SVGOStringStream os;
600 os << getValue() << ';' << getStartSeed();
602 set_sensitive(false);
603 write_to_xml(os.str().c_str());
604 set_sensitive(true);
606 _wr->setUpdating (false);
607 }
609 } // namespace Dialog
610 } // namespace UI
611 } // namespace Inkscape
613 /*
614 Local Variables:
615 mode:c++
616 c-file-style:"stroustrup"
617 c-file-offsets:((innamespace . 0)(inline-open . 0))
618 indent-tabs-mode:nil
619 fill-column:99
620 End:
621 */
622 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :