1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * Insensitive pixcomm building code by Eckehard Berns from GNOME Stock
5 * Copyright (C) 1997, 1998 Free Software Foundation
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.
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.
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.
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/.
31 * Based code for GtkPixcomm off GtkImage from the standard GTK+ distribution.
32 * This widget will have a built-in X window for capturing "click" events, so
33 * that we no longer need to insert it inside a GtkEventBox. -vasc
37 #include <fc_config.h>
48 #include "gtkpixcomm.h"
50 static gboolean
gtk_pixcomm_draw(GtkWidget
*widget
, cairo_t
*cr
);
51 static void gtk_pixcomm_destroy(GtkWidget
*object
);
53 gtk_pixcomm_get_preferred_width(GtkWidget
*widget
, gint
*minimal_width
,
56 gtk_pixcomm_get_preferred_height(GtkWidget
*widget
, gint
*minimal_height
,
57 gint
*natural_height
);
59 static GtkWidgetClass
*parent_class
;
61 typedef struct _GtkPixcommPrivate GtkPixcommPrivate
;
62 struct _GtkPixcommPrivate
64 cairo_surface_t
*surface
;
67 #define GTK_PIXCOMM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_PIXCOMM, GtkPixcommPrivate))
69 G_DEFINE_TYPE (GtkPixcomm
, gtk_pixcomm
, GTK_TYPE_WIDGET
)
71 /***************************************************************************
72 Initialize pixcomm class
73 ***************************************************************************/
75 gtk_pixcomm_class_init(GtkPixcommClass
*klass
)
77 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS(klass
);
79 parent_class
= g_type_class_peek_parent(klass
);
81 widget_class
->destroy
= gtk_pixcomm_destroy
;
82 widget_class
->draw
= gtk_pixcomm_draw
;
83 widget_class
->get_preferred_width
= gtk_pixcomm_get_preferred_width
;
84 widget_class
->get_preferred_height
= gtk_pixcomm_get_preferred_height
;
85 g_type_class_add_private (widget_class
, sizeof(GtkPixcommPrivate
));
88 /***************************************************************************
89 Initialize pixcomm instance
90 ***************************************************************************/
92 gtk_pixcomm_init(GtkPixcomm
*pixcomm
)
94 GtkPixcommPrivate
*priv
= GTK_PIXCOMM_GET_PRIVATE(pixcomm
);
95 gtk_widget_set_has_window(GTK_WIDGET(pixcomm
), FALSE
);
100 /***************************************************************************
101 Destroy pixcomm instance
102 ***************************************************************************/
103 static void gtk_pixcomm_destroy(GtkWidget
*object
)
105 GtkPixcomm
*p
= GTK_PIXCOMM(object
);
106 GtkPixcommPrivate
*priv
= GTK_PIXCOMM_GET_PRIVATE(p
);
108 g_object_freeze_notify(G_OBJECT(p
));
110 cairo_surface_destroy(priv
->surface
);
111 priv
->surface
= NULL
;
113 g_object_thaw_notify(G_OBJECT(p
));
115 if (GTK_WIDGET_CLASS(parent_class
)->destroy
) {
116 (*GTK_WIDGET_CLASS(parent_class
)->destroy
)(object
);
120 /***************************************************************************
121 Create new pixcomm instance
122 ***************************************************************************/
124 gtk_pixcomm_new(gint width
, gint height
)
127 GtkPixcommPrivate
*priv
;
134 p
= g_object_new(gtk_pixcomm_get_type(), NULL
);
135 priv
= GTK_PIXCOMM_GET_PRIVATE(p
);
136 p
->w
= width
; p
->h
= height
;
137 start_pad
= gtk_widget_get_margin_left(GTK_WIDGET(p
));
138 end_pad
= gtk_widget_get_margin_right(GTK_WIDGET(p
));
139 top_pad
= gtk_widget_get_margin_top(GTK_WIDGET(p
));
140 bottom_pad
= gtk_widget_get_margin_bottom(GTK_WIDGET(p
));
141 gtk_widget_set_size_request(GTK_WIDGET(p
), width
+ start_pad
+ end_pad
,
142 height
+ top_pad
+ bottom_pad
);
143 gtk_widget_set_halign(GTK_WIDGET(p
), GTK_ALIGN_CENTER
);
144 gtk_widget_set_valign(GTK_WIDGET(p
), GTK_ALIGN_CENTER
);
146 p
->is_scaled
= FALSE
;
149 priv
->surface
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
, width
, height
);
150 cr
= cairo_create(priv
->surface
);
151 cairo_set_operator(cr
, CAIRO_OPERATOR_CLEAR
);
155 return GTK_WIDGET(p
);
158 /****************************************************************************
159 Set the scaling on the pixcomm. All operations drawn on the pixcomm
160 (before or after this function is called) will simply be scaled
162 ****************************************************************************/
163 void gtk_pixcomm_set_scale(GtkPixcomm
*pixcomm
, gdouble scale
)
165 fc_assert_ret(GTK_IS_PIXCOMM(pixcomm
));
166 fc_assert_ret(scale
> 0.0);
169 pixcomm
->is_scaled
= FALSE
;
170 pixcomm
->scale
= 1.0;
172 pixcomm
->is_scaled
= TRUE
;
173 pixcomm
->scale
= scale
;
177 /***************************************************************************
178 Get cairo surface from pixcomm.
179 ***************************************************************************/
180 cairo_surface_t
*gtk_pixcomm_get_surface(GtkPixcomm
*pixcomm
)
182 fc_assert_ret_val(GTK_IS_PIXCOMM(pixcomm
), NULL
);
183 return GTK_PIXCOMM_GET_PRIVATE(pixcomm
)->surface
;
186 /***************************************************************************
188 ***************************************************************************/
190 gtk_pixcomm_clear(GtkPixcomm
*p
)
192 fc_assert_ret(GTK_IS_PIXCOMM(p
));
193 GtkPixcommPrivate
*priv
= GTK_PIXCOMM_GET_PRIVATE(p
);
195 cairo_t
*cr
= cairo_create(priv
->surface
);
196 cairo_set_operator(cr
, CAIRO_OPERATOR_CLEAR
);
199 gtk_widget_queue_draw(GTK_WIDGET(p
));
202 /***************************************************************************
203 Copy sprite to pixcomm
204 ***************************************************************************/
205 void gtk_pixcomm_copyto(GtkPixcomm
*p
, struct sprite
*src
, gint x
, gint y
)
207 GtkPixcommPrivate
*priv
= GTK_PIXCOMM_GET_PRIVATE(p
);
209 GtkAllocation allocation
;
210 cairo_t
*cr
= cairo_create(priv
->surface
);
214 start_pad
= gtk_widget_get_margin_left(GTK_WIDGET(p
));
215 top_pad
= gtk_widget_get_margin_top(GTK_WIDGET(p
));
216 gtk_widget_get_allocation(GTK_WIDGET(p
), &allocation
);
218 fc_assert_ret(GTK_IS_PIXCOMM(p
));
219 fc_assert_ret(src
!= NULL
);
221 get_sprite_dimensions(src
, &width
, &height
);
222 cairo_rectangle(cr
, x
, y
, width
, height
);
223 cairo_set_source_surface(cr
, src
->surface
, x
, y
);
226 gtk_widget_queue_draw_area(GTK_WIDGET(p
),
227 allocation
.x
+ x
+ start_pad
,
228 allocation
.y
+ y
+ top_pad
,
232 /***************************************************************************
234 ***************************************************************************/
235 static gboolean
gtk_pixcomm_draw(GtkWidget
*widget
, cairo_t
*cr
)
237 GtkPixcommPrivate
*priv
;
242 fc_assert_ret_val(GTK_IS_PIXCOMM(widget
), FALSE
);
244 priv
= GTK_PIXCOMM_GET_PRIVATE(GTK_PIXCOMM(widget
));
246 p
= GTK_PIXCOMM(widget
);
247 start_pad
= gtk_widget_get_margin_left(widget
);
248 top_pad
= gtk_widget_get_margin_top(widget
);
250 cairo_translate(cr
, start_pad
, top_pad
);
253 cairo_scale(cr
, p
->scale
, p
->scale
);
255 cairo_set_source_surface(cr
, priv
->surface
, 0, 0);
261 /***************************************************************************
262 Get width pixcomm uses.
263 ***************************************************************************/
265 gtk_pixcomm_get_preferred_width(GtkWidget
*widget
, gint
*minimal_width
,
271 start_pad
= gtk_widget_get_margin_left(widget
);
272 end_pad
= gtk_widget_get_margin_right(widget
);
273 *minimal_width
= *natural_width
= GTK_PIXCOMM(widget
)->w
+ start_pad
+ end_pad
;
276 /***************************************************************************
277 Get height pixcomm uses.
278 ***************************************************************************/
280 gtk_pixcomm_get_preferred_height(GtkWidget
*widget
, gint
*minimal_height
,
281 gint
*natural_height
)
286 top_pad
= gtk_widget_get_margin_top(widget
);
287 bottom_pad
= gtk_widget_get_margin_bottom(widget
);
288 *minimal_height
= *natural_height
= GTK_PIXCOMM(widget
)->h
+ top_pad
+ bottom_pad
;
291 /***************************************************************************
292 Create new gtkpixcomm from sprite.
293 ***************************************************************************/
294 GtkWidget
*gtk_pixcomm_new_from_sprite(struct sprite
*sprite
)
297 GtkPixcommPrivate
*priv
;
304 p
= g_object_new(gtk_pixcomm_get_type(), NULL
);
305 priv
= GTK_PIXCOMM_GET_PRIVATE(p
);
306 get_sprite_dimensions(sprite
, &p
->w
, &p
->h
);
307 start_pad
= gtk_widget_get_margin_left(GTK_WIDGET(p
));
308 end_pad
= gtk_widget_get_margin_right(GTK_WIDGET(p
));
309 top_pad
= gtk_widget_get_margin_top(GTK_WIDGET(p
));
310 bottom_pad
= gtk_widget_get_margin_bottom(GTK_WIDGET(p
));
311 gtk_widget_set_size_request(GTK_WIDGET(p
), p
->w
+ start_pad
+ end_pad
,
312 p
->h
+ top_pad
+ bottom_pad
);
313 gtk_widget_set_halign(GTK_WIDGET(p
), GTK_ALIGN_CENTER
);
314 gtk_widget_set_valign(GTK_WIDGET(p
), GTK_ALIGN_CENTER
);
316 p
->is_scaled
= FALSE
;
319 priv
->surface
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
, p
->w
, p
->h
);
320 cr
= cairo_create(priv
->surface
);
321 cairo_set_operator(cr
, CAIRO_OPERATOR_SOURCE
);
322 cairo_set_source_surface(cr
, sprite
->surface
, 0, 0);
326 return GTK_WIDGET(p
);
329 /***************************************************************************
330 Draw sprite to gtkpixcomm. Grkpixcomm dimensions may change.
331 ***************************************************************************/
332 void gtk_pixcomm_set_from_sprite(GtkPixcomm
*p
, struct sprite
*sprite
)
334 GtkPixcommPrivate
*priv
;
337 get_sprite_dimensions(sprite
, &width
, &height
);
338 priv
= GTK_PIXCOMM_GET_PRIVATE(p
);
340 cairo_surface_destroy(priv
->surface
);
341 priv
->surface
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
, width
, height
);
342 cr
= cairo_create(priv
->surface
);
343 cairo_set_operator(cr
, CAIRO_OPERATOR_SOURCE
);
344 cairo_set_source_surface(cr
, sprite
->surface
, 0, 0);
349 gtk_widget_queue_resize(GTK_WIDGET(p
));