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, SPColorSpaceType colorspace)
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 }
161 guint ColorSelector::getSubmode() const
162 {
163 guint mode = 0;
164 return mode;
165 }
167 SPColorSpaceType ColorSelector::getColorspace() const
168 {
169 SPColorSpaceType type = SP_COLORSPACE_TYPE_UNKNOWN;
171 return type;
172 }
174 gboolean ColorSelector::setColorspace( SPColorSpaceType colorspace )
175 {
176 return false;
177 }
179 ColorSelector::ColorSelector( SPColorSelector* csel )
180 : _csel(csel),
181 _alpha(1.0),
182 _held(FALSE)
183 {
184 sp_color_set_rgb_rgba32( &_color, 0 );
186 virgin = true;
187 }
189 ColorSelector::~ColorSelector()
190 {
191 }
193 void ColorSelector::init()
194 {
195 _csel->base = new ColorSelector( _csel );
196 }
198 void ColorSelector::setColor( const SPColor& color )
199 {
200 setColorAlpha( color, _alpha );
201 }
203 SPColor ColorSelector::getColor() const
204 {
205 return _color;
206 }
208 void ColorSelector::setAlpha( gfloat alpha )
209 {
210 g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
211 setColorAlpha( _color, alpha );
212 }
214 gfloat ColorSelector::getAlpha() const
215 {
216 return _alpha;
217 }
219 /**
220 Called from the outside to set the color; optionally emits signal (only when called from
221 downstream, e.g. the RGBA value field, but not from the rest of the program)
222 */
223 void ColorSelector::setColorAlpha( const SPColor& color, gfloat alpha, bool emit )
224 {
225 g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
227 if ( virgin || !sp_color_is_close( &color, &_color, _epsilon ) ||
228 (fabs ((_alpha) - (alpha)) >= _epsilon )) {
230 virgin = false;
232 sp_color_copy (&_color, &color);
233 _alpha = alpha;
234 _colorChanged( color, alpha );
236 if (emit)
237 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[CHANGED]);
238 }
239 }
241 void ColorSelector::_grabbed()
242 {
243 _held = TRUE;
244 #ifdef DUMP_CHANGE_INFO
245 g_message ("%s:%d: About to signal %s in %s", __FILE__, __LINE__,
246 "GRABBED",
247 FOO_NAME(_csel));
248 #endif
249 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[GRABBED]);
250 }
252 void ColorSelector::_released()
253 {
254 _held = false;
255 #ifdef DUMP_CHANGE_INFO
256 g_message ("%s:%d: About to signal %s in %s", __FILE__, __LINE__,
257 "RELEASED",
258 FOO_NAME(_csel));
259 #endif
260 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[RELEASED]);
261 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[CHANGED]);
262 }
264 // Called from subclasses to update color and broadcast if needed
265 void ColorSelector::_updateInternals( const SPColor& color, gfloat alpha, gboolean held )
266 {
267 g_return_if_fail( ( 0.0 <= alpha ) && ( alpha <= 1.0 ) );
268 gboolean colorDifferent = ( !sp_color_is_close( &color, &_color, _epsilon )
269 || ( fabs((_alpha) - (alpha)) >= _epsilon ) );
271 gboolean grabbed = held && !_held;
272 gboolean released = !held && _held;
274 // Store these before emmiting any signals
275 _held = held;
276 if ( colorDifferent )
277 {
278 sp_color_copy (&_color, &color);
279 _alpha = alpha;
280 }
282 if ( grabbed )
283 {
284 #ifdef DUMP_CHANGE_INFO
285 g_message ("%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
286 "GRABBED",
287 sp_color_get_rgba32_falpha(&color,alpha), FOO_NAME(_csel));
288 #endif
289 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[GRABBED]);
290 }
291 else if ( released )
292 {
293 #ifdef DUMP_CHANGE_INFO
294 g_message ("%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
295 "RELEASED",
296 sp_color_get_rgba32_falpha(&color,alpha), FOO_NAME(_csel));
297 #endif
298 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[RELEASED]);
299 }
301 if ( colorDifferent || released )
302 {
303 #ifdef DUMP_CHANGE_INFO
304 g_message ("%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
305 (_held ? "CHANGED" : "DRAGGED" ),
306 sp_color_get_rgba32_falpha(&color,alpha), FOO_NAME(_csel));
307 #endif
308 gtk_signal_emit (GTK_OBJECT (_csel), csel_signals[_held ? CHANGED : DRAGGED]);
309 }
310 }
312 void ColorSelector::_colorChanged( const SPColor& color, gfloat alpha )
313 {
314 }
316 void ColorSelector::getColorAlpha( SPColor& color, gfloat* alpha ) const
317 {
318 gint i = 0;
320 sp_color_copy (&color, &_color);
321 if ( alpha )
322 {
323 *alpha = _alpha;
324 }
326 // Try to catch uninitialized value usage
327 if ( color.colorspace )
328 {
329 i++;
330 }
331 if ( color.v.c[0] )
332 {
333 i++;
334 }
335 if ( color.v.c[1] )
336 {
337 i++;
338 }
339 if ( color.v.c[2] )
340 {
341 i++;
342 }
343 if ( color.v.c[3] )
344 {
345 i++;
346 }
347 if ( alpha && *alpha )
348 {
349 i++;
350 }
351 }