diff --git a/fsl/fslview/lightboxcanvas.py b/fsl/fslview/lightboxcanvas.py
index 5a3612a82842c18c18796b7379bd882abb8cb33e..1e5e7396d62e198b1674c07fea8981e2f9443d4c 100644
--- a/fsl/fslview/lightboxcanvas.py
+++ b/fsl/fslview/lightboxcanvas.py
@@ -47,22 +47,86 @@ class LightBoxCanvas(slicecanvas.SliceCanvas):
         'zmax'         : 'Last slice',
         'sliceSpacing' : 'Slice spacing',
         'ncols'        : 'Number of columns',
+        'showCursor'   : 'Show cursor',
         'zax'          : 'Z axis'}
 
-    _view = props.VGroup(('zmin',
+    _view = props.VGroup(('showCursor',
+                          'zmin',
                           'zmax',
                           'sliceSpacing',
                           'ncols',
                           'zax'))
 
     
+    def worldToCanvas(self, xpos, ypos, zpos):
+        """
+        Given an x/y/z location in the image list world (with xpos
+        corresponding to the horizontal screen axis, ypos to the
+        vertical axis, and zpos to the depth axis), converts
+        it into an x/y position, in world coordinates, on the
+        canvas.
+        """
+        sliceno = int(np.floor((zpos - self.zmin) / self.sliceSpacing))
+
+        xlen = self.imageList.bounds.getLen(self.xax)
+        ylen = self.imageList.bounds.getLen(self.yax)
+        
+        row = self._nrows - int(np.floor(sliceno / self.ncols)) - 1
+        col =               int(np.floor(sliceno % self.ncols))
+
+        xpos = xpos + xlen * col
+        ypos = ypos + ylen * row
+        
+        return xpos, ypos
+
+        
     def canvasToWorld(self, xpos, ypos):
         """
-        Given pixel x/y coordinates on this canvas, translates them
-        into the real world x/y/z coordinates of the displayed slice.
-        What order should the returned coordinates be in?
-        """ 
-        pass
+        Overwrites SliceCanvas.canvasToWorld. Given pixel x/y
+        coordinates on this canvas, translates them into the
+        real world x/y/z coordinates of the displayed slice.
+        Returns a 3-tuple containing the (x, y, z) coordinates
+        (in the dimension order of the image list space). If the
+        given canvas position is out of the image range, None
+        is returned.
+        """
+
+        nrows = self._nrows
+        ncols = self.ncols
+
+        screenx, screeny = slicecanvas.SliceCanvas.canvasToWorld(
+            self, xpos, ypos)
+
+        xmin = self.imageList.bounds.getLo( self.xax)
+        ymin = self.imageList.bounds.getLo( self.yax)
+        xlen = self.imageList.bounds.getLen(self.xax)
+        ylen = self.imageList.bounds.getLen(self.yax)
+
+        xmax = xmin + ncols * xlen
+        ymax = ymin + nrows * ylen
+
+        col     =         int(np.floor((screenx - xmin) / xlen))
+        row     = nrows - int(np.floor((screeny - ymin) / ylen)) - 1
+        sliceno = row * ncols + col
+
+        if screenx <  xmin or \
+           screenx >  xmax or \
+           screeny <  ymin or \
+           screeny >  ymax or \
+           sliceno <  0    or \
+           sliceno >= self._nslices:
+            return None
+
+        xpos = screenx -          col      * xlen
+        ypos = screeny - (nrows - row - 1) * ylen
+        zpos = self.zmin + (sliceno + 0.5) * self.sliceSpacing
+
+        pos = [0, 0, 0]
+        pos[self.xax] = xpos
+        pos[self.yax] = ypos
+        pos[self.zax] = zpos
+
+        return tuple(pos)
 
         
     def __init__(self,
@@ -175,13 +239,20 @@ class LightBoxCanvas(slicecanvas.SliceCanvas):
         (which is different from the former if the canvas has a scroll
         bar).
         """
-        zlen = self.zmax - self.zmin
         
-        self._nslices = int(np.floor(zlen / self.sliceSpacing))
-        self._nrows   = int(np.ceil(self._nslices / float(self.ncols)))
-
         xlen = self.imageList.bounds.getLen(self.xax)
         ylen = self.imageList.bounds.getLen(self.yax)
+        zlen = self.zmax - self.zmin
+        width, height = self.GetClientSize().Get()
+
+        if xlen   == 0 or \
+           ylen   == 0 or \
+           width  == 0 or \
+           height == 0:
+            return
+
+        self._nslices = int(np.floor(zlen / self.sliceSpacing))
+        self._nrows   = int(np.ceil(self._nslices / float(self.ncols))) 
 
         # no scrollbar -> display all rows
         if self._scrollbar is None:
@@ -189,9 +260,12 @@ class LightBoxCanvas(slicecanvas.SliceCanvas):
 
         # scrollbar -> display a selection of rows
         else:
-            width, height = self.GetClientSize().Get()
-            sliceWidth    = width / self.ncols
-            sliceHeight   = sliceWidth * (ylen / xlen)
+
+            sliceWidth  = width / self.ncols
+            sliceHeight = sliceWidth * (ylen / xlen)
+
+            if sliceWidth == 0 or sliceHeight == 0:
+                return
 
             self._rowsOnScreen = int(np.ceil(height / sliceHeight))
 
@@ -374,6 +448,40 @@ class LightBoxCanvas(slicecanvas.SliceCanvas):
                                      rowsOnScreen,
                                      True)
 
+
+    def _drawCursor(self):
+        """
+        Draws a cursor at the current canvas position (the SliceCanvas.pos
+        property).
+        """
+
+        xpos, ypos = self.worldToCanvas(*self.pos.xyz)
+
+        xmin, xmax = self.imageList.bounds.getRange(self.xax)
+        ymin, ymax = self.imageList.bounds.getRange(self.yax) 
+
+        xverts = np.zeros((2, 3))
+        yverts = np.zeros((2, 3)) 
+
+        xverts[:, self.xax] = xpos
+        xverts[0, self.yax] = ypos - 5
+        xverts[1, self.yax] = ypos + 5
+        xverts[:, self.zax] = self.pos.z + 1
+
+        yverts[:, self.yax] = ypos
+        yverts[:, self.xax] = [xpos - 5, xpos + 5]
+        yverts[:, self.zax] =  self.pos.z + 1
+
+        log.debug('Drawing cursor at {} - {}'.format(xpos, ypos))
+
+        gl.glBegin(gl.GL_LINES)
+        gl.glColor3f(0, 1, 0)
+        gl.glVertex3f(*xverts[0])
+        gl.glVertex3f(*xverts[1])
+        gl.glVertex3f(*yverts[0])
+        gl.glVertex3f(*yverts[1])
+        gl.glEnd() 
+
         
     def _draw(self, ev):
         """
@@ -426,60 +534,11 @@ class LightBoxCanvas(slicecanvas.SliceCanvas):
             for zi in range(startSlice, endSlice):
                 self._drawSlice(image,
                                 self._sliceIdxs[ i][zi],
-                                self._transforms[i][zi]) 
-
-        gl.glUseProgram(0)
-
-        self.SwapBuffers()
-
-
-class LightBoxPanel(wx.Panel):
-    """
-    Convenience Panel which contains a a LightBoxCanvas and a scrollbar,
-    and sets up mouse-scrolling behaviour.
-    """
-
-    def __init__(self, parent, *args, **kwargs):
-        """
-        Accepts the same parameters as the LightBoxCanvas constructor,
-        although if you pass in a scrollbar, it will be ignored.
-        """
-
-        wx.Panel.__init__(self, parent)
-
-        self.scrollbar = wx.ScrollBar(self, style=wx.SB_VERTICAL)
-        
-        kwargs['scrollbar'] = self.scrollbar
-        
-        self.canvas = LightBoxCanvas(self, *args, **kwargs)
-
-        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
-        self.SetSizer(self.sizer)
+                                self._transforms[i][zi])
 
-        self.sizer.Add(self.canvas,    flag=wx.EXPAND, proportion=1)
-        self.sizer.Add(self.scrollbar, flag=wx.EXPAND)
+        gl.glUseProgram(0) 
 
-        def scrollOnMouse(ev):
+        if self.showCursor:
+            self._drawCursor()
 
-            wheelDir = ev.GetWheelRotation()
-
-            if   wheelDir > 0: wheelDir = -1
-            elif wheelDir < 0: wheelDir =  1
-
-            curPos       = self.scrollbar.GetThumbPosition()
-            newPos       = curPos + wheelDir
-            sbRange      = self.scrollbar.GetRange()
-            rowsOnScreen = self.scrollbar.GetPageSize()
-
-            if self.scrollbar.GetPageSize() >= self.scrollbar.GetRange():
-                return
-            if newPos < 0 or newPos + rowsOnScreen > sbRange:
-                return
-            
-            self.scrollbar.SetThumbPosition(curPos + wheelDir)
-            self.canvas._updateDisplayBounds()
-            self.canvas.Refresh()
-
-        self.Bind(wx.EVT_MOUSEWHEEL, scrollOnMouse)
-
-        self.Layout()        
+        self.SwapBuffers()
diff --git a/fsl/fslview/lightboxpanel.py b/fsl/fslview/lightboxpanel.py
new file mode 100644
index 0000000000000000000000000000000000000000..53adad309f49a1d12bbf42cf99ba102dee6281c4
--- /dev/null
+++ b/fsl/fslview/lightboxpanel.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+#
+# lightboxpanel.py -
+#
+# Author: Paul McCarthy <pauldmccarthy@gmail.com>
+#
+
+import logging
+log = logging.getLogger(__name__)
+
+import wx
+
+import fsl.props                  as props
+import fsl.fslview.lightboxcanvas as lightboxcanvas
+
+class LightBoxPanel(wx.Panel, props.HasProperties):
+    """
+    Convenience Panel which contains a a LightBoxCanvas and a scrollbar,
+    and sets up mouse-scrolling behaviour.
+    """
+
+    def __init__(self, parent, *args, **kwargs):
+        """
+        Accepts the same parameters as the LightBoxCanvas constructor,
+        although if you pass in a scrollbar, it will be ignored.
+        """
+
+        wx.Panel.__init__(self, parent)
+        self.name = 'LightBoxPanel_{}'.format(id(self))
+
+        self.scrollbar = wx.ScrollBar(self, style=wx.SB_VERTICAL)
+        
+        kwargs['scrollbar'] = self.scrollbar
+        
+        self.canvas = lightboxcanvas.LightBoxCanvas(self, *args, **kwargs)
+
+        self.imageList = self.canvas.imageList
+
+        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
+        self.SetSizer(self.sizer)
+
+        self.sizer.Add(self.canvas,    flag=wx.EXPAND, proportion=1)
+        self.sizer.Add(self.scrollbar, flag=wx.EXPAND)
+
+        self.canvas.Bind(wx.EVT_LEFT_DOWN, self.onMouseEvent)
+        self.canvas.Bind(wx.EVT_MOTION,    self.onMouseEvent) 
+
+        self.Bind(wx.EVT_MOUSEWHEEL, self.onMouseScroll)
+
+        def move(*a):
+            xpos = self.imageList.location.getPos(self.canvas.xax)
+            ypos = self.imageList.location.getPos(self.canvas.yax)
+            zpos = self.imageList.location.getPos(self.canvas.zax)
+            self.canvas.pos.xyz = (xpos, ypos, zpos)
+
+        self.imageList.addListener('location', self.name, move)
+
+        def onDestroy(ev):
+            self.imageList.removeListener('location', self.name)
+            ev.Skip()
+
+        self.Layout()
+
+        
+    def onMouseEvent(self, ev):
+
+        if not ev.LeftIsDown():      return
+        if len(self.imageList) == 0: return
+
+        mx, my  = ev.GetPositionTuple()
+        w, h    = self.canvas.GetClientSize()
+
+        my = h - my
+
+        clickPos = self.canvas.canvasToWorld(mx, my)
+
+        if clickPos is None:
+            return
+
+        xpos, ypos, zpos = clickPos
+
+        log.debug('Mouse click on {}: '
+                  '({}, {} -> {: 5.2f}, {: 5.2f}, {: 5.2f})'.format(
+                      self.canvas.name, mx, my, xpos, ypos, zpos))
+
+        self.imageList.location.xyz = xpos, ypos, zpos
+        
+            
+    def onMouseScroll(self, ev):
+
+        wheelDir = ev.GetWheelRotation()
+
+        if   wheelDir > 0: wheelDir = -1
+        elif wheelDir < 0: wheelDir =  1
+
+        curPos       = self.scrollbar.GetThumbPosition()
+        newPos       = curPos + wheelDir
+        sbRange      = self.scrollbar.GetRange()
+        rowsOnScreen = self.scrollbar.GetPageSize()
+
+        if self.scrollbar.GetPageSize() >= self.scrollbar.GetRange():
+            return
+        if newPos < 0 or newPos + rowsOnScreen > sbRange:
+            return
+
+        self.scrollbar.SetThumbPosition(curPos + wheelDir)
+        self.canvas._updateDisplayBounds()
+        self.canvas.Refresh()
diff --git a/fsl/props/properties_types.py b/fsl/props/properties_types.py
index 7521f1407244e60ef28cd28e9478c5bc65a84e2e..429a7f3aafb4cba50d59d5ea29b66ba57ac5d895 100644
--- a/fsl/props/properties_types.py
+++ b/fsl/props/properties_types.py
@@ -468,6 +468,12 @@ class BoundsValueList(propvals.PropertyValueList):
         elif lname == 'xlen': return self.getLen(  0)
         elif lname == 'ylen': return self.getLen(  1)
         elif lname == 'zlen': return self.getLen(  2)
+        elif lname == 'xmin': return self.getMin(  0)
+        elif lname == 'ymin': return self.getMin(  1)
+        elif lname == 'zmin': return self.getMin(  2)
+        elif lname == 'xmax': return self.getMax(  0)
+        elif lname == 'ymax': return self.getMax(  1)
+        elif lname == 'zmax': return self.getMax(  2) 
         elif lname == 'all':  return self[:]
 
         raise AttributeError('{} has no attribute called {}'.format(
diff --git a/fsl/tools/fslview.py b/fsl/tools/fslview.py
index a7fac4a7965f0be8b19542bebbdcc5a9d6acff02..b1ef7ef3902ee49f3d924502527e48c7e0c13b57 100644
--- a/fsl/tools/fslview.py
+++ b/fsl/tools/fslview.py
@@ -12,9 +12,9 @@ import argparse
 import wx
 
 import fsl.fslview.orthopanel     as orthopanel
+import fsl.fslview.lightboxpanel  as lightboxpanel
 import fsl.fslview.locationpanel  as locationpanel
 import fsl.fslview.imagelistpanel as imagelistpanel
-import fsl.fslview.lightboxcanvas as lightboxcanvas
 
 import fsl.data.fslimage as fslimage
 import fsl.props         as props
@@ -92,11 +92,11 @@ class FslViewPanel(wx.Panel):
 
     def showLightBox(self):
 
-        if isinstance(self.mainPanel, lightboxcanvas.LightBoxPanel):
+        if isinstance(self.mainPanel, lightboxpanel.LightBoxPanel):
             return
 
-        mainPanel = lightboxcanvas.LightBoxPanel(self, self.imageList,
-                                                 glContext=self.glContext)
+        mainPanel = lightboxpanel.LightBoxPanel(self, self.imageList,
+                                                glContext=self.glContext)
         
         ctrlPanel = props.buildGUI(self, mainPanel.canvas)