static ObjectChange * _textobj_convert_to_path_callback (DiaObject *obj, Point *clicked, gpointer data) { Textobj *textobj = (Textobj *)obj; const Text *text = textobj->text; DiaObject *path = NULL; if (!text_is_empty(text)) /* still screwed with empty lines ;) */ path = create_standard_path_from_text (text); if (path) { ObjectChange *change; Color bg = textobj->fill_color; /* FIXME: otherwise object_substitue() will tint the text with bg */ textobj->fill_color = text->color; change = object_substitute (obj, path); /* restore */ textobj->fill_color = bg; return change; } /* silently fail */ return change_list_create (); }
/*! * \brief Convert _StdPath to one or more _BezierLine/BezierGon */ static ObjectChange * _convert_to_beziers_callback (DiaObject *obj, Point *clicked, gpointer data) { StdPath *stdpath = (StdPath *)obj; BezPoint *bezier = stdpath->points; GList *list = NULL; int i, n = 0; ObjectChange *change; for (i = 1; i < stdpath->num_points; ++i) { if (bezier[i].type == BEZ_MOVE_TO || i+1 == stdpath->num_points) { DiaObject *rep; int num = bezier[i].type == BEZ_MOVE_TO ? i - n : i - n + 1; if (stdpath->stroke_or_fill & PDO_FILL) rep = create_standard_beziergon (num, &bezier[n]); else rep = create_standard_bezierline (num, &bezier[n], NULL, NULL); if (!rep) /* no Standard objects? */ break; list = g_list_append (list, rep); n = i; } } if (!list) { change = change_list_create (); } else if (g_list_length (list) == 1) { change = object_substitute (obj, (DiaObject *)list->data); g_list_free (list); } else { change = object_substitute (obj, create_standard_group (list)); } return change; }
static ObjectChange * _box_convert_to_path_callback (DiaObject *obj, Point *clicked, gpointer data) { const Box *box = (Box *)obj; const Element *elem = &box->element; DiaObject *path; int num_points; BezPoint *points; if (box->corner_radius > 0) { const real w = elem->width; const real h = elem->height; const real x = elem->corner.x; const real y = elem->corner.y; real r = box->corner_radius; num_points = 9; points = g_alloca (sizeof(BezPoint) * num_points); /* avoid r>w/w and r>h/2 */ r = (w > h ) ? (r > h/2 ? h/2 : r) : (r > w/2 ? w/2 : r); points[0].type = BEZ_MOVE_TO; points[0].p1.x = x + r; points[0].p1.y = y; /* top-left */ points[1].type = BEZ_LINE_TO; points[1].p1.x = x + w - r; points[1].p1.y = y; /* top-right */ points[2].type = BEZ_CURVE_TO; points[2].p1.x = x + w - r; points[2].p1.y = y; /* around */ points[2].p2.x = x + w; points[2].p2.y = y; points[2].p3.x = x + w; points[2].p3.y = y + r; points[3].type = BEZ_LINE_TO; points[3].p1.x = x + w; points[3].p1.y = y + h - r; /* bottom-right */ points[4].type = BEZ_CURVE_TO; points[4].p1.x = x + w; points[4].p1.y = y + h - r; /* around */ points[4].p2.x = x + w; points[4].p2.y = y + h; points[4].p3.x = x + w - r; points[4].p3.y = y + h; points[5].type = BEZ_LINE_TO; points[5].p1.x = x + r; points[5].p1.y = y + h; /* bottom-left */ points[6].type = BEZ_CURVE_TO; points[6].p1.x = x + r; points[6].p1.y = y + h; /* around */ points[6].p2.x = x; points[6].p2.y = y + h; points[6].p3.x = x; points[6].p3.y = y + h - r; points[7].type = BEZ_LINE_TO; points[7].p1.x = x; points[7].p1.y = y + r; /* top-left */ points[8].type = BEZ_CURVE_TO; points[8].p1.x = x; points[8].p1.y = y + r; /* around */ points[8].p2.x = x; points[8].p2.y = y; points[8].p3.x = x + r; points[8].p3.y = y; } else { num_points = 5; points = g_alloca (sizeof(BezPoint) * num_points); points[0].type = BEZ_MOVE_TO; points[0].p1 = elem->corner; points[1].type = points[2].type = points[3].type = points[4].type = BEZ_LINE_TO; points[1].p1.x = elem->corner.x + elem->width; points[1].p1.y = elem->corner.y; points[2].p1.x = elem->corner.x + elem->width; points[2].p1.y = elem->corner.y + elem->height; points[3].p1.x = elem->corner.x; points[3].p1.y = elem->corner.y + elem->height; points[4].p1 = elem->corner; } path = create_standard_path (num_points, points); if (path) return object_substitute (obj, path); /* Empty change */ return change_list_create (); }
/*! * \brief Convert _Beziergon to _Path * \memberof _Beziergon */ static ObjectChange * _beziergon_convert_to_path_callback (DiaObject *obj, Point *clicked, gpointer data) { Beziergon *beziergon = (Beziergon *) obj; BezierShape *bez = &beziergon->bezier; DiaObject *path = NULL; if (bez->bezier.num_points > 1) path = create_standard_path (bez->bezier.num_points, bez->bezier.points); if (path) return object_substitute (obj, path); /* just an empty change */ return change_list_create (); }
/*! * \brief Modification of the objects 'pattern' property * * @param object object to modify * @param pattern the pattern to set * @return an object change or NULL * * If the object does not have a pattern property nothing * happens. If there is a pattern property and the passed * in pattern is identical an empty change is returned. * * \memberof _DiaObject * \ingroup StdProps */ ObjectChange * dia_object_set_pattern (DiaObject *object, DiaPattern *pattern) { ObjectChange *change; GPtrArray *props; PatternProperty *pp; Property *prop = object_prop_by_name_type (object, "pattern", PROP_TYPE_PATTERN); if (!prop) return NULL; pp = (PatternProperty *)prop; if (pp->pattern == pattern) return change_list_create (); if (pp->pattern) g_object_unref (pp->pattern); pp->pattern = g_object_ref (pattern); props = prop_list_from_single (prop); change = object_apply_props (object, props); prop_list_free (props); return change; }
/*! * \brief Modification of the objects 'pixbuf' property * * @param object object to modify * @param pixbuf the pixbuf to set * @return an object change or NULL * * If the object does not have a pixbuf property nothing * happens. If there is a pixbuf property and the passed * in pixbuf is identical an empty change is returned. * * \memberof _DiaObject * \ingroup StdProps */ ObjectChange * dia_object_set_pixbuf (DiaObject *object, GdkPixbuf *pixbuf) { ObjectChange *change; GPtrArray *props; PixbufProperty *pp; Property *prop = object_prop_by_name_type (object, "pixbuf", PROP_TYPE_PIXBUF); if (!prop) return NULL; pp = (PixbufProperty *)prop; if (pp->pixbuf == pixbuf) return change_list_create (); if (pp->pixbuf) g_object_unref (pp->pixbuf); pp->pixbuf = g_object_ref (pixbuf); props = prop_list_from_single (prop); change = object_apply_props (object, props); prop_list_free (props); return change; }
/*! * \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; }
static int text_key_event(Focus *focus, guint keystate, guint keyval, const gchar *str, int strlen, ObjectChange **change) { Text *text; int return_val = FALSE; int row, i; const char *utf; gunichar c; *change = NULL; text = focus->text; switch(keyval) { case GDK_Up: case GDK_KP_Up: text->cursor_row--; if (text->cursor_row<0) text->cursor_row = 0; if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row)) text->cursor_pos = text_get_line_strlen(text, text->cursor_row); break; case GDK_Down: case GDK_KP_Down: text->cursor_row++; if (text->cursor_row >= text->numlines) text->cursor_row = text->numlines - 1; if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row)) text->cursor_pos = text_get_line_strlen(text, text->cursor_row); break; case GDK_Left: case GDK_KP_Left: if (keystate & GDK_CONTROL_MASK) text_move_cursor(text, WORD_START); else text->cursor_pos--; if (text->cursor_pos<0) text->cursor_pos = 0; break; case GDK_Right: case GDK_KP_Right: if (keystate & GDK_CONTROL_MASK) text_move_cursor(text, WORD_END); else text->cursor_pos++; if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row)) text->cursor_pos = text_get_line_strlen(text, text->cursor_row); break; case GDK_Home: case GDK_KP_Home: text->cursor_pos = 0; break; case GDK_End: case GDK_KP_End: text->cursor_pos = text_get_line_strlen(text, text->cursor_row); break; case GDK_Delete: case GDK_KP_Delete: return_val = text_delete_key_handler(focus, change); break; case GDK_BackSpace: return_val = TRUE; row = text->cursor_row; if (text->cursor_pos <= 0) { if (row > 0) { *change = text_create_change(text, TYPE_JOIN_ROW, 'Q', text_get_line_strlen(text, row-1), row-1, focus->obj); } else { return_val = FALSE; break; } } else { utf = text_get_line(text, row); for (i = 0; i < (text->cursor_pos - 1); i++) utf = g_utf8_next_char (utf); c = g_utf8_get_char (utf); *change = text_create_change (text, TYPE_DELETE_BACKWARD, c, text->cursor_pos - 1, text->cursor_row, focus->obj); } text_delete_backward(text); break; case GDK_Return: case GDK_KP_Enter: return_val = TRUE; *change = text_create_change(text, TYPE_SPLIT_ROW, 'Q', text->cursor_pos, text->cursor_row, focus->obj); text_split_line(text); break; case GDK_Shift_L: case GDK_Shift_R: case GDK_Control_L: case GDK_Control_R: case GDK_Alt_L: case GDK_Alt_R: case GDK_Meta_L: case GDK_Meta_R: return_val = FALSE; /* no text change for modifiers */ break; default: if (str || (strlen>0)) { if (str && *str == '\r') break; /* avoid putting junk into our string */ return_val = TRUE; *change = change_list_create(); for (utf = str; utf && *utf && strlen > 0 ; utf = g_utf8_next_char (utf), strlen--) { ObjectChange *step; c = g_utf8_get_char (utf); step = text_create_change (text, TYPE_INSERT_CHAR, c, text->cursor_pos, text->cursor_row, focus->obj); change_list_add (*change, step); text_insert_char (text, c); } } break; } return return_val; }