function Handle=uiswitch(hfig, p1,v1,p2,v2,p3,v3,p4,v4,p5,v5,p6,v6,p7,v7,p8,v8, p9,v9,p10,v10)
%UISWITCH  Make a 'nice' switch uicontrol.
%
%           H=UISWITCH(HFIG, 'P1',V1,'P2',V2,P3,V3...)
%
%
%    UISWITCH makes a switch that works like a
%    checkbuttons but looks like a real switch.
%    The parameters are passed in the same way as the uicontrol
%    function except that the style is not specified.
%    If HFIG is omitted the gcf is chosen.
%    H is the pushbutton handle of the switch.
%
%    Through the 'UserData' property, different types can be specified:
%    Valid type_mode flags are:
%
%       LIGTH_VT  Vertical Switch with a light  (Default)
%       LIGTH_HZ  Horizontal Switch with a light
%       TEXT_VT   Vertical Switch with a text
%       TEXT_HZ   Horizontal Switch with a text
%
%    LIGTH_VT or LIGTH_HZ type:
%    Switch with a light that goes on end off.
%    The function create four uicontrols: 
%    a mainframe, a lightbutton, a pushbutton and a slideframe.
%    All the four handles are stored in the H 'userdata'
%    property in this order:
%       PushButtonHandle
%       MainFrameHandle
%       LightButtonHandle
%       SlideFrameHandle
%
%    TEXT_VT or TEXT_HZ type:
%    Switch with a the text 'ON'  end 'OFF' above and below.
%    The function create five uicontrols: 
%    a mainframe, two text uicontrols,a pushbutton and a slideframe.
%    The text can also be specified using the parameter string.
%    If only one string is specified it goes to the button, if two they
%    go to the two text and if three the first two go to
%    the text and the third to the button.
%    All the five handles are stored in the H 'userdata'
%    property in this order:
%       PushButtonHandle
%       MainFrameHandle
%       TextONHandle
%       TextOFFHandle
%       SlideFrameHandle
%
%
%    The mode will be kept in the pushbutton 'ButtonDownFcn'
%    property.
%
%
%    HOW DELETE THE SWITCH:        
%        if h is the returned handle:
%        delete(get(h, 'userdata'))  will do the job.
%
%    NOTE:
%      The frames and pushbutton parameter 'Userdata'
%      cannot be modified because already used by the function.
%      If a tag is specified it is set to the pushbutton only.
%      Therefore, findobj('tag', 'SWITCH_1') will find only
%      one uicontrol.
%
%    EXAMPLE:
%       h=uiswitch(gcf, 'units', 'pixels',...
%                     'pos', [100 100 50 100],...
%                     'fore', 'r', 'value', 1,...
%                     'userdata', 'LIGHT_VT');
%
%    See Also: UICONTROL.
%

% This function can be modified with the only restriction that the
% next two lines have to be reteined.
%             Copyright (c) 1996 by Claudio Rivetti 
%                  claudio@alice.uoregon.edu
%
% Last version: September 28, 1996.
% ENJOY IT!


% definition of the  default lightframe and pushbutton spacing.
lsp=0.20;  %light spacing in percent
bsp=0.15;  %button spacing in percent
tsp=0.05;  %text spacing percent
ssp=0.20;  %slide spacing percent

if nargin > 21
	error('Too many input arguments.');
end

% Get the passed parameters
if nargin > 0,
	if isstr(hfig)
		if (nargin)/2-fix((nargin)/2),
			error('Incorrect number of input arguments')
		else
			cmdstr=['hfig, p1,'];
			for i=2:(nargin)/2,
					cmdstr = [cmdstr,'v',num2str(i-1),',p',num2str(i),','];
			end
			fig=gcf;
		end	
	else
		if (nargin-1)/2-fix((nargin-1)/2),
			error('Incorrect number of input arguments')
		else
			cmdstr='';
			for i=1:(nargin-1)/2,
					cmdstr = [cmdstr,'p',num2str(i),',v',num2str(i),','];
			end
		end
		fig=hfig;
	end
	cmdstr(length(cmdstr))=' ';
else
	fig=gcf;
end

%Builds the frame uicontrol that will contain the switch
h=uicontrol(fig, 'style', 'frame');
eval(['set(h,',cmdstr,');']);

%Valid type_modes
vtm=[	'LIGHT_VT';...
		'LIGHT_HZ';...
		'TEXT_VT ';...
		'TEXT_HZ '];

%Define type and mode
tm=upper(get(h, 'Userdata'));
if isempty(tm)
	swtype='LIGHT';
	swmode='VT';
else
	ok=0;
	for i=1:size(vtm,1)
		if strcmp(tm, strrep(vtm(i,:), ' ', ''));
			ok=1;
		end
	end
	if ~ok
		delete(h);
		error('Invalid mode_type parameter.');
	end
	[swtype, swmode]=strtok(tm, '_');
	swmode=swmode(2:length(swmode));
end


if strcmp(swtype, 'LIGHT')
	%Define the button callback
	cbk2=get(h, 'callback');
	cbk1=['ans=get(gco, ''user'');'...
		'if get(gco,''min''),'...
			'set(ans(3), ''backgr'', get(ans(2), ''backgr''));'...
			'ans=get(ans(2), ''user'');'...
		'else,'...
			'set(ans(3), ''backgr'', get(ans(1), ''fore''));'...
			'ans=get(ans(3), ''user'');'...
		'end;'...
		'set(gco, ''pos'', ans, ''min'', ~get(gco, ''min''));clear ans;'];
	cbk=[cbk1 'drawnow;' cbk2];
	
	
	%Determine the position of the lightframe and pushbutton of the switch
	pf1=get(h, 'pos');
	
	if strcmp(swmode, 'VT')  %Vertical

		bsp=min(pf1(3)*bsp, pf1(4)*bsp);
		bw=pf1(3)-2*bsp;
		bh=(pf1(4))/5;
		pb1=[pf1(1)+bsp pf1(2)+pf1(4)-bh-bsp bw bh];
		pb2=[pf1(1)+bsp pf1(2)+pf1(4)/3+bsp bw bh];
		
		old_units=get(h, 'units');
		set(h, 'units', 'pixels');
		pf1=get(h, 'pos');
		%set(h, 'units', old_units);
		lsp=min(pf1(3)*lsp, (pf1(4)/3)*lsp);
		lw=pf1(3)-2*lsp;
		lh=pf1(4)/3-2*lsp;
		lw=min(lw,lh);
		lh=lw;
		x=(pf1(3)-lw)/2;
		y=(pf1(4)/3-lh)/2;
		pf2=[pf1(1)+x pf1(2)+y lw lh];
		set(h, 'units', old_units);
		pf1=get(h, 'pos');
		sw=pf1(3)*ssp;
		sh=(pb1(2)+bh+bsp/2)-(pb2(2)-bsp/2);
		pf3=[pf1(1)+pf1(3)/2-sw/2 pb2(2)-bsp/2 sw sh];
		
	else  %Horizontal
	
		bsp=min(pf1(3)*bsp, pf1(4)*bsp);
		bw=(pf1(3))/5;
		bh=pf1(4)-2*bsp;
		pb1=[pf1(1)+pf1(3)-bw-bsp pf1(2)+bsp bw bh];
		pb2=[pf1(1)+pf1(3)/3+bsp pf1(2)+bsp bw bh];

					
		old_units=get(h, 'units');
		set(h, 'units', 'pixels');
		pf1=get(h, 'pos');
		lsp=min((pf1(3)/3)*lsp, pf1(4)*lsp);
		lw=pf1(3)/3-2*lsp;
		lh=pf1(4)-2*lsp;
		lw=min(lw,lh);
		lh=lw;
		x=(pf1(3)/3-lw)/2;
		y=(pf1(4)-lh)/2;
		pf2=[pf1(1)+x pf1(2)+y lw lh];
		set(h, 'units', old_units);
		pf1=get(h, 'pos');
		sh=pf1(4)*ssp;
		sw=(pb1(1)+bw+bsp/2)-(pb2(1)-bsp/2);
		pf3=[pb2(1)-bsp/2 pf1(2)+pf1(4)/2-sh/2 sw sh];
		
	end
	
	str=get(h, 'string');
	if size(str,1)==3
		str=strrep(str(3,:), setstr(0), '');
	end
	
	% set the starting values
	if get(h, 'value')
		pos=pb1;
		bg=get(h, 'ForegroundColor');
	else
		pos=pb2;
		bg=get(h, 'BackgroundColor');
	end
	
	%Builds the lightframe and the pushbutton
	hl=uicontrol(fig, 'style', 'push',...
			'BackgroundColor',     bg,...         
			'Units',               'pixels',...
			'Position',            pf2,...
			'enable',       	   'off',... 
			'Clipping',            get(h, 'Clipping'),... 
			'Interruptible',       get(h, 'Interruptible'),... 
			'Visible',             get(h, 'visible'));

	hs=uicontrol(fig, 'style', 'frame',...
			'BackgroundColor',     [0 0 0],...         
			'Units',               old_units,...
			'Position',            pf3,...
			'enable',       	   get(h, 'enable'),... 
			'Clipping',            get(h, 'Clipping'),... 
			'Interruptible',       get(h, 'Interruptible'),... 
			'Visible',             get(h, 'visible'));
			
				
	hb=uicontrol(fig, 'style', 'pushbutton',...
			'BackgroundColor',     get(h, 'BackgroundColor'),...
			'CallBack',            cbk,...
			'ForegroundColor',     get(h, 'ForegroundColor'),...
			'HorizontalAlignment', get(h, 'HorizontalAlignment'),...            
			'Min',                 get(h, 'value'),...
			'Position',            pos,...
			'String',              str,...
			'Tag',                 get(h, 'tag'),...
			'Units',               old_units,...
			'Value',               get(h, 'value'),...
			'ButtonDownFcn',       get(h, 'ButtonDownFcn'),...
			'enable',       	   get(h, 'enable'),... 
			'Clipping',            get(h, 'Clipping'),... 
			'Interruptible',       get(h, 'Interruptible'),... 
			'Visible',             get(h, 'Visible'));
	
	
	handles=[hb;h;hl;hs];
	
	%set the Pushbutton, mainframe and lightframe handles
	%in the pushbutton userdata
	set(hb, 'userdata', handles);
	
	%set the pushbutton position when OFF in the
	%mainframe userdata
	set(h, 'userdata', pb2, 'tag', '');
	
	%set the pushbutton position when ON in the
	%lightframe userdata
	set(hl, 'userdata', pb1);
	
	set([h;hl;hs], 'units', old_units);

elseif strcmp(swtype, 'TEXT')

	%Define the button callback
	cbk2=get(h, 'callback');
	cbk1=['ans=get(gco, ''user'');'...
		'if get(gco,''min''),'...
			'set(ans(3), ''enable'', ''off'');'...
			'set(ans(4), ''enable'', ''on'');'...
			'ans=get(ans(2), ''user'');'...
		'else,'...
			'set(ans(3), ''enable'', ''on'');'...
			'set(ans(4), ''enable'', ''off'');'...
			'ans=get(ans(3), ''user'');'...
		'end;'...
		'set(gco, ''pos'', ans, ''min'', ~get(gco, ''min''));clear ans;'];
	cbk=[cbk1 'drawnow;' cbk2];
	
	
	str=get(h, 'string');
	if isempty(str)
		btstr='';
		str1='ON';
		str2='OFF';
	elseif size(str,1)==1
		btstr=strrep(str(1,:), setstr(0), '');
		str1='ON';
		str2='OFF';
	elseif size(str,1)==2
		btstr='';
		str1=strrep(str(1,:), setstr(0), '');
		str2=strrep(str(2,:), setstr(0), '');
	elseif size(str,1)==3
		btstr=strrep(str(3,:), setstr(0), '');
		str1=strrep(str(1,:), setstr(0), '');
		str2=strrep(str(2,:), setstr(0), '');
	end
	
	%Determine the position of the lightframe and pushbutton of the switch
	pf1=get(h, 'pos');
	
	if strcmp(swmode, 'VT')  %Vertical
		
		tsp=min(pf1(3)*tsp, (pf1(4)/2)*tsp);
		tw=pf1(3)-2*tsp;
		th=pf1(4)/4-2*tsp;
		x=(pf1(3)-tw)/2;
		y=(pf1(4)/5-th)/2;
		tx1=[pf1(1)+x pf1(2)+pf1(4)-th-tsp tw th];
		tx2=[pf1(1)+x pf1(2)+tsp tw th];
		
		bsp=min(pf1(3)*bsp, pf1(4)/3*bsp);
		bw=pf1(3)-2*bsp;
		bh=pf1(4)/5;
		pb1=[pf1(1)+bsp tx1(2)-bsp-bh bw bh];
		pb2=[pf1(1)+bsp tx2(2)+th+bsp bw bh];
		
		sw=pf1(3)*ssp;
		sh=(tx1(2)-tsp/2)-(tx2(2)+th+tsp/2);
		pf3=[pf1(1)+pf1(3)/2-sw/2 tx2(2)+th+tsp/2 sw sh];
		
	else  %Horizontal
	
		tsp=min((pf1(3)/2)*tsp, pf1(4)*tsp);
		tw=pf1(3)/4-2*tsp;
		th=pf1(4)-2*tsp;
		x=(pf1(3)/4-tw)/2;
		y=(pf1(4)-th)/2;
		tx1=[pf1(1)+x pf1(2)+y tw th];
		tx2=[pf1(1)+pf1(3)-x-tw pf1(2)+y tw th];

		bsp=min(pf1(3)/4*bsp, pf1(4)*bsp);
		bw=pf1(3)/5;
		bh=pf1(4)-2*bsp;
		pb1=[tx1(1)+tw+bsp pf1(2)+bsp bw bh];
		pb2=[tx2(1)-bw-bsp    pf1(2)+bsp bw bh];

		sh=pf1(4)*ssp;
		sw=(tx2(1)-tsp/2)-(tx1(1)+tw+tsp/2);
		pf3=[tx1(1)+tw+tsp/2 pf1(2)+pf1(4)/2-sh/2 sw sh];
		
	end
	

	% set the starting values
	if get(h, 'value')
		pos=pb1;
		tx1e='on';
		tx2e='off';
	else
		pos=pb2;
		tx1e='off';
		tx2e='on';
	end

	%Builds the lightframe and the pushbutton
	htx1=uicontrol(fig, 'style', 'text',...
			'BackgroundColor',     get(h, 'BackgroundColor'),...
			'ForegroundColor',     get(h, 'ForegroundColor'),...
			'Units',               get(h, 'units'),...
			'Position',            tx1,...
			'string',              str1,...
			'enable',       	   tx1e,... 
			'Clipping',            get(h, 'Clipping'),... 
			'Interruptible',       get(h, 'Interruptible'),... 
			'Visible',             get(h, 'visible'));
			
	htx2=uicontrol(fig, 'style', 'text',...
			'BackgroundColor',     get(h, 'BackgroundColor'),...
			'ForegroundColor',     get(h, 'ForegroundColor'),...
			'Units',               get(h, 'units'),...
			'Position',            tx2,...
			'string',              str2,...
			'enable',       	   tx2e,... 
			'Clipping',            get(h, 'Clipping'),... 
			'Interruptible',       get(h, 'Interruptible'),... 
			'Visible',             get(h, 'visible'));

	hs=uicontrol(fig, 'style', 'frame',...
			'BackgroundColor',     [0 0 0],...         
			'Units',               get(h, 'units'),...
			'Position',            pf3,...
			'enable',       	   get(h, 'enable'),... 
			'Clipping',            get(h, 'Clipping'),... 
			'Interruptible',       get(h, 'Interruptible'),... 
			'Visible',             get(h, 'visible'));
		
	
	hb=uicontrol(fig, 'style', 'pushbutton',...
			'BackgroundColor',     get(h, 'BackgroundColor'),...
			'CallBack',            cbk,...
			'ForegroundColor',     get(h, 'ForegroundColor'),...
			'HorizontalAlignment', get(h, 'HorizontalAlignment'),...            
			'Min',                 get(h, 'value'),...
			'Position',            pos,...
			'String',              btstr,...
			'Tag',                 get(h, 'tag'),...
			'Units',               get(h, 'units'),...
			'Value',               get(h, 'value'),...
			'ButtonDownFcn',       get(h, 'ButtonDownFcn'),...
			'enable',       	   get(h, 'enable'),... 
			'Clipping',            get(h, 'Clipping'),... 
			'Interruptible',       get(h, 'Interruptible'),... 
			'Visible',             get(h, 'Visible'));
	
	
	handles=[hb;h;htx1;htx2;hs];
	
	%set the Pushbutton, mainframe and lightframe handles
	%in the pushbutton userdata
	set(hb, 'userdata', handles);
	
	%set the pushbutton position when OFF in the
	%mainframe userdata
	set(h, 'userdata', pb2, 'tag', '');
	
	%set the pushbutton position when ON in the
	%lightframe userdata
	set(htx1, 'userdata', pb1);

end


if nargout >0
	Handle=hb;
end

return


