comparison src/glyphs-widget.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children d7a9135ec789
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
53 Lisp_Object Qtree_view; 53 Lisp_Object Qtree_view;
54 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab_control); 54 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab_control);
55 Lisp_Object Qtab_control; 55 Lisp_Object Qtab_control;
56 DEFINE_IMAGE_INSTANTIATOR_FORMAT (layout); 56 DEFINE_IMAGE_INSTANTIATOR_FORMAT (layout);
57 Lisp_Object Qlayout; 57 Lisp_Object Qlayout;
58 58 DEFINE_IMAGE_INSTANTIATOR_FORMAT (native_layout);
59 Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items; 59 Lisp_Object Qnative_layout;
60 Lisp_Object Q_image, Q_text, Q_percent, Q_orientation, Q_justify, Q_border; 60
61 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; 61 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out;
62 Lisp_Object Qmake_glyph;
62 63
63 #ifdef DEBUG_WIDGETS 64 #ifdef DEBUG_WIDGETS
64 int debug_widget_instances; 65 int debug_widget_instances;
65 #endif 66 #endif
66 67
80 { 81 {
81 return IMAGE_WIDGET_MASK; 82 return IMAGE_WIDGET_MASK;
82 } 83 }
83 84
84 static void 85 static void
85 check_valid_glyph_or_instantiator (Lisp_Object data) 86 check_valid_instantiator (Lisp_Object data)
86 { 87 {
87 Lisp_Object glyph = data; 88 Lisp_Object glyph = data;
88 if (SYMBOLP (data)) 89 if (SYMBOLP (data))
89 glyph = XSYMBOL (data)->value; 90 glyph = XSYMBOL (data)->value;
90 91
91 if (IMAGE_INSTANCEP (glyph)) 92 if (!CONSP (glyph) && !VECTORP (glyph))
92 CHECK_IMAGE_INSTANCE (glyph); 93 invalid_argument ("instantiator item must be a vector", data);
93 else if (!CONSP (glyph) && !VECTORP (glyph))
94 CHECK_BUFFER_GLYPH (glyph);
95 } 94 }
96 95
97 static void 96 static void
98 check_valid_orientation (Lisp_Object data) 97 check_valid_orientation (Lisp_Object data)
99 { 98 {
100 if (!EQ (data, Qhorizontal) 99 if (!EQ (data, Qhorizontal)
101 && 100 &&
102 !EQ (data, Qvertical)) 101 !EQ (data, Qvertical))
103 signal_simple_error ("unknown orientation for layout", data); 102 invalid_argument ("unknown orientation for layout", data);
104 } 103 }
105 104
106 static void 105 static void
107 check_valid_tab_orientation (Lisp_Object data) 106 check_valid_tab_orientation (Lisp_Object data)
108 { 107 {
111 !EQ (data, Qbottom) 110 !EQ (data, Qbottom)
112 && 111 &&
113 !EQ (data, Qleft) 112 !EQ (data, Qleft)
114 && 113 &&
115 !EQ (data, Qright)) 114 !EQ (data, Qright))
116 signal_simple_error ("unknown orientation for tab control", data); 115 invalid_argument ("unknown orientation for tab control", data);
117 } 116 }
118 117
119 static void 118 static void
120 check_valid_justification (Lisp_Object data) 119 check_valid_justification (Lisp_Object data)
121 { 120 {
122 if (!EQ (data, Qleft) && !EQ (data, Qright) && !EQ (data, Qcenter)) 121 if (!EQ (data, Qleft) && !EQ (data, Qright) && !EQ (data, Qcenter))
123 signal_simple_error ("unknown justification for layout", data); 122 invalid_argument ("unknown justification for layout", data);
124 } 123 }
125 124
126 static void 125 static void
127 check_valid_border (Lisp_Object data) 126 check_valid_border (Lisp_Object data)
128 { 127 {
129 if (!EQ (data, Qt) && !EQ (data, Qetched_in) && !EQ (data, Qetched_out) 128 if (!EQ (data, Qt) && !EQ (data, Qetched_in) && !EQ (data, Qetched_out)
130 && !EQ (data, Qbevel_in) && !EQ (data, Qbevel_out) 129 && !EQ (data, Qbevel_in) && !EQ (data, Qbevel_out)
131 && !GLYPHP (data) && !VECTORP (data)) 130 && !GLYPHP (data) && !VECTORP (data))
132 signal_simple_error ("unknown border style for layout", data); 131 invalid_argument ("unknown border style for layout", data);
133 } 132 }
134 133
135 static void 134 static void
136 check_valid_anything (Lisp_Object data) 135 check_valid_anything (Lisp_Object data)
137 { 136 {
142 { 141 {
143 if (!SYMBOLP (data) 142 if (!SYMBOLP (data)
144 && !COMPILED_FUNCTIONP (data) 143 && !COMPILED_FUNCTIONP (data)
145 && !CONSP (data)) 144 && !CONSP (data))
146 { 145 {
147 signal_simple_error (":callback must be a function or expression", data); 146 invalid_argument (":callback must be a function or expression", data);
148 } 147 }
148 }
149
150 static void
151 check_valid_int_or_function (Lisp_Object data)
152 {
153 if (!INTP (data) && !CONSP (data))
154 invalid_argument ("must be an integer or expresssion", data);
149 } 155 }
150 156
151 static void 157 static void
152 check_valid_symbol (Lisp_Object data) 158 check_valid_symbol (Lisp_Object data)
153 { 159 {
156 162
157 static void 163 static void
158 check_valid_string_or_vector (Lisp_Object data) 164 check_valid_string_or_vector (Lisp_Object data)
159 { 165 {
160 if (!STRINGP (data) && !VECTORP (data)) 166 if (!STRINGP (data) && !VECTORP (data))
161 signal_simple_error (":descriptor must be a string or a vector", data); 167 invalid_argument (":descriptor must be a string or a vector", data);
162 } 168 }
163 169
164 void 170 void
165 check_valid_item_list_1 (Lisp_Object items) 171 check_valid_item_list (Lisp_Object items)
166 { 172 {
167 Lisp_Object rest; 173 Lisp_Object rest;
168 174
169 CHECK_LIST (items); 175 CHECK_LIST (items);
170 EXTERNAL_LIST_LOOP (rest, items) 176 EXTERNAL_LIST_LOOP (rest, items)
172 if (STRINGP (XCAR (rest))) 178 if (STRINGP (XCAR (rest)))
173 CHECK_STRING (XCAR (rest)); 179 CHECK_STRING (XCAR (rest));
174 else if (VECTORP (XCAR (rest))) 180 else if (VECTORP (XCAR (rest)))
175 gui_parse_item_keywords (XCAR (rest)); 181 gui_parse_item_keywords (XCAR (rest));
176 else if (LISTP (XCAR (rest))) 182 else if (LISTP (XCAR (rest)))
177 check_valid_item_list_1 (XCAR (rest)); 183 check_valid_item_list (XCAR (rest));
178 else 184 else
179 signal_simple_error ("Items must be vectors, lists or strings", items); 185 invalid_argument ("Items must be vectors, lists or strings", items);
180 } 186 }
181 } 187 }
182 188
183 static void 189 static void
184 check_valid_item_list (Lisp_Object data) 190 check_valid_instantiator_list (Lisp_Object data)
185 {
186 Lisp_Object items;
187
188 Fcheck_valid_plist (data);
189 items = Fplist_get (data, Q_items, Qnil);
190
191 check_valid_item_list_1 (items);
192 }
193
194 static void
195 check_valid_glyph_or_instantiator_list (Lisp_Object data)
196 { 191 {
197 Lisp_Object rest; 192 Lisp_Object rest;
198 193
199 CHECK_LIST (data); 194 CHECK_LIST (data);
200 EXTERNAL_LIST_LOOP (rest, data) 195 EXTERNAL_LIST_LOOP (rest, data)
201 { 196 {
202 check_valid_glyph_or_instantiator (XCAR (rest)); 197 check_valid_instantiator (XCAR (rest));
203 } 198 }
204 } 199 }
205 200
206 static Lisp_Object 201 static Lisp_Object
207 glyph_instantiator_to_glyph (Lisp_Object sym) 202 glyph_instantiator_to_glyph (Lisp_Object sym)
208 { 203 {
209 /* This function calls lisp. */ 204 /* This function calls lisp. */
210 Lisp_Object glyph = sym; 205 Lisp_Object glyph = sym;
211 struct gcpro gcpro1; 206 struct gcpro gcpro1;
212 207
213 GCPRO1 (glyph); 208 GCPRO1 (glyph);
214 /* if we have a symbol get at the actual data */ 209 /* if we have a symbol get at the actual data */
215 if (SYMBOLP (glyph)) 210 if (SYMBOLP (glyph))
216 glyph = XSYMBOL (glyph)->value; 211 glyph = XSYMBOL (glyph)->value;
217 212
218 if (CONSP (glyph)) 213 if (CONSP (glyph))
219 glyph = Feval (glyph); 214 glyph = Feval (glyph);
220 215
221 /* Be really helpful to the user. */ 216 /* Be really helpful to the user. */
222 if (VECTORP (glyph)) 217 if (VECTORP (glyph))
223 { 218 {
224 glyph = call1 (intern ("make-glyph"), glyph); 219 glyph = call1 (Qmake_glyph, glyph);
225 } 220 }
226 221
227 /* substitute the new glyph */ 222 /* substitute the new glyph */
228 RETURN_UNGCPRO (glyph); 223 RETURN_UNGCPRO (glyph);
229 } 224 }
230 225
231 static void 226 static void
232 substitute_keyword_value (Lisp_Object inst, Lisp_Object key, Lisp_Object val) 227 substitute_keyword_value (Lisp_Object inst, Lisp_Object key, Lisp_Object val)
233 { 228 {
234 int i; 229 int i;
235 /* substitute the new glyph */ 230 /* substitute the new glyph */
236 for (i = 0; i < XVECTOR_LENGTH (inst); i++) 231 for (i = 0; i < XVECTOR_LENGTH (inst); i++)
252 field. widget_property gets invoked by decoding the primary type 247 field. widget_property gets invoked by decoding the primary type
253 (Qwidget), <widget>_property then invokes based on the secondary 248 (Qwidget), <widget>_property then invokes based on the secondary
254 type (Qedit_field for example). It is debatable whether we should 249 type (Qedit_field for example). It is debatable whether we should
255 wire things in this generalised way rather than treating widgets 250 wire things in this generalised way rather than treating widgets
256 specially in image_instance_property. */ 251 specially in image_instance_property. */
257 static Lisp_Object 252 static Lisp_Object
258 widget_property (Lisp_Object image_instance, Lisp_Object prop) 253 widget_property (Lisp_Object image_instance, Lisp_Object prop)
259 { 254 {
260 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); 255 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
261 struct image_instantiator_methods* meths; 256 struct image_instantiator_methods* meths;
262 257 #if 0 /* The usefulness of this is dubious. */
263 /* first see if its a general property ... */ 258 /* first see if its a general property ... */
264 if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop))) 259 if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop)))
265 return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil); 260 return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
266 261 #endif
267 /* .. then try device specific methods ... */ 262 /* .. then try device specific methods ... */
268 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 263 meths = decode_device_ii_format (image_instance_device (image_instance),
269 IMAGE_INSTANCE_WIDGET_TYPE (ii), 264 IMAGE_INSTANCE_WIDGET_TYPE (ii),
270 ERROR_ME_NOT); 265 ERROR_ME_NOT);
271 if (meths && HAS_IIFORMAT_METH_P (meths, property)) 266 if (meths && HAS_IIFORMAT_METH_P (meths, property))
272 return IIFORMAT_METH (meths, property, (image_instance, prop)); 267 return IIFORMAT_METH (meths, property, (image_instance, prop));
273 /* ... then format specific methods ... */ 268 /* ... then format specific methods ... */
274 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 269 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
275 ERROR_ME_NOT); 270 ERROR_ME_NOT);
276 if (meths && HAS_IIFORMAT_METH_P (meths, property)) 271 if (meths && HAS_IIFORMAT_METH_P (meths, property))
277 return IIFORMAT_METH (meths, property, (image_instance, prop)); 272 return IIFORMAT_METH (meths, property, (image_instance, prop));
278 /* ... then fail */ 273 /* ... then fail */
279 return Qunbound; 274 return Qunbound;
280 } 275 }
281 276
282 static Lisp_Object 277 /* Update the displayed properties of a widget.
283 widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object val) 278
279 #### This has been adapted from the original set_property functions
280 and thus reuses the state management of that. A better solution is
281 to simply re-parse the instantiator when items need updating. This
282 make comparing differences much simpler and obviates the need for a
283 lot of the state variables.
284
285 #### property is still a valid function since we have to be able to
286 extract information from the actual widget.
287
288 #### update_widget should probably be re-written to use the
289 instantiator. We probably want to keep a record of the differences
290 also to make this easy. We would also need a pending_instantiator
291 so that changes could be delayed. */
292 static void
293 widget_update (Lisp_Object image_instance, Lisp_Object instantiator)
284 { 294 {
285 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); 295 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
286 struct image_instantiator_methods* meths; 296 struct image_instantiator_methods* meths;
287 Lisp_Object ret; 297
288 298 Lisp_Object text = find_keyword_in_vector (instantiator, Q_text);
289 /* PIck up any generic properties that we might need to keep hold 299 /* Pick up any generic properties that we might need to keep hold
290 of. */ 300 of. */
291 if (EQ (prop, Q_text)) 301 if (!NILP (text))
292 { 302 {
293 IMAGE_INSTANCE_WIDGET_TEXT (ii) = val; 303 IMAGE_INSTANCE_WIDGET_TEXT (ii) = text;
304 IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1;
294 } 305 }
295 306
296 /* Now try device specific methods first ... */ 307 /* Now try device specific methods first ... */
297 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 308 meths = decode_device_ii_format (image_instance_device (image_instance),
309 IMAGE_INSTANCE_WIDGET_TYPE (ii),
310 ERROR_ME_NOT);
311 MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
312 /* ... then format specific methods ... */
313 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
314 ERROR_ME_NOT);
315 MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
316 #if 0 /* The usefulness of this is dubious. */
317 /* we didn't do any device specific properties, so shove the property in our plist. */
318 IMAGE_INSTANCE_WIDGET_PROPS (ii)
319 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
320 #endif
321 }
322
323 /* Like the rest of redisplay, we want widget updates to occur
324 asynchronously. Thus toolkit specific methods for setting
325 properties must be called by redisplay instead of by *_update. Thus
326 *_update records the change and this function actually implements
327 it. We want to be slightly clever about this however by supplying
328 format specific functions for the updates instead of lumping them
329 all into this function. Note that there is no need for format
330 generic functions. This is not the same as widget_update! */
331 void
332 redisplay_widget (Lisp_Object widget)
333 {
334 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget);
335 struct image_instantiator_methods* meths;
336
337 if (!WIDGET_IMAGE_INSTANCEP (widget)
338 || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
339 || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
340 return;
341
342 /* Device-format specific methods - e.g. x_tab_control_redisplay () */
343 meths = decode_device_ii_format (image_instance_device (widget),
298 IMAGE_INSTANCE_WIDGET_TYPE (ii), 344 IMAGE_INSTANCE_WIDGET_TYPE (ii),
299 ERROR_ME_NOT); 345 ERROR_ME_NOT);
300 if (meths && HAS_IIFORMAT_METH_P (meths, set_property) 346 MAYBE_IIFORMAT_METH (meths, redisplay, (widget));
301 && 347
302 !UNBOUNDP (ret = 348 /* Device generic methods - e.g. x_redisplay_widget (). We must
303 IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) 349 update the widget's size as it may have been changed by the the
304 { 350 layout routines. We also do this here so that explicit resizing
305 return ret; 351 from lisp does not result in synchronous updates. Do this last so
306 } 352 that format-specific methods have an opportunity to prevent
307 /* ... then format specific methods ... */ 353 wholesale changes - e.g. rebuilding tabs. */
308 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 354 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), redisplay_widget, (ii));
309 ERROR_ME_NOT); 355
310 if (meths && HAS_IIFORMAT_METH_P (meths, set_property) 356 /* Pick up the items we recorded earlier. */
311 && 357 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
312 !UNBOUNDP (ret = 358 {
313 IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) 359 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
314 { 360 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii);
315 return ret; 361 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
316 } 362 }
317 /* we didn't do any device specific properties, so shove the property in our plist */
318 IMAGE_INSTANCE_WIDGET_PROPS (ii)
319 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
320 return val;
321 } 363 }
322 364
323 /* Query for a widgets desired geometry. If no type specific method is 365 /* Query for a widgets desired geometry. If no type specific method is
324 provided then use the widget text to calculate sizes. */ 366 provided then use the widget text to calculate sizes. */
325 static void 367 static void
326 widget_query_geometry (Lisp_Object image_instance, 368 widget_query_geometry (Lisp_Object image_instance,
327 unsigned int* width, unsigned int* height, 369 int* width, int* height,
328 enum image_instance_geometry disp, Lisp_Object domain) 370 enum image_instance_geometry disp, Lisp_Object domain)
329 { 371 {
330 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); 372 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
331 struct image_instantiator_methods* meths; 373 struct image_instantiator_methods* meths;
374 Lisp_Object dynamic_width = Qnil;
375 Lisp_Object dynamic_height = Qnil;
332 376
333 /* First just set up what we already have. */ 377 /* First just set up what we already have. */
334 if (width) *width = IMAGE_INSTANCE_WIDTH (ii); 378 if (width) *width = IMAGE_INSTANCE_WIDTH (ii);
335 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii); 379 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
336 380
337 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) 381 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
338 || 382 ||
339 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) 383 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
340 { 384 {
341 /* .. then try device specific methods ... */ 385 /* .. then try device specific methods ... */
342 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 386 meths = decode_device_ii_format (image_instance_device (image_instance),
343 IMAGE_INSTANCE_WIDGET_TYPE (ii), 387 IMAGE_INSTANCE_WIDGET_TYPE (ii),
344 ERROR_ME_NOT); 388 ERROR_ME_NOT);
345 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) 389 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
346 IIFORMAT_METH (meths, query_geometry, (image_instance, 390 IIFORMAT_METH (meths, query_geometry, (image_instance,
347 width, height, disp, 391 width, height, disp,
348 domain)); 392 domain));
349 else 393 else
350 { 394 {
351 /* ... then format specific methods ... */ 395 /* ... then format specific methods ... */
352 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 396 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
353 ERROR_ME_NOT); 397 ERROR_ME_NOT);
354 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) 398 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
355 IIFORMAT_METH (meths, query_geometry, (image_instance, 399 IIFORMAT_METH (meths, query_geometry, (image_instance,
356 width, height, disp, 400 width, height, disp,
357 domain)); 401 domain));
358 else 402 else
359 { 403 {
360 unsigned int w, h; 404 int w, h;
361 405
362 /* Then if we are allowed to resize the widget, make the 406 /* Then if we are allowed to resize the widget, make the
363 size the same as the text dimensions. */ 407 size the same as the text dimensions. */
364 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), 408 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
365 IMAGE_INSTANCE_WIDGET_FACE (ii), 409 IMAGE_INSTANCE_WIDGET_FACE (ii),
366 &w, &h, 0, domain); 410 &w, &h, 0, domain);
369 *width = w + 2 * WIDGET_BORDER_WIDTH; 413 *width = w + 2 * WIDGET_BORDER_WIDTH;
370 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) 414 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
371 *height = h + 2 * WIDGET_BORDER_HEIGHT; 415 *height = h + 2 * WIDGET_BORDER_HEIGHT;
372 } 416 }
373 } 417 }
374 } 418 /* Finish off with dynamic sizing. */
375 } 419 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
376 420 {
377 static void 421 dynamic_width = Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
378 widget_layout (Lisp_Object image_instance, 422 if (INTP (dynamic_width))
379 unsigned int width, unsigned int height, Lisp_Object domain) 423 *width = XINT (dynamic_width);
424 }
425 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
426 {
427 dynamic_height = Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
428 if (INTP (dynamic_height))
429 *height = XINT (dynamic_height);
430 }
431 }
432 }
433
434 static int
435 widget_layout (Lisp_Object image_instance,
436 int width, int height, int xoffset, int yoffset,
437 Lisp_Object domain)
380 { 438 {
381 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); 439 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
382 struct image_instantiator_methods* meths; 440 struct image_instantiator_methods* meths;
383 441
384 /* .. then try device specific methods ... */ 442 /* .. then try device specific methods ... */
385 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 443 meths = decode_device_ii_format (image_instance_device (image_instance),
386 IMAGE_INSTANCE_WIDGET_TYPE (ii), 444 IMAGE_INSTANCE_WIDGET_TYPE (ii),
387 ERROR_ME_NOT); 445 ERROR_ME_NOT);
388 if (meths && HAS_IIFORMAT_METH_P (meths, layout)) 446 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
389 IIFORMAT_METH (meths, layout, (image_instance, 447 return IIFORMAT_METH (meths, layout, (image_instance,
390 width, height, domain)); 448 width, height, xoffset, yoffset,
449 domain));
391 else 450 else
392 { 451 {
393 /* ... then format specific methods ... */ 452 /* ... then format specific methods ... */
394 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 453 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
395 ERROR_ME_NOT); 454 ERROR_ME_NOT);
396 if (meths && HAS_IIFORMAT_METH_P (meths, layout)) 455 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
397 IIFORMAT_METH (meths, layout, (image_instance, 456 return IIFORMAT_METH (meths, layout, (image_instance,
398 width, height, domain)); 457 width, height, xoffset, yoffset,
399 } 458 domain));
459 }
460 return 1;
400 } 461 }
401 462
402 static void 463 static void
403 widget_validate (Lisp_Object instantiator) 464 widget_validate (Lisp_Object instantiator)
404 { 465 {
405 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor); 466 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
406 467
407 if (NILP (desc)) 468 if (NILP (desc))
408 signal_simple_error ("Must supply :descriptor", instantiator); 469 syntax_error ("Must supply :descriptor", instantiator);
409 470
410 if (VECTORP (desc)) 471 if (VECTORP (desc))
411 gui_parse_item_keywords (desc); 472 gui_parse_item_keywords (desc);
412 473
413 if (!NILP (find_keyword_in_vector (instantiator, Q_width)) 474 if (!NILP (find_keyword_in_vector (instantiator, Q_width))
414 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width))) 475 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
415 signal_simple_error ("Must supply only one of :width and :pixel-width", instantiator); 476 syntax_error ("Must supply only one of :width and :pixel-width", instantiator);
416 477
417 if (!NILP (find_keyword_in_vector (instantiator, Q_height)) 478 if (!NILP (find_keyword_in_vector (instantiator, Q_height))
418 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height))) 479 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
419 signal_simple_error ("Must supply only one of :height and :pixel-height", instantiator); 480 syntax_error ("Must supply only one of :height and :pixel-height", instantiator);
420 } 481 }
421 482
422 static void 483 static void
423 combo_box_validate (Lisp_Object instantiator) 484 combo_box_validate (Lisp_Object instantiator)
424 { 485 {
425 widget_validate (instantiator); 486 widget_validate (instantiator);
426 if (NILP (find_keyword_in_vector (instantiator, Q_properties))) 487 if (NILP (find_keyword_in_vector (instantiator, Q_items)))
427 signal_simple_error ("Must supply item list", instantiator); 488 syntax_error ("Must supply item list", instantiator);
428 } 489 }
429 490
430 /* we need to convert things like glyphs to images, eval expressions 491 /* we need to convert things like glyphs to images, eval expressions
431 etc.*/ 492 etc.*/
432 static Lisp_Object 493 static Lisp_Object
433 widget_normalize (Lisp_Object inst, Lisp_Object console_type) 494 widget_normalize (Lisp_Object inst, Lisp_Object console_type,
495 Lisp_Object dest_mask)
434 { 496 {
435 /* This function can call lisp */ 497 /* This function can call lisp */
436 Lisp_Object glyph = find_keyword_in_vector (inst, Q_image); 498 Lisp_Object glyph = find_keyword_in_vector (inst, Q_image);
437 499
438 /* we need to eval glyph if its an expression, we do this for the 500 /* we need to eval glyph if its an expression, we do this for the
439 same reasons we normalize file to data. */ 501 same reasons we normalize file to data.
502
503 #### should just normalize the data. */
440 if (!NILP (glyph)) 504 if (!NILP (glyph))
441 { 505 {
442 substitute_keyword_value (inst, Q_image, glyph_instantiator_to_glyph (glyph)); 506 substitute_keyword_value (inst, Q_image, glyph_instantiator_to_glyph (glyph));
443 } 507 }
444 508
451 /* initialize_subwindow_image_instance (ii);*/ 515 /* initialize_subwindow_image_instance (ii);*/
452 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type; 516 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
453 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil; 517 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
454 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil); 518 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
455 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item (); 519 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
520 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Qnil;
521 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
522 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil;
523 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil;
456 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1; 524 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1;
457 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1; 525 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1;
458 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 0; 526 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL;
459 IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0; 527 IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0;
460 } 528 }
461 529
462 /* Instantiate a button widget. Unfortunately instantiated widgets are 530 /* Instantiate a button widget. Unfortunately instantiated widgets are
463 particular to a frame since they need to have a parent. It's not 531 particular to a frame since they need to have a parent. It's not
468 void 536 void
469 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 537 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
470 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 538 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
471 int dest_mask, Lisp_Object domain) 539 int dest_mask, Lisp_Object domain)
472 { 540 {
541 /* #### practically all of this should be moved to widget_update()
542 so that users can dynamically change all possible widget
543 properties. */
473 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 544 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
474 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face); 545 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
475 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height); 546 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
476 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width); 547 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
477 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width); 548 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
478 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height); 549 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
479 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor); 550 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
480 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image); 551 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
481 Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties);
482 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); 552 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
483 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation); 553 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
554 Lisp_Object mwidth = find_keyword_in_vector (instantiator, Q_margin_width);
555 Lisp_Object ifocus = find_keyword_in_vector (instantiator, Q_initial_focus);
484 int pw=0, ph=0, tw=0, th=0; 556 int pw=0, ph=0, tw=0, th=0;
485 557
486 /* this just does pixel type sizing */ 558 /* this just does pixel type sizing */
487 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, 559 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
488 dest_mask, domain); 560 dest_mask, domain);
489 561
490 if (!(dest_mask & (IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK))) 562 if (!(dest_mask & IMAGE_WIDGET_MASK))
491 incompatible_image_types (instantiator, dest_mask, 563 incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK);
492 IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK);
493 564
494 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]); 565 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
495 566
496 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET; 567 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
497 IMAGE_INSTANCE_WIDGET_PROPS (ii) = props;
498 568
499 /* retrieve the fg and bg colors */ 569 /* retrieve the fg and bg colors */
500 if (!NILP (face)) 570 if (!NILP (face))
501 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face)); 571 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
502 572
503 /* Do layout specific initialisation. This feels a bit tacky, but
504 the alternative is a myriad of different little functions. */
505 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
506 {
507 Lisp_Object rest, children = Qnil;
508 Lisp_Object border = find_keyword_in_vector (instantiator, Q_border);
509
510 if (NILP (orient))
511 {
512 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
513 }
514 IMAGE_INSTANCE_TYPE (ii) = IMAGE_LAYOUT;
515
516 if (EQ (border, Qt))
517 {
518 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
519 }
520 else if (GLYPHP (border))
521 {
522 /* We are going to be sneaky here and add the border text as
523 just another child, the layout and output routines don't know
524 this and will just display at the offsets we prescribe. */
525 children = Fcons (glyph_image_instance (border, domain, ERROR_ME, 1),
526 children);
527 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
528 }
529 else
530 {
531 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border;
532 }
533
534 /* Pick up the sub-widgets. */
535 LIST_LOOP (rest, items)
536 {
537 /* make sure the image is instantiated */
538 Lisp_Object gii = glyph_image_instance (XCAR (rest), domain, ERROR_ME, 1);
539 children = Fcons (gii, children);
540 /* Make sure elements in the layout are in the order the
541 user expected. */
542 children = Fnreverse (children);
543 }
544 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children;
545 }
546 /* retrieve the gui item information. This is easy if we have been 573 /* retrieve the gui item information. This is easy if we have been
547 provided with a vector, more difficult if we have just been given 574 provided with a vector, more difficult if we have just been given
548 keywords */ 575 keywords */
549 else if (STRINGP (desc) || NILP (desc)) 576 if (STRINGP (desc) || NILP (desc))
550 { 577 {
551 /* big cheat - we rely on the fact that a gui item looks like an instantiator */ 578 /* big cheat - we rely on the fact that a gui item looks like an instantiator */
552 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 579 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
553 gui_parse_item_keywords_no_errors (instantiator); 580 gui_parse_item_keywords_no_errors (instantiator);
554 IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc; 581 IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
555 } 582 }
556 else 583 else
557 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 584 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
558 gui_parse_item_keywords_no_errors (desc); 585 gui_parse_item_keywords_no_errors (desc);
559 586
560 /* Pick up the orientation before we do our first layout. */ 587 /* Pick up the orientation before we do our first layout. */
561 if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical)) 588 if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
562 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 1; 589 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
563 590
564 /* parse more gui items out of the properties */ 591 /* parse more gui items out of the properties */
565 if (!NILP (props) 592 if (!NILP (items) && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
566 && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)) 593 && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
567 { 594 {
568 if (NILP (items)) 595 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
569 { 596 Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
570 items = Fplist_get (props, Q_items, Qnil); 597 parse_gui_item_tree_children (items));
571 }
572 if (!NILP (items))
573 {
574 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
575 Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
576 parse_gui_item_tree_children (items));
577 }
578 } 598 }
579 599
580 /* Normalize size information. We now only assign sizes if the user 600 /* Normalize size information. We now only assign sizes if the user
581 gives us some explicitly, or there are some constraints that we 601 gives us some explicitly, or there are some constraints that we
582 can't change later on. Otherwise we postpone sizing until query 602 can't change later on. Otherwise we postpone sizing until query
583 geometry gets called. */ 603 geometry gets called. */
584 if (!NILP (pixwidth)) /* pixwidth takes precendent */ 604 if (!NILP (pixwidth)) /* pixwidth takes precendent */
585 { 605 {
586 pw = XINT (pixwidth); 606 if (!INTP (pixwidth))
587 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; 607 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = pixwidth;
608 else
609 {
610 pw = XINT (pixwidth);
611 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
612 }
588 } 613 }
589 else if (!NILP (width)) 614 else if (!NILP (width))
590 { 615 {
591 tw = XINT (width); 616 tw = XINT (width);
592 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; 617 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
593 } 618 }
594 619
595 if (!NILP (pixheight)) 620 if (!NILP (pixheight))
596 { 621 {
597 ph = XINT (pixheight); 622 if (!INTP (pixheight))
598 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; 623 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = pixheight;
624 else
625 {
626 ph = XINT (pixheight);
627 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
628 }
599 } 629 }
600 else if (!NILP (height) && XINT (height) > 1) 630 else if (!NILP (height) && XINT (height) > 1)
601 { 631 {
602 th = XINT (height); 632 th = XINT (height);
603 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; 633 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
620 650
621 /* for a widget with an image pick up the dimensions from that */ 651 /* for a widget with an image pick up the dimensions from that */
622 if (!NILP (glyph)) 652 if (!NILP (glyph))
623 { 653 {
624 if (!pw) 654 if (!pw)
625 pw = glyph_width (glyph, domain) + 2 * WIDGET_BORDER_WIDTH; 655 pw = glyph_width (glyph, image_instance) + 2 * WIDGET_BORDER_WIDTH;
626 if (!ph) 656 if (!ph)
627 ph = glyph_height (glyph, domain) + 2 * WIDGET_BORDER_HEIGHT; 657 ph = glyph_height (glyph, image_instance) + 2 * WIDGET_BORDER_HEIGHT;
628 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; 658 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
629 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; 659 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
630 } 660 }
631 661
632 /* When we create the widgets the window system expects a valid 662 /* Pick up the margin width. */
633 size, so If we still don' t have sizes, call layout to pick them 663 if (!NILP (mwidth))
634 up. If query_geometry or layout relies on the widget being in 664 IMAGE_INSTANCE_MARGIN_WIDTH (ii) = XINT (mwidth);
635 existence then we are in catch 22. */ 665
636 image_instance_layout (image_instance, 666 IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (ii) = !NILP (ifocus);
637 pw ? pw : IMAGE_UNSPECIFIED_GEOMETRY, 667
638 ph ? ph : IMAGE_UNSPECIFIED_GEOMETRY, 668 /* Layout for the layout widget is premature at this point since the
639 domain); 669 children will not have been instantiated. We can't instantiate
640 /* Layout has already been done so we don't need to re-layout. */ 670 them until the device instantiation method for the layout has
641 IMAGE_INSTANCE_DIRTYP (ii) = 0; 671 been executed. We do however want to record any specified
642 672 dimensions. */
673 if (pw) IMAGE_INSTANCE_WIDTH (ii) = pw;
674 if (ph) IMAGE_INSTANCE_HEIGHT (ii) = ph;
675 }
676
677 static void
678 widget_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
679 Lisp_Object domain)
680 {
643 #ifdef DEBUG_WIDGETS 681 #ifdef DEBUG_WIDGETS
644 debug_widget_instances++; 682 debug_widget_instances++;
645 stderr_out ("instantiated "); 683 stderr_out ("instantiated ");
646 debug_print (instantiator); 684 debug_print (instantiator);
647 stderr_out ("%d widgets instantiated\n", debug_widget_instances); 685 stderr_out ("%d widgets instantiated\n", debug_widget_instances);
648 #endif 686 #endif
649 } 687 }
650 688
689 /* Get the geometry of a button control. We need to adjust the size
690 depending on the type of button. */
691 static void
692 button_query_geometry (Lisp_Object image_instance,
693 int* width, int* height,
694 enum image_instance_geometry disp, Lisp_Object domain)
695 {
696 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
697 int w, h;
698 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
699 IMAGE_INSTANCE_WIDGET_FACE (ii),
700 &w, &h, 0, domain);
701 /* Adjust the size for borders. */
702 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
703 {
704 *width = w + 2 * WIDGET_BORDER_WIDTH;
705
706 if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio)
707 ||
708 EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qtoggle))
709 /* This is an approximation to the size of the actual button bit. */
710 *width += 12;
711 }
712 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
713 *height = h + 2 * WIDGET_BORDER_HEIGHT;
714 }
715
651 /* tree-view geometry - get the height right */ 716 /* tree-view geometry - get the height right */
652 static void 717 static void
653 tree_view_query_geometry (Lisp_Object image_instance, 718 tree_view_query_geometry (Lisp_Object image_instance,
654 unsigned int* width, unsigned int* height, 719 int* width, int* height,
655 enum image_instance_geometry disp, Lisp_Object domain) 720 enum image_instance_geometry disp, Lisp_Object domain)
656 { 721 {
657 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 722 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
658 Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii); 723 Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
659 724
660 725
661 if (*width) 726 if (*width)
662 { 727 {
663 /* #### what should this be. reconsider when X has tree views. */ 728 /* #### what should this be. reconsider when X has tree views. */
664 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), 729 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
665 IMAGE_INSTANCE_WIDGET_FACE (ii), 730 IMAGE_INSTANCE_WIDGET_FACE (ii),
675 } 740 }
676 741
677 /* Get the geometry of a tab control. This is based on the number of 742 /* Get the geometry of a tab control. This is based on the number of
678 items and text therin in the tab control. */ 743 items and text therin in the tab control. */
679 static void 744 static void
680 tab_control_query_geometry (Lisp_Object image_instance, 745 tab_control_query_geometry (Lisp_Object image_instance,
681 unsigned int* width, unsigned int* height, 746 int* width, int* height,
682 enum image_instance_geometry disp, Lisp_Object domain) 747 enum image_instance_geometry disp, Lisp_Object domain)
683 { 748 {
684 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 749 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
685 Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii); 750 Lisp_Object items = XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
686 Lisp_Object rest; 751 Lisp_Object rest;
687 unsigned int tw = 0, th = 0; 752 int tw = 0, th = 0;
688 753
689 LIST_LOOP (rest, items) 754 LIST_LOOP (rest, items)
690 { 755 {
691 unsigned int h, w; 756 int h, w;
692 757
693 query_string_geometry (XGUI_ITEM (XCAR (rest))->name, 758 query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
694 IMAGE_INSTANCE_WIDGET_FACE (ii), 759 IMAGE_INSTANCE_WIDGET_FACE (ii),
695 &w, &h, 0, domain); 760 &w, &h, 0, domain);
696 tw += 2 * WIDGET_BORDER_WIDTH; /* some bias */ 761 tw += 5 * WIDGET_BORDER_WIDTH; /* some bias */
697 tw += w; 762 tw += w;
698 th = max (th, h + 2 * WIDGET_BORDER_HEIGHT); 763 th = max (th, h + 2 * WIDGET_BORDER_HEIGHT);
699 } 764 }
700 765
701 /* Fixup returned values depending on orientation. */ 766 /* Fixup returned values depending on orientation. */
706 } 771 }
707 else 772 else
708 { 773 {
709 if (height) *height = th; 774 if (height) *height = th;
710 if (width) *width = tw; 775 if (width) *width = tw;
776 }
777 }
778
779 /* Update the contents of a tab control. */
780 static void
781 tab_control_update (Lisp_Object image_instance,
782 Lisp_Object instantiator)
783 {
784 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
785 /* Record new items for update. *_tab_control_redisplay will do the
786 rest. */
787 if (!NILP (items))
788 {
789 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
790 check_valid_item_list (items);
791 #ifdef DEBUG_WIDGET_OUTPUT
792 stderr_out ("tab control %p updated\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
793 #endif
794 /* Don't set the actual items since we might decide not to use
795 the new ones (because nothing has really changed). If we did
796 set them and didn't use them then we would get into whole
797 heaps of trouble when the old items get GC'd. */
798 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
799 Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
800 parse_gui_item_tree_children (items));
801 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
802 }
803 }
804
805 /* Determine whether only the order has changed for a tab. */
806 int tab_control_order_only_changed (Lisp_Object image_instance)
807 {
808 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
809 int found = 0, len, pending_len;
810 Lisp_Object rest;
811
812 /* Degenerate case. */
813 if (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
814 return 1;
815
816 /* See whether we just need a change in order. */
817 GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_ITEMS (ii), len);
818 GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii),
819 pending_len);
820 if (len == pending_len)
821 {
822 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
823 {
824 Lisp_Object pending_rest;
825 found = 0;
826 LIST_LOOP (pending_rest,
827 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
828 {
829 if (gui_item_equal_sans_selected (XCAR (rest),
830 XCAR (pending_rest), 0))
831 {
832 found = 1;
833 break;
834 }
835 }
836 if (!found)
837 break;
838 }
839 }
840 return found;
841 }
842
843 /* Set the properties of a progress gauge */
844 static void
845 progress_gauge_update (Lisp_Object image_instance,
846 Lisp_Object instantiator)
847 {
848 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
849 Lisp_Object value = find_keyword_in_vector (instantiator, Q_value);
850
851 if (!NILP (value))
852 {
853 CHECK_INT (value);
854 #ifdef DEBUG_WIDGET_OUTPUT
855 stderr_out ("progress gauge value set to %ld\n", XINT (value));
856 #endif
857 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
858 copy_gui_item_tree (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
859 #ifdef ERROR_CHECK_GLYPHS
860 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
861 #endif
862 if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
863 XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value = value;
864
865 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
711 } 866 }
712 } 867 }
713 868
714 869
715 /***************************************************************************** 870 /*****************************************************************************
716 * widget layout * 871 * widget layout *
717 *****************************************************************************/ 872 *****************************************************************************/
718 static int 873 /* We need to cascade normalization.*/
719 layout_possible_dest_types (void)
720 {
721 return IMAGE_LAYOUT_MASK;
722 }
723
724 /* we need to convert things like glyphs to images, eval expressions
725 etc.*/
726 static Lisp_Object 874 static Lisp_Object
727 layout_normalize (Lisp_Object inst, Lisp_Object console_type) 875 layout_normalize (Lisp_Object inst, Lisp_Object console_type,
876 Lisp_Object dest_mask)
728 { 877 {
729 /* This function can call lisp */ 878 /* This function can call lisp */
730 Lisp_Object items = find_keyword_in_vector (inst, Q_items); 879 struct gcpro gcpro1, gcpro2;
731 Lisp_Object border = find_keyword_in_vector (inst, Q_border); 880 Lisp_Object alist = Qnil, new_items = Qnil, border;
732 /* we need to eval glyph if its an expression, we do this for the 881 /* This function can call lisp */
733 same reasons we normalize file to data. */ 882 Lisp_Object items;
883
884 GCPRO2 (alist, new_items);
885 alist = tagged_vector_to_alist (inst);
886 items = assq_no_quit (Q_items, alist);
887
888 /* We need to normalize sub-objects. */
734 if (!NILP (items)) 889 if (!NILP (items))
735 { 890 {
736 Lisp_Object rest; 891 Lisp_Object rest;
737 LIST_LOOP (rest, items) 892 LIST_LOOP (rest, XCDR (items))
738 { 893 {
739 /* substitute the new glyph */ 894 /* Substitute the new instantiator */
740 Fsetcar (rest, glyph_instantiator_to_glyph (XCAR (rest))); 895 new_items = Fcons (normalize_image_instantiator (XCAR (rest),
741 } 896 console_type, dest_mask),
742 } 897 new_items);
743 /* normalize the border spec. */ 898 }
744 if (VECTORP (border) || CONSP (border)) 899 new_items = Fnreverse (new_items);
745 { 900 Fsetcdr (items, new_items);
746 substitute_keyword_value (inst, Q_border, glyph_instantiator_to_glyph (border)); 901 }
747 } 902 /* Normalize the border spec. */
748 return inst; 903 border = assq_no_quit (Q_border, alist);
904 if (!NILP (border) && VECTORP (XCDR (border)))
905 {
906 Fsetcdr (border, normalize_image_instantiator (XCDR (border),
907 console_type, dest_mask));
908 }
909
910 {
911 Lisp_Object result = alist_to_tagged_vector (XVECTOR_DATA (inst)[0],
912 alist);
913 free_alist (alist);
914 RETURN_UNGCPRO (result);
915 }
916 }
917
918 /* Update the instances in the layout. */
919 static void
920 layout_update (Lisp_Object image_instance, Lisp_Object instantiator)
921 {
922 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
923 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
924 Lisp_Object border_inst = find_keyword_in_vector (instantiator, Q_border);
925 Lisp_Object border = Qnil;
926 Lisp_Object children = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
927 int structure_changed = 0;
928 struct gcpro gcpro1;
929
930 /* We want to avoid consing if we can. This is quite awkward because
931 we have to deal with the border as well as the items. */
932
933 GCPRO1 (border);
934
935 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
936 {
937 border = XCAR (children);
938 children = XCDR (children);
939 }
940
941 #ifdef DEBUG_WIDGET_OUTPUT
942 stderr_out ("layout updated\n");
943 #endif
944 /* Update the border. */
945 if (!NILP (border_inst))
946 {
947 if (VECTORP (border_inst))
948 {
949 /* We are going to be sneaky here and add the border text as
950 just another child, the layout and output routines don't know
951 this and will just display at the offsets we prescribe. */
952 if (!NILP (border))
953 call3 (Qset_glyph_image, border, border_inst,
954 IMAGE_INSTANCE_DOMAIN (ii));
955 else
956 {
957 border = Fcons (call1 (Qmake_glyph, border_inst), Qnil);
958 structure_changed = 1;
959 }
960 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
961 }
962 else
963 {
964 if (!NILP (border))
965 {
966 border = Qnil;
967 structure_changed = 1;
968 }
969 if (EQ (border_inst, Qt))
970 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
971 else
972 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border_inst;
973 }
974 }
975
976 /* Pick up the sub-widgets. */
977 if (!NILP (items))
978 {
979 int len1, len2;
980 GET_LIST_LENGTH (items, len1);
981 GET_LIST_LENGTH (children, len2);
982 /* The structure hasn't changed so just update the images. */
983 if (!structure_changed && len1 == len2)
984 {
985 /* Pick up the sub-widgets. */
986 for (; !NILP (children); children = XCDR (children), items = XCDR (items))
987 {
988 call3 (Qset_glyph_image, XCAR (children), XCAR (items),
989 IMAGE_INSTANCE_DOMAIN (ii));
990 }
991 }
992 /* The structure has changed so start over. */
993 else
994 {
995 /* Instantiate any new glyphs. */
996 for (; !NILP (items); items = XCDR (items))
997 {
998 border = Fcons (call1 (Qmake_glyph, XCAR (items)), border);
999 }
1000 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Fnreverse (border);
1001 }
1002 }
1003 UNGCPRO;
1004 }
1005
1006 static void
1007 layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1008 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1009 int dest_mask, Lisp_Object domain)
1010 {
1011 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1012 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
1013
1014 #ifdef DEBUG_WIDGET_OUTPUT
1015 stderr_out ("layout instantiated\n");
1016 #endif
1017 /* Do widget type instantiation first. */
1018 widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
1019 dest_mask, domain);
1020
1021 if (NILP (orient))
1022 {
1023 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
1024 }
1025
1026 /* Get child glyphs and finish instantiation. We can't do image
1027 instance children yet as we might not have a containing
1028 window. */
1029 layout_update (image_instance, instantiator);
1030 }
1031
1032 static void
1033 layout_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1034 Lisp_Object domain)
1035 {
749 } 1036 }
750 1037
751 /* Layout widget. Sizing commentary: we have a number of problems that 1038 /* Layout widget. Sizing commentary: we have a number of problems that
752 we would like to address. Some consider some of these more 1039 we would like to address. Some consider some of these more
753 important than others. It used to be that size information was 1040 important than others. It used to be that size information was
756 "big enough" to accommodate whatever they are trying to show and 1043 "big enough" to accommodate whatever they are trying to show and
757 this is dependent on text length, lines, font metrics etc. Of 1044 this is dependent on text length, lines, font metrics etc. Of
758 course these attributes can change dynamically and so the size 1045 course these attributes can change dynamically and so the size
759 should changed dynamically also. Only in a few limited cases should 1046 should changed dynamically also. Only in a few limited cases should
760 the size be fixed and remain fixed. Of course this actually means 1047 the size be fixed and remain fixed. Of course this actually means
761 that we don't really want to specifiy the size *at all* for most 1048 that we don't really want to specify the size *at all* for most
762 widgets - we want it to be discovered dynamically. Thus we can 1049 widgets - we want it to be discovered dynamically. Thus we can
763 envisage the following scenarios: 1050 envisage the following scenarios:
764 1051
765 1. A button is sized to accommodate its text, the text changes and the 1052 1. A button is sized to accommodate its text, the text changes and the
766 button should change size also. 1053 button should change size also.
767 1054
768 2. A button is given an explicit size. Its size should never change. 1055 2. A button is given an explicit size. Its size should never change.
769 1056
770 3. Layout is put inside an area. The size of the area changes, the 1057 3. Layout is put inside an area. The size of the area changes, the
771 layout should change with it. 1058 layout should change with it.
772 1059
773 4. A button grows to accommodate additional text. The whitespace 1060 4. A button grows to accommodate additional text. The whitespace
774 around it should be modified to cope with the new layout 1061 around it should be modified to cope with the new layout
775 requirements. 1062 requirements.
776 1063
777 5. A button grows. The area surrounding it should grow also if 1064 5. A button grows. The area surrounding it should grow also if
778 possible. 1065 possible.
779 1066
780 What metrics are important? 1067 What metrics are important?
781 1. Actual width and height. 1068 1. Actual width and height.
782 1069
783 2. Whether the width and height are what the widget actually wants, or 1070 2. Whether the width and height are what the widget actually wants, or
784 whether it can grow or shrink. 1071 whether it can grow or shrink.
785 1072
786 Text glyphs are particularly troublesome since their metrics depend 1073 Text glyphs are particularly troublesome since their metrics depend
787 on the context in which they are being viewed. For instance they 1074 on the context in which they are being viewed. For instance they
788 can appear differently depending on the window face, frame face or 1075 can appear differently depending on the window face, frame face or
789 glyph face. In order to simplify this text glyphs can now only have 1076 glyph face. In order to simplify this text glyphs can now only have
795 rest. */ 1082 rest. */
796 1083
797 /* Query the geometry of a layout widget. We assume that we can only 1084 /* Query the geometry of a layout widget. We assume that we can only
798 get here if the size is not already fixed. */ 1085 get here if the size is not already fixed. */
799 static void 1086 static void
800 layout_query_geometry (Lisp_Object image_instance, unsigned int* width, 1087 layout_query_geometry (Lisp_Object image_instance, int* width,
801 unsigned int* height, enum image_instance_geometry disp, 1088 int* height, enum image_instance_geometry disp,
802 Lisp_Object domain) 1089 Lisp_Object domain)
803 { 1090 {
804 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 1091 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
805 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest; 1092 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest;
806 int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0; 1093 int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0;
1094 int gheight, gwidth;
1095
1096 /* If we are not initialized then we won't have any children. */
1097 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1098 return;
1099
1100 /* First just set up what we already have. */
1101 if (width) *width = IMAGE_INSTANCE_WIDTH (ii);
1102 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
1103
1104 /* If we are not allowed to dynamically size then return. */
1105 if (!IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
1106 &&
1107 !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
1108 return;
1109
1110 /* Pick up the border text if we have one. */
1111 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
1112 {
1113 glyph_query_geometry (XCAR (items), &gwidth, &gheight, disp,
1114 image_instance);
1115 ph_adjust = gheight / 2;
1116 items = XCDR (items);
1117 }
807 1118
808 /* Flip through the items to work out how much stuff we have to display */ 1119 /* Flip through the items to work out how much stuff we have to display */
809 LIST_LOOP (rest, items) 1120 LIST_LOOP (rest, items)
810 { 1121 {
811 Lisp_Object glyph = XCAR (rest); 1122 Lisp_Object glyph = XCAR (rest);
812 unsigned int gheight, gwidth; 1123 glyph_query_geometry (glyph, &gwidth, &gheight, disp, image_instance);
813 1124
814 image_instance_query_geometry (glyph, &gwidth, &gheight, disp, domain); 1125 nitems ++;
815 1126 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
816 /* Pick up the border text if we have one. */ 1127 == LAYOUT_HORIZONTAL)
817 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) 1128 {
818 && NILP (XCDR (rest))) 1129 maxph = max (maxph, gheight);
819 { 1130 maxpw += gwidth;
820 ph_adjust = gheight / 2;
821 } 1131 }
822 else 1132 else
823 { 1133 {
824 1134 maxpw = max (maxpw, gwidth);
825 nitems ++; 1135 maxph += gheight;
826 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1136 }
827 == LAYOUT_HORIZONTAL) 1137 }
828 { 1138
829 maxph = max (maxph, gheight); 1139 /* Work out minimum space we need to fit all the items. This could
830 maxpw += gwidth; 1140 have been fixed by the user. */
831 } 1141 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
832 else 1142 {
833 { 1143 Lisp_Object dynamic_width =
834 maxpw = max (maxpw, gwidth); 1144 Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
835 maxph += gheight; 1145 if (INTP (dynamic_width))
836 } 1146 *width = XINT (dynamic_width);
837 } 1147 }
838 } 1148 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
839 1149 == LAYOUT_HORIZONTAL)
840 /* work out spacing between items and bounds of the layout. No user 1150 *width = maxpw + ((nitems + 1) * WIDGET_BORDER_WIDTH +
841 provided width so we just do default spacing. */ 1151 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2;
842 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1152 else
843 == LAYOUT_HORIZONTAL) 1153 *width = maxpw + 2 * (WIDGET_BORDER_WIDTH * 2 +
844 *width = maxpw + (nitems + 1) * WIDGET_BORDER_WIDTH * 2; 1154 IMAGE_INSTANCE_MARGIN_WIDTH (ii));
845 else
846 *width = maxpw + 2 * WIDGET_BORDER_WIDTH * 2;
847 1155
848 /* Work out vertical spacings. */ 1156 /* Work out vertical spacings. */
849 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1157 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
850 == LAYOUT_VERTICAL) 1158 {
851 *height = maxph + (nitems + 1) * WIDGET_BORDER_HEIGHT * 2 + ph_adjust; 1159 Lisp_Object dynamic_height =
852 else 1160 Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
853 *height = maxph + 2 * WIDGET_BORDER_HEIGHT * 2 + ph_adjust; 1161 if (INTP (dynamic_height))
854 } 1162 *height = XINT (dynamic_height);
855 1163 }
856 1164 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
857 static void 1165 == LAYOUT_VERTICAL)
858 layout_layout (Lisp_Object image_instance, 1166 *height = maxph + ((nitems + 1) * WIDGET_BORDER_HEIGHT +
859 unsigned int width, unsigned int height, Lisp_Object domain) 1167 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
1168 else
1169 *height = maxph + (2 * WIDGET_BORDER_HEIGHT +
1170 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
1171 }
1172
1173 int
1174 layout_layout (Lisp_Object image_instance,
1175 int width, int height, int xoffset, int yoffset,
1176 Lisp_Object domain)
860 { 1177 {
861 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 1178 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
862 Lisp_Object rest; 1179 Lisp_Object rest;
863 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii); 1180 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
864 int x, y, maxph = 0, maxpw = 0, nitems = 0, 1181 int x, y, maxph = 0, maxpw = 0, nitems = 0,
865 horiz_spacing, vert_spacing, ph_adjust = 0; 1182 horiz_spacing, vert_spacing, ph_adjust = 0;
866 unsigned int gheight, gwidth; 1183 int gheight, gwidth;
867 1184
868 /* flip through the items to work out how much stuff we have to display */ 1185 /* If we are not initialized then we won't have any children. */
1186 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1187 return 0;
1188
1189 /* Pick up the border text if we have one. */
1190 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
1191 {
1192 Lisp_Object border = XCAR (items);
1193 items = XCDR (items);
1194 glyph_query_geometry (border, &gwidth, &gheight,
1195 IMAGE_DESIRED_GEOMETRY, image_instance);
1196 ph_adjust = gheight / 2;
1197 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
1198
1199 /* #### Really, what should this be? */
1200 glyph_do_layout (border, gwidth, gheight, 10, 0,
1201 image_instance);
1202 }
1203
1204 /* Flip through the items to work out how much stuff we have to display. */
869 LIST_LOOP (rest, items) 1205 LIST_LOOP (rest, items)
870 { 1206 {
871 Lisp_Object glyph = XCAR (rest); 1207 Lisp_Object glyph = XCAR (rest);
872 1208
873 image_instance_query_geometry (glyph, &gwidth, &gheight, 1209 glyph_query_geometry (glyph, &gwidth, &gheight,
874 IMAGE_DESIRED_GEOMETRY, domain); 1210 IMAGE_DESIRED_GEOMETRY, image_instance);
875 1211 nitems ++;
876 /* Pick up the border text if we have one. */ 1212 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
877 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) 1213 == LAYOUT_HORIZONTAL)
878 && NILP (XCDR (rest))) 1214 {
879 { 1215 maxph = max (maxph, gheight);
880 XIMAGE_INSTANCE_XOFFSET (glyph) = 10; /* Really, what should this be? */ 1216 maxpw += gwidth;
881 XIMAGE_INSTANCE_YOFFSET (glyph) = 0;
882 ph_adjust = gheight / 2;
883 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
884 } 1217 }
885 else 1218 else
886 { 1219 {
887 1220 maxpw = max (maxpw, gwidth);
888 nitems ++; 1221 maxph += gheight;
889 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
890 == LAYOUT_HORIZONTAL)
891 {
892 maxph = max (maxph, gheight);
893 maxpw += gwidth;
894 }
895 else
896 {
897 maxpw = max (maxpw, gwidth);
898 maxph += gheight;
899 }
900 } 1222 }
901 } 1223 }
902 1224
903 /* work out spacing between items and bounds of the layout */ 1225 /* work out spacing between items and bounds of the layout */
904 if (width < maxpw) 1226 if (width < maxpw)
905 /* The user wants a smaller space than the largest item, so we 1227 /* The user wants a smaller space than the largest item, so we
906 just provide default spacing and will let the output routines 1228 just provide default spacing and will let the output routines
907 clip.. */ 1229 clip.. */
908 horiz_spacing = WIDGET_BORDER_WIDTH * 2; 1230 horiz_spacing = WIDGET_BORDER_WIDTH * 2;
909 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1231 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
910 == LAYOUT_HORIZONTAL) 1232 == LAYOUT_HORIZONTAL)
911 /* We have a larger area to display in so distribute the space 1233 /* We have a larger area to display in so distribute the space
912 evenly. */ 1234 evenly. */
913 horiz_spacing = (width - maxpw) / (nitems + 1); 1235 horiz_spacing = (width - (maxpw +
1236 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
1237 / (nitems + 1);
914 else 1238 else
915 horiz_spacing = (width - maxpw) / 2; 1239 horiz_spacing = (width - maxpw) / 2
1240 - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
916 1241
917 if (height < maxph) 1242 if (height < maxph)
918 vert_spacing = WIDGET_BORDER_HEIGHT * 2; 1243 vert_spacing = WIDGET_BORDER_HEIGHT * 2;
919 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1244 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
920 == LAYOUT_VERTICAL) 1245 == LAYOUT_VERTICAL)
921 vert_spacing = (height - (maxph + ph_adjust)) / (nitems + 1); 1246 vert_spacing = (height - (maxph + ph_adjust +
1247 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
1248 / (nitems + 1);
922 else 1249 else
923 vert_spacing = (height - (maxph + ph_adjust)) / 2; 1250 vert_spacing = (height - (maxph + ph_adjust)) / 2
924 1251 - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
925 y = vert_spacing + ph_adjust; 1252
926 x = horiz_spacing; 1253 y = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1254 x = horiz_spacing + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
927 1255
928 /* Now flip through putting items where we want them, paying 1256 /* Now flip through putting items where we want them, paying
929 attention to justification. Make sure we don't mess with the 1257 attention to justification. Make sure we don't mess with the
930 border glyph. */ 1258 border glyph. */
931 LIST_LOOP (rest, items) 1259 LIST_LOOP (rest, items)
932 { 1260 {
933 Lisp_Object glyph = XCAR (rest); 1261 Lisp_Object glyph = XCAR (rest);
934 1262
935 image_instance_query_geometry (glyph, &gwidth, &gheight, 1263 glyph_query_geometry (glyph, &gwidth, &gheight,
936 IMAGE_DESIRED_GEOMETRY, domain); 1264 IMAGE_DESIRED_GEOMETRY, image_instance);
937 1265
938 if (!INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) 1266 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
939 || !NILP (XCDR (rest))) 1267 == LAYOUT_HORIZONTAL)
940 { 1268 {
941 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1269 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
942 == LAYOUT_HORIZONTAL) 1270 == LAYOUT_JUSTIFY_RIGHT)
943 { 1271 y = height - (gheight + vert_spacing);
944 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 1272 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
945 == LAYOUT_JUSTIFY_RIGHT) 1273 == LAYOUT_JUSTIFY_CENTER)
946 y = height - (gheight + vert_spacing); 1274 y = (height - gheight) / 2;
947 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 1275 }
948 == LAYOUT_JUSTIFY_CENTER) 1276 else
949 y = (height - gheight) / 2; 1277 {
950 } 1278 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
951 else 1279 == LAYOUT_JUSTIFY_RIGHT)
952 { 1280 x = width - (gwidth + horiz_spacing);
953 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 1281 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
954 == LAYOUT_JUSTIFY_RIGHT) 1282 == LAYOUT_JUSTIFY_CENTER)
955 x = width - (gwidth + horiz_spacing); 1283 x = (width - gwidth) / 2;
956 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 1284 }
957 == LAYOUT_JUSTIFY_CENTER) 1285
958 x = (width - gwidth) / 2;
959 }
960
961 XIMAGE_INSTANCE_XOFFSET (glyph) = x;
962 XIMAGE_INSTANCE_YOFFSET (glyph) = y;
963
964 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
965 == LAYOUT_HORIZONTAL)
966 {
967 x += (gwidth + horiz_spacing);
968 }
969 else
970 {
971 y += (gheight + vert_spacing);
972 }
973 }
974
975 /* Now layout subwidgets if they require it. */ 1286 /* Now layout subwidgets if they require it. */
976 image_instance_layout (glyph, gwidth, gheight, domain); 1287 glyph_do_layout (glyph, gwidth, gheight, x, y, image_instance);
977 } 1288
978 1289 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
979 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = width; 1290 == LAYOUT_HORIZONTAL)
980 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = height; 1291 {
1292 x += (gwidth + horiz_spacing);
1293 }
1294 else
1295 {
1296 y += (gheight + vert_spacing);
1297 }
1298
1299 }
1300 return 1;
1301 }
1302
1303 /* Get the glyphs that comprise a layout. These are created internally
1304 and so are otherwise inaccessible to lisp. We need some way of getting
1305 properties from the widgets that comprise a layout and this is the
1306 simplest way of doing it.
1307
1308 #### Eventually we should allow some more intelligent access to
1309 sub-widgets. */
1310 static Lisp_Object
1311 layout_property (Lisp_Object image_instance, Lisp_Object prop)
1312 {
1313 /* This function can GC. */
1314 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1315 if (EQ (prop, Q_items))
1316 {
1317 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) &&
1318 CONSP (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)))
1319 return Fcopy_sequence (XCDR
1320 (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)));
1321 else
1322 return Fcopy_sequence (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii));
1323 }
1324 return Qunbound;
1325 }
1326
1327 /* Layout subwindows if they are real subwindows. */
1328 static int
1329 native_layout_layout (Lisp_Object image_instance,
1330 int width, int height, int xoffset, int yoffset,
1331 Lisp_Object domain)
1332 {
1333 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1334 Lisp_Object rest;
1335
1336 /* The first time this gets called, the layout will be only
1337 partially instantiated. The children get done in
1338 post_instantiate. */
1339 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1340 return 0;
1341
1342 /* Defining this overrides the default layout_layout so we first have to call that to get
1343 suitable instances and values set up. */
1344 layout_layout (image_instance, width, height, xoffset, yoffset, domain);
1345
1346 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))
1347 {
1348 struct display_glyph_area dga;
1349 dga.xoffset = 0;
1350 dga.yoffset = 0;
1351 dga.width = IMAGE_INSTANCE_WIDTH (ii);
1352 dga.height = IMAGE_INSTANCE_HEIGHT (ii);
1353
1354 map_subwindow (XCAR (rest),
1355 IMAGE_INSTANCE_XOFFSET (ii),
1356 IMAGE_INSTANCE_YOFFSET (ii), &dga);
1357 }
1358 return 1;
981 } 1359 }
982 1360
983 1361
984 /************************************************************************/ 1362 /************************************************************************/
985 /* initialization */ 1363 /* initialization */
986 /************************************************************************/ 1364 /************************************************************************/
987 1365
988 void 1366 void
989 syms_of_glyphs_widget (void) 1367 syms_of_glyphs_widget (void)
990 { 1368 {
991 defkeyword (&Q_descriptor, ":descriptor"); 1369 DEFSYMBOL (Qetched_in);
992 defkeyword (&Q_height, ":height"); 1370 DEFSYMBOL (Qetched_out);
993 defkeyword (&Q_width, ":width"); 1371 DEFSYMBOL (Qbevel_in);
994 defkeyword (&Q_properties, ":properties"); 1372 DEFSYMBOL (Qbevel_out);
995 defkeyword (&Q_items, ":items"); 1373 DEFSYMBOL (Qmake_glyph);
996 defkeyword (&Q_image, ":image"); 1374 }
997 defkeyword (&Q_percent, ":percent"); 1375
998 defkeyword (&Q_text, ":text"); 1376 #define VALID_GUI_KEYWORDS(type) do { \
999 defkeyword (&Q_orientation, ":orientation"); 1377 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything); \
1000 defkeyword (&Q_justify, ":justify"); 1378 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \
1001 defkeyword (&Q_border, ":border"); 1379 IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string); \
1002 1380 IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol); \
1003 defsymbol (&Qetched_in, "etched-in"); 1381 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything); \
1004 defsymbol (&Qetched_out, "etched-out"); 1382 IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything); \
1005 defsymbol (&Qbevel_in, "bevel-in"); 1383 IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol); \
1006 defsymbol (&Qbevel_out, "bevel-out"); 1384 IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything); \
1007 } 1385 IIFORMAT_VALID_KEYWORD (type, Q_initial_focus, check_valid_anything); \
1008 1386 IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string); \
1009 #define VALID_GUI_KEYWORDS(type) do { \ 1387 IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string); \
1010 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything); \ 1388 IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything); \
1011 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \ 1389 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback); \
1012 IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string); \ 1390 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback_ex, check_valid_callback); \
1013 IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol); \ 1391 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, \
1014 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything); \ 1392 check_valid_string_or_vector); \
1015 IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything); \
1016 IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol); \
1017 IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything); \
1018 IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string); \
1019 IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string); \
1020 IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything); \
1021 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback); \
1022 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, check_valid_string_or_vector); \
1023 } while (0) 1393 } while (0)
1024 1394
1025 #define VALID_WIDGET_KEYWORDS(type) do { \ 1395 #define VALID_WIDGET_KEYWORDS(type) do { \
1026 IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int); \ 1396 IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int); \
1027 IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int); \ 1397 IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int); \
1028 IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int); \ 1398 IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int_or_function); \
1029 IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int); \ 1399 IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int_or_function); \
1030 IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face); \ 1400 IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face); \
1031 } while (0) 1401 } while (0)
1032 1402
1033 1403
1034 static void image_instantiator_widget (void) 1404 static void image_instantiator_widget (void)
1035 { /* we only do this for properties */ 1405 { /* we only do this for properties */
1036 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget"); 1406 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
1037 IIFORMAT_HAS_METHOD (widget, property); 1407 IIFORMAT_HAS_METHOD (widget, property);
1038 IIFORMAT_HAS_METHOD (widget, set_property); 1408 IIFORMAT_HAS_METHOD (widget, update);
1039 IIFORMAT_HAS_METHOD (widget, query_geometry); 1409 IIFORMAT_HAS_METHOD (widget, query_geometry);
1040 IIFORMAT_HAS_METHOD (widget, layout); 1410 IIFORMAT_HAS_METHOD (widget, layout);
1041 } 1411 }
1042 1412
1043 static void image_instantiator_buttons (void) 1413 static void image_instantiator_buttons (void)
1044 { 1414 {
1045 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button"); 1415 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
1046 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget); 1416 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
1047 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget); 1417 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
1048 IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget); 1418 IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
1419 IIFORMAT_HAS_SHARED_METHOD (button, post_instantiate, widget);
1049 IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget); 1420 IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
1421 IIFORMAT_HAS_SHARED_METHOD (button, governing_domain, subwindow);
1422 IIFORMAT_HAS_METHOD (button, query_geometry);
1050 IIFORMAT_VALID_KEYWORD (button, 1423 IIFORMAT_VALID_KEYWORD (button,
1051 Q_image, check_valid_glyph_or_instantiator); 1424 Q_image, check_valid_instantiator);
1052 VALID_WIDGET_KEYWORDS (button); 1425 VALID_WIDGET_KEYWORDS (button);
1053 VALID_GUI_KEYWORDS (button); 1426 VALID_GUI_KEYWORDS (button);
1054 } 1427 }
1055 1428
1056 static void image_instantiator_edit_fields (void) 1429 static void image_instantiator_edit_fields (void)
1057 { 1430 {
1058 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit_field, "edit-field"); 1431 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit_field, "edit-field");
1059 IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget); 1432 IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
1060 IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget); 1433 IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
1061 IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget); 1434 IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
1435 IIFORMAT_HAS_SHARED_METHOD (edit_field, post_instantiate, widget);
1436 IIFORMAT_HAS_SHARED_METHOD (edit_field, governing_domain, subwindow);
1062 VALID_WIDGET_KEYWORDS (edit_field); 1437 VALID_WIDGET_KEYWORDS (edit_field);
1063 VALID_GUI_KEYWORDS (edit_field); 1438 VALID_GUI_KEYWORDS (edit_field);
1064 } 1439 }
1065 1440
1066 static void image_instantiator_combo_box (void) 1441 static void image_instantiator_combo_box (void)
1067 { 1442 {
1068 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box"); 1443 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box");
1069 IIFORMAT_HAS_METHOD (combo_box, validate); 1444 IIFORMAT_HAS_METHOD (combo_box, validate);
1070 IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget); 1445 IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget);
1446 IIFORMAT_HAS_SHARED_METHOD (combo_box, governing_domain, subwindow);
1447
1071 VALID_GUI_KEYWORDS (combo_box); 1448 VALID_GUI_KEYWORDS (combo_box);
1072 1449
1073 IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int); 1450 IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int);
1074 IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int); 1451 IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int);
1075 IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width, check_valid_int); 1452 IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width,
1453 check_valid_int_or_function);
1076 IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face); 1454 IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face);
1077 IIFORMAT_VALID_KEYWORD (combo_box, Q_properties, check_valid_item_list); 1455 IIFORMAT_VALID_KEYWORD (combo_box, Q_items, check_valid_item_list);
1078 } 1456 }
1079 1457
1080 static void image_instantiator_scrollbar (void) 1458 static void image_instantiator_scrollbar (void)
1081 { 1459 {
1082 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar"); 1460 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar");
1083 IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget); 1461 IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
1084 IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget); 1462 IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
1085 IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget); 1463 IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
1464 IIFORMAT_HAS_SHARED_METHOD (scrollbar, post_instantiate, widget);
1465 IIFORMAT_HAS_SHARED_METHOD (scrollbar, governing_domain, subwindow);
1086 VALID_GUI_KEYWORDS (scrollbar); 1466 VALID_GUI_KEYWORDS (scrollbar);
1087 1467
1088 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int); 1468 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width,
1089 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int); 1469 check_valid_int_or_function);
1470 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height,
1471 check_valid_int_or_function);
1090 IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face); 1472 IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
1091 } 1473 }
1092 1474
1093 static void image_instantiator_progress_guage (void) 1475 static void image_instantiator_progress_guage (void)
1094 { 1476 {
1095 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge"); 1477 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge");
1096 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget); 1478 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget);
1097 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget); 1479 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget);
1098 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget); 1480 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget);
1481 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, post_instantiate, widget);
1482 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, governing_domain, subwindow);
1483 IIFORMAT_HAS_METHOD (progress_gauge, update);
1099 VALID_WIDGET_KEYWORDS (progress_gauge); 1484 VALID_WIDGET_KEYWORDS (progress_gauge);
1100 VALID_GUI_KEYWORDS (progress_gauge); 1485 VALID_GUI_KEYWORDS (progress_gauge);
1486
1487 IIFORMAT_VALID_KEYWORD (progress_gauge, Q_value, check_valid_int);
1101 } 1488 }
1102 1489
1103 static void image_instantiator_tree_view (void) 1490 static void image_instantiator_tree_view (void)
1104 { 1491 {
1105 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view"); 1492 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view");
1106 IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box); 1493 IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
1107 IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget); 1494 IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
1108 IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget); 1495 IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
1496 IIFORMAT_HAS_SHARED_METHOD (tree_view, post_instantiate, widget);
1497 IIFORMAT_HAS_SHARED_METHOD (tree_view, governing_domain, subwindow);
1498 IIFORMAT_HAS_SHARED_METHOD (tree_view, update, tab_control);
1109 IIFORMAT_HAS_METHOD (tree_view, query_geometry); 1499 IIFORMAT_HAS_METHOD (tree_view, query_geometry);
1110 VALID_WIDGET_KEYWORDS (tree_view); 1500 VALID_WIDGET_KEYWORDS (tree_view);
1111 VALID_GUI_KEYWORDS (tree_view); 1501 VALID_GUI_KEYWORDS (tree_view);
1112 IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list); 1502 IIFORMAT_VALID_KEYWORD (tree_view, Q_items, check_valid_item_list);
1113 } 1503 }
1114 1504
1115 static void image_instantiator_tab_control (void) 1505 static void image_instantiator_tab_control (void)
1116 { 1506 {
1117 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control"); 1507 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control");
1118 IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box); 1508 IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
1119 IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget); 1509 IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
1120 IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget); 1510 IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
1511 IIFORMAT_HAS_SHARED_METHOD (tab_control, post_instantiate, widget);
1512 IIFORMAT_HAS_SHARED_METHOD (tab_control, governing_domain, subwindow);
1121 IIFORMAT_HAS_METHOD (tab_control, query_geometry); 1513 IIFORMAT_HAS_METHOD (tab_control, query_geometry);
1514 IIFORMAT_HAS_METHOD (tab_control, update);
1122 VALID_WIDGET_KEYWORDS (tab_control); 1515 VALID_WIDGET_KEYWORDS (tab_control);
1123 VALID_GUI_KEYWORDS (tab_control); 1516 VALID_GUI_KEYWORDS (tab_control);
1124 IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, check_valid_tab_orientation); 1517 IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation,
1125 IIFORMAT_VALID_KEYWORD (tab_control, Q_properties, check_valid_item_list); 1518 check_valid_tab_orientation);
1519 IIFORMAT_VALID_KEYWORD (tab_control, Q_items, check_valid_item_list);
1126 } 1520 }
1127 1521
1128 static void image_instantiator_labels (void) 1522 static void image_instantiator_labels (void)
1129 { 1523 {
1130 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label"); 1524 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
1131 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget); 1525 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
1132 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget); 1526 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget);
1527 IIFORMAT_HAS_SHARED_METHOD (label, post_instantiate, widget);
1528 IIFORMAT_HAS_SHARED_METHOD (label, governing_domain, subwindow);
1133 VALID_WIDGET_KEYWORDS (label); 1529 VALID_WIDGET_KEYWORDS (label);
1134 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string); 1530 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
1135 } 1531 }
1136 1532
1533 #define VALID_LAYOUT_KEYWORDS(layout) \
1534 VALID_WIDGET_KEYWORDS (layout); \
1535 IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); \
1536 IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); \
1537 IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); \
1538 IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int); \
1539 IIFORMAT_VALID_KEYWORD (layout, Q_items, \
1540 check_valid_instantiator_list)
1541
1137 static void image_instantiator_layout (void) 1542 static void image_instantiator_layout (void)
1138 { 1543 {
1139 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout"); 1544 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout");
1140 IIFORMAT_HAS_METHOD (layout, possible_dest_types); 1545 IIFORMAT_HAS_SHARED_METHOD (layout, possible_dest_types, widget);
1141 IIFORMAT_HAS_SHARED_METHOD (layout, instantiate, widget); 1546 IIFORMAT_HAS_METHOD (layout, instantiate);
1547 IIFORMAT_HAS_METHOD (layout, post_instantiate);
1548 IIFORMAT_HAS_SHARED_METHOD (layout, governing_domain, subwindow);
1142 IIFORMAT_HAS_METHOD (layout, normalize); 1549 IIFORMAT_HAS_METHOD (layout, normalize);
1143 IIFORMAT_HAS_METHOD (layout, query_geometry); 1550 IIFORMAT_HAS_METHOD (layout, query_geometry);
1144 IIFORMAT_HAS_METHOD (layout, layout); 1551 IIFORMAT_HAS_METHOD (layout, layout);
1145 IIFORMAT_VALID_KEYWORD (layout, Q_pixel_width, check_valid_int); 1552 IIFORMAT_HAS_METHOD (layout, update);
1146 IIFORMAT_VALID_KEYWORD (layout, Q_pixel_height, check_valid_int); 1553 IIFORMAT_HAS_METHOD (layout, property);
1147 IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); 1554
1148 IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); 1555 VALID_GUI_KEYWORDS (layout);
1149 IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); 1556 VALID_LAYOUT_KEYWORDS (layout);
1150 IIFORMAT_VALID_KEYWORD (layout, Q_items, 1557 }
1151 check_valid_glyph_or_instantiator_list); 1558
1559 static void image_instantiator_native_layout (void)
1560 {
1561 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (native_layout, "native-layout");
1562 IIFORMAT_HAS_SHARED_METHOD (native_layout, possible_dest_types, widget);
1563 IIFORMAT_HAS_SHARED_METHOD (native_layout, instantiate, layout);
1564 IIFORMAT_HAS_SHARED_METHOD (native_layout, post_instantiate, layout);
1565 IIFORMAT_HAS_METHOD (native_layout, layout);
1566 IIFORMAT_HAS_SHARED_METHOD (native_layout, governing_domain, subwindow);
1567 IIFORMAT_HAS_SHARED_METHOD (native_layout, normalize, layout);
1568 IIFORMAT_HAS_SHARED_METHOD (native_layout, query_geometry, layout);
1569 IIFORMAT_HAS_SHARED_METHOD (native_layout, layout, layout);
1570 IIFORMAT_HAS_SHARED_METHOD (native_layout, property, layout);
1571
1572 VALID_GUI_KEYWORDS (native_layout);
1573 VALID_LAYOUT_KEYWORDS (native_layout);
1152 } 1574 }
1153 1575
1154 void 1576 void
1155 image_instantiator_format_create_glyphs_widget (void) 1577 image_instantiator_format_create_glyphs_widget (void)
1156 { 1578 {
1162 image_instantiator_progress_guage(); 1584 image_instantiator_progress_guage();
1163 image_instantiator_tree_view(); 1585 image_instantiator_tree_view();
1164 image_instantiator_tab_control(); 1586 image_instantiator_tab_control();
1165 image_instantiator_labels(); 1587 image_instantiator_labels();
1166 image_instantiator_layout(); 1588 image_instantiator_layout();
1589 image_instantiator_native_layout();
1167 } 1590 }
1168 1591
1169 void 1592 void
1170 reinit_vars_of_glyphs_widget (void) 1593 reinit_vars_of_glyphs_widget (void)
1171 { 1594 {