Code

Refactoring SPColor to C++ and removing legacy CMYK implementation
[inkscape.git] / src / widgets / sp-color-selector.cpp
1 /*
2  *   bulia byak <buliabyak@users.sf.net>
3 */ 
5 #ifdef HAVE_CONFIG_H
6 # include "config.h"
7 #endif
8 #include <math.h>
9 #include <gtk/gtksignal.h>
10 #include <glibmm/i18n.h>
11 #include "sp-color-selector.h"
13 enum {
14         GRABBED,
15         DRAGGED,
16         RELEASED,
17         CHANGED,
18         LAST_SIGNAL
19 };
21 #define noDUMP_CHANGE_INFO
22 #define FOO_NAME(x) g_type_name( G_TYPE_FROM_INSTANCE(x) )
24 static void sp_color_selector_class_init (SPColorSelectorClass *klass);
25 static void sp_color_selector_init (SPColorSelector *csel);
26 static void sp_color_selector_destroy (GtkObject *object);
28 static void sp_color_selector_show_all (GtkWidget *widget);
29 static void sp_color_selector_hide_all (GtkWidget *widget);
31 static GtkVBoxClass *parent_class;
32 static guint csel_signals[LAST_SIGNAL] = {0};
34 GType
35 sp_color_selector_get_type (void)
36 {
37         static GType type = 0;
38         if (!type) {
39                 static const GTypeInfo info = {
40                         sizeof (SPColorSelectorClass),
41                         NULL, /* base_init */
42                         NULL, /* base_finalize */
43                         (GClassInitFunc) sp_color_selector_class_init,
44                         NULL, /* class_finalize */
45                         NULL, /* class_data */
46                         sizeof (SPColorSelector),
47                         0,        /* n_preallocs */
48                         (GInstanceInitFunc) sp_color_selector_init,
49                         NULL
50                 };
52                 type = g_type_register_static (GTK_TYPE_VBOX,
53                                                                            "SPColorSelector",
54                                                                            &info,
55                                                                            static_cast< GTypeFlags > (0) );
56         }
57         return type;
58 }
60 static void
61 sp_color_selector_class_init (SPColorSelectorClass *klass)
62 {
63         static const gchar* nameset[] = {N_("Unnamed"), 0};
64         GtkObjectClass *object_class;
65         GtkWidgetClass *widget_class;
67         object_class = (GtkObjectClass *) klass;
68         widget_class = (GtkWidgetClass *) klass;
70         parent_class = (GtkVBoxClass*)gtk_type_class (GTK_TYPE_VBOX);
72         csel_signals[GRABBED] = gtk_signal_new ("grabbed",
73                                                  (GtkSignalRunType)(GTK_RUN_FIRST | GTK_RUN_NO_RECURSE),
74                                                  GTK_CLASS_TYPE(object_class),
75                                                  GTK_SIGNAL_OFFSET (SPColorSelectorClass, grabbed),
76                                                  gtk_marshal_NONE__NONE,
77                                                  GTK_TYPE_NONE, 0);
78         csel_signals[DRAGGED] = gtk_signal_new ("dragged",
79                                                  (GtkSignalRunType)(GTK_RUN_FIRST | GTK_RUN_NO_RECURSE),
80                                                  GTK_CLASS_TYPE(object_class),
81                                                  GTK_SIGNAL_OFFSET (SPColorSelectorClass, dragged),
82                                                  gtk_marshal_NONE__NONE,
83                                                  GTK_TYPE_NONE, 0);
84         csel_signals[RELEASED] = gtk_signal_new ("released",
85                                                  (GtkSignalRunType)(GTK_RUN_FIRST | GTK_RUN_NO_RECURSE),
86                                                  GTK_CLASS_TYPE(object_class),
87                                                  GTK_SIGNAL_OFFSET (SPColorSelectorClass, released),
88                                                  gtk_marshal_NONE__NONE,
89                                                  GTK_TYPE_NONE, 0);
90         csel_signals[CHANGED] = gtk_signal_new ("changed",
91                                                  (GtkSignalRunType)(GTK_RUN_FIRST | GTK_RUN_NO_RECURSE),
92                                                  GTK_CLASS_TYPE(object_class),
93                                                  GTK_SIGNAL_OFFSET (SPColorSelectorClass, changed),
94                                                  gtk_marshal_NONE__NONE,
95                                                  GTK_TYPE_NONE, 0);
97         klass->name = nameset;
98         klass->submode_count = 1;
100         object_class->destroy = sp_color_selector_destroy;
102         widget_class->show_all = sp_color_selector_show_all;
103         widget_class->hide_all = sp_color_selector_hide_all;
107 void sp_color_selector_init (SPColorSelector *csel)
109     if ( csel->base )
110     {
111         csel->base->init();
112     }
113 /*   gtk_signal_connect (GTK_OBJECT (csel->rgbae), "changed", GTK_SIGNAL_FUNC (sp_color_selector_rgba_entry_changed), csel); */
116 static void
117 sp_color_selector_destroy (GtkObject *object)
119         SPColorSelector *csel;
121         csel = SP_COLOR_SELECTOR (object);
122     if ( csel->base )
123     {
124         delete csel->base;
125         csel->base = 0;
126     }
128         if (((GtkObjectClass *) (parent_class))->destroy)
129                 (* ((GtkObjectClass *) (parent_class))->destroy) (object);
132 static void
133 sp_color_selector_show_all (GtkWidget *widget)
135         gtk_widget_show (widget);
138 static void
139 sp_color_selector_hide_all (GtkWidget *widget)
141         gtk_widget_hide (widget);
144 GtkWidget *
145 sp_color_selector_new( GType selector_type )
147         SPColorSelector *csel;
148         g_return_val_if_fail (g_type_is_a (selector_type, SP_TYPE_COLOR_SELECTOR), NULL);
150         csel = SP_COLOR_SELECTOR (g_object_new (selector_type, NULL));
152         return GTK_WIDGET (csel);
155 double ColorSelector::_epsilon = 1e-4;
157 void ColorSelector::setSubmode( guint submode )
159     (void)submode;
162 guint ColorSelector::getSubmode() const
164     guint mode = 0;
165     return mode;
168 ColorSelector::ColorSelector( SPColorSelector* csel )
169     : _csel(csel),
170       _color( 0 ),
171       _alpha(1.0),
172       _held(FALSE),
173       virgin(true)
177 ColorSelector::~ColorSelector()
181 void ColorSelector::init()
183     _csel->base = new ColorSelector( _csel );
186 void ColorSelector::setColor( const SPColor& color )
188     setColorAlpha( color, _alpha );
191 SPColor ColorSelector::getColor() const
193     return _color;
196 void ColorSelector::setAlpha( gfloat alpha )
198     g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
199     setColorAlpha( _color, alpha );
202 gfloat ColorSelector::getAlpha() const
204     return _alpha;
207 /**
208 Called from the outside to set the color; optionally emits signal (only when called from
209 downstream, e.g. the RGBA value field, but not from the rest of the program)
210 */
211 void ColorSelector::setColorAlpha( const SPColor& color, gfloat alpha, bool emit )
213 #ifdef DUMP_CHANGE_INFO
214     g_message("ColorSelector::setColorAlpha( this=%p, %f, %f, %f,   %f,   %s)", this, color.v.c[0], color.v.c[1], color.v.c[2], alpha, (emit?"YES":"no"));
215 #endif
216     g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
218 #ifdef DUMP_CHANGE_INFO
219     g_message("---- ColorSelector::setColorAlpha    virgin:%s   !close:%s    alpha is:%s",
220               (virgin?"YES":"no"),
221               (!color.isClose( _color, _epsilon )?"YES":"no"),
222                   ((fabs ((_alpha) - (alpha)) >= _epsilon )?"YES":"no")
223               );
224 #endif
226     if ( virgin || !color.isClose( _color, _epsilon ) ||
227          (fabs ((_alpha) - (alpha)) >= _epsilon )) {
229         virgin = false;
231         _color = color;
232         _alpha = alpha;
233         _colorChanged( color, alpha );
235         if (emit)
236                 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[CHANGED]);
237 #ifdef DUMP_CHANGE_INFO
238     } else {
239         g_message("++++ ColorSelector::setColorAlpha   color:%08x  ==>  _color:%08X   isClose", color.toRGBA32(alpha), _color.toRGBA32(_alpha),
240                   (color.isClose( _color, _epsilon )?"YES":"no"));
241 #endif
242     }
245 void ColorSelector::_grabbed()
247     _held = TRUE;
248 #ifdef DUMP_CHANGE_INFO
249     g_message ("%s:%d: About to signal %s in %s", __FILE__, __LINE__,
250                "GRABBED",
251                FOO_NAME(_csel));
252 #endif
253     gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[GRABBED]);
256 void ColorSelector::_released()
258     _held = false;
259 #ifdef DUMP_CHANGE_INFO
260     g_message ("%s:%d: About to signal %s in %s", __FILE__, __LINE__,
261                "RELEASED",
262                FOO_NAME(_csel));
263 #endif
264     gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[RELEASED]);
265     gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[CHANGED]);
268 // Called from subclasses to update color and broadcast if needed
269 void ColorSelector::_updateInternals( const SPColor& color, gfloat alpha, gboolean held )
271     g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
272     gboolean colorDifferent = ( !color.isClose( _color, _epsilon )
273                                 || ( fabs((_alpha) - (alpha)) >= _epsilon ) );
275     gboolean grabbed = held && !_held;
276     gboolean released = !held && _held;
278     // Store these before emmiting any signals
279     _held = held;
280     if ( colorDifferent )
281     {
282         _color = color;
283         _alpha = alpha;
284     }
286     if ( grabbed )
287     {
288 #ifdef DUMP_CHANGE_INFO
289         g_message ("%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
290                    "GRABBED",
291                    color.toRGBA32( alpha ), FOO_NAME(_csel));
292 #endif
293         gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[GRABBED]);
294     }
295     else if ( released )
296     {
297 #ifdef DUMP_CHANGE_INFO
298         g_message ("%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
299                    "RELEASED",
300                    color.toRGBA32( alpha ), FOO_NAME(_csel));
301 #endif
302         gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[RELEASED]);
303     }
305     if ( colorDifferent || released )
306     {
307 #ifdef DUMP_CHANGE_INFO
308         g_message ("%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
309                    (_held ? "CHANGED" : "DRAGGED" ),
310                    color.toRGBA32( alpha ), FOO_NAME(_csel));
311 #endif
312         gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[_held ? CHANGED : DRAGGED]);
313     }
316 void ColorSelector::_colorChanged( const SPColor& color, gfloat alpha )
318     (void)color;
319     (void)alpha;
322 void ColorSelector::getColorAlpha( SPColor& color, gfloat* alpha ) const
324     gint i = 0;
326     color = _color;
327     if ( alpha )
328     {
329         *alpha = _alpha;
330     }
332     // Try to catch uninitialized value usage
333     if ( color.v.c[0] )
334     {
335         i++;
336     }
337     if ( color.v.c[1] )
338     {
339         i++;
340     }
341     if ( color.v.c[2] )
342     {
343         i++;
344     }
345     if ( color.v.c[3] )
346     {
347         i++;
348     }
349     if ( alpha && *alpha )
350     {
351         i++;
352     }