Beispiel #1
0
static GooCanvasAnchorType 
part_item_get_anchor_from_part (Part *part)
{
	int anchor_h, anchor_v;
	int angle;
	IDFlip flip;

	flip = part_get_flip (part);
	angle = part_get_rotation (part);

	switch (angle) {
	case 0:
		anchor_h = ANCHOR_SOUTH;
		anchor_v = ANCHOR_WEST;
		break;
	case 90:
		anchor_h = ANCHOR_NORTH;
		anchor_v = ANCHOR_WEST;
		// Invert Rotation 
		if (flip & ID_FLIP_HORIZ)
			flip = ID_FLIP_VERT;
		else if (flip & ID_FLIP_VERT)
			flip = ID_FLIP_HORIZ;
		break;
	}

	if (flip & ID_FLIP_HORIZ) {
		anchor_v = ANCHOR_EAST;
	}
	if (flip & ID_FLIP_VERT) {
		anchor_h = ANCHOR_NORTH;
	}

	if ((anchor_v == ANCHOR_EAST) && (anchor_h == ANCHOR_NORTH))
		return GOO_CANVAS_ANCHOR_NORTH_EAST;
	if ((anchor_v == ANCHOR_WEST) && (anchor_h == ANCHOR_NORTH))
		return GOO_CANVAS_ANCHOR_NORTH_WEST;
	if ((anchor_v == ANCHOR_WEST) && (anchor_h == ANCHOR_SOUTH))
		return GOO_CANVAS_ANCHOR_SOUTH_WEST;

	return GOO_CANVAS_ANCHOR_SOUTH_EAST;
}
Beispiel #2
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");
}
Beispiel #3
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);
}
Beispiel #4
0
/**
 * whenever the model changes, this one gets called to update the view representation
 * @attention this recalculates the matrix every time, this makes sure no errors stack up
 * @attention further reading on matrix manipulations
 * @attention http://www.cairographics.org/matrix_transform/
 * @param data the model item, a bare C struct derived from ItemData
 * @param sheet_item the view item, derived from goo_canvas_group/item
 */
static void
part_changed_callback (ItemData *data, SheetItem *sheet_item)
{
	//TODO add static vars in order to skip the redraw if nothing changed
	//TODO may happen once in a while and the check is really cheap
	GSList *iter;
	GooCanvasAnchorType anchor;
	GooCanvasGroup *group;
	GooCanvasItem *canvas_item;
	PartItem *item;
	PartItemPriv *priv;
	Part *part;
	int index = 0;
	Coords pos;
	double scale_h, scale_v;


	// states
	int rotation;
	IDFlip flip;

	g_return_if_fail (sheet_item != NULL);
	g_return_if_fail (IS_PART_ITEM (sheet_item));

	item = PART_ITEM (sheet_item);
	group = GOO_CANVAS_GROUP (item);
	part = PART (data);

	priv = item->priv;

	// init the states

	flip = part_get_flip (part);
	rotation = part_get_rotation (part);

	DEGSANITY (rotation);

	scale_h = (flip & ID_FLIP_HORIZ) ? -1. : 1.;
	scale_v = (flip & ID_FLIP_VERT) ? -1. : 1.;


	item_data_get_pos (data, &pos);
	// Move the canvas item and invalidate the bbox cache.
	goo_canvas_item_set_simple_transform (GOO_CANVAS_ITEM (sheet_item),
	                                      pos.x,
	                                      pos.y,
	                                      1.0,
	                                      0.0);

	cairo_matrix_t morph, inv;
	cairo_status_t done;

	cairo_matrix_init_rotate (&morph, DEG2RAD (rotation));
	cairo_matrix_scale (&morph, scale_h, scale_v);

	inv = morph;
	done = cairo_matrix_invert (&inv);
	if (done != CAIRO_STATUS_SUCCESS) {
		g_warning ("Failed to invert matrix. This should never happen. Never!");
		return;
	}

	// rotate all items in the canvas group
	for (index = 0; index < group->items->len; index++) {
		canvas_item = GOO_CANVAS_ITEM (group->items->pdata[index]);
		goo_canvas_item_set_transform (GOO_CANVAS_ITEM (canvas_item), &morph);
	}

	// revert the rotation of all labels and change their anchor to not overlap too badly
	// this assures that the text is always horizontal and properly aligned
	anchor = angle_to_anchor (rotation);

	for (iter = priv->label_items; iter; iter = iter->next) {
		g_object_set (iter->data,
		              "anchor", anchor,
		              NULL);

		goo_canvas_item_set_transform (iter->data, &inv);

	}
	// same for label nodes
	for (iter = priv->label_nodes; iter; iter = iter->next) {
		g_object_set (iter->data,
		              "anchor", anchor, 
		              NULL);

		goo_canvas_item_set_transform (iter->data, &inv);
	}


	// Invalidate the bounding box cache.
	priv->cache_valid = FALSE;
}
Beispiel #5
0
static void
create_canvas_label_nodes (PartItem *item, Part *part)
{
	GooCanvasItem *canvas_item;
	GSList *item_list;
	GooCanvasItem *group;
	Pin *pins;
	int num_pins, i;
	Coords p1, p2;
	GooCanvasAnchorType anchor;
	
	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));

	num_pins = part_get_num_pins (part);
	pins = part_get_pins (part);
	group = item->priv->node_group;
	item_list = NULL;

	get_cached_bounds (item, &p1, &p2);

	switch (part_get_rotation (part)) {
		case 0:
			anchor = GOO_CANVAS_ANCHOR_SOUTH_WEST;
		break;
		case 90:
			anchor = GOO_CANVAS_ANCHOR_NORTH_WEST;
		break;
		case 180:
			anchor = GOO_CANVAS_ANCHOR_NORTH_EAST;
		break;
		case 270:
			anchor = GOO_CANVAS_ANCHOR_SOUTH_EAST;
		break;
		default:
			anchor = GOO_CANVAS_ANCHOR_SOUTH_WEST;
	}

	for (i = 0; i < num_pins; i++) {
		int x, y;
		char *text;
		x = pins[i].offset.x;
		y = pins[i].offset.y;

		text = g_strdup_printf ("%d", pins[i].node_nr);
		canvas_item = goo_canvas_text_new (GOO_CANVAS_ITEM (group),
		                text,
		                (double) x,
		                (double) y,
		                0,
		                anchor,
		                "fill_color", "black",
		                "font", "Sans 8",
		                NULL);
		// Shift slightly the label for a Voltmeter
		if (i == 0) goo_canvas_item_translate (canvas_item, -15.0, -10.0);

		item_list = g_slist_prepend (item_list, canvas_item);
		g_free (text);
	}
	item_list = g_slist_reverse (item_list);
	item->priv->label_nodes = item_list;
}
Beispiel #6
0
static void
write_xml_part (Part *part, parseXmlContext *ctxt)
{
	PartPriv *priv;
	xmlNodePtr node_part;
	gchar *str;
	Coords pos;

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

	priv = part->priv;

	// Create a node for the part.
	node_part = xmlNewChild (ctxt->node_parts, ctxt->ns, BAD_CAST "part", NULL);
	if (!node_part) {
		g_warning ("Failed during save of part %s.\n", priv->name);
		return;
	}

	str = g_strdup_printf ("%d", part_get_rotation (part));
	xmlNewChild (node_part, ctxt->ns, BAD_CAST "rotation",
		xmlEncodeEntitiesReentrant (ctxt->doc, BAD_CAST str));
	g_free (str);

	if (priv->flip & ID_FLIP_HORIZ)
		xmlNewChild (node_part, ctxt->ns, BAD_CAST "flip",
			xmlEncodeEntitiesReentrant (ctxt->doc, BAD_CAST "horizontal"));

	if (priv->flip & ID_FLIP_VERT)
		xmlNewChild (node_part, ctxt->ns, BAD_CAST "flip",
			xmlEncodeEntitiesReentrant (ctxt->doc, BAD_CAST "vertical"));

	// Store the name.
	xmlNewChild (node_part, ctxt->ns, BAD_CAST "name",
		xmlEncodeEntitiesReentrant (ctxt->doc, BAD_CAST priv->name));

	// Store the name of the library the part resides in.
	xmlNewChild (node_part, ctxt->ns, BAD_CAST "library",
		xmlEncodeEntitiesReentrant (ctxt->doc, BAD_CAST priv->library->name));

	// Which symbol to use.
	xmlNewChild (node_part, ctxt->ns, BAD_CAST "symbol",
		xmlEncodeEntitiesReentrant (ctxt->doc, BAD_CAST priv->symbol_name));

	// Position.
	item_data_get_pos (ITEM_DATA (part), &pos);
	str = g_strdup_printf ("(%g %g)", pos.x, pos.y);
	xmlNewChild (node_part, ctxt->ns, BAD_CAST "position", BAD_CAST str);
	g_free (str);

	// Create a node for the properties.
	ctxt->node_props = xmlNewChild (node_part, ctxt->ns, BAD_CAST "properties",
		NULL);
	if (!ctxt->node_props) {
		g_warning ("Failed during save of part %s.\n", priv->name);
		return;
	}
	else{
		g_slist_foreach (priv->properties, (GFunc) write_xml_property,
			ctxt);
	}

	// Create a node for the labels.
	ctxt->node_labels = xmlNewChild (node_part, ctxt->ns, BAD_CAST "labels", NULL);
	if (!ctxt->node_labels) {
		g_warning ("Failed during save of part %s.\n", priv->name);
		return;
	}
	else{
		g_slist_foreach (priv->labels, (GFunc) write_xml_label, ctxt);
	}
}