refactor context menu and keyboard navigation handling for improved clarity and maintainability
This commit is contained in:
+134
-129
@@ -1174,17 +1174,17 @@ function App({ container_id, imageStacks, autoCacheStack, annotationJson, viewer
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const el = appRootRef.current;
|
||||
if (!el) return;
|
||||
const handleContextMenu = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
};
|
||||
el.addEventListener("contextmenu", handleContextMenu);
|
||||
return () => {
|
||||
el.removeEventListener("contextmenu", handleContextMenu);
|
||||
};
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
const el = appRootRef.current;
|
||||
if (!el) return;
|
||||
const handleContextMenu = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
};
|
||||
el.addEventListener("contextmenu", handleContextMenu);
|
||||
return () => {
|
||||
el.removeEventListener("contextmenu", handleContextMenu);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!referenceLinesEnabled) return;
|
||||
@@ -1926,6 +1926,8 @@ useEffect(() => {
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const el = appRootRef.current;
|
||||
if (!el) return;
|
||||
function handleArrowKeyNavigation(e: KeyboardEvent) {
|
||||
console.log("Handling arrow key navigation", e.key);
|
||||
console.log("activeViewport", activeViewport);
|
||||
@@ -1975,8 +1977,11 @@ useEffect(() => {
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", handleArrowKeyNavigation);
|
||||
return () => window.removeEventListener("keydown", handleArrowKeyNavigation);
|
||||
el.addEventListener("keydown", handleArrowKeyNavigation);
|
||||
|
||||
return () => {
|
||||
el.removeEventListener("keydown", handleArrowKeyNavigation);
|
||||
};
|
||||
}, [activeViewport, viewportModes, viewportImageIds, updateOverlay]);
|
||||
|
||||
|
||||
@@ -2401,98 +2406,98 @@ useEffect(() => {
|
||||
</div>
|
||||
|
||||
{/* Preset menu (bottom right of viewport) */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 8,
|
||||
bottom: 8,
|
||||
zIndex: 10,
|
||||
pointerEvents: "auto", // <-- ensure pointer events are enabled
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="preset-menu"
|
||||
style={{
|
||||
background: "rgba(0,0,0,0.7)",
|
||||
color: "#fff",
|
||||
borderRadius: "4px",
|
||||
fontSize: "14px",
|
||||
minWidth: "120px",
|
||||
overflow: "hidden",
|
||||
cursor: "pointer",
|
||||
position: "relative",
|
||||
boxShadow: presetsOpenArr[i] ? "0 2px 8px rgba(0,0,0,0.3)" : undefined,
|
||||
pointerEvents: "auto", // <-- ensure pointer events are enabled
|
||||
}}
|
||||
onClick={e => e.stopPropagation()} // <-- prevent bubbling to viewport
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
padding: "6px 12px",
|
||||
fontWeight: "bold",
|
||||
userSelect: "none",
|
||||
}}
|
||||
onClick={e => {
|
||||
e.stopPropagation(); // <-- prevent bubbling to viewport
|
||||
setPresetsOpenArr(prev => {
|
||||
const next = [...prev];
|
||||
next[i] = !next[i];
|
||||
return next;
|
||||
});
|
||||
}}
|
||||
>
|
||||
Presets
|
||||
<span style={{ float: "right", fontWeight: "normal" }}>
|
||||
{presetsOpenArr[i] ? "▲" : "▼"}
|
||||
</span>
|
||||
</div>
|
||||
{presetsOpenArr[i] && (
|
||||
<div
|
||||
className="preset-menu-content"
|
||||
style={{
|
||||
background: "rgba(0,0,0,0.95)",
|
||||
borderRadius: "0 0 4px 4px",
|
||||
padding: "6px 0 6px 0",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
zIndex: 11,
|
||||
pointerEvents: "auto", // <-- ensure pointer events are enabled
|
||||
}}
|
||||
onClick={e => e.stopPropagation()} // <-- prevent bubbling to viewport
|
||||
>
|
||||
{WINDOW_LEVEL_PRESETS.map((preset) => (
|
||||
<button
|
||||
key={preset.name}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 8,
|
||||
bottom: 8,
|
||||
zIndex: 10,
|
||||
pointerEvents: "auto", // <-- ensure pointer events are enabled
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="preset-menu"
|
||||
style={{
|
||||
display: "block",
|
||||
width: "100%",
|
||||
margin: "2px 0",
|
||||
background: "#333",
|
||||
background: "rgba(0,0,0,0.7)",
|
||||
color: "#fff",
|
||||
border: "none",
|
||||
borderRadius: "3px",
|
||||
borderRadius: "4px",
|
||||
fontSize: "14px",
|
||||
minWidth: "120px",
|
||||
overflow: "hidden",
|
||||
cursor: "pointer",
|
||||
padding: "4px 0",
|
||||
fontSize: "13px",
|
||||
opacity: 0.9,
|
||||
}}
|
||||
onClick={e => {
|
||||
e.stopPropagation(); // <-- prevent bubbling to viewport
|
||||
handleApplyPreset(i, preset.center, preset.width);
|
||||
setPresetsOpenArr(prev => {
|
||||
const next = [...prev];
|
||||
next[i] = false;
|
||||
return next;
|
||||
});
|
||||
position: "relative",
|
||||
boxShadow: presetsOpenArr[i] ? "0 2px 8px rgba(0,0,0,0.3)" : undefined,
|
||||
pointerEvents: "auto", // <-- ensure pointer events are enabled
|
||||
}}
|
||||
onClick={e => e.stopPropagation()} // <-- prevent bubbling to viewport
|
||||
>
|
||||
{preset.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
padding: "6px 12px",
|
||||
fontWeight: "bold",
|
||||
userSelect: "none",
|
||||
}}
|
||||
onClick={e => {
|
||||
e.stopPropagation(); // <-- prevent bubbling to viewport
|
||||
setPresetsOpenArr(prev => {
|
||||
const next = [...prev];
|
||||
next[i] = !next[i];
|
||||
return next;
|
||||
});
|
||||
}}
|
||||
>
|
||||
Presets
|
||||
<span style={{ float: "right", fontWeight: "normal" }}>
|
||||
{presetsOpenArr[i] ? "▲" : "▼"}
|
||||
</span>
|
||||
</div>
|
||||
{presetsOpenArr[i] && (
|
||||
<div
|
||||
className="preset-menu-content"
|
||||
style={{
|
||||
background: "rgba(0,0,0,0.95)",
|
||||
borderRadius: "0 0 4px 4px",
|
||||
padding: "6px 0 6px 0",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
zIndex: 11,
|
||||
pointerEvents: "auto", // <-- ensure pointer events are enabled
|
||||
}}
|
||||
onClick={e => e.stopPropagation()} // <-- prevent bubbling to viewport
|
||||
>
|
||||
{WINDOW_LEVEL_PRESETS.map((preset) => (
|
||||
<button
|
||||
key={preset.name}
|
||||
style={{
|
||||
display: "block",
|
||||
width: "100%",
|
||||
margin: "2px 0",
|
||||
background: "#333",
|
||||
color: "#fff",
|
||||
border: "none",
|
||||
borderRadius: "3px",
|
||||
cursor: "pointer",
|
||||
padding: "4px 0",
|
||||
fontSize: "13px",
|
||||
opacity: 0.9,
|
||||
}}
|
||||
onClick={e => {
|
||||
e.stopPropagation(); // <-- prevent bubbling to viewport
|
||||
handleApplyPreset(i, preset.center, preset.width);
|
||||
setPresetsOpenArr(prev => {
|
||||
const next = [...prev];
|
||||
next[i] = false;
|
||||
return next;
|
||||
});
|
||||
}}
|
||||
>
|
||||
{preset.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* Position bar inside each viewport */}
|
||||
{viewportModes[i] === "stack" && viewportImageIds[i] && (
|
||||
<div
|
||||
@@ -2856,18 +2861,18 @@ useEffect(() => {
|
||||
|
||||
return (
|
||||
// App root
|
||||
<div
|
||||
ref={appRootRef}
|
||||
style={{
|
||||
position: "relative",
|
||||
inset: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
boxSizing: "border-box",
|
||||
background: "#222",
|
||||
padding: "12px",
|
||||
overflow: "hidden",
|
||||
}}>
|
||||
<div
|
||||
ref={appRootRef}
|
||||
style={{
|
||||
position: "relative",
|
||||
inset: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
boxSizing: "border-box",
|
||||
background: "#222",
|
||||
padding: "12px",
|
||||
overflow: "hidden",
|
||||
}}>
|
||||
{/* Loading overlay */}
|
||||
{loadingState && (
|
||||
<div
|
||||
@@ -3086,23 +3091,23 @@ useEffect(() => {
|
||||
? "Disable Alt Key for Reference Cursors"
|
||||
: "Enable Alt Key for Reference Cursors"}
|
||||
</button>
|
||||
<button
|
||||
style={{
|
||||
padding: "10px 18px",
|
||||
background: annotationNavEnabled ? "#1976d2" : "#333",
|
||||
color: "#fff",
|
||||
border: "none",
|
||||
borderRadius: "4px",
|
||||
fontWeight: "bold",
|
||||
cursor: "pointer",
|
||||
fontSize: "15px",
|
||||
marginBottom: "18px",
|
||||
width: "100%",
|
||||
}}
|
||||
onClick={() => setAnnotationNavEnabled((prev) => !prev)}
|
||||
>
|
||||
{annotationNavEnabled ? "Hide" : "Show"} Annotation Navigation
|
||||
</button>
|
||||
<button
|
||||
style={{
|
||||
padding: "10px 18px",
|
||||
background: annotationNavEnabled ? "#1976d2" : "#333",
|
||||
color: "#fff",
|
||||
border: "none",
|
||||
borderRadius: "4px",
|
||||
fontWeight: "bold",
|
||||
cursor: "pointer",
|
||||
fontSize: "15px",
|
||||
marginBottom: "18px",
|
||||
width: "100%",
|
||||
}}
|
||||
onClick={() => setAnnotationNavEnabled((prev) => !prev)}
|
||||
>
|
||||
{annotationNavEnabled ? "Hide" : "Show"} Annotation Navigation
|
||||
</button>
|
||||
{/* Add more menu items here if needed */}
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user