Code

Fix some console warning spam (most cannot be fixed, unfortunately)
[inkscape.git] / src / ui / widget / style-swatch.cpp
1 /** @file
2  * @brief Static style swatch (fill, stroke, opacity)
3  */
4 /* Authors:
5  *   buliabyak@gmail.com
6  *   Krzysztof KosiƄski <tweenk.pl@gmail.com>
7  *
8  * Copyright (C) 2005-2008 Authors
9  *
10  * Released under GNU GPL.  Read the file 'COPYING' for more information.
11  */
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
17 #include <cstring>
18 #include <string>
20 #include "style-swatch.h"
22 #include "widgets/spw-utilities.h"
23 #include "ui/widget/color-preview.h"
25 #include "style.h"
26 #include "sp-linear-gradient-fns.h"
27 #include "sp-radial-gradient-fns.h"
28 #include "sp-pattern.h"
29 #include "xml/repr.h"
30 #include "widgets/widget-sizes.h"
31 #include "helper/units.h"
32 #include "helper/action.h"
33 #include "preferences.h"
34 #include "inkscape.h"
36 enum {
37     SS_FILL,
38     SS_STROKE
39 };
41 namespace Inkscape {
42 namespace UI {
43 namespace Widget {
45 /**
46  * @brief Watches whether the tool uses the current style
47  */
48 class StyleSwatch::ToolObserver : public Inkscape::Preferences::Observer {
49 public:
50     ToolObserver(Glib::ustring const &path, StyleSwatch &ss) : 
51         Observer(path),
52         _style_swatch(ss)
53     {}
54     virtual void notify(Inkscape::Preferences::Entry const &val);
55 private:
56     StyleSwatch &_style_swatch;
57 };
59 /**
60  * @brief Watches for changes in the observed style pref
61  */
62 class StyleSwatch::StyleObserver : public Inkscape::Preferences::Observer {
63 public:
64     StyleObserver(Glib::ustring const &path, StyleSwatch &ss) :
65         Observer(path),
66         _style_swatch(ss)
67     {
68         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
69         this->notify(prefs->getEntry(path));
70     }
71     virtual void notify(Inkscape::Preferences::Entry const &val) {
72         SPCSSAttr *css = val.getInheritedStyle();
73         _style_swatch.setStyle(css);
74         sp_repr_css_attr_unref(css);
75     }
76 private:
77     StyleSwatch &_style_swatch;
78 };
80 void StyleSwatch::ToolObserver::notify(Inkscape::Preferences::Entry const &val)
81 {
82     bool usecurrent = val.getBool();
84     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
85     if (_style_swatch._style_obs) delete _style_swatch._style_obs;
87     if (usecurrent) {
88         _style_swatch._style_obs = new StyleObserver("/desktop/style", _style_swatch);
89         
90         // If desktop's last-set style is empty, a tool uses its own fixed style even if set to use
91         // last-set (so long as it's empty). To correctly show this, we get the tool's style
92         // if the desktop's style is empty.
93         SPCSSAttr *css = prefs->getStyle("/desktop/style");
94         if (!css->attributeList()) {
95             SPCSSAttr *css2 = prefs->getInheritedStyle(_style_swatch._tool_path + "/style");
96             _style_swatch.setStyle(css2);
97             sp_repr_css_attr_unref(css2);
98         }
99         sp_repr_css_attr_unref(css);
100     } else {
101         _style_swatch._style_obs = new StyleObserver(_style_swatch._tool_path + "/style", _style_swatch);
102     }
103     prefs->addObserver(*_style_swatch._style_obs);
106 StyleSwatch::StyleSwatch(SPCSSAttr *css, gchar const *main_tip)
107     :
108       _desktop(NULL),
109       _verb_t(NULL),
110       _css(NULL),
111       _tool_obs(NULL),
112       _style_obs(NULL),
113       _table(2, 6),
114       _sw_unit(NULL),
115       _tooltips ()
117     _label[SS_FILL].set_markup(_("Fill:"));
118     _label[SS_STROKE].set_markup(_("Stroke:"));
120     for (int i = SS_FILL; i <= SS_STROKE; i++) {
121         _label[i].set_alignment(0.0, 0.5);
122         _label[i].set_padding(0, 0);
124         _color_preview[i] = new Inkscape::UI::Widget::ColorPreview (0);
125     }
127     _opacity_value.set_alignment(0.0, 0.5);
128     _opacity_value.set_padding(0, 0);
130     _table.set_col_spacings (2);
131     _table.set_row_spacings (0);
133     _stroke.pack_start(_place[SS_STROKE]);
134     _stroke_width_place.add(_stroke_width);
135     _stroke.pack_start(_stroke_width_place, Gtk::PACK_SHRINK);
137     _table.attach(_label[SS_FILL], 0,1, 0,1, Gtk::FILL, Gtk::SHRINK);
138     _table.attach(_label[SS_STROKE], 0,1, 1,2, Gtk::FILL, Gtk::SHRINK);
140     _table.attach(_place[SS_FILL], 1,2, 0,1);
141     _table.attach(_stroke, 1,2, 1,2);
143     _opacity_place.add(_opacity_value);
144     _table.attach(_opacity_place, 2,3, 0,2, Gtk::SHRINK, Gtk::SHRINK);
146     _swatch.add(_table);
147     pack_start(_swatch, true, true, 0);
149     set_size_request (STYLE_SWATCH_WIDTH, -1);
151     sp_set_font_size_smaller (GTK_WIDGET(_opacity_value.gobj()));
152     sp_set_font_size_smaller (GTK_WIDGET(_stroke_width.gobj()));
153     for (int i = SS_FILL; i <= SS_STROKE; i++) {
154         sp_set_font_size_smaller (GTK_WIDGET(_value[i].gobj()));
155         sp_set_font_size_smaller (GTK_WIDGET(_place[i].gobj()));
156         sp_set_font_size_smaller (GTK_WIDGET(_label[i].gobj()));
157     }
159     setStyle (css);
161     _swatch.signal_button_press_event().connect(sigc::mem_fun(*this, &StyleSwatch::on_click));
163     _tooltips.set_tip(_swatch, main_tip);
166 void StyleSwatch::setClickVerb(sp_verb_t verb_t) {
167     _verb_t = verb_t;
170 void StyleSwatch::setDesktop(SPDesktop *desktop) {
171     _desktop = desktop;
174 bool
175 StyleSwatch::on_click(GdkEventButton */*event*/)
177     if (this->_desktop && this->_verb_t != SP_VERB_NONE) {
178         Inkscape::Verb *verb = Inkscape::Verb::get(this->_verb_t);
179         SPAction *action = verb->get_action((Inkscape::UI::View::View *) this->_desktop);
180         sp_action_perform (action, NULL);
181         return true;
182     }
183     return false;
186 StyleSwatch::~StyleSwatch()
188     if (_css)
189         sp_repr_css_attr_unref (_css);
191     for (int i = SS_FILL; i <= SS_STROKE; i++) {
192         delete _color_preview[i];
193     }
195     if (_style_obs) delete _style_obs;
196     if (_tool_obs) delete _tool_obs;
199 void
200 StyleSwatch::setWatchedTool(const char *path, bool synthesize)
202     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
203     
204     if (_tool_obs) {
205         delete _tool_obs;
206         _tool_obs = NULL;
207     }
209     if (path) {
210         _tool_path = path;
211         _tool_obs = new ToolObserver(_tool_path + "/usecurrent", *this);
212         prefs->addObserver(*_tool_obs);
213     } else {
214         _tool_path = "";
215     }
216     
217     // hack until there is a real synthesize events function for prefs,
218     // which shouldn't be hard to write once there is sufficient need for it
219     if (synthesize && _tool_obs) {
220         _tool_obs->notify(prefs->getEntry(_tool_path + "/usecurrent"));
221     }
225 void
226 StyleSwatch::setStyle(SPCSSAttr *css)
228     if (_css)
229         sp_repr_css_attr_unref (_css);
231     if (!css)
232         return;
234     _css = sp_repr_css_attr_new();
235     sp_repr_css_merge(_css, css);
237     gchar const *css_string = sp_repr_css_write_string (_css);
238     SPStyle *temp_spstyle = sp_style_new(SP_ACTIVE_DOCUMENT);
239     if (css_string)
240         sp_style_merge_from_style_string (temp_spstyle, css_string);
242     setStyle (temp_spstyle);
244     sp_style_unref (temp_spstyle);
247 void
248 StyleSwatch::setStyle(SPStyle *query)
250     _place[SS_FILL].remove();
251     _place[SS_STROKE].remove();
253     bool has_stroke = true;
255     for (int i = SS_FILL; i <= SS_STROKE; i++) {
256         Gtk::EventBox *place = &(_place[i]);
258         SPIPaint *paint;
259         if (i == SS_FILL) {
260             paint = &(query->fill);
261         } else {
262             paint = &(query->stroke);
263         }
265         if (paint->set && paint->isPaintserver()) {
266             SPPaintServer *server = (i == SS_FILL)? SP_STYLE_FILL_SERVER (query) : SP_STYLE_STROKE_SERVER (query);
268             if (SP_IS_LINEARGRADIENT (server)) {
269                 _value[i].set_markup(_("L Gradient"));
270                 place->add(_value[i]);
271                 _tooltips.set_tip(*place, (i == SS_FILL)? (_("Linear gradient fill")) : (_("Linear gradient stroke")));
272             } else if (SP_IS_RADIALGRADIENT (server)) {
273                 _value[i].set_markup(_("R Gradient"));
274                 place->add(_value[i]);
275                 _tooltips.set_tip(*place, (i == SS_FILL)? (_("Radial gradient fill")) : (_("Radial gradient stroke")));
276             } else if (SP_IS_PATTERN (server)) {
277                 _value[i].set_markup(_("Pattern"));
278                 place->add(_value[i]);
279                 _tooltips.set_tip(*place, (i == SS_FILL)? (_("Pattern fill")) : (_("Pattern stroke")));
280             }
282         } else if (paint->set && paint->isColor()) {
283             guint32 color = paint->value.color.toRGBA32( SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value) );
284             ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color);
285             _color_preview[i]->show_all();
286             place->add(*_color_preview[i]);
287             gchar *tip;
288             if (i == SS_FILL) {
289                 tip = g_strdup_printf (_("Fill: %06x/%.3g"), color >> 8, SP_RGBA32_A_F(color));
290             } else {
291                 tip = g_strdup_printf (_("Stroke: %06x/%.3g"), color >> 8, SP_RGBA32_A_F(color));
292             }
293             _tooltips.set_tip(*place, tip);
294             g_free (tip);
295         } else if (paint->set && paint->isNone()) {
296             _value[i].set_markup(_("<i>None</i>"));
297             place->add(_value[i]);
298             _tooltips.set_tip(*place, (i == SS_FILL)? (_("No fill")) : (_("No stroke")));
299             if (i == SS_STROKE) has_stroke = false;
300         } else if (!paint->set) {
301             _value[i].set_markup(_("<b>Unset</b>"));
302             place->add(_value[i]);
303             _tooltips.set_tip(*place, (i == SS_FILL)? (_("Unset fill")) : (_("Unset stroke")));
304             if (i == SS_STROKE) has_stroke = false;
305         }
306     }
308 // Now query stroke_width
309     if (has_stroke) {
310         double w;
311         if (_sw_unit) {
312             w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit);
313         } else {
314             w = query->stroke_width.computed;
315         }
317         {
318             gchar *str = g_strdup_printf(" %.3g", w);
319             _stroke_width.set_markup(str);
320             g_free (str);
321         }
322         {
323             gchar *str = g_strdup_printf(_("Stroke width: %.5g%s"),
324                                          w,
325                                          _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px");
326             _tooltips.set_tip(_stroke_width_place, str);
327             g_free (str);
328         }
329     } else {
330         _tooltips.unset_tip(_stroke_width_place);
331         _stroke_width.set_markup ("");
332     }
334     gdouble op = SP_SCALE24_TO_FLOAT(query->opacity.value);
335     if (op != 1) {
336         {
337             gchar *str;
338             if (op == 0)
339                 str = g_strdup_printf(_("O:%.3g"), op);
340             else
341                 str = g_strdup_printf(_("O:.%d"), (int) (op*10));
342             _opacity_value.set_markup (str);
343             g_free (str);
344         }
345         {
346             gchar *str = g_strdup_printf(_("Opacity: %.3g"), op);
347             _tooltips.set_tip(_opacity_place, str);
348             g_free (str);
349         }
350     } else {
351         _tooltips.unset_tip(_opacity_place);
352         _opacity_value.set_markup ("");
353     }
355     show_all();
358 } // namespace Widget
359 } // namespace UI
360 } // namespace Inkscape
362 /*
363   Local Variables:
364   mode:c++
365   c-file-style:"stroustrup"
366   c-file-offsets:((innamespace . 0)(inline-open . 0))
367   indent-tabs-mode:nil
368   fill-column:99
369   End:
370 */
371 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :