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