| 
 Introduction
 
				    LindyFrame is a desktop application framework that allows the
				quick development of software that supports internationalization and a modular
				plugin environment. The lindyFrame plugin tutorial documents the highlights of
				creating the HTML Viewer plugin that is included with the framework.
 The lindyFrame plugin architecture allows the application
				to dynamically load code from the installation's sub-directory, lib/plugin,
				as the program is initialized when first run. Any Java JAR file placed in that
				directory will be scanned for the proper contents that can be identified as a
				lindyFrame plugin. Once identified the framework will attempt to add that plugin
				as one of the main tabs the user will see on the right hand side of the lindyFrame
				window as shown in Figure 1. As an alternative to loading plugins automatically
				from the plugin directory a user may use the Tools | Plugin Management
				interface to manually load plugins that thereafter will also be available for
				use. Plugins may be loaded via the local file system, LAN, or Internet.
 
 Figure 1. lindyFrame Main Interface 
 LindyFrame_PluginModule
 
				    The core aspect of the lindyFrame framework plugin module architecture
				is oriented around the abstract LindyFrame_PluginModule class. This class implements
				the Plugin Module Interface which defines the needed routines, class methods, that
				are required for loading and running a plugin module. The code for the LindyFrame_PluginModule
				is provided here and shown in Listing 1. below. From this code listing we
				see the LindyFrame_PluginModule class has a default no argument constructor and
				several methods. All plugins which will extend this class should do no initialization
				work in the constructor and just allow the default super() to be called. The key
				initialization for a plugin should be allocated to the initPlugin() method. The
				initPlugin() method has two argument instances of Main_Frame and String. The Main_Frame
				argument instance will allow a plugin to gain access to lindyFrame's Menu commands
				and the String argument, path, is the plugin's location be it local or network based.
				Now from the listing one should see that the initPlugin() method is commented out
				for the LindyFrame_PluginModule abstract class. This is because this will force
				you as a developer to implement this method in your plugin module class.
			 
				
				Code Listing 1: (LindyFrame_PluginModule.java)
			 
			
			
				| 
//=================================================================
//                LindyFrame_PluginModule Class
//=================================================================
//
//    This class provides the abstract framework for plugin classes
// to extends in order to properly function within the lindyFrame
// application.
//
//             << LindyFrame_PluginModule.java >>
//
//=================================================================
// Copyright (C) 2013-2016 Dana M. Proctor
// Version 1.5 05/21/2016
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version
// 2 of the License, or (at your option) any later version. This
~
~
~
//=================================================================
// Version 1.0 Initial LindyFrame_PluginModule Class.
//         1.1 Cleaned Up Un-needed Methods.
//         1.2 Added Interface Method shutdown().
//         1.3 Changed the Return Types for Methods getToolBar(), getPanel(),
//             getControlledToolBar(), & getControlledPanel() From JToolBar
//             & JPanel to JComponent. Class Instance toolBar & panel Changed
//             Accordingly.
//         1.4 Added Interface Methods start() & stop().
//         1.5 Updated Copyright.
//         1.6 Source Formatting Changes & Class Instance pathFileName Changed to
//             path_FileName. Removed All getControlledXXX() Methods.
//         1.7 Returned Methods getControlledXXX(). 
//             
//-----------------------------------------------------------------
//                 danap@dandymadeproductions.com
//=================================================================
package com.dandymadeproductions.lindyframe.plugin;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JMenuBar;
/**
 *    The LindyFrame_PluginModule class provides the abstract framework
 * for plugin classes to extends in order to properly function within
 * the lindyFrame application.
 * 
 * @author Dana M. Proctor
 * @version 1.7 10/03/2016
 */
public abstract class LindyFrame_PluginModule implements PluginModuleInterface
{
   // Class Instances.
   //protected Main_Frame parent;
   protected String path_FileName;
   public String name;
   public String author;
   protected String version;
   protected String description;
   protected String category;
   protected int size;
   protected ImageIcon tabIcon;
   protected JMenuBar menuBar;
   protected JComponent toolBar;
   protected JComponent panel;
   //===========================================================
   // LindyFrame_PluginModule Constructor
   //===========================================================
   public LindyFrame_PluginModule()
   {
      // Just Initialize to a NULL condition.
      
      path_FileName = null;
      name = null;
      author = null;
      version = null;
      description = null;
      category = null;
      size = 0;
      tabIcon = null;
      menuBar = null;
      toolBar = null;
      panel = null;
   }
   
   //==============================================================
   // Class method to setup up your plugin.
   // OVERIDE THIS METHOD!
   //==============================================================
   /*
   public void initPlugin(Main_Frame mainFrame, String path)
   {
      // This is where the plugin should be initialized.
      parent = mainFrame;
   }
   */
   
   //==============================================================
   // Class methods to get/set the plugin's file name.
   //==============================================================
   
   public String getPath_FileName()
   {
      return path_FileName;
   }
   
   protected String getControlledPath_FileName()
   {
      return path_FileName;
   }
   
   //==============================================================
   // Class method to get/set the plugin's name.
   // Interface requirement.
   //==============================================================
   public String getName()
   {
      return name;
   }
   
   public String getControlledName()
   {
      return name;
   }
   
   //==============================================================
   // Class method to get/set the plugin's author.
   // Interface requirement.
   //==============================================================
   public String getAuthor()
   {
      return author;
   }
   
   public String getControlledAuthor()
   {
      return author;
   }
   
   //==============================================================
   // Class method to obtain the plugin's version number.
   // Interface requirement.
   //==============================================================
   public String getVersion()
   {
      return version;
   }
   
   public String getControlledVersion()
   {
      return version;
   }
   
   //==============================================================
   // Class method to obtain the plugin's description.
   // Interface requirement.
   //==============================================================
   public String getDescription()
   {
      return description;
   }
   
   public String getControlledDescription()
   {
      return description;
   }
   
   //==============================================================
   // Class method to obtain the plugin's category.
   // Interface requirement.
   //==============================================================
   public String getCategory()
   {
      return category;
   }
   
   public String getControlledCategory()
   {
      return category;
   }
   
   //==============================================================
   // Class method to obtain the plugin's size.
   // Interface requirement.
   //==============================================================
   public int getSize()
   {
      return size;
   }
   
   public int getControlledSize()
   {
      return size;
   }
   
   //==============================================================
   // Class method to allow the collection of a image icon that
   // will be used as an identifier in the lindyFrame tab structure.
   //
   // NOTE: The tab icon should be no larger than 16 x 16.
   // Interface requirement.
   //==============================================================
   public ImageIcon getTabIcon()
   {
      return tabIcon;
   }
   
   public ImageIcon getControlledTabIcon()
   {
      return tabIcon;
   }
   
   //==============================================================
   // Class method to obtain the plugin's JMenuBar that can be
   // used to control various aspects of the modules functionality.
   // Interface requirement.
   //==============================================================
   public JMenuBar getMenuBar()
   {
      return menuBar;
   }
   
   public JMenuBar getControlledMenuBar()
   {
      return menuBar;
   }
   
   //==============================================================
   // Class method to allow the collection of a JToolBar to be
   // used with the plugin module.
   // Interface requirement.
   //==============================================================
   public JComponent getToolBar()
   {
      return toolBar;
   }
   
   public JComponent getControlledToolBar()
   {
      return toolBar;
   }
   
   //==============================================================
   // Class method for returning a JComponent, JPanel or JFXPanel
   // for inclusion in the application's main tab. Interface
   // requirement.
   //==============================================================
   public JComponent getPanel()
   {
      return panel;
   }
   
   public JComponent getControlledPanel()
   {
      return panel;
   }
   
   //==============================================================
   // Class method to allow the plugin to start activities back
   // up after a stop() sequence.
   // (USED FOR CONTROLLING THREADS)
   //==============================================================
   public void start()
   {
      // Do what you will to start again from stop.
   }
   
   //==============================================================
   // Class method to allow the plugin to temporarily stop 
   // activities that may then be started again.
   // (USED FOR CONTROLLING THREADS)
   //==============================================================
   public void stop()
   {
      // Do what you will to notify stop.
   }
   
   //==============================================================
   // Class method to allow the plugin to close activities pending
   // a closing of the application.
   //==============================================================
   
   public void shutdown()
   {
      // Do what you will to notify pending closing.
   }
}
					 |  
 
				The key aspect of the initPlugin() method that a developer should know is that
				it should create a custom JComponent object that lindyFrame will use to load into
				its tabbed pane for your plugin. That JComponent should be a panel or pane and will
				be what users will see when your plugin tab is selected from the framework's main
				interface window on the right hand side. The correlated companion class method in
				the LindyFrame_PluginModule class is the getPanel() method. That method should
				return the JComponent component that is created in the initPlugin() method.
 Other methods in the LindyFrame_PluginModule class,
				allow the developer to return the name and an icon that will be used to identify
				a plugin's tab. The name will appear as the tooltip for the tab and the icon
				will become the insignia for the tab. The icon returned through the getTabIcon()
				method should be no larger than 12 x 12 pixels. Two of the other getter methods
				shown in the listing allows a plugin to create its own Menu and Toolbar that
				will be used in conjunction with the module. Several other getter methods are
				also provided that allow the plugin to provide various other information for
				consumption via lindyFrame's Plugin Management interface.
 HTML Viewer Plugin Example
 
				    The lindyFrame application comes with the pre-installed
				plugin, HTMLViewer, that is loaded from the lib/plugins directory of
				the installation. The source code for the HTMLViewer is available as a separate
				download that includes all the source code files for the plugin. The download
				may be found at the Dandy Made Productions' web site under the lindyFrame
				application page, 
				HTML Viewer Plugin. The HTML Viewer plugin code provides the outline
				of the discussion that follows. All resources for the discussion in this article
				are made available via links at the end. Any classes given as part of this tutorial
				are covered by the GPL and may be used in accordance with that license.
 Like all plugins for lindyFrame a developer should create a new
				class called PluginModule that extends the LindyFrame_PluginModule class.
				The abbreviated code for the HTMLViewer plugin PluginModule class is shown below
				in listing 2. The constructor for the new class should perform no work except
				call the super() to the parent, LindyFrame_PluginModule. The new PluginModule class
				should orientate initialization of components for the plugin in the initPlugin()
				method. As can be seen from the listing the HTMLViewer initializes three instances,
				pluginName, pluginAuthor, and htmlViewer. The first two will be used to identify
				the name and author of the plugin and the third calls for the construction of a
				new class that will handle the creation of the main JPanel component needed by
				the plugin. Though not shown in the abbreviated listing the HTMLViewer PluginModule
				class overrides all the methods of the LindyFrame_PluginModule class and either
				returns directly or indirectly through the instance htmlViewer the requirements
				for the plugin. A developer need not override all the getter methods for a PluginModule
				class since the lindyFrame framework will substitute defaults for these instances,
				but without a JPanel component no visibility will be given to your plugin.
 
 NOTICE: All PLUGINS MUST FOLLOW THE BASIC INTERFACE DESCRIBED HERE FOR A
				LindyFrame_PluginModule AND BE GIVEN THE CLASS NAME PluginModule. lindyFrame
				WILL ONLY SEARCH FOR AND LOAD PLUGIN CLASSES GIVEN THE NAME PluginModule!
 
				
				Code Listing 2: (PluginModule.java)
			 
			
			
				| 
//=================================================================
//              HTMLViewer PluginModule Class
//=================================================================
//
//    This class provides the hook to incorporate a external plugin
// module into the lindyFrame framework.
//
//              < PluginModule.java >
//
//=================================================================
// Copyright (C) 2013 Dana M. Proctor
// Version 1.0 07/26/2013
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
~
~
~
~
//-----------------------------------------------------------------
//                 danap@dandymadeproductions.com
//=================================================================
package com.dandymadeproductions.htmlviewer;
import javax.swing.ImageIcon;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import com.dandymadeproductions.lindyframe.gui.Main_Frame;
import com.dandymadeproductions.lindyframe.plugin.LindyFrame_PluginModule;
/**
 *    The PluginModule class provides the hook to incorporate a external plugin
 * module into the lindyFrame framework.
 * 
 * @author Dana M. Proctor
 * @version 1.0 07/26/2013
 */
public class PluginModule extends LindyFrame_PluginModule
{
   // Class Instances
   private String pluginName, pluginAuthor;
   private HTMLViewer htmlViewer;
   //==============================================================
   // PluginModule Constructor.
   //==============================================================
   public PluginModule()
   {
      super();
   }
   //==============================================================
   // Class method to initialize your plugin.
   //==============================================================
   public void initPlugin(Main_Frame parentFrame, String path)
   {
      pluginName = "HTML Viewer";
      pluginAuthor = "Dandy Made Productions";
      htmlViewer = new HTMLViewer(parentFrame, path);
   }
~
~
~
   public String getName() {
      return pluginName;
   }
~
~
~
   public String getAuthor() {
      return pluginAuthor;
   }
~
~
~ 
   public JPanel getPanel() {
     return htmlViewer.getPanel();
   }
}
					 |  
 HTMLViewer Class
 
				    The HTMLViewer class is the main component of the HTMLViewer
				plugin and was instantiated in the PluginModule class method initPlugin()
				with the instance htmlViewer. The constructor for this class takes two
				arguments, Main_Frame and String. More will be detailed of the Main_Frame
				argument, but first lets speak more about of the path argument because it
				is used to derive resources for the plugin
				
 The path instance that is passed to plugin modules gives the URL that was derived
				by lindyFrame in loading the plugin's JAR file. A developer should create resources
				for a plugin with this in mind. The standard taken by the lindyFrame group is to
				have a directory in this path, location of JAR file, by the same name as the plugin
				and in this directory have images and other pertinent objects required by the plugin.
				Please see Figure 2. below. With this in mind lets move on to the htmlViewer
				object to understand the use of this path and the other argument in the instantiation
				of this class.
 
 Figure 2. Plugin Directory Structure 
 
				    Though the HTMLViewer class is the core main object for
				the HTMLViewer plugin it is not per say a main class. All plugins do
				not have a main class, but as discussed previously just the PluginModule
				class which lindyFrame initializes through the initPlugin() method and then
				loads the various components needed to utilize the plugin. The main object
				for plugins is always a Java JPanel or JFXPanel component that is the face of the plugin
				in the lindyFrame application tab interface. So what we will see in the
				HTMLViewer core class is the creation of a main Panel object and the
				creation of resources and menu and toolbar objects. Listing 3. below
				shows the HTMLViewer condensed class and as seen is composed of a constructor
				and several methods. Three of the methods just return the objects indicated,
				JPanel, JMenuBar, and JToolBar. The other three a version and description,
				Strings and an ImageIcon. The constructor for the class creates each of these
				objects directly or through additional classes.
			 
				
				Code Listing 3: (HTMLViewer Main Class HTMLViewer.java)
			 
			
			
				| 
//=================================================================
//                        HTMLViewer
//=================================================================
//
//    This class provides the main access point for setting up the
// requirements for the HTMLView plugin module for the lindyFrame
// framework.
//
//                     << HTMLViewer.java >>
//
//=================================================================
// Copyright (C) 2013-2016 Dana M. Proctor
// Version 1.5 11/07/2016
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version
// 2 of the License, or (at your option) any later version. This
~
~
~
//=================================================================
// Revision History
// Changes to the code should be documented here and reflected
// in the present version number. Author information should
// also be included with the original copyright author.
//=================================================================
// Version 1.0 07/27/2013 Initial HTMLViewer Class.
//         1.1 08/02/2013 Added History Functionality and URL Entry
//                        Capability.
//         1.2 08/29/2013 Resources Should NOT Use Local System File Separator
//                        Definition, But Rather Standard File Delimitor Forward
//                        Slash.
//         1.3 06/24/2016 Updated VERSION to Bring Class Into Sync With lindyFrame
//                        v2.5. Now Compiled to Comply With JRE7.
//         1.4 11/07/2016 Updated VERSION & Made Resources Specified in Jar.
//         1.5 11/07/2016 Used imagesDirectory Instead of path as Argument for
//                        Viewer_ToolBar. Updated Version.
//                           
//-----------------------------------------------------------------
//                 danap@dandymadeproductions.com
//=================================================================
package com.dandymadeproductions.htmlviewer;
import java.awt.BorderLayout;
~
~
~
import javax.swing.text.html.HTMLEditorKit;
import com.dandymadeproductions.lindyframe.LindyFrame;
import com.dandymadeproductions.lindyframe.gui.Main_Frame;
import com.dandymadeproductions.lindyframe.utilities.LindyFrame_ResourceBundle;
import com.dandymadeproductions.lindyframe.utilities.LindyFrame_Utils;
/**
 *    The HTMLViewer class provides the main access point for
 * setting up the requirements for the HTMLView plugin module
 * for the lindyFrame framework.
 * 
 * @author Dana M. Proctor
 * @version 1.5 11/07/2016
 */
class HTMLViewer implements ActionListener
{
   // Class Instances
   private ImageIcon tabIcon;
   
   private GridBagLayout gridbag;
   private GridBagConstraints constraints;
   private JPanel mainPanel, urlEntryPanel, statusPanel;
   private JButton historyBackButton, historyForwardButton, refreshButton;
   private JTextField urlEntryTextField;
   private LinkedList historyList;
   protected HTMLEditorPane viewerPane;
   private JProgressBar progressBar;
   private JLabel statusLabel;
   private Viewer_MenuBar menuBar;
   private Viewer_ToolBar toolBar;
   private LindyFrame_ResourceBundle resourceBundle;
   
   private String loadingPageResource, pageNotFoundResource;
   private int stateHistoryIndex;
   private final static String VERSION = "Version 1.5";
   private final static String DESCRIPTION = "The HTMLViewer plugin provides a mean to demostrate a module"
                                             + " example for the lindyFrame framework. The plugin is a basic"
                                             + " HTML viewer that displays the tutorial for creating plugins"
                                             + " with lindyFrame.";
   
   private static final int STATE_HISTORY_LIMIT = 25;
   //==============================================================
   // HTMLViewer Constructor
   //==============================================================
   public HTMLViewer(Main_Frame parent, String path)
   {
      // Constructor Instances.
      String pathDirectory, localeDirectory, imagesDirectory;
      MenuActionListener pluginMenuListener;
      // Setup the Main panel and the plugin's components.
      mainPanel = new JPanel(new BorderLayout());
      // ** NOTE: file/local network only, locale resource not in JAR **
      pathDirectory = path + "/" + "HTMLViewer" + "/";
      localeDirectory = "locale/";
      imagesDirectory = "images/";
      // ** NOTE: http/ftp locale resource in JAR **
      // pathDirectory = path + "/" + "HTMLViewer.jar";
      // localeDirectory = "lib/plugins/HTMLViewer/locale/";
      // imagesDirectory = "lib/plugins/HTMLViewer/images/";
      resourceBundle = new LindyFrame_ResourceBundle(pathDirectory, LindyFrame.getDebug());
      resourceBundle.setLocaleResource(localeDirectory, "HTMLViewer", LindyFrame.getLocaleString());
      tabIcon = resourceBundle.getResourceImage(imagesDirectory + "icons/htmlViewerIcon.png");
      loadingPageResource = resourceBundle.getResourceString("HTMLViewer.label.LoadingPage", "Loading Page");
      pageNotFoundResource = resourceBundle.getResourceString("HTMLViewer.label.PageNotFound",
                                                              "Page Not Found");
      
      // Create the GUI components.
      
      gridbag = new GridBagLayout();
      constraints = new GridBagConstraints();
      // URL Entry Panel.
      initURLEntryPanel(imagesDirectory);
      mainPanel.add(urlEntryPanel, BorderLayout.NORTH);
      // HTML Panel.
      initViewer();
      mainPanel.add(new JScrollPane(viewerPane), BorderLayout.CENTER);
      // Status Panel
      initStatusPanel();
      mainPanel.add(statusPanel, BorderLayout.SOUTH);
      // Setup the MenuBar and ToolBar to be used by the plugin.
      pluginMenuListener = new MenuActionListener(parent, this, resourceBundle);
      menuBar = new Viewer_MenuBar(parent, resourceBundle, pluginMenuListener);
      toolBar = new Viewer_ToolBar("HTMLViewer ToolBar", parent, imagesDirectory, resourceBundle,
                                   pluginMenuListener);
      
      loadPage("file:"
         + LindyFrame_Utils.getResourceBundle().getResourceFile(
            "docs/Plugins/Tutorial/LindyFrame_PluginTutorial.html").getPath());
   }
~
~
~
~ 
   //==============================================================
   // Class method to to the plugin's JMenuBar
   //==============================================================
   protected JMenuBar getMenuBar()
   {
      return menuBar;
   }
   //==============================================================
   // Class method get the plugin's JToolBar
   //==============================================================
   protected JToolBar getToolBar()
   {
      return toolBar;
   }
   //==============================================================
   // Class method to get the main panel associated with the plugin.
   //==============================================================
   protected JPanel getPanel()
   {
      return mainPanel;
   }
   //==============================================================
   // Class method to get the plugin's version.
   //==============================================================
   protected String getVersion()
   {
      return VERSION;
   }
   //==============================================================
   // Class method to get the plugin's description.
   //==============================================================
   protected String getDescription()
   {
      return DESCRIPTION;
   }
   //==============================================================
   // Class method to get the icon that will be used in the
   // lindyFrame tab.
   //==============================================================
   protected ImageIcon getTabIcon()
   {
      return tabIcon;
   }
}
					 |  
 
				    The constructor for the HTMLViewer class like most classes
				is where the setup for the HTML Viewer plugin occurs. The first
				thing that is done in the constructor is to create the JPanel, mainPanel.
				This panel is the face of the plugin that users will see in the selected
				tab for the HTMLViewer module. The mainPanel has several components
				added to it in order to create the plugin and those objects are created
				in the helper methods not shown, but called through initURLEntryPanel(),
				initViewer(), and initStatusPanel(). Those methods are not pertinate to
				the discussion here since they just serve to help create the GUI for
				the HTML Viewer. Before the call to those additional methods it is noted
				that we begin the derivation of a resource reference for the plugin that
				is based on the path argument string in the constructor. LindyFrame has
				the capability of installing a plugin locally automatically from the
				lib/plugins directory or be loaded via the Plugin Management tool.
				When a developer creates the plugin a decision should be made to allow
				these local/remote resources to be either sourced in the JAR file of the
				plugin or not. Note; All plugins that will be loaded remotely, Internet,
				must store resouces in the JAR file.
				
 In the HTMLViewer constructor we see the two ways that this may be
				implemented, one commented out. The example uses resources that will NOT be
				included in the JAR and uses three instances to derive the pathDirectory,
				localeDirectory, & imagesDirectory from the path and layout that was
				chosen by the plugin as shown in Figure 2. We then create a LindyFrame_ResourceBundle
				based on the pathDirectory and set the locale for the plugin. The language
				locale can be obtained directly from the LindyFrame API method getLocaleString().
				That language locale string is chosen by the user when lindyFrame is first
				run or by argument to the application. Though one could use the standard Java
				API for a Resource object lindyFrame uses its own resource class which provides
				greater flexibility, and control in organizing resources in a plugin environment.
 
 In the constructor we now see the use of a resource object. The tabIcon is
				acquired through the LindyFrame_ResourceBundle's getResourceImage(). In that
				method we pass the imagesDirectory and the name of the image file. The tabIcon
				will be returned through the class method getTabIcon() for the plugin module
				so that it may be displayed in lindyFrame's main tab pane. Likewise we may
				also use the resourceBundle object to obtain a getResourceString() that relates
				to properly displaying language aspects of the GUI for the locale.
 
 Now that all the main setup in the constructor has been
				accomplished then the only activities left to do is to create the menu and
				toolbar objects. The menu and toolbar objects for the plugin are created
				through two separate classes Viewer_MenuBar and Viewer_ToolBar. An Action
				Listener object is also created to handle the processing of events in the
				plugin. The Action Listener class, MenuActionListener, is not covered in
				this tutorial, but is supplied as a resource via links available at the
				end of this tutorial.
 
 Note: Any classes given as part of this tutorial are covered by the GPL
				and may be used in accordance with that license.
 HTMLViewer Viewer_MenuBar Class
 
				    The last aspect of this advanced lindyFrame plugin tutorial
				that is to be dealt with is the creation of a custom menu bar and tool bar
				components for the plugin. LindyFrame allows each plugin to share its
				controls, action events, and create their own. As each plugin tab is
				selected in the main interface of lindyFrame the MenuBar and ToolBar for
				that plugin is activated and available for use. Since a tool bar houses
				essential duplicate items in the form of buttons with icons as a menu system
				we will just review the MenuBar object for the HTMLViewer plugin.
 The partial Code Listing 4. shown below is of the HTMLViewer's Viewer_MenuBar
				class. Though the menu systems has both a File and Edit entry all that is
				needed to demonstrate the desired concepts is the creation of the File menu.
				What one should note immediately about this class is it extends the Java JMenuBar
				component so that its meets the needs of a standard MenuBar. The constructor
				for the Viewer_MenuBar class is straight forward with the assignment of the
				three passed arguments to class instances. Remember those objects were the
				lindyFrame main frame, the resourceBundle, and the custom Action Listener
				object. Up to this point we have not used the lindyFrame main frame object,
				but we will shortly. The constructor code continues with calling two helper
				methods to build the file and edit menu systems and then producing a custom
				logo object. Of interest here is the use of the LindyFrame_Utils class to
				obtain the icons directory and loading one of lindyFrame's own icon images
				for the logo.
 
				
				Code Listing 3: (HTMLViewer Viewer_MenuBar.java)
			 
			
			
				| 
//=================================================================
//                  HTMLViewer Viewer_MenuBar
//=================================================================
//
//    This class is used to constructed the menubar for the HTML
// Viewer plugin module.
//
//                 < Viewer_MenuBar.java >
//
//=================================================================
// Copyright (C) 2013 Dana M. Proctor.
// Version 1.0 07/27/2013
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
~
~
~
// Version 1.0 07/27/2013 Original Viewer_MenuBar Class.
//
//-----------------------------------------------------------------
//                 danap@dandymadeproductions.com
//=================================================================
package com.dandymadeproductions.htmlviewer;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import com.dandymadeproductions.lindyframe.LindyFrame;
import com.dandymadeproductions.lindyframe.gui.LindyFrame_MenuActionCommands;
import com.dandymadeproductions.lindyframe.gui.Main_Frame;
import com.dandymadeproductions.lindyframe.utilities.LindyFrame_ResourceBundle;
import com.dandymadeproductions.lindyframe.utilities.LindyFrame_Utils;
/**
 *    The Viewer_MenuBar class is used to constructed the menubar for
 * the HTML Viewer plugin module.
 * 
 * @author Dana M. Proctor
 * @version 1.0 07/27/2013
 */
class Viewer_MenuBar extends JMenuBar
{
   // Instance & Class Fields.
   private static final long serialVersionUID = -6134364585633519070L;
   private Main_Frame mainFrame;
   private LindyFrame_ResourceBundle resourceBundle;
   private MenuActionListener menuListener;
   public static final String ACTION_FILE_OPEN = "File Open";
   public static final String ACTION_EDIT_SEARCH = "Edit Search";
   //==============================================================
   // Viewer_MenuBar JMenuBar Constructor.
   //==============================================================
   protected Viewer_MenuBar(Main_Frame parent, LindyFrame_ResourceBundle resourceBundle,
                            MenuActionListener plugin)
   {
      mainFrame = parent;
      this.resourceBundle = resourceBundle;
      menuListener = plugin;
      // Constructor Instances.
      String iconsDirectory;
      // JMenu Bar for the plugin.
      setBorder(BorderFactory.createEtchedBorder());
      // Creating the File, and Tools Menus
      createFileMenu();
      createEditMenu();
      add(Box.createHorizontalGlue());
      // Logo
      iconsDirectory = LindyFrame_Utils.getIconsDirectory() + LindyFrame_Utils.getFileSeparator();
      ImageIcon logoIcon = LindyFrame.getResourceBundle().getResourceImage(iconsDirectory
                                                                           + "lindyFrameIcon.gif");
      JButton logoIconItem = new JButton(logoIcon);
      logoIconItem.setDisabledIcon(logoIcon);
      logoIconItem.setFocusPainted(false);
      logoIconItem.setBorder(BorderFactory.createLoweredBevelBorder());
      add(logoIconItem);
   }
   //==============================================================
   // Helper Method to create the File Menu.
   //==============================================================
   private void createFileMenu()
   {
      // Method Instances.
      String resource;
      JMenu fileMenu;
      JMenuItem item;
      // ===========
      // File Menu
      resource = resourceBundle.getResourceString("Viewer_MenuBar.menu.File",
                                                  "File");
      fileMenu = new JMenu(resource);
      fileMenu.setFont(fileMenu.getFont().deriveFont(Font.BOLD));
      // Open
      resource = resourceBundle.getResourceString("Viewer_MenuBar.menu.Open",
                                                  "Open");
      fileMenu.add(menuItem(resource, ACTION_FILE_OPEN));
      fileMenu.addSeparator();
      // Exit
      resource = resourceBundle.getResourceString("Viewer_MenuBar.menu.Exit",
                                                  "Exit");
      item = new JMenuItem(resource);
      item.addActionListener(mainFrame);
      item.setActionCommand(LindyFrame_MenuActionCommands.ACTION_EXIT);
      fileMenu.add(item);
      add(fileMenu);
   }
   
   //==============================================================
   // Helper Method to create the Edit Menu.
   //==============================================================
   private void createEditMenu()
   {
      // Method Instances.
      String resource;
      JMenu editMenu;
      // ===========
      // Edit Menu
      resource = resourceBundle.getResourceString("Viewer_MenuBar.menu.Edit",
                                                  "Edit");
      editMenu = new JMenu(resource);
      editMenu.setFont(editMenu.getFont().deriveFont(Font.BOLD));
      // Search
      resource = resourceBundle.getResourceString("Viewer_MenuBar.menu.Search",
                                                  "Search");
      editMenu.add(menuItem(resource, ACTION_EDIT_SEARCH));
     
      add(editMenu);
   }
   
   //==============================================================
   // Instance method used for the creation of menu bar items.
   // Helper Method.
   //==============================================================
   private JMenuItem menuItem(String label, String actionLabel)
   {
      JMenuItem item = new JMenuItem(label);
      item.addActionListener(menuListener);
      item.setActionCommand(actionLabel);
      return item;
   }
}
					 |  
 
				    Moving forward with the menu systems for the plugin we
				have the class method createFileMenu(). Here is where we will create
				a File menu with sub items of File | Open, and File | Exit.
				The first is basic in nature and is derived by using the resourceBundle.getResourceString()
				and calling an additional helper method to create the JMenuItem. Note we
				assign an ActionListener for that sub item of the custom MenuActionListener,
				menuListener, in the helper method menuItem(). The last menu sub item is
				slightly different from the first because it is a call to exit the application.
				It is done via one of lindyFrame's own action events that is part of
				main frame. We find the action event needed by making a reference to the
				LindyFrame_MenuActionCommands class. In this case the action command string
				is ACTION_EXIT. We complete the File menu by adding the JMenu to the classes'
				own add method.
			 Summary
 
				    In this lindyFrame plugin tutorial we have discussed the
				implementation of the HTMLViewer plugin. The HTML Viewer module was
				chosen because it demonstrates advanced features that a plugin may need
				in order to accomplish its purposes. Some of those advanced aspects of
				plugin creation have to do with returning a version string and tab icon
				image for the lindyFrame's tabbed pane. Other requirements that a plugin
				may need to implement is language support. LindyFrame provides a class,
				LindyFrame_ResourceBundle, and a method to return user selected locale
				information via LindyFrame.getLocaleString() to accomplish this goal.
				LindyFrame determines the location of resources via the path string object
				that is passed to the initPlugin() method of the PluginModule class. The
				final advanced features that a plugin may wish to produce is a menu and
				tool bar components. The PluginModule class provides a means to return
				those objects so they may be assigned to the tab interface for the plugin.
				In addition lindyFrame also makes its own menu items, and action events
				available to a plugin via the Main_Frame class and its corresponding
				action commands in the LindyFrame_MenuActionCommands class.
			 
 Resources
				LindyFrame_PluginModule ClassPluginModule Class
 HTMLViewer Main Class
 MenuActionListener Class
 Viewer_MenuBar Class
 Viewer_ToolBar Class
 
 |