]> Pileus Git - ~andy/gtk/blob - gtk/gtkpixmap.c
better error message if you try to add a widget to a bin that already has
[~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 "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   (GObject         *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   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
72   GtkObjectClass *object_class;
73   GtkWidgetClass *widget_class;
74
75   object_class = (GtkObjectClass*) class;
76   widget_class = (GtkWidgetClass*) class;
77   parent_class = gtk_type_class (gtk_widget_get_type ());
78
79   gobject_class->finalize = gtk_pixmap_finalize;
80
81   widget_class->expose_event = gtk_pixmap_expose;
82 }
83
84 static void
85 gtk_pixmap_init (GtkPixmap *pixmap)
86 {
87   GTK_WIDGET_SET_FLAGS (pixmap, GTK_NO_WINDOW);
88
89   pixmap->pixmap = NULL;
90   pixmap->mask = NULL;
91 }
92
93 GtkWidget*
94 gtk_pixmap_new (GdkPixmap *val,
95                 GdkBitmap *mask)
96 {
97   GtkPixmap *pixmap;
98    
99   g_return_val_if_fail (val != NULL, NULL);
100   
101   pixmap = gtk_type_new (gtk_pixmap_get_type ());
102   
103   pixmap->build_insensitive = TRUE;
104   gtk_pixmap_set (pixmap, val, mask);
105   
106   return GTK_WIDGET (pixmap);
107 }
108
109 static void
110 gtk_pixmap_finalize (GObject *object)
111 {
112   gtk_pixmap_set (GTK_PIXMAP (object), NULL, NULL);
113
114   G_OBJECT_CLASS (parent_class)->finalize (object);
115 }
116
117 void
118 gtk_pixmap_set (GtkPixmap *pixmap,
119                 GdkPixmap *val,
120                 GdkBitmap *mask)
121 {
122   gint width;
123   gint height;
124   gint oldwidth;
125   gint oldheight;
126
127   g_return_if_fail (pixmap != NULL);
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 (pixmap != NULL);
180   g_return_if_fail (GTK_IS_PIXMAP (pixmap));
181
182   if (val)
183     *val = pixmap->pixmap;
184   if (mask)
185     *mask = pixmap->mask;
186 }
187
188 static gint
189 gtk_pixmap_expose (GtkWidget      *widget,
190                    GdkEventExpose *event)
191 {
192   GtkPixmap *pixmap;
193   GtkMisc *misc;
194   gint x, y;
195
196   g_return_val_if_fail (widget != NULL, FALSE);
197   g_return_val_if_fail (GTK_IS_PIXMAP (widget), FALSE);
198   g_return_val_if_fail (event != NULL, FALSE);
199
200   if (GTK_WIDGET_DRAWABLE (widget))
201     {
202       pixmap = GTK_PIXMAP (widget);
203       misc = GTK_MISC (widget);
204
205       x = (widget->allocation.x * (1.0 - misc->xalign) +
206            (widget->allocation.x + widget->allocation.width
207             - (widget->requisition.width - misc->xpad * 2)) *
208            misc->xalign) + 0.5;
209       y = (widget->allocation.y * (1.0 - misc->yalign) +
210            (widget->allocation.y + widget->allocation.height
211             - (widget->requisition.height - misc->ypad * 2)) *
212            misc->yalign) + 0.5;
213
214       if (pixmap->mask)
215         {
216           gdk_gc_set_clip_mask (widget->style->black_gc, pixmap->mask);
217           gdk_gc_set_clip_origin (widget->style->black_gc, x, y);
218         }
219
220       if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE
221           && pixmap->build_insensitive)
222         {
223           if (!pixmap->pixmap_insensitive)
224             build_insensitive_pixmap (pixmap);
225           gdk_draw_pixmap (widget->window,
226                            widget->style->black_gc,
227                            pixmap->pixmap_insensitive,
228                            0, 0, x, y, -1, -1);
229         }
230       else
231         {
232           gdk_draw_pixmap (widget->window,
233                            widget->style->black_gc,
234                            pixmap->pixmap,
235                            0, 0, x, y, -1, -1);
236         }
237
238       if (pixmap->mask)
239         {
240           gdk_gc_set_clip_mask (widget->style->black_gc, NULL);
241           gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0);
242         }
243     }
244   return FALSE;
245 }
246
247 void
248 gtk_pixmap_set_build_insensitive (GtkPixmap *pixmap, guint build)
249 {
250   g_return_if_fail (pixmap != NULL);
251   g_return_if_fail (GTK_IS_PIXMAP (pixmap));
252
253   pixmap->build_insensitive = build;
254
255   if (GTK_WIDGET_VISIBLE (pixmap))
256     {
257       gtk_widget_queue_clear (GTK_WIDGET (pixmap));
258     }
259 }
260
261 static void
262 build_insensitive_pixmap(GtkPixmap *gtkpixmap)
263 {
264   GdkPixmap *pixmap = gtkpixmap->pixmap;
265   GdkPixmap *insensitive;
266   gint w, h;
267   GdkPixbuf *pixbuf;
268   GdkPixbuf *stated;
269   
270   gdk_window_get_size (pixmap, &w, &h);
271
272   pixbuf = gdk_pixbuf_get_from_drawable (NULL,
273                                          pixmap,
274                                          gtk_widget_get_colormap (GTK_WIDGET(gtkpixmap)),
275                                          0, 0,
276                                          0, 0,
277                                          w, h);
278   
279   stated = gdk_pixbuf_copy (pixbuf);
280   
281   gdk_pixbuf_saturate_and_pixelate (pixbuf, stated,
282                                     0.8, TRUE);
283
284   g_object_unref (G_OBJECT (pixbuf));
285   pixbuf = NULL;
286   
287   insensitive = gdk_pixmap_new (GTK_WIDGET (gtkpixmap)->window, w, h, -1);
288
289   gdk_pixbuf_render_to_drawable (stated,
290                                  insensitive,
291                                  GTK_WIDGET (gtkpixmap)->style->white_gc,
292                                  0, 0,
293                                  0, 0,
294                                  w, h,
295                                  GDK_RGB_DITHER_NORMAL,
296                                  0, 0);
297
298   gtkpixmap->pixmap_insensitive = insensitive;
299
300   g_object_unref (G_OBJECT (stated));
301 }
302
303