int node_store_is_wire_at_pos (NodeStore *store, SheetPos pos) { GList *list; Wire *wire; SheetPos wire_pos, wire_length; double x1, y1, x2, y2; g_return_val_if_fail (store != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (store), FALSE); for (list = store->wires; list; list = list->next) { wire = list->data; wire_get_pos_and_length (wire, &wire_pos, &wire_length); x1 = wire_pos.x; y1 = wire_pos.y; x2 = x1 + wire_length.x; y2 = y1 + wire_length.y; if (is_wire_at_pos (x1, y1, x2, y2, pos)) return TRUE; } g_list_free_full (list, g_object_unref); return FALSE; }
static void wire_rotated_callback (ItemData *data, int angle, SheetItem *sheet_item) { WireItem *wire_item; GooCanvasPoints *points; Coords start_pos, length; g_return_if_fail (sheet_item != NULL); g_return_if_fail (IS_WIRE_ITEM (sheet_item)); wire_item = WIRE_ITEM (sheet_item); wire_get_pos_and_length (WIRE (data), &start_pos, &length); points = goo_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; g_object_set (wire_item->priv->line, "points", points, NULL); goo_canvas_points_unref (points); g_object_set (wire_item, "x", start_pos.x, "y", start_pos.y, NULL); g_object_set (wire_item->priv->resize2, "x", length.x - RESIZER_SIZE, "y", length.y - RESIZER_SIZE, NULL); // Invalidate the bounding box cache. wire_item->priv->cache_valid = FALSE; }
static void wire_changed_callback (Wire *wire, WireItem *item) { SheetPos start_pos, length; GnomeCanvasPoints *points; wire_get_pos_and_length (wire, &start_pos, &length); points = gnome_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; gnome_canvas_item_set (GNOME_CANVAS_ITEM (item->priv->line), "points", points, NULL); gnome_canvas_points_unref (points); gnome_canvas_item_set (GNOME_CANVAS_ITEM (item->priv->resize1), "x1", -RESIZER_SIZE, "y1", -RESIZER_SIZE, "x2", RESIZER_SIZE, "y2", RESIZER_SIZE, NULL); gnome_canvas_item_set (GNOME_CANVAS_ITEM (item->priv->resize2), "x1", length.x-RESIZER_SIZE, "y1", length.y-RESIZER_SIZE, "x2", length.x+RESIZER_SIZE, "y2", length.y+RESIZER_SIZE, NULL); }
static void wire_flipped_callback (ItemData *data, IDFlip direction, SheetItem *sheet_item) { GooCanvasPoints *points; WireItem *item; WireItemPriv *priv; Coords start_pos, length; g_return_if_fail (sheet_item != NULL); g_return_if_fail (IS_WIRE_ITEM (sheet_item)); item = WIRE_ITEM (sheet_item); priv = item->priv; wire_get_pos_and_length (WIRE (data), &start_pos, &length); points = goo_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; g_object_set (item->priv->line, "points", points, NULL); goo_canvas_points_unref (points); g_object_set (item, "x", start_pos.x, "y", start_pos.y, NULL); // Invalidate the bounding box cache. priv->cache_valid = FALSE; }
static void wire_changed_callback (Wire *wire, WireItem *item) { SheetPos start_pos, length; GooCanvasPoints *points; wire_get_pos_and_length (wire, &start_pos, &length); points = goo_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; g_object_set (item->priv->line, "points", points, NULL); goo_canvas_points_unref (points); g_object_set (item->priv->resize1, "x", -RESIZER_SIZE, "y", -RESIZER_SIZE, "width", 2 * RESIZER_SIZE, "height", 2 * RESIZER_SIZE, NULL); g_object_set (item->priv->resize2, "x", length.x-RESIZER_SIZE, "y", length.y-RESIZER_SIZE, "width", 2 * RESIZER_SIZE, "height", 2 * RESIZER_SIZE, NULL); goo_canvas_item_request_update (GOO_CANVAS_ITEM (item->priv->line)); }
static GSList * wire_intersect_parts (NodeStore *store, Wire *wire) { GList *list; GSList *ip_list; Node *node; SheetPos lookup_pos; SheetPos part_pos, wire_pos, wire_length; Part *part; double x, y, wire_x1, wire_y1, wire_x2, wire_y2; int i, num_pins; g_return_val_if_fail (store != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (store), FALSE); g_return_val_if_fail (wire != NULL, FALSE); g_return_val_if_fail (IS_WIRE (wire), FALSE); ip_list = NULL; wire_get_pos_and_length (wire, &wire_pos, &wire_length); wire_x1 = wire_pos.x; wire_x2 = wire_pos.x + wire_length.x; wire_y1 = wire_pos.y; wire_y2 = wire_pos.y + wire_length.y; // Go through all the parts and see which of their // pins that intersect the wire. for (list = store->parts; list; list = list->next) { part = list->data; num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &part_pos); for (i = 0; i < num_pins; i++) { Pin *pins; pins = part_get_pins (part); x = part_pos.x + pins[i].offset.x; y = part_pos.y + pins[i].offset.y; lookup_pos.x = x; lookup_pos.y = y; // If there is a wire at this pin's position, // add it to the return list. if (is_wire_at_pos (wire_x1, wire_y1, wire_x2, wire_y2, lookup_pos)) { node = node_store_get_node (store, lookup_pos); if (node != NULL) ip_list = g_slist_prepend (ip_list, node); } } } g_list_free_full (list, g_object_unref); return ip_list; }
static void wire_changed_callback (Wire *wire, WireItem *item) { Coords start_pos, length; GooCanvasPoints *points; g_return_if_fail (wire != NULL); g_return_if_fail (IS_ITEM_DATA (wire)); g_return_if_fail (item != NULL); g_return_if_fail (IS_WIRE_ITEM (item)); wire_get_pos_and_length (wire, &start_pos, &length); Sheet *sheet = SHEET (goo_canvas_item_get_canvas (GOO_CANVAS_ITEM (item))); if (G_UNLIKELY(!sheet)) { g_warning ("Failed to determine the Sheet the item is glued to. This should never happen. Ever!"); } else { item_data_snap (ITEM_DATA (wire), sheet->grid); } // Move the canvas item and invalidate the bbox cache. goo_canvas_item_set_simple_transform (GOO_CANVAS_ITEM (item), start_pos.x, start_pos.y, 1.0, 0.0); item->priv->cache_valid = FALSE; points = goo_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; // this does handle cleanup of previous points internally g_object_set (item->priv->line, "points", points, NULL); goo_canvas_points_unref (points); g_object_set (item->priv->resize1, "x", -RESIZER_SIZE, "y", -RESIZER_SIZE, "width", 2 * RESIZER_SIZE, "height", 2 * RESIZER_SIZE, NULL); g_object_set (item->priv->resize2, "x", length.x-RESIZER_SIZE, "y", length.y-RESIZER_SIZE, "width", 2 * RESIZER_SIZE, "height", 2 * RESIZER_SIZE, NULL); goo_canvas_item_request_update (GOO_CANVAS_ITEM (item->priv->line)); }
void wire_update_bbox (Wire *wire) { Coords b1, b2, pos, length; wire_get_pos_and_length (wire, &pos, &length); b1.x = b1.y = 0.0; b2 = length; item_data_set_relative_bbox (ITEM_DATA (wire), &b1, &b2); }
int node_store_remove_wire (NodeStore *store, Wire *wire) { GSList *list; SheetPos lookup_key, pos, length; g_return_val_if_fail (store != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (store), FALSE); g_return_val_if_fail (wire != NULL, FALSE); g_return_val_if_fail (IS_WIRE (wire), FALSE); if (item_data_get_store (ITEM_DATA (wire)) == NULL) { g_warning ("Trying to remove non-stored wire."); return FALSE; } wire_get_pos_and_length (wire, &pos, &length); store->wires = g_list_remove (store->wires, wire); store->items = g_list_remove (store->items, wire); // If the nodes that this wire passes through will be // empty when the wire is removed, remove the node as well. // We must work on a copy of the nodes list, since it // changes as we remove nodes. list = g_slist_copy (wire_get_nodes (wire)); for (; list; list = list->next) { Node *node = list->data; lookup_key = node->key; node_remove_wire (node, wire); wire_remove_node (wire, node); if (node_is_empty (node)) g_hash_table_remove (store->nodes, &lookup_key); } g_slist_free (list); return TRUE; }
static void wire_rotated_callback (ItemData *data, int angle, SheetItem *sheet_item) { WireItem *wire_item; GnomeCanvasPoints *points; SheetPos start_pos, length; g_return_if_fail (sheet_item != NULL); g_return_if_fail (IS_WIRE_ITEM (sheet_item)); wire_item = WIRE_ITEM (sheet_item); wire_get_pos_and_length (WIRE (data), &start_pos, &length); points = gnome_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; gnome_canvas_item_set (GNOME_CANVAS_ITEM (wire_item->priv->line), "points", points, NULL); gnome_canvas_points_unref (points); gnome_canvas_item_set (GNOME_CANVAS_ITEM (wire_item), "x", start_pos.x, "y", start_pos.y, NULL); gnome_canvas_item_set ( GNOME_CANVAS_ITEM (wire_item-> priv->resize2), "x1", length.x-RESIZER_SIZE, "y1", length.y-RESIZER_SIZE, "x2", length.x+RESIZER_SIZE, "y2", length.y+RESIZER_SIZE, NULL ); /* * Invalidate the bounding box cache. */ wire_item->priv->cache_valid = FALSE; }
static GSList * wires_intersect (NodeStore *store, double x1, double y1, double x2, double y2) { GList *list; GSList *ip_list; Wire *wire; SheetPos pos, wire_pos, wire_length; double wire_x1, wire_y1, wire_x2, wire_y2; g_return_val_if_fail (store != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (store), FALSE); // Search through all the wires. Is there a better way? ip_list = NULL; for (list = store->wires; list; list = list->next) { wire = list->data; wire_get_pos_and_length (wire, &wire_pos, &wire_length); wire_x1 = wire_pos.x; wire_y1 = wire_pos.y; wire_x2 = wire_x1 + wire_length.x; wire_y2 = wire_y1 + wire_length.y; if (do_wires_intersect (x1, y1, x2, y2, wire_x1, wire_y1, wire_x2, wire_y2, &pos)) { IntersectionPoint *ip; ip = g_new0 (IntersectionPoint, 1); ip->wire = wire; ip->pos = pos; ip_list = g_slist_prepend (ip_list, ip); } } g_list_free_full (list, g_object_unref); return ip_list; }
static void wire_flipped_callback (ItemData *data, gboolean horizontal, SheetItem *sheet_item) { GnomeCanvasPoints *points; WireItem *item; WireItemPriv *priv; SheetPos start_pos, length; g_return_if_fail (sheet_item != NULL); g_return_if_fail (IS_WIRE_ITEM (sheet_item)); item = WIRE_ITEM (sheet_item); priv = item->priv; wire_get_pos_and_length (WIRE (data), &start_pos, &length); points = gnome_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; gnome_canvas_item_set (GNOME_CANVAS_ITEM (item->priv->line), "points", points, NULL); gnome_canvas_points_unref (points); gnome_canvas_item_set (GNOME_CANVAS_ITEM (item), "x", start_pos.x, "y", start_pos.y, NULL); /* * Invalidate the bounding box cache. */ priv->cache_valid = FALSE; }
gboolean node_needs_dot (Node *node) { Wire *wire1, *wire2; Coords start_pos1, length1, end_pos1; Coords start_pos2, length2, end_pos2; NG_DEBUG ("\nnode: %p --- pins: %i --- wires: %i", node, node->pin_count, node->wire_count); // always display a black dot if a part hits a wire if (node->pin_count >= 1 && node->wire_count >= 1) { NG_DEBUG (" TRUE (pins>=1 && wires>=1)"); return TRUE; // FIXME this can create sparse knots, because of overlaying wires o===xxxx===o // TODO can be fixed by optimizing away/fuzing duplicate/overlaying wires } else if ((node->pin_count + node->wire_count) > 2) { NG_DEBUG (" TRUE (pins+wires>2)"); return TRUE; } else if (node->wire_count == 2) { // Check that we don't have two wire endpoints. wire1 = node->wires->data; wire2 = node->wires->next->data; wire_get_pos_and_length (wire1, &start_pos1, &length1); wire_get_pos_and_length (wire2, &start_pos2, &length2); end_pos1.x = start_pos1.x + length1.x; end_pos1.y = start_pos1.y + length1.y; end_pos2.x = start_pos2.x + length2.x; end_pos2.y = start_pos2.y + length2.y; if (!(SEP (start_pos1, start_pos2) || SEP (start_pos1, end_pos2) || SEP (end_pos1, end_pos2) || SEP (end_pos1, start_pos2))) { // The dot is only needed when the end/start-point of // one of the wires in on the other wire. if (ON_THE_WIRE (start_pos1, start_pos2, end_pos2) || ON_THE_WIRE ( end_pos1, start_pos2, end_pos2) || ON_THE_WIRE (start_pos2, start_pos1, end_pos1) || ON_THE_WIRE ( end_pos2, start_pos1, end_pos1) ) { NG_DEBUG (" TRUE (wires>2 && endpoint on wire)"); return TRUE; } else { NG_DEBUG (" FALSE (wires>2 && crossing)"); return FALSE; } } return FALSE; } else if (node->pin_count == 1 && node->wire_count == 1) { // TODO this is most likely obsolete and is never entered // Check if we have one wire with a pin in the 'middle'. wire1 = node->wires->data; wire_get_pos_and_length (wire1, &start_pos1, &length1); end_pos1.x = start_pos1.x + length1.x; end_pos1.y = start_pos1.y + length1.y; if (!SEP (node->key, start_pos1) && !SEP (node->key, end_pos1)) { NG_DEBUG (" FALSE (pins==1 && wires==1) pin in the middle of a wire"); return TRUE; } } NG_DEBUG (" FALSE (else)"); return FALSE; }
gboolean wire_item_event (WireItem *wire_item, GooCanvasItem *sheet_target_item, GdkEvent *event, Sheet *sheet) { SheetPos start_pos, length; Wire *wire; GooCanvas *canvas; static double last_x, last_y; double dx, dy, zoom; // The selected group's bounding box in window resp. canvas coordinates. double snapped_x, snapped_y; SheetPos pos; canvas = GOO_CANVAS (sheet); g_object_get (G_OBJECT (wire_item), "data", &wire, NULL); wire_get_pos_and_length (WIRE (wire), &start_pos, &length); sheet_get_zoom (sheet, &zoom); switch (event->type) { case GDK_BUTTON_PRESS: switch (event->button.button) { case 1: { double x, y; g_signal_stop_emission_by_name (wire_item, "button_press_event"); sheet_get_pointer (sheet, &x, &y); x = x - start_pos.x; y = y - start_pos.y; if ((x > -RESIZER_SIZE) && (x < RESIZER_SIZE) && (y > -RESIZER_SIZE) && (y < RESIZER_SIZE)) { gtk_widget_grab_focus (GTK_WIDGET (sheet)); sheet->state = SHEET_STATE_DRAG_START; wire_item->priv->resize_state = WIRE_RESIZER_1; sheet_get_pointer (sheet, &x, &y); last_x = x; last_y = y; item_data_unregister (ITEM_DATA (wire)); return TRUE; } if ((x > (length.x-RESIZER_SIZE)) && (x < (length.x+RESIZER_SIZE)) && (y > (length.y-RESIZER_SIZE)) && (y < (length.y+RESIZER_SIZE))) { gtk_widget_grab_focus (GTK_WIDGET (sheet)); sheet->state = SHEET_STATE_DRAG_START; wire_item->priv->resize_state = WIRE_RESIZER_2; sheet_get_pointer (sheet, &x, &y); last_x = x; last_y = y; item_data_unregister (ITEM_DATA (wire)); return TRUE; } } break; } break; case GDK_MOTION_NOTIFY: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) break; if (wire_item->priv->resize_state == WIRE_RESIZER_NONE) break; if (sheet->state == SHEET_STATE_DRAG_START || sheet->state == SHEET_STATE_DRAG) { g_signal_stop_emission_by_name (wire_item, "motion-notify-event"); sheet->state = SHEET_STATE_DRAG; sheet_get_pointer (sheet, &snapped_x, &snapped_y); dx = snapped_x - last_x; dy = snapped_y - last_y; last_x = snapped_x; last_y = snapped_y; wire_get_pos_and_length (wire, &pos, &length); if (wire_item->priv->resize_state == WIRE_RESIZER_1) { switch (wire->priv->direction) { case WIRE_DIR_VERT: /* Vertical Wire */ pos.y = last_y; length.y -= dy; break; case WIRE_DIR_HORIZ: /* Horizontal Wire */ pos.x = last_x; length.x -= dx; break; default: pos.y = last_y; length.y -= dy; pos.x = last_x; length.x -= dx; } } else { switch (wire->priv->direction) { case WIRE_DIR_VERT: /* Vertical Wire */ length.y += dy; break; case WIRE_DIR_HORIZ: /* Horizontal Wire */ length.x += dx; break; default: length.y += dy; length.x += dx; } } snap_to_grid (sheet->grid, &length.x, &length.y); item_data_set_pos (sheet_item_get_data (SHEET_ITEM (wire_item)), &pos); wire_set_length (wire, &length); return TRUE; } break; case GDK_BUTTON_RELEASE: switch (event->button.button) { case 1: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) { break; } if (wire_item->priv->resize_state == WIRE_RESIZER_NONE) { break; } g_signal_stop_emission_by_name (wire_item, "button-release-event"); goo_canvas_pointer_ungrab (canvas, GOO_CANVAS_ITEM (wire_item), event->button.time); wire_item->priv->resize_state = WIRE_RESIZER_NONE; sheet->state = SHEET_STATE_NONE; item_data_register (ITEM_DATA (wire)); return TRUE; } break; default: return sheet_item_event (GOO_CANVAS_ITEM (wire_item), GOO_CANVAS_ITEM (wire_item), event, sheet); } return sheet_item_event (GOO_CANVAS_ITEM (wire_item), GOO_CANVAS_ITEM (wire_item), event, sheet); }
WireItem * wire_item_new (Sheet *sheet, Wire *wire) { GooCanvasItem *item; WireItem *wire_item; GooCanvasPoints *points; WireItemPriv *priv; SheetPos start_pos, length; g_return_val_if_fail (sheet != NULL, NULL); g_return_val_if_fail (IS_SHEET (sheet), NULL); wire_get_pos_and_length (wire, &start_pos, &length); item = g_object_new (TYPE_WIRE_ITEM, NULL); g_object_set (item, "parent", sheet->object_group, NULL); wire_item = WIRE_ITEM (item); g_object_set (wire_item, "data", wire, NULL); priv = wire_item->priv; priv->resize1 = GOO_CANVAS_RECT (goo_canvas_rect_new ( GOO_CANVAS_ITEM (wire_item), -RESIZER_SIZE, -RESIZER_SIZE, 2 * RESIZER_SIZE, 2 * RESIZER_SIZE, "stroke-color", "blue", "fill-color", "green", "line-width", 1.0, NULL)); g_object_set (priv->resize1, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); priv->resize2 = GOO_CANVAS_RECT (goo_canvas_rect_new ( GOO_CANVAS_ITEM (wire_item), length.x - RESIZER_SIZE, length.y - RESIZER_SIZE, 2 * RESIZER_SIZE, 2 * RESIZER_SIZE, "stroke-color", "blue", "fill-color", "green", "line-width", 1.0, NULL)); g_object_set (priv->resize2, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); points = goo_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; priv->line = GOO_CANVAS_POLYLINE (goo_canvas_polyline_new ( GOO_CANVAS_ITEM (wire_item), FALSE, 0, "points", points, "stroke-color", "blue", "line-width", 1.0, NULL)); goo_canvas_points_unref (points); ITEM_DATA (wire)->rotated_handler_id = g_signal_connect_data (wire, "rotated", G_CALLBACK (wire_rotated_callback), G_OBJECT (wire_item), NULL, 0); g_signal_connect_data (wire, "flipped", G_CALLBACK (wire_flipped_callback), G_OBJECT (wire_item), NULL, 0); ITEM_DATA (wire)->moved_handler_id = g_signal_connect_object (wire, "moved", G_CALLBACK (wire_moved_callback), G_OBJECT (wire_item), 0); g_signal_connect (wire, "changed", G_CALLBACK (wire_changed_callback), wire_item); g_signal_connect (wire, "delete", G_CALLBACK (wire_delete_callback), wire_item); wire_update_bbox (wire); return wire_item; }
static int wire_item_event (WireItem *wire_item, const GdkEvent *event, SchematicView *sv) { SheetPos start_pos, length; Wire *wire; Sheet *sheet; GnomeCanvas *canvas; static double last_x, last_y; double dx, dy, zoom; /* The selected group's bounding box in window resp. canvas coordinates. */ double x1, y1, x2, y2; static double bb_x1, bb_y1, bb_x2, bb_y2; int cx1, cy1, cx2, cy2; double snapped_x, snapped_y; int sheet_width, sheet_height; SheetPos pos; sheet = schematic_view_get_sheet (sv); canvas = GNOME_CANVAS (sheet); g_object_get (G_OBJECT (wire_item), "data", &wire, NULL); wire_get_pos_and_length (WIRE (wire), &start_pos, &length); sheet_get_zoom (sheet, &zoom); switch (event->type) { case GDK_BUTTON_PRESS: switch (event->button.button) { case 1: { g_signal_stop_emission_by_name (G_OBJECT (sheet), "event"); double x, y; x = event->button.x - start_pos.x; y = event->button.y - start_pos.y; if ((x > -RESIZER_SIZE) && (x < RESIZER_SIZE) && (y > -RESIZER_SIZE) && (y < RESIZER_SIZE)) { gtk_widget_grab_focus (GTK_WIDGET (sheet)); sheet->state = SHEET_STATE_DRAG_START; wire_item->priv->resize_state = WIRE_RESIZER_1; last_x = event->button.x; last_y = event->button.y; item_data_unregister (ITEM_DATA (wire)); return TRUE; } if ((x > (length.x-RESIZER_SIZE)) && (x < (length.x+RESIZER_SIZE)) && (y > (length.y-RESIZER_SIZE)) && (y < (length.y+RESIZER_SIZE))) { gtk_widget_grab_focus (GTK_WIDGET (sheet)); sheet->state = SHEET_STATE_DRAG_START; wire_item->priv->resize_state = WIRE_RESIZER_2; last_x = event->button.x; last_y = event->button.y; item_data_unregister (ITEM_DATA (wire)); return TRUE; } } break; } break; case GDK_MOTION_NOTIFY: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) break; if (wire_item->priv->resize_state == WIRE_RESIZER_NONE) break; if (sheet->state == SHEET_STATE_DRAG_START || sheet->state == SHEET_STATE_DRAG) { sheet->state = SHEET_STATE_DRAG; snapped_x = event->motion.x; snapped_y = event->motion.y; snap_to_grid (sheet->grid, &snapped_x, &snapped_y); dx = snapped_x - last_x; dy = snapped_y - last_y; last_x = snapped_x; last_y = snapped_y; wire_get_pos_and_length (wire, &pos, &length); if (wire_item->priv->resize_state == WIRE_RESIZER_1) { switch (wire->priv->direction) { case WIRE_DIR_VERT: /* Vertical Wire */ pos.y = last_y; length.y -= dy; break; case WIRE_DIR_HORIZ: /* Horizontal Wire */ pos.x = last_x; length.x -= dx; break; default: pos.y = last_y; length.y -= dy; pos.x = last_x; length.x -= dx; } } else { switch (wire->priv->direction) { case WIRE_DIR_VERT: /* Vertical Wire */ length.y += dy; break; case WIRE_DIR_HORIZ: /* Horizontal Wire */ length.x += dx; break; default: length.y += dy; length.x += dx; } } snap_to_grid (sheet->grid, &length.x, &length.y); item_data_set_pos (sheet_item_get_data (SHEET_ITEM (wire_item)), &pos); wire_set_length (wire, &length); return TRUE; } break; case GDK_BUTTON_RELEASE: switch (event->button.button) { case 1: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) break; if (wire_item->priv->resize_state == WIRE_RESIZER_NONE) break; g_signal_stop_emission_by_name (G_OBJECT (wire_item), "event"); //gtk_timeout_remove (priv->scroll_timeout_id); // Esto no esta bien. sheet->state = SHEET_STATE_NONE; gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (wire_item), event->button.time); wire_item->priv->resize_state = WIRE_RESIZER_NONE; sheet->state = SHEET_STATE_NONE; item_data_register (ITEM_DATA (wire)); return TRUE; } break; default: return sheet_item_event (SHEET_ITEM (wire_item), event, sv); } return sheet_item_event (SHEET_ITEM (wire_item), event, sv); }
WireItem *wire_item_new (Sheet *sheet, Wire *wire) { GooCanvasItem *item; WireItem *wire_item; ItemData *item_data; GooCanvasPoints *points; WireItemPriv *priv; Coords start_pos, length; g_return_val_if_fail (sheet != NULL, NULL); g_return_val_if_fail (IS_SHEET (sheet), NULL); wire_get_pos_and_length (wire, &start_pos, &length); item = g_object_new (TYPE_WIRE_ITEM, NULL); g_object_set (item, "parent", sheet->object_group, NULL); wire_item = WIRE_ITEM (item); g_object_set (wire_item, "data", wire, NULL); priv = wire_item->priv; const int random_color_count = 9; const char *random_color[] = {"blue", "red", "green" /*, "yellow"*/, "orange", "brown", "purple", "pink", "lightblue", "lightgreen"}; priv->resize1 = GOO_CANVAS_RECT ( goo_canvas_rect_new (GOO_CANVAS_ITEM (wire_item), -RESIZER_SIZE, -RESIZER_SIZE, 2 * RESIZER_SIZE, 2 * RESIZER_SIZE, "stroke-color", oregano_options_debug_wires () ? random_color[g_random_int_range (0, random_color_count - 1)] : "blue", "fill-color", "green", "line-width", 1.0, NULL)); g_object_set (priv->resize1, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); priv->resize2 = GOO_CANVAS_RECT (goo_canvas_rect_new ( GOO_CANVAS_ITEM (wire_item), length.x - RESIZER_SIZE, length.y - RESIZER_SIZE, 2 * RESIZER_SIZE, 2 * RESIZER_SIZE, "stroke-color", oregano_options_debug_wires () ? random_color[g_random_int_range (0, random_color_count - 1)] : "blue", "fill-color", "green", "line-width", 1.0, NULL)); g_object_set (priv->resize2, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); points = goo_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; priv->line = GOO_CANVAS_POLYLINE (goo_canvas_polyline_new ( GOO_CANVAS_ITEM (wire_item), FALSE, 0, "points", points, "stroke-color", oregano_options_debug_wires () ? random_color[g_random_int_range (0, random_color_count - 1)] : "blue", "line-width", 1.0, "start-arrow", oregano_options_debug_wires () ? TRUE : FALSE, "end-arrow", oregano_options_debug_wires () ? TRUE : FALSE, NULL)); goo_canvas_points_unref (points); item_data = ITEM_DATA (wire); item_data->rotated_handler_id = g_signal_connect_object ( G_OBJECT (wire), "rotated", G_CALLBACK (wire_rotated_callback), G_OBJECT (wire_item), 0); item_data->flipped_handler_id = g_signal_connect_object ( G_OBJECT (wire), "flipped", G_CALLBACK (wire_flipped_callback), G_OBJECT (wire_item), 0); item_data->moved_handler_id = g_signal_connect_object ( G_OBJECT (wire), "moved", G_CALLBACK (wire_moved_callback), G_OBJECT (wire_item), 0); item_data->changed_handler_id = g_signal_connect_object ( G_OBJECT (wire), "changed", G_CALLBACK (wire_changed_callback), G_OBJECT (wire_item), 0); g_signal_connect (wire, "delete", G_CALLBACK (wire_delete_callback), wire_item); wire_update_bbox (wire); return wire_item; }
WireItem * wire_item_new (Sheet *sheet, Wire *wire) { WireItem *item; GnomeCanvasPoints *points; WireItemPriv *priv; SheetPos start_pos, length; g_return_val_if_fail (sheet != NULL, NULL); g_return_val_if_fail (IS_SHEET (sheet), NULL); //g_object_ref (G_OBJECT(wire)); /* XXX Ver si hay equivalente gtk_object_sink (GTK_OBJECT (wire)); */ wire_get_pos_and_length (wire, &start_pos, &length); /* * Because of the GnomeCanvasGroup inheritance, a small hack is needed * here. The group starts at the startpoint of the wire, and the line * goes from (0,0) to (length.x, length.y). */ item = WIRE_ITEM (gnome_canvas_item_new ( sheet->object_group, wire_item_get_type (), "data", wire, "x", (double) start_pos.x, "y", (double) start_pos.y, NULL)); priv = item->priv; priv->resize1 = GNOME_CANVAS_RECT (gnome_canvas_item_new ( GNOME_CANVAS_GROUP (item), gnome_canvas_rect_get_type (), "x1", -RESIZER_SIZE, "y1", -RESIZER_SIZE, "x2", RESIZER_SIZE, "y2", RESIZER_SIZE, "fill_color", "red", "fill_color_rgba", 0x3cb37180, "outline_color", "blue", "width_pixels", 1, NULL)); priv->resize2 = GNOME_CANVAS_RECT (gnome_canvas_item_new ( GNOME_CANVAS_GROUP (item), gnome_canvas_rect_get_type (), "x1", length.x-RESIZER_SIZE, "y1", length.y-RESIZER_SIZE, "x2", length.x+RESIZER_SIZE, "y2", length.y+RESIZER_SIZE, "fill_color", "red", "fill_color_rgba", 0x3cb37180, "outline_color", "blue", "width_pixels", 1, NULL)); gnome_canvas_item_hide (GNOME_CANVAS_ITEM (priv->resize1)); gnome_canvas_item_hide (GNOME_CANVAS_ITEM (priv->resize2)); points = gnome_canvas_points_new (2); points->coords[0] = 0; points->coords[1] = 0; points->coords[2] = length.x; points->coords[3] = length.y; priv->line = GNOME_CANVAS_LINE (gnome_canvas_item_new ( GNOME_CANVAS_GROUP (item), gnome_canvas_line_get_type (), "points", points, "fill_color", "blue", "width_pixels", 1, NULL)); gnome_canvas_points_free (points); g_signal_connect_object(G_OBJECT(wire), "rotated", G_CALLBACK(wire_rotated_callback), G_OBJECT(item), 0); g_signal_connect_object(G_OBJECT(wire), "flipped", G_CALLBACK(wire_flipped_callback), G_OBJECT(item), 0); g_signal_connect_object(G_OBJECT(wire), "moved", G_CALLBACK(wire_moved_callback), G_OBJECT(item), 0); g_signal_connect (G_OBJECT (wire), "changed", G_CALLBACK (wire_changed_callback), item); g_signal_connect (G_OBJECT (wire), "delete", G_CALLBACK (wire_delete_callback), item); wire_update_bbox (wire); return item; }
int node_store_add_wire (NodeStore *store, Wire *wire) { gdouble x1, y1, x2, y2; GSList *ip_list, *list; IntersectionPoint *ipoint; Node *node; SheetPos pos, length; g_return_val_if_fail (store != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (store), FALSE); g_return_val_if_fail (wire != NULL, FALSE); g_return_val_if_fail (IS_WIRE (wire), FALSE); wire_get_pos_and_length (wire, &pos, &length); x1 = pos.x; y1 = pos.y; x2 = x1 + length.x; y2 = y1 + length.y; // Check for intersection with other wires. ip_list = wires_intersect (store, x1, y1, x2, y2); for (list = ip_list; list; list = list->next) { ipoint = list->data; if (IS_EQ (x1, x2) && ((ipoint->pos.y == y1) || (ipoint->pos.y == y2))) { SheetPos w_pos, w_length; gboolean can_join; GSList *nodes; wire_get_pos_and_length (ipoint->wire, &w_pos, &w_length); gdouble _x1, _x2, _y1, _y2; _x1 = w_pos.x; _y1 = w_pos.y; _x2 = _x1 + w_length.x; _y2 = _y1 + w_length.y; can_join = TRUE; nodes = wire_get_nodes (wire); for (; nodes; nodes = nodes->next) { SheetPos p1; Node *node = (Node *)nodes->data; p1.x = _x1; p1.y = _y1; if ((fabs (node->key.x - p1.x) < 1e-3) && (fabs (node->key.y - p1.y) < 1e-3)){ can_join = FALSE; break; } p1.x = _x2; p1.y = _y2; if ((fabs (node->key.x - p1.x) < 1e-3) && (fabs (node->key.y - p1.y) < 1e-3)){ can_join = FALSE; break; } } if (IS_EQ(_x1, _x2) && can_join) { if (w_pos.x < pos.x) pos.x = w_pos.x; if (w_pos.y < pos.y) pos.y = w_pos.y; length.x += w_length.x; length.y += w_length.y; // Update the new size and pos of the wire item_data_unregister (ITEM_DATA (ipoint->wire)); wire_set_length (ipoint->wire, &length); item_data_set_pos (ITEM_DATA (ipoint->wire), &pos); wire_update_bbox (ipoint->wire); item_data_register (ITEM_DATA (ipoint->wire)); // Done!, return -1 so wire is deleted return -1; } } else if (IS_EQ (y1, y2) && ((ipoint->pos.x == x1) || (ipoint->pos.x == x2))) { SheetPos w_pos, w_length; gboolean can_join; GSList *nodes; wire_get_pos_and_length (ipoint->wire, &w_pos, &w_length); gdouble _x1, _x2, _y1, _y2; _x1 = w_pos.x; _y1 = w_pos.y; _x2 = _x1 + w_length.x; _y2 = _y1 + w_length.y; can_join = TRUE; nodes = wire_get_nodes (wire); for (; nodes; nodes = nodes->next) { SheetPos p; Node *node = (Node *)nodes->data; p.x = _x1; p.y = _y1; if ((fabs (node->key.x - p.x) < 1e-3) && (fabs (node->key.y - p.y) < 1e-3)){ can_join = FALSE; break; } p.x = _x2; p.y = _y2; if ((fabs (node->key.x - p.x) < 1e-3) && (fabs (node->key.y - p.y) < 1e-3)){ can_join = FALSE; break; } } if (IS_EQ(_y1, _y2) && can_join) { if (w_pos.x < pos.x) pos.x = w_pos.x; if (w_pos.y < pos.y) pos.y = w_pos.y; length.x += w_length.x; length.y += w_length.y; // Update the new size and pos of the wire item_data_unregister (ITEM_DATA (ipoint->wire)); wire_set_length (ipoint->wire, &length); item_data_set_pos (ITEM_DATA (ipoint->wire), &pos); wire_update_bbox (ipoint->wire); item_data_register (ITEM_DATA (ipoint->wire)); // Done!, return -1 so wire si deleted return -1; } } node = node_store_get_or_create_node (store, ipoint->pos); // Add the wire, and also the wire that is intersected. node_add_wire (node, wire); node_add_wire (node, ipoint->wire); wire_add_node (wire, node); wire_add_node (ipoint->wire, node); NG_DEBUG ("Add wire to wire.\n"); g_free (ipoint); } g_slist_free (ip_list); // Check for intersection with parts (pins). ip_list = wire_intersect_parts (store, wire); for (list = ip_list; list; list = list->next) { node = list->data; // Add the wire to the node (pin) that it intersected. node_add_wire (node, wire); wire_add_node (wire, node); NG_DEBUG ("Add wire to pin.\n"); } g_slist_free (ip_list); g_object_set (G_OBJECT (wire), "store", store, NULL); store->wires = g_list_prepend (store->wires, wire); store->items = g_list_prepend (store->items, wire); return TRUE; }