function printcomp(varargin) 
%PRINTCOMP Create and display a print preview of SPTool GUI components.

% Copyright 1988-2000 The MathWorks, Inc.
% $Date: 2000/06/08 22:11:13 $ $Revision: 1.12 $  

switch varargin{1}
   
case 'ClosePrevFig'
   % Close the invisible print preview figure window
   stale_hFigPrev = findobj('Tag','PrntPrev');
   if ishandle(stale_hFigPrev),
      close(stale_hFigPrev);
   end
   
% The next 3 cases are selections from component's 'File' menu
case 'prev',       % Preview was selected
   % Handle help mode for uipushtool, TPK 6/26/99
   ud = get(gcbf,'userdata');
   if ud.pointer==2   % help mode
      spthelp('exit','printpreview')
      return
   end

   hFigPrev = create_preview(gcbf,'prev');
   set(hFigPrev,'Visible','on');
   
case 'prnt',       % Print was selected; don't show preview
   % Handle help mode for uipushtool, TPK 6/26/99
   ud = get(gcbf,'userdata');
   if ud.pointer==2   % help mode
      spthelp('exit','print')
      return
   end

   hFigPrev = create_preview(gcbf,'prnt');
   prnt_prev_fig(hFigPrev,'prnt');
   
case 'pgepos',     % Page Position selected
   hFigPrev = create_preview(gcbf,'pgepos');
   prnt_prev_fig(hFigPrev,'pgepos');
   
case 'prevprnt',   % "Print" ui was selected in preview figure
   % Print preview figure
   prnt_prev_fig(gcbf,'prevprnt');
   
case 'resizemenubar',
   % Resize menubar if preview window is resized
   prevInfoStruct = get(gcbf,'UserData');
   resizemenubar(prevInfoStruct.menubarhndls);
end 

%%%%%%%%%%%%%%%%%%%%%%%%
%   Subfunctions       %
%%%%%%%%%%%%%%%%%%%%%%%%


function hFigPrev = create_preview(gcbf,action)
% CREATE_PREVIEW Create an invisible figure containing the preview
%                of the figure to be printed.
%                
% The following logic is used to determine whether to create a new 
% preview figure or to use the existing preview figure.
%
% 1. If no preview figure exists create one.
% 2. If a preview figure exists and user has selected Page Setup or Print 
%    Preview, create a new preview (NOTE: this will override page setup
%    settings if user previously selected Page Setup.)
% 3. If a preview figure exists and user has selected Print then assume
%    user wants to print the existing preview figure (NOTE: the existing
%    preview figure was created because Page Setup was previously selected.
% 4. If a preview figure exists but it belongs to a different component
%    then the one currently being printed from, delete the existing 
%    print preview and create a new one.

% Cache component's figure handle.
hcomp = gcbf;

% Determine which component is being printed from.
compName = get(hcomp,'Name'); % Can be Signal Browser or Spectrum Viewer

% Add a command to close the preview figure to the SPTool component
% figure property DeleteFcn.  This ensures that any invisible preview
% figure window that is left behind is deleted when the tool is closed.
add_closePrev2delFcn(hcomp)

% Search for preview figure.
hFigPrev = findobj('Tag','PrntPrev');

prevFigName = [];
if ishandle(hFigPrev),
   % Find out from which component is the existing preview figure.
   % Using the Figure name instead of a tag to determine which component
   % is being printed.  Hence figure name of preview figure MUST contain
   % the figure name of the component (e.g., Signal Browser).
   prevFigName = get(hFigPrev,'Name');
   prevFigName = prevFigName(1:length(compName));
end

% Check if a preview figure exists and user selected the PRINT option.
% If so, print the existing preview figure window.
if isempty(hFigPrev) | ~ishandle(hFigPrev) | ~strcmp(action,'prnt') | ...
      ~strcmp(compName,prevFigName),
   
   % If user selected Page Setup or Print Preview OR if printing from a
   % new component then delete existing preview before creating a new one.
   if (~strcmp(action,'prnt') & ~isempty(hFigPrev)) | ...
         (~isempty(prevFigName) & ~strcmp(compName,prevFigName)),
      delete(hFigPrev);
   end
   
   % Get specific information from the given component 
   compInfoStruct = getcompinfo(hcomp);

   % Generate preview figure
   [hFigPrev, prevInfoStruct] = preview(compInfoStruct); 
   
   % Store the preview information in UserData of preview figure
   set(hFigPrev,'UserData',prevInfoStruct); 
   
   % Set units to normalized so axes resize correctly
   setaxesnorm(hFigPrev);
end

% end of create_preview
% ---------------------------------------------------------------------------------


function compInfoStruct = getcompinfo(hFig);
%GETCOMPINFO  Build a structure of information for one (at a time) of 
%             sptool's components for printing.  The handle of the 
%             component is the input argument.

showhid = get(0,'ShowHiddenHandles');
set(0,'ShowHiddenHandles','on');

% Get information common to all components
ud = get(hFig,'UserData'); 
compInfoStruct.name = get(hFig,'Name');
compInfoStruct.tag = get(hFig,'Tag');
compInfoStruct.pos = get(hFig,'Position'); 
compInfoStruct.prefs = ud.prefs; 
set(0,'ShowHiddenHandles',showhid); % Turn HiddenHandles back

% For all components but Filter Designer
if ~strcmp(compInfoStruct.name, 'filtdes'),  
   compInfoStruct.opts(1).name = 'mainaxes'; % compInfoStruct.opts is an array of structures  
   compInfoStruct.opts(1).value =  ud.mainaxes;
   if ud.prefs.tool.ruler, 
      compInfoStruct.opts(end+1).name = 'ruler';  
      compInfoStruct.opts(end).value = ud.ruler; 
   end  
end

switch compInfoStruct.tag
   
% Get information specific to each component
case 'sigbrowse',
   if ud.prefs.tool.panner,
     compInfoStruct.opts(end+1).name = 'panner'; 
     compInfoStruct.opts(end).value = ud.panner; 
  end
  
case 'filtview',
% Filter Viewer
  
case 'filtdes',
% Filter Designer
  
case 'spectview',
   compInfoStruct.opts(end+1).name = 'spect';    
   compInfoStruct.opts(end).value = ud.spect;
   compInfoStruct.opts(end+1).name = 'methods';    
   compInfoStruct.opts(end).value = ud.methods;
   compInfoStruct.opts(end+1).name = 'lines';    
   compInfoStruct.opts(end).value = ud.lines; 
end 

% end of getcompinfo
% ---------------------------------------------------------------------------------


function [hFigPrev, prevInfoStruct] = preview(compInfoStruct)
%PREVIEW  Generate a print preview for a component of sptool.

% Create figure for preview
hFigPrev = figure('Position',compInfoStruct.pos, ...
                'Name',[compInfoStruct.name ' Print Preview'],...
                'NumberTitle','off',...
                'ResizeFcn','printcomp(''resizemenubar'')',...
                'Tag','PrntPrev',...
                'PaperPositionMode','auto',... 
                'IntegerHandle','off',...
                'MenuBar','none',...
                'HandleVisibility','on',...
                'Visible','off');
             
% Axes to place Box around entire preview figure
axes('Units','Norm','Position',[0 0 1 1],...
     'XTick',[],'YTick',[],'Box','on','Color','none');
             
for i =1:length(compInfoStruct.opts),
   
   switch compInfoStruct.opts(i).name
      
   case 'mainaxes',          
      set(hFigPrev,'Position',compInfoStruct.pos); % Set preview position to component position
      % Copy mainaxes to preview figure
      hmaxes = copyobj(compInfoStruct.opts(i).value, hFigPrev); 
      set(hmaxes,'Units','Pixels','HandleVisibility','on'); 
      
      % Clear 'ButtonDownFcn' for children of main axes (ruler lines)
      hchildMax = get(hmaxes,'Children');
      set(hchildMax,'ButtonDownFcn','');
      
      % Build a structure of preview information
      prevInfoStruct.prevItem(i).name = 'mainaxes';
      prevInfoStruct.prevItem(i).axhandle = hmaxes;
      prevInfoStruct.prevItem(i).pos = get(hmaxes,'Position');  
           
   case 'ruler',
      % Get Ruler Values       
      [rulervals, rulerlbls] = getrulervals(compInfoStruct.opts(i).value); 
      
      % Create frame (by making an axes) to display ruler values
      hraxes = axes('Ytick',[],'Xtick',[],'Visible','off',...  
                    'Box','on','Color','none','Tag','ruler',...
                    'Units','Pixels');
      hrxlabel = xlabel('Marker Values'); 
      
      % Create text to display ruler values and labels.
      hrvalstxt = createrulervalstxt(hraxes, rulervals, rulerlbls);
      
      prevInfoStruct.prevItem(i).name = 'ruler'; 
      prevInfoStruct.prevItem(i).axhandle = hraxes;
      prevInfoStruct.prevItem(i).pos = get(hraxes,'Position'); 

      % Ruler specific information
      prevInfoStruct.rulerinfo.rulervals = rulervals;
      prevInfoStruct.rulerinfo.rulerlbls = rulerlbls;
      prevInfoStruct.rulerinfo.hrvalstxt = hrvalstxt;      
      
   case 'panner',
      % Copy panaxes to preview figure
      hpaxes = copyobj(compInfoStruct.opts(i).value.panaxes, hFigPrev); 
      set(hpaxes,'Units','Pixels');
      % Change color of panner xlabel because when copied to preview
      % it becomes white. See private/panner.m  
      hxlbl = get(hpaxes,'Xlabel');
      set(hxlbl,'Color',[0 0 0]);      
      
      prevInfoStruct.prevItem(i).name = 'panaxes';
      prevInfoStruct.prevItem(i).axhandle = hpaxes; 
      prevInfoStruct.prevItem(i).pos = get(hpaxes,'Position');
      
   case 'spect',
      [hspecs, specStrs] = getSpecInfo(compInfoStruct.opts(:));
      
      prevInfoStruct.specinfo.hspecs = hspecs;
      prevInfoStruct.specinfo.specStrs = specStrs;
   end
end

% Set position of preview information being printed
setpos(hFigPrev, prevInfoStruct);

% Turn on the "Print" and "Close" uicontrols in the preview figure
prevInfoStruct.menubarhndls = menubar_on(hFigPrev);

% end of preview
% ---------------------------------------------------------------------------------


function resizemenubar(menubar_hndls)
%RESIZEMENUBAR  Resizes the preview menubar when window is resized. 

% Get specific information from the preview figure
hFigPrev = gcbf;
old_units = get(hFigPrev,'Units');
set(hFigPrev,'Units','pixels');
figpos = get(hFigPrev,'Position');

% Set the new positions of the uicontrols
uibarpos = [2, figpos(4)-20, figpos(3)-3, 20];
set(menubar_hndls.huibar ,'Position',uibarpos);

uiprntpos = [uibarpos(1)+10, figpos(4)-20, 50, 20];
set(menubar_hndls.huiprnt,'Position',uiprntpos);

uiclsepos = [uiprntpos(1)+uiprntpos(3)+10, figpos(4)-20, 50, 20];
set(menubar_hndls.huiclse,'Position',uiclsepos);

set(hFigPrev,'Units', old_units);

% end of resizemenubar
% ---------------------------------------------------------------------------------


function h = menubar_on(hFigPrev)
%MENUBAR_ON  Uicontrols for print and close in the preview figure.


h.huibar = uicontrol(hFigPrev,...
                           'Style','text',...
                           'Tag','pprevbarui');

h.huiprnt = uicontrol(hFigPrev,...
                            'Style','Push',...
                            'String','Print...',...
                            'Tag','pprevui',...
                            'CallBack','printcomp(''prevprnt'')');
                         
h.huiclse = uicontrol(hFigPrev,...
                            'Style','Push',...
                            'String','Close',...
                            'Tag','ppcloseui',...
                            'CallBack','closereq;');

resizemenubar(h);

% end of menubar_on
% ---------------------------------------------------------------------------------


function [rulervals, rulerlbls] = getrulervals(rulerstruct)
%GETRULERVALS  Get ruler values to display.

field_name = fieldnames(rulerstruct.value);
rulervals = []; % Initialize ruler value 
rulerlbls = {}; % and label cell arrays

for i = 1:length(field_name),
   if ~isnan(getfield(rulerstruct.value,field_name{i})), % Get all non-NaN values
      rulervals(end+1) = getfield(rulerstruct.value,field_name{i}); 
      rulerlbls{end+1} = field_name{i}; 
   end
end

% Need to check if 'type' is track and not display last value and label.
% There's a bug in Sigbrowse that doesn't set the slope value to NaN when not
% in slope mode.
if strcmp(rulerstruct.type, 'track') & length(field_name)==length(rulervals),
      rulervals = rulervals(1:end-1); % All but the last (for the dydx case)
      rulerlbls = rulerlbls(1:end-1); %  "   "  last label
end

% Need to check if 'type' is slope and display the last label as "m" and not "dydx."
if strcmp(rulerstruct.type, 'slope') 
   rulerlbls{end} = 'm'; 
end


% end of getrulervals
% ---------------------------------------------------------------------------------


function hrvalstxt = createrulervalstxt(hraxes, rulervals, rulerlbls)
%CREATERULERVALSTXT Creates the text objects to display the Ruler values.

for k = 1:length(rulervals),
   hrvalstxt(k) = text(10*k, 20, [rulerlbls{k} ': ' num2str(rulervals(k),4)]);
   set(hrvalstxt(k),'Visible','off','Units','Pixels');
end

% end of createrulervalstxt
% ---------------------------------------------------------------------------------


function prnt_prev_fig(hndl_prev, prnt_option)
%PRNT_PREV_FIG Prints the preview figure.

% Need to turn visiblity off for uicontrols (or else the figure is displayed)
prevInfoStruct = get(hndl_prev,'UserData');
menubar_off(prevInfoStruct.menubarhndls);

if strcmp(prnt_option,'pgepos'),
   dlg = pagesetupdlg(hndl_prev);
   % Leave the invisible preview figure open so that when the user
   % actually selects print the changes made in the page setup dialog 
   % box will take effect (in the printout).
else
   dlg = printdlg(hndl_prev);
   
   % On UNIX platforms this function executes asynchronously, while on PCWIN 
   % it's executed synchronously.  Therefore, for UNIX we must add "close
   % preview figure" to the dialog box DeleteFcn callback so that the 
   % preview figure is closed when the user dismisses the print dialog box.
   % While for PCWIN we can simply issue the command, to close preview figure,
   % right after the call to printdlg because ONLY after the dialog box has 
   % been dismissed by the user will the close command be executed.
   %
   % Also, the following code should be executed if the HG pagesetupdlg 
   % function was called - we want to delete the preview figure ONLY 
   % after the page setup dialog box has been dismissed by the user.
   %
   % As of R12, printdlg and pagesetupdlg will return a:
   % - nonempty value, which means the old HG dialog was launched and 
   % it returns the dialog's handle (which we need to delete).
   % or 
   %  - an empty value, which means the dialog came and went and is no longer
   % available - either because it was a native PC dialog or because it was a
   % Java dialog.
   %
   if ~isempty(dlg), 
      add_closePrev2delFcn(dlg)
   else 
      % Do it this way because printdlg doesn't return a handle on the PC.
      close(hndl_prev);
   end
end

% end of prnt_prev_fig
% ---------------------------------------------------------------------------------


function add_closePrev2delFcn(hFig)
%ADD_CLOSEPREV2DELFCN Prepends a command to close the preview figure to
%                     to the figure's (specified by the input handle h)
%                     DeleteFcn property.

% Cache the preview figure's DeleteFcn string (if one exists)
oldDelFcn = get(hFig,'DeleteFcn');

% Prepend a command (to close the preview figure) to the print or pagesetup 
% dialog figure's DeleteFcn string.
newDelFcn = ['printcomp(''ClosePrevFig''); ',oldDelFcn];
set(hFig,'DeleteFcn',newDelFcn);

% end of add_closePrev2delFcn
% ---------------------------------------------------------------------------------

function menubar_off(menubar_hndls)
%MENUBAR_OFF  Turn off visibility of the "Print" and "Close" uicontrols. 
%            
set(menubar_hndls.huibar,'Visible','off');
set(menubar_hndls.huiprnt,'Visible','off');
set(menubar_hndls.huiclse,'Visible','off');

% end of menubar_off
% ---------------------------------------------------------------------------------


function  setaxesnorm(hndl_prev);
%SETAXESNORM Set units to normalized so axes resize correctly

set(hndl_prev,'Units','Norm');

prevInfoStruct = get(hndl_prev,'UserData');
set([prevInfoStruct.prevItem(:).axhandle], 'Units','Norm'); % Mainaxes, panaxes, and ruler

if isfield(prevInfoStruct,'rulerinfo'),
   set([prevInfoStruct.rulerinfo.hrvalstxt], 'Units','Norm');
end

% end of setaxesnorm
% ---------------------------------------------------------------------------------


function setpos(hFigPrev, previnfo)
%SETPOS  Sets the position of the different information being printed.

% These positions will be set later depending on whether or not these items 
% will be printed; Please do not change these values.
ruler_ax_pos = [0 0 0 0];
panner_ax_pos = [0 0 0 0];
space_between_ax = 20;  % Vertical spacing between axes

% Get component position 
figpos = get(hFigPrev,'Position');

% Set dimensions for items
main_ax_left_edge = 57; 
main_ax_bottom_edge = 28;
main_ax_wdth = figpos(3)-100; 
main_ax_hght = figpos(4)-75;% 325; 
main_ax_pos = [main_ax_left_edge main_ax_bottom_edge main_ax_wdth main_ax_hght]; 

% Determining what items exist and their respective widths and heights
for indx = 1:length(previnfo.prevItem),
   switch previnfo.prevItem(indx).name
      
   case 'mainaxes',
      hmainaxes = (previnfo.prevItem(indx).axhandle);
      
   case 'ruler',
      ruler_ax_pos(4) = 25; % Need height (arbitrary) to determine how much to move up others
      hruleraxes = (previnfo.prevItem(indx).axhandle);
              
   case 'panaxes',
      pos = previnfo.prevItem(indx).pos; 
      panner_ax_pos(4) = pos(4);
      hpanner = (previnfo.prevItem(indx).axhandle);
      
   end
end
% Vertical space multiplier
vspace_multi = sum(([main_ax_pos(2) ruler_ax_pos(4) panner_ax_pos(4)]~=0))-1;

% Set the positions of items that exist

% Offset for mainaxes Y position and height relative to the other items
offset = main_ax_pos(2)+ruler_ax_pos(4)+panner_ax_pos(4)+(vspace_multi*space_between_ax);
main_ax_pos = [main_ax_left_edge main_ax_bottom_edge+offset main_ax_wdth main_ax_hght-offset];
set(hmainaxes,'Position', main_ax_pos);
      
if exist('hruleraxes'), % If rulers are selected
   set(hruleraxes,'Position',[main_ax_left_edge main_ax_bottom_edge main_ax_wdth ruler_ax_pos(4)],...
       'Visible','on');
    
    % Set the positions for the text of ruler values based on the ruler axes
    ruler_pos = get(hruleraxes,'Position');    
    horzspace = (ruler_pos(3)-20)/length(previnfo.rulerinfo.rulervals); % Subtract 20 from Ruler axes
    ypos = ruler_pos(4)/2;                                              % width to make sure values appear 
    for k = 1:length(previnfo.rulerinfo.rulervals),                     % within axes
       xpos(k) = 7 + (k-1)*horzspace;
       set(previnfo.rulerinfo.hrvalstxt(k),'Position',[xpos(k) ypos],'Visible','on');
    end    
 end

if exist('hpanner'), % If panner is selected
   panner_bottom_edge = main_ax_bottom_edge + ruler_ax_pos(4) + (vspace_multi-1)*space_between_ax;
   set(hpanner,'Position',[main_ax_left_edge panner_bottom_edge main_ax_wdth panner_ax_pos(4)]);
end

% Spectrum Viewer: Need to put legend on axes after the main axes position is set
if isfield(previnfo, 'specinfo'),
   prevFont = get(hmainaxes,'FontName'); % Change FontName so that strings in legend
   set(hmainaxes,'FontName','Courier');  % line up properly.   
   
   % Cache state of figure visibility
   visState = get(get(hmainaxes,'parent'),'visible');
   
   % Call legend here instead of in the "preview" so that legend is positioned correctly
   legend(hmainaxes, previnfo.specinfo.hspecs, previnfo.specinfo.specStrs);
   
   % Legend makes an invisible figure visible, so workaround that.
   set(get(hmainaxes,'parent'),'visible',visState);
   set(hmainaxes,'FontName',prevFont);
end


% end of setpos
% ---------------------------------------------------------------------------------


function [hspecs, specStrs] = getSpecInfo(spectrumStruct)
%GETSPECINFO    Get the spectrum legend information.

% Index for "spect", "lines", and "methods" 
indxs = strmatch('spect',{spectrumStruct(:).name});
indxl = strmatch('lines',{spectrumStruct(:).name});
indxm = strmatch('methods',{spectrumStruct(:).name});

% Get spectra handles, labels(i.e. spect1, spect2, ...) and method name
for h = 1:length(spectrumStruct(indxs).value),
   hspecs(h) = spectrumStruct(indxl).value(h).h;
   Lbl{h} = spectrumStruct(indxs).value(h).label;
   methodName(h) = spectrumStruct(indxs).value(h).specs.methodName(spectrumStruct(indxs).value(h).specs.methodNum);
   
   % Get index for current "Method Name" from ud.methods(:).methodName 
   indxmethNam = strmatch(methodName{h}, {spectrumStruct(indxm).value(:).methodName});
   
   % Find index for "Nfft" label from ud.methods(:).label
   % Check if "methodName" is "Welch" or "MUSIC" and set the Index for the Nfft Label 
   % manually.  There is a bug (geck # 40830) with the ud.methods structure which 
   % doesn't allow strmatch to find "Nfft" for these two cases.
   if strcmp(methodName{h}, 'Welch'),
      indxNfftLbl = 1;                % First parameter down from "Method"
   elseif strcmp(methodName{h}, 'MUSIC')
      indxNfftLbl = 3;                % third   "         "    "    "
   else
      indxNfftLbl = strmatch('Nfft', spectrumStruct(indxm).value(indxmethNam).label);
   end
   
   % Actual Nfft value
   numfft{h} = spectrumStruct(indxs).value(h).specs.valueArrays{spectrumStruct(indxs).value(h).specs.methodNum}{indxNfftLbl};
end

% Pad strings with spaces so they line up correctly in the legend
Lbl = str2mat(Lbl);
methodName = str2mat(methodName);
numfft = str2mat(numfft); 

[M, N] = size(Lbl); % M (number of rows in legend)
for k = 1:M,
   specStrs{k} = [Lbl(k,:) ': ' methodName(k,:) ': Nfft = ' num2str(numfft(k,:))]; 
end

% end of getSpecInfo
% ---------------------------------------------------------------------------------

% [EOF] printcomp.m
