]> Pileus Git - ~andy/gtk/blob - gtk/gtkgamma.c
977aabe67feab49613a2dc2f4f07f86e6e73669a
[~andy/gtk] / gtk / gtkgamma.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1997 David Mosberger
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <string.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21
22 #include "gtkgamma.h"
23 #include "gtkcurve.h"
24 #include "gtkdialog.h"
25 #include "gtkdrawingarea.h"
26 #include "gtkentry.h"
27 #include "gtkhbox.h"
28 #include "gtklabel.h"
29 #include "gtkmain.h"
30 #include "gtkpixmap.h"
31 #include "gtkradiobutton.h"
32 #include "gtksignal.h"
33 #include "gtktable.h"
34 #include "gtkvbox.h"
35 #include "gtkwindow.h"
36
37 static GtkVBoxClass *parent_class = NULL;
38
39
40 /* forward declarations: */
41 static void gtk_gamma_curve_class_init (GtkGammaCurveClass *class);
42 static void gtk_gamma_curve_init (GtkGammaCurve *curve);
43 static void gtk_gamma_curve_destroy (GtkObject *object);
44
45 enum
46   {
47     LINEAR = 0,
48     SPLINE,
49     FREE,
50     GAMMA,
51     RESET,
52     NUM_XPMS
53   };
54
55 static char *xpm[][27] =
56   {
57     /* spline: */
58     {
59       /* width height ncolors chars_per_pixel */
60       "16 16 4 1",
61       /* colors */
62       ". c None",
63       "B c #000000",
64       "+ c #BC2D2D",
65       "r c #FF0000",
66       /* pixels */
67       "..............BB",
68       ".........rrrrrrB",
69       ".......rr.......",
70       ".....B+.........",
71       "....BBB.........",
72       "....+B..........",
73       "....r...........",
74       "...r............",
75       "...r............",
76       "..r.............",
77       "..r.............",
78       ".r..............",
79       ".r..............",
80       ".r..............",
81       "B+..............",
82       "BB.............."
83     },
84     /* linear: */
85     {
86       /* width height ncolors chars_per_pixel */
87       "16 16 5 1",
88       /* colors */
89       ". c None", /* transparent */
90       "B c #000000",
91       "' c #7F7F7F",
92       "+ c #824141",
93       "r c #FF0000",
94       /* pixels */
95       "..............BB",
96       "..............+B",
97       "..............r.",
98       ".............r..",
99       ".............r..",
100       "....'B'.....r...",
101       "....BBB.....r...",
102       "....+B+....r....",
103       "....r.r....r....",
104       "...r...r..r.....",
105       "...r...r..r.....",
106       "..r.....rB+.....",
107       "..r.....BBB.....",
108       ".r......'B'.....",
109       "B+..............",
110       "BB.............."
111     },
112     /* free: */
113     {
114       /* width height ncolors chars_per_pixel */
115       "16 16 2 1",
116       /* colors */
117       ". c None",
118       "r c #FF0000",
119       /* pixels */
120       "................",
121       "................",
122       "......r.........",
123       "......r.........",
124       ".......r........",
125       ".......r........",
126       ".......r........",
127       "........r.......",
128       "........r.......",
129       "........r.......",
130       ".....r...r.rrrrr",
131       "....r....r......",
132       "...r.....r......",
133       "..r.......r.....",
134       ".r........r.....",
135       "r..............."
136     },
137     /* gamma: */
138     {
139       /* width height ncolors chars_per_pixel */
140       "16 16 10 1",
141       /* colors */
142       ". c None",
143       "B c #000000",
144       "& c #171717",
145       "# c #2F2F2F",
146       "X c #464646",
147       "= c #5E5E5E",
148       "/ c #757575",
149       "+ c #8C8C8C",
150       "- c #A4A4A4",
151       "` c #BBBBBB",
152       /* pixels */
153       "................",
154       "................",
155       "................",
156       "....B=..+B+.....",
157       "....X&`./&-.....",
158       "...../+.XX......",
159       "......B.B+......",
160       "......X.X.......",
161       "......X&+.......",
162       "......-B........",
163       "....../=........",
164       "......#B........",
165       "......BB........",
166       "......B#........",
167       "................",
168       "................"
169     },
170     /* reset: */
171     {
172       /* width height ncolors chars_per_pixel */
173       "16 16 4 1",
174       /* colors */
175       ". c None",
176       "B c #000000",
177       "+ c #824141",
178       "r c #FF0000",
179       /* pixels */
180       "..............BB",
181       "..............+B",
182       ".............r..",
183       "............r...",
184       "...........r....",
185       "..........r.....",
186       ".........r......",
187       "........r.......",
188       ".......r........",
189       "......r.........",
190       ".....r..........",
191       "....r...........",
192       "...r............",
193       "..r.............",
194       "B+..............",
195       "BB.............."
196     }
197   };
198
199 guint
200 gtk_gamma_curve_get_type (void)
201 {
202   static guint gamma_curve_type = 0;
203
204   if (!gamma_curve_type)
205     {
206       GtkTypeInfo gamma_curve_info =
207       {
208         "GtkGammaCurve",
209         sizeof (GtkGammaCurve),
210         sizeof (GtkGammaCurveClass),
211         (GtkClassInitFunc) gtk_gamma_curve_class_init,
212         (GtkObjectInitFunc) gtk_gamma_curve_init,
213         (GtkArgFunc) NULL,
214       };
215
216       gamma_curve_type =
217         gtk_type_unique (gtk_vbox_get_type (), &gamma_curve_info);
218     }
219   return gamma_curve_type;
220 }
221
222 static void
223 gtk_gamma_curve_class_init (GtkGammaCurveClass *class)
224 {
225   GtkObjectClass *object_class;
226
227   parent_class = gtk_type_class (gtk_vbox_get_type ());
228
229   object_class = (GtkObjectClass *) class;
230   object_class->destroy = gtk_gamma_curve_destroy;
231 }
232
233 static void
234 gtk_gamma_curve_init (GtkGammaCurve *curve)
235 {
236   curve->gamma = 1.0;
237 }
238
239 static void
240 button_realize_callback (GtkWidget *w)
241 {
242   GtkWidget *pixmap;
243   GdkBitmap *mask;
244   GdkPixmap *pm;
245   int i;
246
247   i = (long) gtk_object_get_data (GTK_OBJECT (w), "_GtkGammaCurveIndex");
248   pm = gdk_pixmap_create_from_xpm_d (w->window, &mask,
249                                      &w->style->bg[GTK_STATE_NORMAL], xpm[i]);
250
251   pixmap = gtk_pixmap_new (pm, mask);
252   gtk_container_add (GTK_CONTAINER (w), pixmap);
253   gtk_widget_show (pixmap);
254
255   gdk_pixmap_unref (pm);
256   gdk_bitmap_unref (mask);   /* a bitmap is really just a special pixmap */
257 }
258
259 static void
260 button_toggled_callback (GtkWidget *w, gpointer data)
261 {
262   GtkGammaCurve *c = data;
263   GtkCurveType type;
264   int active, i;
265
266   if (!GTK_TOGGLE_BUTTON (w)->active)
267     return;
268
269   active = (long) gtk_object_get_data (GTK_OBJECT (w), "_GtkGammaCurveIndex");
270
271   for (i = 0; i < 3; ++i)
272     if ((i != active) && GTK_TOGGLE_BUTTON (c->button[i])->active)
273       break;
274
275   if (i < 3)
276     gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (c->button[i]), FALSE);
277
278   switch (active)
279     {
280     case 0:  type = GTK_CURVE_TYPE_SPLINE; break;
281     case 1:  type = GTK_CURVE_TYPE_LINEAR; break;
282     default: type = GTK_CURVE_TYPE_FREE; break;
283     }
284   gtk_curve_set_curve_type (GTK_CURVE (c->curve), type);
285 }
286
287 static void
288 gamma_cancel_callback (GtkWidget *w, gpointer data)
289 {
290   GtkGammaCurve *c = data;
291
292   gtk_widget_destroy (c->gamma_dialog);
293   c->gamma_dialog = 0;
294 }
295
296 static void
297 gamma_ok_callback (GtkWidget *w, gpointer data)
298 {
299   GtkGammaCurve *c = data;
300   gchar *start, *end;
301   gfloat v;
302
303   start = gtk_entry_get_text (GTK_ENTRY (c->gamma_text));
304   if (start)
305     {
306       v = strtod (start, &end);
307       if (end > start && v > 0.0)
308         c->gamma = v;
309     }
310   gtk_curve_set_gamma (GTK_CURVE (c->curve), c->gamma);
311   gamma_cancel_callback (w, data);
312 }
313
314 static void
315 button_clicked_callback (GtkWidget *w, gpointer data)
316 {
317   GtkGammaCurve *c = data;
318   int active;
319
320   active = (long) gtk_object_get_data (GTK_OBJECT (w), "_GtkGammaCurveIndex");
321   if (active == 3)
322     /* set gamma */
323     if (c->gamma_dialog)
324       return;
325     else
326       {
327         GtkWidget *vbox, *hbox, *label, *button;
328         gchar buf[64];
329
330         c->gamma_dialog = gtk_dialog_new ();
331         gtk_window_set_title (GTK_WINDOW (c->gamma_dialog), "Gamma");
332         vbox = GTK_DIALOG (c->gamma_dialog)->vbox;
333
334         hbox = gtk_hbox_new (/* homogeneous */ FALSE, 0);
335         gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 2);
336         gtk_widget_show (hbox);
337
338         label = gtk_label_new ("Gamma value");
339         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2);
340         gtk_widget_show (label);
341
342         sprintf (buf, "%g", c->gamma);
343         c->gamma_text = gtk_entry_new ();
344         gtk_entry_set_text (GTK_ENTRY (c->gamma_text), buf);
345         gtk_box_pack_start (GTK_BOX (hbox), c->gamma_text, TRUE, TRUE, 2);
346         gtk_widget_show (c->gamma_text);
347
348         /* fill in action area: */
349         hbox = GTK_DIALOG (c->gamma_dialog)->action_area;
350
351         button = gtk_button_new_with_label ("OK");
352         GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
353         gtk_signal_connect (GTK_OBJECT (button), "clicked",
354                             (GtkSignalFunc) gamma_ok_callback, c);
355         gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
356         gtk_widget_grab_default (button);
357         gtk_widget_show (button);
358
359         button = gtk_button_new_with_label ("Cancel");
360         gtk_signal_connect (GTK_OBJECT (button), "clicked",
361                             (GtkSignalFunc) gamma_cancel_callback, c);
362         gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
363         gtk_widget_show (button);
364
365         gtk_widget_show (c->gamma_dialog);
366       }
367   else
368     /* reset */
369     gtk_curve_reset (GTK_CURVE (c->curve));
370 }
371
372 static void
373 curve_type_changed_callback (GtkWidget *w, gpointer data)
374 {
375   GtkGammaCurve *c = data;
376   GtkCurveType new_type;
377   int active;
378
379   new_type = GTK_CURVE (w)->curve_type;
380   switch (new_type)
381     {
382     case GTK_CURVE_TYPE_SPLINE: active = 0; break;
383     case GTK_CURVE_TYPE_LINEAR: active = 1; break;
384     default:                    active = 2; break;
385     }
386   if (!GTK_TOGGLE_BUTTON (c->button[active])->active)
387     gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (c->button[active]), TRUE);
388 }
389
390 GtkWidget*
391 gtk_gamma_curve_new (void)
392 {
393   GtkGammaCurve *c;
394   GtkWidget *vbox;
395   int i;
396
397   c = gtk_type_new (gtk_gamma_curve_get_type ());
398
399   c->table = gtk_table_new (1, 2, FALSE);
400   gtk_table_set_col_spacings (GTK_TABLE (c->table), 3);
401   gtk_container_add (GTK_CONTAINER (c), c->table);
402
403   c->curve = gtk_curve_new ();
404   gtk_signal_connect (GTK_OBJECT (c->curve), "curve_type_changed",
405                       (GtkSignalFunc) curve_type_changed_callback, c);
406   gtk_table_attach_defaults (GTK_TABLE (c->table), c->curve, 0, 1, 0, 1);
407
408   vbox = gtk_vbox_new (/* homogeneous */ FALSE, /* spacing */ 3);
409   gtk_table_attach (GTK_TABLE (c->table), vbox, 1, 2, 0, 1, 0, 0, 0, 0);
410
411   /* toggle buttons: */
412   for (i = 0; i < 3; ++i)
413     {
414       c->button[i] = gtk_toggle_button_new ();
415       gtk_object_set_data (GTK_OBJECT (c->button[i]), "_GtkGammaCurveIndex",
416                            (gpointer) (long) i);
417       gtk_container_add (GTK_CONTAINER (vbox), c->button[i]);
418       gtk_signal_connect (GTK_OBJECT (c->button[i]), "realize",
419                           (GtkSignalFunc) button_realize_callback, 0);
420       gtk_signal_connect (GTK_OBJECT (c->button[i]), "toggled",
421                           (GtkSignalFunc) button_toggled_callback, c);
422       gtk_widget_show (c->button[i]);
423     }
424
425   /* push buttons: */
426   for (i = 3; i < 5; ++i)
427     {
428       c->button[i] = gtk_button_new ();
429       gtk_object_set_data (GTK_OBJECT (c->button[i]), "_GtkGammaCurveIndex",
430                            (gpointer) (long) i);
431       gtk_container_add (GTK_CONTAINER (vbox), c->button[i]);
432       gtk_signal_connect (GTK_OBJECT (c->button[i]), "realize",
433                           (GtkSignalFunc) button_realize_callback, 0);
434       gtk_signal_connect (GTK_OBJECT (c->button[i]), "clicked",
435                           (GtkSignalFunc) button_clicked_callback, c);
436       gtk_widget_show (c->button[i]);
437     }
438
439   gtk_widget_show (vbox);
440   gtk_widget_show (c->table);
441   gtk_widget_show (c->curve);
442
443   return GTK_WIDGET (c);
444 }
445
446 static void
447 gtk_gamma_curve_destroy (GtkObject *object)
448 {
449   GtkGammaCurve *c;
450
451   g_return_if_fail (object != NULL);
452   g_return_if_fail (GTK_IS_GAMMA_CURVE (object));
453
454   c = GTK_GAMMA_CURVE (object);
455
456   if (c->gamma_dialog)
457     {
458       gtk_widget_destroy (c->gamma_dialog);
459       c->gamma_dialog = 0;
460     }
461
462   if (GTK_OBJECT_CLASS (parent_class)->destroy)
463     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
464 }