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);
80 /*! \brief Recalculate position of the given object.
81 * \par Function Description
82 * This function will take an object and recalculate its
83 * position on the screen.
85 * \param [in] toplevel The TOPLEVEL object.
86 * \param [in,out] o_current OBJECT to recalculate.
89 void o_recalc_single_object(TOPLEVEL
*toplevel
, OBJECT
*o_current
)
91 if (o_current
!= NULL
) {
92 switch(o_current
->type
) {
95 o_line_recalc(toplevel
, o_current
);
99 o_net_recalc(toplevel
, o_current
);
103 o_bus_recalc(toplevel
, o_current
);
107 o_box_recalc(toplevel
, o_current
);
111 o_path_recalc(toplevel
, o_current
);
115 o_picture_recalc(toplevel
, o_current
);
119 o_circle_recalc(toplevel
, o_current
);
123 case(OBJ_PLACEHOLDER
):
124 o_complex_recalc(toplevel
, o_current
);
128 o_pin_recalc(toplevel
, o_current
);
132 o_arc_recalc(toplevel
, o_current
);
136 o_text_recalc(toplevel
, o_current
);
143 /*! \brief Recalculate position of a list (GList) of objects.
144 * \par Function Description
145 * This function will take a list (GList) of objects and recalculate their
146 * positions on the screen.
148 * \param [in] toplevel The TOPLEVEL object.
149 * \param [in,out] object_glist OBJECT list to recalculate.
153 o_recalc_object_glist(TOPLEVEL
*toplevel
, GList
*object_glist
)
155 GList
*list
= object_glist
;
158 while (list
!= NULL
) {
159 o_current
= (OBJECT
*) list
->data
;
160 o_recalc_single_object(toplevel
, o_current
);
161 list
= g_list_next(list
);
166 /*! \brief Set an #OBJECT's line options.
167 * \par Function Description
168 * This function allows a line's end, type, width, length and space to be set.
169 * See #OBJECT_END and #OBJECT_TYPE for information on valid
170 * object end and type values.
172 * \param [in] toplevel The TOPLEVEL object.
173 * \param [in,out] o_current OBJECT to set line options on.
174 * \param [in] end An OBJECT_END.
175 * \param [in] type An OBJECT_TYPE.
176 * \param [in] width Line width.
177 * \param [in] length Line length.
178 * \param [in] space Spacing between dashes/dots. Cannot be negative.
180 * \todo Make space an unsigned int and check for a max value instead.
181 * If a max value is not required, then it would simplify the code.
183 void o_set_line_options(TOPLEVEL
*toplevel
, OBJECT
*o_current
,
184 OBJECT_END end
, OBJECT_TYPE type
,
185 int width
, int length
, int space
)
187 if(o_current
== NULL
) {
191 /* do some error checking / correcting */
196 s_log_message (_("Invalid space specified, setting to 100\n"));
204 s_log_message (_("Invalid length specified, setting to 100\n"));
208 s_log_message (_("Invalid space specified, setting to 100\n"));
216 o_emit_pre_change_notify (toplevel
, o_current
);
218 o_current
->line_width
= width
;
219 o_current
->line_end
= end
;
220 o_current
->line_type
= type
;
222 o_current
->line_length
= length
;
223 o_current
->line_space
= space
;
225 /* Recalculate the object's bounding box */
226 o_recalc_single_object( toplevel
, o_current
);
227 o_emit_change_notify (toplevel
, o_current
);
231 /*! \brief get #OBJECT's line properties.
232 * \par Function Description
233 * This function get's the #OBJECT's line options.
234 * See #OBJECT_END and #OBJECT_TYPE for information on valid
235 * object end and type values.
237 * \param [in] object OBJECT to read the properties
238 * \param [out] end An OBJECT_END.
239 * \param [out] type An OBJECT_TYPE.
240 * \param [out] width Line width.
241 * \param [out] length Line length.
242 * \param [out] space Spacing between dashes/dots.
243 * \return TRUE on succes, FALSE otherwise
246 gboolean
o_get_line_options(OBJECT
*object
,
247 OBJECT_END
*end
, OBJECT_TYPE
*type
,
248 int *width
, int *length
, int *space
)
250 if (object
->type
!= OBJ_LINE
251 && object
->type
!= OBJ_ARC
252 && object
->type
!= OBJ_BOX
253 && object
->type
!= OBJ_CIRCLE
254 && object
->type
!= OBJ_PATH
)
257 *end
= object
->line_end
;
258 *type
= object
->line_type
;
259 *width
= object
->line_width
;
260 *length
= object
->line_length
;
261 *space
= object
->line_space
;
266 /*! \brief Set #OBJECT's fill options.
267 * \par Function Description
268 * This function allows an #OBJECT's fill options to be configured.
269 * See #OBJECT_FILLING for information on valid fill types.
271 * \param [in] toplevel The TOPLEVEL object.
272 * \param [in,out] o_current OBJECT to be updated.
273 * \param [in] type OBJECT_FILLING type.
274 * \param [in] width fill width.
275 * \param [in] pitch1 cross hatch line distance
276 * \param [in] angle1 cross hatch angle
277 * \param [in] pitch2 cross hatch line distance
278 * \param [in] angle2 cross hatch angle
281 void o_set_fill_options(TOPLEVEL
*toplevel
, OBJECT
*o_current
,
282 OBJECT_FILLING type
, int width
,
283 int pitch1
, int angle1
,
284 int pitch2
, int angle2
)
286 if(o_current
== NULL
) {
290 o_emit_pre_change_notify (toplevel
, o_current
);
292 o_current
->fill_type
= type
;
293 o_current
->fill_width
= width
;
295 o_current
->fill_pitch1
= pitch1
;
296 o_current
->fill_angle1
= angle1
;
298 o_current
->fill_pitch2
= pitch2
;
299 o_current
->fill_angle2
= angle2
;
301 o_emit_change_notify (toplevel
, o_current
);
304 /*! \brief get #OBJECT's fill properties.
305 * \par Function Description
306 * This function get's the #OBJECT's fill options.
307 * See #OBJECT_FILLING for information on valid fill types.
309 * \param [in] object OBJECT to read the properties
310 * \param [out] type OBJECT_FILLING type
311 * \param [out] width fill width.
312 * \param [out] pitch1 cross hatch line distance
313 * \param [out] angle1 cross hatch angle
314 * \param [out] pitch2 cross hatch line distance
315 * \param [out] angle2 cross hatch angle
316 * \return TRUE on succes, FALSE otherwise
319 gboolean
o_get_fill_options(OBJECT
*object
,
320 OBJECT_FILLING
*type
, int *width
,
321 int *pitch1
, int *angle1
,
322 int *pitch2
, int *angle2
)
324 if (object
->type
!= OBJ_BOX
325 && object
->type
!= OBJ_CIRCLE
326 && object
->type
!= OBJ_PATH
)
329 *type
= object
->fill_type
;
330 *width
= object
->fill_width
;
331 *pitch1
= object
->fill_pitch1
;
332 *angle1
= object
->fill_angle1
;
333 *pitch2
= object
->fill_pitch2
;
334 *angle2
= object
->fill_angle2
;
339 /*! \brief get the base position of an object
340 * \par Function Description
341 * This function gets the position of an object in world coordinates.
343 * \param [in] toplevel The toplevel environment.
344 * \param [out] x pointer to the x-position
345 * \param [out] y pointer to the y-position
346 * \param [in] object The object to get the position.
347 * \return TRUE if successfully determined the position, FALSE otherwise
349 gboolean
o_get_position (TOPLEVEL
*toplevel
, gint
*x
, gint
*y
, OBJECT
*object
)
351 gboolean (*func
) (TOPLEVEL
*, int*, int*, OBJECT
*) = NULL
;
353 switch (object
->type
) {
354 case OBJ_LINE
: func
= o_line_get_position
; break;
355 case OBJ_NET
: func
= o_net_get_position
; break;
356 case OBJ_BUS
: func
= o_bus_get_position
; break;
357 case OBJ_BOX
: func
= o_box_get_position
; break;
358 case OBJ_PICTURE
: func
= o_picture_get_position
; break;
359 case OBJ_CIRCLE
: func
= o_circle_get_position
; break;
360 case OBJ_PLACEHOLDER
:
361 case OBJ_COMPLEX
: func
= o_complex_get_position
; break;
362 case OBJ_TEXT
: func
= o_text_get_position
; break;
363 case OBJ_PATH
: func
= o_path_get_position
; break;
364 case OBJ_PIN
: func
= o_pin_get_position
; break;
365 case OBJ_ARC
: func
= o_arc_get_position
; break;
367 g_critical ("o_get_position: object %p has bad type '%c'\n",
368 object
, object
->type
);
372 return (*func
) (toplevel
, x
, y
, object
);
378 /*! \brief Translates an object in world coordinates
379 * \par Function Description
380 * This function translates the object <B>object</B> by
381 * <B>dx</B> and <B>dy</B>.
383 * \param [in] toplevel The toplevel environment.
384 * \param [in] dx Amount to horizontally translate object
385 * \param [in] dy Amount to vertically translate object
386 * \param [in] object The object to translate.
388 void o_translate_world (TOPLEVEL
*toplevel
, gint dx
, gint dy
, OBJECT
*object
)
390 void (*func
) (TOPLEVEL
*, int, int, OBJECT
*) = NULL
;
392 switch (object
->type
) {
393 case OBJ_LINE
: func
= o_line_translate_world
; break;
394 case OBJ_NET
: func
= o_net_translate_world
; break;
395 case OBJ_BUS
: func
= o_bus_translate_world
; break;
396 case OBJ_BOX
: func
= o_box_translate_world
; break;
397 case OBJ_PICTURE
: func
= o_picture_translate_world
; break;
398 case OBJ_CIRCLE
: func
= o_circle_translate_world
; break;
399 case OBJ_PLACEHOLDER
:
400 case OBJ_COMPLEX
: func
= o_complex_translate_world
; break;
401 case OBJ_TEXT
: func
= o_text_translate_world
; break;
402 case OBJ_PATH
: func
= o_path_translate_world
; break;
403 case OBJ_PIN
: func
= o_pin_translate_world
; break;
404 case OBJ_ARC
: func
= o_arc_translate_world
; break;
406 g_critical ("o_translate_world: object %p has bad type '%c'\n",
407 object
, object
->type
);
411 (*func
) (toplevel
, dx
, dy
, object
);
416 /*! \brief Rotates an object in world coordinates
417 * \par Function Description
418 * This function rotates the object <B>object</B> about the coordinates
419 * <B>world_centerx</B> and <B>world_centery</B>, by <B>angle</B>degrees.
421 * \param [in] toplevel The toplevel environment.
422 * \param [in] world_centerx X coordinate of rotation center (world coords)
423 * \param [in] world_centery Y coordinate of rotation center (world coords)
424 * \param [in] angle Angle of rotation (degrees)
425 * \param [in] object The object to rotate.
427 void o_rotate_world (TOPLEVEL
*toplevel
, int world_centerx
, int world_centery
, int angle
, OBJECT
*object
)
429 void (*func
) (TOPLEVEL
*, int, int, int, OBJECT
*) = NULL
;
431 switch (object
->type
) {
432 case OBJ_LINE
: func
= o_line_rotate_world
; break;
433 case OBJ_NET
: func
= o_net_rotate_world
; break;
434 case OBJ_BUS
: func
= o_bus_rotate_world
; break;
435 case OBJ_BOX
: func
= o_box_rotate_world
; break;
436 case OBJ_PICTURE
: func
= o_picture_rotate_world
; break;
437 case OBJ_CIRCLE
: func
= o_circle_rotate_world
; break;
438 case OBJ_PLACEHOLDER
:
439 case OBJ_COMPLEX
: func
= o_complex_rotate_world
; break;
440 case OBJ_TEXT
: func
= o_text_rotate_world
; break;
441 case OBJ_PATH
: func
= o_path_rotate_world
; break;
442 case OBJ_PIN
: func
= o_pin_rotate_world
; break;
443 case OBJ_ARC
: func
= o_arc_rotate_world
; break;
445 g_critical ("o_rotate_world: object %p has bad type '%c'\n",
446 object
, object
->type
);
450 (*func
) (toplevel
, world_centerx
, world_centery
, angle
, object
);
455 /*! \brief Mirrors an object in world coordinates
456 * \par Function Description
457 * This function mirrors an object about the point
458 * (<B>world_centerx</B>,<B>world_centery</B>) in world units.
460 * \param [in] toplevel The TOPLEVEL object.
461 * \param [in] world_centerx Origin x coordinate in WORLD units.
462 * \param [in] world_centery Origin y coordinate in WORLD units.
463 * \param [in,out] object The OBJECT to mirror.
465 void o_mirror_world (TOPLEVEL
*toplevel
, int world_centerx
, int world_centery
, OBJECT
*object
)
467 void (*func
) (TOPLEVEL
*, int, int, OBJECT
*) = NULL
;
469 switch (object
->type
) {
470 case OBJ_LINE
: func
= o_line_mirror_world
; break;
471 case OBJ_NET
: func
= o_net_mirror_world
; break;
472 case OBJ_BUS
: func
= o_bus_mirror_world
; break;
473 case OBJ_BOX
: func
= o_box_mirror_world
; break;
474 case OBJ_PICTURE
: func
= o_picture_mirror_world
; break;
475 case OBJ_CIRCLE
: func
= o_circle_mirror_world
; break;
476 case OBJ_PLACEHOLDER
:
477 case OBJ_COMPLEX
: func
= o_complex_mirror_world
; break;
478 case OBJ_TEXT
: func
= o_text_mirror_world
; break;
479 case OBJ_PATH
: func
= o_path_mirror_world
; break;
480 case OBJ_PIN
: func
= o_pin_mirror_world
; break;
481 case OBJ_ARC
: func
= o_arc_mirror_world
; break;
483 g_critical ("o_mirror_world: object %p has bad type '%c'\n",
484 object
, object
->type
);
488 (*func
) (toplevel
, world_centerx
, world_centery
, object
);
493 /*! \brief Calculates the distance between the given point and the closest
494 * point on the given object.
496 * \param [in] object The given object.
497 * \param [in] x The x coordinate of the given point.
498 * \param [in] y The y coordinate of the given point.
499 * \return The shortest distance from the object to the point. If the
500 * distance cannot be calculated, this function returns a really large
501 * number (G_MAXDOUBLE). If an error occurs, this function returns
504 double o_shortest_distance (OBJECT
*object
, int x
, int y
)
506 return o_shortest_distance_full (object
, x
, y
, FALSE
);
509 /*! \brief Calculates the distance between the given point and the closest
510 * point on the given object. Allows forcing objects to solid.
512 * \param [in] object The given object.
513 * \param [in] x The x coordinate of the given point.
514 * \param [in] y The y coordinate of the given point.
515 * \param [in] force_solid If true, force treating the object as solid.
516 * \return The shortest distance from the object to the point. If the
517 * distance cannot be calculated, this function returns a really large
518 * number (G_MAXDOUBLE). If an error occurs, this function returns
521 double o_shortest_distance_full (OBJECT
*object
, int x
, int y
, int force_solid
)
523 double shortest_distance
= G_MAXDOUBLE
;
524 double (*func
) (OBJECT
*, int, int, int) = NULL
;
526 g_return_val_if_fail (object
!= NULL
, G_MAXDOUBLE
);
528 switch(object
->type
) {
532 case OBJ_LINE
: func
= o_line_shortest_distance
; break;
533 case OBJ_BOX
: func
= o_box_shortest_distance
; break;
534 case OBJ_PICTURE
: func
= o_picture_shortest_distance
; break;
535 case OBJ_CIRCLE
: func
= o_circle_shortest_distance
; break;
536 case OBJ_PLACEHOLDER
:
537 case OBJ_COMPLEX
: func
= o_complex_shortest_distance
; break;
538 case OBJ_TEXT
: func
= o_text_shortest_distance
; break;
539 case OBJ_PATH
: func
= o_path_shortest_distance
; break;
540 case OBJ_ARC
: func
= o_arc_shortest_distance
; break;
542 g_critical ("o_shortest_distance: object %p has bad type '%c'\n",
543 object
, object
->type
);
547 shortest_distance
= (*func
) (object
, x
, y
, force_solid
);
550 return shortest_distance
;
553 /*! \brief Mark an OBJECT's cached bounds as invalid
554 * \par Function Description
555 * Recursively marks the cached bounds of the given OBJECT and its
556 * parents as having been invalidated and in need of an update. They
557 * will be recalculated next time the OBJECT's bounds are requested
558 * (e.g. via world_get_single_object_bounds() ).
559 * \param [in] toplevel
562 * \todo Turn this into a macro?
564 void o_bounds_invalidate(TOPLEVEL
*toplevel
, OBJECT
*obj
)
567 obj
->w_bounds_valid
= FALSE
;
568 } while ((obj
= obj
->parent
) != NULL
);
572 /*! \brief Change the color of an object
574 * \par Function Description
575 * This function changes the color of an object.
577 * \param [in] toplevel The TOPLEVEL structure.
578 * \param [in] object The OBJECT to change color.
579 * \param [in] color The new color.
581 void o_set_color (TOPLEVEL
*toplevel
, OBJECT
*object
, int color
)
583 g_return_if_fail (object
!= NULL
);
585 object
->color
= color
;
587 if (object
->type
== OBJ_COMPLEX
||
588 object
->type
== OBJ_PLACEHOLDER
)
589 o_glist_set_color (toplevel
, object
->complex->prim_objs
, color
);
593 /*! \brief Get an object's parent PAGE.
595 * \par Function Description
596 * Returns the PAGE structure which owns \a object. If \a object is
597 * not currently associated with a PAGE, returns NULL. If \a object is
598 * part of a compound object, recurses upward.
600 * \param [in] toplevel The TOPLEVEL structure.
601 * \param [in] object The OBJECT for which to retrieve the parent PAGE.
602 * \return The PAGE which owns \a object or NULL.
604 * \sa s_page_append_object() s_page_append() s_page_remove()
607 o_get_page (TOPLEVEL
*toplevel
, OBJECT
*object
)
609 if (object
->parent
!= NULL
) {
610 return o_get_page (toplevel
, object
->parent
);
615 /*! \brief Get an object's parent PAGE, or fall back to global current page.
617 * \par Function Description
618 * If set, returns the PAGE structure which owns \a object. If \a
619 * object does not have a parent page set, returns the global current
620 * page from \a toplevel. If the object parent page is inconsistent
621 * with the global current page, a critical-level error message is
624 * \warning This function is primarily intended to assist in the
625 * migration of code from using the TOPLEVEL current page to using the
626 * o_get_page(). It should not be used in new code.
628 * \deprecated Use o_get_page() in new code.
630 * \param [in] toplevel The TOPLEVEL structure.
631 * \param [in] object The OBJECT for which to retrieve the parent PAGE.
632 * \return The PAGE which owns \a object, the global current PAGE, or NULL.
635 o_get_page_compat (TOPLEVEL
*toplevel
, OBJECT
*object
) {
636 PAGE
*page
= o_get_page (toplevel
, object
);
637 if (page
!= toplevel
->page_current
) {
638 g_critical ("o_get_page_compat: OBJECT.page = %p, TOPLEVEL.page_current = %p",
639 page
, toplevel
->page_current
);
640 return toplevel
->page_current
;
646 /*! \brief Get an object's containing complex object.
648 * \par Function Description
649 * If \a object is part of a complex #OBJECT, returns that
650 * #OBJECT. Otherwise, returns NULL.
652 * \param [in] toplevel The TOPLEVEL structure.
653 * \param [in] object The OBJECT for which to get the containing OBJECT.
654 * \return The complex OBJECT which owns \a object, or NULL.
657 o_get_parent (TOPLEVEL
*toplevel
, OBJECT
*object
)
659 g_return_val_if_fail ((object
!= NULL
), NULL
);
661 if (object
->parent
!= NULL
) {
662 return object
->parent
;
667 /* Structure for each entry in a TOPLEVEL's list of registered change
668 * notification handlers */
669 struct change_notify_entry
{
670 ChangeNotifyFunc pre_change_func
;
671 ChangeNotifyFunc change_func
;
675 /*! \brief Add change notification handlers to a TOPLEVEL.
676 * \par Function Description
677 * Adds a set of change notification handlers to a #TOPLEVEL instance.
678 * \a pre_change_func will be called just before an object is
679 * modified, and \a change_func will be called just after an object is
680 * modified, with the affected object and the given \a user_data.
682 * \param toplevel #TOPLEVEL structure to add handlers to.
683 * \param pre_change_func Function to be called just before changes.
684 * \param change_func Function to be called just after changes.
685 * \param user_data User data to be passed to callback functions.
688 o_add_change_notify (TOPLEVEL
*toplevel
,
689 ChangeNotifyFunc pre_change_func
,
690 ChangeNotifyFunc change_func
,
693 struct change_notify_entry
*entry
= g_new0 (struct change_notify_entry
, 1);
694 entry
->pre_change_func
= pre_change_func
;
695 entry
->change_func
= change_func
;
696 entry
->user_data
= user_data
;
697 toplevel
->change_notify_funcs
=
698 g_list_prepend (toplevel
->change_notify_funcs
, entry
);
701 /*! \brief Remove change notification handlers from a TOPLEVEL.
702 * \par Function Description
703 * Removes a set of change notification handlers and their associated
704 * \a user_data from \a toplevel. If no registered set of handlers
705 * matches the given \a pre_change_func, \a change_func and \a
706 * user_data, does nothing.
708 * \see o_add_change_notify()
710 * \param toplevel #TOPLEVEL structure to remove handlers from.
711 * \param pre_change_func Function called just before changes.
712 * \param change_func Function called just after changes.
713 * \param user_data User data passed to callback functions.
716 o_remove_change_notify (TOPLEVEL
*toplevel
,
717 ChangeNotifyFunc pre_change_func
,
718 ChangeNotifyFunc change_func
,
722 for (iter
= toplevel
->change_notify_funcs
;
723 iter
!= NULL
; iter
= g_list_next (iter
)) {
725 struct change_notify_entry
*entry
=
726 (struct change_notify_entry
*) iter
->data
;
729 && (entry
->pre_change_func
== pre_change_func
)
730 && (entry
->change_func
== change_func
)
731 && (entry
->user_data
== user_data
)) {
736 toplevel
->change_notify_funcs
=
737 g_list_remove_all (toplevel
->change_notify_funcs
, NULL
);
740 /*! \brief Emit an object pre-change notification.
741 * \par Function Description
742 * Calls each pre-change callback function registered with #TOPLEVEL
743 * to notify listeners that \a object is about to be modified. All
744 * libgeda functions that modify #OBJECT structures should call this
745 * just before making a change to an #OBJECT.
747 * \param toplevel #TOPLEVEL structure to emit notifications from.
748 * \param object #OBJECT structure to emit notifications for.
751 o_emit_pre_change_notify (TOPLEVEL
*toplevel
, OBJECT
*object
)
754 for (iter
= toplevel
->change_notify_funcs
;
755 iter
!= NULL
; iter
= g_list_next (iter
)) {
757 struct change_notify_entry
*entry
=
758 (struct change_notify_entry
*) iter
->data
;
760 if ((entry
!= NULL
) && (entry
->pre_change_func
!= NULL
)) {
761 entry
->pre_change_func (entry
->user_data
, object
);
766 /*! \brief Emit an object change notification.
767 * \par Function Description
768 * Calls each change callback function registered with #TOPLEVEL to
769 * notify listeners that \a object has just been modified. All
770 * libgeda functions that modify #OBJECT structures should call this
771 * just after making a change to an #OBJECT.
773 * \param toplevel #TOPLEVEL structure to emit notifications from.
774 * \param object #OBJECT structure to emit notifications for.
777 o_emit_change_notify (TOPLEVEL
*toplevel
, OBJECT
*object
)
780 for (iter
= toplevel
->change_notify_funcs
;
781 iter
!= NULL
; iter
= g_list_next (iter
)) {
783 struct change_notify_entry
*entry
=
784 (struct change_notify_entry
*) iter
->data
;
786 if ((entry
!= NULL
) && (entry
->change_func
!= NULL
)) {
787 entry
->change_func (entry
->user_data
, object
);
792 /*! \brief Query visibility of the object.
793 * \par Function Description
794 * Attribute getter for the visible field within the object.
796 * \param toplevel The TOPLEVEL structure
797 * \param object The OBJECT structure to be queried
798 * \return TRUE when VISIBLE, FALSE otherwise
801 o_is_visible (TOPLEVEL
*toplevel
, OBJECT
*object
)
803 g_return_val_if_fail (object
!= NULL
, FALSE
);
804 return object
->visibility
== VISIBLE
;
807 /*! \brief Set visibility of the object.
808 * \par Function Description
809 * Set value of visibility field within the object.
810 * If resulting visibility value is changed,
811 * invalidate the bounds of the object and parent objects.
813 * \param toplevel The #TOPLEVEL structure
814 * \param object The #OBJECT structure to be modified
817 o_set_visibility (TOPLEVEL
*toplevel
, OBJECT
*object
, int visibility
)
819 g_return_if_fail (object
!= NULL
);
820 if (object
->visibility
!= visibility
) {
821 object
->visibility
= visibility
;
822 o_bounds_invalidate (toplevel
, object
);