1 /*
2  * Copyright (c) 2003 by the gtk2-perl team (see the file AUTHORS)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301  USA.
18  *
19  * $Id$
20  */
21 
22 #include "gtk2perl.h"
23 
24 /* ------------------------------------------------------------------------- */
25 
26 SV *
newSVGdkGeometry(GdkGeometry * geometry)27 newSVGdkGeometry (GdkGeometry *geometry)
28 {
29 	HV *object = newHV ();
30 
31 	if (geometry) {
32 		gperl_hv_take_sv_s (object, "min_width", newSViv (geometry->min_width));
33 		gperl_hv_take_sv_s (object, "min_height", newSViv (geometry->min_height));
34 		gperl_hv_take_sv_s (object, "max_width", newSViv (geometry->max_width));
35 		gperl_hv_take_sv_s (object, "max_height", newSViv (geometry->max_height));
36 		gperl_hv_take_sv_s (object, "base_width", newSViv (geometry->base_width));
37 		gperl_hv_take_sv_s (object, "base_height", newSViv (geometry->base_height));
38 		gperl_hv_take_sv_s (object, "width_inc", newSViv (geometry->width_inc));
39 		gperl_hv_take_sv_s (object, "height_inc", newSViv (geometry->height_inc));
40 		gperl_hv_take_sv_s (object, "min_aspect", newSVnv (geometry->min_aspect));
41 		gperl_hv_take_sv_s (object, "max_aspect", newSVnv (geometry->max_aspect));
42 		gperl_hv_take_sv_s (object, "win_gravity", newSVGdkGravity (geometry->win_gravity));
43 	}
44 
45 	return sv_bless (newRV_noinc ((SV *) object),
46 	                 gv_stashpv ("Gtk2::Gdk::Geometry", 1));
47 }
48 
49 #define GTK2PERL_GEOMETRY_FETCH(member, key, type) \
50 	member = hv_fetch (hv, key, strlen (key), FALSE); \
51 	if (member) geometry->member = type (*member);
52 
53 GdkGeometry *
SvGdkGeometryReal(SV * object,GdkWindowHints * hints)54 SvGdkGeometryReal (SV *object, GdkWindowHints *hints)
55 {
56 	HV *hv = (HV *) SvRV (object);
57 	SV **min_width, **min_height, **max_width, **max_height, **base_width,
58 	   **base_height, **width_inc, **height_inc, **min_aspect, **max_aspect,
59 	   **win_gravity;
60 
61 	GdkGeometry *geometry = gperl_alloc_temp (sizeof (GdkGeometry));
62 	if (hints)
63 		*hints = 0;
64 
65 	if (gperl_sv_is_hash_ref (object)) {
66 		GTK2PERL_GEOMETRY_FETCH (min_width, "min_width", SvIV);
67 		GTK2PERL_GEOMETRY_FETCH (min_height, "min_height", SvIV);
68 		GTK2PERL_GEOMETRY_FETCH (max_width, "max_width", SvIV);
69 		GTK2PERL_GEOMETRY_FETCH (max_height, "max_height", SvIV);
70 		GTK2PERL_GEOMETRY_FETCH (base_width, "base_width", SvIV);
71 		GTK2PERL_GEOMETRY_FETCH (base_height, "base_height", SvIV);
72 		GTK2PERL_GEOMETRY_FETCH (width_inc, "width_inc", SvIV);
73 		GTK2PERL_GEOMETRY_FETCH (height_inc, "height_inc", SvIV);
74 		GTK2PERL_GEOMETRY_FETCH (min_aspect, "min_aspect", SvNV);
75 		GTK2PERL_GEOMETRY_FETCH (max_aspect, "max_aspect", SvNV);
76 		GTK2PERL_GEOMETRY_FETCH (win_gravity, "win_gravity", SvGdkGravity);
77 
78 		if (hints) {
79 			if (min_width && min_height)
80 				*hints |= GDK_HINT_MIN_SIZE;
81 
82 			if (max_width && max_height)
83 				*hints |= GDK_HINT_MAX_SIZE;
84 
85 			if (base_width && base_height)
86 				*hints |= GDK_HINT_BASE_SIZE;
87 
88 			if (min_aspect && max_aspect)
89 				*hints |= GDK_HINT_ASPECT;
90 
91 			if (width_inc && height_inc)
92 				*hints |= GDK_HINT_RESIZE_INC;
93 
94 			if (win_gravity)
95 				*hints |= GDK_HINT_WIN_GRAVITY;
96 		}
97 	}
98 
99 	return geometry;
100 }
101 
102 GdkGeometry *
SvGdkGeometry(SV * object)103 SvGdkGeometry (SV *object)
104 {
105 	return SvGdkGeometryReal (object, NULL);
106 }
107 
108 /* ------------------------------------------------------------------------- */
109 
110 SV *
newSVGdkAtom(GdkAtom atom)111 newSVGdkAtom (GdkAtom atom)
112 {
113 	SV * sv = newSV(0);
114 	sv_setref_pv (sv, "Gtk2::Gdk::Atom", (void*)atom);
115 	return sv;
116 }
117 
118 GdkAtom
SvGdkAtom(SV * sv)119 SvGdkAtom (SV * sv)
120 {
121 	if (!gperl_sv_is_defined (sv))
122 		return (GdkAtom)NULL;
123 	else if (sv_derived_from (sv, "Gtk2::Gdk::Atom"))
124                 return INT2PTR (GdkAtom, SvIV ((SV*)SvRV (sv)));
125         else
126                 croak ("variable is not of type Gtk2::Gdk::Atom");
127 	return (GdkAtom)NULL; /* not reached */
128 }
129 
130 MODULE = Gtk2::Gdk::Types	PACKAGE = Gtk2::Gdk::Rectangle
131 
132 GdkRectangle_copy *
133 new (class, x, y, width, height)
134 	gint x
135 	gint y
136 	gint width
137 	gint height
138     PREINIT:
139 	GdkRectangle rect;
140     CODE:
141 	rect.x = x;
142 	rect.y = y;
143 	rect.width = width;
144 	rect.height = height;
145 	RETVAL = ▭
146     OUTPUT:
147 	RETVAL
148 
149 =for apidoc Gtk2::Gdk::Rectangle::x
150 =for signature integer = $rectangle->x
151 =for signature oldvalue = $rectangle->x ($newvalue)
152 =for arg newvalue (integer)
153 =cut
154 
155 =for apidoc y
156 =for signature integer = $rectangle->y
157 =for signature oldvalue = $rectangle->y ($newvalue)
158 =for arg newvalue (integer)
159 =cut
160 
161 =for apidoc width
162 =for signature integer = $rectangle->width
163 =for signature oldvalue = $rectangle->width ($newvalue)
164 =for arg newvalue (integer)
165 =cut
166 
167 =for apidoc height
168 =for signature integer = $rectangle->height
169 =for signature oldvalue = $rectangle->height ($newvalue)
170 =for arg newvalue (integer)
171 =cut
172 
173 gint
174 x (GdkRectangle *rectangle, SV *newvalue = 0)
175     ALIAS:
176 	y = 1
177 	width = 2
178 	height = 3
179     CODE:
180 	switch (ix) {
181 		case 0: RETVAL = rectangle->x; break;
182 		case 1: RETVAL = rectangle->y; break;
183 		case 2: RETVAL = rectangle->width; break;
184 		case 3: RETVAL = rectangle->height; break;
185 		default:
186 			RETVAL = 0;
187 			g_assert_not_reached ();
188 	}
189         if (newvalue) {
190                 switch (ix) {
191                         case 0: rectangle->x      = SvIV (newvalue); break;
192                         case 1: rectangle->y      = SvIV (newvalue); break;
193                         case 2: rectangle->width  = SvIV (newvalue); break;
194                         case 3: rectangle->height = SvIV (newvalue); break;
195 			default:
196 				g_assert_not_reached ();
197                 }
198         }
199     OUTPUT:
200 	RETVAL
201 
202 =for apidoc
203 =for signature (x, y, width, height) = $rectangle->values
204 =cut
205 void
206 values (rectangle)
207 	GdkRectangle * rectangle
208     PPCODE:
209 	EXTEND (SP, 4);
210 	PUSHs (sv_2mortal (newSViv (rectangle->x)));
211 	PUSHs (sv_2mortal (newSViv (rectangle->y)));
212 	PUSHs (sv_2mortal (newSViv (rectangle->width)));
213 	PUSHs (sv_2mortal (newSViv (rectangle->height)));
214 
215 MODULE = Gtk2::Gdk::Types	PACKAGE = Gtk2::Gdk::Geometry
216 
217 GdkGeometry *
218 new (class)
219     PREINIT:
220 	GdkGeometry geometry;
221     CODE:
222 	memset (&geometry, 0, sizeof (GdkGeometry));
223 	geometry.win_gravity = GDK_GRAVITY_NORTH_WEST;
224 	RETVAL = &geometry;
225     OUTPUT:
226 	RETVAL
227 
228 SV *
229 min_width (SV *object, SV *newvalue=NULL)
230     ALIAS:
231         min_height = 1
232         max_width = 2
233         max_height = 3
234         base_width = 4
235         base_height = 5
236         width_inc = 6
237         height_inc = 7
238 	min_aspect = 8
239 	max_aspect = 9
240 	win_gravity = 10
241 	gravity = 11
242     PREINIT:
243 	SV **value = NULL;
244 	HV *geometry;
245     CODE:
246 	geometry = (HV *) SvRV (object);
247 	RETVAL = &PL_sv_undef;
248 
249 	switch (ix) {
250 		case 0: value = hv_fetch (geometry, "min_width", 9, 0); break;
251 		case 1: value = hv_fetch (geometry, "min_height", 10, 0); break;
252 		case 2: value = hv_fetch (geometry, "max_width", 9, 0); break;
253 		case 3: value = hv_fetch (geometry, "max_height", 10, 0); break;
254 		case 4: value = hv_fetch (geometry, "base_width", 10, 0); break;
255 		case 5: value = hv_fetch (geometry, "base_height", 11, 0); break;
256 		case 6: value = hv_fetch (geometry, "width_inc", 9, 0); break;
257 		case 7: value = hv_fetch (geometry, "height_inc", 10, 0); break;
258 		case 8: value = hv_fetch (geometry, "min_aspect", 10, 0); break;
259 		case 9: value = hv_fetch (geometry, "max_aspect", 10, 0); break;
260 		case 10: /* fall-through */
261 		case 11: value = hv_fetch (geometry, "win_gravity", 11, 0); break;
262 		default:
263 			g_assert_not_reached ();
264 	}
265 
266 	if (value && gperl_sv_is_defined (*value))
267 		RETVAL = newSVsv (*value);
268 
269 	if (items > 1) {
270 		newvalue = newSVsv (newvalue);
271 
272 		switch (ix) {
273 			case 0: gperl_hv_take_sv_s (geometry, "min_width", newvalue); break;
274 			case 1: gperl_hv_take_sv_s (geometry, "min_height", newvalue); break;
275 			case 2: gperl_hv_take_sv_s (geometry, "max_width", newvalue); break;
276 			case 3: gperl_hv_take_sv_s (geometry, "max_height", newvalue); break;
277 			case 4: gperl_hv_take_sv_s (geometry, "base_width", newvalue); break;
278 			case 5: gperl_hv_take_sv_s (geometry, "base_height", newvalue); break;
279 			case 6: gperl_hv_take_sv_s (geometry, "width_inc", newvalue); break;
280 			case 7: gperl_hv_take_sv_s (geometry, "height_inc", newvalue); break;
281 			case 8: gperl_hv_take_sv_s (geometry, "min_aspect", newvalue); break;
282 			case 9: gperl_hv_take_sv_s (geometry, "max_aspect", newvalue); break;
283 			case 10: /* fall-through */
284 			case 11: gperl_hv_take_sv_s (geometry, "win_gravity", newvalue); break;
285 			default:
286 				g_assert_not_reached ();
287 		}
288 	}
289     OUTPUT:
290 	RETVAL
291 
292 ## moved here because it makes plain sense
293 =for apidoc
294 
295 =for signature (new_width, new_height) = $geometry->constrain_size ($width, $height)
296 =for signature (new_width, new_height) = $geometry->constrain_size ($flags, $width, $height)
297 
298 =for arg flags (Gtk2::Gdk::WindowHints) optional, usually inferred from I<$geometry>
299 
300 The $flags argument, describing which fields in the geometry are valid, is
301 optional.  If omitted it will be inferred from the geometry itself.
302 
303 =cut
304 ## void gdk_window_constrain_size (GdkGeometry *geometry, guint flags, gint width, gint height, gint *new_width, gint *new_height)
305 void
306 constrain_size (geometry_ref, ...)
307 	SV *geometry_ref
308     PREINIT:
309 	GdkGeometry *geometry;
310 	GdkWindowHints flags;
311 	gint width;
312 	gint height;
313 	gint new_width;
314 	gint new_height;
315     PPCODE:
316 	if (items == 4) {
317 		if (!gperl_sv_is_defined (ST (1)))
318 			warn ("Warning: You passed undef for the flags parameter.  Consider simply omitting it instead.");
319 
320 		geometry = SvGdkGeometry (geometry_ref);
321 		flags = SvGdkWindowHints (ST (1));
322 		width = SvIV (ST (2));
323 		height = SvIV (ST (3));
324 	} else if (items == 3) {
325 		geometry = SvGdkGeometryReal (geometry_ref, &flags);
326 		width = SvIV (ST (1));
327 		height = SvIV (ST (2));
328 	} else {
329 		croak ("Usage: Gtk2::Gdk::Geometry::constrain_size(geometry, width, height) or Gtk2::Gdk::Geometry::constrain_size(geometry, flags, width, height)");
330 	}
331 
332 	gdk_window_constrain_size (geometry, flags, width, height, &new_width, &new_height);
333 	EXTEND (SP, 2);
334 	PUSHs (sv_2mortal (newSViv (new_width)));
335 	PUSHs (sv_2mortal (newSViv (new_height)));
336 
337