Пример #1
0
static void
part_copy (ItemData *dest, ItemData *src)
{
	Part *dest_part, *src_part;
	GSList *list;
	int i;

	g_return_if_fail (dest != NULL);
	g_return_if_fail (IS_PART (dest));
	g_return_if_fail (src != NULL);
	g_return_if_fail (IS_PART (src));

	if (parent_class->copy != NULL)
		parent_class->copy (dest, src);

	dest_part = PART (dest);
	src_part = PART (src);

	dest_part->priv->rotation = src_part->priv->rotation;
	dest_part->priv->flip = src_part->priv->flip;
	dest_part->priv->num_pins = src_part->priv->num_pins;
	dest_part->priv->library = src_part->priv->library;
	dest_part->priv->name = g_strdup (src_part->priv->name);
	dest_part->priv->symbol_name = g_strdup (src_part->priv->symbol_name);

	memcpy (dest_part->priv->pins, src_part->priv->pins,
		src_part->priv->num_pins * sizeof (Pin));
	for (i = 0; i < dest_part->priv->num_pins; i++)
		dest_part->priv->pins[i].part = dest_part;

	// Copy properties and labels.
	dest_part->priv->properties =
		g_slist_copy (src_part->priv->properties);
	for (list = dest_part->priv->properties; list; list = list->next) {
		PartProperty *prop, *new_prop;

		new_prop = g_new0 (PartProperty, 1);
		prop = list->data;
		new_prop->name = g_strdup (prop->name);
		new_prop->value = g_strdup (prop->value);
		list->data = new_prop;
	}

	dest_part->priv->labels = g_slist_copy (src_part->priv->labels);
	for (list = dest_part->priv->labels; list; list = list->next) {
		PartLabel *label, *new_label;

		new_label = g_new0 (PartLabel, 1);
		label = list->data;
		new_label->name = g_strdup (label->name);
		new_label->text = g_strdup (label->text);
		new_label->pos = label->pos;
		list->data = new_label;
	}
}
Пример #2
0
static int
part_set_properties (Part *part, GSList *properties)
{
	PartPriv *priv;
	GSList *list;

	g_return_val_if_fail (part != NULL, FALSE);
	g_return_val_if_fail (IS_PART (part), FALSE);

	priv = part->priv;

	if (priv->properties != NULL)
		g_warning ("Properties already set!");

	// Copy the properties list to the part.
	for (list = properties; list; list = list->next) {
		PartProperty *prop_new, *prop;

		prop = list->data;
		prop_new = g_new0 (PartProperty, 1);
		prop_new->name = g_strdup (prop->name);
		prop_new->value = g_strdup (prop->value);

		priv->properties = g_slist_prepend (priv->properties, prop_new);
	}

	return TRUE;
}
Пример #3
0
int
part_set_pins (Part *part, GSList *pins)
{
	PartPriv *priv;
	GSList *list;
	int num_pins, i;

	g_return_val_if_fail (part != NULL, FALSE);
	g_return_val_if_fail (IS_PART (part), FALSE);
	g_return_val_if_fail (pins != NULL, FALSE);

	priv = part->priv;

	num_pins = g_slist_length (pins);

	if (priv->pins)
		g_free (priv->pins);

	priv->pins = g_new0 (Pin, num_pins);
	priv->num_pins = num_pins;

	for (list = pins, i = 0; list; list = list->next, i++) {
		// Note that this is slightly hackish. The list contains
		// Connections which only have the Coords field.
		Pin *pin = list->data;

		priv->pins[i].pin_nr = i;
		priv->pins[i].node_nr= 0;
		priv->pins[i].offset.x = pin->offset.x;
		priv->pins[i].offset.y = pin->offset.y;
		priv->pins[i].part = part;
	}

	return TRUE;
}
Пример #4
0
/**
 * @returns the rotation in degrees
 * @attention steps of 90 degrees only!
 */
gint part_get_rotation (Part *part)
{
	ItemData *item;
	gdouble register a, b, c, d, sx, sy;
	cairo_matrix_t *t;

	g_return_val_if_fail (part != NULL, 0);
	g_return_val_if_fail (IS_PART (part), 0);

	item = ITEM_DATA (part);

	t = item_data_get_rotate (item);
	a = t->xx;
	b = t->xy;
	c = t->yx;
	d = t->yy;

	sx = a * a + c * c;
	sy = b * b + d * d;
	if (G_UNLIKELY (abs (sx) < 1e-10 && abs (sy) < 1e-10)) {
		g_warning ("Unabled to calculate rotation from matrix. Assuming 0°.");
		return 0;
	}

	gint register r = -1;
	if (abs (sx) > abs (sy))
		r = 90 * (gint)(2. * acos (a / sqrt (sx)) / M_PI);
	else
		r = 90 * (gint)(2. * acos (d / sqrt (sy)) / M_PI);
	return r;
}
Пример #5
0
static char *
part_get_refdes_prefix (ItemData *data)
{
	Part *part;
	char *refdes;
	int i, length;

	g_return_val_if_fail (IS_PART (data), NULL);

	part = PART (data);

	refdes = part_get_property (part, "refdes");
	if (refdes == NULL)
		return NULL;

	// Get the 'prefix' i.e R for resistors.
	length = strlen (refdes);
	for (i = 0; i < length; i++) { 
		if (isdigit (refdes[length-i -1])) {
			refdes[length -i -1] = '\0';
		}
		else break;
	}
	return g_strdup (refdes);
}
Пример #6
0
static void
part_set_property (ItemData *data, char *property, char *value)
{
	Part *part;
	PartPriv *priv;
	GSList *props;
	PartProperty *prop;

	part = PART (data);

	g_return_if_fail (part != NULL);
	g_return_if_fail (IS_PART (part));
	g_return_if_fail (property != NULL);

	priv = part->priv;

	for (props = priv->properties; props; props = props->next) {
		prop = props->data;
		if (g_ascii_strcasecmp (prop->name, property) == 0) {
			g_free (prop->value);
			if (value != NULL)
				prop->value = g_strdup (value);
			else
				prop->value = NULL;
			break;
		}
	}
}
Пример #7
0
PartItem *
part_item_canvas_new (Sheet *sheet, Part *part)
{
	PartItem *part_item;
	PartItemPriv *priv;
	GooCanvasItem *item;
	ItemData *item_data;

	g_return_val_if_fail (sheet != NULL, NULL);
	g_return_val_if_fail (IS_SHEET (sheet), NULL);
	g_return_val_if_fail (part != NULL, NULL);
	g_return_val_if_fail (IS_PART (part), NULL);

	item = g_object_new (TYPE_PART_ITEM, NULL);
	
	g_object_set (item, 
	              "parent", sheet->object_group, 
	              NULL);
	
	part_item = PART_ITEM (item);
	g_object_set (part_item, 
                  "data", part, 
                  NULL);
	priv = part_item->priv;
	
	priv->label_group = GOO_CANVAS_ITEM (goo_canvas_group_new (
	        GOO_CANVAS_ITEM (part_item),
	        "width", -1.0,
	        "height", -1.0,
	        NULL));
	g_object_unref (item);
	
	priv->node_group = GOO_CANVAS_ITEM (goo_canvas_group_new (
	        GOO_CANVAS_ITEM (part_item), 
	        NULL));

	g_object_set (GOO_CANVAS_ITEM (priv->node_group),
	              "visibility", GOO_CANVAS_ITEM_INVISIBLE, 
	              NULL);

	item_data = ITEM_DATA (part);
	item_data->rotated_handler_id = g_signal_connect_object (G_OBJECT (part), 
	                                "rotated",
	                                G_CALLBACK (part_rotated_callback),
	                                G_OBJECT (part_item), 0);
	item_data->flipped_handler_id = g_signal_connect_object (G_OBJECT (part), 
	                                "flipped",
	                                G_CALLBACK (part_flipped_callback),
	                                G_OBJECT (part_item), 0);
	item_data->moved_handler_id = g_signal_connect_object (G_OBJECT (part),
	                                "moved",
	                                G_CALLBACK (part_moved_callback),
	                                G_OBJECT (part_item), 0);
	item_data->changed_handler_id = g_signal_connect_object (G_OBJECT (part),
	                                "changed",
	                                G_CALLBACK (part_changed_callback),
	                                G_OBJECT (part_item), 0);

	return part_item;
}
Пример #8
0
// Create a SheetItem from an ItemData object. This is a bit ugly.
// It could be beautified by having a method that creates the item.
// E.g. sheet_item->new_from_data (data);
SheetItem *
sheet_item_factory_create_sheet_item (Sheet *sheet, ItemData *data)
{
	SheetItem *item;

	g_return_val_if_fail (data != NULL, NULL);
	g_return_val_if_fail (IS_ITEM_DATA (data), NULL);
	g_return_val_if_fail (sheet != NULL, NULL);
	g_return_val_if_fail (IS_SHEET (sheet), NULL);

	item = NULL;

	// Pick the right model.
	if (IS_PART (data)) {
		NG_DEBUG ("sheet_item_factory_create_sheet_item part\n\n");
		item = SHEET_ITEM (part_item_new (sheet, PART (data)));
	} 
	else if (IS_WIRE (data)) {
		NG_DEBUG ("sheet_item_factory_create_sheet_item wire\n\n");
		item = SHEET_ITEM (wire_item_new (sheet, WIRE (data)));
	} 
	else if (IS_TEXTBOX (data)) {
		NG_DEBUG ("sheet_item_factory_create_sheet_item text\n\n");
		item = SHEET_ITEM (textbox_item_new (sheet, TEXTBOX (data)));
	} 
	else
		g_warning ("Unknown Item type.");

	return item;
}
Пример #9
0
static void part_unregister (ItemData *data)
{
	NodeStore *store;

	g_return_if_fail (IS_PART (data));

	store = item_data_get_store (data);
	node_store_remove_part (store, PART (data));
}
Пример #10
0
int
node_store_add_part (NodeStore *self, Part *part)
{
	GSList *wire_list, *list;
	Node *node;
	SheetPos lookup_key;
	SheetPos part_pos;
	gdouble x, y;
	int i, num_pins;

	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (IS_NODE_STORE (self), FALSE);
	g_return_val_if_fail (part != NULL, FALSE);
	g_return_val_if_fail (IS_PART (part), FALSE);

	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;

		//Use the position of the pin as hash key.
		lookup_key.x = x;
		lookup_key.y = y;

		// Retrieve a node for this position.
		node = node_store_get_or_create_node (self, lookup_key);

		// Add all the wires that intersect this pin to the node store.
		wire_list = wires_at_pos (self, lookup_key);

		for (list = wire_list; list; list = list->next) {
			Wire *wire = list->data;

		    NG_DEBUG ("Add pin to wire.\n");

			node_add_wire (node, wire);
			wire_add_node (wire, node);
		}

		g_slist_free (wire_list);

		node_add_pin (node, &pins[i]);
	}

	g_object_set (G_OBJECT (part), "store", self, NULL);
	self->parts = g_list_prepend (self->parts, part);
	self->items = g_list_prepend (self->items, part);

	return TRUE;
}
Пример #11
0
Pin *part_get_pins (Part *part)
{
	PartPriv *priv;

	g_return_val_if_fail (part != NULL, NULL);
	g_return_val_if_fail (IS_PART (part), NULL);

	priv = part->priv;
	return priv->pins;
}
Пример #12
0
IDFlip part_get_flip (Part *part)
{
	PartPriv *priv;

	g_return_val_if_fail (part != NULL, 0);
	g_return_val_if_fail (IS_PART (part), 0);

	priv = part->priv;
	return priv->flip;
}
Пример #13
0
gint part_get_num_pins (Part *part)
{
	PartPriv *priv;

	g_return_val_if_fail (part != NULL, 0);
	g_return_val_if_fail (IS_PART (part), 0);

	priv = part->priv;
	return priv->num_pins;
}
Пример #14
0
static void
part_item_paste (Sheet *sheet, ItemData *data)
{
	g_return_if_fail (sheet != NULL);
	g_return_if_fail (IS_SHEET (sheet));
	g_return_if_fail (data != NULL);
	g_return_if_fail (IS_PART (data));

	sheet_add_ghost_item (sheet, data);
}
Пример #15
0
int
part_get_rotation (Part *part)
{
	PartPriv *priv;

	g_return_val_if_fail (part != NULL, 0);
	g_return_val_if_fail (IS_PART (part), 0);

	priv = part->priv;
	return priv->rotation;
}
Пример #16
0
GSList *part_get_properties (Part *part)
{
	PartPriv *priv;

	g_return_val_if_fail (part != NULL, FALSE);
	g_return_val_if_fail (IS_PART (part), FALSE);

	priv = part->priv;

	return priv->properties;
}
Пример #17
0
GSList *part_get_labels (Part *part)
{
	PartPriv *priv;

	g_return_val_if_fail (part != NULL, NULL);
	g_return_val_if_fail (IS_PART (part), NULL);

	priv = part->priv;

	return priv->labels;
}
Пример #18
0
/**
 * register a part to its nodestore
 * @param data the part
 * @attention the @data has to have a valid nodestore set
 */
static int part_register (ItemData *data)
{
	NodeStore *store;

	g_return_val_if_fail (IS_PART (data), FALSE);

	store = item_data_get_store (data);
	node_store_add_part (store, PART (data));

	return TRUE;
}
Пример #19
0
int
node_store_remove_part (NodeStore *self, Part *part)
{
	Node *node;
	SheetPos lookup_key;
	SheetPos pos;
	gdouble x, y;
	int i, num_pins;
	Pin *pins;

	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (IS_NODE_STORE (self), FALSE);
	g_return_val_if_fail (part != NULL, FALSE);
	g_return_val_if_fail (IS_PART (part), FALSE);

	self->parts = g_list_remove (self->parts, part);
	self->items = g_list_remove (self->items, part);

	num_pins = part_get_num_pins (part);
	item_data_get_pos (ITEM_DATA (part), &pos);

	pins = part_get_pins (part);
	for (i = 0; i < num_pins; i++) {
		x = pos.x + pins[i].offset.x;
		y = pos.y + pins[i].offset.y;

		// Use the position of the pin as lookup key.
		lookup_key.x = x;
		lookup_key.y = y;

		node = g_hash_table_lookup (self->nodes, &lookup_key);
		if (node) {
			if (!node_remove_pin (node, &pins[i])) {
				g_warning ("Couldn't remove pin.");
				return FALSE;
			}

			// If the node is empty after removing the pin,
			// remove the node as well.
			if (node_is_empty (node)) {
				g_hash_table_remove (self->nodes, &lookup_key);
				g_object_unref (G_OBJECT (node));
			}
		} 
		else {
			return FALSE;
		}
	}

	return TRUE;
}
Пример #20
0
/**
 * register a part to the nodestore
 */
gboolean node_store_add_part (NodeStore *self, Part *part)
{
	NG_DEBUG ("-0-");
	g_return_val_if_fail (self, FALSE);
	g_return_val_if_fail (IS_NODE_STORE (self), FALSE);
	g_return_val_if_fail (part, FALSE);
	g_return_val_if_fail (IS_PART (part), FALSE);

	GSList *iter, *copy;
	Node *node;
	Coords pin_pos;
	Coords part_pos;
	int i, num_pins;
	Pin *pins;

	num_pins = part_get_num_pins (part);
	pins = part_get_pins (part);

	item_data_get_pos (ITEM_DATA (part), &part_pos);

	for (i = 0; i < num_pins; i++) {
		// Use the position of the pin as hash key.
		pin_pos.x = part_pos.x + pins[i].offset.x;
		pin_pos.y = part_pos.y + pins[i].offset.y;

		// Retrieve a node for this position.
		node = node_store_get_or_create_node (self, pin_pos);

		// Add all the wires that intersect this pin to the node store.
		copy = get_wires_at_pos (self, pin_pos);
		for (iter = copy; iter; iter = iter->next) {
			Wire *wire = copy->data;

			node_add_wire (node, wire);
			wire_add_node (wire, node);
		}

		g_slist_free (copy);

		node_add_pin (node, &pins[i]);
	}

	g_object_set (G_OBJECT (part), "store", self, NULL);
	self->parts = g_list_prepend (self->parts, part);
	self->items = g_list_prepend (self->items, part);

	return TRUE;
}
Пример #21
0
/**
 * remove/unregister a part from the nodestore
 * this does _not_ free the part!
 */
gboolean node_store_remove_part (NodeStore *self, Part *part)
{
	Node *node;
	Coords pin_pos;
	Coords part_pos;
	int i, num_pins;
	Pin *pins;

	g_return_val_if_fail (self, FALSE);
	g_return_val_if_fail (IS_NODE_STORE (self), FALSE);
	g_return_val_if_fail (part, FALSE);
	g_return_val_if_fail (IS_PART (part), FALSE);

	self->parts = g_list_remove (self->parts, part);
	self->items = g_list_remove (self->items, part);

	num_pins = part_get_num_pins (part);
	item_data_get_pos (ITEM_DATA (part), &part_pos);

	pins = part_get_pins (part);
	for (i = 0; i < num_pins; i++) {
		pin_pos.x = part_pos.x + pins[i].offset.x;
		pin_pos.y = part_pos.y + pins[i].offset.y;

		node = g_hash_table_lookup (self->nodes, &pin_pos);
		if (node) {
			if (!node_remove_pin (node, &pins[i])) {
				g_warning ("Could not remove pin[%i] from node %p.", i, node);
				return FALSE;
			}

			// If the node is empty after removing the pin,
			// remove the node as well.
			if (node_is_empty (node)) {
				g_hash_table_remove (self->nodes, &pin_pos);
				g_object_unref (G_OBJECT (node));
			}
		} else {
			return FALSE;
		}
	}

	return TRUE;
}
Пример #22
0
void
part_item_update_node_label (PartItem *item)
{
	PartItemPriv *priv;
	Part *part;
	GSList *labels;
	GooCanvasItem *canvas_item;
	Pin *pins;
	gint num_pins;

	g_return_if_fail (item != NULL);
	g_return_if_fail (IS_PART_ITEM (item));
	priv = item->priv;
	part = PART (sheet_item_get_data (SHEET_ITEM (item)));

	g_return_if_fail (IS_PART (part) );

	// Put the label of each node
	num_pins = part_get_num_pins (part);
	
	if (num_pins == 1) {
		pins = part_get_pins (part);
		labels = priv->label_nodes;
		for (labels = priv->label_nodes; labels; labels=labels->next) {
			char *txt;

			txt = g_strdup_printf ("V(%d)", pins[0].node_nr);
			canvas_item = labels->data;
			if (pins[0].node_nr != 0)
				g_object_set (canvas_item, 
			              "text", txt,  
			        	  "fill_color", LABEL_COLOR,
			        	  "font", "Sans 8", 
			              NULL);
			else
				g_object_set (canvas_item, 
			              "text", "", 
			              NULL);

			g_free (txt);
		}
	}
}
Пример #23
0
static ItemData *part_clone (ItemData *src)
{
	Part *src_part, *new_part;
	ItemDataClass *id_class;

	g_return_val_if_fail (src != NULL, NULL);
	g_return_val_if_fail (IS_PART (src), NULL);

	id_class = ITEM_DATA_CLASS (G_OBJECT_GET_CLASS (src));
	if (id_class->copy == NULL)
		return NULL;

	src_part = PART (src);
	new_part = g_object_new (TYPE_PART, NULL);
	new_part->priv->pins = g_new0 (Pin, src_part->priv->num_pins);
	id_class->copy (ITEM_DATA (new_part), src);

	return ITEM_DATA (new_part);
}
Пример #24
0
/**
 * @returns [transfer-full]
 */
char *part_get_property (Part *part, char *name)
{
	PartPriv *priv;
	GSList *props;
	PartProperty *prop;

	g_return_val_if_fail (part != NULL, NULL);
	g_return_val_if_fail (IS_PART (part), NULL);
	g_return_val_if_fail (name != NULL, NULL);

	priv = part->priv;

	for (props = priv->properties; props; props = props->next) {
		prop = props->data;
		if (g_ascii_strcasecmp (prop->name, name) == 0) {
			return g_strdup (prop->value);
		}
	}
	return NULL;
}
Пример #25
0
static void
create_canvas_labels (PartItem *item, Part *part)
{
	GooCanvasItem *canvas_item;
	GSList *list, *item_list;
	GooCanvasGroup *group;

	g_return_if_fail (item != NULL);
	g_return_if_fail (IS_PART_ITEM (item));
	g_return_if_fail (part != NULL);
	g_return_if_fail (IS_PART (part));

	group = GOO_CANVAS_GROUP (item->priv->label_group);
	item_list = NULL;

	for (list = part_get_labels (part); list; list = list->next) {
		PartLabel *label = list->data;
		char *text;

		text = part_property_expand_macros (part, label->text);

		canvas_item = goo_canvas_text_new (GOO_CANVAS_ITEM (group),
		                text,
		                (double) label->pos.x,
		                (double) label->pos.y,
		                0,
		                GOO_CANVAS_ANCHOR_SOUTH_WEST,
		                "fill_color", LABEL_COLOR,
		                "font", "Sans 8",
		                NULL);

		item_list = g_slist_prepend (item_list, canvas_item);
		g_free (text);
	}
	g_slist_free_full (list, g_object_unref);

	item_list = g_slist_reverse (item_list);
	part_item_set_label_items (item, item_list);
}
Пример #26
0
static int
part_set_labels (Part *part, GSList *labels)
{
	PartPriv *priv;
	GSList *list;

	g_return_val_if_fail (part != NULL, FALSE);
	g_return_val_if_fail (IS_PART (part), FALSE);

	priv = part->priv;

	if (priv->labels != NULL) {
		g_warning ("Part already has labels.");
		for (list = priv->labels; list; list = list->next) {
			PartLabel *label = list->data;
			g_free (label->name);
			g_free (label->text);
			g_free (label);
		}
		g_slist_free (priv->labels);
		priv->labels = NULL;
	}

	for (list = labels; list; list = list->next) {
		PartLabel *label, *label_copy;

		label = list->data;

		label_copy = g_new0 (PartLabel, 1);
		label_copy->name = g_strdup (label->name);
		label_copy->text = g_strdup (label->text);
		label_copy->pos.x = label->pos.x;
		label_copy->pos.y = label->pos.y;
		priv->labels = g_slist_prepend (priv->labels, label_copy);
	}

	return TRUE;
}
Пример #27
0
static void
part_changed (ItemData *data)
{
	Part *part;
	Coords loc = {0., 0.};
	int angle = 0;
	IDFlip flip = ID_FLIP_NONE;

	g_return_if_fail (IS_PART (data));

	part = (Part *)data;

	flip = part_get_flip (part);
	angle = part_get_rotation (part);
	item_data_get_pos (data, &loc);

#if 0
	//FIXME isn't it more sane to just emit the changed?
	g_signal_emit_by_name (data, "moved", &loc);
	g_signal_emit_by_name (data, "flipped", flip);
	g_signal_emit_by_name (data, "rotated", angle);
#endif
	g_signal_emit_by_name (data, "changed");
}
Пример #28
0
/**
 * add/register the wire to the nodestore
 *
 * @param store
 * @param wire
 * @returns TRUE if the wire was added or merged, else FALSE
 */
gboolean node_store_add_wire (NodeStore *store, Wire *wire)
{
	GList *list;
	Node *node;
	int i = 0;

	g_return_val_if_fail (store, FALSE);
	g_return_val_if_fail (IS_NODE_STORE (store), FALSE);
	g_return_val_if_fail (wire, FALSE);
	g_return_val_if_fail (IS_WIRE (wire), FALSE);

	// Check for intersection with other wires.
	for (list = store->wires; list; list = list->next) {
		g_assert (list->data != NULL);
		g_assert (IS_WIRE (list->data));

		Coords where = {-77.77, -77.77};
		Wire *other = list->data;
		if (do_wires_intersect (wire, other, &where)) {
			if (is_t_crossing (wire, other, &where) || is_t_crossing (other, wire, &where)) {

				node = node_store_get_or_create_node (store, where);

				node_add_wire (node, wire);
				node_add_wire (node, other);

				wire_add_node (wire, node);
				wire_add_node (other, node);

				NG_DEBUG ("Add wire %p to wire %p @ %lf,%lf.\n", wire, other, where.x, where.y);
			} else {
				// magic node removal if a x crossing is overlapped with another wire
				node = node_store_get_node (store, where);
				NG_DEBUG ("Nuke that node [ %p ] at coords inbetween", node);
				if (node) {
					Coords c[4];
					wire_get_start_and_end_pos (other, c + 0, c + 1);
					wire_get_start_and_end_pos (wire, c + 2, c + 3);
					if (!coords_equal (&where, c + 0) && !coords_equal (&where, c + 1) &&
					    !coords_equal (&where, c + 2) && !coords_equal (&where, c + 3)) {

						wire_remove_node (wire, node);
						wire_remove_node (other, node);
						node_remove_wire (node, wire);
						node_remove_wire (node, other);
					}
				}
			}
		}
	}

	// Check for overlapping with other wires.
	do {
		for (list = store->wires; list; list = list->next) {
			g_assert (list->data != NULL);
			g_assert (IS_WIRE (list->data));
			Wire *other = list->data;
			Coords so, eo;
			const gboolean overlap = do_wires_overlap (wire, other, &so, &eo);
			NG_DEBUG ("overlap [ %p] and [ %p ] -- %s", wire, other,
			          overlap == TRUE ? "YES" : "NO");
			if (overlap) {
				Node *sn = node_store_get_node (store, eo);
				Node *en = node_store_get_node (store, so);
#if 1
				wire = vulcanize_wire (store, wire, other, &so, &eo);
				node_store_remove_wire (store, g_object_ref (other)); // equiv
				                                                      // wire_unregister
				                                                      // XXX FIXME this
				                                                      // modifies the list
				                                                      // we iterate over!
				// delay this until idle, so all handlers like adding view
				// representation are completed so existing wire-items can be deleted
				// properly
				// this is not fancy nor nice but seems to work fairly nicly
				g_idle_add (delayed_wire_delete, other);
				break;
				NG_DEBUG ("overlapping of %p with %p ", wire, other);
#else
				if (!sn && !en) {
					wire = vulcanize_wire (store, wire, other, &so, &eo);
				} else if (!sn) {
					NG_DEBUG ("do_something(TM) : %p sn==NULL ", other);
				} else if (!en) {
					NG_DEBUG ("do_something(TM) : %p en==NULL ", other);
				} else {
					NG_DEBUG ("do_something(TM) : %p else ", other);
				}
#endif
			} else {
				NG_DEBUG ("not of %p with %p ", wire, other);
			}
		}
	} while (list);

	// Check for intersection with parts (pins).
	for (list = store->parts; list; list = list->next) {
		g_assert (list->data != NULL);
		g_assert (IS_PART (list->data));

		Coords part_pos;
		gint num_pins = -1;
		Part *part = list->data;

		num_pins = part_get_num_pins (part);
		item_data_get_pos (ITEM_DATA (part), &part_pos);

		// Go through all the parts and see which of their
		// pins that intersect the wire.
		for (i = 0; i < num_pins; i++) {
			Pin *pins;
			Coords lookup_pos;

			pins = part_get_pins (part);
			lookup_pos.x = part_pos.x + pins[i].offset.x;
			lookup_pos.y = part_pos.y + pins[i].offset.y;

			// If there is a wire at this pin's position,
			// add it to the return list.
			if (is_point_on_wire (wire, &lookup_pos)) {
				Node *node;
				node = node_store_get_node (store, lookup_pos);

				if (node != NULL) {
					// Add the wire to the node (pin) that it intersected.
					node_add_wire (node, wire);
					wire_add_node (wire, node);
					NG_DEBUG ("Add wire %p to pin (node) %p.\n", wire, node);
				} else {
					g_warning ("Bug: Found no node at pin at (%g %g).\n", lookup_pos.x,
					           lookup_pos.y);
				}
			}
		}
	}

	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;
}
Пример #29
0
static void
part_print (ItemData *data, cairo_t *cr, SchematicPrintContext *ctx)
{
	GSList *objects, *labels;
	SymbolObject *object;
	LibrarySymbol *symbol;
	double x0, y0;
	int i, rotation;
	Part *part;
	PartPriv *priv;
	Coords pos;
	IDFlip flip;
	GooCanvasPoints *line;

	g_return_if_fail (data != NULL);
	g_return_if_fail (IS_PART (data));

	part = PART (data);
	priv = part->priv;

	symbol = library_get_symbol (priv->symbol_name);
	if (symbol == NULL) {
		return;
	}

	item_data_get_pos (ITEM_DATA (part), &pos);
	x0 = pos.x;
	y0 = pos.y;

	cairo_save (cr);

	gdk_cairo_set_source_rgba (cr, &ctx->colors.components);
	rotation = part_get_rotation (part);
	flip = part_get_flip (part);

	if ((flip & ID_FLIP_HORIZ) && (flip & ID_FLIP_VERT))
		rotation += 180;
	else if (flip == ID_FLIP_HORIZ)
		cairo_scale (cr, -1, 1);
	else if (flip == ID_FLIP_VERT)
		cairo_scale (cr, 1, -1);

	if (rotation %= 360)
		cairo_rotate (cr, rotation*M_PI/180);

	for (objects = symbol->symbol_objects; objects; objects = objects->next) {
		object = (SymbolObject *)(objects->data);

		switch (object->type) {
			case SYMBOL_OBJECT_LINE:
				line = object->u.uline.line;
				for (i = 0; i < line->num_points; i++) {
					double x, y;

					x = line->coords[i * 2];
					y = line->coords[i * 2 + 1];

					if (i == 0)
						cairo_move_to (cr, x0 + x, y0 + y);
					else
						cairo_line_to (cr, x0 + x, y0 + y);
				}
			break;
			case SYMBOL_OBJECT_ARC: {
				gdouble x1 = object->u.arc.x1;
				gdouble y1 = object->u.arc.y1;
				gdouble x2 = object->u.arc.x2;
				gdouble y2 = object->u.arc.y2;
				gdouble width, height, x, y;

				x = (x2 + x1) / 2;
				y = (y2 + y1) / 2;
				width = x2 - x1;
				height = y2 - y1;

				cairo_save (cr);
					cairo_translate (cr, x0 + x, y0 + y);
					cairo_scale (cr, width / 2.0, height / 2.0);
					cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 2 * M_PI);
				cairo_restore (cr);
			}
			break;
			default:
				g_warning (
					"Print part: Part %s contains unknown object.",
					priv->name
				);
			continue;
		}

		cairo_stroke (cr);
	}

	// We don't want to rotate labels text, only the (x,y) coordinate
	gdk_cairo_set_source_rgba (cr, &ctx->colors.labels);
	for (labels = part_get_labels (part); labels; labels = labels->next) {
		gdouble x, y;
		PartLabel *label = (PartLabel *)labels->data;
		gchar *text;
		/* gint text_width, text_height; */

		x = label->pos.x + x0;
		y = label->pos.y + y0;

		text = part_property_expand_macros (part, label->text);
		/* Align the label.
		switch (rotation) {
			case 90:
				y += text_height*opc->scale;
			break;
			case 180:
			break;
			case 270:
				x -= text_width*opc->scale;
			break;
			case 0:
			default:
			break;
		} */

		cairo_save (cr);
			cairo_move_to (cr, x, y);
			cairo_show_text (cr, text);
		cairo_restore (cr);
		g_free (text);
	}
	cairo_restore (cr);
}
Пример #30
0
/**
 * flip a part in a given direction
 * @direction gives the direction the item will be flipped, end users pov!
 * @center the center to flip over - currently ignored FIXME
 */
static void
part_flip (ItemData *data, IDFlip direction, Coords *center)
{
	Part *part;
	PartPriv *priv;
	int i;
	cairo_matrix_t affine;
	double x, y;
	double scale_v, scale_h;
	gboolean handler_connected;
	Coords pos, trans;
	Coords b1, b2;
	Coords pos_new, pos_old, delta;
	//FIXME properly recenter after flipping
	//Coords part_center_before, part_center_after, delta;

	g_return_if_fail (data);
	g_return_if_fail (IS_PART (data));

	part = PART (data);
	priv = part->priv;

	item_data_get_pos (data, &trans);

	// mask, just for the sake of cleanness
	direction &= ID_FLIP_MASK;
	
	// TODO evaluate if we really want to be able to do double flips (180* rots via flipping)
	g_assert (direction != ID_FLIP_MASK);


	// create a transformation _relativ_ to the current _state_
	// reverse axis and fix the created offset by adding 2*pos.x or .y
	
	// convert the flip direction to binary, used in the matrix setup
	// keep in mind that we do relativ manipulations within the model
	// which in turn makes this valid for all rotations!
	scale_h = ((direction & ID_FLIP_HORIZ) != 0) ? -1. : 1.;
	scale_v = ((direction & ID_FLIP_VERT) != 0) ? -1. : 1.;

	// magic, if we are in either 270 or 90 state, we need to rotate the flip state by 90° to draw it properly
	// TODO maybe better put this into the rotation function
	if ((priv->rotation / 90) % 2 == 1) {
		priv->flip ^= ID_FLIP_MASK;
	}
	// toggle the direction
	priv->flip ^= direction;
	if ((priv->flip & ID_FLIP_MASK)== ID_FLIP_MASK) {
		priv->flip = ID_FLIP_NONE;
		priv->rotation += 180;
		priv->rotation %= 360;
	}

	cairo_matrix_init_scale (&affine, scale_h, scale_v);

	item_data_get_pos (data, &pos_old);
	pos_new = pos_old;
	cairo_matrix_transform_point (&affine, &pos_new.x, &pos_new.y);

	g_printf ("\ncenter %p [old] x=%lf,y=%lf -->", data, pos_old.x, pos_old.y);
	g_printf ("  x=%lf, y=%lf\n", pos_new.x, pos_new.y);
	delta.x = - pos_new.x + pos_old.x;
	delta.y = - pos_new.y + pos_old.y;

	// flip the pins
	for (i = 0; i < priv->num_pins; i++) {

		x = priv->pins[i].offset.x;
		y = priv->pins[i].offset.y;
		cairo_matrix_transform_point (&affine, &x, &y);

		if (fabs (x) < 1e-2)
			x = 0.0;
		if (fabs (y) < 1e-2)
			y = 0.0;

		priv->pins[i].offset.x = x;
		priv->pins[i].offset.y = y;
	}
	item_data_snap (data);

	// tell the view
	handler_connected = g_signal_handler_is_connected (G_OBJECT (part), 
	                                                   ITEM_DATA(part)->flipped_handler_id);
	if (handler_connected) {
		g_signal_emit_by_name (G_OBJECT (part), "flipped", priv->flip);

		// TODO - proper boundingbox center calculation

		item_data_get_relative_bbox (ITEM_DATA (part), &b1, &b2);

		// flip the bounding box.
		cairo_matrix_transform_point (&affine, &b1.x, &b1.y);
		cairo_matrix_transform_point (&affine, &b2.x, &b2.y);

		item_data_set_relative_bbox (ITEM_DATA (part), &b1, &b2);
		item_data_set_pos (ITEM_DATA (part), &pos);

		// FIXME - proper recenter to boundingbox center
	}
	if (g_signal_handler_is_connected (G_OBJECT (part),
	                                   ITEM_DATA (part)->changed_handler_id)) {
		g_signal_emit_by_name (G_OBJECT (part),
		                       "changed");
	}

}