/**
 * Copyright (c) 2011, Martin Foster <martin@ethereal-realms.org>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice, 
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright 
 *       notice, this list of conditions and the following disclaimer in the 
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Ethereal-Realms.org nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.lyra;

// Main Imports
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.HashMap;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.WindowConstants;
import javax.swing.border.Border;

import org.icepdf.core.views.DocumentViewController;
import org.icepdf.ri.common.SwingController;
import org.icepdf.ri.common.SwingViewBuilder;
import org.icepdf.ri.common.views.DocumentViewControllerImpl;
import org.lyra.Lyra;


/**
 * Class dedicated to the loading and viewing of PDF documents. The interface is
 * similar to that offered by the Adobe Acrobat program, simply embedded within
 * the application and used for the display of help information.
 * <p>
 * All of the button handling is completed using the ICEpdf SwingController
 * class and methods.  Hence there is no instance of an Interact Class which
 * is typically accompanies user interface classes within this Package to
 * separate interface and programming elements.
 * <p>
 * @author Martin Foster
 * @version 1.0.4, %Revision, 147%, %LastChangedDate, 06/11/11 4:57PM%
 */
public class HelpManager {

	// Display controller
	SwingController viewerController;

	// Path name
	String filePath;

	/*
	 * DISPLAY ELEMENTS
	 */
	
	// Standard Buttons
	private JLockedButton buttonPrint = null;
	private JLockedButton buttonSearch = null;
	private JLockedButton buttonPane = null;
	private JLockedButton buttonFirst = null;
	private JLockedButton buttonPrev = null;
	private JLockedButton buttonNext = null;
	private JLockedButton buttonLast = null;
	private JLockedButton buttonZoomIn = null;
	private JLockedButton buttonZoomOut = null;

	// Toggle Buttons
	private JLockedToggleButton togglePan = null;
	private JLockedToggleButton toggleSelect = null;
	private JLockedToggleButton toggleWidth = null;

	// Viewer container
	private JPanel viewerPanel = null;
	private JFrame viewerFrame = null;

	// State Elements
	private String stateName;


	/*
	 * PACKAGE INSTANCES
	 */
	private Map<String,String> Lang;
	private String Title;
	
	// Base constructor generation
	private boolean Base = false;
	
	
	/**
	 * Standard constructor method.
	 */
	@SuppressWarnings("serial")
	public HelpManager() {
		
		// Base constructor management
		Base = true;
		
		// Pass Up
		filePath = Lyra.DOC_SOURCE + "Default.pdf";

		/*
		 * Under normal circumstances this section will be passed on from the
		 * database.   However Visual Editors do not have this ability to we
		 * create a HashMap that can be used either way.
		 */
		Lang = new HashMap<String,String>(){
			{
				// Titles and Sections
	        	put("Help.Window.Title","Lyra - Help");
	        	
	    		// Establish language elements
	    		put("Tooltip.Help.Print","Print Document");
	    		put("Tooltip.Help.Search","Search");
	  			put("Tooltip.Help.Pane","View/Hide Pane");
	    		put("Tooltip.Help.First","Goto First Page");
	    		put("Tooltip.Help.Prev","Back a Page");
	    		put("Tooltip.Help.Next","Forward a Page");
	    		put("Tooltip.Help.Last","Goto Last Page");
	    		put("Tooltip.Help.ZoomIn","Zoom In");
	    		put("Tooltip.Help.ZoomOut","Zoom Out");
	    		put("Tooltip.Help.Pan","Pan Mode");
	    		put("Tooltip.Help.Select","Selection Mode");
	    		put("Tooltip.Help.Width","Adjust Zoom to Page Width");
			}
		};
		
		// Pass up
		Title = Lang.get("Help.Window.Title");
		
		// build a component controller
		viewerController = new SwingController();

		// View
		getViewerFrame();
	}
	// End of Constructor Method

	
	/**
	 * Main constructor method which is used specifically to carry forth
	 * language independence.
	 * <p>
	 * @param lang Language element.
	 * @param path String element with path to PDF document.
	 */
	public HelpManager(Map<String,String> lang, String path) {
		
		// Pass up the file path
		this.filePath = path;
		
		// Pass up the language
		this.Lang = lang;
		
		// Pass up title
		this.Title = Lang.get("Help.Window.Title");
		
		// build a component controller
		viewerController = new SwingController();
	}
	// End of Constructor Method

	
	/**
	 * Main constructor method which is used specifically to carry forth
	 * language independence.
	 * <p>
	 * @param lang Language element.
	 * @param title String containing window title. 
	 * @param path String element with path to PDF document.
	 */
	public HelpManager(Map<String,String> lang, String title, String path) {
				
		// Pass up the language
		this.Lang = lang;
		
		// Pass up title
		this.Title = title;

		// Pass up the file path
		this.filePath = path;
		
		// Adjust identifier
		setName(title);
		
		// build a component controller
		viewerController = new SwingController();
	}
	// End of Constructor Method
	
	
	/**
	 * We do not necessarily care to do anything overly complex when the
	 * visual editor constructor is enacted.  This will tell us in order
	 * to avoid.
	 * <p>
	 * @return Boolean indicating base constructor instance.
	 */
	public boolean isDefault() {
		
		// Return base value
		return Base;
	}
	// End of isDefault Method
	
	
	/**
	 * This is an instance of the viewer panel that is to be embedded within
	 * an existing element such as a JFrame.  While not always the preferred
	 * method it offers certain advantages over a self-sufficient method also
	 * available.
	 * <p>
	 * @return JComponent containing the panel.
	 */
	public JPanel getViewerPanel() {
		
		// Create if not defined
		if (viewerPanel == null) {
			
			// Builder class element
			SwingViewBuilder factory = new SwingViewBuilder(viewerController);

			// Now that the GUI is all in place, we can try opening a PDF
			viewerController.openDocument(filePath);
			viewerController.setPageFitMode(
					DocumentViewController.PAGE_FIT_WINDOW_WIDTH, true);
			viewerController.setPageViewMode(
					DocumentViewControllerImpl.ONE_COLUMN_VIEW, true);

			// Generate Panel
			viewerPanel = buildViewerPanel(factory);
		}

		// Generate a complete panel
		return viewerPanel;
	}
	// End getViewerPanel Method.

	
	/**
	 * The viewer component is what we really want when the viewer is called.
	 * This will pass along the generated JPanel elements to the caller.
	 * <p>
	 * @return JComponent containing the panel.
	 */
	public JFrame getViewerFrame() {
		
		// Create if not defined
		if (viewerFrame == null) {
			
			// Setup frame
			viewerFrame = new JFrame();
			viewerFrame.getContentPane().add(getViewerPanel());

			// Adjust title
			viewerFrame.setTitle(Title);
			
			// Adjust Icon
			viewerFrame.setIconImage(new ImageIcon(
					getClass().getResource(
							Lyra.IMG_SOURCE + Lyra.LYRA)).getImage());
			
			// Show the component
			viewerFrame.pack();
			viewerFrame.setDefaultCloseOperation(
					WindowConstants.HIDE_ON_CLOSE);
		}

		// Generate a complete panel
		return viewerFrame;
	}
	// End getViewerFrame Method.
	
	
	/**
	 * The default buildViewerPanel method used by the PDF libraries tends to
	 * offer little to no custom capabilities. At least not in terms of unique
	 * icons and language elements.
	 * <p>
	 * This method will implement many of the features found in the source of
	 * buildViewerPanel but will also adapt it to suit out needs. Most
	 * specifically the capabilities provided in the tool bar.
	 * <p>
	 * @param factory SwingViewBuilder factory object.
	 * @return JPanel containing the complete PDF viewer.
	 */
	private JPanel buildViewerPanel(SwingViewBuilder factory) {
		
		// Create and Set Panel Layout
		JPanel panel = new JPanel();
		panel.setLayout(new BorderLayout());

		// Establish a tool bar
		panel.add(buildCompleteToolBar(), BorderLayout.NORTH);

		// Builds the utility pane as well as the main document View, important
		// code entry point.
		panel.add(factory.buildUtilityAndDocumentSplitPane(true),
				BorderLayout.CENTER);

		// Return completed panel
		return panel;
	}
	// End of buildViewerPanel Method

	
	/**
	 * This method is used specifically to generate the complete Tool Bar
	 * element which is required for easy operation of the PDF viewer. Since the
	 * built-in factory element does not adequately allow for modification this
	 * is essentially a direct application of the necessary elements to suit out
	 * needs.
	 * <p>
	 * @return JToolBar containing all of the desired buttons matching out theme
	 */
	private JToolBar buildCompleteToolBar() {
		
		// Setup Graphical Interface
		JToolBar toolbar = new JToolBar();

		// File tools
		toolbar.add(getButtonPrint());
		toolbar.add(getButtonSearch());
		toolbar.add(getButtonPane());
		toolbar.addSeparator();

		// Navigation tools
		toolbar.add(getButtonFirst());
		toolbar.add(getButtonPrev());
		toolbar.add(getButtonNext());
		toolbar.add(getButtonLast());
		toolbar.addSeparator();

		// Zoom tool bar
		toolbar.add(getButtonZoomIn());
		toolbar.add(getButtonZoomOut());
		toolbar.addSeparator();

		// Add toggle buttons
		toolbar.add(getToggleWidth());
		toolbar.add(getTogglePan());
		toolbar.add(getToggleSelect());

		// Tool Bar options
		toolbar.requestFocus();
		toolbar.setRollover(true);

		// Return completed element
		return toolbar;
	}
	// End of buildCompleteTollbar Method


	/**
	 * This method initialises buttonPrint
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getButtonPrint() {
		
		// Check for Existence
		if (buttonPrint == null) {
			
			// Create Instance
			buttonPrint = new JLockedButton();
			
			// Icon and tool tips
			buttonPrint.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-Printer"))));
			buttonPrint.setToolTipText(Lang.get("Tooltip.Help.Print"));

			// Prevent controller from making changes
			buttonPrint.setLocked(true);
			
			// Set Controller
			viewerController.setPrintButton(buttonPrint);
		}
		
		// Return Instance
		return buttonPrint;
	}
	// End of getButtonPrint Method

	
	/**
	 * This method initialises buttonSearch
	 * <p>
	 * @return javax.swing.JButton
	 */
	private JButton getButtonSearch() {
		
		// Check for Existence
		if (buttonSearch == null) {
			
			// Create Instance
			buttonSearch = new JLockedButton();
			
			// Icon and Tool Tip
			buttonSearch.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-Search"))));
			buttonSearch.setToolTipText(Lang.get("Tooltip.Help.Search"));

			// Prevent controller from making changes
			buttonSearch.setLocked(true);
			
			// Set Controller
			viewerController.setSearchButton(buttonSearch);
		}
		
		// Return Instance
		return buttonSearch;
	}
	// End of getButtonSearch Method

	
	/**
	 * This method initialises buttonPane
	 * <p> 
	 * @return javax.swing.JButton
	 */
	private JButton getButtonPane() {
		
		// Check for Existence
		if (buttonPane == null) {
			
			// Create Instance
			buttonPane = new JLockedButton();
			
			// Icon and Tool tip
			buttonPane.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-Pane"))));
			buttonPane.setToolTipText(Lang.get("Tooltip.Help.Pane"));

			// Prevent controller from making changes
			buttonPane.setLocked(true);
			
			// Set Controller
			viewerController.setShowHideUtilityPaneButton(buttonPane);
		}
		
		// Return Instance
		return buttonPane;
	}

	// End of getButtonPane

	
	/**
	 * This method initialises buttonFirst
	 * <p>
	 * @return javax.swing.JButton
	 */
	private JButton getButtonFirst() {
		
		// Check for Existence
		if (buttonFirst == null) {
			
			// Create Instance
			buttonFirst = new JLockedButton();
			
			// Icon and Tool tip
			buttonFirst.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-First"))));
			buttonFirst.setToolTipText(Lang.get("Tooltip.Help.First"));

			// Prevent controller from making changes
			buttonFirst.setLocked(true);
			
			// Set Controller
			viewerController.setFirstPageButton(buttonFirst);
		}
		
		// Return Instance
		return buttonFirst;
	}
	// End of getButtonFirst Method

	
	/**
	 * This method initialises buttonPrev.
	 * <p>
	 * @return javax.swing.JButton
	 */
	private JButton getButtonPrev() {
		
		// Check for Existence
		if (buttonPrev == null) {
			
			// Create Instance
			buttonPrev = new JLockedButton();
			
			// Icon and Tool tip
			buttonPrev.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-Previous"))));
			buttonPrev.setToolTipText(Lang.get("Tooltip.Help.Prev"));

			// Prevent controller from making changes
			buttonPrev.setLocked(true);
			
			// Set Controller
			viewerController.setPreviousPageButton(buttonPrev);
		}
		
		// Return Instance
		return buttonPrev;
	}
	// End of getButtonPrev Method

	
	/**
	 * This method initialises buttonNext
	 * <p> 
	 * @return javax.swing.JButton
	 */
	private JButton getButtonNext() {
		
		// Check for Existence
		if (buttonNext == null) {
			
			// Create Instance
			buttonNext = new JLockedButton();
			
			// Icon and Tool tip
			buttonNext.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-Next"))));
			buttonNext.setToolTipText(Lang.get("Tooltip.Help.Next"));

			// Prevent controller from making changes
			buttonNext.setLocked(true);
			
			// Set Controller
			viewerController.setNextPageButton(buttonNext);
		}
		
		// Return Instance
		return buttonNext;
	}
	// End of getButtonNext Method

	
	/**
	 * This method initialises buttonLast
	 * <p> 
	 * @return javax.swing.JButton
	 */
	private JButton getButtonLast() {
		
		// Check for Existence
		if (buttonLast == null) {
			
			// Create Instance
			buttonLast = new JLockedButton();
			
			// Icon and Tool Tip
			buttonLast.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-Last"))));
			buttonLast.setToolTipText(Lang.get("Tooltip.Help.Last"));

			// Prevent controller from making changes
			buttonLast.setLocked(true);
			
			// Set Controller
			viewerController.setLastPageButton(buttonLast);
		}
		
		// Return Instance
		return buttonLast;
	}
	// End of getButtonLast Method

	
	/**
	 * This method initialises toggleWidth.
	 * <p>
	 * @return javax.swing.JButton
	 */
	private JToggleButton getToggleWidth() {
		
		// Check for Existence
		if (toggleWidth == null) {
			
			// Create New Instance
			toggleWidth = new JLockedToggleButton();
			
			// Icon and Tool Tip
			toggleWidth.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-Width"))));
			toggleWidth.setToolTipText(Lang.get("Tooltip.Help.Width"));

			// Prevent controller from making changes
			toggleWidth.setLocked(true);
			
			// Set Controller
			viewerController.setFitWidthButton(toggleWidth);
		}
		
		// Return Instance
		return toggleWidth;
	}
	// End of getButtonWidth Method

	
	/**
	 * This method initialises buttonZoomIn
	 * <p>
	 * @return javax.swing.JButton
	 */
	private JButton getButtonZoomIn() {
		
		// Check for Existence
		if (buttonZoomIn == null) {
			
			// Create Instance
			buttonZoomIn = new JLockedButton();
			
			// Icon and Language
			buttonZoomIn.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-ZoomIn"))));
			buttonZoomIn.setToolTipText(Lang.get("Tooltip.Help.ZoomIn"));

			// Prevent controller from making changes
			buttonZoomIn.setLocked(true);
			
			// Set Controller
			viewerController.setZoomInButton(buttonZoomIn);
		}
		
		// Return Instance
		return buttonZoomIn;
	}
	// End of getButtonZoomIn Method

	
	/**
	 * This method initialises buttonZoomOut
	 * <p> 
	 * @return javax.swing.JButton
	 */
	private JButton getButtonZoomOut() {
		
		// Check for Existence
		if (buttonZoomOut == null) {
			
			// Create Instance
			buttonZoomOut = new JLockedButton();
			
			// Icon and tool tip
			buttonZoomOut.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-ZoomOut"))));
			buttonZoomOut.setToolTipText(Lang.get("Tooltip.Help.ZoomOut"));

			// Prevent controller from making changes
			buttonZoomOut.setLocked(true);
			
			// Set Controller
			viewerController.setZoomOutButton(buttonZoomOut);
		}
		
		// Return Instance
		return buttonZoomOut;
	}
	// End of buttonZoomOut Method

	
	/**
	 * This method initialises togglePan.
	 * <p>
	 * @return javax.swing.JButton
	 */
	private JToggleButton getTogglePan() {
		
		// Check for Existence
		if (togglePan == null) {
			
			// Create Instance
			togglePan = new JLockedToggleButton();
			
			// Icon and Tool tip
			togglePan.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-Pan"))));
			togglePan.setToolTipText(Lang.get("Tooltip.Help.Pan"));

			// Prevent controller from making changes
			togglePan.setLocked(true);
			
			// Set Controller
			viewerController.setPanToolButton(togglePan);
		}
		
		// Return Instance
		return togglePan;
	}
	// End of getButtonPan Button

	
	/**
	 * This method initialises toggleSelect
	 * <p>
	 * @return javax.swing.JButton
	 */
	private JToggleButton getToggleSelect() {
		
		// Check for Existence
		if (toggleSelect == null) {
			
			// Create Instance
			toggleSelect = new JLockedToggleButton();
			
			// Icon and Tool tip
			toggleSelect.setIcon(new ImageIcon(
					getClass().getResource(
							Lyra.getIconByMap("Help-Select"))));
			toggleSelect.setToolTipText(Lang.get("Tooltip.Help.Select"));

			// Prevent controller from making changes
			toggleSelect.setLocked(true);
			
			// Set Controller
			viewerController.setTextSelectToolButton(toggleSelect);
		}
		
		// Return Instance
		return toggleSelect;
	}
	// End of getButtonSelect Method

	
	/**
	 * Since these elements will be stored for a period of time, it may come in
	 * handy to be able to dispose of their resources once we plan to get rid of
	 * them. Without waiting for the garbage collector to do so.
	 */
	public void closeViewer() {
		
		// Close association with document
		viewerController.closeDocument();

		// Dispose of resources
		viewerController.dispose();
	}
	// End closeViewer Method.


	/**
	 * Name allows to keep a certain amount of state information on exactly what
	 * this viewer is displaying.
	 * <p>
	 * @return String containing name information.
	 */
	public String getName() {
		
		// Return State
		return stateName;
	}
	// End of getName Method.
	
	
	/**
	 * Name allows to keep a certain amount of state information on exactly what
	 * this viewer is displaying.
	 * <p>
	 * @param name String containing name information.
	 */
	public void setName(String name) {
		
		// Pass up
		stateName = name;
	}
	// End of SetName Method.
	
	
	/**
	 * Creates an extension of JButton which prevents user interface changes
	 * when certain controlling items attempt to do so.   A lock can be enabled
	 * when required.
	 * <p>
	 * @author Martin Foster
	 */
	private class JLockedButton extends JButton {
		
		// Serial requirement
		private static final long serialVersionUID = 1L;

		// Locked State
		private boolean myLocked = false;
		
		
		/**
		 * Base constructor class which simply passes it onto super.
		 */
		public JLockedButton() {
			
			// Pass on our responsibility
			super();
		}
		// End of Constructor Method
		
		
		/**
		 * Adjusts the locked state.  When locked adjustment values are ignored
		 * otherwise they are handled normally.
		 * <p>
		 * @param lock Locked state.
		 */
		public void setLocked(boolean lock) {
			
			// Adjust locked state
			myLocked = lock;
		}
		// End of setLocked Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setBorder(javax.swing.border.Border)
		 */
		public void setBorder(Border border) {
			
			// Adjust the border element
			if (!myLocked)
				super.setBorder(border);
		}
		// End of setBorder Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setForeground(java.awt.Color)
		 */
		public void setForeground(Color fg) {
			
			// Adjust the foreground element
			if (!myLocked)
				super.setForeground(fg);
		}
		// End of setForeground Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setBackground(java.awt.Color)
		 */
		public void setBackground(Color bg) {
			
			// Adjust the background element
			if (!myLocked)
				super.setBackground(bg);
		}
		// End of setBackground Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setOpaque(boolean)
		 */
		public void setOpaque(boolean isOpaque) {
			
			// Adjusts opaque value
			if (!myLocked)
				super.setOpaque(isOpaque);
		}
		// End of setOpaque Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setPreferredSize(java.awt.Dimension)
		 */
		public void setPreferredSize(Dimension preferredSize) {
			
			// Adjusts minimum size
			if (!myLocked)
				super.setPreferredSize(preferredSize);
		}
		// End of setMinimimSize Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setMaximumSize(java.awt.Dimension)
		 */
		public void setMaximumSize(Dimension maximumSize) {
			
			// Adjusts maximum size value
			if (!myLocked)
				super.setMaximumSize(maximumSize);
		}
		// End of setMaximumSize Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setMinimumSize(java.awt.Dimension)
		 */
		public void setMinimumSize(Dimension minimumSize) {
			
			// Adjusts minimum size value
			if (!myLocked)
				super.setMinimumSize(minimumSize);
		}
		// End of setMinimumSize Method
	}
	// End of JLockedButton Method
	
	
	
	/**
	 * Creates an extension of JToggleButton which prevents user interface changes
	 * when certain controlling items attempt to do so.   A lock can be enabled
	 * when required.
	 * <p>
	 * @author Martin Foster
	 */
	private class JLockedToggleButton extends JToggleButton {
		
		// Serial requirement
		private static final long serialVersionUID = 1L;

		// Locked State
		private boolean myLocked = false;
		
		
		/**
		 * Base constructor class which simply passes it onto super.
		 */
		public JLockedToggleButton() {
			
			// Pass on our responsibility
			super();
		}
		// End of Constructor Method
		
		
		/**
		 * Adjusts the locked state.  When locked adjustment values are ignored
		 * otherwise they are handled normally.
		 * <p>
		 * @param lock Locked state.
		 */
		public void setLocked(boolean lock) {
			
			// Adjust locked state
			myLocked = lock;
		}
		// End of setLocked Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setBorder(javax.swing.border.Border)
		 */
		public void setBorder(Border border) {
			
			// Adjust the border element
			if (!myLocked)
				super.setBorder(border);
		}
		// End of setBorder Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setForeground(java.awt.Color)
		 */
		public void setForeground(Color fg) {
			
			// Adjust the foreground element
			if (!myLocked)
				super.setForeground(fg);
		}
		// End of setForeground Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setBackground(java.awt.Color)
		 */
		public void setBackground(Color bg) {
			
			// Adjust the background element
			if (!myLocked)
				super.setBackground(bg);
		}
		// End of setBackground Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setOpaque(boolean)
		 */
		public void setOpaque(boolean isOpaque) {
			
			// Adjusts opaque value
			if (!myLocked)
				super.setOpaque(isOpaque);
		}
		// End of setOpaque Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setPreferredSize(java.awt.Dimension)
		 */
		public void setPreferredSize(Dimension preferredSize) {
			
			// Adjusts minimum size
			if (!myLocked)
				super.setPreferredSize(preferredSize);
		}
		// End of setMinimimSize Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setMaximumSize(java.awt.Dimension)
		 */
		public void setMaximumSize(Dimension maximumSize) {
			
			// Adjusts maximum size value
			if (!myLocked)
				super.setMaximumSize(maximumSize);
		}
		// End of setMaximumSize Method
		
		
		/* (non-Javadoc)
		 * @see javax.swing.JComponent#setMinimumSize(java.awt.Dimension)
		 */
		public void setMinimumSize(Dimension minimumSize) {
			
			// Adjusts minimum size value
			if (!myLocked)
				super.setMinimumSize(minimumSize);
		}
		// End of setMinimumSize Method
	}
	// End of JLockedToggleButton Method
}