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