Code

492da2833ae8efa00083d7ff9d49132ccbedba41
[inkscape.git] / src / ui / widget / style-swatch.cpp
1 /**
2  * \brief Static style swatch (fill, stroke, opacity)
3  *
4  * Author:
5  *   buliabyak@gmail.com
6  *
7  * Copyright (C) 2005 author
8  *
9  * Released under GNU GPL.  Read the file 'COPYING' for more information.
10  */
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
16 #include "style-swatch.h"
18 #include "widgets/spw-utilities.h"
19 #include "ui/widget/color-preview.h"
21 #include "style.h"
22 #include "sp-linear-gradient-fns.h"
23 #include "sp-radial-gradient-fns.h"
24 #include "sp-pattern.h"
25 #include "xml/repr.h"
26 #include "xml/node-event-vector.h"
27 #include "widgets/widget-sizes.h"
28 #include "helper/units.h"
29 #include "inkscape.h"
31 enum {
32     SS_FILL,
33     SS_STROKE
34 };
36 static void style_swatch_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
37                                        gchar const *old_value, gchar const *new_value,
38                                        bool is_interactive, gpointer data)
39 {
40     Inkscape::UI::Widget::StyleSwatch *ss = (Inkscape::UI::Widget::StyleSwatch *) data;
42     if (!strcmp (name, "style")) { // FIXME: watching only for the style attr, no CSS attrs
43         SPCSSAttr *css = sp_repr_css_attr_inherited(repr, "style");
44         ss->setStyle (css);
45     }
46 }
49 static Inkscape::XML::NodeEventVector style_swatch_repr_events =
50 {
51     NULL, /* child_added */
52     NULL, /* child_removed */
53     style_swatch_attr_changed,
54     NULL, /* content_changed */
55     NULL  /* order_changed */
56 };
59 static void style_swatch_tool_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
60                                        gchar const *old_value, gchar const *new_value,
61                                        bool is_interactive, gpointer data)
62 {
63     Inkscape::UI::Widget::StyleSwatch *ss = (Inkscape::UI::Widget::StyleSwatch *) data;
65     if (!strcmp (name, "usecurrent")) { // FIXME: watching only for the style attr, no CSS attrs
66         if (!strcmp (new_value, "1")) {
67             ss->setWatched (inkscape_get_repr(INKSCAPE, "desktop"));
68         } else {
69             ss->setWatched (inkscape_get_repr(INKSCAPE, ss->_tool_path));
70         }
71         // UGLY HACK: we have to reconnect to the watched tool repr again, retrieving it from the stored
72         // tool_path, because the actual repr keeps shifting with each change, no idea why
73         ss->setWatchedTool(ss->_tool_path, false); 
74     }
75 }
77 static Inkscape::XML::NodeEventVector style_swatch_tool_repr_events =
78 {
79     NULL, /* child_added */
80     NULL, /* child_removed */
81     style_swatch_tool_attr_changed,
82     NULL, /* content_changed */
83     NULL  /* order_changed */
84 };
86 namespace Inkscape {
87 namespace UI {
88 namespace Widget {
90 StyleSwatch::StyleSwatch(SPCSSAttr *css)
91     : 
92       _tool_path(NULL),
93       _css (NULL),
95       _watched(NULL),
96       _watched_tool(NULL),
98       _table(2, 6),
100       _sw_unit(NULL),
102       _tooltips ()
104     _label[SS_FILL].set_markup(_("F:"));
105     _label[SS_STROKE].set_markup(_("S:"));
107     for (int i = SS_FILL; i <= SS_STROKE; i++) {
108         _label[i].set_alignment(0.0, 0.5);
109         _label[i].set_padding(0, 0);
111         _color_preview[i] = new Inkscape::UI::Widget::ColorPreview (0);
112     }
114     _opacity_value.set_alignment(0.0, 0.5);
115     _opacity_value.set_padding(0, 0);
117     _table.set_col_spacings (2);
118     _table.set_row_spacings (0);
120     _stroke.pack_start(_place[SS_STROKE]);
121     _stroke_width_place.add(_stroke_width);
122     _stroke.pack_start(_stroke_width_place, Gtk::PACK_SHRINK);
124     _table.attach(_label[SS_FILL], 0,1, 0,1, Gtk::SHRINK, Gtk::SHRINK);
125     _table.attach(_label[SS_STROKE], 0,1, 1,2, Gtk::SHRINK, Gtk::SHRINK);
127     _table.attach(_place[SS_FILL], 1,2, 0,1);
128     _table.attach(_stroke, 1,2, 1,2);
130     _opacity_place.add(_opacity_value);
131     _table.attach(_opacity_place, 2,3, 0,2, Gtk::SHRINK, Gtk::SHRINK);
133     pack_start(_table, true, true, 0);
135     set_size_request (STYLE_SWATCH_WIDTH, -1);
137     sp_set_font_size_smaller (GTK_WIDGET(_opacity_value.gobj()));
138     sp_set_font_size_smaller (GTK_WIDGET(_stroke_width.gobj()));
139     for (int i = SS_FILL; i <= SS_STROKE; i++) {
140         sp_set_font_size_smaller (GTK_WIDGET(_value[i].gobj()));
141         sp_set_font_size_smaller (GTK_WIDGET(_place[i].gobj()));
142         sp_set_font_size_smaller (GTK_WIDGET(_label[i].gobj()));
143     }
145     setStyle (css);
148 StyleSwatch::~StyleSwatch()
150     if (_css) 
151         sp_repr_css_attr_unref (_css);
153     for (int i = SS_FILL; i <= SS_STROKE; i++) {
154         delete _color_preview[i];
155     }
157     if (_watched) {
158         sp_repr_remove_listener_by_data(_watched, this);
159         Inkscape::GC::release(_watched);
160         _watched = NULL;
161     }
163     if (_watched_tool) {
164         std::cout << " =============remove\n";
165         sp_repr_remove_listener_by_data(_watched_tool, this);
166         Inkscape::GC::release(_watched_tool);
167         _watched_tool = NULL;
168         _tool_path = NULL;
169     }
172 void
173 StyleSwatch::setWatched(Inkscape::XML::Node *watched)
175     if (_watched) {
176         sp_repr_remove_listener_by_data(_watched, this);
177         Inkscape::GC::release(_watched);
178         _watched = NULL;
179     }
181     if (watched) {
182         _watched = watched;
183         Inkscape::GC::anchor(_watched);
184         sp_repr_add_listener(_watched, &style_swatch_repr_events, this);
185         sp_repr_synthesize_events(_watched, &style_swatch_repr_events, this);
186     }
189 void
190 StyleSwatch::setWatchedTool(const char *path, bool synthesize)
192     if (_watched_tool) {
193         sp_repr_remove_listener_by_data(_watched_tool, this);
194         Inkscape::GC::release(_watched_tool);
195         _watched_tool = NULL;
196         _tool_path = NULL;
197     }
199     if (path) {
200         _tool_path = (char *) path;
201         Inkscape::XML::Node *watched_tool = inkscape_get_repr(INKSCAPE, path);
202         if (watched_tool) {
203             _watched_tool = watched_tool;
204             Inkscape::GC::anchor(_watched_tool);
205             sp_repr_add_listener(_watched_tool, &style_swatch_tool_repr_events, this);
206             if (synthesize) {
207                 sp_repr_synthesize_events(_watched_tool, &style_swatch_tool_repr_events, this);
208             }
209         }
210     }
215 void
216 StyleSwatch::setStyle(SPCSSAttr *css)
218     if (_css) 
219         sp_repr_css_attr_unref (_css);
221     if (!css)
222         return;
224     _css = sp_repr_css_attr_new();
225     sp_repr_css_merge(_css, css);
227     gchar const *css_string = sp_repr_css_write_string (_css);
228     SPStyle *temp_spstyle = sp_style_new();
229     if (css_string)
230         sp_style_merge_from_style_string (temp_spstyle, css_string);
232     setStyle (temp_spstyle);
234     sp_style_unref (temp_spstyle);
237 void
238 StyleSwatch::setStyle(SPStyle *query)
240     _place[SS_FILL].remove();
241     _place[SS_STROKE].remove();
243     bool has_stroke = true;
245     for (int i = SS_FILL; i <= SS_STROKE; i++) {
246         Gtk::EventBox *place = &(_place[i]);
248         SPIPaint *paint;
249         if (i == SS_FILL) {
250             paint = &(query->fill);
251         } else {
252             paint = &(query->stroke);
253         }
255         if (paint->set && paint->type == SP_PAINT_TYPE_COLOR) {
256             guint32 color = sp_color_get_rgba32_falpha (&(paint->value.color), 
257                                                         SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value));
258             ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color);
259             _color_preview[i]->show_all();
260             place->add(*_color_preview[i]);
261             gchar *tip;
262             if (i == SS_FILL) {
263                 tip = g_strdup_printf ("Fill: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
264             } else {
265                 tip = g_strdup_printf ("Stroke: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
266             }
267             _tooltips.set_tip(*place, tip);
268             g_free (tip);
269         } else if (paint->set && paint->type == SP_PAINT_TYPE_PAINTSERVER) {
270             SPPaintServer *server = (i == SS_FILL)? SP_STYLE_FILL_SERVER (query) : SP_STYLE_STROKE_SERVER (query);
272             if (SP_IS_LINEARGRADIENT (server)) {
273                 _value[i].set_markup(_("L Gradient"));
274                 place->add(_value[i]);
275                 _tooltips.set_tip(*place, (i == SS_FILL)? (_("Linear gradient fill")) : (_("Linear gradient stroke")));
276             } else if (SP_IS_RADIALGRADIENT (server)) {
277                 _value[i].set_markup(_("R Gradient"));
278                 place->add(_value[i]);
279                 _tooltips.set_tip(*place, (i == SS_FILL)? (_("Radial gradient fill")) : (_("Radial gradient stroke")));
280             } else if (SP_IS_PATTERN (server)) {
281                 _value[i].set_markup(_("Pattern"));
282                 place->add(_value[i]);
283                 _tooltips.set_tip(*place, (i == SS_FILL)? (_("Pattern fill")) : (_("Pattern stroke")));
284             }
286         } else if (paint->set && paint->type == SP_PAINT_TYPE_NONE) {
287             _value[i].set_markup(_("None"));
288             place->add(_value[i]);
289             _tooltips.set_tip(*place, (i == SS_FILL)? (_("No fill")) : (_("No stroke")));
290             if (i == SS_STROKE) has_stroke = false;
291         } else if (!paint->set) {
292             _value[i].set_markup(_("Unset"));
293             place->add(_value[i]);
294             _tooltips.set_tip(*place, (i == SS_FILL)? (_("Unset fill")) : (_("Unset stroke")));
295             if (i == SS_STROKE) has_stroke = false;
296         }
297     }
299 // Now query stroke_width
300     if (has_stroke) {
301         double w;
302         if (_sw_unit) {
303             w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit);
304         } else {
305             w = query->stroke_width.computed;
306         }
308         {
309             gchar *str = g_strdup_printf(" %.3g", w);
310             _stroke_width.set_markup(str);
311             g_free (str);
312         }
313         {
314             gchar *str = g_strdup_printf(_("Stroke width: %.5g%s"), 
315                                          w, 
316                                          _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px");
317             _tooltips.set_tip(_stroke_width_place, str);
318             g_free (str);
319         }
320     } else {
321         _tooltips.unset_tip(_stroke_width_place);
322         _stroke_width.set_markup ("");
323     }
325     gdouble op = SP_SCALE24_TO_FLOAT(query->opacity.value);
326     if (op != 1) {
327         {
328             gchar *str;
329             if (op == 0)
330                 str = g_strdup_printf(_("0:%.3g"), op);
331             else 
332                 str = g_strdup_printf(_("0:.%d"), (int) (op*10));
333             _opacity_value.set_markup (str);
334             g_free (str);
335         }
336         {
337             gchar *str = g_strdup_printf(_("Opacity: %.3g"), op);
338             _tooltips.set_tip(_opacity_place, str);
339             g_free (str);
340         }
341     } else {
342         _tooltips.unset_tip(_opacity_place);
343         _opacity_value.set_markup ("");
344     }
346     show_all();
349 } // namespace Widget
350 } // namespace UI
351 } // namespace Inkscape
353 /* 
354   Local Variables:
355   mode:c++
356   c-file-style:"stroustrup"
357   c-file-offsets:((innamespace . 0)(inline-open . 0))
358   indent-tabs-mode:nil
359   fill-column:99
360   End:
361 */
362 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :