diff --git a/@Viewer/Viewer.m b/@Viewer/Viewer.m
index bb38bccc21670ca4084a92f9eeef113711304101..a23d7719e0813b633aff005c12a8b36fe5995265 100644
--- a/@Viewer/Viewer.m
+++ b/@Viewer/Viewer.m
@@ -2,34 +2,32 @@ classdef Viewer < handle
     %VIEWER Summary of this class goes here
     %   Detailed explanation goes here
     
-    properties(SetObservable, AbortSet)
+    properties(SetObservable)
         data
+        dims = 'xy'
         name = 'LightField'
-        state = 'xy'
         range = 'class'
-        curView = [1,1]
-        curPos = [1,1]
+        cv = [1,1]
+        cmap = gray
+        slice
+        clim
+        title
     end
     
     properties
         h  = []
         im = []
         ax = []
-        
-        slices
-    end
-    
-    properties(Dependent, Hidden)
-        range_
     end
     
     properties(Hidden)
-        classRange
-        currentRange
-        allRange
-        validStates = {'xy','uv','ux','vy','yx','vu','xu','yv'};
-        validRanges = {'class','current','all'};
-        statevec = logical([0,0,0,1,1]);
+        validDims = {'xy','uv','ux','vy','yx','vu','xu','yv'};
+        validRanges = {'class','slice','data'};
+        climClass
+        climData
+        gv
+        perm = [1,2,3,4,5]
+        maxView
     end
     
     methods
@@ -37,9 +35,11 @@ classdef Viewer < handle
             p = inputParser; p.StructExpand = true; p.KeepUnmatched = true;
             
             p.addRequired('data');
+            p.addParameter('dims' , obj.dims  ,@(dims) any(strcmpi(dims,obj.validDims)));
             p.addParameter('name' , obj.name  ,@ischar);
-            p.addParameter('state', obj.state ,@(state) any(strcmpi(state,obj.validStates)));
             p.addParameter('range', obj.range ,@(range) any(strcmpi(range,obj.validRanges)));
+            p.addParameter('cv'   , obj.cv    ,@isnumeric);
+            p.addParameter('cmap' , obj.cmap  ,@isnumeric);
             
             p.parse(data,varargin{:});
             
@@ -49,29 +49,24 @@ classdef Viewer < handle
                 obj.(fn) = res.(fn);
             end
             
-            addlistener(obj, 'data'   , 'PostSet', @(src,evnt) obj.updateSlices);
-            addlistener(obj, 'state'  , 'PostSet', @(src,evnt) obj.updateSlices);
-            addlistener(obj, 'curView', 'PostSet', @(src,evnt) obj.updateFigure);
-            addlistener(obj, 'curPos' , 'PostSet', @(src,evnt) obj.updateFigure);
-            addlistener(obj, 'range'  , 'PostSet', @(src,evnt) obj.updateFigure);
-            addlistener(obj, 'name'   , 'PostSet', @(src,evnt) obj.updateFigure);
+            obj.updateData();
+            obj.updateDims();
             
-            obj.updateSlices();
-            obj.setRanges();
-            obj.view;
-        end
-        
-        function range_ = get.range_(obj)
-            switch lower(obj.range)
-                case 'class'
-                    range_ = obj.classRange;
-                case 'current'
-                    u=obj.curView(1); v=obj.curView(2);
-                    range_ = obj.currentRange{u,v};
-                case 'all'
-                    range_ = obj.allRange;
-                otherwise
-            end
+            obj.updateSlice();
+            obj.updateCLim();
+            obj.updateTitle();
+            
+            addlistener(obj, 'data' , 'PostSet', @(src,evnt) obj.updateData);
+            addlistener(obj, 'dims' , 'PostSet', @(src,evnt) obj.updateDims);
+            addlistener(obj, 'name' , 'PostSet', @(src,evnt) obj.updateName);
+            addlistener(obj, 'range', 'PostSet', @(src,evnt) obj.updateRange);
+            addlistener(obj, 'cv'   , 'PostSet', @(src,evnt) obj.updateCV);
+            addlistener(obj, 'cmap' , 'PostSet', @(src,evnt) obj.updateCMap);
+            addlistener(obj, 'slice', 'PostSet', @(src,evnt) obj.updateSlice);
+            addlistener(obj, 'title', 'PostSet', @(src,evnt) obj.updateTitle);
+            addlistener(obj, 'clim' , 'PostSet', @(src,evnt) obj.updateCLim);
+            
+            obj.view();
         end
         
         function view(obj)
@@ -79,107 +74,165 @@ classdef Viewer < handle
                 obj.h  = figure;
                 obj.ax = gca;
                 
-                cv = num2cell(obj.curView);
-                
-                obj.im = imagesc(obj.ax,obj.slices{cv{:}});
-                colormap gray; axis image;
+                obj.im = imagesc(obj.ax,obj.slice);
+                obj.ax.Colormap = obj.cmap;
+                axis(obj.ax,'image');
                 
                 obj.h.KeyPressFcn         = @obj.KeyPressCallback;
                 obj.h.WindowButtonDownFcn = @obj.ButtonDownCallback;
                 obj.h.WindowButtonUpFcn   = @obj.ButtonUpCallback;
-                
-                obj.updateFigure();
             end
+            
+            obj.updateFigure();
         end
     end
     
     methods(Hidden)
-        function setRanges(obj)
-            obj.classRange = getrangefromclass(obj.data);
-            
-            cMin = cellfun(@(slice) min(slice(:)),obj.slices);
-            cMax = cellfun(@(slice) max(slice(:)),obj.slices);
-            
-            cMin(isnan(cMin)) = obj.classRange(1);
-            cMax(isnan(cMax)) = obj.classRange(2);
-            
-            minmax = cMin>=cMax;
-            cMin(minmax) = cMax(minmax)-1;
-            cMax(minmax) = cMin(minmax)+1;
+        function updateData(obj)
+            if islogical(obj.data)
+                data_ = obj.data;
+                data_ = uint8(data_);
+                obj.data = [];
+                obj.data = data_;
+            end
             
-            obj.currentRange = arrayfun(@(a,b) [a,b],cMin,cMax,'UniformOutput',false);
+            obj.gv = arrayfun(@(x) 1:x,size(obj.data),'UniformOutput',false);
+            obj.climClass = getrangefromclass(obj.data);
+            obj.climData = [min(obj.data(:)) max(obj.data(:))];
             
-            obj.allRange = [min(cMin(:)) max(cMax(:))];
+            obj.updateCV();
+        end
+        
+        function updateDims(obj)
+            obj.updatePerm();
+            obj.updateCV();
         end
         
-        function updateSlices(obj)
-            switch lower(obj.state)
+        function updatePerm(obj)
+            switch lower(obj.dims)
                 case 'xu'
-                    perm = [1,4,3,2,5];
+                    obj.perm = [1,4,3,2,5];
                 case 'ux'
-                    perm = [4,1,3,2,5];
+                    obj.perm = [4,1,3,2,5];
                 case 'yv'
-                    perm = [2,5,3,1,4];
+                    obj.perm = [2,5,3,1,4];
                 case 'vy'
-                    perm = [5,2,3,1,4];
+                    obj.perm = [5,2,3,1,4];
                 case 'xy'
-                    perm = [1,2,3,4,5];
+                    obj.perm = [1,2,3,4,5];
                 case 'yx'
-                    perm = [2,1,3,4,5];
+                    obj.perm = [2,1,3,4,5];
                 case 'uv'
-                    perm = [4,5,3,1,2];
+                    obj.perm = [4,5,3,1,2];
                 case 'vu'
-                    perm = [5,4,3,1,2];
+                    obj.perm = [5,4,3,1,2];
             end
+        end
+        
+        function updateName(obj)
+            obj.updateTitle();
+        end
+        
+        function updateRange(obj)
+            obj.updateCLim();
+        end
+        
+        function updateCV(obj)
+            obj.maxView = arrayfun(@(x) size(obj.data,x),obj.perm(4:5));
+            obj.cv = min(obj.maxView,max([1,1],obj.cv));
             
-            obj.slices = LF.toSlices(permute(obj.data,perm));
-            obj.statevec = false(1,5);
-            obj.statevec(perm(4:5)) = true;
+            obj.updateTitle();
+            obj.updateSlice();
         end
         
-        function updateFigure(obj)
+        function updateSlice(obj)
+            gv_ = obj.gv;
+            ccv = num2cell(obj.cv);
+            [gv_{obj.perm(4:5)}] = deal(ccv{:});
+            
+            obj.slice = permute(obj.data(gv_{:}),obj.perm);
+            
             if obj.validFigure()
-                
-                coordStr = {'x','y','c','u','v'};
-                coordStr(obj.statevec) = arrayfun(@num2str,obj.curView,'UniformOutput',false);
-                coordStr(~obj.statevec) = deal({':'});
-                coordStr = ['(' strjoin(coordStr,','),')'];
-                
-                title_{1} = [obj.name ' ' coordStr];
-                title(title_);
-                
-                cv = num2cell(obj.curView);
-                
-                obj.im.CData = obj.slices{cv{:}};
+                obj.im.CData = obj.slice;
                 obj.im.AlphaData = double(any(~isnan(obj.im.CData),3));
-                
-                obj.ax.CLim = obj.range_;
             end
         end
         
+        function updateCLim(obj)
+            switch lower(obj.range)
+                case 'class'
+                    obj.clim = obj.climClass;
+                case 'slice'
+                    obj.clim = [min(obj.slice(:)) max(obj.slice(:))];
+                case 'data'
+                    obj.clim = obj.climData;
+            end
+            
+            if diff(obj.clim)<=0
+                obj.clim(2) = obj.clim(1) + diff(getrangefromclass(obj.clim))/2;
+            end
+            
+            if obj.validFigure()
+                obj.ax.CLim = obj.clim;
+            end
+        end
+        
+        function updateTitle(obj)
+            coordVec = false(1,5);
+            coordVec(obj.perm(4:5)) = true;
+            
+            coordStr = {'x','y','c','u','v'};
+            coordStr(coordVec) = arrayfun(@num2str,obj.cv,'UniformOutput',false);
+            coordStr(~coordVec) = deal({':'});
+            coordStr = ['(' strjoin(coordStr,','),')'];
+            
+            obj.title = [obj.name,' ',coordStr];
+            
+            if obj.validFigure()
+                obj.ax.Title.String = obj.title;
+            end
+        end
+        
+        function updateCMap(obj)
+            if obj.validFigure()
+                obj.ax.Colormap = obj.cmap;
+            end
+        end
+        
+        function updateFigure(obj)
+            if ~obj.validFigure()
+                return
+            end
+            
+            obj.im.CData = obj.slice;
+            obj.im.AlphaData = double(any(~isnan(obj.im.CData),3));
+            obj.ax.CLim = obj.clim;
+            obj.ax.Title.String = obj.title;
+            obj.ax.Colormap = obj.cmap;
+        end
+        
         function KeyPressCallback(obj,~,evnt)
-            curView_ = obj.curView;
+            cv_ = obj.cv;
             switch evnt.Key
                 case    'uparrow'
-                    curView_(1) = curView_(1)-1;
+                    cv_(1) = cv_(1)-1;
                 case  'downarrow'
-                    curView_(1) = curView_(1)+1;
+                    cv_(1) = cv_(1)+1;
                 case  'leftarrow'
-                    curView_(2) = curView_(2)-1;
+                    cv_(2) = cv_(2)-1;
                 case 'rightarrow'
-                    curView_(2) = curView_(2)+1;
+                    cv_(2) = cv_(2)+1;
                 case 'space'
                     rangeInd = find(strcmp(obj.range,obj.validRanges));
                     rangeInd = mod(rangeInd,3)+1;
                     obj.range = obj.validRanges{rangeInd};
             end
             
-            sz = size(obj.slices);
-            obj.curView = min(sz,max([1,1],curView_));
+            obj.cv = min(obj.maxView,max([1,1],cv_));
         end
         
         function ButtonDownCallback(obj,~,~)
-            refView = obj.curView;
+            refView = obj.cv;
             refPos = obj.ax.CurrentPoint(1,[2 1]);
             
             obj.h.WindowButtonMotionFcn = ...
@@ -191,24 +244,20 @@ classdef Viewer < handle
         end
         
         function ButtonMotionCallback(obj,~,~,refView,refPos)
-            axSize = [diff(obj.ax.YLim) diff(obj.ax.XLim)];
+            axSize = [diff(obj.ax.YLim),diff(obj.ax.XLim)];
             axPos = obj.ax.CurrentPoint(1,[2,1]);
             
             switch obj.h.SelectionType
                 case 'normal'
-                    slicesSize = size(obj.slices);
-                    mv = 2.*(axPos - refPos)./axSize.*slicesSize;
-                    curView_ = refView + round(mv);
-                    obj.curView = min(slicesSize,max([1,1],curView_));
+                    mv = 2.*(axPos - refPos)./axSize.*obj.maxView;
+                    cv_ = refView + round(mv);
+                    obj.cv = min(obj.maxView,max([1,1],cv_));
                 case 'alt'
-                    obj.curPos = flip(axPos);
             end
         end
         
         function bool = validFigure(obj)
-            bool = ~isempty(obj.h) &&isvalid(obj.h) &&...
-                ~isempty(obj.ax)&&isvalid(obj.ax)&&...
-                ~isempty(obj.im)&&isvalid(obj.im);
+            bool = ~isempty(obj.im) && isvalid(obj.im);
         end
     end
 end
\ No newline at end of file