image thumbnail
from keyControlPlugin by georg
A figure plugin class usable as keyPress callback Function.

keyControlPlugin
classdef keyControlPlugin < handle
    %KEYCONTROLPLUGIN                key-control plugin for plot figures
    %   KEYCONTROLPLUGIN is a simple class whose 'KEYPRESSFUNCTION' method
    %   can be used as a callback function for plot figures in order to
    %   add basic key-enabled scrolling and zooming functionality.
    %
    %   Usage example:
    %     t = 0:0.01:100 ;
    %     y = sin(t) ;
    %     c = keyControlPlugin('scrollFactor',0.25) ;
    %     plot(t,y) ;
    %     set(gcf,'KeyPressFcn',@c.keyPressFunction)
    %     c.keyPressFunctionInit(gcf)
    %
    %   For more examples see the attached TESTPLOTCONTROL script.
    %
    %   Use this plugin in combination with LINKAXES in order to control
    %   multiple plot figures, see examples
    %
    %   Options: (key-value style)
    %       ydisabled: [ false | true ], default: false
    %       zoomFactor: [ 0.1 ... 0.9 ], default: 0.5
    %       scrollFactor: [ 0 ... 1 ], default: 0.5
    %
    %   These keys are available in the current version:
    %       h ... list of available commands
    %       n ... next slice (jump by scrollFactor)
    %       b ... backwards (jump by scrollFactor)
    %       i ... zoom in (visiblerange = visiblerange*zoomFactor)
    %       o ... zoom out (visiblerange = visiblerange*(1+zoomFactor))
    %
    %   These modifiers are available
    %       Shift n ... jump to the beginning
    %       Shift b ... jump to the end
    %       Shift i ... zoom in (fast mode)
    %       Shift o ... show entire axis range
    %       Alt <COMMAND> ... apply any command to the y-axis
    %       AltShift <COMMAND> ... apply shift command to y-axis
    %
    %   Known issues:
    %     - In case the figure is not in default mode, the plugin may fail;
    %       it may even fail to be initialized. You will either notice
    %       no change or see a warning message.
    %       Use figure(...,'ToolBar','none') in case you won't use the mouse
    %       anyway.
    %
    %
    %   See also FIGURE, LINKAXES.
    
    %   georg ogris ::: spantec.at ::: fall 2011

    % Copyright (c) 2011 ::: georg ogris
    % All rights reserved.
    %
    % Redistribution and use in source and binary forms, with or without
    % modification, are permitted provided that the following conditions are
    % met:
    %
    %     * Redistributions of source code must retain the above copyright
    %       notice, this list of conditions and the following disclaimer.
    %     * Redistributions in binary form must reproduce the above copyright
    %       notice, this list of conditions and the following disclaimer in
    %       the documentation and/or other materials provided with the distribution
    %     * Neither the name of the author nor the names
    %       of its contributors may be used to endorse or promote products derived
    %       from this software without specific prior written permission.
    %
    % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    % POSSIBILITY OF SUCH DAMAGE.
    
    % -------------------------------------------------------------------
    properties (SetAccess = private, Hidden=true)
        xmin ;
        ymin ;
        xmax ;
        ymax ;
        axes ;
    end
    
    % -------------------------------------------------------------------
    properties (SetAccess = private)
        ydisabled = false ;
    end
    
    % -------------------------------------------------------------------
    properties (SetAccess = public)
        scrollFactor = 0.5 ;
        zoomFactor = 0.5 ;
    end
    
    % -------------------------------------------------------------------
    methods
        
        % ---------------------------------------------------------------
        function k = keyControlPlugin(varargin)
            nV = numel(varargin) ;
            if mod(nV,2)
                error('Options should be passed in key-value-style.')
            end
            %% parse options
            for iV = 1:2:nV
                if strcmpi('ydisabled',varargin{iV})
                    if ~islogical(varargin{iV+1}) || length(varargin{iV+1}) ~= 1
                        error('''ydisabled'' must be either true or false.') ;
                    end
                    k.ydisabled = varargin{iV+1} ;
                elseif strcmpi('scrollFactor',varargin{iV})
                    if varargin{iV+1} < 0 || varargin{iV+1} > 1
                        error('''scrollFactor'' must be in [0 ... 1].') ;
                    end
                    k.scrollFactor = varargin{iV+1} ;
                elseif strcmpi('zoomFactor',varargin{iV})
                    if varargin{iV+1} < 0.1 || varargin{iV+1} > 0.9
                        error('''zoomFactor'' must be in [0.1 ... 0.9].') ;
                    end
                    k.zoomFactor = varargin{iV+1} ;
                end
            end
            
        end
        
        % ---------------------------------------------------------------
        function keyPressFunction(k,h,e)
            %% initialize maximum ratings
            if isempty(k.xmax)
                k.keyPressFunctionInit(h) ;
            end
            
            %% basic checking whether something has to be changed
            switch e.Key
                case {'n','b','i','o'}
                    k.axes = get(h,'Children') ;
                    k.axes = k.axes(ishghandle(k.axes)) ;
                    nA = length(k.axes) ;
                    if ~nA
                        return
                    end
                case 'h'
                    k.helptext() ;
                otherwise
                    return
            end
            
            %% modifier key handling
            mod = [e.Modifier{:}] ;
            if isempty(mod)
                current.lim = 'xlim' ;
                current.max = k.xmax ;
                current.min = k.xmin ;
                current.fun = @xlim ;
                current.ext = false ;
            else
                switch mod
                    case 'alt'
                        if k.ydisabled
                            return
                        end
                        current.lim = 'ylim' ;
                        current.max = k.ymax ;
                        current.min = k.ymin ;
                        current.fun = @ylim ;
                        current.ext = false ;
                    case 'shift'
                        current.lim = 'xlim' ;
                        current.max = k.xmax ;
                        current.min = k.xmin ;
                        current.fun = @xlim ;
                        current.ext = true ;
                    case {'shiftalt','altshift'}
                        if k.ydisabled
                            return
                        end
                        current.lim = 'ylim' ;
                        current.max = k.ymax ;
                        current.min = k.ymin ;
                        current.fun = @ylim ;
                        current.ext = true ;
                    otherwise
                        return
                end
            end
            
            %% the actual key-stroke handling
            
            switch e.Key
                case 'n'
                    l = get(k.axes(1),current.lim) ;
                    if l(2) >= current.max
                        return
                    end
                    r = diff(l) ;
                    l = l + r*k.scrollFactor ;
                    if l(2)>current.max || current.ext
                        l = [current.max-r current.max] ;
                    end
                    for iA = 1:length(k.axes)
                        current.fun(k.axes(iA),l)
                    end
                case 'b'
                    l = get(k.axes(1),current.lim) ;
                    if l(1) <= current.min
                        return
                    end
                    r = diff(l) ;
                    l = l - r*k.scrollFactor ;
                    if l(1)<current.min || current.ext
                        l = [current.min current.min+r] ;
                    end
                    for iA = 1:length(k.axes)
                        current.fun(k.axes(iA),l)
                    end
                case 'i'
                    l = get(k.axes(1),current.lim) ;
                    if ~current.ext
                        r = diff(l)*(k.zoomFactor/2) ;
                    else
                        r = diff(l)*0.45 ;
                    end
                    l = l + [r -r] ;
                    for iA = 1:length(k.axes)
                        current.fun(k.axes(iA),l)
                    end
                case 'o'
                    l = get(k.axes(1),current.lim) ;
                    r = diff(l)*(1+k.zoomFactor/2) ;
                    l = l + [-r r] ;
                    if l(1)<current.min || current.ext
                        l(1) = current.min ;
                    end
                    if l(2)>current.max || current.ext
                        l(2) = current.max ;
                    end
                    for iA = 1:length(k.axes)
                        current.fun(k.axes(iA),l)
                    end
            end
            
        end
        
    end
    
    % -------------------------------------------------------------------
    methods (Access = private)
        
        % ---------------------------------------------------------------
        function keyPressFunctionInit(k,h)
            
            if ~ishghandle(h)
                figure(h)
                return
            end
            
            k.axes = get(h,'Children') ;
            k.axes = k.axes(ishghandle(k.axes)) ;
            nA = length(k.axes) ;
            if ~nA
                return
            end
            
            xl = get(k.axes(1),'xlim') ;
            k.xmin = xl(1) ;
            k.xmax = xl(2) ;
            for iA = 2:length(k.axes)
                xl = get(k.axes(iA),'xlim') ;
                k.xmin = min(k.xmin,xl(1)) ;
                k.xmax = max(k.xmax,xl(2)) ;
            end
            
            if ~k.ydisabled
                yl = get(k.axes(1),'ylim') ;
                k.ymin = yl(1) ;
                k.ymax = yl(2) ;
                for iA = 2:length(k.axes)
                    yl = get(k.axes(iA),'ylim') ;
                    k.ymin = min(k.ymin,yl(1)) ;
                    k.ymax = max(k.ymax,yl(2)) ;
                end
            end
            
            for iA = 1:length(k.axes)
                xlim([k.xmin k.xmax]);
                if ~k.ydisabled
                    ylim([k.ymin k.ymax]);
                end
            end
            
        end
        
    end
    
    % -------------------------------------------------------------------
    methods (Static = true)
        
        % ---------------------------------------------------------------
        function helptext()
            fprintf(' \n') ;
            fprintf(' These keys are available in the current version:\n') ;
            fprintf(' h ... this list\n');
            fprintf(' n ... next slice (jump by scrollFactor)\n') ;
            fprintf(' b ... backwards (jump by scrollFactor)\n') ;
            fprintf(' i ... zoom in (visiblerange = visiblerange*zoomFactor)\n') ;
            fprintf(' o ... zoom out (visiblerange = visiblerange*(1+zoomFactor))\n') ;
            fprintf(' \n') ;
            fprintf(' These modifiers are available\n') ;
            fprintf(' Shift n ... jump to the beginning\n') ;
            fprintf(' Shift b ... jump to the end\n') ;
            fprintf(' Shift i ... zoom in (fast mode)\n') ;
            fprintf(' Shift o ... show entire axis range\n') ;
            fprintf(' Alt <COMMAND> ... apply any command to the y-axis\n') ;
            fprintf(' AltShift <COMMAND> ... apply shift command to y-axis\n') ;
            fprintf(' \n') ;
        end
        
    end
    
end

Contact us