Beispiel #1
0
/*traverse the stack and return the magnetic field*/
int mcmagnet_get_field(double x, double y, double z, double t, double *bx,double *by, double *bz, void *dummy){
  mcmagnet_field_info *p=stack[0];
  Coords in,loc,b,bsum={0,0,0},zero={0,0,0};
  Rotation r;

  /*PROP_MAGNET takes care of transforming local "PROP" coordinates to lab system*/
  in.x=x;in.y=y;in.z=z;

  int i=0,stat=1;
  p=stack[i];
  *bx=0;*by=0;*bz=0;
  if (!p) return 0;
  //mcmagnet_print_stack();
  //printf("getfield_(lab):_(xyz,t)=( %g %g %g %g )\n",x,y,z,t);
  while(p){
    /*transform to the coordinate system of the particular magnetic function*/
    loc=coords_sub(rot_apply(*(p->rot),in),*(p->pos));
    stat=(p->func) (loc.x,loc.y,loc.z,t,&(b.x),&(b.y),&(b.z),p->data);
    /*check if the field function should be garbage collected*/
    //printf("getfield_(loc):_(xyz,t)=( %g %g %g %g )\n",loc.x,loc.y,loc.z,t);
    if (stat){
      /*transform to the lab system and add up. (resusing loc variable - to now contain the field in lab coords)*/
      rot_transpose(*(p->rot),r);
      loc=rot_apply(r,b);
      bsum.x+=loc.x;bsum.y+=loc.y;bsum.z+=loc.z;
      //printf("Bs=(%g %g %g), B=(%g %g %g)\n",bsum.x,bsum.y,bsum.z,loc.x,loc.y,loc.z);
    }
    if (p->stop) break;
    p=stack[++i];
  }
  /*we now have the magnetic field in lab coords in loc., transfer it back to caller*/
  *bx=bsum.x;
  *by=bsum.y;
  *bz=bsum.z;
  return 1;
}
Beispiel #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");
	}
}
Beispiel #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");
}
Beispiel #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 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;
}
Beispiel #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.
	GooCanvas *canvas;
	SheetPriv *priv;
	GList *list;

	static Coords last, current, snapped;
	// snapped : Mouse cursor position in window coordinates, snapped to the grid
	// spacing.
	// delta   : Move the selected item(s) by this movement.
	Coords delta;

	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;
			g_assert (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
			g_assert (sheet_get_pointer (sheet, &snapped.x, &snapped.y));
			delta = coords_sub (&snapped, &last);

			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;

				item_data = SHEET_ITEM (list->data)->priv->data;
				item_data_move (item_data, &delta);
				item_data_snap (item_data, sheet->grid);
				item_data_register (item_data);
			}
			break;
		}

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

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

			bbdelta.x = (bounds.x2 - bounds.x1) / 2.;
			bbdelta.y = (bounds.y2 - bounds.y1) / 2.;
#endif
			sheet_rotate_selection (sheet, 90);
#ifndef FIXME_STILL_MINI_OFFSET
			// Center the objects around the mouse pointer.
			goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (priv->selected_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->selected_group), bbdelta.x,
			                           bbdelta.y);
#endif
		} 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);

		delta = coords_sub (&snapped, &last);

// 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;
*/

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

	default:
		return FALSE;
	}
	return TRUE;
}
Beispiel #6
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");
}