-
Notifications
You must be signed in to change notification settings - Fork 26
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
Shortcuts for navigating to next/prev node #4784
Conversation
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.
Very nice, I like this feature a lot and you did a good job implementing it, it's already a pleasure to use 🎉
There are a couple of edge-cases which I annotated and I suggested a more edge-case-resistant approach to detect invalid navigation lists :)
frontend/javascripts/oxalis/controller/combinations/skeletontracing_plane_controller.js
Outdated
Show resolved
Hide resolved
frontend/javascripts/oxalis/controller/combinations/skeletontracing_plane_controller.js
Outdated
Show resolved
Hide resolved
frontend/javascripts/oxalis/model/actions/skeletontracing_actions.js
Outdated
Show resolved
Hide resolved
@@ -229,6 +303,7 @@ function onClick( | |||
); | |||
} else { | |||
Store.dispatch(setActiveNodeAction(nodeId)); | |||
Store.dispatch(updateNavigationListAction([nodeId], 0)); |
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.
I think it's very hard to catch all the cases where the navigation list becomes "invalid" and would need to emptied. For example, this is the straight-forward case where a user selects another node, but there are also many other cases, like: Deleting one (or all) nodes of a tree, deleting a group with all its trees, creating a new tree, jumping to a branchpoint (using the J
shortcut), ...
Therefore, what do you think about not trying to catch all these cases preemptively, but on-demand. What I mean by that is for every "hit" in the navigation list in the toSubsequentNode
and toPrecedingNode
functions, so whenever a node that was already in the list would be set active, before doing that you check whether the node from the list is a neighbor of the currently active node:
- If it is not a neighbor, empty the list (as you did here) because something happened in between that made the navigation list invalid, otherwise the nodes would be neighbors. Then you search a neighbor as you would do if the list was empty or exhausted.
- If it is a neighbor, proceed as usual
What do you think about this approach? :)
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.
I adjusted it a little bit and just check it in advance by comparing the active node with the list's node at the active index.
frontend/javascripts/oxalis/controller/combinations/skeletontracing_plane_controller.js
Outdated
Show resolved
Hide resolved
frontend/javascripts/oxalis/controller/combinations/skeletontracing_plane_controller.js
Outdated
Show resolved
Hide resolved
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.
Works like a charm in my tests, very cool!
I made some suggestions to simplify the code. I'm not too happy about the code duplication, but as the two cases differ in quite a few lines I don't see an easy way to unify the two functions. So I'd say we should aim to simplify the methods as much as possible but keep them separate :)
Please also add the two new shortcuts to the list of keyboard shortcuts (keyboard_shortcuts.md
)
frontend/javascripts/oxalis/controller/combinations/skeletontracing_plane_controller.js
Outdated
Show resolved
Hide resolved
if ( | ||
activeNodeId !== navigationList.list[navigationList.activeIndex] || | ||
!navigationList.list.length | ||
) { | ||
isValidList = false; | ||
} |
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.
You could get rid of the let isValidList
by directly assigning the result of the comparison here, like:
const isValidList = navigationList.list.length && activeNodeId === navigationList.list[navigationList.activeIndex];
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.
Same in the other function.
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.
That's pretty neat! Thanks :)
const { tree, node } = getNodeAndTree(tracing, activeNodeId, activeTreeId) | ||
.map(([maybeTree, maybeNode]) => ({ tree: maybeTree, node: maybeNode })) | ||
.getOrElse({ | ||
tree: null, | ||
node: null, | ||
}); |
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.
Maybe simplify this to
const [ tree, node ] = getNodeAndTree(tracing, activeNodeId, activeTreeId)
.getOrElse([null, null]);
Same in the other method.
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.
Flow is not happy with that :( . Maybe I could extract it in an extra method so it at least doesn't appear twice?
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.
:/ Yes you could put it into a getNodeAndTreeOrNull
method in the skeleton tracing accessor file or you could annotate my proposed solution with a // $FlowFixMe
to silence flow (as we know that the code is correct).
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.
Well done, lgtm 👍
This PR makes it possible to navigate between nodes in a skeleton tracing via "," and "ctr + ." .
URL of deployed dev instance (used for testing):
Steps to test:
Issues:
Updated (unreleased) migration guide if applicableUpdated documentation if applicableAdapted wk-connect if datastore API changesNeeds datastore update after deployment