]> Pileus Git - ~andy/gtk/blob - gtk/gtkpixmap.c
Use the correct screen for getting the height. (Fix from Stephen Browne,
[~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 Lesser 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  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser 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-2000.  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 #undef GDK_DISABLE_DEPRECATED
31 #undef GTK_DISABLE_DEPRECATED
32
33 #include <math.h>
34 #include "gtkcontainer.h"
35 #include "gtkpixmap.h"
36
37
38 static void gtk_pixmap_class_init (GtkPixmapClass  *klass);
39 static void gtk_pixmap_init       (GtkPixmap       *pixmap);
40 static gint gtk_pixmap_expose     (GtkWidget       *widget,
41                                    GdkEventExpose  *event);
42 static void gtk_pixmap_finalize   (GObject         *object);
43 static void build_insensitive_pixmap (GtkPixmap *gtkpixmap);
44
45 static GtkWidgetClass *parent_class;
46
47 GtkType
48 gtk_pixmap_get_type (void)
49 {
50   static GtkType pixmap_type = 0;
51
52   if (!pixmap_type)
53     {
54       static const GtkTypeInfo pixmap_info =
55       {
56         "GtkPixmap",
57         sizeof (GtkPixmap),
58         sizeof (GtkPixmapClass),
59         (GtkClassInitFunc) gtk_pixmap_class_init,
60         (GtkObjectInitFunc) gtk_pixmap_init,
61         /* reserved_1 */ NULL,
62         /* reserved_2 */ NULL,
63         (GtkClassInitFunc) NULL,
64       };
65
66       pixmap_type = gtk_type_unique (GTK_TYPE_MISC, &pixmap_info);
67     }
68
69   return pixmap_type;
70 }
71
72 static void
73 gtk_pixmap_class_init (GtkPixmapClass *class)
74 {
75   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
76   GtkObjectClass *object_class;
77   GtkWidgetClass *widget_class;
78
79   object_class = (GtkObjectClass*) class;
80   widget_class = (GtkWidgetClass*) class;
81   parent_class = gtk_type_class (gtk_misc_get_type ());
82
83   gobject_class->finalize = gtk_pixmap_finalize;
84
85   widget_class->expose_event = gtk_pixmap_expose;
86 }
87
88 static void
89 gtk_pixmap_init (GtkPixmap *pixmap)
90 {
91   GTK_WIDGET_SET_FLAGS (pixmap, GTK_NO_WINDOW);
92
93   pixmap->pixmap = NULL;
94   pixmap->mask = NULL;
95 }
96
97 GtkWidget*
98 gtk_pixmap_new (GdkPixmap *val,
99                 GdkBitmap *mask)
100 {
101   GtkPixmap *pixmap;
102    
103   g_return_val_if_fail (val != NULL, NULL);
104   
105   pixmap = gtk_type_new (gtk_pixmap_get_type ());
106   
107   pixmap->build_insensitive = TRUE;
108   gtk_pixmap_set (pixmap, val, mask);
109   
110   return GTK_WIDGET (pixmap);
111 }
112
113 static void
114 gtk_pixmap_finalize (GObject *object)
115 {
116   gtk_pixmap_set (GTK_PIXMAP (object), NULL, NULL);
117
118   G_OBJECT_CLASS (parent_class)->finalize (object);
119 }
120
121 void
122 gtk_pixmap_set (GtkPixmap *pixmap,
123                 GdkPixmap *val,
124                 GdkBitmap *mask)
125 {
126   gint width;
127   gint height;
128   gint oldwidth;
129   gint oldheight;
130
131   g_return_if_fail (GTK_IS_PIXMAP (pixmap));
132
133   if (pixmap->pixmap != val)
134     {
135       oldwidth = GTK_WIDGET (pixmap)->requisition.width;
136       oldheight = GTK_WIDGET (pixmap)->requisition.height;
137       if (pixmap->pixmap)
138         gdk_pixmap_unref (pixmap->pixmap);
139       if (pixmap->pixmap_insensitive)
140         gdk_pixmap_unref (pixmap->pixmap_insensitive);
141       pixmap->pixmap = val;
142       pixmap->pixmap_insensitive = NULL;
143       if (pixmap->pixmap)
144         {
145           gdk_pixmap_ref (pixmap->pixmap);
146           gdk_window_get_size (pixmap->pixmap, &width, &height);
147           GTK_WIDGET (pixmap)->requisition.width =
148             width + GTK_MISC (pixmap)->xpad * 2;
149           GTK_WIDGET (pixmap)->requisition.height =
150             height + GTK_MISC (pixmap)->ypad * 2;
151         }
152       else
153         {
154           GTK_WIDGET (pixmap)->requisition.width = 0;
155           GTK_WIDGET (pixmap)->requisition.height = 0;
156         }
157       if (GTK_WIDGET_VISIBLE (pixmap))
158         {
159           if ((GTK_WIDGET (pixmap)->requisition.width != oldwidth) ||
160               (GTK_WIDGET (pixmap)->requisition.height != oldheight))
161             gtk_widget_queue_resize (GTK_WIDGET (pixmap));
162           else
163             gtk_widget_queue_clear (GTK_WIDGET (pixmap));
164         }
165     }
166
167   if (pixmap->mask != mask)
168     {
169       if (pixmap->mask)
170         gdk_bitmap_unref (pixmap->mask);
171       pixmap->mask = mask;
172       if (pixmap->mask)
173         gdk_bitmap_ref (pixmap->mask);
174     }
175 }
176
177 void
178 gtk_pixmap_get (GtkPixmap  *pixmap,
179                 GdkPixmap **val,
180                 GdkBitmap **mask)
181 {
182   g_return_if_fail (GTK_IS_PIXMAP (pixmap));
183
184   if (val)
185     *val = pixmap->pixmap;
186   if (mask)
187     *mask = pixmap->mask;
188 }
189
190 static gint
191 gtk_pixmap_expose (GtkWidget      *widget,
192                    GdkEventExpose *event)
193 {
194   GtkPixmap *pixmap;
195   GtkMisc *misc;
196   gint x, y;
197   gfloat xalign;
198
199   g_return_val_if_fail (GTK_IS_PIXMAP (widget), FALSE);
200   g_return_val_if_fail (event != NULL, FALSE);
201
202   if (GTK_WIDGET_DRAWABLE (widget))
203     {
204       pixmap = GTK_PIXMAP (widget);
205       misc = GTK_MISC (widget);
206
207       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
208         xalign = misc->xalign;
209       else
210         xalign = 1.0 - misc->xalign;
211   
212       x = floor (widget->allocation.x + misc->xpad
213                  + ((widget->allocation.width - widget->requisition.width) * xalign)
214                  + 0.5);
215       y = floor (widget->allocation.y + misc->ypad 
216                  + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
217                  + 0.5);
218       
219       if (pixmap->mask)
220         {
221           gdk_gc_set_clip_mask (widget->style->black_gc, pixmap->mask);
222           gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
223         }
224
225       if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE
226           && pixmap->build_insensitive)
227         {
228           if (!pixmap->pixmap_insensitive)
229             build_insensitive_pixmap (pixmap);
230           gdk_draw_pixmap (widget->window,
231                            widget->style->black_gc,
232                            pixmap->pixmap_insensitive,
233                            0, 0, x, y, -1, -1);
234         }
235       else
236         {
237           gdk_draw_pixmap (widget->window,
238                            widget->style->black_gc,
239                            pixmap->pixmap,
240                            0, 0, x, y, -1, -1);
241         }
242
243       if (pixmap->mask)
244         {
245           gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
246           gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
247         }
248     }
249   return FALSE;
250 }
251
252 void
253 gtk_pixmap_set_build_insensitive (GtkPixmap *pixmap, gboolean build)
254 {
255   g_return_if_fail (GTK_IS_PIXMAP (pixmap));
256
257   pixmap->build_insensitive = build;
258
259   if (GTK_WIDGET_VISIBLE (pixmap))
260     {
261       gtk_widget_queue_clear (GTK_WIDGET (pixmap));
262     }
263 }
264
265 static void
266 build_insensitive_pixmap (GtkPixmap *gtkpixmap)
267 {
268   GdkPixmap *pixmap = gtkpixmap->pixmap;
269   GdkPixmap *insensitive;
270   gint w, h;
271   GdkPixbuf *pixbuf;
272   GdkPixbuf *stated;
273   
274   gdk_window_get_size (pixmap, &w, &h);
275
276   pixbuf = gdk_pixbuf_get_from_drawable (NULL,
277                                          pixmap,
278                                          gtk_widget_get_colormap (GTK_WIDGET(gtkpixmap)),
279                                          0, 0,
280                                          0, 0,
281                                          w, h);
282   
283   stated = gdk_pixbuf_copy (pixbuf);
284   
285   gdk_pixbuf_saturate_and_pixelate (pixbuf, stated,
286                                     0.8, TRUE);
287
288   g_object_unref (G_OBJECT (pixbuf));
289   pixbuf = NULL;
290   
291   insensitive = gdk_pixmap_new (GTK_WIDGET (gtkpixmap)->window, w, h, -1);
292
293   gdk_draw_pixbuf (insensitive,
294                    GTK_WIDGET (gtkpixmap)->style->white_gc,
295                    stated,
296                    0, 0,
297                    0, 0,
298                    w, h,
299                    GDK_RGB_DITHER_NORMAL,
300                    0, 0);
301
302   gtkpixmap->pixmap_insensitive = insensitive;
303
304   g_object_unref (G_OBJECT (stated));
305 }
306
307