Example #1
0
/*
   When using the mouse wheel button to zoom in and out, it is more 
   intuitive to maintain the drawing zoom center-point based on the 
   cursor position. This can help orientation and prevent the drawing 
   from "jumping" around while zooming in and out.
 */
void
ddisplay_zoom_centered(DDisplay *ddisp, Point *point, real magnify)
{
  Rectangle *visible;
  real width, height;
  /* cursor position ratios */
  real rx,ry;

  if ((ddisp->zoom_factor <= DDISPLAY_MIN_ZOOM) && (magnify<=1.0))
    return;
  if ((ddisp->zoom_factor >= DDISPLAY_MAX_ZOOM) && (magnify>=1.0))
    return;

  visible = &ddisp->visible;

  /* calculate cursor position ratios */
  rx = (point->x-visible->left)/(visible->right - visible->left);
  ry = (point->y-visible->top)/(visible->bottom - visible->top);

  width = (visible->right - visible->left)/magnify;
  height = (visible->bottom - visible->top)/magnify;

  ddisp->zoom_factor *= magnify;

  /* set new origin based on the calculated ratios before zooming */
  ddisplay_set_origo(ddisp, point->x-(width*rx),point->y-(height*ry));

  ddisplay_update_scrollbars(ddisp);
  ddisplay_add_update_all(ddisp);
  ddisplay_flush(ddisp);

  update_zoom_status (ddisp);
}
Example #2
0
static PyObject *
PyDiaDisplay_Flush(PyDiaDisplay *self, PyObject *args)
{
    if (!PyArg_ParseTuple(args, ":Display.flush"))
	return NULL;
    ddisplay_flush(self->disp);
    Py_INCREF(Py_None);
    return Py_None;
}
Example #3
0
static void
interface_toggle_mainpoint_magnetism(GtkWidget *widget, gpointer data)
{
  DDisplay *ddisp = (DDisplay *)data;
  ddisplay_set_snap_to_objects(ddisp,
				   gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
  ddisplay_add_update_all(ddisp);
  ddisplay_flush(ddisp);
}
Example #4
0
static void
scroll_motion(ScrollTool *tool, GdkEventMotion *event,
	      DDisplay *ddisp)
{
  Point to;
  Point delta;

  /* set the cursor appropriately, and change use_hand if needed */
  if (!tool->scrolling) {
    /* try to minimise the number of cursor type changes */
    if ((event->state & GDK_SHIFT_MASK) != 0) {
      if (!tool->use_hand) {
	tool->use_hand = TRUE;
	if (!open_hand_cursor)
	  open_hand_cursor = create_cursor(ddisp->canvas->window,
					   hand_open_data_bits,
					   hand_open_data_width,
					   hand_open_data_height,
					   hand_open_mask_bits,
					   hand_open_data_width/2,
					   hand_open_data_height/2);
	ddisplay_set_all_cursor(open_hand_cursor);
      }
    } else
      if (tool->use_hand) {
	tool->use_hand = FALSE;
	ddisplay_set_all_cursor(scroll_cursor);
      }
    return;
  }

  ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);

  if (tool->use_hand) {
    delta = tool->last_pos;
    point_sub(&delta, &to);

    tool->last_pos = to;
    point_add(&tool->last_pos, &delta);

    /* we use this so you can scroll past the edge of the image */
    point_add(&delta, &ddisp->origo);
    ddisplay_set_origo(ddisp, delta.x, delta.y);
    ddisplay_update_scrollbars(ddisp);
    ddisplay_add_update_all(ddisp);
  } else {
    delta = to;
    point_sub(&delta, &tool->last_pos);
    point_scale(&delta, 0.5);

    ddisplay_scroll(ddisp, &delta);
    tool->last_pos = to;
  }
  ddisplay_flush(ddisp);
}
Example #5
0
static void
modify_button_press(ModifyTool *tool, GdkEventButton *event,
		     DDisplay *ddisp)
{
  Point clickedpoint;
  DiaObject *clicked_obj;
  gboolean some_selected;

  ddisplay_untransform_coords(ddisp,
			      (int)event->x, (int)event->y,
			      &clickedpoint.x, &clickedpoint.y);

  /* don't got to single handle movement if there is more than one object selected */
  some_selected = g_list_length (ddisp->diagram->data->selected) > 1;
  if (!some_selected && do_if_clicked_handle(ddisp, tool, &clickedpoint, event))
    return;

  clicked_obj = click_select_object(ddisp, &clickedpoint, event);
  if (!some_selected && do_if_clicked_handle(ddisp, tool, &clickedpoint, event))
    return;

  if ( clicked_obj != NULL ) {
    tool->state = STATE_MOVE_OBJECT;
    tool->object = clicked_obj;
    tool->move_compensate = clicked_obj->position;
    point_sub(&tool->move_compensate, &clickedpoint);
    tool->break_connections = TRUE; /* unconnect when not grabbing handles, just setting to
				      * FALSE is not enough. Need to refine the move op, too. */
    gdk_pointer_grab (gtk_widget_get_window(ddisp->canvas), FALSE,
                      GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
                      NULL, NULL, event->time);
    tool->start_at = clickedpoint;
    tool->start_time = time_micro();
    ddisplay_set_all_cursor_name (NULL, "move");
  } else {
    tool->state = STATE_BOX_SELECT;
    tool->start_box = clickedpoint;
    tool->end_box = clickedpoint;
    tool->x1 = tool->x2 = (int) event->x;
    tool->y1 = tool->y2 = (int) event->y;

    dia_interactive_renderer_set_selection (ddisp->renderer,
                                            TRUE,
                                            tool->x1,
                                            tool->y1,
                                            tool->x2 - tool->x1,
                                            tool->y2 - tool->y1);
    ddisplay_flush (ddisp);

    gdk_pointer_grab (gtk_widget_get_window (ddisp->canvas), FALSE,
                      GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
                      NULL, NULL, event->time);
  }
}
Example #6
0
/* Got when an area previously obscured need to be redrawn.
 * Needs GDK_EXPOSURE_MASK.
 * Gone with gtk+-3.0 or better replaced by "draw".
 */
static gboolean
canvas_expose_event (GtkWidget      *widget,
		     GdkEventExpose *event,
		     DDisplay       *ddisp)
{
  ddisplay_add_display_area (ddisp,
			     event->area.x, event->area.y,
			     event->area.x + event->area.width,
			     event->area.y + event->area.height);
  ddisplay_flush(ddisp);
  return FALSE;
}
Example #7
0
void
diagram_flush(Diagram *dia)
{
  GSList *l;
  DDisplay *ddisp;
  l = dia->displays;
  while (l!=NULL) {
    ddisp = (DDisplay *) l->data;

    ddisplay_flush(ddisp);
    
    l = g_slist_next(l);
  }
  dynobj_refresh_kick();
}
Example #8
0
/** Scroll display to where point x,y (window coords) is visible */
gboolean
ddisplay_autoscroll(DDisplay *ddisp, int x, int y)
{
  guint16 width, height;
  Point scroll;
  
  if (! ddisp->autoscroll)
    return FALSE;

  scroll.x = scroll.y = 0;

  width = GTK_WIDGET(ddisp->canvas)->allocation.width;
  height = GTK_WIDGET(ddisp->canvas)->allocation.height;

  if (x < 0)
  {
    scroll.x = x;
  }
  else if ( x > width)
  {
    scroll.x = x - width;
  }

  if (y < 0)
  {
    scroll.y = y;
  }
  else if (y > height)
  {
    scroll.y = y - height;
  }

  if ((scroll.x != 0) || (scroll.y != 0))
  {
    gboolean scrolled;

    scroll.x = ddisplay_untransform_length(ddisp, scroll.x);
    scroll.y = ddisplay_untransform_length(ddisp, scroll.y);

    scrolled = ddisplay_scroll(ddisp, &scroll);

    if (scrolled) {
      ddisplay_flush(ddisp);        
      return TRUE;
    }
  }
  return FALSE;
}
Example #9
0
void
ddisplay_show_all (DDisplay *ddisp)
{
  Diagram *dia;
  real magnify_x, magnify_y;
  int width, height;
  Point middle;

  g_return_if_fail (ddisp != NULL);
  
  dia = ddisp->diagram;

  width = dia_renderer_get_width_pixels (ddisp->renderer);
  height = dia_renderer_get_height_pixels (ddisp->renderer);

  /* if there is something selected show that instead of all exisiting objects */
  if (dia->data->selected) {
    GList *list = dia->data->selected;
    Rectangle extents = *dia_object_get_enclosing_box ((DiaObject*)list->data);
    list = g_list_next(list);
    while (list) {
      DiaObject *obj = (DiaObject *)list->data;
      rectangle_union(&extents, dia_object_get_enclosing_box (obj));
      list = g_list_next(list);
    }
    magnify_x = (real)width / (extents.right - extents.left) / ddisp->zoom_factor;
    magnify_y = (real)height / (extents.bottom - extents.top) / ddisp->zoom_factor;
    middle.x = extents.left + (extents.right - extents.left) / 2.0;
    middle.y = extents.top + (extents.bottom - extents.top) / 2.0;
  } else {
    magnify_x = (real)width /
      (dia->data->extents.right - dia->data->extents.left) / ddisp->zoom_factor;
    magnify_y = (real)height /
      (dia->data->extents.bottom - dia->data->extents.top) / ddisp->zoom_factor;

    middle.x = dia->data->extents.left +
      (dia->data->extents.right - dia->data->extents.left) / 2.0;
    middle.y = dia->data->extents.top +
      (dia->data->extents.bottom - dia->data->extents.top) / 2.0;
  }

  ddisplay_zoom (ddisp, &middle, 
		 ((magnify_x<magnify_y)?magnify_x:magnify_y)/1.05);

  ddisplay_update_scrollbars(ddisp);
  ddisplay_add_update_all(ddisp);
  ddisplay_flush(ddisp);
}
Example #10
0
void
ddisplay_resize_canvas(DDisplay *ddisp,
		       int width,  int height)
{
  if (ddisp->renderer==NULL) {
    if (ddisp->aa_renderer)
      ddisp->renderer = new_aa_renderer (ddisp);
    else
      ddisp->renderer = new_gdk_renderer(ddisp);
  }

  dia_renderer_set_size(ddisp->renderer, gtk_widget_get_window(ddisp->canvas), width, height);

  ddisplay_set_origo(ddisp, ddisp->origo.x, ddisp->origo.y);

  ddisplay_add_update_all(ddisp);
  ddisplay_flush(ddisp);
}
Example #11
0
void
ddisplay_zoom(DDisplay *ddisp, Point *point, real magnify)
{
  Rectangle *visible;
  real width, height, old_zoom;

  visible = &ddisp->visible;

  if ((ddisp->zoom_factor <= DDISPLAY_MIN_ZOOM) && (magnify<=1.0))
    return;
  if ((ddisp->zoom_factor >= DDISPLAY_MAX_ZOOM) && (magnify>=1.0))
    return;

  old_zoom = ddisp->zoom_factor;
  ddisp->zoom_factor = old_zoom * magnify;

  /* clip once more */
  if (ddisp->zoom_factor < DDISPLAY_MIN_ZOOM)
    ddisp->zoom_factor = DDISPLAY_MIN_ZOOM;
  else if (ddisp->zoom_factor > DDISPLAY_MAX_ZOOM)
    ddisp->zoom_factor = DDISPLAY_MAX_ZOOM;

  /* the real one used - after clipping */
  magnify = ddisp->zoom_factor / old_zoom;
  width = (visible->right - visible->left)/magnify;
  height = (visible->bottom - visible->top)/magnify;


  ddisplay_set_origo(ddisp, point->x - width/2.0, point->y - height/2.0);
  
  ddisplay_update_scrollbars(ddisp);
  ddisplay_add_update_all(ddisp);
  ddisplay_flush(ddisp);

  update_zoom_status (ddisp);
}
Example #12
0
static void
modify_button_release(ModifyTool *tool, GdkEventButton *event,
		      DDisplay *ddisp)
{
  Point *dest_pos, to;
  GList *list;
  int i;
  ObjectChange *objchange;

  tool->break_connections = FALSE;
  ddisplay_set_all_cursor(default_cursor);

  /* remove position from status bar */
  {
    GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status);
    guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
    gtk_statusbar_pop (statusbar, context_id);
  }
  switch (tool->state) {
  case STATE_MOVE_OBJECT:
    /* Return to normal state */
    gdk_pointer_ungrab (event->time);

    ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);
    if (!modify_move_already(tool, ddisp, &to)) {
      tool->orig_pos = NULL;
      tool->state = STATE_NONE;
      return;
    }

    diagram_update_connections_selection(ddisp->diagram);

    if (tool->orig_pos != NULL) {
      /* consider the non-selected children affected */
      list = parent_list_affected(ddisp->diagram->data->selected);
      dest_pos = g_new(Point, g_list_length(list));
      i=0;
      while (list != NULL) {
	DiaObject *obj = (DiaObject *)  list->data;
	dest_pos[i] = obj->position;
	list = g_list_next(list); i++;
      }

      undo_move_objects(ddisp->diagram, tool->orig_pos, dest_pos,
			parent_list_affected(ddisp->diagram->data->selected));
    }

    ddisplay_connect_selected(ddisp); /* pushes UNDO info */
    diagram_update_extents(ddisp->diagram);
    diagram_modified(ddisp->diagram);
    diagram_flush(ddisp->diagram);

    undo_set_transactionpoint(ddisp->diagram->undo);

    tool->orig_pos = NULL;
    tool->state = STATE_NONE;
    break;
  case STATE_MOVE_HANDLE:
    gdk_pointer_ungrab (event->time);
    tool->state = STATE_NONE;

    if (tool->orig_pos != NULL) {
      undo_move_handle(ddisp->diagram, tool->handle, tool->object,
		       *tool->orig_pos, tool->last_to, gdk_event_to_dia_ModifierKeys(event->state));
    }

    /* Final move: */
    object_add_updates(tool->object, ddisp->diagram);
    objchange = tool->object->ops->move_handle(tool->object, tool->handle,
					       &tool->last_to, NULL,
					       HANDLE_MOVE_USER_FINAL,gdk_event_to_dia_ModifierKeys(event->state));
    if (objchange != NULL) {
      undo_object_change(ddisp->diagram, tool->object, objchange);
    }

    object_add_updates(tool->object, ddisp->diagram);

    /* Connect if possible: */
    if (tool->handle->connect_type != HANDLE_NONCONNECTABLE) {
      object_connect_display(ddisp, tool->object, tool->handle, TRUE); /* pushes UNDO info */
      diagram_update_connections_selection(ddisp->diagram);
    }

    highlight_reset_all(ddisp->diagram);
    diagram_flush(ddisp->diagram);

    diagram_modified(ddisp->diagram);
    diagram_update_extents(ddisp->diagram);

    undo_set_transactionpoint(ddisp->diagram->undo);

    if (tool->orig_pos != NULL) {
      g_free(tool->orig_pos);
      tool->orig_pos = NULL;
    }

    break;
  case STATE_BOX_SELECT:

    gdk_pointer_ungrab (event->time);
    /* Remove last box: */
    dia_interactive_renderer_set_selection (ddisp->renderer,
                                            FALSE, 0, 0, 0, 0);

    {
      GList *list, *list_to_free;

      list = list_to_free = find_selected_objects(ddisp, tool);

      if (selection_style == SELECT_REPLACE &&
          !(event->state & GDK_SHIFT_MASK)) {
        /* Not Multi-select => Remove all selected */
        diagram_remove_all_selected(ddisp->diagram, TRUE);
      }

      if (selection_style == SELECT_INTERSECTION) {
        GList *intersection = NULL;

        while (list != NULL) {
          DiaObject *obj = (DiaObject *)list->data;

          if (diagram_is_selected(ddisp->diagram, obj)) {
            intersection = g_list_append(intersection, obj);
          }

          list = g_list_next(list);
        }
        list = intersection;
        diagram_remove_all_selected(ddisp->diagram, TRUE);
        while (list != NULL) {
          DiaObject *obj = (DiaObject *)list->data;

          diagram_select(ddisp->diagram, obj);

          list = g_list_next(list);
        }
        g_list_free(intersection);
      } else {
        while (list != NULL) {
          DiaObject *obj = (DiaObject *)list->data;

          if (selection_style == SELECT_REMOVE) {
            if (diagram_is_selected(ddisp->diagram, obj))
              diagram_unselect_object(ddisp->diagram, obj);
          } else if (selection_style == SELECT_INVERT) {
            if (diagram_is_selected(ddisp->diagram, obj))
              diagram_unselect_object(ddisp->diagram, obj);
            else
              diagram_select(ddisp->diagram, obj);
          } else {
            if (!diagram_is_selected(ddisp->diagram, obj))
              diagram_select(ddisp->diagram, obj);
          }

          list = g_list_next(list);
        }
      }

      g_list_free(list_to_free);

    }

    ddisplay_do_update_menu_sensitivity(ddisp);
    ddisplay_flush(ddisp);

    tool->state = STATE_NONE;
    break;
  case STATE_NONE:
    break;
  default:
    message_error("Internal error: Strange state in modify_tool\n");

  }
}
Example #13
0
static void
modify_motion (ModifyTool     *tool,
               GdkEventMotion *event,
               DDisplay       *ddisp)
{
  Point to;
  Point now, delta, full_delta;
  gboolean auto_scroll, vertical = FALSE;
  ConnectionPoint *connectionpoint = NULL;
  ObjectChange *objchange = NULL;

  ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);

  if (tool->state==STATE_NONE) {
    DiaObject *obj = NULL;
    Handle *handle = NULL;

    diagram_find_closest_handle (ddisp->diagram, &handle, &obj, &to);
    if  (handle && handle->type != HANDLE_NON_MOVABLE
      && handle->id >= HANDLE_RESIZE_NW && handle->id <= HANDLE_RESIZE_SE
      && handle_is_clicked(ddisp, handle, &to)
      && g_list_length (ddisp->diagram->data->selected) == 1)
      ddisplay_set_all_cursor (get_direction_cursor (CURSOR_DIRECTION_0 + handle->id));
    else
      ddisplay_set_all_cursor_name (NULL, "default");
    return; /* Fast path... */
  }
  auto_scroll = ddisplay_autoscroll(ddisp, event->x, event->y);

  if (!modify_move_already(tool, ddisp, &to)) return;

  switch (tool->state) {
  case STATE_MOVE_OBJECT:

    if (tool->orig_pos == NULL) {
      GList *list, *pla;
      int i;
      DiaObject *obj;

      /* consider non-selected children affected */
      pla = list = parent_list_affected(ddisp->diagram->data->selected);
      tool->orig_pos = g_new(Point, g_list_length(list));
      i=0;
      while (list != NULL) {
        obj = (DiaObject *)  list->data;
        tool->orig_pos[i] = obj->position;
        list = g_list_next(list); i++;
      }
      g_list_free (pla);
    }

    if (tool->break_connections)
      diagram_unconnect_selected(ddisp->diagram); /* Pushes UNDO info */

    if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) {
      full_delta = to;
      point_sub(&full_delta, &tool->start_at);
      vertical = (fabs(full_delta.x) < fabs(full_delta.y));
    }

    point_add(&to, &tool->move_compensate);
    snap_to_grid(ddisp, &to.x, &to.y);

    now = tool->object->position;

    delta = to;
    point_sub(&delta, &now);

    if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) {
      /* Up-down or left-right */
      if (vertical) {
       delta.x = tool->start_at.x + tool->move_compensate.x - now.x;
      } else {
       delta.y = tool->start_at.y + tool->move_compensate.y - now.y;
      }
    }

    object_add_updates_list(ddisp->diagram->data->selected, ddisp->diagram);
    objchange = object_list_move_delta(ddisp->diagram->data->selected, &delta);
    if (objchange != NULL) {
      undo_object_change(ddisp->diagram, tool->object, objchange);
    }
    object_add_updates_list(ddisp->diagram->data->selected, ddisp->diagram);

    object_add_updates(tool->object, ddisp->diagram);

    /* Put current mouse position in status bar */
    {
      gchar *postext;
      GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status);
      guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
      gtk_statusbar_pop (statusbar, context_id);
      postext = g_strdup_printf("%.3f, %.3f - %.3f, %.3f",
			        tool->object->bounding_box.left,
			        tool->object->bounding_box.top,
			        tool->object->bounding_box.right,
			        tool->object->bounding_box.bottom);

      gtk_statusbar_pop (statusbar, context_id);
      gtk_statusbar_push (statusbar, context_id, postext);

      g_free(postext);
    }

    diagram_update_connections_selection(ddisp->diagram);
    diagram_flush(ddisp->diagram);
    break;
  case STATE_MOVE_HANDLE:
    full_delta = to;
    point_sub(&full_delta, &tool->start_at);
    /* make sure resizing is restricted to its parent */

    /* if resize was blocked by parent, that means the resizing was
      outward, thus it won't bother the children so we don't have to
      check the children */
    if (!parent_handle_move_out_check(tool->object, &to))
      parent_handle_move_in_check(tool->object, &to, &tool->start_at);

    if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL)
      vertical = (fabs(full_delta.x) < fabs(full_delta.y));

    highlight_reset_all(ddisp->diagram);
    if ((tool->handle->connect_type != HANDLE_NONCONNECTABLE)) {
      /* Move to ConnectionPoint if near: */
      connectionpoint = object_find_connectpoint_display (ddisp,
                                                          &to,
                                                          tool->object, TRUE);
      if (connectionpoint != NULL) {
        DiaHighlightType type;
        to = connectionpoint->pos;
        if (connectionpoint->flags & CP_FLAGS_MAIN) {
          type = DIA_HIGHLIGHT_CONNECTIONPOINT_MAIN;
        } else {
          type = DIA_HIGHLIGHT_CONNECTIONPOINT;
        }
        highlight_object(connectionpoint->object, type, ddisp->diagram);
        ddisplay_set_all_cursor_name (NULL, "crosshair");
      }
    }
    if (connectionpoint == NULL) {
      /* No connectionopoint near, then snap to grid (if enabled) */
      snap_to_grid(ddisp, &to.x, &to.y);
      ddisplay_set_all_cursor_name (NULL, "move");
    }

    if (tool->break_connections) {
      /* break connections to the handle currently selected. */
      if (tool->handle->connected_to!=NULL) {
        Change *change = undo_unconnect (ddisp->diagram,
                                         tool->object,
                                         tool->handle);

        (change->apply)(change, ddisp->diagram);
      }
    }

    if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) {
      /* Up-down or left-right */
      if (vertical) {
       to.x = tool->start_at.x;
      } else {
       to.y = tool->start_at.y;
      }
    }

    if (tool->orig_pos == NULL) {
      tool->orig_pos = g_new(Point, 1);
      *tool->orig_pos = tool->handle->pos;
    }

    /* Put current mouse position in status bar */
    {
      gchar *postext;
      GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status);
      guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");

      if (tool->object) { /* play safe */
        real w = tool->object->bounding_box.right - tool->object->bounding_box.left;
        real h = tool->object->bounding_box.bottom - tool->object->bounding_box.top;
        postext = g_strdup_printf("%.3f, %.3f (%.3fx%.3f)", to.x, to.y, w, h);
      } else {
        postext = g_strdup_printf("%.3f, %.3f", to.x, to.y);
      }

      gtk_statusbar_pop (statusbar, context_id);
      gtk_statusbar_push (statusbar, context_id, postext);

      g_free(postext);
    }

    object_add_updates(tool->object, ddisp->diagram);

    /* Handle undo */
    if (tool->object)
      objchange = tool->object->ops->move_handle(tool->object, tool->handle,
					         &to, connectionpoint,
					         HANDLE_MOVE_USER, gdk_event_to_dia_ModifierKeys(event->state));
    if (objchange != NULL) {
      undo_object_change(ddisp->diagram, tool->object, objchange);
    }
    object_add_updates(tool->object, ddisp->diagram);

    diagram_update_connections_selection(ddisp->diagram);
    diagram_flush(ddisp->diagram);
    break;
  case STATE_BOX_SELECT:
    tool->end_box = to;

    ddisplay_transform_coords (ddisp,
                               MIN (tool->start_box.x, tool->end_box.x),
                               MIN (tool->start_box.y, tool->end_box.y),
                               &tool->x1, &tool->y1);
    ddisplay_transform_coords (ddisp,
                               MAX (tool->start_box.x, tool->end_box.x),
                               MAX (tool->start_box.y, tool->end_box.y),
                               &tool->x2, &tool->y2);

    dia_interactive_renderer_set_selection (ddisp->renderer,
                                            TRUE,
                                            tool->x1,
                                            tool->y1,
                                            tool->x2 - tool->x1,
                                            tool->y2 - tool->y1);
    ddisplay_flush (ddisp);

    break;
  case STATE_NONE:
    break;
  default:
    message_error("Internal error: Strange state in modify_tool\n");
  }

  tool->last_to = to;
  tool->auto_scrolled = auto_scroll;
}