diff --git a/CHANGELOG.md b/CHANGELOG.md index c99e8ad45df..12214a89f71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md). [Commits](https://github.com/scalableminds/webknossos/compare/19.11.0...HEAD) ### Added -- +- Added an API to set a tree active by name. [#4317](https://github.com/scalableminds/webknossos/pull/4317) ### Changed - diff --git a/frontend/javascripts/oxalis/api/api_latest.js b/frontend/javascripts/oxalis/api/api_latest.js index 4f5cf9e2e3e..020e1889770 100644 --- a/frontend/javascripts/oxalis/api/api_latest.js +++ b/frontend/javascripts/oxalis/api/api_latest.js @@ -63,6 +63,7 @@ import { setNodeRadiusAction, setTreeNameAction, setActiveTreeAction, + setActiveTreeByNameAction, setTreeColorIndexAction, setTreeVisibilityAction, setTreeGroupAction, @@ -286,6 +287,18 @@ class TracingApi { Store.dispatch(setActiveTreeAction(treeId)); } + /** + * Makes the tree specified by name active. Within the tree, the node with the highest ID will be activated. + * + * @example + * api.tracing.setActiveTree("tree_1"); + */ + setActiveTreeByName(treeName: string) { + const { tracing } = Store.getState(); + assertSkeleton(tracing); + Store.dispatch(setActiveTreeByNameAction(treeName)); + } + /** * Changes the color of the referenced tree. Internally, a pre-defined array of colors is used which is * why this function uses a colorIndex (between 0 and 500) instead of a proper color. diff --git a/frontend/javascripts/oxalis/api/cross_origin_api.js b/frontend/javascripts/oxalis/api/cross_origin_api.js index c51e3ea7e91..38f5d517062 100644 --- a/frontend/javascripts/oxalis/api/cross_origin_api.js +++ b/frontend/javascripts/oxalis/api/cross_origin_api.js @@ -27,6 +27,15 @@ const onMessage = event => { api.tracing.resetSkeletonTracing(); break; } + case "setActiveTreeByName": { + const treeName = args[0]; + if (_.isString(treeName)) { + api.tracing.setActiveTreeByName(treeName); + } else { + console.warn("The first argument needs to be the name of the tree."); + } + break; + } case "importNml": { const nmlAsString = args[0]; if (_.isString(nmlAsString)) { diff --git a/frontend/javascripts/oxalis/model/actions/skeletontracing_actions.js b/frontend/javascripts/oxalis/model/actions/skeletontracing_actions.js index 2ea9558e962..85dc50f1d1f 100644 --- a/frontend/javascripts/oxalis/model/actions/skeletontracing_actions.js +++ b/frontend/javascripts/oxalis/model/actions/skeletontracing_actions.js @@ -81,6 +81,7 @@ type AddTreesAndGroupsAction = { type DeleteTreeAction = { type: "DELETE_TREE", treeId?: number, timestamp: number }; type ResetSkeletonTracingAction = { type: "RESET_SKELETON_TRACING" }; type SetActiveTreeAction = { type: "SET_ACTIVE_TREE", treeId: number }; +type SetActiveTreeByNameAction = { type: "SET_ACTIVE_TREE_BY_NAME", treeName: string }; type DeselectActiveTreeAction = { type: "DESELECT_ACTIVE_TREE" }; type SetActiveGroupAction = { type: "SET_ACTIVE_GROUP", groupId: number }; type DeselectActiveGroupAction = { type: "DESELECT_ACTIVE_GROUP" }; @@ -124,6 +125,7 @@ export type SkeletonTracingAction = | DeleteTreeAction | ResetSkeletonTracingAction | SetActiveTreeAction + | SetActiveTreeByNameAction | DeselectActiveTreeAction | MergeTreesAction | SetTreeNameAction @@ -157,6 +159,7 @@ export const SkeletonTracingSaveRelevantActions = [ "ADD_TREES_AND_GROUPS", "DELETE_TREE", "SET_ACTIVE_TREE", + "SET_ACTIVE_TREE_BY_NAME", "SET_TREE_NAME", "MERGE_TREES", "SELECT_NEXT_TREE", @@ -330,6 +333,11 @@ export const setActiveTreeAction = (treeId: number): SetActiveTreeAction => ({ treeId, }); +export const setActiveTreeByNameAction = (treeName: string): SetActiveTreeByNameAction => ({ + type: "SET_ACTIVE_TREE_BY_NAME", + treeName, +}); + export const deselectActiveTreeAction = (): DeselectActiveTreeAction => ({ type: "DESELECT_ACTIVE_TREE", }); diff --git a/frontend/javascripts/oxalis/model/reducers/skeletontracing_reducer.js b/frontend/javascripts/oxalis/model/reducers/skeletontracing_reducer.js index 908b2fd399d..531aa90453e 100644 --- a/frontend/javascripts/oxalis/model/reducers/skeletontracing_reducer.js +++ b/frontend/javascripts/oxalis/model/reducers/skeletontracing_reducer.js @@ -370,6 +370,25 @@ function SkeletonTracingReducer(state: OxalisState, action: Action): OxalisState }) .getOrElse(state); } + case "SET_ACTIVE_TREE_BY_NAME": { + const { treeName } = action; + const { trees } = skeletonTracing; + const treeWithMatchingName = _.values(trees).find(tree => tree.name === treeName); + if (!treeWithMatchingName) { + return state; + } + const newActiveNodeId = _.max(treeWithMatchingName.nodes.map(el => el.id)) || null; + + return update(state, { + tracing: { + skeleton: { + activeNodeId: { $set: newActiveNodeId }, + activeTreeId: { $set: treeWithMatchingName.treeId }, + activeGroupId: { $set: null }, + }, + }, + }); + } case "DESELECT_ACTIVE_TREE": { return update(state, { diff --git a/frontend/javascripts/oxalis/model/sagas/skeletontracing_saga.js b/frontend/javascripts/oxalis/model/sagas/skeletontracing_saga.js index dbf74ce9822..fea634abf94 100644 --- a/frontend/javascripts/oxalis/model/sagas/skeletontracing_saga.js +++ b/frontend/javascripts/oxalis/model/sagas/skeletontracing_saga.js @@ -176,6 +176,7 @@ export function* watchSkeletonTracingAsync(): Saga { yield _takeEvery( [ "SET_ACTIVE_TREE", + "SET_ACTIVE_TREE_BY_NAME", "SET_ACTIVE_NODE", "DELETE_NODE", "DELETE_BRANCHPOINT",