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 setProgrammatically = true;
114 _button->set_active (b);
115 //The slave button is greyed out if the master button is unchecked
116 for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
117 (*i)->set_sensitive(b);
118 }
119 setProgrammatically = false;
120 }
122 void
123 RegisteredCheckButton::on_toggled()
124 {
125 if (setProgrammatically) {
126 setProgrammatically = false;
127 return;
128 }
130 if (_wr->isUpdating())
131 return;
132 _wr->setUpdating (true);
134 write_to_xml(_button->get_active() ? "true" : "false");
135 //The slave button is greyed out if the master button is unchecked
136 for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
137 (*i)->set_sensitive(_button->get_active());
138 }
140 _wr->setUpdating (false);
141 }
143 RegisteredUnitMenu::RegisteredUnitMenu()
144 : _label(0), _sel(0)
145 {
146 }
148 RegisteredUnitMenu::~RegisteredUnitMenu()
149 {
150 _changed_connection.disconnect();
151 if (_label) delete _label;
152 if (_sel) delete _sel;
153 }
155 void
156 RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
157 {
158 init_parent(key, wr, repr_in, doc_in);
160 _label = new Gtk::Label (label, 1.0, 0.5);
161 _label->set_use_underline (true);
162 _sel = new UnitMenu ();
163 _label->set_mnemonic_widget (*_sel);
164 _sel->setUnitType (UNIT_TYPE_LINEAR);
165 _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
166 }
168 void
169 RegisteredUnitMenu::setUnit (const SPUnit* unit)
170 {
171 _sel->setUnit (sp_unit_get_abbreviation (unit));
172 }
174 void
175 RegisteredUnitMenu::on_changed()
176 {
177 if (_wr->isUpdating())
178 return;
180 Inkscape::SVGOStringStream os;
181 os << _sel->getUnitAbbr();
183 _wr->setUpdating (true);
185 write_to_xml(os.str().c_str());
187 _wr->setUpdating (false);
188 }
191 RegisteredScalarUnit::RegisteredScalarUnit()
192 : _widget(0), _um(0)
193 {
194 }
196 RegisteredScalarUnit::~RegisteredScalarUnit()
197 {
198 if (_widget) delete _widget;
199 _value_changed_connection.disconnect();
200 }
202 void
203 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)
204 {
205 init_parent(key, wr, repr_in, doc_in);
207 _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel);
208 _widget->initScalar (-1e6, 1e6);
209 _widget->setUnit (rum._sel->getUnitAbbr());
210 _widget->setDigits (2);
211 _um = rum._sel;
212 _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
213 }
215 ScalarUnit*
216 RegisteredScalarUnit::getSU()
217 {
218 return _widget;
219 }
221 void
222 RegisteredScalarUnit::setValue (double val)
223 {
224 if (_widget)
225 _widget->setValue (val);
226 }
228 void
229 RegisteredScalarUnit::on_value_changed()
230 {
231 g_message("on_value_changed");
232 if (_widget->setProgrammatically) {
233 _widget->setProgrammatically = false;
234 return;
235 }
236 g_message("on_value_changed1");
238 if (_wr->isUpdating())
239 return;
241 _wr->setUpdating (true);
243 Inkscape::SVGOStringStream os;
244 os << _widget->getValue("");
245 if (_um)
246 os << _um->getUnitAbbr();
248 write_to_xml(os.str().c_str());
250 _wr->setUpdating (false);
251 }
254 RegisteredScalar::RegisteredScalar()
255 {
256 _widget = NULL;
257 }
259 RegisteredScalar::~RegisteredScalar()
260 {
261 if (_widget)
262 delete _widget;
264 _value_changed_connection.disconnect();
265 }
267 void
268 RegisteredScalar::init ( const Glib::ustring& label, const Glib::ustring& tip,
269 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
270 SPDocument * doc_in )
271 {
272 init_parent(key, wr, repr_in, doc_in);
274 _widget = new Scalar (label, tip);
275 _widget->setRange (-1e6, 1e6);
276 _widget->setDigits (2);
277 _widget->setIncrements(0.1, 1.0);
278 _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
279 }
281 Scalar*
282 RegisteredScalar::getS()
283 {
284 return _widget;
285 }
287 void
288 RegisteredScalar::setValue (double val)
289 {
290 if (_widget)
291 _widget->setValue (val);
292 }
294 void
295 RegisteredScalar::on_value_changed()
296 {
297 if (_widget->setProgrammatically) {
298 _widget->setProgrammatically = false;
299 return;
300 }
302 if (_wr->isUpdating()) {
303 return;
304 }
305 _wr->setUpdating (true);
307 Inkscape::SVGOStringStream os;
308 os << _widget->getValue();
310 _widget->set_sensitive(false);
311 write_to_xml(os.str().c_str());
312 _widget->set_sensitive(true);
314 _wr->setUpdating (false);
315 }
318 RegisteredColorPicker::RegisteredColorPicker()
319 : _label(0), _cp(0)
320 {
321 }
323 RegisteredColorPicker::~RegisteredColorPicker()
324 {
325 _changed_connection.disconnect();
326 if (_cp) delete _cp;
327 if (_label) delete _label;
328 }
330 void
331 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)
332 {
333 init_parent("", wr, repr_in, doc_in);
335 _label = new Gtk::Label (label, 1.0, 0.5);
336 _label->set_use_underline (true);
337 _cp = new ColorPicker (title,tip,0,true);
338 _label->set_mnemonic_widget (*_cp);
339 _ckey = ckey;
340 _akey = akey;
341 _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
342 }
344 void
345 RegisteredColorPicker::setRgba32 (guint32 rgba)
346 {
347 _cp->setRgba32 (rgba);
348 }
350 void
351 RegisteredColorPicker::closeWindow()
352 {
353 _cp->closeWindow();
354 }
356 void
357 RegisteredColorPicker::on_changed (guint32 rgba)
358 {
359 if (_wr->isUpdating())
360 return;
362 _wr->setUpdating (true);
364 // Use local repr here. When repr is specified, use that one, but
365 // if repr==NULL, get the repr of namedview of active desktop.
366 Inkscape::XML::Node *local_repr = repr;
367 SPDocument *local_doc = doc;
368 if (!local_repr) {
369 // no repr specified, use active desktop's namedview's repr
370 SPDesktop *dt = SP_ACTIVE_DESKTOP;
371 if (!dt)
372 return;
373 local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
374 local_doc = sp_desktop_document(dt);
375 }
377 gchar c[32];
378 sp_svg_write_color(c, sizeof(c), rgba);
379 bool saved = sp_document_get_undo_sensitive (local_doc);
380 sp_document_set_undo_sensitive (local_doc, false);
381 local_repr->setAttribute(_ckey.c_str(), c);
382 sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
383 local_doc->rroot->setAttribute("sodipodi:modified", "true");
384 sp_document_set_undo_sensitive (local_doc, saved);
385 sp_document_done (local_doc, SP_VERB_NONE,
386 /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
388 _wr->setUpdating (false);
389 }
391 RegisteredSuffixedInteger::RegisteredSuffixedInteger()
392 : _label(0),
393 setProgrammatically(false),
394 _sb(0),
395 _adj(0.0,0.0,100.0,1.0,1.0,1.0),
396 _suffix(0)
397 {
398 }
400 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
401 {
402 _changed_connection.disconnect();
403 if (_label) delete _label;
404 if (_suffix) delete _suffix;
405 if (_sb) delete _sb;
406 }
408 void
409 RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
410 {
411 init_parent(key, wr, repr_in, doc_in);
413 _label = new Gtk::Label (label);
414 _label->set_alignment (1.0, 0.5);
415 _label->set_use_underline();
416 _sb = new Gtk::SpinButton (_adj, 1.0, 0);
417 _sb->set_numeric();
418 _label->set_mnemonic_widget (*_sb);
419 _suffix = new Gtk::Label (suffix);
420 _hbox.pack_start (*_sb, true, true, 0);
421 _hbox.pack_start (*_suffix, false, false, 0);
423 _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
424 }
426 void
427 RegisteredSuffixedInteger::setValue (int i)
428 {
429 setProgrammatically = true;
430 _adj.set_value (i);
431 }
433 void
434 RegisteredSuffixedInteger::on_value_changed()
435 {
436 if (setProgrammatically) {
437 setProgrammatically = false;
438 return;
439 }
441 if (_wr->isUpdating())
442 return;
444 _wr->setUpdating (true);
446 Inkscape::SVGOStringStream os;
447 int value = int(_adj.get_value());
448 os << value;
450 write_to_xml(os.str().c_str());
452 _wr->setUpdating (false);
453 }
455 RegisteredRadioButtonPair::RegisteredRadioButtonPair()
456 : _hbox(0),
457 setProgrammatically(false)
458 {
459 }
461 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
462 {
463 _changed_connection.disconnect();
464 }
466 void
467 RegisteredRadioButtonPair::init (const Glib::ustring& label,
468 const Glib::ustring& label1, const Glib::ustring& label2,
469 const Glib::ustring& tip1, const Glib::ustring& tip2,
470 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
471 {
472 init_parent(key, wr, repr_in, doc_in);
474 _hbox = new Gtk::HBox;
475 _hbox->add (*manage (new Gtk::Label (label)));
476 _rb1 = manage (new Gtk::RadioButton (label1, true));
477 _hbox->add (*_rb1);
478 Gtk::RadioButtonGroup group = _rb1->get_group();
479 _rb2 = manage (new Gtk::RadioButton (group, label2, true));
480 _hbox->add (*_rb2);
481 _rb2->set_active();
482 _tt.set_tip (*_rb1, tip1);
483 _tt.set_tip (*_rb2, tip2);
484 _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
485 }
487 void
488 RegisteredRadioButtonPair::setValue (bool second)
489 {
490 if (!_rb1 || !_rb2)
491 return;
493 setProgrammatically = true;
494 if (second) {
495 _rb2->set_active();
496 } else {
497 _rb1->set_active();
498 }
499 }
501 void
502 RegisteredRadioButtonPair::on_value_changed()
503 {
504 if (setProgrammatically) {
505 setProgrammatically = false;
506 return;
507 }
509 if (_wr->isUpdating())
510 return;
512 _wr->setUpdating (true);
514 bool second = _rb2->get_active();
515 write_to_xml(second ? "true" : "false");
517 _wr->setUpdating (false);
518 }
520 /*#########################################
521 * Registered POINT
522 */
524 RegisteredPoint::RegisteredPoint()
525 {
526 _widget = NULL;
527 }
529 RegisteredPoint::~RegisteredPoint()
530 {
531 if (_widget)
532 delete _widget;
534 _value_x_changed_connection.disconnect();
535 _value_y_changed_connection.disconnect();
536 }
538 void
539 RegisteredPoint::init ( const Glib::ustring& label, const Glib::ustring& tip,
540 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
541 SPDocument* doc_in )
542 {
543 init_parent(key, wr, repr_in, doc_in);
545 _widget = new Point (label, tip);
546 _widget->setRange (-1e6, 1e6);
547 _widget->setDigits (2);
548 _widget->setIncrements(0.1, 1.0);
549 _value_x_changed_connection = _widget->signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
550 _value_y_changed_connection = _widget->signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
551 }
553 Point*
554 RegisteredPoint::getPoint()
555 {
556 return _widget;
557 }
559 void
560 RegisteredPoint::setValue (double xval, double yval)
561 {
562 if (_widget)
563 _widget->setValue(xval, yval);
564 }
566 void
567 RegisteredPoint::on_value_changed()
568 {
569 if (_widget->setProgrammatically()) {
570 _widget->clearProgrammatically();
571 return;
572 }
574 if (_wr->isUpdating())
575 return;
577 _wr->setUpdating (true);
579 Inkscape::SVGOStringStream os;
580 os << _widget->getXValue() << "," << _widget->getYValue();
582 write_to_xml(os.str().c_str());
584 _wr->setUpdating (false);
585 }
587 /*#########################################
588 * Registered RANDOM
589 */
591 RegisteredRandom::RegisteredRandom()
592 {
593 _widget = NULL;
594 }
596 RegisteredRandom::~RegisteredRandom()
597 {
598 if (_widget)
599 delete _widget;
601 _value_changed_connection.disconnect();
602 _reseeded_connection.disconnect();
603 }
605 void
606 RegisteredRandom::init ( const Glib::ustring& label, const Glib::ustring& tip,
607 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
608 SPDocument * doc_in )
609 {
610 init_parent(key, wr, repr_in, doc_in);
612 _widget = new Random (label, tip);
613 _widget->setRange (-1e6, 1e6);
614 _widget->setDigits (2);
615 _widget->setIncrements(0.1, 1.0);
616 _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
617 _reseeded_connection = _widget->signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
618 }
620 Random*
621 RegisteredRandom::getR()
622 {
623 return _widget;
624 }
626 void
627 RegisteredRandom::setValue (double val, long startseed)
628 {
629 if (!_widget)
630 return;
632 _widget->setValue (val);
633 _widget->setStartSeed(startseed);
634 }
636 void
637 RegisteredRandom::on_value_changed()
638 {
639 if (_widget->setProgrammatically) {
640 _widget->setProgrammatically = false;
641 return;
642 }
644 if (_wr->isUpdating()) {
645 return;
646 }
647 _wr->setUpdating (true);
649 Inkscape::SVGOStringStream os;
650 os << _widget->getValue() << ';' << _widget->getStartSeed();
652 _widget->set_sensitive(false);
653 write_to_xml(os.str().c_str());
654 _widget->set_sensitive(true);
656 _wr->setUpdating (false);
657 }
660 } // namespace Dialog
661 } // namespace UI
662 } // namespace Inkscape
664 /*
665 Local Variables:
666 mode:c++
667 c-file-style:"stroustrup"
668 c-file-offsets:((innamespace . 0)(inline-open . 0))
669 indent-tabs-mode:nil
670 fill-column:99
671 End:
672 */
673 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :