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 /**
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 )
212 {
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 }
243 }
245 void ColorSelector::_grabbed()
246 {
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]);
254 }
256 void ColorSelector::_released()
257 {
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]);
266 }
268 // Called from subclasses to update color and broadcast if needed
269 void ColorSelector::_updateInternals( const SPColor& color, gfloat alpha, gboolean held )
270 {
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 }
314 }
316 void ColorSelector::_colorChanged( const SPColor& color, gfloat alpha )
317 {
318 (void)color;
319 (void)alpha;
320 }
322 void ColorSelector::getColorAlpha( SPColor& color, gfloat* alpha ) const
323 {
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 }
353 }