function clk_obj

% function clk_obj
%
% This function is used in conjunction with FD3.  It is called whenever
% a user clicks on any object on the flow diagram.
%
% ACP

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

global FD3FIGURE FD3AXES FD3MODULES FD3STREAMS FD3MESSAGE 
global FD3NEXT FD3FUNCLEVEL FD3LASTPOS FD3OBJECT FD3TEMP
global FD3BOXES FD3TEXT

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

if button==1

   % modindex -- index of module if user clicked on primary or sec. objects
   % strindex -- index of stream if user clicked on stream or arrow objects

   modindex=find(any(FD3MODULES([1 3],:)==h));
   strindex=find(any(FD3STREAMS([1 3],:)==h));

   % modlabindex -- index of module if user clicked on primary, secondary, or
   %		    objects
   % strlabindex -- index of module if user clicked on stream, arrow, or text
   % 		    objects

   modlabindex=find(any(FD3MODULES(1:3,:)==h));
   strlabindex=find(any(FD3STREAMS(1:3,:)==h));

   % connected -- if any modindex, the indices of streams connected to that
   %		  module, else the empty set

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

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

   if strcmp(FD3NEXT,'Delete')

      % Follow this branch is the user is set to delete something.  First
      % close the message now that the user has clicked.  Also disengage all
      % menus since dialog boxes will soon pop up.

      close(FD3MESSAGE);
      FD3MESSAGE=[];
      set_menu(1:6,'off')

      if any(modindex)

	 % Follow this branch if the object is a module.  If there are streams
         % connected to h, issue a warning that they will be deleted along
         % with the object.  Next, ask the user if he wishes to delete the
         % module.

	 if any(connected)
	   di_warn('WARNING!','Connected streams will be deleted.', ...
              'CONTINUE')
	 end
         choice=di_choic('','Delete module?','YES','NO');
      
         if choice==1

	    % The user has chosen to delete.

	    % First, delete the streams, stream labels, and arrow heads of the
	    % connected streams.  Then remove these objects' handles from
	    % FD3STREAMS.

	    delete(reshape(FD3STREAMS(1:3,connected),1,3*length(connected)))

	    notconnected=find(all(FD3STREAMS(4:5,:)~=FD3MODULES(1,modindex)));
	    FD3STREAMS=FD3STREAMS(:,notconnected);

	    % Next, close the primary line object, the text object, and, if it
	    % exists, the secondary line object.  Then remove these objects'
	    % handles from FD3MODULES.

	    delete(FD3MODULES(find(FD3MODULES(1:3,modindex)~=0)',modindex))
	    FD3MODULES=FD3MODULES(:,find(1:size(FD3MODULES,2)~=modindex));

	    % If there were any connected streams, redo the bumps.

	    if any(connected)
	       make_bmp
	    end

	 end

      elseif any(strindex)

	 % Follow this branch if the object is a stream.  The actions are
	 % similar (though much simpler) than those taken in the module
	 % branch.

	 choice=di_choic('','Delete stream?','YES','NO');
	 if choice==1
	    delete(FD3STREAMS(1:3,strindex)')
	    FD3STREAMS=FD3STREAMS(:,find(1:size(FD3STREAMS,2)~=strindex));
	    make_bmp
	 end

      elseif (any(modlabindex) | any(strlabindex))

	 % Follow this branch if the object is a label.  Labels are not
	 % actually deleted, instead they are set to the empty string.

	 choice=di_choic('','Delete label?','YES','NO');
	 if choice==1
	    set(h,'String','')
	 end

      elseif any(FD3TEXT==h)

	 % Follow this branch is the object is a text object.  Unlike labels,
	 % text objects are actually deleted.

	 choice=di_choic('','Delete text?','YES','NO');
	 if choice==1
	    delete(h);
	    FD3TEXT=FD3TEXT(find(FD3TEXT~=h));
	 end

      elseif any(FD3BOXES(1,:)==h)

	 % The only thing left is a box.

	 choice=di_choic('','Delete box?','YES','NO');
	 if choice==1
	    delete(h);
	    FD3BOXES=FD3BOXES(:,find(FD3BOXES(1,:)~=h));
 	 end

      end

      % Turn Save on if user actually deleted anything, otherwise leave
      % Save as is.

      if choice==1
         fd_reset(1)
      else
	 fd_reset(0)
      end

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

   elseif strcmp(FD3NEXT,'Reverse') & any(strlabindex)

      % Follow this branch if the user is set to reverse stream flows.
      % When make_arw determines where to put the arrow head, it
      % always places it at the last point in xdata/ydata.  Therefore,
      % when stream flow is reversed, it is also necessary to reverse
      % the xdata and ydata vectors so that the new arrow head will be
      % placed properly.

      xdata=fliplr(get(FD3STREAMS(1,strlabindex),'Xdata'));
      ydata=fliplr(get(FD3STREAMS(1,strlabindex),'Ydata'));
      set(FD3STREAMS(1,strlabindex),'Xdata',xdata,'Ydata',ydata);

      % Swap handles for module 1 and module 2.  Then adjust arrow and label.

      FD3STREAMS(4:5,strlabindex)=FD3STREAMS([5 4],strlabindex);
      adj_arw(strlabindex)
      adj_lbl(strlabindex)
	    
      fd_reset(1)

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

   elseif strcmp(FD3NEXT,'Raise') & any(strlabindex)

      % Follow this branch if the user wishes to "raise" a stream.  When a
      % stream is raised, all bumps are placed on that stream (i.e. that
      % stream is now on top of any streams which intersect it and therefore
      % gets the bumps).  A stream need not intersect any other streams to
      % be raised.  Although there would really be nothing wrong with raising
      % streams when the bump mode is off, this is not allowed because it
      % would be confusing to the user.

      notraised=find(1:size(FD3STREAMS,2)~=strlabindex);
      FD3STREAMS=[FD3STREAMS(:,notraised) FD3STREAMS(:,strlabindex)];
      make_bmp

      fd_reset(1)

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

   elseif (strcmp(FD3NEXT,'HandV') | strcmp(FD3NEXT,'Diag')) & ...
      any(FD3MODULES(1,:)==h)

      % Follow this branch if the user has just clicked on the primary section
      % of a module and is in the stream creation mode

      if FD3FUNCLEVEL==0

	 % In this case, the user just clicked on the the first module.
         % Close previous message.  Set the point where the user
         % clicked to FD3LASTPOS.  This will be the starting point
	 % for the first line.  Advance FUNCLEVEL to 1.  The user
	 % may next click on another object or on the window to
	 % complete the first line.

	 close(FD3MESSAGE)
	 FD3MESSAGE=[];

         if strcmp(FD3NEXT,'HandV')

	    % If the user is making H and V streams, adjust the xy
	    % coordinate so that the end of the line will be exactly on the
	    % edge of the object and centered on a grid line.  First, however,
	    % define a horribl(y long) instruction message.

	    str='Point and|click on the|body of another|module to|complete ';
	    str=[str 'the|stream or on an|empty section|'];
	    str=[str 'of the flow|diagram to add|a segment to|the stream.'];

            xy=adj_edpt(modindex,xy);

	 else

	    str='Point and|click on the|body of the|module where|the stream';
	    str=[str '|ends.'];

	 end

	 % Store coordinate for later user, make message, save module index
	 % for later use, and make sure FD3FUNCLEVEL is advanced.

	 FD3LASTPOS=xy;
	 FD3MESSAGE=di_mssg(str);
      	 FD3TEMP=modindex;
         FD3FUNCLEVEL=1;

      elseif FD3FUNCLEVEL==1

	 % Follow this branch if the user just clicked on a second module.

	 if modindex==FD3TEMP

	    % In this case, the user click on the same module both times.
	    % This is a not allowed!

	    di_warn('WARNING!','Inlet and outlet must be different.',...
	       'CONTINUE')
	    fd_reset(0)
	    return

         end

	 if strcmp(FD3NEXT,'HandV')

	    % In this case, the user is making horiz/vertical lines.  First,
	    % adjust the xy coordinate as for the first click.

	    xy=adj_edpt(modindex,xy);

	    if length(FD3OBJECT)>0

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

	       if length(xdata)==2

		  % If the final FD3OBJECT only has two data points, 
		  % auto stream should ALWAYS be used instead.  Otherwise
		  % it is possible to get a stream which does not touch
		  % both modules.

		  [xdata,ydata]=auto_str(FD3TEMP,FD3LASTPOS(1,:), ...
		     modindex,xy(1,:));

	       end

	    else

	       % In this case, the user immediately clicked on the second
	       % object after clicking on the first.  The computer will
	       % therefore decide how to draw the stream.

	       [xdata,ydata]=auto_str(FD3TEMP,FD3LASTPOS(1,:), ...
		  modindex,xy(1,:));

	    end

	    % This is a h and v stream. It's type is zero.

	    strtype=0;

	 else

	    % In this case the user is creating and arbitrary straight line
	    % and has just made the second click.  Extending the streams
	    % is easy in this case.  The stream type is one.

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

	    strtype=1;

	 end

	 % Make stream.

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

         % Turn off all menus so the user doesn't try anything funny when
	 % he is supposed to be entering label.

         set_menu(1:6,'off')
         close(FD3MESSAGE);
         FD3MESSAGE=[];

	 % Get label.

	 label=str_inp('');

	 % Make arrow and label.  First make sure we are on the right axes.

	 axes(FD3AXES(2))

         th=make_lbl(xdata,ydata,label);
         ah=make_arw(xdata,ydata);

	 % Add stream to the global matrix.

         FD3STREAMS=[FD3STREAMS [FD3OBJECT th ah FD3MODULES(1,FD3TEMP) h ...
	    strtype]'];

	 % Make everything clickable.

         set([FD3OBJECT th ah],'ButtonDownFcn','clk_obj','Inter','yes');

	 % Adjust for bumps

	 make_bmp

         FD3OBJECT=[];
         fd_reset(1)

      end

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

   elseif strcmp(FD3NEXT,'RotateCCW') | strcmp(FD3NEXT,'RotateCW')

      % The user wishes to rotate some module, text, or label.

      if strcmp(get(h,'Type'),'text')

	 % In this case, the object is a label or a text object.  The
	 % value for the label's 'Rotation' is adjusted so it does not
	 % go beyod 360 degrees.

	 if strcmp(FD3NEXT,'RotateCCW')
	    set(h,'Rotation',rem(get(h,'Rotation')+90,360));
	 else
	    set(h,'Rotation',rem(get(h,'Rotation')-90,360));
	 end

	 fd_reset(1)

      elseif any(modindex)

	 % In this case, the the user clicked on a module (either
	 % the primary or secondary handle).

	 if any(connected)

	    % If there are any conneced streams, tell the user "too bad."
	    % Rotating a module with streams attached is too much trouble.

	    di_warn('BUMMER!','You cannot rotate this module.','CONTINUE')
	    fd_reset(0)
	    return

	 else

	    % Otherwise, rotate the module in the appropriate direction.

	    if strcmp(FD3NEXT,'RotateCCW')
	       mod_rot(modindex,1);
	    else
	       mod_rot(modindex,-1);
	    end

	    fd_reset(1)

	 end

      end

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

   elseif (strcmp(FD3NEXT,'EditLabel') | strcmp(FD3NEXT,'AddLabel')) & ...
      any([modlabindex strlabindex]) 

      % The user is adding or changing a label.  First turn off the menus and
      % get the text handle.

      close(FD3MESSAGE);
      FD3MESSAGE=[];
      set_menu(1:6,'Off')

      th=[FD3MODULES(2,modlabindex) FD3STREAMS(2,strlabindex)];

      % Get the old string.

      old=get(th,'String');

      if old~='' & strcmp(FD3NEXT,'AddLabel')

	 % If old label is not the empty string, you cannot add a label since
	 % there already is a label.  Give user option to edit label

	 choice=di_choic('There is already a label.', ...
            'Do you wish to edit it?','YES','NO');

	 if choice==2

	    % User choses not to edit.

	    fd_reset(0)
	    return

         end

      elseif old=='' & strcmp(FD3NEXT,'EditLabel');

	 % If old label is empty string, it is either "non-existent" or
	 % "deleted".  Give the user the option of adding a label.

	 choice=di_choic('There is no label to edit.', ...
	    'Do you wish to add one?','YES','NO');

	 if choice==2

	    % User choses not to add label

	    fd_reset(0)
	    return

	 end

      end

      if any(strlabindex)

	 % Either a stream or its label was clicked on.  Get new stream label.

	 label=str_inp(old);

      else

	 % Either a module or its label was clicked on.  Get new module label.

	 [label,flag]=di_inp_c('Enter the new module label.',old,1);

	 if flag
	    label=old;
	 end

      end

      if ~strcmp(label,old)

         % Give object its new label if necessary.

         set(th,'String',label)
         fd_reset(1)

      else

	 % No real change occurred.

	 fd_reset(0)

      end

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

   elseif strcmp(FD3NEXT,'EditText') & any(h==FD3TEXT)

      % We are editing text.  First, get rid of instructions and close
      % the menus so nothing funny is done.

      close(FD3MESSAGE)
      FD3MESSAGE=[];
      set_menu(1:6,'Off')

      % Querry for new text.

      def=get(h,'String');
      [txt,flag]=di_inp_c('Enter the new text.',def,1);

      if flag | strcmp(txt,def)

	 fd_reset(0)

      else

	 if length(txt)>0

	    % In this case, the user entered a "substantial" string so we
	    % change the text to it's edit form.

            set(h,'String',txt)

	 else

	    % If the edited version is a blank string, delete it because there
	    % is no way the user could ever access it again.

	    delete(h)
	    FD3TEXT=FD3TEXT(find(FD3TEXT~=h));

	 end

	 fd_reset(1)

      end

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

   elseif (strcmp(FD3NEXT,'Copy') | strcmp(FD3NEXT,'Move')) & ...
      (any(modlabindex) | any(h==FD3TEXT))

      % The user has clicked on a module or text object he wishes to copy
      % or move.

      if FD3FUNCLEVEL==0

	 % Only the first click (FD3FUNCLEVEL==0) is handled by clk_obj.
	 % The second click is handled by clk_win.  First, close the
	 % instruction message.

	 close(FD3MESSAGE)
	 FD3MESSAGE=[];

	 % Give the appropriate next instruction and advance FD3FUNCLEVEL.

	 if strcmp(FD3NEXT,'Copy')
	    str='Point and|click on the|copy''s center.';
	 else
	    str='Point and|click on the|new center.';
	 end

         FD3MESSAGE=di_mssg(str);
	 FD3FUNCLEVEL=1;

	 % FD3TEMP is set to a flag of 0 if we are dealing with a module
	 % and a flag of 1 if we are dealing with a text object.

	 if any(modlabindex)
	    FD3TEMP=[0 modlabindex];
	 else
	    FD3TEMP=[1 h];
	 end

      end

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

   elseif strcmp(FD3NEXT,'Resize') & any(modlabindex)

      % Follow this route if the user is resizing a module.  First, turn
      % off all the menus and close the instruction message.

      set_menu(1:6,'Off')
      close(FD3MESSAGE);
      FD3MESSAGE=[];

      if any(connected)

	 % If there are streams connected to the module, it cannot be
	 % resized.

	 di_warn('BUMMER!','You cannot resize this module.','CONTINUE')
	 fd_reset(0)
	 return

      end

      % Get the old x scaling factor (olds1) and the old y scaling factor
      % (olds2). 

      olds1=FD3MODULES(14,modlabindex);
      olds2=FD3MODULES(15,modlabindex);

      % Keep going through the following while loop until the user enters
      % an appropriate response.

      wflag=1;

      while wflag

	 [s1,s2,flag]=di_inp_2('X Scaling Factor',num2str(olds1),...
	    'Y Scaling Factor',num2str(olds2));

	 if flag
	    s1=olds1;
	    s2=olds2;
	 else
	    s1=str2num(s1);
	    s2=str2num(s2);
	 end

	 if any([(s1<=0) (s2<=0) (s1==[]) (s2==[])])
	    di_warn('WARNING!','Scaling factors must be (+) numbers.',...
	       'CONTINUE')
	 else
	    wflag=0;
	 end

      end

      if s1==olds1 & s2==olds2
	 fd_reset(0)
      else
	 mod_resz(modlabindex,s1,s2);
	 fd_reset(1)
      end

   end

   restack

end

