Add ability to safely disengage unintentionally dragged handle

In the 3D viewport a common operation would be to use the mouse to rotate by left-clicking (or, strictly speaking, left-button-pressing) & dragging. The same sequence is also used for other tasks, though, such as resizing a ROI, or moving a fiducial marker (from the the the Markups module.

It has happened to me occasionally that I have intended to rotate the 3D view, but ended up inadvertently grabbing the handle of a ROI or a fiducial marker. In such cases I’d like to be able to safely disengage the handle without making a change. In other applications a similar action can be accomplished by pressing the Esc key on the keyboard before the mouse button is released.

Currently it is possible to lock marker positions, but they are unlocked by default, and some users must also like to have the ability to drag the marker positions from time to time. A ROI can be hidden, but sometimes a user will want it to be visible while also rotating the 3D view.

The converse
On some other occasions I might have wanted to resize the ROI, but ended up accidentally rotating the 3D view. (Maybe it could happen to some users attempting to drag a marker too.) Likewise in this converse situation it would be helpful to be able to disengage the view rotation safely, without changing it, by pressing the Esc key before the mouse button is released.

The other option, of course, would be a global Undo functionality, but I imagine that would be a bigger job.


During dragging the control point position or the view, the node parameters are updated immediately, so disengaging by Esc key would not help (the original state would not be restored). We could implement saving and restoring the state of the fiducial, but that is not trivial. We’d better spend that time with polishing up the global undo/redo feature in Slicer and enable it for markups - see details here.

It would be nice if each of the widgets remembered the state at the start of the interaction and reset it if the escape key is pressed. This doesn’t seem like a lot of complexity since it would be localized to the event handler code.

1 Like

Automatically reverting all changes that happened to a node during time of drag-and-drop could cause serious problems (any module can make any changes during the drag-and-drop and they would not expect all those changes to be reverted because a point was moved and point move was cancelled).

We could store and revert selected properties of the node (such as control point position, orientation, position status, autocreated flag), but instead of spending time with implementing and testing this, I think it would be better to provide the solution that users actually want: enabling undo/redo for markups.

I agree that finishing undo/redo is a worthwhile goal.

Regarding move events, if any code is updating continuously while the move it happening then it won’t be a problem for it to get another move event that resets the location to the start of the move. If the code is just watching for the end of a move then it won’t matter if it’s cancelled.

1 Like

I agree that both would be valuable.

Allowing Esc to disengage could potentially have some performance benefit, if re-computations could be avoided; it’s also more immediate, and has the benefit of not needing a mouse manoeuvre or hotkey combination.
Furthermore, I’m not sure how you intend/envisage implementing the ‘global’ undo. Are you contemplating that it would even be keeping track of zoom/pan along with rotation in 3D port and slice number selection in slice viewports? I’m not entirely sure whether that’s how users would want/expect it implemented, and it’s certainly not how all other applications work. For instance, in Microsoft’s Office suite the undo button applies to distinct actions (such as typing a word), rather than view settings (e.g. cursor position, page/sheet/slide magnification) associated with ‘banal’ actions such as cursoring or scrolling. .
Yet Esc to disengage unintentional rotation in the 3D view could be useful, and intuitive, I feel.

Global undo is already implemented in Slicer and used in specific projects. It is hard to implement it to work as expected for all nodes and all situations.

Slicer’s undo infrastructure is configurable so that you can choose what to include or exclude. We had projects where including view parameters in the undo history was a requirement, but for the reasons that you described I agree that in general it is better to exclude them.

An issue has been created at Add ability to safely release unintentionally dragged handle · Issue #6038 · Slicer/Slicer · GitHub .