From 15eb7aa55cd2d9dfbdaba68a0221faf894a849a4 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Fri, 17 Oct 2014 16:01:05 +0100
Subject: [PATCH] SliceCanvas has option to flip the viewport along
 horizontal/vertical axes. These are exposed to the user by Orthopanel for the
 time being, but will be removed at some stage.

---
 fsl/fslview/gl/slicecanvas.py   | 24 +++++++++++++++++++++++-
 fsl/fslview/views/orthopanel.py | 26 ++++++++++++++++++++++++--
 2 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/fsl/fslview/gl/slicecanvas.py b/fsl/fslview/gl/slicecanvas.py
index aedb51faa..53b987e1e 100644
--- a/fsl/fslview/gl/slicecanvas.py
+++ b/fsl/fslview/gl/slicecanvas.py
@@ -74,11 +74,23 @@ class SliceCanvas(props.HasProperties):
     zax = props.Choice((0, 1, 2), ('X axis', 'Y axis', 'Z axis'))
     """The image axis to be used as the screen 'depth' axis."""
 
+    
+    invertX = props.Boolean(default=False)
+    """If True, the display is inverted along the X (horizontal screen) axis.
+    """
+
+    
+    invertY = props.Boolean(default=False)
+    """If True, the display is inverted along the Y (vertical screen) axis.
+    """ 
 
+    
     _labels = {
         'zoom'       : 'Zoom level',
         'showCursor' : 'Show cursor',
-        'zax'        : 'Z axis'}
+        'zax'        : 'Z axis',
+        'invertX'    : 'Invert X axis',
+        'invertY'    : 'Invert Y axis'}
     """Labels for the properties which are intended to be user editable."""
 
     
@@ -117,6 +129,9 @@ class SliceCanvas(props.HasProperties):
         realHeight                = self.displayBounds.ylen
         canvasWidth, canvasHeight = map(float, self._getSize())
 
+        if self.invertX: xpos = canvasWidth  - xpos
+        if self.invertY: ypos = canvasHeight - ypos
+
         if realWidth    == 0 or \
            canvasWidth  == 0 or \
            realHeight   == 0 or \
@@ -224,6 +239,8 @@ class SliceCanvas(props.HasProperties):
         self.addListener('pos',           self.name, refresh)
         self.addListener('showCursor',    self.name, refresh)
         self.addListener('displayBounds', self.name, refresh)
+        self.addListener('invertX',       self.name, refresh)
+        self.addListener('invertY',       self.name, refresh)
         self.addListener('zoom',
                          self.name,
                          lambda *a: self._updateDisplayBounds())
@@ -518,6 +535,11 @@ class SliceCanvas(props.HasProperties):
         gl.glViewport(0, 0, width, height)
         gl.glMatrixMode(gl.GL_PROJECTION)
         gl.glLoadIdentity()
+
+        # Flip the viewport if necessary
+        if self.invertX: xmin, xmax = xmax, xmin
+        if self.invertY: ymin, ymax = ymax, ymin
+        
         gl.glOrtho(xmin,        xmax,
                    ymin,        ymax,
                    zmin - 1000, zmax + 1000)
diff --git a/fsl/fslview/views/orthopanel.py b/fsl/fslview/views/orthopanel.py
index 4f64072e0..5b7e41e83 100644
--- a/fsl/fslview/views/orthopanel.py
+++ b/fsl/fslview/views/orthopanel.py
@@ -30,6 +30,14 @@ class OrthoPanel(canvaspanel.CanvasPanel):
     showXCanvas = props.Boolean(default=True)
     showYCanvas = props.Boolean(default=True)
     showZCanvas = props.Boolean(default=True)
+
+
+    invertX_X   = props.Boolean(default=False)
+    invertX_Y   = props.Boolean(default=False)
+    invertY_X   = props.Boolean(default=False)
+    invertY_Y   = props.Boolean(default=False)
+    invertZ_X   = props.Boolean(default=False)
+    invertZ_Y   = props.Boolean(default=False) 
     
     # How should we lay out each of the three slice panels?
     layout = props.Choice(['Horizontal', 'Vertical', 'Grid'])
@@ -58,6 +66,9 @@ class OrthoPanel(canvaspanel.CanvasPanel):
                       'showYCanvas',
                       'showZCanvas',
                       'showColourBar',
+                      props.HGroup(('invertX_X', 'invertX_Y')),
+                      props.HGroup(('invertY_X', 'invertY_Y')),
+                      props.HGroup(('invertZ_X', 'invertZ_Y')),
                       props.Widget('colourBarLocation',
                                    visibleWhen=lambda i: i.showColourBar),
                       props.Widget('colourBarLabelSide',
@@ -106,6 +117,14 @@ class OrthoPanel(canvaspanel.CanvasPanel):
         self.bindProps('yzoom',      self._ycanvas, 'zoom')
         self.bindProps('zzoom',      self._zcanvas, 'zoom')
 
+
+        self.bindProps('invertX_X', self._xcanvas, 'invertX')
+        self.bindProps('invertX_Y', self._xcanvas, 'invertY')
+        self.bindProps('invertY_X', self._ycanvas, 'invertX')
+        self.bindProps('invertY_Y', self._ycanvas, 'invertY')
+        self.bindProps('invertZ_X', self._zcanvas, 'invertX')
+        self.bindProps('invertZ_Y', self._zcanvas, 'invertY') 
+
         llName = '{}_layout'.format(self._name)
         
         self.addListener('layout',            llName, self._layoutChanged)
@@ -202,14 +221,17 @@ class OrthoPanel(canvaspanel.CanvasPanel):
 
         layout = self.layout.lower()
 
+        canvases = [self._xcanvas, self._ycanvas, self._zcanvas]
+
         if   layout == 'horizontal':
             self._canvasSizer = wx.BoxSizer(wx.HORIZONTAL)
         elif layout == 'vertical':
             self._canvasSizer = wx.BoxSizer(wx.VERTICAL)
         elif layout == 'grid':
-            self._canvasSizer = wx.WrapSizer(wx.HORIZONTAL) 
+            self._canvasSizer = wx.WrapSizer(wx.HORIZONTAL)
+            canvases = [self._ycanvas, self._xcanvas, self._zcanvas]
 
-        for c in [self._xcanvas, self._ycanvas, self._zcanvas]:
+        for c in canvases:
             self._canvasSizer.Add(c, flag=wx.EXPAND, proportion=1)
 
         self.getCanvasPanel().SetSizer(self._canvasSizer)
-- 
GitLab