From 172d0a128de73225485b88dd89265d5b0ddc6fa5 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Tue, 10 Feb 2015 10:21:10 +0000
Subject: [PATCH] Sequences of changes recorded by the editor can now be
 grouped into a single entity for undo/redo purposes.

---
 fsl/fslview/editor/editor.py             | 56 ++++++++++++++++++------
 fsl/fslview/profiles/orthoeditprofile.py | 20 ++++++++-
 2 files changed, 61 insertions(+), 15 deletions(-)

diff --git a/fsl/fslview/editor/editor.py b/fsl/fslview/editor/editor.py
index 37b35a387..01ab7ecf9 100644
--- a/fsl/fslview/editor/editor.py
+++ b/fsl/fslview/editor/editor.py
@@ -57,6 +57,7 @@ class Editor(props.HasProperties):
         # undone.
         self._doneList  = []
         self._doneIndex = -1
+        self._inGroup   = False
 
         self._displayCtx.addListener('selectedImage',
                                      self._name,
@@ -98,7 +99,7 @@ class Editor(props.HasProperties):
         old, new, offset = self._selection.getLastChange()
         
         change = SelectionChange(image, offset, old, new)
-        self._do(change)
+        self._changeMade(change)
 
 
     def getSelection(self):
@@ -129,18 +130,37 @@ class Editor(props.HasProperties):
         newVals[selectBlock] = oldVals[selectBlock]
         
         change = ValueChange(image, offset, oldVals, newVals)
-        self._do(change)
+        self._applyChange(change)
+        self._changeMade( change)
 
+        
+    def startChangeGroup(self):
+        self._inGroup    = True
+        self._doneIndex += 1
+        self._doneList.append([])
 
-    def _do(self, change):
+        log.debug('Starting change group - merging subsequent '
+                  'changes at index {} of {}'.format(self._doneIndex,
+                                                     len(self._doneList)))
 
-        self._applyChange(change)
-        del self._doneList[self._doneIndex + 1:]
-        self._doneList.append(change)
+        
+    def endChangeGroup(self):
+        self._inGroup = False
+        log.debug('Ending change group at {} of {}'.format(
+            self._doneIndex, len(self._doneList))) 
 
-        self._doneIndex += 1
-        self.canUndo     = True
-        self.canRedo     = False
+        
+    def _changeMade(self, change):
+
+        if self._inGroup:
+            self._doneList[self._doneIndex].append(change)
+        else:
+            del self._doneList[self._doneIndex + 1:]
+            self._doneList.append(change)
+            self._doneIndex += 1
+            
+        self.canUndo = True
+        self.canRedo = False
 
         log.debug('New change ({} of {})'.format(self._doneIndex,
                                                  len(self._doneList)))
@@ -155,11 +175,16 @@ class Editor(props.HasProperties):
 
         change = self._doneList[self._doneIndex]
 
-        self._revertChange(change)
+        if not isinstance(change, collections.Sequence):
+            change = [change]
+
+        for c in reversed(change):
+            self._revertChange(c)
 
         self._doneIndex -= 1
 
-        self.canRedo = True
+        self._inGroup = False
+        self.canRedo  = True
         if self._doneIndex == -1:
             self.canUndo = False
         
@@ -172,12 +197,17 @@ class Editor(props.HasProperties):
                                                 len(self._doneList))) 
 
         change = self._doneList[self._doneIndex + 1]
+        
+        if not isinstance(change, collections.Sequence):
+            change = [change] 
 
-        self._applyChange(change)
+        for c in change:
+            self._applyChange(c)
 
         self._doneIndex += 1
 
-        self.canUndo = True
+        self._inGroup = False
+        self.canUndo  = True
         if self._doneIndex == len(self._doneList) - 1:
             self.canRedo = False
 
diff --git a/fsl/fslview/profiles/orthoeditprofile.py b/fsl/fslview/profiles/orthoeditprofile.py
index 28b0392a7..10b63f87c 100644
--- a/fsl/fslview/profiles/orthoeditprofile.py
+++ b/fsl/fslview/profiles/orthoeditprofile.py
@@ -262,7 +262,9 @@ class OrthoEditProfile(orthoviewprofile.OrthoViewProfile):
 
 
     def _selModeLeftMouseDown(self, ev, canvas, mousePos, canvasPos):
-        
+
+        self._editor.startChangeGroup()
+
         if self.selectionMode == 'replace':
             self._editor.getSelection().clearSelection()
 
@@ -276,8 +278,15 @@ class OrthoEditProfile(orthoviewprofile.OrthoViewProfile):
         self._applySelection(         canvas, voxel)
         self._makeSelectionAnnotation(canvas, voxel)
 
+
+    def _selModeLeftMouseUp(self, ev, canvas, mousePos, canvasPos):
+        self._editor.endChangeGroup()
+
         
     def _deselModeLeftMouseDown(self, ev, canvas, mousePos, canvasPos):
+
+        self._editor.startChangeGroup()
+
         voxel = self._getVoxelLocation(canvasPos)
         self._applySelection(         canvas, voxel, False)
         self._makeSelectionAnnotation(canvas, voxel) 
@@ -286,7 +295,11 @@ class OrthoEditProfile(orthoviewprofile.OrthoViewProfile):
     def _deselModeLeftMouseDrag(self, ev, canvas, mousePos, canvasPos):
         voxel = self._getVoxelLocation(canvasPos)
         self._applySelection(         canvas, voxel, False)
-        self._makeSelectionAnnotation(canvas, voxel) 
+        self._makeSelectionAnnotation(canvas, voxel)
+
+        
+    def _deselModeLeftMouseUp(self, ev, canvas, mousePos, canvasPos):
+        self._editor.endChangeGroup()
 
         
     def _selintModeMouseMove(self, ev, canvas, mousePos, canvasPos):
@@ -295,6 +308,8 @@ class OrthoEditProfile(orthoviewprofile.OrthoViewProfile):
 
         
     def _selintModeLeftMouseDown(self, ev, canvas, mousePos, canvasPos):
+
+        self._editor.startChangeGroup()
         self._editor.getSelection().clearSelection() 
         self._selecting = True
         self._lastDist  = 0
@@ -360,4 +375,5 @@ class OrthoEditProfile(orthoviewprofile.OrthoViewProfile):
 
         
     def _selintModeLeftMouseUp(self, ev, canvas, mousePos, canvasPos):
+        self._editor.endChangeGroup()
         self._selecting = False
-- 
GitLab