[dia] path: add "<Selection>/Convert to Path" context menu entry
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] path: add "<Selection>/Convert to Path" context menu entry
- Date: Sat, 20 Jul 2013 22:26:39 +0000 (UTC)
commit 67d056f1415432ae8d62f504e50ba4ba2965b60e
Author: Hans Breuer <hans breuer org>
Date: Sat Jul 20 20:18:26 2013 +0200
path: add "<Selection>/Convert to Path" context menu entry
and fix some path segment ordering issue with the path
renderer as well as "Standard - Path" property setting.
app/disp_callbacks.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-
lib/diapathrenderer.c | 36 ++++++++++++++++++++++++-----
lib/standard-path.c | 32 ++++++++++++++++++++++----
3 files changed, 114 insertions(+), 13 deletions(-)
---
diff --git a/app/disp_callbacks.c b/app/disp_callbacks.c
index b5e25d5..088420b 100644
--- a/app/disp_callbacks.c
+++ b/app/disp_callbacks.c
@@ -46,6 +46,7 @@
#include "dia_dirs.h"
#include "object.h"
#include "disp_callbacks.h"
+#include "create.h"
typedef struct {
GdkEvent *event; /* Button down event which may be holding */
@@ -163,17 +164,67 @@ _follow_link_callback (GtkAction *action, gpointer data)
static void
add_follow_link_menu_item (GtkMenu *menu)
{
- GtkWidget *menu_item = gtk_menu_item_new_with_label(_("Follow linkā¦"));
+ GtkWidget *menu_item = gtk_menu_item_new_with_label(_("Follow link\342\200\246"));
g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(_follow_link_callback), NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
gtk_widget_show(menu_item);
}
+
+static void
+_convert_to_path_callback (GtkAction *action, gpointer data)
+{
+ DiaObject *obj;
+ DDisplay *ddisp = ddisplay_active();
+ GList *selected, *list;
+ ObjectChange *change_list = NULL;
+
+ if (!ddisp) return;
+
+ /* copy the list before modifying it */
+ list = selected = diagram_get_sorted_selected (ddisp->diagram);
+ while (list) {
+ DiaObject *obj = (DiaObject *)list->data;
+
+ if (obj) { /* paranoid */
+ DiaObject *path = create_standard_path_from_object (obj);
+
+ if (path) { /* not so paranoid */
+ ObjectChange *change = object_substitute (obj, path);
+
+ if (!change_list)
+ change_list = change_list_create ();
+ if (change)
+ change_list_add (change_list, change);
+ }
+ }
+ list = g_list_next(list);
+ }
+ g_list_free (selected);
+ if (change_list) {
+ undo_object_change(ddisp->diagram, NULL, change_list);
+
+ diagram_modified(ddisp->diagram);
+ diagram_update_extents(ddisp->diagram);
+
+ undo_set_transactionpoint(ddisp->diagram->undo);
+ diagram_flush(ddisp->diagram);
+ }
+}
+static void
+add_convert_to_path_menu_item (GtkMenu *menu)
+{
+ GtkWidget *menu_item = gtk_menu_item_new_with_label(_("Convert to Path"));
+ g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(_convert_to_path_callback), NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+ gtk_widget_show(menu_item);
+}
static void
create_object_menu(DiaMenu *dia_menu, gboolean root_menu)
{
int i;
GtkWidget *menu;
GtkWidget *menu_item;
+ gboolean native_convert_to_path = FALSE;
menu = gtk_menu_new();
@@ -192,6 +243,10 @@ create_object_menu(DiaMenu *dia_menu, gboolean root_menu)
for (i=0;i<dia_menu->num_items;i++) {
DiaMenuItem *item = &dia_menu->items[i];
+ /* HACK: rely on object menu naming convention to avoid duplicated menu entry/functionality */
+ if (item->text && strcmp (item->text, "Convert to Path") == 0)
+ native_convert_to_path = TRUE;
+
if (item->active & DIAMENU_TOGGLE) {
if (item->text)
menu_item = gtk_check_menu_item_new_with_label(gettext(item->text));
@@ -231,6 +286,8 @@ create_object_menu(DiaMenu *dia_menu, gboolean root_menu)
/* Finally add a Properties... menu item for objects*/
add_properties_menu_item(GTK_MENU (menu), i > 0);
add_follow_link_menu_item(GTK_MENU (menu));
+ if (!native_convert_to_path)
+ add_convert_to_path_menu_item(GTK_MENU (menu));
}
dia_menu->app_data = menu;
diff --git a/lib/diapathrenderer.c b/lib/diapathrenderer.c
index 2eea0b9..04380df 100644
--- a/lib/diapathrenderer.c
+++ b/lib/diapathrenderer.c
@@ -139,6 +139,15 @@ static void
end_render(DiaRenderer *self)
{
}
+static gboolean
+is_capable_to (DiaRenderer *renderer, RenderCapability cap)
+{
+ if (RENDER_HOLES == cap)
+ return TRUE;
+ else if (RENDER_ALPHA == cap)
+ return TRUE;
+ return FALSE;
+}
static void
set_linewidth(DiaRenderer *self, real linewidth)
{ /* 0 == hairline **/
@@ -344,18 +353,24 @@ _arc (DiaRenderer *self,
GArray *path = _get_current_path (renderer, stroke, fill);
Point start;
real radius = sqrt(width * height) / 2.0;
- real ar1 = (M_PI / 180.0) * angle1;
- real ar2 = (M_PI / 180.0) * angle2;
+ real ar1;
+ real ar2;
int i, segs;
real ars;
-
+
+ while (angle1 > angle2)
+ angle1 -= 360;
+
+ ar1 = (M_PI / 180.0) * angle2;
+ ar2 = (M_PI / 180.0) * angle1;
/* one segment for ever 90 degrees */
segs = (int)(fabs(ar2 - ar1) / (M_PI/2)) + 1;
ars = - (ar2 - ar1) / segs;
/* move to start point */
- start.x = center->x + (width / 2.0) * cos(ar1);
+ start.x = center->x + (width / 2.0) * cos(ar1);
start.y = center->y - (height / 2.0) * sin(ar1);
+
/* Dia and Cairo don't agree on arc definitions, so it needs
* to be converted, i.e. mirrored at the x axis
*/
@@ -478,9 +493,15 @@ _bezier (DiaRenderer *self,
{
DiaPathRenderer *renderer = DIA_PATH_RENDERER (self);
GArray *path = _get_current_path (renderer, stroke, fill);
- int i;
+ int i = 0;
- for (i = 0; i < numpoints; ++i)
+ /* get rid of the first move-to if we can attach to the previous point */
+ if (path->len > 0) {
+ BezPoint *bp = &g_array_index (path, BezPoint, path->len-1);
+ if (distance_point_point(&bp->p3, &points[0].p1) < 0.001)
+ i = 1;
+ }
+ for (i; i < numpoints; ++i)
g_array_append_val (path, points[i]);
if (fill)
_path_lineto (path, &points[0].p1);
@@ -640,7 +661,8 @@ dia_path_renderer_class_init (DiaPathRendererClass *klass)
renderer_class->draw_bezier = draw_bezier;
renderer_class->fill_bezier = fill_bezier;
renderer_class->draw_text = draw_text;
-
+ /* other */
+ renderer_class->is_capable_to = is_capable_to;
}
#include "object.h"
diff --git a/lib/standard-path.c b/lib/standard-path.c
index 26efbff..896fdec 100644
--- a/lib/standard-path.c
+++ b/lib/standard-path.c
@@ -37,6 +37,7 @@
#include "diarenderer.h"
#include "attributes.h"
#include "properties.h"
+#include "propinternals.h"
#include "boundingbox.h"
#include "standard-path.h"
#include "create.h"
@@ -185,6 +186,7 @@ static void stdpath_destroy (StdPath *stdpath);
static DiaObject *stdpath_copy (StdPath *stdpath);
static DiaMenu *stdpath_get_object_menu(StdPath *stdpath,
Point *clickedpoint);
+static void stdpath_get_props(StdPath *stdpath, GPtrArray *props);
static void stdpath_set_props(StdPath *stdpath, GPtrArray *props);
static ObjectOps stdpath_ops = {
@@ -199,7 +201,7 @@ static ObjectOps stdpath_ops = {
(ApplyPropertiesDialogFunc) object_apply_props_from_dialog,
(ObjectMenuFunc) stdpath_get_object_menu,
(DescribePropsFunc) object_describe_props,
- (GetPropsFunc) object_get_props,
+ (GetPropsFunc) stdpath_get_props,
(SetPropsFunc) stdpath_set_props,
(TextEditFunc) 0,
(ApplyPropertiesListFunc) object_apply_props,
@@ -484,18 +486,38 @@ stdpath_get_object_menu(StdPath *stdpath, Point *clickedpoint)
return &_stdpath_menu;
}
/*!
+ * \brief Initialize the given property vector from the object state.
+ *
+ * If offsets and props are part of the object type this does not to be
+ * implemented usually. Just object_get_props in the 'vtable' would be enough.
+ * We want to ensure that stroke_or_fill and show_background are in sync, though.
+ */
+static void
+stdpath_get_props(StdPath *stdpath, GPtrArray *props)
+{
+ stdpath->show_background = (stdpath->stroke_or_fill & PDO_FILL) != 0;
+ object_get_props(&stdpath->object, props);
+}
+/*!
* \brief Set the object state from the given proeprty vector
* \memberof StdPath
*/
static void
stdpath_set_props (StdPath *stdpath, GPtrArray *props)
{
+ Property *prop;
stdpath->show_background = (stdpath->stroke_or_fill & PDO_FILL) != 0;
object_set_props_from_offsets(&stdpath->object, stdpath_offsets, props);
- if (stdpath->show_background)
- stdpath->stroke_or_fill |= PDO_FILL;
- else
- stdpath->stroke_or_fill &= ~PDO_FILL;
+ /* Usually the list wont contain "show_background", but if it
+ * it set let it take precedence
+ */
+ if ( (prop = find_prop_by_name (props, "show_background")) != NULL
+ && (prop->experience & PXP_NOTSET) == 0) {
+ if (stdpath->show_background)
+ stdpath->stroke_or_fill |= PDO_FILL;
+ else
+ stdpath->stroke_or_fill &= ~PDO_FILL;
+ }
/* now when transfering properties from text we'll loose stroke and fill
* Instead of drawing nothing maket it just fill.
*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]