05299624791ebedbe29bab9618217b0455e1d685
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;
105 }
107 void sp_color_selector_init (SPColorSelector *csel)
108 {
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); */
114 }
116 static void
117 sp_color_selector_destroy (GtkObject *object)
118 {
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);
130 }
132 static void
133 sp_color_selector_show_all (GtkWidget *widget)
134 {
135 gtk_widget_show (widget);
136 }
138 static void
139 sp_color_selector_hide_all (GtkWidget *widget)
140 {
141 gtk_widget_hide (widget);
142 }
144 GtkWidget *
145 sp_color_selector_new( GType selector_type )
146 {
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);
153 }
155 double ColorSelector::_epsilon = 1e-4;
157 void ColorSelector::setSubmode( guint submode )
158 {
159 (void)submode;
160 }
162 guint ColorSelector::getSubmode() const
163 {
164 guint mode = 0;
165 return mode;
166 }
168 ColorSelector::ColorSelector( SPColorSelector* csel )
169 : _csel(csel),
170 _color( 0 ),
171 _alpha(1.0),
172 _held(FALSE),
173 virgin(true)
174 {
175 }
177 ColorSelector::~ColorSelector()
178 {
179 }
181 void ColorSelector::init()
182 {
183 _csel->base = new ColorSelector( _csel );
184 }
186 void ColorSelector::setColor( const SPColor& color )
187 {
188 setColorAlpha( color, _alpha );
189 }
191 SPColor ColorSelector::getColor() const
192 {
193 return _color;
194 }
196 void ColorSelector::setAlpha( gfloat alpha )
197 {
198 g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
199 setColorAlpha( _color, alpha );
200 }
202 gfloat ColorSelector::getAlpha() const
203 {
204 return _alpha;
205 }
207 #include "svg/svg-icc-color.h"
209 /**
210 Called from the outside to set the color; optionally emits signal (only when called from
211 downstream, e.g. the RGBA value field, but not from the rest of the program)
212 */
213 void ColorSelector::setColorAlpha( const SPColor& color, gfloat alpha, bool emit )
214 {
215 #ifdef DUMP_CHANGE_INFO
216 g_message("ColorSelector::setColorAlpha( this=%p, %f, %f, %f, %s, %f, %s) in %s", this, color.v.c[0], color.v.c[1], color.v.c[2], (color.icc?color.icc->colorProfile.c_str():"<null>"), alpha, (emit?"YES":"no"), FOO_NAME(_csel));
217 #endif
218 g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
220 #ifdef DUMP_CHANGE_INFO
221 g_message("---- ColorSelector::setColorAlpha virgin:%s !close:%s alpha is:%s in %s",
222 (virgin?"YES":"no"),
223 (!color.isClose( _color, _epsilon )?"YES":"no"),
224 ((fabs ((_alpha) - (alpha)) >= _epsilon )?"YES":"no"),
225 FOO_NAME(_csel)
226 );
227 #endif
229 if ( virgin || !color.isClose( _color, _epsilon ) ||
230 (fabs ((_alpha) - (alpha)) >= _epsilon )) {
232 virgin = false;
234 _color = color;
235 _alpha = alpha;
236 _colorChanged( color, alpha );
238 if (emit)
239 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[CHANGED]);
240 #ifdef DUMP_CHANGE_INFO
241 } else {
242 g_message("++++ ColorSelector::setColorAlpha color:%08x ==> _color:%08X isClose:%s in %s", color.toRGBA32(alpha), _color.toRGBA32(_alpha),
243 (color.isClose( _color, _epsilon )?"YES":"no"), FOO_NAME(_csel));
244 #endif
245 }
246 }
248 void ColorSelector::_grabbed()
249 {
250 _held = TRUE;
251 #ifdef DUMP_CHANGE_INFO
252 g_message ("%s:%d: About to signal %s in %s", __FILE__, __LINE__,
253 "GRABBED",
254 FOO_NAME(_csel));
255 #endif
256 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[GRABBED]);
257 }
259 void ColorSelector::_released()
260 {
261 _held = false;
262 #ifdef DUMP_CHANGE_INFO
263 g_message ("%s:%d: About to signal %s in %s", __FILE__, __LINE__,
264 "RELEASED",
265 FOO_NAME(_csel));
266 #endif
267 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[RELEASED]);
268 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[CHANGED]);
269 }
271 // Called from subclasses to update color and broadcast if needed
272 void ColorSelector::_updateInternals( const SPColor& color, gfloat alpha, gboolean held )
273 {
274 g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
275 gboolean colorDifferent = ( !color.isClose( _color, _epsilon )
276 || ( fabs((_alpha) - (alpha)) >= _epsilon ) );
278 gboolean grabbed = held && !_held;
279 gboolean released = !held && _held;
281 // Store these before emmiting any signals
282 _held = held;
283 if ( colorDifferent )
284 {
285 _color = color;
286 _alpha = alpha;
287 }
289 if ( grabbed )
290 {
291 #ifdef DUMP_CHANGE_INFO
292 g_message ("%s:%d: About to signal %s to color %08x::%s in %s", __FILE__, __LINE__,
293 "GRABBED",
294 color.toRGBA32( alpha ), (color.icc?color.icc->colorProfile.c_str():"<null>"), FOO_NAME(_csel));
295 #endif
296 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[GRABBED]);
297 }
298 else if ( released )
299 {
300 #ifdef DUMP_CHANGE_INFO
301 g_message ("%s:%d: About to signal %s to color %08x::%s in %s", __FILE__, __LINE__,
302 "RELEASED",
303 color.toRGBA32( alpha ), (color.icc?color.icc->colorProfile.c_str():"<null>"), FOO_NAME(_csel));
304 #endif
305 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[RELEASED]);
306 }
308 if ( colorDifferent || released )
309 {
310 #ifdef DUMP_CHANGE_INFO
311 g_message ("%s:%d: About to signal %s to color %08x::%s in %s", __FILE__, __LINE__,
312 (_held ? "CHANGED" : "DRAGGED" ),
313 color.toRGBA32( alpha ), (color.icc?color.icc->colorProfile.c_str():"<null>"), FOO_NAME(_csel));
314 #endif
315 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[_held ? CHANGED : DRAGGED]);
316 }
317 }
319 void ColorSelector::_colorChanged( const SPColor& color, gfloat alpha )
320 {
321 (void)color;
322 (void)alpha;
323 }
325 void ColorSelector::getColorAlpha( SPColor& color, gfloat* alpha ) const
326 {
327 gint i = 0;
329 color = _color;
330 if ( alpha )
331 {
332 *alpha = _alpha;
333 }
335 // Try to catch uninitialized value usage
336 if ( color.v.c[0] )
337 {
338 i++;
339 }
340 if ( color.v.c[1] )
341 {
342 i++;
343 }
344 if ( color.v.c[2] )
345 {
346 i++;
347 }
348 if ( color.v.c[3] )
349 {
350 i++;
351 }
352 if ( alpha && *alpha )
353 {
354 i++;
355 }
356 }