libgeda: remove LEAVE_VISIBILITY_ALONE
[geda-gaf.git] / libgeda / src / o_basic.c
blob37b941e781a359a5e7f84a1ac367509769b8914e
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
21 /*! \file o_basic.c
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
26 * and symbol files.
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
45 #include <config.h>
47 #include <stdio.h>
49 /* instrumentation code */
50 #if 0
51 #include <sys/time.h>
52 #include <unistd.h>
53 #endif
55 #include "libgeda_priv.h"
57 #ifdef HAVE_LIBDMALLOC
58 #include <dmalloc.h>
59 #endif
61 /*! Default setting for object selection function. */
62 void (*select_func)() = NULL;
65 /*! \brief Check if point is inside a region
66 * \par Function Description
67 * This function takes a rectangular region and a point. It will check
68 * if the point is located in the region or not.
70 * \param [in] xmin Smaller x coordinate of the region.
71 * \param [in] ymin Smaller y coordinate of the region.
72 * \param [in] xmax Larger x coordinate of the region.
73 * \param [in] ymax Larger y coordinate of the region.
74 * \param [in] x x coordinate of the point to check.
75 * \param [in] y y coordinate of the point to check.
76 * \return 1 if the point is inside the region, 0 otherwise.
78 int inside_region(int xmin, int ymin, int xmax, int ymax, int x, int y)
80 return ((x >= xmin && x <= xmax && y >= ymin && y <= ymax) ? 1 : 0);
83 /*! \brief Recalculate position of the given object.
84 * \par Function Description
85 * This function will take an object and recalculate its
86 * position on the screen.
88 * \param [in] toplevel The TOPLEVEL object.
89 * \param [in,out] o_current OBJECT to recalculate.
92 void o_recalc_single_object(TOPLEVEL *toplevel, OBJECT *o_current)
94 if (o_current != NULL) {
95 switch(o_current->type) {
97 case(OBJ_LINE):
98 o_line_recalc(toplevel, o_current);
99 break;
101 case(OBJ_NET):
102 o_net_recalc(toplevel, o_current);
103 break;
105 case(OBJ_BUS):
106 o_bus_recalc(toplevel, o_current);
107 break;
109 case(OBJ_BOX):
110 o_box_recalc(toplevel, o_current);
111 break;
113 case(OBJ_PATH):
114 o_path_recalc(toplevel, o_current);
115 break;
117 case(OBJ_PICTURE):
118 o_picture_recalc(toplevel, o_current);
119 break;
121 case(OBJ_CIRCLE):
122 o_circle_recalc(toplevel, o_current);
123 break;
125 case(OBJ_COMPLEX):
126 case(OBJ_PLACEHOLDER):
127 o_complex_recalc(toplevel, o_current);
128 break;
130 case(OBJ_PIN):
131 o_pin_recalc(toplevel, o_current);
132 break;
134 case(OBJ_ARC):
135 o_arc_recalc(toplevel, o_current);
136 break;
138 case(OBJ_TEXT):
139 o_text_recalc(toplevel, o_current);
140 break;
146 /*! \brief Recalculate position of a list (GList) of objects.
147 * \par Function Description
148 * This function will take a list (GList) of objects and recalculate their
149 * positions on the screen.
151 * \param [in] toplevel The TOPLEVEL object.
152 * \param [in,out] object_glist OBJECT list to recalculate.
155 void
156 o_recalc_object_glist(TOPLEVEL *toplevel, GList *object_glist)
158 GList *list = object_glist;
159 OBJECT *o_current;
161 while (list != NULL) {
162 o_current = (OBJECT *) list->data;
163 o_recalc_single_object(toplevel, o_current);
164 list = g_list_next(list);
169 /*! \brief Set an #OBJECT's line options.
170 * \par Function Description
171 * This function allows a line's end, type, width, length and space to be set.
172 * See #OBJECT_END and #OBJECT_TYPE for information on valid
173 * object end and type values.
175 * \param [in] toplevel The TOPLEVEL object.
176 * \param [in,out] o_current OBJECT to set line options on.
177 * \param [in] end An OBJECT_END.
178 * \param [in] type An OBJECT_TYPE.
179 * \param [in] width Line width.
180 * \param [in] length Line length.
181 * \param [in] space Spacing between dashes/dots. Cannot be negative.
183 * \todo Make space an unsigned int and check for a max value instead.
184 * If a max value is not required, then it would simplify the code.
186 void o_set_line_options(TOPLEVEL *toplevel, OBJECT *o_current,
187 OBJECT_END end, OBJECT_TYPE type,
188 int width, int length, int space)
190 if(o_current == NULL) {
191 return;
194 /* do some error checking / correcting */
195 switch(type) {
196 case(TYPE_DOTTED):
197 if (space < 1) {
198 space = 100;
199 s_log_message (_("Invalid space specified, setting to 100\n"));
201 break;
202 case(TYPE_DASHED):
203 case(TYPE_CENTER):
204 case(TYPE_PHANTOM):
205 if (length < 1) {
206 length = 100;
207 s_log_message (_("Invalid length specified, setting to 100\n"));
209 if (space < 1) {
210 space = 100;
211 s_log_message (_("Invalid space specified, setting to 100\n"));
213 break;
214 default:
216 break;
219 o_emit_pre_change_notify (toplevel, o_current);
221 o_current->line_width = width;
222 o_current->line_end = end;
223 o_current->line_type = type;
225 o_current->line_length = length;
226 o_current->line_space = space;
228 /* Recalculate the object's bounding box */
229 o_recalc_single_object( toplevel, o_current );
230 o_emit_change_notify (toplevel, o_current);
234 /*! \brief get #OBJECT's line properties.
235 * \par Function Description
236 * This function get's the #OBJECT's line options.
237 * See #OBJECT_END and #OBJECT_TYPE for information on valid
238 * object end and type values.
240 * \param [in] object OBJECT to read the properties
241 * \param [out] end An OBJECT_END.
242 * \param [out] type An OBJECT_TYPE.
243 * \param [out] width Line width.
244 * \param [out] length Line length.
245 * \param [out] space Spacing between dashes/dots.
246 * \return TRUE on succes, FALSE otherwise
249 gboolean o_get_line_options(OBJECT *object,
250 OBJECT_END *end, OBJECT_TYPE *type,
251 int *width, int *length, int *space)
253 if (object->type != OBJ_LINE
254 && object->type != OBJ_ARC
255 && object->type != OBJ_BOX
256 && object->type != OBJ_CIRCLE
257 && object->type != OBJ_PATH)
258 return FALSE;
260 *end = object->line_end;
261 *type = object->line_type;
262 *width = object->line_width;
263 *length = object->line_length;
264 *space = object->line_space;
266 return TRUE;
269 /*! \brief Set #OBJECT's fill options.
270 * \par Function Description
271 * This function allows an #OBJECT's fill options to be configured.
272 * See #OBJECT_FILLING for information on valid fill types.
274 * \param [in] toplevel The TOPLEVEL object.
275 * \param [in,out] o_current OBJECT to be updated.
276 * \param [in] type OBJECT_FILLING type.
277 * \param [in] width fill width.
278 * \param [in] pitch1 cross hatch line distance
279 * \param [in] angle1 cross hatch angle
280 * \param [in] pitch2 cross hatch line distance
281 * \param [in] angle2 cross hatch angle
284 void o_set_fill_options(TOPLEVEL *toplevel, OBJECT *o_current,
285 OBJECT_FILLING type, int width,
286 int pitch1, int angle1,
287 int pitch2, int angle2)
289 if(o_current == NULL) {
290 return;
293 o_emit_pre_change_notify (toplevel, o_current);
295 o_current->fill_type = type;
296 o_current->fill_width = width;
298 o_current->fill_pitch1 = pitch1;
299 o_current->fill_angle1 = angle1;
301 o_current->fill_pitch2 = pitch2;
302 o_current->fill_angle2 = angle2;
304 o_emit_change_notify (toplevel, o_current);
307 /*! \brief get #OBJECT's fill properties.
308 * \par Function Description
309 * This function get's the #OBJECT's fill options.
310 * See #OBJECT_FILLING for information on valid fill types.
312 * \param [in] object OBJECT to read the properties
313 * \param [out] type OBJECT_FILLING type
314 * \param [out] width fill width.
315 * \param [out] pitch1 cross hatch line distance
316 * \param [out] angle1 cross hatch angle
317 * \param [out] pitch2 cross hatch line distance
318 * \param [out] angle2 cross hatch angle
319 * \return TRUE on succes, FALSE otherwise
322 gboolean o_get_fill_options(OBJECT *object,
323 OBJECT_FILLING *type, int *width,
324 int *pitch1, int *angle1,
325 int *pitch2, int *angle2)
327 if (object->type != OBJ_BOX
328 && object->type != OBJ_CIRCLE
329 && object->type != OBJ_PATH)
330 return FALSE;
332 *type = object->fill_type;
333 *width = object->fill_width;
334 *pitch1 = object->fill_pitch1;
335 *angle1 = object->fill_angle1;
336 *pitch2 = object->fill_pitch2;
337 *angle2 = object->fill_angle2;
339 return TRUE;
342 /*! \brief get the base position of an object
343 * \par Function Description
344 * This function gets the position of an object in world coordinates.
346 * \param [in] toplevel The toplevel environment.
347 * \param [out] x pointer to the x-position
348 * \param [out] y pointer to the y-position
349 * \param [in] object The object to get the position.
350 * \return TRUE if successfully determined the position, FALSE otherwise
352 gboolean o_get_position (TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *object)
354 gboolean (*func) (TOPLEVEL*, int*, int*, OBJECT*) = NULL;
356 switch (object->type) {
357 case OBJ_LINE: func = o_line_get_position; break;
358 case OBJ_NET: func = o_net_get_position; break;
359 case OBJ_BUS: func = o_bus_get_position; break;
360 case OBJ_BOX: func = o_box_get_position; break;
361 case OBJ_PICTURE: func = o_picture_get_position; break;
362 case OBJ_CIRCLE: func = o_circle_get_position; break;
363 case OBJ_PLACEHOLDER:
364 case OBJ_COMPLEX: func = o_complex_get_position; break;
365 case OBJ_TEXT: func = o_text_get_position; break;
366 case OBJ_PATH: func = o_path_get_position; break;
367 case OBJ_PIN: func = o_pin_get_position; break;
368 case OBJ_ARC: func = o_arc_get_position; break;
369 default:
370 g_critical ("o_get_position: object %p has bad type '%c'\n",
371 object, object->type);
374 if (func != NULL) {
375 return (*func) (toplevel, x, y, object);
377 return FALSE;
381 /*! \brief Translates an object in world coordinates
382 * \par Function Description
383 * This function translates the object <B>object</B> by
384 * <B>dx</B> and <B>dy</B>.
386 * \param [in] toplevel The toplevel environment.
387 * \param [in] dx Amount to horizontally translate object
388 * \param [in] dy Amount to vertically translate object
389 * \param [in] object The object to translate.
391 void o_translate_world (TOPLEVEL *toplevel, gint dx, gint dy, OBJECT *object)
393 void (*func) (TOPLEVEL*, int, int, OBJECT*) = NULL;
395 switch (object->type) {
396 case OBJ_LINE: func = o_line_translate_world; break;
397 case OBJ_NET: func = o_net_translate_world; break;
398 case OBJ_BUS: func = o_bus_translate_world; break;
399 case OBJ_BOX: func = o_box_translate_world; break;
400 case OBJ_PICTURE: func = o_picture_translate_world; break;
401 case OBJ_CIRCLE: func = o_circle_translate_world; break;
402 case OBJ_PLACEHOLDER:
403 case OBJ_COMPLEX: func = o_complex_translate_world; break;
404 case OBJ_TEXT: func = o_text_translate_world; break;
405 case OBJ_PATH: func = o_path_translate_world; break;
406 case OBJ_PIN: func = o_pin_translate_world; break;
407 case OBJ_ARC: func = o_arc_translate_world; break;
408 default:
409 g_critical ("o_translate_world: object %p has bad type '%c'\n",
410 object, object->type);
413 if (func != NULL) {
414 (*func) (toplevel, dx, dy, object);
419 /*! \brief Rotates an object in world coordinates
420 * \par Function Description
421 * This function rotates the object <B>object</B> about the coordinates
422 * <B>world_centerx</B> and <B>world_centery</B>, by <B>angle</B>degrees.
424 * \param [in] toplevel The toplevel environment.
425 * \param [in] world_centerx X coordinate of rotation center (world coords)
426 * \param [in] world_centery Y coordinate of rotation center (world coords)
427 * \param [in] angle Angle of rotation (degrees)
428 * \param [in] object The object to rotate.
430 void o_rotate_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object)
432 void (*func) (TOPLEVEL*, int, int, int, OBJECT*) = NULL;
434 switch (object->type) {
435 case OBJ_LINE: func = o_line_rotate_world; break;
436 case OBJ_NET: func = o_net_rotate_world; break;
437 case OBJ_BUS: func = o_bus_rotate_world; break;
438 case OBJ_BOX: func = o_box_rotate_world; break;
439 case OBJ_PICTURE: func = o_picture_rotate_world; break;
440 case OBJ_CIRCLE: func = o_circle_rotate_world; break;
441 case OBJ_PLACEHOLDER:
442 case OBJ_COMPLEX: func = o_complex_rotate_world; break;
443 case OBJ_TEXT: func = o_text_rotate_world; break;
444 case OBJ_PATH: func = o_path_rotate_world; break;
445 case OBJ_PIN: func = o_pin_rotate_world; break;
446 case OBJ_ARC: func = o_arc_rotate_world; break;
447 default:
448 g_critical ("o_rotate_world: object %p has bad type '%c'\n",
449 object, object->type);
452 if (func != NULL) {
453 (*func) (toplevel, world_centerx, world_centery, angle, object);
458 /*! \brief Mirrors an object in world coordinates
459 * \par Function Description
460 * This function mirrors an object about the point
461 * (<B>world_centerx</B>,<B>world_centery</B>) in world units.
463 * \param [in] toplevel The TOPLEVEL object.
464 * \param [in] world_centerx Origin x coordinate in WORLD units.
465 * \param [in] world_centery Origin y coordinate in WORLD units.
466 * \param [in,out] object The OBJECT to mirror.
468 void o_mirror_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object)
470 void (*func) (TOPLEVEL*, int, int, OBJECT*) = NULL;
472 switch (object->type) {
473 case OBJ_LINE: func = o_line_mirror_world; break;
474 case OBJ_NET: func = o_net_mirror_world; break;
475 case OBJ_BUS: func = o_bus_mirror_world; break;
476 case OBJ_BOX: func = o_box_mirror_world; break;
477 case OBJ_PICTURE: func = o_picture_mirror_world; break;
478 case OBJ_CIRCLE: func = o_circle_mirror_world; break;
479 case OBJ_PLACEHOLDER:
480 case OBJ_COMPLEX: func = o_complex_mirror_world; break;
481 case OBJ_TEXT: func = o_text_mirror_world; break;
482 case OBJ_PATH: func = o_path_mirror_world; break;
483 case OBJ_PIN: func = o_pin_mirror_world; break;
484 case OBJ_ARC: func = o_arc_mirror_world; break;
485 default:
486 g_critical ("o_mirror_world: object %p has bad type '%c'\n",
487 object, object->type);
490 if (func != NULL) {
491 (*func) (toplevel, world_centerx, world_centery, object);
496 /*! \brief Calculates the distance between the given point and the closest
497 * point on the given object.
499 * \param [in] object The given object.
500 * \param [in] x The x coordinate of the given point.
501 * \param [in] y The y coordinate of the given point.
502 * \return The shortest distance from the object to the point. If the
503 * distance cannot be calculated, this function returns a really large
504 * number (G_MAXDOUBLE). If an error occurs, this function returns
505 * G_MAXDOUBLE.
507 double o_shortest_distance (OBJECT *object, int x, int y)
509 return o_shortest_distance_full (object, x, y, FALSE);
512 /*! \brief Calculates the distance between the given point and the closest
513 * point on the given object. Allows forcing objects to solid.
515 * \param [in] object The given object.
516 * \param [in] x The x coordinate of the given point.
517 * \param [in] y The y coordinate of the given point.
518 * \param [in] force_solid If true, force treating the object as solid.
519 * \return The shortest distance from the object to the point. If the
520 * distance cannot be calculated, this function returns a really large
521 * number (G_MAXDOUBLE). If an error occurs, this function returns
522 * G_MAXDOUBLE.
524 double o_shortest_distance_full (OBJECT *object, int x, int y, int force_solid)
526 double shortest_distance = G_MAXDOUBLE;
527 double (*func) (OBJECT *, int, int, int) = NULL;
529 g_return_val_if_fail (object != NULL, G_MAXDOUBLE);
531 switch(object->type) {
532 case OBJ_BUS:
533 case OBJ_NET:
534 case OBJ_PIN:
535 case OBJ_LINE: func = o_line_shortest_distance; break;
536 case OBJ_BOX: func = o_box_shortest_distance; break;
537 case OBJ_PICTURE: func = o_picture_shortest_distance; break;
538 case OBJ_CIRCLE: func = o_circle_shortest_distance; break;
539 case OBJ_PLACEHOLDER:
540 case OBJ_COMPLEX: func = o_complex_shortest_distance; break;
541 case OBJ_TEXT: func = o_text_shortest_distance; break;
542 case OBJ_PATH: func = o_path_shortest_distance; break;
543 case OBJ_ARC: func = o_arc_shortest_distance; break;
544 default:
545 g_critical ("o_shortest_distance: object %p has bad type '%c'\n",
546 object, object->type);
549 if (func != NULL) {
550 shortest_distance = (*func) (object, x, y, force_solid);
553 return shortest_distance;
556 /*! \brief Mark an OBJECT's cached bounds as invalid
557 * \par Function Description
558 * Recursively marks the cached bounds of the given OBJECT and its
559 * parents as having been invalidated and in need of an update. They
560 * will be recalculated next time the OBJECT's bounds are requested
561 * (e.g. via world_get_single_object_bounds() ).
562 * \param [in] toplevel
563 * \param [in] obj
565 * \todo Turn this into a macro?
567 void o_bounds_invalidate(TOPLEVEL *toplevel, OBJECT *obj)
569 do {
570 obj->w_bounds_valid = FALSE;
571 } while ((obj = obj->parent) != NULL);
575 /*! \brief Change the color of an object
577 * \par Function Description
578 * This function changes the color of an object.
580 * \param [in] toplevel The TOPLEVEL structure.
581 * \param [in] object The OBJECT to change color.
582 * \param [in] color The new color.
584 void o_set_color (TOPLEVEL *toplevel, OBJECT *object, int color)
586 g_return_if_fail (object != NULL);
588 object->color = color;
590 if (object->type == OBJ_COMPLEX ||
591 object->type == OBJ_PLACEHOLDER)
592 o_glist_set_color (toplevel, object->complex->prim_objs, color);
596 /*! \brief Get an object's parent PAGE.
598 * \par Function Description
599 * Returns the PAGE structure which owns \a object. If \a object is
600 * not currently associated with a PAGE, returns NULL. If \a object is
601 * part of a compound object, recurses upward.
603 * \param [in] toplevel The TOPLEVEL structure.
604 * \param [in] object The OBJECT for which to retrieve the parent PAGE.
605 * \return The PAGE which owns \a object or NULL.
607 * \sa s_page_append_object() s_page_append() s_page_remove()
609 PAGE *
610 o_get_page (TOPLEVEL *toplevel, OBJECT *object)
612 if (object->parent != NULL) {
613 return o_get_page (toplevel, object->parent);
615 return object->page;
618 /*! \brief Get an object's parent PAGE, or fall back to global current page.
620 * \par Function Description
621 * If set, returns the PAGE structure which owns \a object. If \a
622 * object does not have a parent page set, returns the global current
623 * page from \a toplevel. If the object parent page is inconsistent
624 * with the global current page, a critical-level error message is
625 * emitted.
627 * \warning This function is primarily intended to assist in the
628 * migration of code from using the TOPLEVEL current page to using the
629 * o_get_page(). It should not be used in new code.
631 * \deprecated Use o_get_page() in new code.
633 * \param [in] toplevel The TOPLEVEL structure.
634 * \param [in] object The OBJECT for which to retrieve the parent PAGE.
635 * \return The PAGE which owns \a object, the global current PAGE, or NULL.
637 PAGE *
638 o_get_page_compat (TOPLEVEL *toplevel, OBJECT *object) {
639 PAGE *page = o_get_page (toplevel, object);
640 if (page != toplevel->page_current) {
641 g_critical ("o_get_page_compat: OBJECT.page = %p, TOPLEVEL.page_current = %p",
642 page, toplevel->page_current);
643 return toplevel->page_current;
644 } else {
645 return page;
649 /* Structure for each entry in a TOPLEVEL's list of registered change
650 * notification handlers */
651 struct change_notify_entry {
652 ChangeNotifyFunc pre_change_func;
653 ChangeNotifyFunc change_func;
654 void *user_data;
657 /*! \brief Add change notification handlers to a TOPLEVEL.
658 * \par Function Description
659 * Adds a set of change notification handlers to a #TOPLEVEL instance.
660 * \a pre_change_func will be called just before an object is
661 * modified, and \a change_func will be called just after an object is
662 * modified, with the affected object and the given \a user_data.
664 * \param toplevel #TOPLEVEL structure to add handlers to.
665 * \param pre_change_func Function to be called just before changes.
666 * \param change_func Function to be called just after changes.
667 * \param user_data User data to be passed to callback functions.
669 void
670 o_add_change_notify (TOPLEVEL *toplevel,
671 ChangeNotifyFunc pre_change_func,
672 ChangeNotifyFunc change_func,
673 void *user_data)
675 struct change_notify_entry *entry = g_new0 (struct change_notify_entry, 1);
676 entry->pre_change_func = pre_change_func;
677 entry->change_func = change_func;
678 entry->user_data = user_data;
679 toplevel->change_notify_funcs =
680 g_list_prepend (toplevel->change_notify_funcs, entry);
683 /*! \brief Remove change notification handlers from a TOPLEVEL.
684 * \par Function Description
685 * Removes a set of change notification handlers and their associated
686 * \a user_data from \a toplevel. If no registered set of handlers
687 * matches the given \a pre_change_func, \a change_func and \a
688 * user_data, does nothing.
690 * \see o_add_change_notify()
692 * \param toplevel #TOPLEVEL structure to remove handlers from.
693 * \param pre_change_func Function called just before changes.
694 * \param change_func Function called just after changes.
695 * \param user_data User data passed to callback functions.
697 void
698 o_remove_change_notify (TOPLEVEL *toplevel,
699 ChangeNotifyFunc pre_change_func,
700 ChangeNotifyFunc change_func,
701 void *user_data)
703 GList *iter;
704 for (iter = toplevel->change_notify_funcs;
705 iter != NULL; iter = g_list_next (iter)) {
707 struct change_notify_entry *entry =
708 (struct change_notify_entry *) iter->data;
710 if ((entry != NULL)
711 && (entry->pre_change_func == pre_change_func)
712 && (entry->change_func == change_func)
713 && (entry->user_data == user_data)) {
714 g_free (entry);
715 iter->data = NULL;
718 toplevel->change_notify_funcs =
719 g_list_remove_all (toplevel->change_notify_funcs, NULL);
722 /*! \brief Emit an object pre-change notification.
723 * \par Function Description
724 * Calls each pre-change callback function registered with #TOPLEVEL
725 * to notify listeners that \a object is about to be modified. All
726 * libgeda functions that modify #OBJECT structures should call this
727 * just before making a change to an #OBJECT.
729 * \param toplevel #TOPLEVEL structure to emit notifications from.
730 * \param object #OBJECT structure to emit notifications for.
732 void
733 o_emit_pre_change_notify (TOPLEVEL *toplevel, OBJECT *object)
735 GList *iter;
736 for (iter = toplevel->change_notify_funcs;
737 iter != NULL; iter = g_list_next (iter)) {
739 struct change_notify_entry *entry =
740 (struct change_notify_entry *) iter->data;
742 if ((entry != NULL) && (entry->pre_change_func != NULL)) {
743 entry->pre_change_func (entry->user_data, object);
748 /*! \brief Emit an object change notification.
749 * \par Function Description
750 * Calls each change callback function registered with #TOPLEVEL to
751 * notify listeners that \a object has just been modified. All
752 * libgeda functions that modify #OBJECT structures should call this
753 * just after making a change to an #OBJECT.
755 * \param toplevel #TOPLEVEL structure to emit notifications from.
756 * \param object #OBJECT structure to emit notifications for.
758 void
759 o_emit_change_notify (TOPLEVEL *toplevel, OBJECT *object)
761 GList *iter;
762 for (iter = toplevel->change_notify_funcs;
763 iter != NULL; iter = g_list_next (iter)) {
765 struct change_notify_entry *entry =
766 (struct change_notify_entry *) iter->data;
768 if ((entry != NULL) && (entry->change_func != NULL)) {
769 entry->change_func (entry->user_data, object);
774 /*! \brief Query visibility of the object.
775 * \par Function Description
776 * Attribute getter for the visible field within the object.
778 * \param toplevel The TOPLEVEL structure
779 * \param object The OBJECT structure to be queried
780 * \return TRUE when VISIBLE, FALSE otherwise
782 gboolean
783 o_is_visible (TOPLEVEL *toplevel, OBJECT *object)
785 g_return_val_if_fail (object != NULL, FALSE);
786 return object->visibility == VISIBLE;
789 /*! \brief Set visibility of the object.
790 * \par Function Description
791 * Set value of visibility field within the object.
792 * If resulting visibility value is changed,
793 * invalidate the bounds of the object and parent objects.
795 * \param toplevel The #TOPLEVEL structure
796 * \param object The #OBJECT structure to be modified
798 void
799 o_set_visibility (TOPLEVEL *toplevel, OBJECT *object, int visibility)
801 g_return_if_fail (object != NULL);
802 if (object->visibility != visibility) {
803 object->visibility = visibility;
804 o_bounds_invalidate (toplevel, object);