]> Pileus Git - ~andy/gtk/blob - gtk/gtkpixmap.c
Added notice to look in AUTHORS and ChangeLog files for a list of changes.
[~andy/gtk] / gtk / gtkpixmap.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * Insensitive pixmap building code by Eckehard Berns from GNOME Stock
5  * Copyright (C) 1997, 1998 Free Software Foundation
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
25  * file for a list of people on the GTK+ Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
28  */
29
30 #include "gtkcontainer.h"
31 #include "gtkpixmap.h"
32
33
34 static void gtk_pixmap_class_init (GtkPixmapClass  *klass);
35 static void gtk_pixmap_init       (GtkPixmap       *pixmap);
36 static gint gtk_pixmap_expose     (GtkWidget       *widget,
37                                    GdkEventExpose  *event);
38 static void gtk_pixmap_finalize   (GtkObject       *object);
39 static void build_insensitive_pixmap (GtkPixmap *gtkpixmap);
40
41 static GtkWidgetClass *parent_class;
42
43 GtkType
44 gtk_pixmap_get_type (void)
45 {
46   static GtkType pixmap_type = 0;
47
48   if (!pixmap_type)
49     {
50       static const GtkTypeInfo pixmap_info =
51       {
52         "GtkPixmap",
53         sizeof (GtkPixmap),
54         sizeof (GtkPixmapClass),
55         (GtkClassInitFunc) gtk_pixmap_class_init,
56         (GtkObjectInitFunc) gtk_pixmap_init,
57         /* reserved_1 */ NULL,
58         /* reserved_2 */ NULL,
59         (GtkClassInitFunc) NULL,
60       };
61
62       pixmap_type = gtk_type_unique (GTK_TYPE_MISC, &pixmap_info);
63     }
64
65   return pixmap_type;
66 }
67
68 static void
69 gtk_pixmap_class_init (GtkPixmapClass *class)
70 {
71   GtkObjectClass *object_class;
72   GtkWidgetClass *widget_class;
73
74   object_class = (GtkObjectClass*) class;
75   widget_class = (GtkWidgetClass*) class;
76   parent_class = gtk_type_class (gtk_widget_get_type ());
77
78   object_class->finalize = gtk_pixmap_finalize;
79   widget_class->expose_event = gtk_pixmap_expose;
80 }
81
82 static void
83 gtk_pixmap_init (GtkPixmap *pixmap)
84 {
85   GTK_WIDGET_SET_FLAGS (pixmap, GTK_NO_WINDOW);
86
87   pixmap->pixmap = NULL;
88   pixmap->mask = NULL;
89 }
90
91 GtkWidget*
92 gtk_pixmap_new (GdkPixmap *val,
93                 GdkBitmap *mask)
94 {
95   GtkPixmap *pixmap;
96    
97   g_return_val_if_fail (val != NULL, NULL);
98   
99   pixmap = gtk_type_new (gtk_pixmap_get_type ());
100   
101   pixmap->build_insensitive = TRUE;
102   gtk_pixmap_set (pixmap, val, mask);
103   
104   return GTK_WIDGET (pixmap);
105 }
106
107 static void
108 gtk_pixmap_finalize (GtkObject *object)
109 {
110   gtk_pixmap_set (GTK_PIXMAP (object), NULL, NULL);
111   (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
112 }
113
114 void
115 gtk_pixmap_set (GtkPixmap *pixmap,
116                 GdkPixmap *val,
117                 GdkBitmap *mask)
118 {
119   gint width;
120   gint height;
121   gint oldwidth;
122   gint oldheight;
123
124   g_return_if_fail (pixmap != NULL);
125   g_return_if_fail (GTK_IS_PIXMAP (pixmap));
126
127   if (pixmap->pixmap != val)
128     {
129       oldwidth = GTK_WIDGET (pixmap)->requisition.width;
130       oldheight = GTK_WIDGET (pixmap)->requisition.height;
131       if (pixmap->pixmap)
132         gdk_pixmap_unref (pixmap->pixmap);
133       if (pixmap->pixmap_insensitive)
134         gdk_pixmap_unref (pixmap->pixmap_insensitive);
135       pixmap->pixmap = val;
136       pixmap->pixmap_insensitive = NULL;
137       if (pixmap->pixmap)
138         {
139           gdk_pixmap_ref (pixmap->pixmap);
140           gdk_window_get_size (pixmap->pixmap, &width, &height);
141           GTK_WIDGET (pixmap)->requisition.width =
142             width + GTK_MISC (pixmap)->xpad * 2;
143           GTK_WIDGET (pixmap)->requisition.height =
144             height + GTK_MISC (pixmap)->ypad * 2;
145         }
146       else
147         {
148           GTK_WIDGET (pixmap)->requisition.width = 0;
149           GTK_WIDGET (pixmap)->requisition.height = 0;
150         }
151       if (GTK_WIDGET_VISIBLE (pixmap))
152         {
153           if ((GTK_WIDGET (pixmap)->requisition.width != oldwidth) ||
154               (GTK_WIDGET (pixmap)->requisition.height != oldheight))
155             gtk_widget_queue_resize (GTK_WIDGET (pixmap));
156           else
157             gtk_widget_queue_clear (GTK_WIDGET (pixmap));
158         }
159     }
160
161   if (pixmap->mask != mask)
162     {
163       if (pixmap->mask)
164         gdk_bitmap_unref (pixmap->mask);
165       pixmap->mask = mask;
166       if (pixmap->mask)
167         gdk_bitmap_ref (pixmap->mask);
168     }
169 }
170
171 void
172 gtk_pixmap_get (GtkPixmap  *pixmap,
173                 GdkPixmap **val,
174                 GdkBitmap **mask)
175 {
176   g_return_if_fail (pixmap != NULL);
177   g_return_if_fail (GTK_IS_PIXMAP (pixmap));
178
179   if (val)
180     *val = pixmap->pixmap;
181   if (mask)
182     *mask = pixmap->mask;
183 }
184
185 static gint
186 gtk_pixmap_expose (GtkWidget      *widget,
187                    GdkEventExpose *event)
188 {
189   GtkPixmap *pixmap;
190   GtkMisc *misc;
191   gint x, y;
192
193   g_return_val_if_fail (widget != NULL, FALSE);
194   g_return_val_if_fail (GTK_IS_PIXMAP (widget), FALSE);
195   g_return_val_if_fail (event != NULL, FALSE);
196
197   if (GTK_WIDGET_DRAWABLE (widget))
198     {
199       pixmap = GTK_PIXMAP (widget);
200       misc = GTK_MISC (widget);
201
202       x = (widget->allocation.x * (1.0 - misc->xalign) +
203            (widget->allocation.x + widget->allocation.width
204             - (widget->requisition.width - misc->xpad * 2)) *
205            misc->xalign) + 0.5;
206       y = (widget->allocation.y * (1.0 - misc->yalign) +
207            (widget->allocation.y + widget->allocation.height
208             - (widget->requisition.height - misc->ypad * 2)) *
209            misc->yalign) + 0.5;
210
211       if (pixmap->mask)
212         {
213           gdk_gc_set_clip_mask (widget->style->black_gc, pixmap->mask);
214           gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
215         }
216
217       if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE
218           && pixmap->build_insensitive)
219         {
220           if (!pixmap->pixmap_insensitive)
221             build_insensitive_pixmap (pixmap);
222           gdk_draw_pixmap (widget->window,
223                            widget->style->black_gc,
224                            pixmap->pixmap_insensitive,
225                            0, 0, x, y, -1, -1);
226         }
227       else
228         {
229           gdk_draw_pixmap (widget->window,
230                            widget->style->black_gc,
231                            pixmap->pixmap,
232                            0, 0, x, y, -1, -1);
233         }
234
235       if (pixmap->mask)
236         {
237           gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
238           gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
239         }
240     }
241   return FALSE;
242 }
243
244 void
245 gtk_pixmap_set_build_insensitive (GtkPixmap *pixmap, guint build)
246 {
247   g_return_if_fail (pixmap != NULL);
248   g_return_if_fail (GTK_IS_PIXMAP (pixmap));
249
250   pixmap->build_insensitive = build;
251
252   if (GTK_WIDGET_VISIBLE (pixmap))
253     {
254       gtk_widget_queue_clear (GTK_WIDGET (pixmap));
255     }
256 }
257
258 static void
259 build_insensitive_pixmap(GtkPixmap *gtkpixmap)
260 {
261   GdkGC *gc;
262   GdkPixmap *pixmap = gtkpixmap->pixmap;
263   GdkPixmap *insensitive;
264   gint w, h, x, y;
265   GdkGCValues vals;
266   GdkVisual *visual;
267   GdkImage *image;
268   GdkColorContext *cc;
269   GdkColor color;
270   GdkColormap *cmap;
271   gint32 red, green, blue;
272   GtkStyle *style;
273   GtkWidget *window;
274   GdkColor c;
275   int failed;
276
277   window = GTK_WIDGET (gtkpixmap);
278
279   g_return_if_fail(window != NULL);
280
281   gdk_window_get_size(pixmap, &w, &h);
282   image = gdk_image_get(pixmap, 0, 0, w, h);
283   insensitive = gdk_pixmap_new(GTK_WIDGET (gtkpixmap)->window, w, h, -1);
284   gc = gdk_gc_new (pixmap);
285
286   visual = gtk_widget_get_visual(GTK_WIDGET(gtkpixmap));
287   cmap = gtk_widget_get_colormap(GTK_WIDGET(gtkpixmap));
288   cc = gdk_color_context_new(visual, cmap);
289
290   if ((cc->mode != GDK_CC_MODE_TRUE) && (cc->mode != GDK_CC_MODE_MY_GRAY)) 
291     {
292       gdk_draw_image(insensitive, gc, image, 0, 0, 0, 0, w, h);
293
294       style = gtk_widget_get_style(window);
295       color = style->bg[0];
296       gdk_gc_set_foreground (gc, &color);
297       for (y = 0; y < h; y++) 
298         {
299           for (x = y % 2; x < w; x += 2) 
300             {
301               gdk_draw_point(insensitive, gc, x, y);
302             }
303         }
304     }
305   else
306     {
307       gdk_gc_get_values(gc, &vals);
308       style = gtk_widget_get_style(window);
309
310       color = style->bg[0];
311       red = color.red;
312       green = color.green;
313       blue = color.blue;
314
315       for (y = 0; y < h; y++) 
316         {
317           for (x = 0; x < w; x++) 
318             {
319               c.pixel = gdk_image_get_pixel(image, x, y);
320               gdk_color_context_query_color(cc, &c);
321               c.red = (((gint32)c.red - red) >> 1) + red;
322               c.green = (((gint32)c.green - green) >> 1) + green;
323               c.blue = (((gint32)c.blue - blue) >> 1) + blue;
324               c.pixel = gdk_color_context_get_pixel(cc, c.red, c.green, c.blue,
325                                                     &failed);
326               gdk_image_put_pixel(image, x, y, c.pixel);
327             }
328         }
329
330       for (y = 0; y < h; y++) 
331         {
332           for (x = y % 2; x < w; x += 2) 
333             {
334               c.pixel = gdk_image_get_pixel(image, x, y);
335               gdk_color_context_query_color(cc, &c);
336               c.red = (((gint32)c.red - red) >> 1) + red;
337               c.green = (((gint32)c.green - green) >> 1) + green;
338               c.blue = (((gint32)c.blue - blue) >> 1) + blue;
339               c.pixel = gdk_color_context_get_pixel(cc, c.red, c.green, c.blue,
340                                                     &failed);
341               gdk_image_put_pixel(image, x, y, c.pixel);
342             }
343         }
344
345       gdk_draw_image(insensitive, gc, image, 0, 0, 0, 0, w, h);
346     }
347
348   gtkpixmap->pixmap_insensitive = insensitive;
349
350   gdk_image_destroy(image);
351   gdk_color_context_free(cc);
352   gdk_gc_destroy(gc);
353 }
354
355