]> granicus.if.org Git - graphviz/commitdiff
add support for object selection in gui
authorellson <devnull@localhost>
Fri, 29 Jul 2005 16:50:30 +0000 (16:50 +0000)
committerellson <devnull@localhost>
Fri, 29 Jul 2005 16:50:30 +0000 (16:50 +0000)
   extract attribute/value list from selected object

lib/common/const.h
lib/common/emit.c
lib/common/globals.h
lib/common/shapes.c
lib/common/types.h
lib/gvc/gvcint.h
lib/gvc/gvevent.c
lib/gvc/gvjobs.c

index 16dad866e8942ec0dd949121fd1fffa172c20500..549ced00fa40338413dd75ba8fa74dd7e2c23d67 100644 (file)
@@ -61,6 +61,8 @@
 #define                DEFAULT_COLOR           "black"
 #define                DEFAULT_ACTIVEPENCOLOR  "yellow"
 #define                DEFAULT_ACTIVEFILLCOLOR "yellow"
+#define                DEFAULT_SELECTEDPENCOLOR        "orange"
+#define                DEFAULT_SELECTEDFILLCOLOR       "orange"
 #define                DEFAULT_FONTSIZE        14.0
 #define                DEFAULT_LABEL_FONTSIZE  11.0    /* for head/taillabel */
 #define                MIN_FONTSIZE            1.0
index 9bfd29fff218dfde3f5de907c6df4671f7ce22f0..c429d65340ae2a806cdaca483cb9178b83245541 100644 (file)
@@ -775,7 +775,13 @@ void emit_edge_graphics(GVJ_t * job, edge_t * e)
            if (*p == ':')
                numc++;
 
-       if (ED_active(e)) {
+       if (ED_selected(e)) {
+           color = late_nnstring(e, E_selectedpencolor, DEFAULT_SELECTEDPENCOLOR);
+           gvrender_set_pencolor(job, color);
+           color = late_nnstring(e, E_selectedfillcolor, DEFAULT_SELECTEDFILLCOLOR);
+           gvrender_set_fillcolor(job, color);
+       }
+       else if (ED_active(e)) {
            color = late_nnstring(e, E_activepencolor, DEFAULT_ACTIVEPENCOLOR);
            gvrender_set_pencolor(job, color);
            color = late_nnstring(e, E_activefillcolor, DEFAULT_ACTIVEFILLCOLOR);
@@ -825,7 +831,7 @@ void emit_edge_graphics(GVJ_t * job, edge_t * e)
            colors = strdup(color);
            for (cnum = 0, color = strtok(colors, ":"); color;
                 cnum++, color = strtok(0, ":")) {
-               if (! ED_active(e)) {
+               if (! ED_active(e) && ! ED_selected(e)) {
                    if (color[0]) {
                        gvrender_set_pencolor(job, color);
                        gvrender_set_fillcolor(job, color);
@@ -860,7 +866,7 @@ void emit_edge_graphics(GVJ_t * job, edge_t * e)
            free(offspl.list);
            free(tmpspl.list);
        } else {
-           if (! ED_active(e)) {
+           if (! ED_active(e) && ! ED_selected(e)) {
                if (color[0]) {
                    gvrender_set_pencolor(job, color);
                    gvrender_set_fillcolor(job, color);
@@ -1387,7 +1393,13 @@ void emit_clusters(GVJ_t * job, Agraph_t * g, int flags)
                    break;
                }
        }
-       if (GD_active(sg)) {
+       if (GD_selected(sg)) {
+           color = late_nnstring(sg, G_activepencolor, DEFAULT_SELECTEDPENCOLOR);
+           gvrender_set_pencolor(job, color);
+           color = late_nnstring(sg, G_activefillcolor, DEFAULT_SELECTEDFILLCOLOR);
+           gvrender_set_fillcolor(job, color);
+       }
+       else if (GD_active(sg)) {
            color = late_nnstring(sg, G_activepencolor, DEFAULT_ACTIVEPENCOLOR);
            gvrender_set_pencolor(job, color);
            color = late_nnstring(sg, G_activefillcolor, DEFAULT_ACTIVEFILLCOLOR);
index a9f5adecd544416b17bd00d4efacc567b1c8af94..367c0235c8f63f0b329c56781f9ad64243d1bf88 100644 (file)
@@ -91,10 +91,12 @@ extern "C" {
 
     EXTERN attrsym_t
        *G_activepencolor, *G_activefillcolor,
+       *G_selectedpencolor, *G_selectedfillcolor,
        *G_peripheries;
     EXTERN attrsym_t
        *N_height, *N_width, *N_shape, *N_color, *N_fillcolor,
        *N_activepencolor, *N_activefillcolor,
+       *N_selectedpencolor, *N_selectedfillcolor,
        *N_fontsize, *N_fontname, *N_fontcolor,
        *N_label, *N_nojustify, *N_style, *N_showboxes,
        *N_sides, *N_peripheries, *N_orientation,
@@ -103,6 +105,7 @@ extern "C" {
     EXTERN attrsym_t
        *E_weight, *E_minlen, *E_color,
        *E_activepencolor, *E_activefillcolor,
+       *E_selectedpencolor, *E_selectedfillcolor,
        *E_fontsize, *E_fontname, *E_fontcolor,
        *E_label, *E_dir, *E_style, *E_decorate,
        *E_showboxes, *E_arrowsz, *E_constr, *E_layer,
index 9e950934ed70b4a75fe3bcbc38a62d3f4547e838..e2f68ccb2467c77f9382ff9f82b5e8e0f15d3a48 100644 (file)
@@ -229,24 +229,6 @@ static int same_side(pointf p0, pointf p1, pointf L0, pointf L1)
     return (s0 == s1);
 }
 
-static
-void activepencolor(GVJ_t * job, node_t * n)
-{
-    char *color;
-
-    color = late_nnstring(n, N_activepencolor, DEFAULT_ACTIVEPENCOLOR);
-    gvrender_set_pencolor(job, color);
-}
-
-static
-void activefillcolor(GVJ_t * job, node_t * n)
-{
-    char *color;
-
-    color = late_nnstring(n, N_activefillcolor, DEFAULT_ACTIVEFILLCOLOR);
-    gvrender_set_fillcolor(job, color);
-}
-
 static
 void pencolor(GVJ_t * job, node_t * n)
 {
@@ -282,11 +264,6 @@ char *findFill(node_t * n)
     return color;
 }
 
-static void fillcolor(GVJ_t * job, node_t * n)
-{
-    gvrender_set_fillcolor(job, findFill(n));
-}
-
 static char **checkStyle(node_t * n, int *flagp)
 {
     char *style;
@@ -440,7 +417,7 @@ static void round_corners(GVJ_t * job, node_t * n, point * A, int sides,
     } else {                   /* diagonals are weird.  rewrite someday. */
        pencolor(job, n);
        if (style & FILLED)
-           fillcolor(job, n);  /* emit fill color */
+           gvrender_set_fillcolor(job, findFill(n)); /* emit fill color */
        gvrender_polygon(job, A, sides, style & FILLED);
        for (seg = 0; seg < sides; seg++) {
 #ifdef NOTDEF
@@ -1211,6 +1188,7 @@ static void poly_gencode(GVJ_t * job, node_t * n)
     static int A_size;
     boolean filled;
     extern int xdemitState;
+    char *color;
 
     xdemitState = EMIT_DRAW;
     poly = (polygon_t *) ND_shape_info(n);
@@ -1244,14 +1222,23 @@ static void poly_gencode(GVJ_t * job, node_t * n)
     } else {
        style = stylenode(job, n);
     }
-    if (ND_active(n)) {
-       activefillcolor(job,n);
+    if (ND_selected(n)) {
+        color = late_nnstring(n, N_selectedpencolor, DEFAULT_SELECTEDPENCOLOR);
+        gvrender_set_pencolor(job, color);
+        color = late_nnstring(n, N_selectedfillcolor, DEFAULT_SELECTEDFILLCOLOR);
+        gvrender_set_fillcolor(job, color);
+       filled = TRUE;
+    }
+    else if (ND_active(n)) {
+        color = late_nnstring(n, N_activepencolor, DEFAULT_ACTIVEPENCOLOR);
+        gvrender_set_pencolor(job, color);
+        color = late_nnstring(n, N_activefillcolor, DEFAULT_ACTIVEFILLCOLOR);
+        gvrender_set_fillcolor(job, color);
        filled = TRUE;
-       activepencolor(job,n);
     }
     else {
         if (style & FILLED) {
-           fillcolor(job, n);  /* emit fill color */
+           gvrender_set_fillcolor(job, findFill(n)); /* emit fill color */
            filled = TRUE;
         } else {
            filled = FALSE;
@@ -1867,7 +1854,7 @@ static void record_gencode(GVJ_t * job, node_t * n)
     style = stylenode(job, n);
     pencolor(job, n);
     if (style & FILLED)
-       fillcolor(job, n);      /* emit fill color */
+       gvrender_set_fillcolor(job, findFill(n)); /* emit fill color */
     if (streq(ND_shape(n)->name, "Mrecord"))
        style |= ROUNDED;
     if (style & (ROUNDED | DIAGONALS))
index ef28a58afb896c59cbcc011d97a44a4db8d6fe5b..4d61c207237ff6a41b90beb54e2a5a066ba0014e 100644 (file)
@@ -285,11 +285,16 @@ extern "C" {
            0, R_VALUE, R_FILL, R_COMPRESS, R_AUTO, R_EXPAND } ratio_t;
 
     typedef struct layout_t {
-       double quantum, scale;
+       double quantum;
+       double scale;
        double ratio;           /* set only if ratio_kind == R_VALUE */
        double dpi;
-       point margin, page, size;
-       boolean filled, landscape, centered;
+       point margin;
+       point page;
+       point  size;
+       boolean filled;
+       boolean landscape;
+       boolean centered;
        ratio_t ratio_kind;
     } layout_t;
 
@@ -349,7 +354,10 @@ extern "C" {
        textlabel_t *label;     /* if the cluster has a title */
        box bb;                 /* bounding box */
        point border[4];        /* sizes of margins for graph labels */
-       boolean has_labels, has_images, active;
+       boolean has_labels;
+       boolean has_images;
+       boolean active;
+       boolean selected;
        unsigned char charset; /* input character set */
        int rankdir;
        int ht1, ht2;           /* below and above extremal ranks */
@@ -380,7 +388,7 @@ extern "C" {
 
        /* various flags */
        boolean has_flat_edges;
-       boolean showboxes;
+       boolean showboxes;
        boolean cluster_was_collapsed;
 
        int nodesep, ranksep;
@@ -443,6 +451,7 @@ extern "C" {
 #define GD_rankleader(g) (g)->u.rankleader
 #define GD_ranksep(g) (g)->u.ranksep
 #define GD_rn(g) (g)->u.rn
+#define GD_selected(g) (g)->u.selected
 #define GD_set_type(g) (g)->u.set_type
 #define GD_label_pos(g) (g)->u.label_pos
 #define GD_showboxes(g) (g)->u.showboxes
@@ -461,7 +470,8 @@ extern "C" {
        void *alg;
        char state;
        boolean clustnode;
-       boolean  active;
+       boolean active;
+       boolean selected;
 
 #ifndef DOT_ONLY
        boolean pinned;
@@ -470,7 +480,8 @@ extern "C" {
        double *pos, dist;
 #endif
 #ifndef NEATO_ONLY
-       boolean showboxes, has_port;
+       boolean showboxes;
+       boolean  has_port;
 
        /* fast graph */
        char node_type, mark, onstack;
@@ -542,6 +553,7 @@ extern "C" {
 #define ND_rw_i(n) (n)->u.rw
 #define ND_save_in(n) (n)->u.save_in
 #define ND_save_out(n) (n)->u.save_out
+#define ND_selected(n) (n)->u.selected
 #define ND_shape(n) (n)->u.shape
 #define ND_shape_info(n) (n)->u.shape_info
 #define ND_showboxes(n) (n)->u.showboxes
@@ -564,6 +576,7 @@ extern "C" {
        edge_t *to_orig;        /* for dot's shapes.c    */
        void *alg;
        boolean active;
+       boolean selected;
 
 #ifndef DOT_ONLY
        double factor;
@@ -598,6 +611,7 @@ extern "C" {
 #define ED_label_ontop(e) (e)->u.label_ontop
 #define ED_minlen(e) (e)->u.minlen
 #define ED_path(e) (e)->u.path
+#define ED_selected(e) (e)->u.selected
 #define ED_showboxes(e) (e)->u.showboxes
 #define ED_spl(e) (e)->u.spl
 #define ED_tail_label(e) (e)->u.tail_label
index 9c79fe2bd7d3a3409f67730a418e156a9c2eabac..6fd75f172c34a29cdd366d3e9ba705ee1a0051ea 100644 (file)
@@ -123,6 +123,12 @@ extern "C" {
        double x0; double y0;
     } gv_matrix_t;
 
+    typedef struct gv_argvlist_s {
+       char **argv;
+       int argc;
+       int alloc;
+    } gv_argvlist_t;
+
     struct GVJ_s {
        GVJ_t *next;  /* linked list of jobs */
        GVJ_t *next_active;   /* linked list of active jobs (e.g. multiple windows) */
@@ -184,11 +190,24 @@ extern "C" {
        pointf compscale;       /* composite device scale incl: scale, zoom, dpi, y_goes_down */
        pointf offset;          /* composite translation */
        
-       boolean fit_mode, needs_refresh, click, active, has_grown;
+       boolean fit_mode,
+               needs_refresh,
+               click,
+               active,
+               has_grown;
+
        pointf pointer;         /* pointer position in device units */
        pointf oldpointer;      /* old pointer position in device units */
+
        void *current_obj;      /* graph object that pointer is in currently */
 
+       void *selected_obj;      /* graph object that has been selected */
+                                       /* (e.g. button 1 clicked on current obj) */
+       char *selected_obj_type; /* "graph", "node", "edge" */
+       gv_argvlist_t selected_obj_pathname; /* e.g. "G" "cluster0" "node3" */
+       gv_argvlist_t selected_obj_attributes; /* even args are attribute names, odd are values */
+                               /* e.g. "color" "red" "style" "filled" */
+
        void *window;           /* display-specific data for gvrender plugin */
     };
 
index 9dcd17afa2070114f59e894f3df076b349205064..cc0f4afd2030c8f7128d4eb38a3e1f64c5670bf9 100644 (file)
@@ -143,18 +143,132 @@ static void gvevent_find_current_obj(GVJ_t * job, pointf pointer)
     }
 }
 
+/* FIXME - gv_argvlist_set_item and gv_argvlist_free should be in a utilities sourcefile */
+static void gv_argvlist_set_item(gv_argvlist_t *list, int index, char *item)
+{
+    if (index >= list->alloc) {
+       list->alloc = index + 10;
+       list->argv = realloc(list->argv, (list->alloc)*(sizeof(char*)));
+    }
+    list->argv[index] = item;
+}
+
+static void gv_graph_attributes(gv_argvlist_t *list, graph_t *g)
+{
+    int i, j;
+    Agsym_t *a;
+
+    for (i = 0, j = 0; i < dtsize(g->univ->globattr->dict); i++) {
+        a = g->univ->globattr->list[i];
+        gv_argvlist_set_item(list, j++, a->name);
+        gv_argvlist_set_item(list, j++, agxget(g, a->index));
+    }
+    list->argc = j;
+}
+
+static void gv_node_attributes(gv_argvlist_t *list, node_t *n)
+{
+    int i, j;
+    Agsym_t *a;
+    Agraph_t *g;
+
+    g = n -> graph -> root;
+    for (i = 0, j = 0; i < dtsize(g->univ->nodeattr->dict); i++) {
+        a = g->univ->nodeattr->list[i];
+        gv_argvlist_set_item(list, j++, a->name);
+        gv_argvlist_set_item(list, j++, agxget(n, a->index));
+    }
+    list->argc = j;
+}
+
+static void gv_edge_attributes(gv_argvlist_t *list, edge_t *e)
+{
+    int i, j;
+    Agsym_t *a;
+    Agraph_t *g;
+
+    g = e -> head -> graph -> root;
+    for (i = 0, j = 0; i < dtsize(g->univ->edgeattr->dict); i++) {
+        a = g->univ->edgeattr->list[i];
+        gv_argvlist_set_item(list, j++, a->name);
+        gv_argvlist_set_item(list, j++, agxget(e, a->index));
+    }
+    list->argc = j;
+}
+
+static void gvevent_select_current_obj(GVJ_t * job)
+{
+    void *obj;
+    int i;
+
+    obj = job->selected_obj;
+    if (obj) {
+        switch (agobjkind(obj)) {
+        case AGGRAPH:
+           GD_selected((graph_t*)obj) = FALSE;
+           break;
+        case AGNODE:
+           ND_selected((node_t*)obj) = FALSE;
+           break;
+        case AGEDGE:
+           ED_selected((edge_t*)obj) = FALSE;
+           break;
+        }
+    }
+    job->selected_obj_type = "";
+
+    obj = job->current_obj;
+    if (obj) {
+        switch (agobjkind(obj)) {
+        case AGGRAPH:
+           GD_selected((graph_t*)obj) = TRUE;
+            job->selected_obj_type = "graph";
+           gv_graph_attributes(&(job->selected_obj_attributes), (graph_t*)obj);
+           break;
+        case AGNODE:
+           ND_selected((node_t*)obj) = TRUE;
+            job->selected_obj_type = "node";
+           gv_node_attributes(&(job->selected_obj_attributes), (node_t*)obj);
+           break;
+        case AGEDGE:
+           ED_selected((edge_t*)obj) = TRUE;
+            job->selected_obj_type = "edge";
+           gv_edge_attributes(&(job->selected_obj_attributes), (edge_t*)obj);
+           break;
+        }
+    }
+    job->selected_obj = obj;
+
+#if 0
+fprintf(stderr,"type = %s\n", job->selected_obj_type);
+
+for (i = 0; i < job->selected_obj_attributes.argc; i++) {
+    fprintf(stderr,"%s%s", job->selected_obj_attributes.argv[i], (i%2)?"\n":" = ");
+}
+#endif
+}
+
 void gvevent_button_press(GVJ_t * job, int button, pointf pointer)
 {
     switch (button) {
     case 1: /* select / create in edit mode */
-    case 3: /* insert node or edge */
        gvevent_find_current_obj(job, pointer);
-        /* fall through */
+       gvevent_select_current_obj(job);
+        job->click = 1;
+       job->active = button;
+       job->needs_refresh = 1;
+       break;
     case 2: /* pan */
         job->click = 1;
        job->active = button;
        job->needs_refresh = 1;
        break;
+    case 3: /* insert node or edge */
+       gvevent_find_current_obj(job, pointer);
+        job->click = 1;
+       job->active = button;
+       job->needs_refresh = 1;
+       break;
     case 4:
        /* scrollwheel zoom in at current mouse x,y */
        job->fit_mode = 0;
index 1be6f42e02eb320b479a9393aabdc655a1263d5d..e7c6bd056ef726f49a5cdd24c47c5d0428caafaa 100644 (file)
@@ -97,13 +97,6 @@ boolean gvrender_output_langname_job(GVC_t * gvc, char *name)
     return FALSE;
 }
 
-#if 0
-/* -R switches */
-void gvrender_output_option_job(GVC_t * gvc, char *name, char *value)
-{
-}
-#endif
-
 GVJ_t *gvrender_first_job(GVC_t * gvc)
 {
     return (gvc->job = gvc->jobs);
@@ -122,6 +115,16 @@ GVJ_t *gvrender_next_job(GVC_t * gvc)
     return (gvc->job = job);
 }
 
+/* FIXME - gv_argvlist_append_item and gv_argvlist_free should be in a utilities sourcefile */
+static void gv_argvlist_free(gv_argvlist_t *list)
+{
+    if (list->argv)
+       free(list->argv);
+    list->argv = NULL;
+    list->alloc = 0;
+    list->argc = 0;
+}
+
 void gvrender_delete_jobs(GVC_t * gvc)
 {
     GVJ_t *job, *j;
@@ -129,6 +132,8 @@ void gvrender_delete_jobs(GVC_t * gvc)
     job = gvc->jobs;
     while ((j = job)) {
        job = job->next;
+       gv_argvlist_free(&(j->selected_obj_pathname));
+       gv_argvlist_free(&(j->selected_obj_attributes));
        free(j);
     }
     gvc->jobs = gvc->job = output_filename_job = output_langname_job =