diff --git a/pd/nw/DejaVuSansMono.ttf b/pd/nw/DejaVuSansMono.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8b7bb2a4e1b2c27786398c320e9020bcc24c3af3 Binary files /dev/null and b/pd/nw/DejaVuSansMono.ttf differ diff --git a/pd/nw/index.html b/pd/nw/index.html new file mode 100644 index 0000000000000000000000000000000000000000..b8f71616f4addcecd22240fb5702e1af4bf852fa --- /dev/null +++ b/pd/nw/index.html @@ -0,0 +1,489 @@ +<!DOCTYPE html> +<html> + <head> + </head> + <body> + <input style="display:none;" id="fileDialog" type="file" nwworkingdir multiple /> + <script> + 'use strict'; + var nw = require('nw.gui'); + console.log(nw.App.argv); + var pdgui = require('./pdgui.js'); + var port_no = nw.App.argv[0]; // fed to us by the Pd process + var pwd = process.env.PWD; + pdgui.set_port(port_no); + pdgui.set_pwd(pwd); + pdgui.set_pd_window(this); + pdgui.set_app_quitfn(app_quit); + + console.log("Hello from " + pwd); + + function app_quit () { + console.log("quitting for reals"); + nw.App.quit(); + } + + var chooser = document.querySelector("#fileDialog"); + chooser.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); + + + +// prompt("hey", "you"); + + // Invoke some functions to create main menus, etc. + + nw.Window.get().on("close", function() { + pdgui.menu_quit(); +// stop-gap to shutdown properly +// this.close(true); + }); + console.log(nw.App.argv); + + document.getElementById("fileDialog").setAttribute("nwworkingdir", pwd); + document.getElementById("fileDialog").setAttribute("accept", + Object.keys(pdgui.pd_filetypes).toString()); + + nw_create_pd_window_menus(); + + pdgui.connect(); + pdgui.init_socket_events(); + + // nw context callbacks (mostly just creating/destroying windows) + pdgui.set_new_window_fn(nw_create_window); + pdgui.set_close_window_fn(nw_close_window); + + + function pdmenu_copy () { + alert("Please implement pdmenu_copy"); + } + + function pdmenu_selectall () { + alert("Please implement pdmenu_selectall"); + } + + function pdmenu_preferences () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_next_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_previous_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_parent_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_console_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_audio_on () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_audio_off () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_test_audio () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_load_meter () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_about_pd () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_manual () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_help_browser () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_l2ork_mailinglist () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_pd_mailinglists () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_forums () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_irc () { + alert("Please implement pdmenu_preferences"); + } + +// Menus for the main Pd window +function nw_create_pd_window_menus () { + // 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: 'File', + submenu: fileMenu + })); + + // File sub-entries + fileMenu.append(new nw.MenuItem({ + label: 'New', + click: pdgui.menu_new, + key: 'n', + modifiers: "ctrl" + })); + + fileMenu.append(new nw.MenuItem({ + label: 'Open', + key: 'o', + modifiers: "ctrl", + click: function (){ + var chooser = document.querySelector('#fileDialog'); + chooser.click(); + } + })); + + if (pdgui.k12_mode == 1) { + fileMenu.append(new nw.MenuItem({ + label: 'K12 Demos', + 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: 'Save', + click: function () {}, + enabled: false, + key: 's', + modifiers: "ctrl" + })); + + fileMenu.append(new nw.MenuItem({ + label: 'Save as...', + click: function (){}, + enabled: false, + key: 'S', + modifiers: "ctrl" + })); + + if (pdgui.k12_mode == 0) { + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + } + + fileMenu.append(new nw.MenuItem({ + label: 'Message...', + click: pdgui.menu_send, + key: 'm', + modifiers: "ctrl" + })); + + 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 + + // Note: there's no good reason to have this here + fileMenu.append(new nw.MenuItem({ + label: 'Close', + click: function () {}, + enabled: false, + })); + + // Quit Pd + fileMenu.append(new nw.MenuItem({ + label: 'Quit', + click: pdgui.menu_quit, + key: 'q', + modifiers: "ctrl" + })); + + + // Edit menu + var editMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: 'Edit', + submenu: editMenu + })); + + // Edit sub-entries + editMenu.append(new nw.MenuItem({ + label: 'Copy', + click: pdmenu_copy, + key: 'c', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Select All', + click: function () { + document.selectAllChildren(document); + }, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: 'Zoom In', + click: function () { + nw.Window.get().zoomLevel += 1; + pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); + }, + key: '=', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Zoom Out', + click: function () { + nw.Window.get().zoomLevel -= 1; + pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); + }, + key: '-', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Preferences...', + click: pdmenu_preferences, + key: 'a', + modifiers: "ctrl" + })); + + + // 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: 'Windows', + submenu: winmanMenu + })); + + // Winman sub-entries + winmanMenu.append(new nw.MenuItem({ + label: 'Next Window', + click: pdmenu_next_win, + key: 'c', + modifiers: "ctrl" + })); + + winmanMenu.append(new nw.MenuItem({ + label: 'Previous Window', + click: pdmenu_previous_win, + key: 'a', + modifiers: "ctrl" + })); + + winmanMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + winmanMenu.append(new nw.MenuItem({ + label: 'Parent Window', + click: pdmenu_parent_win, + key: 'a', + modifiers: "ctrl" + })); + + winmanMenu.append(new nw.MenuItem({ + label: 'Pd & Console', + click: pdmenu_console_win, + key: 'a', + modifiers: "ctrl" + })); + + // Media menu + var mediaMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: 'Media', + submenu: mediaMenu + })); + + // Media sub-entries + mediaMenu.append(new nw.MenuItem({ + label: 'Audio On', + click: function() { + pdgui.pdsend("pd dsp 1"); + }, + key: 'c', + modifiers: "ctrl" + })); + + mediaMenu.append(new nw.MenuItem({ + label: 'Audio Off', + click: function() { + pdgui.pdsend("pd dsp 0"); + }, + key: 'a', + modifiers: "ctrl" + })); + + mediaMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + mediaMenu.append(new nw.MenuItem({ + label: 'Test Audio and Midi', + click: pdmenu_test_audio, + key: 'a', + modifiers: "ctrl" + })); + + mediaMenu.append(new nw.MenuItem({ + label: 'Load Meter', + click: pdmenu_load_meter, + key: 'a', + modifiers: "ctrl" + })); + + // Help menu + var helpMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: 'Help', + submenu: helpMenu + })); + + // Help sub-entries + helpMenu.append(new nw.MenuItem({ + label: 'About Pd-L2ork', + click: pdmenu_about_pd, + key: 'c', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Manual', + click: pdmenu_manual, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Help Browser', + click: pdmenu_help_browser, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Pd-L2ork Mailing List', + click: pdmenu_l2ork_mailinglist, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Pure Data Mailing Lists', + click: pdmenu_pd_mailinglists, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Forums', + click: pdmenu_forums, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'IRC Chat', + click: pdmenu_irc, + key: 'a', + modifiers: "ctrl" + })); + + // Assign to window + nw.Window.get().menu = windowMenu; +} + +function nw_close_window(window) { + window.close(true); +} + +function nw_create_window(cid, width, height, xpos, ypos, menu_flag, resize, topmost, cnv_color, + canvas_string, dir, dirty_flag, cargs) { + // todo: make a separate way to format the title for OSX + var my_title = pdgui.format_window_title(canvas_string, dirty_flag, cargs, dir); + + var new_win = nw.Window.open('pdcanvas.html', { + title: my_title, + position: "center", + toolbar: true, + focus: true, + width: width, + height: height, + x: xpos, + y: ypos + }); + return new_win; +} + +function canvasNew(args) { + console.log(args); +} + + + + + + </script> + <input style="display:none;" id="saveDialog" type="file" nwsaveas /> + + <pre id="p1" style="white-space: pre-wrap;">Welcome to Pd GUI using Node-Webkit + <script>document.write(process.versions['node-webkit'])</script><br/></pre> + + <script> + + + </script> + </body> +</html> diff --git a/pd/nw/package.json b/pd/nw/package.json new file mode 100644 index 0000000000000000000000000000000000000000..de61b251c46c28907a3f4646afa2f2511de9b79e --- /dev/null +++ b/pd/nw/package.json @@ -0,0 +1,8 @@ +{ + "name": "my-app", + "version": "0.1.0", + "main": "index.html", + "window": { + "toolbar": true + } +} diff --git a/pd/nw/pdcanvas.css b/pd/nw/pdcanvas.css new file mode 100644 index 0000000000000000000000000000000000000000..88baa317e9d4a9598f82761739c0cbe90abfa5d3 --- /dev/null +++ b/pd/nw/pdcanvas.css @@ -0,0 +1,50 @@ +@font-face { + font-family: "DejaVu Sans Mono"; + src: url("DejaVuSansMono.ttf"); +} + +body { + margin: 0px; + font-family: "DejaVu Sans Mono"; +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +text { + // fill: red; + cursor: default; +} + +.selected_border { + stroke: blue; + stroke-dasharray: none; + stroke-width: 1; +} + +.selected_line { + stroke: blue; +} + +.broken_border { + fill: #f7f7f7; + stroke: red; + stroke-dasharray: 3 2; +} + +.xlet { + stroke: black; + fill: gray; + stroke-width: 1; + shape-rendering: optimizeSpeed; +} + +//.xlet:hover { +// stroke: red; +//} diff --git a/pd/nw/pdcanvas.html b/pd/nw/pdcanvas.html new file mode 100644 index 0000000000000000000000000000000000000000..9bd9af314103021e2233b364dd70403d8478956f --- /dev/null +++ b/pd/nw/pdcanvas.html @@ -0,0 +1,1009 @@ +<!DOCTYPE html> +<html> + <head> + </head> + <link rel="stylesheet" type="text/css" href="pdcanvas.css"> + <body> + <input style="display:none;" id="fileDialog" type="file" multiple /> + <input style="display:none;" id="saveDialog" type="file" nwsaveas nwworkingdir accept=".pd" /> + <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="patchsvg" height="1000" width="1000" class="noselect"> + <rect/> + </svg> + <script> + 'use strict'; + var nw = require('nw.gui'); + var pdgui = require('./pdgui.js'); + + var name = pdgui.last_loaded(); + + console.log("my working dire 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()); + + + + // 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); + } + })); + + document.querySelector("#saveDialog").addEventListener("change", function(evt) { + pdgui.saveas_callback(name, this.value); + 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.addEventListener("mousemove", function(evt) { + //pdgui.gui_post("x: " + evt.pageX + " y: " + evt.pageY + + // " modifier: " + (evt.shiftKey + (evt.ctrlKey << 1))); + pdgui.pdsend(name + " motion " + evt.pageX + " " + evt.pageY + " " + + (evt.shiftKey + (evt.ctrlKey << 1))); + evt.stopPropagation(); +// evt.preventDefault(); + return false; + }); + + var last_keydown = ""; + + + function add_keymods(key, evt) { + var shift = evt.shiftKey ? "Shift" : ""; + var ctrl = evt.ctrlKey ? "Ctrl" : ""; + return shift + ctrl + key; + } + + document.addEventListener("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; + + // 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(); + }); + + document.addEventListener("keypress", function(evt) { + 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(); + }); + + document.addEventListener("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); + }); + + // just left-clicks for the moment + document.onmousedown = function(evt) { + //pdgui.gui_post("mousedown: x: " + evt.pageX + " y: " + evt.pageY + + // " button: " + (evt.button + 1) + " modifier: " + (evt.shiftKey + (evt.ctrlKey << 1))); + // tk events 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 + " " + evt.pageY + " " + + b + " " + mod); + evt.stopPropagation(); + evt.preventDefault(); + } + + document.onmouseup = function(evt) { + //pdgui.gui_post("mouseup: x: " + evt.pageX + " y: " + evt.pageY + + // " button: " + (evt.button + 1)); + pdgui.pdsend(name + " mouseup " + evt.pageX + " " + evt.pageY + " " + + (evt.button + 1)); + } + + + + + // let's handle some events for this window... + + // closing the Window + // this isn't actually closing the window yet + nw.Window.get().on("close", function() { + pdgui.pdsend(name + " menuclose 0"); + }); + // draw the objects in the patch once we've finished loading this boilerplate page + // We could probably use the window.onload here, which would make it standard javascript + this.onload = function() { + pdgui.canvas_map(name); + }; + + + + + +nw_create_patch_window_menus(name); + + function menu_generic () { + alert("Please implement this"); + } + + function pdmenu_copy () { + alert("Please implement pdmenu_copy"); + } + + function pdmenu_selectall () { + alert("Please implement pdmenu_selectall"); + } + + function pdmenu_preferences () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_next_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_previous_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_parent_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_console_win () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_audio_on () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_audio_off () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_test_audio () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_load_meter () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_about_pd () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_manual () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_help_browser () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_l2ork_mailinglist () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_pd_mailinglists () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_forums () { + alert("Please implement pdmenu_preferences"); + } + + function pdmenu_irc () { + alert("Please implement pdmenu_preferences"); + } + +// Menus for the Patch window +function nw_create_patch_window_menus () { + + // 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: 'File', + submenu: fileMenu + })); + + // File sub-entries + fileMenu.append(new nw.MenuItem({ + label: 'New', + click: pdgui.menu_new, + key: 'n', + modifiers: "ctrl" + })); + + fileMenu.append(new nw.MenuItem({ + label: 'Open', + key: 'o', + modifiers: "ctrl", + click: function (){ + var chooser = document.querySelector('#fileDialog'); + chooser.click(); + } + })); + + if (pdgui.k12_mode == 1) { + fileMenu.append(new nw.MenuItem({ + label: 'K12 Demos', + 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: 'Save', + click: function () { + pdgui.menu_save(name); + }, + key: 's', + modifiers: "ctrl" + })); + + fileMenu.append(new nw.MenuItem({ + label: 'Save as...', + click: function (){ + pdgui.menu_saveas(name); + }, + key: 's', + modifiers: "ctrl+shift" + })); + + if (pdgui.k12_mode == 0) { + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + } + + fileMenu.append(new nw.MenuItem({ + label: 'Message...', + click: pdgui.menu_send, + key: 'm', + modifiers: "ctrl" + })); + + 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: 'Close', + click: function() { + pdgui.menu_close(name); + } + })); + + // Quit Pd + fileMenu.append(new nw.MenuItem({ + label: 'Quit', + click: pdgui.menu_quit, + key: 'q', + modifiers: "ctrl" + })); + + + // Edit menu + var editMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: 'Edit', + submenu: editMenu + })); + + // Edit sub-entries + editMenu.append(new nw.MenuItem({ + label: 'Undo', + click: menu_generic, + key: 'c', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Redo', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: 'Cut', + click: menu_generic, + key: 'c', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Copy', + click: menu_generic, + key: 'c', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Paste', + click: menu_generic, + key: 'c', + modifiers: "ctrl" + })); + + + editMenu.append(new nw.MenuItem({ + label: 'Duplicate', + click: menu_generic, + key: 'c', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Select All', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Reselect', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: 'Zoom In', + click: function () { + nw.Window.get().zoomLevel += 1; + pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); + }, + key: '=', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Zoom Out', + click: function () { + nw.Window.get().zoomLevel -= 1; + pdgui.gui_post("zoom level is " + nw.Window.get().zoomLevel); + }, + key: '-', + modifiers: "ctrl" + })); + + + + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: 'Tidy Up', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Bring to Front', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Send to Back', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: 'Font', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Cord Inspector', + click: function() { + pdgui.pdsend(name + " magicglass 0"); + }, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: 'Find', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Find Again', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Find Last Error', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: 'Autotips', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + label: 'Editmode', + click: function() { pdgui.pdsend(name + " editmode 0"); }, + key: 'e', + modifiers: "ctrl" + })); + + editMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + editMenu.append(new nw.MenuItem({ + label: 'Preferences...', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + // Put menu + var putMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: 'Put', + submenu: putMenu + })); + + // Put menu sub-entries + putMenu.append(new nw.MenuItem({ + label: 'Object', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " obj 0"); + }, + key: '1', + modifiers: "ctrl" + })); + +/* + +proc menu_floatatom {name accel} { + pd [concat $name dirty 1 \;] + pd [concat $name floatatom $accel \;] +} + +proc menu_symbolatom {name accel} { + pd [concat $name dirty 1 \;] + pd [concat $name symbolatom $accel \;] +} + +proc menu_comment {name accel} { + pd [concat $name dirty 1 \;] + pd [concat $name text $accel \;] +} + +proc menu_graph {name} { + pd [concat $name dirty 1 \;] + set xdraw [expr int([$name.c canvasx 0])] + set ydraw [expr int([$name.c canvasy 0])] + pd [concat $name graph NULL 0 0 0 0 [expr $xdraw+30] [expr $ydraw+30] 0 [expr $ydraw+30]\;] + #pd [concat $name graph \;] +} + +proc menu_array {name} { + pd [concat $name dirty 1 \;] + pd [concat $name menuarray \;] +} + + +*/ + + putMenu.append(new nw.MenuItem({ + label: 'Message', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " msg 0"); + }, + key: '2', + modifiers: "ctrl" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Number', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " floatatom 0"); + }, + key: '3', + modifiers: "ctrl" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Symbol', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " symbolatom 0"); + }, + key: '4', + modifiers: "ctrl" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Comment', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " text 0"); + }, + key: '5', + modifiers: "ctrl" + })); + + putMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + putMenu.append(new nw.MenuItem({ + label: 'Bang', + click: function(e) { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " bng 0"); + }, + key: 'b', + modifiers: "ctrl-shift" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Toggle', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " toggle 0"); + }, + key: 't', + modifiers: "ctrl-shift" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Number2', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " numbox 0"); + }, + key: 'n', + modifiers: "ctrl-shift" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Vslider', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " vslider 0"); + }, + key: 'v', + modifiers: "ctrl-shift" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Hslider', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " hslider 0"); + }, + key: 'h', + modifiers: "ctrl-shift" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Vradio', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " vradio 0"); + }, + key: 'd', + modifiers: "ctrl" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Hradio', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " hradio 0"); + }, + key: 'i', + modifiers: "ctrl" + })); + + putMenu.append(new nw.MenuItem({ + label: 'VU', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " vumeter 0"); + }, + key: 'u', + modifiers: "ctrl" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Canvas', + click: function() { + pdgui.pdsend(name + " dirty 1"); + pdgui.pdsend(name + " mycnv 0"); + }, + key: 'c', + modifiers: "ctrl" + })); + + putMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + putMenu.append(new nw.MenuItem({ + label: 'Graph', + click: function() { + 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"); + }, + key: 'a', + modifiers: "ctrl" + })); + + putMenu.append(new nw.MenuItem({ + label: 'Array', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + + // 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: 'Windows', + submenu: winmanMenu + })); + + // Winman sub-entries + winmanMenu.append(new nw.MenuItem({ + label: 'Next Window', + click: menu_generic, + key: 'c', + modifiers: "ctrl" + })); + + winmanMenu.append(new nw.MenuItem({ + label: 'Previous Window', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + winmanMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + winmanMenu.append(new nw.MenuItem({ + label: 'Parent Window', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + winmanMenu.append(new nw.MenuItem({ + label: 'Pd & Console', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + // Media menu + var mediaMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: 'Media', + submenu: mediaMenu + })); + + // Media sub-entries + mediaMenu.append(new nw.MenuItem({ + label: 'Audio On', + click: menu_generic, + key: 'c', + modifiers: "ctrl" + })); + + mediaMenu.append(new nw.MenuItem({ + label: 'Audio Off', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + mediaMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + mediaMenu.append(new nw.MenuItem({ + label: 'Test Audio and Midi', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + mediaMenu.append(new nw.MenuItem({ + label: 'Load Meter', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + // Help menu + var helpMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: 'Help', + submenu: helpMenu + })); + + // Help sub-entries + helpMenu.append(new nw.MenuItem({ + label: 'About Pd-L2ork', + click: menu_generic, + key: 'c', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Manual', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Help Browser', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + type: 'separator' + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Pd-L2ork Mailing List', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Pure Data Mailing Lists', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'Forums', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + helpMenu.append(new nw.MenuItem({ + label: 'IRC Chat', + click: menu_generic, + key: 'a', + modifiers: "ctrl" + })); + + // Assign to window + nw.Window.get().menu = windowMenu; + +} + + + +/* +function nw_create_canvas_window_menus(name) { + // Window menu + var windowMenu = new nw.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: 'File', + submenu: fileMenu + })); + + // File sub-entries + fileMenu.append(new nw.MenuItem({ + label: 'New', + click: pdgui.menu_new, + key: 'n', + modifiers: "ctrl" + })); + + fileMenu.append(new nw.MenuItem({ + label: 'Open', + key: 'o', + modifiers: "ctrl", + click: function (){ + var chooser = document.querySelector('#fileDialog'); + chooser.click(); + chooser.addEventListener("change", function(evt) { + menu_open(this.value); + console.log("tried to open something"); + }, false); + } + })); + + if (pdgui.k12_mode == 1) { + fileMenu.append(new nw.MenuItem({ + label: 'K12 Demos', + 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: 'Save', + click: function (){ + pdgui.menu_save(name); + }, + key: 's', + modifiers: "ctrl" + })); + + fileMenu.append(new nw.MenuItem({ + label: 'Save as...', + click: function (){ + pdgui.menu_saveas(name); + }, + key: 'S', + modifiers: "ctrl" + })); + + if (pdgui.k12_mode == 0) { + fileMenu.append(new nw.MenuItem({ + type: 'separator' + })); + } + + // Assign to window + nw.Window.get().menu = windowMenu; +} +*/ + + </script> + </body> +</html> diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js new file mode 100644 index 0000000000000000000000000000000000000000..825bafcca3a97700da137998c8579acad0dca7fa --- /dev/null +++ b/pd/nw/pdgui.js @@ -0,0 +1,2695 @@ +'use strict'; + +// Modules + +var pwd; + +exports.set_pwd = function(pwd_string) { + pwd = pwd_string; +} + +exports.get_pwd = function() { + return pwd; +} + +var fs = require('fs'); // for fs.existsSync +var path = require('path'); // for path.dirname path.extname + +var pd_window; +exports.pd_window; + +exports.set_pd_window = function(win) { + pd_window = win; + exports.pd_window = win; +} + +var nw_create_window; +var nw_close_window; +var nw_app_quit; + +exports.set_new_window_fn = function (nw_context_fn) { + nw_create_window = nw_context_fn; +} + +exports.set_close_window_fn = function (nw_context_fn) { + nw_close_window = nw_context_fn; +} + +// Global variables from tcl +var pd_myversion, // Pd version string + pd_apilist, // Available Audio APIs (tcl list) + pd_midiapilist, // MIDI APIsa (tcl list) + pd_nt, // Something to do with Windows configuration + fontname, // Font + fontweight, // config + pd_fontlist, // (Seems to be hard coded in Pd-l2ork) + pd_whichmidiapi, // MIDI API, set by pd->gui message + pd_whichapi, // Audio API, set by pd->gui message + pd_opendir, // + pd_guidir, // + pd_tearoff, // + put_tearoff, // + tcl_version, // + canvas_fill, // + colors, // + global_clipboard, // + global_selection, // + k12_mode = 0, // should be set from argv ('0' is just a stopgap) + k12_saveas_on_new, // + autotips, // tooltips + magicglass, // cord inspector + window_prefs, //retaining window-specific preferences + pdtk_canvas_mouseup_name, // not sure what this does + filetypes, // valid file extensions for opening/saving (includes Max filetypes) + untitled_number, // number to increment for each new patch that is opened + untitled_directory, // default directory where to create/save new patches + popup_coords, // x/y for current popup window (global because there's only one at a time) + pd_colors = {}; // associative array of canvas color presets + + var pd_filetypes = { ".pd": "Pd Files", + ".pat":"Max Patch Files", + ".mxt":"Max Text Files", + ".mxb":"Max Binary Files", + ".help":"Max Help Files" + }; + + exports.k12_mode = k12_mode; + exports.pd_filetypes = pd_filetypes; + + popup_coords = [0,0]; + + var startup_files = []; // Array of files to be opened at startup (from the command line) + + var pd_keymap = {}; // to iteratively map keydown/keyup keys + // to keypress char codes + +function set_keymap(keycode, charcode) { + pd_keymap[keycode] = charcode; +} + +exports.set_keymap = set_keymap; + +function get_char_code(keycode) { + return pd_keymap[keycode]; +} + +exports.get_char_code = get_char_code; + + // Hard-coded Pd-l2ork font metrics +/* +var font_fixed_metrics = "\ +8 5 11 \ +9 6 12 \ +10 6 13 \ +12 7 16 \ +14 8 17 \ +16 10 19 \ +18 11 22 \ +24 14 29 \ +30 18 37 \ +36 22 44"; +*/ + +// Let's try to get some metrics specific to Node-webkit... + // Hard-coded Pd-l2ork font metrics +var font_fixed_metrics = "\ +8 5 11 \ +9 6 12 \ +10 6 13 \ +12 7 16 \ +14 8 17 \ +16 10 19 \ +18 11 22 \ +24 14 29 \ +30 18 37 \ +36 22 44"; + + +// Utility Functions + +// originally used to enquote a string to send it to a tcl function +function enquote (x) { + var foo = x.replace(/,/g, ""); + foo = foo.replace(/;/g, ""); + foo = foo.replace(/"/g, ""); + foo = foo.replace(/ /g, "\\ "); + foo = foo.trim(); + return foo; +} + +// from stackoverflow.com/questions/21698906/how-to-check-if-a-path-is-absolute-or-relative +// this doesn't seem to be needed atm +function path_is_absolute(myPath) { + var ret = (path.resolve(myPath) === path.normalize(myPath).replace(/(.+)([\/]\\])$/, '$1')); + return ret; +} + +function set_midiapi(val) { + pd_whichmidiapi = val; +} + +function set_audioapi(val) { + pd_whichapi = val; +} + +function gui_post(string, color) { + if (color === undefined) { color = "black" }; + var myp = pd_window.document.getElementById('p1'); + var text; + var span = pd_window.document.createElement("span"); + span.style.color = color; + var text = pd_window.document.createTextNode(string + "\n"); + span.appendChild(text); + myp.appendChild(span); + pd_window.window.scrollTo(0, pd_window.document.body.scrollHeight); +} + +exports.gui_post = gui_post; + +function pd_error_select_by_id(objectid) { + if (objectid !== null) { + pdsend("pd findinstance " + objectid); + } +} +exports.pd_error_select_by_id = pd_error_select_by_id + +function gui_post_error(objectid, loglevel, errormsg) { + var my_p = pd_window.document.getElementById('p1'); + // if we have an object id, make a friendly link... + var error_title = pd_window.document.createTextNode("error"); + if (objectid.length > 0) { + var my_a = pd_window.document.createElement('a'); + my_a.href = "javascript:pdgui.pd_error_select_by_id('" + objectid + "')"; + my_a.appendChild(error_title); + my_p.appendChild(my_a); + } else { + my_p.appendChild(error_title); + } + var rest = pd_window.document.createTextNode(": " + errormsg + "\n"); + my_p.appendChild(rest); + + // looks like tcl/tk tried to throttle this... maybe we should, too... + /* + after cancel .printout.frame.text yview end-2char + after idle .printout.frame.text yview end-2char + .printout.frame.text configure -state disabled + */ +} + +function menu_save(name) { +// gui_post(name + " menusave"); + pdsend(name + " menusave"); +} + +exports.menu_save = menu_save; + +function gui_canvas_saveas (name, initfile, initdir) { + gui_post("working directory is " + pwd); + //global pd_nt filetypes untitled_directory + if (!fs.existsSync(initdir)) { + initdir = pwd; + } +// patchwin[name].window.document.getElementById("fileDialog").setAttribute("nwworkingdir", pwd); + var chooser = patchwin[name].window.document.querySelector('#saveDialog'); + chooser.click(); +// chooser.addEventListener("change", function(evt) { +// saveas_callback(name, this.value); +// console.log("tried to open something"); +// }, false); +} + +function saveas_callback(cid, file) { + gui_post("tried a saveas, and the file chosen is " + file); + var filename = file; + // It probably isn't possible to arrive at the callback with an + // empty string. But I've only tested on Debian so far... + if (filename === null) { + return; + } + // We don't need to use the codepath below because node-webkit + // let's us specify the allowed files extensions. Lo and behold, + // nw just does the "right thing" whether the user types an extension + // or not. This should put us on part with Microsoft Word in the late + // 90s. + //var lc = filename.toLowerCase(); + //if (lc.slice(-3) !== '.pd' && + // lc.slice(-4) !== '.pat' && + // lc.slice(-4) !== '.mxt') { + // remove any other extensions + // filename = filename.slice(0, + // (filename.length - path.extname(filename).length)); + // add ".pd" + // filename = filename + '.pd'; + //} + // test again after downcasing and maybe adding a ".pd" on the end + //if (fs.existsSync(filename)) { + // var reply = patchwin[cid].window.confirm(filename + + // " already exists. Do you want to replace it?"); + // if (!reply) { + // return; + // } + //} + var directory = path.dirname(filename); + var basename = path.basename(filename); + pdsend(cid + " savetofile " + enquote(basename) + " " + + enquote(directory)); + + // haven't implemented these last few commands yet... + // set untitled_directory $directory + // add to recentfiles + //::pd_guiprefs::update_recentfiles "$filename" 1 +} + +exports.saveas_callback = saveas_callback; + +function menu_saveas(name) { + pdsend(name + " menusaveas"); +} + +exports.menu_saveas = menu_saveas; + +function menu_new () { + //if { ! [file isdirectory $untitled_directory]} {set untitled_directory $::env(HOME)} + untitled_directory = pwd; + pdsend("pd filename " + "Untitled-" + untitled_number + " " + enquote(untitled_directory)); + if (k12_mode == 1) { + k12_saveas_on_new = 1; + pdsend("#N canvas"); + pdsend("#X obj -30 -30 preset_hub k12 1 %hidden%"); + pdsend("#X pop 1"); + } else { + pdsend("#N canvas"); + pdsend("#X pop 1"); + } + untitled_number++; +} + +exports.menu_new = menu_new; + +function gui_close_window(cid) { + nw_close_window(patchwin[cid]); +} + +function menu_k12_open_demos () { + +} + +exports.menu_k12_open_demos = menu_k12_open_demos; + + +function menu_open (filenames_string) { + gui_post("menu_open " + filenames_string); + var file_array = filenames_string.split(";"); + var length = file_array.length; + gui_post("file_array is " + file_array); + for (var i = 0; i < length; i++) { + open_file(file_array[i]); + } +} + +exports.menu_open = menu_open; + +function menu_close(name) { + // not handling the "text editor" yet + // not handling the "Window" menu yet + //pdtk_canvas_checkgeometry $name + pdsend(name + " menuclose 0"); +} + +exports.menu_close = menu_close; + +function canvas_menuclose_callback(cid_for_dialog, cid, force) { + // Hacky-- this should really be dir/filename here instead of + // filename/args/dir which is ugly + var title = patchwin[cid_for_dialog].window.document.title; + var reply = patchwin[cid_for_dialog].window.confirm("Save changes to " + title + "?"); + if (reply) { + pdsend(cid_for_dialog + " menusave"); + } else { + pdsend(cid_for_dialog + " dirty 0"); + pdsend(cid + " menuclose " + force); + } +} + +function gui_canvas_menuclose(cid_for_dialog, cid, force) { + // Hack to get around a renderer bug-- not guaranteed to work + // for long patches + setTimeout(function() { + canvas_menuclose_callback(cid_for_dialog, cid, force); + }, 450); +} + +function gui_pd_quit_dialog() { + var reply = pd_window.window.confirm("Really quit?"); + if (reply === true) { + pdsend("pd quit"); + } +} + +// send a message to Pd +function menu_send() { + gui_post("message...pdwindow is " + pd_window); + var message = pd_window.window.prompt("Type a message to send to Pd"); + if (message != undefined && message.length) { + gui_post("Sending message to Pd: " + message + ";"); + pdsend(message); + } +} + +exports.menu_send = menu_send; + +function menu_quit() { + pdsend("pd verifyquit"); +} + +exports.menu_quit = menu_quit; + +var nw_app_quit; + +function app_quit() { + nw_app_quit(); +} + +exports.set_app_quitfn = function(quitfn) { + nw_app_quit = quitfn; +} + +function open_file(file) { + //from tcl... + //global pd_opendir pd_guidir pd_nt + gui_post("open_file: " + file); + var directory = path.dirname(file); + var basename = path.basename(file); + var cyclist; + if (basename.match(/\.(pat|mxb|help)$/) !=null) { + gui_post("warning: opening pat|mxb|help not implemented yet"); + //gui_post("converting " + filename); + if (pd_nt == 0) { + // on GNU/Linux, cyclist is installed into /usr/bin usually + cyclist = "/usr/bin/cyclist"; + } else { + cyclist = pd_guidir + "/bin/cyclist" + } + //gui_post(cyclist + filename); + //convert Max binary to text .pat + // The following is tcl code which needs to get converted to javascript... + //set binport [open "| \"$cyclist\" \"$filename\""] + //set convertedtext [read $binport] + //if { ! [catch {close $binport} err]} { + // if {! [file writable $directory]} { set directory "/tmp" } + // set basename "$basename.pat" + // set textpatfile [open "$directory/$basename" w] + // puts $textpatfile $convertedtext + // close $textpatfile + // puts stderr "converted Max binary to text format: $directory/$basename" + //} + } + if (basename.match(/\.(pd|pat|mxt)$/i) != null) { + pdsend("pd open" + " " + enquote(basename) + " " + enquote(directory)); + pd_opendir = directory; + //::pd_guiprefs::update_recentfiles "$filename" 1 + } +} + +// Doesn't work yet... need to figure out how to send command line args (files) to be opened by +// the unique instance +function gui_open_files_via_unique(filenames) +{ + gui_post("pdtk_open_files_via_unique " + filenames); + length = filenames.length; + if (length != 0) { + for (var i = 0; i < length; i++) { + var file = filenames[i]; + //gui_post("open_file " + file); + open_file(file); + } + } +} + +function gui_build_filelist(file) { + startup_files.push(file); +} + +// This doesn't work at the moment. Not sure how to feed the command line filelist to a single +// instance of node-webkit. +function gui_check_unique (unique) { + // gui_post("pdtk_check_unique " + unique); + // global appname + return; + var final_filenames = new Array; + var startup_dir = pwd; + if (unique == 0) { + var filelist_length = startup_files.length; + for (var i = 0; i < filelist_length; i++) { + var file = startup_files[i]; + var dir; + //gui_post (file [file dirname $file] $startup_dir" + if (!pathIsAbsolute(file)) { + file = fs.join(pwd, file); + } + final_filenames.push(file); + } + gui_open_files_via_unique(final_filenames); + } + // old tcl follows... + //if path is relative + //then join pwd and relative path + //else + //use the absolute path + //(no need to check for existence here) + + // catch {cd [file dirname $file]} + // set dir [pwd] + + //file tail should be the filename + + // set name [file tail $file] + // #puts stderr "********DIR:$dir FILE:$name COMBINED:[file join $dir $name]" + // lappend final_filenames [file join $dir $name] + // cd $startup_dir + // } + // #puts stderr "send pd-l2ork pdtk_open_files_via_unique $final_filenames" + // set outcome [catch {send pd-l2ork pdtk_open_files_via_unique \{$final_filenames\}}] + // #puts stderr "outcome = $outcome" + // if { $outcome == 0 } { + // menu_really_quit + // exit + // } + //} + // tk appname $appname + // #puts stderr "this is unique instance [tk appname]" +} + + + +function gui_startup(version, apilist, midiapilist, fontname_from_pd, fontweight_from_pd) { + console.log("we're starting up..."); + // # tb: user defined typefaces + // our args: +// console.log(version); +// console.log(apilist); +// console.log(fontname); + + // set some global variables + pd_myversion = version; + pd_apilist = apilist; + pd_midiapilist = midiapilist; + + fontname = fontname_from_pd; + fontweight = fontweight_from_pd; + pd_fontlist = ""; + untitled_number = 1; // global variable to increment for each new patch + + // From tcl, not sure if needed... + // # on Mac OS X, lower the Pd window to the background so patches open on top + // if {$pd_nt == 2} { lower . } + // # on Windows, raise the Pd window so that it has focused when launched + // if {$pd_nt == 1} { raise . } + +// set fontlist "" +// if {[info tclversion] >= 8.5} {find_default_font} +// set_base_font $fontname_from_pd $fontweight_from_pd +// fit_font_into_metrics + +// # UBUNTU MONO 6 6 8 10 11 14 14 19 22 30 +// # DEJAVU SANS MONO 6 6 8 9 10 12 14 18 22 29 + +//# foreach i {6 6 8 10 11 14 14 19 22 30} { +//# set font [format {{%s} %d %s} $fontname_from_pd $i $fontweight_from_pd] +//# set pd_fontlist [linsert $pd_fontlist 100000 $font] +//# set width0 [font measure $font x] +//# set height0 [lindex [font metrics $font] 5] +//# set fontlist [concat $fontlist $i [font measure $font x] \ +//# [lindex [font metrics $font] 5]] +//# } + +// set tclpatch [info patchlevel] +// if {$tclpatch == "8.3.0" || \ +// $tclpatch == "8.3.1" || \ +// $tclpatch == "8.3.2" || \ +// $tclpatch == "8.3.3" } { +// set oldtclversion 1 +// } else { +// set oldtclversion 0 +// } + pdsend("pd init " + enquote(pwd) + " 0 " + font_fixed_metrics); + +// # add the audio and help menus to the Pd window. We delayed this +// # so that we'd know the value of "apilist". +// menu_addstd .mbar + +// global pd_nt +// if {$pd_nt == 2} { +// global pd_macdropped pd_macready +// set pd_macready 1 +// foreach file $pd_macdropped { +// pd [concat pd open [pdtk_enquote [file tail $file]] \ +// [pdtk_enquote [file dirname $file]] \;] +// menu_doc_open [file dirname $file] [file tail $file] +// } +// } +} + + + + + + + +/* + // Some other menu + var fooMenu = new nw.Menu(); + + // Add to window menu + windowMenu.append(new nw.MenuItem({ + label: 'Foo', + submenu: fooMenu + })); + + // Foo sub-entry + fooMenu.append(new nw.MenuItem({ + label: 'flub', + click: function(){ + alert('Foo flub'); + } + })); + + // Another Foo sub-entry + fooMenu.append(new nw.MenuItem({ + label: 'bub', + click: function(){ + alert('Foo bub'); + } + })); +} + + +/* +function canvas_create_menus(name) { + // the "File" menu + + // The menus are instantiated here for the patch windows. + // For the main window, they are created on load, at the + // top of this file. + match_linux_wm [list menu $name.m -relief flat] + match_linux_wm [list menu $name.m.file -postcommand [concat pdtk_fixfilemenu $name.m.file] -tearoff $pd_tearoff] + $name.m add cascade -label File -menu $name.m.file + + $name.m.file add command -label New -command {menu_new} \ + -accelerator [accel_munge "Ctrl+n"] + + $name.m.file add command -label Open -command {menu_open} \ + -accelerator [accel_munge "Ctrl+o"] + + if { $k12_mode == 1 } { + $name.m.file add command -label {K12 Demos} -command {menu_k12_open_demos} + } + + match_linux_wm [list $name.m.file add separator] + + $name.m.file add command -label Save -command [concat menu_save $name] \ + -accelerator [accel_munge "Ctrl+s"] + + $name.m.file add command -label "Save as..." \ + -command [concat menu_saveas $name] \ + -accelerator [accel_munge "Ctrl+S"] + if { $k12_mode == 0 } { + match_linux_wm [list $name.m.file add separator] + + # arrange menus according to Apple HIG + if {$pd_nt != 2 } { + $name.m.file add command -label "Message..." -command {menu_send} \ + -accelerator [accel_munge "Ctrl+m"] + # these are now part of Preferences... on Mac OS X + $name.m.file add command -label Path... \ + -command {pd pd start-path-dialog \;} + $name.m.file add command -label Startup... \ + -command {pd pd start-startup-dialog \;} + } else { + # Cmd-m is minimize window on Mac OS X + $name.m.file add command -label "Message..." -command {menu_send} + match_linux_wm [list $name.m.file add separator] + $name.m.file add command -label "Make app from patch..." \ + -command {menu_makeapp 0} + $name.m.file add command -label "Make app from folder..." \ + -command {menu_makeapp 1} + } + match_linux_wm [list $name.m.file add separator] + $name.m.file add command -label "Print..." -command [concat menu_print $name] \ + -accelerator [accel_munge "Ctrl+p"] + } + # update recent files + match_linux_wm [list $name.m.file add separator] + $name.m.file add command -label "No Recent Files" -state disabled + #match_linux_wm [list $name.m.file add separator] + #if {[llength $::recentfiles_list] > 0} { + # ::pd_menus::update_recentfiles_menu $name.m.file false + #} + + match_linux_wm [list $name.m.file add separator] + $name.m.file add command -label Close \ + -command [concat menu_close $name] \ + -accelerator [accel_munge "Ctrl+w"] + + if {$pd_nt != 2} { + # Mac OS X doesn't put Quit on the File menu + $name.m.file add command -label Quit -command {menu_quit} \ + -accelerator [accel_munge "Ctrl+q"] + } + + # the "Edit" menu + match_linux_wm [list menu $name.m.edit -postcommand [concat menu_fixeditmenu $name] -tearoff $pd_tearoff] + $name.m add cascade -label Edit -menu $name.m.edit + + $name.m.edit add command -label Undo -command [concat menu_undo $name] \ + -accelerator [accel_munge "Ctrl+z"] + + $name.m.edit add command -label Redo -command [concat menu_redo $name] \ + -accelerator [accel_munge "Ctrl+Z"] + + match_linux_wm [list $name.m.edit add separator] + + $name.m.edit add command -label Cut -command [concat menu_cut $name] \ + -accelerator [accel_munge "Ctrl+x"] -state disabled + + $name.m.edit add command -label Copy -command [concat menu_copy $name] \ + -accelerator [accel_munge "Ctrl+c"] -state disabled + + $name.m.edit add command -label Paste \ + -command [concat menu_paste $name] \ + -accelerator [accel_munge "Ctrl+v"] + + if {!$global_clipboard} { + $name.m.edit entryconfigure "Paste" -state disabled + } else { + $name.m.edit entryconfigure "Paste" -state normal + } + + $name.m.edit add command -label Duplicate \ + -command [concat menu_duplicate $name] \ + -accelerator [accel_munge "Ctrl+d"] + + if {!$global_selection} { + $name.m.edit entryconfigure "Duplicate" -state disabled + } else { + $name.m.edit entryconfigure "Duplicate" -state normal + } + + $name.m.edit add command -label {Select all} \ + -command [concat menu_selectall $name] \ + -accelerator [accel_munge "Ctrl+a"] + + if { $k12_mode == 0 } { + $name.m.edit add command -label {Reselect} \ + -command [concat menu_reselect $name] \ + -accelerator "Ctrl+Enter" -state disabled + } + + match_linux_wm [list $name.m.edit add separator] + + $name.m.edit add command -label {Tidy Up} \ + -command [concat menu_tidyup $name] \ + -accelerator [accel_munge "Ctrl+y"] -state disabled + + if { $k12_mode == 0 } { + + $name.m.edit add command -label {Bring To Front} \ + -command [concat popup_action $name 3] \ + -accelerator [accel_munge "Ctrl+Up"] -state disabled + + $name.m.edit add command -label {Send To Back} \ + -command [concat popup_action $name 4] \ + -accelerator [accel_munge "Ctrl+Down"] -state disabled + } + + match_linux_wm [list $name.m.edit add separator] + + if { $k12_mode == 0 } { + + #if {$pd_nt == 2} { # no key command on Mac OS X, conflicts with standard + # $name.m.edit add command -label {Text Editor} \ + # -command [concat menu_texteditor $name] + #} else { + # $name.m.edit add command -label {Text Editor} \ + # -accelerator [accel_munge "Ctrl+t"] \ + # -command [concat menu_texteditor $name] + #} + + $name.m.edit add command -label Font \ + -command [concat menu_font $name] + } + +## jsarlo + $name.m.edit add checkbutton -label "Cord Inspector" \ + -indicatoron false -selectcolor black \ + -command [concat menu_magicglass $name] \ + -accelerator [accel_munge "Ctrl+r"] + + #if { $editable == 0 } { + # $name.m.edit entryconfigure "Cord Inspector" -indicatoron false } + + match_linux_wm [list $name.m.edit add separator] +## end jsarlo + + $name.m.edit add command -label "Toggle console" \ + -accelerator [accel_munge "Ctrl+R"] \ + -command [concat .controls.switches.console invoke] + + $name.m.edit add command -label "Clear console" \ + -accelerator [accel_munge "Ctrl+L"] \ + -command [concat menu_clear_console] + + match_linux_wm [list $name.m.edit add separator] + + if { $k12_mode == 0 } { + + # Apple, Microsoft, and others put find functions in the Edit menu. + $name.m.edit add command -label {Find...} \ + -accelerator [accel_munge "Ctrl+f"] \ + -command [concat menu_findobject $name] + $name.m.edit add command -label {Find Again} \ + -accelerator [accel_munge "Ctrl+g"] \ + -command [concat menu_findagain $name] + $name.m.edit add command -label {Find last error} \ + -command [concat menu_finderror] + + match_linux_wm [list $name.m.edit add separator] + + ############iemlib################## + # instead of "red = #BC3C60" we take "grey85", so there is no difference, + # if widget is selected or not. + + $name.m.edit add checkbutton -label "Autotips" \ + -indicatoron false -selectcolor black \ + -command [concat menu_tooltips $name] \ + -accelerator [accel_munge "Ctrl+E"] + } + + $name.m.edit add checkbutton -label "Edit mode" \ + -indicatoron false -selectcolor black \ + -command [concat menu_editmode $name] \ + -accelerator [accel_munge "Ctrl+e"] + if {$k12_mode == 0} { + match_linux_wm [list $name.m.edit add separator] + $name.m.edit add command -label {Preferences...} \ + -command {::dialog_prefs::open_prefs_dialog .} + } + + if { $editable == 1 } { + $name.m.edit entryconfigure "Edit mode" -background "#7dd37d" -foreground black + } + + if { $k12_mode == 0 && $autotips == 1 } { + $name.m.edit entryconfigure "Autotips" -background "#7dd37d" -foreground "#dddddd" + } + + set ::editmode($name) $editable + + #if { $magicglass == 1 } { + # $name.m.edit entryconfigure "Cord Inspector" -background "#7dd37d" + # menu_magicglass $name + #} + + #if { $editable == 0 } { + # $name.m.edit entryconfigure "Edit mode" -indicatoron false + #} + +*/ + + + +// From what used to be canvas.js + +// Global canvas associative arrays (aka javascript objects) +var scroll = {}, + menu = {}, + canvas_color = {}, + topmost = {}, + resize = {}, + xscrollable = {}, + yscrollable = {}, + update_tick = {}, + drag_tick = {}, + undo = {}, + redo = {}, + font = {}, + doscroll = {}, + last_loaded, + loaded = {}, + popup_menu = {}; + + var patchwin = {}; // Associative array of patch windows + +exports.get_patchwin = function(name) { + return patchwin[name]; +} + +// stopgap... +pd_colors['canvas_color'] = "white"; + +exports.last_loaded = function () { + return last_loaded; +} + +// close a canvas window + +function gui_canvas_cursor(cid, pd_event_type) { + var patch = get_item(cid, "patchsvg"); + var c; + // A quick mapping of events to pointers-- these can + // be revised later + switch(pd_event_type) { + case "cursor_runmode_nothing": + c = 'default'; + break; + case "cursor_runmode_clickme": + c = 'pointer'; + break; + case "cursor_runmode_thicken": + c = 'inherit'; + break; + case "cursor_runmode_addpoint": + c = 'cell'; + break; + case "cursor_editmode_nothing": + c = 'pointer'; + break; + case "cursor_editmode_connect": + c = '-webkit-grabbing'; + break; + case "cursor_editmode_disconnect": + c = 'no-drop'; + break; + case "cursor_editmode_resize": + c = 'ew-resize'; + break; + case "cursor_editmode_resize_bottom_right": + c = 'se-resize'; + break; + case "cursor_scroll": + c = 'all-scroll'; + break; + } + patch.style.cursor = c; +} + +function gui_canvas_sendkey(cid, state, evt, char_code) { + pdsend( + cid + " key " + + state + " " + + char_code + " " + + (evt.shiftKey ? 1 : 0) + " " + + 1 + " " + + (evt.repeat ? 1 : 0) + ); +} + +exports.gui_canvas_sendkey = gui_canvas_sendkey; + +function title_callback(cid, title) { + patchwin[cid].window.document.title = title; +} + +function format_window_title(name, dirty_flag, args, dir) { + return name + " " + (dirty_flag ? "*" : "") + args + " - " + dir; +} + +exports.format_window_title = format_window_title; + +// This should be used when a file is saved with the name changed (and maybe in other situations) +function gui_canvas_set_title(cid, name, args, dir, dirty_flag) { + var title = format_window_title(name, dirty_flag, args, dir); + patchwin[cid].title = title; +} + +// create a new canvas +// todo: rename parameter "name" to "cid" +function gui_canvas_new(cid, width, height, geometry, editable, name, dir, dirty_flag, cargs) { + gui_post("canvas name is " + name); + gui_post("canvas string is " + name); + gui_post("canvas dir " + dir); + gui_post("canvas dirty_flag is " + dirty_flag); + gui_post("canvas cargsis " + cargs); + // hack for buggy tcl popups... should go away for node-webkit + //reset_ctrl_on_popup_window + + // local vars for window-specific behavior + // visibility of menu and scrollbars, plus canvas background + scroll[cid] = 1; + menu[cid] = 1; + // attempt at getting global presets to play + // well with local settings. + var my_canvas_color = ""; + //canvas_color[cid] = orange; + my_canvas_color = pd_colors['canvas_color']; + topmost[cid] = 0; + resize[cid] = 1; + xscrollable[cid] = 0; + yscrollable[cid] = 0; + update_tick[cid] = 0; + drag_tick[cid] = 0; + undo[cid] = false; + redo[cid] = false; + font[cid] = 10; + doscroll[cid] = 0; + // 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) + // Keep patches on the visible screen + var xpos = Math.min(Number(geometry[0]), window.screen.height - width); + var ypos = Math.min(Number(geometry[1]), window.screen.height - height); + xpos = Math.max(xpos, 0); + ypos = Math.max(ypos, 0); + var menu_flag; + if (menu[cid] == 1) { + menu_flag = true; + } else { + menu_flag = false; + } + last_loaded = cid; + // Not sure why resize and topmost are here-- but we'll pass them on for the time being... + patchwin[cid] = nw_create_window(cid, width, height, xpos, ypos, menu_flag, + resize[cid], topmost[cid], my_canvas_color, name, dir, dirty_flag, cargs); + + // initialize variable to reflect that this window has been opened + loaded[cid] = 1; + //#pdtk_standardkeybindings $cid.c +} + +function canvas_map(name) { + console.log("canvas mapping " + name + "..."); + pdsend(name + " map 1"); +} + +exports.canvas_map = canvas_map; + +/* + ############iemlib################## + + if { $k12_mode == 0 } { + + # the "Put" menu + match_linux_wm [list menu $name.m.put -tearoff $put_tearoff] + $name.m add cascade -label Put -menu $name.m.put + + $name.m.put add command -label Object \ + -command [concat menu_object $name 0] \ + -accelerator [accel_munge "Ctrl+1"] + + $name.m.put add command -label Message \ + -command [concat menu_message $name 0] \ + -accelerator [accel_munge "Ctrl+2"] + + $name.m.put add command -label Number \ + -command [concat menu_floatatom $name 0] \ + -accelerator [accel_munge "Ctrl+3"] + + $name.m.put add command -label Symbol \ + -command [concat menu_symbolatom $name 0] \ + -accelerator [accel_munge "Ctrl+4"] + + $name.m.put add command -label Comment \ + -command [concat menu_comment $name 0] \ + -accelerator [accel_munge "Ctrl+5"] + + match_linux_wm [list $name.m.put add separator] + + ############iemlib################## + + $name.m.put add command -label Bang \ + -command [concat menu_bng $name 0] \ + -accelerator [accel_munge "Shift+Ctrl+b"] + + $name.m.put add command -label Toggle \ + -command [concat menu_toggle $name 0] \ + -accelerator [accel_munge "Shift+Ctrl+t"] + + $name.m.put add command -label Number2 \ + -command [concat menu_numbox $name 0] \ + -accelerator [accel_munge "Shift+Ctrl+n"] + + $name.m.put add command -label Vslider \ + -command [concat menu_vslider $name 0] \ + -accelerator [accel_munge "Shift+Ctrl+v"] + + $name.m.put add command -label Hslider \ + -command [concat menu_hslider $name 0] \ + -accelerator [accel_munge "Shift+Ctrl+h"] + + $name.m.put add command -label Vradio \ + -command [concat menu_vradio $name 0] \ + -accelerator [accel_munge "Shift+Ctrl+d"] + + $name.m.put add command -label Hradio \ + -command [concat menu_hradio $name 0] \ + -accelerator [accel_munge "Shift+Ctrl+i"] + + $name.m.put add command -label VU \ + -command [concat menu_vumeter $name 0] \ + -accelerator [accel_munge "Shift+Ctrl+u"] + + $name.m.put add command -label Canvas \ + -command [concat menu_mycnv $name 0] \ + -accelerator [accel_munge "Shift+Ctrl+c"] + + ############iemlib################## + + match_linux_wm [list $name.m.put add separator] + + $name.m.put add command -label Graph \ + -command [concat menu_graph $name] + + $name.m.put add command -label Array \ + -command [concat menu_array $name] + + # the find menu + # Apple, Microsoft, and others put find functions in the Edit menu. + # But in order to move these items to the Edit menu, the Find menu + # handling needs to be dealt with, including this line in g_canvas.c: + # sys_vgui(".mbar.find delete %d\n", i); + # <hans@at.or.at> + #match_linux_wm [list menu $name.m.find -tearoff $put_tearoff] + #$name.m add cascade -label Find -menu $name.m.find + # + #$name.m.find add command -label {Find...} \ + # -accelerator [accel_munge "Ctrl+f"] \ + # -command [concat menu_findobject $name] + #$name.m.find add command -label {Find Again} \ + # -accelerator [accel_munge "Ctrl+g"] \ + # -command [concat menu_findagain $name] + #$name.m.find add command -label {Find last error} \ + # -command [concat menu_finderror] + + # the window menu + match_linux_wm [list menu $name.m.windows -postcommand \ + [concat menu_fixwindowmenu $name] -tearoff $pd_tearoff] + + if {$pd_nt == 2} { + $name.m.windows add command -label {Minimize} \ + -command "menu_minimize $name" -accelerator [accel_munge "Ctrl+m"] + $name.m.windows add command -label {Zoom} -command "menu_zoom $name" + } else { + $name.m.windows add command -label "Next Window" -command {menu_raisenextwindow} \ + -accelerator "Ctrl+PageDown" + $name.m.windows add command -label "Previous Window" -command {menu_raisepreviouswindow} \ + -accelerator "Ctrl+PageUp" + } + match_linux_wm [list $name.m.windows add separator] + $name.m.windows add command -label {parent window}\ + -command [concat menu_windowparent $name] + $name.m.windows add command -label {Pd & Console} -command menu_raise_console \ + -accelerator [accel_munge "Ctrl+;"] + match_linux_wm [list $name.m.windows add separator] + + # the audio menu + match_linux_wm [list menu $name.m.audio -tearoff $pd_tearoff] + + if {$pd_nt != 2} { + $name.m add cascade -label Windows -menu $name.m.windows + $name.m add cascade -label Media -menu $name.m.audio + } else { + $name.m add cascade -label Media -menu $name.m.audio + $name.m add cascade -label Window -menu $name.m.windows + # the MacOS X app menu + menu $name.m.apple -tearoff $pd_tearoff + $name.m add cascade -label "Apple" -menu $name.m.apple + } + + # the "Help" menu + + match_linux_wm [list menu $name.m.help -tearoff $pd_tearoff] + $name.m add cascade -label Help -menu $name.m.help + + menu_addstd $name.m + } + + # the popup menu + match_linux_wm [list menu $name.popup -tearoff false] + if { $k12_mode == 0 } { + $name.popup add command -label {Properties} \ + -command [concat popup_action $name 0] + $name.popup add command -label {Open} \ + -command [concat popup_action $name 1] + $name.popup add command -label {Help} \ + -command [concat popup_action $name 2] + match_linux_wm [list $name.popup add separator] + $name.popup add command -label {To Front} \ + -command [concat popup_action $name 3] + $name.popup add command -label {To Back} \ + -command [concat popup_action $name 4] + } else { + $name.popup add command -label {Properties} -state disabled \ + -command [concat popup_action $name 0] + $name.popup add command -label {Open} -state disabled \ + -command [concat popup_action $name 1] + $name.popup add command -label {Help} \ + -command [concat popup_action $name 2] + match_linux_wm [list $name.popup add separator] + $name.popup add command -label {To Front} -state disabled \ + -command [concat popup_action $name 3] + $name.popup add command -label {To Back} -state disabled \ + -command [concat popup_action $name 4] + } + + # fix menu font size on Windows with tk scaling = 1 + if {$pd_nt == 1} { + $name.m.file configure -font menuFont + $name.m.edit configure -font menuFont + $name.m.find configure -font menuFont + $name.m.put configure -font menuFont + $name.m.windows configure -font menuFont + $name.m.audio configure -font menuFont + $name.m.help configure -font menuFont + $name.popup configure -font menuFont + } + + # WM protocol + wm protocol $name WM_DELETE_WINDOW [concat menu_close $name] + + # bindings. + # this is idiotic -- how do you just sense what mod keys are down and + # pass them on? I can't find it anywhere. + # Here we encode shift as 1, control 2, alt 4, in agreement + # with definitions in g_canvas.c. The third button gets "8" but we don't + # bother with modifiers there. + # We don't handle multiple clicks yet. + + bind $name.c <Configure> {pdtk_canvas_getscroll %W} + #bind $name.c <Configure> {after 100 pdtk_canvas_getscroll_configure %W} + bind $name.c <Button> {pdtk_canvas_click %W %x %y %b 0} + bind $name.c <Shift-Button> {pdtk_canvas_click %W %x %y %b 1} + bind $name.c <Control-Shift-Button> {pdtk_canvas_click %W %x %y %b 3} + # Alt key is called Option on the Mac + if {$pd_nt == 2} { + bind $name.c <Option-Button> {pdtk_canvas_click %W %x %y %b 4} + bind $name.c <Option-Shift-Button> {pdtk_canvas_click %W %x %y %b 5} + bind $name.c <Option-Control-Button> {pdtk_canvas_click %W %x %y %b 6} + bind $name.c <Mod1-Button> {pdtk_canvas_click %W %x %y %b 6} + bind $name.c <Option-Control-Shift-Button> \ + {pdtk_canvas_click %W %x %y %b 7} + } else { + bind $name.c <Alt-Button> {pdtk_canvas_click %W %x %y %b 4} + bind $name.c <Alt-Shift-Button> {pdtk_canvas_click %W %x %y %b 5} + bind $name.c <Alt-Control-Button> {pdtk_canvas_click %W %x %y %b 6} + bind $name.c <Alt-Control-Shift-Button> \ + {pdtk_canvas_click %W %x %y %b 7} + } + # button 2 is the right button on Mac; on other platforms it's button 3. + if {$pd_nt == 2} { + bind $name.c <Button-2> {pdtk_canvas_rightclick %W %x %y %b} + bind $name.c <Control-Button> {pdtk_canvas_rightclick %W %x %y %b} + } else { + bind $name.c <Button-3> {pdtk_canvas_rightclick %W %x %y %b} + bind $name.c <Control-Button> {pdtk_canvas_click %W %x %y %b 2} + } + #on linux, button 2 "pastes" from the X windows clipboard + if {$pd_nt == 0} { + bind $name.c <Button-2> {pdtk_canvas_middleclick %W %x %y %b 0;} + } + + bind $name.c <ButtonRelease> {pdtk_canvas_mouseup %W %x %y %b} + bind $name.c <Control-Key> {pdtk_canvas_ctrlkey %W %K 0} + bind $name.c <Control-Shift-Key> {pdtk_canvas_ctrlkey %W %K 1} + # bind $name.c <Mod1-Key> {puts stderr [concat mod1 %W %K %A]} + if {$pd_nt == 2} { + bind $name.c <Mod1-Key> {pdtk_canvas_ctrlkey %W %K 0} + bind $name.c <Mod1-Shift-Key> {pdtk_canvas_ctrlkey %W %K 1} + bind $name.c <Mod1-BackSpace> {pdtk_canvas_sendkey %W 1 %K %A 0 1 %t} + bind $name.c <Mod1-quoteleft> {menu_raisenextwindow} + } else { + bind $name.c <Control-Next> {menu_raisenextwindow} + bind $name.c <Control-Prior> {menu_raisepreviouswindow} ;# needs Tcl/Tk 8.5 + } + bind $name.c <Key> {pdtk_canvas_sendkey %W 1 %K %A 0 1 %t} + bind $name.c <Shift-Key> {pdtk_canvas_sendkey %W 1 %K %A 1 1 %t} + bind $name.c <KeyRelease> {pdtk_canvas_sendkey %W 0 %K %A 0 1 %t} + bind $name.c <Motion> {pdtk_canvas_motion %W %x %y 0} + bind $name.c <Shift-Motion> {pdtk_canvas_motion %W %x %y 1} + bind $name.c <Control-Motion> {pdtk_canvas_motion %W %x %y 2} + bind $name.c <Control-Shift-Motion> {pdtk_canvas_motion %W %x %y 3} + + # canvas bindings --------------------------------------------------------- + # just for tooltips right now + #$name.c bind all <Enter> "puts stderr {%x %y}" + #$name.c bind inlet <Enter> "pdtk_canvas_enteritem %W %x %y inlet %t" + #$name.c bind outlet <Enter> "pdtk_canvas_enteritem %W %x %y outlet %t" + #$name.c bind text <Enter> "pdtk_canvas_enteritem %W %x %y text %t" + #$name.c bind inlet <Leave> "pdtk_canvas_leaveitem %W inlet 0" + #$name.c bind outlet <Leave> "pdtk_canvas_leaveitem %W outlet 0" + #$name.c bind text <Leave> "pdtk_canvas_leaveitem %W text 0" + + if {$pd_nt == 2} { + bind $name.c <Option-Motion> {pdtk_canvas_motion %W %x %y 4} + } else { + bind $name.c <Alt-Motion> {pdtk_canvas_motion %W %x %y 4} + } + bind $name.c <Map> {pdtk_canvas_map %W} + bind $name.c <Unmap> {pdtk_canvas_unmap %W} + + switch $pd_nt { 0 { + bind $name.c <Button-4> "pdtk_canvas_scroll $name.c y -1" + bind $name.c <Button-5> "pdtk_canvas_scroll $name.c y +1" + bind $name.c <Shift-Button-4> "pdtk_canvas_scroll $name.c x -1" + bind $name.c <Shift-Button-5> "pdtk_canvas_scroll $name.c x +1" + #if { $k12_mode == 0 } { + # bind $name.c <Control-Button-4> "pdtk_zoom $name 1" + # bind $name.c <Control-Button-5> "pdtk_zoom $name -1" + #} + } default { + bind $name.c <MouseWheel> \ + "pdtk_canvas_scroll $name.c y \[expr -abs(%D)/%D\]" + bind $name.c <Shift-MouseWheel> \ + "pdtk_canvas_scroll $name.c x \[expr -abs(%D)/%D\]" + }} + + #dnd bindtarget $name.c text/uri-list <Drop> { pdtk_canvas_makeobjs $name %D %x %y } + after idle [list dnd bindtarget $name text/uri-list <Drop> { foreach file %D {open_file $file} }] + + # puts stderr "all done" + # after 1 [concat raise $name] + set pdtk_canvas_mouseup_name "" + + bind $name <FocusIn> "menu_fixeditmenu $name" + bind $name <FocusOut> "pdtk_canvas_leaveitem $name.c" + if { $k12_mode == 1 } { pd [concat $name tooltips 1 \;] } + after idle [concat focus $name.c] + + if { $k12_mode == 1 && $k12_saveas_on_new == 1 } { + after 1000 [concat pdtk_k12_saveas_on_new $name] + } + + set ::scroll_on($name) 0 + set ::hit_scrollbar($name) 0 + #set ::scroll_was_cursor($name) 0 + set ::last_scroll_x($name) 0 + set ::last_scroll_y($name) 0 + set ::canvaswidth($name) 0 + set ::canvasheight($name) 0 + + +/* + if { $k12_mode == 1 } { + # K-12 menu + + match_linux_wm [list frame $name.k12frame] + pack $name.k12frame -side left -fill y + + # ---------------------------------- EDIT BUTTON ----------------------------------------- + match_linux_wm [list frame $name.k12frame.edit -relief flat] + if {$editable==1} { + match_linux_wm [list button $name.k12frame.edit.b -image i.edit \ + -command [concat menu_editmode $name]] + } else { + match_linux_wm [list button $name.k12frame.edit.b -image i.perform \ + -command [concat menu_editmode $name]] + } + pack $name.k12frame.edit.b -side left -expand 1 -padx 1 -pady 0 + setTooltip $name.k12frame.edit.b "Toggle between building and playing an instrument" + pdtk_k12panel_standardkeybindings $name.k12frame.edit.b + bind $name.k12frame.edit.b <Key> [list pdtk_canvas_sendkey $name.c 1 %K %A 0 1 %t] + bind $name.k12frame.edit.b <KeyRelease> [list pdtk_canvas_sendkey $name.c 0 %K %A 0 1 %t] + + # ---------------------------------- DATA VS SOUND BUTTONS ---------------------------------- + match_linux_wm [list frame $name.k12frame.datasound -relief flat] + match_linux_wm [list button $name.k12frame.datasound.data -text "DATA" -image i.data_on -command [concat pdtk_k12_show_data_icons $name]] + match_linux_wm [list button $name.k12frame.datasound.sound -text "SOUND" -image i.sound -command [concat pdtk_k12_show_sound_icons $name]] + pack $name.k12frame.datasound.data $name.k12frame.datasound.sound -side left -pady 1 -padx 1 -expand 0 + setTooltip $name.k12frame.datasound.data "Show DATA objects" + setTooltip $name.k12frame.datasound.sound "Show SOUND objects" + pdtk_k12panel_standardkeybindings $name.k12frame.datasound.data + pdtk_k12panel_standardkeybindings $name.k12frame.datasound.sound + + # ---------------------------------- MESSAGES LABEL ----------------------------------------- + + #match_linux_wm [list frame $name.k12frame.msgs -relief flat] + #match_linux_wm [list label $name.k12frame.msgs.label -relief flat -text "MESSAGES"] + #pack $name.k12frame.msgs.label -fill x -pady 0 -padx 1 + + # ---------------------------------- WII ----------------------------------------- + match_linux_wm [list frame $name.k12frame.wii -relief flat] + match_linux_wm [list button $name.k12frame.wii.b_wii_connect -image i.wii_connect \ + -command [concat put_K12_objects $name wii_connect]] + match_linux_wm [list button $name.k12frame.wii.b_wii_buttons -image i.wii_buttons \ + -command [concat put_K12_objects $name wii_buttons]] + match_linux_wm [list button $name.k12frame.wii.b_wii_hit -image i.wii_hit \ + -command [concat put_K12_objects $name wii_hit]] + match_linux_wm [list button $name.k12frame.wii.b_wii_accelerometer -image i.wii_accelerometer \ + -command [concat put_K12_objects $name wii_accelerometer]] + match_linux_wm [list button $name.k12frame.wii.b_wii_speed_xry -image i.wii_speed_xry \ + -command [concat put_K12_objects $name wii_speed_xry]] + pack $name.k12frame.wii.b_wii_connect $name.k12frame.wii.b_wii_buttons $name.k12frame.wii.b_wii_hit $name.k12frame.wii.b_wii_accelerometer $name.k12frame.wii.b_wii_speed_xry -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.wii.b_wii_connect "Wiimote Connect: Use this to connect wiimote to the computer" + setTooltip $name.k12frame.wii.b_wii_buttons "Wiimote Buttons: Use this to select which Wiimote button should activate objects connected to this object" + setTooltip $name.k12frame.wii.b_wii_hit "Wiimote Hit: Use this to detect when the wiimote has been shaken like a mallet" + setTooltip $name.k12frame.wii.b_wii_accelerometer "Wiimote Accelerometer: Use this to monitor Wiimotes acceleration across X, Y, and Z axes" + setTooltip $name.k12frame.wii.b_wii_speed_xry "Wiimote Speed X, Roll, Y: Use this to detect how quickly is Wiimote moving across individual axes x, roll, and y (requires motion plus)" + pdtk_k12panel_standardkeybindings $name.k12frame.wii.b_wii_connect + pdtk_k12panel_standardkeybindings $name.k12frame.wii.b_wii_buttons + pdtk_k12panel_standardkeybindings $name.k12frame.wii.b_wii_hit + pdtk_k12panel_standardkeybindings $name.k12frame.wii.b_wii_accelerometer + pdtk_k12panel_standardkeybindings $name.k12frame.wii.b_wii_speed_xry + + # ---------------------------------- WII2 ----------------------------------------- + match_linux_wm [list frame $name.k12frame.wii2 -relief flat] + match_linux_wm [list button $name.k12frame.wii2.b_wii_speed -image i.wii_speed \ + -command [concat put_K12_objects $name wii_speed]] + match_linux_wm [list button $name.k12frame.wii2.b_wii_nunchuk_buttons -image i.wii_nunchuk_buttons \ + -command [concat put_K12_objects $name wii_nunchuk_buttons]] + match_linux_wm [list button $name.k12frame.wii2.b_wii_nunchuk_hit -image i.wii_nunchuk_hit \ + -command [concat put_K12_objects $name wii_nunchuk_hit]] + match_linux_wm [list button $name.k12frame.wii2.b_wii_nunchuk_accelerometer -image i.wii_nunchuk_accelerometer \ + -command [concat put_K12_objects $name wii_nunchuk_accelerometer]] + match_linux_wm [list button $name.k12frame.wii2.b_wii_nunchuk_stick -image i.wii_nunchuk_stick \ + -command [concat put_K12_objects $name wii_nunchuk_stick]] + pack $name.k12frame.wii2.b_wii_speed $name.k12frame.wii2.b_wii_nunchuk_buttons $name.k12frame.wii2.b_wii_nunchuk_hit $name.k12frame.wii2.b_wii_nunchuk_accelerometer $name.k12frame.wii2.b_wii_nunchuk_stick -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.wii2.b_wii_speed "Wiimote Speed: Use this to detect how quickly is Wiimote moving (requires motion plus)" + setTooltip $name.k12frame.wii2.b_wii_nunchuk_buttons "Wiimote Nunchuk Buttons: Use this to select which Nunchuk button should activate objects connected to this object (requires nunchuk extension)" + setTooltip $name.k12frame.wii2.b_wii_nunchuk_hit "Wiimote Nunchuk Hit: Use this to detect when the wiimote has been shaken like a mallet (requires nunchuk extension)" + setTooltip $name.k12frame.wii2.b_wii_nunchuk_accelerometer "Wiimote Nunchuk Accelerometer: Use this to monitor Nunchuk acceleration across X, Y, and Z axes (requires nunchuk extension)" + setTooltip $name.k12frame.wii2.b_wii_nunchuk_stick "Wiimote Nunchuk stick: Use this to monitor Nunchuk stick motion across X and Y axes (requires nunchuk extension)" + pdtk_k12panel_standardkeybindings $name.k12frame.wii2.b_wii_speed + pdtk_k12panel_standardkeybindings $name.k12frame.wii2.b_wii_nunchuk_buttons + pdtk_k12panel_standardkeybindings $name.k12frame.wii2.b_wii_nunchuk_hit + pdtk_k12panel_standardkeybindings $name.k12frame.wii2.b_wii_nunchuk_accelerometer + pdtk_k12panel_standardkeybindings $name.k12frame.wii2.b_wii_nunchuk_stick + + # ---------------------------------- ARDUINO ----------------------------------------- + match_linux_wm [list frame $name.k12frame.arduino -relief flat] + match_linux_wm [list button $name.k12frame.arduino.b_sarcduino -image i.sarcduino \ + -command [concat put_K12_objects $name sarcduino_connect]] + match_linux_wm [list button $name.k12frame.arduino.b_sarcduino_digital -image i.sarcduino_digital \ + -command [concat put_K12_objects $name sarcduino_digital]] + match_linux_wm [list button $name.k12frame.arduino.b_sarcduino_analog -image i.sarcduino_analog \ + -command [concat put_K12_objects $name sarcduino_analog]] + match_linux_wm [list button $name.k12frame.arduino.b_sarcduino_hit -image i.sarcduino_hit \ + -command [concat put_K12_objects $name sarcduino_hit]] + match_linux_wm [list button $name.k12frame.arduino.b_sarcduino_piezo -image i.sarcduino_piezo \ + -command [concat put_K12_objects $name sarcduino_piezo]] + pack $name.k12frame.arduino.b_sarcduino $name.k12frame.arduino.b_sarcduino_digital $name.k12frame.arduino.b_sarcduino_analog $name.k12frame.arduino.b_sarcduino_hit $name.k12frame.arduino.b_sarcduino_piezo -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.arduino.b_sarcduino "Arduino Connect: Use this to arduino to the computer" + setTooltip $name.k12frame.arduino.b_sarcduino_digital "Arduino Digital: Use this to detect on/off states of a digital sensor" + setTooltip $name.k12frame.arduino.b_sarcduino_analog "Arduino Analog: Use this to monitor analog sensor speed" + setTooltip $name.k12frame.arduino.b_sarcduino_hit "Arduino Hit: Use this to detect when the arduino analog sensor data has rapidly changed" + setTooltip $name.k12frame.arduino.b_sarcduino_piezo "Arduino Piezo: Use this to analyze data coming from a piezo microphone sensor" + pdtk_k12panel_standardkeybindings $name.k12frame.arduino.b_sarcduino + pdtk_k12panel_standardkeybindings $name.k12frame.arduino.b_sarcduino_digital + pdtk_k12panel_standardkeybindings $name.k12frame.arduino.b_sarcduino_analog + pdtk_k12panel_standardkeybindings $name.k12frame.arduino.b_sarcduino_hit + pdtk_k12panel_standardkeybindings $name.k12frame.arduino.b_sarcduino_piezo + + # ---------------------------------- RPI & MATH ROW 1 ----------------------------------------- + match_linux_wm [list frame $name.k12frame.math_1 -relief flat] + #match_linux_wm [list button $name.k12frame.math_1.b_sarcduino_net -image i.sarcduino_net \ + # -command [concat put_K12_objects $name sarcduino_net]] + match_linux_wm [list button $name.k12frame.math_1.b_rpi_digital -image i.raspberry_digital \ + -command [concat put_K12_objects $name raspberrypi_digital]] + match_linux_wm [list button $name.k12frame.math_1.b_rpi_analog_out -image i.raspberry_analog_out \ + -command [concat put_K12_objects $name raspberrypi_analog_out]] + match_linux_wm [list button $name.k12frame.math_1.b_rpi_analog_in -image i.raspberry_analog_in \ + -command [concat put_K12_objects $name raspberrypi_analog_in]] + match_linux_wm [list button $name.k12frame.math_1.b_math_number -image i.math_number \ + -command [concat put_K12_objects $name math_number]] + match_linux_wm [list button $name.k12frame.math_1.b_math_netsend -image i.math_netsend \ + -command [concat put_K12_objects $name math_netsend]] + pack $name.k12frame.math_1.b_rpi_digital $name.k12frame.math_1.b_rpi_analog_out $name.k12frame.math_1.b_rpi_analog_in $name.k12frame.math_1.b_math_number $name.k12frame.math_1.b_math_netsend -side left -expand 0 -padx 1 -pady 1 + #setTooltip $name.k12frame.math_1.b_sarcduino_net "Arduino Net: Use this to retrieve data from arduino devices connected via network" + setTooltip $name.k12frame.math_1.b_rpi_digital "RaspberryPi Digital: Use this to read from or write to GPIO pins in digital format" + setTooltip $name.k12frame.math_1.b_rpi_analog_out "RaspberryPi Analog Out: Use this to write to GPIO pins in analog format using PWM" + setTooltip $name.k12frame.math_1.b_rpi_analog_in "RaspberryPi Analog In: Use this to read from RaspberryPi LOP Shield's analog inputs" + setTooltip $name.k12frame.math_1.b_math_number "Number: Use this to assign a value to other objects" + setTooltip $name.k12frame.math_1.b_math_netsend "Netsend: Use this to send data over network to another computer" + pdtk_k12panel_standardkeybindings $name.k12frame.math_1.b_rpi_digital + pdtk_k12panel_standardkeybindings $name.k12frame.math_1.b_rpi_analog_out + pdtk_k12panel_standardkeybindings $name.k12frame.math_1.b_rpi_analog_in + pdtk_k12panel_standardkeybindings $name.k12frame.math_1.b_math_number + pdtk_k12panel_standardkeybindings $name.k12frame.math_1.b_math_netsend + + # ---------------------------------- MATH ROW 2 ----------------------------------------- + match_linux_wm [list frame $name.k12frame.math_2 -relief flat] + match_linux_wm [list button $name.k12frame.math_2.b_math_netreceive -image i.math_netreceive \ + -command [concat put_K12_objects $name math_netreceive]] + match_linux_wm [list button $name.k12frame.math_2.b_math_tag -image i.math_tag \ + -command [concat put_K12_objects $name math_tag]] + match_linux_wm [list button $name.k12frame.math_2.b_math_routebytag -image i.math_routebytag \ + -command [concat put_K12_objects $name math_routebytag]] + match_linux_wm [list button $name.k12frame.math_2.b_math_add -image i.math_add \ + -command [concat put_K12_objects $name math_add]] + match_linux_wm [list button $name.k12frame.math_2.b_math_subtract -image i.math_subtract \ + -command [concat put_K12_objects $name math_subtract]] + pack $name.k12frame.math_2.b_math_netreceive $name.k12frame.math_2.b_math_tag $name.k12frame.math_2.b_math_routebytag $name.k12frame.math_2.b_math_add $name.k12frame.math_2.b_math_subtract -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.math_2.b_math_netreceive "Netreceive: Use this to receive data from another computer over network" + setTooltip $name.k12frame.math_2.b_math_tag "Tag: Use this to tag data to be sent over network" + setTooltip $name.k12frame.math_2.b_math_routebytag "Route By Tag: Use this to filter incoming network data by tag" + setTooltip $name.k12frame.math_2.b_math_add "Add: Use this to add two values" + setTooltip $name.k12frame.math_2.b_math_subtract "Subtract: Use this to subtract two values" + pdtk_k12panel_standardkeybindings $name.k12frame.math_2.b_math_netreceive + pdtk_k12panel_standardkeybindings $name.k12frame.math_2.b_math_tag + pdtk_k12panel_standardkeybindings $name.k12frame.math_2.b_math_routebytag + pdtk_k12panel_standardkeybindings $name.k12frame.math_2.b_math_add + pdtk_k12panel_standardkeybindings $name.k12frame.math_2.b_math_subtract + + # ---------------------------------- MATH ROW 3 ----------------------------------------- + match_linux_wm [list frame $name.k12frame.math_3 -relief flat] + match_linux_wm [list button $name.k12frame.math_3.b_math_multiply -image i.math_multiply \ + -command [concat put_K12_objects $name math_multiply]] + match_linux_wm [list button $name.k12frame.math_3.b_math_divide -image i.math_divide \ + -command [concat put_K12_objects $name math_divide]] + match_linux_wm [list button $name.k12frame.math_3.b_math_random -image i.math_random \ + -command [concat put_K12_objects $name math_random]] + match_linux_wm [list button $name.k12frame.math_3.b_math_average -image i.math_average \ + -command [concat put_K12_objects $name math_average]] + match_linux_wm [list button $name.k12frame.math_3.b_math_scale -image i.math_scale \ + -command [concat put_K12_objects $name math_scale]] + pack $name.k12frame.math_3.b_math_multiply $name.k12frame.math_3.b_math_divide $name.k12frame.math_3.b_math_random $name.k12frame.math_3.b_math_average $name.k12frame.math_3.b_math_scale -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.math_3.b_math_multiply "Multiply: Use this to multiply two values" + setTooltip $name.k12frame.math_3.b_math_divide "Divide: Use this to divide two values" + setTooltip $name.k12frame.math_3.b_math_random "Random: Use this to generate random numbers" + setTooltip $name.k12frame.math_3.b_math_average "Average: Use this to calculate average from a stream of numbers" + setTooltip $name.k12frame.math_3.b_math_scale "Scale: Use this to scale incoming values to a new range and direction" + pdtk_k12panel_standardkeybindings $name.k12frame.math_3.b_math_multiply + pdtk_k12panel_standardkeybindings $name.k12frame.math_3.b_math_divide + pdtk_k12panel_standardkeybindings $name.k12frame.math_3.b_math_random + pdtk_k12panel_standardkeybindings $name.k12frame.math_3.b_math_average + pdtk_k12panel_standardkeybindings $name.k12frame.math_3.b_math_scale + + # ---------------------------------- LOGIC ----------------------------------------- + match_linux_wm [list frame $name.k12frame.logic -relief flat] + match_linux_wm [list button $name.k12frame.logic.b_logic_compare -image i.logic_compare \ + -command [concat put_K12_objects $name logic_compare]] + match_linux_wm [list button $name.k12frame.logic.b_logic_mapper -image i.logic_mapper \ + -command [concat put_K12_objects $name logic_mapper]] + match_linux_wm [list button $name.k12frame.logic.b_logic_metronome -image i.logic_metronome \ + -command [concat put_K12_objects $name logic_metronome]] + match_linux_wm [list button $name.k12frame.logic.b_logic_counter -image i.logic_counter \ + -command [concat put_K12_objects $name logic_counter]] + match_linux_wm [list button $name.k12frame.logic.b_logic_sequencer -image i.logic_sequencer \ + -command [concat put_K12_objects $name logic_sequencer]] + pack $name.k12frame.logic.b_logic_compare $name.k12frame.logic.b_logic_mapper $name.k12frame.logic.b_logic_metronome $name.k12frame.logic.b_logic_counter $name.k12frame.logic.b_logic_sequencer -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.logic.b_logic_compare "Compare: Use this to compare two values" + setTooltip $name.k12frame.logic.b_logic_mapper "Mapper: Use this to map one value to two different but related values" + setTooltip $name.k12frame.logic.b_logic_metronome "Metronome: Use this to create a steady pulse" + setTooltip $name.k12frame.logic.b_logic_counter "Counter: Use this to count events" + setTooltip $name.k12frame.logic.b_logic_sequencer "Sequencer: Use this to map values to MIDI pitches" + pdtk_k12panel_standardkeybindings $name.k12frame.logic.b_logic_compare + pdtk_k12panel_standardkeybindings $name.k12frame.logic.b_logic_mapper + pdtk_k12panel_standardkeybindings $name.k12frame.logic.b_logic_metronome + pdtk_k12panel_standardkeybindings $name.k12frame.logic.b_logic_counter + pdtk_k12panel_standardkeybindings $name.k12frame.logic.b_logic_sequencer + + # ---------------------------------- OTHER ----------------------------------------- + match_linux_wm [list frame $name.k12frame.other -relief flat] + match_linux_wm [list button $name.k12frame.other.b_preset -image i.preset \ + -command [concat put_K12_objects $name preset]] + match_linux_wm [list button $name.k12frame.other.b_comment -image i.comment \ + -command [concat menu_comment $name 1]] + pack $name.k12frame.other.b_preset $name.k12frame.other.b_comment -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.other.b_preset "Preset: Use this to store and recall up to four different states of your instrument" + setTooltip $name.k12frame.other.b_comment "Comment: Use this to post comments inside your patch" + pdtk_k12panel_standardkeybindings $name.k12frame.other.b_preset + pdtk_k12panel_standardkeybindings $name.k12frame.other.b_comment + + # ---------------------------------- SOUND LABEL ----------------------------------------- + #match_linux_wm [list frame $name.k12frame.sound -relief flat] + #match_linux_wm [list label $name.k12frame.sound.label -relief flat -text "SOUND"] + #pack $name.k12frame.sound.label -fill x -pady 0 -padx 1 + + # ---------------------------------- SIGNAL ROW 1 ----------------------------------------- + match_linux_wm [list frame $name.k12frame.signal_1 -relief flat] + match_linux_wm [list button $name.k12frame.signal_1.b_signal_microphone -image i.signal_microphone \ + -command [concat put_K12_objects $name signal_microphone]] + + match_linux_wm [list button $name.k12frame.signal_1.b_signal_netsend -image i.signal_netsend \ + -command [concat put_K12_objects $name signal_netsend]] + match_linux_wm [list button $name.k12frame.signal_1.b_signal_netreceive -image i.signal_netreceive \ + -command [concat put_K12_objects $name signal_netreceive]] + + match_linux_wm [list button $name.k12frame.signal_1.b_signal_sampler -image i.signal_sampler \ + -command [concat put_K12_objects $name signal_sampler]] + match_linux_wm [list button $name.k12frame.signal_1.b_signal_player -image i.signal_player \ + -command [concat put_K12_objects $name signal_player]] + pack $name.k12frame.signal_1.b_signal_microphone $name.k12frame.signal_1.b_signal_netsend $name.k12frame.signal_1.b_signal_netreceive $name.k12frame.signal_1.b_signal_sampler $name.k12frame.signal_1.b_signal_player -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.signal_1.b_signal_microphone "Microphone: Use this to capture and monitor microphone input" + setTooltip $name.k12frame.signal_1.b_signal_netsend "Netsend Sound: Use this to send your sound over network to another computer" + setTooltip $name.k12frame.signal_1.b_signal_netreceive "Netreceive Sound: Use this to receive sound from another computer over network" + setTooltip $name.k12frame.signal_1.b_signal_sampler "Sampler: Use this to record audio from microphone and play it back in various ways" + setTooltip $name.k12frame.signal_1.b_signal_player "Player: Use this to play WAV files in various ways" + pdtk_k12panel_standardkeybindings $name.k12frame.signal_1.b_signal_microphone + pdtk_k12panel_standardkeybindings $name.k12frame.signal_1.b_signal_netsend + pdtk_k12panel_standardkeybindings $name.k12frame.signal_1.b_signal_netreceive + pdtk_k12panel_standardkeybindings $name.k12frame.signal_1.b_signal_sampler + pdtk_k12panel_standardkeybindings $name.k12frame.signal_1.b_signal_player + + # ---------------------------------- SIGNAL ROW 2 ----------------------------------------- + match_linux_wm [list frame $name.k12frame.signal_2 -relief flat] + match_linux_wm [list button $name.k12frame.signal_2.b_signal_sine -image i.signal_sine \ + -command [concat put_K12_objects $name signal_sine]] + match_linux_wm [list button $name.k12frame.signal_2.b_signal_saw -image i.signal_saw \ + -command [concat put_K12_objects $name signal_saw]] + match_linux_wm [list button $name.k12frame.signal_2.b_signal_square -image i.signal_square \ + -command [concat put_K12_objects $name signal_square]] + match_linux_wm [list button $name.k12frame.signal_2.b_signal_triangle -image i.signal_triangle \ + -command [concat put_K12_objects $name signal_triangle]] + match_linux_wm [list button $name.k12frame.signal_2.b_signal_envelope -image i.signal_envelope \ + -command [concat put_K12_objects $name signal_envelope]] + pack $name.k12frame.signal_2.b_signal_sine $name.k12frame.signal_2.b_signal_saw $name.k12frame.signal_2.b_signal_square $name.k12frame.signal_2.b_signal_triangle $name.k12frame.signal_2.b_signal_envelope -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.signal_2.b_signal_sine "Sine: Use this to generate sine tone" + setTooltip $name.k12frame.signal_2.b_signal_saw "Sawtooth: Use this to generate sawtooth tone" + setTooltip $name.k12frame.signal_2.b_signal_square "Square: Use this to generate square tone" + setTooltip $name.k12frame.signal_2.b_signal_triangle "Triangle: Use this to generate triangle tone" + setTooltip $name.k12frame.signal_2.b_signal_envelope "Envelope: Use this to shape sound loudness" + pdtk_k12panel_standardkeybindings $name.k12frame.signal_2.b_signal_sine + pdtk_k12panel_standardkeybindings $name.k12frame.signal_2.b_signal_saw + pdtk_k12panel_standardkeybindings $name.k12frame.signal_2.b_signal_square + pdtk_k12panel_standardkeybindings $name.k12frame.signal_2.b_signal_triangle + pdtk_k12panel_standardkeybindings $name.k12frame.signal_2.b_signal_envelope + + # ---------------------------------- SIGNAL ROW 3 ----------------------------------------- + match_linux_wm [list frame $name.k12frame.signal_3 -relief flat] + match_linux_wm [list button $name.k12frame.signal_3.b_signal_noise -image i.signal_noise \ + -command [concat put_K12_objects $name signal_noise]] + match_linux_wm [list button $name.k12frame.signal_3.b_signal_pink -image i.signal_pink \ + -command [concat put_K12_objects $name signal_pink]] + match_linux_wm [list button $name.k12frame.signal_3.b_signal_add -image i.signal_add \ + -command [concat put_K12_objects $name signal_add]] + match_linux_wm [list button $name.k12frame.signal_3.b_signal_multiply -image i.signal_multiply \ + -command [concat put_K12_objects $name signal_multiply]] + pack $name.k12frame.signal_3.b_signal_noise $name.k12frame.signal_3.b_signal_pink $name.k12frame.signal_3.b_signal_add $name.k12frame.signal_3.b_signal_multiply -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.signal_3.b_signal_noise "Noise: Use this to generate white (harsh) noise" + setTooltip $name.k12frame.signal_3.b_signal_pink "Pink: Use this to generate pink (softer) noise" + setTooltip $name.k12frame.signal_3.b_signal_add "Signal Add: Use this to add two sounds (signals)" + setTooltip $name.k12frame.signal_3.b_signal_multiply "Signal Multiply: Use this to multiply two sounds (signals)" + pdtk_k12panel_standardkeybindings $name.k12frame.signal_3.b_signal_noise + pdtk_k12panel_standardkeybindings $name.k12frame.signal_3.b_signal_pink + pdtk_k12panel_standardkeybindings $name.k12frame.signal_3.b_signal_add + pdtk_k12panel_standardkeybindings $name.k12frame.signal_3.b_signal_multiply + + # ---------------------------------- INSTRUMENTS ----------------------------------------- + match_linux_wm [list frame $name.k12frame.instr -relief flat] + match_linux_wm [list button $name.k12frame.instr.b_instr_short1 -image i.instr_short1 \ + -command [concat put_K12_objects $name instr_short1]] + match_linux_wm [list button $name.k12frame.instr.b_instr_short2 -image i.instr_short2 \ + -command [concat put_K12_objects $name instr_short2]] + match_linux_wm [list button $name.k12frame.instr.b_instr_sustained1 -image i.instr_sustained1 \ + -command [concat put_K12_objects $name instr_sustained1]] + match_linux_wm [list button $name.k12frame.instr.b_instr_sustained2 -image i.instr_sustained2 \ + -command [concat put_K12_objects $name instr_sustained2]] + pack $name.k12frame.instr.b_instr_short1 $name.k12frame.instr.b_instr_short2 $name.k12frame.instr.b_instr_sustained1 $name.k12frame.instr.b_instr_sustained2 -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.instr.b_instr_short1 "Bass Drum: Use this to produce short sounds like a single bass drum hit" + setTooltip $name.k12frame.instr.b_instr_short2 "Snare Drum: Use this to produce short sounds like a single snare drum hit" + setTooltip $name.k12frame.instr.b_instr_sustained1 "Air Instrument: Use this to produce long sustained sound like a sound of a woodwind instrument" + setTooltip $name.k12frame.instr.b_instr_sustained2 "Brass Instrument: Use this to produce long sustained sound like a sound of brass instrument" + pdtk_k12panel_standardkeybindings $name.k12frame.instr.b_instr_short1 + pdtk_k12panel_standardkeybindings $name.k12frame.instr.b_instr_short2 + pdtk_k12panel_standardkeybindings $name.k12frame.instr.b_instr_sustained1 + pdtk_k12panel_standardkeybindings $name.k12frame.instr.b_instr_sustained2 + + # ---------------------------------- F/X ----------------------------------------- + match_linux_wm [list frame $name.k12frame.fx -relief flat] + match_linux_wm [list button $name.k12frame.fx.b_fx_filter -image i.fx_filter \ + -command [concat put_K12_objects $name fx_filter]] + match_linux_wm [list button $name.k12frame.fx.b_fx_multitap -image i.fx_multitap \ + -command [concat put_K12_objects $name fx_multitap]] + match_linux_wm [list button $name.k12frame.fx.b_fx_reverb -image i.fx_reverb \ + -command [concat put_K12_objects $name fx_reverb]] + pack $name.k12frame.fx.b_fx_filter $name.k12frame.fx.b_fx_multitap $name.k12frame.fx.b_fx_reverb -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.fx.b_fx_filter "Filter: Use this to make sound appear muffled or brighter" + setTooltip $name.k12frame.fx.b_fx_multitap "Echo: Use this to make sound echo" + setTooltip $name.k12frame.fx.b_fx_reverb "Reverb: Use this to make sound appear as if it is being played in a large space" + pdtk_k12panel_standardkeybindings $name.k12frame.fx.b_fx_filter + pdtk_k12panel_standardkeybindings $name.k12frame.fx.b_fx_multitap + pdtk_k12panel_standardkeybindings $name.k12frame.fx.b_fx_reverb + + # ---------------------------------- OUTPUT/OTHER ----------------------------------------- + + match_linux_wm [list frame $name.k12frame.output -relief flat] + match_linux_wm [list button $name.k12frame.output.b_output -image i.output \ + -command [concat put_K12_objects $name output]] + pack $name.k12frame.output.b_output -side left -expand 0 -padx 1 -pady 1 + setTooltip $name.k12frame.output.b_output "Output: Use this to send audio from computer into speakers" + pdtk_k12panel_standardkeybindings $name.k12frame.output.b_output + + # ---------------------------------------- NOW PACK THEM ALL ----------------------------------------- + pack $name.k12frame.edit $name.k12frame.datasound $name.k12frame.wii $name.k12frame.wii2 $name.k12frame.arduino $name.k12frame.math_1 $name.k12frame.math_2 $name.k12frame.math_3 $name.k12frame.logic $name.k12frame.other -side top -expand 0 -fill x + } + + if { $k12_mode == 0 } { + wm minsize $name 50 20 + } else { + wm minsize $name 580 407 + } +*/ + + + +// net stuff +var net = require('net'); + +var HOST = '127.0.0.1'; +var PORT; +var client; + +exports.set_port = function (port_no) { + PORT = port_no; +} + + +function connect () { + client = new net.Socket(); + client.setNoDelay(true); + client.connect(PORT, HOST, function() { + console.log('CONNECTED TO: ' + HOST + ':' + PORT); + // Write a test message to the socket as soon as the client is connected, + //the server will receive it as message from the client. This can be removed + // once it's obvious it works... + client.write('I am Chuck Norris!;'); + }); +} + +exports.connect = connect; + +// Add a 'data' event handler for the client socket +// data parameter is what the server sent to this socket + +// Pd can send us different types of data: +// 1) The old style tcl commands with "\n" at end (or "\\\n" for continuation) +// 2) new style commands: "nw selector { param1: 'value', param2: 42, etc. };\n" +// 3) raw javascript (not implemented yet) +// Below we separate the wheat from chaff, eval'ing the new commands and just +// printing the old ones in blue to the console + +// This wheat/chaff setup has the side-effect of stripping all newline +// characters from pd->gui messages. Because of this a newline is added in +// gui_post. Once all the old tcl messages are removed we can parse solely +// on ";", and the side effect can be removed. + +// can be removed. + +var nextCmd = ""; // Build up a command across lines (or buffers) + +function init_socket_events () { + client.on('data', function(data) { + // console.log('DATA: ' + data); + var dataStr = data.toString('utf-8'); +// console.log("The whole buffer is " + dataStr); + var arr = dataStr.split("\n"); + var arrLen = arr.length; + var cmdHeader = 0; + for (var i = 0; i < arrLen; i++) { + var prefix = arr[i].substring(0, 2); + if (prefix == 'nw' || prefix == 'nn') { + nextCmd = arr[i].substring(3); +// console.log("nextCmd is " + nextCmd); + cmdHeader = 1; + } else if (cmdHeader) { + nextCmd += arr[i]; + // console.log("2nd part of cmd is " + arr[i]); + } else { +// gui_post(arr[i], "blue"); + } + // check if we end with a semicolon followed by a newline + if (nextCmd.slice(-1) === ";" && nextCmd.slice(-2) !== '\\') { +// console.log("raw cmd is: " + nextCmd); + nextCmd = nextCmd.replace(/\n/g, "\\n"); +// nextCmd = nextCmd.replace(/'/g, "\\\'"); + var selector = nextCmd.slice(0, nextCmd.indexOf(" ")); + var args = nextCmd.slice(selector.length + 1, -1); +// console.log(selector + '(' + args + ');'); + eval(selector + '(' + args + ');'); + nextCmd = ""; + cmdHeader = 0; + } + + } + // Close the client socket completely + // client.destroy(); + // console.log('Connection closed'); + + }); + + // Add a 'close' event handler for the client socket + client.on('close', function() { + //console.log('Connection closed'); + //client.destroy(); + nw_app_quit(); // set a timeout here if you need to debug + }); +} + +exports.init_socket_events = init_socket_events; + +// Send commands to Pd +function pdsend(string) { + client.write(string + ';'); + // for now, let's reprint the outgoing string to the pdwindow +// gui_post(string + ';', "red"); +} + +exports.pdsend = pdsend; + +// Send a ping message back to Pd +function gui_ping() { + pdsend("pd ping"); +} + +// Send a message to Pd to ping the "watchdog", which is a program +// that supervises Pd when run with -rt flag on some OSes +function gui_ping_watchdog() { + pdsend("pd watchdog"); +} + +// Schedule watchdog pings for the life of the GUI +function gui_watchdog() { + setInterval(gui_ping_watchdog, 2000); +} + +// Text drawing stuff + +// Here's the main API, structured to make an easier (inital) transition +// from tcl/tk to javascript + +// Gobj container, so that all drawn items are contained in a <g> which +// handles displacing (and in the future, possibly clicks and other events) +function get_gobj(cid, object) { + return patchwin[cid].window.document.getElementById(object + 'gobj'); +} + +// Convenience function to get a drawn item of gobj +function get_item(cid,item_id) { + return patchwin[cid].window.document.getElementById(item_id); +} + +// Similar to [canvas create] in tk +function create_item(cid,type,args) { + var item = patchwin[cid].window.document.createElementNS('http://www.w3.org/2000/svg', type); + if (args !== null) { + configure_item(item, args); + } + return item; +} + +// Similar to [canvas itemconfigure], without the need for a reference to the canvas +function configure_item(item, attributes) { + // draw_vis from g_template sends attributes as a ['attr1',val1, 'attr2', val2, etc.] array, + // so we check for that here + if (Array.isArray(attributes)) { + // we should check to make sure length is even here... + for (var i = 0; i < attributes.length; i+=2) { + item.setAttributeNS(null, attributes[i], attributes[i+1]); + } + } else { + for (var attr in attributes) { + if (attributes.hasOwnProperty(attr)) { + item.setAttributeNS(null, attr, attributes[attr]); + } + } + } +} + +// Most of these map either to pd.tk procs, or in some cases Tk canvas subcommands +function gui_text_create_gobj(cid, tag, xpos, ypos) { + var svg = get_item(cid, "patchsvg"); // "patchsvg" is id for the svg in the DOM + // Put objects on half-pixels to make them crisp (look in to the difference between + // this and the object-rendering 'crispEdges' attribute) + xpos += 0.5; + ypos += 0.5; + var transform_string = 'translate(' + xpos + ',' + ypos + ')'; + var g = create_item(cid, 'g', { + id: tag + 'gobj', + transform: transform_string + }); + svg.appendChild(g); + return g; +} + +function gui_text_drawborder(cid, tag, isbroken, x1, y1, x2, y2) { + var g = get_gobj(cid, tag); + // isbroken means either + // a) the object couldn't create or + // b) the box is empty + var rect = create_item(cid, 'rect', { + width: x2 - x1, + height: y2 - y1, + stroke: 'black', + fill: 'none', + 'shape-rendering': 'optimizeSpeed', + id: tag + 'border', + class: (isbroken ? 'broken_border' : '') + }); + g.appendChild(rect); +} + +function gui_canvas_drawio(cid, parenttag, tag, x1, y1, x2, y2, basex, basey) { + var g = get_gobj(cid, parenttag); + // probably need to add an id for xlets below + var rect = create_item(cid, 'rect', { + width: x2 - x1, + height: y2 - y1, + x: x1 - basex, + y: y1 - basey, + class: 'xlet' + }); + g.appendChild(rect); +} + +function gui_message_drawborder(cid,tag,width,height) { + var g = get_gobj(cid, tag); + var p_array = [0,0, + width+4, 0, + width, 4, + width, height-4, + width+4, height, + 0, height, + 0, 0]; + var polygon = create_item(cid, 'polygon', { + points: p_array.join(), + fill: 'none', + stroke: 'black', + 'stroke-width': 1, + id: tag + 'border' + }); + g.appendChild(polygon); +} + +function gui_message_flash(cid, tag, state) { + var b = get_item(cid, tag + 'border'); + var w; + if (state != 0) { w = 4; } else { w = 1; } + configure_item(b, { 'stroke-width': w }); +} + +function gui_message_redraw_border(cid,tag,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14) { + var b = get_item(cid, tag + 'border'); + var p_array = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14]; + configure_item(b, { + points: p_array.join(" "), + }); +} + + +function gui_atom_drawborder(cid,tag,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12) { + var p_array = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12]; + var g = get_gobj(cid, tag); + var polygon = create_item(cid, 'polygon', { + points: p_array.join(" "), + fill: 'none', + stroke: 'gray', + 'stroke-width': 1, + id: tag + 'border' + }); + g.appendChild(polygon); +} + +// draw a patch cord +function gui_canvas_line(cid,tag,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) { + var d_array = ['M', p1 + 0.5, p2 + 0.5, + 'Q', p3 + 0.5, p4 + 0.5, p5 + 0.5, p6 + 0.5, + 'Q', p7 + 0.5, p8 + 0.5 ,p9 + 0.5, p10 + 0.5]; + var svg = get_item(cid, "patchsvg"); + var path = create_item(cid, 'path', { + d: d_array.join(" "), + fill: 'none', + stroke: 'gray', + 'stroke-width': 1, + 'shape-rendering': 'optimizeSpeed', + id: tag + }); + svg.appendChild(path); +} + +function gui_canvas_select_line(cid, tag) { + var line = get_item(cid, tag); + if (line !== null) { + configure_item(line, { class: 'selected_line' }); + } else { + gui_post("gui_canvas_select_line: can't find line"); + } +} + +function gui_canvas_deselect_line(cid, tag) { + var line = get_item(cid, tag); + if (line !== null) { + configure_item(line, { class: '' }); + } else { + gui_post("gui_canvas_select_line: can't find line"); + } +} + +// rename to erase_line (or at least standardize with gobj_erase) +function gui_canvas_delete_line(cid, tag) { + var line = get_item(cid, tag); + if (line !== null) { + line.parentNode.removeChild(line); + } else { + gui_post("canvas_delete_line: something is fucked up because the line doesn't exist"); + } +} + +function gui_canvas_updateline(cid,tag,x1,y1,x2,y2,yoff) { +// console.log("cord tag in gui_canvas_updateline is " + tag); + var halfx = parseInt((x2 - x1)/2); + var halfy = parseInt((y2 - y1)/2); + var d_array = ['M',x1,y1, + 'Q',x1,y1+yoff,x1+halfx,y1+halfy, + 'Q',x2,y2-yoff,x2,y2]; +// gui_post(d_array.toString()); + var cord = get_item(cid, tag); + configure_item(cord, { d: d_array.join(" ") }); +} + +function gui_text_new(canvasname, myname, type, isselected, x, y, text, font) { +// gui_post("font is " + font); + + var g = get_gobj(canvasname, myname); + var svg_text = create_item(canvasname, 'text', { + // x and y are fudge factors. Text on the tk canvas used an anchor + // at the top-right corner of the text's bbox. SVG uses the baseline. + // There's probably a programmatic way to do this, but for now-- fudge factors + // based on the DejaVu Sans Mono font. :) + x: 1, + y: 13, + 'shape-rendering': 'optimizeSpeed', + 'font-size': font + 'px', + id: myname + 'text' + }); + + // find a way to abstract away the canvas array and the DOM here + var text_node = patchwin[canvasname].window.document.createTextNode(text); + svg_text.appendChild(text_node); + if (g !== null) { + g.appendChild(svg_text); + } else { + gui_post("gui_text_new: can't find parent group"); + } + + if (isselected) { + gui_text_select(canvasname, myname); + } +} + +function gui_gobj_erase(cid, tag) { + var g = get_gobj(cid, tag); + if (g !== null) { + g.parentNode.removeChild(g); + } else { + gui_post("gui_gobj_erase: gobj " + tag + " didn't exist in the first place!"); + } +} + +function gui_text_set (cid, tag, text) { + var svg_text = get_item(cid, tag + 'text'); + if (svg_text !== null) { + svg_text.textContent = text; + } else { + gui_post("gui_text_set: svg_text doesn't exist!"); + } +} + +// Not sure whether this is even used anymore +function gui_text_redraw_border(cid, tag, x1, y1, x2, y2) { + var b = get_item(cid, tag + 'border'); + configure_item(b, { + width: x2 - x1, + height: y2 - y1 + }); +} + +function gui_text_select(cid, tag) { + var g = get_gobj(cid, tag); + var b = get_item(cid, tag + 'border'); + if (g !== null) { + configure_item(g, { class: 'selected' }); + } else { + console.log("text_select: something wrong with group tag: " + tag); + } + if (b !== null) { + configure_item(b, { class: 'selected_border' }); + } +} + +function gui_text_deselect(cid, tag) { + gui_post("deselecting text with tag..." + tag); + var gobj = get_gobj(cid, tag) + var border = get_item(cid, tag + 'border'); + if (gobj !== null) { + configure_item(gobj, { class: "" }); + } else { + console.log("text_deselect: something wrong with tag: " + tag + 'gobj'); + } + if (border !== null) { + configure_item(border, { class: "" }); + } else { + console.log("text_select: something wrong with tag: " + tag + 'border'); + } +} + +function gui_text_select_color(cid, tag) { +// nb: this is handled in css now +return; + var rect = get_item(cid, tag + 'border'); + if (rect !== null) { + configure_item(rect, { + stroke: 'blue', + 'stroke-width': 1, + 'stroke-dasharray': 'none' + }); + } else { + gui_post("select_color: something wrong with tag: " + tag + 'border'); + } +} + +function gui_canvas_displace_withtag(name, dx, dy) { + var pwin = patchwin[name]; + var ol = pwin.window.document.getElementsByClassName('selected'); + for (var i = 0; i < ol.length; i++) { + var new_tx = dx + ol[i].transform.baseVal.getItem(0).matrix.e; + var new_ty = dy + ol[i].transform.baseVal.getItem(0).matrix.f; + ol[i].setAttributeNS(null, 'transform', + 'translate(' + new_tx + ',' + new_ty + ')'); + } +} + +function gui_create_selection_rectangle(cid, x1, y1, x2, y2) { + var svg = get_item(cid, "patchsvg"); + var points_array = [x1 + 0.5, y1 + 0.5, + x2 + 0.5, y1 + 0.5, + x2 + 0.5, y2 + 0.5, + x1 + 0.5, y2 + 0.5 + ]; + var rect = create_item(cid, 'polygon', { + points: points_array.join(" "), + fill: 'none', + stroke: 'black', + 'shape-rendering': 'optimizeSpeed', + 'stroke-width': 1, + id: 'selection_rectangle', + display: 'inline' + }); + svg.appendChild(rect); +} + +function gui_move_selection_rectangle(cid, x1, y1, x2, y2) { + var points_array = [x1 + 0.5, y1 + 0.5, x2 + 0.5, y1 + 0.5, + x2 + 0.5, y2 + 0.5, x1 + 0.5, y2 + 0.5]; + var rect = get_item(cid, 'selection_rectangle'); + configure_item(rect, { points: points_array }); +} + +function gui_hide_selection_rectangle(cid) { +// gui_post("hiding selection"); + var rect = get_item(cid, 'selection_rectangle'); + rect.parentElement.removeChild(rect); +} + +// iemguis + +function gui_create_bng(cid, tag, cx, cy, radius) { + var g = get_gobj(cid, tag); + var circle = create_item(cid, 'circle', { + cx: cx, + cy: cy, + r: radius, + fill: 'none', + stroke: 'black', + 'stroke-width': 1, + id: tag + 'button' + }); + g.appendChild(circle); +} + +function gui_bng_update(cid, tag, flashed) { + var button = get_item(cid, tag + 'button'); + var fill = flashed ? 'red' : 'none'; + configure_item(button, { fill: fill }); +} + +function gui_create_toggle(cid, tag, color, width, p1,p2,p3,p4,p5,p6,p7,p8,basex,basey) { + var g = get_gobj(cid, tag); + var points_array = [p1 - basex, p2 - basey, + p3 - basex, p4 - basey + ]; + var cross1 = create_item(cid, 'polyline', { + points: points_array.join(" "), + stroke: color, + fill: 'none', + id: tag + 'cross1', + display: 'none', + 'stroke-width': width + }); + + points_array = [p5 - basex, p6 - basey, + p7 - basex, p8 - basey + ]; + var cross2 = create_item(cid, 'polyline', { + points: points_array.join(" "), + stroke: color, + fill: 'none', + id: tag + 'cross2', + display: 'none', + 'stroke-width': width + }); + g.appendChild(cross1); + g.appendChild(cross2); +} + +function gui_toggle_update(cid, tag, state) { + var cross1 = get_item(cid, tag + 'cross1'); + var cross2 = get_item(cid, tag + 'cross2'); + if (state) { + configure_item(cross1, { display: 'inline' }); + configure_item(cross2, { display: 'inline' }); + } else { + configure_item(cross1, { display: 'none' }); + configure_item(cross2, { display: 'none' }); + } +} + +// Todo: send fewer parameters from c +function gui_create_numbox(cid,tag,bgcolor,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,basex,basey,half) { + // numbox doesn't have a standard iemgui border, so we must create its gobj manually + var g = gui_text_create_gobj(cid, tag, basex, basey) + var data_array = ['M', p1 - basex, p2 - basey, + 'L', p3 - basex, p4 - basey, + p5 - basex, p6 - basey, + p7 - basex, p8 - basey, + p9 - basex, p10 - basey, + 'z', + 'L', basex - basex, basey - basey, + half, half, + p9 - basex, p10 - basey]; + var border = create_item(cid, 'path', { + d: data_array.join(" "), + fill: bgcolor, + stroke: 'black', + 'stroke-width': 1, + id: (tag + 'border') + }); + g.appendChild(border); +} + +function gui_numbox_drawtext(cid,tag,text,color,xpos,ypos,basex,basey) { + var g = get_gobj(cid, tag); + var svg_text = create_item(cid, 'text', { + x: xpos - basex, + y: ypos - basey + 5, + 'font-size': font, + id: tag + 'text' + }); + + var text_node = patchwin[cid].window.document.createTextNode(text); + svg_text.appendChild(text_node); + g.appendChild(svg_text); +} + +function gui_create_slider(cid,tag,color,p1,p2,p3,p4,basex, basey) { + var g = get_gobj(cid, tag); + var indicator = create_item(cid, 'line', { + x1: p1 - basex, + y1: p2 - basey, + x2: p3 - basex, + y2: p4 - basey, + stroke: color, + 'stroke-width': 3, + fill: 'none', + id: tag + 'indicator' + }); + g.appendChild(indicator); + +} + +function gui_slider_update(cid,tag,p1,p2,p3,p4,basex,basey) { + var indicator = get_item(cid, tag + 'indicator'); + configure_item(indicator, { + x1: p1 - basex, + y1: p2 - basey, + x2: p3 - basex, + y2: p4 - basey + }); +} + +function gui_create_radio(cid,tag,p1,p2,p3,p4,i,basex,basey) { + var g = get_gobj(cid, tag); + var cell = create_item(cid, 'line', { + x1: p1 - basex, + y1: p2 - basey, + x2: p3 - basex, + y2: p4 - basey, + // stroke is just black for now + stroke: 'black', + 'stroke-width': 1, + fill: 'none', + id: tag + 'cell_' + i + }); + g.appendChild(cell); +} + +function gui_create_radio_buttons(cid,tag,color,p1,p2,p3,p4,basex,basey,i,state) { + var g = get_gobj(cid, tag); + var b = create_item(cid, 'rect', { + x: p1 - basex, + y: p2 -basey, + width: p3 - p1, + height: p4 - p2, + stroke: color, + fill: color, + id: tag + 'button_' + i, + display: state ? 'inline' : 'none' + }); + g.appendChild(b); +} + +function gui_radio_update(cid,tag,prev,next) { + var prev = get_item(cid, tag + 'button_' + prev); + var next = get_item(cid, tag + 'button_' + next); + configure_item(prev, { display: 'none' }); + configure_item(next, { display: 'inline' }); +} + +function gui_create_vumeter_text(cid,tag,color,xpos,ypos,text,index,basex,basey) { + var g = get_gobj(cid, tag); + var svg_text = create_item(cid, 'text', { + x: xpos - basex, + y: ypos - basey, + // font-size: font); + id: tag + 'text_' + index + }); + + var text_node = patchwin[cid].window.document.createTextNode(text); + svg_text.appendChild(text_node); + g.appendChild(svg_text); +} + +function gui_create_vumeter_steps(cid,tag,color,p1,p2,p3,p4,width,index,basex,basey) { + var g = get_gobj(cid, tag); + var l = create_item(cid, 'line', { + x1: p1 - basex, + y1: p2 - basey, + x2: p3 - basex, + y2: p4 - basey, + stroke: color, + 'stroke-width': width, + 'id': tag + 'led_' + i + }); + g.appendChild(l); +} + +function gui_create_vumeter_rect(cid,tag,color,p1,p2,p3,p4,basex,basey) { + var g = get_gobj(cid, tag); + var rect = create_item(cid, 'rect', { + x: p1 - basex, + y: p2 - basey, + width: p3 - p1, + height: p4 + 1 - p2, + stroke: color, + fill: color, + id: tag + 'rect' + }); + g.appendChild(rect); +} + +function gui_create_vumeter_peak(cid,tag,color,p1,p2,p3,p4,width,basex,basey) { + var g = get_gobj(cid, tag); + var line = create_item(cid, 'line', { + x1: p1 - basex, + y1: p2 - basey, + x2: p3 - basex, + y2: p4 - basey, + stroke: color, + 'stroke-width': width, + id: tag + 'peak' + }); + g.appendChild(line); +} + +// change tag from "rect" to "rms" +function gui_vumeter_update_rms(cid,tag,p1,p2,p3,p4,basex,basey) { + rect = get_item(cid, tag + 'rect'); + configure_item(rect, { + x: p1 - basex, + y: p2 - basey, + width: p3 - p1, + height: p4 - p2 + 1 + }); +} + +function gui_vumeter_update_peak(cid,tag,color,p1,p2,p3,p4,basex,basey) { + line = get_item(cid, tag + 'peak'); + configure_item(line, { + x1: p1 - basex, + y1: p2 - basey, + x2: p3 - basex, + y2: p4 - basey, + stroke: color + }); +} + +// Think about merging with gui_text_drawborder +function gui_iemgui_drawborder(cid, tag, bgcolor, x1, y1, x2, y2) { + var g = get_gobj(cid, tag); + var rect = create_item(cid, 'rect', { + width: x2 - x1, + height: y2 - y1, + fill: bgcolor, + stroke: 'black', + 'shape-rendering': 'optimizeSpeed', + 'stroke-width': 1, + id: tag + 'border' + }); + g.appendChild(rect); +} + + +function gui_create_mycanvas(cid,tag,color,x1,y1,x2_vis,y2_vis,x2,y2) { + var rect_vis = create_item(cid,'rect', { + width: x2_vis - x1, + height: y2_vis - y1, + fill: color, + stroke: color + } + ); + + // we use a drag_handle-- unlike a 'border' it takes + // the same color as the visible rectangle when deselected + var rect = create_item(cid,'rect', { + width: x2 - x1, + height: y2 - y1, + fill: color, + stroke: color, + id: tag + 'drag_handle' + } + ); + var g = get_gobj(cid,tag); + g.appendChild(rect_vis); + g.appendChild(rect); +} + +function gui_mycanvas_select_color(cid,tag,color) { + item = get_item(cid,tag + 'drag_handle'); + configure_item(item, {stroke: color}); +} + +// This should be merged with gui_create_gobj somehow +function gui_create_scalar(cid, tag, isselected, t1, t2, t3, t4, t5, t6) { + var svg = get_item(cid, "patchsvg"); // "patchsvg" is id for the svg in the DOM + // Normally put objects on half-pixels to make them crisp, but if we create a + // scalar in an object box we already did that. This unfortunately creates a 0.5 + // pix discrepancy between scalars created in object boxes and ones created with + // [append]. Think about just using shape-rendering value of 'crispEdges' in the + // places where it matters... + t5 += 0.5; + t6 += 0.5; + var matrix = [t1,t2,t3,t4,t5,t6]; + var transform_string = 'matrix(' + matrix.join() + ')'; + var g = create_item(cid, 'g', { + id: tag + 'gobj', + transform: transform_string, + class: (isselected ? 'selected' : '') + }); + // Let's make a selection rect... but we can't make it + // a child of the gobj group because the getrect fn gives + // us a bbox in the canvas coord system + var selection_rect = create_item(cid, 'rect', { + id: tag + 'selection_rect', + display: 'none', + fill: 'none', + 'pointer-events': 'none' + }); + g.appendChild(selection_rect); + svg.appendChild(g); + gui_post("made a scalar..."); + return g; +} + +function gui_scalar_erase(cid, tag) { + var g = get_gobj(cid, tag); + g.parentNode.removeChild(g); + // selection rect... +// var sr = get_item(cid, tag + 'selection_rect'); +// sr.parentNode.removeChild(sr); +} + +function gui_scalar_draw_select_rect(cid, tag, state, x1, y1, x2, y2, basex, basey) { + // This is unnecessarily complex-- the select rect is a child of the parent + // scalar group, but in the initial Tkpath API the rect was free-standing. This + // means all the coordinate parameters are in the screen position. But we need + // the coords relative to the scalar's x/y-- hence we subtract the scalar's basex/basey + // from the coords below + //gui_post("drawselectrect: " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + basex + " " + basey); + var r = get_item(cid, tag + 'selection_rect'); + configure_item(r, { + display: (state ? 'inline' : 'none'), + x: (x1 - basex), + y: (y1 - basey), + width: x2 - x1, + height: y2 - y1, + stroke: 'blue', + }); +} + +function gui_create_scalar_group(cid, tag, parent_tag, attr_array) { + var parent = get_item(cid, parent_tag); + if (attr_array === undefined) { + attr_array = []; + } + attr_array.push("id", tag); + var g = create_item(cid, 'g', attr_array); + parent.appendChild(g); + gui_post("made an innder scalar group"); + return g; +} + +function gui_scalar_configure_gobj(cid, tag, isselected, t1, t2, t3, t4, t5, t6) { + var gobj = get_gobj(cid, tag); + var matrix = [t1,t2,t3,t4,t5,t6]; + var transform_string = 'matrix(' + matrix.join() + ')'; + configure_item(gobj, { transform: transform_string }); +} + +function gui_draw_vis(cid, type, coords, attr_array, tag_array) { + gui_post("inside gui_draw_vis"); + for(var i = 0; i < arguments.length; i++) { + gui_post("arg1 is " + arguments[i]); + } + gui_post("coords is " + coords); + gui_post("coords is array: " + Array.isArray(coords)); + gui_post("arguments[2] is " + arguments[2]); + gui_post("type of coords is " + typeof coords); + gui_post("type of arguments[2] is " + typeof arguments[2]); + gui_post("arguments[2] is array: " + Array.isArray(arguments[2])); + var g = get_item(cid, tag_array[0]); + if (g !== null) { + gui_post("our parent exists."); + } else { + gui_post("our parent doe not exists."); + } + //var ca = coords; + switch(type) { + case 'rect': + attr_array.push('x', coords[0]); + attr_array.push('y', coords[1]); + attr_array.push('width', coords[2]); + attr_array.push('height',coords[3]); + break; + // we originally treated circle as an ellipse because we were manually changing the + // aspect ratio using coordinates (with glist_xtopixels/ytopixels). That can probably + // be changed now that we're applying that in the parent group transform... + case 'circle': + type = 'ellipse'; + case 'ellipse': + attr_array.push('cx',coords[0]); + attr_array.push('cy',coords[1]); + attr_array.push('rx',coords[2]); + attr_array.push('ry',coords[3]); + break; + case 'line': + attr_array.push('x1',coords[0]); + attr_array.push('y1',coords[1]); + attr_array.push('x2',coords[2]); + attr_array.push('y2',coords[3]); + break; + case 'polyline': + case 'polygon': + attr_array.push('points',coords.join(" ")); + break; + case 'path': + attr_array.push('d',coords.join(" ")); + break; + } + attr_array.push('id', tag_array[1]); + gui_post("create is " + tag_array[1]); + var item = create_item(cid, type, attr_array); + if (item !== null) { + gui_post("we got create."); + } else { + gui_post("we doe not got creat."); + } + g.appendChild(item); +} + +function gui_draw_erase_item(cid, tag) { + gui_post("baleting... tag is " + tag); + var item = get_item(cid, tag); + if (item !== null) { + item.parentNode.removeChild(item); + } else { + gui_post("uh oh... gui_draw_erase_item couldn't find the item..."); + } +} + +// Configure one attr/val pair at a time, received from Pd +function gui_draw_configure(cid, tag, attr, val) { + var item = get_item(cid, tag); + var obj = {}; + if (Array.isArray(val)) { + obj[attr] = val.join(" "); + } else { + // strings or numbers + obj[attr] = val; + } + configure_item(item, obj); +} + +// Configure multiple attr/val pairs (this should be merged with gui_draw_configure at some point +function gui_draw_configure_all(cid, tag, attr_array) { + var item = get_item(cid, tag); + configure_item(item, attr_array); +} + +function add_popup(cid, popup) { + popup_menu[cid] = popup; +} + +exports.add_popup = add_popup; + +function gui_canvas_popup(cid, xpos, ypos, canprop, canopen, isobject) { + gui_post("canvas_popup called... " + JSON.stringify(arguments)); + // Set the global popup x/y so they can be retrieved by the relevant doc's event handler + popup_coords[0] = xpos; + popup_coords[1] = ypos; + popup_menu[cid].items[0].enabled = canprop; + popup_menu[cid].items[1].enabled = canopen; + + // We'll use "isobject" to enable/disable "To Front" and "To Back" + //isobject; + + // Get page coords for top of window, in case we're scrolled + var left = patchwin[cid].window.document.body.scrollLeft; + var top = patchwin[cid].window.document.body.scrollTop; + + popup_menu[cid].popup(xpos - left, ypos - top); +} + +function popup_action(cid, index) { + pdsend(cid + " done-popup " + index + " " + popup_coords.join(" ")); +} + +exports.popup_action = popup_action; + + +// Graphs and Arrays + +function gui_graph_drawborder(cid, tag, x1, y1, x2, y2) { + var svgelem = get_item(cid, 'patchsvg'); + var b = create_item(cid, 'rect', { + x: x1, + y: y1, + width: x2 - x1, + height: y2 - y1, + stroke: 'black', + fill: 'none', + id: tag + }); + svgelem.appendChild(b); +} + +function gui_graph_deleteborder(cid, tag) { + var b = get_item(cid, tag); + b.parentNode.removeChild(b); +} + +function gui_canvas_drawredrect(cid, x1, y1, x2, y2) { + var svgelem = get_item(cid, 'patchsvg'); + var b = create_item(cid, 'rect', { + x: x1, + y: y1, + width: x2 - x1, + height: y2 - y1, + stroke: 'red', + id: 'GOP' + }); + svgelem.appendChild(b); +} + +function gui_canvas_deleteredrect(cid) { + var r = get_item(cid, 'GOP'); + r.parentNode.removeChild(r); +} + +// Magic Glass (aka Cord Inspector) + +// For clarity, this probably shouldn't be a gobj. Also, it might be easier to +// make it a div that lives on top of the patchsvg +function gui_create_cord_inspector(cid) { + var g = get_gobj(cid, 'cord_inspector'); + var ci_rect = create_item(cid, 'rect', { id: 'cord_inspector_rect' }); + var ci_poly = create_item(cid, 'polygon', { id: 'cord_inspector_polygon' }); + var ci_text = create_item(cid, 'text', { id: 'cord_inspector_text' }); + var text_node = patchwin[cid].window.document.createTextNode(''); + ci_text.appendChild(text_node); + g.appendChild(ci_rect); + g.appendChild(ci_poly); + g.appendChild(ci_text); +} + +function gui_cord_inspector_update(cid, text, basex, basey, bg_size, y1, y2, moved) { + var gobj = get_gobj(cid, 'cord_inspector'); + gobj.setAttributeNS(null, 'transform', + 'translate(' + (basex + 10.5) + ',' + (basey + 0.5) + ')'); + gobj.setAttributeNS(null, 'pointer-events', 'none'); + var rect = get_item(cid, 'cord_inspector_rect'); + var poly = get_item(cid, 'cord_inspector_polygon'); + var svg_text = get_item(cid, 'cord_inspector_text'); + // Lots of fudge factors here, tailored to the current default font size + configure_item(rect, { + x: 13, + y: y1 - basey, + width: bg_size - basex, + height: y2 - basey + 10, + fill: 'none', + stroke: 'black' + }); + var polypoints_array = [8,0,13,5,13,-5]; + configure_item(poly, { + points: polypoints_array.join() + }); + configure_item(svg_text, { + x: 20, + y: 5, + fill: 'black' + }); + // set the text + svg_text.textContent = text; +} + +function gui_erase_cord_inspector(cid) { + var ci = get_gobj(cid, 'cord_inspector'); + if (ci !== null) { + ci.parentNode.removeChild(ci); + } else { + gui_post("oops, trying to erase cord inspector that doesn't exist!"); + } +} + +function gui_cord_inspector_flash(cid) { + var ct = get_item(cid, 'cord_inspector_text'); + if (ct !== null) { + configure_item(ct, { fill: 'red' }); + } else { + gui_post("gui_cord_inspector_flash: trying to flash a non-existent cord inspector!"); + } +} + + +// Window functions + +function gui_raise_window(cid) { + patchwin[cid].focus(); +} diff --git a/pd/nw/todo.txt b/pd/nw/todo.txt new file mode 100644 index 0000000000000000000000000000000000000000..9946e7abf9e596cc2a3c491b25b0ad069eb1cb87 --- /dev/null +++ b/pd/nw/todo.txt @@ -0,0 +1,80 @@ +Problems to put off until all (or most) sys_vgui calls are eliminated: +1) gui-side parser inside -- pdgui.js. Currently we're splitting on newlines so we can separate + gui_vmess from sys_vgui calls. This makes it very difficult to handle multi-line msg and text + boxes. +2) Semicolons -- currently the parser can't tell the difference between semicolons inside symbols + and semicolons that end statements. Again, this will be easy to solve once we eliminate sys_gui. + +HTML5 which may not be standard yet: +1) mouse.pageX/pageY -- exist in Chromium but maybe not in FF et al. +2) svg 'overflow' attribute -- probably doesn't work in other browsers +3) document.body.scrollTop (might be Chromium-specific, not sure) +3) document.body.scrollLeft (might be Chromium-specific, not sure) + +Node-webkit stuff: +1) popup API +2) new window API +3) window menus +4) (probably) present working directory +5) command line argv + +Everything else: +* packaging as app, setting correct appname, etc +* get -unique to work (relied on tcl [send] command) +* check if patch windows with screenposition (0,0) get stuck underneath Ubuntu/OSX menu. If so, + Node-webkit has a "screen" interface to retrieve the "workable" area of the screen +* choosing the same directory multiple times (see dialog API page) +* figure out why there is a "pd_opendir" global var +* pass k12 mode arg +* implement recent files (using Pd's prefs loading mechanism instead of reimplementing gui prefs) +* implement verifyquit +* save and saveas dialogs aren't defaulting to the present working directory +* create a loop (maybe every second) to check bbox of patchsvg, and set the height/width to that + bbox for the svg. That should trigger the correct scrollbar behavior. +* change canvas string to a single int (and investigate any side-effects) +* destroy (or, more likely, hide) selection rectangle when not needed +* change gui_text_select to gui_gobj_select +* make it possible to have the inner cells of hradio change color with the selection, as the border currently does. Tk just uses the non-hierarchical tags and appends the word "BASE". (Maybe use an inner <g> to do this.) +* make mycnv use its own selection logic +* abstract away appendChild +* font-size should be set as css property for a class of text, rather than per each gobj in svg +* remove the "fudge_factor" kludge in g_rtext.c, and handle fonts in a sane manner. In doing so + we must decide whether or not we want to be able to fetch the bounding box of objects from + within a Pd patch. (Currently [canvasinfo] and [objectinfo] are the only objects that can + do this, though there might also be) +* replace things like gui_select_color with css +* find a better approach to escaping characters for the gui than escape_double_quotes kludge (and handle any other problematic chars) +* look into using <def> and <use> for scalars. +* use Atom's selectors for standard OSX behavior (cut, paste, about, etc.) +* in draw_vis, make circle and ellipse radii attr floats instead of ints +* should stroke-dasharray values be floats? +* once garrays are drawn inside a <g> we won't have to individually erase each child of a scalar +* clean up svg_sendupdate -- put a single gui_vmess at the end +* svg_sendupdate -- make sure there aren't arbitrary %d's that should actually be %g's +* svg_sendupdate -- need a gui interface for stuff like stroke-dasharray (and garrays) +* ibid., for path data, points +* make pdgui function names more consistent +* in draw_vis, move tags to front of function call so they don't have to be an ugly array +* in draw_vis, remove all the coords logic and let svg_togui do that work. In svg_new, + leverage the "d", "points", etc. methods to do the same. +* remove the draw_vis warning/code about needing 2 points to draw +* might want to clean up dead windows inside patchwin object (on close) +* make gui_menu_close filename less hacky (currently includes patch args in the middle) +* figure out why -nrt flag causes Pd to bail on the GUI (it wasn't doing this + on the amd_64 virtual Jessie machine) +* make dialogs with [yes/no] instead of [cancel/ok] +* make a gui_mess interface for the edge cases that don't require args (similar to sys_gui) +* make sure we're breaking down the socket properly from the GUI side on quit +* nwworkingdir isn't working with the saveas dialog in pdcanvas.html +* nwworkingdir only works on the second file open +* implement the stuff at the end of saveas_callback (recentfiles et al); +* make an "export" menu command for max patch saving. That way we can accept a single extension + for saving (.pd), and the native save dialog will warn us on potential file overwrites (even when + the user neglects to type an extension). +* draw graph inside gobj group +* merge gui_text_select and gui_text_deselect +* in function gui_cord_inspector_update, use parameter "moved" to flash text +* cord_inspector_flash doesn't seem to be deterministic-- if you move among several cords very fast + it will try to flash a non-existent svg item. (Probably want to either make a permanent item in + the pdcanvas.html for it, or hard-code a separate div.) +* for data structures, change "" to 'none' diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c index 2194b67c86f3e3b106bc220fc9465c46f36514a9..312d1e51c4865840ad682ac87fc9b56cb3a07c02 100644 --- a/pd/src/g_all_guis.c +++ b/pd/src/g_all_guis.c @@ -496,7 +496,9 @@ void iemgui_displace_withtag(t_gobj *z, t_glist *glist, int dx, int dy) void iemgui_select(t_gobj *z, t_glist *glist, int selected) { + char tagbuf[MAXPDSTRING]; t_iemgui *x = (t_iemgui *)z; + sprintf(tagbuf, "x%lx", (long unsigned int)x); t_canvas *canvas=glist_getcanvas(glist); if (selected) x->x_selected = canvas; @@ -504,6 +506,7 @@ void iemgui_select(t_gobj *z, t_glist *glist, int selected) x->x_selected = NULL; sys_vgui(".x%lx.c itemconfigure {x%lx&&border} -stroke %s\n", canvas, x, x->x_selected && x->x_glist == canvas ? selection_color : border_color); + gui_vmess("gui_text_select_color", "ss", canvas_string(canvas), tagbuf); x->x_draw((void *)z, glist, IEM_GUI_DRAW_MODE_SELECT); if (selected < 2) { @@ -941,11 +944,19 @@ static void scalehandle_check_and_redraw(t_iemgui *x) // IEMGUI refactor (by Mathieu) void iemgui_tag_selected(t_iemgui *x) { + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); t_canvas *canvas=glist_getcanvas(x->x_glist); if(x->x_selected) + { sys_vgui(".x%lx.c addtag selected withtag x%lx\n", canvas, x); + gui_vmess("gui_text_select", "ss", canvas_string(canvas), tagbuf); + } else + { sys_vgui(".x%lx.c dtag x%lx selected\n", canvas, x); + gui_vmess("gui_text_deselect", "ss", canvas_string(canvas), tagbuf); + } } void iemgui_label_draw_new(t_iemgui *x) { @@ -1023,12 +1034,18 @@ void iemgui_draw_io(t_iemgui *x, int old_sr_flags) //fprintf(stderr,"%lx SND: old_sr_flags=%d SND_FLAG=%d || OUTCOME: OLD_SND_FLAG=%d not_empty=%d\n", (t_int)x, old_sr_flags, IEM_GUI_OLD_SND_FLAG, a, b); if(a && !b) for (i=0; i<n; i++) + { sys_vgui(".x%lx.c create prect %d %d %d %d " "-stroke $pd_colors(iemgui_nlet) " "-tags {%so%d x%lx outlet %s}\n", canvas, x1+i*k, y2-1, x1+i*k + IOWIDTH, y2, iem_get_tag(canvas, x), i, x, x->x_selected == x->x_glist ? "iemgui selected" : "iemgui"); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_canvas_drawio", "sssiiiiii", canvas_string(canvas), tagbuf, + iem_get_tag(canvas, x), x1+i*k, y2-1, x1+i*k + IOWIDTH, y2, x1, y1); + } if(!a && b) for (i=0; i<n; i++) sys_vgui(".x%lx.c delete %so%d\n", canvas, iem_get_tag(canvas, x), i); @@ -1036,12 +1053,18 @@ void iemgui_draw_io(t_iemgui *x, int old_sr_flags) b=x->x_rcv!=s_empty; //fprintf(stderr,"%lx RCV: old_sr_flags=%d RCV_FLAG=%d || OUTCOME: OLD_RCV_FLAG=%d not_empty=%d\n", (t_int)x, old_sr_flags, IEM_GUI_OLD_RCV_FLAG, a, b); if(a && !b) for (i=0; i<n; i++) + { sys_vgui(".x%lx.c create prect %d %d %d %d " "-stroke $pd_colors(iemgui_nlet) " "-tags {%si%d x%lx inlet %s}\n", canvas, x1+i*k, y1, x1+i*k + IOWIDTH, y1+1, iem_get_tag(canvas, x), i, x, x->x_selected == x->x_glist ? "iemgui selected" : "iemgui"); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_canvas_drawio", "sssiiiiii", canvas_string(canvas), tagbuf, + iem_get_tag(canvas, x), x1+i*k, y1, x1+i*k + IOWIDTH, y1+1, x1, y1); + } if(!a && b) for (i=0; i<n; i++) sys_vgui(".x%lx.c delete %si%d\n", canvas, iem_get_tag(canvas, x), i); } @@ -1061,6 +1084,8 @@ void iemgui_io_draw_move(t_iemgui *x) { } void iemgui_base_draw_new(t_iemgui *x) { + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); t_canvas *canvas=glist_getcanvas(x->x_glist); t_class *c = pd_class((t_pd *)x); int x1,y1,x2,y2,gr=gop_redraw; gop_redraw=0; @@ -1070,6 +1095,12 @@ void iemgui_base_draw_new(t_iemgui *x) { "-stroke $pd_colors(iemgui_border) -fill #%6.6x " "-tags {%lxBASE x%lx text iemgui border}\n", canvas, x1,y1,x2,y2, x->x_bcol, x, x); + gui_vmess("gui_text_create_gobj", "ssii", canvas_string(canvas), tagbuf, + x1, y1); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", x->x_bcol); + gui_vmess("gui_iemgui_drawborder", "sssiiii", canvas_string(canvas), tagbuf, + colorbuf, x1, y1, x2, y2); } void iemgui_base_draw_move(t_iemgui *x) { @@ -1114,6 +1145,9 @@ void iemgui_draw_move(t_iemgui *x) { void iemgui_draw_erase(t_iemgui *x) { t_canvas *canvas=glist_getcanvas(x->x_glist); sys_vgui(".x%lx.c delete x%lx\n", canvas, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_gobj_erase", "ss", canvas_string(canvas), tagbuf); scalehandle_draw_erase2(x); } diff --git a/pd/src/g_bang.c b/pd/src/g_bang.c index 4370ebe4b6590c32b1fe6abaaf7bca466344486b..3ca7b2e71265f89cb277c1f8d9ce1fbb4337affb 100644 --- a/pd/src/g_bang.c +++ b/pd/src/g_bang.c @@ -24,18 +24,24 @@ static t_class *bng_class; void bng_draw_update(t_gobj *xgobj, t_glist *glist) { + char tagbuf[MAXPDSTRING]; t_bng *x = (t_bng *)xgobj; + sprintf(tagbuf, "x%lx", (long unsigned int)&x->x_gui); if (x->x_gui.x_changed != x->x_flashed && glist_isvisible(glist)) { - sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n", - glist_getcanvas(glist), x, - x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol); +// sys_vgui(".x%lx.c itemconfigure %lxBUT -fill #%6.6x\n", +// glist_getcanvas(glist), x, +// x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol); + gui_vmess("gui_bng_update", "ssi", + canvas_string(glist_getcanvas(glist)), tagbuf, x->x_flashed); } x->x_gui.x_changed = x->x_flashed; } void bng_draw_new(t_bng *x, t_glist *glist) { + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)&x->x_gui); t_canvas *canvas=glist_getcanvas(glist); int x1=text_xpix(&x->x_gui.x_obj, glist); int y1=text_ypix(&x->x_gui.x_obj, glist); @@ -49,6 +55,8 @@ void bng_draw_new(t_bng *x, t_glist *glist) "-tags {%lxBUT x%lx text iemgui border}\n", canvas, cx, cy, cr, x->x_flashed?x->x_gui.x_fcol:x->x_gui.x_bcol, x, x); + gui_vmess("gui_create_bng", "ssfff", canvas_string(canvas), tagbuf, + cx - x1 - 0.5, cy - y1 - 0.5, cr); } void bng_draw_move(t_bng *x, t_glist *glist) diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c index 4c6d9372d5b28a737313ffd4d0c56d7ac5551160..10a16bc1ea6dd91d221fe9dfe3ee8d0b20f52601 100644 --- a/pd/src/g_canvas.c +++ b/pd/src/g_canvas.c @@ -248,6 +248,13 @@ void canvas_makefilename(t_canvas *x, char *file, char *result, int resultsize) //fprintf(stderr,"resulting file = <%s>\n", result); } +char *canvas_string(t_canvas *x) +{ + static char s[MAXPDSTRING]; + sprintf(s, ".x%lx", (long unsigned int)x); + return s; +} + void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir) { canvas_unbind(x); @@ -650,9 +657,32 @@ t_symbol *canvas_makebindsym(t_symbol *s) return (gensym(buf)); } +void canvas_args_to_string(char *namebuf, t_canvas *x) +{ + t_canvasenvironment *env = canvas_getenv(x); + if (env->ce_argc) + { + int i; + strcpy(namebuf, " ("); + for (i = 0; i < env->ce_argc; i++) + { + if (strlen(namebuf) > MAXPDSTRING/2 - 5) + break; + if (i != 0) + strcat(namebuf, " "); + atom_string(&env->ce_argv[i], namebuf + strlen(namebuf), + MAXPDSTRING/2); + } + strcat(namebuf, ")"); + } + else namebuf[0] = 0; +} + void canvas_reflecttitle(t_canvas *x) { char namebuf[MAXPDSTRING]; + canvas_args_to_string(namebuf, x); +/* t_canvasenvironment *env = canvas_getenv(x); if (env->ce_argc) { @@ -670,6 +700,7 @@ void canvas_reflecttitle(t_canvas *x) strcat(namebuf, ")"); } else namebuf[0] = 0; +*/ #ifdef __APPLE__ sys_vgui("wm attributes .x%lx -modified %d -titlepath {%s/%s}\n", x, x->gl_dirty, canvas_getdir(x)->s_name, x->gl_name->s_name); @@ -681,9 +712,11 @@ void canvas_reflecttitle(t_canvas *x) x->gl_isgraph && x->gl_havewindow, x->gl_loading, x->gl_dirty);*/ - sys_vgui("wm title .x%lx {%s%c%s - %s}\n", - x, x->gl_name->s_name, (x->gl_dirty? '*' : ' '), namebuf, - canvas_getdir(x)->s_name); + //sys_vgui("wm title .x%lx {%s%c%s - %s}\n", + // x, x->gl_name->s_name, (x->gl_dirty? '*' : ' '), namebuf, + // canvas_getdir(x)->s_name); + gui_vmess("gui_canvas_set_title", "ssssi", canvas_string(x), x->gl_name->s_name, + namebuf, canvas_getdir(x)->s_name, x->gl_dirty); //} #endif } @@ -753,14 +786,22 @@ void canvas_drawredrect(t_canvas *x, int doit) { int x1=x->gl_xmargin, y1=x->gl_ymargin; int x2=x1+x->gl_pixwidth, y2=y1+x->gl_pixheight; - sys_vgui(".x%lx.c create line\ - %d %d %d %d %d %d %d %d %d %d -fill #ff8080 -tags GOP\n", - glist_getcanvas(x), x1, y1, x2, y1, x2, y2, x1, y2, x1, y1); + //sys_vgui(".x%lx.c create line " + // "%d %d %d %d %d %d %d %d %d %d -fill #ff8080 -tags GOP\n", + // glist_getcanvas(x), x1, y1, x2, y1, x2, y2, x1, y2, x1, y1); + gui_vmess("gui_canvas_drawredrect", "siiii", + canvas_string(glist_getcanvas(x)), + x1, y1, x2, y2); //dpsaha@vt.edu for drawing the GOP_blobs if (x->gl_goprect && x->gl_edit) canvas_draw_gop_resize_hooks(x); } - else sys_vgui(".x%lx.c delete GOP\n", glist_getcanvas(x)); + else + { + //sys_vgui(".x%lx.c delete GOP\n", glist_getcanvas(x)); + gui_vmess("gui_canvas_deleteredrect", "s", + canvas_string(glist_getcanvas(x))); + } } /* the window becomes "mapped" (visible and not miniaturized) or @@ -1008,8 +1049,12 @@ void canvas_eraselinesfor(t_canvas *x, t_text *text) { if (x->gl_editor) { - sys_vgui(".x%lx.c delete l%lx\n", - glist_getcanvas(x), oc); + //sys_vgui(".x%lx.c delete l%lx\n", + // glist_getcanvas(x), oc); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "l%lx", (long unsigned int)oc); + gui_vmess("gui_canvas_delete_line", "ss", + canvas_string(glist_getcanvas(x)), tagbuf); } } } diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h index 90574b3deb26a43d3af2691081870e2c47a57334..d6bdecee1084aedf77cbde2e2a01661f410a70e3 100644 --- a/pd/src/g_canvas.h +++ b/pd/src/g_canvas.h @@ -480,6 +480,7 @@ EXTERN void text_drawborder(t_text *x, t_glist *glist, char *tag, int width, int height, int firsttime); EXTERN void text_drawborder_withtag(t_text *x, t_glist *glist, char *tag, int width, int height, int firsttime); +EXTERN void text_erase_gobj(t_text *x, t_glist *glist, char *tag); EXTERN void text_eraseborder(t_text *x, t_glist *glist, char *tag); EXTERN int text_xcoord(t_text *x, t_glist *glist); EXTERN int text_ycoord(t_text *x, t_glist *glist); @@ -561,6 +562,7 @@ EXTERN t_gobj *canvas_findhitbox(t_canvas *x, int xpos, int ypos, int *x1p, int *y1p, int *x2p, int *y2p); EXTERN int canvas_setdeleting(t_canvas *x, int flag); EXTERN int canvas_hasarray(t_canvas *x); +EXTERN char *canvas_string(t_canvas *x); /* canvas as string to send to gui */ /* ---- for parsing @pd_extra and other sys paths in filenames --------------------- */ diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c index 58ff2c21c066a76fe8bf8a217d4edd9b1e945899..0bacbb29b44cba71b69cbd3ae80e997077c39150 100644 --- a/pd/src/g_editor.c +++ b/pd/src/g_editor.c @@ -430,10 +430,13 @@ void glist_selectline(t_glist *x, t_outconnect *oc, int index1, x->gl_editor->e_selectline_index2 = index2; x->gl_editor->e_selectline_inno = inno; x->gl_editor->e_selectline_tag = oc; - sys_vgui(".x%lx.c itemconfigure l%lx -stroke $pd_colors(selection)\n", - x, x->gl_editor->e_selectline_tag); - sys_vgui(".x%lx.c addtag selected withtag l%lx\n", - glist_getcanvas(x), x->gl_editor->e_selectline_tag); + //sys_vgui(".x%lx.c itemconfigure l%lx -stroke $pd_colors(selection)\n", + // x, x->gl_editor->e_selectline_tag); + //sys_vgui(".x%lx.c addtag selected withtag l%lx\n", + // glist_getcanvas(x), x->gl_editor->e_selectline_tag); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "l%lx", (long unsigned int)oc); + gui_vmess("gui_canvas_select_line", "ss", canvas_string(x), tagbuf); c_selection = x; canvas_draw_gop_resize_hooks(x); } @@ -455,14 +458,18 @@ void glist_deselectline(t_glist *x) issignal = 1; else issignal = 0; - sys_vgui(".x%lx.c itemconfigure l%lx -stroke %s\n", - x, x->gl_editor->e_selectline_tag, - (issignal ? - "$pd_colors(signal_cord)" : "$pd_colors(control_cord)")); - sys_vgui(".x%lx.c dtag l%lx selected\n", - glist_getcanvas(x), - glist_getcanvas(x)->gl_editor->e_selectline_tag); + //sys_vgui(".x%lx.c itemconfigure l%lx -stroke %s\n", + // x, x->gl_editor->e_selectline_tag, + // (issignal ? + // "$pd_colors(signal_cord)" : "$pd_colors(control_cord)")); + //sys_vgui(".x%lx.c dtag l%lx selected\n", + // glist_getcanvas(x), + // glist_getcanvas(x)->gl_editor->e_selectline_tag); canvas_draw_gop_resize_hooks(x); + + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "l%lx", (long unsigned int)x->gl_editor->e_selectline_tag); + gui_vmess("gui_canvas_deselect_line", "ss", canvas_string(x), tagbuf); } } @@ -858,7 +865,11 @@ void canvas_disconnect(t_canvas *x, if (srcno == index1 && t.tr_outno == outno && sinkno == index2 && t.tr_inno == inno) { - sys_vgui(".x%lx.c delete l%lx\n", x, oc); + //sys_vgui(".x%lx.c delete l%lx\n", x, oc); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "l%lx", (long unsigned int)oc); + gui_vmess("gui_canvas_delete_line", "ss", + canvas_string(x), tagbuf); // jsarlo if(x->gl_editor && x->gl_editor->gl_magic_glass) { @@ -2177,16 +2188,16 @@ void canvas_undo_font(t_canvas *x, void *z, int action) /* ------------------------ event handling ------------------------ */ static char *cursorlist[] = { - "$cursor_runmode_nothing", - "$cursor_runmode_clickme", - "$cursor_runmode_thicken", - "$cursor_runmode_addpoint", - "$cursor_editmode_nothing", - "$cursor_editmode_connect", - "$cursor_editmode_disconnect", - "$cursor_editmode_resize", - "$cursor_editmode_resize_bottom_right", - "$cursor_scroll" + "cursor_runmode_nothing", + "cursor_runmode_clickme", + "cursor_runmode_thicken", + "cursor_runmode_addpoint", + "cursor_editmode_nothing", + "cursor_editmode_connect", + "cursor_editmode_disconnect", + "cursor_editmode_resize", + "cursor_editmode_resize_bottom_right", + "cursor_scroll" }; void canvas_setcursor(t_canvas *x, unsigned int cursornum) @@ -2203,7 +2214,9 @@ void canvas_setcursor(t_canvas *x, unsigned int cursornum) } if (xwas != x || cursorwas != cursornum) { - sys_vgui(".x%lx configure -cursor %s\n", x, cursorlist[cursornum]); + //sys_vgui(".x%lx configure -cursor %s\n", x, cursorlist[cursornum]); + gui_vmess("gui_canvas_cursor", "ss", canvas_string(x), + cursorlist[cursornum]); xwas = x; cursorwas = cursornum; } @@ -2305,8 +2318,10 @@ static void canvas_rightclick(t_canvas *x, int xpos, int ypos, t_gobj *y_sel) isobject = 1; } else isobject = 0; - sys_vgui("pdtk_canvas_popup .x%lx %d %d %d %d %d\n", - x, xpos, ypos, canprop, canopen, isobject); + //sys_vgui("pdtk_canvas_popup .x%lx %d %d %d %d %d\n", + // x, xpos, ypos, canprop, canopen, isobject); + gui_vmess("gui_canvas_popup", "siiiii", + canvas_string(x), xpos, ypos, canprop, canopen, isobject); } /* ---- editors -- perhaps this and "vis" should go to g_editor.c ------- */ @@ -2380,7 +2395,11 @@ void canvas_destroy_editor(t_glist *x) } } -void canvas_reflecttitle(t_canvas *x); + +// void canvas_reflecttitle(t_canvas *x); +// This should replace canvas_reflecttitle above +extern void canvas_args_to_string(char *namebuf, t_canvas *x); + void canvas_map(t_canvas *x, t_floatarg f); /* we call this when we want the window to become visible, mapped, and @@ -2394,6 +2413,10 @@ void canvas_map(t_canvas *x, t_floatarg f); void canvas_vis(t_canvas *x, t_floatarg f) { //fprintf(stderr,"canvas_vis .x%lx %f\n", (t_int)x, f); + char geobuf[MAXPDSTRING]; + char argsbuf[MAXPDSTRING]; + sprintf(geobuf, "+%d+%d", + (int)(x->gl_screenx1), (int)(x->gl_screeny1)); t_gobj *g; t_int properties; @@ -2408,21 +2431,38 @@ void canvas_vis(t_canvas *x, t_floatarg f) if (x->gl_editor && x->gl_havewindow && glist_isvisible(x)) { /* just put us in front */ //fprintf(stderr,"existing\n"); - sys_vgui("raise .x%lx\n", x); - sys_vgui("focus .x%lx.c\n", x); - sys_vgui("wm deiconify .x%lx\n", x); + //sys_vgui("raise .x%lx\n", x); + //sys_vgui("focus .x%lx.c\n", x); + //sys_vgui("wm deiconify .x%lx\n", x); + gui_vmess("gui_raise_window", "s", canvas_string(x)); } else { //fprintf(stderr,"new\n"); canvas_create_editor(x); - sys_vgui("pdtk_canvas_new .x%lx %d %d +%d+%d %d\n", x, +// sys_vgui("pdtk_canvas_new .x%lx %d %d +%d+%d %d\n", x, +// (int)(x->gl_screenx2 - x->gl_screenx1), +// (int)(x->gl_screeny2 - x->gl_screeny1), +// (int)(x->gl_screenx1), (int)(x->gl_screeny1), +// x->gl_edit); + + canvas_args_to_string(argsbuf, x); + + gui_vmess("gui_canvas_new", "siisissis", + canvas_string(x), (int)(x->gl_screenx2 - x->gl_screenx1), (int)(x->gl_screeny2 - x->gl_screeny1), - (int)(x->gl_screenx1), (int)(x->gl_screeny1), - x->gl_edit); + geobuf, + x->gl_edit, + x->gl_name->s_name, + canvas_getdir(x)->s_name, + x->gl_dirty, + argsbuf); + + + sys_vgui("pdtk_canvas_set_font .x%lx %d\n", x, x->gl_font); - canvas_reflecttitle(x); +// canvas_reflecttitle(x); x->gl_havewindow = 1; // check if this is a subpatch with an array @@ -2507,7 +2547,7 @@ void canvas_vis(t_canvas *x, t_floatarg f) if (glist_isvisible(x)) canvas_map(x, 0); canvas_destroy_editor(x); - sys_vgui("destroy .x%lx\n", x); + gui_vmess("gui_close_window", "s", canvas_string(x)); // delete properties windows of objects in the patcher we're closing g = x->gl_list; while (g) @@ -3289,6 +3329,9 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, "$pd_colors(signal_cord_width)" : "$pd_colors(control_cord_width)"), (issignal ? "signal" : "control")); + gui_vmess("gui_canvas_line", "ssiiiiiiiiii", + canvas_string(x), "newcord", + xpos, ypos, xpos, ypos, xpos, ypos, xpos, ypos, xpos, ypos); } else // jsarlo @@ -3309,7 +3352,6 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, "-strokewidth $highlight_width\n", x, x->gl_editor->canvas_cnct_outlet_tag); - //sys_vgui(".x%x.c raise %s\n", // x, // x->gl_editor->canvas_cnct_outlet_tag); @@ -3591,6 +3633,8 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which, sys_vgui(".x%lx.c create prect %d %d %d %d -tags x " "-stroke $pd_colors(selection_rectangle)\n", x, xpos, ypos, xpos, ypos); + gui_vmess("gui_create_selection_rectangle", "siiii", canvas_string(x), + xpos, ypos, xpos, ypos); x->gl_editor->e_xwas = xpos; x->gl_editor->e_ywas = ypos; x->gl_editor->e_onmotion = MA_REGION; @@ -3686,6 +3730,7 @@ void canvas_sort_selection_according_to_location(t_canvas *x) void canvas_drawconnection(t_canvas *x, int lx1, int ly1, int lx2, int ly2, t_int tag, int issignal) { + char tagbuf[MAXPDSTRING]; int ymax = 0; int halfx = (lx2 - lx1)/2; int halfy = (ly2 - ly1)/2; @@ -3727,11 +3772,16 @@ void canvas_drawconnection(t_canvas *x, int lx1, int ly1, int lx2, int ly2, "$pd_colors(signal_cord_width)" : "$pd_colors(control_cord_width)"), tag, (issignal ? "signal" : "control")); + sprintf(tagbuf, "l%lx", (long unsigned int)tag); + gui_vmess("gui_canvas_line", "ssiiiiiiiiii", + canvas_string(x), tagbuf, lx1, ly1, lx1, ly1 + yoff, + lx1 + halfx, ly1 + halfy, lx2, ly2 - yoff, lx2, ly2); } void canvas_updateconnection(t_canvas *x, int lx1, int ly1, int lx2, int ly2, t_int tag) { + char cord_tag[MAXPDSTRING]; if (glist_isvisible(x) && glist_istoplevel(x)) { int ymax = 0; @@ -3768,6 +3818,11 @@ void canvas_updateconnection(t_canvas *x, int lx1, int ly1, int lx2, int ly2, x, tag, lx1, ly1, lx1, ly1 + yoff, lx1 + halfx, ly1 + halfy, lx2, ly2 - yoff, lx2, ly2); + sprintf(cord_tag, "l%lx", (long unsigned int)tag); + gui_vmess("gui_canvas_updateline", "ssiiiii", canvas_string(x), cord_tag, + lx1, ly1, lx2, ly2, yoff); +// lx1, ly1, lx1, ly1 + yoff, lx1 + halfx, ly1 + halfy, +// lx2, ly2 - yoff, lx2, ly2); } else { @@ -3777,6 +3832,10 @@ void canvas_updateconnection(t_canvas *x, int lx1, int ly1, int lx2, int ly2, x, lx1, ly1, lx1, ly1 + yoff, lx1 + halfx, ly1 + halfy, lx2, ly2 - yoff, lx2, ly2); + gui_vmess("gui_canvas_updateline", "ssiiiii", canvas_string(x), "newcord", + lx1, ly1, lx2, ly2, yoff); +// lx1, ly1, lx1, ly1 + yoff, lx1 + halfx, ly1 + halfy, lx2, ly2 - yoff, +// lx2, ly2); } } } @@ -4371,7 +4430,10 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit) int xwas = x->gl_editor->e_xwas, ywas = x->gl_editor->e_ywas; if (doit && !glob_shift) + { sys_vgui(".x%lx.c delete x\n", x); + gui_vmess("gui_canvas_delete_line", "ss", canvas_string(x), "newcord"); + } else { canvas_updateconnection(x, x->gl_editor->e_xwas, x->gl_editor->e_ywas, @@ -4514,11 +4576,17 @@ static void canvas_doregion(t_canvas *x, int xpos, int ypos, int doit) else hiy = x->gl_editor->e_ywas, loy = ypos; canvas_selectinrect(x, lox, loy, hix, hiy); sys_vgui(".x%lx.c delete x\n", x); + gui_vmess("gui_hide_selection_rectangle", "s", canvas_string(x)); x->gl_editor->e_onmotion = MA_NONE; } - else sys_vgui(".x%lx.c coords x %d %d %d %d\n", + else + { + sys_vgui(".x%lx.c coords x %d %d %d %d\n", x, x->gl_editor->e_xwas, x->gl_editor->e_ywas, xpos, ypos); + gui_vmess("gui_move_selection_rectangle", "siiii", + canvas_string(x), x->gl_editor->e_xwas, x->gl_editor->e_ywas, xpos, ypos); + } } /* @@ -4744,6 +4812,7 @@ void canvas_displaceselection(t_canvas *x, int dx, int dy) if (dx || dy) { sys_vgui("pdtk_canvas_displace_withtag .x%lx.c %d %d\n", x, dx, dy); + gui_vmess("gui_canvas_displace_withtag", "sii", canvas_string(x), dx, dy); if (resortin) canvas_resortinlets(x); if (resortout) canvas_resortoutlets(x); //scrollbar_update(x); @@ -5254,13 +5323,21 @@ void glob_verifyquit(void *dummy, t_floatarg f) if (!glist_istoplevel(g2) && g->gl_env) { /* if this is an abstraction */ - sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 3;}\n", - g2, g2); + //sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 3;}\n", + // g2, g2); + gui_vmess("gui_canvas_menuclose", "ssi", + canvas_string(g2), + canvas_string(g2), + 3); } else { - sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 3;}\n", - canvas_getrootfor(g2), g2); + //sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 3;}\n", + // canvas_getrootfor(g2), g2); + gui_vmess("gui_canvas_menuclose", "ssi", + canvas_string(canvas_getrootfor(g2)), + canvas_string(g2), + 3); } //canvas_vis(g2, 1); //sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 3;\n}\n", @@ -5268,8 +5345,15 @@ void glob_verifyquit(void *dummy, t_floatarg f) return; } if (f == 0 && sys_perf) - sys_vgui("pdtk_check . {really quit?} {pd quit;\n} yes\n"); - else glob_quit(0); + { + //sys_vgui("pdtk_check . {really quit?} {pd quit;\n} yes\n"); + gui_vmess("gui_pd_quit_dialog", ""); + } + else + { + gui_vmess("gui_post", "s", "about to quite seresly dood"); + glob_quit(0); + } } //void canvas_dofree(t_gobj *dummy, t_glist *x) @@ -5305,6 +5389,7 @@ void canvas_menuclose(t_canvas *x, t_floatarg fforce) /* first open window */ if (!glist_istoplevel(g) && g->gl_env) { + post("opening menu"); /* if this is an abstraction */ vmess(&g->gl_pd, gensym("menu-open"), ""); } @@ -5316,13 +5401,21 @@ void canvas_menuclose(t_canvas *x, t_floatarg fforce) if (!glist_istoplevel(g) && g->gl_env) { /* if this is an abstraction */ - sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;}\n", - g, g); + //sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;}\n", + // g, g); + gui_vmess("gui_canvas_menuclose", "ssi", + canvas_string(g), + canvas_string(g), + 2); } else { - sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;}\n", - canvas_getrootfor(g), g); + //sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;}\n", + // canvas_getrootfor(g), g); + gui_vmess("gui_canvas_menuclose", "ssi", + canvas_string(canvas_getrootfor(g)), + canvas_string(g), + 2); } return; } @@ -5359,6 +5452,7 @@ void canvas_menuclose(t_canvas *x, t_floatarg fforce) { if (!glist_istoplevel(g) && g->gl_env) { +post("opening up the motherfucker x%lx", g); /* if this is an abstraction */ vmess(&g->gl_pd, gensym("menu-open"), ""); } @@ -5366,18 +5460,29 @@ void canvas_menuclose(t_canvas *x, t_floatarg fforce) { /* is this even necessary? */ canvas_vis(g, 1); +post("fuck you canvas_vis x%lx", g); } //vmess(&g->gl_pd, gensym("menu-open"), ""); if (!glist_istoplevel(g) && g->gl_env) { +post("farging..."); /* if this is an abstraction */ - sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;}\n", - g, g); + //sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;}\n", + // g, g); + gui_vmess("gui_canvas_menuclose", "ssi", + canvas_string(g), + canvas_string(g), + 2); } else { - sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;}\n", - canvas_getrootfor(g), g); +post("dildo"); + //sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;}\n", + // canvas_getrootfor(g), g); + gui_vmess("gui_canvas_menuclose", "ssi", + canvas_string(canvas_getrootfor(g)), + canvas_string(g), + 2); } //sys_vgui("pdtk_canvas_menuclose .x%lx {.x%lx menuclose 2;\n}\n", // canvas_getrootfor(x), g); diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c index 6c1b05bdf4290d1131845f0baf74df688c3a4040..b5771002a66dde463166e9f92d514ba89229ac5e 100644 --- a/pd/src/g_graph.c +++ b/pd/src/g_graph.c @@ -881,14 +881,32 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) //} //fprintf(stderr,"tgt=.x%lx %d\n", (t_int)tgt, exception); - if (vis && canvas_showtext(x) && gobj_shouldvis(gr, parent_glist)) - rtext_draw(glist_findrtext(parent_glist, &x->gl_obj)); + sprintf(tag, "%s", rtext_gettag(glist_findrtext(parent_glist, &x->gl_obj))); +//post("before rtext_draw: %s", tag); + + if (vis & gobj_shouldvis(gr, parent_glist)) + { + int xpix, ypix; + xpix = text_xpix(&x->gl_obj, parent_glist); + ypix = text_ypix(&x->gl_obj, parent_glist); + gui_vmess("gui_text_create_gobj", "ssii", + canvas_string(glist_getcanvas(x->gl_owner)), + tag, xpix, ypix); + if (canvas_showtext(x)) + rtext_draw(glist_findrtext(parent_glist, &x->gl_obj)); + } + +// sprintf(tag, "%s", rtext_gettag(glist_findrtext(parent_glist, &x->gl_obj))); +//post("after rtext_draw: %s", tag); + + // need the rect to create the gobj, so this should perhaps be above the + // conditional graph_getrect(gr, parent_glist, &x1, &y1, &x2, &y2); //fprintf(stderr,"%d %d %d %d\n", x1, y1, x2, y2); + if (!vis) rtext_erase(glist_findrtext(parent_glist, &x->gl_obj)); - sprintf(tag, "%s", rtext_gettag(glist_findrtext(parent_glist, &x->gl_obj))); //sprintf(tag, "graph%lx", (t_int)x); //fprintf(stderr, "gettag=%s, tag=graph%lx\n", // rtext_gettag(glist_findrtext(parent_glist, &x->gl_obj)),(t_int)x); @@ -898,19 +916,30 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) { if (vis && gobj_shouldvis(gr, parent_glist)) { - sys_vgui(".x%lx.c create ppolygon %d %d %d %d %d %d %d %d %d %d " - "-tags {%sfill graph} -fill $pd_colors(graph_border) " - "-stroke $pd_colors(graph_border)\n", - glist_getcanvas(x->gl_owner), - //parent_glist, - x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag); + //sys_vgui(".x%lx.c create ppolygon %d %d %d %d %d %d %d %d %d %d " + // "-tags {%sfill graph} -fill $pd_colors(graph_border) " + // "-stroke $pd_colors(graph_border)\n", + // glist_getcanvas(x->gl_owner), + ////parent_glist, + // x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "%sfill", tag); + gui_vmess("gui_text_drawborder", "ssiiiii", + canvas_string(glist_getcanvas(x->gl_owner)), + tag, + 0, x1, y1, x2, y2); glist_noselect(x->gl_owner); } else if (gobj_shouldvis(gr, parent_glist)) { - sys_vgui(".x%lx.c delete %sfill\n", - glist_getcanvas(x->gl_owner), tag); - //parent_glist, tag); + //sys_vgui(".x%lx.c delete %sfill\n", + // glist_getcanvas(x->gl_owner), tag); + ////parent_glist, tag); + char tagbuf2[MAXPDSTRING]; + sprintf(tagbuf2, "%sfill", tag); + gui_vmess("gui_graph_deleteborder", "ss", + canvas_string(glist_getcanvas(x->gl_owner)), + tagbuf2); } return; } @@ -926,12 +955,17 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis) "-stroke $pd_colors(graph_border) -tags {%sR %s graph}\n", glist_getcanvas(x->gl_owner), x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag, tag);*/ - sys_vgui(".x%lx.c create prect %d %d %d %d " - "-stroke $pd_colors(graph_border) -tags {%sR graph}\n", - //REMOVED: -fill $pd_colors(graph) - glist_getcanvas(x->gl_owner), - x1, y1, x2, y2, tag); // -fill $pd_colors(graph) - + //sys_vgui(".x%lx.c create prect %d %d %d %d " + // "-stroke $pd_colors(graph_border) -tags {%sR graph}\n", + // //REMOVED: -fill $pd_colors(graph) + // glist_getcanvas(x->gl_owner), + // x1, y1, x2, y2, tag); // -fill $pd_colors(graph) + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "%sR", tag); + gui_vmess("gui_text_drawborder", "ssiiiii", + canvas_string(glist_getcanvas(x->gl_owner)), + tag, + 0, x1, y1, x2, y2); /* write garrays' names along the top */ for (i = (y1 < y2 ? y1 : y2)-1, g = x->gl_list; g; g = g->g_next) { @@ -1380,6 +1414,12 @@ static void graph_select(t_gobj *z, t_glist *glist, int state) canvas, rtext_gettag(y), (state? "$pd_colors(selection)" : "$pd_colors(graph_border)"), (state? "$pd_colors(selection)" : "$pd_colors(graph_border)")); + if (state) + gui_vmess("gui_text_select", "ss", + canvas_string(canvas), rtext_gettag(y)); + else + gui_vmess("gui_text_deselect", "ss", + canvas_string(canvas), rtext_gettag(y)); } t_gobj *g; diff --git a/pd/src/g_magicglass.c b/pd/src/g_magicglass.c index bdde53081870642f7344de7a96e067bee5e67fd0..22cd07fe0d45cb013ba9a0552d6b59d01cc541f5 100644 --- a/pd/src/g_magicglass.c +++ b/pd/src/g_magicglass.c @@ -5,6 +5,7 @@ #include "m_imp.h" #include "s_stuff.h" #include "g_magicglass.h" +#include "g_canvas.h" #define MG_CLOCK_CLEAR_DELAY 500.5 #define MG_CLOCK_FLASH_DELAY 50 @@ -116,6 +117,12 @@ void magicGlass_updateText(t_magicGlass *x, int moved) x->x_y - (int)(sys_fontheight(x->x_display_font)/2) - 3, bgSize, x->x_y + (int)(sys_fontheight(x->x_display_font)/2) + 3); + gui_vmess("gui_cord_inspector_update", "ssiiiiii", + canvas_string(x->x_c), x->x_string, + x->x_x, x->x_y, bgSize, + x->x_y - (int)(sys_fontheight(x->x_display_font)/2) - 3, + x->x_y + (int)(sys_fontheight(x->x_display_font)/2) + 3, + moved); } } @@ -137,6 +144,10 @@ void magicGlass_drawNew(t_magicGlass *x) x->x_c); sys_vgui(".x%x.c raise magicGlassText\n", x->x_c); + gui_vmess("gui_text_create_gobj", "ssii", + canvas_string(x->x_c), "cord_inspector", 0, 0); + gui_vmess("gui_create_cord_inspector", "s", + canvas_string(x->x_c)); magicGlass_updateText(x, 0); clock_delay(x->x_flashClock, MG_CLOCK_FLASH_DELAY); } @@ -147,6 +158,8 @@ void magicGlass_undraw(t_magicGlass *x) sys_vgui(".x%x.c delete magicGlassBg\n", x->x_c); sys_vgui(".x%x.c delete magicGlassLine\n", x->x_c); sys_vgui(".x%x.c delete magicGlassText\n", x->x_c); + gui_vmess("gui_erase_cord_inspector", "s", + canvas_string(x->x_c)); } void magicGlass_flashText(t_magicGlass *x) @@ -155,6 +168,8 @@ void magicGlass_flashText(t_magicGlass *x) sys_vgui(".x%x.c itemconfigure magicGlassText " "-fill $pd_colors(magic_glass_text)\n", x->x_c); + gui_vmess("gui_cord_inspector_flash", "s", + canvas_string(x->x_c)); } void magicGlass_clearText(t_magicGlass *x) diff --git a/pd/src/g_mycanvas.c b/pd/src/g_mycanvas.c index c3254df71a4f95cff18f815fbec523005f510644..bb13898654a02e873cd1e709c636fc7b9bc6f355 100644 --- a/pd/src/g_mycanvas.c +++ b/pd/src/g_mycanvas.c @@ -33,6 +33,15 @@ void my_canvas_draw_new(t_my_canvas *x, t_glist *glist) "-tags {%lxBASE x%lx text iemgui}\n", canvas, x1, y1, x1+x->x_gui.x_w, y1+x->x_gui.x_h, x->x_gui.x_bcol, x, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", x->x_gui.x_bcol); + gui_vmess("gui_text_create_gobj", "ssii", canvas_string(canvas), + tagbuf, x1, y1); + gui_vmess("gui_create_mycanvas", "sssiiiiii", canvas_string(canvas), + tagbuf, colorbuf, x1, y1, x1+x->x_vis_w, y1+x->x_vis_h, + x1+x->x_gui.x_w, y1+x->x_gui.x_h); } void my_canvas_draw_move(t_my_canvas *x, t_glist *glist) @@ -67,6 +76,11 @@ void my_canvas_draw_select(t_my_canvas* x, t_glist* glist) sys_vgui(".x%lx.c itemconfigure %lxBASE -stroke %s\n", canvas, x, x->x_gui.x_selected == canvas && x->x_gui.x_glist == canvas ? "$pd_colors(selection)" : bcol); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_mycanvas_select_color", "sss", canvas_string(canvas), + tagbuf, x->x_gui.x_selected == canvas && x->x_gui.x_glist == canvas ? + "blue" : bcol); } static void my_canvas__clickhook(t_scalehandle *sh, int newstate) diff --git a/pd/src/g_numbox.c b/pd/src/g_numbox.c index b120354e51f43b6db123e64bf4a5d7a4d33ae361..6459ba4d101127790f5cc6a20a32841940fcf042 100644 --- a/pd/src/g_numbox.c +++ b/pd/src/g_numbox.c @@ -140,6 +140,11 @@ static void my_numbox_draw_update(t_gobj *client, t_glist *glist) sys_vgui( ".x%lx.c itemconfigure %lxNUMBER -fill #%6.6x -text {%s}\n", glist_getcanvas(glist), x, IEM_GUI_COLOR_EDITED, cp); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_text_set", "sss", canvas_string(glist_getcanvas(glist)), + tagbuf, cp); + x->x_buf[sl] = 0; } else @@ -153,6 +158,10 @@ static void my_numbox_draw_update(t_gobj *client, t_glist *glist) glist_getcanvas(glist), x, x->x_gui.x_selected == glist_getcanvas(glist) && !x->x_gui.x_change ? selection_color : fcol, x->x_buf); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_text_set", "sss", canvas_string(glist_getcanvas(glist)), + tagbuf, x->x_buf); x->x_buf[0] = 0; } } @@ -171,7 +180,10 @@ static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist) canvas, x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x->x_hide_frame <= 1 ? "$pd_colors(iemgui_border)" : bcol, bcol, x, x); - + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_create_numbox", "sssiiiiiiiiiiiii", canvas_string(canvas), + tagbuf, bcol, x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1, half); if (!x->x_hide_frame || x->x_hide_frame == 2) sys_vgui(".x%lx.c create polyline %d %d %d %d %d %d -stroke #%6.6x " "-tags {%lxBASE2 x%lx text iemgui}\n", @@ -182,6 +194,10 @@ static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist) "-font %s -fill #%6.6x -tags {%lxNUMBER x%lx noscroll text iemgui}\n", canvas, x1+half+2, y1+half+d, x->x_buf, iemgui_font(&x->x_gui), x->x_gui.x_fcol, x, x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", x->x_gui.x_fcol); + gui_vmess("gui_numbox_drawtext", "ssssiiii", canvas_string(canvas), tagbuf, + x->x_buf, colorbuf, x1+half+2, y1+half+d, x1, y1); } static void my_numbox_draw_move(t_my_numbox *x, t_glist *glist) diff --git a/pd/src/g_radio.c b/pd/src/g_radio.c index ca476b52678797997cc01a8fce5bfbd6ac2ff0e4..aa9fb81f2b431aeb29b33a8501e18642453b6782 100644 --- a/pd/src/g_radio.c +++ b/pd/src/g_radio.c @@ -32,6 +32,10 @@ void radio_draw_update(t_gobj *client, t_glist *glist) canvas, x, x->x_drawn, x->x_gui.x_bcol, x->x_gui.x_bcol); sys_vgui(".x%lx.c itemconfigure %lxBUT%d -fill #%6.6x -stroke #%6.6x\n", canvas, x, x->x_on, x->x_gui.x_fcol, x->x_gui.x_fcol); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_radio_update", "ssii", canvas_string(canvas), + tagbuf, x->x_drawn, x->x_on); x->x_drawn = x->x_on; } @@ -44,29 +48,55 @@ void radio_draw_new(t_radio *x, t_glist *glist) iemgui_base_draw_new(&x->x_gui); for(i=0; i<n; i++) if (x->x_orient) { - if (i) sys_vgui(".x%lx.c create prect %d %d %d %d " + if (i) + { + sys_vgui(".x%lx.c create prect %d %d %d %d " "-stroke $pd_colors(iemgui_border) " "-tags {%lxBASE%d %lxBASE x%lx text iemgui border}\n", canvas, x1, yi, x1+d, yi, x, i, x, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_create_radio", "ssiiiiiii", + canvas_string(canvas), tagbuf, x1, yi, x1+d, yi, i, x1, y1); + } sys_vgui(".x%lx.c create prect %d %d %d %d -fill #%6.6x " "-stroke #%6.6x -tags {%lxBUT%d x%lx text iemgui}\n", canvas, x1+s, yi+s, x1+d-s, yi+d-s, (x->x_on==i)?x->x_gui.x_fcol:x->x_gui.x_bcol, (x->x_on==i)?x->x_gui.x_fcol:x->x_gui.x_bcol, x, i, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", x->x_gui.x_fcol); + gui_vmess("gui_create_radio_buttons", "sssiiiiiiii", canvas_string(canvas), + tagbuf, colorbuf, x1+s, yi+s, x1+d-s, yi+d-s, x1, y1, i, x->x_on==i); yi += d; x->x_drawn = x->x_on; } else { - if (i) sys_vgui(".x%lx.c create prect %d %d %d %d " + if (i) + { + sys_vgui(".x%lx.c create prect %d %d %d %d " "-stroke $pd_colors(iemgui_border) " "-tags {%lxBASE%d %lxBASE x%lx text iemgui border}\n", canvas, xi, y1, xi, y1+d, x, i, x, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_create_radio", "ssiiiiiii", canvas_string(canvas), + tagbuf, xi, y1, xi, y1+d, i, x1, y1); + } sys_vgui(".x%lx.c create prect %d %d %d %d -fill #%6.6x " "-stroke #%6.6x -tags {%lxBUT%d x%lx text iemgui}\n", canvas, xi+s, y1+s, xi+d-s, y1+d-s, (x->x_on==i)?x->x_gui.x_fcol:x->x_gui.x_bcol, (x->x_on==i)?x->x_gui.x_fcol:x->x_gui.x_bcol, x, i, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", x->x_gui.x_fcol); + gui_vmess("gui_create_radio_buttons", "sssiiiiiiii", canvas_string(canvas), + tagbuf, colorbuf, xi+s, y1+s, xi+d-s, yi+d-s, x1, y1, i, x->x_on==i); xi += d; x->x_drawn = x->x_on; } diff --git a/pd/src/g_readwrite.c b/pd/src/g_readwrite.c index 6d31a8a2ae9daa6e1da58d870d3c9f727d24e342..5dd0951803f5dc22fe25318faea3b32ce229afea 100644 --- a/pd/src/g_readwrite.c +++ b/pd/src/g_readwrite.c @@ -776,8 +776,9 @@ static void canvas_savetofile(t_canvas *x, t_symbol *filename, t_symbol *dir) static void canvas_menusaveas(t_canvas *x) { t_canvas *x2 = canvas_getrootfor(x); - sys_vgui("pdtk_canvas_saveas .x%lx \"%s\" \"%s\"\n", x2, - x2->gl_name->s_name, canvas_getdir(x2)->s_name); + gui_vmess("gui_canvas_saveas", "sss", canvas_string(x2), x2->gl_name->s_name, canvas_getdir(x2)->s_name); +// sys_vgui("pdtk_canvas_saveas .x%lx \"%s\" \"%s\"\n", x2, +// x2->gl_name->s_name, canvas_getdir(x2)->s_name); } static void canvas_menusave(t_canvas *x) diff --git a/pd/src/g_rtext.c b/pd/src/g_rtext.c index 4e7ba86b77cbc9d9c113ec9a53b6baccb8426522..961e07918c14a71b3069bc77e3d5ac7ec6b6d990 100644 --- a/pd/src/g_rtext.c +++ b/pd/src/g_rtext.c @@ -330,7 +330,12 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp, // add a null character at the end of the string (for u8_charnum) tempbuf[outchars_b++] = '\0'; - pixwide = ncolumns * fontwidth + (LMARGIN + RMARGIN); + // The following is an enormous hack to get the box width to match size 12px + // DejaVu as closely as possible. A better solution would require a fuller + // understanding of the font logic here and in s_main. + //pixwide = ncolumns * fontwidth + (LMARGIN + RMARGIN); + float fudge_factor = 0.2; + pixwide = (int)(ncolumns * (fontwidth + fudge_factor) + (LMARGIN + RMARGIN)); pixhigh = nlines * fontheight + (TMARGIN + BMARGIN); //printf("outchars_b=%d bufsize=%d %d\n", outchars_b, x->x_bufsize, x->x_buf[outchars_b]); @@ -357,11 +362,20 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp, dispx + LMARGIN, dispy + TMARGIN, outchars_b, tempbuf, sys_hostfontsize(font), (glist_isselected(x->x_glist, ((t_gobj*)x->x_text)) ? "$pd_colors(selection)" : "$pd_colors(text)")); + gui_vmess("gui_text_new", "sssiffsi", + canvas_string(canvas), x->x_tag, rtext_gettype(x)->s_name, + glist_isselected(x->x_glist, ((t_gobj*)x->x_text)), + dispx + LMARGIN, + dispy + TMARGIN, + tempbuf, + sys_hostfontsize(font)); + } else if (action == SEND_UPDATE) { sys_vgui("pdtk_text_set .x%lx.c %s {%.*s}\n", canvas, x->x_tag, outchars_b, tempbuf); + gui_vmess("gui_text_set", "sss", canvas_string(canvas), x->x_tag, tempbuf); if (pixwide != x->x_drawnwidth || pixhigh != x->x_drawnheight) text_drawborder(x->x_text, x->x_glist, x->x_tag, diff --git a/pd/src/g_scalar.c b/pd/src/g_scalar.c index 02d2e78b1dc3d592fac20fcfbf729d106adcceaa..baebc17ae9da94003a52ac02fb7eb0ebf03d1a17 100644 --- a/pd/src/g_scalar.c +++ b/pd/src/g_scalar.c @@ -412,45 +412,56 @@ static void scalar_getrect(t_gobj *z, t_glist *owner, void scalar_drawselectrect(t_scalar *x, t_glist *glist, int state) { + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "scalar%lx", (long unsigned int)x->sc_vec); + //fprintf(stderr,"scalar_drawselecterect%d\n", state); if (state) { int x1, y1, x2, y2; - + t_float basex, basey; + scalar_getbasexy(x, &basex, &basey); + scalar_getrect(&x->sc_gobj, glist, &x1, &y1, &x2, &y2); x1--; x2++; y1--; y2++; if (glist_istoplevel(glist)) + { sys_vgui(".x%lx.c create prect %d %d %d %d " "-strokewidth 1 -stroke $pd_colors(selection) " "-tags {select%lx selected}\n", glist_getcanvas(glist), x1, y1, x2, y2, x); + gui_vmess("gui_scalar_draw_select_rect", "ssiiiiiff", + canvas_string(glist_getcanvas(glist)), tagbuf, + state, + x1, y1, x2, y2, basex, basey); + } } else { if (glist_istoplevel(glist)) sys_vgui(".x%lx.c delete select%lx\n", glist_getcanvas(glist), x); + gui_vmess("gui_scalar_draw_select_rect", "ssiiiiiii", + canvas_string(glist_getcanvas(glist)), tagbuf, + state, + 0, 0, 0, 0, 0, 0); } } -/* This is a workaround. Since scalars are contained within a tkpath - group, and since tkpath groups don't have coords, we can't just use - the same "selected" tag that is used to move all other Pd objects. That - would move scalars in their local coordinate system, which is wrong - for transformed objects. For example, if a rectangle is rotated 45 and - we try to do a [canvas move 10 0] command on it, it would get moved to - the northeast instead of to the right! +/* This is greatly simplified with Node-Webkit-- we just need to get the + basex/basey for the scalar, in addition to the bbox of the scalar. - Instead, we tag selected scalars with the "scalar_selected" tag. Then in - the GUI we use that tag to loop through and change each scalar's group - matrix, and add (dx,dy) to its current translation values. The scalar - group matrix .scalar%lx isn't accessible by the user, so it will only - ever contain these translation values. + This can be simplified further by using a single function on the GUI + side, and sending it the "state" parameter. */ void scalar_select(t_gobj *z, t_glist *owner, int state) { //fprintf(stderr,"scalar_select %d\n", state); t_scalar *x = (t_scalar *)z; + + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "scalar%lx", (long unsigned int)x->sc_vec); + t_template *tmpl; t_symbol *templatesym = x->sc_template; t_atom at; @@ -473,6 +484,8 @@ void scalar_select(t_gobj *z, t_glist *owner, int state) glist_getcanvas(owner), x); sys_vgui(".x%lx.c addtag scalar_selected withtag {.scalar%lx}\n", glist_getcanvas(owner), x->sc_vec); + gui_vmess("gui_text_select", "ss", + canvas_string(glist_getcanvas(owner)), tagbuf); } else { @@ -481,6 +494,8 @@ void scalar_select(t_gobj *z, t_glist *owner, int state) glist_getcanvas(owner), x); sys_vgui(".x%lx.c dtag .scalar%lx scalar_selected\n", glist_getcanvas(owner), x->sc_vec); + gui_vmess("gui_text_deselect", "ss", + canvas_string(glist_getcanvas(owner)), tagbuf); } //sys_vgui("pdtk_select_all_gop_widgets .x%lx %lx %d\n", // glist_getcanvas(owner), owner, state); @@ -617,6 +632,112 @@ static void scalar_delete(t_gobj *z, t_glist *glist) extern void svg_grouptogui(t_glist *g, t_template *template, t_word *data); +extern void svg_parentwidgettogui(t_gobj *z, t_glist *owner, t_word *data, + t_template *template); + +static void scalar_group_configure(t_scalar *x, t_glist *owner, + t_template *template, t_glist *gl, t_glist *parent) +{ + t_gobj *y; + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "dgroup%lx.%lx", (long unsigned int)gl, + (long unsigned int)x->sc_vec); + char parentbuf[MAXPDSTRING]; + sprintf(parentbuf, "dgroup%lx.%lx", (long unsigned int)parent, + (long unsigned int)x->sc_vec); + gui_start_vmess("gui_draw_configure_all", "ss", + canvas_string(glist_getcanvas(owner)), tagbuf); + svg_grouptogui(gl, template, x->sc_vec); + gui_end_vmess(); + for (y = gl->gl_list; y; y = y->g_next) + { + if (pd_class(&y->g_pd) == canvas_class && + ((t_glist *)y)->gl_svg) + { + scalar_group_configure(x, owner, template, (t_glist *)y, gl); + } + t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); + if (!wb) continue; + //(*wb->w_parentvisfn)(y, owner, gl, x, x->sc_vec, template, + // 0, 0, vis); + svg_parentwidgettogui(y, owner, x->sc_vec, template); + } +} + +void scalar_configure(t_scalar *x, t_glist *owner) +{ + int vis = glist_isvisible(owner); + if (vis) + { + //fprintf(stderr,"scalar_vis %d %lx\n", vis, (t_int)z); + x->sc_bboxcache = 0; + + t_template *template = template_findbyname(x->sc_template); + t_canvas *templatecanvas = template_findcanvas(template); + t_gobj *y; + t_float basex, basey; + scalar_getbasexy(x, &basex, &basey); + /* if we don't know how to draw it, make a small rectangle */ + + t_float xscale = glist_xtopixels(owner, 1) - glist_xtopixels(owner, 0); + t_float yscale = glist_ytopixels(owner, 1) - glist_ytopixels(owner, 0); + + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "scalar%lx", (long unsigned int)x->sc_vec); + gui_vmess("gui_scalar_configure_gobj", "ssiffffii", + canvas_string(glist_getcanvas(owner)), + tagbuf, + glist_isselected(owner, &x->sc_gobj), + xscale, 0.0, 0.0, yscale, + (int)glist_xtopixels(owner, basex), + (int)glist_ytopixels(owner, basey)); + + char groupbuf[MAXPDSTRING]; + // Quick hack to make gui_create_scalar_group more general (so we + // don't have to tack on "gobj" manually) + + + //Not sure if we need this here... + //sprintf(tagbuf, "scalar%lxgobj", (long unsigned int)x->sc_vec); + //sprintf(groupbuf, "dgroup%lx.%lx", (long unsigned int)templatecanvas, + // (long unsigned int)x->sc_vec); + //gui_vmess("gui_create_scalar_group", "sss", + // canvas_string(glist_getcanvas(owner)), groupbuf, tagbuf); + //sys_vgui("pdtk_bind_scalar_mouseover " + // ".x%lx.c .x%lx.x%lx.template%lx {.x%lx}\n", + // glist_getcanvas(owner), glist_getcanvas(owner), + // owner, x->sc_vec, x); + + for (y = templatecanvas->gl_list; y; y = y->g_next) + { + t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); + if (!wb) + { + /* check subpatches for more drawing commands. + (Optimized to only search [group] subpatches) */ + if (pd_class(&y->g_pd) == canvas_class && + ((t_glist *)y)->gl_svg) + { + scalar_group_configure(x, owner, template, + (t_glist *)y, templatecanvas); + } + continue; + } + //(*wb->w_parentvisfn)(y, owner, 0, x, x->sc_vec, template, + // basex, basey, vis); + svg_parentwidgettogui(y, owner, x->sc_vec, template); + } + if (glist_isselected(owner, &x->sc_gobj)) + { + // we removed this because it caused infinite recursion + // in the scalar-help.pd example + //scalar_select(z, owner, 1); + scalar_drawselectrect(x, owner, 0); + scalar_drawselectrect(x, owner, 1); + } + } +} + static void scalar_groupvis(t_scalar *x, t_glist *owner, t_template *template, t_glist *gl, t_glist *parent, int vis) { @@ -627,8 +748,17 @@ static void scalar_groupvis(t_scalar *x, t_glist *owner, t_template *template, "-parent {.dgroup%lx.%lx}\\\n", glist_getcanvas(owner), gl, x->sc_vec, parent, x->sc_vec); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "dgroup%lx.%lx", (long unsigned int)gl, + (long unsigned int)x->sc_vec); + char parentbuf[MAXPDSTRING]; + sprintf(parentbuf, "dgroup%lx.%lx", (long unsigned int)parent, + (long unsigned int)x->sc_vec); + gui_start_vmess("gui_create_scalar_group", "sss", + canvas_string(glist_getcanvas(owner)), tagbuf, parentbuf); svg_grouptogui(gl, template, x->sc_vec); - sys_gui("\n"); + gui_end_vmess(); + //sys_gui("\n"); } for (y = gl->gl_list; y; y = y->g_next) @@ -727,9 +857,26 @@ static void scalar_vis(t_gobj *z, t_glist *owner, int vis) xscale, 0.0, 0.0, yscale, (int)glist_xtopixels(owner, basex), (int)glist_ytopixels(owner, basey) ); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "scalar%lx", (long unsigned int)x->sc_vec); + gui_vmess("gui_create_scalar", "ssiffffii", + canvas_string(glist_getcanvas(owner)), + tagbuf, + glist_isselected(owner, &x->sc_gobj), + xscale, 0.0, 0.0, yscale, + (int)glist_xtopixels(owner, basex), + (int)glist_ytopixels(owner, basey)); sys_vgui(".x%lx.c create group -tags {.dgroup%lx.%lx} " "-parent {.scalar%lx}\n", glist_getcanvas(owner), templatecanvas, x->sc_vec, x->sc_vec); + char groupbuf[MAXPDSTRING]; + // Quick hack to make gui_create_scalar_group more general (so we + // don't have to tack on "gobj" manually) + sprintf(tagbuf, "scalar%lxgobj", (long unsigned int)x->sc_vec); + sprintf(groupbuf, "dgroup%lx.%lx", (long unsigned int)templatecanvas, + (long unsigned int)x->sc_vec); + gui_vmess("gui_create_scalar_group", "sss", + canvas_string(glist_getcanvas(owner)), groupbuf, tagbuf); sys_vgui("pdtk_bind_scalar_mouseover " ".x%lx.c .x%lx.x%lx.template%lx {.x%lx}\n", glist_getcanvas(owner), glist_getcanvas(owner), @@ -742,8 +889,8 @@ static void scalar_vis(t_gobj *z, t_glist *owner, int vis) t_parentwidgetbehavior *wb = pd_getparentwidget(&y->g_pd); if (!wb) { - /* check subpatches for more drawing commands. This - can be optimized to only search [group] subpatches */ + /* check subpatches for more drawing commands. + (Optimized to only search [group] subpatches) */ if (pd_class(&y->g_pd) == canvas_class && ((t_glist *)y)->gl_svg) { @@ -756,8 +903,14 @@ static void scalar_vis(t_gobj *z, t_glist *owner, int vis) basex, basey, vis); } if (!vis) + { sys_vgui(".x%lx.c delete .scalar%lx\n", glist_getcanvas(owner), x->sc_vec); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "scalar%lx", (long unsigned int)x->sc_vec); + gui_vmess("gui_scalar_erase", "ss", + canvas_string(glist_getcanvas(owner)), tagbuf); + } sys_unqueuegui(x); if (glist_isselected(owner, &x->sc_gobj)) diff --git a/pd/src/g_slider.c b/pd/src/g_slider.c index 08fc5c5113d68b049398a6327d75ab2688accd91..1be19a1e2ada06be0a95bab39c5792a2e40de67d 100644 --- a/pd/src/g_slider.c +++ b/pd/src/g_slider.c @@ -33,10 +33,20 @@ static void slider_draw_update(t_gobj *client, t_glist *glist) r=y2-3 - (x->x_val+50)/100; sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n", canvas, x, x1+2, r, x2-2, r); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_slider_update", "ssiiiiii", + canvas_string(canvas), tagbuf, x1+2, r, x2-2, r, + x1, y1); } else { r=x1+3 + (x->x_val+50)/100; sys_vgui(".x%lx.c coords %lxKNOB %d %d %d %d\n", canvas, x, r, y1+2, r, y2-2); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_slider_update", "ssiiiiii", + canvas_string(canvas), tagbuf, r, y1+2, r, y2-2, + x1, y1); } int t = x->x_thick; x->x_thick = x->x_val == x->x_center; @@ -59,10 +69,22 @@ static void slider_draw_new(t_slider *x, t_glist *glist) sys_vgui(".x%lx.c create polyline %d %d %d %d -strokewidth 3 " "-stroke #%6.6x -tags {%lxKNOB x%lx text iemgui}\n", canvas, x1+2, r, x2-2, r, x->x_gui.x_fcol, x, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", x->x_gui.x_fcol); + gui_vmess("gui_create_slider", "sssiiiiii", canvas_string(canvas), tagbuf, + colorbuf, x1+2, r, x2-2, r, x1, y1); } else { sys_vgui(".x%lx.c create polyline %d %d %d %d -strokewidth 3 " "-stroke #%6.6x -tags {%lxKNOB x%lx text iemgui}\n", canvas, r, y1+2, r, y2-2, x->x_gui.x_fcol, x, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", x->x_gui.x_fcol); + gui_vmess("gui_create_slider", "sssiiiiii", canvas_string(canvas), tagbuf, + colorbuf, r, y1+2, r, y2-2, x1, y1); } } diff --git a/pd/src/g_template.c b/pd/src/g_template.c index 08fba1d1ec2acb4b9fefd880dbeae4ddd03c5425..32c415f500ee61bc567e9e9eb6f69edcd44eb50e 100644 --- a/pd/src/g_template.c +++ b/pd/src/g_template.c @@ -1472,13 +1472,13 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s, if (x->x_type == gensym("group")) { sprintf(tag, "%s%lx.%lx", - (in_array ? ".scelem" : ".dgroup"), + (in_array ? "scelem" : "dgroup"), (long unsigned int)x->x_parent, (long unsigned int)data); } else { - sprintf(tag, ".draw%lx.%lx", + sprintf(tag, "draw%lx.%lx", (long unsigned int)x->x_parent, (long unsigned int)data); } @@ -1499,8 +1499,10 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s, } else fill = &s_; - sys_vgui(".x%lx.c itemconfigure %s -fill %s\n", - glist_getcanvas(c), tag, fill->s_name); + //sys_vgui(".x%lx.c itemconfigure %s -fill %s\n", + // glist_getcanvas(c), tag, fill->s_name); + gui_vmess("gui_draw_configure", "ssss", + canvas_string(glist_getcanvas(c)), tag, s->s_name, fill->s_name); } else if (s == gensym("stroke")) { @@ -1516,79 +1518,120 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s, (int)fielddesc_getfloat(fd+2, template, data, 1))); } else stroke = &s_; - sys_vgui(".x%lx.c itemconfigure %s -stroke %s\n", - glist_getcanvas(c), tag, stroke->s_name); + //sys_vgui(".x%lx.c itemconfigure %s -stroke %s\n", + // glist_getcanvas(c), tag, stroke->s_name); + gui_vmess("gui_draw_configure", "ssss", + canvas_string(glist_getcanvas(c)), tag, s->s_name, stroke->s_name); } else if (s == gensym("fill-opacity")) - sys_vgui(".x%lx.c itemconfigure %s -fillopacity %g\n", - glist_getcanvas(c), tag, + //sys_vgui(".x%lx.c itemconfigure %s -fillopacity %g\n", + // glist_getcanvas(c), tag, + // fielddesc_getcoord(&x->x_fillopacity.a_attr, template, data, 1)); + gui_vmess("gui_draw_configure", "sssf", + canvas_string(glist_getcanvas(c)), tag, "fill-opacity", fielddesc_getcoord(&x->x_fillopacity.a_attr, template, data, 1)); else if (s == gensym("fill-rule")) - sys_vgui(".x%lx.c itemconfigure %s -fillrule %s\n", - glist_getcanvas(c), tag, (int)fielddesc_getcoord( + //sys_vgui(".x%lx.c itemconfigure %s -fillrule %s\n", + // glist_getcanvas(c), tag, (int)fielddesc_getcoord( + // &x->x_fillrule.a_attr, template, data, 1) ? + // "evenodd" : "nonzero"); + gui_vmess("gui_draw_configure", "sssi", + canvas_string(glist_getcanvas(c)), tag, "fill-rule", (int)fielddesc_getcoord( &x->x_fillrule.a_attr, template, data, 1) ? "evenodd" : "nonzero"); else if (s == gensym("pointer-events")) *predraw_bbox = 1; else if (s == gensym("stroke-linecap")) - sys_vgui(".x%lx.c itemconfigure %s -strokelinecap %s\n", - glist_getcanvas(c), tag, get_strokelinecap( + //sys_vgui(".x%lx.c itemconfigure %s -strokelinecap %s\n", + // glist_getcanvas(c), tag, get_strokelinecap( + // (int)fielddesc_getcoord(&x->x_strokelinecap.a_attr, + // template, data, 1))); + gui_vmess("gui_draw_configure", "ssss", + canvas_string(glist_getcanvas(c)), tag, "stroke-linecap", get_strokelinecap( (int)fielddesc_getcoord(&x->x_strokelinecap.a_attr, template, data, 1))); else if (s == gensym("stroke-linejoin")) - sys_vgui(".x%lx.c itemconfigure %s -strokelinejoin %s\n", - glist_getcanvas(c), tag, get_strokelinejoin( + //sys_vgui(".x%lx.c itemconfigure %s -strokelinejoin %s\n", + // glist_getcanvas(c), tag, get_strokelinejoin( + // (int)fielddesc_getcoord(&x->x_strokelinejoin.a_attr, + // template, data, 1))); + gui_vmess("gui_draw_configure", "ssss", + canvas_string(glist_getcanvas(c)), tag, "stroke-linejoin", get_strokelinejoin( (int)fielddesc_getcoord(&x->x_strokelinejoin.a_attr, template, data, 1))); else if (s == gensym("stroke-miterlimit")) - sys_vgui(".x%lx.c itemconfigure %s -strokemiterlimit %g\n", - glist_getcanvas(c), tag, fielddesc_getcoord( + //sys_vgui(".x%lx.c itemconfigure %s -strokemiterlimit %g\n", + // glist_getcanvas(c), tag, fielddesc_getcoord( + // &x->x_strokemiterlimit.a_attr, template, data, 1)); + gui_vmess("gui_draw_configure", "sssf", + canvas_string(glist_getcanvas(c)), tag, "stroke-miterlimit", fielddesc_getcoord( &x->x_strokemiterlimit.a_attr, template, data, 1)); else if (s == gensym("stroke-opacity")) - sys_vgui(".x%lx.c itemconfigure %s -strokeopacity %g\n", - glist_getcanvas(c), tag, fielddesc_getcoord( + //sys_vgui(".x%lx.c itemconfigure %s -strokeopacity %g\n", + // glist_getcanvas(c), tag, fielddesc_getcoord( + // &x->x_strokeopacity.a_attr, template, data, 1)); + gui_vmess("gui_draw_configure", "sssg", + canvas_string(glist_getcanvas(c)), tag, "stroke-opacity", fielddesc_getcoord( &x->x_strokeopacity.a_attr, template, data, 1)); else if (s == gensym("stroke-width")) { - sys_vgui(".x%lx.c itemconfigure %s -strokewidth %g\n", - glist_getcanvas(c), tag, fielddesc_getcoord( + //sys_vgui(".x%lx.c itemconfigure %s -strokewidth %g\n", + // glist_getcanvas(c), tag, fielddesc_getcoord( + // &x->x_strokewidth.a_attr, template, data, 1)); + gui_vmess("gui_draw_configure", "sssf", + canvas_string(glist_getcanvas(c)), tag, "stroke-width", fielddesc_getcoord( &x->x_strokewidth.a_attr, template, data, 1)); *predraw_bbox = 1; } else if (s == gensym("r")) { - sys_vgui(".x%lx.c itemconfigure %s -rx %g -ry %g\n", - glist_getcanvas(c), tag, - fielddesc_getcoord(x->x_vec+2, template, data, 1), - fielddesc_getcoord(x->x_vec+2, template, data, 1)); + //sys_vgui(".x%lx.c itemconfigure %s -rx %g -ry %g\n", + //glist_getcanvas(c), tag, + //fielddesc_getcoord(x->x_vec+2, template, data, 1), + //fielddesc_getcoord(x->x_vec+2, template, data, 1)); + gui_vmess("gui_draw_configure", "sssf", + canvas_string(glist_getcanvas(c)), tag, s->s_name, + fielddesc_getcoord(x->x_vec+2, template, data, 1)); *predraw_bbox = 1; } else if (s == gensym("rx")) { if (x->x_type == gensym("rect")) - sys_vgui(".x%lx.c itemconfigure %s -rx %d\n", - glist_getcanvas(c), tag, (int)fielddesc_getcoord( + //sys_vgui(".x%lx.c itemconfigure %s -rx %d\n", + // glist_getcanvas(c), tag, (int)fielddesc_getcoord( + // &x->x_rx.a_attr, template, data, 1)); + gui_vmess("gui_draw_configure", "sssi", + canvas_string(glist_getcanvas(c)), tag, s->s_name, (int)fielddesc_getcoord( &x->x_rx.a_attr, template, data, 1)); else { - sys_vgui(".x%lx.c itemconfigure %s -rx %g\n", - glist_getcanvas(c), tag, fielddesc_getcoord( - x->x_vec+2, template, data, 1)); + //sys_vgui(".x%lx.c itemconfigure %s -rx %g\n", + // glist_getcanvas(c), tag, fielddesc_getcoord( + // x->x_vec+2, template, data, 1)); + gui_vmess("gui_draw_configure", "sssf", + canvas_string(glist_getcanvas(c)), tag, s->s_name, fielddesc_getcoord( + x->x_vec+2, template, data, 1)); *predraw_bbox = 1; } } else if (s == gensym("ry")) { if (x->x_type == gensym("rect")) - sys_vgui(".x%lx.c itemconfigure %s -ry %d\n", - glist_getcanvas(c), tag, (int)fielddesc_getcoord( - &x->x_ry.a_attr, template, data, 1)); + //sys_vgui(".x%lx.c itemconfigure %s -ry %d\n", + // glist_getcanvas(c), tag, (int)fielddesc_getcoord( + // &x->x_ry.a_attr, template, data, 1)); + gui_vmess("gui_draw_configure", "sssi", + canvas_string(glist_getcanvas(c)), tag, s->s_name, (int)fielddesc_getcoord( + &x->x_ry.a_attr, template, data, 1)); else { - sys_vgui(".x%lx.c itemconfigure %s -ry %g\n", - glist_getcanvas(c), tag, fielddesc_getcoord( - x->x_vec+3, template, data, 1)); - *predraw_bbox = 1; + //sys_vgui(".x%lx.c itemconfigure %s -ry %g\n", + // glist_getcanvas(c), tag, fielddesc_getcoord( + // x->x_vec+3, template, data, 1)); + gui_vmess("gui_draw_configure", "sssf", + canvas_string(glist_getcanvas(c)), tag, fielddesc_getcoord( + x->x_vec+3, template, data, 1)); + *predraw_bbox = 1; } } else if (s == gensym("transform")) @@ -1607,39 +1650,57 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s, x->x_pathrect_cache = 0; } svg_parsetransform(x, template, data, &m1, &m2, &m3, &m4, &m5, &m6); - sys_vgui(".x%lx.c itemconfigure %s -matrix " - "{ {%g %g} {%g %g} {%g %g} }\n", - glist_getcanvas(c), tag, - m1, m2, m3, m4, m5, m6); + //sys_vgui(".x%lx.c itemconfigure %s -matrix " + // "{ {%g %g} {%g %g} {%g %g} }\n", + // glist_getcanvas(c), tag, + // m1, m2, m3, m4, m5, m6); + char mbuf[MAXPDSTRING]; + sprintf(mbuf, "matrix(%g %g %g %g %g %g)", m1, m2, m3, m4, m5, m6); + gui_vmess("gui_draw_configure", "ssss", + canvas_string(glist_getcanvas(c)), tag, s->s_name, + mbuf); *predraw_bbox = 1; - } else if (s == gensym("vis")) { - sys_vgui(".x%lx.c itemconfigure %s -state %s\n", - glist_getcanvas(c), tag, (int)fielddesc_getcoord( - &x->x_vis.a_attr, template, data, 1) ? "normal" : "hidden"); + //sys_vgui(".x%lx.c itemconfigure %s -state %s\n", + // glist_getcanvas(c), tag, (int)fielddesc_getcoord( + // &x->x_vis.a_attr, template, data, 1) ? "normal" : "hidden"); + gui_vmess("gui_draw_configure", "ssss", + canvas_string(glist_getcanvas(c)), tag, "visibility", (int)fielddesc_getcoord( + &x->x_vis.a_attr, template, data, 1) ? "visible" : "hidden"); *predraw_bbox = 1; } else if (s == gensym("stroke-dasharray")) { + // not ready yet... need a gui interface for variable size attrs if (x->x_ndash) { t_fielddesc *fd = x->x_strokedasharray; int i; - sys_vgui(".x%lx.c itemconfigure %s -strokedasharray {", - glist_getcanvas(c), tag); + //sys_vgui(".x%lx.c itemconfigure %s -strokedasharray {", + // glist_getcanvas(c), tag); + gui_start_vmess("gui_draw_configure", "sss", + canvas_string(glist_getcanvas(c)), tag, s->s_name); + gui_start_array(); for (i = 0; i < x->x_ndash; i++) { - sys_vgui(" %g ", fielddesc_getcoord(fd+i, template, data, 1)); + //sys_vgui(" %g ", fielddesc_getcoord(fd+i, template, data, 1)); + gui_float_elem(fielddesc_getcoord(fd+i, template, data, 1)); } - sys_gui("}\n"); + //sys_gui("}\n"); + gui_end_array(); + gui_end_vmess(); } } else if (s == gensym("data")) { - sys_vgui(".x%lx.c coords .draw%lx.%lx {\\\n", - glist_getcanvas(c), parent, data); + //sys_vgui(".x%lx.c coords .draw%lx.%lx {\\\n", + // glist_getcanvas(c), parent, data); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "draw%lx.%lx", (long unsigned int)parent, (long unsigned int)data); + gui_start_vmess("gui_draw_configure", "sss", + canvas_string(glist_getcanvas(c)), tagbuf, "d"); /* let's turn off bbox caching so we can recalculate the bbox */ if (x->x_pathrect_cache != -1) x->x_pathrect_cache = 0; @@ -1648,19 +1709,28 @@ void svg_sendupdate(t_svg *x, t_canvas *c, t_symbol *s, char *cmd; t_fielddesc *f; int totalpoints = 0; /* running tally */ + /* start an array parameter */ + char cmdbuf[2]; + gui_start_array(); /* path parser: no error checking yet */ for (i = 0, cmd = x->x_pathcmds; i < x->x_npathcmds; i++, cmd++) { int j; int cargs = x->x_nargs_per_cmd[i]; f = (x->x_vec)+totalpoints; - sys_vgui("%c\\\n", *(cmd)); + //sys_vgui("%c\\\n", *(cmd)); + sprintf(cmdbuf, "%c", *(cmd)); + gui_string_elem(cmdbuf); for (j = 0; j < x->x_nargs_per_cmd[i]; j++) - sys_vgui("%g\\\n", fielddesc_getcoord( - f+j, template, data, 1)); + //sys_vgui("%g\\\n", fielddesc_getcoord( + // f+j, template, data, 1)); + gui_float_elem(fielddesc_getcoord( + f+j, template, data, 0)); totalpoints += x->x_nargs_per_cmd[i]; } - sys_gui("}\n"); + //sys_gui("}\n"); + gui_end_array(); + gui_end_vmess(); } else if (s == gensym("index")) { @@ -2421,16 +2491,16 @@ void svg_parsetransform(t_svg *x, t_template *template, t_word *data, } else if (type == gensym("skewx")) { - t_float a = fielddesc_getfloat(fd++, template, data, 0) * - 3.14159 / 180; + t_float a = fielddesc_getfloat(fd++, template, data, 0); // * + // 3.14159 / 180; argc--; mset(m2, 1, 0, tan(a), 1, 0, 0); mmult(m, m2, m); } else if (type == gensym("skewy")) { - t_float a = fielddesc_getfloat(fd++, template, data, 0) * - 3.14159 / 180; + t_float a = fielddesc_getfloat(fd++, template, data, 0); // * + // 3.14159 / 180; argc--; mset(m2, 1, tan(a), 0, 1, 0, 0); mmult(m, m2, m); @@ -3429,6 +3499,10 @@ static void draw_activate(t_gobj *z, t_glist *glist, static void svg_togui(t_svg *x, t_template *template, t_word *data) { + // Hack to send parameter as an object to the GUI. Not sure yet if + // we want to generalize that... + //sys_gui(",{ "); + gui_start_array(); if (x->x_type != gensym("line")) { if (x->x_filltype) @@ -3437,24 +3511,60 @@ static void svg_togui(t_svg *x, t_template *template, t_word *data) if (x->x_filltype == 1) { t_symbol *f = fielddesc_getsymbol(fd, template, data, 1); - sys_vgui("-fill %s ", f->s_name); + //sys_vgui("-fill %s ", f->s_name); + //sys_vgui("fill: '%s',", f->s_name); + gui_string_elem("fill"); + gui_string_elem(f->s_name); } else if (x->x_filltype == 2) - sys_vgui("-fill %s ", rgb_to_hex( + { + //sys_vgui("-fill %s ", rgb_to_hex( + // (int)fielddesc_getfloat(fd, + // template, data, 1), + // (int)fielddesc_getfloat(fd+1, + // template, data, 1), + // (int)fielddesc_getfloat(fd+2, + // template, data, 1))); + + //sys_vgui("fill: '%s',", rgb_to_hex( + // (int)fielddesc_getfloat(fd, + // template, data, 1), + // (int)fielddesc_getfloat(fd+1, + // template, data, 1), + // (int)fielddesc_getfloat(fd+2, + // template, data, 1))); + gui_string_elem("fill"); + gui_string_elem(rgb_to_hex( (int)fielddesc_getfloat(fd, template, data, 1), (int)fielddesc_getfloat(fd+1, template, data, 1), (int)fielddesc_getfloat(fd+2, template, data, 1))); + } } if (x->x_fillopacity.a_flag) - sys_vgui("-fillopacity %g ", - fielddesc_getfloat(&x->x_fillopacity.a_attr, template, data, 1)); + { + //sys_vgui("-fillopacity %g ", + // fielddesc_getfloat(&x->x_fillopacity.a_attr, template, data, 1)); + //sys_vgui("fill-opacity: %g,", + // fielddesc_getfloat(&x->x_fillopacity.a_attr, template, data, 1)); + gui_string_elem("fill-opacity"); + gui_float_elem(fielddesc_getfloat(&x->x_fillopacity.a_attr, template, data, 1)); + } if (x->x_fillrule.a_flag) - sys_vgui("-fillrule %s ", (int)fielddesc_getfloat( + { + //sys_vgui("-fillrule %s ", (int)fielddesc_getfloat( + // &x->x_fillrule.a_attr, template, data, 1) ? + // "evenodd" : "nonzero"); + //sys_vgui("'fill-rule': '%s',", (int)fielddesc_getfloat( + // &x->x_fillrule.a_attr, template, data, 1) ? + // "evenodd" : "nonzero"); + gui_string_elem("fill-rule"); + gui_string_elem((int)fielddesc_getfloat( &x->x_fillrule.a_attr, template, data, 1) ? "evenodd" : "nonzero"); + } } if (x->x_stroketype) { @@ -3462,46 +3572,124 @@ static void svg_togui(t_svg *x, t_template *template, t_word *data) if (x->x_stroketype == 1) { t_symbol *s = fielddesc_getsymbol(fd, template, data, 1); - sys_vgui("-stroke %s ", s->s_name); + //sys_vgui("-stroke %s ", s->s_name); + //sys_vgui("stroke: '%s',", s->s_name); + gui_string_elem("stroke"); + gui_string_elem(s->s_name); } else if (x->x_stroketype == 2) - sys_vgui("-stroke %s ", rgb_to_hex( + { + //sys_vgui("-stroke %s ", rgb_to_hex( + // (int)fielddesc_getfloat(fd, + // template, data, 1), + // (int)fielddesc_getfloat(fd+1, + // template, data, 1), + // (int)fielddesc_getfloat(fd+2, + // template, data, 1))); + //sys_vgui("stroke: '%s',", rgb_to_hex( + // (int)fielddesc_getfloat(fd, + // template, data, 1), + // (int)fielddesc_getfloat(fd+1, + // template, data, 1), + // (int)fielddesc_getfloat(fd+2, + // template, data, 1))); + + gui_string_elem("stroke"); + gui_string_elem(rgb_to_hex( (int)fielddesc_getfloat(fd, template, data, 1), (int)fielddesc_getfloat(fd+1, template, data, 1), (int)fielddesc_getfloat(fd+2, template, data, 1))); + } } if (x->x_strokewidth.a_flag) - sys_vgui("-strokewidth %g\\\n", - fielddesc_getfloat(&x->x_strokewidth.a_attr, template, data, 1)); + { + //sys_vgui("-strokewidth %g\\\n", + // fielddesc_getfloat(&x->x_strokewidth.a_attr, template, data, 1)); + //sys_vgui("stroke-width: %g,", + // fielddesc_getfloat(&x->x_strokewidth.a_attr, template, data, 1)); + gui_string_elem("stroke-width"); + gui_float_elem(fielddesc_getfloat(&x->x_strokewidth.a_attr, template, data, 1)); + } + if (x->x_type == gensym("circle")) + { + if (x->x_nargs > 0) + { + gui_string_elem("cx"); + gui_float_elem(fielddesc_getfloat(&x->x_vec[0], template, data, 1)); + } + } if (x->x_strokeopacity.a_flag) - sys_vgui("-strokeopacity %g ", - fielddesc_getfloat(&x->x_strokeopacity.a_attr, template, data, 1)); + { + //sys_vgui("-strokeopacity %g ", + // fielddesc_getfloat(&x->x_strokeopacity.a_attr, template, data, 1)); + //sys_vgui("'stroke-opacity': %g,", + // fielddesc_getfloat(&x->x_strokeopacity.a_attr, template, data, 1)); + + gui_string_elem("stroke-opacity"); + gui_float_elem(fielddesc_getfloat(&x->x_strokeopacity.a_attr, template, data, 1)); + } if (x->x_strokelinecap.a_flag) - sys_vgui("-strokelinecap %s ", get_strokelinecap( + { + //sys_vgui("-strokelinecap %s ", get_strokelinecap( + // (int)fielddesc_getcoord(&x->x_strokelinecap.a_attr, + // template, data, 1))); + //sys_vgui("'stroke-linecap': '%s',", get_strokelinecap( + // (int)fielddesc_getcoord(&x->x_strokelinecap.a_attr, + // template, data, 1))); + + gui_string_elem("stroke-linecap"); + gui_string_elem(get_strokelinecap( (int)fielddesc_getcoord(&x->x_strokelinecap.a_attr, template, data, 1))); + } if (x->x_strokelinejoin.a_flag) - sys_vgui("-strokelinejoin %s ", get_strokelinejoin( + { + //sys_vgui("-strokelinejoin %s ", get_strokelinejoin( + // (int)fielddesc_getfloat(&x->x_strokelinejoin.a_attr, + //template, data, 1))); + //sys_vgui("'stroke-linejoin': '%s',", get_strokelinejoin( + // (int)fielddesc_getfloat(&x->x_strokelinejoin.a_attr, + //template, data, 1))); + + gui_string_elem("stroke-linejoin"); + gui_string_elem(get_strokelinejoin( (int)fielddesc_getfloat(&x->x_strokelinejoin.a_attr, template, data, 1))); + } if (x->x_strokemiterlimit.a_flag) - sys_vgui("-strokemiterlimit %g ", - fielddesc_getfloat(&x->x_strokemiterlimit.a_attr, + { + //sys_vgui("-strokemiterlimit %g ", + // fielddesc_getfloat(&x->x_strokemiterlimit.a_attr, + // template, data, 1)); + //sys_vgui("'stroke-miterlimit': %g,", + // fielddesc_getfloat(&x->x_strokemiterlimit.a_attr, + // template, data, 1)); + gui_string_elem("stroke-miterlimit"); + gui_float_elem(fielddesc_getfloat(&x->x_strokemiterlimit.a_attr, template, data, 1)); + } if (x->x_ndash) { int i; t_fielddesc *fd; - sys_gui(" -strokedasharray {\\\n"); + // inner array... + //sys_gui(" -strokedasharray {\\\n"); + //sys_gui("'stroke-dasharray': \""); + gui_string_elem("stroke-dasharray"); + gui_start_array(); for (i = 0, fd = x->x_strokedasharray; i < x->x_ndash; i++) { - sys_vgui("%d\\\n", (int)fielddesc_getfloat(fd+i, + // Should this be a float? + //sys_vgui("%d ", (int)fielddesc_getfloat(fd+i, + //template, data, 1)); + gui_int_elem((int)fielddesc_getfloat(fd+i, template, data, 1)); } - sys_gui("}\\\n"); + //sys_gui("\","); + gui_end_array(); } if (x->x_transform_n > 0) { @@ -3509,24 +3697,48 @@ static void svg_togui(t_svg *x, t_template *template, t_word *data) t_float m1, m2, m3, m4, m5, m6; svg_parsetransform(x, template, data, &m1, &m2, &m3, &m4, &m5, &m6); - sys_vgui("-matrix { {%g %g} {%g %g} {%g %g} }\\\n", + //sys_vgui("-matrix { {%g %g} {%g %g} {%g %g} }\\\n", + // m1, m2, m3, m4, m5, m6); + gui_string_elem("transform"); + char transbuf[MAXPDSTRING]; + sprintf(transbuf, "matrix(%g,%g,%g,%g,%g,%g)", m1, m2, m3, m4, m5, m6); + gui_string_elem(transbuf); } if (x->x_vis.a_flag) { - sys_vgui("-state %s ", fielddesc_getfloat(&x->x_vis.a_attr, - template, data, 1) ? "normal" : "hidden"); + //sys_vgui("-state %s ", fielddesc_getfloat(&x->x_vis.a_attr, + // template, data, 1) ? "normal" : "hidden"); + //sys_vgui("visibility: '%s',", fielddesc_getfloat(&x->x_vis.a_attr, + // template, data, 1) ? "visible" : "hidden"); + gui_string_elem("visibility"); + gui_string_elem(fielddesc_getfloat(&x->x_vis.a_attr, + template, data, 1) ? "visible" : "hidden"); } if (x->x_rx.a_flag) { - sys_vgui("-rx %d ", (int)fielddesc_getfloat(&x->x_rx.a_attr, + //sys_vgui("-rx %d ", (int)fielddesc_getfloat(&x->x_rx.a_attr, + // template, data, 1)); + //sys_vgui("rx: %d,", (int)fielddesc_getfloat(&x->x_rx.a_attr, + // template, data, 1)); + gui_string_elem("rx"); + gui_int_elem((int)fielddesc_getfloat(&x->x_rx.a_attr, template, data, 1)); } if (x->x_ry.a_flag) { - sys_vgui("-ry %d ", (int)fielddesc_getfloat(&x->x_ry.a_attr, + //sys_vgui("-ry %d ", (int)fielddesc_getfloat(&x->x_ry.a_attr, + // template, data, 1)); + //sys_vgui("ry: %d,", (int)fielddesc_getfloat(&x->x_ry.a_attr, + // template, data, 1)); + gui_string_elem("ry"); + gui_float_elem((int)fielddesc_getfloat(&x->x_ry.a_attr, template, data, 1)); } + gui_string_elem("display"); + gui_string_elem("inline"); + //sys_gui("display: 'inline'},"); + gui_end_array(); } void svg_grouptogui(t_glist *g, t_template *template, t_word *data) @@ -3535,6 +3747,23 @@ void svg_grouptogui(t_glist *g, t_template *template, t_word *data) svg_togui(x, template, data); } +void svg_parentwidgettogui(t_gobj *z, t_glist *owner, t_word *data, + t_template *template) +{ + if (pd_class(&z->g_pd) == draw_class) + { + t_draw *x = (t_draw *)z; + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "draw%lx.%lx", (long unsigned int)x, + (long unsigned int)data); + gui_start_vmess("gui_draw_configure_all", "ss", + canvas_string(glist_getcanvas(owner)), tagbuf); + svg_togui((t_svg *)x->x_attr, template, data); + gui_end_vmess(); + } +} + + static void draw_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, t_scalar *sc, t_word *data, t_template *template, t_float basex, t_float basey, int vis) @@ -3608,6 +3837,15 @@ static void draw_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, sys_vgui(".x%lx.c create path {\\\n", glist_getcanvas(glist)); else if (sa->x_type == gensym("circle")) sys_vgui(".x%lx.c create ellipse\\\n", glist_getcanvas(glist)); + + /* cheap hack... there should instead be a gui_vmess style function + for incrementally building a message to the GUI (possibly with atom + arrays) */ + //sys_vgui("nn gui_draw_vis \".x%lx\",\"%s\",\"", glist_getcanvas(glist), + // sa->x_type->s_name); + gui_start_vmess("gui_draw_vis", "ss", canvas_string(glist_getcanvas(glist)), + sa->x_type->s_name); + /* next send the gui drawing arguments: commands and points for paths, points for everything else */ if (sa->x_type == gensym("path")) @@ -3616,75 +3854,142 @@ static void draw_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, the bbox */ if (sa->x_pathrect_cache != -1) sa->x_pathrect_cache = 0; - char *cmd; + char *cmd, cmdbuf[2]; int totalpoints = 0; /* running tally */ + gui_start_array(); /* path parser: no error checking yet */ for (i = 0, cmd = sa->x_pathcmds; i < sa->x_npathcmds; i++, cmd++) { int j; int cargs = sa->x_nargs_per_cmd[i]; f = (sa->x_vec)+totalpoints; - sys_vgui("%c\\\n", *(cmd)); + //sys_vgui("%c\\\n", *(cmd)); + //sys_vgui("%c ", *(cmd)); + sprintf(cmdbuf, "%c", *(cmd)); + gui_string_elem(cmdbuf); for (j = 0; j < sa->x_nargs_per_cmd[i]; j++) - sys_vgui("%g\\\n", fielddesc_getcoord( - f+j, template, data, 1)); + //sys_vgui("%g\\\n", fielddesc_getcoord( + // f+j, template, data, 1)); + //sys_vgui("%g ", fielddesc_getcoord(f+j, template, data, 1)); + gui_float_elem(fielddesc_getcoord(f+j, template, data, 0)); totalpoints += sa->x_nargs_per_cmd[i]; } - sys_gui("}\\\n"); + //sys_gui("}\\\n"); + //sys_gui("\","); + gui_end_array(); } else /* all other shapes */ { + gui_start_array(); int nxy = n >> 1; for (i = 0; i < nxy; i++) { - sys_vgui("%g %g\\\n", pix[2*i], pix[2*i+1]); + //sys_vgui("%g %g\\\n", pix[2*i], pix[2*i+1]); + //sys_vgui("%g %g ", pix[2*i], pix[2*i+1]); + gui_float_elem(pix[2*i]); + gui_float_elem(pix[2*i+1]); if ((sa->x_type == gensym("ellipse") || sa->x_type == gensym("circle")) && n > 1) { - sys_vgui("-rx %d -ry %d\\\n", - (int)(fielddesc_getcoord(sa->x_vec+2, - template, data, 1)), - (int)(fielddesc_getcoord(sa->x_vec + + //sys_vgui("-rx %d -ry %d\\\n", + // (int)(fielddesc_getcoord(sa->x_vec+2, + // template, data, 1)), + // (int)(fielddesc_getcoord(sa->x_vec + + // (sa->x_type == gensym("ellipse")? + // 3 : 2), + // template, data, 1))); + // These should be floats... + //sys_vgui("%d %d ", + // (int)(fielddesc_getcoord(sa->x_vec+2, + // template, data, 1)), + // (int)(fielddesc_getcoord(sa->x_vec + + // (sa->x_type == gensym("ellipse")? + // 3 : 2), + // template, data, 1))); + + gui_float_elem(fielddesc_getcoord(sa->x_vec+2, + template, data, 0)); + gui_float_elem(fielddesc_getcoord(sa->x_vec + (sa->x_type == gensym("ellipse")? 3 : 2), - template, data, 1))); + template, data, 1)); break; } else if (sa->x_type == gensym("rect") && n > 1) { - sys_vgui("%g %g\\\n", - fielddesc_getcoord(sa->x_vec, - template, data, 1) + - fielddesc_getcoord(sa->x_vec+2, - template, data, 1), - fielddesc_getcoord(sa->x_vec+1, - template, data, 1) + - fielddesc_getcoord(sa->x_vec+3, - template, data, 1)); + //sys_vgui("%g %g\\\n", + // fielddesc_getcoord(sa->x_vec, + // template, data, 1) + + // fielddesc_getcoord(sa->x_vec+2, + // template, data, 1), + // fielddesc_getcoord(sa->x_vec+1, + // template, data, 1) + + // fielddesc_getcoord(sa->x_vec+3, + // template, data, 1)); + + //sys_vgui("%g %g ", + // fielddesc_getcoord(sa->x_vec+2, + // template, data, 1), + // fielddesc_getcoord(sa->x_vec+3, + // template, data, 1)); + + gui_float_elem(fielddesc_getcoord(sa->x_vec+2, + template, data, 0)); + gui_float_elem(fielddesc_getcoord(sa->x_vec+3, + template, data, 0)); break; } else if (sa->x_type == gensym("circle")) { - sys_vgui("-r %d\\\n", - (t_int)fielddesc_getcoord(sa->x_vec+2, - template, data, 1)); + //sys_vgui("-r %d\\\n", + // (t_int)fielddesc_getcoord(sa->x_vec+2, + // template, data, 1)); + //sys_vgui("%d ", + // (t_int)fielddesc_getcoord(sa->x_vec+2, + // template, data, 1)); + gui_int_elem((t_int)fielddesc_getcoord(sa->x_vec+2, + template, data, 1)); break; } } + //sys_gui("\","); + gui_end_array(); } svg_togui(sa, template, data); + + gui_start_array(); + char parent_tagbuf[MAXPDSTRING]; if (in_array) - sys_vgui(" -parent .scelem%lx.%lx \\\n", parentglist, data); + { + //sys_vgui(" -parent .scelem%lx.%lx \\\n", parentglist, data); + //sys_vgui("\"scelem%lx.%lx\",", parentglist, data); + sprintf(parent_tagbuf, "scelem%lx.%lx", (long unsigned int)parentglist, + (long unsigned int)data); + gui_string_elem(parent_tagbuf); + } else - sys_vgui(" -parent .dgroup%lx.%lx \\\n", - x->x_canvas, data); + { + //sys_vgui(" -parent .dgroup%lx.%lx \\\n", + //sys_vgui("\"dgroup%lx.%lx\",", + // x->x_canvas, data); + sprintf(parent_tagbuf, "dgroup%lx.%lx", (long unsigned int)x->x_canvas, + (long unsigned int)data); + gui_string_elem(parent_tagbuf); + } /* tags - one for this scalar (not sure why the double glist thingy) one for this specific draw item */ - sys_vgui("-tags {.x%lx.x%lx.template%lx .draw%lx.%lx}\n", - glist_getcanvas(glist), glist, data, x, data); + //sys_vgui("-tags {.x%lx.x%lx.template%lx .draw%lx.%lx}\n", + // glist_getcanvas(glist), glist, data, x, data); + + // Let's try to get rid of Ico's tag + //sys_vgui("\"draw%lx.%lx\"", x, data); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "draw%lx.%lx", (long unsigned int)x, + (long unsigned int)data); + gui_string_elem(tagbuf); if (!glist_istoplevel(glist)) { t_canvas *gl = glist_getcanvas(glist); @@ -3696,14 +4001,25 @@ static void draw_vis(t_gobj *z, t_glist *glist, t_glist *parentglist, canvas_restore_original_position(gl, (t_gobj *)glist, objtag, -1); } + //sys_gui(";\n"); + gui_end_array(); + gui_end_vmess(); } else post("warning: draws need at least two points to be graphed"); } else { if (n > 1) - sys_vgui(".x%lx.c delete .x%lx.x%lx.template%lx\n", - glist_getcanvas(glist), glist_getcanvas(glist), glist, data); + { +// sys_vgui(".x%lx.c delete .x%lx.x%lx.template%lx\n", +// glist_getcanvas(glist), glist_getcanvas(glist), glist, data); + char itemtagbuf[MAXPDSTRING]; + sprintf(itemtagbuf, "draw%lx.%lx", (long unsigned int)x, + (long unsigned int)data); + gui_vmess("gui_draw_erase_item", "ss", canvas_string(glist_getcanvas(glist)), + itemtagbuf); + } + } } diff --git a/pd/src/g_text.c b/pd/src/g_text.c index 84a72926c28232d8ed693d88c1cbe16b30f03165..51ab8316f24849445f504b826deecbd83a725897 100644 --- a/pd/src/g_text.c +++ b/pd/src/g_text.c @@ -709,6 +709,9 @@ static void message_click(t_message *x, t_rtext *y = glist_findrtext(x->m_glist, &x->m_text); sys_vgui(".x%lx.c itemconfigure %sR -strokewidth 5\n", glist_getcanvas(x->m_glist), rtext_gettag(y)); + gui_vmess("gui_message_flash", "ssi", + canvas_string(glist_getcanvas(x->m_glist)), + rtext_gettag(y), 1); clock_delay(x->m_clock, 120); } } @@ -720,6 +723,9 @@ static void message_tick(t_message *x) t_rtext *y = glist_findrtext(x->m_glist, &x->m_text); sys_vgui(".x%lx.c itemconfigure %sR -strokewidth 1\n", glist_getcanvas(x->m_glist), rtext_gettag(y)); + gui_vmess("gui_message_flash", "ssi", + canvas_string(glist_getcanvas(x->m_glist)), + rtext_gettag(y), 0); } } @@ -1559,6 +1565,8 @@ static void text_select(t_gobj *z, t_glist *glist, int state) sys_vgui(".x%lx.c itemconfigure %sR -stroke %s\n", glist_getcanvas(glist), rtext_gettag(y), (state? "$pd_colors(selection)" : outline)); + gui_vmess("gui_text_select_color", "ss", + canvas_string(glist_getcanvas(glist)), rtext_gettag(y)); if (z->g_pd == gatom_class) { sys_vgui(".x%lx.c itemconfigure %lx.l -fill %s\n", @@ -1578,6 +1586,8 @@ static void text_select(t_gobj *z, t_glist *glist, int state) } sys_vgui(".x%lx.c addtag selected withtag %sR \n", glist_getcanvas(glist), rtext_gettag(y)); + gui_vmess("gui_text_select", "ss", + canvas_string(glist_getcanvas(glist)), rtext_gettag(y)); if (pd_class(&x->te_pd) == text_class && x->te_type != T_TEXT && glist_istoplevel(glist)) sys_vgui(".x%lx.c itemconfigure %sR -strokewidth 1 -strokedasharray {} " @@ -1608,6 +1618,9 @@ static void text_select(t_gobj *z, t_glist *glist, int state) } sys_vgui(".x%lx.c dtag %sR selected\n", glist_getcanvas(glist), rtext_gettag(y)); + gui_vmess("gui_text_deselect", "ss", + canvas_string(glist_getcanvas(glist)), + rtext_gettag(y)); if (pd_class(&x->te_pd) == text_class && x->te_type != T_TEXT) sys_vgui(".x%lx.c itemconfigure %sR -strokewidth 2 -strokelinecap projecting -strokedasharray {2 3} " @@ -1651,6 +1664,7 @@ static void text_vis(t_gobj *z, t_glist *glist, int vis) { //fprintf(stderr,"text_vis %d\n", vis); t_text *x = (t_text *)z; + int x1, y1, x2, y2; #ifdef PDL2ORK //if we are in k12 mode and this is hub with level 1 (global) @@ -1675,6 +1689,12 @@ static void text_vis(t_gobj *z, t_glist *glist, int vis) { //fprintf(stderr," draw it\n"); t_rtext *y = glist_findrtext(glist, x); + + // make a group + text_getrect(&x->te_g, glist, &x1, &y1, &x2, &y2); + gui_vmess("gui_text_create_gobj", "ssii", + canvas_string(glist), rtext_gettag(y), x1, y1); + if (x->te_type == T_ATOM) glist_retext(glist, x); text_drawborder(x, glist, rtext_gettag(y), @@ -1688,8 +1708,9 @@ static void text_vis(t_gobj *z, t_glist *glist, int vis) if (gobj_shouldvis(&x->te_g, glist)) { //fprintf(stderr," erase it %lx %lx\n", x, glist); - text_eraseborder(x, glist, rtext_gettag(y)); - rtext_erase(y); + text_erase_gobj(x, glist, rtext_gettag(y)); + //text_eraseborder(x, glist, rtext_gettag(y)); + //rtext_erase(y); } } #ifdef PDL2ORK @@ -1860,6 +1881,7 @@ static t_widgetbehavior gatom_widgetbehavior = void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime, char *tag, int x1, int y1, int x2, int y2) { + t_rtext *y = glist_findrtext(glist, ob); //if this is a comment or we are drawing inside gop on one of //our parents return if (pd_class(&ob->te_pd) == text_class || glist_getcanvas(glist) != glist) @@ -1886,8 +1908,12 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime, tag, i, tag, (issignal ? "signal" : "control"), (selected ? "selected" : "")); + gui_vmess("gui_canvas_drawio", "sssiiiiii", + canvas_string(glist_getcanvas(glist)), rtext_gettag(y), tag, + onset, y2 - 2, onset + IOWIDTH, y2, x1, y1); } - else { + else + { //fprintf(stderr,"glist_drawiofor o redraw\n"); sys_vgui(".x%lx.c coords %so%d %d %d %d %d\n", glist_getcanvas(glist), tag, i, @@ -1921,8 +1947,12 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime, tag, i, tag, (issignal ? "signal" : "control"), (selected ? "selected" : "")); + gui_vmess("gui_canvas_drawio", "sssiiiiii", + canvas_string(glist_getcanvas(glist)), rtext_gettag(y), tag, + onset, y1, onset + IOWIDTH, y1 + EXTRAPIX, x1, y1); } - else { + else + { //fprintf(stderr,"glist_drawiofor i firsttime\n"); sys_vgui(".x%lx.c coords %si%d %d %d %d %d\n", glist_getcanvas(glist), tag, i, @@ -2018,6 +2048,7 @@ void text_drawborder(t_text *x, t_glist *glist, t_object *ob; int x1, y1, x2, y2; + int broken; int selected = glist_isselected(glist, (t_gobj*)x); @@ -2052,6 +2083,7 @@ void text_drawborder(t_text *x, t_glist *glist, outline = "$pd_colors(dash_outline) -strokewidth 2 -strokelinecap projecting -strokedasharray {2 3}"; //-strokedasharray {4 1} fill = invalid_fill; box_tag = "broken box"; + broken = 1; } else { @@ -2059,9 +2091,11 @@ void text_drawborder(t_text *x, t_glist *glist, outline = "$pd_colors(box_border)"; fill = "$pd_colors(box)"; box_tag = "box"; + broken = 0; } if (firsttime) { + /* sys_vgui(".x%lx.c create ppolygon %d %d %d %d %d %d %d %d %d %d \ -stroke %s -fill %s -tags {%sR %lx text %s %s}\n", glist_getcanvas(glist), @@ -2069,6 +2103,10 @@ void text_drawborder(t_text *x, t_glist *glist, (selected ? "$pd_colors(selection)" : outline), fill, tag, tag, box_tag, (selected ? "selected" : "")); + */ + gui_vmess("gui_text_drawborder", "ssiiiii", + canvas_string(glist_getcanvas(glist)), tag, broken, x1, y1, x2, y2); + //-dash %s -> pattern disabled for tkpath } else @@ -2078,6 +2116,8 @@ void text_drawborder(t_text *x, t_glist *glist, sys_vgui(".x%lx.c coords %sR %d %d %d %d %d %d %d %d %d %d\n", glist_getcanvas(glist), tag, x1, y1, x2, y1, x2, y2, x1, y2, x1, y1); + gui_vmess("gui_text_redraw_border", "ssiiii", + canvas_string(glist_getcanvas(glist)), tag, x1, y1, x2, y2); /* this seems to be totally extraneous hans@at.or.at sys_vgui(".x%lx.c itemconfigure %sR -dash %s -outline %s\n", glist_getcanvas(glist), tag, pattern, outline); */ @@ -2086,6 +2126,8 @@ void text_drawborder(t_text *x, t_glist *glist, else if (x->te_type == T_MESSAGE) { if (firsttime) + { + /* sys_vgui(".x%lx.c create ppolygon " "%d %d %d %d %d %d %d %d %d %d %d %d %d %d " "-stroke %s -fill $pd_colors(msg) " @@ -2095,16 +2137,32 @@ void text_drawborder(t_text *x, t_glist *glist, x1, y2, x1, y1, (selected ? "$pd_colors(selection)" : "$pd_colors(msg_border)"), tag, tag, (selected ? "selected" : "")); + */ + + // coords are a quick hack to separate gobj's x/y from the polygon's coords + // which of course can be greatly simplified + gui_vmess("gui_message_drawborder", "ssii", + canvas_string(glist_getcanvas(glist)), tag, x2 - x1, y2 - y1); +// x1-x1, y1-y1, x2+4-x1, y1-y1, x2-x1, +// y1+4-y1, x2-x1, y2-4-y1, x2+4-x1, y2-y1, x1-x1, y2-y1, x1-x1, y1-y1); + } else + { sys_vgui(".x%lx.c coords %sR " "%d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", glist_getcanvas(glist), tag, x1, y1, x2+4, y1, x2, y1+4, x2, y2-4, x2+4, y2, x1, y2, x1, y1); + gui_vmess("gui_message_redraw_border", "ssiiiiiiiiiiiiii", + canvas_string(glist_getcanvas(glist)), tag, + x1-x1, y1-y1, x2+4-x1, y1-y1, x2-x1, y1+4-y1, x2-x1, y2-4-y1, x2+4-x1, y2-y1, + x1-x1, y2-y1, x1-x1, y1-y1); + } } else if (x->te_type == T_ATOM) { if (firsttime) + { sys_vgui(".x%lx.c create ppolygon " "%d %d %d %d %d %d %d %d %d %d %d %d " "-stroke %s " @@ -2114,11 +2172,19 @@ void text_drawborder(t_text *x, t_glist *glist, x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1, (selected ? "$pd_colors(selection)" : "$pd_colors(atom_box_border)"), tag, tag, (selected ? "selected" : "")); + + gui_vmess("gui_atom_drawborder", "ssiiiiiiiiiiii", + canvas_string(glist_getcanvas(glist)), tag, + x1-x1, y1-y1, x2-4-x1, y1-y1, x2-x1, + y1+4-y1, x2-x1, y2-y1, x1-x1, y2-y1, x1-x1, y1-y1); + } else + { sys_vgui(".x%lx.c coords %sR " "%d %d %d %d %d %d %d %d %d %d %d %d\n", glist_getcanvas(glist), tag, x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1); + } } /* for comments, just draw a dotted rectangle unlocked; when a visible canvas is unlocked we have to call this anew on all comments, and when @@ -2274,6 +2340,13 @@ void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag) glist_getcanvas(glist), tag, i); } +// erase the whole gobj in the gui one go +void text_erase_gobj(t_text *x, t_glist *glist, char *tag) +{ + if (x->te_type == T_TEXT && !glist->gl_edit) return; + gui_vmess("gui_gobj_erase", "ss", canvas_string(glist_getcanvas(glist)), tag); +} + void text_eraseborder(t_text *x, t_glist *glist, char *tag) { if (x->te_type == T_TEXT && !glist->gl_edit) return; diff --git a/pd/src/g_toggle.c b/pd/src/g_toggle.c index bb8b3beb1fb86be9ec568f31f85befcaf943f48b..f91af52f49af9f933b6b38841cb1d7b07eb6d1c1 100644 --- a/pd/src/g_toggle.c +++ b/pd/src/g_toggle.c @@ -30,6 +30,10 @@ void toggle_draw_update(t_gobj *xgobj, t_glist *glist) (x->x_on!=0.0)?x->x_gui.x_fcol:x->x_gui.x_bcol); sys_vgui(".x%lx.c itemconfigure %lxX2 -stroke #%6.6x\n", canvas, x, (x->x_on!=0.0)?x->x_gui.x_fcol:x->x_gui.x_bcol); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_toggle_update", "ssi", canvas_string(canvas), + tagbuf, x->x_on != 0.0); } x->x_gui.x_changed = 0; } @@ -37,12 +41,15 @@ void toggle_draw_update(t_gobj *xgobj, t_glist *glist) void toggle_draw_new(t_toggle *x, t_glist *glist) { + char tagbuf[MAXPDSTRING], colorbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); t_canvas *canvas=glist_getcanvas(glist); int w=(x->x_gui.x_w+29)/30; int x1=text_xpix(&x->x_gui.x_obj, glist); int y1=text_ypix(&x->x_gui.x_obj, glist); int x2=x1+x->x_gui.x_w, y2=y1+x->x_gui.x_h; int col = (x->x_on!=0.0)?x->x_gui.x_fcol:x->x_gui.x_bcol; + sprintf(colorbuf, "#%6.6x", x->x_gui.x_fcol); iemgui_base_draw_new(&x->x_gui); sys_vgui(".x%lx.c create polyline %d %d %d %d -strokewidth %d " @@ -51,6 +58,10 @@ void toggle_draw_new(t_toggle *x, t_glist *glist) sys_vgui(".x%lx.c create polyline %d %d %d %d -strokewidth %d " "-stroke #%6.6x -tags {%lxX2 x%lx text iemgui}\n", canvas, x1+w+1, y2-w-1, x2-w-1, y1+w+1, w, col, x, x); + gui_vmess("gui_create_toggle", "sssiiiiiiiiiii", canvas_string(canvas), tagbuf, + colorbuf, w, + x1+w+1, y1+w+1, x2-w-1, y2-w-1, + x1+w+1, y2-w-1, x2-w-1, y1+w+1, x1, y1); } void toggle_draw_move(t_toggle *x, t_glist *glist) diff --git a/pd/src/g_traversal.c b/pd/src/g_traversal.c index 49488dd169d8074a249aa7fbacf32935014769d8..4a29f7416c66dabc1005dc5bc130c5a35ab6b6ca 100644 --- a/pd/src/g_traversal.c +++ b/pd/src/g_traversal.c @@ -582,6 +582,8 @@ static void set_set(t_set *x, t_symbol *templatesym, t_symbol *field) } } +static void scalar_configure(t_scalar *x, t_glist *owner); + static void set_bang(t_set *x) { int nitems = x->x_nin, i; @@ -618,7 +620,7 @@ static void set_bang(t_set *x) else for (i = 0, vp = x->x_variables; i < nitems; i++, vp++) template_setfloat(template, vp->gv_sym, vec, vp->gv_w.w_float, 1); if (gs->gs_which == GP_GLIST) - scalar_redraw((t_scalar *)(gp->gp_un.gp_gobj), gs->gs_un.gs_glist); + scalar_configure((t_scalar *)(gp->gp_un.gp_gobj), gs->gs_un.gs_glist); else { t_array *owner_array = gs->gs_un.gs_array; diff --git a/pd/src/g_vumeter.c b/pd/src/g_vumeter.c index fd42b1e0b493b704762ad94387a2033ef6f966b8..d86fbc31f140072b306645694449407c4d1799e4 100644 --- a/pd/src/g_vumeter.c +++ b/pd/src/g_vumeter.c @@ -71,11 +71,18 @@ static void vu_update_rms(t_vu *x, t_glist *glist) { int w4 = x->x_gui.x_w / 4, off=text_ypix(&x->x_gui.x_obj, glist) - 1; int x1 = text_xpix(&x->x_gui.x_obj, glist), + y1 = text_ypix(&x->x_gui.x_obj, glist), quad1 = x1 + w4 + 1, quad3 = x1 + x->x_gui.x_w-w4 - 1; sys_vgui(".x%lx.c coords %lxRCOVER %d %d %d %d\n", glist_getcanvas(glist), x, quad1 + 1, off + 2, quad3 + 1, off + (x->x_led_size + 1) * (IEM_VU_STEPS - x->x_rms) + 2); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + gui_vmess("gui_vumeter_update_rms", "ssiiiiii", + canvas_string(glist_getcanvas(glist)), + tagbuf, quad1 + 1, off + 2, quad3 + 1, off + (x->x_led_size + 1) * + (IEM_VU_STEPS - x->x_rms) + 2, x1, y1); } } @@ -96,6 +103,12 @@ static void vu_update_peak(t_vu *x, t_glist *glist) sys_vgui(".x%lx.c coords %lxPLED %d %d %d %d\n", canvas, x, x1 + 1, j + 2, x1 + x->x_gui.x_w + 2, j + 2); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", iemgui_color_hex[i]); + gui_vmess("gui_vumeter_update_peak", "sssiiiiii", canvas_string(canvas), + tagbuf, colorbuf, x1 + 1, j + 2, x1 + x->x_gui.x_w + 2, j + 2, x1, y1); sys_vgui(".x%lx.c itemconfigure %lxPLED -stroke #%6.6x\n", canvas, x, iemgui_color_hex[i]); } @@ -141,28 +154,56 @@ static void vu_draw_new(t_vu *x, t_glist *glist) { yyy = k4 + k1 * (k2-i); if((i&3)==1 && (x->x_scale)) + { sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w " "-font %s -fill #%6.6x " "-tags {%lxSCALEN %lxSCALE%d x%lx text iemgui}\n", canvas, end+1, yyy+k3+2, iemgui_vu_scale_str[i/4], iemgui_font(&x->x_gui), x->x_gui.x_lcol, x, x, i, x); - + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", x->x_gui.x_lcol); + // not handling font size yet + gui_vmess("gui_create_vumeter_text", "sssiisiii", canvas_string(canvas), + tagbuf, colorbuf, end+1, yyy+k3+2, iemgui_vu_scale_str[i/4], + i, x1, y1); + } led_col = iemgui_vu_col[i]; - if (i<=IEM_VU_STEPS) sys_vgui(".x%lx.c create polyline %d %d %d %d " + if (i<=IEM_VU_STEPS) + { + sys_vgui(".x%lx.c create polyline %d %d %d %d " "-strokewidth %d -stroke #%6.6x " "-tags {%lxRLED%d x%lx text iemgui}\n", canvas, quad1+1, yyy+2, quad3, yyy+2, x->x_led_size, iemgui_color_hex[led_col], x, i, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", iemgui_color_hex[led_col]); + gui_vmess("gui_create_vumeter_steps", "sssiiiiiiii", + canvas_string(canvas), tagbuf, colorbuf, quad1+1, + yyy+2, quad3, yyy+2, x->x_led_size, index, x1, y1); + } } sys_vgui(".x%lx.c create prect %d %d %d %d -fill #%6.6x " "-stroke #%6.6x -tags {%lxRCOVER x%lx text iemgui}\n", canvas, quad1+1, y1+1, quad3, y1+1 + k1*IEM_VU_STEPS, x->x_gui.x_bcol, x->x_gui.x_bcol, x, x); + char tagbuf[MAXPDSTRING]; + sprintf(tagbuf, "x%lx", (long unsigned int)x); + char colorbuf[MAXPDSTRING]; + sprintf(colorbuf, "#%6.6x", x->x_gui.x_bcol); + gui_vmess("gui_create_vumeter_rect", "sssiiiiii", canvas_string(canvas), + tagbuf, colorbuf, quad1+1, y1+1, quad3, y1+1 + k1*IEM_VU_STEPS, x1, y1); sys_vgui(".x%lx.c create polyline %d %d %d %d " "-strokewidth %d -fill #%6.6x " "-tags {%lxPLED x%lx text iemgui}\n", canvas, mid+1, y1+12, mid+1, y1+12, x->x_led_size, x->x_gui.x_bcol, x, x); + sprintf(colorbuf, "#%6.6x", x->x_gui.x_bcol); + gui_vmess("gui_create_vumeter_peak", "sssiiiiiii", canvas_string(canvas), + tagbuf, colorbuf, mid+1, y1+12, mid+1, y1+12, x->x_led_size, x1, y1); x->x_updaterms = x->x_updatepeak = 1; sys_queuegui(x, x->x_gui.x_glist, vu_draw_update); } diff --git a/pd/src/m_pd.h b/pd/src/m_pd.h index d36eee4e08578466b17b73495a0a1f5efa136ec4..1d939d6c49dc3ee28cc8ea6d435f8df0328ecb49 100644 --- a/pd/src/m_pd.h +++ b/pd/src/m_pd.h @@ -667,6 +667,15 @@ EXTERN void sys_vvguid(const char *file, int line, const char *fmt, va_list); EXTERN void sys_gui(const char *s); #define sys_vgui(args...) sys_vguid(__FILE__,__LINE__,args) #define sys_gui(s) sys_vguid(__FILE__,__LINE__,"%s",s) +EXTERN void gui_vmess(const char *sel, char *fmt, ...); +/* some more gui interfaces for building incremental messages */ +EXTERN void gui_start_vmess(const char *sel, char *fmt, ...); +EXTERN void gui_start_array(void); +EXTERN void gui_float_elem(t_float f); +EXTERN void gui_int_elem(int i); +EXTERN void gui_string_elem(const char *s); +EXTERN void gui_end_array(void); +EXTERN void gui_end_vmess(void); EXTERN void sys_pretendguibytes(int n); EXTERN void sys_queuegui(void *client, t_glist *glist, t_guicallbackfn f); diff --git a/pd/src/s_audio.c b/pd/src/s_audio.c index 1d658800025f4d158c6c16ad1423cc4cc128ec54..33586c2b20c6229d1f743124678c8f697c0a7783 100644 --- a/pd/src/s_audio.c +++ b/pd/src/s_audio.c @@ -501,7 +501,7 @@ void sys_reopen_audio( void) sys_audioapiopened = sys_audioapi; audio_callback_is_open = callback; } - sys_vgui("set pd_whichapi %d\n", (outcome == 0 ? sys_audioapi : 0)); + gui_vmess("set_audioapi", "i", (outcome == 0 ? sys_audioapi : 0)); } int sys_send_dacs(void) diff --git a/pd/src/s_inter.c b/pd/src/s_inter.c index 78f115ee842ad9ebc4b3fa479689c912126bb5e6..2ae0a991218d0a63f220c1a6a35dee4ca7e0de13 100644 --- a/pd/src/s_inter.c +++ b/pd/src/s_inter.c @@ -752,6 +752,124 @@ void sys_gui(const char *s) sys_vgui("%s", s); } +char *escape_double_quotes(const char *src) { + static char ret[MAXPDSTRING*2+1]; + char *escaped = ret; + int i, len = MAXPDSTRING*2; + for (i = 0; i < len-1 && src[i] != 0; i++) + { + if (src[i] == '\"') + *(escaped++) = '\\'; + *(escaped++) = src[i]; + } + *escaped = '\0'; + if (i >= len) fprintf(stderr, "oops, you caught me statically allocating a string " + "in a lazy attempt to escape double-quotes for the gui. " + "Please call me out publicly for this regression, and/or revise this " + "so it doesn't arbitrarily limit the size of the strings " + "we can send to the gui."); + return ret; +} + +/* quick hack to send a parameter list for use as a function call in + Node-Webkit */ +void gui_do_vmess(const char *sel, char *fmt, int end, va_list ap) +{ + //va_list ap; + int nargs = 0; + char *fp = fmt; + + //va_start(ap, end); + sys_vgui("nn %s ", sel); + while (*fp) + { + // stop-gap-- increase to 20 until we find a way to pass a list or array + if (nargs >= 20) + { + error("sys_gui_vmess: only 10 named parameters allowed"); + break; + } + if (nargs > 0) sys_gui(","); + switch(*fp++) + { + case 'f': sys_vgui("%g", va_arg(ap, double)); break; + case 's': sys_vgui("\"%s\"", escape_double_quotes(va_arg(ap, const char *))); break; + case 'i': sys_vgui("%d", va_arg(ap, t_int)); break; + //case 'p': SETPOINTER(at, va_arg(ap, t_gpointer *)); break; + default: goto done; + } + nargs++; + } +done: + va_end(ap); + if (end) + sys_gui(";\n"); +} + +void gui_vmess(const char *sel, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + gui_do_vmess(sel, fmt, 1, ap); +} + +void gui_start_vmess(const char *sel, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + gui_do_vmess(sel, fmt, 0, ap); +} + +static int gui_array_head; +void gui_start_array(void) +{ + gui_array_head = 1; + sys_gui(",["); +} + +void gui_float_elem(t_float f) +{ + if (gui_array_head) + { + gui_array_head = 0; + sys_vgui("%g", f); + } + else + sys_vgui(",%g", f); +} + +void gui_int_elem(int i) +{ + if (gui_array_head) + { + gui_array_head = 0; + sys_vgui("%d", i); + } + else + sys_vgui(",%d", i); +} + +void gui_string_elem(const char *s) +{ + if (gui_array_head) + { + gui_array_head = 0; + sys_vgui("\"%s\"", escape_double_quotes(s)); + } + else + sys_vgui(",\"%s\"", escape_double_quotes(s)); +} + +void gui_end_array(void) +{ + sys_gui("]"); +} + +void gui_end_vmess(void) +{ + sys_gui(";\n"); +} + int sys_flushtogui( void) { int writesize = sys_guibufhead - sys_guibuftail, nwrote = 0; @@ -805,6 +923,7 @@ static int sys_flushqueue(void ) if (sys_bytessincelastping >= GUI_BYTESPERPING) { sys_gui("pdtk_ping\n"); + gui_vmess("gui_ping", ""); sys_bytessincelastping = 0; sys_waitingforping = 1; return (1); @@ -1145,6 +1264,16 @@ int sys_startgui(const char *guidir) "TCL_LIBRARY=\"%s/tcl/library\" TK_LIBRARY=\"%s/tk/library\" \ \"%s/pd-gui\" %d localhost %s\n", sys_libdir->s_name, sys_libdir->s_name, guidir, portno, (sys_k12_mode ? "pd-l2ork-k12" : "pd-l2ork")); + +/* SUPERHACK - let's just load node-webkit and see what happens */ + sprintf(cmdbuf, + "/home/nu/Downloads/nwjs-v0.12.0-alpha2-linux-ia32/nw " +// "/home/user/Downloads/node-webkit-v0.11.6-linux-ia32/nw " +// "/home/user/Downloads/atom/atom/atom " + "/home/nu/Downloads/test/ %d localhost %s\n", + portno, + (sys_k12_mode ? "pd-l2ork-k12" : "pd-l2ork")); + #endif sys_guicmd = cmdbuf; } @@ -1179,6 +1308,9 @@ int sys_startgui(const char *guidir) } } #endif + + fprintf(stderr, "fuck %s", sys_guicmd); + execl("/bin/sh", "sh", "-c", sys_guicmd, (char*)0); perror("pd: exec"); _exit(1); @@ -1332,12 +1464,19 @@ int sys_startgui(const char *guidir) /* here is where we start the pinging. */ #if defined(__linux__) || defined(IRIX) if (sys_hipriority) - sys_gui("pdtk_watchdog\n"); + gui_vmess("gui_watchdog", ""); #endif sys_get_audio_apis(buf); sys_get_midi_apis(buf2); - sys_vgui("pdtk_pd_startup {%s} %s %s {%s} %s\n", pd_version, buf, buf2, - sys_font, sys_fontweight); +// sys_vgui("pdtk_pd_startup {%s} %s %s {%s} %s\n", pd_version, buf, buf2, +// sys_font, sys_fontweight); + + gui_vmess("gui_startup", "sssss", + pd_version, + buf, + buf2, + sys_font, + sys_fontweight); } return (0); @@ -1387,7 +1526,8 @@ void glob_quit(void *dummy) canvas_suspend_dsp(); do_not_redraw = 1; glob_closeall(0, 1); - sys_vgui("exit\n"); + //sys_vgui("exit\n"); + gui_vmess("app_quit", ""); if (!sys_nogui) { sys_closesocket(sys_guisock); diff --git a/pd/src/s_main.c b/pd/src/s_main.c index 1949d76b1d0db431c0b8165dfbd07bb5e9205d06..1336b0a01994f3553253a865d312f28bf7aa22b8 100644 --- a/pd/src/s_main.c +++ b/pd/src/s_main.c @@ -309,36 +309,38 @@ int sys_main(int argc, char **argv) // let's create one continuous string from all files int length = 0; t_namelist *nl; - for (nl = sys_openlist; nl; nl = nl->nl_next) - { +// for (nl = sys_openlist; nl; nl = nl->nl_next) +// { // for starting and ending quotes plus a space or null terminating // character, we add 3 additional characters per entry - length = length + strlen(nl->nl_string) + 3; - } - if(length && (filenames = (char*) calloc(length, sizeof(char*)) ) != NULL) +// length = length + strlen(nl->nl_string) + 3; +// } +// if(length && (filenames = (char*) calloc(length, sizeof(char*)) ) != NULL) + if (1) { - strcat(filenames,"\""); +// strcat(filenames,"\\\""); if (sys_openlist) { for (nl = sys_openlist; nl; nl = nl->nl_next) { - strcat(filenames,nl->nl_string); - if (nl->nl_next) - strcat(filenames,"\" \""); - else strcat(filenames,"\"\0"); // ensures proper termination + gui_vmess("gui_build_filelist", "s", nl->nl_string); +// strcat(filenames,nl->nl_string); +// if (nl->nl_next) +// strcat(filenames,"\\\" \\\""); +// else strcat(filenames,"\\\"\\\0"); // ensures proper termination } } //fprintf(stderr,"final list: <%s> <%c> %d\n", filenames, filenames[0], length); } else { - error("filelist malloc failed!\n"); - return(1); +// error("filelist malloc failed!\n"); +// return(1); } } - sys_vgui("pdtk_check_unique %d {%s}\n", sys_unique, - (filenames ? filenames : "0")); - if (filenames != NULL) free(filenames); + gui_vmess("gui_check_unique", "i", sys_unique); +// (filenames ? filenames : "0")); +// if (filenames != NULL) free(filenames); if (sys_externalschedlib) return (sys_run_scheduler(sys_externalschedlibname, sys_extraflagsstring)); diff --git a/pd/src/s_midi.c b/pd/src/s_midi.c index c850097c264e7354180dc7ace12db93dbca9f686..e9e6ac0bda46c3a3fbfac69182243fbbf57386f4 100644 --- a/pd/src/s_midi.c +++ b/pd/src/s_midi.c @@ -565,7 +565,7 @@ void sys_open_midi(int nmidiindev, int *midiindev, sys_save_midi_params(nmidiindev, midiindev, nmidioutdev, midioutdev); - sys_vgui("set pd_whichmidiapi %d\n", sys_midiapi); + gui_vmess("set_midiapi", "i", sys_midiapi); } diff --git a/pd/src/s_print.c b/pd/src/s_print.c index 8df706ae0bd6c5e472361de99efe1c17303f3bd2..620711a5198d1459d398577af34c506f14d3f284 100644 --- a/pd/src/s_print.c +++ b/pd/src/s_print.c @@ -65,6 +65,10 @@ static void doerror(const void *object, const char *s) sys_vgui("pdtk_posterror {%s} 1 {%s}\n", strnpointerid(obuf, object, MAXPDSTRING), strnescape(upbuf, s, MAXPDSTRING)); + gui_vmess("gui_post_error", "sis", + strnpointerid(obuf, object, MAXPDSTRING), + 1, + strnescape(upbuf, s, MAXPDSTRING)); } } @@ -118,7 +122,8 @@ static void dopost(const char *s) //if (ptout && upbuf[ptout-1] == '\n') // upbuf[--ptout] = 0, heldcr = 1; upbuf[ptout] = 0; - sys_vgui("pdtk_post {%s}\n", upbuf); +// sys_vgui("pdtk_post {%s}\n", upbuf); + gui_vmess("gui_post", "s", upbuf); } }