diff --git a/pd/nw/css/c64.css b/pd/nw/css/c64.css index abb0cc816834f4a6a55b48206d91739753f5db97..62c3c54d9926626dc0ae3039d3d5b5413f16b338 100644 --- a/pd/nw/css/c64.css +++ b/pd/nw/css/c64.css @@ -124,7 +124,8 @@ mark.console_find_highlighted { /* selected connection between objects */ .cord.signal.selected_line, -.cord.control.selected_line { +.cord.control.selected_line, +#newcord { stroke: #cc9933; } diff --git a/pd/nw/css/default.css b/pd/nw/css/default.css index 0864425328cea236a724256ab68e61932c1757b5..da5b7ad6d899dfb3713ab621aa5f5db4802aa9d4 100644 --- a/pd/nw/css/default.css +++ b/pd/nw/css/default.css @@ -20,6 +20,13 @@ body { font-family: "DejaVu Sans Mono"; } +/* delete the default scrollbars, and let's make our own */ +body::-webkit-scrollbar { + width: 0px; + height: 0px; + background: transparent; +} + .noselect { -webkit-touch-callout: none; -webkit-user-select: none; @@ -228,9 +235,10 @@ mark.console_find_highlighted { stroke: #565; } -/* selected connection between objects */ +/* selected connection between objects, or a new cord not yet connected */ .cord.signal.selected_line, -.cord.control.selected_line { +.cord.control.selected_line, +#newcord { stroke: #e87216; } @@ -387,7 +395,7 @@ text { #patchsvg.editmode .comment .border { stroke: #aaa; - stroke-dasharray: 8 4; + stroke-dasharray: 3 2; } /* A little hack for special case of [cnv]. @@ -425,21 +433,22 @@ text { /* text inside selected objects */ :not(.gop).selected text { - fill: blue; + fill: #e87216; } /* for an object that didn't create */ .obj .border.broken_border { - fill: #f7f7f7; + fill: #f7d7d7; stroke: #f00; - stroke-dasharray: 3 2; + stroke-width: 2; + stroke-dasharray: 6 2; } /* control inlet */ .xlet_control { stroke: #777; fill: white; -// stroke-width: 1; + stroke-width: 1; } /* signal inlet */ @@ -458,7 +467,7 @@ text { /* text label for an iemgui */ .iemgui_label_selected { - fill: blue; + fill: #e87216; } /* test of xlet hover animation... this should @@ -474,19 +483,26 @@ text { rx: 1; ry: 1; } - 100% { - stroke-width: 20; - stroke-opacity: 0.2; - rx: 50; - ry: 50; + 33% { + stroke-width: 12; + stroke-opacity: 1; + rx: 1; + ry: 1; + } + 66% { + stroke-width: 5; + stroke-opacity: 1; + rx: 1; + ry: 1; } } /* can't remember why this was tagged !important */ .xlet_selected { - stroke: orange !important; - fill: orange; - -webkit-animation: fizzle 0.4s linear 1; + stroke: #e87216; + fill: #e87216; + stroke-width: 5; + -webkit-animation: fizzle 0.4s ease-in 1; } #canvas_find { diff --git a/pd/nw/css/inverted.css b/pd/nw/css/inverted.css index cfd662a755dd5ecc0a3c447b074dc08a4a236e0e..8e3510bd04f062cd2e495a99e72c3c83398e4a1c 100644 --- a/pd/nw/css/inverted.css +++ b/pd/nw/css/inverted.css @@ -135,7 +135,8 @@ mark.console_find_highlighted { /* selected connection between objects */ .cord.signal.selected_line, -.cord.control.selected_line { +.cord.control.selected_line, +#newcord { stroke: blue; } diff --git a/pd/nw/css/solarized.css b/pd/nw/css/solarized.css index 3b2e4b836c902baad81e6f0f690e86fc39a398ab..45aff43aa09cf773089ca76bb2d8aedffa2ce2e1 100644 --- a/pd/nw/css/solarized.css +++ b/pd/nw/css/solarized.css @@ -128,7 +128,8 @@ mark.console_find_highlighted { /* selected connection between objects */ .cord.signal.selected_line, -.cord.control.selected_line { +.cord.control.selected_line, +#newcord { stroke: #268bd2; } diff --git a/pd/nw/css/solarized_inverted.css b/pd/nw/css/solarized_inverted.css index 63a64fb063cbf54d561c878c4981fced8e903c5b..834fff642ad4f11ba266b941b2d5e9714dee905f 100644 --- a/pd/nw/css/solarized_inverted.css +++ b/pd/nw/css/solarized_inverted.css @@ -128,7 +128,8 @@ mark.console_find_highlighted { /* selected connection between objects */ .cord.signal.selected_line, -.cord.control.selected_line { +.cord.control.selected_line, +#newcord { stroke: #b58900; } diff --git a/pd/nw/css/strongbad.css b/pd/nw/css/strongbad.css index dbc601349ce4641c889a8cb717c7ba5b1d487111..3251fc431bf73951e65dac358b5919790ddf93d5 100644 --- a/pd/nw/css/strongbad.css +++ b/pd/nw/css/strongbad.css @@ -125,7 +125,8 @@ mark.console_find_highlighted { /* selected connection between objects */ .cord.signal.selected_line, -.cord.control.selected_line { +.cord.control.selected_line, +#newcord { stroke: #53b83b; } diff --git a/pd/nw/css/subdued.css b/pd/nw/css/subdued.css index 5a364bbc17c075e3cf2836d6780ea6644663113d..a0a9e3dd69f6764eacd98224834816c516d43a35 100644 --- a/pd/nw/css/subdued.css +++ b/pd/nw/css/subdued.css @@ -125,7 +125,8 @@ mark.console_find_highlighted { /* selected connection between objects */ .cord.signal.selected_line, -.cord.control.selected_line { +.cord.control.selected_line, +#newcord { stroke: blue; } diff --git a/pd/nw/index.js b/pd/nw/index.js index 6e9da613c3d48c96ffb10ddc1ee07eee7a9542da..0361f595a9f7488770f1f81f4ffc2654d448a438 100644 --- a/pd/nw/index.js +++ b/pd/nw/index.js @@ -408,7 +408,8 @@ function nw_create_window(cid, type, width, height, xpos, ypos, attr_array) { // the window. Ideally we would just get rid of the canvas menu // altogether to simplify things. But we'd have to add some kind of // widget for the "Put" menu. - height: height + 23, + // ico@vt.edu: on 0.46.2 this is now 25, go figure... + height: height + 25, x: xpos, y: ypos }, function (new_win) { diff --git a/pd/nw/pd_canvas.html b/pd/nw/pd_canvas.html index 5b6da1ff2d362252e9e38dbd5d5a75b087490679..6c2753b8775a52ec9c7360ae64f55b05aefb0956 100644 --- a/pd/nw/pd_canvas.html +++ b/pd/nw/pd_canvas.html @@ -76,6 +76,8 @@ </button> </div> </dialog> + <div id="hscroll" style="background-color: #00000044; position: fixed; left: 2px; bottom: 2px; border-radius: 0px; width: 10px; height: 5px; visibility: hidden;"></div> + <div id="vscroll" style="background-color: #00000044; position: fixed; right: 2px; top: 2px; border-radius: 0px; width: 5px; height: 10px; visibility: hidden;"></div> <script type="text/javascript" src="./pd_canvas.js"></script> </body> </html> diff --git a/pd/nw/pd_canvas.js b/pd/nw/pd_canvas.js index d2fb09295342f414dc8ab45e2d84e14cc51c0cad..6009838e427c97d726d8208a2125975d93411035 100644 --- a/pd/nw/pd_canvas.js +++ b/pd/nw/pd_canvas.js @@ -233,6 +233,13 @@ var canvas_events = (function() { return false; }, mousedown: function(evt) { + // ico@vt.edu capture middle click for a different type of scroll + // currently disabled due to problem with scrollBy and zoom + /*if (evt.which == 2) + { + evt.stopPropagation(); + evt.preventDefault(); + }*/ var target_id, resize_type; if (target_is_scrollbar(evt)) { return; @@ -521,6 +528,64 @@ var canvas_events = (function() { } canvas_events[canvas_events.get_previous_state()](); }, + hscroll_mouseup: function(evt) { + canvas_events[canvas_events.get_previous_state()](); + }, + hscroll_mousemove: function(evt) { + if (evt.movementX != 0) { + //console.log("move: " + e.movementX); + + var hscroll = document.getElementById("hscroll"); + var svg_elem = document.getElementById("patchsvg"); + + var min_width = document.body.clientWidth + 3; + var width = svg_elem.getAttribute('width'); + var xScrollSize; + + xScrollSize = hscroll.offsetWidth; + + var xTranslate = evt.movementX * + ((width - min_width)/(min_width - xScrollSize)) * + (evt.movementX > 0 ? 1 : 0.75); + if (xTranslate > 0 && xTranslate < 1) { + xTranslate = 1; + } + if (xTranslate < 0 && xTranslate > -1) { + xTranslate = -1; + } + //console.log(xTranslate); + window.scrollBy(xTranslate, 0); + } + }, + vscroll_mouseup: function(evt) { + canvas_events[canvas_events.get_previous_state()](); + }, + vscroll_mousemove: function(evt) { + if (evt.movementY != 0) { + //console.log("move: " + e.movementY); + + var vscroll = document.getElementById("vscroll"); + var svg_elem = document.getElementById("patchsvg"); + + var min_height = document.body.clientHeight + 3; + var height = svg_elem.getAttribute('height'); + var yScrollSize; + + yScrollSize = vscroll.offsetHeight; + + var yTranslate = evt.movementY * + ((height - min_height)/(min_height - yScrollSize)) * + (evt.movementY > 0 ? 2 : 1.5); + if (yTranslate > 0 && yTranslate < 1) { + yTranslate = 1; + } + if (yTranslate < 0 && yTranslate > -1) { + yTranslate = -1; + } + //console.log(yTranslate); + window.scrollBy(0, yTranslate); + } + }, dropdown_menu_keydown: function(evt) { var select_elem = document.querySelector("#dropdown_list"), li; @@ -729,6 +794,16 @@ var canvas_events = (function() { document.addEventListener("mouseup", events.iemgui_label_mouseup, false); }, + hscroll_drag: function() { + canvas_events.none(); + document.addEventListener("mouseup", events.hscroll_mouseup, false); + document.addEventListener("mousemove", events.hscroll_mousemove, false); + }, + vscroll_drag: function() { + canvas_events.none(); + document.addEventListener("mouseup", events.vscroll_mouseup, false); + document.addEventListener("mousemove", events.vscroll_mousemove, false); + }, text: function() { canvas_events.none(); @@ -770,6 +845,9 @@ var canvas_events = (function() { document.addEventListener("keydown", events.find_keydown, false); state = "search"; }, + update_scrollbars: function() { + pdgui.gui_update_scrollbars(name); + }, register: function(n) { name = n; }, @@ -887,6 +965,13 @@ var canvas_events = (function() { console.log("tried to save something"); }, false ); + + // add listener for the scrollbars + document.getElementById("hscroll"). + addEventListener("mousedown", canvas_events.hscroll_drag, false); + document.getElementById("vscroll"). + addEventListener("mousedown", canvas_events.vscroll_drag, false); + // Whoa-- huge workaround! Right now we're getting // the popup menu the way Pd Vanilla does it: // 1) send a mouse(down) message to Pd @@ -1030,15 +1115,16 @@ var canvas_events = (function() { gui.Window.get().on("maximize", function() { pdgui.gui_canvas_get_scroll(name); }); - gui.Window.get().on("unmaximize", function() { + gui.Window.get().on("restore", function() { pdgui.gui_canvas_get_scroll(name); }); gui.Window.get().on("resize", function() { + pdgui.post("resize"); pdgui.gui_canvas_get_scroll(name); }); gui.Window.get().on("focus", function() { nw_window_focus_callback(name); - }); + }); gui.Window.get().on("blur", function() { nw_window_blur_callback(name); }); @@ -1047,6 +1133,12 @@ var canvas_events = (function() { pdgui.pdsend(name, "setbounds", x, y, x + w.width, y + w.height); }); + + // map onscroll event + document.addEventListener("scroll", function() { + pdgui.gui_update_scrollbars(name); + }); + // set minimum window size gui.Window.get().setMinimumSize(150, 100); } @@ -1514,6 +1606,7 @@ function nw_create_patch_window_menus(gui, w, name) { click: function() { var win = gui.Window.get(); win.toggleFullscreen(); + pdgui.gui_canvas_get_scroll(name); } }); diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index c9caafb9da4d6f105f7c0b71c0a527c54542888c..4d6d79472e51766ebc956e5558bfae7e91a4242a 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -814,16 +814,23 @@ function canvas_check_geometry(cid) { var win_w = patchwin[cid].width, // "23" is a kludge to account for the menubar size. See comment // in nw_create_window of index.js - win_h = patchwin[cid].height - 23, + // ico@vt.edu in 0.46.2 this is now 25 pixels, so I guess + // it is now officially kludge^2 + win_h = patchwin[cid].height - 25, win_x = patchwin[cid].x, win_y = patchwin[cid].y, cnv_width = patchwin[cid].window.innerWidth, - cnv_height = patchwin[cid].window.innerHeight - 23; + cnv_height = patchwin[cid].window.innerHeight - 25; // We're reusing win_x and win_y below, as it // shouldn't make a difference to the bounds - // algorithm in Pd + // algorithm in Pd (ico@vt.edu: this is not true anymore) + //post("relocate " + pd_geo_string(cnv_width, cnv_height, win_x, win_y) + " " + + // pd_geo_string(cnv_width, cnv_height, win_x, win_y)); + // ico@vt.edu: replaced first pd_geo_string's first two args (originally + // win_x and win_y with cnv_width and cnv_height + 25 to ensure the window + // reopens exactly how it was saved) pdsend(cid, "relocate", - pd_geo_string(win_w, win_h, win_x, win_y), + pd_geo_string(cnv_width, cnv_height + 25, win_x, win_y), pd_geo_string(cnv_width, cnv_height, win_x, win_y) ); } @@ -1412,7 +1419,8 @@ var scroll = {}, last_focused, // last focused canvas (doesn't include Pd window or dialogs) loading = {}, title_queue= {}, // ugly kluge to work around an ugly race condition - popup_menu = {}; + popup_menu = {}, + toplevel_scalars = {}; var patchwin = {}; // object filled with cid: [Window object] pairs var dialogwin = {}; // object filled with did: [Window object] pairs @@ -1574,9 +1582,13 @@ function create_window(cid, type, width, height, xpos, ypos, attr_array) { } // create a new canvas -function gui_canvas_new(cid, width, height, geometry, zoom, editmode, name, dir, dirty_flag, hide_scroll, hide_menu, cargs) { +function gui_canvas_new(cid, width, height, geometry, zoom, editmode, name, dir, dirty_flag, hide_scroll, hide_menu, has_toplevel_scalars, cargs) { // hack for buggy tcl popups... should go away for node-webkit //reset_ctrl_on_popup_window + + // ico@vt.edu: added has_toplevel_scalars, which is primarily + // being used for detecting toplevel garrays but may need to be + // expanded to also deal with scalars // local vars for window-specific behavior // visibility of menu and scrollbars, plus canvas background @@ -1597,6 +1609,7 @@ function gui_canvas_new(cid, width, height, geometry, zoom, editmode, name, dir, redo[cid] = false; font[cid] = 10; doscroll[cid] = 0; + toplevel_scalars[cid] = has_toplevel_scalars; // geometry is just the x/y screen offset "+xoff+yoff" geometry = geometry.slice(1); // remove the leading "+" geometry = geometry.split("+"); // x/y screen offset (in pixels) @@ -2604,6 +2617,10 @@ function gui_gobj_select(cid, tag) { function gui_gobj_deselect(cid, tag) { gui(cid).get_gobj(tag, function(e) { e.classList.remove("selected"); + // ico@vt.edu: check for scroll in case the handle disappears + // during deselect. LATER: make handles always fit inside the + // object, so this won't be necessary + gui_canvas_get_scroll(cid); }); } @@ -3430,15 +3447,88 @@ function gui_mycanvas_coords(cid, tag, vis_width, vis_height, select_width, sele }); } +/* this creates a group immediately below the patchsvg object */ function gui_scalar_new(cid, tag, isselected, t1, t2, t3, t4, t5, t6, - is_toplevel) { + is_toplevel, plot_style) { var g; // we should probably use gui_gobj_new here, but we"re doing some initial // scaling that normal gobjs don't need... + //post("gui_scalar_new " + t1 + " " + t2 + + // " " + t3 + " " + t4 + " " + t5 + " " + t6); + + /* ico@vt.edu HACKTASCTIC: calculating scrollbars is throwing 0.997 for + plots drawn inside the subpatch and it is a result of the -1 in the + (min_width - 1) / width call inside canvas_params. Yet, if we don't + call this, we don't have nice flush scrollbars with the regular edges. + This is why here we make a hacklicious hack and simply hide hscrollbar + since the scroll is not doing anything anyhow. + + After further testing, it seems that the aforesaid margin is a hit'n'miss + depending on the patch, so we will disable this and make the aforesaid + canvas_params equation min_width / width. + + if (is_toplevel === 1) { + gui(cid).get_elem("hscroll", function(elem) { + elem.style.setProperty("display", "none"); + }); + gui(cid).get_elem("vscroll", function(elem) { + elem.style.setProperty("display", "none"); + }); + }*/ + gui(cid).get_elem("patchsvg", function(svg_elem) { var matrix, transform_string, selection_rect; - matrix = [t1,t2,t3,t4,t5,t6]; - transform_string = "matrix(" + matrix.join() + ")"; + if (is_toplevel === 1) { + // here we deal with weird scrollbar offsets and + // inconsistencies for the various plot styles. + // the matrix format is xscale, 0, 0, yscale, width, height + // we don't use the matrix for the bar graph since it is + // difficult to get the right ratio, so we do the manual + // translate and scale instead. + // cases are: 0=points, 1=plot, 2=bezier, 3=bars + switch (plot_style) { + case 0: + matrix = [t1,t2,t3,t4,t5,t6+0.5]; + break; + case 1: + matrix = [t1,t2,t3,t4,t5,t6+1.5]; + break; + case 2: + matrix = [t1,t2,t3,t4,t5,t6+1.5]; + break; + case 3: + //matrix = [t1*.995,t2,t3,t4+1,t5+0.5,t6-2]; + matrix = 0; + transform_string = "translate(" + 0 + + "," + (t6+1) + ") scale(" + t1 + "," + t4 + ")"; + //post("transform_string = " + transform_string); + break; + } + } + else { + switch (plot_style) { + case 0: + matrix = [t1,t2,t3,t4,t5,t6+0.5]; + break; + case 1: + matrix = [t1,t2,t3,t4,t5,t6+1.5]; + break; + case 2: + matrix = [t1,t2,t3,t4,t5,t6+1.5]; + break; + case 3: + //matrix = [t1,t2,t3,t4+1,t5+0.5,t6+0.5]; + matrix = 0; + transform_string = "translate(" + (t5+(t1 < 1 ? 0.5 : 1.5)) + + "," + (t6+1) + ") scale(" + t1 + "," + t4 + ")"; + //post("transform_string = " + transform_string); + break; + } + } + + if (matrix !== 0) { + transform_string = "matrix(" + matrix.join() + ")"; + } g = create_item(cid, "g", { id: tag + "gobj", transform: transform_string, @@ -3520,6 +3610,7 @@ function gui_draw_vis(cid, type, attr_array, tag_array) { gui(cid).get_elem(tag_array[0]) .append(function(frag) { var item; + post("gui_draw_vis cid=" + cid + " type=" + type + " attr_array=" + attr_array); attr_array.push("id", tag_array[1]); item = create_item(cid, type, attr_array); frag.appendChild(item); @@ -3621,6 +3712,7 @@ function gui_draw_configure(cid, tag, attr, val) { // the default behavior. function gui_draw_viewbox(cid, tag, attr, val) { // Value will be an empty array if the user provided no values + post("gui_draw_viewbox cid=" + cid + " tag=" + tag + " attr=" + attr + " val=" + val); gui(cid).get_elem("patchsvg", function(svg_elem) { if (val.length) { gui_draw_configure(cid, tag, attr, val) @@ -4680,8 +4772,9 @@ function zoom_kludge(zoom_level) { function gui_canvas_popup(cid, xpos, ypos, canprop, canopen, isobject) { // Get page coords for top of window, in case we're scrolled gui(cid).get_nw_window(function(nw_win) { - var win_left = nw_win.window.document.body.scrollLeft, - win_top = nw_win.window.document.body.scrollTop, + // ico@vt.edu updated win_left and win_top for the 0.46.2 + var win_left = nw_win.window.scrollX, + win_top = nw_win.window.scrollY, zoom_level = nw_win.zoomLevel, // these were used to work zfactor, // around an old nw.js popup pos // bug. Now it's only necessary @@ -5746,11 +5839,64 @@ function gui_undo_menu(cid, undo_text, redo_text) { }); } +function zoom_level_to_chrome_percent(nw_win) { + var zoom = nw_win.zoomLevel; + switch (zoom) { + case -7: + zoom = 4; + break; + case -6: + zoom = 100/33; + break; + case -5: + zoom = 2; + break; + case -4: + zoom = 100/67; + break; + case -3: + zoom = 100/75; + break; + case -2: + zoom = 100/80; + break; + case -1: + zoom = 100/90; + break; + case 0: + zoom = 1; + break; + case 1: + zoom = 100/110; + break; + case 2: + zoom = 100/125; + break; + case 3: + zoom = 100/150; + break; + case 4: + zoom = 100/175; + break; + case 5: + zoom = 100/200; + break; + case 6: + zoom = 100/250; + break; + case 7: + zoom = 100/300; + break; + } + return zoom; +} + // leverages the get_nw_window method in the callers... function canvas_params(nw_win) { // calculate the canvas parameters (svg bounding box and window geometry) // for do_getscroll and do_optimalzoom + //post("nw_win=" + nw_win + " " + nw_win.window + " " + nw_win.window.document); var bbox, width, height, min_width, min_height, x, y, svg_elem; svg_elem = nw_win.window.document.getElementById("patchsvg"); bbox = svg_elem.getBBox(); @@ -5764,22 +5910,18 @@ function canvas_params(nw_win) x = bbox.x > 0 ? 0 : bbox.x, y = bbox.y > 0 ? 0 : bbox.y; - // The svg "overflow" attribute on an <svg> seems to be buggy-- for example, - // you can't trigger a mouseover event for a <rect> that is outside of the - // explicit bounds of the svg. - // To deal with this, we want to set the svg width/height to always be - // at least as large as the browser's viewport. There are a few ways to - // do this this, like documentElement.clientWidth, but window.innerWidth - // seems to give the best results. - // However, there is either a bug or some strange behavior regarding - // the viewport size: setting both the height and width of an <svg> to - // the viewport height/width will display the scrollbars. The height or - // width must be set to 4 less than the viewport size in order to keep - // the scrollbars from appearing. Here, we just subtract 4 from both - // of them. This could lead to some problems with event handlers but I - // haven't had a problem with it yet. - min_width = nw_win.window.innerWidth - 4; - min_height = nw_win.window.innerHeight - 4; + // ico@vt.edu: adjust body width and height to match patchsvg to ensure + // scrollbars only come up when we are indeed inside svg and not before + // with extra margins around. This is accurate to a pixel on nw 0.47.0. + // This is also needed when maximizing and restoring the window in order + // to trigger resizing of scrollbars. + min_width = nw_win.window.innerWidth; + min_height = nw_win.window.innerHeight; + + var body_elem = nw_win.window.document.body; + body_elem.style.width = min_width + "px"; + body_elem.style.height = min_height + "px"; + // Since we don't do any transformations on the patchsvg, // let's try just using ints for the height/width/viewBox // to keep things simple. @@ -5789,11 +5931,78 @@ function canvas_params(nw_win) min_height |= 0; x |= 0; y |= 0; + + /* ico@vt.edu: now let's draw/update our own scrollbars, so that we + don't have to deal with the window size nonsense caused by the + built-in ones... */ + // zoom var is used to compensate for the zoom level and keep + // the scrollbars the same height + var zoom = zoom_level_to_chrome_percent(nw_win); + var yScrollSize, yScrollTopOffset; + var vscroll = nw_win.window.document.getElementById("vscroll"); + yScrollSize = min_height / height; // used to be (min_height - 1) / height + yScrollTopOffset = Math.floor((nw_win.window.scrollY / height) * (min_height + 3)); + + // yScrollSize reflects the amount of the patch we currently see, + // so if it drops below 1, that means we need our scrollbars + if (yScrollSize < 1) { + var yHeight = Math.floor(yScrollSize * (min_height + 3)); + vscroll.style.setProperty("height", (yHeight - 6) + "px"); + vscroll.style.setProperty("top", (yScrollTopOffset + 2) + "px"); + vscroll.style.setProperty("-webkit-clip-path", + "polygon(0px 0px, 5px 0px, 5px " + (yHeight - 6) + + "px, 0px " + (yHeight - 11) + "px, 0px 5px)"); + vscroll.style.setProperty("width", (5 * zoom) + "px"); + vscroll.style.setProperty("right", (2 * zoom) + "px"); + vscroll.style.setProperty("visibility", "visible"); + } else { + vscroll.style.setProperty("visibility", "hidden"); + } + + var xScrollSize, xScrollLeftOffset; + var hscroll = nw_win.window.document.getElementById("hscroll"); + xScrollSize = min_width / width; // used to be (min_width - 1) / width + xScrollLeftOffset = Math.floor((nw_win.window.scrollX / width) * (min_width + 3)); + + if (xScrollSize < 1) { + var xWidth = Math.floor(xScrollSize * (min_width + 3)); + hscroll.style.setProperty("width", (xWidth - 6) + "px"); + hscroll.style.setProperty("left", (xScrollLeftOffset + 2) + "px"); + hscroll.style.setProperty("-webkit-clip-path", + "polygon(0px 0px, " + (xWidth - 11) + "px 0px, " + + (xWidth - 6) + "px 5px, 0px 5px)"); + hscroll.style.setProperty("height", (5 * zoom) + "px"); + hscroll.style.setProperty("bottom", (2 * zoom) + "px"); + hscroll.style.setProperty("visibility", "visible"); + } else { + hscroll.style.setProperty("visibility", "hidden"); + } + + //post("x=" + xScrollSize + " y=" + yScrollSize); + return { x: x, y: y, w: width, h: height, mw: min_width, mh: min_height }; } -function do_getscroll(cid) { + +// ico@vt.edu: +// the timeout is a bad hack and does not solve the problem consistently +// even on a fast computer, while also slowing down the overall user +// experience. As such, ti is disabled and left here for reference. +/*var pd_getscroll_var = {}; + +function pd_do_getscroll(cid) { + if (!pd_getscroll_var[cid]) { + pd_getscroll_var[cid] = setTimeout(function() { + do_getscroll(cid, 0); + pd_getscroll_var[cid] = null; + }, 250); + } +} + +exports.pd_do_getscroll = pd_do_getscroll;*/ + +function do_getscroll(cid, checkgeom) { // Since we're throttling these getscroll calls, they can happen after // the patch has been closed. We remove the cid from the patchwin // object on close, so we can just check to see if our Window object has @@ -5801,6 +6010,11 @@ function do_getscroll(cid) { // This is an awfully bad pattern. The whole scroll-checking mechanism // needs to be rethought, but in the meantime this should prevent any // errors wrt the rendering context disappearing. + //post("do_getscroll " + checkgeom); + if (checkgeom == 1) { + canvas_check_geometry(cid); + return; + } gui(cid).get_nw_window(function(nw_win) { var svg_elem = nw_win.window.document.getElementById("patchsvg"); var { x: x, y: y, w: width, h: height, @@ -5824,7 +6038,11 @@ function do_getscroll(cid) { }); } +exports.do_getscroll = do_getscroll; + var getscroll_var = {}; +var checkgeom_and_getscroll_var = {}; +var overriding_getscroll_var = {}; // We use a setTimeout here for two reasons: // 1. nw.js has a nasty Renderer bug when you try to modify the @@ -5839,16 +6057,51 @@ var getscroll_var = {}; // graphics from displaying until the user releases the mouse, // which would be a buggy UI function gui_canvas_get_scroll(cid) { + //post("win=" + cid); + //win_width = win.style.width; + //win_height = win.style.height; + if (toplevel_scalars[cid]) { + // we have scalars, so let's override the previous call + // because this will be a cpu intensive redraw, so we + // should do it only when the action that requested it + // is either done or stopped for long enough for the + // recalculation to happen + if (getscroll_var[cid]) { + clearTimeout(getscroll_var[cid]); + getscroll_var[cid] = null; + } + } if (!getscroll_var[cid]) { - getscroll_var[cid] = setTimeout(function() { - do_getscroll(cid); + getscroll_var[cid] = setTimeout(function() { + do_getscroll(cid, toplevel_scalars[cid]); getscroll_var[cid] = null; - }, 250); + }, 50); } } exports.gui_canvas_get_scroll = gui_canvas_get_scroll; +/* ico@vt.edu: here is one alternative getscroll call, it focuses on + overriding the previous call, so the getscroll is more delayed. This + is useful when manipulating a plot with a mouse, for instance, so that + we prevent excessive getscroll calls which can be rather cpu intensive. +*/ + +function gui_canvas_get_overriding_scroll(cid) { + //post("win=" + cid); + //win_width = win.style.width; + //win_height = win.style.height; + if (overriding_getscroll_var[cid]) { + clearTimeout(overriding_getscroll_var[cid]); + } + overriding_getscroll_var[cid] = setTimeout(function() { + do_getscroll(cid, 0); + overriding_getscroll_var[cid] = null; + }, 100); +} + +exports.gui_canvas_get_overriding_scroll = gui_canvas_get_overriding_scroll; + function do_optimalzoom(cid, hflag, vflag) { // determine an optimal zoom level that makes the entire patch fit within // the window @@ -6012,3 +6265,73 @@ function gui_pddplink_open(filename, dir) { post("pddplink: error: file not found: " + filename); } } + + +/* ico@vt.edu: this function is run when we scroll with a mouse wheel, + a touchpad (e.g. two-finger scroll), or some other HID. It is + linked from the pd_canvas.js and called from the garray_fittograph 1 + call when we are resizing the plot toplevel window to avoid race condition. +*/ +function gui_update_scrollbars(cid) { + //post("gui_update_scrollbars " + cid); + gui(cid).get_nw_window(function(nw_win) { + var hscroll = nw_win.window.document.getElementById("hscroll"); + var vscroll = nw_win.window.document.getElementById("vscroll"); + var svg_elem = nw_win.window.document.getElementById("patchsvg"); + + if (vscroll.style.visibility == "visible") + { + var height, min_height; + min_height = nw_win.window.innerHeight + 3; + height = svg_elem.getAttribute('height'); + + var yScrollSize, yScrollTopOffset; + yScrollSize = (min_height - 4) / height; + yScrollTopOffset = Math.floor((nw_win.window.scrollY / height) * min_height); + + if (yScrollSize < 1) { + var yHeight = Math.floor(yScrollSize * min_height); + vscroll.style.setProperty("height", (yHeight - 6) + "px"); + vscroll.style.setProperty("top", (yScrollTopOffset + 2) + "px"); + vscroll.style.setProperty("-webkit-clip-path", + "polygon(0px 0px, 5px 0px, 5px " + (yHeight - 6) + + "px, 0px " + (yHeight - 11) + "px, 0px 5px)"); + vscroll.style.setProperty("visibility", "visible"); + } else { + vscroll.style.setProperty("visibility", "hidden"); + } + } + + if (hscroll.style.visibility == "visible") + { + var min_width = nw_win.window.innerWidth + 3; + var width = svg_elem.getAttribute('width'); + var xScrollSize, xScrollTopOffset; + + xScrollSize = (min_width - 4) / width; + xScrollTopOffset = Math.floor((nw_win.window.scrollX / width) * min_width); + + /* console.log("win_width=" + min_width + " bbox=" + + width + " xScrollSize=" + (xScrollSize * min_width) + + " topOffset=" + xScrollTopOffset); */ + + if (xScrollSize < 1) { + var xWidth = Math.floor(xScrollSize * min_width); + hscroll.style.setProperty("width", (xWidth - 6) + "px"); + hscroll.style.setProperty("left", (xScrollTopOffset + 2) + "px"); + hscroll.style.setProperty("-webkit-clip-path", + "polygon(0px 0px, " + (xWidth - 11) + "px 0px, " + + (xWidth - 6) + "px 5px, 0px 5px)"); + hscroll.style.setProperty("visibility", "visible"); + } else { + hscroll.style.setProperty("visibility", "hidden"); + } + } + // for future reference + //nw_win.document.getElementById("hscroll"). + // style.setProperty("visibility", "visible"); + //console.log("width="+width); + }); +} + +exports.gui_update_scrollbars = gui_update_scrollbars; diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c index f5c4e9dcd3b59f7a6ebb40b24a7a27f86ff3aaa7..1723a986bde9f9b1ce6e3f3dbed473dc3b960c74 100644 --- a/pd/src/g_all_guis.c +++ b/pd/src/g_all_guis.c @@ -987,8 +987,8 @@ void iemgui_label_draw_new(t_iemgui *x) { char col[8]; t_canvas *canvas=glist_getcanvas(x->x_glist); - int x1=text_xpix(&x->x_obj, x->x_glist)+x->legacy_x; - int y1=text_ypix(&x->x_obj, x->x_glist)+x->legacy_y; + int x1=text_xpix(&x->x_obj, x->x_glist) + (sys_legacy ? x->legacy_x : 0); + int y1=text_ypix(&x->x_obj, x->x_glist) + (sys_legacy ? x->legacy_y : 0); iemgui_getrect_legacy_label(x, &x1, &y1); sprintf(col, "#%6.6x", x->x_lcol); gui_vmess("gui_iemgui_label_new", "xxiissssi", @@ -1018,8 +1018,8 @@ void iemgui_label_draw_move(t_iemgui *x) gui_vmess("gui_iemgui_label_coords", "xxii", canvas, x, - x->x_ldx + x->legacy_x, - x->x_ldy + x->legacy_y); + x->x_ldx + (sys_legacy ? x->legacy_x : 0), + x->x_ldy + (sys_legacy ? x->legacy_y : 0)); } void iemgui_label_draw_config(t_iemgui *x) diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c index d3ed51dab44bf74937fcc6d2a66a9f6b9094c246..1cf072df1179d239037484ed6ace020fb5da397c 100644 --- a/pd/src/g_canvas.c +++ b/pd/src/g_canvas.c @@ -713,16 +713,38 @@ void canvas_args_to_string(char *namebuf, t_canvas *x) strcpy(namebuf, " ("); for (i = 0; i < env->ce_argc; i++) { - if (strlen(namebuf) > MAXPDSTRING/2 - 5) + if (strlen(namebuf) > MAXPDSTRING / 2 - 5) break; if (i != 0) strcat(namebuf, " "); - atom_string(&env->ce_argv[i], namebuf + strlen(namebuf), - MAXPDSTRING/2); + atom_string(&env->ce_argv[i], namebuf + strlen(namebuf), + MAXPDSTRING / 2); } strcat(namebuf, ")"); } - else namebuf[0] = 0; + else + { + namebuf[0] = 0; + t_gobj *g = NULL; + t_garray *a = NULL; + t_symbol *arrayname; + int found = 0, res; + for (g = x->gl_list; g; g = g->g_next) + { + + if (pd_class(&g->g_pd) == garray_class) + { + res = garray_getname((t_garray *)g, &arrayname); + if (found) + { + strcat(namebuf, " "); + } + strcat(namebuf, arrayname->s_name); + found++; + //post("found=%d %s %s", found, arrayname->s_name, namebuf); + } + } + } } void canvas_reflecttitle(t_canvas *x) @@ -1314,8 +1336,8 @@ static void canvas_relocate(t_canvas *x, t_symbol *canvasgeom, < 4 || sscanf(topgeom->s_name, "%dx%d+%d+%d", &tw, &th, &txpix, &typix) < 4) bug("canvas_relocate"); - /* for some reason this is initially called with cw=ch=1 so - we just suppress that here. */ + /* for some reason this is initially called with cw=ch=1 so + we just suppress that here. */ if (cw > 5 && ch > 5) canvas_dosetbounds(x, txpix, typix, txpix + cw, typix + ch); @@ -1325,24 +1347,44 @@ static void canvas_relocate(t_canvas *x, t_symbol *canvasgeom, t_array *a = NULL; int num_elem = 0; + //int found_garray = 0; + for (g = x->gl_list; g; g = g->g_next) { //fprintf(stderr, "searching\n"); - + //post("searching"); //for subpatch garrays if (pd_class(&g->g_pd) == garray_class) { //fprintf(stderr,"found ya\n"); + //post("found ya"); ga = (t_garray *)g; if (ga) { a = garray_getarray(ga); num_elem = a->a_n; garray_fittograph(ga, num_elem, 1); + //found_garray = 1; } } } canvas_checkconfig(x); + + // ico@vt.edu: + // Here we update only scrollbars to avoid race condition + // caused by doing gui_canvas_get_scroll which in turn + // calls canvas_relocate to ensure garrays in subpatches + // are properly updated when those windows are resized. + // given that the scroll update will happen likely faster + // than the return value from the backend, we do this to + // get rid of the stale scrollbars, e.g. when making the + // window smaller (at first the scrollbars are there because + // the garray has not been redrawn yet, and then we update + // scrollbars once again here below. + //if (found_garray == 1) { + //post("found garray"); + gui_vmess("do_getscroll", "xi", x, 0); + //} } void canvas_popabstraction(t_canvas *x) diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c index 92f03ded89ea76c2a5548cf642d390e52e35b28d..4258618a15b8734d44d8161909cf814af658c5b7 100644 --- a/pd/src/g_editor.c +++ b/pd/src/g_editor.c @@ -172,7 +172,7 @@ static void canvas_nlet_conf (t_canvas *x, int type) { void canvas_getscroll (t_canvas *x) { //sys_vgui("pdtk_canvas_getscroll .x%lx.c\n",(long)x); - gui_vmess("gui_canvas_get_scroll", "x", x); + gui_vmess("gui_canvas_get_overriding_scroll", "x", x); } /* ---------------- generic widget behavior ------------------------- */ @@ -2299,7 +2299,11 @@ static void canvas_rightclick(t_canvas *x, int xpos, int ypos, t_gobj *y_sel) otherwise they end-up being dirty without visible notification besides, why would one mess with their properties without seeing what is inside them? CURRENTLY DISABLED */ + //post("canvas_rightclick %d", (y && pd_class(&y->g_pd) == garray_class ? 1 : 0)); canprop = (!y || (y && class_getpropertiesfn(pd_class(&y->g_pd))) + // ico@vt.edu: the following ensures that even if we are clicking on + // a garray, we should still be able to get the canvas properties + || (y && pd_class(&y->g_pd) == garray_class) /*&& !canvas_isabstraction( ((t_glist*)y) )*/ ); canopen = (y && zgetfn(&y->g_pd, gensym("menu-open"))); /* we add an extra check for scalars to enable the "Open" button @@ -2478,9 +2482,12 @@ void canvas_vis(t_canvas *x, t_floatarg f) canvas_destroy_editor(x); } //fprintf(stderr,"new\n"); + /* ico@vt.edu: here we use hasarray only for toplevel garrays + because they require check_config every time resize is invoked. + We may need to expand this to include scalars, as well. */ canvas_create_editor(x); canvas_args_to_string(argsbuf, x); - gui_vmess("gui_canvas_new", "xiisiissiiis", + gui_vmess("gui_canvas_new", "xiisiissiiiis", x, (int)(x->gl_screenx2 - x->gl_screenx1), (int)(x->gl_screeny2 - x->gl_screeny1), @@ -2492,6 +2499,7 @@ void canvas_vis(t_canvas *x, t_floatarg f) x->gl_dirty, x->gl_noscroll, x->gl_nomenu, + canvas_hasarray(x), argsbuf); /* It looks like this font size call is no longer needed, @@ -2618,13 +2626,7 @@ void canvas_setgraph(t_glist *x, int flag, int nogoprect) // check if we have array inside GOP, if so, // make sure hidetext is always hidden no matter what - t_gobj *g = x->gl_list; - int hasarray = 0; - while (g) - { - if (pd_class(&g->g_pd) == garray_class) hasarray = 1; - g = g->g_next; - } + int hasarray = canvas_hasarray(x); if (hasarray) x->gl_hidetext = 1; if (!nogoprect && !x->gl_goprect && !hasarray) @@ -2810,13 +2812,7 @@ static void canvas_donecanvasdialog(t_glist *x, // check if we have array inside GOP, if so, // make sure GOP/hidetext is always enabled no matter what - t_gobj *g = x->gl_list; - int hasarray = 0; - while (g) - { - if (pd_class(&g->g_pd) == garray_class) hasarray = 1; - g = g->g_next; - } + int hasarray = canvas_hasarray(x); if (hasarray && graphme != 3) { graphme = 3; //gop flag + bit-shifted hidetext @@ -3233,6 +3229,7 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, to array_motion so that we can update corresponding send when the array has been changed */ array_garray = NULL; + //post("canvas_doclick %d", doit); t_gobj *y; int shiftmod, runmode, altmod, doublemod = 0, rightclick, @@ -3479,10 +3476,14 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, canvas_check_nlet_highlights(x); } } - /* look for an outlet */ - // if object is valid, has outlets, - // and we are within the bottom area of an object - else if (ob && (noutlet = obj_noutlets(ob)) && ypos >= y2-4) + /* look for an outlet + if object is valid, has outlets, + and we are within the bottom area of an object + ico@vt.edu: 2020-06-05 added expanded hotspot for + nlets for easier pinpointing + */ + else if (ob && (noutlet = obj_noutlets(ob)) && + ypos >= y2-4-(x->gl_editor->canvas_cnct_inlet_tag[0] != 0 ? 2 : 0)) { int width = x2 - x1; int nout1 = (noutlet > 1 ? noutlet - 1 : 1); @@ -3490,8 +3491,13 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, int hotspot = x1 + (width - IOWIDTH) * closest / (nout1); // if we are within the boundaries of an nlet + /* ico@vt.edu: account for enlarged nlet when already + highlighted to make it easier to "hit" the nlet */ + int enlarged = 0; + if (x->gl_editor->canvas_cnct_inlet_tag[0] == closest) + enlarged = 5; if (closest < noutlet && - xpos >= (hotspot-1) && xpos <= hotspot + (IOWIDTH+1)) + xpos >= (hotspot-1-enlarged) && xpos <= hotspot + (IOWIDTH+1+enlarged)) { if (doit) { @@ -3566,8 +3572,12 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, } } /* look for an inlet (these are colored differently - since they are not connectable) */ - else if (ob && (ninlet = obj_ninlets(ob)) && ypos <= y1+4) + since they are not connectable) + ico@vt.edu: 2020-06-05 added expanded hotspot for + nlets for easier pinpointing + */ + else if (ob && (ninlet = obj_ninlets(ob)) + && ypos <= y1+4+(x->gl_editor->canvas_cnct_inlet_tag[0] != 0 ? 2 : 0)) { canvas_setcursor(x, CURSOR_EDITMODE_NOTHING); int width = x2 - x1; @@ -3575,8 +3585,13 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, int closest = ((xpos-x1) * (nin1) + width/2)/width; int hotspot = x1 + (width - IOWIDTH) * closest / (nin1); + /* ico@vt.edu: account for enlarged nlet when already + highlighted to make it easier to "hit" the nlet */ + int enlarged = 0; + if (x->gl_editor->canvas_cnct_inlet_tag[0] == closest) + enlarged = 5; if (closest < ninlet && - xpos >= (hotspot-1) && xpos <= hotspot + (IOWIDTH+1)) + xpos >= (hotspot-1-enlarged) && xpos <= hotspot + (IOWIDTH+1+enlarged)) { t_rtext *yr = glist_findrtext(x, (t_text *)&ob->ob_g); diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c index b4a37cb9be3f4e958ff76475389025f261f722da..fcee84bb7fee6ab97f6e6a22a38ae09edc6a7dc4 100644 --- a/pd/src/g_graph.c +++ b/pd/src/g_graph.c @@ -729,21 +729,32 @@ extern int garray_get_style(t_garray *x); /* convert an x coordinate value to an x pixel location in window */ t_float glist_xtopixels(t_glist *x, t_float xval) { + // ico@vt.edu: used to deal with the bar graph + t_float plot_offset = 0; + t_gobj *g = x->gl_list; + if (!x->gl_isgraph) return ((xval - x->gl_x1) / (x->gl_x2 - x->gl_x1)); else if (x->gl_isgraph && x->gl_havewindow) - return (x->gl_screenx2 - x->gl_screenx1) * - (xval - x->gl_x1) / (x->gl_x2 - x->gl_x1); + { + if (g != NULL && g->g_pd == garray_class) + { + t_garray *g_a = (t_garray *)g; + if (garray_get_style(g_a) == PLOTSTYLE_BARS) + plot_offset = 10; + } + //fprintf(stderr, "xtopixels xval=%f gl_x1=%f gl_x2=%f screenx1=%d screenx2=%d\n", + // xval, x->gl_x1, x->gl_x2, x->gl_screenx1, x->gl_screenx2); + return (x->gl_screenx2 - x->gl_screenx1) * + (xval - x->gl_x1 - plot_offset) / (x->gl_x2 - x->gl_x1); + } else { /* ico@vt.edu: some really stupid code to compensate for the fact that the svg stroke featue adds unaccounted width to the bars */ - t_float plot_offset = 0; - t_gobj *g = x->gl_list; if (g != NULL && g->g_pd == garray_class) { - t_garray *g_a = (t_garray *)g; - if (garray_get_style(g_a) == PLOTSTYLE_BARS) + if (garray_get_style((t_garray *)g) == PLOTSTYLE_BARS) plot_offset = 2; } int x1, y1, x2, y2; @@ -756,23 +767,61 @@ t_float glist_xtopixels(t_glist *x, t_float xval) t_float glist_ytopixels(t_glist *x, t_float yval) { + t_float plot_offset = 0; + t_gobj *g = x->gl_list; + if (!x->gl_isgraph) return ((yval - x->gl_y1) / (x->gl_y2 - x->gl_y1)); else if (x->gl_isgraph && x->gl_havewindow) - return (x->gl_screeny2 - x->gl_screeny1) * - (yval - x->gl_y1) / (x->gl_y2 - x->gl_y1); + { + if (g != NULL && g->g_pd == garray_class) + { + /*t_garray *g_a = (t_garray *)g; + if (garray_get_style((t_garray *)g) == PLOTSTYLE_POLY || + garray_get_style((t_garray *)g) == PLOTSTYLE_BEZ)*/ + switch (garray_get_style((t_garray *)g)) + { + case PLOTSTYLE_POINTS: + plot_offset = 2; + break; + case PLOTSTYLE_POLY: + plot_offset = 2; + break; + case PLOTSTYLE_BEZ: + plot_offset = 2; + break; + case PLOTSTYLE_BARS: + plot_offset = 2; + break; + } + } + return (x->gl_screeny2 - x->gl_screeny1 - plot_offset) * + (yval - x->gl_y1) / (x->gl_y2 - x->gl_y1); + } else { /* ico@vt.edu: some really stupid code to compensate for the fact that the poly and bezier tend to overlap the GOP edges */ - t_float plot_offset = 0; - t_gobj *g = x->gl_list; if (g != NULL && g->g_pd == garray_class) { - t_garray *g_a = (t_garray *)g; - if (garray_get_style(g_a) == PLOTSTYLE_POLY || - garray_get_style(g_a) == PLOTSTYLE_BEZ) - plot_offset = 2; + /*t_garray *g_a = (t_garray *)g; + if (garray_get_style((t_garray *)g) == PLOTSTYLE_POLY || + garray_get_style((t_garray *)g) == PLOTSTYLE_BEZ)*/ + switch (garray_get_style((t_garray *)g)) + { + case PLOTSTYLE_POINTS: + plot_offset = 2; + break; + case PLOTSTYLE_POLY: + plot_offset = 2; + break; + case PLOTSTYLE_BEZ: + plot_offset = 2; + break; + case PLOTSTYLE_BARS: + plot_offset = 2; + break; + } } int x1, y1, x2, y2; if (!x->gl_owner) @@ -974,17 +1023,6 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) } else if (gobj_shouldvis(gr, parent_glist)) { - /* erase contents of glist. We need to do this because - scalar_vis is currently using pd_bind/unbind to handle - scalar events. */ - for (g = x->gl_list; g; g = g->g_next) - { - gop_redraw = 1; - //fprintf(stderr,"drawing gop objects\n"); - gobj_vis(g, x, 0); - //fprintf(stderr,"done\n"); - gop_redraw = 0; - } gui_vmess("gui_gobj_erase", "xs", glist_getcanvas(x->gl_owner), tag); diff --git a/pd/src/g_scalar.c b/pd/src/g_scalar.c index a1f778fe710130da9f1e46fa7f4e60be4eef8355..7d8f9e0deb5f6519aaf8c290c3be2b0355e40a80 100644 --- a/pd/src/g_scalar.c +++ b/pd/src/g_scalar.c @@ -1056,8 +1056,10 @@ static void scalar_vis(t_gobj *z, t_glist *owner, int vis) } t_float xscale = ((glist_xtopixels(owner, 1) - glist_xtopixels(owner, 0))); t_float yscale = glist_ytopixels(owner, 1) - glist_ytopixels(owner, 0); - t_float nw_yoffset = 0; - switch (plot_style) + // this has been moved into pdgui.js gui_scalar_new, leaving here just + // in case the other implementation proves problematic + //t_float nw_yoffset = 0; + /*switch (plot_style) { case 0: nw_yoffset = -0.5; @@ -1073,7 +1075,7 @@ static void scalar_vis(t_gobj *z, t_glist *owner, int vis) nw_yoffset = 0.5; yscale += 1; break; - } + }*/ /* we translate the .scalar%lx group to displace it on the tk side. This is the outermost group for the scalar, something like a poor man's viewport. @@ -1086,14 +1088,15 @@ static void scalar_vis(t_gobj *z, t_glist *owner, int vis) understand "None"-- instead we must send an empty symbol.) */ char tagbuf[MAXPDSTRING]; sprintf(tagbuf, "scalar%lx", (long unsigned int)x->sc_vec); - gui_vmess("gui_scalar_new", "xsiffffffi", + gui_vmess("gui_scalar_new", "xsiffffffii", glist_getcanvas(owner), tagbuf, glist_isselected(owner, &x->sc_gobj), xscale, 0.0, 0.0, yscale, - glist_xtopixels(owner, basex) + (plot_style == 3 ? 0.5 : 0), - glist_ytopixels(owner, basey) + nw_yoffset, - glist_istoplevel(owner)); + glist_xtopixels(owner, basex), + glist_ytopixels(owner, basey), + glist_istoplevel(owner), + plot_style); char groupbuf[MAXPDSTRING]; // Quick hack to make gui_scalar_draw_group more general (so we // don't have to tack on "gobj" manually) @@ -1313,7 +1316,7 @@ int scalar_doclick(t_word *data, t_template *template, t_scalar *sc, static int scalar_click(t_gobj *z, struct _glist *owner, int xpix, int ypix, int shift, int alt, int dbl, int doit) { - //fprintf(stderr,"scalar_click %d %d\n", xpix, ypix); + //post("scalar_click %d %d %d", xpix, ypix, doit); t_scalar *x = (t_scalar *)z; x->sc_bboxcache = 0; diff --git a/pd/src/g_template.c b/pd/src/g_template.c index e177742bf538f80bdc36010321889e053e55d7bf..4bdd67f3ca9558c2f9185fd44cb0671700958abf 100644 --- a/pd/src/g_template.c +++ b/pd/src/g_template.c @@ -6148,8 +6148,10 @@ static void plot_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, } else { - /* case for open window displaying the array */ - /* tbd */ + /* case for open window displaying the array, + apparently we use the same value for the bottom + of the bar */ + py2 = glist->gl_y2; } } int mex1 = fielddesc_cvttocoord(xfielddesc, usexloc); diff --git a/pd/src/g_text.c b/pd/src/g_text.c index 40460727b4a7c706985406df76888d289c5b171c..4eae176faf5ab4d41d05110fdea158b946211b36 100644 --- a/pd/src/g_text.c +++ b/pd/src/g_text.c @@ -855,7 +855,7 @@ void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv) /* ---------------------- the "atom" text item ------------------------ */ -#define ATOMBUFSIZE 40 +#define ATOMBUFSIZE 160 #define ATOM_LABELLEFT 0 #define ATOM_LABELRIGHT 1 #define ATOM_LABELUP 2 @@ -1190,8 +1190,8 @@ static void gatom_param(t_gatom *x, t_symbol *sel, int argc, t_atom *argv) x->a_draghi = draghi; if (width < 0) width = 4; - else if (width > 80) - width = 80; + else if (width > ATOMBUFSIZE) + width = ATOMBUFSIZE; x->a_text.te_width = width; x->a_wherelabel = ((int)wherelabel & 3); x->a_label = label; diff --git a/pd/src/m_class.c b/pd/src/m_class.c index 0656d38f82e76e139482f4ce373c275787e0ad97..cf0ab0721bc4626ab3479b60def17aa093f51793 100644 --- a/pd/src/m_class.c +++ b/pd/src/m_class.c @@ -705,7 +705,7 @@ extern t_pd *pd_mess_from_responder(t_pd *x); Pd Vanilla apparently made a special case to handle this-- instead of using the comma after the "restore" message it starts a new "#X f 12;" which ensures that the #X is bound to the correct canvas. But that means it fails - for the old the old syntax, and there are patches in the wild that use it. + for the old syntax, and there are patches in the wild that use it. So we support _both_ of these styles in Purr Data by doing the following: 1. Checking if the last typedmess was "restore" selector.