Code covered by the BSD License  

Highlights from
POINTEREDITOR

image thumbnail
from POINTEREDITOR by Jiro Doke
A GUI for creating custom pointers.

pointereditor(m)
function out = pointereditor(m)

%POINTEREDITOR  GUI for creating cursor (pointer) data.
%   POINTEREDITOR opens a GUI for creating custom PointerShapeCData.
%   PointerShapeCData must be a 16-by-16 matrix that defines the pointer
%   using 3 values (black, white, transparent). The editor allows you to
%   create the pointer by clicking on pixels (left click, right click,
%   shift+left click, respectively). You can also click and drag to color
%   continuous pixels. The bucket fill button allows you to fill in a
%   contiguous space with a single color. Closing the editor via the close
%   button cancels the changes.
%
%   M = POINTEREDITOR returns the CData matrix. To incorporate the Cdata in
%   your m-file, copy and paste the output of the matrix. See examples in
%   this code.
%
%   M = POINTEREDITOR(C) accepts a 16-by-16 CData matrix.
%
%   The mouse click interface is designed to be used in MS-Windows
%   environment. In other platforms, they correspond to 'Normal',
%   'Alternate', and 'Extend' SelectionType.
%
%   The GUI includes a few UI control buttons on the right.
%     Done!      - Exit editor and return CData.
%     ?          - Open help message box.
%     All Black  - Change all pixels to black.
%     All White  - Change all pixels to white.
%     All Transp - Change all pixels to transparent.
%     Bucket     - Fill contiguous pixels with single color.
%     Undo       - Undo last change.
%     Test       - Test the current pointer.
%
%   VERSIONS:
%   v1.0 - first version
%   v1.1 - Allow click and drag for continuous pixel selection (Feb 6, 2006)
%   v1.2 - Allow passing in of a CData matrix. Remove outputing of matrix
%          on screen, because one can get that from the actual matrix (Feb
%          7, 2006)
%   v1.2.1 - minor code change, from MLINT (Mar 2, 2006)
%   v1.3 - added bucket fill feature, UNDO feature, and cursor previews
%          with various backgrounds. (Mar 4, 2006)
%   v1.3.1 - modify help text. (Mar 12, 2006)
%

% Copyright 2006 The MathWorks, Inc.

% The pointer shape data must be a 16-by-16 element.
height =  16;
width  =  16;

% The colors of the pixels in the GUI
colors = {'Black', 'White', [.5 .5 .5]};

if nargin == 1 % Pointer CData is passed in
  if isnumeric(m) && ...
      isequal(size(m), [height, width]) && ...
      all(isnan(m(:)) + ismember(m(:), [1 2]))
    % Save original in case of CANCEL
    m_orig = m;
  else
    error('Input must be a 16-by-16 matrix of 1''s, 2''s, and NaN''s.');
  end
  
else
  m_orig = [];
  m      = repmat(NaN, height, width);
  
end

hFig = findobj('Type', 'Figure', 'Tag', 'PointerEditor');
if ishandle(hFig)
  close(hFig);
end

bgcolor1 = [.9 .9 .9];
bgcolor2 = [.7 .7 .7];

arrowPointer = [
     2     2   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
     2     1     2     2   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
   NaN     2     1     1     2     2   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
   NaN     2     1     1     1     1     2     2   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
   NaN   NaN     2     1     1     1     1     1     2     2   NaN   NaN   NaN   NaN   NaN   NaN
   NaN   NaN     2     1     1     1     1     1     1     1     2     2   NaN   NaN   NaN   NaN
   NaN   NaN   NaN     2     1     1     1     1     1     1     1     1     2   NaN   NaN   NaN
   NaN   NaN   NaN     2     1     1     1     1     1     2     2     2   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN     2     1     1     1     1     1     2   NaN   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN     2     1     1     2     1     1     1     2   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN   NaN     2     1     2     2     1     1     1     2   NaN   NaN   NaN
   NaN   NaN   NaN   NaN   NaN     2     1     2   NaN     2     1     1     1     2   NaN   NaN
   NaN   NaN   NaN   NaN   NaN   NaN     2   NaN   NaN   NaN     2     1     1     1     2   NaN
   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN     2     1     2   NaN   NaN
   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN     2   NaN   NaN   NaN
   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
 ];

fillPointer = [
   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN     2   NaN   NaN   NaN   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN   NaN   NaN   NaN     2     1     2   NaN   NaN   NaN   NaN   NaN   NaN
   NaN   NaN   NaN     2     2     2     2     1     2     1     2   NaN   NaN   NaN   NaN   NaN
   NaN   NaN     2     1     1     1     1     2     2     2     1     2   NaN   NaN   NaN   NaN
   NaN     2     1     1     2     1     2     2     2     2     2     1     2   NaN   NaN   NaN
     2     1     1     2     1     2     2     2     2     2     2     2     1     2   NaN   NaN
     2     1     2     1     1     1     1     1     1     1     1     1     1     1     2   NaN
     2     1     1     2     1     2     1     2     1     2     1     2     1     2     1     2
     2     1     1     2     2     1     2     1     2     1     2     1     2     1     2     1
     2     1     1     2   NaN     2     1     2     1     2     1     2     1     2     1     2
     2     1     1     2   NaN   NaN     2     1     2     1     2     1     2     1     2   NaN
     2     1     1     2   NaN   NaN   NaN     2     1     2     1     2     1     2   NaN   NaN
   NaN     2     1     2   NaN   NaN   NaN   NaN     2     1     2     1     2   NaN   NaN   NaN
   NaN     2     1     2   NaN   NaN   NaN   NaN   NaN     2     1     2   NaN   NaN   NaN   NaN
   NaN     2     1     2   NaN   NaN   NaN   NaN   NaN   NaN     2   NaN   NaN   NaN   NaN   NaN
   NaN   NaN     2   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
 ];

% create fill icon (from fill pointer)
fillIcon            = repmat(fillPointer, [1, 1, 3]);
blueRGB = [0 0 .5];
for id = 1:3
  tmp               = fillIcon(:,:,id);
  tmp(tmp == 1)     = blueRGB(id);
  tmp(tmp == 2)     = 1;
  tmp(isnan(tmp))   = bgcolor2(id);
  fillIcon(:,:,id)  = tmp;
end

hFig = figure(                                                                        ...
  'Numbertitle'                     , 'Off'                                         , ...
  'Name'                            , 'Pointer Editor'                              , ...
  'Units'                           , 'Pixels'                                      , ...
  'Position'                        , [200, 200, 20*width+70, 20*height]            , ...
  'DoubleBuffer'                    , 'On'                                          , ...
  'WindowStyle'                     , 'Normal'                                      , ...
  'MenuBar'                         , 'None'                                        , ...
  'Resize'                          , 'Off'                                         , ...
  'Color'                           , bgcolor1                                      , ...
  'Pointer'                         , 'custom'                                      , ...
  'PointerShapeCData'               , arrowPointer                                  , ...
  'PointerShapeHotSpot'             , [2 2]                                         , ...
  'Tag'                             , 'PointerEditor'                               , ...
  'WindowButtonUpFcn'               , @myWinBtnUpFcn                                , ...
  'defaultUIControlFontName'        , 'Arial'                                       , ...
  'defaultUIControlFontUnits'       , 'Pixels'                                      , ...
  'defaultUIControlFontSize'        , 10                                            , ...
  'defaultUIControlUnits'           , 'pixels'                                      , ...
  'defaultUIControlBackgroundColor' , bgcolor2);

% Create UI control buttons
controlX = 20*width+5;
maxHeight = 20*height;
uicontrol(                                                                            ...
  'Style'                           , 'PushButton'                                  , ...
  'Position'                        , [controlX, maxHeight-25, 60, 20]              , ...
  'String'                          , 'Done!'                                       , ...
  'FontWeight'                      , 'bold'                                        , ...
  'Callback'                        , @uicontrolPress                               , ...
  'BackgroundColor'                 , [0 .7 0]                                      , ...
  'ForegroundColor'                 , [.5 0 0]                                      , ...
  'ToolTipString'                   , 'Close editor and return CData'               , ...
  'Tag'                             , 'Done');
uicontrol(                                                                            ...
  'Style'                           , 'PushButton'                                  , ...
  'Position'                        , [controlX, maxHeight-50, 60, 20]              , ...
  'String'                          , '?'                                           , ...
  'Callback'                        , @uicontrolPress                               , ...
  'ToolTipString'                   , 'Help'                                        , ...
  'Tag'                             , 'Help');

uicontrol(                                                                            ...
  'Style'                           , 'Text'                                        , ...
  'Position'                        , [controlX, maxHeight-66, 13, 13]              , ...
  'BackgroundColor'                 , 'Black');
uicontrol(                                                                            ...
  'Style'                           , 'Text'                                        , ...
  'Position'                        , [controlX+15, maxHeight-66, 50, 13]           , ...
  'BackgroundColor'                 , bgcolor1                                      , ...
  'FontSize'                        , 9                                             , ...
  'HorizontalAlignment'             , 'Left'                                        , ...
  'ToolTipString'                   , 'Left-Click for BLACK pixels'                 , ...
  'String'                          , 'L-CLK');
uicontrol(                                                                            ...
  'Style'                           , 'Text'                                        , ...
  'Position'                        , [controlX, maxHeight-79, 13, 13]              , ...
  'BackgroundColor'                 , 'White');
uicontrol(                                                                            ...
  'Style'                           , 'Text'                                        , ...
  'Position'                        , [controlX+15, maxHeight-79, 50, 13]           , ...
  'BackgroundColor'                 , bgcolor1                                      , ...
  'FontSize'                        , 9                                             , ...
  'HorizontalAlignment'             , 'Left'                                        , ...
  'ToolTipString'                   , 'Right-Click for WHITE pixels'                , ...
  'String'                          , 'R-CLK');
uicontrol(                                                                            ...
  'Style'                           , 'Text'                                        , ...
  'Position'                        , [controlX, maxHeight-92, 13, 13]              , ...
  'BackgroundColor'                 , [.5 .5 .5]);
uicontrol(                                                                            ...
  'Style'                           , 'Text'                                        , ...
  'Position'                        , [controlX+15, maxHeight-92, 50, 13]           , ...
  'BackgroundColor'                 , bgcolor1                                      , ...
  'FontSize'                        , 9                                             , ...
  'HorizontalAlignment'             , 'Left'                                        , ...
  'ToolTipString'                   , 'Shift-Left-Click for TRANSPARENT pixels'     , ...
  'String'                          , 'SHFT-CLK');

uicontrol(                                                                            ...
  'Style'                           , 'PushButton'                                  , ...
  'Position'                        , [controlX, maxHeight-115, 60, 20]             , ...
  'String'                          , 'All Black'                                   , ...
  'Callback'                        , @uicontrolPress                               , ...
  'BackgroundColor'                 , 'Black'                                       , ...
  'ForegroundColor'                 , 'White'                                       , ...
  'ToolTipString'                   , 'Change all pixels to BLACK'                  , ...
  'Tag'                             , 'AllBlack');
uicontrol(                                                                            ...
  'Style'                           , 'PushButton'                                  , ...
  'Position'                        , [controlX, maxHeight-140, 60, 20]             , ...
  'String'                          , 'All White'                                   , ...
  'Callback'                        , @uicontrolPress                               , ...
  'BackgroundColor'                 , 'White'                                       , ...
  'ForegroundColor'                 , 'Black'                                       , ...
  'ToolTipString'                   , 'Change all pixels to WHITE'                  , ...
  'Tag'                             , 'AllWhite');
uicontrol(                                                                            ...
  'Style'                           , 'PushButton'                                  , ...
  'Position'                        , [controlX, maxHeight-165, 60, 20]             , ...
  'String'                          , 'All Transp'                                  , ...
  'Callback'                        , @uicontrolPress                               , ...
  'BackgroundColor'                 , [.5 .5 .5]                                    , ...
  'ForegroundColor'                 , 'Black'                                       , ...
  'ToolTipString'                   , 'Change all pixels to TRANSPARENT'            , ...
  'Tag'                             , 'AllTransp');

uicontrol(                                                                            ...
  'Style'                           , 'ToggleButton'                                , ...
  'Position'                        , [controlX, 130, 60, 20]                       , ...
  'CData'                           , fillIcon                                      , ...
  'Callback'                        , @uicontrolPress                               , ...
  'ToolTipString'                   , 'Fill Bucket'                                 , ...
  'Tag'                             , 'FillBucket');
uicontrol(                                                                            ...
  'Style'                           , 'PushButton'                                  , ...
  'Position'                        , [controlX, 105, 60, 20]                       , ...
  'String'                          , 'Undo'                                        , ...
  'Callback'                        , @uicontrolPress                               , ...
  'ToolTipString'                   , 'Undo last change'                            , ...
  'Tag'                             , 'Undo');
uicontrol(                                                                            ...
  'Style'                           , 'ToggleButton'                                , ...
  'Position'                        , [controlX, 80, 60, 20]                        , ...
  'String'                          , 'Test'                                        , ...
  'Callback'                        , @uicontrolPress                               , ...
  'ToolTipString'                   , 'Test pointer'                                , ...
  'Tag'                             , 'PointerTest');

uicontrol(                                                                            ...
  'Style'                           , 'Frame'                                       , ...
  'Position'                        , [controlX, 5, 65, 70]                         , ...
  'BackgroundColor'                 , bgcolor1);
uicontrol(                                                                            ...
  'Style'                           , 'Text'                                        , ...
  'Position'                        , [controlX+5, 66, 55, 13]                      , ...
  'String'                          , 'Preview'                                     , ...
  'BackgroundColor'                 , bgcolor1);
uicontrol(                                                                            ...
  'Style'                           , 'Pushbutton'                                  , ...
  'Position'                        , [controlX+5, 40, 25 ,25]                      , ...
  'BackgroundColor'                 , 'Black'                                       , ...
  'Enable'                          , 'Inactive'                                    , ...
  'ToolTipString'                   , 'Pointer sample in various backgrounds'       , ...
  'Tag'                             , 'BlackTest');
uicontrol(                                                                            ...
  'Style'                           , 'Pushbutton'                                  , ...
  'Position'                        , [controlX+35, 40, 25 ,25]                     , ...
  'BackgroundColor'                 , 'White'                                       , ...
  'Enable'                          , 'Inactive'                                    , ...
  'ToolTipString'                   , 'Pointer sample in various backgrounds'       , ...
  'Tag'                             , 'WhiteTest');
uicontrol(                                                                            ...
  'Style'                           , 'Pushbutton'                                  , ...
  'Position'                        , [controlX+5, 10, 25 ,25]                      , ...
  'BackgroundColor'                 , [.3 .3 .3]                                    , ...
  'Enable'                          , 'Inactive'                                    , ...
  'ToolTipString'                   , 'Pointer sample in various backgrounds'       , ...
  'Tag'                             , 'DarkGrayTest');
uicontrol(                                                                            ...
  'Style'                           , 'Pushbutton'                                  , ...
  'Position'                        , [controlX+35, 10, 25 ,25]                     , ...
  'BackgroundColor'                 , [.7 .7 .7]                                    , ...
  'Enable'                          , 'Inactive'                                    , ...
  'ToolTipString'                   , 'Pointer sample in various backgrounds'       , ...
  'Tag'                             , 'LightGrayTest');

axes(                                                                                 ...
  'Units'                           , 'Pixels'                                      , ...
  'Position'                        , [0, 0, 20*width, 20*height]                   , ...
  'XLim'                            , [0, max([320, 20*width])]                     , ...
  'XTick'                           , []                                            , ...
  'YLim'                            , [0, 20*height]                                , ...
  'YTick'                           , []                                            , ...
  'ButtonDownFcn'                   , @myWinBtnDownFcn);

% Create rectangles representing pixels
hax = repmat(NaN, height, width);
mtemp = m;  % create temp matrix for color selection
mtemp(isnan(mtemp)) = 3;
for i = 1:height
  for j = 1:width
    hax(i, j) = rectangle(                                                            ...
      'Position'                    , [20*(j-1), 20*height-20*i, 20, 20]            , ...
      'EdgeColor'                   , 'Blue'                                        , ...
      'FaceColor'                   , colors{mtemp(i, j)}                           , ...
      'HitTest'                     , 'off');
  end
end

handles                           = guihandles(hFig);
handles.bgcolor1                  = bgcolor1;
handles.bgcolor2                  = bgcolor2;
handles.colors                    = {[0, 0, 0], [1, 1, 1], [.5, .5, .5]};
handles.hax                       = hax;
handles.mat                       = mtemp;
handles.mat_bk                    = mtemp;
handles.height                    = height;
handles.width                     = width;
handles.fillMode                  = false;
handles.arrowPointer              = arrowPointer;
handles.fillPointer               = fillPointer;
handles.samplePointer             = [];
handles.curPointer                = 'arrowPointer';
handles.curWindowButtonMotionFcn  = '';

guidata(hFig, handles);

updateTestBlocks(handles);

% Wait until the editor is closed
uiwait(hFig);

if isappdata(0, 'TEMP_ptr_matrix')
  % Retrieve pointer shape data (created by myCloseFcn)
  mat = getappdata(0, 'TEMP_ptr_matrix');
  
  % Remove temporary shape data
  rmappdata(0, 'TEMP_ptr_matrix');
  
  out = mat;
  
else
  fprintf('Canceled...\n');
  
  out = m_orig;
  
end


%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
% myWinBtnDownFcn - Set ButtonDownFcn
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function myWinBtnDownFcn(obj, edata) %#ok

handles = guidata(obj);

% If it's in pointer test mode, ignore clicking.
if get(handles.PointerTest, 'Value')
  return;
end

% Update previous state (for Undo)
handles.mat_bk = handles.mat;
guidata(obj, handles);

if handles.fillMode % bucket mode
  handles = fillColorFcn(handles);
  guidata(obj, handles);
else
  set(handles.PointerEditor, 'WindowButtonMotionFcn', @myWinBtnMotionFcn);
  myWinBtnMotionFcn(handles.PointerEditor, []);
end


%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
% fillColorFcn - Action for bucket filling
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function handles = fillColorFcn(handles)

pt = get(handles.PointerEditor, 'CurrentPoint');
st = get(handles.PointerEditor, 'SelectionType');

% Determine which pixel the pointer is in
row = handles.height - floor(pt(2)/20);
col = ceil(pt(1)/20);

curColor = handles.mat(row, col);
switch lower(st)
  case 'normal'
    newColor = 1;
  case 'extend'
    newColor = 3;
  case 'alt'
    newColor = 2;
  otherwise
    return;
end

% if the current pixel color is the same as the new color, don't do
% anything
if curColor ~= newColor
  % recursively fill pixels
  handles.mat = ...
    recursiveColorCheck(handles.mat, row, col, curColor, newColor, 0);
end

tmp = handles.colors(handles.mat);
set(handles.hax, {'FaceColor'}, tmp(:));


%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
% recursiveColorCheck - Recursive pixel checking
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function mat = recursiveColorCheck(mat, row, col, curColor, newColor, idx)
% mat - pixel color matrix
% row - current row
% col - current col
% curColor - current color of the current pixel
% newColor - new color of the current pixel
% idx - index indicating where the recursion came from.
%       0 - initial recursion
%       1 - from below
%       2 - from left
%       3 - from above
%       4 - from right

% if the current pixel is current color, then change to new color
if mat(row, col) == curColor
  mat(row, col) = newColor;
end

% check the pixel above. if it is the current color, then call this
% function recursively.
if idx ~= 3 && row > 1 && mat(row-1, col) == curColor
  mat = recursiveColorCheck(mat, row-1, col, curColor, newColor, 1);
end

% check the pixel below
if idx ~= 1 && row < 16 && mat(row+1, col) == curColor
  mat = recursiveColorCheck(mat, row+1, col, curColor, newColor, 3);
end

% check the left pixel
if idx ~= 2 && col > 1 && mat(row, col-1) == curColor
  mat = recursiveColorCheck(mat, row, col-1, curColor, newColor, 4);
end

% check the right pixel
if idx ~= 4 && col < 16 && mat(row, col+1) == curColor
  mat = recursiveColorCheck(mat, row, col+1, curColor, newColor, 2);
end


%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
% myWinBtnMotionFcn - Color pixels accordingly
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function myWinBtnMotionFcn(obj, edata) %#ok

handles = guidata(obj);

pt = get(handles.PointerEditor, 'CurrentPoint');
st = get(handles.PointerEditor, 'SelectionType');

% Determine which pixel the pointer is in
row = handles.height - floor(pt(2)/20);
col = ceil(pt(1)/20);

% Set color, if pointer is within one of the pixels
if all([([row col] > 0), ([row col] <= [handles.height handles.width])])
  switch lower(st)
    
    case 'normal'   % black
      handles.mat(row, col) = 1;
      
    case 'extend'   % transparent
      handles.mat(row, col) = 3;
      
    case 'alt'      % white
      handles.mat(row, col) = 2;
      
    otherwise % Ignore double clicks
      return;
  end
  
  % change the color of the pixel
  set(handles.hax(row, col), ...
    'FaceColor', handles.colors{handles.mat(row, col)});
  
  guidata(obj, handles);
end


%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
% myWinBtnUpFcn - Remove WindowButtonMotionFcn
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function myWinBtnUpFcn(obj, edata) %#ok

handles = guidata(obj);
set(obj, 'WindowButtonMotionFcn', handles.curWindowButtonMotionFcn);
updateTestBlocks(handles);


%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
% uicontrolPress - Process UI control button presses
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function uicontrolPress(obj, edata) %#ok

handles = guidata(obj);

switch get(obj, 'Tag')
  % Change all pixels to black
  case 'AllBlack'
    handles.mat_bk = handles.mat;
    handles.mat(:) = 1;
    set(handles.hax, 'FaceColor', handles.colors{1});
    updateTestBlocks(handles);
    
  % Change all pixels to white
  case 'AllWhite'
    handles.mat_bk = handles.mat;
    handles.mat(:) = 2;
    set(handles.hax, 'FaceColor', handles.colors{2});
    updateTestBlocks(handles);
    
  % Change all pixels to transparent
  case 'AllTransp'
    handles.mat_bk = handles.mat;
    handles.mat(:) = 3;
    set(handles.hax, 'FaceColor', handles.colors{3});
    updateTestBlocks(handles);
    
  % Fill bucket
  case 'FillBucket'
    switch get(obj, 'Value')
      case 0  % end fill mode
        handles.fillMode                 = false;
        handles.curWindowButtonMotionFcn = '';
        set(handles.PointerEditor, ...
          'PointerShapeCData'     , handles.arrowPointer, ...
          'PointerShapeHotSpot'   , [2 2], ...
          'WindowButtonMotionFcn' , '');
        set(handles.PointerTest, 'Enable' , 'on');
      case 1  % begin fill mode
        handles.fillMode = true;
        handles.curWindowButtonMotionFcn = ...
          {@setPointer, handles, 'fillPointer', [15 3]};
        set(handles.PointerEditor, ...
          'WindowButtonMotionFcn' , handles.curWindowButtonMotionFcn);
        set(handles.PointerTest, 'Enable', 'off');
    end
    
  % Undo
  case 'Undo'
    % swap current and previous states
    [handles.mat, handles.mat_bk] = deal(handles.mat_bk, handles.mat);

    tmp = handles.colors(handles.mat);
    set(handles.hax, {'FaceColor'}, tmp(:));
    updateTestBlocks(handles);
    
  % Test the pointer
  case 'PointerTest'
    if get(obj, 'Value')
      if isequal(size(handles.hax), [16 16])
        mat = handles.mat;
        mat(mat == 3) = NaN;
        handles.samplePointer = mat;
        handles.curWindowButtonMotionFcn = ...
          {@setPointer, handles, 'samplePointer', [1 1]};
        set(handles.PointerEditor, ...
          'WindowButtonMotionFcn' , handles.curWindowButtonMotionFcn);
        set([handles.Done, ...
            handles.Help, ...
            handles.AllBlack, ...
            handles.AllWhite, ...
            handles.AllTransp, ...
            handles.FillBucket, ...
            handles.Undo], ...
          'Enable', 'off');
      else
        set(obj, 'Value', false);
      end
    else
      set([handles.Done, ...
          handles.Help, ...
          handles.AllBlack, ...
          handles.AllWhite, ...
          handles.AllTransp, ...
          handles.FillBucket, ...
          handles.Undo], ...
        'Enable', 'on');
      handles.curWindowButtonMotionFcn = '';
      set(handles.PointerEditor, ...
        'PointerShapeCData'     , handles.arrowPointer, ...
        'PointerShapeHotSpot'   , [2 2], ...
        'WindowButtonMotionFcn' , '');
    end
    
  % Close editor
  case 'Done'
    mat = handles.mat;
    mat(mat == 3) = NaN;
    
    % Save shape data to a temporary variable
    setappdata(0, 'TEMP_ptr_matrix', mat);
    closereq;    
    return;
  
  % Help window
  case 'Help'
    uiwait(msgbox({                                ...
        'In Windows:'                             , ...
        'Left-click for a black pixel'            , ...
        'Right-click for a white pixel'           , ...
        'Shift+Left-click for a transparent pixel', ...
        ''                                        , ...
        'Click and drag for continuous pixels.'}  , ...
      'Info', ...
      'help', 'modal'));
end

guidata(obj, handles);

% Remove focus
set(obj, 'Enable', 'Inactive');
set(obj, 'Enable', 'On');


%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
% setPointer - Sets pointer when hovering over axes
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function setPointer(obj, edata, handles, ptrType, hotSpot) %#ok

pt = get(handles.PointerEditor, 'CurrentPoint');
if pt(1) < handles.width*20 && pt(2) < handles.height*20
  set(handles.PointerEditor, ...
    'PointerShapeCData'   , handles.(ptrType), ...
    'PointerShapeHotSpot' , hotSpot);
else
  set(handles.PointerEditor, ...
    'PointerShapeCData'   , handles.arrowPointer, ...
    'PointerShapeHotSpot' , [2 2]);
end


%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
% updateTestBlocks - Updates the pointer sample blocks
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function updateTestBlocks(handles)

testBlocks = {'BlackTest', 'WhiteTest', 'DarkGrayTest', 'LightGrayTest'};
testBlockC = [0, 1, .3, .7];
cdat = 3 * ones(25, 25);
for id = 1:4
  cdat(6:21,6:21)   = handles.mat;
  cdata             = repmat(cdat, [1 1 3]);
  cdata(cdata == 1) = 0;
  cdata(cdata == 2) = 1;
  cdata(cdata == 3) = testBlockC(id);
  set(handles.(testBlocks{id}), 'CData', cdata);
end

Contact us at files@mathworks.com