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); }
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; }
/* 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; }
/* 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); } } }
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; }
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); }
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; }
/* 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); } }
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); }
/*! * \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); }