-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Undo/redo for tools #394
base: main
Are you sure you want to change the base?
Undo/redo for tools #394
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,12 @@ import { computed } from 'vue'; | |
import { useCurrentImage } from '@/src/composables/useCurrentImage'; | ||
import { AnnotationToolStore } from '@/src/store/tools/useAnnotationTool'; | ||
import { frameOfReferenceToImageSliceAndAxis } from '@/src/utils/frameOfReference'; | ||
import useHistoryStore from '@/src/store/history'; | ||
import { createRemoveToolOperation } from '@/src/store/operations/tools'; | ||
import { Store } from 'pinia'; | ||
|
||
const props = defineProps<{ | ||
toolStore: AnnotationToolStore<ToolID>; | ||
toolStore: AnnotationToolStore<ToolID> & Store; | ||
icon: string; | ||
}>(); | ||
|
||
|
@@ -33,7 +36,10 @@ const tools = computed(() => { | |
}); | ||
|
||
const remove = (id: ToolID) => { | ||
props.toolStore.removeTool(id); | ||
const imageID = currentImageID.value; | ||
if (!imageID) return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No imageID, but showing remove button in toolList would be strange. Throw Error or derive imageID from toolID so imageID is guarrentied? Worried that defensive programming could lead to corner case runtime quirks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like deriving the image ID from the tool ID in this case. |
||
const op = createRemoveToolOperation(props.toolStore, id); | ||
useHistoryStore().pushOperation({ datasetID: imageID }, op, true); | ||
}; | ||
|
||
const jumpTo = (id: ToolID) => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,13 @@ import { | |
} from '@/src/utils/frameOfReference'; | ||
import { usePolygonStore } from '@/src/store/tools/polygons'; | ||
import { Polygon, PolygonID } from '@/src/types/polygon'; | ||
import { | ||
createAddToolOperation, | ||
createRemoveToolOperation, | ||
} from '@/src/store/operations/tools'; | ||
import useHistoryStore from '@/src/store/history'; | ||
import { IHistoryOperation } from '@/src/types/history'; | ||
import { Maybe } from '@/src/types'; | ||
import PolygonWidget2D from './PolygonWidget2D.vue'; | ||
|
||
type ToolID = PolygonID; | ||
|
@@ -100,6 +107,17 @@ export default defineComponent({ | |
const viewAxis = computed(() => getLPSAxisFromDir(viewDirection.value)); | ||
|
||
const placingToolID = ref<ToolID | null>(null); | ||
let addToolOperation: Maybe<IHistoryOperation<PolygonID>> = null; | ||
|
||
const addPlacingTool = () => { | ||
const imageID = currentImageID.value; | ||
if (!imageID) return; | ||
addToolOperation = createAddToolOperation(activeToolStore, { | ||
imageID, | ||
placing: true, | ||
}); | ||
placingToolID.value = addToolOperation.apply(); | ||
}; | ||
|
||
// --- active tool management --- // | ||
|
||
|
@@ -124,10 +142,7 @@ export default defineComponent({ | |
placingToolID.value = null; | ||
} | ||
if (active && imageID) { | ||
placingToolID.value = activeToolStore.addTool({ | ||
imageID, | ||
placing: true, | ||
}); | ||
addPlacingTool(); | ||
} | ||
}, | ||
{ immediate: true } | ||
|
@@ -154,11 +169,13 @@ export default defineComponent({ | |
}); | ||
|
||
const onToolPlaced = () => { | ||
if (currentImageID.value) { | ||
placingToolID.value = activeToolStore.addTool({ | ||
imageID: currentImageID.value, | ||
placing: true, | ||
}); | ||
const imageID = currentImageID.value; | ||
if (imageID) { | ||
useHistoryStore().pushOperation( | ||
{ datasetID: imageID }, | ||
addToolOperation! | ||
); | ||
Comment on lines
+174
to
+177
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about hiding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be good to do it later down the road. I'm opting not to for now because I don't want to make the tool stores undo/redo aware just yet. |
||
addPlacingTool(); | ||
} | ||
}; | ||
|
||
|
@@ -207,7 +224,13 @@ export default defineComponent({ | |
}; | ||
|
||
const deleteToolFromContextMenu = () => { | ||
activeToolStore.removeTool(contextMenu.forToolID); | ||
const imageID = currentImageID.value; | ||
if (!imageID) return; | ||
const op = createRemoveToolOperation( | ||
activeToolStore, | ||
contextMenu.forToolID | ||
); | ||
useHistoryStore().pushOperation({ datasetID: imageID }, op, true); | ||
}; | ||
|
||
// --- tool data --- // | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the future, should I put
& Store
on theAnnotationToolStore
shared type?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that is a good idea. I could add that as an extra commit to this PR if you'd like.