From 5d02756a1cdc3f2421755f274eb2ca7a03992156 Mon Sep 17 00:00:00 2001 From: Charlie Meister Date: Thu, 16 Jan 2025 19:34:26 +0100 Subject: [PATCH 01/10] show measurement tool in view mode --- .../oxalis/model/reducers/ui_reducer.ts | 12 +++++ .../oxalis/view/action-bar/toolbar_view.tsx | 45 +++++++++++-------- .../oxalis/view/action_bar_view.tsx | 4 +- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts index a35e6b62e7..e02f956cee 100644 --- a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts +++ b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts @@ -1,3 +1,4 @@ +import { AnnotationToolEnum, ControlModeEnum } from "oxalis/constants"; import type { Action } from "oxalis/model/actions/actions"; import { updateKey, updateKey2 } from "oxalis/model/helpers/deep_update"; import { @@ -8,6 +9,12 @@ import { import { hideBrushReducer } from "oxalis/model/reducers/volumetracing_reducer_helpers"; import type { OxalisState } from "oxalis/store"; +const ALLOWED_TOOLS_IN_VIEW_MODE = [ + AnnotationToolEnum.MOVE, + AnnotationToolEnum.AREA_MEASUREMENT, + AnnotationToolEnum.LINE_MEASUREMENT, +]; // TODO_c make prettier + function UiReducer(state: OxalisState, action: Action): OxalisState { switch (action.type) { case "SET_DROPZONE_MODAL_VISIBILITY": { @@ -54,6 +61,11 @@ function UiReducer(state: OxalisState, action: Action): OxalisState { } case "SET_TOOL": { + if (state.temporaryConfiguration.controlMode === ControlModeEnum.VIEW) { + if (ALLOWED_TOOLS_IN_VIEW_MODE.includes(AnnotationToolEnum[action.tool])) { + return setToolReducer(state, action.tool); + } + } if (!state.tracing.restrictions.allowUpdate) { return state; } diff --git a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx index 22c05fe511..cc0539b738 100644 --- a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx +++ b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx @@ -26,6 +26,7 @@ import { document } from "libs/window"; import { type AnnotationTool, AnnotationToolEnum, + ControlModeEnum, FillModeEnum, type InterpolationMode, InterpolationModeEnum, @@ -126,6 +127,7 @@ const handleToggleSelectiveVisibilityInProofreading = (value: boolean) => { const handleSetTool = (event: RadioChangeEvent) => { const value = event.target.value as AnnotationTool; Store.dispatch(setToolAction(value)); + console.log("Tool set to", value); }; const handleCreateCell = () => { @@ -847,8 +849,11 @@ const TOOL_NAMES = { export default function ToolbarView() { const dispatch = useDispatch(); - const hasVolume = useSelector((state: OxalisState) => state.tracing.volumes.length > 0); - const hasSkeleton = useSelector((state: OxalisState) => state.tracing.skeleton != null); + const hasVolume = useSelector((state: OxalisState) => state.tracing?.volumes.length > 0); + const hasSkeleton = useSelector((state: OxalisState) => state.tracing?.skeleton != null); + const isViewMode = useSelector( + (state: OxalisState) => state.temporaryConfiguration.controlMode === ControlModeEnum.VIEW, + ); const isAgglomerateMappingEnabled = useSelector(hasAgglomerateMapping); const [lastForcefullyDisabledTool, setLastForcefullyDisabledTool] = @@ -1103,22 +1108,26 @@ export default function ToolbarView() { ) : null} - - Bounding Box Icon - + {!isViewMode && ( + + Bounding Box Icon + + )} {hasSkeleton && hasVolume ? ( { const { dataset, is2d, - isReadOnly, + isReadOnly, // TODO_c are there any cases where this is true, that are not read-only annotations or view mode? showVersionRestore, controlMode, hasSkeleton, @@ -298,7 +298,7 @@ class ActionBarView extends React.PureComponent { {getIsAIAnalysisEnabled() && isAdminOrDatasetManager ? this.renderStartAIJobButton(shouldDisableAIJobButton, tooltip) : null} - {!isReadOnly && constants.MODES_PLANE.indexOf(viewMode) > -1 ? : null} + {constants.MODES_PLANE.indexOf(viewMode) > -1 ? : null} {isViewMode ? this.renderStartTracingButton() : null} Date: Thu, 23 Jan 2025 21:56:30 +0100 Subject: [PATCH 02/10] lint and remove console log --- frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx | 1 - frontend/javascripts/oxalis/view/action_bar_view.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx index 95a4c16830..ef36209110 100644 --- a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx +++ b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx @@ -127,7 +127,6 @@ const handleToggleSelectiveVisibilityInProofreading = (value: boolean) => { const handleSetTool = (event: RadioChangeEvent) => { const value = event.target.value as AnnotationTool; Store.dispatch(setToolAction(value)); - console.log("Tool set to", value); }; const handleCreateCell = () => { diff --git a/frontend/javascripts/oxalis/view/action_bar_view.tsx b/frontend/javascripts/oxalis/view/action_bar_view.tsx index c886cad785..e499f19969 100644 --- a/frontend/javascripts/oxalis/view/action_bar_view.tsx +++ b/frontend/javascripts/oxalis/view/action_bar_view.tsx @@ -237,7 +237,7 @@ class ActionBarView extends React.PureComponent { const { dataset, is2d, - isReadOnly, // TODO_c are there any cases where this is true, that are not read-only annotations or view mode? + //isReadOnly, //TODO_c are there any cases where this is true, that are not read-only annotations or view mode? showVersionRestore, controlMode, hasSkeleton, From f64d244d15892265ce72d4bc3e03eed2340609cb Mon Sep 17 00:00:00 2001 From: Charlie Meister Date: Fri, 24 Jan 2025 09:36:25 +0100 Subject: [PATCH 03/10] improve code structure and change position of buttons in action bar --- frontend/javascripts/oxalis/constants.ts | 2 ++ .../javascripts/oxalis/model/reducers/ui_reducer.ts | 10 ++-------- frontend/javascripts/oxalis/view/action_bar_view.tsx | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/frontend/javascripts/oxalis/constants.ts b/frontend/javascripts/oxalis/constants.ts index 1630557c41..06c500a78e 100644 --- a/frontend/javascripts/oxalis/constants.ts +++ b/frontend/javascripts/oxalis/constants.ts @@ -223,6 +223,8 @@ export const MeasurementTools: Array = [ AnnotationToolEnum.AREA_MEASUREMENT, ]; +export const AvailableToolsInViewMode = [...MeasurementTools, AnnotationToolEnum.MOVE]; + export type AnnotationTool = keyof typeof AnnotationToolEnum; export enum ContourModeEnum { DRAW = "DRAW", diff --git a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts index e02f956cee..8e76057827 100644 --- a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts +++ b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts @@ -1,4 +1,4 @@ -import { AnnotationToolEnum, ControlModeEnum } from "oxalis/constants"; +import { AnnotationToolEnum, AvailableToolsInViewMode, ControlModeEnum } from "oxalis/constants"; import type { Action } from "oxalis/model/actions/actions"; import { updateKey, updateKey2 } from "oxalis/model/helpers/deep_update"; import { @@ -9,12 +9,6 @@ import { import { hideBrushReducer } from "oxalis/model/reducers/volumetracing_reducer_helpers"; import type { OxalisState } from "oxalis/store"; -const ALLOWED_TOOLS_IN_VIEW_MODE = [ - AnnotationToolEnum.MOVE, - AnnotationToolEnum.AREA_MEASUREMENT, - AnnotationToolEnum.LINE_MEASUREMENT, -]; // TODO_c make prettier - function UiReducer(state: OxalisState, action: Action): OxalisState { switch (action.type) { case "SET_DROPZONE_MODAL_VISIBILITY": { @@ -62,7 +56,7 @@ function UiReducer(state: OxalisState, action: Action): OxalisState { case "SET_TOOL": { if (state.temporaryConfiguration.controlMode === ControlModeEnum.VIEW) { - if (ALLOWED_TOOLS_IN_VIEW_MODE.includes(AnnotationToolEnum[action.tool])) { + if (AvailableToolsInViewMode.includes(AnnotationToolEnum[action.tool])) { return setToolReducer(state, action.tool); } } diff --git a/frontend/javascripts/oxalis/view/action_bar_view.tsx b/frontend/javascripts/oxalis/view/action_bar_view.tsx index e499f19969..2441853f25 100644 --- a/frontend/javascripts/oxalis/view/action_bar_view.tsx +++ b/frontend/javascripts/oxalis/view/action_bar_view.tsx @@ -298,8 +298,8 @@ class ActionBarView extends React.PureComponent { {getIsAIAnalysisEnabled() && isAdminOrDatasetManager ? this.renderStartAIJobButton(shouldDisableAIJobButton, tooltip) : null} - {constants.MODES_PLANE.indexOf(viewMode) > -1 ? : null} {isViewMode ? this.renderStartTracingButton() : null} + {constants.MODES_PLANE.indexOf(viewMode) > -1 ? : null} Date: Fri, 24 Jan 2025 09:37:57 +0100 Subject: [PATCH 04/10] add changelog --- CHANGELOG.unreleased.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index a6c37f2e20..56b1edeacd 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -12,6 +12,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released ### Added - Added the possibility to configure a rotation for a dataset, which can be toggled off and on when viewing and annotating data. [#8159](https://github.com/scalableminds/webknossos/pull/8159) +- Measurement tools are now accesible when viewing datasets outside of an annotation. [#8334](https://github.com/scalableminds/webknossos/pull/8334) ### Changed From f65b68c853124f881895b2213d1284c90a74420d Mon Sep 17 00:00:00 2001 From: Charlie Meister Date: Fri, 24 Jan 2025 09:39:11 +0100 Subject: [PATCH 05/10] fix spelling --- CHANGELOG.unreleased.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 56b1edeacd..267c1b62c8 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -12,7 +12,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released ### Added - Added the possibility to configure a rotation for a dataset, which can be toggled off and on when viewing and annotating data. [#8159](https://github.com/scalableminds/webknossos/pull/8159) -- Measurement tools are now accesible when viewing datasets outside of an annotation. [#8334](https://github.com/scalableminds/webknossos/pull/8334) +- Measurement tools are now accessible when viewing datasets outside of an annotation. [#8334](https://github.com/scalableminds/webknossos/pull/8334) ### Changed From 0503a6219e2667e53260dcbde054f09c646c0736 Mon Sep 17 00:00:00 2001 From: Charlie Meister Date: Fri, 24 Jan 2025 11:09:01 +0100 Subject: [PATCH 06/10] fix that actions were falsely available in read-only annotations --- .../oxalis/view/action-bar/toolbar_view.tsx | 15 +++++++-------- .../javascripts/oxalis/view/action_bar_view.tsx | 6 ++++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx index ef36209110..acfe4ce53c 100644 --- a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx +++ b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx @@ -846,13 +846,11 @@ const TOOL_NAMES = { AREA_MEASUREMENT: "Area Measurement Tool", }; -export default function ToolbarView() { +export default function ToolbarView({ isReadOnly = false }: { isReadOnly?: boolean }) { const dispatch = useDispatch(); const hasVolume = useSelector((state: OxalisState) => state.tracing?.volumes.length > 0); const hasSkeleton = useSelector((state: OxalisState) => state.tracing?.skeleton != null); - const isViewMode = useSelector( - (state: OxalisState) => state.temporaryConfiguration.controlMode === ControlModeEnum.VIEW, - ); + const isAgglomerateMappingEnabled = useSelector(hasAgglomerateMapping); const [lastForcefullyDisabledTool, setLastForcefullyDisabledTool] = @@ -860,6 +858,7 @@ export default function ToolbarView() { const isVolumeModificationAllowed = useSelector( (state: OxalisState) => !hasEditableMapping(state), ); + const isModificationAllowed = !isReadOnly && isVolumeModificationAllowed; const useLegacyBindings = useSelector( (state: OxalisState) => state.userConfiguration.useLegacyBindings, ); @@ -944,7 +943,7 @@ export default function ToolbarView() { - {hasSkeleton ? ( + {hasSkeleton && !isReadOnly ? ( ) : null} - {hasVolume && isVolumeModificationAllowed ? ( + {hasVolume && isModificationAllowed ? ( ) : null} - {!isViewMode && ( + {!isReadOnly && ( )} - {hasSkeleton && hasVolume ? ( + {hasSkeleton && hasVolume && !isReadOnly ? ( { const { dataset, is2d, - //isReadOnly, //TODO_c are there any cases where this is true, that are not read-only annotations or view mode? + isReadOnly, showVersionRestore, controlMode, hasSkeleton, @@ -299,7 +299,9 @@ class ActionBarView extends React.PureComponent { ? this.renderStartAIJobButton(shouldDisableAIJobButton, tooltip) : null} {isViewMode ? this.renderStartTracingButton() : null} - {constants.MODES_PLANE.indexOf(viewMode) > -1 ? : null} + {constants.MODES_PLANE.indexOf(viewMode) > -1 ? ( + + ) : null} Date: Fri, 24 Jan 2025 19:44:54 +0100 Subject: [PATCH 07/10] allow to set tools in ui reducer --- frontend/javascripts/oxalis/model/reducers/ui_reducer.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts index 8e76057827..c74cc3f7ab 100644 --- a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts +++ b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts @@ -55,14 +55,11 @@ function UiReducer(state: OxalisState, action: Action): OxalisState { } case "SET_TOOL": { - if (state.temporaryConfiguration.controlMode === ControlModeEnum.VIEW) { + if (!state.tracing.restrictions.allowUpdate) { if (AvailableToolsInViewMode.includes(AnnotationToolEnum[action.tool])) { return setToolReducer(state, action.tool); } } - if (!state.tracing.restrictions.allowUpdate) { - return state; - } return setToolReducer(state, action.tool); } From 2e8952150f8db73acef4e4e803b4dbe48740b63a Mon Sep 17 00:00:00 2001 From: Charlie Meister Date: Fri, 24 Jan 2025 19:46:17 +0100 Subject: [PATCH 08/10] complete case distinction in reducer --- frontend/javascripts/oxalis/model/reducers/ui_reducer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts index c74cc3f7ab..ad514ed4f0 100644 --- a/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts +++ b/frontend/javascripts/oxalis/model/reducers/ui_reducer.ts @@ -59,6 +59,7 @@ function UiReducer(state: OxalisState, action: Action): OxalisState { if (AvailableToolsInViewMode.includes(AnnotationToolEnum[action.tool])) { return setToolReducer(state, action.tool); } + return state; } return setToolReducer(state, action.tool); From 2b3ec11aeb3d61788dcbc4c52994fb6ac4d847b1 Mon Sep 17 00:00:00 2001 From: Charlie Meister Date: Fri, 24 Jan 2025 20:13:04 +0100 Subject: [PATCH 09/10] remove default value and optional param --- frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx index acfe4ce53c..5e6e369d3e 100644 --- a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx +++ b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx @@ -846,7 +846,7 @@ const TOOL_NAMES = { AREA_MEASUREMENT: "Area Measurement Tool", }; -export default function ToolbarView({ isReadOnly = false }: { isReadOnly?: boolean }) { +export default function ToolbarView({ isReadOnly }: { isReadOnly: boolean }) { const dispatch = useDispatch(); const hasVolume = useSelector((state: OxalisState) => state.tracing?.volumes.length > 0); const hasSkeleton = useSelector((state: OxalisState) => state.tracing?.skeleton != null); From 6a56e28cf56c123ae7b2f10d2dacfbdb6f7365d0 Mon Sep 17 00:00:00 2001 From: Charlie Meister Date: Sat, 1 Feb 2025 14:41:28 +0100 Subject: [PATCH 10/10] address review --- CHANGELOG.unreleased.md | 1 - .../javascripts/oxalis/view/action-bar/toolbar_view.tsx | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 909fed6d4d..0a33c40ad0 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -11,7 +11,6 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released [Commits](https://github.com/scalableminds/webknossos/compare/25.01.0...HEAD) ### Added -- Added the possibility to configure a rotation for a dataset, which can be toggled off and on when viewing and annotating data. [#8159](https://github.com/scalableminds/webknossos/pull/8159) - Added the possibility to use the "merger mode" even when the user has annotated volume data in the current layer (as long as no other mapping is active). [#8335](https://github.com/scalableminds/webknossos/pull/8335) - Measurement tools are now accessible when viewing datasets outside of an annotation. [#8334](https://github.com/scalableminds/webknossos/pull/8334) diff --git a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx index 31dab1431f..0d301c4ab0 100644 --- a/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx +++ b/frontend/javascripts/oxalis/view/action-bar/toolbar_view.tsx @@ -857,10 +857,8 @@ export default function ToolbarView({ isReadOnly }: { isReadOnly: boolean }) { const [lastForcefullyDisabledTool, setLastForcefullyDisabledTool] = useState(null); - const isVolumeModificationAllowed = useSelector( - (state: OxalisState) => !hasEditableMapping(state), - ); - const isModificationAllowed = !isReadOnly && isVolumeModificationAllowed; + const isVolumeModificationAllowed = + useSelector((state: OxalisState) => !hasEditableMapping(state)) && !isReadOnly; const useLegacyBindings = useSelector( (state: OxalisState) => state.userConfiguration.useLegacyBindings, ); @@ -962,7 +960,7 @@ export default function ToolbarView({ isReadOnly }: { isReadOnly: boolean }) { ) : null} - {hasVolume && isModificationAllowed ? ( + {hasVolume && isVolumeModificationAllowed ? (