function pj = prepareui( pj, Fig )
%PREPAREUI Method to draw Uicontrol objects in output.
%   Mimics user interface objects as Images so they appear in output.
%   Takes screen captures of user interface objects and creates true  
%   color Images in the same location as the user interface objects so 
%   the uicontrols themselves seem to print (which they can not because
%   they are drawn by the windowing system, not MATLAB).
%
%   Ex:
%      pj = PREPAREUI( pj, h ); %modifies PrintJob object pj and creates
%                               %Images of Uicontrols in Figure h
%
%   See also PREPARE, RESTORE, PREPAREHG, RESTOREUI.

%   Copyright 1984-2002 The MathWorks, Inc. 
%   $Revision: 1.8.4.2 $  $Date: 2004/11/29 23:32:33 $

error( nargchk(2,2,nargin) )

if ~isequal(size(Fig), [1 1]) | ~isfigure( Fig )
    error( 'Need a handle to a Figure object.' )
end
    
%Early exist if the user has requested not to see controls in output.
if ~pj.PrintUI
    return
end

%Bail if device doesn't support TC images.
if  strcmp( pj.Driver, 'hpgl' ) | strcmp( pj.Driver, 'ill' )
    pj.UIData = [];
    return
end

%Now that we know it is a Figure, see if there is anything to do:
% Get handles to all visible uicontrols.
pj.UIData.UICHandles = findall(Fig,'Type','uicontrol','Visible','on');
% Get handles to all visible java components.
pj.UIData.UICHandles = [pj.UIData.UICHandles; 
                        findall(Fig, 'Type', 'uijavacontainer', 'Visible', 'on');];
conts = findall(Fig, 'Type', 'uicontainer', 'Visible', 'on');
jconts = [];
for i=1:length(conts)
    if isappdata(conts(i), 'javacomphandle');
        jconts(end+1, :) = conts(i);
    end
end
pj.UIData.UICHandles = [pj.UIData.UICHandles; jconts];

if isempty(pj.UIData.UICHandles)
    pj.UIData = [];
    return
end
    

ComputerType=computer;
pj.UIData.OldRootUnits=get(0,'Units');
pj.UIData.OldFigUnits=get(Fig,'Units');
pj.UIData.OldFigPosition=get(Fig,'Position');
pj.UIData.OldFigVisible=get(Fig,'Visible');
set( Fig, 'units', 'points' )
pj.UIData.MovedFigure = screenpos( Fig, get( Fig, 'position' ) );
pj.UIData.OldFigCMap=get(Fig,'Colormap');

set([0 Fig],'Units','pixels');

%%% UI Controls %%%

pj.UIData.AxisHandles = [];
Frame = [];
FrameNum = 0;
if ~isempty(pj.UIData.UICHandles)
    % Making the assumption that the bottom uicontrol is usually
    % created first and underneath the others.
    pj.UIData.UICHandles=flipud(pj.UIData.UICHandles);
    pj.UIData.UICUnits=get(pj.UIData.UICHandles,{'Units'});
    
    % This should not be necessary anymore since we depend on the
    % getpixelposition API for uicontrol position. But, printing popupmenu
    % uicontrol on the Mac (native) causes a hang if this is not done.
    % Keep this for now till that issue is resolved of Mac supports java
    % figures. Corresponding restore in restoreui.m
    set(pj.UIData.UICHandles,'Units','pixels');
    
    for Clp=1:length(pj.UIData.UICHandles)
        FrameFlag=1;
        CurCtrlPos = rectaroundcontrol( pj.UIData.UICHandles(Clp) );
        CurCtrlUnits = pj.UIData.UICUnits{Clp};
        
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %Check to see if completely contained in previous frames
        %and that the framing control has same units (so the scale similarly)
        for Frmlp=1:FrameNum
            if CurCtrlPos(1)>=Frame{Frmlp}.Pos(1) & ...
                    CurCtrlPos(2)>=Frame{Frmlp}.Pos(2) & ...
                    sum(CurCtrlPos([1 3]))<=sum(Frame{Frmlp}.Pos([1 3])) & ...
                    sum(CurCtrlPos([2 4]))<=sum(Frame{Frmlp}.Pos([2 4])) & ...
                    strcmp( Frame{Frmlp}.Units, CurCtrlUnits )
                
                FrameFlag=0;
                break;
            end % if CurCtrlPos
        end % Frmlp
        
        %%%%%%%%%%%%%%%%%%%
        % It is the not the first or a new frame
        if FrameNum > 0
            RmvFrmLoc=[];
            if FrameFlag,
                for inlp=1:length(Frame),
                    if CurCtrlPos(1)>=Frame{inlp}.Pos(1) & ...
                            CurCtrlPos(2)>=Frame{inlp}.Pos(2) & ...
                            sum(CurCtrlPos([1 3]))<=sum(Frame{inlp}.Pos([1 3])) & ...
                            sum(CurCtrlPos([2 4]))<=sum(Frame{inlp}.Pos([2 4])) & ...
                            strcmp( Frame{Frmlp}.Units, CurCtrlUnits )
                        
                        % New Frame Contains an old frame
                        RmvFrmLoc=[RmvFrmLoc inlp];
                    end
                end
                
                if ~isempty( RmvFrmLoc )
                    Frame(RmvFrmLoc) = [];
                end
                FrameNum=length(Frame)+1;
                Frame{FrameNum}.Pos = CurCtrlPos;
                Frame{FrameNum}.Units = CurCtrlUnits;
            end % if FrameFlag
            
        else
            Frame{1}.Pos = CurCtrlPos;
            Frame{1}.Units = CurCtrlUnits;
            FrameNum=1;
        end % if FrameNum
    end % for Clp
    
end % if ~isempty(UIC)


%%% Create images %%%

if FrameNum > 0
    CapturedImages = [];
    CapturedMaps = [];
    
    %Pop it to top of window stacking order
    figure( Fig ); 
    
    % Make sure the figure is on top before proceeding.
    % In R14, the above call doesn't guarantee that the figure will be on
    % top before the next block of code is executed.
    drawnow; drawnow;
    
    % Capture images for each uicontrol first
    prevWarnState=warning;
    warning('off');
    for lp=1:length(Frame)
        if feature('NewMovieFormat')
            CapturedImages{lp} = getframe(Fig,Frame{lp}.Pos(:)); 
        else
            [CapturedImages{lp}.cdata, CapturedImages{lp}.colormap]=getframe(Fig,Frame{lp}.Pos(:));
        end
    end
    warning(prevWarnState);
    
    %reinstate warning status
    
    % Draw each image to stand in for the uicontrols
    for lp=1:length(Frame)
        if ~isempty(CapturedImages{lp})
            if ~isempty( CapturedImages{lp}.colormap )
                CapturedImages{lp}.cdata = ind2rgb(CapturedImages{lp}.cdata, CapturedImages{lp}.colormap);    
                CapturedImages{lp}.colormap = [];
            end
            
            pj.UIData.AxisHandles(lp)=axes('Parent',Fig, ...
                'Units'         ,'pixels'        , ...
                'Position'      ,Frame{lp}.Pos(:), ...
                'Tag'           ,'PrintUI'         ...
                );                       
            %call low level command so NextPlot has no affect, fix Axes.
            ImgHandle=image('cdata',CapturedImages{lp}.cdata, 'Parent',pj.UIData.AxisHandles(lp));
            set(pj.UIData.AxisHandles(lp), ...
                'Units'          ,Frame{lp}.Units, ...
                'Visible'        ,'off'       , ...
                'ColorOrder'     ,[0 0 0]     , ...
                'XTick'          ,[]          , ...
                'XTickLabelMode' ,'manual'    , ...
                'YTick'          ,[]          , ...
                'YTickLabelMode' ,'manual'    , ...
                'YDir'           ,'reverse'   , ...
                'XLim'           ,[0.5 Frame{lp}.Pos(3)+0.5], ...
                'YLim'           ,[0.5 Frame{lp}.Pos(4)+0.5]  ...
                );
        else
            pj.UIData.AxisHandles(lp)=[-1];
            warning('Screen capture failed - UIcontrol will not appear in output.');
        end %if ~isempty(capturedimages)
    end % for lp
    
end % if FrameNum

set(Fig, 'Units', pj.UIData.OldFigUnits );
set(0,   'Units', pj.UIData.OldRootUnits);
if ~isempty(pj.UIData.UICHandles),
  % Make uicontrols invisible because Motif on Sol2 sometimes seg-v's
  % if the uicontrols are visible while resizing in normalized units.
  % note we don't store the old visible state since we searched for visible
  % uicontrols in the findobj above.
  set(pj.UIData.UICHandles,'visible','off');
end



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% RectAroundControl %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function rect = rectaroundcontrol( ch )
%RECTAROUNDCONTROL Get rectangle that tightly bounds UiControl
%   On some platforms the asked for position is not used because it
%   is the LAF on those platforms to have the height of some styles of
%   UiControls be dependent upon the fontsize of the label of the control.

% rect = get(ch,'position');
% For every iteration up the hierarchy we seem to be losing a pixel in X
% and Y. So contained components may not show the edges correctly. Need to
% revisit.
rect = getpixelposition(ch, true);

if ~strcmp('uicontrol', get(ch, 'Type'))
    % It may be a uicontainer for a javacomponent.
    return;
end

%A little fudgying is required since pop-up menus do not obey their
%position property -- they are Windows widgets we can't control completely.
if strcmp( 'popupmenu', get(ch,'style') ) & strncmp(computer,'PC',2)
    oldUnits = get(ch, 'Units');
    set(ch, 'Units', 'pixels');
    pix_ext = get(ch,'extent');
    set(ch, 'Units', oldUnits);

    rect(2) = rect(2) + rect(4) - pix_ext(4) - 4;
    rect(4) = pix_ext(4)+4;
end
