function hout = impixelregion(h)
%IMPIXELREGION Pixel region tool.
%   IMPIXELREGION creates a Pixel Region tool associated with the
%   image displayed in the current figure, called the target image.
%
%   The Pixel Region tool opens a separate figure window containing
%   an extreme close-up view of a small region of pixels in the 
%   target image. The tool superimposes the numeric value of the pixel
%   over each pixel. To define the region being examined, the tool overlays
%   a rectangle on the target image, called the pixel region rectangle. 
%   To view pixels in a different region, click and drag the rectangle
%   over the target image. 
%
%   IMPIXELREGION(H) creates a Pixel Region tool associated with the 
%   image specified by the handle H. H may be an image, axes, uipanel, 
%   or figure handle.  If H is an axes or figure handle, IMPIXELREGION
%   uses the first image found in the axes or figure.
%
%   HFIGURE = IMPIXELREGION(...) returns the handle of the figure
%   containing the Pixel Region tool.
%
%   Note
%   ----
%   To create a Pixel Region tool that can be embedded in an existing 
%   figure window or uipanel, use IMPIXELREGIONPANEL.
%
%   Example
%   -------
%
%      imshow peppers.png
%      impixelregion
%
%   See also IMPIXELINFO, IMPIXELREGIONPANEL, IMTOOL.

%   Copyright 1993-2004 The MathWorks, Inc.
%   $Revision: 1.1.8.2 $  $Date: 2004/12/18 07:36:08 $

if nargin < 1
  hFig = get(0,'CurrentFigure');
  hAx  = get(hFig,'CurrentAxes');
  hIm = findobj(hAx, 'Type', 'image');
else
  iptcheckhandle(h, {'image', 'axes', 'figure','uipanel'}, mfilename, 'H', 1);
  hIm = imhandles(h);
  if numel(hIm) > 1
    hIm = hIm(1);
  end
  hFig = ancestor(hIm,'figure');
end

if isempty(hIm)
  eid = sprintf('Images:%s:noImage',mfilename);
  msg = sprintf('%s expects a current figure containing an image.', ...
                upper(mfilename));
  error(eid,'%s',msg);
end
  
hPixelRegionFig = figure('Menubar',          'none',...
                         'IntegerHandle',    'off', ...
                         'NumberTitle',      'off', ...
                         'Name',             createFigureName('Pixel Region', ...
                                                  hFig), ...
                         'Colormap',         get(hFig, 'Colormap'), ...
                         'InvertHardCopy',   'off', ...
                         'HandleVisibility', 'callback', ...
                         'Visible',          'off');

isIndexedUint16Image = strcmpi(get(hIm,'CDataMapping'),'direct') && ...
    (size(get(ancestor(hIm, 'figure'), 'Colormap'), 1) > 256);

% This is to workaround the problem of indexed image showing up black on
% windows.  G208494
if isIndexedUint16Image && ispc
  set(hPixelRegionFig, 'Renderer', 'Zbuffer');
end

% Make the pixel region figure smaller than the default.
set(hPixelRegionFig, 'Position', ...
                  get(hPixelRegionFig, 'Position') .* [1 1 .6 .6]);

sp_h = impixelregionpanel(hPixelRegionFig, hIm);
scrollpanelAPI = iptgetapi(sp_h);

hPixelRegionIm = findobj(sp_h, 'type', 'image');
set(hPixelRegionIm,'HitTest','on',...
                   'ButtonDownFcn', @impan);
set(findobj(sp_h, 'type', 'line'), 'ButtonDownFcn', ...
                  @(varargin) impan(hPixelRegionIm));

hPixelInfoPanel = impixelinfo(hPixelRegionFig, hPixelRegionIm);
hPixelRegionFigPos = get(hPixelRegionFig, 'Position');
hPixelInfoPanelOrigPos = get(hPixelInfoPanel,'Position');
setChildColorToMatchParent(hPixelInfoPanel, hPixelRegionFig);

toolbarOld = findall(hPixelRegionFig, 'type', 'uitoolbar');
delete(toolbarOld);
createToolbar;
createMenubar;

resizePixRegion(hPixelRegionFig);
  
% Position the pixel region figure to the upper right and make visible.
iptwindowalign(hFig, 'right', hPixelRegionFig, 'left');
iptwindowalign(hFig, 'top', hPixelRegionFig, 'top');
set(hPixelRegionFig, ...
    'Visible', 'on',...
    'ResizeFcn', @resizePixRegion);

setptr(hPixelRegionFig, 'hand');

reactToImageChangesInFig(hIm, @targetImageDeleted);

if nargout > 0
  hout = hPixelRegionFig;
end

  % mouse_is_off_image is a boolean used to indicate when the mouse
  % pointer has made a transition onto or off of the image.  It is
  % used by nested function cursorCheck().
  mouse_is_off_image = false;
  
  % saved_mouse_pointer is used to save the figure's mouse pointer before
  % changing it to arrow when the mouse moves off the image.  It is
  % used by nested function cursorCheck().
  saved_mouse_pointer = [];
  
  cursor_check_callback_id = iptaddcallback(hPixelRegionFig,...
                                           'WindowButtonMotionFcn', ...
                                           @cursorCheck);  
  set(hPixelRegionFig, 'DeleteFcn', ...
            @(src, varargin) iptremovecallback(hPixelRegionFig, ...
                                              'WindowButtonMotionFcn', ...
                                              cursor_check_callback_id));

   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   function cursorCheck(varargin)
      
     cp = get(hPixelRegionFig, 'CurrentPoint');
     cpx = cp(1,1,1);
     cpy = cp(1,2,1);
 
     over_panel = isOver(cpx,cpy,getpixelposition(hPixelInfoPanel));
     over_scrollbars = isOverScrollbars(cpx,cpy,sp_h);

     off_image = over_panel || over_scrollbars;
     
     [mouse_is_off_image,saved_mouse_pointer] = updateCursor(...
         hPixelRegionFig,...
         off_image, mouse_is_off_image, saved_mouse_pointer, 'arrow');
          
   end

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function targetImageDeleted(varargin)
    if ishandle(hPixelRegionFig)
      delete(hPixelRegionFig);
    end
  end
  %---------------------------------------------------------------------

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function resizePixRegion(src, varargin)
    figPos = get(src, 'Position');
    set(hPixelInfoPanel, 'position', [0 0 figPos(3) hPixelInfoPanelOrigPos(4)]);
    panelPos = get(hPixelInfoPanel, 'Position');

    % Set position of scrollpanel in normalized units based on Figure and
    % hPixInfoPanel position.
    set(sp_h, 'Position', ...
              [0 (panelPos(4)/figPos(4)) 1 ...
               (figPos(4) - panelPos(4)) / figPos(4)]);
  end
  %---------------------------------------------------------------------

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function createToolbar

    toolbar = uitoolbar(hPixelRegionFig);
    [iconRoot, iconRootMATLAB] = ipticondir;

    zoomInIcon = makeToolbarIconFromPNG(fullfile(iconRoot,...
                                                 'pixelreg_zoom_in.png'));
    zoomInTool = createToolbarPushItem(toolbar,zoomInIcon,...
                                       {@zoomIn},...
                                       'Zoom in');
  
    zoomOutIcon = makeToolbarIconFromPNG(fullfile(iconRoot,...
                                                  'pixelreg_zoom_out.png'));
    zoomOutTool = createToolbarPushItem(toolbar,zoomOutIcon,...
                                       {@zoomOut},...
                                       'Zoom out');
    
    if ~isdeployed
      helpIcon = makeToolbarIconFromGIF(fullfile(iconRootMATLAB, 'helpicon.gif'));
      helpTool = createToolbarPushItem(toolbar, helpIcon, ...
                                       @(varargin) ipthelp('imtool_pixelregion_help', 'Pixel Region'), ...
                                       'Help');
    end

  end
  %-----------------------------------------------------------------------------

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function zoomIn(varargin)
    
    scrollpanelAPI.setMagnification(1.25 * scrollpanelAPI.getMagnification());
    
  end
  %-----------------------------------------------------------------------------
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function zoomOut(varargin)

    scrollpanelAPI.setMagnification(scrollpanelAPI.getMagnification() / 1.25);
    
  end  
  %-----------------------------------------------------------------------------

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function item = createMenubar
    filemenu = uimenu(hPixelRegionFig, 'Label', '&File', 'Tag', 'file menu');

    printItem = uimenu(filemenu, 'Label', '&Print to Figure', ...
                       'Tag', 'print menu', ...
                       'Callback', @(varargin) printImageToFigure(sp_h));

    closeItem = uimenu(filemenu, 'Label', '&Close', ...
                       'Callback', @(varargin) close(hPixelRegionFig), ...
                       'Accelerator', 'W');
    
    editmenu = uimenu(hPixelRegionFig, 'Label', '&Edit', 'Tag', 'edit menu', ...
                      'Callback', @setupEditMenu);
    
    copyItem = uimenu(editmenu, 'Label', '&Copy Position', ...
                      'Callback', @(varargin) clipboard('copy', scrollpanelAPI.getVisibleImageRect()), ...
                      'Tag', 'copyItem');
    
    showPixValuesItem = uimenu(editmenu, 'Label', '&Superimpose Pixel Values', ...
                              'Callback', @showPixelValuesCallback, ...
                              'Checked', 'on');

    if isJavaFigure    
      windowmenu = uimenu(hPixelRegionFig, 'Label', '&Window', ...
                          'Callback', winmenu('callback'));
    end

    if ~isdeployed    
      helpmenu = uimenu(hPixelRegionFig, 'Label', '&Help', 'Tag', 'help menu');
      uimenu(helpmenu, 'Label', 'Pixel Region Help', ...
             'Callback', @(varargin) ipthelp('imageframe', 'Pixel Region'));
    
      iptstandardhelp(helpmenu);
    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function setupEditMenu(varargin)
    
      api = getappdata(sp_h, 'impixelregionpanelAPI');
      if api.isValueDisplayPossible()
        set(showPixValuesItem, 'Enable', 'on');
      else
        set(showPixValuesItem, 'Enable', 'off');
      end
      
    end
    %---------------------------------------------------------------------------
  
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function showPixelValuesCallback(varargin)

      api = getappdata(sp_h, 'impixelregionpanelAPI');
      if strcmp(get(gcbo, 'Checked'), 'on')
        api.setShowPixelValues(false);
        set(gcbo, 'Checked', 'off');
      else
        api.setShowPixelValues(true);
        set(gcbo, 'Checked', 'on');
      end

    end
  end
  %-----------------------------------------------------------------------------

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function printToFigure

    mag      = scrollpanelAPI.getMagnification();
    vis_rect = scrollpanelAPI.getVisibleImageRect();
    
    fig_width  = mag * vis_rect(3);
    fig_height = mag * vis_rect(4);

    fp = figparams;
    
    fig_left   = round((fp.ScreenWidth - fig_width) / 2);
    fig_bottom = round((fp.ScreenHeight - fig_height) / 2);
    
    fig_position = [fig_left fig_bottom fig_width fig_height];
    
    h_figure = figure('Visible', 'off', ...
                      'Units', 'pixels', ...
                      'Position', fig_position, ...
                      'Colormap', get(hPixelRegionFig, 'Colormap'), ...
                      'PaperPositionMode', 'auto', ...
                      'InvertHardcopy', 'off');

    h_axes = copyobj(findobj(sp_h, 'type', 'axes'), h_figure);
    set(h_axes, 'Units', 'normalized', ...
                'Position', [0 0 1 1], ...
                'XLim', vis_rect(1) + [0 vis_rect(3)], ...
                'YLim', vis_rect(2) + [0 vis_rect(4)]);

    set(findobj(h_axes, 'type', 'image'), 'ButtonDownFcn', '');

    set(h_figure, 'Visible', 'on');
  
  end
  %-----------------------------------------------------------------------------
  
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function item = createToolbarPushItem(toolbar,icon,callback,tooltip)

  item = uipushtool(toolbar,...
                    'Cdata',icon,...
                    'TooltipString',tooltip,...
                    'Tag',lower(tooltip),...
                    'ClickedCallback',callback);
  
end
%-------------------------------------------------------------------------------

