Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

Revision 4dbf0ec391b877f21402aed9e8351fe8f7468d14 authored by D019 Rig on 19 December 2019, 23:25:22 UTC, committed by D019 Rig on 19 December 2019, 23:25:22 UTC
Update Calibration
1 parent 4cac1d4
  • Files
  • Changes
  • cb6e09d
  • /
  • Tools
  • /
  • Program_Spike2_SON
  • /
  • dragzoom.m
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • revision
  • directory
  • content
revision badge
swh:1:rev:4dbf0ec391b877f21402aed9e8351fe8f7468d14
directory badge Iframe embedding
swh:1:dir:ec5b34a28116a7e19dae0fc31e4a7f57ba18c05b
content badge Iframe embedding
swh:1:cnt:87d4b254bfaefb426463c717c5cc62c4c8f270e9

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • revision
  • directory
  • content
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
dragzoom.m
function dragzoom(varargin)
%DRAGZOOM Drag and zoom tool
%
% Description:
%   DRAGZOOM allows you to interactively manage the axes in figure.
%   This simple function for usable draging and zooming of axes, using the 
%   mouse and the keyboard shortcuts.
%
%   - Supported 2D-Plots, 3D-plots, semilogx-plots, semilogy-plots, loglog-plots and Images;
%   - Supported subplots (mixed axes).
%
%
% Using:
%   dragzoom()
%   dragzoom(hFig)
%   dragzoom(hAx)
%   dragzoom(hAxes)
%   dragzoom(hFig, status)
%   dragzoom(status)
%
%
% Input:
%   hObj -- Figure or axes handle or array of axes handles
%   status -- 'on' or 'off'
%
%
% Control Enable Status of DRAGZOOM:
%   dragzoom(hFig, 'on') 	: Enable DRAGZOOM for figure "hFig"
%   dragzoom(hFig, 'off') 	: Disable DRAGZOOM for figure "hFig"
%   dragzoom('on')          : Enable DRAGZOOM for figure "GCF"
%   dragzoom('off')         : Disable DRAGZOOM for figure "GCF"
%
%
% Interactive mode:
%   Available the following actions:
% 
%   Mouse actions in 2D mode:
%   Normal mode:
%       single-click and holding LB : Activation Drag mode
%       single-click and holding RB : Activation Rubber Band for region zooming
%       single-click MB             : Activation 'Extend' Zoom mode
%       scroll wheel MB             : Activation Zoom mode
%       double-click LB, RB, MB     : Reset to Original View
% 
%   Magnifier mode:
%       single-click LB             : Not Used
%       single-click RB             : Not Used
%       single-click MB             : Reset Magnifier to Original View
%       scroll MB                   : Change Magnifier Zoom
%       double-click LB             : Increase Magnifier Size
%       double-click RB             : Decrease Magnifier Size
% 
%   Hotkeys in 2D mode:
%       '+'                         : Zoom plus
%       '-'                         : Zoom minus
%       '0'                         : Set default axes (reset to original view)
%       'uparrow'                   : Up or down (inrerse) drag
%       'downarrow'                 : Down or up (inverse) drag
%       'leftarrow'                 : Left or right (inverse) drag
%       'rightarrow'                : Right or left (inverse) drag
%       'c'                         : On/Off Pointer Symbol 'fullcrosshair'
%       'g'                         : On/Off Axes Grid
%       'x'                         : If pressed and holding, zoom and drag works only for X axis
%       'y'                         : If pressed and holding, zoom and drag works only for Y axis
%       'm'                         : If pressed and holding, Magnifier mode on
%       'l'                         : On/Off Synchronize XY manage of 2-D axes 
%       'control+l'                 : On Synchronize X manage of 2-D axes 
%       'alt+l'                     : On Synchronize Y manage of 2-D axes 
%       's'                         : On/Off Smooth Plot (Experimental)
% 
%   Mouse actions in 3D mode:
%       single-click and holding LB : Activation Drag mode
%       single-click and holding MB : Activation 'Extend' Zoom mode
%       single-click and holding RB : Activation Rotate mode
%       scroll wheel MB             : Activation Zoom mode
%       double-click LB, RB, MB     : Reset to Original View
% 
%   Hotkeys in 3D mode:
%       '+'                         : Zoom plus
%       '-'                         : Zoom minus  
%       '0'                         : Set default axes (reset to original view)
%       'uparrow'                   : Rotate up-down
%       'downarrow'                 : Rotate down-up
%       'leftarrow'                 : Rotate left-right
%       'rightarrow'                : Rotate right-left
%       'ctrl'+'uparrow'            : Up or down (inrerse) drag
%       'ctrl'+'downarrow'          : Down or up (inverse) drag
%       'ctrl'+'leftarrow'          : Left or right (inverse) drag
%       'ctrl'+'rightarrow'         : Right or left (inverse) drag
%       '1'                         : Go to X-Y view
%       '2'                         : Go to X-Z view
%       '3'                         : Go to Y-Z view
%       'v'                         : On/Off Visible Axes
%       'f'                         : On/Off Fixed Aspect Ratio
%       'g'                         : On/Off Axes Grid
% 
%
% Example:
%   x = -pi:0.1:pi;
%   y = sin(x);
%   figure; plot(x, y);
%   dragzoom
%
% Example:
%   I = imread('cameraman.tif');
%   figure; imshow(I, []);
%   dragzoom
%
% Example:
%   figure;
%   x = -pi*2:0.1:pi*2;
%   y1 = sin(x);
%   y2 = cos(x);
%   subplot(2,1,1); plot(x,y1, '.-r')
%   title('Income')
%   subplot(2,1,2); plot(x, y2, 'o-b')
%   title('Outgo')
%   dragzoom;
%
% Example:
%   figure;
%   x = -pi*2:0.1:pi*2;
%   y1 = sin(x);
%   y2 = cos(x);
%   hax1 = subplot(2,1,1); plot(hax1, x, y1, '.-r')
%   hax2 = subplot(2,1,2); plot(hax2, x, y2, 'o-b')
%   dragzoom(hax1); % manage only axes 1
%
% Example:
%   figure;
%   x = -pi*2:0.1:pi*2;
%   y1 = sin(x);
%   y2 = cos(x);
%   hax1 = subplot(2,1,1); plot(hax1, x, y1, '.-r')
%   hax2 = subplot(2,1,2); plot(hax2, x, y2, 'o-b')
%   dragzoom([hax1, hax2]); % manage axes 1 and axes 2
%
% Example:
%   figure;
%   k = 5;
%   n = 2^k-1;
%   [x,y,z] = sphere(n);
%   surf(x,y,z);
%   dragzoom;
%
% Example:
%   x = 0:100;
%   y = log10(x);
%   figure;
%   semilogx(x, y, '*-b')
%   dragzoom;
%
%
% See Also PAN, ZOOM, PANZOOM, ROTATE3D
%

% -------------------------------------------------------------------------
%   Version   : 0.9.7
%   Author    : Evgeny Pr aka iroln <esp.home@gmail.com>
%   Created   : 10.07.10
%   Updated   : 05.06.11
%
%   Copyright : Evgeny Pr (c) 2010-2011
% -------------------------------------------------------------------------

%TODO: Show Pixel Info (Pixel Value(s)) for Images
%TODO: "Sticking to Data" PointerCross

error(nargchk(0, 2, nargin));


% handles
hFig = [];
hAx = [];
hAxes = [];

% variables
mOrigFigName = [];
mOrigCallbacks = [];
mAxesInfo = [];
mDragStartX = [];
mDragStartY = [];
mDragKeysX = [];
mDragKeysY = [];
mDragShiftStep = [];
mDragSaveShiftStep = [];
mDragShiftStepInc = [];
mDragSave3DShiftStep = [];
mDrag3DShiftStep = [];
mZoomScroll = [];
mZoomMinPow = [];
mZoomMaxPow = [];
mZoomNum = [];
mZoomExtendNum = [];
mZoomKeysNum = [];
mZoom3DExtendNum = [];
mZoom3DKeysNum = [];
mZoom3DIndex = [];
mDefaultZoomGrid = [];
mDefaultZoomSteps = [];
mZoomGrid = [];
mZoomSteps = [];
mZoomIndexX = [];
mZoomIndexY = [];
mZoom3DStartX = [];
mZoom3DStartY = [];
mZoom3DBindX = [];
mZoom3DBindY = [];
mDefaultXLim = [];
mDefaultYLim = [];
mDefaultAxPos = [];
mRotStartAZ = [];
mRotStartEL = [];
mRotStartX = [];
mRotStartY = [];
mRot3DKeysInc = [];
mPointerCross = [];
mRubberBand = [];
mRbEdgeColor = [];
mRbFaceColor = [];
mRbFaceAlpha = [];
mMagnifier = [];
mMgSize = [];
mMgMinSize = [];
mMgMaxSize = [];
mMgZoom = [];
mMgMinZoom = [];
mMgMaxZoom = [];
mMgLinesWidth = [];
mMgShadow = [];
mMgSizeStep = [];
mMgZoomStep = [];
mMgDirection = [];
mLinkOpt = 'xy';

% flags
fIsEnabled = false;
fIsSelectedCurrentAxes = true;
fIsDragAllowed = false;
fIsZoomExtendAllowed = false;
fIsZoomExtend3DAllowed = false;
fIsRotate3DAllowed = false;
fIsRubberBandOn = false;
fIsPointerCross = false;
fIsAxesGrid = false;
fIsSmoothing = false;
fIsEnableDragX = true;
fIsEnableDragY = true;
fIsEnableZoomX = true;
fIsEnableZoomY = true;
fIsAxes2D = false;
fIsImage = false;
fIsMagnifierOn = false;
fIsLinkAxesOn = false;
fIsEnableControl = false;
fIsMouseOnLegend = false;


% Initialize and Setup
Initialize(varargin{:})
%--------------------------------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%==========================================================================
    function Setup()
        %Setup setup options
        
        % Drag Options
        mDragKeysX = 'normal';      % 'normal', 'reverse'
        mDragKeysY = 'normal';      % 'normal', 'reverse'
        mDragShiftStep = 3;         % step dragging on keys
        mDragShiftStepInc = 1;      % increase speed dragging on keys
        mDrag3DShiftStep = 10;      % step dragging 3D on keys
        
        % Zoom Options
        mZoomScroll = 'normal';     % 'normal', 'reverse'
        mZoomMinPow = 0;            % min zoom percent 10 ^ mZoomMinPow
        mZoomMaxPow = 5;            % max zoom perzent 10 ^ mZoomMaxPow
        mZoomNum = 51;              % count steps of log zoom grid
        mZoomExtendNum = 301;       % count steps of log grid zoom extend for 2D
        mZoomKeysNum = 181;         % count steps of log grid zoom for keys for 2D
        mZoom3DExtendNum = 201;     % count steps of log grid zoom extend for 3D
        mZoom3DKeysNum = 181;       % count steps of log grid zoom for keys for 3D
        
        % Rubber Band Options
        mRbEdgeColor = 'k';         % rubber band edge color
        mRbFaceColor = 'none';      % rubber band face color
        mRbFaceAlpha = 1;           % rubber band face alpha (transparency)
        
        % Magnifier Options
        mMgSize = 100;              % default size of magnifier (pixels)
        mMgMinSize = 50;            % min size of magnifier
        mMgMaxSize = 200;           % max size of magnifier
        mMgZoom = 2;                % default zoom on magnifier
        mMgMinZoom = 1;             % min zoom on magnifier
        mMgMaxZoom = 100;           % max zoom on magnifier
        mMgLinesWidth = 1;          % lines width on magnifier
        mMgShadow = 0.95;           % shadow area without magnifier
        mMgSizeStep = 15;           % step change in the magnifier size
        mMgZoomStep = 1.2;          % step change in the magnifier zoom
        
        % Rotate Options
        mRot3DKeysInc = 3;          % rotate increase for keys
    end
%--------------------------------------------------------------------------

%==========================================================================
    function Initialize(varargin)
        %Initialize initialize tool
        
        % Parse Input Arguments
        isWithStatus = ParseInputs(varargin{:});
        
        if isempty(hAxes), return; end
        
        hAx = hAxes(1);
        set(hFig, 'CurrentAxes', hAx);
        
        % setup tool
        Setup();
        
        % initialize tool
        UserData = get(hFig, 'UserData');
        
        if (isfield(UserData, 'axesinfo') && isWithStatus)
            mAxesInfo = UserData.axesinfo;
            mOrigCallbacks = UserData.origcallbacks;
            mOrigFigName = UserData.origfigname;
        else
            % first call dragzoom or call without enable status
            if ~isfield(UserData, 'origfigname')
                mOrigFigName = get(hFig, 'Name');
            end
            
            if isfield(UserData, 'origcallbacks')
                mOrigCallbacks = UserData.origcallbacks;
                SetOriginalCallbacks();
            end
            
            % save original callbacks
            SaveOriginalCallbacks();
            
            % get info about all axes and create axes info struct
            mAxesInfo = GetAxesInfo();
            
            % save initialize view for all axes
            for i = 1:numel(mAxesInfo)
                resetplotview(mAxesInfo(i).handle, 'InitializeCurrentView');
            end
            
            UserData.axesinfo = mAxesInfo;
            UserData.origcallbacks = mOrigCallbacks;
            UserData.origfigname = mOrigFigName;
            
            if ~isfield(UserData, 'tools')
                UserData.tools.pointercross = mPointerCross;
                UserData.tools.islinkaxeson = fIsLinkAxesOn;
            end
            
            set(hFig, 'UserData', UserData);    
        end
        
        DeleteOldTools();
        
        axi = GetCurrentAxesIndex();
        SetCurrentAxes(axi);
        SetDefaultZoomGrid();
        SetFigureName();
        
        mDragSaveShiftStep = mDragShiftStep;
        mDragSave3DShiftStep = mDrag3DShiftStep;
        
        % In case the figure will be saved
        set(hFig, 'CreateFcn', {@CreateFigureCallback});
        
        if fIsEnabled
            SetCallbacks();
        else
            SetOriginalCallbacks();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SaveOriginalCallbacks()
        %SaveOriginalCallbacks
        
        mOrigCallbacks.window_button_down_fcn   = get(hFig, 'WindowButtonDownFcn');
        mOrigCallbacks.window_button_up_fcn     = get(hFig, 'WindowButtonUpFcn');
        mOrigCallbacks.window_button_motion_fcn = get(hFig, 'WindowButtonMotionFcn');
        mOrigCallbacks.window_scroll_whell_fcn  = get(hFig, 'WindowScrollWheelFcn');
        mOrigCallbacks.window_key_press_fcn     = get(hFig, 'WindowKeyPressFcn');
        mOrigCallbacks.window_key_release_fcn   = get(hFig, 'WindowKeyReleaseFcn');
        mOrigCallbacks.create_fcn               = get(hFig, 'CreateFcn');
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetOriginalCallbacks()
        %SetOriginalCallbacks
        
        set(hFig, ...
            'WindowButtonDownFcn',      mOrigCallbacks.window_button_down_fcn, ...
        	'WindowButtonUpFcn',        mOrigCallbacks.window_button_up_fcn, ...
        	'WindowButtonMotionFcn',    mOrigCallbacks.window_button_motion_fcn, ...
        	'WindowScrollWheelFcn',     mOrigCallbacks.window_scroll_whell_fcn, ...
        	'WindowKeyPressFcn',        mOrigCallbacks.window_key_press_fcn, ...
        	'WindowKeyReleaseFcn',      mOrigCallbacks.window_key_release_fcn, ...
        	'CreateFcn',                mOrigCallbacks.create_fcn);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetCallbacks()
        %SetCallbacks
        
        if fIsAxes2D
            % 2D mode
            SetFigureCallbacks2D();
        else
            % 3D mode
            SetFigureCallbacks3D();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetFigureCallbacks2D()
        %SetFigureCallbacks2D set callback-functions for processing figure events in mode 2D
        
        set(hFig, ...
            'WindowButtonDownFcn',      {@WindowButtonDownCallback2D}, ...
            'WindowButtonUpFcn',        {@WindowButtonUpCallback2D}, ...
            'WindowButtonMotionFcn',    {@WindowButtonMotionCallback2D}, ...
            'WindowScrollWheelFcn',     {@WindowScrollWheelFcn2D}, ...
            'WindowKeyPressFcn',        {@WindowKeyPressCallback2D}, ...
            'WindowKeyReleaseFcn',      {@WindowKeyReleaseCallback2D});
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetFigureCallbacks3D()
        %SetFigureCallbacks3D set callback-functions for processing figure events in mode 3D
        
        set(hFig, ...
            'WindowButtonDownFcn',      {@WindowButtonDownCallback3D}, ...
            'WindowButtonUpFcn',        {@WindowButtonUpCallback3D}, ...
            'WindowButtonMotionFcn',    {@WindowButtonMotionCallback3D}, ...
            'WindowScrollWheelFcn',     {@WindowScrollWheelFcn3D}, ...
            'WindowKeyPressFcn',        {@WindowKeyPressCallback3D}, ...
            'WindowKeyReleaseFcn',      {@WindowKeyReleaseCallback3D});
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowButtonDownCallback2D(src, evnt)    %#ok
        %WindowButtonDownCallback2D
        
        if fIsMouseOnLegend, return; end
        
        clickType = get(src, 'SelectionType');
        
        switch clickType
            case 'normal'
                DragMouseBegin();
                mMgDirection = 'plus';
            case 'open'
                if fIsMagnifierOn
                    MagnifierSizeChange(mMgDirection);
                else
                    ResetAxesToOrigView();
                end
            case 'alt'
                RubberBandBegin();
                mMgDirection = 'minus';
            case 'extend'
                if fIsMagnifierOn
                    MagnifierReset();
                else
                    ZoomMouseExtendBegin();
                end
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowButtonUpCallback2D(src, evnt)      %#ok
        %WindowButtonUpCallback2D
        
        DragMouseEnd();
        ZoomMouseExtendEnd();
        RubberBandEnd();
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowButtonMotionCallback2D(src, evnt)  %#ok
        %WindowButtonMotionCallback2D
                
        if ~(fIsMagnifierOn || fIsDragAllowed || fIsRubberBandOn)
            % set current axes under cursor
            SelectAxesUnderCursor();
        end
        
        if fIsEnableControl
            DragMouse();
            RubberBandUpdate();
            MagnifierUpdate();
        end
        
        ZoomMouseExtend();
        PointerCrossUpdate();
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowScrollWheelFcn2D(src, evnt)        %#ok
        %WindowScrollWheelFcn2D
        
        if fIsMouseOnLegend, return; end
        
        % Update Zoom Info
        % because it can be changed function 'zoom'
        UpdateCurrentZoomAxes();
        
        switch mZoomScroll
            case 'normal'
                directions = {'minus', 'plus'};
            case 'reverse'
                directions = {'plus', 'minus'};
        end
        
        verScrollCount = evnt.VerticalScrollCount;
        
        if (verScrollCount > 0)
            direction = directions{1};
        elseif (verScrollCount < 0)
            direction = directions{2};
        else
            return;
        end
        
        % if fIsEnableControl
        ZoomMouse(direction);
        PointerCrossUpdate();
        % end
        MagnifierZoomChange(direction);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowKeyPressCallback2D(src, evnt)      %#ok
        %WindowKeyPressCallback2D
        
        modifier = evnt.Modifier;
        
        switch evnt.Key
            case '0'
                ResetAxesToOrigView();
            case {'equal', 'add'}
                ZoomKeys('plus');
            case {'hyphen', 'subtract'}
                ZoomKeys('minus');
            case 'leftarrow'
                DragKeys('left');
            case 'rightarrow'
                DragKeys('right');
            case 'uparrow'
                DragKeys('up');
            case 'downarrow'
                DragKeys('down');
            case 'c'
                SetPointerCrossKeys();
            case 'g'
                SetAxesGridKeys();
            case 'x'
                DragEnable('y', 'off');
                ZoomEnable('y', 'off');
            case 'y'
                DragEnable('x', 'off');
                ZoomEnable('x', 'off');
            case 'm'
                if fIsEnableControl
                    MagnifierOn();
                end
            case 'l'
                SetLinkAxesKeys(modifier);
            case 's'
                % smooth plot
                SetSmoothKeys();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowKeyReleaseCallback2D(src, evnt)    %#ok
        %WindowKeyReleaseCallback2D
        
        switch evnt.Key
            case {'leftarrow', 'rightarrow', 'uparrow', 'downarrow'}
                mDragShiftStep = mDragSaveShiftStep;
            case 'x'
                DragEnable('y', 'on');
                ZoomEnable('y', 'on');
            case 'y'
                DragEnable('x', 'on');
                ZoomEnable('x', 'on');
            case 'm'
                MagnifierOff();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowButtonDownCallback3D(src, evnt)    %#ok
        %WindowButtonDownCallback3D
        
        if fIsMouseOnLegend, return; end
        
        clickType = get(src, 'SelectionType');
        
        switch clickType
            case 'normal'
                DragMouseBegin3D();
            case 'open'
                ResetAxesToOrigView3D();
            case 'alt'
                RotateMouseBegin3D();
            case 'extend'
                ZoomMouseExtendBegin3D();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowButtonUpCallback3D(src, evnt)    %#ok
        %WindowButtonUpCallback3D
                
        DragMouseEnd3D();
        ZoomMouseExtendEnd3D();
        RotateMouseEnd3D();
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowButtonMotionCallback3D(src, evnt)    %#ok
        %WindowButtonMotionCallback3D
                
        if ~(fIsDragAllowed || fIsZoomExtend3DAllowed || fIsRotate3DAllowed)
            SelectAxesUnderCursor();
        end
        
        if fIsEnableControl
            DragMouse3D();
            RotateMouse3D();
        end
        ZoomMouseExtend3D();
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowScrollWheelFcn3D(src, evnt)    %#ok
        %WindowScrollWheelFcn3D
        
        if fIsMouseOnLegend, return; end
        
        UpdateCurrentZoomAxes3D();
        
        switch mZoomScroll
            case 'normal'
                directions = {'minus', 'plus'};
            case 'reverse'
                directions = {'plus', 'minus'};
        end
        
        verScrollCount = evnt.VerticalScrollCount;
        
        if (verScrollCount > 0)
            direction = directions{1};
        elseif (verScrollCount < 0)
            direction = directions{2};
        else
            return;
        end
        
        % if fIsEnableControl
        ZoomMouse3D(direction);
        % end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowKeyPressCallback3D(src, evnt)    %#ok
        %WindowKeyPressCallback3D
        
        isModifier = ~isempty(intersect(evnt.Modifier, {'control', 'command'}));
        
        switch evnt.Key
            case {'equal', 'add'}
                ZoomKeys3D('plus');
            case {'hyphen', 'subtract'}
                ZoomKeys3D('minus');
            case 'leftarrow'
                if isModifier
                    DragKeys3D('left');
                else
                    RotateKeys3D('az-');
                end
            case 'rightarrow'
                if isModifier
                    DragKeys3D('right');
                else
                    RotateKeys3D('az+');
                end
            case 'uparrow'
                if isModifier
                    DragKeys3D('up');
                else
                    RotateKeys3D('el-');
                end
            case 'downarrow'
                if isModifier
                    DragKeys3D('down');
                else
                    RotateKeys3D('el+');
                end
            case '0'
                ResetAxesToOrigView3D();
            case '1'
                RotateKeys3D('xy');
            case '2'
                RotateKeys3D('xz');
            case '3'
                RotateKeys3D('yz');
            case 'v'
                VisibleAxesKeys3D();
            case 'f'
                SwitchAspectRatioKeys3D()
            case 'g'
                SetAxesGridKeys();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function WindowKeyReleaseCallback3D(src, evnt)    %#ok
        %WindowKeyReleaseCallback3D
        
        switch evnt.Key
            case {'equal', 'add', 'hyphen', 'subtract'}
                SetDefaultZoomGrid3D();
            case {'leftarrow', 'rightarrow', 'uparrow', 'downarrow'}
                mDrag3DShiftStep = mDragSave3DShiftStep;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function CreateFigureCallback(src, evnt)    %#ok
        %CreateFigureCallback
        
        hFig = src;
        
        UserData = get(hFig, 'UserData');
        mAxesInfo = UserData.axesinfo;
        mOrigCallbacks = UserData.origcallbacks;
        mOrigFigName = UserData.origfigname;
        hAxes = arrayfun(@(x) x.handle, mAxesInfo);
        
        axi = GetCurrentAxesIndex();
        SetCurrentAxes(axi)
        DeleteOldTools();
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetFigureName()
        %SetFigureName Set Name of Figure
        
        enableStatus = 'off';
        if fIsEnabled
            enableStatus = 'on';
        end
        
        syncMode = 'Normal';
        if fIsLinkAxesOn
            syncMode = sprintf('Synchronized %s', upper(mLinkOpt));
        end
        
        sep = '';
        if ~isempty(mOrigFigName)
            sep = ':';
        end
        
        newName = sprintf('[DRAGZOOM : "%s" (%s)]%s %s', ...
            enableStatus, syncMode, sep, mOrigFigName);
        set(hFig, 'Name', newName)
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragMouseBegin()
        %DragMouseBegin begin draging
        
        if (~fIsDragAllowed && ~fIsMagnifierOn)
            [cx, cy] = GetCursorCoordOnWindow();
            
            mDragStartX = cx;
            mDragStartY = cy;
            
            fIsDragAllowed = true;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragMouseEnd()
        %DragMouseEnd end draging

        if fIsDragAllowed
            fIsDragAllowed = false;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragMouse()
        %DragMouse

        if fIsDragAllowed
            [cx, cy] = GetCursorCoordOnWindow();
            
            pdx = mDragStartX - cx;
            pdy = mDragStartY - cy;
            
            mDragStartX = cx;
            mDragStartY = cy;
            
            DragAxes(pdx, pdy);
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragKeys(direction)
        %DragKeys
        
        dx = mDragShiftStep;
        dy = mDragShiftStep;
        
        % Increment of speed when you hold the button
        mDragShiftStep = mDragShiftStep + mDragShiftStepInc;
        
        directionsX = {'right', 'left'};
        directionsY = {'down', 'up'};
        
        switch mDragKeysX
            case 'normal'
            case 'reverse'
                directionsX = fliplr(directionsX);
        end
        switch mDragKeysY
            case 'normal'
            case 'reverse'
                directionsY = fliplr(directionsY);
        end
        
        switch direction
            case directionsX{1}
                DragAxes(-dx, 0);
            case directionsX{2}
                DragAxes(dx, 0);
            case directionsY{1}
                DragAxes(0, dy);
            case directionsY{2}
                DragAxes(0, -dy);
        end
        
        PointerCrossUpdate();
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragAxes(pdx, pdy)
        %DragAxes
        
        [xLim, yLim] = GetAxesLimits();
        
        pos = GetObjPos(hAx, 'Pixels');
        pbar = get(hAx, 'PlotBoxAspectRatio');
        
        %NOTE: MATLAB Bug?
        % Fixed problem with AspectRatio and Position of Axes
        % MATLAB Function PAN is not correct works with rectangular images!
        % Here it is correctly.
        
        imAspectRatioX = pbar(2) / pbar(1);
        if (imAspectRatioX ~= 1)
            posAspectRatioX = pos(3) / pos(4);
            arFactorX = imAspectRatioX * posAspectRatioX;
            if (arFactorX < 1)
                arFactorX = 1;
            end
        else
            arFactorX = 1;
        end
        
        imAspectRatioY = pbar(1) / pbar(2);
        if (imAspectRatioY ~= 1)
            posAspectRatioY = pos(4) / pos(3);
            arFactorY = imAspectRatioY * posAspectRatioY;
            if (arFactorY < 1)
                arFactorY = 1;
            end
        else
            arFactorY = 1;
        end
        
        if fIsEnableDragX
            % For log plots, transform to linear scale
            if strcmp(get(hAx, 'xscale'), 'log')
                xLim = log10(xLim);
                xLim = FixInfLogLimits('x', xLim);
                isXLog = true;
            else
                isXLog = false;
            end
            
            dx = pdx * range(xLim) / (pos(3) / arFactorX);
            xLim = xLim + dx;
            
            % For log plots, untransform limits
            if isXLog
                xLim = 10.^(xLim);
            end
        end
        if fIsEnableDragY
            if strcmp(get(hAx, 'yscale'), 'log')
                yLim = log10(yLim);
                yLim = FixInfLogLimits('y', yLim);
                isYLog = true;
            else
                isYLog = false;
            end
            
            dy = pdy * range(yLim) / (pos(4) / arFactorY);
            
            if fIsImage
                yLim = yLim - dy; 
            else
                yLim = yLim + dy; 
            end
            
            if isYLog
                yLim = 10.^(yLim);
            end
        end
        
        SetAxesLimits(xLim, yLim);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragMouseBegin3D()
        %DragMouseBegin3D
        
        if ~fIsDragAllowed
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            
            mDragStartX = wcx;
            mDragStartY = wcy;
            
            fIsDragAllowed = true;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragMouseEnd3D()
        %DragMouseEnd3D
        
        if fIsDragAllowed
            fIsDragAllowed = false;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragMouse3D()
        %DragMouse3D
        
        if fIsDragAllowed
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            
            dx = mDragStartX - wcx;
            dy = mDragStartY - wcy;
            
            DragAxes3D(dx, dy);
            
            mDragStartX = wcx;
            mDragStartY = wcy;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragKeys3D(direction)
        %DragKeys3D
        
        dx = mDrag3DShiftStep;
        dy = mDrag3DShiftStep;
        
        mDrag3DShiftStep = mDrag3DShiftStep + mDragShiftStepInc;
        
        directionsX = {'right', 'left'};
        directionsY = {'down', 'up'};
        
        switch mDragKeysX
            case 'normal'
            case 'reverse'
                directionsX = fliplr(directionsX);
        end
        switch mDragKeysY
            case 'normal'
            case 'reverse'
                directionsY = fliplr(directionsY);
        end
        
        switch direction
            case directionsX{1}
                DragAxes3D(-dx, 0);
            case directionsX{2}
                DragAxes3D(dx, 0);
            case directionsY{1}
                DragAxes3D(0, dy);
            case directionsY{2}
                DragAxes3D(0, -dy);
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragAxes3D(dx, dy)
        %DragAxes3D
        
        axPos = GetObjPos(hAx, 'pixels');
        
        axPos(1) = axPos(1) - dx;
        axPos(2) = axPos(2) - dy;
        
        SetObjPos(hAx, axPos, 'pixels');
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DragEnable(ax, action)
        %DragEnable
        
        switch lower(action)
            case 'on'
                tf = true;
            case 'off'
                tf = false;
        end
                
        switch lower(ax)
            case 'x'
                fIsEnableDragX = tf;
            case 'y'
                fIsEnableDragY = tf;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomEnable(ax, action)
        %ZoomEnable
        
        switch lower(action)
            case 'on'
                tf = true;
            case 'off'
                tf = false;
        end
                
        switch lower(ax)
            case 'x'
                fIsEnableZoomX = tf;
            case 'y'
                fIsEnableZoomY = tf;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomMouse(direction)
        %ZoomMouse zooming axes with mouse
        
        if (IsZoomMouseAllowed && ~fIsMagnifierOn)
            [acx, acy] = GetCursorCoordOnAxes();
            ZoomAxes(direction, acx, acy)
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomMouseExtendBegin()
        %ZoomMouseExtendBegin
        
        if ~fIsZoomExtendAllowed
            UpdateCurrentZoomAxes();
            
            % set new zoom grid for extend zoom
            [mZoomGrid, mZoomSteps] = ZoomLogGrid(mZoomMinPow, mZoomMaxPow, mZoomExtendNum);
            UpdateCurrentZoomAxes();
            
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            [acx, acy] = GetCursorCoordOnAxes();
            
            mZoom3DStartX = wcx;
            mZoom3DStartY = wcy;
            
            mZoom3DBindX = acx;
            mZoom3DBindY = acy;
            
            fIsZoomExtendAllowed = true;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomMouseExtendEnd()
        %ZoomMouseExtendEnd
        
        if fIsZoomExtendAllowed
            % set default zoom grid
            SetDefaultZoomGrid();
            fIsZoomExtendAllowed = false;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomMouseExtend()
        %ZoomMouseExtend
        
        if fIsZoomExtendAllowed
            directions = {'minus', 'plus'};
            
            switch mZoomScroll
                case 'normal'
                case 'reverse'
                    directions = fliplr(directions);
            end
        
            % Heuristic for pixel change to camera zoom factor 
            % (taken from function ZOOM)
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            
            xy(1) = wcx - mZoom3DStartX;
            xy(2) = wcy - mZoom3DStartY;
            q = max(-0.9, min(0.9, sum(xy)/70)) + 1;
   
            if (q < 1)
                direction = directions{1};
            elseif (q > 1)
                direction = directions{2};
            else
                return;
            end
            
            ZoomAxes(direction, mZoom3DBindX, mZoom3DBindY)
            
            mZoom3DStartX = wcx;
            mZoom3DStartY = wcy;            
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomKeys(direction)
        %ZoomKeys zooming axes with keyboard
        
        UpdateCurrentZoomAxes();
        
        [mZoomGrid, mZoomSteps] = ZoomLogGrid(mZoomMinPow, mZoomMaxPow, mZoomKeysNum);
        UpdateCurrentZoomAxes();
        
        [acx, acy] = GetCursorCoordOnAxes();
        
        ZoomAxes(direction, acx, acy)
        PointerCrossUpdate();
        SetDefaultZoomGrid();
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomAxes(direction, cx, cy)
        %ZoomAxes Zoom axes in 2D and image modes
        
        [xLim, yLim] = GetAxesLimits();
        
        if fIsImage
            mZoomIndexX = ChangeZoomIndex(direction, mZoomIndexX);
            mZoomIndexY = mZoomIndexX;
            zoomPct = GetZoomPercent(mZoomIndexX);
            
            xLim = RecalcZoomAxesLimits('x', xLim, mDefaultXLim, cx, zoomPct);
            yLim = RecalcZoomAxesLimits('y', yLim, mDefaultYLim, cy, zoomPct);            
        else
            if fIsEnableZoomX
                mZoomIndexX = ChangeZoomIndex(direction, mZoomIndexX);
                zoomPct = GetZoomPercent(mZoomIndexX);
                
                xLim = RecalcZoomAxesLimits('x', xLim, mDefaultXLim, cx, zoomPct);
            end
            if fIsEnableZoomY
                mZoomIndexY = ChangeZoomIndex(direction, mZoomIndexY);
                zoomPct = GetZoomPercent(mZoomIndexY);
                
                yLim = RecalcZoomAxesLimits('y', yLim, mDefaultYLim, cy, zoomPct);
            end
        end
        
        SetAxesLimits(xLim, yLim);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function zoomPct = GetZoomPercent(zoomIndex, zoomGrid)
        %GetZoomPercent get zoom percent

        if (nargin < 2)
            zoomGrid = mZoomGrid;
        end
        
        zoomPct = zoomGrid(zoomIndex);       
    end
%--------------------------------------------------------------------------

%==========================================================================
    function zoomIndex = ChangeZoomIndex(direction, zoomIndex, zoomSteps)
        %ChangeZoomIndex
        
        if (nargin < 3)
            zoomSteps = mZoomSteps;
        end
        
        switch direction
            case 'plus'
                if (zoomIndex < zoomSteps)
                    zoomIndex = zoomIndex + 1;
                end
            case 'minus'
                if (zoomIndex > 1)
                    zoomIndex = zoomIndex - 1;
                end
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function axLim = RecalcZoomAxesLimits(ax, axLim, axLimDflt, zcCrd, zoomPct)
        %RecalcZoomAxesLimits recalc axes limits
        
        if strcmp(get(hAx, [ax, 'scale']), 'log')
            axLim = log10(axLim);
            axLim = FixInfLogLimits(ax, axLim);
            axLimDflt = log10(axLimDflt);
            zcCrd = log10(zcCrd);
            isLog = true;
        else
            isLog = false;
        end
                
        if (zcCrd < axLim(1)), zcCrd = axLim(1); end
        if (zcCrd > axLim(2)), zcCrd = axLim(2); end
        
        rf = range(axLim);
        ra = range([axLim(1), zcCrd]);
        rb = range([zcCrd, axLim(2)]);
        
        cfa = ra / rf; 
        cfb = rb / rf;
        
        newRange = range(axLimDflt) * 100 / zoomPct;
        dRange = newRange - rf;
        
        axLim(1) = axLim(1) - dRange * cfa;
        axLim(2) = axLim(2) + dRange * cfb;
        
        if isLog
            axLim = 10.^axLim;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function UpdateCurrentZoomAxes()
        %UpdateCurrentZoomAxes
        
        [xLim, yLim] = GetAxesLimits();
        [curentZoomX, curentZoomY] = GetCurrentZoomAxesPercent(xLim, yLim);
        
        if (curentZoomX ~= GetZoomPercent(mZoomIndexX))
            [nu, mZoomIndexX] = min(abs(mZoomGrid - curentZoomX));  %#ok ([~, ...])
        end
        if (curentZoomY ~= GetZoomPercent(mZoomIndexY))
            [nu, mZoomIndexY] = min(abs(mZoomGrid - curentZoomY));  %#ok ([~, ...])
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function [curentZoomX, curentZoomY] = GetCurrentZoomAxesPercent(xLim, yLim)
        %GetCurrentZoomAxesPercent
        
        if strcmp(get(hAx, 'xscale'), 'log')
            xLim = log10(xLim);
            defaultXLim = log10(mDefaultXLim);
        else
            defaultXLim = mDefaultXLim;
        end
        if strcmp(get(hAx, 'yscale'), 'log')
            yLim = log10(yLim);
            defaultYLim = log10(mDefaultYLim);
        else
            defaultYLim = mDefaultYLim;
        end
        
        curentZoomX = range(defaultXLim) * 100 / range(xLim);
        curentZoomY = range(defaultYLim) * 100 / range(yLim);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomMouse3D(direction)
        %ZoomMouse3D
        
        if IsZoomMouseAllowed
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            ZoomAxes3D(direction, wcx, wcy)
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomMouseExtendBegin3D()
        %ZoomMouseExtendBegin3D
        
        if ~fIsZoomExtend3DAllowed
            UpdateCurrentZoomAxes3D();
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            
            % set new zoom grid for extend zoom
            SetNewZoomGrid3D(mZoomMinPow, mZoomMaxPow, mZoom3DExtendNum);
            
            mZoom3DStartX = wcx;
            mZoom3DStartY = wcy;
            
            mZoom3DBindX = wcx;
            mZoom3DBindY = wcy;
            
            fIsZoomExtend3DAllowed = true;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomMouseExtendEnd3D()
        %ZoomMouseExtendEnd3D
        
        if fIsZoomExtend3DAllowed
            SetDefaultZoomGrid3D();
            
            fIsZoomExtend3DAllowed = false;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomMouseExtend3D()
        %ZoomMouseExtended3D
        
        if fIsZoomExtend3DAllowed
            directions = {'minus', 'plus'};
            
            switch mZoomScroll
                case 'normal'
                case 'reverse'
                    directions = fliplr(directions);
            end
        
            % Heuristic for pixel change to camera zoom factor 
            % (taken from function ZOOM)
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            
            xy(1) = wcx - mZoom3DStartX;
            xy(2) = wcy - mZoom3DStartY;
            q = max(-0.9, min(0.9, sum(xy)/70)) + 1;
   
            if (q < 1)
                direction = directions{1};
            elseif (q > 1)
                direction = directions{2};
            else
                return;
            end
            
            ZoomAxes3D(direction, mZoom3DBindX, mZoom3DBindY)
            
            mZoom3DStartX = wcx;
            mZoom3DStartY = wcy;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomAxes3D(direction, cx, cy)
        %ZoomAxes3D
        
        mZoom3DIndex = ChangeZoomIndex(direction, mZoom3DIndex, mZoomSteps);
        zoomPct = GetZoomPercent(mZoom3DIndex, mZoomGrid);
        
        axPos = GetObjPos(hAx, 'pixels');
        
        [axPos(1), axPos(3)] = RecalcZoomAxesPos3D(axPos(1), axPos(3), ...
            mDefaultAxPos(3), cx, zoomPct);
        
        [axPos(2), axPos(4)] = RecalcZoomAxesPos3D(axPos(2), axPos(4), ...
            mDefaultAxPos(4), cy, zoomPct);
        
        SetObjPos(hAx, axPos, 'pixels');
    end
%--------------------------------------------------------------------------

%==========================================================================
    function [npc, nsz] = RecalcZoomAxesPos3D(pc, sz, dfltSz, zcCrd, zoomPct)
        %RecalcZoomAxesPos3D
        
        dd = dfltSz * zoomPct / 100 - sz;
        rng = range([pc zcCrd]);
        cf = rng / sz; 
        nsz = sz + dd;
        npc = pc - dd * cf;
    end
%--------------------------------------------------------------------------
        
%==========================================================================
    function UpdateCurrentZoomAxes3D()
        %UpdateCurrentZoomAxes3D
        
        curentZoom = GetCurrentZoomAxesPercent3D();
        [nu, mZoom3DIndex] = min(abs(mZoomGrid - curentZoom));  %#ok ([~, ...])
    end
%--------------------------------------------------------------------------

%==========================================================================
    function currentZoom = GetCurrentZoomAxesPercent3D()
        %GetCurrentZoomAxesPercent3D

        axPos = GetObjPos(hAx, 'pixels');
        currentZoom = axPos(3) / mDefaultAxPos(3) * 100;
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ZoomKeys3D(direction)
        %ZoomKeys3D
        
        UpdateCurrentZoomAxes3D();
        SetNewZoomGrid3D(mZoomMinPow, mZoomMaxPow, mZoom3DKeysNum);
        
        [wcx, wcy] = GetCursorCoordOnWindow('pixels');
        ZoomAxes3D(direction, wcx, wcy)
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetNewZoomGrid3D(minPow, maxPow, num)
        %SetNewZoomGrid3D set new zoom grid for 3D mode
        
        [mZoomGrid, mZoomSteps] = ZoomLogGrid(minPow, maxPow, num);
        UpdateCurrentZoomAxes3D();
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetDefaultZoomGrid()
        %SetDefaultZoomGrid set default zoom grid
        
        [mDefaultZoomGrid, mDefaultZoomSteps] = ...
            ZoomLogGrid(mZoomMinPow, mZoomMaxPow, mZoomNum);
        
        mZoomGrid = mDefaultZoomGrid;
        mZoomSteps = mDefaultZoomSteps;
        
        mZoomIndexX = find(mZoomGrid == 100);
        mZoomIndexY = mZoomIndexX;
        mZoom3DIndex = mZoomIndexX;
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetDefaultZoomGrid3D()
        %SetDefaultZoomGrid for 3D mode
        
        mZoomGrid = mDefaultZoomGrid;
        mZoomSteps = mDefaultZoomSteps;
        UpdateCurrentZoomAxes3D();
    end
%--------------------------------------------------------------------------

%==========================================================================
    function VisibleAxesKeys3D()
        %VisibleAxesKeys3D
        
        axi = GetCurrentAxesIndex();
        
        if mAxesInfo(axi).isvisible
            set(hAx, 'Visible', 'off');
            mAxesInfo(axi).isvisible = false;
        else
            set(hAx, 'Visible', 'on');
            mAxesInfo(axi).isvisible = true;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SwitchAspectRatioKeys3D()
        %SwitchAspectRatioKeys3D
        
        axi = GetCurrentAxesIndex();
        
        if mAxesInfo(axi).isvis3d
            axis(hAx, 'normal');
            mAxesInfo(axi).isvis3d = false;
        else
            axis(hAx, 'vis3d');
            mAxesInfo(axi).isvis3d = true;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RotateMouseBegin3D()
        %RotateMouseBegin3D
        
        if ~fIsRotate3DAllowed
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            
            [az, el] = view(hAx);
            
            mRotStartAZ = az;
            mRotStartEL = el;
            mRotStartX = wcx;
            mRotStartY = wcy;
                        
            fIsRotate3DAllowed = true;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RotateMouseEnd3D()
        %RotateMouseEnd3D
        
        if fIsRotate3DAllowed
            fIsRotate3DAllowed = false;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RotateMouse3D()
        %RotateMouse3D
        
        if fIsRotate3DAllowed
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            
            dAZ = mRotStartX - wcx;
            dEL = mRotStartY - wcy;
            
            az = mRotStartAZ + dAZ;
            el = mRotStartEL + dEL;
            
            SetView3D(az, el);
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RotateKeys3D(mode)
        %RotateKeys3D
        
        [az, el] = view(hAx);
                
        switch lower(mode)
            case 'xy'
                az = 0;
                el = 90;                
            case 'xz'
                az = 0;
                el = 0;
            case 'yz'
                az = 90;
                el = 0;
            case 'az+'
                az = az + mRot3DKeysInc;
            case 'az-'
                az = az - mRot3DKeysInc;
            case 'el+'
                el = el + mRot3DKeysInc;
            case 'el-'
                el = el - mRot3DKeysInc;
        end
        
        SetView3D(az, el)
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetView3D(az, el)
        %SetView3D
        
        if (el > 90), el = 90; end
        if (el < -90), el = -90; end
        
        view(hAx, [az, el]);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function PointerCrossOn()
        %PointerCrossOn
        
        if ~fIsPointerCross
            SetPointer('crosshair');
            
            % text objects
            h = [
                text('Parent', hAx)     % left
                text('Parent', hAx)     % right
                text('Parent', hAx)     % bottom
                text('Parent', hAx)     % top
                ];
            
            % create pointer cross struct
            mPointerCross = struct(...
                'htext',    h, ...
                'left',     1, ...
                'right',    2, ...
                'bottom',   3, ...
                'top',      4);
            
            PointerCrossSetup();
            fIsPointerCross = true;
            PointerCrossUpdate();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function PointerCrossOff()
        %PointerCrossOff
        
        if fIsPointerCross
            delete(mPointerCross.htext);
            SetPointer('arrow');
            fIsPointerCross = false;
            mPointerCross = [];
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function PointerCrossSetup()
        %PointerCrossSetup
        
        left = mPointerCross.left;
        right = mPointerCross.right;
        bottom = mPointerCross.bottom;
        top = mPointerCross.top;
        
        vabt = {'top', 'bottom'};
        if fIsImage
            vabt = fliplr(vabt);
        end
        
        set(mPointerCross.htext(left), 'VerticalAlignment', 'bottom');
        set(mPointerCross.htext(right), 'VerticalAlignment', 'bottom');
        set(mPointerCross.htext(bottom), 'VerticalAlignment', vabt{1});
        set(mPointerCross.htext(top), 'VerticalAlignment', vabt{2});
        
        bgColor = [251 248 230]/255;
        set(mPointerCross.htext(left), 'BackgroundColor', bgColor);
        set(mPointerCross.htext(right), 'BackgroundColor', bgColor);
        set(mPointerCross.htext(bottom), 'BackgroundColor', bgColor);
        set(mPointerCross.htext(top), 'BackgroundColor', bgColor);
        
        edColor = [180 180 180]/255;
        set(mPointerCross.htext(left), 'EdgeColor', edColor);
        set(mPointerCross.htext(right), 'EdgeColor', edColor);
        set(mPointerCross.htext(bottom), 'EdgeColor', edColor);
        set(mPointerCross.htext(top), 'EdgeColor', edColor);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function PointerCrossUpdate()
        %PointerCrossUpdate
        
        if fIsPointerCross
            [xlim, ylim] = GetAxesLimits();
            [acx, acy] = GetCursorCoordOnAxes();
            
            left = mPointerCross.left;
            right = mPointerCross.right;
            bottom = mPointerCross.bottom;
            top = mPointerCross.top;
                        
            if fIsImage
                xValStr = sprintf(' %d ', round(acx));
                yValStr = sprintf(' %d ', round(acy));
            else
                xtick = get(hAx, 'XTick');
                ytick = get(hAx, 'YTick');
                
                %FIXME:
                prth = 5;
                
                [lenTick, maxi] = max(arrayfun(@(x) length(num2str(x)), xtick));
                atick = abs(xtick(maxi));
                flt = mod(atick, 1);
                
                if (flt == 0)
                    countDigX = lenTick + 1;
                    if countDigX > prth
                        countDigX = prth;
                    end
                else
                    countDigX = length(num2str(atick));
                    if (fix(acx) == 0)
                        countDigX = countDigX - 1;
                    end
                end
                
                [lenTick, maxi] = max(arrayfun(@(x) length(num2str(x)), ytick));
                atick = abs(ytick(maxi));
                flt = mod(atick, 1);
                
                if (flt == 0)
                    countDigY = lenTick + 1;
                    if countDigY > prth
                        countDigY = prth;
                    end
                else
                    countDigY = length(num2str(atick));
                    if (fix(acy) == 0)
                        countDigY = countDigY - 1;
                    end
                end
                
                xValStr = sprintf(' %.*g ', countDigX, acx);
                yValStr = sprintf(' %.*g ', countDigY, acy);
            end
            
            set(mPointerCross.htext(left), 'String', yValStr);
            set(mPointerCross.htext(right), 'String', yValStr);
            set(mPointerCross.htext(bottom), 'String', xValStr);
            set(mPointerCross.htext(top), 'String', xValStr);
            
            extent = get(mPointerCross.htext(left), 'Extent');
            xx = extent(3);
            
            if strcmp(get(hAx, 'xscale'), 'log')
                leftx = xlim(1);
            else
                leftx = xlim(1) - xx;
            end
            
            set(mPointerCross.htext(left), 'Position', [leftx, acy]);
            set(mPointerCross.htext(right), 'Position', [xlim(2) acy]);
            set(mPointerCross.htext(bottom), 'Position', [acx, ylim(1)]);
            set(mPointerCross.htext(top), 'Position', [acx, ylim(2)]);
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RubberBandBegin()
        %RubberBandBegin
        
        if (~fIsRubberBandOn && ~fIsMagnifierOn)
            [acx, acy] = GetCursorCoordOnAxes();
            
            % create rubber band struct
            mRubberBand = struct(...
                'obj',	[patch('Parent', hAx), patch('Parent', hAx)], ...
                'x1',  	acx, ...
                'y1',  	acy, ...
                'x2',  	acx, ...
                'y2',  	acy);
            
            hAxes2d = GetHandlesAxes2D();
            if ~isempty(hAxes2d)
                set(hAxes2d, ...
                    'XLimMode', 'manual', ...
                    'YLimMode', 'manual');
            end
            
            RubberBandSetPos();
            RubberBandSetup();
            fIsRubberBandOn = true;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RubberBandEnd()
        %RubberBandEnd
        
        if fIsRubberBandOn
            fIsRubberBandOn = false;
            
            delete(mRubberBand.obj);          
            RubberBandZoomAxes();
            PointerCrossUpdate();
            mRubberBand = [];
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RubberBandUpdate()
        %RubberBandUpdate
        
        if fIsRubberBandOn
            [acx, acy] = GetCursorCoordOnAxes();
            
            mRubberBand.x2 = acx;
            mRubberBand.y2 = acy;
            RubberBandSetPos();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RubberBandSetPos()
        %RubberBandSetPos set position of rubber band
        
        x1 = mRubberBand.x1;
        y1 = mRubberBand.y1;
        x2 = mRubberBand.x2;
        y2 = mRubberBand.y2;
        
        set(mRubberBand.obj, ...
            'XData', [x1 x2 x2 x1], ...
            'YData', [y1 y1 y2 y2]);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RubberBandSetup()
        %RubberBandSetup
        
        set(mRubberBand.obj(1), ...
            'EdgeColor', 'w', ...
            'FaceColor', 'none', ...
            'LineWidth', 1.5, ...
            'LineStyle', '-');
        
        set(mRubberBand.obj(2), ...
            'EdgeColor', mRbEdgeColor, ...
            'FaceColor', mRbFaceColor, ...
            'FaceAlpha', mRbFaceAlpha, ...
            'LineWidth', 0.5, ...
            'LineStyle', '-');    
    end
%--------------------------------------------------------------------------

%==========================================================================
    function RubberBandZoomAxes()
        %RubberBandZoomAxes apply zoom from rubber band
        
        xLim = sort([mRubberBand.x1, mRubberBand.x2]);
        yLim = sort([mRubberBand.y1, mRubberBand.y2]);
        
        if (range(xLim) == 0 || range(yLim) == 0)
            return;
        end
        
        [zoomPctX, zoomPctY] = GetCurrentZoomAxesPercent(xLim, yLim);
        
        if fIsImage
            zoomPctX = min(zoomPctX, zoomPctY);
            zoomPctY = zoomPctX;
        end
        
        cx = mean(xLim);
        cy = mean(yLim);
        
        xLim = RecalcZoomAxesLimits('x', xLim, mDefaultXLim, cx, zoomPctX);
        yLim = RecalcZoomAxesLimits('y', yLim, mDefaultYLim, cy, zoomPctY);
        
        SetAxesLimits(xLim, yLim);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function MagnifierOn()
        %MagnifierCreate
        
        if ~fIsMagnifierOn    
            if fIsPointerCross
                isPointerCross = true;
                PointerCrossOff();
            else
                isPointerCross = false;
            end
            
            mMgDirection = 'plus';
            
            % create magnifier struct
            mMagnifier = struct(...
                'obj',          copyobj(hAx, hFig), ...
                'frame_obj',    [], ...
                'size',         mMgSize, ...
                'zoom',         mMgZoom);
            
            fIsMagnifierOn = true;
            MagnifierSetup();
            MagnifierUpdate();
            
            if isPointerCross
                PointerCrossOn();
            end
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function MagnifierOff()
        %MagnifierOff
        
        if fIsMagnifierOn
            fIsMagnifierOn = false;
            set(hAx, 'Color', get(mMagnifier.obj, 'Color'));
            
            delete(mMagnifier.obj);
            mMagnifier = [];
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function MagnifierUpdate()
        %MagnifierUpdate
        
        if fIsMagnifierOn            
            % see original idea of magnify by Rick Hindman -- 7/29/04
            % http://www.mathworks.com/matlabcentral/fileexchange/5961
            
            [acx, acy] = GetCursorCoordOnAxes();
            [wcx, wcy] = GetCursorCoordOnWindow('pixels');
            
            [xLim, yLim] = GetAxesLimits();
            
            if strcmp(get(hAx, 'xscale'), 'log')
                xLim = log10(xLim);
                xLim = FixInfLogLimits('x', xLim);
                acx = log10(acx);
                isXLog = true;
            else
                isXLog = false;
            end
            if strcmp(get(hAx, 'yscale'), 'log')
                yLim = log10(yLim);
                yLim = FixInfLogLimits('y', yLim);
                acy = log10(acy);
                isYLog = true;
            else
                isYLog = false;
            end
            
            figPos = GetObjPos(hFig, 'pixels');
            axPos = GetObjPos(hAx, 'normalized');
            
            % always square magnifier
            pbar = get(hAx, 'PlotBoxAspectRatio');
            af = pbar(1) / pbar(2);
            if (af == 1 && (pbar(1) == 1 && pbar(2) == 1))
                af = figPos(3) / figPos(4);
            end
            
            mgSizePix = round(mMagnifier.size);
            mgZoom = mMagnifier.zoom;
            
            mgSize = mgSizePix / figPos(3); % normalized size
            
            mgPos(3) = mgSize * 2;
            mgPos(4) = mgPos(3) * af;
            
            mg3 = round(mgPos(3) * figPos(3));
            mg4 = round(mgPos(4) * figPos(4));
            
            if (mg4 < mg3)
                mgSize = (mgSizePix * (mg3 / mg4)) / figPos(3);
            end
            
            mgPos(3) = mgSize * 2;
            mgPos(4) = mgPos(3) * af;
            
            mgPos(1) = wcx / figPos(3) - mgSize;
            mgPos(2) = wcy / figPos(4) - mgSize * af;
            
            mgXLim = acx + (1 / mgZoom) * (mgPos(3) / axPos(3)) * diff(xLim) * [-0.5 0.5];
            mgYLim = acy + (1 / mgZoom) * (mgPos(4) / axPos(4)) * diff(yLim) * [-0.5 0.5];
            
            SetObjPos(mMagnifier.obj, mgPos, 'normalized');
            
            if isXLog
                mgXLim = 10.^mgXLim;
            end
            if isYLog
                mgYLim = 10.^mgYLim;
            end
            
            set(mMagnifier.obj, ...
                'XLim', mgXLim, ...
                'YLim', mgYLim);
            
            MagnifierBorderUpdate();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function MagnifierSetup()
        %MagnifierSetup

        set(mMagnifier.obj, ...
            'Box', 'on', ...
            'XMinorTick', 'on', ...
            'YMinorTick', 'on');
        
        title(mMagnifier.obj, '');
        xlabel(mMagnifier.obj, ''); 
        ylabel(mMagnifier.obj, '');
        
        if fIsImage
            mMagnifier.frame_obj = ...
                [patch('Parent', mMagnifier.obj), ...
                patch('Parent', mMagnifier.obj)];
            
            set(mMagnifier.frame_obj, 'FaceColor', 'none');
            
            set(mMagnifier.frame_obj(1), ...
                'LineWidth', 1.5, ...
                'EdgeColor', 'w')
            set(mMagnifier.frame_obj(2), ...
                'LineWidth', 1, ...
                'EdgeColor', 'k')
            
            MagnifierBorderUpdate();
        end
        
        hLines = findobj(mMagnifier.obj, 'Type', 'line');
        if ~isempty(hLines)
            if (mMgLinesWidth ~= 1)
                set(hLines, 'LineWidth', mMgLinesWidth);
            end
        end
        
        set(hAx, 'Color', get(hAx, 'Color')*mMgShadow);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function MagnifierBorderUpdate()
        %MagnifierBorderUpdate
        
        if fIsImage
            x = get(mMagnifier.obj, 'XLim');
            y = get(mMagnifier.obj, 'YLim');
            
            set(mMagnifier.frame_obj, ...
                'XData', [x(1) x(2) x(2) x(1)], ...
                'YData', [y(1) y(1) y(2) y(2)]);
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function MagnifierSizeChange(direction)
        %MagnifierSizeChange
        
        if fIsMagnifierOn
            switch direction
                case 'plus'
                    if (mMagnifier.size < mMgMaxSize)
                        mMagnifier.size = mMagnifier.size + mMgSizeStep;
                    end
                case 'minus'
                    if (mMagnifier.size > mMgMinSize)
                        mMagnifier.size = mMagnifier.size - mMgSizeStep;
                    end
            end
            
            MagnifierUpdate();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function MagnifierZoomChange(direction)
        %MagnifierZoomChange
        
        if fIsMagnifierOn
            switch direction
                case 'plus'
                    if (mMagnifier.zoom < mMgMaxZoom)
                        mMagnifier.zoom = mMagnifier.zoom * mMgZoomStep;
                    end
                case 'minus'
                    if (mMagnifier.zoom > mMgMinZoom)
                        mMagnifier.zoom = mMagnifier.zoom / mMgZoomStep;
                    end
            end
            
            MagnifierUpdate();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function MagnifierReset()
        %MagnifierReset
        
        if fIsMagnifierOn
            mMagnifier.size = mMgSize;
            mMagnifier.zoom = mMgZoom;
            MagnifierUpdate();
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetLinkAxesKeys(modifier)
        %SetLinkAxesKeys Set Linking of 2-D axes
        
        if isempty(modifier)
            mLinkOpt = 'xy';
        else
            switch modifier{1}
                case 'control'
                    mLinkOpt = 'x';
                case 'alt'
                    mLinkOpt = 'y';
            end
        end
        
        if fIsLinkAxesOn
            LinkAxesOff();
        else
            LinkAxesOn();
        end
        
        UserData = get(hFig, 'UserData');
        UserData.tools.islinkaxeson = fIsLinkAxesOn;
        set(hFig, 'UserData', UserData);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function LinkAxesOn()
        %LinkAxesOn On of 2-D axes linking
        
        if ~fIsLinkAxesOn
            hAxes2d = GetHandlesAxes2D();
            if (length(hAxes2d) > 1)
                linkaxes(hAxes2d, mLinkOpt);
                fIsLinkAxesOn = true;
                SetFigureName();
            end
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function LinkAxesOff()
        %LinkAxesOff Off of 2-D axes linking
        
        if fIsLinkAxesOn
            fIsLinkAxesOn = false;
            
            SetFigureName();
            hAxes2d = GetHandlesAxes2D();
            linkaxes(hAxes2d, 'off');    
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DeleteOldTools()
        %DeleteOldTools
        
        UserData = get(hFig, 'UserData');
        
        if (~isempty(UserData) && isfield(UserData, 'tools'))
            if ~isempty(UserData.tools.pointercross)
                mPointerCross = UserData.tools.pointercross;
                fIsPointerCross = true;
                PointerCrossOff();
                UserData.tools.pointercross = [];
            end
            
            if UserData.tools.islinkaxeson
                fIsLinkAxesOn = true;
                LinkAxesOff();
                UserData.tools.islinkaxeson = false;
            end
            
            set(hFig, 'UserData', UserData);
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function hAxes2d = GetHandlesAxes2D()
        %GetHandlesAxes2D Get handles of 2-D axes
        
        isAxes2d = arrayfun(@(x) x.is2d && ~x.islegend, mAxesInfo);
        hAxes2d = hAxes(isAxes2d);
        
        if ~isempty(hAxes2d)
            % Set current axes on first position
            hAxes2d(eq(hAxes2d, hAx)) = 0;
            hAxes2d = sort(hAxes2d);
            hAxes2d(eq(hAxes2d, 0)) = hAx;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ResetAxesToOrigView()
        %ResetAxesToOrigView reset axes to original limits
        
        SetAxesLimits(mDefaultXLim, mDefaultYLim);
        PointerCrossUpdate();
        
        mZoomIndexX = find(mZoomGrid == 100);
        mZoomIndexY = mZoomIndexX;
    end
%--------------------------------------------------------------------------

%==========================================================================
    function ResetAxesToOrigView3D()
        %ResetAxesToOrigView3D reset axes to original position in 3D mode
        
        % position reset
        axi = GetCurrentAxesIndex();
        pos = mAxesInfo(axi).normposition;
        SetObjPos(hAx, pos, 'normalized');
        
        % view reset
        resetplotview(hAx, 'ApplyStoredView'); % (!!!) undocumented function
        
        if mAxesInfo(axi).isvis3d
            axis(hAx, 'vis3d');
        end
        
        % zoom reset
        mZoom3DIndex = find(mZoomGrid == 100);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function [x, y, z] = GetCursorCoordOnAxes()
        %GetCursorCoordOnAxImg
        
        crd = get(hAx, 'CurrentPoint');
        x = crd(2,1);
        y = crd(2,2);
        z = crd(2,3);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function [x, y] = GetCursorCoordOnWindow(units)
        %GetCursorCoordOnWindow
        
        if (nargin < 1), units = 'pixels'; end
        
        dfltUnits = get(hFig, 'Units');
        set(hFig, 'Units', units);
        
        crd = get(hFig, 'CurrentPoint');
        x = crd(1); 
        y = crd(2);
        
        set(hFig, 'Units', dfltUnits);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function pos = GetObjPos(h, units)
        %GetObjPos get object position
        
        if (nargin < 2), units = get(h, 'Units'); end
        
        dfltUnits = get(h, 'Units');
        set(h, 'Units', units);
        pos = get(h, 'Position');
        set(h, 'Units', dfltUnits);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetObjPos(h, pos, units)
        %SetObjPos set object position
        
        if (nargin < 3), units = get(h, 'Units'); end
        
        dfltUnits = get(h, 'Units');
        set(h, 'Units', units);
        set(h, 'Position', pos);
        set(h, 'Units', dfltUnits);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function [xLim, yLim] = GetAxesLimits()
        %GetAxesLimits
        
        xLim = get(hAx, 'XLim');
        yLim = get(hAx, 'YLim');
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetAxesLimits(xLim, yLim)
        %SetAxesLimits
        
        set(hAx, 'XLim', xLim);
        set(hAx, 'YLim', yLim);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetPointerCrossKeys()
        %SetPointerCrossKeys set pointer fullcross
        
        if fIsPointerCross
            PointerCrossOff();
        else
            PointerCrossOn();
        end
        
        UserData = get(hFig, 'UserData');
        UserData.tools.pointercross = mPointerCross;
        set(hFig, 'UserData', UserData);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetPointer(pointerType)
        %SetPointer set pointer symbol
        
        set(hFig, 'Pointer', pointerType);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetAxesGridKeys()
        %SetAxesGridKeys on/off axes grid
        
        if fIsAxesGrid
            action = 'off';
            fIsAxesGrid = false;
        else
            action = 'on';
            fIsAxesGrid = true;
        end
        
        set(hAx, 'XGrid', action, 'YGrid', action, 'ZGrid', action);
        
        if fIsMagnifierOn
            set(mMagnifier.obj, 'XGrid', action, 'YGrid', action);
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetSmoothKeys()
        %SetSmoothKeys on/off cmoothing plots
        
        if fIsSmoothing
            action = 'off';
            fIsSmoothing = false;
        else
            action = 'on';
            fIsSmoothing = true;
        end
        
        if ~fIsImage
            %FIXME: bug with switching opengl/painter renderer here
            %Lost figure focus
            hLine = findobj(hAx, 'Type', 'Line');
            if ~isempty(hLine)
                set(hLine, 'LineSmooth', action);   % !!! Undocumented property
            end
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function [zg, st] = ZoomLogGrid(a, b, n)
        %ZoomLogGrid log zoom grid
        
        zg = unique(round(logspace(a, b, n)));
        
        zg(zg<10) = [];	% begin zoom == 10%
        st = length(zg);
        
        if isempty(find(zg == 100, 1))
            error('dragzoom:badZoomGridOptions', 'Options for zoom grid is bad.')
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function tf = IsZoomMouseAllowed()
        %IsZoomMouseAllowed
        
        [wcx, wcy] = GetCursorCoordOnWindow();
        figPos = get(hFig, 'Position');
        
        if (wcx >= 1 && wcx <= figPos(3) && wcy >= 1 && wcy <= figPos(4))
            tf = true;
        else
            tf = false;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function tf = IsImageOnAxes(ax)
        %IsImageOnAxes
        
        if (nargin < 1), ax = hAx; end
        
        h = findobj(ax, 'Type', 'Image');
        
        if isempty(h)
            tf = false;
        else
            tf = true;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function tf = IsAxes2D(ax)
        %IsAxes2D
        
        if (nargin < 1), ax = hAx; end
        
        tf = is2D(ax); % (!!!) internal undocumented function
    end
%--------------------------------------------------------------------------

%==========================================================================
    function tf = IsLegendAxes(ax)
        %IsLegendAxes
        
        tf = strcmp(get(ax, 'Tag'), 'legend');
    end
%--------------------------------------------------------------------------

%==========================================================================
    function targetInBounds = IsInBoundsAxes(ax)
        %InBoundsAxes Check if the user clicked within the bounds of the axes. If not, do nothing
        
        targetInBounds = true;
        tol = 3e-16;
        cp = get(ax, 'CurrentPoint');
        
        XLims = get(ax, 'XLim');
        if ((cp(1,1) - min(XLims)) < -tol || (cp(1,1) - max(XLims)) > tol) && ...
                ((cp(2,1) - min(XLims)) < -tol || (cp(2,1) - max(XLims)) > tol)
            targetInBounds = false;
        end
        
        YLims = get(ax, 'YLim');
        if ((cp(1,2) - min(YLims)) < -tol || (cp(1,2) - max(YLims)) > tol) && ...
                ((cp(2,2) - min(YLims)) < -tol || (cp(2,2) - max(YLims)) > tol)
            targetInBounds = false;
        end
        
        ZLims = get(ax, 'ZLim');
        if ((cp(1,3) - min(ZLims)) < -tol || (cp(1,3) - max(ZLims)) > tol) && ...
                ((cp(2,3) - min(ZLims)) < -tol || (cp(2,3) - max(ZLims)) > tol)
            targetInBounds = false;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function tf = IsCurrentAxes(ax)
        %IsCurrentAxes
        
        hcAx = get(hFig, 'CurrentAxes');
        tf = eq(ax, hcAx);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function tf = IsAxesVis3D(ax)
        %IsAxesVis3D
        
        visProp = {
            get(ax, 'PlotBoxAspectRatioMode')
            get(ax, 'DataAspectRatioMode')
            get(ax, 'CameraViewAngleMode')
            };
        
        tf = all(strcmpi(visProp, 'manual'));
    end
%--------------------------------------------------------------------------

%==========================================================================
    function AxesInfo = GetAxesInfo()
        %GetAxesInfo make and get axes info struct
        
        countAxes = length(hAxes);
        
        AxesInfo = struct(...
            'handle',       cell(1, countAxes), ...
            'iscurrent',    cell(1, countAxes), ...
            'is2d',         cell(1, countAxes), ...
            'isimage',      cell(1, countAxes), ...  
            'isvisible',    cell(1, countAxes), ...  
            'isvis3d',      cell(1, countAxes), ...
            'islegend',     cell(1, countAxes), ...
            'position',     cell(1, countAxes), ...
            'normposition', cell(1, countAxes), ...
            'xlim',         cell(1, countAxes), ...
            'ylim',         cell(1, countAxes), ...
            'camtarget',    cell(1, countAxes), ...
            'camposition',  cell(1, countAxes));
        
        for i = 1:countAxes
            h = hAxes(i);
            
            AxesInfo(i).handle = h;
            AxesInfo(i).iscurrent = IsCurrentAxes(h);
            AxesInfo(i).is2d = IsAxes2D(h);
            AxesInfo(i).isimage = IsImageOnAxes(h);
            AxesInfo(i).isvisible = strcmpi(get(h, 'Visible'), 'on');
            AxesInfo(i).isvis3d = IsAxesVis3D(h);
            AxesInfo(i).islegend = IsLegendAxes(h);
            AxesInfo(i).position = GetObjPos(h, 'pixels');
            AxesInfo(i).normposition = GetObjPos(h, 'normalized');
            AxesInfo(i).xlim = get(h, 'XLim');
            AxesInfo(i).ylim = get(h, 'YLim');
            AxesInfo(i).camtarget = get(h, 'CameraTarget');
            AxesInfo(i).camposition = get(h, 'CameraPosition');
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SelectAxesUnderCursor()
        %SelectAxesUnderCursor select axes under cursor as current
        
        axi = GetAxesIndexUnderCursor();
        
        if (axi > 0)
            fIsEnableControl = true;
            
            if ~mAxesInfo(axi).iscurrent
                caxi = GetCurrentAxesIndex();
                
                if isempty(caxi)
                    DeleteInvalidAxesInfo();
                    
                    axi = GetAxesIndexUnderCursor();
                    isCax2d = mAxesInfo(axi).is2d;
                else
                    isCax2d = mAxesInfo(caxi).is2d;
                end
                
                SetCurrentAxes(axi);
                
                % for fix "legend" axes capture
                if mAxesInfo(axi).islegend;
                    fIsMouseOnLegend = true;
                else
                    fIsMouseOnLegend = false;
                end
                
                % check callbacks
                if (isCax2d ~= mAxesInfo(axi).is2d)
                    % if dimension of axes has changed
                    SetCallbacks();
                    
                    if fIsPointerCross
                        % disable pointer cross
                        PointerCrossOff()
                    end
                else
                    if fIsPointerCross
                        % reset pointer cross
                        PointerCrossOff()
                        SetPointerCrossKeys()
                    end
                end
            end
        else
            fIsEnableControl = false;
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function SetCurrentAxes(axi)
        %SetCurrentAxes set current axes and work mode
        
        hAx = mAxesInfo(axi).handle;
        
        set(hFig, 'CurrentAxes', hAx);
        for i = 1:numel(mAxesInfo)
            mAxesInfo(i).iscurrent = false;
        end
        mAxesInfo(axi).iscurrent = true;
        
        fIsAxes2D = mAxesInfo(axi).is2d;
        fIsImage = mAxesInfo(axi).isimage;
        
        mDefaultAxPos = mAxesInfo(axi).position;
        mDefaultXLim = mAxesInfo(axi).xlim;
        mDefaultYLim = mAxesInfo(axi).ylim;
        
        % save info to work correctly after saving figures
        UserData = get(hFig, 'UserData');
        UserData.axesinfo = mAxesInfo;
        set(hFig, 'UserData', UserData);
    end
%--------------------------------------------------------------------------

%==========================================================================
    function axi = GetCurrentAxesIndex()
        %GetCurrentAxesIndex
        
        axi = [];
        
        for i = 1:numel(mAxesInfo)
            if (ishandle(mAxesInfo(i).handle) && mAxesInfo(i).iscurrent)
                axi = i;
                return;
            end
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function axi = GetAxesIndexUnderCursor()
        %FindAxesUnderCursor find current axes under cursor
        
        axi = GetCurrentAxesIndex();
        
        if ~fIsSelectedCurrentAxes
            caxi = GetCurrentAxesIndex();
            if ~IsInBoundsAxes(mAxesInfo(caxi).handle)
                axi = 0;
            end
            return;
        end
        
        for i = 1:numel(mAxesInfo)
            if (ishandle(mAxesInfo(i).handle) && IsInBoundsAxes(mAxesInfo(i).handle))
                axi = i;
                return;
            else
                axi = 0; % without axes
            end
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function axLim = FixInfLogLimits(ax, axLim)
        %FixInfLogLimits Fix Axes Inf Log Limits
        
        if (~all(isfinite(axLim)) || ~all(isreal(axLim)))
            
            % The following code has been taken from zoom.m
            % If any of the public limits are inf then we need the actual limits
            % by getting the hidden deprecated RenderLimits.
            oldstate = warning('off', 'MATLAB:HandleGraphics:NonfunctionalProperty:RenderLimits');
            renderlimits = get(hAx, 'RenderLimits');
            warning(oldstate);
            
            switch ax
                case 'x'
                    axLim = renderlimits(1:2);
                case 'y'
                    axLim = renderlimits(3:4);
            end
            axLim = log10(axLim);
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function DeleteInvalidAxesInfo()
        %DeleteInvalidAxesInfo
        
        invalidAxes = arrayfun(@(x) ~ishandle(x.handle), mAxesInfo);
        mAxesInfo(invalidAxes) = [];
        hAxes(invalidAxes) = [];
    end
%--------------------------------------------------------------------------

%==========================================================================
    function isWithStatus = ParseInputs(varargin)
        %ParseInputs parse input arguments
        
        isWithStatus = false;
        
        switch nargin
            case 0
                hObj = gcf;
                status = 'on';
                ih = 0;
            case 1
                if ischar(varargin{1})
                    isWithStatus = true;
                    hObj = gcf;
                    status = varargin{1};
                    ih = 2;
                    is = 1;
                else
                    hObj = varargin{1};
                    status = 'on';
                    ih = 1;
                    is = 2;
                end
            case 2
                isWithStatus = true;
                hObj = varargin{1};
                status = varargin{2};
                ih = 1;
                is = 2;
        end
        
        switch lower(status)
            case 'on'
                fIsEnabled = true;
            case 'off'
                fIsEnabled = false;
            otherwise
                error('dragzoom:invalidInputs', ...
                    'Input Argument %d must be a string "on" or "off".', is)
        end
        
        if all(ishandle(hObj))
            handleType = get(hObj(1), 'Type');
            
            switch handleType
                case 'axes'
                    hAxes = unique(hObj);
                    hFig = ancestor(hAxes(1), 'figure');
                    
                case 'figure'
                    hFig = hObj;
                    hAxes = findobj(hFig, 'Type', 'axes'); % all axes
                    
                    if isempty(hAxes)
                        warning('dragzoom:notFoundAxes', 'Not found axes objects on figure.')
                    end
                    
                otherwise
                    error('dragzoom:invalidHandle', ...
                        'Input Argument %d must be figure or axes handle.', ih)
            end
        else
            error('dragzoom:invalidInputs', ...
                'Input Argument %d must be a figure or axes handle.', ih)
        end
    end
%--------------------------------------------------------------------------

%==========================================================================
    function res = range(x)
        %RANGE
        
        res = abs(diff([min(x) max(x)]));
    end
%--------------------------------------------------------------------------

end % DRAGZOOM

The diff you're trying to view is too large. Only the first 1000 changed files have been loaded.
Showing with 0 additions and 0 deletions (0 / 0 diffs computed)
swh spinner

Computing file changes ...

back to top

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API