Пример #1
0
static void
move_objects_revert(struct MoveObjectsChange *change, Diagram *dia)
{
  GList *list;
  int i;
  DiaObject *obj;

  object_add_updates_list(change->obj_list, dia);

  list = change->obj_list;
  i=0;
  while (list != NULL) {
    obj = (DiaObject *)  list->data;
    
    obj->ops->move(obj, &change->orig_pos[i]);
    
    list = g_list_next(list); i++;
  }

  list = change->obj_list;
  while (list!=NULL) {
    obj = (DiaObject *) list->data;
    
    diagram_update_connections_object(dia, obj, TRUE);
    
    list = g_list_next(list);
  }

  object_add_updates_list(change->obj_list, dia);
}
Пример #2
0
static gint
properties_apply(GtkWidget *canvas, gpointer data)
{
  ObjectChange *obj_change = NULL;

  if ( (current_obj == NULL) || (current_dia == NULL) )
    return 0;
  
  object_add_updates(current_obj, current_dia);
  obj_change = current_obj->ops->apply_properties(current_obj);
  object_add_updates(current_obj, current_dia);

  diagram_update_connections_object(current_dia, current_obj, TRUE);
  
  if (obj_change != NULL) {
    undo_object_change(current_dia, current_obj, obj_change);
  }
  
  diagram_modified(current_dia);

  diagram_update_extents(current_dia);
    
  if (obj_change != NULL) {
    undo_set_transactionpoint(current_dia->undo);
  }  else {
    message_warning(_("This object doesn't support Undo/Redo.\n"
		      "Undo information erased."));
    undo_clear(current_dia->undo);
  }

  diagram_flush(current_dia);

  return 0;
}
Пример #3
0
/* Match and replace property values. */
static gboolean
_replace (DiaObject *obj, const SearchData *sd, const char *replacement)
{
  ObjectChange *obj_change;
  GPtrArray *plist = NULL;

  plist = _match_props (obj, sd, replacement);
  if (!plist)
    return FALSE;

  /* Refresh screen and free the list of modified properties. */
  obj_change = object_apply_props (obj, plist);
  prop_list_free (plist);

  if (obj_change)
    undo_object_change(sd->diagram, obj, obj_change);
    
  object_add_updates(obj, sd->diagram);
  diagram_update_connections_object(sd->diagram, obj, TRUE);
  diagram_modified(sd->diagram);
  diagram_object_modified(sd->diagram, obj);
  diagram_update_extents(sd->diagram);
  diagram_flush(sd->diagram);
  
  return TRUE;
}
Пример #4
0
/* Updates all objects connected to the 'obj' object.
   Calls this function recursively for objects modified.
   
   If update_nonmoved is TRUE, also objects that have not
   moved since last time is updated. This is not propagated
   in the recursion.
 */
void
diagram_update_connections_object(Diagram *dia, DiaObject *obj,
				  int update_nonmoved)
{
  int i,j;
  ConnectionPoint *cp;
  GList *list;
  DiaObject *connected_obj;
  Handle *handle;

  for (i=0;i<dia_object_get_num_connections(obj);i++) {
    cp = obj->connections[i];
    if ((update_nonmoved) ||
	(distance_point_point_manhattan(&cp->pos, &cp->last_pos) > CHANGED_TRESHOLD)) {
      cp->last_pos = cp->pos;

      list = cp->connected;
      while (list!=NULL) {
	connected_obj = (DiaObject *) list->data;

	object_add_updates(connected_obj, dia);
	handle = NULL;
	for (j=0;j<connected_obj->num_handles;j++) {
	  if (connected_obj->handles[j]->connected_to == cp) {
	    handle = connected_obj->handles[j];
	    connected_obj->ops->move_handle(connected_obj, handle, &cp->pos,
					    cp, HANDLE_MOVE_CONNECTED,0);
	  }
	}
	object_add_updates(connected_obj, dia);

	diagram_update_connections_object(dia, connected_obj, FALSE);
	
	list = g_list_next(list);
      }
    }
  }
  if (obj->children) {
    GList *child;
    for (child = obj->children; child != NULL; child = child->next) {
      DiaObject *child_obj = (DiaObject *)child->data;
      diagram_update_connections_object(dia, child_obj, update_nonmoved);
    }    
  }
}
Пример #5
0
static gint
properties_respond(GtkWidget *widget,
                   gint       response_id,
                   gpointer   data)
{
  ObjectChange *obj_change = NULL;
  gboolean set_tp = TRUE;
  GList *tmp;

  if (   response_id == GTK_RESPONSE_APPLY
      || response_id == GTK_RESPONSE_OK) {
    if ((current_objects != NULL) && (current_dia != NULL)) {
      object_add_updates_list(current_objects, current_dia);

      for (tmp = current_objects; tmp != NULL; tmp = tmp->next) {
	DiaObject *current_obj = (DiaObject*)tmp->data;
	obj_change = current_obj->ops->apply_properties_from_dialog(current_obj, object_part);
	object_add_updates(current_obj, current_dia);
	diagram_update_connections_object(current_dia, current_obj, TRUE);

	if (obj_change != NULL) {
	  undo_object_change(current_dia, current_obj, obj_change);
	  set_tp = set_tp && TRUE;
	} else
	  set_tp = FALSE;

	diagram_object_modified(current_dia, current_obj);
      }

      diagram_modified(current_dia);
      diagram_update_extents(current_dia);

      if (set_tp) {
	undo_set_transactionpoint(current_dia->undo);
      }  else {
	message_warning(_("This object doesn't support Undo/Redo.\n"
  			"Undo information erased."));
	undo_clear(current_dia->undo);
      }

      diagram_flush(current_dia);
    }
  }

  if (response_id != GTK_RESPONSE_APPLY) {
#ifdef G_OS_WIN32
    /* on windows we are not hiding the dialog, because shrinking when hidden does
     * not work (the dialog shows up with the same size as before, bug #333751) */
    gtk_widget_destroy (dialog);
#else
    properties_dialog_hide();
#endif
  }

  return 0;
}
Пример #6
0
static void
move_handle_revert(struct MoveHandleChange *change, Diagram *dia)
{
  object_add_updates(change->obj, dia);
  change->obj->ops->move_handle(change->obj, change->handle,
				&change->orig_pos, NULL,
				HANDLE_MOVE_USER_FINAL, 0);
  object_add_updates(change->obj, dia);
  diagram_update_connections_object(dia, change->obj, TRUE);
}
Пример #7
0
static PyObject *
PyDiaDiagram_UpdateConnections(PyDiaDiagram *self, PyObject *args)
{
    PyDiaObject *obj;

    if (!PyArg_ParseTuple(args, "O!:Diagram.update_connections",
                          &PyDiaObject_Type, &obj))
	return NULL;
    diagram_update_connections_object(self->dia, obj->object, TRUE);
    Py_INCREF(Py_None);
    return Py_None;
}
Пример #8
0
/* run diagram_update_connections_object on all selected objects. */
void
diagram_update_connections_selection(Diagram *dia)
{
  GList *list = dia->data->selected;

  while (list!=NULL) {
    DiaObject * selected_obj = (DiaObject *) list->data;
    
    diagram_update_connections_object(dia, selected_obj, TRUE);
    
    list = g_list_next(list);
  }
}
Пример #9
0
static void
object_change_revert(struct ObjectChangeChange *change,
		     Diagram *dia)
{
  object_add_updates(change->obj, dia);
  change->obj_change->revert(change->obj_change, change->obj);
  { /* Make sure object updates its data: */
    Point p = change->obj->position;
    (change->obj->ops->move)(change->obj,&p);
  }
  object_add_updates(change->obj, dia);
  
  diagram_update_connections_object(dia, change->obj, TRUE);

  properties_update_if_shown(dia, change->obj);
}
Пример #10
0
/*!
 * \brief Align objects at their connected points
 *
 * The result of the algorithm depends on the order of objects
 * in the list. The list is typically coming from the selection.
 * That order depends on the kind of selection performed.
 *  - selection by rubberband gives objects in reverse order of
 *    the the original layer order as of this writing
 *  - Select/Transitive lets the order follow the connection order,
 *    but still reversed due data_select() prepending
 *  - Step-wise manual selection would also be in reverse order
 * So it appears to be a good idea to reverse the processing order
 * In this function to minimize surpise.
 *
 * The result also currently depends on the direction of the connections.
 * When aligning two objects the one connected with HANDLE_MOVE_ENDPOINT
 * will be moved. This might be contradictory to the selection order.
 *
 * @param objects  selection of objects to be considered
 * @param dia      the diagram owning the objects (and holding undo information)
 * @param align    unused
 */
void
object_list_align_connected (GList *objects, Diagram *dia, int align)
{
    GList *list;
    Point *orig_pos;
    Point *dest_pos;
    DiaObject *obj, *o2;
    int i, nobjs;
    GList *connected = NULL;
    GList *to_be_moved = NULL;
    GList *movelist = NULL;

    /* find all elements to be moved directly */
    filter_connected (objects, 2, &connected, &to_be_moved);
    dia_log_message ("Moves %d - Connections %d\n", g_list_length (to_be_moved), g_list_length (connected));
    /* for every connection check:
     * - "matching" directions of both object connection points (this also gives
     *    the direction of the move of the second object)
     * -
     * - move every object only once
     */
    nobjs = g_list_length (to_be_moved);
    orig_pos = g_new (Point, nobjs);
    dest_pos = g_new (Point, nobjs);

    list = g_list_reverse (connected);
    while (list != NULL) {
        DiaObject *con = list->data;
        Handle *h1 = NULL, *h2 = NULL;

        g_assert (con->num_handles >= 2);
        for (i = 0; i < con->num_handles; ++i) {
            if (con->handles[i]->id == HANDLE_MOVE_STARTPOINT)
                h1 = con->handles[i];
            else if (con->handles[i]->id == HANDLE_MOVE_ENDPOINT)
                h2 = con->handles[i];
        }
        /* should this be an assert? */
        if (h1 && h2 && h1->connected_to && h2->connected_to) {
            ConnectionPoint *cps = h1->connected_to;
            ConnectionPoint *cpe = h2->connected_to;

            obj = cps->object;
            o2 = cpe->object;
            /* swap alignment direction if we are working backwards by the selection order */
            if (g_list_index (to_be_moved, obj) < g_list_index (to_be_moved, o2)) {
                DiaObject *otmp = o2;
                ConnectionPoint *cptmp = cpe;
                o2 = obj;
                obj = otmp;
                cpe = cps;
                cps = cptmp;
            }
            if (   !g_list_find (movelist, o2)
                    && g_list_find(to_be_moved, o2) && g_list_find(to_be_moved, obj)) {
                Point delta = {0, 0};
                /* If we haven't moved it yet, check if we want to */
                int hweight = 0;
                int vweight = 0;
                if (cps->directions == DIR_NORTH || cps->directions == DIR_SOUTH)
                    ++vweight;
                else if (cps->directions == DIR_EAST || cps->directions == DIR_WEST)
                    ++hweight;
                if (cpe->directions == DIR_NORTH || cpe->directions == DIR_SOUTH)
                    ++vweight;
                else if (cpe->directions == DIR_EAST || cpe->directions == DIR_WEST)
                    ++hweight;

                /* One clear directions is required to move at all */
                if (vweight > hweight) {
                    /* horizontal move */
                    delta.x = cps->pos.x - cpe->pos.x;
                } else if (hweight > vweight) {
                    /* vertical move */
                    delta.y = cps->pos.y - cpe->pos.y;
                } else {
                    /* would need more context */
                    char dirs[] = "NESW";
                    int j;
                    for (j = 0; j < 4; ++j) if (cps->directions & (1<<j)) g_print ("%c", dirs[j]);
                    g_print ("(%s) -> ", obj->type->name);
                    for (j = 0; j < 4; ++j) if (cpe->directions & (1<<j)) g_print ("%c", dirs[j]);
                    g_print ("(%s)\n", o2->type->name);
                }
                if (delta.x != 0.0 || delta.y != 0) {
                    Point pos = o2->position;

                    point_add (&pos, &delta);

                    i = g_list_length (movelist);
                    orig_pos[i] = o2->position;
                    dest_pos[i] = pos;

                    dia_log_message ("Move '%s' by %g,%g\n", o2->type->name, delta.x, delta.y);
#if 0
                    o2->ops->move (o2, &pos);
#else
                    {
                        GList *move_list = g_list_append (NULL, o2);
                        object_list_move_delta (move_list, &delta);
                        g_list_free (move_list);
                    }
#endif
                    diagram_update_connections_object (dia, o2, TRUE);
                    movelist = g_list_append (movelist, o2);
                }
            }
        }

        list = g_list_next (list);
    }

    /* eating all the passed in parameters */
    undo_move_objects (dia, orig_pos, dest_pos, movelist);
    g_list_free (to_be_moved);
    g_list_free (connected);
}