Code

023f91c55bef63350f2436a40dc35a1fc2a337f3
[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     sp_style_merge_from_style_string (temp_spstyle, css_string);
231     setStyle (temp_spstyle);
233     sp_style_unref (temp_spstyle);
236 void
237 StyleSwatch::setStyle(SPStyle *query)
239     _place[SS_FILL].remove();
240     _place[SS_STROKE].remove();
242     bool has_stroke = true;
244     for (int i = SS_FILL; i <= SS_STROKE; i++) {
245         Gtk::EventBox *place = &(_place[i]);
247         SPIPaint *paint;
248         if (i == SS_FILL) {
249             paint = &(query->fill);
250         } else {
251             paint = &(query->stroke);
252         }
254         if (paint->set && paint->type == SP_PAINT_TYPE_COLOR) {
255             guint32 color = sp_color_get_rgba32_falpha (&(paint->value.color), 
256                                                         SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value));
257             ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color);
258             _color_preview[i]->show_all();
259             place->add(*_color_preview[i]);
260             gchar *tip;
261             if (i == SS_FILL) {
262                 tip = g_strdup_printf ("Fill: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
263             } else {
264                 tip = g_strdup_printf ("Stroke: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
265             }
266             _tooltips.set_tip(*place, tip);
267             g_free (tip);
268         } else if (paint->set && paint->type == SP_PAINT_TYPE_PAINTSERVER) {
269             SPPaintServer *server = (i == SS_FILL)? SP_STYLE_FILL_SERVER (query) : SP_STYLE_STROKE_SERVER (query);
271             if (SP_IS_LINEARGRADIENT (server)) {
272                 _value[i].set_markup(_("L Gradient"));
273                 place->add(_value[i]);
274                 _tooltips.set_tip(*place, (i == SS_FILL)? (_("Linear gradient fill")) : (_("Linear gradient stroke")));
275             } else if (SP_IS_RADIALGRADIENT (server)) {
276                 _value[i].set_markup(_("R Gradient"));
277                 place->add(_value[i]);
278                 _tooltips.set_tip(*place, (i == SS_FILL)? (_("Radial gradient fill")) : (_("Radial gradient stroke")));
279             } else if (SP_IS_PATTERN (server)) {
280                 _value[i].set_markup(_("Pattern"));
281                 place->add(_value[i]);
282                 _tooltips.set_tip(*place, (i == SS_FILL)? (_("Pattern fill")) : (_("Pattern stroke")));
283             }
285         } else if (paint->set && paint->type == SP_PAINT_TYPE_NONE) {
286             _value[i].set_markup(_("None"));
287             place->add(_value[i]);
288             _tooltips.set_tip(*place, (i == SS_FILL)? (_("No fill")) : (_("No stroke")));
289             if (i == SS_STROKE) has_stroke = false;
290         } else if (!paint->set) {
291             _value[i].set_markup(_("Unset"));
292             place->add(_value[i]);
293             _tooltips.set_tip(*place, (i == SS_FILL)? (_("Unset fill")) : (_("Unset stroke")));
294             if (i == SS_STROKE) has_stroke = false;
295         }
296     }
298 // Now query stroke_width
299     if (has_stroke) {
300         double w;
301         if (_sw_unit) {
302             w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit);
303         } else {
304             w = query->stroke_width.computed;
305         }
307         {
308             gchar *str = g_strdup_printf(" %.3g", w);
309             _stroke_width.set_markup(str);
310             g_free (str);
311         }
312         {
313             gchar *str = g_strdup_printf(_("Stroke width: %.5g%s"), 
314                                          w, 
315                                          _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px");
316             _tooltips.set_tip(_stroke_width_place, str);
317             g_free (str);
318         }
319     } else {
320         _tooltips.unset_tip(_stroke_width_place);
321         _stroke_width.set_markup ("");
322     }
324     gdouble op = SP_SCALE24_TO_FLOAT(query->opacity.value);
325     if (op != 1) {
326         {
327             gchar *str;
328             if (op == 0)
329                 str = g_strdup_printf(_("0:%.3g"), op);
330             else 
331                 str = g_strdup_printf(_("0:.%d"), (int) (op*10));
332             _opacity_value.set_markup (str);
333             g_free (str);
334         }
335         {
336             gchar *str = g_strdup_printf(_("Opacity: %.3g"), op);
337             _tooltips.set_tip(_opacity_place, str);
338             g_free (str);
339         }
340     } else {
341         _tooltips.unset_tip(_opacity_place);
342         _opacity_value.set_markup ("");
343     }
345     show_all();
348 } // namespace Widget
349 } // namespace UI
350 } // namespace Inkscape
352 /* 
353   Local Variables:
354   mode:c++
355   c-file-style:"stroustrup"
356   c-file-offsets:((innamespace . 0)(inline-open . 0))
357   indent-tabs-mode:nil
358   fill-column:99
359   End:
360 */
361 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :