Code

fix compositing for premultiplication and non-alpha cases
[inkscape.git] / src / ui / widget / registered-widget.cpp
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 "widgets/spinbutton-events.h"
28 #include "helper/units.h"
29 #include "xml/repr.h"
30 #include "svg/svg-color.h"
31 #include "svg/stringstream.h"
33 #include "inkscape.h"
34 #include "document.h"
35 #include "desktop-handles.h"
36 #include "sp-namedview.h"
38 #include "registered-widget.h"
39 #include "verbs.h"
41 // for interruptability bug:
42 #include "display/sp-canvas.h"
44 namespace Inkscape {
45 namespace UI {
46 namespace Widget {
48 //===================================================
50 //---------------------------------------------------
53 void
54 RegisteredWidget::write_to_xml(const char * svgstr)
55 {
56     // Use local repr here. When repr is specified, use that one, but
57     // if repr==NULL, get the repr of namedview of active desktop.
58     Inkscape::XML::Node *local_repr = repr;
59     SPDocument *local_doc = doc;
60     if (!local_repr) {
61         // no repr specified, use active desktop's namedview's repr
62         SPDesktop* dt = SP_ACTIVE_DESKTOP;
63         local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
64         local_doc = sp_desktop_document(dt);
65     }
67     bool saved = sp_document_get_undo_sensitive (local_doc);
68     sp_document_set_undo_sensitive (local_doc, false);
69     if (!write_undo) local_repr->setAttribute(_key.c_str(), svgstr);
70     local_doc->rroot->setAttribute("sodipodi:modified", "true");
71     sp_document_set_undo_sensitive (local_doc, saved);
72     if (write_undo) {
73         local_repr->setAttribute(_key.c_str(), svgstr);
74         sp_document_done (local_doc, event_type, event_description);
75     }
76 }
79 //====================================================
81 RegisteredCheckButton::RegisteredCheckButton()
82 : _button(0)
83 {
84 }
86 RegisteredCheckButton::~RegisteredCheckButton()
87 {
88     _toggled_connection.disconnect();
89     if (_button) delete _button;
90 }
92 void
93 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)
94 {
95     init_parent(key, wr, repr_in, doc_in);
97     _button = new Gtk::CheckButton;
98     _tt.set_tip (*_button, tip);
99     Gtk::Label *l = new Gtk::Label (label);
100     l->set_use_underline (true);
101     _button->add (*manage (l));
102     _button->set_alignment (right? 1.0 : 0.0, 0.5);
103     _toggled_connection = _button->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled));
106 void
107 RegisteredCheckButton::setActive (bool b)
109     _button->set_active (b);
110         //The slave button is greyed out if the master button is unchecked
111         for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
112                 (*i)->set_sensitive(b);
113         }
116 void
117 RegisteredCheckButton::on_toggled()
119     if (_wr->isUpdating())
120         return;
122     _wr->setUpdating (true);
124     write_to_xml(_button->get_active() ? "true" : "false");
125     //The slave button is greyed out if the master button is unchecked
126     for (std::list<Gtk::ToggleButton*>::const_iterator i = _slavebuttons.begin(); i != _slavebuttons.end(); i++) {
127         (*i)->set_sensitive(_button->get_active());
128     }
130     write_to_xml(_button->get_active() ? "true" : "false");
132     _wr->setUpdating (false);
135 RegisteredUnitMenu::RegisteredUnitMenu()
136 : _label(0), _sel(0)
140 RegisteredUnitMenu::~RegisteredUnitMenu()
142     _changed_connection.disconnect();
143     if (_label) delete _label;
144     if (_sel) delete _sel;
147 void
148 RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
150     init_parent(key, wr, repr_in, doc_in);
152     _label = new Gtk::Label (label, 1.0, 0.5);
153     _label->set_use_underline (true);
154     _sel = new UnitMenu ();
155     _label->set_mnemonic_widget (*_sel);
156     _sel->setUnitType (UNIT_TYPE_LINEAR);
157     _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed));
160 void
161 RegisteredUnitMenu::setUnit (const SPUnit* unit)
163     _sel->setUnit (sp_unit_get_abbreviation (unit));
166 void
167 RegisteredUnitMenu::on_changed()
169     if (_wr->isUpdating())
170         return;
172     Inkscape::SVGOStringStream os;
173     os << _sel->getUnitAbbr();
175     _wr->setUpdating (true);
177     write_to_xml(os.str().c_str());
179     _wr->setUpdating (false);
183 RegisteredScalarUnit::RegisteredScalarUnit()
184 : _widget(0), _um(0)
188 RegisteredScalarUnit::~RegisteredScalarUnit()
190     if (_widget) delete _widget;
191     _value_changed_connection.disconnect();
194 void
195 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     init_parent(key, wr, repr_in, doc_in);
199     _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel);
200     _widget->initScalar (-1e6, 1e6);
201     _widget->setUnit (rum._sel->getUnitAbbr());
202     _widget->setDigits (2);
203     _um = rum._sel;
204     _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed));
207 ScalarUnit*
208 RegisteredScalarUnit::getSU()
210     return _widget;
213 void
214 RegisteredScalarUnit::setValue (double val)
216     _widget->setValue (val);
217     on_value_changed();
220 void
221 RegisteredScalarUnit::on_value_changed()
223     if (_wr->isUpdating())
224         return;
226     _wr->setUpdating (true);
228     Inkscape::SVGOStringStream os;
229     os << _widget->getValue("");
230     if (_um)
231         os << _um->getUnitAbbr();
233     write_to_xml(os.str().c_str());
235     _wr->setUpdating (false);
239 RegisteredScalar::RegisteredScalar()
241     _widget = NULL;
244 RegisteredScalar::~RegisteredScalar()
246     if (_widget) 
247         delete _widget;
249     _value_changed_connection.disconnect();
252 void
253 RegisteredScalar::init ( const Glib::ustring& label, const Glib::ustring& tip, 
254                          const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in,
255                          SPDocument * doc_in )
257     init_parent(key, wr, repr_in, doc_in);
259     _widget = new Scalar (label, tip);
260     _widget->setRange (-1e6, 1e6);
261     _widget->setDigits (2);
262     _widget->setIncrements(0.1, 1.0);
263     _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalar::on_value_changed));
266 Scalar*
267 RegisteredScalar::getS()
269     return _widget;
272 void
273 RegisteredScalar::setValue (double val)
275     _widget->setValue (val);
276     on_value_changed();
279 void
280 RegisteredScalar::on_value_changed()
282     if (_wr->isUpdating())
283         return;
284     _wr->setUpdating (true);
286     // FIXME:  gtk bug?
287     // disable interruptibility: see http://inkscape.svn.sourceforge.net/viewvc/inkscape/inkscape/trunk/src/ui/widget/selected-style.cpp?r1=13149&r2=13257&sortby=date
288     SPDesktop* dt = SP_ACTIVE_DESKTOP;
289     sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(dt), 0);
291     Inkscape::SVGOStringStream os;
292     os << _widget->getValue();
294     write_to_xml(os.str().c_str());
296     // resume interruptibility
297     sp_canvas_end_forced_full_redraws(sp_desktop_canvas(dt));
299     _wr->setUpdating (false);
303 RegisteredColorPicker::RegisteredColorPicker()
304 : _label(0), _cp(0)
308 RegisteredColorPicker::~RegisteredColorPicker()
310     _changed_connection.disconnect();
311     if (_cp) delete _cp;
312     if (_label) delete _label;
315 void
316 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)
318     init_parent("", wr, repr_in, doc_in);
320     _label = new Gtk::Label (label, 1.0, 0.5);
321     _label->set_use_underline (true);
322     _cp = new ColorPicker (title,tip,0,true);
323     _label->set_mnemonic_widget (*_cp);
324     _ckey = ckey;
325     _akey = akey;
326     _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed));
329 void
330 RegisteredColorPicker::setRgba32 (guint32 rgba)
332     _cp->setRgba32 (rgba);
335 void
336 RegisteredColorPicker::closeWindow()
338     _cp->closeWindow();
341 void
342 RegisteredColorPicker::on_changed (guint32 rgba)
344     if (_wr->isUpdating())
345         return;
347     _wr->setUpdating (true);
349     // Use local repr here. When repr is specified, use that one, but
350     // if repr==NULL, get the repr of namedview of active desktop.
351     Inkscape::XML::Node *local_repr = repr;
352     SPDocument *local_doc = doc;
353     if (!local_repr) {
354         // no repr specified, use active desktop's namedview's repr
355         SPDesktop *dt = SP_ACTIVE_DESKTOP;
356         if (!dt)
357             return;
358         local_repr = SP_OBJECT_REPR (sp_desktop_namedview(dt));
359         local_doc = sp_desktop_document(dt);
360     }
362     gchar c[32];
363     sp_svg_write_color(c, 32, rgba);
364     bool saved = sp_document_get_undo_sensitive (local_doc);
365     sp_document_set_undo_sensitive (local_doc, false);
366     local_repr->setAttribute(_ckey.c_str(), c);
367     sp_repr_set_css_double(local_repr, _akey.c_str(), (rgba & 0xff) / 255.0);
368     local_doc->rroot->setAttribute("sodipodi:modified", "true");
369     sp_document_set_undo_sensitive (local_doc, saved);
370     sp_document_done (local_doc, SP_VERB_NONE,
371                       /* TODO: annotate */ "registered-widget.cpp: RegisteredColorPicker::on_changed");
373     _wr->setUpdating (false);
376 RegisteredSuffixedInteger::RegisteredSuffixedInteger()
377 : _label(0), _sb(0),
378   _adj(0.0,0.0,100.0,1.0,1.0,1.0),
379   _suffix(0)
383 RegisteredSuffixedInteger::~RegisteredSuffixedInteger()
385     _changed_connection.disconnect();
386     if (_label) delete _label;
387     if (_suffix) delete _suffix;
388     if (_sb) delete _sb;
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)
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     _label->set_mnemonic_widget (*_sb);
401     _suffix = new Gtk::Label (suffix);
402     _hbox.pack_start (*_sb, true, true, 0);
403     _hbox.pack_start (*_suffix, false, false, 0);
405     _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed));
408 void
409 RegisteredSuffixedInteger::setValue (int i)
411     _adj.set_value (i);
414 void
415 RegisteredSuffixedInteger::on_value_changed()
417     if (_wr->isUpdating())
418         return;
420     _wr->setUpdating (true);
422     Inkscape::SVGOStringStream os;
423     int value = int(_adj.get_value());
424     os << value;
426     write_to_xml(os.str().c_str());
428     _wr->setUpdating (false);
431 RegisteredRadioButtonPair::RegisteredRadioButtonPair()
432 : _hbox(0)
436 RegisteredRadioButtonPair::~RegisteredRadioButtonPair()
438     _changed_connection.disconnect();
441 void
442 RegisteredRadioButtonPair::init (const Glib::ustring& label,
443 const Glib::ustring& label1, const Glib::ustring& label2,
444 const Glib::ustring& tip1, const Glib::ustring& tip2,
445 const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, SPDocument *doc_in)
447     init_parent(key, wr, repr_in, doc_in);
449     _hbox = new Gtk::HBox;
450     _hbox->add (*manage (new Gtk::Label (label)));
451     _rb1 = manage (new Gtk::RadioButton (label1, true));
452     _hbox->add (*_rb1);
453     Gtk::RadioButtonGroup group = _rb1->get_group();
454     _rb2 = manage (new Gtk::RadioButton (group, label2, true));
455     _hbox->add (*_rb2);
456     _rb2->set_active();
457     _tt.set_tip (*_rb1, tip1);
458     _tt.set_tip (*_rb2, tip2);
459     _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed));
462 void
463 RegisteredRadioButtonPair::setValue (bool second)
465     if (second) _rb2->set_active();
466     else        _rb1->set_active();
469 void
470 RegisteredRadioButtonPair::on_value_changed()
472     if (_wr->isUpdating())
473         return;
475     _wr->setUpdating (true);
477     bool second = _rb2->get_active();
478     write_to_xml(second ? "true" : "false");
480     _wr->setUpdating (false);
483 /*#########################################
484  * Registered POINT
485  */
487 RegisteredPoint::RegisteredPoint()
489     _widget = NULL;
492 RegisteredPoint::~RegisteredPoint()
494     if (_widget) 
495         delete _widget;
497     _value_x_changed_connection.disconnect();
498     _value_y_changed_connection.disconnect();
501 void
502 RegisteredPoint::init ( const Glib::ustring& label, const Glib::ustring& tip, 
503                         const Glib::ustring& key, Registry& wr, Inkscape::XML::Node* repr_in, 
504                         SPDocument* doc_in )
506     init_parent(key, wr, repr_in, doc_in);
508     _widget = new Point (label, tip);
509     _widget->setRange (-1e6, 1e6);
510     _widget->setDigits (2);
511     _widget->setIncrements(0.1, 1.0);
512     _value_x_changed_connection = _widget->signal_x_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
513     _value_y_changed_connection = _widget->signal_y_value_changed().connect (sigc::mem_fun (*this, &RegisteredPoint::on_value_changed));
516 Point*
517 RegisteredPoint::getPoint()
519     return _widget;
522 void
523 RegisteredPoint::setValue (double xval, double yval)
525     _widget->setValue(xval, yval);
526     on_value_changed();
529 void
530 RegisteredPoint::on_value_changed()
532     if (_wr->isUpdating())
533         return;
535     _wr->setUpdating (true);
537     Inkscape::SVGOStringStream os;
538     os << _widget->getXValue() << "," << _widget->getYValue();
540     write_to_xml(os.str().c_str());
542     _wr->setUpdating (false);
545 } // namespace Dialog
546 } // namespace UI
547 } // namespace Inkscape
549 /*
550   Local Variables:
551   mode:c++
552   c-file-style:"stroustrup"
553   c-file-offsets:((innamespace . 0)(inline-open . 0))
554   indent-tabs-mode:nil
555   fill-column:99
556   End:
557 */
558 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :