function clk_win

% function clk_win
%
% This function is used in conjunction with FD3.  It is called every time that
% a user clicks on anywhere in the workspace and takes actions dependent on
% which menu item is currently selected.
%
% ACP

% Last update:  July 12, 1993
% Author:       Adrian C. Penisson

global FD3FIGURE FD3AXES FD3MODULES FD3STREAMS FD3MESSAGE FD3SCALE
global FD3NEXT FD3FUNCLEVEL FD3LASTPOS FD3OBJECT FD3TEMP
global FD3TEXT FD3BOXES FD3SCALE FD3STATUS FD3MENUS FD3SLIDERS

% Don't do anything unless user is clicking on axis or one of it's children.

c=get(FD3FIGURE,'CurrentObject');

if any([c==gca c==get(FD3AXES(1),'Children')' ...
   c==get(FD3AXES(2),'Children')' c==get(FD3AXES(3),'Children')'])

   % Find the current position of the cursor, and which button was clicked.

   xy=get(gca,'currentpoint');
   button=get_but(FD3FIGURE);

   if button==1

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      if strcmp(FD3NEXT,'DashedBox') | strcmp (FD3NEXT,'SolidBox')

	 % Make box

	 if FD3FUNCLEVEL==0

	    % First Click

	    close(FD3MESSAGE);
	    FD3MESSAGE=di_mssg('Point and|click on the|opposite|corner.');

	    % Make a small block showing where the user clicked.

	    ph=patch(xy(1,1)+FD3SCALE*[-1 1 1 -1]/6, ...
                     xy(1,2)+FD3SCALE*[-1 -1 1 1]/6,'w');

	    FD3OBJECT=[FD3OBJECT ph];

	    % Save position and advance FD3FUNCLEVEL

	    FD3LASTPOS=xy;
	    FD3FUNCLEVEL=1;

	 elseif FD3FUNCLEVEL==1

	    % Now that both clicks have been made, the box can be drawn.

	    xdata=[FD3LASTPOS(1,1) xy(1,1) xy(1,1) FD3LASTPOS(1,1) ...
	       FD3LASTPOS(1,1)];
	    ydata=[FD3LASTPOS(1,2) FD3LASTPOS(1,2) xy(1,2) xy(1,2) ...
	       FD3LASTPOS(1,2)];

	    % Make line after first verifying that we are on the proper
	    % axes.  Boxes are children of FD3AXES(1).

	    if gca~=FD3AXES(1)
	       axes(FD3AXES(1))
	    end

	    bh=line(xdata,ydata);

	    % If the box is dashed, make it so.  Dashed boxes are
	    % are type 1 and solid boxes are type 2.

	    if strcmp(FD3NEXT,'DashedBox')
	       set(bh,'LineStyle','--');
	       boxtype=1;
	    else
	       boxtype=2;
	    end

	    % Make box clickable and add to FD3BOXES

	    set(bh,'ButtonDownFcn','clk_obj','Inter','yes');
	    FD3BOXES=[FD3BOXES [bh boxtype]'];

	    fd_reset(1)

	 end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      elseif strcmp(FD3NEXT,'AddText')

	 % Add text

	 close(FD3MESSAGE);
	 FD3MESSAGE=[];

	 [txt,flag]=di_inp_c('Enter your text','',1);

	 if length(txt)>0 & (~flag)

	    % Only create the text object if the actually entered some text.
	    % Text objects are children of FD3AXES(2).

	    axes(FD3AXES(2))

	    th=nice_txt(xy(1,1),xy(1,2),txt,0);
	    set(th,'ButtonDownFcn','clk_obj','Inter','yes');
	    FD3TEXT=[FD3TEXT th];

	    fd_reset(1)

	 else

	    % Since nothing was actaully created, the status of save
	    % is not changed.

	    fd_reset(0)

	 end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      elseif strcmp(FD3NEXT,'HandV') & FD3FUNCLEVEL==1 & ...
	 ~any(any(c==FD3MODULES([1 3],:)))

	 % The user has just clicked on the window after previously clicking
	 % on the module where the stream started.  This is the only case
	 % in clk_win where the click must have been on FD3AXES and not
	 % one of its children.  If the object is just being created, it is
	 % necessary to switch to FD3AXES(2) first.

	 [xdata,ydata]=extd_str(xy,1);

	 if length(FD3OBJECT)>0
	    set(FD3OBJECT,'Xdata',xdata,'Ydata',ydata)
	 else
	    axes(FD3AXES(2))
	    FD3OBJECT=line(xdata,ydata);
	 end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      elseif strcmp(FD3NEXT,'Copy') & FD3FUNCLEVEL==1

	 % The user has just made his second click.

	 if FD3TEMP(1)==0

	    % In this case, the object originally click on was a module, as
	    % shown by the flag.  Round the second click to the nearest grid
	    % intersection.

	    xy(1,1:2)=round(xy(1,1:2)/FD3SCALE)*FD3SCALE;

	    oldx=FD3MODULES(4,FD3TEMP(2));
	    oldy=FD3MODULES(5,FD3TEMP(2));

	    % Get the old modules data.

	    data=FD3MODULES(:,FD3TEMP(2));

	    % First copy the secondary object, if present.  Secondary objects
	    % are placed on FD3AXES(1).

	    if data(3)

	       if gca~=FD3AXES(1)
		  axes(FD3AXES(1))
	       end

	       [xdata,ydata]=shft_dat(data(3),oldx,oldy,xy(1,1),xy(1,2));
	       data(3)=line(xdata,ydata);

	    end

	    % Next, copy the label.  Labels are placed on FD3AXES(2).

	    axes(FD3AXES(2))

	    data(2)=nice_txt(xy(1,1),xy(1,2),get(data(2),'String'),...
	       get(data(2),'Rotation'));

	    % Finally, make the primary object.  Primary objects are placed
	    % on FD3AXES(3).

	    axes(FD3AXES(3))

	    [xdata,ydata]=shft_dat(data(1),oldx,oldy,xy(1,1),xy(1,2));
	    data(1)=line(xdata,ydata);

	    % Put the copy's adjusted [x, y] pair in its data.

	    data(4:5)=xy(1,1:2);

	    % Make the module's primary object and label clickable.

	    set(data(1),'User',get(FD3MODULES(1,FD3TEMP(2)),'User'))
            set(data(1:2),'But','clk_obj','Inter','yes')

	    % Make the module's secondary object, if present, clickable.

	    if data(3)
               set(data(3),'But','clk_obj','Inter','yes')
	    end

	    FD3MODULES=[FD3MODULES data];

	 else

	    % In this case, text is being copied.  Get the text rotation and
	    % string.  Text objects are placed on FD3AXES(2).

	    axes(FD3AXES(2))

	    rot=get(FD3TEMP(2),'Rotation');
	    txt=get(FD3TEMP(2),'String');
	    th=nice_txt(xy(1,1),xy(1,2),txt,rot);
	    FD3TEXT=[FD3TEXT th];
            set(th,'But','clk_obj','Inter','yes')

	 end

	 fd_reset(1)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      elseif strcmp(FD3NEXT,'Move') & FD3FUNCLEVEL==1

	 if FD3TEMP(1)==0

	    % The object being moved is a module as indicate by the flag.
	    % First, adjust, the [x, y] click to the nearest grid.

	    xy(1,1:2)=round(xy(1,1:2)/FD3SCALE)*FD3SCALE;

	    oldx=FD3MODULES(4,FD3TEMP(2));
	    oldy=FD3MODULES(5,FD3TEMP(2));

	    % First, move the secondary object, if present.

	    if FD3MODULES(3,FD3TEMP(2))

	       [xdata,ydata]=shft_dat(FD3MODULES(3,FD3TEMP(2)),oldx,oldy,...
		  xy(1,1),xy(1,2));
	       set(FD3MODULES(3,FD3TEMP(2)),'Xdata',xdata,'Ydata',ydata)

	    end

	    % Next, move the label.

	    set(FD3MODULES(2,FD3TEMP(2)),'Position',[xy(1,1:2) 0]);

	    % Finally, move the primary object.

	    [xdata,ydata]=shft_dat(FD3MODULES(1,FD3TEMP(2)),oldx,oldy,...
	       xy(1,1),xy(1,2));
	    set(FD3MODULES(1,FD3TEMP(2)),'Xdata',xdata,'Ydata',ydata);

	    % Save the modules [x, y] position.

	    FD3MODULES([4 5],FD3TEMP(2))=xy(1,1:2)';

	    % Find out if there are any streams connected to the module.

	    connected=find(any(FD3STREAMS([4 5],:)==...
	       FD3MODULES(1,FD3TEMP(2))));

	    if any(connected)

	       % If this branch is being followed, there must be some
	       % connected streams.

	       for i=1:length(connected)

		  % We are going through the connected streams one at a time.
		  % The situation must be handled differently depending
		  % on whether or not the stream is an inlet or outlet for the
		  % the module.

	     	  if FD3STREAMS(4,connected(i))==FD3MODULES(1,FD3TEMP(2))

		     % Follow this branch if the stream exits the module
		     % being moved.  First get the stream's x/ydata.

		     xdata=get(FD3STREAMS(1,connected(i)),'Xdata');
		     ydata=get(FD3STREAMS(1,connected(i)),'Ydata');

		     % Use the stream's x/ydata and the objects new position
		     % to calculate the new endpts for the stream.

		     xy1=[xdata(1)-oldx+xy(1,1) ...
			ydata(1)-oldy+xy(1,2)];
		     xy2=[xdata(length(xdata)) ydata(length(ydata))];

		     if FD3STREAMS(6,connected(i))

			% In this case, the stream is a simple arbitrary
			% straight line type.

		        xdata=[xy1(1) xy2(1)];
		        ydata=[xy1(2) xy2(2)];

		     else

			% In this case, the stream is composed of alternating
			% horizontal and vertical lines.  Use auto_str to
			% come up with new stream.

		        [xdata,ydata]=auto_str(FD3TEMP(2),xy1,find(...
			   FD3STREAMS(5,connected(i))==FD3MODULES(1,:)),xy2);

		     end

	          else

		     % Follow this branch if the stream enters the module
		     % being moved.  First get the stream's x/ydata.

		     xdata=get(FD3STREAMS(1,connected(i)),'Xdata');
		     ydata=get(FD3STREAMS(1,connected(i)),'Ydata');

		     % Use the stream's x/ydata and the objects new position
		     % to calculate the new endpts for the stream.

		     xy1=[xdata(1) ydata(1)];
		     xy2=[xdata(length(xdata))-oldx+xy(1,1) ...
		        ydata(length(ydata))-oldy+xy(1,2)];

		     if FD3STREAMS(6,connected(i))

			% In this case, the stream is a simple arbitrary
			% straight line type.

		        xdata=[xy1(1) xy2(1)];
		        ydata=[xy1(2) xy2(2)];

		     else

			% In this case, the stream is composed of alternating
			% horizontal and vertical lines.  Use auto_str to
			% come up with new stream.

		        [xdata,ydata]=auto_str(find(...
			   FD3STREAMS(4,connected(i))==FD3MODULES(1,:)),...
		           xy1,FD3TEMP(2),xy2);

		     end

	          end

		  % Give the streams its new x/ydata and adjust the arrow.

		  set(FD3STREAMS(1,connected(i)),'Xdata',xdata,'Ydata',ydata)
		  adj_arw(connected(i))

	       end

	       % Because the order of FD3STREAMS is important (most recently
	       % updated streams are last), the "connected" streams are
	       % removed (leaving tempstreams) and placed again at the end.

	       for j=1:size(FD3STREAMS,2)
	          if ~any(j==connected)
		     tempstreams=[tempstreams FD3STREAMS(:,j)];
	          end
	       end

	       FD3STREAMS=[tempstreams FD3STREAMS(:,connected)];

	       % Update those bumps.

	       make_bmp

	    end

	 else

	    % In this case, text is being moved.  Simply change the position.

	    set(FD3TEMP(2),'Position',[xy(1,1:2) 0])

         end

	 fd_reset(1)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      elseif strcmp(FD3NEXT,'Page')

	 % Follow this branch if the user is in Page View and has just clicked
	 % on the window to return to quadrant view.  First, calculate a
	 % values for xlim and ylim which would center a quadrant on that
	 % point.

         xlim=FD3SCALE*([-11 11]+xy(1,1)/FD3SCALE);
         ylim=FD3SCALE*([-8.25 8.25]+xy(1,2)/FD3SCALE);

	 % If xlim would go out of the work space, move xlim so it will just
	 % be within the work space.

         if min(xlim)<0
	    xlim=[0 22]*FD3SCALE;
         elseif max(xlim)>(44*FD3SCALE)
	    xlim=[22 44]*FD3SCALE;
         end

	 % If ylim would go out of the work space, move ylim so it will just
	 % be within the work space.

         if min(ylim)<0
	    ylim=[0 16.5]*FD3SCALE;
         elseif max(ylim)>(33*FD3SCALE)
	    ylim=[16.5 33]*FD3SCALE;
         end

	 % set axes

         set(FD3AXES,'Xlim',xlim,'Ylim',ylim);

	 % Flip/flop menu

         child=get(FD3MENUS(6),'Children');
         set(child(2),'Label','Full Page');

	 % Move sliders to apprpriate positions

         set(FD3SLIDERS(1),'Value',max(xlim)/FD3SCALE);
         set(FD3SLIDERS(2),'Value',max(ylim)/FD3SCALE);
         set(FD3SLIDERS,'Visible','on');

	 % Put tick marks and menus back on.

         set(FD3AXES,'TickLength','factory')
         set_menu(6,'on',1);

	 % Turn all the text back on.

	 lenmod=size(FD3MODULES,2);
	 if lenmod>1
	    set(FD3MODULES(2,2:lenmod),'Visible','on');
	 end

	 lenstr=size(FD3STREAMS,2);
	 if lenstr>1
	    set(FD3STREAMS(2,2:lenstr),'Visible','on');
	 end

	 set(FD3TEXT,'Visible','on');

	 % Turn grid back on if necessary.  The grid is a child of FD3AXES(1).

         if FD3STATUS(2)
	    if gca~=FD3AXES(1)
	       axes(FD3AXES(1))
	    end
	    grid
         end

	 fd_reset(0)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      elseif ( ~(strcmp(FD3NEXT,'Delete')|strcmp(FD3NEXT,'Reverse')|...
	 strcmp(FD3NEXT,'Diag')|strcmp(FD3NEXT,'RotateCCW')|...
	 strcmp(FD3NEXT,'RotateCW')|strcmp(FD3NEXT,'EditLabel')|...
	 strcmp(FD3NEXT,'AddLabel')|strcmp(FD3NEXT,'EditText')|...
	 strcmp(FD3NEXT,'Resize')|strcmp(FD3NEXT,'DashedBox')|...
	 strcmp(FD3NEXT,'SolidBox')|strcmp(FD3NEXT,'AddText')|...
	 strcmp(FD3NEXT,'HandV')|strcmp(FD3NEXT,'Copy')|...
	 strcmp(FD3NEXT,'Move')|strcmp(FD3NEXT,'Page')|...
	 strcmp(FD3NEXT,'Raise')) & FD3NEXT~=[] )

	 % If this branch is followed, the user is creating a module.  First,
         % get rid of instruction message now that user has clicked.

         close(FD3MESSAGE);
	 FD3MESSAGE=[];

	 % For the first click, FD3FUNCLEVEL always equals zero at this point.
	 % If it is the first click, the xy coordinates need to be rounded
	 % to the nearest gridline intersection.

	 if FD3FUNCLEVEL==0
	    xy(1,1:2)=round(xy(1,1:2)/FD3SCALE)*FD3SCALE;	
	 end

	 % Evaluate the module function.  If the module function requires
	 % multiple clicks, the module function will advance FD3FUNCLEVEL
	 % to a value greater than one.  If FD3FUNCLEVEL is reset to zero
	 % (or remains zero) after the eval, no more clicks will be read
	 % and the module will be created.

	 eval(['data=' FD3NEXT '(xy);'])

	 if FD3FUNCLEVEL==0

	    % If this branch is followed, the module is complete.  If the 
	    % module does not already have a label, disenable menus, read in
	    % the label, and create it.

	    if ~data(2)
	       set_menu(1:6,'off')
	       [label,flag]=di_inp_c('Enter the module''s label.','',1);
	       if flag
		  label='';
	       end
	       axes(FD3AXES(2))
	       data(2)=nice_txt(data(4),data(5),label,0);
	    end

	    % Store the name of the module's m-file in its UserData and make
	    % the module's primary object and label clickable.

	    set(data(1),'User',FD3NEXT)
            set(data(1:2),'But','clk_obj','Inter','yes')

	    % Make the module's secondary object, if present, clickable.

	    if data(3)
	       set(data(3),'But','clk_obj','Inter','yes')
	    end

	    % Add the new module to the module matrix.

	    FD3MODULES=[FD3MODULES data'];

	    fd_reset(1)
	
	 else

	    % Follow this branch if the user will have to click another time.
	    % Make a small block showing where the user just clicked (or the
	    % where the user clicked rounded to the nearest grid intersection
	    % if this is the first click).

	    ph=patch(xy(1,1)+FD3SCALE*[-1 1 1 -1]/6, ...
                     xy(1,2)+FD3SCALE*[-1 -1 1 1]/6,'w');
	    FD3OBJECT=[FD3OBJECT ph];

         end

      end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

   end

   restack

end
