From 55f0f5d25d7bbc40344d679506676214233d2fa7 Mon Sep 17 00:00:00 2001 From: Jonathan Wilkes <jon.w.wilkes@gmail.com> Date: Thu, 21 May 2020 00:01:12 -0400 Subject: [PATCH] first shot at l2ork-style graph labels inside the graph --- pd/nw/dialog_canvas.html | 12 ++++---- pd/nw/pdgui.js | 65 ++++++++++++++++++++++++++++++++++++---- pd/src/g_array.c | 11 +++++-- pd/src/g_graph.c | 41 +++++++++++++++++-------- 4 files changed, 102 insertions(+), 27 deletions(-) diff --git a/pd/nw/dialog_canvas.html b/pd/nw/dialog_canvas.html index b86cf8193..ed9a8b106 100644 --- a/pd/nw/dialog_canvas.html +++ b/pd/nw/dialog_canvas.html @@ -630,12 +630,12 @@ function populate_array_form(objects) { opt.textContent = "Array #" + (i+1); arrays_select.appendChild(opt); } - // We're permanently hiding the checkbutton for creating a new array - // inside an existing graph. It's just a weird interface with very - // few benefits. However, patches that already have multiple arrays - // inside a graph will continue to work. (And if users really want - // this feature back it's easy to turn it back on. - if (!new_array_dialog || 1) { // to re-enable, remove the "|| 1" + // The "array in existing graph" interface is horrible. There should + // just be a button in the graph dialog to create an additional array + // if the user really wants to do that. Nevertheless, I just added a + // color key for multi-array graphs. So I guess it should be "discoverable" + // through this horrible interface. + if (!new_array_dialog) { document.getElementsByClassName("array_in_existing_graph")[0] .classList.add("hidden"); } diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index bbc30f0a3..a24a6f714 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -4759,11 +4759,62 @@ function gui_graph_deleteborder(cid, tag) { }); } -function gui_graph_label(cid, tag, label_number, font_height, array_name, - font, font_size, font_weight, is_selected) { - gui(cid).get_elem("patchsvg", function(e) { - var y = font_height * label_number * -1; - gui_text_new(cid, tag, "graph_label", 0, 0, y, array_name, font_size); +function gui_graph_label(cid, tag, font_size, font_height, is_selected, + legacy_mode, array_of_attr_arrays) { + // first let's check if we have any colors other than black. If so we + // we will create a little rectangle next to the label to show the color. + var show_color_rect = false; + array_of_attr_arrays.forEach(function(e) { + var c; + if (!show_color_rect) { + c = attr_array_to_object(e).color; + show_color_rect = (c !== "black" && c !== "#000000"); + } + }); + + // if the graph only holds a single array, don't display the color + if (array_of_attr_arrays.length <= 1) { + show_color_rect = false; + } + + array_of_attr_arrays.forEach(function(e, i) { + var a = attr_array_to_object(e), + narrays = array_of_attr_arrays.length; + // a.label for the label + // a.color for the color + gui(cid).get_elem("patchsvg", function(elem) { + var x, y; + if (!!legacy_mode) { // Pd Vanilla labels go above the box + y = -font_height * (narrays - (i + 1)) - 1; + } else { // In L2ork they go inside the box + // shift the label to the right if we're displaying a small + // rectangle to show the color + x = show_color_rect ? 17 : 2; + y = font_height * (i + 1); + } + gui_text_new(cid, tag, "graph_label", !!is_selected, + x, y, a.label, font_size); + }) + .get_gobj(tag) + .append(function(frag) { + var colorbar; + if (legacy_mode == 0 && show_color_rect) { + colorbar = create_item(cid, "rect", { + fill: a.color, + stroke: "black", + "stroke-width": 1, + x: 4, + y: font_height * i + (font_height * 0.5), + width: 10, + height: 10 + }); + frag.appendChild(colorbar); + } + return frag; + }) + .get_elem(tag + "text", function(e) { + e.id = tag + "text" + i; + }); }); } @@ -5089,7 +5140,9 @@ function file_dialog_callback(file_string) { exports.file_dialog_callback = file_dialog_callback; // Used to convert the ["key", "value"...] arrays coming from -// Pd to a javascript object +// Pd to a javascript object. This is a hack that I employ because +// I had already implemented JSON arrays in the Pd->GUI interface +// and didn't feel like adding object notation. function attr_array_to_object(attr_array) { var i, len = attr_array.length, diff --git a/pd/src/g_array.c b/pd/src/g_array.c index ccaaea793..0f270eeb4 100644 --- a/pd/src/g_array.c +++ b/pd/src/g_array.c @@ -136,8 +136,8 @@ struct _garray char x_hidename; /* don't print name above graph */ int x_style; /* so much simpler to keep it here */ t_symbol *x_send; /* send_changed hook */ - t_symbol *x_fillcolor; /* color for filled area of the are */ - t_symbol *x_outlinecolor; /* color of the outline around the element */ + t_symbol *x_fillcolor; /* filled area of bar in bar graph */ + t_symbol *x_outlinecolor; /* bar graph: bar outline. Others: line color */ }; t_pd *garray_arraytemplatecanvas; @@ -279,6 +279,13 @@ t_scalar *garray_getscalar(t_garray *x) return (x->x_scalar); } + /* get a garray's colors and style */ +t_symbol *garray_getlabelcolor(t_garray *x) +{ + if (x->x_style == PLOTSTYLE_BARS) return x->x_fillcolor; + else return x->x_outlinecolor; +} + /* helper function for fittograph to see if the same GOP has multiple arrays in which case take length of the largest one */ static int garray_get_largest_array(t_garray *x) diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c index d2b58b94d..dfbf6739c 100644 --- a/pd/src/g_graph.c +++ b/pd/src/g_graph.c @@ -862,6 +862,7 @@ void glist_redraw(t_glist *x) /* --------------------------- widget behavior ------------------- */ int garray_getname(t_garray *x, t_symbol **namep); +t_symbol *garray_getlabelcolor(t_garray *x); /* Note that some code in here would also be useful for drawing @@ -977,8 +978,6 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) (x->gl_ylabelx > 0.5*(x->gl_x1 + x->gl_x2) ? "w" : "e"); char *xlabelanchor = (x->gl_xlabely > 0.5*(x->gl_y1 + x->gl_y2) ? "s" : "n"); - char tagbuf[MAXPDSTRING]; - sprintf(tagbuf, "%sR", tag); gui_vmess("gui_text_draw_border", "xssiii", glist_getcanvas(x->gl_owner), tag, @@ -986,7 +985,23 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) 0, x2 - x1, y2 - y1); - /* write garrays' names along the top */ + /* write garrays' names along the top. Since we can have multiple + arrays inside a single graph, we want to send all the fun + label data to the GUI in one message. That way the GUI can do + fun stuff like selectively displaying a color key if we have + multiple arrays with different colors. */ + gui_start_vmess("gui_graph_label", "xsiiii", + glist_getcanvas(x), + tag, + sys_hostfontsize(glist_getfont(x)), + sys_fontheight(glist_getfont(x)), + glist_isselected(x, gr), + sys_legacy + ); + + /* Now start an array to hold each array of label info */ + gui_start_array(); + for (i = 0, g = x->gl_list; g; g = g->g_next, i++) { //fprintf(stderr,".\n"); @@ -995,18 +1010,18 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) if (g->g_pd == garray_class && !garray_getname((t_garray *)g, &arrayname)) { - gui_vmess("gui_graph_label", "xsiissisi", - glist_getcanvas(x), - tag, - i, - sys_fontheight(glist_getfont(x)), - arrayname->s_name, - sys_font, - sys_hostfontsize(glist_getfont(x)), - sys_fontweight, - glist_isselected(x, gr)); + t_symbol *labelcolor = garray_getlabelcolor((t_garray *)g); + /* Now send an attribute array with the label data */ + gui_start_array(); + gui_s("label"); gui_s(arrayname->s_name); + gui_s("color"); gui_s(labelcolor->s_name); + gui_end_array(); } } + /* Finally, end the final array as wel as the call to the GUI */ + gui_end_array(); + gui_end_vmess(); + /* draw ticks on horizontal borders. If lperb field is zero, this is disabled. */ if (x->gl_xtick.k_lperb) -- GitLab