From 9744d551a4a015cc9b2ea296e46c43bef2cef10d Mon Sep 17 00:00:00 2001 From: Jonathan Wilkes <jon.w.wilkes@gmail.com> Date: Sun, 20 Sep 2015 17:55:01 -0400 Subject: [PATCH] separate pd_canvas.js from pd_canvas.html --- pd/nw/pd_canvas.html | 1200 +----------------------------------------- pd/nw/pd_canvas.js | 1173 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1188 insertions(+), 1185 deletions(-) create mode 100644 pd/nw/pd_canvas.js diff --git a/pd/nw/pd_canvas.html b/pd/nw/pd_canvas.html index d66f61372..252014c03 100644 --- a/pd/nw/pd_canvas.html +++ b/pd/nw/pd_canvas.html @@ -1,1192 +1,22 @@ <!DOCTYPE html> <html> <head> - <link id="page_style" rel="stylesheet" type="text/css" href="css/default.css"> + <link id="page_style" rel="stylesheet" + type="text/css" href="css/default.css"> </head> <body id="patch_body"> - <input style="display:none;" id="fileDialog" type="file" multiple /> - <input style="display:none;" id="saveDialog" type="file" nwsaveas nwworkingdir accept=".pd" /> - - <input style="display:none;" id="openpanel_dialog" type="file" /> - <input style="display:none;" id="savepanel_dialog" type="file" nwsaveas nwworkingdir /> - - <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="patchsvg" overflow="visible" class="noselect"> - </svg> - <script> -'use strict'; -var nw = require('nw.gui'); -var pdgui = require('./pdgui.js'); - -// Apply gui preset to this canvas -pdgui.skin.apply(this); - -//var name = pdgui.last_loaded(); - -var l = pdgui.get_local_string; - -console.log("my working dir is " + pdgui.get_pwd()); -document.getElementById("saveDialog") - .setAttribute("nwworkingdir", pdgui.get_pwd()); -document.getElementById("fileDialog") - .setAttribute("nwworkingdir", pdgui.get_pwd()); -document.getElementById("fileDialog").setAttribute("accept", - Object.keys(pdgui.pd_filetypes).toString()); - -var last_keydown = ""; - -// This could probably be in pdgui.js -function add_keymods(key, evt) { - var shift = evt.shiftKey ? "Shift" : ""; - var ctrl = evt.ctrlKey ? "Ctrl" : ""; - return shift + ctrl + key; -} - -function text_to_fudi(text) { - text = text.trim(); - text = text.replace(/(\$[0-9]+)/g, '\\$1'); // escape dollar signs - text = text.replace(/(?!\\)(,|;)/g, ' \\$1 '); // escape ',' and ';' - text = text.replace(/\{|\}/g, ''); // filter '{' and '}' - text = text.replace(/\s+/g, ' '); // filter consecutive /s - - return text; -} - -var canvas_events = (function() { - var name, - state, - svg_view = document.getElementById('patchsvg').viewBox.baseVal, - textbox = function () { - return document.getElementById('new_object_textentry'); - }, - events = { - mousemove: function(evt) { - //pdgui.gui_post("x: " + evt.pageX + " y: " + evt.pageY + - // " modifier: " + (evt.shiftKey + (evt.ctrlKey << 1))); - pdgui.pdsend(name, "motion", - (evt.pageX + svg_view.x), - (evt.pageY + svg_view.y), - (evt.shiftKey + (evt.ctrlKey << 1)) - ); - evt.stopPropagation(); - evt.preventDefault(); - return false; - }, - mousedown: function(evt) { - // tk events (and, therefore, Pd evnets) are one greater than html5... - var b = evt.button + 1; - var mod; - // For some reason right-click sends a modifier value of "8", - // and canvas_doclick in g_editor.c depends on that value to - // do the right thing. So let's hack... - if (b === 3) { // right-click - mod = 8; - } else { - mod = (evt.shiftKey + (evt.ctrlKey << 1)); - } - pdgui.pdsend(name, "mouse", - (evt.pageX + svg_view.x), - (evt.pageY + svg_view.y), - b, mod - ); - //evt.stopPropagation(); - evt.preventDefault(); - }, - mouseup: function(evt) { - //pdgui.gui_post("mouseup: x: " + - // evt.pageX + " y: " + evt.pageY + - // " button: " + (evt.button + 1)); - pdgui.pdsend(name, "mouseup", - (evt.pageX + svg_view.x), - (evt.pageY + svg_view.y), - (evt.button + 1) - ); - evt.stopPropagation(); - evt.preventDefault(); - }, - keydown: function(evt) { - var key_code = evt.keyCode; - var hack = null; // hack for unprintable ascii codes - switch(key_code) { - case 8: - case 9: - case 10: - case 27: - //case 32: - case 127: hack = key_code; break; - case 37: hack = add_keymods('Left', evt); break; - case 38: hack = add_keymods('Up', evt); break; - case 39: hack = add_keymods('Right', evt); break; - case 40: hack = add_keymods('Down', evt); break; - case 33: hack = add_keymods('Prior', evt); break; - case 34: hack = add_keymods('Next', evt); break; - case 35: hack = add_keymods('End', evt); break; - case 36: hack = add_keymods('Home', evt); break; - - // These may be different on Safari... - case 112: hack = add_keymods('F1', evt); break; - case 113: hack = add_keymods('F2', evt); break; - case 114: hack = add_keymods('F3', evt); break; - case 115: hack = add_keymods('F4', evt); break; - case 116: hack = add_keymods('F5', evt); break; - case 117: hack = add_keymods('F6', evt); break; - case 118: hack = add_keymods('F7', evt); break; - case 119: hack = add_keymods('F8', evt); break; - case 120: hack = add_keymods('F9', evt); break; - case 121: hack = add_keymods('F10', evt); break; - case 122: hack = add_keymods('F11', evt); break; - case 123: hack = add_keymods('F12', evt); break; - - // Handle weird behavior for clipboard shortcuts - // Which don't fire a keypress for some odd reason - - case 65: - if (evt.ctrlKey === true) { - pdgui.pdsend(name, "selectall"); - hack = 0; // not sure what to report here... - } - break; - case 88: - if (evt.ctrlKey === true) { - pdgui.pdsend(name, "cut"); - hack = 0; // not sure what to report here... - } - break; - case 67: - if (evt.ctrlKey === true) { - pdgui.pdsend(name, "copy"); - hack = 0; // not sure what to report here... - } - break; - case 86: - if (evt.ctrlKey === true) { - pdgui.pdsend(name, "paste"); - hack = 0; // not sure what to report here... - } - break; - - // Need to handle Control key, Alt - - case 16: hack = 'Shift'; break; - case 17: hack = 'Control'; break; - case 18: hack = 'Alt'; break; - } - if (hack !== null) { - pdgui.gui_canvas_sendkey(name, 1, evt, hack); - pdgui.set_keymap(key_code, hack); - } -// pdgui.gui_post("keydown time: keycode is " + evt.keyCode); - last_keydown = evt.keyCode; - //evt.stopPropagation(); - //evt.preventDefault(); - }, - keypress: function(evt) { - // Hack to handle undo/redo shortcuts - if (evt.charCode === 26) { - if (evt.ctrlKey === true) { - if (evt.shiftKey === true) { // ctrl-Shift-z - pdgui.pdsend(name, "redo"); - } else { // ctrl-z - pdgui.pdsend(name, "undo"); - } - return; - } - } - - pdgui.gui_canvas_sendkey(name, 1, evt, evt.charCode); - pdgui.set_keymap(last_keydown, evt.charCode); -// pdgui.gui_post("keypress time: charcode is " + evt.charCode); - // Don't do things like scrolling on space, arrow keys, etc. - //evt.stopPropagation(); - evt.preventDefault(); - }, - keyup: function(evt) { - var my_char_code = pdgui.get_char_code(evt.keyCode); - pdgui.gui_canvas_sendkey(name, 0, evt, my_char_code); -// pdgui.gui_post("keyup time: charcode is: " + my_char_code); - if (evt.keyCode === 13 && evt.ctrlKey) { - pdgui.pdsend(name, "reselect"); - } - evt.stopPropagation(); - evt.preventDefault(); - }, - text_mousemove: function(evt) { - evt.stopPropagation(); - //evt.preventDefault(); - return false; - }, - text_mousedown: function(evt) { - if (textbox() !== evt.target) { - // Yes: I _really_ want .innerText and NOT .textContent - // here. I want those newlines: although that isn't - // standard in Pd-Vanilla, Pd-l2ork uses and preserves - // them inside comments - utils.create_obj(); -// var fudi_msg = text_to_fudi(textbox().innerText); -// pdgui.pdsend(name, "createobj", fudi_msg); -// pdgui.gui_post("formatted content is " + fudi_msg); - events.mousedown(evt); - canvas_events.normal(); - } - evt.stopPropagation(); - //evt.preventDefault(); - return false; - }, - text_mouseup: function(evt) { - pdgui.gui_post("mouseup target is " + - evt.target + " and textbox is " + textbox()); - //evt.stopPropagation(); - //evt.preventDefault(); - return false; - }, - text_keydown: function(evt) { - evt.stopPropagation(); - //evt.preventDefault(); - return false; - }, - text_keyup: function(evt) { - evt.stopPropagation(); - //evt.preventDefault(); - // ctrl-Enter to reselect - if (evt.keyCode === 13 && evt.ctrlKey) { - canvas_events.set_obj(); - pdgui.pdsend(name, "reselect"); - } - return false; - }, - text_keypress: function(evt) { - evt.stopPropagation(); - //evt.preventDefault(); - return false; - }, - floating_text_click: function(evt) { - //pdgui.gui_post("leaving floating mode"); - canvas_events.text(); - evt.stopPropagation(); - evt.preventDefault(); - return false; - }, - floating_text_keypress: function(evt) { - //pdgui.gui_post("leaving floating mode"); - canvas_events.text(); - //evt.stopPropagation(); - //evt.preventDefault(); - //return false; - } - }, - utils = { - create_obj: function() { - var fudi_msg = text_to_fudi(textbox().innerText); - pdgui.pdsend(name, "createobj", fudi_msg); - //pdgui.gui_post("formatted content is " + fudi_msg); - }, - set_obj: function() { - var fudi_msg = text_to_fudi(textbox().innerText); - pdgui.pdsend(name, "setobj", fudi_msg); - //pdgui.gui_post("formatted content is " + fudi_msg); - } - } - ; - - // Dialog events - document.querySelector("#saveDialog").addEventListener("change", - function(evt) { - pdgui.saveas_callback(name, this.value); - // reset value so that we can open the same file twice - this.value = null; - console.log("tried to open something"); - }, false - ); - document.querySelector("#fileDialog").addEventListener("change", - function(evt) { - var file_array = this.value; - // reset value so that we can open the same file twice - this.value = null; - pdgui.menu_open(file_array); - console.log("tried to open something"); - }, false - ); - document.querySelector("#openpanel_dialog").addEventListener("change", - function(evt) { - var file_string = this.value; - // reset value so that we can open the same file twice - this.value = null; - pdgui.file_dialog_callback(file_string); - console.log("tried to openpanel something"); - }, false - ); - document.querySelector("#savepanel_dialog").addEventListener("change", - function(evt) { - var file_string = this.value; - // reset value so that we can open the same file twice - this.value = null; - pdgui.file_dialog_callback(file_string); - console.log("tried to savepanel something"); - }, false - ); - - // closing the Window - // this isn't actually closing the window yet - nw.Window.get().on("close", function() { - pdgui.pdsend(name, "menuclose 0"); - }); - - return { - none: function() { - var name; - state = 'none'; - for (var prop in events) { - if (events.hasOwnProperty(prop)) { - name = prop.split('_'); - name = name[name.length -1]; - document.removeEventListener(name, events[prop], false); - } - } - }, - normal: function() { - //pdgui.gui_post("resetting to normal..."); - this.none(); - - document.addEventListener("mousemove", events.mousemove, false); - document.addEventListener("keydown", events.keydown, false); - document.addEventListener("keypress", events.keypress, false); - document.addEventListener("keyup", events.keyup, false); - document.addEventListener("mousedown", events.mousedown, false); - document.addEventListener("mouseup", events.mouseup, false); - state = 'normal'; - set_edit_menu_modals(true); - }, - text: function() { - this.none(); - - document.addEventListener("mousemove", events.text_mousemove, false); - document.addEventListener("keydown", events.text_keydown, false); - document.addEventListener("keypress", events.text_keypress, false); - document.addEventListener("keyup", events.text_keyup, false); - document.addEventListener("mousedown", events.text_mousedown, false); - document.addEventListener("mouseup", events.text_mouseup, false); - state = 'text'; - set_edit_menu_modals(false); - }, - floating_text: function() { - this.none(); - this.text(); - document.removeEventListener("mousedown", events.text_mousedown, false); - document.removeEventListener("mouseup", events.text_mouseup, false); - document.removeEventListener("keypress", events.text_keypress, false); - document.removeEventListener("mousemove", events.text_mousemove, false); - document.addEventListener("click", events.floating_text_click, false); - document.addEventListener("keypress", events.floating_text_keypress, false); - document.addEventListener("mousemove", events.mousemove, false); - state = 'floating_text'; - set_edit_menu_modals(false); - }, - register: function(n) { - name = n; - }, - get_state: function() { - return state; - }, - set_obj: function() { - utils.set_obj(); - } - } -}()); - -// This gets called from the nw_create_window function in index.html -// It provides us with our canvas id from the C side. Once we have it -// we can create the menu and register event callbacks -function register_canvas_id(cid) { - name = cid; // hack - create_popup_menu(cid); - canvas_events.register(cid); - canvas_events.normal(); - nw_create_patch_window_menus(cid); - pdgui.canvas_map(cid); -} - -function create_popup_menu(name) { - // The right-click popup menu - var popup_menu = new nw.Menu(); - pdgui.add_popup(name, popup_menu); - - popup_menu.append(new nw.MenuItem({ - label: 'Properties', - click: function() { - pdgui.popup_action(name, 0); - } - })); - popup_menu.append(new nw.MenuItem({ - label: 'Open', - click: function() { - pdgui.popup_action(name, 1); - } - })); - popup_menu.append(new nw.MenuItem({ - label: 'Help', - click: function() { - pdgui.popup_action(name, 2); - } - })); -} - -// stop-gap -function menu_generic () { - alert("Please implement this"); -} - -var modals = {}; // Edit menu items that should be disabled when editing - // an object box - -function set_edit_menu_modals(state) { - var item; - for (item in modals) { - if (modals.hasOwnProperty(item)) { - modals[item].enabled = state; - } - } -} - -function nw_undo_menu(undo_text, redo_text) { - if (undo_text === 'no') { - modals.undo.enabled = false; - } else { - modals.undo.enabled = true; - modals.undo.label = l('menu.undo') + " " + undo_text; - } - if (redo_text === 'no') { - modals.redo.enabled = false; - } else { - modals.redo.enabled = true; - modals.redo.label = l('menu.redo') + " " + redo_text; - } -} - -function check_box_for_text() { - var state = canvas_events.get_state(); - if (state === 'text' || state === 'floating_text') { - canvas_events.set_obj(); - } -} - -// Menus for the Patch window -function nw_create_patch_window_menus (name) { - - // Window menu - var windowMenu = new nw.Menu({ - type: 'menubar' - }); - - // File menu - var fileMenu = new nw.Menu(); - - // Add to window menu - windowMenu.append(new nw.MenuItem({ - label: l('menu.file'), - submenu: fileMenu - })); - - // File sub-entries - fileMenu.append(new nw.MenuItem({ - label: l('menu.new'), - click: pdgui.menu_new, - key: 'n', - modifiers: "ctrl", - tooltip: l('menu.new_tt') - })); - - fileMenu.append(new nw.MenuItem({ - label: l('menu.open'), - key: 'o', - modifiers: "ctrl", - tooltip: l('menu.open_tt'), - click: function() { - var chooser = document.querySelector('#fileDialog'); - chooser.click(); - } - })); - - if (pdgui.k12_mode == 1) { - fileMenu.append(new nw.MenuItem({ - label: l('menu.k12_demos'), - tooltip: l('menu.k12_demos_tt'), - click: pdgui.menu_k12_open_demos - })); - } - - fileMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - // Note: this must be different for the main Pd window - fileMenu.append(new nw.MenuItem({ - label: l('menu.save'), - click: function () { - pdgui.canvas_check_geometry(name); - pdgui.menu_save(name); - }, - key: 's', - modifiers: "ctrl", - tooltip: l('menu.save_tt') - })); - - fileMenu.append(new nw.MenuItem({ - label: l('menu.saveas'), - click: function (){ - pdgui.canvas_check_geometry(name); - pdgui.menu_saveas(name); - }, - key: 's', - modifiers: "ctrl+shift", - tooltip: l('menu.saveas_tt') - })); - - if (pdgui.k12_mode == 0) { - fileMenu.append(new nw.MenuItem({ - type: 'separator' - })); - } - - fileMenu.append(new nw.MenuItem({ - label: l('menu.message'), - click: pdgui.menu_send, - key: 'm', - modifiers: "ctrl", - tooltip: l('menu.message_tt') - })); - - if (pdgui.k12_mode == 0) { - fileMenu.append(new nw.MenuItem({ - type: 'separator' - })); - } - - // recent files go here - - // anther separator goes here if there are any recent files - - fileMenu.append(new nw.MenuItem({ - label: l('menu.close'), - tooltip: l('menu.close_tt'), - click: function() { - pdgui.menu_close(name); - }, - key: 'w', - modifiers: "ctrl" - })); - - // Quit Pd - fileMenu.append(new nw.MenuItem({ - label: l('menu.quit'), - click: pdgui.menu_quit, - key: 'q', - modifiers: "ctrl", - tooltip: l('menu.quit_tt') - })); - - // Edit menu - var editMenu = new nw.Menu(); - - // Add to window menu - windowMenu.append(new nw.MenuItem({ - label: l('menu.edit'), - submenu: editMenu - })); - - // Edit sub-entries - editMenu.append(modals.undo = new nw.MenuItem({ - label: l('menu.undo'), - click: function () { - pdgui.pdsend(name, "undo"); - }, - tooltip: l('menu.undo_tt'), - })); - - editMenu.append(modals.redo = new nw.MenuItem({ - label: l('menu.redo'), - click: function () { - pdgui.pdsend(name, "redo"); - }, - tooltip: l('menu.redo_tt'), - })); - - editMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - editMenu.append(modals.cut = new nw.MenuItem({ - label: l('menu.cut'), - click: function () { - pdgui.pdsend(name, "cut"); - }, - tooltip: l('menu.cut_tt'), - })); - - editMenu.append(modals.copy = new nw.MenuItem({ - label: l('menu.copy'), - click: function () { - pdgui.pdsend(name, "copy"); - }, - tooltip: l('menu.copy_tt'), - })); - - editMenu.append(modals.paste = new nw.MenuItem({ - label: l('menu.paste'), - click: function () { - pdgui.pdsend(name, "paste"); - }, - tooltip: l('menu.paste_tt'), - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.duplicate'), - click: function () { - pdgui.pdsend(name, "duplicate"); - }, - key: 'd', - modifiers: "ctrl", - tooltip: l('menu.duplicate_tt') - })); - - editMenu.append(modals.selectall = new nw.MenuItem({ - label: l('menu.selectall'), - click: function (evt) { - if (canvas_events.get_state() === 'normal') { - pdgui.pdsend(name, "selectall"); - } - }, - tooltip: l('menu.selectall_tt'), - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.reselect'), - // Unfortunately nw.js doesn't allow - // key: "Return" or key: "Enter", so we - // can't bind to ctrl-Enter here. (Even - // tried fromCharCode...) - click: function () { - pdgui.pdsend(name, "reselect"); - }, - key: String.fromCharCode(10), - modifiers: "ctrl", - tooltip: l('menu.reselect_tt') - })); - - editMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.zoomin'), - click: function () { - var z = nw.Window.get().zoomLevel; - if (z < 8) { z++; } - nw.Window.get().zoomLevel = z; - pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); - }, - key: '=', - modifiers: "ctrl", - tooltip: l('menu.zoomin') - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.zoomout'), - click: function () { - var z = nw.Window.get().zoomLevel; - if (z > -7) { z--; } - nw.Window.get().zoomLevel = z; - pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); - }, - key: '-', - modifiers: "ctrl", - tooltip: l('menu.zoomout_tt'), - })); - - editMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.tidyup'), - click: function() { - pdgui.pdsend(name, "tidy"); - }, - key: 'y', - modifiers: "ctrl", - tooltip: l('menu.tidyup_tt') - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.tofront'), - click: function() { - pdgui.popup_action(name, 3); - }, - tooltip: l('menu.tofront_tt'), - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.toback'), - click: function() { - pdgui.popup_action(name, 4); - }, - tooltip: l('menu.toback_tt'), - })); - - editMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.font'), - click: function () { - pdgui.pdsend(name, "menufont"); - }, - tooltip: l('menu.font_tt'), - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.cordinspector'), - click: function() { - pdgui.pdsend(name, "magicglass 0"); - }, - key: 'r', - modifiers: "ctrl", - tooltip: l('menu.cordinspector_tt'), - })); - - editMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.find'), - click: menu_generic, - key: 'f', - modifiers: "ctrl", - tooltip: l('menu.find_tt'), - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.findagain'), - click: menu_generic, - key: 'g', - modifiers: "ctrl", - tooltip: l('menu.findagain') - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.finderror'), - click: function() { - pdgui.pdsend("pd finderror"); - }, - tooltip: l('menu.finderror_tt'), - })); - - editMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.autotips'), - click: menu_generic, - tooltip: l('menu.autotips_tt'), - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.editmode'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "editmode 0"); - }, - key: 'e', - modifiers: "ctrl", - tooltip: l('menu.editmode_tt') - })); - - editMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - editMenu.append(new nw.MenuItem({ - label: l('menu.preferences'), - click: pdgui.open_prefs, - key: 'p', - modifiers: "ctrl", - tooltip: l('menu.preferences_tt') - })); - - // Put menu - var putMenu = new nw.Menu(); - - // Add to window menu - windowMenu.append(new nw.MenuItem({ - label: l('menu.put'), - submenu: putMenu - })); - - // Put menu sub-entries - putMenu.append(new nw.MenuItem({ - label: l('menu.object'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "obj 0"); - }, - key: '1', - modifiers: "ctrl", - tooltip: l('menu.object_tt'), - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.msgbox'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "msg 0"); - }, - key: '2', - modifiers: "ctrl", - tooltip: l('menu.msgbox_tt'), - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.number'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "floatatom 0"); - }, - key: '3', - modifiers: "ctrl", - tooltip: l('menu.number_tt') - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.symbol'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "symbolatom 0"); - }, - key: '4', - modifiers: "ctrl", - tooltip: l('menu.symbol_tt') - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.comment'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "text 0"); - }, - key: '5', - modifiers: "ctrl", - tooltip: l('menu.comment_tt') - })); - - putMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.bang'), - click: function(e) { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "bng 0"); - }, - key: 'b', - modifiers: "ctrl-shift", - tooltip: l('menu.bang_tt') - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.toggle'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "toggle 0"); - }, - key: 't', - modifiers: "ctrl-shift", - tooltip: l('menu.toggle_tt') - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.number2'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "numbox 0"); - }, - key: 'n', - modifiers: "ctrl-shift", - tooltip: l('menu.number2') - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.vslider'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "vslider 0"); - }, - key: 'v', - modifiers: "ctrl-shift", - tooltip: l('menu.vslider_tt'), - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.hslider'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "hslider 0"); - }, - key: 'h', - modifiers: "ctrl-shift", - tooltip: l('menu.hslider_tt'), - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.vradio'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "vradio 0"); - }, - key: 'd', - modifiers: "ctrl-shift", - tooltip: l('menu.vradio_tt'), - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.hradio'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "hradio 0"); - }, - key: 'i', - modifiers: "ctrl", - tooltip: l('menu.hradio_tt'), - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.vu'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "vumeter 0"); - }, - key: 'u', - modifiers: "ctrl", - tooltip: l('menu.vu_tt'), - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.cnv'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "mycnv 0"); - }, - key: 'c', - modifiers: "ctrl-shift", - tooltip: l('menu.cnv_tt') - })); - - putMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.graph'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - // leaving out some placement logic... see pd.tk menu_graph - pdgui.pdsend(name, "graph NULL 0 0 0 0 30 30 0 30"); - }, - tooltip: l('menu.graph_tt'), - })); - - putMenu.append(new nw.MenuItem({ - label: l('menu.array'), - click: function() { - check_box_for_text(); - pdgui.pdsend(name, "dirty 1"); - pdgui.pdsend(name, "menuarray"); - }, - tooltip: l('menu.array_tt'), - })); - - - // Windows menu... call it "winman" (i.e., window management) - // to avoid confusion - var winmanMenu = new nw.Menu(); - - // Add to windows menu - windowMenu.append(new nw.MenuItem({ - label: l('menu.windows'), - submenu: winmanMenu - })); - - // Winman sub-entries - winmanMenu.append(new nw.MenuItem({ - label: l('menu.fullscreen'), - click: function() { - var win = nw.Window.get(); - var fullscreen = win.isFullscreen; - win.isFullscreen = !fullscreen; - pdgui.gui_post("fullscreen is " + fullscreen); - }, - key: "f11", - //modifiers: "ctrl", - tooltip: l('menu.nextwin_tt'), - })); - - winmanMenu.append(new nw.MenuItem({ - label: l('menu.nextwin'), - click: menu_generic, - key: String.fromCharCode(12), // Page down - modifiers: "ctrl", - tooltip: l('menu.nextwin_tt'), - })); - - winmanMenu.append(new nw.MenuItem({ - label: l('menu.prevwin'), - click: menu_generic, - key: String.fromCharCode(11), // Page up - modifiers: "ctrl", - tooltip: l('menu.prevwin_tt'), - })); - - winmanMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - winmanMenu.append(new nw.MenuItem({ - label: l('menu.parentwin'), - click: menu_generic, - tooltip: l('menu.parentwin_tt'), - })); - - winmanMenu.append(new nw.MenuItem({ - label: l('menu.pdwin'), - click: menu_generic, - tooltip: l('menu.pdwin_tt'), - })); - - // Media menu - var mediaMenu = new nw.Menu(); - - // Add to window menu - windowMenu.append(new nw.MenuItem({ - label: l('menu.media'), - submenu: mediaMenu - })); - - // Media sub-entries - mediaMenu.append(new nw.MenuItem({ - label: l('menu.audio_on'), - click: function() { - pdgui.pdsend("pd dsp 1"); - }, - key: '/', - modifiers: "ctrl", - tooltip: l('menu.audio_on_tt'), - })); - - mediaMenu.append(new nw.MenuItem({ - label: l('menu.audio_off'), - click: function() { - pdgui.pdsend("pd dsp 0"); - }, - key: '.', - modifiers: "ctrl", - tooltip: l('menu.audio_off_tt'), - })); - - mediaMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - mediaMenu.append(new nw.MenuItem({ - label: l('menu.test'), - click: menu_generic, - tooltip: l('menu.test_tt'), - })); - - mediaMenu.append(new nw.MenuItem({ - label: l('menu.loadmeter'), - click: menu_generic, - tooltip: l('menu.loadmeter_tt'), - })); - - // Help menu - var helpMenu = new nw.Menu(); - - // Add to window menu - windowMenu.append(new nw.MenuItem({ - label: l('menu.help'), - submenu: helpMenu - })); - - // Help sub-entries - helpMenu.append(new nw.MenuItem({ - label: l('menu.about'), - click: menu_generic, - //key: 'c', - //modifiers: "ctrl", - tooltip: l('menu.about_tt'), - })); - - helpMenu.append(new nw.MenuItem({ - label: l('menu.manual'), - click: menu_generic, - tooltip: l('menu.manual'), - })); - - helpMenu.append(new nw.MenuItem({ - label: l('menu.browser'), - click: menu_generic, - tooltip: l('menu.browser_tt'), - })); - - helpMenu.append(new nw.MenuItem({ - type: 'separator' - })); - - helpMenu.append(new nw.MenuItem({ - label: l('menu.l2ork_list'), - click: menu_generic, - tooltip: l('menu.l2ork_list_tt'), - })); - - helpMenu.append(new nw.MenuItem({ - label: l('menu.pd_list'), - click: menu_generic, - tooltip: l('menu.pd_list_tt'), - })); - - helpMenu.append(new nw.MenuItem({ - label: l('menu.forums'), - click: menu_generic, - tooltip: l('menu.forums_tt'), - })); - - helpMenu.append(new nw.MenuItem({ - label: l('menu.irc'), - click: menu_generic, - tooltip: l('menu.irc_tt'), - })); - - // Assign to window - nw.Window.get().menu = windowMenu; - -} - - </script> + <input style="display:none;" id="fileDialog" type="file" multiple /> + <input style="display:none;" id="saveDialog" type="file" + nwsaveas nwworkingdir accept=".pd" /> + <input style="display:none;" id="openpanel_dialog" type="file" /> + <input style="display:none;" id="savepanel_dialog" type="file" + nwsaveas nwworkingdir /> + <svg xmlns="http://www.w3.org/2000/svg" + version="1.1" + id="patchsvg" + overflow="visible" + class="noselect"> + </svg> + <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 new file mode 100644 index 000000000..1982bb5b2 --- /dev/null +++ b/pd/nw/pd_canvas.js @@ -0,0 +1,1173 @@ +'use strict'; +var nw = require('nw.gui'); +var pdgui = require('./pdgui.js'); + +// Apply gui preset to this canvas +pdgui.skin.apply(this); + +//var name = pdgui.last_loaded(); + +var l = pdgui.get_local_string; + +console.log("my working dir is " + pdgui.get_pwd()); +document.getElementById("saveDialog") + .setAttribute("nwworkingdir", pdgui.get_pwd()); +document.getElementById("fileDialog") + .setAttribute("nwworkingdir", pdgui.get_pwd()); +document.getElementById("fileDialog").setAttribute("accept", + Object.keys(pdgui.pd_filetypes).toString()); + +var last_keydown = ""; + +// This could probably be in pdgui.js +function add_keymods(key, evt) { + var shift = evt.shiftKey ? "Shift" : ""; + var ctrl = evt.ctrlKey ? "Ctrl" : ""; + return shift + ctrl + key; +} + +function text_to_fudi(text) { + text = text.trim(); + text = text.replace(/(\$[0-9]+)/g, '\\$1'); // escape dollar signs + text = text.replace(/(?!\\)(,|;)/g, ' \\$1 '); // escape ',' and ';' + text = text.replace(/\{|\}/g, ''); // filter '{' and '}' + text = text.replace(/\s+/g, ' '); // filter consecutive /s + + return text; +} + +var canvas_events = (function() { + var name, + state, + svg_view = document.getElementById('patchsvg').viewBox.baseVal, + textbox = function () { + return document.getElementById('new_object_textentry'); + }, + events = { + mousemove: function(evt) { + //pdgui.gui_post("x: " + evt.pageX + " y: " + evt.pageY + + // " modifier: " + (evt.shiftKey + (evt.ctrlKey << 1))); + pdgui.pdsend(name, "motion", + (evt.pageX + svg_view.x), + (evt.pageY + svg_view.y), + (evt.shiftKey + (evt.ctrlKey << 1)) + ); + evt.stopPropagation(); + evt.preventDefault(); + return false; + }, + mousedown: function(evt) { + // tk events (and, therefore, Pd evnets) are one greater than html5... + var b = evt.button + 1; + var mod; + // For some reason right-click sends a modifier value of "8", + // and canvas_doclick in g_editor.c depends on that value to + // do the right thing. So let's hack... + if (b === 3) { // right-click + mod = 8; + } else { + mod = (evt.shiftKey + (evt.ctrlKey << 1)); + } + pdgui.pdsend(name, "mouse", + (evt.pageX + svg_view.x), + (evt.pageY + svg_view.y), + b, mod + ); + //evt.stopPropagation(); + evt.preventDefault(); + }, + mouseup: function(evt) { + //pdgui.gui_post("mouseup: x: " + + // evt.pageX + " y: " + evt.pageY + + // " button: " + (evt.button + 1)); + pdgui.pdsend(name, "mouseup", + (evt.pageX + svg_view.x), + (evt.pageY + svg_view.y), + (evt.button + 1) + ); + evt.stopPropagation(); + evt.preventDefault(); + }, + keydown: function(evt) { + var key_code = evt.keyCode; + var hack = null; // hack for unprintable ascii codes + switch(key_code) { + case 8: + case 9: + case 10: + case 27: + //case 32: + case 127: hack = key_code; break; + case 37: hack = add_keymods('Left', evt); break; + case 38: hack = add_keymods('Up', evt); break; + case 39: hack = add_keymods('Right', evt); break; + case 40: hack = add_keymods('Down', evt); break; + case 33: hack = add_keymods('Prior', evt); break; + case 34: hack = add_keymods('Next', evt); break; + case 35: hack = add_keymods('End', evt); break; + case 36: hack = add_keymods('Home', evt); break; + + // These may be different on Safari... + case 112: hack = add_keymods('F1', evt); break; + case 113: hack = add_keymods('F2', evt); break; + case 114: hack = add_keymods('F3', evt); break; + case 115: hack = add_keymods('F4', evt); break; + case 116: hack = add_keymods('F5', evt); break; + case 117: hack = add_keymods('F6', evt); break; + case 118: hack = add_keymods('F7', evt); break; + case 119: hack = add_keymods('F8', evt); break; + case 120: hack = add_keymods('F9', evt); break; + case 121: hack = add_keymods('F10', evt); break; + case 122: hack = add_keymods('F11', evt); break; + case 123: hack = add_keymods('F12', evt); break; + + // Handle weird behavior for clipboard shortcuts + // Which don't fire a keypress for some odd reason + + case 65: + if (evt.ctrlKey === true) { + pdgui.pdsend(name, "selectall"); + hack = 0; // not sure what to report here... + } + break; + case 88: + if (evt.ctrlKey === true) { + pdgui.pdsend(name, "cut"); + hack = 0; // not sure what to report here... + } + break; + case 67: + if (evt.ctrlKey === true) { + pdgui.pdsend(name, "copy"); + hack = 0; // not sure what to report here... + } + break; + case 86: + if (evt.ctrlKey === true) { + pdgui.pdsend(name, "paste"); + hack = 0; // not sure what to report here... + } + break; + + // Need to handle Control key, Alt + + case 16: hack = 'Shift'; break; + case 17: hack = 'Control'; break; + case 18: hack = 'Alt'; break; + } + if (hack !== null) { + pdgui.gui_canvas_sendkey(name, 1, evt, hack); + pdgui.set_keymap(key_code, hack); + } +// pdgui.gui_post("keydown time: keycode is " + evt.keyCode); + last_keydown = evt.keyCode; + //evt.stopPropagation(); + //evt.preventDefault(); + }, + keypress: function(evt) { + // Hack to handle undo/redo shortcuts + if (evt.charCode === 26) { + if (evt.ctrlKey === true) { + if (evt.shiftKey === true) { // ctrl-Shift-z + pdgui.pdsend(name, "redo"); + } else { // ctrl-z + pdgui.pdsend(name, "undo"); + } + return; + } + } + + pdgui.gui_canvas_sendkey(name, 1, evt, evt.charCode); + pdgui.set_keymap(last_keydown, evt.charCode); +// pdgui.gui_post("keypress time: charcode is " + evt.charCode); + // Don't do things like scrolling on space, arrow keys, etc. + //evt.stopPropagation(); + evt.preventDefault(); + }, + keyup: function(evt) { + var my_char_code = pdgui.get_char_code(evt.keyCode); + pdgui.gui_canvas_sendkey(name, 0, evt, my_char_code); +// pdgui.gui_post("keyup time: charcode is: " + my_char_code); + if (evt.keyCode === 13 && evt.ctrlKey) { + pdgui.pdsend(name, "reselect"); + } + evt.stopPropagation(); + evt.preventDefault(); + }, + text_mousemove: function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + text_mousedown: function(evt) { + if (textbox() !== evt.target) { + // Yes: I _really_ want .innerText and NOT .textContent + // here. I want those newlines: although that isn't + // standard in Pd-Vanilla, Pd-l2ork uses and preserves + // them inside comments + utils.create_obj(); +// var fudi_msg = text_to_fudi(textbox().innerText); +// pdgui.pdsend(name, "createobj", fudi_msg); +// pdgui.gui_post("formatted content is " + fudi_msg); + events.mousedown(evt); + canvas_events.normal(); + } + evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + text_mouseup: function(evt) { + pdgui.gui_post("mouseup target is " + + evt.target + " and textbox is " + textbox()); + //evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + text_keydown: function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + text_keyup: function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + // ctrl-Enter to reselect + if (evt.keyCode === 13 && evt.ctrlKey) { + canvas_events.set_obj(); + pdgui.pdsend(name, "reselect"); + } + return false; + }, + text_keypress: function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + floating_text_click: function(evt) { + //pdgui.gui_post("leaving floating mode"); + canvas_events.text(); + evt.stopPropagation(); + evt.preventDefault(); + return false; + }, + floating_text_keypress: function(evt) { + //pdgui.gui_post("leaving floating mode"); + canvas_events.text(); + //evt.stopPropagation(); + //evt.preventDefault(); + //return false; + } + }, + utils = { + create_obj: function() { + var fudi_msg = text_to_fudi(textbox().innerText); + pdgui.pdsend(name, "createobj", fudi_msg); + //pdgui.gui_post("formatted content is " + fudi_msg); + }, + set_obj: function() { + var fudi_msg = text_to_fudi(textbox().innerText); + pdgui.pdsend(name, "setobj", fudi_msg); + //pdgui.gui_post("formatted content is " + fudi_msg); + } + } + ; + + // Dialog events + document.querySelector("#saveDialog").addEventListener("change", + function(evt) { + pdgui.saveas_callback(name, this.value); + // reset value so that we can open the same file twice + this.value = null; + console.log("tried to open something"); + }, false + ); + document.querySelector("#fileDialog").addEventListener("change", + function(evt) { + var file_array = this.value; + // reset value so that we can open the same file twice + this.value = null; + pdgui.menu_open(file_array); + console.log("tried to open something"); + }, false + ); + document.querySelector("#openpanel_dialog").addEventListener("change", + function(evt) { + var file_string = this.value; + // reset value so that we can open the same file twice + this.value = null; + pdgui.file_dialog_callback(file_string); + console.log("tried to openpanel something"); + }, false + ); + document.querySelector("#savepanel_dialog").addEventListener("change", + function(evt) { + var file_string = this.value; + // reset value so that we can open the same file twice + this.value = null; + pdgui.file_dialog_callback(file_string); + console.log("tried to savepanel something"); + }, false + ); + + // closing the Window + // this isn't actually closing the window yet + nw.Window.get().on("close", function() { + pdgui.pdsend(name, "menuclose 0"); + }); + + return { + none: function() { + var name; + state = 'none'; + for (var prop in events) { + if (events.hasOwnProperty(prop)) { + name = prop.split('_'); + name = name[name.length -1]; + document.removeEventListener(name, events[prop], false); + } + } + }, + normal: function() { + //pdgui.gui_post("resetting to normal..."); + this.none(); + + document.addEventListener("mousemove", events.mousemove, false); + document.addEventListener("keydown", events.keydown, false); + document.addEventListener("keypress", events.keypress, false); + document.addEventListener("keyup", events.keyup, false); + document.addEventListener("mousedown", events.mousedown, false); + document.addEventListener("mouseup", events.mouseup, false); + state = 'normal'; + set_edit_menu_modals(true); + }, + text: function() { + this.none(); + + document.addEventListener("mousemove", events.text_mousemove, false); + document.addEventListener("keydown", events.text_keydown, false); + document.addEventListener("keypress", events.text_keypress, false); + document.addEventListener("keyup", events.text_keyup, false); + document.addEventListener("mousedown", events.text_mousedown, false); + document.addEventListener("mouseup", events.text_mouseup, false); + state = 'text'; + set_edit_menu_modals(false); + }, + floating_text: function() { + this.none(); + this.text(); + document.removeEventListener("mousedown", events.text_mousedown, false); + document.removeEventListener("mouseup", events.text_mouseup, false); + document.removeEventListener("keypress", events.text_keypress, false); + document.removeEventListener("mousemove", events.text_mousemove, false); + document.addEventListener("click", events.floating_text_click, false); + document.addEventListener("keypress", events.floating_text_keypress, false); + document.addEventListener("mousemove", events.mousemove, false); + state = 'floating_text'; + set_edit_menu_modals(false); + }, + register: function(n) { + name = n; + }, + get_state: function() { + return state; + }, + set_obj: function() { + utils.set_obj(); + } + } +}()); + +// This gets called from the nw_create_window function in index.html +// It provides us with our canvas id from the C side. Once we have it +// we can create the menu and register event callbacks +function register_canvas_id(cid) { + name = cid; // hack + create_popup_menu(cid); + canvas_events.register(cid); + canvas_events.normal(); + nw_create_patch_window_menus(cid); + pdgui.canvas_map(cid); +} + +function create_popup_menu(name) { + // The right-click popup menu + var popup_menu = new nw.Menu(); + pdgui.add_popup(name, popup_menu); + + popup_menu.append(new nw.MenuItem({ + label: 'Properties', + click: function() { + pdgui.popup_action(name, 0); + } + })); + popup_menu.append(new nw.MenuItem({ + label: 'Open', + click: function() { + pdgui.popup_action(name, 1); + } + })); + popup_menu.append(new nw.MenuItem({ + label: 'Help', + click: function() { + pdgui.popup_action(name, 2); + } + })); +} + +// stop-gap +function menu_generic () { + alert("Please implement this"); +} + +var modals = {}; // Edit menu items that should be disabled when editing + // an object box + +function set_edit_menu_modals(state) { + var item; + for (item in modals) { + if (modals.hasOwnProperty(item)) { + modals[item].enabled = state; + } + } +} + +function nw_undo_menu(undo_text, redo_text) { + if (undo_text === 'no') { + modals.undo.enabled = false; + } else { + modals.undo.enabled = true; + modals.undo.label = l('menu.undo') + " " + undo_text; + } + if (redo_text === 'no') { + modals.redo.enabled = false; + } else { + modals.redo.enabled = true; + modals.redo.label = l('menu.redo') + " " + redo_text; + } +} + +function check_box_for_text() { + var state = canvas_events.get_state(); + if (state === 'text' || state === 'floating_text') { + canvas_events.set_obj(); + } +} + +// Menus for the Patch window +function nw_create_patch_window_menus (name) { + + // Window menu + var windowMenu = new nw.Menu({ + type: 'menubar' + }); + + // File menu + var fileMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.file'), + submenu: fileMenu + })); + + // File sub-entries + fileMenu.append(new nw.MenuItem({ + label: l('menu.new'), + click: pdgui.menu_new, + key: 'n', + modifiers: "ctrl", + tooltip: l('menu.new_tt') + })); + + fileMenu.append(new nw.MenuItem({ + label: l('menu.open'), + key: 'o', + modifiers: "ctrl", + tooltip: l('menu.open_tt'), + click: function() { + var chooser = document.querySelector('#fileDialog'); + chooser.click(); + } + })); + + if (pdgui.k12_mode == 1) { + fileMenu.append(new nw.MenuItem({ + label: l('menu.k12_demos'), + tooltip: l('menu.k12_demos_tt'), + click: pdgui.menu_k12_open_demos + })); + } + + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + // Note: this must be different for the main Pd window + fileMenu.append(new nw.MenuItem({ + label: l('menu.save'), + click: function () { + pdgui.canvas_check_geometry(name); + pdgui.menu_save(name); + }, + key: 's', + modifiers: "ctrl", + tooltip: l('menu.save_tt') + })); + + fileMenu.append(new nw.MenuItem({ + label: l('menu.saveas'), + click: function (){ + pdgui.canvas_check_geometry(name); + pdgui.menu_saveas(name); + }, + key: 's', + modifiers: "ctrl+shift", + tooltip: l('menu.saveas_tt') + })); + + if (pdgui.k12_mode == 0) { + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + } + + fileMenu.append(new nw.MenuItem({ + label: l('menu.message'), + click: pdgui.menu_send, + key: 'm', + modifiers: "ctrl", + tooltip: l('menu.message_tt') + })); + + if (pdgui.k12_mode == 0) { + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + } + + // recent files go here + + // anther separator goes here if there are any recent files + + fileMenu.append(new nw.MenuItem({ + label: l('menu.close'), + tooltip: l('menu.close_tt'), + click: function() { + pdgui.menu_close(name); + }, + key: 'w', + modifiers: "ctrl" + })); + + // Quit Pd + fileMenu.append(new nw.MenuItem({ + label: l('menu.quit'), + click: pdgui.menu_quit, + key: 'q', + modifiers: "ctrl", + tooltip: l('menu.quit_tt') + })); + + // Edit menu + var editMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.edit'), + submenu: editMenu + })); + + // Edit sub-entries + editMenu.append(modals.undo = new nw.MenuItem({ + label: l('menu.undo'), + click: function () { + pdgui.pdsend(name, "undo"); + }, + tooltip: l('menu.undo_tt'), + })); + + editMenu.append(modals.redo = new nw.MenuItem({ + label: l('menu.redo'), + click: function () { + pdgui.pdsend(name, "redo"); + }, + tooltip: l('menu.redo_tt'), + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(modals.cut = new nw.MenuItem({ + label: l('menu.cut'), + click: function () { + pdgui.pdsend(name, "cut"); + }, + tooltip: l('menu.cut_tt'), + })); + + editMenu.append(modals.copy = new nw.MenuItem({ + label: l('menu.copy'), + click: function () { + pdgui.pdsend(name, "copy"); + }, + tooltip: l('menu.copy_tt'), + })); + + editMenu.append(modals.paste = new nw.MenuItem({ + label: l('menu.paste'), + click: function () { + pdgui.pdsend(name, "paste"); + }, + tooltip: l('menu.paste_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.duplicate'), + click: function () { + pdgui.pdsend(name, "duplicate"); + }, + key: 'd', + modifiers: "ctrl", + tooltip: l('menu.duplicate_tt') + })); + + editMenu.append(modals.selectall = new nw.MenuItem({ + label: l('menu.selectall'), + click: function (evt) { + if (canvas_events.get_state() === 'normal') { + pdgui.pdsend(name, "selectall"); + } + }, + tooltip: l('menu.selectall_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.reselect'), + // Unfortunately nw.js doesn't allow + // key: "Return" or key: "Enter", so we + // can't bind to ctrl-Enter here. (Even + // tried fromCharCode...) + click: function () { + pdgui.pdsend(name, "reselect"); + }, + key: String.fromCharCode(10), + modifiers: "ctrl", + tooltip: l('menu.reselect_tt') + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.zoomin'), + click: function () { + var z = nw.Window.get().zoomLevel; + if (z < 8) { z++; } + nw.Window.get().zoomLevel = z; + pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); + }, + key: '=', + modifiers: "ctrl", + tooltip: l('menu.zoomin') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.zoomout'), + click: function () { + var z = nw.Window.get().zoomLevel; + if (z > -7) { z--; } + nw.Window.get().zoomLevel = z; + pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); + }, + key: '-', + modifiers: "ctrl", + tooltip: l('menu.zoomout_tt'), + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.tidyup'), + click: function() { + pdgui.pdsend(name, "tidy"); + }, + key: 'y', + modifiers: "ctrl", + tooltip: l('menu.tidyup_tt') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.tofront'), + click: function() { + pdgui.popup_action(name, 3); + }, + tooltip: l('menu.tofront_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.toback'), + click: function() { + pdgui.popup_action(name, 4); + }, + tooltip: l('menu.toback_tt'), + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.font'), + click: function () { + pdgui.pdsend(name, "menufont"); + }, + tooltip: l('menu.font_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.cordinspector'), + click: function() { + pdgui.pdsend(name, "magicglass 0"); + }, + key: 'r', + modifiers: "ctrl", + tooltip: l('menu.cordinspector_tt'), + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.find'), + click: menu_generic, + key: 'f', + modifiers: "ctrl", + tooltip: l('menu.find_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.findagain'), + click: menu_generic, + key: 'g', + modifiers: "ctrl", + tooltip: l('menu.findagain') + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.finderror'), + click: function() { + pdgui.pdsend("pd finderror"); + }, + tooltip: l('menu.finderror_tt'), + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.autotips'), + click: menu_generic, + tooltip: l('menu.autotips_tt'), + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.editmode'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "editmode 0"); + }, + key: 'e', + modifiers: "ctrl", + tooltip: l('menu.editmode_tt') + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: l('menu.preferences'), + click: pdgui.open_prefs, + key: 'p', + modifiers: "ctrl", + tooltip: l('menu.preferences_tt') + })); + + // Put menu + var putMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.put'), + submenu: putMenu + })); + + // Put menu sub-entries + putMenu.append(new nw.MenuItem({ + label: l('menu.object'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "obj 0"); + }, + key: '1', + modifiers: "ctrl", + tooltip: l('menu.object_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.msgbox'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "msg 0"); + }, + key: '2', + modifiers: "ctrl", + tooltip: l('menu.msgbox_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.number'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "floatatom 0"); + }, + key: '3', + modifiers: "ctrl", + tooltip: l('menu.number_tt') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.symbol'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "symbolatom 0"); + }, + key: '4', + modifiers: "ctrl", + tooltip: l('menu.symbol_tt') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.comment'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "text 0"); + }, + key: '5', + modifiers: "ctrl", + tooltip: l('menu.comment_tt') + })); + + putMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.bang'), + click: function(e) { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "bng 0"); + }, + key: 'b', + modifiers: "ctrl-shift", + tooltip: l('menu.bang_tt') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.toggle'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "toggle 0"); + }, + key: 't', + modifiers: "ctrl-shift", + tooltip: l('menu.toggle_tt') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.number2'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "numbox 0"); + }, + key: 'n', + modifiers: "ctrl-shift", + tooltip: l('menu.number2') + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.vslider'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "vslider 0"); + }, + key: 'v', + modifiers: "ctrl-shift", + tooltip: l('menu.vslider_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.hslider'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "hslider 0"); + }, + key: 'h', + modifiers: "ctrl-shift", + tooltip: l('menu.hslider_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.vradio'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "vradio 0"); + }, + key: 'd', + modifiers: "ctrl-shift", + tooltip: l('menu.vradio_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.hradio'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "hradio 0"); + }, + key: 'i', + modifiers: "ctrl", + tooltip: l('menu.hradio_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.vu'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "vumeter 0"); + }, + key: 'u', + modifiers: "ctrl", + tooltip: l('menu.vu_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.cnv'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "mycnv 0"); + }, + key: 'c', + modifiers: "ctrl-shift", + tooltip: l('menu.cnv_tt') + })); + + putMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.graph'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + // leaving out some placement logic... see pd.tk menu_graph + pdgui.pdsend(name, "graph NULL 0 0 0 0 30 30 0 30"); + }, + tooltip: l('menu.graph_tt'), + })); + + putMenu.append(new nw.MenuItem({ + label: l('menu.array'), + click: function() { + check_box_for_text(); + pdgui.pdsend(name, "dirty 1"); + pdgui.pdsend(name, "menuarray"); + }, + tooltip: l('menu.array_tt'), + })); + + + // Windows menu... call it "winman" (i.e., window management) + // to avoid confusion + var winmanMenu = new nw.Menu(); + + // Add to windows menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.windows'), + submenu: winmanMenu + })); + + // Winman sub-entries + winmanMenu.append(new nw.MenuItem({ + label: l('menu.fullscreen'), + click: function() { + var win = nw.Window.get(); + var fullscreen = win.isFullscreen; + win.isFullscreen = !fullscreen; + pdgui.gui_post("fullscreen is " + fullscreen); + }, + key: "f11", + //modifiers: "ctrl", + tooltip: l('menu.nextwin_tt'), + })); + + winmanMenu.append(new nw.MenuItem({ + label: l('menu.nextwin'), + click: menu_generic, + key: String.fromCharCode(12), // Page down + modifiers: "ctrl", + tooltip: l('menu.nextwin_tt'), + })); + + winmanMenu.append(new nw.MenuItem({ + label: l('menu.prevwin'), + click: menu_generic, + key: String.fromCharCode(11), // Page up + modifiers: "ctrl", + tooltip: l('menu.prevwin_tt'), + })); + + winmanMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + winmanMenu.append(new nw.MenuItem({ + label: l('menu.parentwin'), + click: menu_generic, + tooltip: l('menu.parentwin_tt'), + })); + + winmanMenu.append(new nw.MenuItem({ + label: l('menu.pdwin'), + click: menu_generic, + tooltip: l('menu.pdwin_tt'), + })); + + // Media menu + var mediaMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.media'), + submenu: mediaMenu + })); + + // Media sub-entries + mediaMenu.append(new nw.MenuItem({ + label: l('menu.audio_on'), + click: function() { + pdgui.pdsend("pd dsp 1"); + }, + key: '/', + modifiers: "ctrl", + tooltip: l('menu.audio_on_tt'), + })); + + mediaMenu.append(new nw.MenuItem({ + label: l('menu.audio_off'), + click: function() { + pdgui.pdsend("pd dsp 0"); + }, + key: '.', + modifiers: "ctrl", + tooltip: l('menu.audio_off_tt'), + })); + + mediaMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + mediaMenu.append(new nw.MenuItem({ + label: l('menu.test'), + click: menu_generic, + tooltip: l('menu.test_tt'), + })); + + mediaMenu.append(new nw.MenuItem({ + label: l('menu.loadmeter'), + click: menu_generic, + tooltip: l('menu.loadmeter_tt'), + })); + + // Help menu + var helpMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: l('menu.help'), + submenu: helpMenu + })); + + // Help sub-entries + helpMenu.append(new nw.MenuItem({ + label: l('menu.about'), + click: menu_generic, + //key: 'c', + //modifiers: "ctrl", + tooltip: l('menu.about_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.manual'), + click: menu_generic, + tooltip: l('menu.manual'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.browser'), + click: menu_generic, + tooltip: l('menu.browser_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.l2ork_list'), + click: menu_generic, + tooltip: l('menu.l2ork_list_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.pd_list'), + click: menu_generic, + tooltip: l('menu.pd_list_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.forums'), + click: menu_generic, + tooltip: l('menu.forums_tt'), + })); + + helpMenu.append(new nw.MenuItem({ + label: l('menu.irc'), + click: menu_generic, + tooltip: l('menu.irc_tt'), + })); + + // Assign to window + nw.Window.get().menu = windowMenu; + +} -- GitLab