
package jp.riken.brain.ni.samuraigraph.base;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.MediaTracker;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.swing.AbstractButton;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;


/**
 * A class of the tool bar.
 *
 */
public class SGToolBar extends JToolBar
	implements ActionListener, ComponentListener, MouseListener,
//		PropertyChangeListener,
		SGIRootObjectConstants
{

	// array of filename of icons
	private static final String[] ICON_FILENAME_ARRAY = {
		NEW_WINDOW_ICON_FILENAME,
		DRAW_GRAPH_ICON_FILENAME,
		LOAD_PROPERTY_ICON_FILENAME,
		SAVE_PROPERTY_ICON_FILENAME,
		EXPORT_IMAGE_ICON_FILENAME,
		PRINT_ICON_FILENAME,
		UNDO_ICON_FILENAME,
		REDO_ICON_FILENAME,
		CUT_ICON_FILENAME,
		COPY_ICON_FILENAME,
		PASTE_ICON_FILENAME,
		INSERT_LABEL_ICON_FILENAME,
		INSERT_SIGDIFF_ICON_FILENAME,
		INSERT_BREAK_ICON_FILENAME,
		INSERT_TIMING_ICON_FILENAME,
		BOUNDING_BOX_ICON_FILENAME,
		LOCK_ICON_FILENAME,
		UNLOCK_ICON_FILENAME,
		HELP_ICON_FILENAME
	};


	// array of commands
	private static final String[] COMMANDS_ARRAY = {
		MENUBARCMD_CREATE_NEW_WINDOW,
		MENUBARCMD_DRAW_GRAPH,
		MENUBARCMD_LOAD_PROPERTY,
		MENUBARCMD_SAVE_PROPERTY,
		MENUBARCMD_EXPORT_AS_IMAGE,
		MENUBARCMD_PRINT,
		MENUBARCMD_UNDO,
		MENUBARCMD_REDO,
		MENUBARCMD_CUT,
		MENUBARCMD_COPY,
		MENUBARCMD_PASTE,
		MENUBARCMD_INSERT_LABEL,
		MENUBARCMD_INSERT_SIG_DIFF_SYMBOL,
		MENUBARCMD_INSERT_AXIS_BREAK_SYMBOL,
		MENUBARCMD_INSERT_TIMING_LINE,
		MENUBARCMD_BOUNDING_BOX,
		MENUBARCMD_LOCK,
		MENUBARCMD_LOCK,
		MENUBARCMD_HELP
	};



	/**
	 * Buttons.
	 */
	private ToolBarButton mCreateNewWindowButton;
	private ToolBarButton mDrawGraphButton;
	private ToolBarButton mLoadPropertyButton;
	private ToolBarButton mSavePropertyButton;
	private ToolBarButton mExportFormatButton;
	private ToolBarButton mPrintButton;
	private ToolBarButton mUndoButton;
	private ToolBarButton mRedoButton;
	private ToolBarButton mCutButton;
	private ToolBarButton mCopyButton;
	private ToolBarButton mPasteButton;
	private ToolBarToggleButton mInsertBreakButton;
	private ToolBarButton mBoundingBoxButton;
	private ToolBarToggleButton mInsertLabelButton;
	private ToolBarToggleButton mInsertTimingLineButton;
	private ToolBarToggleButton mInsertSignificantDifferenceSymbolButton;
	private ToolBarToggleButton mLockFigureButton;
	private ToolBarButton mHelpButton;


	/**
	 * Tool Bars.
	 */
	private JToolBar mFileToolBar;
	private JToolBar mEditToolBar;
	private JToolBar mInsertToolBar;
	private JToolBar mLayoutToolBar;
//	private JToolBar mHelpToolBar;
	private JToolBar mZoomToolBar;

	/**
	 * Tool Bars Title.
	 */
	private static final String FILE_TOOLBAR_TITLE   = "File";
	private static final String EDIT_TOOLBAR_TITLE   = "Edit";
	private static final String INSERT_TOOLBAR_TITLE = "Insert";
	private static final String LAYOUT_TOOLBAR_TITLE = "Layout";
	private static final String HELP_TOOLBAR_TITLE   = "Help";
	private static final String ZOOM_TOOLBAR_TITLE   = "Zoom";


	/**
	 * A combo box to set the magnification.
	 */
	private SGZoomComboBox mZoomComboBox;


	/**
	 * The root object.
	 */
	private SGIRootObject mRoot;


	/**
	 * A popup menu.
	 */
	private JPopupMenu mPopupMenu = new JPopupMenu();


	/**
	 * Default constructor.
	 *
	 */
	public SGToolBar()
	{
		super();

		this.create();
	}


	/**
	 * A constructor setting the root object.
	 *
	 */
	public SGToolBar( SGIRootObject root )
	{
		super();
		
		this.setRoot( root );

		this.create();
	}


	// create all objects in the tool bar.
	private boolean create()
	{

		// array of filename
		final String[] filenameArray = ICON_FILENAME_ARRAY;
		final int num = filenameArray.length;


		//
		// create icon array
		//

		ImageIcon[] icons = new ImageIcon[num];
		for( int ii=0; ii<num; ii++ )
		{
			icons[ii] = this.createIcon( filenameArray[ii] );
		}
		MediaTracker mt = new MediaTracker(this);
		for( int ii=0; ii<num; ii++ )
		{
			mt.addImage( icons[ii].getImage(), ii );
		}
		try
		{
			mt.waitForAll();
		}
		catch( InterruptedException e )
		{
			e.printStackTrace();
		}


		// a map of file name and icon
		HashMap map = new HashMap();
		for( int ii=0; ii<num; ii++ )
		{
			map.put( filenameArray[ii], icons[ii] );
		}



		//
		// create buttons
		//

		this.mCreateNewWindowButton
			= this.createButton( map, NEW_WINDOW_ICON_FILENAME, TIP_CREATE_NEW_WINDOW );

		this.mDrawGraphButton
			= this.createButton( map, DRAW_GRAPH_ICON_FILENAME, TIP_DRAW_GRAPH );

		this.mLoadPropertyButton
			= this.createButton( map, LOAD_PROPERTY_ICON_FILENAME, TIP_LOAD_PROPERTY );

		this.mSavePropertyButton
			= this.createButton( map, SAVE_PROPERTY_ICON_FILENAME, TIP_SAVE_PROPERTY );

		this.mExportFormatButton
			= this.createButton( map, EXPORT_IMAGE_ICON_FILENAME, TIP_EXPORT_FORMAT );

		this.mPrintButton
			= this.createButton( map, PRINT_ICON_FILENAME, TIP_PRINT );

		this.mUndoButton
			= this.createButton( map, UNDO_ICON_FILENAME, TIP_UNDO );

		this.mRedoButton
			= this.createButton( map, REDO_ICON_FILENAME, TIP_REDO );

		this.mCutButton
			= this.createButton( map, CUT_ICON_FILENAME, TIP_CUT );

		this.mCopyButton
			= this.createButton( map, COPY_ICON_FILENAME, TIP_COPY );

		this.mPasteButton
			= this.createButton( map, PASTE_ICON_FILENAME, TIP_PASTE );

		this.mInsertLabelButton
			= this.createToggleButton( map, INSERT_LABEL_ICON_FILENAME, TIP_INSERT_LABEL );

		this.mInsertSignificantDifferenceSymbolButton
			= this.createToggleButton( map, INSERT_SIGDIFF_ICON_FILENAME, TIP_INSERT_SIG_DIFF_SYMBOL );

		this.mInsertBreakButton
			= this.createToggleButton( map, INSERT_BREAK_ICON_FILENAME, TIP_INSERT_AXIS_BREAK_SYMBOL );

		this.mInsertTimingLineButton
			= this.createToggleButton( map, INSERT_TIMING_ICON_FILENAME, TIP_INSERT_TIMING_LINE );

		this.mBoundingBoxButton
			= this.createButton( map, BOUNDING_BOX_ICON_FILENAME, TIP_BOUNDING_BOX );

		this.mLockFigureButton
			= this.createToggleButton( map, UNLOCK_ICON_FILENAME, TIP_LOCK );

		this.mHelpButton
			= this.createButton( map, HELP_ICON_FILENAME, TIP_HELP );


		// add insert buttons to an original button group
		SGButtonGroup bg = new SGButtonGroup();
		bg.add( this.mInsertBreakButton );
		bg.add( this.mInsertLabelButton );
		bg.add( this.mInsertSignificantDifferenceSymbolButton );
		bg.add( this.mInsertTimingLineButton );
		bg.add( new JToggleButton() );



		// create a combo box for zoom
		this.mZoomComboBox = new SGZoomComboBox();


		//
		String laf = SGUtility.getLookAndFeelID();
		if( LAF_WINDOWS.equals(laf) )
		{
			this.setRollover(true);
		}

//		this.setLayout( new FlowLayout( FlowLayout.LEFT ) );
		this.setLayout( new BoxLayout( this, BoxLayout.X_AXIS ) );
//		this.setBorder( new javax.swing.border.EtchedBorder(javax.swing.border.EtchedBorder.LOWERED) );
		this.setOrientation( JToolBar.HORIZONTAL );
		this.setFloatable( false );


		// add components
		JToolBar barFile = new JToolBar( FILE_TOOLBAR_TITLE );
		barFile.add(this.mCreateNewWindowButton);
		barFile.add(this.mDrawGraphButton);
		barFile.add(this.mLoadPropertyButton);
		barFile.add(this.mSavePropertyButton);
		barFile.add(this.mExportFormatButton);
		barFile.add(this.mPrintButton);
		this.mFileToolBar = barFile;

		JToolBar barEdit = new JToolBar( EDIT_TOOLBAR_TITLE );
		barEdit.add(this.mUndoButton);
		barEdit.add(this.mRedoButton);
		barEdit.add(this.mCutButton);
		barEdit.add(this.mCopyButton);
		barEdit.add(this.mPasteButton);
		this.mEditToolBar = barEdit;

		JToolBar barInsert = new JToolBar( INSERT_TOOLBAR_TITLE );
		barInsert.add(this.mInsertLabelButton);
		barInsert.add(this.mInsertSignificantDifferenceSymbolButton);
		barInsert.add(this.mInsertBreakButton);
		barInsert.add(this.mInsertTimingLineButton);
		this.mInsertToolBar = barInsert;

		JToolBar barLayout = new JToolBar( LAYOUT_TOOLBAR_TITLE );
		barLayout.add(this.mBoundingBoxButton);
		barLayout.add(this.mLockFigureButton);
		this.mLayoutToolBar = barLayout;

		JToolBar barHelp = new JToolBar( HELP_TOOLBAR_TITLE );
		barHelp.add(this.mHelpButton);
//		this.mHelpToolBar = barHelp;

		JToolBar barZoom = new JToolBar( ZOOM_TOOLBAR_TITLE );
		JPanel panel = new JPanel();
//		panel.setLayout( new BorderLayout( BorderLayout.CENTER ) );
		panel.setPreferredSize( new Dimension(132, this.mBoundingBoxButton.getPreferredSize().height ) );
		panel.setMaximumSize( panel.getPreferredSize() );
		panel.setMinimumSize( panel.getPreferredSize() );

//		panel.setBorder( new EtchedBorder() );
		panel.add( mZoomComboBox, BorderLayout.CENTER );
		barZoom.add(panel);
		this.mZoomToolBar = barZoom;

		if( LAF_WINDOWS.equals(laf) )
		{
			barFile.setRollover(true);
			barEdit.setRollover(true);
			barInsert.setRollover(true);
			barLayout.setRollover(true);
			barHelp.setRollover(true);
			barZoom.setRollover(true);
		}

		AbstractButton btn = new JToggleButton("..");
		btn.addActionListener( this );
		this.mButton = btn;

		this.add( barFile );
		this.add( barEdit );
		this.add( barInsert );
		this.add( barLayout );
//		this.add( barHelp );
		this.add( barZoom );

//		this.add( btn );


//		this.setPreferredSize(
//			new Dimension( this.getWidth(), this.getHeight() ) );
//		this.setSize( this.getPreferredSize() );


		//
//		barFile.addPropertyChangeListener( this );
//		barEdit.addPropertyChangeListener( this );
//		barInsert.addPropertyChangeListener( this );
//		barArrange.addPropertyChangeListener( this );
//		barHelp.addPropertyChangeListener( this );
//		barZoom.addPropertyChangeListener( this );

		//
		this.createButtonMap();
		this.createToolBarMap();

		// add itself as a mouse listener
		this.addMouseListener( this );


		// create the popup menu
		this.createPopupMenu();


		return true;
	}


	private AbstractButton mButton;


	private static final String TOOL_BARS_VISIBLE = "Visible";


//	private void createPopupMenu()
//	{
//		JPopupMenu p = this.mPopupMenu;
//		p.setBounds( 0, 0, 100, 100 );
//
//		p.add( new JLabel( "  -- Tool Bar --" ) );
//		p.addSeparator();
//
//		// commands
//		JMenu visibleMenu = new JMenu( TOOL_BARS_VISIBLE );
//		String[] commands = TOOLBAR_MENUCMD_ARRAY;
//		for( int ii=0; ii<commands.length; ii++ )
//		{
//			JCheckBoxMenuItem item = new JCheckBoxMenuItem( commands[ii] );
//			item.addActionListener( this );
//			visibleMenu.add( item );
//		}
//
//		p.add( visibleMenu );
//	}


	private void createPopupMenu()
	{
		JPopupMenu p = this.mPopupMenu;
		p.setBounds( 0, 0, 100, 100 );

		p.add( new JLabel( "  -- Tool Bar --" ) );
		p.addSeparator();

		// commands
		String[] commands = TOOLBAR_MENUCMD_ARRAY;
		for( int ii=0; ii<commands.length; ii++ )
		{
			JCheckBoxMenuItem item = new JCheckBoxMenuItem( commands[ii] );
			item.addActionListener( this );
			p.add( item );
		}
	}


	private ToolBarButton createButton( Map map, String filename, String tip )
	{
		ImageIcon icon = (ImageIcon)map.get(filename);
		ToolBarButton b = new ToolBarButton( icon );
		b.setToolTipText( tip );
		b.addActionListener( this );
		return b;
	}


	private ToolBarToggleButton createToggleButton( Map map, String filename, String tip )
	{
		ImageIcon icon = (ImageIcon)map.get(filename);
		ToolBarToggleButton b = new ToolBarToggleButton( icon );
		b.setToolTipText( tip );
		b.addActionListener( this );
		return b;
	}



	/**
	 * Create an icon object.
	 * @param name - name of resource file
	 */
	private ImageIcon createIcon( final String name )
	{
		URL url = this.getClass().getResource( RESOURCES_DIRNAME + name );
		ImageIcon icon = new ImageIcon(url);
		return icon;
	}


	/**
	 * 
	 * @param obj
	 */
	public void setRoot( SGIRootObject obj )
	{
		this.mRoot = obj;
		this.mZoomComboBox.addZoomable( obj );
	}



	//
	// action event
	//


	/**
	 * 
	 */
	private ArrayList mActionListenerList = new ArrayList();



	/**
	 * 
	 */
	public void addActionListener( final ActionListener listener )
	{
		this.mActionListenerList.add( listener );
	}



	/**
	 * 
	 */
	public void removeActionListener( ActionListener listener )
	{
		this.mActionListenerList.remove( listener );
	}



	/**
	 * 
	 */
	public void notifyToListener( final String command )
	{
		ActionEvent e = new ActionEvent( this, 0, command );
		this.notifyToListener(e);
	}


	/**
	 * 
	 */
	public void notifyToListener( final ActionEvent e )
	{
		ArrayList list = this.mActionListenerList;
		for( int ii=0; ii<list.size(); ii++ )
		{
			final ActionListener el = (ActionListener)list.get(ii);
			el.actionPerformed(e);
		}
	}


	/**
	 * Returns an array of buttons.
	 */
	private IToolBarButton[] getButtonArray()
	{
		IToolBarButton[] bArray = {
			this.mCreateNewWindowButton,
			this.mDrawGraphButton,
			this.mLoadPropertyButton,
			this.mSavePropertyButton,
			this.mExportFormatButton,
			this.mPrintButton,
			this.mUndoButton,
			this.mRedoButton,
			this.mCutButton,
			this.mCopyButton,
			this.mPasteButton,
			this.mInsertLabelButton,
			this.mInsertSignificantDifferenceSymbolButton,
			this.mInsertBreakButton,
			this.mInsertTimingLineButton,
			this.mBoundingBoxButton,
			this.mLockFigureButton,
			this.mLockFigureButton,
			this.mHelpButton
		};

		return bArray;
	}


	private IToolBarButton getButton( String com )
	{
		IToolBarButton[] bArray = this.getButtonArray();
		for( int ii=0; ii<bArray.length; ii++ )
		{
			String com_ = bArray[ii].getCommand();
			if( com_.equals(com) )
			{
				return bArray[ii];
			}
		}
		
		return null;
	}



	private void createButtonMap()
	{
		// commands
		String[] commands = COMMANDS_ARRAY;

		IToolBarButton[] bArray = this.getButtonArray();

		final int num = commands.length;
		for( int ii=0; ii<num; ii++ )
		{
			bArray[ii].setCommand( commands[ii] );
		}
	}



	private void createToolBarMap()
	{

		// commands
		String[] commands = TOOLBAR_MENUCMD_ARRAY;

		JToolBar[] tArray = {
			this.mFileToolBar,
			this.mEditToolBar,
			this.mInsertToolBar,
			this.mLayoutToolBar,
//			this.mHelpToolBar,
			this.mZoomToolBar
		};

		final int num = commands.length;

		HashMap map = new HashMap();
		for( int ii=0; ii<num; ii++ )
		{
			map.put( commands[ii], tArray[ii] );
		}

		this.mToolBarMap = map;
	}


	/**
	 * 
	 */
	private Map mToolBarMap;



	/**
	 * 
	 */
	public void actionPerformed( ActionEvent e )
	{
		Object source = e.getSource();
		String command = e.getActionCommand();

//System.out.println(command);
//System.out.println(e);
//System.out.println();

		// from the popup menu
		if( Arrays.asList( TOOLBAR_MENUCMD_ARRAY ).contains( command ) )
		{
			// set buttons visibility
			this.setToolBarVisible( command, !this.isToolBarVisible( command ) );

			// throw a PropertyChangeEvent
//			this.propertyChange( new PropertyChangeEvent( this, command, null, null ) );

			this.mButton.setSelected(false);

		}


//		// from the button
//		if( source.equals( this.mButton ) )
//		{
//			if( this.mButton.isSelected() )
//			{
//				final int x = this.mButton.getX();
//				final int y = this.mButton.getY() + this.mButton.getHeight();
//				this.showPopupMenu( x, y );
//			}
//		}


		// from the lock button
		if( source.equals( this.mLockFigureButton ) )
		{
			this.setButtonSelected( MENUBARCMD_LOCK, this.mLockFigureButton.isSelected() );
		}


		// notify the command to listeners
		if( source instanceof IToolBarButton )
		{
			IToolBarButton b = (IToolBarButton)source;
			String com = b.getCommand();

			IToolBarButton[] array = this.getButtonArray();
			for( int ii=0; ii<array.length; ii++ )
			{
				String com_ = array[ii].getCommand();
				if( com_.equals( com ) )
				{
					this.notifyToListener(com);
					break;
				}
			}
			
		}


		// throw an action event
		ArrayList lList = this.mActionListenerList;
		for( int ii=0; ii<lList.size(); ii++ )
		{
			ActionListener l = (ActionListener)lList.get(ii);
			l.actionPerformed( new ActionEvent( this, e.getID(), command, e.getModifiers() ) );
		}


		// clear focus in the tool bar
		SGUtility.clearGlobalFocusOwner();
	}



	/**
	 * 
	 * @param command
	 * @return
	 */
	public boolean isButtonEnabled( final String command )
	{
		Object obj = this.getButton( command );
		if( obj==null )
		{
			throw new IllegalArgumentException("obj==null");
		}
		AbstractButton btn = (AbstractButton)obj;
		return btn.isEnabled();
	}


	/**
	 * 
	 * @param command
	 * @param b
	 */
	public void setButtonEnabled( final String command, final boolean b )
	{
		Object obj = this.getButton( command );
		if( obj==null )
		{
			throw new IllegalArgumentException("obj==null");
		}
		AbstractButton btn = (AbstractButton)obj;
		btn.setEnabled(b);
	}



	/**
	 * 
	 * @param command
	 * @return
	 */
	public boolean isButtonSelected( final String command )
	{
		Object obj = this.getButton( command );
		if( obj==null )
		{
			throw new IllegalArgumentException("obj==null");
		}
		AbstractButton btn = (AbstractButton)obj;
		return btn.isSelected();
	}


	/**
	 * 
	 * @param command
	 * @param b
	 */
	public void setButtonSelected( final String command, final boolean b )
	{
		Object obj = this.getButton( command );
		if( obj==null )
		{
			throw new IllegalArgumentException("obj==null");
		}
		AbstractButton btn = (AbstractButton)obj;
		btn.setSelected(b);

		if( command.equals( MENUBARCMD_LOCK ) )
		{
			this.setLockButtonIcon(b);
		}
	}


	/**
	 * 
	 * @return
	 */
	public boolean isInsertToggleButtonSelected()
	{
		final ArrayList list = this.getInsertToggleButtonList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			final AbstractButton btn = (AbstractButton)list.get(ii);
			if( btn.isSelected() )
			{
				return true;
			}
		}
		return false;
	}


	/**
	 * 
	 */
	public void setInsertToggleButtonsEnabled(
		final  boolean flag )
	{
		final ArrayList btnList = this.getInsertToggleButtonList();
		for( int ii=0; ii<btnList.size(); ii++ )
		{
			final AbstractButton btn = (AbstractButton)btnList.get(ii);
			btn.setEnabled( flag );
		}
	}


	/**
	 * 
	 */
	public void setInsertToggleItemsUnSelected()
	{
		final ArrayList btnList = this.getInsertToggleButtonList();
		for( int ii=0; ii<btnList.size(); ii++ )
		{
			final AbstractButton btn = (AbstractButton)btnList.get(ii);
			btn.setSelected( false );
		}
	}


	/**
	 * 
	 */
	private ArrayList getInsertToggleButtonList()
	{
		final ArrayList list = new ArrayList(
			Arrays.asList( this.getInsertToggleButtonArray() ) );
		return list;
	}



	/**
	 * 
	 * @return
	 */
	private JToggleButton[] getInsertToggleButtonArray()
	{
		JToggleButton[] array = {
			this.mInsertLabelButton, this.mInsertSignificantDifferenceSymbolButton,
			this.mInsertBreakButton, this.mInsertTimingLineButton
		};

		return array;
	}


	/**
	 * 
	 * @param command
	 * @return
	 */
	public boolean hasButton( final String command )
	{
		Object obj = this.getButton( command );
		return (obj!=null);
	}


	/**
	 * 
	 * @param command
	 * @param b
	 */
	public void setInsertTogglebuttonSelected( final String command, final boolean b )
	{
		Object obj = this.getButton( command );
		if( obj!=null )
		{
			AbstractButton btn = (AbstractButton)obj;
			btn.setSelected(b);
		}
		else
		{
			throw new IllegalArgumentException();
		}
	}


	/**
	 * 
	 * @param command
	 */
	public boolean isInsertTogglebuttonSelected( final String command )
	{
		Object obj = this.getButton( command );
		if( obj!=null )
		{
			AbstractButton btn = (AbstractButton)obj;
			return btn.isSelected();
		}
		else
		{
			throw new IllegalArgumentException();
		}
	}



	/**
	 * 
	 */
	private void setLockButtonIcon( final boolean flag )
	{

		ImageIcon iconLock;
		if( flag )
		{
			iconLock = this.createIcon( LOCK_ICON_FILENAME );
		}
		else
		{
			iconLock = this.createIcon( UNLOCK_ICON_FILENAME );
		}

		this.mLockFigureButton.setIcon( iconLock );
	}



	/**
	 * 
	 * @param command
	 * @param b
	 */
	public void setToolBarVisible( final String command, final boolean b )
	{
		Object obj = this.mToolBarMap.get(command);
		if( obj==null )
		{
			throw new IllegalArgumentException("obj==null");
		}
		JToolBar tb = (JToolBar)obj;
		tb.setVisible(b);
		
		// update the bounds
		this.updateBounds();
		
		this.updatePopupMenu();
	}



	/**
	 * 
	 * @param command
	 * @return
	 */
	public boolean isToolBarVisible( final String command )
	{
		Object obj = this.mToolBarMap.get(command);
		if( obj==null )
		{
			throw new IllegalArgumentException("obj==null");
		}
		JToolBar tb = (JToolBar)obj;
		return tb.isVisible();
	}



	private JToolBar[] getToolBarArray()
	{
		Component[] com = this.getComponents();

		ArrayList list = new ArrayList();
		for( int ii=0; ii<com.length; ii++ )
		{
			if( com[ii] instanceof JToolBar )
			{
				list.add( com[ii] );
			}
		}

		JToolBar[] array = new JToolBar[list.size()];
		for( int ii=0; ii<array.length; ii++ )
		{
			array[ii] = (JToolBar)list.get(ii);
		}

		return array;
	}


	/**
	 * Returns an array of keys of inner tool bars.
	 * @return an array of keys of inner tool bars.
	 */
	public String[] getToolBarPattern()
	{
		Component[] com = this.getToolBarArray();
		String[] keys = TOOLBAR_MENUCMD_ARRAY;
		Map map = this.mToolBarMap;

		ArrayList keyList = new ArrayList();
		for( int ii=0; ii<com.length; ii++ )
		{
			if( !com[ii].isVisible() )
			{
				continue;
			}
			
			for( int jj=0; ii<keys.length; jj++ )
			{
				Object value = map.get( keys[jj] );
				if( com[ii].equals( value ) )
				{
					keyList.add( keys[jj] );
					break;
				}
			}
		}
		
		String[] array = new String[keyList.size()];
		for( int ii=0; ii<array.length; ii++ )
		{
			array[ii] = (String)keyList.get(ii);
		}
		
		return array;
	}



	/**
	 * Set visible inner tool bars.
	 * @param pattern - an array of keys of visible tool bars.
	 */
	public void setToolBarPattern( final String[] pattern )
	{
		if( pattern==null )
		{
			throw new IllegalArgumentException("pattern==null");
		}

		ArrayList visibleList = new ArrayList();
		for( int ii=0; ii<pattern.length; ii++ )
		{
			final String key = pattern[ii];
			visibleList.add(key);
		}

		Map map = this.mToolBarMap;
		String[] keys = TOOLBAR_MENUCMD_ARRAY;
		for( int ii=0; ii<keys.length; ii++ )
		{
			final boolean visible = (visibleList.contains(keys[ii]));
			JToolBar bar = (JToolBar)map.get(keys[ii]);
			bar.setVisible(visible);
		}

	}



	/**
	 * コンポーネントが可視になると呼び出されます。 
	 */
	public void componentShown(final ComponentEvent e)
	{
	}


	/**
	 * コンポーネントが不可視になると呼び出されます。 
	 */
	public void componentHidden(final ComponentEvent e){}


	/**
	 * コンポーネントの位置が変わると呼び出されます。 
	 */
	public void componentMoved(final ComponentEvent e)
	{
	}


	/**
	 * コンポーネントのサイズが変わると呼び出されます。 
	 */
	public void componentResized(final ComponentEvent e)
	{
		this.updateBounds();
	}



//	/**
//	 * 
//	 */
//	public void propertyChange( PropertyChangeEvent evt )
//	{
//		PropertyChangeEvent e = new PropertyChangeEvent(
//			this, evt.getPropertyName(), evt.getOldValue(), evt.getNewValue() );
//		PropertyChangeListener[] array = this.getPropertyChangeListeners();
//		for( int ii=0; ii<array.length; ii++ )
//		{
//			array[ii].propertyChange(e);
//		}
//System.out.println(evt);
//		this.updateBounds();
//	}


	/**
	 * Update the bounds with the parent.
	 *
	 */
	private void updateBounds()
	{

		JToolBar[] array = this.getToolBarArray();

//		int cnt = 0;
//		if( array.length!=0 )
//		{
//			for( int ii=0; ii<array.length; ii++ )
//			{
//				if( array[ii].isVisible() )
//				{
//					cnt = 1;
//					break;
//				}
//			}
//		}

		ArrayList tList = new ArrayList();
		ArrayList pList = new ArrayList();
		int num = array.length;
		int x = 0;
		for( int ii=0; ii<array.length; ii++ )
		{
			if( array[ii].isVisible() == false )
			{
				continue;
			}

			final int width = array[ii].getPreferredSize().width;
			x += width;
			if( x > this.getWidth() )
			{
				num = ii;
				break;
			}
		}


		for( int ii=0; ii<num; ii++ )
		{
			if( array[ii].isVisible() == false )
			{
				continue;
			}
			tList.add( array[ii] );
		}
		for( int ii=num; ii<array.length; ii++ )
		{
			if( array[ii].isVisible() == false )
			{
				continue;
			}
			pList.add( array[ii] );
		}

//System.out.println(tList.size());
//System.out.println(pList.size());
//System.out.println();

//		for( int ii=0; ii<tList.size(); ii++ )
//		{
//			JToolBar bar = (JToolBar)tList.get(ii);
//			this.removeToolBarFromPopupMenu( bar );
//		}
//		for( int ii=0; ii<pList.size(); ii++ )
//		{
//			JToolBar bar = (JToolBar)pList.get(ii);
//			this.addToolBarToPopupMenu( bar );
//		}

	}



//	private static final int BASE_HEIGHT = 39;



	//
	// for zooming
	//


	/**
	 * 
	 */
	public void setZoomValue( final Number mag )
	{
		if( mag==null )
		{
			return;
		}
		this.mZoomComboBox.setZoomValue( mag );
	}




	/**
	 * 
	 */
	public void mouseClicked(final MouseEvent e)
	{

		if( e.getClickCount() == 1 )
		{
			if( SwingUtilities.isRightMouseButton(e) )
			{
				this.showPopupMenu( e.getX(), e.getY() );
			}
			else if( SwingUtilities.isLeftMouseButton(e) )
			{
				this.mButton.setSelected( false );
			}
		}
		
	}


	private void showPopupMenu( final int x, final int y )
	{
		this.mPopupMenu.show( this, x, y );
	}


	// update the menu items
//	private void updatePopupMenu()
//	{
//		Map map = this.mToolBarMap;
//		Component[] array = this.mPopupMenu.getComponents();
//		for( int ii=0; ii<array.length; ii++ )
//		{
//			if( array[ii] instanceof JMenu )
//			{
//				JMenu menu = (JMenu)array[ii];
//				final int count = menu.getItemCount();
//				for( int jj=0; jj<count; jj++ )
//				{
//					JMenuItem item = menu.getItem(jj);
//					String command = item.getActionCommand();
//					JToolBar bar = (JToolBar)map.get(command);
//					item.setSelected( bar.isVisible() );
//				}
//			}
//		}
//	}

	private void updatePopupMenu()
	{
		Map map = this.mToolBarMap;
		Component[] array = this.mPopupMenu.getComponents();
		for( int ii=0; ii<array.length; ii++ )
		{
			if( array[ii] instanceof JMenuItem )
			{
				JMenuItem item = (JMenuItem)array[ii];
				String command = item.getActionCommand();
				JToolBar bar = (JToolBar)map.get(command);
				item.setSelected( bar.isVisible() );
			}
		}
	}


	private void addToolBarToPopupMenu( JToolBar bar )
	{
		JPopupMenu p = this.mPopupMenu;
		int index = 1;
		Component[] array = p.getComponents();
		for( int ii=array.length-1; ii>=0; ii-- )
		{
			if( array[ii] instanceof JToolBar )
			{
				index = ii;
				break;
			}
		}
		p.add( bar, index );
		this.remove( bar );

		this.validate();
		p.validate();
	}


	private void removeToolBarFromPopupMenu( JToolBar bar )
	{
		JPopupMenu p = this.mPopupMenu;
		p.remove(bar);
		this.add( bar );
		
		this.validate();
		p.validate();
	}


	public void mouseEntered(final MouseEvent e){}

	public void mouseExited(final MouseEvent e){}

	public void mousePressed( final MouseEvent e )
	{
		// clear focus in the tool bar
		SGUtility.clearGlobalFocusOwner();
	}

	public void mouseReleased(final MouseEvent e){}




	/**
	 * Inner interface for buttons which holds command string.
	 */
	private interface IToolBarButton
	{
		public void setCommand( String com );
		public String getCommand();
	}


	/**
	 * An inner button class with commmand string.
	 */
	private class ToolBarButton extends JButton implements IToolBarButton
	{
		private String mCommand;
		
		ToolBarButton( Icon icon )
		{
			super(icon);
		}

		public void setCommand( String com )
		{
			this.mCommand = com;
		}

		public String getCommand()
		{
			return this.mCommand;
		}
	}


	/**
	 * An inner toggle button class with commmand string.
	 */
	private class ToolBarToggleButton extends JToggleButton implements IToolBarButton
	{
		private String mCommand;

		ToolBarToggleButton( Icon icon )
		{
			super(icon);
		}

		public void setCommand( String com )
		{
			this.mCommand = com;
		}

		public String getCommand()
		{
			return this.mCommand;
		}
	}


}

