Example #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.x = (b2.x + b1.x) / 2.;
	center.y = (b2.y + b1.y) / 2.;

	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);
}
Example #2
0
static void
rotate_items (Sheet *sheet, GList *items, gint angle)
{
	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 (item_data==NULL)
			continue;

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

		item_data_rotate (item_data, angle, &center);

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

	g_list_free (item_data_list);
}
Example #3
0
static void item_data_dispose (GObject *object)
{
	ItemDataPriv *priv = ITEM_DATA (object)->priv;
	// Remove the item from the sheet node store if there.
	if (priv->store) {
		item_data_unregister (ITEM_DATA (object));
	}
	g_slice_free (ItemDataPriv, priv);
	G_OBJECT_CLASS (item_data_parent_class)->dispose (object);
}
Example #4
0
static void move_items (Sheet *sheet, GList *items, const Coords *trans)
{
	GList *list;

	for (list = items; list; list = list->next) {
		g_assert (list->data != NULL);
		ItemData *item_data = sheet_item_get_data (list->data);
		g_assert (item_data != NULL);

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

		item_data_move (item_data, trans);

		if (sheet->state == SHEET_STATE_NONE)
			item_data_register (item_data);
	}
}
Example #5
0
static void
flip_items (Sheet *sheet, GList *items, IDFlip direction)
{
	GList *iter, *item_data_list;
	Coords center, b1, b2;
	Coords after;

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

	item_data_list_get_absolute_bbox (item_data_list, &b1, &b2);

	// FIXME center is currently not used by item_data_flip (part.c implentation)
	center.x = (b2.x + b1.x) / 2;
	center.y = (b2.y + b1.y) / 2;

	// FIXME - registering an item after flipping it still creates an offset as the position is still 0
	for (iter = item_data_list; iter; iter = iter->next) {
		ItemData *item_data = iter->data;

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

		item_data_flip (item_data, direction, &center);

		// Make sure we snap to grid.
		item_data_get_pos (item_data, &after);

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

		item_data_set_pos (item_data, &after);

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

	g_list_free (item_data_list);
}
Example #6
0
static void
flip_items (Sheet *sheet, GList *items, gboolean horizontal)
{
	GList *list, *item_data_list;
	SheetPos center, b1, b2;
	SheetPos after;

	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.x = (b2.x + b1.x) / 2;
	center.y = (b2.y + b1.y) / 2;

	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_flip (item_data, horizontal, &center);

		// Make sure we snap to grid.
		item_data_get_pos (item_data, &after);

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

		item_data_move (item_data, &after);

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

	g_list_free (item_data_list);
	g_list_free_full (list, g_object_unref);
}
Example #7
0
/**
 * remove a single item from the sheet
 */
void sheet_remove_item_in_sheet (SheetItem *item, Sheet *sheet)
{
	g_return_if_fail (sheet != NULL);
	g_return_if_fail (IS_SHEET (sheet));
	g_return_if_fail (item != NULL);
	g_return_if_fail (IS_SHEET_ITEM (item));

	sheet->priv->items = g_list_remove (sheet->priv->items, item);

	//  Remove the object from the selected-list before destroying.
	sheet_remove_selected_object (sheet, item);
	sheet_remove_floating_object (sheet, item);

	ItemData *data = sheet_item_get_data (item);
	g_return_if_fail (data != NULL);
	g_return_if_fail (IS_ITEM_DATA (data));

	// properly unregister the itemdata from the sheet
	item_data_unregister (data);
	// Destroy the item-data (model) associated to the sheet-item
	g_object_unref (data);
}
Example #8
0
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);
}
Example #9
0
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;
}
Example #10
0
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);
}
Example #11
0
// Event handler for a SheetItem
gboolean
sheet_item_event (GooCanvasItem *sheet_item,
		 GooCanvasItem *sheet_target_item,
		 GdkEvent *event, Sheet *sheet)
{
	// Remember the last position of the mouse cursor.
	static double last_x, last_y;
	GooCanvas *canvas;
	SheetPriv *priv;
	GList *list;
	// Mouse cursor position in window coordinates, snapped to the grid spacing.
	double snapped_x, snapped_y;
	// Move the selected item(s) by this movement.
	double dx, dy;
	
	
	g_return_val_if_fail (sheet_item != NULL, FALSE);
	g_return_val_if_fail (sheet != NULL, FALSE);

	priv = sheet->priv;

	canvas = GOO_CANVAS (sheet);
	
	switch (event->type) {
	case GDK_BUTTON_PRESS:
		// Grab focus to sheet for correct use of events
		gtk_widget_grab_focus (GTK_WIDGET (sheet));
		switch (event->button.button) {
		case 1:
			g_signal_stop_emission_by_name (sheet_item, "button_press_event");
			sheet->state = SHEET_STATE_DRAG_START;
			sheet_get_pointer (sheet, &last_x, &last_y);
			break;
		case 3:
			g_signal_stop_emission_by_name (sheet_item, "button_press_event");

			if (sheet->state != SHEET_STATE_NONE)
				return TRUE;

			// Bring up a context menu for right button clicks.
			if (!SHEET_ITEM (sheet_item)->priv->selected &&
				!((event->button.state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK))
					sheet_select_all (sheet, FALSE);

			sheet_item_select (SHEET_ITEM (sheet_item), TRUE);

			sheet_item_run_menu (SHEET_ITEM (sheet_item), sheet, 
			                     (GdkEventButton *) event);
			break;
		default:
			return FALSE;
		}
		break;

	case GDK_2BUTTON_PRESS:
		// Do not interfere with object dragging.
		if (sheet->state == SHEET_STATE_DRAG)
			return FALSE;

		switch (event->button.button) {
		case 1:
			if (sheet->state == SHEET_STATE_DRAG_START)
				sheet->state = SHEET_STATE_NONE;
			g_signal_stop_emission_by_name (sheet_item, "button_press_event");
			g_signal_emit_by_name (sheet_item, "double_clicked");
			break;

		default:
			return FALSE;
		}
		break;

	case GDK_3BUTTON_PRESS:
		g_signal_stop_emission_by_name (sheet_item, "button_press_event");
		return TRUE;

	case GDK_BUTTON_RELEASE:
		switch (event->button.button) {
		case 1:
			if (sheet->state != SHEET_STATE_DRAG &&
				sheet->state != SHEET_STATE_DRAG_START)
				return TRUE;

			g_signal_stop_emission_by_name (sheet_item, "button-release-event");

			if (sheet->state == SHEET_STATE_DRAG_START) {
				sheet->state = SHEET_STATE_NONE;

				if (!(event->button.state & GDK_SHIFT_MASK))
					sheet_select_all (sheet, FALSE);

				if (IS_SHEET_ITEM (sheet_item))
					sheet_item_select (SHEET_ITEM (sheet_item), TRUE);

				return TRUE;
			}

			// Get the mouse motion
			sheet_get_pointer (sheet, &snapped_x, &snapped_y);
			snapped_x -= last_x;
			snapped_y -= last_y;

			sheet->state = SHEET_STATE_NONE;
			goo_canvas_pointer_ungrab (canvas, GOO_CANVAS_ITEM (sheet_item),
			                           event->button.time);

			// Reparent the selected objects to the normal group
			// to have correct behaviour
			for (list = priv->selected_objects; list; list = list->next) {
            	sheet_item_reparent (SHEET_ITEM (list->data), 
	                                 sheet->object_group);
            }

			for (list = priv->selected_objects; list; list = list->next) {
            	ItemData *item_data;
				Coords pos;

                item_data = SHEET_ITEM (list->data)->priv->data;
				pos.x = snapped_x;
				pos.y = snapped_y;
				item_data_move (item_data, &pos);
                item_data_register (item_data);
            }
			g_list_free_full (list, g_object_unref);
				
			break;
		}
			
	case GDK_KEY_PRESS:
		switch (event->key.keyval) {
			case GDK_KEY_r:
				sheet_rotate_selection (sheet);
				{
					gdouble x, y;
					GooCanvasBounds bounds;
					
					sheet_get_pointer (sheet, &x, &y);

                    // Center the objects around the mouse pointer.
					goo_canvas_item_get_bounds (
						GOO_CANVAS_ITEM (priv->floating_group), &bounds);

					dx = x - (bounds.x1 + bounds.x2) / 2;
					dy = y - (bounds.y1 + bounds.y2) / 2;
                    snap_to_grid (sheet->grid, &dx, &dy);

					goo_canvas_item_translate (
						GOO_CANVAS_ITEM (priv->floating_group), dx, dy);

                    last_x = snapped_x;
                    last_y = snapped_y;
				}
				break;
			default:
				return FALSE;
		}
		return TRUE;

	case GDK_MOTION_NOTIFY:
		if (sheet->state != SHEET_STATE_DRAG &&
			sheet->state != SHEET_STATE_DRAG_START)
			return FALSE;

		if (sheet->state == SHEET_STATE_DRAG_START) {
			sheet->state = SHEET_STATE_DRAG;
			
			// Update the selection if needed. 
			if (IS_SHEET_ITEM (sheet_item)					&&
	    		(!SHEET_ITEM (sheet_item)->priv->selected))	{
				if (!(event->button.state & GDK_SHIFT_MASK)) {
					sheet_select_all (sheet, FALSE);
				}
				sheet_item_select (SHEET_ITEM (sheet_item), TRUE);
			}

			// Reparent the selected objects so that we can move them 
			// efficiently.
			for (list = priv->selected_objects; list; list = list->next) {
				ItemData *item_data;

				item_data = SHEET_ITEM (list->data)->priv->data;
				item_data_unregister (item_data);
				sheet_item_reparent (SHEET_ITEM (list->data), 
                                     priv->selected_group);
			}
			
			goo_canvas_pointer_grab (canvas, GOO_CANVAS_ITEM (sheet_item),
	    		GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
	    		NULL, 
	    		event->button.time);
		}

		// Set last_x & last_y to the pointer position
		sheet_get_pointer (sheet, &snapped_x, &snapped_y);

		dx = snapped_x - last_x;
		dy = snapped_y - last_y;
		
		// Check that we don't move outside the sheet... 
		// Horizontally: 
		/*
		if (cx1 <= 0) {  // leftmost edge 
			dx = dx - x1;
			snap_to_grid (sheet->grid, &dx, NULL);
			snapped_x = last_x + dx;
		} 
		else if (cx2 >= sheet_width) {  // rightmost edge 
			dx = dx - (x2 - sheet_width / priv->zoom);
			snap_to_grid (sheet->grid, &dx, NULL);
			snapped_x = last_x + dx;
		}

		// And vertically:
		if (cy1 <= 0) {  // upper edge
			dy = dy - y1;
			snap_to_grid (sheet->grid, NULL, &dy);
			snapped_y = last_y + dy;
		} 
		else if (cy2 >= sheet_height) {  // lower edge 
			dy = dy - (y2 - sheet_height / priv->zoom);
			snap_to_grid (sheet->grid, NULL, &dy);
			snapped_y = last_y + dy;
		}
		//last_x = snapped_x;
		//last_y = snapped_y;
		*/

		goo_canvas_item_set_transform (GOO_CANVAS_ITEM (priv->selected_group), 
		                               NULL);
		goo_canvas_item_translate (GOO_CANVAS_ITEM (priv->selected_group), 
			                       dx, dy);
		return TRUE;
	
	default:
		return FALSE;
	}
	return TRUE;
}