Exemple #1
0
static void
rotate_items (Sheet *sheet, GList *items)
{
	GList *list, *item_data_list;
	Coords center, b1, b2;

	item_data_list = NULL;
	for (list = items; list; list = list->next) {
		item_data_list = g_list_prepend (item_data_list,
			sheet_item_get_data (list->data));
	}

	item_data_list_get_absolute_bbox (item_data_list, &b1, &b2);

	center = coords_average(&b1, &b2);

	snap_to_grid (sheet->grid, &center.x, &center.y);

	for (list = item_data_list; list; list = list->next) {
		ItemData *item_data = list->data;

		if (sheet->state == SHEET_STATE_NONE)
			item_data_unregister (item_data);

		item_data_rotate (item_data, 90, &center);

		if (sheet->state == SHEET_STATE_NONE)
			item_data_register (item_data);
	}

	g_list_free (item_data_list);
}
Exemple #2
0
/**
 * rotate an item by an @angle increment (may be negative)
 * @angle the increment the item will be rotated (usually 90° steps)
 * @center_pos if rotated as part of a group, this is the center to rotate around
 * FIXME XXX TODO an issue arises as the center changes with part_rotate
 * FIXME XXX TODO the view callback needs to compensate this somehow
 */
static void
part_rotate (ItemData *data, int angle, Coords *center_pos)
{
	cairo_matrix_t affine;
	double x, y;
	Part *part;
	PartPriv *priv;
	int i, tot_rotation;
	Coords b1, b2;
	Coords part_center_before, part_center_after, delta;
	Coords delta_cp_before, delta_cp_after;
	gboolean handler_connected;

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

	if (angle == 0)
		return;

	part = PART (data);

	priv = part->priv;

	tot_rotation = (priv->rotation + angle + 360) % 360;

	NG_DEBUG ("rotation: angle=%i tot_rotation=%i", angle, tot_rotation);

	// use the cairo matrix funcs to transform the pin
	// positions relative to the item center
	// this is only indirectly related to displaying
	cairo_matrix_init_rotate (&affine, (double)angle * M_PI / 180.);

	if (center_pos) {
		delta_cp_before = coords_sub (&part_center_before, center_pos);
		delta_cp_after = delta_cp_before;
		cairo_matrix_transform_point (&affine, &delta_cp_after.x, &delta_cp_after.y);
	}

	priv->rotation = tot_rotation;
	angle = tot_rotation;

	// Rotate 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;
	}

	// Rotate the bounding box, recenter to old center
	item_data_get_relative_bbox (ITEM_DATA (part), &b1, &b2);
	part_center_before = coords_average (&b1, &b2);

	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);
	part_center_after = coords_average (&b1, &b2);

	delta = coords_sub (&part_center_before, &part_center_after);
	if (center_pos) {
		Coords diff = coords_sub (&delta_cp_after, &delta_cp_before);
		coords_add (&delta, &diff);
	}
	item_data_move (data, &delta);
	item_data_snap (data);

	handler_connected = g_signal_handler_is_connected (G_OBJECT (part),
	                                   ITEM_DATA (part)->rotated_handler_id);
	if (handler_connected) {
		g_signal_emit_by_name (G_OBJECT (part),
		                       "rotated", tot_rotation);
	}

	handler_connected = g_signal_handler_is_connected (G_OBJECT (part),
	                                   ITEM_DATA (part)->changed_handler_id);
	if (handler_connected) {
		g_signal_emit_by_name (G_OBJECT (part),
		                       "changed");
	}
}
Exemple #3
0
static void wire_rotate (ItemData *data, int angle, Coords *center_pos)
{
    cairo_matrix_t affine;
    double x, y;
    Wire *wire;
    WirePriv *priv;
    Coords b1, b2;
    Coords wire_center_before, wire_center_after, delta;
    Coords delta_cp_before, delta_cp_after;

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

    if (angle == 0)
        return;

    wire = WIRE (data);

    item_data_get_absolute_bbox (ITEM_DATA (wire), &b1, &b2);
    wire_center_before = coords_average (&b1, &b2);

    priv = wire->priv;

    if (priv->direction == WIRE_DIR_VERT) {
        priv->direction = WIRE_DIR_HORIZ;
    } else if (priv->direction == WIRE_DIR_HORIZ) {
        priv->direction = WIRE_DIR_VERT;
    }

    cairo_matrix_init_rotate (&affine, (double)angle * M_PI / 180.0);

    // Rotate the wire's end point.
    x = priv->length.x;
    y = priv->length.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->length.x = x;
    priv->length.y = y;

    if (center_pos) {
        delta_cp_before = coords_sub (&wire_center_before, center_pos);
        delta_cp_after = delta_cp_before;
        cairo_matrix_transform_point (&affine, &delta_cp_after.x, &delta_cp_after.y);
    }

    // Update bounding box.
    wire_update_bbox (wire);

    item_data_get_absolute_bbox (ITEM_DATA (wire), &b1, &b2);
    wire_center_after = coords_average (&b1, &b2);

    delta = coords_sub (&wire_center_before, &wire_center_after);
    if (center_pos) {
        Coords diff = coords_sub (&delta_cp_after, &delta_cp_before);
        coords_add (&delta, &diff);
    }
    item_data_move (ITEM_DATA (wire), &delta);
    //	item_data_snap (ITEM_DATA (wire), NULL); //FIXME XXX

    // Let the views (canvas items) know about the rotation.
    g_signal_emit_by_name (G_OBJECT (wire), "rotated", angle); // legacy
    g_signal_emit_by_name (G_OBJECT (wire), "changed");
}
Exemple #4
0
/**
 * \brief rotate an item by an @angle increment (may be negative)
 *
 * @angle the increment the item will be rotated (usually 90° steps)
 * @center_pos if rotated as part of a group, this is the center to rotate
 *around
 */
static void part_rotate (ItemData *data, int angle, Coords *center_pos)
{
	g_return_if_fail (data);
	g_return_if_fail (IS_PART (data));

	cairo_matrix_t morph, morph_rot, local_rot;
	Part *part;
	PartPriv *priv;
	gboolean handler_connected;
	// Coords b1, b2;

	part = PART (data);

	priv = part->priv;

	// FIXME store vanilla coords, apply the morph
	// FIXME to these and store the result in the
	// FIXME instance then everything will be fine
	// XXX also prevents rounding yiggle up downs

	angle /= 90;
	angle *= 90;

	cairo_matrix_init_rotate (&local_rot, (double)angle * M_PI / 180.);

	cairo_matrix_multiply (item_data_get_rotate (data), item_data_get_rotate (data), &local_rot);

	morph_rot = *(item_data_get_rotate (data));

	cairo_matrix_multiply (&morph, &morph_rot, item_data_get_translate (data));

	Coords delta_to_center, delta_to_center_transformed;
	Coords delta_to_apply, delta_bbox;
	Coords bbox_center, bbox_center_transformed;
	Coords item_pos;

// get bbox
#if 0 // this causes #115 to reappear
	item_data_get_relative_bbox (ITEM_DATA (part), &b1, &b2);
	bbox_center = coords_average (&b1, &b2);
#endif
	item_data_get_pos (ITEM_DATA (part), &item_pos);

	Coords rotation_center;

	if (center_pos == NULL) {
		rotation_center = coords_sum (&bbox_center, &item_pos);
	} else {
		rotation_center = *center_pos;
	}

	delta_to_center_transformed = delta_to_center = coords_sub (&rotation_center, &item_pos);
	cairo_matrix_transform_point (&local_rot, &(delta_to_center_transformed.x),
	                              &(delta_to_center_transformed.y));

	delta_to_apply = coords_sub (&delta_to_center, &delta_to_center_transformed);

#define DEBUG_THIS 0
	// use the cairo matrix funcs to transform the pin
	// positions relative to the item center
	// this is only indirectly related to displayin
	// HINT: we need to modify the actual pins to make the
	// pin tests work being used to detect connections

	gint i;
	gdouble x, y;
	// Rotate the pins.
	for (i = 0; i < priv->num_pins; i++) {
		x = priv->pins_orig[i].offset.x;
		y = priv->pins_orig[i].offset.y;
		cairo_matrix_transform_point (&morph_rot, &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_move (data, &delta_to_apply);

	handler_connected = g_signal_handler_is_connected (G_OBJECT (data), data->changed_handler_id);
	if (handler_connected) {
		g_signal_emit_by_name (G_OBJECT (data), "changed");
	} else {
		NG_DEBUG ("handler not yet registerd.");
	}
	NG_DEBUG ("\n\n");
}