function z=pushprop(h, varargin)
%PUSHPROP Get, set and restore Handle Graphics objects
% PUSHPROP is used to temporarily save and optionally set one or more
% properties of one or more Handle Graphics objects.
%
% SFUN=PUSHPROP(H,'PropertyName') gets the current value of the named
% property and returns a restore struct SFUN, containing one field, the
% function handle 'pop'. Calling SFUN.pop() will reset the object to the
% previous value.
%
% SFUN=PUSHPROP(H,pn) saves the current values of properties specified by
% cell array pn and returns the restore function SFUN.
%
% SFUN=PUSHPROP(H,'PropertyName',PropertyValue, ...) will save the
% current values of the properties and also set the object's property to
% PropertyValue.
%
% SFUN=PUSHPROP(H,pn,MxN_pv) saves n property values from each of m
% graphics objects, where m=length(H) and n is equal to the number of
% property names contained in the cell array pn and then sets the same
% objects to the new values MxN_pv. This allows you to set a given group
% of properties to different values on each object.
%
% PUSHPROP is used in passages normally coded like this:
%
% SavedProp = get(h, 'Property');
% set(h, 'Property', newval);
% ... interact some more with object h
% set(h, 'Property', SavedProp;
%
% With PUSHPROP, the above segment can be written as
%
% SavedProp = pushprop(h, 'Property', newval);
% % ... interact some more with object h
% SavedProp.pop();
%
% Although it does save you one line of code, the real advantage is that
% the saved and restored property name(s) only need to be entered once,
% making the code easier to maintain and also makes the coder's
% intentions more transparent.
%
% Remarks:
% PUSHPROP closely mimics the syntax of SET, except for the output. Also,
% it behaves consistently for a structure array, in that it treats the
% elements in the array as individual setting for each handle. SET uses
% the last element of the struct for all objects.
%
% Example:
% % Set the current figure's background color to red for two seconds.
% SavedColor=pushprop(gcf, 'Color', [1 0 0]);
% pause(2);
% SavedColor.pop();
%
% See also: SET, GET
% 071122 Version 1.0 Released to FEX
% 071123 Version 1.1 Realized that some settings depend on the order they
% are set. Fixed by restoring in reverse order.
%
% Author: Jerker Wgberg, More Research, SWEDEN
% email: char(hex2dec(reshape('6A65726B65722E77616762657267406D6F72652E7365',2,[])')')
% Check for correct number of arguments. Not much more error checking
% to do since GET and SET seem to return meaningful error messages.
error(nargchk(2,inf,nargin, 'struct'));
nargs=length(varargin);
if nargin==2 && ~isstruct(varargin{1})
% Caller just wants some properties saved.
saved{1}=cellstr(varargin{1});
saved{2} = get(h,saved{1});
else
% Preallocate storage for saved properties. Too big if structs are
% used, but we correct that later.
saved=cell(2,(nargs+rem(nargs,2))/2);
% Initilize the saved setting counter
ns=0;
i=1;
while i<=nargs
ns=ns+1;
if isstruct(varargin{i})
s=varargin{i};
saved{1,ns}=flipud(fieldnames(s));
saved{2,ns}=get(h, saved{1,ns});
% Fix for SET's questionable behaviour when input is a
% structure array.
set(h,flipud(saved{1,ns}),struct2cell(s(:))');
i=i+1;
else
saved{1,ns}=cellstr(varargin{i});
% Get in reverse order so we can set in back correctly
saved{1,ns}=flipud(saved{1,ns}(:));
saved{2,ns} = get(h,saved{1,ns});
if i==nargs
error('pushprop:MissingValues', 'Argument/Value pairs must come in pairs');
end
set(h, varargin{i}, varargin{i+1});
i=i+2;
end
end
% Trim the saved properties array
saved(:,nargs+1:end)=[];
saved=fliplr(saved);
end
z.pop=@()set(h, saved{:});
end