diff --git a/pd/nw/locales/de/translation.json b/pd/nw/locales/de/translation.json index f275b2538bafc1a5086283792b40279d3c5ad527..5b3c1c5ac673944ab8c371ea977d95f64140cdd1 100644 --- a/pd/nw/locales/de/translation.json +++ b/pd/nw/locales/de/translation.json @@ -165,6 +165,8 @@ "zoomout_tt": "Verkleinere die Anzeige des Patches", "zoomreset": "Originalgröße", "zoomreset_tt": "Setze die Anzeige des Patches auf die Originalgröße zurück", + "zoomoptimal": "Optimale Größe", + "zoomoptimal_tt": "Wahlt die optimale Größe, mit der der gesamte Patch angezeigt werden kann (soweit möglich)", "fullscreen": "Vollbild", "put": "Hinzufügen", diff --git a/pd/nw/locales/en/translation.json b/pd/nw/locales/en/translation.json index e5cfb44ec8a4c4794de0fd58dacc3c5e06651ac4..7f4cf14fa6f8afc83354e79dacbcf5e1b2d10461 100644 --- a/pd/nw/locales/en/translation.json +++ b/pd/nw/locales/en/translation.json @@ -165,6 +165,8 @@ "zoomout_tt": "Make the patch visually smaller", "zoomreset": "Reset Zoom", "zoomreset_tt": "Reset the zoom to the original level", + "zoomoptimal": "Optimal Zoom", + "zoomoptimal_tt": "Change the zoom to the optimal level which makes the entire patch visible (as far as possible)", "fullscreen": "Fullscreen", "put": "Put", diff --git a/pd/nw/pd_canvas.js b/pd/nw/pd_canvas.js index 2f0b2b170389d7450988006eff07ac70c4ba6041..2f697bebe94fea0e4cf7d0965f7b2b12189243b5 100644 --- a/pd/nw/pd_canvas.js +++ b/pd/nw/pd_canvas.js @@ -1352,10 +1352,18 @@ function nw_create_patch_window_menus(gui, w, name) { pdgui.gui_canvas_get_scroll(name); } }); + minit(m.view.optimalzoom, { + enabled: true, + click: function () { + pdgui.gui_canvas_optimal_zoom(name); + pdgui.gui_canvas_get_scroll(name); + } + }); minit(m.view.zoomreset, { enabled: true, click: function () { gui.Window.get().zoomLevel = 0; + pdgui.gui_canvas_get_scroll(name); } }); minit(m.view.fullscreen, { diff --git a/pd/nw/pd_menus.js b/pd/nw/pd_menus.js index 2121a94d5f371405fa7ce1745bcf4fff1ea723a3..d32c46ef79c1de74d15d0d528d94c87e5faf4a56 100644 --- a/pd/nw/pd_menus.js +++ b/pd/nw/pd_menus.js @@ -325,6 +325,14 @@ function create_menu(gui, type) { modifiers: cmd_or_ctrl, tooltip: l("menu.zoomreset_tt") })); + if (canvas_menu) { + view_menu.append(m.view.optimalzoom = new gui.MenuItem({ + label: l("menu.zoomoptimal"), + key: "0", + modifiers: cmd_or_ctrl + "+alt", + tooltip: l("menu.zoomoptimal_tt") + })); + } view_menu.append(new gui.MenuItem({ type: "separator" })); view_menu.append(m.view.fullscreen = new gui.MenuItem({ label: l("menu.fullscreen"), diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index 09244de1fc77db09573b31da760769c28d572ce3..c4c7df9c2ec25835198a3df9b3c696215ec39cb6 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -4458,6 +4458,62 @@ function gui_canvas_get_scroll(cid) { exports.gui_canvas_get_scroll = gui_canvas_get_scroll; +function do_optimalzoom(cid) { + // determine an optimal zoom level; this uses pretty much the same + // logic as do_getscroll above to determine bbox and actual window + // size, and then determines the maximal zoom level that makes the + // entire patch fit within the window + var bbox, width, height, min_width, min_height, x, y, + svg; + if (!patchwin[cid]) { return; } + svg = get_item(cid, "patchsvg"); + bbox = svg.getBBox(); + width = bbox.x > 0 ? bbox.x + bbox.width : bbox.width; + height = bbox.y > 0 ? bbox.y + bbox.height : bbox.height; + x = bbox.x > 0 ? 0 : bbox.x, + y = bbox.y > 0 ? 0 : bbox.y; + min_width = patchwin[cid].window.innerWidth - 4; + min_height = patchwin[cid].window.innerHeight - 4; + width |= 0; // drop everything to the right of the decimal point + height |= 0; + min_width |= 0; + min_height |= 0; + x |= 0; + y |= 0; + // Calculate the optimal horizontal and vertical zoom values, + // using floor to always round down to the nearest integer. Note + // that these may well be negative, if the viewport is too small + // for the patch at the current zoom level. XXXREVIEW: We assume a + // zoom factor of 1.2 here; this works for me on Linux, but I'm + // not sure how portable it is. -ag + var zx = 0, zy = 0; + if (width>0) zx = Math.floor(Math.log(min_width/width)/Math.log(1.2)); + if (height>0) zy = Math.floor(Math.log(min_height/height)/Math.log(1.2)); + // Optimal zoom is the minimum of the horizontal and vertical zoom + // values. This gives us the offset to the current zoom level. We + // then need to clamp the resulting new zoom level to the valid + // zoom level range of -8..+7. + var actz = patchwin[cid].zoomLevel, z = actz+Math.min(zx, zy); + if (z < -8) z = -8; if (z > 7) z = 7; + //post("bbox: "+width+"x"+height+"+"+x+"+"+y+" window size: "+min_width+"x"+min_height+" current zoom level: "+actz+" optimal zoom level: "+z); + if (z != actz) { + patchwin[cid].zoomLevel = z; + } +} + +var optimalzoom_var = {}; + +// We use a setTimeout here as with do_getscroll above, but we have to +// use a smaller value here, so that we're done before a subsequent +// call to do_getscroll updates the viewport. XXXREVIEW: Hopefully +// 100 msec are enough for do_optimalzoom to finish. +function gui_canvas_optimal_zoom(cid) { + clearTimeout(optimalzoom_var[cid]); + optimalzoom_var[cid] = setTimeout(do_optimalzoom, 150, cid); +} + +exports.gui_canvas_optimal_zoom = gui_canvas_optimal_zoom; + // handling the selection function gui_lower(cid, tag) { var svg = patchwin[cid].window.document.getElementById("patchsvg"),