/*
* Copyright 2003-2010 Tufts University  Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 * 
 * http://www.osedu.org/licenses/ECL-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
package tufts.vue.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;

import tufts.Util;
import tufts.vue.Actions;
import tufts.vue.ActiveInstance;
import tufts.vue.DEBUG;
import tufts.vue.Images;
import tufts.vue.JavaAnalysisPanel;
import tufts.vue.LWComponent;
import tufts.vue.LWImage;
import tufts.vue.LWLink;
import tufts.vue.LWMap;
import tufts.vue.LWNode;
import tufts.vue.LWPathway;
import tufts.vue.LWPathwayList;
import tufts.vue.LWPortal;
import tufts.vue.LWSelection;
import tufts.vue.LWText;
import tufts.vue.LayoutAction;
import tufts.vue.MapTabbedPane;
import tufts.vue.MapViewer;
import tufts.vue.PresentationTool;
import tufts.vue.RecentlyOpenedFilesManager;
import tufts.vue.Resource;
import tufts.vue.VUE;
import tufts.vue.VueAction;
import tufts.vue.VueApplet;
import tufts.vue.VueConstants;
import tufts.vue.VueResources;
import tufts.vue.VueTool;
import tufts.vue.VueToolbarController;
import tufts.vue.VueUtil;
import tufts.vue.action.AboutAction;
import tufts.vue.action.AnalyzeCM;
import tufts.vue.action.CreateCM;
import tufts.vue.action.ExitAction;
import tufts.vue.action.OpenAction;
import tufts.vue.action.OpenURLAction;
import tufts.vue.action.PrintAction;
import tufts.vue.action.PublishActionFactory;
import tufts.vue.action.SaveAction;
import tufts.vue.action.ShortcutsAction;
import tufts.vue.action.ShowURLAction;
import edu.tufts.vue.dataset.QuickImportAction;
import edu.tufts.vue.dsm.impl.VueDataSourceManager;
import edu.tufts.vue.ontology.action.OntologyControlsOpenAction;
import edu.tufts.vue.ontology.ui.OntologyBrowser;
import edu.tufts.vue.preferences.VuePrefEvent;
import edu.tufts.vue.preferences.VuePrefListener;
import edu.tufts.vue.preferences.implementations.BooleanPreference;

/**
 * The main VUE application menu bar.
 *
 * @version $Revision: 1.176 $ / $Date: 2010-03-11 21:15:01 $ / $Author: mike $
 * @author Scott Fraize
 */
public class VueMenuBar extends javax.swing.JMenuBar
    implements java.awt.event.FocusListener
{
    private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(VueMenuBar.class);
    
    public static VueMenuBar RootMenuBar;
    private static JCheckBoxMenuItem fullScreenToolbarItem = null;
    public static SaveAction saveAction = null;
    public static SaveAction saveAsAction = null;
    public static JMenu importMenu = null;
    public static JMenu publishMenu = null;
    public static PrintAction printAction  = null;
    public static JMenu pdfExportMenu = null;
    public static JMenu transformMenu = null;
    public static JMenu arrangeMenu = null;
    public static JMenu alignMenu = null;
    public static JMenu layoutMenu = null;
    public static JMenu linkMenu = null;
    public static JMenu playbackMenu = null;
    public boolean isMenuEnableFontFlg = false;
    // this may be created multiple times as a workaround for the inability
    // to support a single JMenuBar for the whole application on the Mac
/*    public VueMenuBar()
    {
        this(VUE.ToolWindows);
    }
*/
    /*
      public void paint(Graphics g) {
      System.err.println("\nVueMenuBar: paint");

      }
    */

    private static class VueMenu extends JMenu {
        private boolean unadjusted = true;
        
        VueMenu(String name) {
            super(name);
            
            /* on the mac this works fine on windows the menus paint behind the dockwindows
             * so we'll install our own UI which creates heavyweight popups.
             */
            if (Util.isWindowsPlatform() ||Util.isUnixPlatform())
            	this.getPopupMenu().setUI(new VuePopupMenuUI());
            
                       
        }

        @Override
        public void addNotify() {
            if (unadjusted) {
                GUI.adjustMenuIcons(this);
                unadjusted = false;
            }
            super.addNotify();
        }

//         @Override
//         protected JMenuItem createActionComponent(Action a) {

//             JMenuItem mi;

//             if (false && a == Actions.ToggleAutoZoom) {
//                 mi = new JCheckBoxMenuItem((String)a.getValue(Action.NAME), (Icon)a.getValue(Action.SMALL_ICON));
//             } else {
//                 //mi = new JMenuItem((String)a.getValue(Action.NAME), (Icon)a.getValue(Action.SMALL_ICON));
//                 mi = new JMenuItem(a);
                
// //                     protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
// //                         PropertyChangeListener pcl = createActionChangeListener(this);
// //                         if (pcl == null) {
// //                             pcl = super.createActionPropertyChangeListener(a);
// //                         }
// //                         return pcl;
// //                     }
// //                 };
//             }
//             mi.setHorizontalTextPosition(JButton.TRAILING);
//             mi.setVerticalTextPosition(JButton.CENTER);
//             mi.setEnabled(a.isEnabled());   
//             return mi;
//         }
        
    }

    private static JMenu makeMenu(String name) {
        return new VueMenu(name);
        
//         if (Util.isMacPlatform())
//             return new JMenu(name);
//         else
//             return new VueMenu(name);
    }


//     private static class MenuToggleItem extends JCheckBoxMenuItem
//     {
//         MenuToggleItem(VueAction va) {
//             super(va);
//             va.trackToggler(this);
//         }
// //         @Override
// //         public final void setSelected(boolean selected) {
// //             if (DEBUG.EVENTS) Log.debug(GUI.name(this) + "; setSelected " + selected + " (isSelected=" + isSelected() + ")");
// //             super.setSelected(selected);
// //         }
//     }

    private static JCheckBoxMenuItem makeCheckBox(Action a) {
        return makeCheckBox((VueAction) a);
    }
    
   private static JCheckBoxMenuItem makeCheckBox(VueAction a) {
        return makeCheckBox(a, a.isToggler() ? a.getToggleState() : false);
    }
    
    private static JCheckBoxMenuItem makeCheckBox(VueAction a, boolean initialState) {
        final JCheckBoxMenuItem item = new JCheckBoxMenuItem(a);
        //final JCheckBoxMenuItem item = new JCheckBoxMenuItem(a.getPermanentActionName());
        if (a.getKeyStroke() != null)
            item.setAccelerator(a.getKeyStroke());
        item.setSelected(initialState);
        return item;
    }
    private static JCheckBoxMenuItem makeLinkedCheckBox(VueAction a) {
        final JCheckBoxMenuItem item = makeCheckBox(a);
        a.trackToggler(item);
        return item;
    }
    

    private final JCheckBoxMenuItem viewFullScreen = makeLinkedCheckBox(Actions.ToggleFullScreen);
    
    private final JCheckBoxMenuItem viewSuperScreen = new JCheckBoxMenuItem(Actions.SuperScreen) {
            {
                Actions.SuperScreen.trackToggler(this);
            }
            @Override public void setEnabled(boolean b) {
                //Log.debug("SS SET ENABLED " + b);
                super.setEnabled(b);
                setVisible(b);
            }
        };
    
        private final JCheckBoxMenuItem viewKiosk = new JCheckBoxMenuItem(Actions.KioskScreen) {
            {
                Actions.SuperScreen.trackToggler(this);
            }
            @Override public void setEnabled(boolean b) {
                //Log.debug("SS SET ENABLED " + b);
                super.setEnabled(b);
                setVisible(b);
            }
        };

    
    Object[] arguments = { new Date(), "TestFile" };
    private final JMenu windowMenu = makeMenu(VueResources.getFormatMessage(arguments, "menu.windows"));
    //private final OntologyControlsOpenAction ontcontrls = new OntologyControlsOpenAction(VueResources.getString("menu.windows.ontologies"));

    private static final java.util.concurrent.atomic.AtomicInteger PublishRebuildCount = new java.util.concurrent.atomic.AtomicInteger();

    public VueMenuBar()
    {
        final int metaMask = tufts.vue.Actions.COMMAND;
        
        ////////////////////////////////////////////////////////////////////////////////////
        // Initialize Top Level Menus
        ////////////////////////////////////////////////////////////////////////////////////
        /* Need to pull the menu strings from the resource bundle*/
        final JMenu fileMenu = makeMenu(VueResources.getString("menu.file"));
        final JMenu recentlyOpenedMenu = makeMenu(VueResources.getString("menu.windiws.openrecent"));
        final JMenu editMenu = makeMenu(VueResources.getString("menu.edit"));
        final JMenu viewMenu = makeMenu(VueResources.getString("menu.view"));
        final JMenu formatMenu = makeMenu(VueResources.getString("menu.format"));
        
        transformMenu = makeMenu(VueResources.getString("menu.font"));
        transformMenu.setEnabled(false);
        arrangeMenu = makeMenu(VueResources.getString("menu.arrange"));
        arrangeMenu.setEnabled(false);
        
        final JMenu contentMenu = makeMenu(VueResources.getString("menu.content"));
        final JMenu presentationMenu = makeMenu(VueResources.getString("menu.pathway.label"));
        final JMenu analysisMenu = makeMenu(VueResources.getString("menu.analysis"));
      
        alignMenu = makeMenu(VueResources.getString("menu.align"));
        alignMenu.setEnabled(false);
        
        layoutMenu = makeMenu(VueResources.getString("menu.layout"));
        layoutMenu.setEnabled(false);        
        
        linkMenu = makeMenu(VueResources.getString("menu.link"));
        linkMenu.setEnabled(false); 
        final JMenu helpMenu = add(makeMenu(VueResources.getString("menu.help")));
        
      //  final JMenu slidePreviewMenu = new JMenu("Slide preview");
        final JMenu notesMenu = new JMenu(VueResources.getString("menu.pathways.handoutsandnotes"));
        playbackMenu = new JMenu(VueResources.getString("menu.playback.play.label"));
        playbackMenu.setEnabled(false); 
        ////////////////////////////////////////////////////////////////////////////////////
        // Initialize Actions
        ////////////////////////////////////////////////////////////////////////////////////

        final JMenuItem splitScreenItem = new JCheckBoxMenuItem(Actions.ToggleSplitScreen);
        final JMenuItem toggleLinksItem = new JCheckBoxMenuItem(Actions.ToggleLinks);
        final JMenuItem toggleSlideIconsItem = makeLinkedCheckBox(Actions.ToggleSlideIcons);
        final JMenuItem togglePruningItem = new JCheckBoxMenuItem(Actions.TogglePruning);

        final JMenuItem toggleAutoZoomItem = makeCheckBox(Actions.ToggleAutoZoom);
        toggleAutoZoomItem.setSelected(Actions.ToggleAutoZoom.getToggleState());

        ////////////////////////////////////////////////////////////////////////////////////
        // Initialize Actions
        ////////////////////////////////////////////////////////////////////////////////////
                
        saveAction = new SaveAction(VueResources.getString("menu.windows.save"), false); 
        saveAction.setEnabled(false);
        saveAsAction = new SaveAction(VueResources.getString("menu.windows.saveas"));
        saveAsAction.setEnabled(false);
        //final SaveAction exportAction = new SaveAction("Export ...",true,true);
        final OpenAction openAction = new OpenAction(VueResources.getString("menu.windows.open"));
        final OpenURLAction openFromURLAction = new OpenURLAction(VueResources.getString("menu.windows.openfromurl"));
        final ExitAction exitAction = new ExitAction(Util.isMacPlatform() ? VueResources.getString("menu.windows.quit") : VueResources.getString("menu.windows.exit"));
        
        importMenu = makeMenu(VueResources.getString("menu.file.import"));        
        final  QuickImportAction quickImport = new QuickImportAction();
        publishMenu = makeMenu(VueResources.getString("menu.windows.publish"));        
        //final JMenu publishAction =  Publish.getPublishMenu();

        final CreateCM createCMAction = new CreateCM(VueResources.getString("menu.windows.conanalysis"));
        final AnalyzeCM analyzeCMAction = new AnalyzeCM(VueResources.getString("menu.windows.mergemaps"));

        // Actions added by the power team
        printAction = PrintAction.getPrintAction();
        printAction.setEnabled(false);
    //    final PDFTransform pdfAction = new PDFTransform("PDF");
    /*    final HTMLConversion htmlAction = new HTMLConversion("HTML");
        final ImageConversion imageAction = new ImageConversion("JPEG");
        final ImageMap imageMap = new ImageMap("IMAP");
        final SVGConversion svgAction = new SVGConversion("SVG");
        final XMLView xmlAction = new XMLView("XML View");*/
        final RecentlyOpenedFilesManager rofm = RecentlyOpenedFilesManager.getInstance();

        rofm.getPreference().addVuePrefListener(new VuePrefListener()
        {
			public void preferenceChanged(VuePrefEvent prefEvent) {
				rebuildRecentlyOpenedItems(fileMenu, recentlyOpenedMenu, rofm);
				
			}
        	
        });
        // create menu for dataset import
       
        // Note: now that repositories are configured after loading, this gets called
        // each time a new repository completes its configuration, which is a bit
        // overkill for the normal case where everything loads immediately without
        // problem -- we're resetting the menu once for every data source.  Importantly,
        // this code is idempotent, so it can be re-run as many times as needed.  It
        // must stay this way.
        
        edu.tufts.vue.dsm.impl.VueDataSourceManager.getInstance().addDataSourceListener(new edu.tufts.vue.dsm.DataSourceListener() {
            public void changed(edu.tufts.vue.dsm.DataSource[] dataSource, Object state, edu.tufts.vue.dsm.DataSource changed) {
                if (DEBUG.DR) Log.debug("data sources changed; " + state);
                if (state == VueDataSourceManager.DS_CONFIGURED) {
                    // Rebuild the publish menu.  Note that we don't wait for just
                    // DS_ALL_CONFIGURED, as it's possible that may never come
                } else if (state == VueDataSourceManager.DS_ALL_CONFIGURED && VUE.BLOCKING_OSID_LOAD) {
                    // Rebuild the publish menu.  If OSID load is blocking, we won't get
                    // any DS_CONFIGURED events -- only the DS_ALL_CONFIGURED at the
                    // end.
                } else {
                    return;
                }
                    
                //final int rebuildCount = PublishRebuildCount.incrementAndGet();
                final List<Action> typeActions = new java.util.ArrayList();
           
                int count = 0;
                boolean sakaiFlag = false;
                boolean fedoraFlag = false;
                //publishMenu.removeAll();
                final List<Action> publishActions = new java.util.ArrayList();
                for(int i =0;i<dataSource.length;i++) {
                    try {
                        final org.osid.repository.Repository r = dataSource[i].getRepository();
                        if (r == null) {
                            if (DEBUG.DR) Log.debug("null repository in " + dataSource[i]);
                            continue;
                        }
                        if (r.getType().isEqual(edu.tufts.vue.dsm.DataSourceTypes.FEDORA_REPOSITORY_TYPE)) {
                        	if(!fedoraFlag) {
                        		typeActions.add(PublishActionFactory.createPublishAction(edu.tufts.vue.dsm.DataSourceTypes.FEDORA_REPOSITORY_TYPE));
                        		fedoraFlag = true;
                        		if (DEBUG.DR) Log.debug("PUBLISHABLE: " + dataSource[i]);	
                        	}
                        	publishActions.add(PublishActionFactory.createPublishAction(dataSource[i]));
                            count++;
                        } else if (r.getType().isEqual(edu.tufts.vue.dsm.DataSourceTypes.SAKAI_REPOSITORY_TYPE)) {
                        	if(!sakaiFlag) {                  
                        		typeActions.add(PublishActionFactory.createPublishAction(edu.tufts.vue.dsm.DataSourceTypes.SAKAI_REPOSITORY_TYPE));
                        		sakaiFlag = true;
                        		if (DEBUG.DR) Log.debug("PUBLISHABLE: " + dataSource[i]);
                        	}
                        	publishActions.add(PublishActionFactory.createPublishAction(dataSource[i]));
                            count++;
                        }
  
                    } catch(org.osid.repository.RepositoryException ex) {
                        Log.error("changed:", ex);
                    }
                }
                // todo: could create an GUI MostRecentOnly Runnable with an exec that is only called
                // if it's the most recent -- would be very handy -- tho how to collate with various
                // types?  Would need to have a HashMap of all class instances (the inner anonomous
                // one generated) containing atomic counts for each instance -- eithar that or require
                // passing in a constant AtomicLong for each instancing group -- that'd be easier.

                final int rebuildCount = PublishRebuildCount.incrementAndGet();
                // technically, would be most efficient to increment this counter
                // above at the moment we know we'll be issuing a new AWT invocation,
                // tho any exception between then and here would have to be caught
                // to ensure the menu was rebuilt no matter what.

                GUI.invokeAfterAWT(new Runnable() { public void run() {

                    final int curCount = PublishRebuildCount.get();

                    if (rebuildCount < curCount) {
                        if (DEBUG.INIT || DEBUG.DR) Log.debug("skipping rebuild; runnable count " + rebuildCount + " < " + curCount);
                        return;
                    } else {
                        Log.info("rebuilding with " + publishActions.size()
                                 + " publishable data source(s) after "
                                 + curCount
                                 + " updates");
                    }

                    // rebuild the menus on the AWT thread for thread safety

                    publishMenu.removeAll();

                    if (typeActions.size() > 0) {
                        
                        for (Action a : typeActions)
                            publishMenu.add(a);
                        
                        if (publishActions.size() > 0) {
                            publishMenu.addSeparator();    
                            for (Action a : publishActions)
                                publishMenu.add(a);
                        }
                        
                    } else {
                        
                        // no accelerator key for this menu
                        publishMenu.add(createWindowItem(VUE.getContentDock(), 0, VueResources.getString("menu.publisher.resourcewindow")));
                    }

                    publishMenu.setEnabled(false);
                    fileMenu.remove(publishMenu);
                    fileMenu.add(publishMenu,11);
                    
                }});
                
            }
        });
        
        ////////////////////////////////////////////////////////////////////////////////////
        // Initializing DEBUG code
        ////////////////////////////////////////////////////////////////////////////////////

        if (false && DEBUG.Enabled) {
            // THIS CODE IS TRIGGERING THE TIGER ARRAY BOUNDS BUG:
            // we're hitting bug in java (1.4.2, 1.5) on Tiger (OSX 10.4.2) here
            // (apple.laf.ScreenMenuBar array index out of bounds exception)
            JButton u = new JButton(Actions.Undo);
            JButton r = new JButton(Actions.Redo);
            JButton p = new JButton(printAction);
            JButton v = new JButton(printAction);
            v.setText(VueResources.getString("vuemenubar.printvisible.tooltip"));
            
            u.setBackground(Color.white);
            r.setBackground(Color.white);
            add(u).setFocusable(false);
            add(r).setFocusable(false);
            add(p).setFocusable(false);
            add(v).setFocusable(false);

            //menuBar.add(new tufts.vue.gui.VueButton(Actions.Undo)).setFocusable(false);
            // not picking up icon yet...
        }
        /*
        if (false && DEBUG.Enabled) {
            // THIS CODE IS TRIGGERING THE TIGER ARRAY BOUNDS BUG (see above)
            JMenu exportMenu = add(makeMenu("Export"));
            exportMenu.add(htmlAction);
           // exportMenu.add(pdfAction);
            exportMenu.add(imageAction);
            exportMenu.add(svgAction);
            exportMenu.add(xmlAction);
            exportMenu.add(imageMap);
        }
        */
        ////////////////////////////////////////////////////////////////////////////////////
        // Build File Menu
        ////////////////////////////////////////////////////////////////////////////////////

        fileMenu.add(Actions.NewMap);
        fileMenu.add(openAction).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, metaMask));
        fileMenu.add(openFromURLAction);
        fileMenu.add(Actions.CloseMap);
        fileMenu.addSeparator();        
        fileMenu.add(saveAction).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, metaMask));
        fileMenu.add(saveAsAction).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, metaMask+Event.SHIFT_MASK));                
        if (VUE.isApplet() && VueApplet.isZoteroApplet())
        {
        	fileMenu.add(Actions.SaveCopyToZotero);
        }
        fileMenu.add(Actions.Revert);
        Actions.Revert.setEnabled(false);
        fileMenu.addSeparator();
     //   fileMenu.add(Actions.ZoteroAction);
        //fileMenu.add(exportAction);

        //fileMenu.add(quickImport);

        //publishMenu.setEnabled(false);
        //if (!VUE.isApplet())
        //	fileMenu.add(publishMenu);
        	
        pdfExportMenu = new JMenu(VueResources.getString("menu.windows.exporthandouts"));
        pdfExportMenu.setEnabled(false);
        //pdfExportMenu.add(Actions.MapAsPDF);
        final JMenuItem fullPageSlideNotesItem = new JMenuItem(Actions.FullPageSlideNotes);
        final JMenuItem slides8PerPageItem = new JMenuItem(Actions.Slides8PerPage);
        final JMenuItem speakerNotes1Item = new JMenuItem(Actions.SpeakerNotes1);
        final JMenuItem speakerNotes4Item = new JMenuItem(Actions.SpeakerNotes4);
        final JMenuItem audienceNotesItem = new JMenuItem(Actions.AudienceNotes);
        final JMenuItem speakerNotesOutlineItem = new JMenuItem(Actions.SpeakerNotesOutline);
        final JMenuItem nodeNotes4Item = new JMenuItem(Actions.NodeNotes4);
        final JMenuItem nodeNotesOutlineItem = new JMenuItem(Actions.NodeNotesOutline);
        
        pdfExportMenu.add(fullPageSlideNotesItem);
        pdfExportMenu.add(slides8PerPageItem);
        pdfExportMenu.add(speakerNotes1Item);
        pdfExportMenu.add(speakerNotes4Item);
        pdfExportMenu.add(audienceNotesItem);        
        pdfExportMenu.add(speakerNotesOutlineItem);
        pdfExportMenu.addSeparator();
        pdfExportMenu.add(nodeNotes4Item);
        pdfExportMenu.add(nodeNotesOutlineItem);        
      
        fileMenu.addMenuListener(new MenuListener(){
			public void menuCanceled(MenuEvent e) {/* no op	*/}
			public void menuDeselected(MenuEvent e) {/*no op */}
			public void menuSelected(MenuEvent e) {handleActivation();}
			private void handleActivation() {
				LWPathway p =VUE.getActivePathway();
				if (p == null || p.length() == 0)
				{
					fullPageSlideNotesItem.setEnabled(false);
					slides8PerPageItem.setEnabled(false);
					speakerNotes1Item.setEnabled(false);
					speakerNotes4Item.setEnabled(false);
					audienceNotesItem.setEnabled(false);
					speakerNotesOutlineItem.setEnabled(false);
					
				}
					//pdfExportMenu.setEnabled(false);			
				else
				{
					fullPageSlideNotesItem.setEnabled(true);
					slides8PerPageItem.setEnabled(true);
					speakerNotes1Item.setEnabled(true);
					speakerNotes4Item.setEnabled(true);
					audienceNotesItem.setEnabled(true);
					speakerNotesOutlineItem.setEnabled(true);
				}
				if (VUE.getActiveMap()!=null && VUE.getActiveMap().hasContent())
				{
					nodeNotesOutlineItem.setEnabled(true);
					nodeNotes4Item.setEnabled(true);
				}
				else
				{
					nodeNotesOutlineItem.setEnabled(false);
					nodeNotes4Item.setEnabled(false);
				}
					//pdfExportMenu.setEnabled(true);				
			}});                   
      //  pdfExportMenu.add(Actions.NodeNotesOutline);
        fileMenu.addSeparator();
        fileMenu.add(printAction).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, metaMask));
        fileMenu.add(printAction).setText(VueResources.getString("menu.windows.printvisible"));
        if (!VUE.isApplet())
        	fileMenu.add(pdfExportMenu);        
        rebuildRecentlyOpenedItems(fileMenu, recentlyOpenedMenu, rofm);
      
        if (VUE.isApplet() || (VUE.isSystemPropertyTrue("apple.laf.useScreenMenuBar") && GUI.isMacAqua())) {
            // Do NOT add quit to the file menu.
            // Either we're an applet w/no quit, or it's already in the mac application menu bar.
            // FYI, MRJAdapter.isSwingUsingScreenMenuBar() is not telling us the truth.
        } else {
            fileMenu.addSeparator();
            JMenuItem exitItem = new JMenuItem(VueResources.getString("menu.windows.exit"));
            exitItem.setMnemonic('x');
            exitItem.addActionListener(exitAction);
            fileMenu.add(exitItem);
        }
        
        ////////////////////////////////////////////////////////////////////////////////////
        // Build Edit Menu
        ////////////////////////////////////////////////////////////////////////////////////
        
        editMenu.add(Actions.Undo);
        editMenu.add(Actions.Redo);
        editMenu.addSeparator();
        editMenu.add(Actions.Cut);
        editMenu.add(Actions.Copy);
        editMenu.add(Actions.Paste);
        editMenu.add(Actions.Duplicate);
        editMenu.add(Actions.Rename);
        editMenu.add(Actions.Delete);                        
        editMenu.addSeparator();
        editMenu.add(Actions.SelectAll);
        editMenu.add(Actions.SelectAllNodes);
        editMenu.add(Actions.SelectAllLinks);
        editMenu.add(Actions.ExpandSelection);
        editMenu.add(Actions.ShrinkSelection);
        editMenu.add(Actions.Reselect);
        editMenu.add(Actions.DeselectAll);
        if (!tufts.Util.isMacPlatform() || VUE.isApplet())
        {   editMenu.addSeparator();
            editMenu.add(Actions.Preferences);
        }
        
        if (DEBUG.IMAGE)
            editMenu.add(Images.ClearCacheAction);

        ////////////////////////////////////////////////////////////////////////////////////
        // Build View Menu
        ////////////////////////////////////////////////////////////////////////////////////
                
        viewMenu.add(Actions.ZoomIn);
        viewMenu.add(Actions.ZoomOut);
        viewMenu.addSeparator();            
        viewMenu.add(Actions.ZoomFit);
        viewMenu.add(Actions.ZoomToSelection);
        viewMenu.add(Actions.ZoomActual);
        viewMenu.addSeparator();            
        if (!(Util.isUnixPlatform() || VUE.isApplet()) ) {
            viewMenu.add(viewFullScreen);
        }
        
        if (!VUE.isApplet()) {
            viewMenu.add(splitScreenItem);
            viewMenu.add(viewSuperScreen);
        }
        
        if (DEBUG.TWITTER)
        	viewMenu.add(viewKiosk);
        
        if (!VUE.isApplet())
        	viewMenu.addSeparator();
        if (!VUE.isApplet())
        {
        	viewMenu.add(toggleSlideIconsItem);
        	viewMenu.addSeparator();
        }

        if (LWComponent.COLLAPSE_IS_GLOBAL)
            viewMenu.add(makeCheckBox(Actions.ToggleGlobalCollapse));
        else
            viewMenu.add(Actions.Collapse);
        
        viewMenu.add(togglePruningItem);
        viewMenu.add(Actions.ClearAllPruning);

        viewMenu.add(toggleLinksItem);
//        viewMenu.add(Actions.unhideLinks);
        // JAVA BUG: ADDING A JMenuItem (maybe just JCheckBoxMenuItem)
        // already constructe, instead of letting the menu code do it
        // itself, breaks the display of accelerators in the item:
        // anything other than APPLE (ctrl/alt) display as the APPLE
        // glpyh.  This is true on Tiger java 1.5, Leopard java 1.5
        // and 1.6 -- SMF 2008-05-31
        
        viewMenu.add(toggleAutoZoomItem);
        if (DEBUG.Enabled && DEBUG.KEYS) viewMenu.add(Actions.ToggleAutoZoom);
        
//         viewMenu.addSeparator();
//         viewMenu.add(Actions.ViewBackward);
//         viewMenu.add(Actions.ViewForward);

//         GUI.getFullScreenWindow().addWindowFocusListener(new WindowFocusListener()
//         {
//             public void windowGainedFocus(WindowEvent arg0) {
//                 viewFullScreen.setSelected(true);
//             }
            
//             public void windowLostFocus(WindowEvent arg0) {
//                 viewFullScreen.setSelected(false);
//             }
//             });

        ////////////////////////////////////////////////////////////////////////////////////
        // Build Format Menu
        ////////////////////////////////////////////////////////////////////////////////////
        
        formatMenu.add(Actions.CopyStyle);
        formatMenu.add(Actions.PasteStyle);
        formatMenu.addSeparator();        
        
        //build format submenus...
        buildMenu(alignMenu, Actions.ALIGN_MENU_ACTIONS);
        buildMenu(arrangeMenu, Actions.ARRANGE_MENU_ACTIONS);
        buildMenu(layoutMenu,LayoutAction.LAYOUT_ACTIONS);
        buildMenu(linkMenu, Actions.LINK_MENU_ACTIONS);
        transformMenu.add(Actions.FontBigger);
        transformMenu.add(Actions.FontSmaller);
        transformMenu.add(Actions.FontBold);
        transformMenu.add(Actions.FontItalic);      
        transformMenu.add(Actions.FontUnderline);
        formatMenu.add(buildMenu("menu.node",Actions.NODE_FORMAT_MENU_ACTIONS));
        formatMenu.add(transformMenu);
        formatMenu.add(buildMenu("menu.image", Actions.IMAGE_MENU_ACTIONS));
        formatMenu.add(linkMenu);
        formatMenu.add(alignMenu);
        formatMenu.add(arrangeMenu);
        formatMenu.add(layoutMenu);
        formatMenu.addSeparator();
        formatMenu.add(Actions.Group);
        formatMenu.add(Actions.Ungroup);
        formatMenu.addSeparator();
        
        
        ////////////////////////////////////////////////////////////////////////////////////
        // Build Content Menu
        ////////////////////////////////////////////////////////////////////////////////////
        GUI.addToMenu(contentMenu, Actions.NEW_OBJECT_ACTIONS);
        
        final JMenuItem addFileItem = new JMenuItem(Actions.AddFileAction);
        final JMenuItem addURLItem = new JMenuItem(Actions.AddURLAction);
        final JMenuItem newSlideItem = new JMenuItem(Actions.NewSlide);
        final JMenuItem newMergeNodeItem = new JMenuItem(Actions.MergeNodeSlide);        
        final JMenuItem removeResourceItem = new JMenuItem(Actions.RemoveResourceAction);
        final JMenuItem removeResourceKeepImageItem = new JMenuItem(Actions.RemoveResourceKeepImageAction);
        
        contentMenu.add(addFileItem);
        contentMenu.add(addURLItem);
        contentMenu.addSeparator();
        contentMenu.add(removeResourceItem);
        contentMenu.add(removeResourceKeepImageItem);
        
        
        formatMenu.addMenuListener(new MenuListener(){        	
        	public void menuCanceled(MenuEvent e) {/* no op	*/}
			public void menuDeselected(MenuEvent e) {/*no op */}
			public void menuSelected(MenuEvent e) {handleActivation();}
			private void handleActivation()
			{
				LWSelection selection = VUE.getSelection();
				
				if (selection.count(LWText.class) > 0)
				{
					if(!isMenuEnableFontFlg){
						transformMenu.setEnabled(isMenuEnableFontFlg);
					}
				}
				else
				{
					if(!isMenuEnableFontFlg){
						transformMenu.setEnabled(false);
					}else{
						transformMenu.setEnabled(true);
					}
				}
				
			}});
        contentMenu.addMenuListener(new MenuListener(){
			public void menuCanceled(MenuEvent e) {/* no op	*/}
			public void menuDeselected(MenuEvent e) {/*no op */}
			public void menuSelected(MenuEvent e) {handleActivation();}
			private void handleActivation()
			{
				LWComponent c =VUE.getActiveComponent();
				if (c instanceof LWNode)
				{
					if ((c).hasResource())
					{
						final Resource resource = c.getResource();
						removeResourceItem.setEnabled(true);
						if (c.hasChildren())
			        	{
			        		List<LWComponent> children = c.getChildren();
			        		Iterator<LWComponent> childIterator = children.iterator();
			        		boolean enabled= false;
			        		while (childIterator.hasNext())
			        		{
			        			LWComponent comp = childIterator.next();
			        			if (comp instanceof LWImage)
			        			{
			    					LWImage image = ((LWImage)comp);
			        				if (image.getResource().equals(resource))
			        				{
			        					removeResourceKeepImageItem.setEnabled(true);
			        					enabled=true;
			        					break;
			        				}
			        			}
			        		}
			        		if (!enabled)
			        			removeResourceKeepImageItem.setEnabled(false);
			        	}
					
						
						addFileItem.setLabel(VueResources.getString("mapViewer.componentMenu.replaceFile.label"));
						addURLItem.setLabel(VueResources.getString("mapViewer.componentMenu.replaceURL.label"));						
					}
					else
					{
						removeResourceItem.setEnabled(false);
						removeResourceKeepImageItem.setEnabled(false);
						addFileItem.setLabel(VueResources.getString("mapViewer.componentMenu.addFile.label"));
						addURLItem.setLabel(VueResources.getString("mapViewer.componentMenu.addURL.label"));
					}
				}
			}});
        
  //      contentMenu.addSeparator();
  //      contentMenu.add(Actions.AddResource);
  //      contentMenu.add(Actions.UpdateResource).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, metaMask));
        
        ////////////////////////////////////////////////////////////////////////////////////
        // Build Presentation Menu
        ////////////////////////////////////////////////////////////////////////////////////
        if (!VUE.isApplet())
        {
        	presentationMenu.add(playbackMenu);
        	presentationMenu.addSeparator();
        }
        
        presentationMenu.addMenuListener(new MenuListener(){
			public void menuCanceled(MenuEvent e) {/* no op	*/}
			public void menuDeselected(MenuEvent e) {/*no op */}
			public void menuSelected(MenuEvent e) {handleActivation();}
			private void handleActivation()
			{
				LWComponent c =VUE.getActiveComponent();
				if (c instanceof LWNode)
				{
					if (c instanceof LWPortal)
					{					
						newSlideItem.setEnabled(false);
						newMergeNodeItem.setEnabled(false);										
					}					
					else
					{
						newSlideItem.setEnabled(true);
						newMergeNodeItem.setEnabled(true);
					}
				}
			}});
        presentationMenu.add(newSlideItem);
        presentationMenu.add(newMergeNodeItem);
        if (!VUE.isApplet())
        	presentationMenu.addSeparator();
        if (VUE.getSlideDock() != null) {
            presentationMenu.add(Actions.MasterSlide);                
            presentationMenu.add(Actions.PreviewInViewer);
        }
        //slidePreviewMenu.add(Actions.PreviewOnMap);
        if (!VUE.isApplet())
        {
        	presentationMenu.add(Actions.PreviewOnMap);
        	presentationMenu.add(Actions.EditMasterSlide);
        }
        	// slidePreviewMenu.add(Actions.PreviewInViewer);
      //  presentationMenu.add(slidePreviewMenu);
         playbackMenu.addMenuListener(new MenuListener()
        {

			public void menuCanceled(MenuEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			public void menuDeselected(MenuEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			public void menuSelected(MenuEvent arg0) {
				playbackMenu.removeAll();
				final LWPathwayList pathways = VUE.getActiveMap().getPathwayList();
				
				//Iterator i = pathways.iterator();
				final Collection coll = pathways.getElementList();
				final Iterator i = coll.iterator();
				while (i.hasNext())
				{
					final LWPathway path = (LWPathway) i.next();
					final JMenuItem menuItem = new JMenuItem(path.getDisplayLabel());
					if (path.getEntries().isEmpty())
						menuItem.setEnabled(false);

					menuItem.addActionListener(new ActionListener()
					{
						public void actionPerformed(ActionEvent e)
						{
                                                    Actions.startPresentation(path, this);
						}
					});
					playbackMenu.add(menuItem);
				}
				
			}
        	
        });
        
        if (!VUE.isApplet())
        {
        	notesMenu.add(Actions.MapAsPDF);
        	notesMenu.add(Actions.FullPageSlideNotes);
        	notesMenu.add(Actions.Slides8PerPage);
        	notesMenu.add(Actions.SpeakerNotes1);
        	notesMenu.add(Actions.SpeakerNotes4);
        	notesMenu.add(Actions.AudienceNotes);
        	notesMenu.add(Actions.SpeakerNotesOutline);   
        }
        
        if (!VUE.isApplet())
        	presentationMenu.add(notesMenu);
        
        presentationMenu.addMenuListener(new MenuListener(){
			public void menuCanceled(MenuEvent e) {/* no op	*/}
			public void menuDeselected(MenuEvent e) {/*no op */}
			public void menuSelected(MenuEvent e) {handleActivation();}
			private void handleActivation() {
				LWPathway p =VUE.getActivePathway();
				if (p == null || p.length() == 0)
					notesMenu.setEnabled(false);			
				else	
					notesMenu.setEnabled(true);				
			}});             
        ////////////////////////////////////////////////////////////////////////////////////
        // Build Analysis Menu
        ////////////////////////////////////////////////////////////////////////////////////
       // if (!VUE.isApplet())
        //{
        	analysisMenu.add(createCMAction);

        	if (VUE.getMergeMapsDock()!= null ){
        		analysisMenu.add(createWindowItem(VUE.getMergeMapsDock(), 0, VueResources.getString("menu.windows.mergemaps")));            
        	}
        	//analysisMenu.add(analyzeCMAction);

        	analysisMenu.add(createWindowItem(JavaAnalysisPanel.getJavaAnalysisDock(), 0, VueResources.getString("menu.windows.java")));
        //}
       
        
      rebuildWindowsMenu();
        
        
        
        ////////////////////////////////////////////////////////////////////////////////////
        // Build Help Menu
        ////////////////////////////////////////////////////////////////////////////////////

        if (tufts.Util.isMacPlatform() == false || VUE.isApplet()) {
            // already in standard MacOSX place
            helpMenu.add(new AboutAction());
            helpMenu.addSeparator();
        }
        helpMenu.add(new ShowURLAction(VueResources.getString("helpMenu.userGuide.label"), VueResources.getString("helpMenu.userGuide.url")));        
        helpMenu.add(new ShowURLAction(VueResources.getString("helpMenu.feedback.label"), VueResources.getString("helpMenu.feedback.url")));
        //helpMenu.add(new ShowURLAction(VueResources.getString("helpMenu.vueWebsite.label"), VueResources.getString("helpMenu.vueWebsite.url")));
      
      /*
       * This feature was removed from the VUE website because of a security issue in the web-feature, it doesn't make 
       * sense to have it here until we decided we're going to support it again on the website.
       *  helpMenu.add(new ShowURLAction(VueResources.getString("helpMenu.mymaps.label"), VueResources.getString("helpMenu.mymaps.url"))); 
       */                
        
        helpMenu.addSeparator();
/*        helpMenu.add(new ShowURLAction(VueResources.getString("helpMenu.releaseNotes.label"), VueResources.getURL("helpMenu.releaseNotes.file"),
                new String("ReleaseNotes_" + VueResources.getString("vue.version") + ".htm").replace(' ', '_')
                ));
        helpMenu.addSeparator();*/
        helpMenu.add(new ShortcutsAction());
        
        helpMenu.addSeparator();
        if (!VUE.isApplet())
        	helpMenu.add(new ShowLogAction());
      
        ////////////////////////////////////////////////////////////////////////////////////
        // Build final main menu bar
        ////////////////////////////////////////////////////////////////////////////////////
        
        //build out the main menus..
        add(fileMenu);
        add(editMenu);
        add(viewMenu);
        add(formatMenu);
        add(contentMenu);
        add(presentationMenu);
      //  if (!VUE.isApplet())
        	add(analysisMenu);        
        add(windowMenu);
        add(helpMenu);
        
        if (DEBUG.Enabled) {
            add(new JMenu("    ")); // gap
            add(TitleItem);
            VUE.addActiveListener(LWMap.class, this);
        }
        
        if (RootMenuBar == null)
            RootMenuBar = this;       
       
    }

    public void rebuildWindowsMenu()
    {
    	////////////////////////////////////////////////////////////////////////////////////
        // Window Menu
        ////////////////////////////////////////////////////////////////////////////////////
    	windowMenu.removeAll();
    	
        if (VUE.getFormatDock() != null)        
        	windowMenu.add(createWindowItem(VUE.getFormatDock(), KeyEvent.VK_1,VueResources.getString("menu.windows.formatpalette")));                
        windowMenu.addSeparator();                
        if (VUE.getInfoDock() !=null)
        	windowMenu.add(createWindowItem(VUE.getInfoDock(), KeyEvent.VK_2, VueResources.getString("menu.windows.info")));
        windowMenu.add(Actions.KeywordAction);
        windowMenu.add(Actions.NotesAction);
        windowMenu.addSeparator();
//      if (VUE.getContentDock()!= null && !VUE.isApplet()){
            windowMenu.add(createWindowItem(VUE.getContentDock(), KeyEvent.VK_3, VueResources.getString("dockWindow.contentPanel.title")));
            if (!VUE.isApplet())
            	windowMenu.add(Actions.ResourcesAction);
            windowMenu.add(Actions.DatasetsAction);
            windowMenu.add(Actions.OntologiesAction);
            windowMenu.addSeparator();

//            OntologyBrowser.getBrowser().initializeBrowser(false, null);
//      }

        if (VUE.getInteractionToolsDock()!= null)
            windowMenu.add(createWindowItem(VUE.getInteractionToolsDock(), KeyEvent.VK_4, VueResources.getString("dockWindow.interactionTools.title")));            
        if (VUE.getLayersDock() != null)	
            windowMenu.add(createWindowItem(VUE.getLayersDock(), KeyEvent.VK_5, VueResources.getString("menu.windows.layers")));
        if (VUE.getMapInfoDock() !=null)
            windowMenu.add(createWindowItem(VUE.getMapInfoDock(), KeyEvent.VK_6, VueResources.getString("menu.windows.mapinfo")));
        if (VUE.getOutlineDock() !=null && !VUE.isApplet())	
        	windowMenu.add(createWindowItem(VUE.getOutlineDock(), KeyEvent.VK_7, VueResources.getString("menu.windows.outline")));
        if (VUE.getPannerDock() !=null && !VUE.isApplet())	
        	windowMenu.add(createWindowItem(VUE.getPannerDock(), 0, VueResources.getString("menu.windows.panner")));
        if (VUE.getPresentationDock() !=null)	
        	windowMenu.add(createWindowItem(VUE.getPresentationDock(), KeyEvent.VK_8, VueResources.getString("menu.windows.pathways")));
        if (VUE.getMetadataSearchMainGUI()!= null)
            windowMenu.add(createWindowItem(VUE.getMetadataSearchMainGUI(), KeyEvent.VK_9, VueResources.getString("menu.windows.search")));            
       
          
           
//      final KeyStroke acceleratorKey = KeyStroke.getKeyStroke(KeyEvent.VK_9, Actions.COMMAND);
//    	Actions.SearchFilterAction.putValue(Action.ACCELERATOR_KEY, acceleratorKey);
//      windowMenu.add(Actions.SearchFilterAction);
        windowMenu.addSeparator();
        if (VUE.getFloatingZoomDock()!=null)
        {
        	fullScreenToolbarItem = createWindowItem(VUE.getFloatingZoomDock(),KeyEvent.VK_0, VueResources.getString("menu.windows.fullscreentoolbar"));
        	fullScreenToolbarItem.setEnabled(false);
        	windowMenu.add(fullScreenToolbarItem);        	
        }     
        windowMenu.add(Actions.GatherWindows);
    }
    private final JMenuItem TitleItem = new JMenu("");
    //private final java.util.Map<LWMap,JMenuItem> items = new java.util.HashMap();
    
    public void activeChanged(tufts.vue.ActiveEvent e, LWMap map) {
        //TitleItem.setFont(VueConstants.SmallFont);

        if (VUE.isStartupUnderway())
            return;
        
        TitleItem.setLabel("[ " + (map==null?"?":map.getLabel()) + " ]");
        TitleItem.removeAll();
        
        MapTabbedPane tp = VUE.getLeftTabbedPane();
        for (int i = 0; i < tp.getTabCount(); i++) {
            final MapViewer v = tp.getViewerAt(i);
            final LWMap m = v.getMap();
            
            JMenuItem item = new JMenuItem(new VueAction(m.getSaveFileModelVersion() + " | " +  m.getLabel()) {
                    public void act() {
                        Log.debug("quik-map " + m);
                        // this currently only works in full-screen mode
                        ActiveInstance.getHandler(LWMap.class).setActive(this, m);
                        // VueTabbedPane should be auto-updating based
                        // on the active map event, but too close to
                        // release to mess with fundamental events right now.
                        VUE.getLeftTabbedPane().setSelectedMap(m);
                    }
                    public boolean overrideIgnoreAllActions() { return true; }
                }
                );

            if (m == map)
                item.setEnabled(false);
            
            item.setToolTipText(""+m.getFile());
            TitleItem.add(item);
        }
    }

    
    
    public static void toggleFullScreenTools()
    {
    	fullScreenToolbarItem.setEnabled(FullScreen.inFullScreen());
    }
    
    public JCheckBoxMenuItem createWindowItem(DockWindow dock,int accelKey, String text)
    {
        final JCheckBoxMenuItem checkBox;
        
        if (dock != null) {
            final WindowDisplayAction windowAction = new WindowDisplayAction(dock);
            final KeyStroke acceleratorKey = KeyStroke.getKeyStroke(accelKey, Actions.COMMAND);
            if (accelKey > 0)
    		windowAction.putValue(Action.ACCELERATOR_KEY, acceleratorKey);    	
            if (text !=null)
    		windowAction.setTitle(text);
    	
            checkBox = new JCheckBoxMenuItem(windowAction);    	
    	
    		//checkBox.setText(text);
            windowAction.setLinkedButton(checkBox);
        } else {
            checkBox = new JCheckBoxMenuItem(text + " (missing window)");
        }
    	
    	return checkBox;
    }
    protected void rebuildRecentlyOpenedItems(JMenu fileMenu, JMenu recentlyOpenedMenu, RecentlyOpenedFilesManager rofm) {
    	if (rofm.getFileListSize() > 0)
        {
        	List files = rofm.getRecentlyOpenedFiles();
        	Iterator i = files.iterator();

        	recentlyOpenedMenu.removeAll();
        	
        	while (i.hasNext())
        	{
        		
        		File f = new File((String)i.next());
        		if (f.exists())
        			recentlyOpenedMenu.add(new RecentOpenAction(f));
        		else 
        			f=null;
        	}
        	fileMenu.remove(recentlyOpenedMenu);
        	fileMenu.add(recentlyOpenedMenu,2);
        }
		
	}


	private KeyEvent alreadyProcessed;

    /*
    public boolean doProcessKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
        //return super.processKeyBinding(ks, e, condition, pressed);
        //if (e != alreadyProcessed) {
            System.out.println("VueMenuBar: handling relayed " + ks);
            return processKeyBinding(ks, e, condition, pressed);
            //}
            //return true;
    }
    */

    public void processKeyEvent(KeyEvent e) {
        if (!e.isConsumed())
            super.processKeyEvent(e);
        else
            Log.debug("processKeyEvent: already consumed " + GUI.name(e));
    }
    
    /** hardwired entry-point called by FocusManager for handling unconsumed KeyEvent's */
    void doProcessKeyEvent(KeyEvent e) {

        // todo: need to allow BACK_SPACE to process as DELETE (esp
        // for laptop keyboards?) -- time for an action map for this
        // code -- long overdue -- e.g. Actions.Delete should
        // trigger for VK_BACK_SPACE as well as VK_DELETE.
        
        if (e != alreadyProcessed) {
            if (DEBUG.KEYS) Log.debug("doProcessKeyEvent " + GUI.name(e));
            processKeyEvent(e);
        }
        else if (DEBUG.KEYS) Log.debug("already processed " + GUI.name(e));
    }
    
    // // todo: this doesn't work: safer if can get working instead of above
    // void doProcessKeyPressEventToBinding(KeyEvent e) {
    //     if (e != alreadyProcessed) {
    //         //System.out.println("VueMenuBar: doProcessKeyPressEventToBinding " + e);
    //         Log.debug("KEY->BIND " + e);
    //         KeyStroke ks = KeyStroke.getKeyStroke(e.getKeyCode(), e.getModifiers(), false);
    //         super.processKeyBinding(ks, e, WHEN_FOCUSED, true);
    //     }
    //     else Log.debug("already processed " + e);
    // }
    
    protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
        if (e.isConsumed())
            Log.debug("GOT CONSUMED " + ks);

        if (!pressed) // we only ever handle on key-press
            return false;

        // todo: find the right keymap to stick these kinds of non-menu actions in
        if (Actions.FocusToSearchField.keyStroke.equals(ks)) {
            Actions.FocusToSearchField.fire(e);
            return true;
        } else if (Actions.FocusToViewer.keyStroke.equals(ks)) {
            Actions.FocusToViewer.fire(e);
            return true;
        }
            
        final boolean didAction = super.processKeyBinding(ks, e, condition, pressed);
        if (DEBUG.KEYS) {
            String used = didAction ?
                "CONSUMED " :
                "NOACTION ";
            Log.debug("processKeyBinding " + used + "[" + ks + "] " + GUI.name(e));
        }
        if (didAction)
            e.consume();
        // checking for extra keys to process here can give us "Aquired pre-used event!" stack
        // traces from javax.swing.KeyboardManager.fireKeyboardAction if they're actually fired.
        alreadyProcessed = e;
        return didAction;
    }
    

    public void setVisible(boolean b) {
        Log.debug("VMB: setVisible: " + b);
        super.setVisible(b);
    }
    public void focusGained(java.awt.event.FocusEvent e) {
        Log.debug("VMB: focusGained from " + e.getOppositeComponent());
    }
    public void focusLost(java.awt.event.FocusEvent e) {
        Log.debug("VMB: focusLost to " + e.getOppositeComponent());
    }


//     public static JMenu buildMenu(String name, Action[] actions) {
//         return buildMenu(makeMenu(name), actions);
//     }
    
    public static JMenu buildMenu(String localizationKey, Action[] actions) {
        return buildMenu(localizationKey, actions, true);
    }
        
    public static JMenu buildMenu(String localizationKey, Action[] actions, boolean enabled) {
        final JMenu menu = new JMenu(VueResources.getString(localizationKey, localizationKey));
        buildMenu(menu, actions);
        if (!enabled)
            menu.setEnabled(false);
        return menu;
    }
    
    public static JMenu buildMenu(JMenu menu, Action[] actions) {
        for (int i = 0; i < actions.length; i++) {
            Action a = actions[i];
            if (a == null)
                menu.addSeparator();
            else
                menu.add(a);
        }
        return menu;
    }




    private static class RecentOpenAction extends VueAction {
    	private File file;
    	public RecentOpenAction(File f) {
            super(f.getName());
            if (DEBUG.Enabled)
            	putValue(SHORT_DESCRIPTION, f.toString());
            else
            	putValue(SHORT_DESCRIPTION, "");
            file = f;
    	}

        @Override
        public boolean isUserEnabled() { return true; }
        // Don't allow if locked into a presentation:
        //public boolean isUserEnabled() { return VUE.getActiveTool().permitsToolChange(); }
    	
    	public void act()
    	{
            OpenAction.displayMap(file);
    	}
    	
    }

    private static class ShowLogAction extends VueAction {
        private static DockWindow errorDock;
        private static JTextArea textArea;

        private static final String ReportAddress = "vue-dev@elist.tufts.edu";
        
    	public ShowLogAction() {
            super(VueResources.getString("menu.help.vuelog"));
    	}

        @Override
        public boolean isUserEnabled() { return true; }
    	
    	public void act() {
            if (errorDock == null)
                buildGUI();
            textArea.setText(tufts.Util.getExceptionLog().toString());
           // errorDock.setVisible(true);
            GUI.makeVisibleOnScreen(panel);
    	}
    	
    	JPanel panel = null;
        
    	private void buildGUI() {
            panel = new JPanel(new BorderLayout());
            textArea = new JTextArea();
            textArea.setFont(VueConstants.SmallFixedFont);
            textArea.setLineWrap(true);
            textArea.setEditable(false);
            panel.add(new JScrollPane(textArea), BorderLayout.CENTER);

            if (!Util.isWindowsPlatform())
            // can't get enough log into the email for now on Windows to be useful.
                panel.add(new JButton(VueResources.getString("button.submitrep.label")) {
                    @Override
                    protected void fireActionPerformed(ActionEvent ae) {                        
                        //System.out.println("ACTION " + ae);
                        
                        final String body;

                        if (Util.isWindowsPlatform()) {
                            // There's a 2048 byte WinXP argument limit for url.dll,FileProtocolHandler,
                            // so don't add anything extra...
                            body = Util.getExceptionLog().toString();
                        } else {
                            body =
                                "Thank you for submitting a problem report.\n"
                                + "Please feel free to add any comments/feedback here:\n"
                                + "\n\n\n"
                                + Util.getExceptionLog()
                                + "\nEnd report: " + new java.util.Date() + ".\n";
                        }
                            
                        final String subject =
                            "VUE Log Report from " + VUE.getSystemProperty("user.name");
                        
                        try {
                            VueUtil.openURL(Util.makeQueryURL("mailto:" + ReportAddress,
                                                              "subject", subject,
                                                              "body", body));
                        } catch (Throwable t) {
                            t.printStackTrace();
                        }
                    }
                },
                BorderLayout.SOUTH);
            errorDock = GUI.createDockWindow(VueResources.getString("menu.help.vuelog"), panel);
            errorDock.setSize(800,600);
        }
    }

    
    
    public static void main(String args[])
    {
        VUE.init(args);

        // Ensure the tools are loaded to we can see their shortcuts:
        VueToolbarController.getController();
        
        JFrame frame = new JFrame("vueParentWindow");

        // Ensure that all the Actions are instantiated so we can see them:
        tufts.vue.Actions.Delete.toString();
	         
        // Let us see the actual menu bar:
        frame.setJMenuBar(new VueMenuBar());
        frame.setVisible(true); // do this or we can't see the menu bar

        new ShortcutsAction().act();

    }


	public void setMenuEnableFlg(boolean enable) {
		isMenuEnableFontFlg = enable;
		
	}

}

