/*! \brief Ends the process of arc input. * \par Function Description * The #o_arc_end4() function ends the process of the input of an arc. * <B>start_angle</B> and <B>sweep_angle</B> are the start and sweep angle of the * arc in degrees. The partial internal representation of the arc, i.e. * the center and the radius of the arc, are converted in world units. * A new object is created and linked to the object list. * * \param [in] w_current The GschemToplevel object. * \param [in] radius Radius of the arc * \param [in] start_angle Start of angle in degrees. * \param [in] sweep_angle Angle sweep in degrees. */ void o_arc_end4(GschemToplevel *w_current, int radius, int start_angle, int sweep_angle) { GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); TOPLEVEL *toplevel = page->toplevel; g_return_if_fail (toplevel != NULL); OBJECT *new_obj; /* create, initialize and link the new arc object */ new_obj = geda_arc_object_new (toplevel, GRAPHIC_COLOR, w_current->first_wx, w_current->first_wy, radius, start_angle, sweep_angle); s_page_append (toplevel, page, new_obj); w_current->first_wx = -1; w_current->first_wy = -1; w_current->distance = 0; /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate(w_current, page, UNDO_ALL); }
/*! \brief End the input of a box. * \par Function Description * This function ends the input of the second corner of a box. * The (<B>w_x</B>,<B>w_y</B>) point is set to be this second corner. The box is * then defined by (<B>w_current->first_wx</B>,<B>w_current->first_wy</B> and * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>. * <B>w_x</B> and <B>w_y</B> are in screen unit. * * The temporary box is erased ; a new box object is allocated, initialized * and linked to the object list ; The object is finally drawn on the * current sheet. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in] w_x Current x coordinate of pointer in world units. * \param [in] w_y Current y coordinate of pointer in world units. */ void o_box_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; int box_width, box_height; int box_left, box_top; g_assert( w_current->inside_action != 0 ); /* get the last coords of the pointer */ w_current->second_wx = w_x; w_current->second_wy = w_y; /* erase the temporary box */ /* o_box_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; box_width = GET_BOX_WIDTH (w_current); box_height = GET_BOX_HEIGHT(w_current); box_left = GET_BOX_LEFT (w_current); box_top = GET_BOX_TOP (w_current); /* boxes with null width or height are not allowed */ if ((box_width == 0) || (box_height == 0)) { /* cancel the object creation */ w_current->first_wx = (-1); w_current->first_wy = (-1); w_current->second_wx = (-1); w_current->second_wy = (-1); return; } /* create the object */ new_obj = o_box_new (toplevel, OBJ_BOX, GRAPHIC_COLOR, box_left, box_top, box_left + box_width, box_top - box_height); s_page_append (toplevel, toplevel->page_current, new_obj); #if DEBUG printf("coords: %d %d %d %d\n", box_left, box_top, box_width, box_height); #endif w_current->first_wx = (-1); w_current->first_wy = (-1); w_current->second_wx = (-1); w_current->second_wy = (-1); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); toplevel->page_current->CHANGED = 1; o_undo_savestate(w_current, UNDO_ALL); }
/*! \brief finish a bus drawing action * \par Function Description * This function finishes a net drawing action. The function draws * a bus from the point (<B>first_wx</B>,<B>first_wy</B>) to * (<B>second_wx</B>,<B>second_wy</B>). Both points are taken from * the <B>GschemToplevel</B> structure. * * The function returns TRUE if a bus object has been created and * FALSE if no bus object has been created. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x (unused) * \param [in] w_y (unused) */ void o_bus_end(GschemToplevel *w_current, int w_x, int w_y) { OBJECT *new_obj; GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); g_assert( w_current->inside_action != 0 ); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); TOPLEVEL *toplevel = page->toplevel; g_return_if_fail (toplevel != NULL); GList *prev_conn_objects = NULL; /* erase the rubberbus */ /* o_bus_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; /* don't allow zero length bus */ /* this ends the bus drawing behavior we want this? hack */ if ( (w_current->first_wx != w_current->second_wx) || (w_current->first_wy != w_current->second_wy) ) { new_obj = geda_bus_object_new (toplevel, BUS_COLOR, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy, 0); s_page_append (toplevel, page, new_obj); /* connect the new bus to the other busses */ prev_conn_objects = s_conn_return_others (prev_conn_objects, new_obj); o_invalidate_glist (w_current, prev_conn_objects); g_list_free (prev_conn_objects); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); w_current->first_wx = w_current->second_wx; w_current->first_wy = w_current->second_wy; gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate(w_current, page, UNDO_ALL); } /* Don't reset w_current->inside_action here since we want to continue drawing */ }
/*! \brief Delete an object. * \par Function Description * This function erases the object \a object before deleting it. It * deals with connection and object connected to it. * * \param [in] w_current The GschemToplevel object. * \param [in] object The object to delete. */ void o_delete (GschemToplevel *w_current, OBJECT *object) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); g_return_if_fail (object != NULL); o_selection_remove (toplevel, toplevel->page_current->selection_list, object); s_page_remove (toplevel, toplevel->page_current, object); g_run_hook_object (w_current, "%remove-objects-hook", object); s_delete_object (toplevel, object); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); }
/*! \brief End the input of a circle. * \par Function Description * This function ends the input of the radius of the circle. * The (<B>w_x</B>,<B>w_y</B>) point is taken as the other end of the radius * segment, i.e. on the circle. The distance between this point and the * center is the radius of the circle. * <B>w_x</B> and <B>w_y</B> are in world coords. * * The center has previously been input and saved as * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). * * The temporary circle drawn during the input of the radius is erased. * A new object is allocated, initialized and linked in the object list. * This new object is finally drawn. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x (unused) * \param [in] w_y (unused) */ void o_circle_end(GschemToplevel *w_current, int w_x, int w_y) { OBJECT *new_obj; GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); g_assert( w_current->inside_action != 0 ); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); TOPLEVEL *toplevel = page->toplevel; g_return_if_fail (toplevel != NULL); /* erase the temporary circle */ /* o_circle_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; /* circle with null radius are not allowed */ if (w_current->distance == 0) { /* cancel the object creation */ return; } /* create the object */ new_obj = geda_circle_object_new (toplevel, GRAPHIC_COLOR, w_current->first_wx, w_current->first_wy, w_current->distance); s_page_append (toplevel, page, new_obj); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate(w_current, page, UNDO_ALL); i_action_stop (w_current); }
/*! \brief End the input of a circle. * \par Function Description * This function ends the input of the second corner of a picture. * The picture is defined by (<B>w_current->first_wx</B>,<B>w_current->first_wy</B> * and (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>. * * The temporary picture frame is erased ; a new picture object is allocated, * initialized and linked to the object list ; The object is finally * drawn on the current sheet. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x (unused) * \param [in] w_y (unused) */ void o_picture_end(GschemToplevel *w_current, int w_x, int w_y) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *new_obj; int picture_width, picture_height; int picture_left, picture_top; g_assert( w_current->inside_action != 0 ); /* erase the temporary picture */ /* o_picture_draw_rubber(w_current); */ w_current->rubber_visible = 0; picture_width = GET_PICTURE_WIDTH (w_current); picture_height = GET_PICTURE_HEIGHT(w_current); picture_left = GET_PICTURE_LEFT (w_current); picture_top = GET_PICTURE_TOP (w_current); /* pictures with null width and height are not allowed */ if ((picture_width == 0) && (picture_height == 0)) { /* cancel the object creation */ return; } /* create the object */ new_obj = o_picture_new(toplevel, NULL, 0, w_current->pixbuf_filename, OBJ_PICTURE, picture_left, picture_top, picture_left + picture_width, picture_top - picture_height, 0, FALSE, FALSE); s_page_append (toplevel, toplevel->page_current, new_obj); /* Run %add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); o_undo_savestate_old(w_current, UNDO_ALL); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_pin_end(GSCHEM_TOPLEVEL *w_current, int x, int y) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; int color; g_assert( w_current->inside_action != 0 ); if (toplevel->override_pin_color == -1) { color = PIN_COLOR; } else { color = toplevel->override_pin_color; } /* undraw rubber line */ /* o_pin_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; /* don't allow zero length pins */ if ((w_current->first_wx == w_current->second_wx) && (w_current->first_wy == w_current->second_wy)) { return; } new_obj = o_pin_new(toplevel, OBJ_PIN, color, w_current->first_wx, w_current->first_wy, w_current->second_wx, w_current->second_wy, PIN_TYPE_NET, 0); s_page_append (toplevel, toplevel->page_current, new_obj); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); toplevel->page_current->CHANGED=1; o_undo_savestate(w_current, UNDO_ALL); }
/*! \brief End the input of a box. * \par Function Description * This function ends the input of the second corner of a box. * The (<B>w_x</B>,<B>w_y</B>) point is set to be this second corner. The box is * then defined by (<B>w_current->first_wx</B>,<B>w_current->first_wy</B> and * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>. * <B>w_x</B> and <B>w_y</B> are in screen unit. * * The temporary box is erased ; a new box object is allocated, initialized * and linked to the object list ; The object is finally drawn on the * current sheet. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x Current x coordinate of pointer in world units. * \param [in] w_y Current y coordinate of pointer in world units. */ void o_box_end(GschemToplevel *w_current, int w_x, int w_y) { OBJECT *new_obj; GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); g_return_if_fail (page_view != NULL); g_assert( w_current->inside_action != 0 ); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (page != NULL); TOPLEVEL *toplevel = page->toplevel; g_return_if_fail (toplevel != NULL); int box_width, box_height; int box_left, box_top; /* get the last coords of the pointer */ w_current->second_wx = w_x; w_current->second_wy = w_y; /* erase the temporary box */ /* o_box_invalidate_rubber (w_current); */ w_current->rubber_visible = 0; box_width = GET_BOX_WIDTH (w_current); box_height = GET_BOX_HEIGHT(w_current); box_left = GET_BOX_LEFT (w_current); box_top = GET_BOX_TOP (w_current); /* boxes with null width or height are not allowed */ if ((box_width == 0) || (box_height == 0)) { /* cancel the object creation */ w_current->first_wx = (-1); w_current->first_wy = (-1); w_current->second_wx = (-1); w_current->second_wy = (-1); } else { /* create the object */ new_obj = geda_box_object_new (toplevel, OBJ_BOX, GRAPHIC_COLOR, box_left, box_top, box_left + box_width, box_top - box_height); s_page_append (toplevel, page, new_obj); #if DEBUG printf("coords: %d %d %d %d\n", box_left, box_top, box_width, box_height); #endif w_current->first_wx = (-1); w_current->first_wy = (-1); w_current->second_wx = (-1); w_current->second_wy = (-1); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate(w_current, page, UNDO_ALL); } i_action_stop (w_current); }
/* text item */ OBJECT *o_attrib_add_attrib(GschemToplevel *w_current, const char *text_string, int visibility, int show_name_value, OBJECT *object) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *new_obj; int world_x = - 1, world_y = -1; int align = LOWER_LEFT; int angle = 0; int color; int left, right, top, bottom; OBJECT *o_current; color = DETACHED_ATTRIBUTE_COLOR; o_current = object; /* creating a toplevel or unattached attribute */ if (o_current) { /* get coordinates of where to place the text object */ switch(o_current->type) { case(OBJ_COMPLEX): case(OBJ_PLACEHOLDER): world_x = o_current->complex->x; world_y = o_current->complex->y; align = LOWER_LEFT; angle = 0; color = ATTRIBUTE_COLOR; break; case(OBJ_ARC): world_x = o_current->arc->x; world_y = o_current->arc->y; align = LOWER_LEFT; angle = 0; color = ATTRIBUTE_COLOR; break; case(OBJ_CIRCLE): world_x = o_current->circle->center_x; world_y = o_current->circle->center_y; align = LOWER_LEFT; angle = 0; color = ATTRIBUTE_COLOR; break; case(OBJ_BOX): world_x = o_current->box->upper_x; world_y = o_current->box->upper_y; align = LOWER_LEFT; angle = 0; color = ATTRIBUTE_COLOR; break; case(OBJ_LINE): case(OBJ_NET): case(OBJ_PIN): case(OBJ_BUS): { int dx = o_current->line->x[1] - o_current->line->x[0]; int dy = o_current->line->y[1] - o_current->line->y[0]; if (dy == 0) { if (dx > 0) { world_x = o_current->line->x[0] + SPACING_FROM_END; world_y = o_current->line->y[0] + SPACING_PERPENDICULAR; align = LOWER_LEFT; angle = 0; } else { world_x = o_current->line->x[0] - SPACING_FROM_END; world_y = o_current->line->y[0] + SPACING_PERPENDICULAR; align = LOWER_RIGHT; angle = 0; } } else if (dx == 0) { if (dy > 0) { world_x = o_current->line->x[0] - SPACING_PERPENDICULAR; world_y = o_current->line->y[0] + SPACING_FROM_END; align = LOWER_LEFT; angle = 90; } else { world_x = o_current->line->x[0] - SPACING_PERPENDICULAR; world_y = o_current->line->y[0] - SPACING_FROM_END; align = LOWER_RIGHT; angle = 90; } } else { world_x = o_current->line->x[0]; world_y = o_current->line->y[0]; align = LOWER_LEFT; angle = 0; } color = ATTRIBUTE_COLOR; } break; case(OBJ_TEXT): world_x = o_current->text->x; world_y = o_current->text->y; color = DETACHED_ATTRIBUTE_COLOR; align = LOWER_LEFT; angle = 0; o_current = NULL; break; } } else { world_get_object_glist_bounds (toplevel, s_page_objects (toplevel->page_current), &left, &top, &right, &bottom); /* this really is the lower left hand corner */ world_x = left; world_y = top; /* printf("%d %d\n", world_x, world_y); */ align = LOWER_LEFT; angle = 0; color = DETACHED_ATTRIBUTE_COLOR; } /* first create text item */ new_obj = o_text_new(toplevel, color, world_x, world_y, align, angle, text_string, w_current->text_size, /* current text size */ visibility, show_name_value); s_page_append (toplevel, toplevel->page_current, new_obj); /* now attach the attribute to the object (if o_current is not NULL) */ /* remember that o_current contains the object to get the attribute */ if (o_current) { o_attrib_attach (toplevel, new_obj, o_current, FALSE); } o_selection_add (toplevel, toplevel->page_current->selection_list, new_obj); /* handle slot= attribute, it's a special case */ if (o_current != NULL && g_ascii_strncasecmp (text_string, "slot=", 5) == 0) { o_slot_end (w_current, o_current, text_string); } /* Call add-objects-hook. */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); g_run_hook_object (w_current, "%select-objects-hook", new_obj); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); return new_obj; }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_slot_end(GSCHEM_TOPLEVEL *w_current, OBJECT *object, const char *string) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; char *slot_value; char *numslots_value; OBJECT *o_slot; char *value = NULL; int numslots; int new_slot_number; int status; g_return_if_fail (object != NULL); status = o_attrib_string_get_name_value (string, NULL, &value); if (!status) { s_log_message (_("Slot attribute malformed\n")); return; } numslots_value = o_attrib_search_object_attribs_by_name (object, "numslots", 0); if (!numslots_value) { s_log_message (_("numslots attribute missing\n")); s_log_message (_("Slotting not allowed for this component\n")); g_free (value); return; } numslots = atoi (numslots_value); g_free (numslots_value); new_slot_number = atoi (value); #if DEBUG printf ("numslots = %d\n", numslots); #endif if (new_slot_number > numslots || new_slot_number <=0 ) { s_log_message (_("New slot number out of range\n")); g_free (value); return; } /* first see if slot attribute already exists outside * complex */ slot_value = s_slot_search_slot (object, &o_slot); g_free (slot_value); if (o_slot != NULL && !o_attrib_is_inherited (o_slot)) { o_text_set_string (toplevel, o_slot, string); } else { /* here you need to do the add the slot attribute since it doesn't exist */ new_obj = o_text_new (toplevel, OBJ_TEXT, ATTRIBUTE_COLOR, object->complex->x, object->complex->y, LOWER_LEFT, 0, /* zero is angle */ string, 10, INVISIBLE, SHOW_NAME_VALUE); s_page_append (toplevel, toplevel->page_current, new_obj); /* manually attach attribute */ o_attrib_attach (toplevel, new_obj, object, FALSE); /* Call add-objects-hook */ g_run_hook_object (w_current, "%add-objects-hook", new_obj); } s_slot_update_object (toplevel, object); toplevel->page_current->CHANGED = 1; g_free (value); }
/*! \brief End the input of a path. * \par Function Description * This function ends the process of interactively adding a path to the * current sheet. * * It first erases the last temporary path displayed, calculates the * corresponding world coordinates of the two ends of the path and finally * adds a new initialized path object to the list of object of the current * sheet. * * \param [in] w_current The GschemToplevel object. * \param [in] w_x (unused) * \param [in] w_y (unused) */ gboolean o_path_end(GschemToplevel *w_current, int w_x, int w_y) { GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); TOPLEVEL *toplevel = gschem_page_view_get_toplevel (page_view); PAGE *page = gschem_page_view_get_page (page_view); gboolean close_path, end_path, start_path; PATH *p; PATH_SECTION *section, *prev_section; int x1, y1, x2, y2; g_assert (w_current); g_assert (w_current->toplevel); g_assert (w_current->temp_path != NULL); g_assert (w_current->temp_path->sections != NULL); g_assert (toplevel != NULL); g_assert (page != NULL); o_path_invalidate_rubber (w_current); x1 = w_current->first_wx; y1 = w_current->first_wy; x2 = w_current->second_wx; y2 = w_current->second_wy; p = w_current->temp_path; /* Check whether the section that's being added is the initial * MOVETO. This is detected if the path is currently empty. */ start_path = (p->num_sections == 0); prev_section = start_path ? NULL : &p->sections[p->num_sections - 1]; /* Check whether the section that's being added closes the path. * This is detected if the location of the node is the same as the * location of the starting node, and there is at least one section * in the path in addition to the initial MOVETO section. */ section = &p->sections[0]; close_path = (!start_path && x1 == section->x3 && y1 == section->y3); /* Check whether the section that's being added ends the path. This * is detected if the location of the node is the same as the * location of the previous node. */ end_path = (!start_path && x1 == prev_section->x3 && y1 == prev_section->y3); /* Add predicted next sections */ path_next_sections (w_current); if (end_path || close_path) { /* Add object to page and clean up path drawing state */ OBJECT *obj = o_path_new_take_path (toplevel, OBJ_PATH, GRAPHIC_COLOR, p); w_current->temp_path = NULL; w_current->first_wx = -1; w_current->first_wy = -1; w_current->second_wx = -1; w_current->second_wy = -1; w_current->third_wx = -1; w_current->third_wy = -1; s_page_append (toplevel, page, obj); g_run_hook_object (w_current, "%add-objects-hook", obj); gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate (w_current, page, UNDO_ALL); w_current->rubber_visible = FALSE; return FALSE; } else { /* Leave state as it is and continue path drawing... */ /* Save the control point coordinates for the next section */ w_current->third_wx = x2; w_current->third_wy = y2; return TRUE; } }