function varargout=spm_xbrain_getrotation(action,varargin)
% GUI letting user to specify brain view
% version 2.0
% John Ashburner, Tomas Sieger, 01/12/13
% 

switch action
case 'redraw_brain',
   % args:
   %	patch (brain surface)
   %  brain volume
   %  vox2mni matrix
   %	condition (which brain voxels should be drawn) 
   %	mni_tal_space - use MNI (0) / Talairach (1) space 
   p=varargin{1};
   brain=varargin{2};
   m_vox2mni=varargin{3};
   cond=varargin{4};
   mni_tal_space=varargin{5};
   xx=1:size(brain,1);
	yy=1:size(brain,2);
	zz=1:size(brain,3);
   [y0,z0]=ndgrid(yy,zz);
   for xi=1:size(brain,1)
      points=[repmat(xi,1,size(brain,2)*size(brain,3)); y0(:)'; z0(:)'; ones(1,size(brain,2)*size(brain,3))];
      points=m_vox2mni*points;
      points=points(1:3,:);
      if mni_tal_space==1
         % no MNI -> Talairach transform due low-resolution brain volume causing ugly alias
         % points=mni2tal(points);
      end
      x=points(1,:);
      y=points(2,:);
      z=points(3,:);
      msk=eval(['~(' cond ')']);
      brain(xi,msk)=0;
   end
   set(p,isosurface(brain,.6));
%	isonormals(brain,p);
case 'edit_cond_callback',
   % no args
   et=findobj(gcf,'Style','edit');
   cond=get(et,'String');
   data=get(gcf,'UserData');
   try,
      x=1;y=1;z=1;
      eval([cond ';']);
      p=findobj(gcf,'Type','patch');
      data.curr_cond=cond;
      set(gcf,'UserData',data); % remember last successful condition
      spm_xbrain_getrotation('redraw_brain',p,data.brain,data.m_vox2mni,cond,data.mni_tal_space);
   catch,
      errordlg('Can''t evaluate condition!','Error');
   end;
case 'delete_cond_callback',
   % no args
   et=findobj(gcf,'Style','edit');
   set(et,'String','1');
   data=get(gcf,'UserData');
   p=findobj(gcf,'Type','patch');
   spm_xbrain_getrotation('redraw_brain',p,data.brain,data.m_vox2mni,'1',data.mni_tal_space);
case 'reuse_cond_callback',
   % no args
   data=get(gcf,'UserData');
   et=findobj(gcf,'Style','edit');
   set(et,'String',data.prev_fig_cond);
   data.curr_cond=data.prev_fig_cond;
   set(gcf,'UserData',data); % remember last successful condition
   p=findobj(gcf,'Type','patch');
   spm_xbrain_getrotation('redraw_brain',p,data.brain,data.m_vox2mni,data.prev_fig_cond,data.mni_tal_space);
case 'reuse_rotation_callback',
   % no args
   data=get(gcf,'UserData');
   set(gca,'View',[data.prev_fig_azimuth,data.prev_fig_elevation]);
case 'map_morph_callback',
   % no args
   data=get(gcf,'UserData');
   cb_map_morph=findobj(gcf,'Style','checkbox','String','Map morphology onto brain');
   cb_map_morph_cuts_only=findobj(gcf,'Style','checkbox','String','Map onto cuts only');
   if get(cb_map_morph,'Value')==1
      if isempty(data.morphology)
         set(gcf,'WindowStyle','normal');
         data.morphology=spm_get(1,'n*.img','Select normalized morphology image');
         set(gcf,'WindowStyle','modal');
		   set(gcf,'UserData',data);
      end
      set(cb_map_morph_cuts_only,'Enable','on');
      set(cb_map_morph_cuts_only,'Value',get(cb_map_morph_cuts_only,'Max'));
   else
      set(cb_map_morph_cuts_only,'Enable','off');
   end
case 'draw_figure',
   % args:
   %	figure title
   %  morphology image (to be mapped onto brain)
   %	[prev figure condition, can be empty if no prev figure]
   %	[prev figure azimuth, can be empty if no prev figure]
   %	[prev figure elevation, can be empty if no prev figure]
   title=varargin{1};
   morphology=varargin{2};
   if nargin>3 & ~isempty(varargin{3})
      prev_fig_cond=varargin{3};
      prev_fig_azimuth=varargin{4};
      prev_fig_elevation=varargin{5};
   end

	load brain
	FV=isosurface(brain,.6);
	data.brain=brain;
	data.m_vox2mni=m_vox2mni;
   data.curr_cond='1';
   data.mni_tal_space=0;
   data.morphology=morphology;
	if exist('prev_fig_cond','var')
   	data.prev_fig_cond=prev_fig_cond;
   	data.prev_fig_azimuth=prev_fig_azimuth;
   	data.prev_fig_elevation=prev_fig_elevation;
	end

	fg = figure('NumberTitle','off','Name',title,'Resize','off',...
	   'UserData',data,'MenuBar','none');%'WindowStyle','modal');

	fg_pos=get(fg,'Position');
	ax = axes('Parent',fg,'position',[.13 .3 .7 .64]);
	p = patch(FV, 'Parent',ax,...
	   'FaceColor', [0.8 0.7 0.7], 'FaceVertexCData', [],...
   	'EdgeColor', 'none',...
	   'FaceLighting', 'phong',...
   	'SpecularStrength' ,.6, 'AmbientStrength', .6,...
	   'DiffuseStrength', .7, 'SpecularExponent', 10);

	set(0,'CurrentFigure',fg);    
	set(fg,'CurrentAxes',ax);
	camlight(-40,20);
	camlight(-210,0);
	axis image;
	axis off
	box on;
	view(3);
%	isonormals(brain,p);
	st_info=uicontrol(fg,'Style','text','Position',[fg_pos(3)*.35 fg_pos(4)*.95 174 17],...
	   'String','Use mouse to rotate the brain in 3D.',...
	   'Background',get(fg,'Color'));
	cb_map_morph=uicontrol(fg,'Style','checkbox','Position',[fg_pos(3)*.7 fg_pos(4)*.07 147 17],...
	   'String','Map morphology onto brain',...
      'Background',get(fg,'Color'),...
      'CallBack','spm_xbrain_getrotation(''map_morph_callback'')');
	cb_map_morph_cuts_only=uicontrol(fg,'Style','checkbox','Position',[fg_pos(3)*.7 fg_pos(4)*.03 110 17],...
	   'String','Map onto cuts only',...
      'Background',get(fg,'Color'),...
      'Enable','off');
	st_cond=uicontrol(fg,'Style','text','Position',[fg_pos(3)*.05 fg_pos(4)*.23 191 17],...
	   'String','Condition (which voxels ARE selected)',...
	   'Background',get(fg,'Color'));
	et_cond=uicontrol(fg,'Style','edit','Position',[fg_pos(3)*.02 fg_pos(4)*.18 fg_pos(3)*.75 20],...
	   'String','1',...
	   'Background',get(fg,'Color'),...
	   'CallBack','spm_xbrain_getrotation(''edit_cond_callback'')');
	pb_delete_cond=uicontrol(fg,'Style','pushbutton','Position',[fg_pos(3)*.029 fg_pos(4)*.12 100 20 ],...
	   'String','Delete condition',...
	   'CallBack','spm_xbrain_getrotation(''delete_cond_callback'')');
	if exist('prev_fig_cond','var')
		pb_reuse_cond=uicontrol(fg,'Style','pushbutton','Position',[fg_pos(3)*.22 fg_pos(4)*.12 150 20 ],... 
	      'String','Use previous view condition',...
	      'CallBack','spm_xbrain_getrotation(''reuse_cond_callback'')');
		pb_reuse_rotation=uicontrol(fg,'Style','pushbutton','Position',[fg_pos(3)*.5 fg_pos(4)*.12 145 20 ],...
	      'String','Use previous view rotation',...
	      'CallBack','spm_xbrain_getrotation(''reuse_rotation_callback'')');
	end
	rb_space_mni=uicontrol(fg,'Style','radiobutton','Position',[fg_pos(3)*.8 fg_pos(4)*.205 80 20 ],...
	   'String','MNI Space','Value',1,'Background',get(fg,'Color'),...
	   'CallBack',[...
         'set(findobj(''Style'',''radiobutton'',''String'',''Talairach Space''),''Value'',0);',...
         'set(findobj(''Style'',''radiobutton'',''String'',''MNI Space''),''Value'',1);',...
         'p=findobj(''type'',''patch'');',...
         'data=get(gcf,''UserData'');',...
         'data.mni_tal_space=0;',...
         'set(gcf,''UserData'',data);',...
         'clear p data;']);
%         'spm_xbrain_getrotation(''redraw_brain'',p,data.brain,data.m_vox2mni,data.curr_cond,data.mni_tal_space);',...
	rb_space_tal=uicontrol(fg,'Style','radiobutton','Position',[fg_pos(3)*.8 fg_pos(4)*.165 100 20 ],...
	   'String','Talairach Space','Value',0,'Background',get(fg,'Color'),...
	   'CallBack',[...
         'set(findobj(''Style'',''radiobutton'',''String'',''MNI Space''),''Value'',0);',...
         'set(findobj(''Style'',''radiobutton'',''String'',''Talairach Space''),''Value'',1);',...
         'p=findobj(''type'',''patch'');',...
         'data=get(gcf,''UserData'');',...
         'data.mni_tal_space=1;',...
         'set(gcf,''UserData'',data);',...
         'clear p data;']);
%         'spm_xbrain_getrotation(''redraw_brain'',p,data.brain,data.m_vox2mni,data.curr_cond,data.mni_tal_space);',...
   
	pb_accept=uicontrol(fg,'Style','pushbutton','Position',[fg_pos(3)/2-40 10 80 30 ],'String','Accept','CallBack','uiresume(gcf)');

	rotate3d on;
	uiwait(fg);
	view=get(gca,'View');
	data=get(fg,'UserData');
   varargout={view(1) view(2) data.curr_cond data.mni_tal_space ...
         get(cb_map_morph,'Value') data.morphology get(cb_map_morph_cuts_only,'Value') };
   delete(fg);
otherwise
   fprintf(1,'%s\n',action);
   error('''action'' not specified');
end


