Code covered by the BSD License  

Highlights from
popupPanel Displays a popup panel with specified help topic, HTML or webpage

image thumbnail
from popupPanel Displays a popup panel with specified help topic, HTML or webpage by Yair Altman
popupPanel Displays a popup panel with specified help topic, HTML or webpage

popupPanel(contents, position, highlightedWords)
function hPopupPanel = popupPanel(contents, position, highlightedWords)
% popupPanel Displays a popup panel with specified help topic, HTML or webpage
%
% Syntax:
%    hPopupPanel = popupPanel(contents, position, highlightedWords)
%
% Description:
%    popupPanel(CONTENTS) displays Matlab's help popup (available on Matlab
%    releases R2007b onward) with the specified CONTENTS, which is one of:
%      - Help topic string (e.g. 'surf' or 'myFunction')
%      - HTML text (e.g. '<b>bold</b> <i>italic</i> text')
%      - Webpage URL (e.g. 'UndocumentedMatlab.com')
%
%    popupPanel(CONTENTS,POSITION) indicates the panel's position and
%    size in screen-relative regular Matlab format: [x,y,width,height].
%    If POSITION is empty or unspecified, then [x,y,500,300] is assumed,
%    where (x,y) is the current pointer's location.
%
%    popupPanel(CONTENTS,POSITION,HIGHLIGHTEDWORDS) specifies a string term
%    or cell-array of string terms that should be highlighted in the
%    presented panel's CONTENTS. This is not supported in R2013a and later.
%
%    hPopupPanel = popupPanel(...) returns the Java handle reference of the
%    created panel, allowing access to many useful properties and callbacks.
%    Type "get(hPopupPanel)", "methodsview(hPopupPanel)" for details.
%
% Examples:
%    popupPanel('surf');          % display the specified documentation page
%    popupPanel('myFunction');    % display a user-created help topic
%    popupPanel('myFunction.m');  % display a user-created help topic
%    popupPanel('<b>bold</b> <i>italic</i> text');  % display HTML text
%    popupPanel('C:\myLocalTextPage.txt');  % display a local file
%    popupPanel('myLocalHtmlPage.html');    % display a local webpage
%    popupPanel('UndocumentedMatlab.com');  % display an online webpage
%    popupPanel('surf',[200,300,400,500]);  % display 400x500 popup at [200,300]
%    popupPanel('surf',[],'surf');  % display popup, highlight 'surf' terms
%    popupPanel('surf',[],{'surf','surfc'});  % highlight several terms
%
% Warning:
%    This code heavily relies on undocumented and unsupported Matlab
%    functionality. It works on Matlab 7.5+ (R2007b+), but use at your own risk!
%
% Bugs and suggestions:
%    Please send to Yair Altman (altmany at gmail dot com)
%
% Change log:
%    2013-06-28: Several fixes for modern Matlab releases
%    2009-12-01: Fixed compatibility problem with R2009 highlightedWords (browser = HTMLRenderer)
%    2009-11-30: First version posted on <a href="http://www.mathworks.com/matlabcentral/fileexchange/loadAuthor.do?objectType=author&mfx=1&objectId=1096533#">MathWorks File Exchange</a>
%
% Notes:
%    <a href="http://undocumentedmatlab.com/blog/customizing-help-popup-contents">Technical details on the UndocumentedMatlab.com website</a>

% Technical details: http://undocumentedmatlab.com/blog/customizing-help-popup-contents

% Programmed by Yair M. Altman: altmany(at)gmail.com
% $Revision: 1.1 $  $Date: 2013/06/28 14:27:45 $

  try
      % Sanity checks before starting...
      error(nargchk(1,3,nargin,'struct'));

      % Require Java engine to run
      if ~usejava('jvm')
          error([mfilename ' requires Java to run.']);
      end

      if ~ischar(contents)
          error('YMA:popupPanel:badContents','CONTENTS must be a string');
      end

      % Default position = 500x300 at current pointer location
      oldunits = get(0,'Units');
      set(0,'Units','pixels');
      screenSize = get(0,'ScreenSize');
      set(0,'Units',oldunits);
      if nargin<2 || isempty(position)
          oldunits = get(0,'Units');
          set(0,'Units','pixels');
          curPosition = get(0,'PointerLocation');
          set(0,'Units',oldunits);
          position = [curPosition 500,300];
      elseif ~isnumeric(position) || length(position)~=4
          error('YMA:popupPanel:badPosition','POSITION must be a 4-element numeric array: [x,y,width,height]');
      elseif all(position<=1)
          % normalized units - convert to pixels
          position = position .* screenSize([3,4,3,4]);
      end
      % Convert to Java X,Y position
      posX = position(1) - 1;                            % Java X starts from screen left = 0
      posY = screenSize(4) - position(4) - position(2);  % Java Y starts from screen top = 0

      % Default highlighted words = none
      if nargin<3 || isempty(highlightedWords)
          highlightedWords = {};
      elseif ischar(highlightedWords)  % single string - convert to cell array
          highlightedWords = {highlightedWords};
      end

      % Display the popup with default contents
      jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
      jTextArea = jDesktop.getMainFrame.getFocusOwner;
      jClassName = 'com.mathworks.mlwidgets.help.HelpPopup';
      jPosition = java.awt.Rectangle(posX,posY,position(3),position(4));
      helpTopic = '';
      if ~isempty(helpfunc(contents))
          helpTopic = contents;
      end
      try
          javaMethodEDT('showHelp',jClassName,jTextArea,[],jPosition,helpTopic);
      catch
          % probably Matlab R2007b
          jniSig = 'showHelp(Ljavax.swing.JComponent;Lcom.mathworks.mwswing.binding.KeyStrokeList;Ljava.awt.Rectangle;Ljava.lang.String;)';
          awtinvoke(jClassName,jniSig,jTextArea,[],jPosition,helpTopic);
      end

      % Find the Help popup window
      jPopup = getPopupHandle;

      % If the popup was already displayed, its position & size are not modified so manually set them
       jPopup.setSize(jPosition.getSize);
       jPopup.setLocation(jPosition.getLocation);

      % Update the contents with the user-specified contents
      if ~isempty(jPopup)

          % Add a promotional link at the bottom (status bar)
          promoLink(jPopup);

          % Get the handle of the internal browser container
          browserPanel = jPopup.getContentPane.getComponent(1);
          browser = browserPanel.getComponent(0);
          oldBrowser = true;
          if isa(browser,'com.mathworks.mwswing.MJToolBar')  % R2013a's new JXBrowser
              browser = browserPanel.getComponent(browserPanel.getComponentCount-1).getComponent(0);
              oldBrowser = false;
          end

          % If there is valid help text, then display it
          url = '';
          if ~isempty(helpTopic)
              %Highlight the displayed text
              try
                  pause(0.1); drawnow;
                  if oldBrowser
                      try
                          htmlRenderer = browser.getHTMLRenderer;
                      catch
                          htmlRenderer = browser;
                      end
                      contents = char(htmlRenderer.getHtmlText);
                      url      = char(htmlRenderer.getCurrentLocation);
                  else  % R2013a's new JXBrowser
                      contents = char(browser.getContent);
                      url      = char(browser.getLocationURL);
                  end
                  baseUrl = fileparts(url);

                  % Relative links in Matlab's help don't work (e.g. for 'surf', 'mesh')
                  % so we must convert relative links to absolute links
                  %contents = regexprep(contents,'file:../../techdoc/','file://'); %([^/])',[baseUrl '/$1']);
                  contents = regexprep(contents,'file:../../techdoc',fileparts(baseUrl));
              catch
                  a=1;  %#ok never mind... - debug point
              end
          elseif (~isempty(which(contents)) || ~isempty(dir(contents))) && isempty(strfind(lower(contents),'.htm'))
              % Local file found - display within <PRE>...</PRE>
              url = contents;
              htmlStr = ['<html><h2>Loading ' url ' - please wait...'];
              try
                  browser.setHtmlText(htmlStr);
              catch
                  browser.setContent(htmlStr);
              end
              contents = evalc(['type(''' url ''')']); 
              contents = ['<html><pre>' contents '</pre></html>'];
          elseif isempty(strfind(contents,' '))
              % No spaces in the contents so treat the contents as a webpage URL
              %browser.setCurrentLocation(contents);  % asynchronous - not good...
              %text = browser.getHTMLRenderer.getHtmlText;
              try
                  url = contents;
                  %domain = regexprep(url,'[\\/].*','');
                  if isempty(strfind(url,'://'))
                      if ~isempty(dir(contents))
                          url = ['file:///' url];
                      else
                          url = ['http://' url];
                      end
                  end
                  htmlStr = ['<html><h2>Loading ' url ' - please wait...'];
                  try
                      browser.setHtmlText(htmlStr);
                  catch
                      browser.setContent(htmlStr);
                  end
                  contents = urlread(url);
              catch
                  a=1; %#ok never mind... - debug point
              end
          else
              % Otherwise, treat as a displayable HTML text
              % ensure we have both <HTML> and <BODY>, otherwise some text may disappear
              contents = ['<html><body>' contents];
          end

          % Correct the HTML <base> location so that images appear correctly
          newBaseStr = ['<BASE href=''' url '''>' 10];
          %contents = regexprep(contents, '<BASE href=''''>',newBaseStr,'ignorecase');  % no good - rewritten by setHtmlText() !!!
          contents = regexprep(contents, '<head>',['<head>' newBaseStr],'ignorecase');

          % Update the popup-panel's contents
          try
              browser.setHtmlTextAndHighlightKeywords(contents,highlightedWords);
          catch
              % Probably R2013a's new JXBRowser
              browser.setContent(contents);
          end
      end

      % Initialize output var, if requested
      if nargout
          hPopupPanel = jPopup;
      end

  % Error handling
  catch
      err = lasterror;  %#ok
      err.message = regexprep(err.message,'Error using ==> [^\n]+\n','');
      if isempty(strfind(err.message,mfilename))
          % Indicate error origin, if not already stated within the error message
          err.message = [mfilename ': ' err.message];
      end
      rethrow(err);
  end

%% Get the popup panel's handle
function jPopup = getPopupHandle
  jPopup = [];
  retryIdx = 1;
  while isempty(jPopup) && retryIdx < 10
      pause(0.05*retryIdx); drawnow;
      jWindows = com.mathworks.mwswing.MJDialog.getWindows;
      for idx=1 : length(jWindows)
          if strcmp(get(jWindows(idx),'Name'),'HelpPopup')
              if jWindows(idx).isVisible
                  jPopup = jWindows(idx);
                  break;
              end
          end
      end
  end
  
%% Prepare the promo link
function promoLink(jPopup)
  hyperlink = jPopup.findComponentAt(15,jPopup.getHeight-10);
  
  % Prepare the new promo hyperlink
  blogLabel = javax.swing.JLabel('<html><center><a href="">UndocumentedMatlab.com</a></center></html>');
  try blogLabel = javaObjectEDT(blogLabel); catch, end
  oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty');
  warning('off','MATLAB:hg:PossibleDeprecatedJavaSetHGProperty');
  set(blogLabel,'MouseClickedCallback',@promoLink_Callback);
  warning(oldWarn);
  blogLabel.setCursor(java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
  blogLabel.setOpaque(true);

  % Place the new hyperlink in the panel's statusbar
  if isa(hyperlink,'com.mathworks.widgets.HyperlinkLabel$Hyperlink')
      hyperlink = handle(hyperlink,'CallbackProperties');
      %hyperlink.removeListener;
      set(hyperlink, 'MouseClickedCallback',@promoLink_Callback, 'Text',''); %'<html><a href="">UndocumentedMatlab.com</a></html>');
      hyperlabel = hyperlink.getParent;
      %set(hyperlabel, 'MouseClickedCallback',@promoLink_Callback);
      hyperlabel.getParent.add(blogLabel);
      hyperlabel.revalidate;
  elseif isa(hyperlink,'com.mathworks.mwswing.MJEditorPane')
      jPanel = hyperlink.getParent;
      %jPanel.removeAll;
      jPanel.add(blogLabel);
      jAncestor = jPanel.getParent.getParent;
      jAncestor.setVisible(false); jAncestor.setVisible(true);  % solve R2013 bug
      jPanel.repaint;
  end

%% Promo link callback
function promoLink_Callback(hObject, eventData, varargin)  %#ok
  %eventData.consume;
  url = 'http://undocumentedmatlab.com/blog/customizing-help-popup-contents';
  web(url,'-browser');  % integrated browser is slow and does not display all URLs

Contact us