Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/help/input_event_bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
type EventActionMap,
} from "#src/util/event_action_map.js";
import { emptyToUndefined } from "#src/util/json.js";
import { isMacPlatform } from "#src/util/platform.js";

declare let NEUROGLANCER_BUILD_INFO:
| { tag: string; url?: string; timestamp?: string }
Expand All @@ -51,8 +52,16 @@ export function formatKeyName(name: string) {
}

export function formatKeyStroke(stroke: string) {
const parts = stroke.split("+");
return parts.map(formatKeyName).join("+");
const mac = isMacPlatform();
return stroke
.split("+")
.map((part) => {
if (mac && part === "control") return "⌘";
if (mac && part === "alt") return "⌥";
if (mac && part === "shift") return "⇧";
return formatKeyName(part);
})
.join("+");
}

const DEFAULT_HELP_PANEL_LOCATION: SidePanelLocation = {
Expand Down
5 changes: 3 additions & 2 deletions src/rendered_data_panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { KeyboardEventBinder } from "#src/util/keyboard_bindings.js";
import * as matrix from "#src/util/matrix.js";
import { MouseEventBinder } from "#src/util/mouse_bindings.js";
import { startRelativeMouseDrag } from "#src/util/mouse_drag.js";
import { isMacPlatform } from "#src/util/platform.js";
import type {
TouchPinchInfo,
TouchTranslateInfo,
Expand Down Expand Up @@ -431,8 +432,8 @@ export abstract class RenderedDataPanel extends RenderedPanel {
typeof NEUROGLANCER_SHOW_OBJECT_SELECTION_TOOLTIP !== "undefined" &&
NEUROGLANCER_SHOW_OBJECT_SELECTION_TOOLTIP === true
) {
element.title =
"Double click to toggle display of object under mouse pointer. Control+rightclick to pin/unpin selection.";
const modifierKeyLabel = isMacPlatform() ? "Cmd" : "Control";
element.title = `Double click to toggle display of object under mouse pointer. ${modifierKeyLabel}+rightclick to pin/unpin selection.`;
}

this.registerDisposer(new AutomaticallyFocusedElement(element));
Expand Down
5 changes: 4 additions & 1 deletion src/segmentation_display_state/frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import { measureElementClone } from "#src/util/dom.js";
import type { vec3 } from "#src/util/geom.js";
import { kOneVec, vec4 } from "#src/util/geom.js";
import { parseUint64 } from "#src/util/json.js";
import { isMacPlatform } from "#src/util/platform.js";
import { NullarySignal } from "#src/util/signal.js";
import { withSharedVisibility } from "#src/visibility_priority/frontend.js";
import { makeCopyButton } from "#src/widget/copy_button.js";
Expand Down Expand Up @@ -303,8 +304,10 @@ export function bindSegmentListWidth(
const segmentWidgetTemplate = (() => {
const template = document.createElement("div");
template.classList.add("neuroglancer-segment-list-entry");
const colorModifierLabel = isMacPlatform() ? "option" : "alt";
template.title =
"Right click to move to segment, alt+click to set color, alt+shift+click to unset color";
`Right click to move to segment, ${colorModifierLabel}+click to set color, ` +
`${colorModifierLabel}+shift+click to unset color`;
const stickyContainer = document.createElement("div");
stickyContainer.classList.add("neuroglancer-segment-list-entry-sticky");
template.appendChild(stickyContainer);
Expand Down
6 changes: 4 additions & 2 deletions src/ui/layer_bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
import { RefCounted } from "#src/util/disposable.js";
import { removeFromParent } from "#src/util/dom.js";
import { preventDrag } from "#src/util/drag_and_drop.js";
import { isMacPlatform } from "#src/util/platform.js";
import { makeCloseButton } from "#src/widget/close_button.js";
import { makeDeleteButton } from "#src/widget/delete_button.js";
import { makeIcon } from "#src/widget/icon.js";
Expand Down Expand Up @@ -331,8 +332,9 @@ export class LayerBar extends RefCounted {

const addButton = makeIcon({
svg: svg_plus,
title:
"Click to add layer, control+click/right click/⌘+click to add local annotation layer.",
title: `Click to add layer, ${
isMacPlatform() ? "⌘+click" : "control+click"
}/right click to add local annotation layer.`,
});
addButton.classList.add("neuroglancer-layer-add-button");

Expand Down
7 changes: 4 additions & 3 deletions src/ui/selection_details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { SidePanel } from "#src/ui/side_panel.js";
import { setClipboard } from "#src/util/clipboard.js";
import type { Borrowed } from "#src/util/disposable.js";
import { MouseEventBinder } from "#src/util/mouse_bindings.js";
import { isMacPlatform } from "#src/util/platform.js";
import { CheckboxIcon } from "#src/widget/checkbox_icon.js";
import { makeCopyButton } from "#src/widget/copy_button.js";
import { DependentViewWidget } from "#src/widget/dependent_view_widget.js";
Expand Down Expand Up @@ -72,15 +73,15 @@ export class SelectionDetailsPanel extends SidePanel {
});
titleBar.appendChild(backButton);
titleBar.appendChild(forwardButton);
const modifierKeyLabel = isMacPlatform() ? "cmd" : "ctrl";
titleBar.appendChild(
this.registerDisposer(
new CheckboxIcon(state.pin, {
// Note: \ufe0e forces text display, as otherwise the pin icon may as an emoji with
// color.
text: "📌\ufe0e",
enableTitle: "Pin selection\nctrl+rightclick to select and pin",
disableTitle:
"Unpin selection\nctrl+shift+rightclick to select on hover",
enableTitle: `Pin selection\n${modifierKeyLabel}+rightclick to select and pin`,
disableTitle: `Unpin selection\n${modifierKeyLabel}+shift+rightclick to select on hover`,
}),
).element,
);
Expand Down
2 changes: 1 addition & 1 deletion src/ui/tool_palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1274,7 +1274,7 @@ export class MultiToolPaletteDropdownButton extends RefCounted {
const checkbox = this.registerDisposer(
new CheckboxIcon(this.dropdownVisible, {
svg: svg_tool,
enableTitle: "Show tool palette list (control+click to create new)",
enableTitle: "Show tool palette list",
disableTitle: "Hide tool palette list",
backgroundScheme: "dark",
}),
Expand Down
78 changes: 77 additions & 1 deletion src/util/drag_and_drop.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
* limitations under the License.
*/

import { describe, it, expect } from "vitest";
import { afterEach, describe, it, expect, vi } from "vitest";
import {
encodeParametersAsDragType,
decodeParametersFromDragType,
getDropEffectFromModifiers,
} from "#src/util/drag_and_drop.js";

describe("drag_and_drop", () => {
Expand All @@ -31,3 +32,78 @@ describe("drag_and_drop", () => {
expect(result).toEqual(json);
});
});

describe("getDropEffectFromModifiers", () => {
afterEach(() => {
vi.unstubAllGlobals();
});

function makeDragEvent(
modifiers: Partial<
Pick<DragEvent, "shiftKey" | "ctrlKey" | "metaKey" | "altKey">
>,
) {
return {
shiftKey: false,
ctrlKey: false,
metaKey: false,
altKey: false,
...modifiers,
} as DragEvent;
}

it("uses Ctrl as the move modifier off Mac", () => {
vi.stubGlobal("navigator", { platform: "Win32" });
const { dropEffect } = getDropEffectFromModifiers(
makeDragEvent({ ctrlKey: true }),
"link",
true,
);
expect(dropEffect).toBe("move");
});

it("uses Cmd as the move modifier on Mac", () => {
vi.stubGlobal("navigator", { platform: "MacIntel" });
const { dropEffect } = getDropEffectFromModifiers(
makeDragEvent({ metaKey: true }),
"link",
true,
);
expect(dropEffect).toBe("move");
});

it("ignores Ctrl on Mac, where it is the secondary-click gesture", () => {
vi.stubGlobal("navigator", { platform: "MacIntel" });
const { dropEffect } = getDropEffectFromModifiers(
makeDragEvent({ ctrlKey: true }),
"link",
true,
);
expect(dropEffect).toBe("link");
});

it("names the move modifier per platform in the message", () => {
vi.stubGlobal("navigator", { platform: "Win32" });
expect(
getDropEffectFromModifiers(makeDragEvent({}), "link", true)
.dropEffectMessage,
).toContain("hold CONTROL to move");
vi.stubGlobal("navigator", { platform: "MacIntel" });
expect(
getDropEffectFromModifiers(makeDragEvent({}), "link", true)
.dropEffectMessage,
).toContain("hold COMMAND to move");
});

it("uses Shift to copy on both platforms", () => {
for (const platform of ["Win32", "MacIntel"]) {
vi.stubGlobal("navigator", { platform });
const { dropEffect } = getDropEffectFromModifiers(
makeDragEvent({ shiftKey: true }),
"link",
true,
);
expect(dropEffect).toBe("copy");
}
});
});
Loading