/*! * \brief Create a new diagram data object only containing the selected objects * \memberof _DiagramData */ DiagramData * diagram_data_clone_selected (DiagramData *data) { DiagramData *clone; Layer *dest_layer; GList *sorted; clone = g_object_new (DIA_TYPE_DIAGRAM_DATA, NULL); clone->extents = data->extents; clone->bg_color = data->bg_color; clone->paper = data->paper; /* so ugly */ clone->paper.name = g_strdup (data->paper.name); clone->is_compressed = data->is_compressed; /* the selection - if any - can only be on the active layer */ dest_layer = g_ptr_array_index(clone->layers, 0); g_free (dest_layer->name); dest_layer->name = layer_get_name (data->active_layer); sorted = data_get_sorted_selected (data); dest_layer->objects = object_copy_list (sorted); g_list_free (sorted); dest_layer->visible = data->active_layer->visible; dest_layer->connectable = data->active_layer->connectable; data_update_extents (clone); return clone; }
dia::Objects& dia::DiagramData::get_sorted_selected () const { if (_selected) delete _selected; static GList* list = data_get_sorted_selected(self); const_cast< DiagramData* >(this)->_selected = new dia::Objects (&list); return *_selected; }
static PyObject * PyDiaDiagramData_GetSortedSelected(PyDiaDiagramData *self, PyObject *args) { GList *list, *tmp; PyObject *ret; guint i, len; if (!PyArg_ParseTuple(args, ":DiagramData.get_sorted_selected")) return NULL; list = data_get_sorted_selected(self->data); len = g_list_length (list); ret = PyTuple_New(len); for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) PyTuple_SetItem(ret, i, PyDiaObject_New((DiaObject *)tmp->data)); g_list_free(list); return ret; }
GList * diagram_get_sorted_selected(Diagram *dia) { return data_get_sorted_selected(dia->data); }
/*! * \brief Calback function invoking layout algorithms from Dia's menu * \ingroup LayoutPlugin */ static ObjectChange * layout_callback (DiagramData *data, const gchar *filename, guint flags, /* further additions */ void *user_data, GraphCreateFunc func) { ObjectChange *changes = NULL; GList *nodes = NULL, *edges = NULL, *list; const char *algorithm = (const char*)user_data; /* from the selection create two lists */ list = data_get_sorted_selected (data); while (list) { DiaObject *o = (DiaObject *)list->data; if (!maybe_edge (o)) nodes = g_list_append (nodes, o); //FIXME: neither 1 nor num_handles-1 is guaranteed to be the second connection // it entirely depends on the objects implementation else if ( o->num_handles > 1 && o->handles[0]->connected_to && (o->handles[1]->connected_to || o->handles[o->num_handles-1]->connected_to)) edges = g_list_append (edges, o); list = g_list_next(list); } if (g_list_length (edges) < 1 || g_list_length (nodes) < 2) { message_warning (_("Please select edges and nodes to layout.")); } else { IGraph *g = func ? func () : NULL; if (!g) message_error (_("Graph creation failed")); else { std::vector<double> coords; /* transfer nodes and edges */ for (list = nodes; list != NULL; list = g_list_next(list)) { DiaObject *o = (DiaObject *)list->data; const Rectangle *bbox = dia_object_get_bounding_box (o); g->AddNode (bbox->left, bbox->top, bbox->right, bbox->bottom); } for (list = edges; list != NULL; list = g_list_next(list)) { DiaObject *o = (DiaObject *)list->data; DiaObject *src = o->handles[0]->connected_to->object; // see above: there is no guarantee ... DiaObject *dst = o->handles[1]->connected_to ? o->handles[1]->connected_to->object : o->handles[o->num_handles-1]->connected_to->object; if (_obj_get_bends (o, coords)) g->AddEdge (g_list_index (nodes, src), g_list_index (nodes, dst), &coords[0], coords.size()); else g->AddEdge (g_list_index (nodes, src), g_list_index (nodes, dst), NULL, 0); } IGraph::eResult res; if ((res = g->Layout (algorithm)) != IGraph::SUCCESS) { const char *sErr; switch (res) { case IGraph::NO_MODULE : sErr = _("No such module."); break; case IGraph::OUT_OF_MEMORY : sErr = _("Out of memory."); break; case IGraph::NO_TREE: sErr = _("Not a tree."); break; case IGraph::NO_FOREST: sErr = _("Not a forest."); break; case IGraph::FAILED_ALGORITHM: sErr = _("Failed algorithm."); break; case IGraph::FAILED_PRECONDITION: sErr = _("Failed precondition."); break; case IGraph::CRASHED : sErr = _("OGDF crashed."); break; default : sErr = _("Unknown reason"); break; } message_warning (_("Layout '%s' failed.\n%s"), (const char*)user_data, sErr); } else { changes = change_list_create (); /* transfer back information */ int n; for (n = 0, list = nodes; list != NULL; list = g_list_next (list), ++n) { Point pt; if (g->GetNodePosition (n, &pt.x, &pt.y)) { DiaObject *o = (DiaObject *)list->data; GPtrArray *props = g_ptr_array_new (); //FIXME: can't use "obj_pos", it is not read in usual update_data impementations // "elem_corner" will only work for Element derived classes, but that covers most // of the cases here ... prop_list_add_point (props, "elem_corner", &pt); change_list_add (changes, object_apply_props (o, props)); } } // first update to reuse the connected points diagram_update_connections_selection(DIA_DIAGRAM (data)); /* use edge bends, if any */ int e; for (e = 0, list = edges; list != NULL; list = g_list_next (list), ++e) { DiaObject *o = (DiaObject *)list->data; // number of bends / 2 is the number of points int n = g->GetEdgeBends (e, NULL, 0); if (n >= 0) { // with 0 it is just a reset of the exisiting line try { coords.resize (n); } catch (std::bad_alloc& ex) { g_warning ("%s", ex.what()); continue; } g->GetEdgeBends (e, &coords[0], n); change_list_add (changes, _obj_set_bends (o, coords)); } } /* update view */ diagram_update_connections_selection(DIA_DIAGRAM (data)); } g->Release (); } } g_list_free (nodes); g_list_free (edges); return changes; }