From 3fb7aab2084285727b6f6c6c243a8e2b849c1892 Mon Sep 17 00:00:00 2001 From: user <user@user-ThinkPad-X60.(none)> Date: Sat, 16 May 2015 01:18:37 -0400 Subject: [PATCH] first stab at doing text editing completely in html --- pd/nw/pd_canvas.html | 345 +++++++++++++++++++++++++------------------ pd/nw/pdgui.js | 26 ++++ pd/nw/todo.txt | 10 +- pd/src/g_rtext.c | 18 ++- pd/src/g_text.c | 6 +- 5 files changed, 254 insertions(+), 151 deletions(-) diff --git a/pd/nw/pd_canvas.html b/pd/nw/pd_canvas.html index 4f739817e..80ab73882 100644 --- a/pd/nw/pd_canvas.html +++ b/pd/nw/pd_canvas.html @@ -34,19 +34,6 @@ var last_keydown = ""; - // This gets called from the nw_create_window function in index.html - // It provides us with our canvas id from the C side. Once we have it - // we can create the menu and register event callbacks - function register_canvas_id(cid) { -console.log("fuck you"); - create_popup_menu(cid); - add_events(cid); - nw_create_patch_window_menus(cid); - pdgui.canvas_map(cid); - } - - - // This could probably be in pdgui.js function add_keymods(key, evt) { var shift = evt.shiftKey ? "Shift" : ""; @@ -54,46 +41,141 @@ function add_keymods(key, evt) { return shift + ctrl + key; } -function create_popup_menu(name) { - // The right-click popup menu - var popup_menu = new nw.Menu(); - pdgui.add_popup(name, popup_menu); - - popup_menu.append(new nw.MenuItem({ - label: 'Properties', - click: function() { - pdgui.popup_action(name, 0); - } - })); - popup_menu.append(new nw.MenuItem({ - label: 'Open', - click: function() { - pdgui.popup_action(name, 1); - } - })); - popup_menu.append(new nw.MenuItem({ - label: 'Help', - click: function() { - pdgui.popup_action(name, 2); +var canvas_events = (function() { + var name, + 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; + }, + mousedown = function(evt) { + // 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(); + }, + mouseup = 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)); + evt.stopPropagation(); + evt.preventDefault(); + }, + keydown = function(evt) { + var key_code = evt.keyCode; + var hack = null; // hack for unprintable ascii codes + switch(key_code) { + case 8: + case 9: + case 10: + case 27: + //case 32: + case 127: hack = key_code; break; + case 37: hack = add_keymods('Left', evt); break; + case 38: hack = add_keymods('Up', evt); break; + case 39: hack = add_keymods('Right', evt); break; + case 40: hack = add_keymods('Down', evt); break; + case 33: hack = add_keymods('Prior', evt); break; + case 34: hack = add_keymods('Next', evt); break; + case 35: hack = add_keymods('End', evt); break; + case 36: hack = add_keymods('Home', evt); break; + + // Need to handle Control key, Alt + + case 16: hack = 'Shift'; break; + case 17: hack = 'Control'; break; + case 18: hack = 'Alt'; break; + } + if (hack !== null) { + pdgui.gui_canvas_sendkey(name, 1, evt, hack); + pdgui.set_keymap(key_code, hack); + } + pdgui.gui_post("keydown time: keycode is " + evt.keyCode); + last_keydown = evt.keyCode; + //evt.stopPropagation(); + //evt.preventDefault(); + }, + keypress = function(evt) { + pdgui.gui_canvas_sendkey(name, 1, evt, evt.charCode); + pdgui.set_keymap(last_keydown, evt.charCode); + pdgui.gui_post("keypress time: charcode is " + evt.charCode); + // Don't do things like scrolling on space, arrow keys, etc. + //evt.stopPropagation(); + evt.preventDefault(); + }, + keyup = function(evt) { + var my_char_code = pdgui.get_char_code(evt.keyCode); + pdgui.gui_canvas_sendkey(name, 0, evt, my_char_code); + pdgui.gui_post("keyup time: charcode is: " + my_char_code); + evt.stopPropagation(); + evt.preventDefault(); + }, + text_mousemove = function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + text_mousedown = function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + text_mouseup = function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + text_keydown = function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + text_keyup = function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + return false; + }, + text_keypress = function(evt) { + evt.stopPropagation(); + //evt.preventDefault(); + return false; } - })); -} - -function add_events(name) { - 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); + ; + // Dialog events + 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.querySelector("#openpanel_dialog").addEventListener("change", function(evt) { var file_string = this.value; @@ -103,7 +185,6 @@ function add_events(name) { console.log("tried to openpanel something"); }, false ); - document.querySelector("#savepanel_dialog").addEventListener("change", function(evt) { var file_string = this.value; @@ -115,106 +196,89 @@ function add_events(name) { ); - 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; - }); - - 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); + // closing the Window + // this isn't actually closing the window yet + nw.Window.get().on("close", function() { + pdgui.pdsend(name + " menuclose 0"); }); - // 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)); + return { + normal: function() { + document.removeEventListener("mousemove", text_mousemove, false); + document.removeEventListener("keydown", text_keydown, false); + document.removeEventListener("keypress", text_keypress, false); + document.removeEventListener("keyup", text_keyup, false); + document.removeEventListener("mousedown", text_mousedown, false); + document.removeEventListener("mouseup", text_mouseup, false); + + document.addEventListener("mousemove", mousemove, false); + document.addEventListener("keydown", keydown, false); + document.addEventListener("keypress", keypress, false); + document.addEventListener("keyup", keyup, false); + document.addEventListener("mousedown", mousedown, false); + document.addEventListener("mouseup", mouseup, false); + }, + text: function() { + document.removeEventListener("mousemove", mousemove, false); + document.removeEventListener("keydown", keydown, false); + document.removeEventListener("keypress", keypress, false); + document.removeEventListener("keyup", keyup, false); + document.removeEventListener("mousedown", mousedown, false); + document.removeEventListener("mouseup", mouseup, false); + + document.addEventListener("mousemove", text_mousemove, false); + document.addEventListener("keydown", text_keydown, false); + document.addEventListener("keypress", text_keypress, false); + document.addEventListener("keyup", text_keyup, false); + document.addEventListener("mousedown", text_mousedown, false); + document.addEventListener("mouseup", mouseup, false); + }, + register: function(n) { + name = n; } - 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)); - } + // This gets called from the nw_create_window function in index.html + // It provides us with our canvas id from the C side. Once we have it + // we can create the menu and register event callbacks + function register_canvas_id(cid) { +console.log("fuck you"); + create_popup_menu(cid); + canvas_events.register(cid); + canvas_events.normal(); + nw_create_patch_window_menus(cid); + pdgui.canvas_map(cid); + } - // 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"); - }); +function create_popup_menu(name) { + // The right-click popup menu + var popup_menu = new nw.Menu(); + pdgui.add_popup(name, popup_menu); + popup_menu.append(new nw.MenuItem({ + label: 'Properties', + click: function() { + pdgui.popup_action(name, 0); + } + })); + popup_menu.append(new nw.MenuItem({ + label: 'Open', + click: function() { + pdgui.popup_action(name, 1); + } + })); + popup_menu.append(new nw.MenuItem({ + label: 'Help', + click: function() { + pdgui.popup_action(name, 2); + } + })); } @@ -222,6 +286,7 @@ function add_events(name) { + //nw_create_patch_window_menus(name); function menu_generic () { diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index 460958622..2fd515699 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -3395,3 +3395,29 @@ exports.skin = (function () { } }; }()); + +function gui_textarea(cid, tag, x, y, font_size, state) { + gui_post("x/y is " + x + '/' + y); + if (state === 1) { + var p = patchwin[cid].window.document.createElement('p'); + configure_item(p, { + id: 'new_object_textentry' + }); + p.contentEditable = 'true'; + p.style.setProperty('left', x + 'px'); + p.style.setProperty('top', y + 'px'); + p.style.setProperty('font-size', font_size + 'px'); + p.textContent = "Fuck Butts"; + patchwin[cid].window.document.body.appendChild(p); + p.focus(); + patchwin[cid].window.canvas_events.text(); + /* here we need to make sure that events inside the + <p> don't propogate down to the svg below... */ + } else { + var p = patchwin[cid].window.document.getElementById('new_object_textentry'); + if (p !== null) { + p.parentNode.removeChild(p); + } + patchwin[cid].window.canvas_events.normal(); + } +} diff --git a/pd/nw/todo.txt b/pd/nw/todo.txt index 6e5c2609b..5e7d09edc 100644 --- a/pd/nw/todo.txt +++ b/pd/nw/todo.txt @@ -18,12 +18,12 @@ Node-webkit stuff: 4) (probably) present working directory 5) command line argv -Everything else: (A [*] means we've fixed it) +Everything else: (A [x] means we've fixed it) [ ] 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 doesn't work (see dialog API page) +[x] choosing the same directory multiple times doesn't work (see dialog API page) [ ] "Save As" on an overwrite doesn't seem to clear the dirty flag [ ] figure out why there is a "pd_opendir" global var [ ] pass k12 mode arg @@ -142,10 +142,10 @@ Everything else: (A [*] means we've fixed it) [ ] getting the sense that glist_isselected should _always_ have glist_getcanvas(x) as its first parameter [x] get rid of the old tcl specific sys_get_audio_apis -[ ] have a single function to set t_svg_attr -[ ] change x_x1..y2 to simple x_bbox[4], and change current x_bbox to +[x] have a single function to set t_svg_attr +[ ] t_svg: change x_x1..y2 to simple x_bbox[4], and change current x_bbox to x_cachebbox (or something like that) -[ ] figure out why gatom_retext sends a fill color to GUI +[x] figure out why gatom_retext sends a fill color to GUI [ ] look into changing 'x' format specifier from \"x%.6lx\" to more generic \"%.6lx\". (Not exactly sure what good the "x" does there.) It's only specified in s_inter and in editor_new, so it should be easy to amend diff --git a/pd/src/g_rtext.c b/pd/src/g_rtext.c index d14c840c6..c82c9be14 100644 --- a/pd/src/g_rtext.c +++ b/pd/src/g_rtext.c @@ -532,6 +532,7 @@ void rtext_displace(t_rtext *x, int dx, int dy) /* Not sure if this is still used */ void rtext_select(t_rtext *x, int state) { +post("selected an rtext"); t_glist *glist = x->x_glist; t_canvas *canvas = glist_getcanvas(glist); if (glist_istoplevel(glist)) @@ -551,7 +552,7 @@ void rtext_select(t_rtext *x, int state) void rtext_activate(t_rtext *x, int state) { - //fprintf(stderr,"rtext_activate\n"); + fprintf(stderr,"rtext_activate state=%d\n", state); int w = 0, h = 0, indx; t_glist *glist = x->x_glist; t_canvas *canvas = glist_getcanvas(glist); @@ -562,7 +563,7 @@ void rtext_activate(t_rtext *x, int state) //if (state == x->x_active) return; // avoid excess calls if (state) { - sys_vgui(".x%lx.c focus %s\n", canvas, x->x_tag); + //sys_vgui(".x%lx.c focus %s\n", canvas, x->x_tag); glist->gl_editor->e_textedfor = x; glist->gl_editor->e_textdirty = 0; x->x_dragfrom = x->x_selstart = 0; @@ -571,13 +572,22 @@ void rtext_activate(t_rtext *x, int state) } else { - sys_vgui("selection clear .x%lx.c\n", canvas); - sys_vgui(".x%lx.c focus \"\"\n", canvas); + //sys_vgui("selection clear .x%lx.c\n", canvas); + //sys_vgui(".x%lx.c focus \"\"\n", canvas); if (glist->gl_editor->e_textedfor == x) glist->gl_editor->e_textedfor = 0; x->x_active = 0; } + /* so I guess the following would need to be commented out + if we want to use the textarea junk to feed to Pd... */ rtext_senditup(x, SEND_UPDATE, &w, &h, &indx); + gui_vmess("gui_textarea", "xsiiii", + canvas, + x->x_tag, + x->x_text->te_xpix, + x->x_text->te_ypix, + sys_hostfontsize(glist_getfont(glist)), + state); } // outputs 1 if found one of the special chars diff --git a/pd/src/g_text.c b/pd/src/g_text.c index df0898f9b..05de05aa4 100644 --- a/pd/src/g_text.c +++ b/pd/src/g_text.c @@ -355,7 +355,9 @@ void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv) int connectme, xpix, ypix, indx, nobj; canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj); pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1); - canvas_objtext(gl, xpix, ypix, 0, 1, b); + canvas_objtext(gl, + connectme ? xpix : xpix - 8, + connectme ? ypix : ypix - 8, 0, 1, b); if (connectme == 1) { //fprintf(stderr,"canvas_obj calls canvas_connect\n"); @@ -366,7 +368,7 @@ void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv) else if (connectme == 0) { //fprintf(stderr,"canvas_obj calls canvas_startmotion\n"); - canvas_displaceselection(glist_getcanvas(gl), -8, -8); +// canvas_displaceselection(glist_getcanvas(gl), -8, -8); canvas_startmotion(glist_getcanvas(gl)); } //canvas_setundo(glist_getcanvas(gl), -- GitLab