1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * \brief functions for the basic object type
24 * This file contains the code used to handle OBJECTs (st_object).
25 * The object is the basic type of all elements stored in schematic
28 * The object be extended to become concrete objects like a line,
29 * a pin, text, a circle or a picture. These extentions are substructures
30 * in the object struct.
31 * The subobjects are picture (st_picture), path (st_path), arcs (st_arc),
32 * a line (st_line), box (st_box), circle (st_circle), text (st_text) and
33 * a complex type (st_complex).
35 * Pins, nets and busses are just a kind of a line.
37 * The complex object can carry many primary objects. If the complex
38 * object is a symbol, then the complex symbol contains all the pins,
39 * the text and the graphics.
41 * \image html o_object_relations.png
42 * \image latex o_object_relations.pdf "object relations" width=14cm
49 /* instrumentation code */
55 #include "libgeda_priv.h"
57 #ifdef HAVE_LIBDMALLOC
62 /*! \brief Check if point is inside a region
63 * \par Function Description
64 * This function takes a rectangular region and a point. It will check
65 * if the point is located in the region or not.
67 * \param [in] xmin Smaller x coordinate of the region.
68 * \param [in] ymin Smaller y coordinate of the region.
69 * \param [in] xmax Larger x coordinate of the region.
70 * \param [in] ymax Larger y coordinate of the region.
71 * \param [in] x x coordinate of the point to check.
72 * \param [in] y y coordinate of the point to check.
73 * \return 1 if the point is inside the region, 0 otherwise.
75 int inside_region(int xmin
, int ymin
, int xmax
, int ymax
, int x
, int y
)
77 return ((x
>= xmin
&& x
<= xmax
&& y
>= ymin
&& y
<= ymax
) ? 1 : 0);
81 /*! \brief Set an #OBJECT's line options.
82 * \par Function Description
83 * This function allows a line's end, type, width, length and space to be set.
84 * See #OBJECT_END and #OBJECT_TYPE for information on valid
85 * object end and type values.
87 * \param [in] toplevel The TOPLEVEL object.
88 * \param [in,out] o_current OBJECT to set line options on.
89 * \param [in] end An OBJECT_END.
90 * \param [in] type An OBJECT_TYPE.
91 * \param [in] width Line width.
92 * \param [in] length Line length.
93 * \param [in] space Spacing between dashes/dots. Cannot be negative.
95 * \todo Make space an unsigned int and check for a max value instead.
96 * If a max value is not required, then it would simplify the code.
98 void o_set_line_options(TOPLEVEL
*toplevel
, OBJECT
*o_current
,
99 OBJECT_END end
, OBJECT_TYPE type
,
100 int width
, int length
, int space
)
102 g_return_if_fail (o_current
!= NULL
);
104 /* do some error checking / correcting */
131 o_emit_pre_change_notify (toplevel
, o_current
);
133 o_current
->line_width
= width
;
134 o_current
->line_end
= end
;
135 o_current
->line_type
= type
;
137 o_current
->line_length
= length
;
138 o_current
->line_space
= space
;
140 /* Recalculate the object's bounding box */
141 o_current
->w_bounds_valid_for
= NULL
;
142 o_emit_change_notify (toplevel
, o_current
);
146 /*! \brief get #OBJECT's line properties.
147 * \par Function Description
148 * This function get's the #OBJECT's line options.
149 * See #OBJECT_END and #OBJECT_TYPE for information on valid
150 * object end and type values.
152 * \param [in] object OBJECT to read the properties
153 * \param [out] end An OBJECT_END.
154 * \param [out] type An OBJECT_TYPE.
155 * \param [out] width Line width.
156 * \param [out] length Line length.
157 * \param [out] space Spacing between dashes/dots.
158 * \return TRUE on succes, FALSE otherwise
161 gboolean
o_get_line_options(OBJECT
*object
,
162 OBJECT_END
*end
, OBJECT_TYPE
*type
,
163 int *width
, int *length
, int *space
)
165 if (object
->type
!= OBJ_LINE
166 && object
->type
!= OBJ_ARC
167 && object
->type
!= OBJ_BOX
168 && object
->type
!= OBJ_CIRCLE
169 && object
->type
!= OBJ_PATH
)
172 *end
= object
->line_end
;
173 *type
= object
->line_type
;
174 *width
= object
->line_width
;
175 *length
= object
->line_length
;
176 *space
= object
->line_space
;
181 /*! \brief Set #OBJECT's fill options.
182 * \par Function Description
183 * This function allows an #OBJECT's fill options to be configured.
184 * See #OBJECT_FILLING for information on valid fill types.
186 * \param [in] toplevel The TOPLEVEL object.
187 * \param [in,out] o_current OBJECT to be updated.
188 * \param [in] type OBJECT_FILLING type.
189 * \param [in] width fill width.
190 * \param [in] pitch1 cross hatch line distance
191 * \param [in] angle1 cross hatch angle
192 * \param [in] pitch2 cross hatch line distance
193 * \param [in] angle2 cross hatch angle
196 void o_set_fill_options(TOPLEVEL
*toplevel
, OBJECT
*o_current
,
197 OBJECT_FILLING type
, int width
,
198 int pitch1
, int angle1
,
199 int pitch2
, int angle2
)
201 if(o_current
== NULL
) {
205 o_emit_pre_change_notify (toplevel
, o_current
);
207 o_current
->fill_type
= type
;
208 o_current
->fill_width
= width
;
210 o_current
->fill_pitch1
= pitch1
;
211 o_current
->fill_angle1
= angle1
;
213 o_current
->fill_pitch2
= pitch2
;
214 o_current
->fill_angle2
= angle2
;
216 o_emit_change_notify (toplevel
, o_current
);
219 /*! \brief get #OBJECT's fill properties.
220 * \par Function Description
221 * This function get's the #OBJECT's fill options.
222 * See #OBJECT_FILLING for information on valid fill types.
224 * \param [in] object OBJECT to read the properties
225 * \param [out] type OBJECT_FILLING type
226 * \param [out] width fill width.
227 * \param [out] pitch1 cross hatch line distance
228 * \param [out] angle1 cross hatch angle
229 * \param [out] pitch2 cross hatch line distance
230 * \param [out] angle2 cross hatch angle
231 * \return TRUE on succes, FALSE otherwise
234 gboolean
o_get_fill_options(OBJECT
*object
,
235 OBJECT_FILLING
*type
, int *width
,
236 int *pitch1
, int *angle1
,
237 int *pitch2
, int *angle2
)
239 if (object
->type
!= OBJ_BOX
240 && object
->type
!= OBJ_CIRCLE
241 && object
->type
!= OBJ_PATH
)
244 *type
= object
->fill_type
;
245 *width
= object
->fill_width
;
246 *pitch1
= object
->fill_pitch1
;
247 *angle1
= object
->fill_angle1
;
248 *pitch2
= object
->fill_pitch2
;
249 *angle2
= object
->fill_angle2
;
254 /*! \brief get the base position of an object
255 * \par Function Description
256 * This function gets the position of an object in world coordinates.
258 * \param [in] toplevel The toplevel environment.
259 * \param [out] x pointer to the x-position
260 * \param [out] y pointer to the y-position
261 * \param [in] object The object to get the position.
262 * \return TRUE if successfully determined the position, FALSE otherwise
264 gboolean
o_get_position (TOPLEVEL
*toplevel
, gint
*x
, gint
*y
, OBJECT
*object
)
266 gboolean (*func
) (TOPLEVEL
*, int*, int*, OBJECT
*) = NULL
;
268 switch (object
->type
) {
269 case OBJ_LINE
: func
= o_line_get_position
; break;
270 case OBJ_NET
: func
= o_net_get_position
; break;
271 case OBJ_BUS
: func
= o_bus_get_position
; break;
272 case OBJ_BOX
: func
= o_box_get_position
; break;
273 case OBJ_PICTURE
: func
= o_picture_get_position
; break;
274 case OBJ_CIRCLE
: func
= o_circle_get_position
; break;
275 case OBJ_PLACEHOLDER
:
276 case OBJ_COMPLEX
: func
= o_complex_get_position
; break;
277 case OBJ_TEXT
: func
= o_text_get_position
; break;
278 case OBJ_PATH
: func
= o_path_get_position
; break;
279 case OBJ_PIN
: func
= o_pin_get_position
; break;
280 case OBJ_ARC
: func
= o_arc_get_position
; break;
282 g_critical ("o_get_position: object %p has bad type '%c'\n",
283 object
, object
->type
);
287 return (*func
) (toplevel
, x
, y
, object
);
293 /*! \brief Translates an object in world coordinates
294 * \par Function Description
295 * This function translates the object <B>object</B> by
296 * <B>dx</B> and <B>dy</B>.
298 * \param [in] toplevel The toplevel environment.
299 * \param [in] dx Amount to horizontally translate object
300 * \param [in] dy Amount to vertically translate object
301 * \param [in] object The object to translate.
303 void o_translate_world (TOPLEVEL
*toplevel
, gint dx
, gint dy
, OBJECT
*object
)
305 void (*func
) (TOPLEVEL
*, int, int, OBJECT
*) = NULL
;
307 switch (object
->type
) {
308 case OBJ_LINE
: func
= o_line_translate_world
; break;
309 case OBJ_NET
: func
= o_net_translate_world
; break;
310 case OBJ_BUS
: func
= o_bus_translate_world
; break;
311 case OBJ_BOX
: func
= o_box_translate_world
; break;
312 case OBJ_PICTURE
: func
= o_picture_translate_world
; break;
313 case OBJ_CIRCLE
: func
= o_circle_translate_world
; break;
314 case OBJ_PLACEHOLDER
:
315 case OBJ_COMPLEX
: func
= o_complex_translate_world
; break;
316 case OBJ_TEXT
: func
= o_text_translate_world
; break;
317 case OBJ_PATH
: func
= o_path_translate_world
; break;
318 case OBJ_PIN
: func
= o_pin_translate_world
; break;
319 case OBJ_ARC
: func
= o_arc_translate_world
; break;
321 g_critical ("o_translate_world: object %p has bad type '%c'\n",
322 object
, object
->type
);
326 (*func
) (toplevel
, dx
, dy
, object
);
331 /*! \brief Rotates an object in world coordinates
332 * \par Function Description
333 * This function rotates the object <B>object</B> about the coordinates
334 * <B>world_centerx</B> and <B>world_centery</B>, by <B>angle</B>degrees.
336 * \param [in] toplevel The toplevel environment.
337 * \param [in] world_centerx X coordinate of rotation center (world coords)
338 * \param [in] world_centery Y coordinate of rotation center (world coords)
339 * \param [in] angle Angle of rotation (degrees)
340 * \param [in] object The object to rotate.
342 void o_rotate_world (TOPLEVEL
*toplevel
, int world_centerx
, int world_centery
, int angle
, OBJECT
*object
)
344 void (*func
) (TOPLEVEL
*, int, int, int, OBJECT
*) = NULL
;
346 switch (object
->type
) {
347 case OBJ_LINE
: func
= o_line_rotate_world
; break;
348 case OBJ_NET
: func
= o_net_rotate_world
; break;
349 case OBJ_BUS
: func
= o_bus_rotate_world
; break;
350 case OBJ_BOX
: func
= o_box_rotate_world
; break;
351 case OBJ_PICTURE
: func
= o_picture_rotate_world
; break;
352 case OBJ_CIRCLE
: func
= o_circle_rotate_world
; break;
353 case OBJ_PLACEHOLDER
:
354 case OBJ_COMPLEX
: func
= o_complex_rotate_world
; break;
355 case OBJ_TEXT
: func
= o_text_rotate_world
; break;
356 case OBJ_PATH
: func
= o_path_rotate_world
; break;
357 case OBJ_PIN
: func
= o_pin_rotate_world
; break;
358 case OBJ_ARC
: func
= o_arc_rotate_world
; break;
360 g_critical ("o_rotate_world: object %p has bad type '%c'\n",
361 object
, object
->type
);
365 (*func
) (toplevel
, world_centerx
, world_centery
, angle
, object
);
370 /*! \brief Mirrors an object in world coordinates
371 * \par Function Description
372 * This function mirrors an object about the point
373 * (<B>world_centerx</B>,<B>world_centery</B>) in world units.
375 * \param [in] toplevel The TOPLEVEL object.
376 * \param [in] world_centerx Origin x coordinate in WORLD units.
377 * \param [in] world_centery Origin y coordinate in WORLD units.
378 * \param [in,out] object The OBJECT to mirror.
380 void o_mirror_world (TOPLEVEL
*toplevel
, int world_centerx
, int world_centery
, OBJECT
*object
)
382 void (*func
) (TOPLEVEL
*, int, int, OBJECT
*) = NULL
;
384 switch (object
->type
) {
385 case OBJ_LINE
: func
= o_line_mirror_world
; break;
386 case OBJ_NET
: func
= o_net_mirror_world
; break;
387 case OBJ_BUS
: func
= o_bus_mirror_world
; break;
388 case OBJ_BOX
: func
= o_box_mirror_world
; break;
389 case OBJ_PICTURE
: func
= o_picture_mirror_world
; break;
390 case OBJ_CIRCLE
: func
= o_circle_mirror_world
; break;
391 case OBJ_PLACEHOLDER
:
392 case OBJ_COMPLEX
: func
= o_complex_mirror_world
; break;
393 case OBJ_TEXT
: func
= o_text_mirror_world
; break;
394 case OBJ_PATH
: func
= o_path_mirror_world
; break;
395 case OBJ_PIN
: func
= o_pin_mirror_world
; break;
396 case OBJ_ARC
: func
= o_arc_mirror_world
; break;
398 g_critical ("o_mirror_world: object %p has bad type '%c'\n",
399 object
, object
->type
);
403 (*func
) (toplevel
, world_centerx
, world_centery
, object
);
408 /*! \brief Calculates the distance between the given point and the closest
409 * point on the given object.
411 * \param [in] toplevel The TOPLEVEL object.
412 * \param [in] object The given object.
413 * \param [in] x The x coordinate of the given point.
414 * \param [in] y The y coordinate of the given point.
415 * \return The shortest distance from the object to the point. If the
416 * distance cannot be calculated, this function returns a really large
417 * number (G_MAXDOUBLE). If an error occurs, this function returns
420 double o_shortest_distance (TOPLEVEL
*toplevel
, OBJECT
*object
, int x
, int y
)
422 return o_shortest_distance_full (toplevel
, object
, x
, y
, FALSE
);
425 /*! \brief Calculates the distance between the given point and the closest
426 * point on the given object. Allows forcing objects to solid.
428 * \param [in] toplevel The TOPLEVEL object.
429 * \param [in] object The given object.
430 * \param [in] x The x coordinate of the given point.
431 * \param [in] y The y coordinate of the given point.
432 * \param [in] force_solid If true, force treating the object as solid.
433 * \return The shortest distance from the object to the point. If the
434 * distance cannot be calculated, this function returns a really large
435 * number (G_MAXDOUBLE). If an error occurs, this function returns
438 double o_shortest_distance_full (TOPLEVEL
*toplevel
, OBJECT
*object
,
439 int x
, int y
, int force_solid
)
441 double shortest_distance
= G_MAXDOUBLE
;
442 double (*func
) (TOPLEVEL
*, OBJECT
*, int, int, int) = NULL
;
444 g_return_val_if_fail (object
!= NULL
, G_MAXDOUBLE
);
446 switch(object
->type
) {
450 case OBJ_LINE
: func
= o_line_shortest_distance
; break;
451 case OBJ_BOX
: func
= o_box_shortest_distance
; break;
452 case OBJ_PICTURE
: func
= o_picture_shortest_distance
; break;
453 case OBJ_CIRCLE
: func
= o_circle_shortest_distance
; break;
454 case OBJ_PLACEHOLDER
:
455 case OBJ_COMPLEX
: func
= o_complex_shortest_distance
; break;
456 case OBJ_TEXT
: func
= o_text_shortest_distance
; break;
457 case OBJ_PATH
: func
= o_path_shortest_distance
; break;
458 case OBJ_ARC
: func
= o_arc_shortest_distance
; break;
460 g_critical ("o_shortest_distance: object %p has bad type '%c'\n",
461 object
, object
->type
);
465 shortest_distance
= (*func
) (toplevel
, object
, x
, y
, force_solid
);
468 return shortest_distance
;
471 /*! \brief Mark an OBJECT's cached bounds as invalid
472 * \par Function Description
473 * Recursively marks the cached bounds of the given OBJECT and its
474 * parents as having been invalidated and in need of an update. They
475 * will be recalculated next time the OBJECT's bounds are requested
476 * (e.g. via world_get_single_object_bounds() ).
477 * \param [in] toplevel
480 * \todo Turn this into a macro?
482 void o_bounds_invalidate(TOPLEVEL
*toplevel
, OBJECT
*obj
)
485 obj
->w_bounds_valid_for
= NULL
;
486 } while ((obj
= obj
->parent
) != NULL
);
490 /*! \brief Change the color of an object
492 * \par Function Description
493 * This function changes the color of an object.
495 * \param [in] toplevel The TOPLEVEL structure.
496 * \param [in] object The OBJECT to change color.
497 * \param [in] color The new color.
499 void o_set_color (TOPLEVEL
*toplevel
, OBJECT
*object
, int color
)
501 g_return_if_fail (object
!= NULL
);
503 object
->color
= color
;
505 if (object
->type
== OBJ_COMPLEX
||
506 object
->type
== OBJ_PLACEHOLDER
)
507 o_glist_set_color (toplevel
, object
->complex->prim_objs
, color
);
511 /*! \brief Get an object's parent PAGE.
513 * \par Function Description
514 * Returns the PAGE structure which owns \a object. If \a object is
515 * not currently associated with a PAGE, returns NULL. If \a object is
516 * part of a compound object, recurses upward.
518 * \param [in] toplevel The TOPLEVEL structure.
519 * \param [in] object The OBJECT for which to retrieve the parent PAGE.
520 * \return The PAGE which owns \a object or NULL.
522 * \sa s_page_append_object() s_page_append() s_page_remove()
525 o_get_page (TOPLEVEL
*toplevel
, OBJECT
*object
)
527 if (object
->parent
!= NULL
) {
528 return o_get_page (toplevel
, object
->parent
);
533 /*! \brief Get an object's containing complex object.
535 * \par Function Description
536 * If \a object is part of a complex #OBJECT, returns that
537 * #OBJECT. Otherwise, returns NULL.
539 * \param [in] toplevel The TOPLEVEL structure.
540 * \param [in] object The OBJECT for which to get the containing OBJECT.
541 * \return The complex OBJECT which owns \a object, or NULL.
544 o_get_parent (TOPLEVEL
*toplevel
, OBJECT
*object
)
546 g_return_val_if_fail ((object
!= NULL
), NULL
);
548 if (object
->parent
!= NULL
) {
549 return object
->parent
;
554 /* Structure for each entry in a TOPLEVEL's list of registered change
555 * notification handlers */
556 struct change_notify_entry
{
557 ChangeNotifyFunc pre_change_func
;
558 ChangeNotifyFunc change_func
;
562 /*! \brief Add change notification handlers to a TOPLEVEL.
563 * \par Function Description
564 * Adds a set of change notification handlers to a #TOPLEVEL instance.
565 * \a pre_change_func will be called just before an object is
566 * modified, and \a change_func will be called just after an object is
567 * modified, with the affected object and the given \a user_data.
569 * \param toplevel #TOPLEVEL structure to add handlers to.
570 * \param pre_change_func Function to be called just before changes.
571 * \param change_func Function to be called just after changes.
572 * \param user_data User data to be passed to callback functions.
575 o_add_change_notify (TOPLEVEL
*toplevel
,
576 ChangeNotifyFunc pre_change_func
,
577 ChangeNotifyFunc change_func
,
580 struct change_notify_entry
*entry
= g_new0 (struct change_notify_entry
, 1);
581 entry
->pre_change_func
= pre_change_func
;
582 entry
->change_func
= change_func
;
583 entry
->user_data
= user_data
;
584 toplevel
->change_notify_funcs
=
585 g_list_prepend (toplevel
->change_notify_funcs
, entry
);
588 /*! \brief Remove change notification handlers from a TOPLEVEL.
589 * \par Function Description
590 * Removes a set of change notification handlers and their associated
591 * \a user_data from \a toplevel. If no registered set of handlers
592 * matches the given \a pre_change_func, \a change_func and \a
593 * user_data, does nothing.
595 * \see o_add_change_notify()
597 * \param toplevel #TOPLEVEL structure to remove handlers from.
598 * \param pre_change_func Function called just before changes.
599 * \param change_func Function called just after changes.
600 * \param user_data User data passed to callback functions.
603 o_remove_change_notify (TOPLEVEL
*toplevel
,
604 ChangeNotifyFunc pre_change_func
,
605 ChangeNotifyFunc change_func
,
609 for (iter
= toplevel
->change_notify_funcs
;
610 iter
!= NULL
; iter
= g_list_next (iter
)) {
612 struct change_notify_entry
*entry
=
613 (struct change_notify_entry
*) iter
->data
;
616 && (entry
->pre_change_func
== pre_change_func
)
617 && (entry
->change_func
== change_func
)
618 && (entry
->user_data
== user_data
)) {
623 toplevel
->change_notify_funcs
=
624 g_list_remove_all (toplevel
->change_notify_funcs
, NULL
);
627 /*! \brief Emit an object pre-change notification.
628 * \par Function Description
629 * Calls each pre-change callback function registered with #TOPLEVEL
630 * to notify listeners that \a object is about to be modified. All
631 * libgeda functions that modify #OBJECT structures should call this
632 * just before making a change to an #OBJECT.
634 * \param toplevel #TOPLEVEL structure to emit notifications from.
635 * \param object #OBJECT structure to emit notifications for.
638 o_emit_pre_change_notify (TOPLEVEL
*toplevel
, OBJECT
*object
)
641 for (iter
= toplevel
->change_notify_funcs
;
642 iter
!= NULL
; iter
= g_list_next (iter
)) {
644 struct change_notify_entry
*entry
=
645 (struct change_notify_entry
*) iter
->data
;
647 if ((entry
!= NULL
) && (entry
->pre_change_func
!= NULL
)) {
648 entry
->pre_change_func (entry
->user_data
, object
);
653 /*! \brief Emit an object change notification.
654 * \par Function Description
655 * Calls each change callback function registered with #TOPLEVEL to
656 * notify listeners that \a object has just been modified. All
657 * libgeda functions that modify #OBJECT structures should call this
658 * just after making a change to an #OBJECT.
660 * \param toplevel #TOPLEVEL structure to emit notifications from.
661 * \param object #OBJECT structure to emit notifications for.
664 o_emit_change_notify (TOPLEVEL
*toplevel
, OBJECT
*object
)
667 for (iter
= toplevel
->change_notify_funcs
;
668 iter
!= NULL
; iter
= g_list_next (iter
)) {
670 struct change_notify_entry
*entry
=
671 (struct change_notify_entry
*) iter
->data
;
673 if ((entry
!= NULL
) && (entry
->change_func
!= NULL
)) {
674 entry
->change_func (entry
->user_data
, object
);
679 /*! \brief Query visibility of the object.
680 * \par Function Description
681 * Attribute getter for the visible field within the object.
683 * \param toplevel The TOPLEVEL structure
684 * \param object The OBJECT structure to be queried
685 * \return TRUE when VISIBLE, FALSE otherwise
688 o_is_visible (TOPLEVEL
*toplevel
, OBJECT
*object
)
690 g_return_val_if_fail (object
!= NULL
, FALSE
);
691 return object
->visibility
== VISIBLE
;
694 /*! \brief Set visibility of the object.
695 * \par Function Description
696 * Set value of visibility field within the object.
697 * If resulting visibility value is changed,
698 * invalidate the bounds of the object and parent objects.
700 * \param toplevel The #TOPLEVEL structure
701 * \param object The #OBJECT structure to be modified
704 o_set_visibility (TOPLEVEL
*toplevel
, OBJECT
*object
, int visibility
)
706 g_return_if_fail (object
!= NULL
);
707 if (object
->visibility
!= visibility
) {
708 object
->visibility
= visibility
;
709 o_bounds_invalidate (toplevel
, object
);