From 2f4a7e1d6fde0adaeb95749108fa2f731ebeb6e9 Mon Sep 17 00:00:00 2001 From: ellson Date: Fri, 29 Jul 2005 16:50:30 +0000 Subject: [PATCH] add support for object selection in gui extract attribute/value list from selected object --- lib/common/const.h | 2 + lib/common/emit.c | 20 ++++++-- lib/common/globals.h | 3 ++ lib/common/shapes.c | 45 ++++++----------- lib/common/types.h | 28 +++++++--- lib/gvc/gvcint.h | 21 +++++++- lib/gvc/gvevent.c | 118 ++++++++++++++++++++++++++++++++++++++++++- lib/gvc/gvjobs.c | 19 ++++--- 8 files changed, 206 insertions(+), 50 deletions(-) diff --git a/lib/common/const.h b/lib/common/const.h index 16dad866e..549ced00f 100644 --- a/lib/common/const.h +++ b/lib/common/const.h @@ -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 diff --git a/lib/common/emit.c b/lib/common/emit.c index 9bfd29fff..c429d6534 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -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); diff --git a/lib/common/globals.h b/lib/common/globals.h index a9f5adecd..367c0235c 100644 --- a/lib/common/globals.h +++ b/lib/common/globals.h @@ -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, diff --git a/lib/common/shapes.c b/lib/common/shapes.c index 9e950934e..e2f68ccb2 100644 --- a/lib/common/shapes.c +++ b/lib/common/shapes.c @@ -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)) diff --git a/lib/common/types.h b/lib/common/types.h index ef28a58af..4d61c2072 100644 --- a/lib/common/types.h +++ b/lib/common/types.h @@ -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 diff --git a/lib/gvc/gvcint.h b/lib/gvc/gvcint.h index 9c79fe2bd..6fd75f172 100644 --- a/lib/gvc/gvcint.h +++ b/lib/gvc/gvcint.h @@ -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 */ }; diff --git a/lib/gvc/gvevent.c b/lib/gvc/gvevent.c index 9dcd17afa..cc0f4afd2 100644 --- a/lib/gvc/gvevent.c +++ b/lib/gvc/gvevent.c @@ -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; diff --git a/lib/gvc/gvjobs.c b/lib/gvc/gvjobs.c index 1be6f42e0..e7c6bd056 100644 --- a/lib/gvc/gvjobs.c +++ b/lib/gvc/gvjobs.c @@ -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 = -- 2.40.0