Example #1
0
static gboolean create_textbox_event (Sheet *sheet, GdkEvent *event)
{
	switch (event->type) {
	case GDK_3BUTTON_PRESS:
	case GDK_2BUTTON_PRESS:
		return TRUE;

	case GDK_BUTTON_PRESS:
		if (event->button.button == 4 || event->button.button == 5)
			return FALSE;

		if (event->button.button == 1) {
			if (sheet->state == SHEET_STATE_TEXTBOX_WAIT)
				sheet->state = SHEET_STATE_TEXTBOX_START;

			return TRUE;
		} else
			return FALSE;

	case GDK_BUTTON_RELEASE:
		if (event->button.button == 4 || event->button.button == 5)
			return FALSE;

		if (sheet->state == SHEET_STATE_TEXTBOX_START) {
			Textbox *textbox;
			Coords pos;

			sheet->state = SHEET_STATE_NONE;

			sheet_get_pointer (sheet, &pos.x, &pos.y);
			textbox = textbox_new (NULL);

			textbox_set_text (textbox, _ ("Label"));

			item_data_set_pos (ITEM_DATA (textbox), &pos);
			schematic_add_item (schematic_view_get_schematic_from_sheet (sheet),
			                    ITEM_DATA (textbox));

			schematic_view_reset_tool (schematic_view_get_schematicview_from_sheet (sheet));
			g_signal_handlers_disconnect_by_func (G_OBJECT (sheet),
			                                      G_CALLBACK (create_textbox_event), sheet);
		}

		return TRUE;

	default:
		return FALSE;
	}

	return TRUE;
}
Example #2
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 #3
0
int    
sheet_motion_rubberband (Sheet *sheet, GdkEventMotion *event)
{
	static double width_old = 0, height_old = 0;
	double x, y;
	double height, width;
	
	double dx, dy;
	GList *list = NULL;
	SheetPos p1, p2;

    // Obtains the current pointer position and modifier state.
    // The position is given in coordinates relative to window.
	sheet_get_pointer (sheet, &x, &y);

	if (x < sheet->priv->rubberband->start_x) {
		width = sheet->priv->rubberband->start_x - x;
	}
	else {
		double tmp = x;
		x = sheet->priv->rubberband->start_x;
		width = tmp - sheet->priv->rubberband->start_x;
	}

	if (y < sheet->priv->rubberband->start_y) {
		height = sheet->priv->rubberband->start_y - y;
	}
	else {
		double tmp = y;
		y = sheet->priv->rubberband->start_y;
		height = tmp - sheet->priv->rubberband->start_y;
	}

	p1.x = x;
	p1.y = y;
	p2.x = x + width;
	p2.y = y + height;

	// Scroll the sheet if needed.
	// Need FIX
	/*{
		int width, height;
		int dx = 0, dy = 0;
		GtkAllocation allocation;
		
		sheet_get_pointer (sheet, &x, &y);

		gtk_widget_get_allocation (GTK_WIDGET (sheet), &allocation);
		width = allocation.width;
		height = allocation.height;

		if (_x < 0)
			dx = -1;
		else if (_x > width)
			dx = 1;

		if (_y < 0)
			dy = -1;
		else if (_y > height)
			dy = 1;

		if (!(_x > 0 && _x < width && _y > 0 && _y < height))
			sheet_scroll (sheet, dx * 5, dy * 5);
	}*/

	// Modify the rubberband rectangle if needed
	dx = fabs (width - width_old);
	dy = fabs (height - height_old);
	if (dx > 1.0 || dy > 1.0) {
		// Save old state
		width_old = width;
		height_old = height;

		for (list = sheet->priv->items; list; list = list->next) {
			sheet_item_select_in_area (list->data, &p1, &p2);
		}

		g_object_set (sheet->priv->rubberband->rectangle,
		              "x", (double) x, 
		              "y", (double) y,
		              "width", width, 
		              "height", height,
		              NULL);

		//g_list_free_full (list, g_object_unref); //FIXME
	}
	return TRUE;
}
Example #4
0
// Event handler for a "floating" group of objects.
int
sheet_item_floating_event (Sheet *sheet, const GdkEvent *event)
{
	SheetPriv *priv;
	GList *list;
	static Coords pos;
	static int keep = 0;

	// Remember the last position of the mouse cursor.
	static double last_x, last_y;

	// 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 != NULL, FALSE);
	g_return_val_if_fail (IS_SHEET (sheet), FALSE);
	g_return_val_if_fail (sheet->priv->floating_objects != NULL, FALSE);

	priv = sheet->priv;

	switch (event->type) {
	case GDK_BUTTON_RELEASE:
		g_signal_stop_emission_by_name (sheet, "event");
		break;

	case GDK_BUTTON_PRESS:
		if (sheet->state != SHEET_STATE_FLOAT)
			return TRUE;

		switch (event->button.button) {
		case 2:
		case 4:
		case 5:
			return FALSE;

		case 1:
			// do not free the floating items, but use them like a stamp
			keep = event->button.state & GDK_CONTROL_MASK;

			// Continue adding if CTRL is pressed
			if (!keep) {
				sheet->state = SHEET_STATE_NONE;
				g_signal_stop_emission_by_name (sheet, "event");
				if (g_signal_handler_is_connected (sheet, 
				    	sheet->priv->float_handler_id))
					g_signal_handler_disconnect (sheet, 
          				sheet->priv->float_handler_id);

				sheet->priv->float_handler_id = 0;
			}

			// Get pointer position in canvas coordinates
			sheet_get_pointer (sheet, &pos.x, &pos.y);
			
			for (list = priv->floating_objects; list; list = list->next) {
				SheetItem *floating_item;
				ItemData *floating_data;
				
				// Create a real item.
				floating_item = list->data;
				if (!keep) {
					floating_data = sheet_item_get_data (floating_item);
					g_object_set (floating_item,
					              "visibility", GOO_CANVAS_ITEM_INVISIBLE,
					              NULL);
				} else {
					floating_data = item_data_clone (sheet_item_get_data (floating_item));
				}
				g_object_ref (G_OBJECT (floating_data));

				item_data_set_pos (floating_data, &pos);
				schematic_add_item (schematic_view_get_schematic_from_sheet (sheet), floating_data);

				if (!keep)
					g_object_unref (G_OBJECT (floating_item));
			}

			if (keep) {
				g_object_set (G_OBJECT (sheet->priv->floating_group),
				              "x", pos.x,
				              "y", pos.y,
				              NULL);
			} else {
				g_list_free (sheet->priv->floating_objects);
				sheet->priv->floating_objects = NULL;
			}
			pos.x = 0.0; 
			pos.y = 0.0; 
			break;

		case 3:
			// Cancel the "float-placement" for button-3 clicks.
			g_signal_stop_emission_by_name (sheet, "event");
			sheet_item_cancel_floating (sheet);
			break;
		}
		break;

	case GDK_2BUTTON_PRESS:
	case GDK_3BUTTON_PRESS:
		g_signal_stop_emission_by_name (sheet, "event");
		return TRUE;

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

		g_signal_stop_emission_by_name (sheet, "event");

		if (sheet->state == SHEET_STATE_FLOAT_START) {
			sheet->state = SHEET_STATE_FLOAT;

			// Reparent the selected objects so that we can move them 
			// efficiently.
			for (list = priv->floating_objects; list; list = list->next) {
				sheet_item_reparent (SHEET_ITEM (list->data), 
				                     priv->floating_group);
				
				// Set the floating item visible
				g_object_set (G_OBJECT (list->data),
	              		  	  "visibility", GOO_CANVAS_ITEM_VISIBLE,
	              		      NULL);
			}	
			last_x = 0.0;
			last_y = 0.0;
		}

		// Get pointer position independantly of the zoom
		sheet_get_pointer (sheet, &snapped_x, &snapped_y);
			
		// Calculate which amount to move the selected objects by.
		dx = snapped_x - last_x;
		dy = snapped_y - last_y;
	
		last_x = snapped_x;
		last_y = snapped_y;

		for (list = priv->floating_objects; list; list = list->next) {
			goo_canvas_item_translate (GOO_CANVAS_ITEM (list->data),
			                           dx, dy);
		}	
		g_list_free_full (list, g_object_unref);
		break;

	case GDK_KEY_PRESS:
		switch (event->key.keyval) {
			case GDK_KEY_r:
			case GDK_KEY_R:
				sheet_rotate_ghosts (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);

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

					goo_canvas_item_translate (
					    GOO_CANVAS_ITEM (priv->floating_group), snapped_x, snapped_y);

                    last_x = snapped_x;
                    last_y = snapped_y;
				}
				break;
			default:
				return FALSE;
		}
	default:
		return FALSE;
	}
	return TRUE;
}
Example #5
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;
}
Example #6
0
// Event handler for a "floating" group of objects.
int sheet_item_floating_event (Sheet *sheet, const GdkEvent *event)
{
	SheetPriv *priv;
	GList *list;
	static gboolean keep = FALSE;

	// Remember the start position of the mouse cursor.
	static Coords last = {0., 0.};

	// Mouse cursor position in window coordinates, snapped to the grid spacing.
	static Coords snapped = {0., 0.};

	// Move the selected item(s) by this movement.
	Coords delta = {0., 0.};

	g_return_val_if_fail (sheet != NULL, FALSE);
	g_return_val_if_fail (IS_SHEET (sheet), FALSE);
	g_return_val_if_fail (sheet->priv->floating_objects != NULL, FALSE);

	priv = sheet->priv;

	switch (event->type) {
	case GDK_BUTTON_RELEASE:
		g_signal_stop_emission_by_name (sheet, "event");
		break;

	case GDK_BUTTON_PRESS:
		if (sheet->state != SHEET_STATE_FLOAT)
			return TRUE;

		switch (event->button.button) {
		case 2:
		case 4:
		case 5:
			return FALSE;

		case 1:
			// do not free the floating items, but use them like a stamp
			keep = event->button.state & GDK_CONTROL_MASK;

			// Continue adding if CTRL is pressed
			if (!keep) {
				sheet->state = SHEET_STATE_NONE;
				g_signal_stop_emission_by_name (sheet, "event");
				if (g_signal_handler_is_connected (sheet, sheet->priv->float_handler_id))
					g_signal_handler_disconnect (sheet, sheet->priv->float_handler_id);

				sheet->priv->float_handler_id = 0;
			}
			// FIXME assert that `Coords current` has been set by now!
			for (list = priv->floating_objects; list; list = list->next) {
				SheetItem *floating_item;
				ItemData *floating_data;

				// Create a real item.
				floating_item = list->data;
				if (!keep) {
					floating_data = sheet_item_get_data (floating_item);
					g_object_set (floating_item, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL);
				} else {
					// FIXME the bounding box of the clone is wrong
					floating_data = item_data_clone (sheet_item_get_data (floating_item));
				}
				g_object_ref (G_OBJECT (floating_data));

				NG_DEBUG ("Item Data Pos will be %lf %lf", snapped.x, snapped.y)

				item_data_set_pos (floating_data, &snapped);
				item_data_snap (floating_data, sheet->grid);

				schematic_add_item (schematic_view_get_schematic_from_sheet (sheet), floating_data);

				if (!keep)
					g_object_unref (G_OBJECT (floating_item));
			}

			if (keep) {
				g_object_set (G_OBJECT (priv->floating_group), "x", snapped.x, "y", snapped.y,
				              NULL);
			} else {
				g_list_free (priv->floating_objects);
				priv->floating_objects = NULL;
			}
			break;

		case 3:
			// Cancel the "float-placement" for button-3 clicks.
			g_signal_stop_emission_by_name (sheet, "event");
			sheet_item_cancel_floating (sheet);
			break;
		}
		break;

	case GDK_2BUTTON_PRESS:
	case GDK_3BUTTON_PRESS:
		g_signal_stop_emission_by_name (sheet, "event");
		return TRUE;

	case GDK_MOTION_NOTIFY:
// keep track of the position, as `sheet_get_pointer*()` does not work
// in other events than MOTION_NOTIFY
#if 0
		{
			Coords tmp;
			last = current;
			if (sheet_get_pointer (sheet, &tmp.x, &tmp.y)) {
				snapped_current = current = tmp;
				snap_to_grid (sheet->grid, &snapped_current.x, &snapped_current.y);
			}
		}
#endif
		if (sheet->state != SHEET_STATE_FLOAT && sheet->state != SHEET_STATE_FLOAT_START)
			return FALSE;

		g_signal_stop_emission_by_name (sheet, "event");

		// Get pointer position independantly of the zoom

		if (sheet->state == SHEET_STATE_FLOAT_START) {
			sheet->state = SHEET_STATE_FLOAT;
			last.x = last.y = 0.;
			// Reparent the selected objects so that we can move them
			// efficiently.
			for (list = priv->floating_objects; list; list = list->next) {
				sheet_item_reparent (SHEET_ITEM (list->data), priv->floating_group);
				// Set the floating item visible
				g_object_set (G_OBJECT (list->data), "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL);
			}
#if 0
			GooCanvasBounds box;
			goo_canvas_item_get_bounds (priv->floating_group, &box);
#endif
			NG_DEBUG ("\n\n\nFLOAT ### START\n\n\n\n");
		}

		sheet_get_pointer_snapped (sheet, &snapped.x, &snapped.y);

		delta = coords_sub (&snapped, &last);
		NG_DEBUG ("drag floating current      sx=%lf sy=%lf \n", snapped.x, snapped.y);
		NG_DEBUG ("drag floating last         lx=%lf ly=%lf \n", last.x, last.y);
		NG_DEBUG ("drag floating delta     -> dx=%lf dy=%lf \n", delta.x, delta.y);

#if !FIXME_INCREMENTAL_MOVMENT_DOES_NOT_WORK
		last = snapped;
#else
		goo_canvas_item_set_transform (GOO_CANVAS_ITEM (priv->floating_group), NULL);
#endif
		goo_canvas_item_translate (GOO_CANVAS_ITEM (priv->floating_group), delta.x, delta.y);

		break;

	case GDK_KEY_PRESS:
		switch (event->key.keyval) {
		case GDK_KEY_r:
		case GDK_KEY_R: {
			Coords bbdelta;
			GooCanvasBounds bounds;

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

			bbdelta.x = (bounds.x2 - bounds.x1) / 2.;
			bbdelta.y = (bounds.y2 - bounds.y1) / 2.;

			sheet_rotate_ghosts (sheet);

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

			bbdelta.x -= (bounds.x2 - bounds.x1) / 2.;
			bbdelta.y -= (bounds.y2 - bounds.y1) / 2.;

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

			goo_canvas_item_translate (GOO_CANVAS_ITEM (priv->floating_group), bbdelta.x,
			                           bbdelta.y);
		} break;
		default:
			return FALSE;
		}
	default:
		return FALSE;
	}
	return TRUE;
}