image thumbnail

gridcolor

by

 

30 Jan 2006 (Updated )

Change color of grid lines without changing color of axis labels or box

gridcolor(varargin)
function gridcolor(varargin)
%
% function gridcolor([h_axes], [xcolor],  [ycolor],  [zcolor])
%
% Use this function to change the color of gridlines to a color different to the label and box
% color, which is currently not implemented in Matlab. 
% (-> http://www.mathworks.com/support/solutions/data/1-1PAYMC.html?solution=1-1PAYMC)
%
% Input parameters (all optional)
% -------------------------------
% hAx                   Handle of axis resp. array of handles to several axes, first arg. if specified
% xyzcolor              Color specification (e.g. 'r' or [1 0 0])
%
% Syntax
% ------
% gridcolor             Change/update the current axis (gca) with the default grid color (cstd)
% gridcolor(hAx)        Change/update axis(axes) with handle(s) hAx with the default grid color (cstd)
% gridcolor(hAx, col)   Change/update axis(axes) (hAx) with grid color col (e.g. 'r' or [1 0 0])
%
% Notes
% -----
% This function creates a second "empty" axis, which only contains the grid lines, as suggested
% in the Matlab support page. Additionally this "grid" axis is linked to the original axis to
% enable correct behavior during zooming and paning.
% From version 0.99 it is also possible to issue commands like "grid on" or "set(gca,'xminorGrid','on')",
% which will update the axis accordingly
%
% The list of 
% linked properties includes everything I can think of, which may "disalign" the two axes. The 
% linking updates the second axis automatically, so you should be able to do all sorts of zooming, 
% paning, changing axis limits, axis directions, etc. If you are experiencing unwanted changes in 
% the overall display of your plot (e.g. dataaspectratio ...) you may want to take out some of the 
% properties in this line.  
%
% For Matlab 6 (or lower) gridcolor will not notice any changes on the axis (e.g. 'xlim')
% If you do change these parameters you will have to call gridcolor again, to update the gridlines !!!
%
% Example (execute one command after the other ...)
% -------------------------------------------------
% plot([1 20],[1 50],'k');
% gridcolor('r')
% set(gca,'gridlinestyle','-','minorgridlinestyle',':'); grid on
% set(gca,'xminorgrid','on')
% view(3); gridcolor([1 0 0],'g','b')
% 
% Author
% ------
% Sebastian Hoelz
% IFM-GEOMAR
% s[->Insert my family name<-]ATifm-geomar.de
% 
% Version 0.95 - 10.06.2009
%   Color of box was still displayed incorrectly ... hopefully fixed correctly this time.
%   Added some more relevant properties to link ...
%
% Version 0.94 - 10.01.2009
%   Color of box was displayed incorrectly due to wrong stacking.
%   Changed: ax2('color','w'),uistack(ax2,'bottom'),ax1('color','none')
%
% Version 0.93 - 01.09.2008
%   Included bug fix, which was caused by Matlabs version command
%   Gridstate (on/off) is now transfered from ax1->ax2, before turning it off for ax1 (s. lines 120ff.)
%
% Version 0.92 - 10.08.2006
%   Changed the stack order of the reference axis (now bottom) and the "color-axis" (now top)
%   Removed the linkaxis-command for Matlab 6.5 and lower, since it does not exist in this version
%
% Version 0.91 - 31.01.2006
%   Original Release
    
    cstd = [.8 .8 .8];       % Standard color
    persistent show_only_once
    
    % Parsing input with recursive calls to this function, 
    % if less than 4 input arguments are supplied
    % ----------------------------------------------------
    error(nargchk(0, 4, nargin))
    
    if nargin==0
        gridcolor(gca); return
        
    elseif nargin>=1 && nargin<4
        a1 = varargin{1};
        if iscolor(a1)
            % First argument seems to be a color spec. !!!
            gridcolor(gca,varargin{:}); return
            
        elseif length(a1)>1
            % First argument might be an array with handles of axes
            for i=1:length(a1); gridcolor(a1(i),varargin{2:end}); end; return
            
        else
            % Check if argument is an axis handle
            if ~ishandle(a1) || ~strcmpi(get(a1,'type'),'axes'); error('Input argument is not an axis handle'); end
            if nargin == 1
                % See if grid-axis already exists (-> axis is updated without color change!)
                ax2 = getappdata(a1,'hGridAxis');
                if ~isempty(ax2) && ishandle(ax2); cxyz=get(ax2,{'xcolor','ycolor','zcolor'}); 
                else cxyz={cstd, cstd, cstd}; end
                gridcolor(a1,cxyz{:}); return
                
            elseif nargin == 2
                gridcolor(a1,varargin{2},varargin{2},varargin{2}); return
                
            elseif nargin == 3
                gridcolor(a1,varargin{2},varargin{3},cstd); return
            end
        end
    end
    
    % Get / create grid axis
    ax1 = varargin{1};
    ax2 = getappdata(ax1,'hGridAxis');
    if isempty(ax2)
        ax2 = copyobj(ax1,get(ax1,'parent'));
        setappdata(ax1,'hGridAxis',ax2)
        uistack(ax2,'top')
        set(ax2,'xticklabel','','yticklabel','','zticklabel','','handlevisibility','off','hittest','off','color','none')
        set(ax1,'deletefcn',{@hGridAxis_delete, ax2})
        CreatePropertyListener(ax1,ax2)
    end
        
    set(ax2,'xcolor',varargin{2},'ycolor',varargin{3},'zcolor',varargin{4},'handlevisibility','off','hittest','off')
    
    % Set linked properties
    if any(exist('linkprop','file') == [2 5])     
        % Matlab version 7 (or higher)
        hlink = linkprop([ax2 ax1],{'CameraPosition','CameraUpVector','CameraTarget','CameraViewAngle',  ...
            'xscale','yscale','zscale','xlim','ylim','zlim','xdir','ydir','zdir', ...
            'xtick','ytick','ztick','tickdir','ticklength', ...
            'XAxisLocation','YAxisLocation', ...
            'PlotBoxAspectRatio','Dataaspectratio','position','units','Projection','box','linewidth','visible'});

        setappdata(ax1,'axes_linkprop',hlink);
        
    else
        % Matlab 6.5 and lower, will probably not work ...
        set(ax2,{'CameraPosition','CameraUpVector', 'gridlinestyle','minorgridlinestyle',...
            'xscale','yscale','zscale','xlim','ylim','zlim', 'xdir','ydir','zdir'}, ...
            get(ax1, {'CameraPosition','CameraUpVector','gridlinestyle','minorgridlinestyle',...
            'xscale','yscale','zscale','xlim','ylim','zlim', 'xdir','ydir','zdir'}))
        if isempty(show_only_once)
            warning('GridColor:OldMatlabVersion', ...
                '\n\t"gridcolor" will only work properly for Matlab 7.0 or higher. \n\tNo support for Matlab 6.x or lower.')
            show_only_once = 1;
        end
    end
end
    
% ------------------------    
function out = iscolor(in)
    % See if input argument is a valid Matlab color specification
	out = (ischar(in) && any(strcmpi(in,{'y','m','c','r','g','b','w','k'}))) || (isnumeric(in) && length(in)==3 &&  all(in>=0) && all(in<=1)); 
end

% ---------------------------    
function hGridAxis_delete(varargin)
    try delete(varargin{3}); end
end
    
function CreatePropertyListener(ax1,ax2)
    % This is adapted from Yair Altman's submission "PropListener" (see FEX)
    % Create property listener for grid-calls
    h_ax1 = handle(ax1);
    props = {'XGrid' 'YGrid' 'ZGrid' 'XMinorGrid' 'YMinorGrid' 'ZMinorGrid' 'MinorGridLineStyle' 'GridLineStyle'};
    event = 'PropertyPostSet';
    callback = {@UpdateGridStyle,ax1,ax2,props};

    for i = 1:length(props); hSrc(i) = h_ax1.findprop(props{i}); end

    hl = handle([]);
    hl = handle.listener(h_ax1, hSrc, event, callback);

    % Persist property listeners (or remove if empty callback)
    p = findprop(h_ax1, 'Listeners__');
    if (isempty(p))
        p = schema.prop(h_ax1, 'Listeners__', 'handle vector');
        set(p,  'AccessFlags.Serialize', 'off', 'AccessFlags.Copy', 'off', 'FactoryValue', [], 'Visible', 'off');
    end

    % filter out any non-handles
    h_ax1.Listeners__ = h_ax1.Listeners__(ishandle(h_ax1.Listeners__));
    h_ax1.Listeners__ = [h_ax1.Listeners__; hl];
end

function UpdateGridStyle(varargin)
    
    ax1 = varargin{3}; h_ax1 = handle(ax1);
    ax2 = varargin{4};
    props = varargin{5};
    
    set(ax2, props, get(ax1,props))
    
%     % 
%     tmp = h_ax1.Listeners__;
%     h_ax1.Listeners__ = [];
%     set(ax1,'xgrid','off', 'ygrid','off','zgrid','off','xminorgrid','off','yminorgrid','off','zminorgrid','off')
%     h_ax1.Listeners__ = tmp;
    
end
    

Contact us