function blowup(flag);

%BLOWUP  A general purpose zoom routine for plots.
%	Usage:  blowup (with NO arguments)
%       Author: L. Larrabee Strow
%
%Blowup assumes you have generated an (m by 1) set of plot(s).  You need to 
%generate subplots in order from top to bottom of the page.  The first (top) 
%plot is called A1 and so on to Am.  Four GUI controls are used to do the 
%zooms.  The top one is a menu that selects which subplot will be used to do 
%a rubberband blowup.  The rubberband determines both x and y scaling for 
%the chosen plot.  Only the x limits of the rubberband are used to zoom the 
%other plots in the figure.  If you instead choose the middle control called 
%Blowup, the mouse is used only to select the x limits for all plots.  The 
%third control is called Default, and it sets all axes back to the default 
%limits.  To move back to the previous X-axis limite, select the button 
%Backup.  Note that Backup does not preserve rubber band box Y-axis limite.
%Finally the GUI button called Done deletes all GUI buttons and
%puts the plot back to its original form before you called blowup.
%
%This single source file both sets up the GUI, and contains the routines for 
%the callbacks.  If blowup is called with no arguments, the GUI is set up.  
%The GUI then calls this same source file, now with the flag argument, 
%which determines which callback to execute.
echo on
% Get handles for all axes
ah=[];
  h=gcf;
  hc=get(h,'children');
  for ii = hc'
    if strcmp(get(ii, 'Type'), 'axes')
       ah = [ah;ii];
    end
  end
n=length(ah);  
% Sort handles, Matlab changes their order at times.  They must be 
% sorted so we can identify first plot as smallest handle, and so on...
ah=sort(ah);

if nargin == 0 

	% Shorten all x-axes to make room for buttons
	for ii=1:n
		apos=get(ah(ii),'Position');
		set(ah(ii),'Position',[apos(1) apos(2) apos(3)*0.93 apos(4)]);
	end

	% Create the Blowup pushbutton
	BlowUpButton = uicontrol(...
					'Style','Pushbutton',...
					'Position',[.89 .50 .10 .05],...
					'Units','normalized',...
					'String','Blowup',...
					'Callback','blowup(1)');
	
	% Create the Default pushbutton
	DefaultAxisButton = uicontrol(...
					'Style','Pushbutton',...
					'Position',[.89 .35 .10 .05],...
					'Units','normalized',...
					'String','Default',...
					'Callback','blowup(2)');

	% Create the Back pushbutton
	BackupButton =   uicontrol(...
					'Style','Pushbutton',...
					'Position',[.89 .425 .10 .05],...
					'Units','normalized',...
					'String','Backup',...
					'Callback','blowup(5)');
	
	% Create the Done pushbutton
	DoneButton = uicontrol(...
					'Style','Pushbutton',...
					'Position',[.89 .15 .10 .05],...
					'Units','normalized',...
					'String','Done',...
					'Callback','blowup(4)');

	% Create the MoveRight pushbutton
	MoveRight = uicontrol(...
					'Style','Pushbutton',...
					'Position',[.89 .65 .10 .05],...
					'Units','normalized',...
					'String',' Right(+) ',...
					'Callback','blowup(6)');
	
	% Create the MoveRight pushbutton
	MoveLeft = uicontrol(...
					'Style','Pushbutton',...
					'Position',[.89 .57 .10 .05],...
					'Units','normalized',...
					'String',' Left(-) ',...
					'Callback','blowup(7)');
	
	% Create a textbox denoting A1..Am as selections for rbbox zooming
	Rbbox_Info = uicontrol(...
					'Style','Text',...
					'Units','Normalized',...
					'String','Rbbox',...
					'Position',[.8885 .80 .10 .05]);
	
	% Create string that controls rbbox menu appearance
	menu_string=[];
	for ii = 1:n
	  menu_string = [menu_string,'A ',int2str(ii),'|'];
	end
	% Get rid of trailing |
	mn=length(menu_string)-1;
	menu_string=menu_string(1:mn);
	
	% Create rbbox menu to select which subplot to do rbbox command on
	Rbbox_PopMenu = uicontrol(...
					'Style','popup',...
					'Units','Normalized',...
					'String',menu_string,...
					'Position',[.89 .75 .10 .05],...
					'Value',1,...
					'Callback','blowup(3)',...
					'Interruptible','yes');

    % Put all handles in UserData so I don't need globals, needed for rbbox
    % callback and to delete all widgets when done.
    LastXLimits=[0 0];
	set(gcf,'UserData',[BlowUpButton DefaultAxisButton Rbbox_Info Rbbox_PopMenu DoneButton BackupButton MoveRight MoveLeft LastXLimits]);

% Callback routines
elseif nargin == 1

	% Select blow(flag = 1:4) callbacks
	if flag == 1
		% Save axis values for Backup
		temp=get(gcf,'UserData');
		x=axis;
		temp(9:10)=[x(1) x(2)];
		set(gcf,'UserData',temp);
		% x-axis blowup
		% Array to hold temporary handles of vertical cut lines
		th=zeros(1,2*n);
		% Get start x value
		  axes(ah(1));
		  x = axis;
		  [x1,y1] = ginput(1);
		  th(1)=line([x1 x1],[x(3) x(4)],'erasemode','xor','color','g');
		% Put vertical line denoting start x-value on all plots
		  for ii = 2:n
			% Make axis with handle ah(ii) current
		    axes(ah(ii));
		    % Save min,max of y-axis in x(3), x(4)
		    x=axis;
		    % Plot start-x line
		    th(ii)=line([x1 x1],[x(3) x(4)],'erasemode','xor','color','g');
		  end;
		% Get stop x value, first set current axis to top one
		  axes(ah(1))
		  [x2, y2] = ginput(1); 
		  th(n+1)=line([x2 x2],[x(3) x(4)],'erasemode','xor','color','g');
		% Put vertical line denoting stop x-value of all plots
		  for ii = 2:n
		    axes(ah(ii));
		    x=axis;
		    th(n+ii)=line([x2 x2],[x(3) x(4)],'erasemode','xor','color','g');
		  end;
		  pause(0.50);
		% Get rid of vertical cut lines
   		    delete(th);
		% Redo all axes
		    set(ah,'xlim', [x1, x2]); 
   	elseif flag == 2
		% Set all axes to their default values
		  set(ah,'xlimmode','auto','ylimmode','auto');
	elseif flag == 3
		% Get the Rbbox_PopMenu handle from UserData, and then find the Value of 
		% the menu selection
		% Save axis values for Backup
		temp=get(gcf,'UserData');
		x=axis;
		temp(9:10)=[x(1) x(2)];
		set(gcf,'UserData',temp);		  
		mi=get(temp(4),'Value');
		% h is the handle of the axis to a rbbox on (assumes subplots 
        %	plotted in order from top to bottom)
		h=ah(mi);
		% Make the selected axis current
		axes(h);
		% Do the rrbox command
		set(gcf,'Pointer','Crosshair');
		waitforbuttonpress;
		drawnow
  		Pt1 = get(h,'currentpoint');
		drawnow
		rbbox([get(gcf,'currentpoint') 0 0],get(gcf,'currentpoint'));
		drawnow
		Pt2 = get(h,'currentpoint');
		drawnow
		rect = [min([Pt1(1,1:2);Pt2(1,1:2)]) abs(Pt2(1,1:2)-Pt1(1,1:2))];
		x1=rect(1);x2=rect(1)+rect(3);
		set(h,'xlim',[rect(1) rect(1)+rect(3)],'ylim',[rect(2) rect(2)+rect(4)]);
		drawnow
		% Redo all other axes
		for ii=1:n 
		  if ~(ii == mi) set(ah(ii),'xlim', [x1, x2]); end; 
		end
		set(gcf,'Pointer','Arrow');
	elseif flag == 4
	    temp=get(gcf,'UserData');
		delete(temp(1:8));
		% Widen all axes to what they were before calling blowup
		for ii=1:n
			apos=get(ah(ii),'Position');
			set(ah(ii),'Position',[apos(1) apos(2) apos(3)./0.93 apos(4)]);
		end
	elseif flag == 5
	   	temp=get(gcf,'UserData');
    	set(ah,'xlim', temp(9:10), 'ylimmode','auto'); 	
	elseif flag == 6
		% Get start x value for whatever axes is current
  		% Move to the right by the width
		  axes(ah(1));
          x = axis;
		  newx1=x(2);
		  newx2=x(2)+(x(2)-x(1));
		  set(ah,'xlim', [newx1, newx2]);
	elseif flag == 7
		% Get start x value for whatever axes is current
  		% Move to the right by the width
		  axes(ah(1));
          x = axis;
		  newx1=x(1)-(x(2)-x(1));
		  newx2=x(1);
		  set(ah,'xlim', [newx1, newx2]);
	end  % flag
end % nargin