Commit ce48a4ca authored by Jonathan Wilkes's avatar Jonathan Wilkes
Browse files

first try at getting App and "Edit" menu to behave correctly on OSX

parent fc05a951
......@@ -618,12 +618,14 @@ var canvas_events = (function() {
// Copy event
document.addEventListener("copy", function(evt) {
// This event doesn't currently get called because the
// nw menubar receives the event and doesn't propagate
// to the DOM. But if we add the ability to toggle menubar
// display, we might need to rely on this listener.
pdgui.post("copy detected by DOM listener");
pdgui.pdsend(name, "copy");
// On OSX, this event gets triggered when we're editing
// inside an object/message box. So we only forward the
// copy message to Pd if we're in a "normal" canvas state
pdgui.post("copy detected by DOM listener");
if (canvas_events.get_state() === "normal") {
pdgui.pdsend(name, "copy");
}
});
// Listen to paste event using the half-baked Clipboard API from HTML5
......@@ -658,12 +660,19 @@ var canvas_events = (function() {
// user won't get bothered with a prompt at all, and normal Pd
// paste behavior will follow.
// Finally, from a usability standpoint the main drawback is that
// From a usability standpoint the main drawback is that
// you can't try to paste the same Pd source code more than once.
// For users who want to pasting lots of source code this could be
// a frustration, but Pd's normal copy/paste behavior remains
// intuitive and in line with the way other apps tend to work.
// Yet another caveat: we only want to check the external buffer
// and/or send a "paste" event to Pd if the canvas is in a "normal"
// state.
if (canvas_events.get_state() !== "normal") {
return;
}
if (might_be_a_pd_file(clipboard_data) &&
clipboard_data !== pdgui.get_last_clipboard_data()) {
if (permission_to_paste_from_external_clipboard()) {
......@@ -952,13 +961,18 @@ function create_popup_menu(name) {
}
function nw_undo_menu(undo_text, redo_text) {
if (undo_text === "no") {
// Disabling undo/redo menu buttons on OSX will
// turn off any DOM events associated with that
// key command. So we can't disable them here--
// otherwise it would turn off text-editing
// undo/redo.
if (process.platform !== "darwin" && undo_text === "no") {
canvas_menu.edit.undo.enabled = false;
} else {
canvas_menu.edit.undo.enabled = true;
canvas_menu.edit.undo.label = l("menu.undo") + " " + undo_text;
}
if (redo_text === "no") {
if (process.platform !== "darwin" && redo_text === "no") {
canvas_menu.edit.redo.enabled = false;
} else {
canvas_menu.edit.redo.enabled = true;
......@@ -994,11 +1008,16 @@ function instantiate_live_box() {
var canvas_menu = {};
function set_edit_menu_modals(state) {
// OSX needs to keep these enabled, otherwise the events won't trigger
if (process.platform === "darwin") {
state = true;
}
canvas_menu.edit.undo.enabled = state;
canvas_menu.edit.redo.enabled = state;
canvas_menu.edit.cut.enabled = state;
canvas_menu.edit.copy.enabled = state;
canvas_menu.edit.paste.enabled = state;
canvas_menu.edit.selectall.enabled = state;
}
function set_editmode_checkbox(state) {
......@@ -1100,11 +1119,25 @@ function nw_create_patch_window_menus(gui, w, name) {
// Edit menu
minit(m.edit.undo, {
enabled: true,
click: function () { pdgui.pdsend(name, "undo"); }
click: function () {
if (process.platform === "darwin" &&
canvas_events.get_state() === "text") {
document.execCommand("undo", false, null);
} else {
pdgui.pdsend(name, "undo");
}
}
});
minit(m.edit.redo, {
enabled: true,
click: function () { pdgui.pdsend(name, "redo"); }
click: function () {
if (process.platform === "darwin" &&
canvas_events.get_state() === "text") {
document.execCommand("redo", false, null);
} else {
pdgui.pdsend(name, "redo");
}
}
});
minit(m.edit.cut, {
enabled: true,
......
......@@ -36,6 +36,16 @@ function create_menu(gui, type) {
// Window menu
window_menu = new gui.Menu({ type: "menubar" });
// On OSX, we need to start with the built-in mac menu in order to
// get the application menu to show up correctly. Unfortunately, this
// will also spawn a built-in "Edit" and "Window" menu. Even more
// unfortunately, we must use the built-in "Edit" menu-- without it
// there is no way to get <command-v> shortcut to trigger the
// DOM "paste" event.
if (osx) {
window_menu.createMacBuiltin("purr-data");
}
// File menu
file_menu = new gui.Menu();
......@@ -101,46 +111,94 @@ function create_menu(gui, type) {
}));
// Edit menu
edit_menu = new gui.Menu();
// Edit sub-entries
m.edit = {};
if (canvas_menu) {
edit_menu.append(m.edit.undo = new gui.MenuItem({
// For OSX, we have to use the built-in "Edit" menu-- I haven't
// found any other way to get "paste" event to trickle down to
// the DOM. As a consequence, we must fetch the relevant menu
// items that were created above with createMacBuiltin and assign
// them to the relevant variables below
if (osx) {
edit_menu = window_menu.items[1].submenu;
m.edit.undo = window_menu.items[1].submenu.items[0];
// Remove the default Undo, since we can't seem to bind
// a click function to it
window_menu.items[1].submenu.remove(m.edit.undo);
// Now create a new one and insert it at the top
edit_menu.insert(m.edit.undo = new gui.MenuItem({
label: l("menu.undo"),
tooltip: l("menu.undo_tt")
}));
edit_menu.append(m.edit.redo = new gui.MenuItem({
tooltip: l("menu.undo_tt"),
key: "z",
modifiers: cmd_or_ctrl
}), 0);
m.edit.redo = window_menu.items[1].submenu.items[1];
// Remove the default Undo, since we can't seem to bind
// a click function to it
window_menu.items[1].submenu.remove(m.edit.redo);
// Now create a new one and insert it at the top
edit_menu.insert(m.edit.redo = new gui.MenuItem({
label: l("menu.redo"),
tooltip: l("menu.redo_tt")
}));
edit_menu.append(new gui.MenuItem({ type: "separator" }));
edit_menu.append(m.edit.cut = new gui.MenuItem({
label: l("menu.cut"),
key: "x",
tooltip: l("menu.redo_tt"),
key: "z",
modifiers: "shift+" + cmd_or_ctrl
}), 1);
// Note: window_menu.items[1].submenu.items[2] is the separator
m.edit.cut = window_menu.items[1].submenu.items[3];
m.edit.copy = window_menu.items[1].submenu.items[4];
m.edit.paste = window_menu.items[1].submenu.items[5];
// There's no "Delete" item for GNU/Linux or Windows--
// not sure yet what to do with it.
m.edit.delete = window_menu.items[1].submenu.items[6];
m.edit.selectall= window_menu.items[1].submenu.items[7];
} else {
edit_menu = new gui.Menu();
// Edit sub-entries
if (canvas_menu) {
edit_menu.append(m.edit.undo = new gui.MenuItem({
label: l("menu.undo"),
tooltip: l("menu.undo_tt")
}));
edit_menu.append(m.edit.redo = new gui.MenuItem({
label: l("menu.redo"),
tooltip: l("menu.redo_tt")
}));
edit_menu.append(new gui.MenuItem({ type: "separator" }));
edit_menu.append(m.edit.cut = new gui.MenuItem({
label: l("menu.cut"),
key: "x",
modifiers: cmd_or_ctrl,
tooltip: l("menu.cut_tt")
}));
}
edit_menu.append(m.edit.copy = new gui.MenuItem({
label: l("menu.copy"),
key: "c",
modifiers: cmd_or_ctrl,
tooltip: l("menu.cut_tt")
}));
tooltip: l("menu.copy_tt")
}));
if (canvas_menu) {
// The nwjs menubar keybindings don't propagate down
// to the DOM. Here, we need the DOM to receive the
// "paste" event in case we want to paste a Pd file
// from an external buffer. So unfortunately we can't
// do the keybindings here. The side-effect is that
// "Ctrl-V" isn't displayed in the menu item.
edit_menu.append(m.edit.paste = new gui.MenuItem({
label: l("menu.paste"),
//key: "v",
//modifiers: cmd_or_ctrl,
tooltip: l("menu.paste_tt")
}));
}
}
edit_menu.append(m.edit.copy = new gui.MenuItem({
label: l("menu.copy"),
key: "c",
modifiers: cmd_or_ctrl,
tooltip: l("menu.copy_tt")
}));
// We need "duplicate" for canvas_menu and for OSX, where it's not
// part of the builtin Edit menu...
if (canvas_menu) {
// The nwjs menubar keybindings don't propagate down
// to the DOM. Here, we need the DOM to receive the
// "paste" event in case we want to paste a Pd file
// from an external buffer. So unfortunately we can't
// do the keybindings here. The side-effect is that
// "Ctrl-V" isn't displayed in the menu item.
edit_menu.append(m.edit.paste = new gui.MenuItem({
label: l("menu.paste"),
//key: "v",
//modifiers: cmd_or_ctrl,
tooltip: l("menu.paste_tt")
}));
edit_menu.append(m.edit.duplicate = new gui.MenuItem({
label: l("menu.duplicate"),
key: "d",
......@@ -148,12 +206,17 @@ function create_menu(gui, type) {
tooltip: l("menu.duplicate_tt")
}));
}
edit_menu.append(m.edit.selectall = new gui.MenuItem({
label: l("menu.selectall"),
key: "a",
modifiers: cmd_or_ctrl,
tooltip: l("menu.selectall_tt")
}));
// OSX already has "Select All" in the builtin Edit menu...
if (!osx) {
edit_menu.append(m.edit.selectall = new gui.MenuItem({
label: l("menu.selectall"),
key: "a",
modifiers: cmd_or_ctrl,
tooltip: l("menu.selectall_tt")
}));
}
if (canvas_menu) {
// Unfortunately nw.js doesn't allow
// key: "Return" or key: "Enter", so we
......@@ -374,8 +437,12 @@ function create_menu(gui, type) {
// Windows menu... call it "winman" (i.e., window management)
// to avoid confusion
winman_menu = new gui.Menu();
if (osx) {
// on OSX, createMacBuiltin creates a window menu
winman_menu = window_menu.items[2].submenu;
} else {
winman_menu = new gui.Menu();
}
// Win sub-entries
m.win = {};
winman_menu.append(m.win.nextwin = new gui.MenuItem({
......@@ -479,46 +546,61 @@ function create_menu(gui, type) {
}));
// Add submenus to window menu
// On OSX, we need to start with the built-in mac menu in order to
// get the application menu to show up correctly. Unfortunately, this
// will also spawn a built-in "Edit" and "Window" menu. Even more
// unfortunately, we must use the built-in "Edit" menu-- without it
// there is no way to get <command-v> shortcut to trigger the
// DOM "paste" event.
if (osx) {
window_menu.createMacBuiltin("purr-data");
}
window_menu.append(new gui.MenuItem({
label: l("menu.file"),
submenu: file_menu
}));
window_menu.append(new gui.MenuItem({
label: l("menu.edit"),
submenu: edit_menu
}));
window_menu.append(new gui.MenuItem({
label: l("menu.view"),
submenu: view_menu
}));
if (canvas_menu) {
window_menu.insert(new gui.MenuItem({
label: l("menu.file"),
submenu: file_menu
}), 1);
// Edit menu created from mac builtin above
window_menu.insert(new gui.MenuItem({
label: l("menu.view"),
submenu: view_menu
}), 3);
window_menu.insert(new gui.MenuItem({
label: l("menu.put"),
submenu: put_menu
}), 4);
// "Window" menu created from mac builtin above
window_menu.insert(new gui.MenuItem({
label: l("menu.media"),
submenu: media_menu
}), 5);
window_menu.append(new gui.MenuItem({
label: l("menu.help"),
submenu: help_menu
}));
} else {
window_menu.append(new gui.MenuItem({
label: l("menu.file"),
submenu: file_menu
}));
window_menu.append(new gui.MenuItem({
label: l("menu.edit"),
submenu: edit_menu
}));
window_menu.append(new gui.MenuItem({
label: l("menu.put"),
submenu: put_menu
label: l("menu.view"),
submenu: view_menu
}));
if (canvas_menu) {
window_menu.append(new gui.MenuItem({
label: l("menu.put"),
submenu: put_menu
}));
}
window_menu.append(new gui.MenuItem({
label: l("menu.windows"),
submenu: winman_menu
}));
window_menu.append(new gui.MenuItem({
label: l("menu.media"),
submenu: media_menu
}));
window_menu.append(new gui.MenuItem({
label: l("menu.help"),
submenu: help_menu
}));
}
window_menu.append(new gui.MenuItem({
label: l("menu.windows"),
submenu: winman_menu
}));
window_menu.append(new gui.MenuItem({
label: l("menu.media"),
submenu: media_menu
}));
window_menu.append(new gui.MenuItem({
label: l("menu.help"),
submenu: help_menu
}));
// Assign to window
gui.Window.get().menu = window_menu;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment