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 {
87 }
89 RegisteredCheckButton::~RegisteredCheckButton()
90 {
91 _toggled_connection.disconnect();
92 if (_button) delete _button;
93 }
95 void
96 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)
97 {
98 init_parent(key, wr, repr_in, doc_in);
100 _button = new Gtk::CheckButton;
101 _tt.set_tip (*_button, tip);
102 Gtk::Label *l = new Gtk::Label (label);
103 l->set_use_underline (true);
104 _button->add (*manage (l));
105 _button->set_alignment (right? 1.0 : 0.0, 0.5);
106 _toggled_connection = _button->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
107 }
109 void
110 RegisteredCheckButton::setActive (bool b)
111 {
112 _button->set_active (b);
113 //The slave button is greyed out if the master button is unchecked
114 for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
115 (*i)->set_sensitive(b);
116 }
117 }
119 void
120 RegisteredCheckButton::on_toggled()
121 {
122 if (_wr->isUpdating())
123 return;
125 _wr->setUpdating (true);
127 write_to_xml(_button->get_active() ? "true" : "false");
128 //The slave button is greyed out if the master button is unchecked
129 for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
130 (*i)->set_sensitive(_button->get_active());
131 }
133 _wr->setUpdating (false);
134 }
136 RegisteredUnitMenu::RegisteredUnitMenu()
137 : _label(0), _sel(0)
138 {
139 }
141 RegisteredUnitMenu::~RegisteredUnitMenu()
142 {
143 _changed_connection.disconnect();
144 if (_label) delete _label;
145 if (_sel) delete _sel;
146 }
148 void
149 RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
150 {
151 init_parent(key, wr, repr_in, doc_in);
153 _label = new Gtk::Label (label, 1.0, 0.5);
154 _label->set_use_underline (true);
155 _sel = new UnitMenu ();
156 _label->set_mnemonic_widget (*_sel);
157 _sel->setUnitType (UNIT_TYPE_LINEAR);
158 _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
159 }
161 void
162 RegisteredUnitMenu::setUnit (const SPUnit* unit)
163 {
164 _sel->setUnit (sp_unit_get_abbreviation (unit));
165 }
167 void
168 RegisteredUnitMenu::on_changed()
169 {
170 if (_wr->isUpdating())
171 return;
173 Inkscape::SVGOStringStream os;
174 os << _sel->getUnitAbbr();
176 _wr->setUpdating (true);
178 write_to_xml(os.str().c_str());
180 _wr->setUpdating (false);
181 }
184 RegisteredScalarUnit::RegisteredScalarUnit()
185 : _widget(0), _um(0)
186 {
187 }
189 RegisteredScalarUnit::~RegisteredScalarUnit()
190 {
191 if (_widget) delete _widget;
192 _value_changed_connection.disconnect();
193 }
195 void
196 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)
197 {
198 init_parent(key, wr, repr_in, doc_in);
200 _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel);
201 _widget->initScalar (-1e6, 1e6);
202 _widget->setUnit (rum._sel->getUnitAbbr());
203 _widget->setDigits (2);
204 _um = rum._sel;
205 _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
206 }
208 ScalarUnit*
209 RegisteredScalarUnit::getSU()
210 {
211 return _widget;
212 }
214 void
215 RegisteredScalarUnit::setValue (double val)
216 {
217 _widget->setValue (val);
218 on_value_changed();
219 }
221 void
222 RegisteredScalarUnit::on_value_changed()
223 {
224 if (_wr->isUpdating())
225 return;
227 _wr->setUpdating (true);
229 Inkscape::SVGOStringStream os;
230 os << _widget->getValue("");
231 if (_um)
232 os << _um->getUnitAbbr();
234 write_to_xml(os.str().c_str());
236 _wr->setUpdating (false);
237 }
240 RegisteredScalar::RegisteredScalar()
241 {
242 _widget = NULL;
243 }
245 RegisteredScalar::~RegisteredScalar()
246 {
247 if (_widget)
248 delete _widget;
250 _value_changed_connection.disconnect();
251 }
253 void
254 RegisteredScalar::init ( const Glib::ustring& label, const Glib::ustring& tip,
255 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
256 SPDocument * doc_in )
257 {
258 init_parent(key, wr, repr_in, doc_in);
260 _widget = new Scalar (label, tip);
261 _widget->setRange (-1e6, 1e6);
262 _widget->setDigits (2);
263 _widget->setIncrements(0.1, 1.0);
264 _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
265 }
267 Scalar*
268 RegisteredScalar::getS()
269 {
270 return _widget;
271 }
273 void
274 RegisteredScalar::setValue (double val)
275 {
276 _widget->setValue (val);
277 on_value_changed();
278 }
280 void
281 RegisteredScalar::on_value_changed()
282 {
283 if (_wr->isUpdating()) {
284 return;
285 }
286 _wr->setUpdating (true);
288 Inkscape::SVGOStringStream os;
289 os << _widget->getValue();
291 _widget->set_sensitive(false);
292 write_to_xml(os.str().c_str());
293 _widget->set_sensitive(true);
295 _wr->setUpdating (false);
296 }
299 RegisteredColorPicker::RegisteredColorPicker()
300 : _label(0), _cp(0)
301 {
302 }
304 RegisteredColorPicker::~RegisteredColorPicker()
305 {
306 _changed_connection.disconnect();
307 if (_cp) delete _cp;
308 if (_label) delete _label;
309 }
311 void
312 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)
313 {
314 init_parent("", wr, repr_in, doc_in);
316 _label = new Gtk::Label (label, 1.0, 0.5);
317 _label->set_use_underline (true);
318 _cp = new ColorPicker (title,tip,0,true);
319 _label->set_mnemonic_widget (*_cp);
320 _ckey = ckey;
321 _akey = akey;
322 _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
323 }
325 void
326 RegisteredColorPicker::setRgba32 (guint32 rgba)
327 {
328 _cp->setRgba32 (rgba);
329 }
331 void
332 RegisteredColorPicker::closeWindow()
333 {
334 _cp->closeWindow();
335 }
337 void
338 RegisteredColorPicker::on_changed (guint32 rgba)
339 {
340 if (_wr->isUpdating())
341 return;
343 _wr->setUpdating (true);
345 // Use local repr here. When repr is specified, use that one, but
346 // if repr==NULL, get the repr of namedview of active desktop.
347 Inkscape::XML::Node *local_repr = repr;
348 SPDocument *local_doc = doc;
349 if (!local_repr) {
350 // no repr specified, use active desktop's namedview's repr
351 SPDesktop *dt = SP_ACTIVE_DESKTOP;
352 if (!dt)
353 return;
354 local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
355 local_doc = sp_desktop_document(dt);
356 }
358 gchar c[32];
359 sp_svg_write_color(c, sizeof(c), rgba);
360 bool saved = sp_document_get_undo_sensitive (local_doc);
361 sp_document_set_undo_sensitive (local_doc, false);
362 local_repr->setAttribute(_ckey.c_str(), c);
363 sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
364 local_doc->rroot->setAttribute("sodipodi:modified", "true");
365 sp_document_set_undo_sensitive (local_doc, saved);
366 sp_document_done (local_doc, SP_VERB_NONE,
367 /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
369 _wr->setUpdating (false);
370 }
372 RegisteredSuffixedInteger::RegisteredSuffixedInteger()
373 : _label(0), _sb(0),
374 _adj(0.0,0.0,100.0,1.0,1.0,1.0),
375 _suffix(0)
376 {
377 }
379 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
380 {
381 _changed_connection.disconnect();
382 if (_label) delete _label;
383 if (_suffix) delete _suffix;
384 if (_sb) delete _sb;
385 }
387 void
388 RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
389 {
390 init_parent(key, wr, repr_in, doc_in);
392 _label = new Gtk::Label (label);
393 _label->set_alignment (1.0, 0.5);
394 _label->set_use_underline();
395 _sb = new Gtk::SpinButton (_adj, 1.0, 0);
396 _label->set_mnemonic_widget (*_sb);
397 _suffix = new Gtk::Label (suffix);
398 _hbox.pack_start (*_sb, true, true, 0);
399 _hbox.pack_start (*_suffix, false, false, 0);
401 _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
402 }
404 void
405 RegisteredSuffixedInteger::setValue (int i)
406 {
407 _adj.set_value (i);
408 }
410 void
411 RegisteredSuffixedInteger::on_value_changed()
412 {
413 if (_wr->isUpdating())
414 return;
416 _wr->setUpdating (true);
418 Inkscape::SVGOStringStream os;
419 int value = int(_adj.get_value());
420 os << value;
422 write_to_xml(os.str().c_str());
424 _wr->setUpdating (false);
425 }
427 RegisteredRadioButtonPair::RegisteredRadioButtonPair()
428 : _hbox(0)
429 {
430 }
432 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
433 {
434 _changed_connection.disconnect();
435 }
437 void
438 RegisteredRadioButtonPair::init (const Glib::ustring& label,
439 const Glib::ustring& label1, const Glib::ustring& label2,
440 const Glib::ustring& tip1, const Glib::ustring& tip2,
441 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
442 {
443 init_parent(key, wr, repr_in, doc_in);
445 _hbox = new Gtk::HBox;
446 _hbox->add (*manage (new Gtk::Label (label)));
447 _rb1 = manage (new Gtk::RadioButton (label1, true));
448 _hbox->add (*_rb1);
449 Gtk::RadioButtonGroup group = _rb1->get_group();
450 _rb2 = manage (new Gtk::RadioButton (group, label2, true));
451 _hbox->add (*_rb2);
452 _rb2->set_active();
453 _tt.set_tip (*_rb1, tip1);
454 _tt.set_tip (*_rb2, tip2);
455 _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
456 }
458 void
459 RegisteredRadioButtonPair::setValue (bool second)
460 {
461 if (second) _rb2->set_active();
462 else _rb1->set_active();
463 }
465 void
466 RegisteredRadioButtonPair::on_value_changed()
467 {
468 if (_wr->isUpdating())
469 return;
471 _wr->setUpdating (true);
473 bool second = _rb2->get_active();
474 write_to_xml(second ? "true" : "false");
476 _wr->setUpdating (false);
477 }
479 /*#########################################
480 * Registered POINT
481 */
483 RegisteredPoint::RegisteredPoint()
484 {
485 _widget = NULL;
486 }
488 RegisteredPoint::~RegisteredPoint()
489 {
490 if (_widget)
491 delete _widget;
493 _value_x_changed_connection.disconnect();
494 _value_y_changed_connection.disconnect();
495 }
497 void
498 RegisteredPoint::init ( const Glib::ustring& label, const Glib::ustring& tip,
499 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
500 SPDocument* doc_in )
501 {
502 init_parent(key, wr, repr_in, doc_in);
504 _widget = new Point (label, tip);
505 _widget->setRange (-1e6, 1e6);
506 _widget->setDigits (2);
507 _widget->setIncrements(0.1, 1.0);
508 _value_x_changed_connection = _widget->signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
509 _value_y_changed_connection = _widget->signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
510 }
512 Point*
513 RegisteredPoint::getPoint()
514 {
515 return _widget;
516 }
518 void
519 RegisteredPoint::setValue (double xval, double yval)
520 {
521 _widget->setValue(xval, yval);
522 on_value_changed();
523 }
525 void
526 RegisteredPoint::on_value_changed()
527 {
528 if (_wr->isUpdating())
529 return;
531 _wr->setUpdating (true);
533 Inkscape::SVGOStringStream os;
534 os << _widget->getXValue() << "," << _widget->getYValue();
536 write_to_xml(os.str().c_str());
538 _wr->setUpdating (false);
539 }
541 /*#########################################
542 * Registered RANDOM
543 */
545 RegisteredRandom::RegisteredRandom()
546 {
547 _widget = NULL;
548 }
550 RegisteredRandom::~RegisteredRandom()
551 {
552 if (_widget)
553 delete _widget;
555 _value_changed_connection.disconnect();
556 _reseeded_connection.disconnect();
557 }
559 void
560 RegisteredRandom::init ( const Glib::ustring& label, const Glib::ustring& tip,
561 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
562 SPDocument * doc_in )
563 {
564 init_parent(key, wr, repr_in, doc_in);
566 _widget = new Random (label, tip);
567 _widget->setRange (-1e6, 1e6);
568 _widget->setDigits (2);
569 _widget->setIncrements(0.1, 1.0);
570 _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredRandom::on_value_changed));
571 _reseeded_connection = _widget->signal_reseeded.connect(sigc::mem_fun(*this, &RegisteredRandom::on_value_changed));
572 }
574 Random*
575 RegisteredRandom::getR()
576 {
577 return _widget;
578 }
580 void
581 RegisteredRandom::setValue (double val, long startseed)
582 {
583 _widget->setValue (val);
584 _widget->setStartSeed(startseed);
585 on_value_changed();
586 }
588 void
589 RegisteredRandom::on_value_changed()
590 {
591 if (_wr->isUpdating())
592 return;
593 _wr->setUpdating (true);
595 // FIXME: gtk bug?
596 // disable interruptibility: see http://inkscape.svn.sourceforge.net/viewvc/inkscape/inkscape/trunk/src/ui/widget/selected-style.cpp?r1=13149&r2=13257&sortby=date
597 SPDesktop* dt = SP_ACTIVE_DESKTOP;
598 sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(dt), 0);
600 Inkscape::SVGOStringStream os;
601 os << _widget->getValue() << ';' << _widget->getStartSeed();
603 write_to_xml(os.str().c_str());
605 // resume interruptibility
606 sp_canvas_end_forced_full_redraws(sp_desktop_canvas(dt));
608 _wr->setUpdating (false);
609 }
612 } // namespace Dialog
613 } // namespace UI
614 } // namespace Inkscape
616 /*
617 Local Variables:
618 mode:c++
619 c-file-style:"stroustrup"
620 c-file-offsets:((innamespace . 0)(inline-open . 0))
621 indent-tabs-mode:nil
622 fill-column:99
623 End:
624 */
625 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :