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