JAL-2089 patch broken merge to master for Release 2.10.0b1
[jalview.git] / src / jalview / appletgui / EmbmenuFrame.java
index 23f6aa2..f61077a 100644 (file)
-package jalview.appletgui;\r
-\r
-import java.awt.BorderLayout;\r
-import java.awt.Color;\r
-import java.awt.Container;\r
-import java.awt.FlowLayout;\r
-import java.awt.Font;\r
-import java.awt.Frame;\r
-import java.awt.GraphicsConfiguration;\r
-import java.awt.HeadlessException;\r
-import java.awt.Label;\r
-import java.awt.Menu;\r
-import java.awt.MenuBar;\r
-import java.awt.Panel;\r
-import java.awt.PopupMenu;\r
-import java.awt.event.ActionListener;\r
-import java.awt.event.ItemListener;\r
-import java.awt.event.MouseEvent;\r
-import java.awt.event.MouseListener;\r
-import java.util.Enumeration;\r
-import java.util.Hashtable;\r
-/**\r
- * This class implements a pattern form embedding toolbars as a panel with popups\r
- * for situations where the system menu bar is either invisible or inappropriate.\r
- * It was derived from the code for embedding the jalview applet alignFrame as\r
- * a component on the web-page, which requires the local alignFrame menu to be\r
- * attached to that panel rather than placed on the parent (which isn't allowed\r
- * anyhow).\r
- * TODO: try to modify the embeddedMenu display so it looks like a real toolbar menu\r
- * TODO: modify click/mouse handler for embeddedMenu so it behaves more like a real pulldown menu toolbar\r
- * \r
- * @author Jim Procter and Andrew Waterhouse\r
- *\r
- */\r
-public class EmbmenuFrame extends Frame implements MouseListener\r
-{\r
-  /**\r
-   * map from labels to popup menus for the embedded menubar\r
-   */\r
-  protected Hashtable embeddedPopup;\r
-  /**\r
-   * the embedded menu is built on this and should be \r
-   * added to the frame at the appropriate position.\r
-   * \r
-   */\r
-  protected Panel embeddedMenu;\r
-\r
-  public EmbmenuFrame() throws HeadlessException\r
-  {\r
-    super();\r
-  }\r
-  public EmbmenuFrame(String title) throws HeadlessException\r
-  {\r
-    super(title);\r
-  }\r
-  /**\r
-   * Check if the applet is running on a platform that requires the Frame menuBar to be embedded,\r
-   * and if so, embeds it.\r
-   * @param tobeAdjusted the panel that is to be reduced to make space for the embedded menu bar\r
-   * @return true if menuBar was embedded and tobeAdjusted's height modified\r
-   */\r
-  protected boolean embedMenuIfNeeded(Panel tobeAdjusted)\r
-  {\r
-    MenuBar topMenuBar = getMenuBar();\r
-    if (topMenuBar==null)\r
-    {\r
-      return false;\r
-    }\r
-    // DEBUG Hint: can test embedded menus by inserting true here.\r
-    if (new jalview.util.Platform().isAMac())\r
-    {\r
-      // Build the embedded menu panel\r
-      embeddedMenu = makeEmbeddedPopupMenu(topMenuBar, "Arial", Font.PLAIN, 10, true); // try to pickup system font.\r
-      setMenuBar(null);\r
-      // add the components to the TreePanel area.\r
-      add(embeddedMenu, BorderLayout.NORTH);\r
-      tobeAdjusted.setSize(getSize().width,\r
-              getSize().height\r
-              - embeddedMenu.HEIGHT);        \r
-      return true;\r
-    }\r
-    return false;\r
-  }\r
-  /**\r
-   * move all menus on menuBar onto embeddedMenu.\r
-   * embeddedPopup is used to store the popups for each menu removed from the menuBar and added\r
-   * to the panel.\r
-   * NOTE: it is up to the caller to remove menuBar from the Frame if it is already attached.\r
-   * @param menuBar\r
-   * @param fn\r
-   * @param fstyle\r
-   * @param fsz\r
-   * @param overrideFonts true if we take the menuBar fonts in preference to the supplied defaults\r
-   * @return the embedded menu instance to be added to the frame.\r
-   */\r
-  protected Panel makeEmbeddedPopupMenu(MenuBar menuBar, String fn,\r
-          int fstyle, int fsz, boolean overrideFonts)\r
-  {\r
-    return makeEmbeddedPopupMenu(menuBar, fn, fstyle, fsz, overrideFonts, false);\r
-  }\r
-  /**\r
-   * Create or add elements to the embedded menu from menuBar. This removes all menu from\r
-   * menuBar and it is up to the caller to remove the now useless menuBar from the Frame if it is already attached. \r
-   * @param menuBar\r
-   * @param fn\r
-   * @param fstyle\r
-   * @param fsz\r
-   * @param overrideFonts \r
-   * @param append true means existing menu will be emptied before adding new elements\r
-   * @return\r
-   */\r
-  protected Panel makeEmbeddedPopupMenu(MenuBar menuBar, String fn,\r
-          int fstyle, int fsz, boolean overrideFonts, boolean append)\r
-  {\r
-    if (!append)\r
-    {\r
-      if (embeddedPopup != null)\r
-      {\r
-        embeddedPopup.clear(); // TODO: check if j1.1\r
-      } \r
-      if (embeddedMenu!=null)\r
-      {\r
-        embeddedMenu.removeAll(); \r
-      }\r
-    }\r
-    if (embeddedPopup==null)\r
-    {\r
-      embeddedPopup = new Hashtable();\r
-    }\r
-    \r
-    embeddedMenu = makeEmbeddedPopupMenu(menuBar, fn, fstyle, fsz, overrideFonts, embeddedPopup, new Panel(), this);\r
-    return embeddedMenu;\r
-  }\r
-  /**\r
-   * Generic method to move elements from menubar onto embeddedMenu using the existing or the supplied font, \r
-   * and adds binding from panel to attached menus in embeddedPopup\r
-   * This removes all menu from\r
-   * menuBar and it is up to the caller to remove the now useless menuBar from the Frame if it is already attached.\r
-   * @param menuBar must be non-null\r
-   * @param fn\r
-   * @param fstyle\r
-   * @param fsz\r
-   * @param overrideFonts\r
-   * @param embeddedPopup must be non-null\r
-   * @param embeddedMenu if null, a new panel will be created and returned\r
-   * @param clickHandler - usually the instance of EmbmenuFrame that holds references to embeddedPopup and embeddedMenu\r
-   * @return the panel instance for convenience.\r
-   */\r
-  protected Panel makeEmbeddedPopupMenu(MenuBar menuBar, String fn,\r
-          int fstyle, int fsz, boolean overrideFonts, Hashtable embeddedPopup, Panel embeddedMenu, MouseListener clickHandler)\r
-  {\r
-    if (embeddedPopup==null)\r
-    {\r
-      throw new Error("Implementation error - embeddedPopup must be non-null");\r
-    }\r
-    if (overrideFonts)\r
-    {\r
-      Font mbf = menuBar.getFont();\r
-      if (mbf!=null)\r
-      {\r
-        fn = mbf.getName();\r
-        fstyle = mbf.getStyle();\r
-        fsz = mbf.getSize();\r
-      }\r
-    }\r
-    if (embeddedMenu==null)\r
-      embeddedMenu = new Panel();\r
-    FlowLayout flowLayout1 = new FlowLayout();\r
-    embeddedMenu.setBackground(Color.lightGray);\r
-    embeddedMenu.setLayout(flowLayout1);\r
-    // loop thru\r
-    for (int mbi = 0,nMbi=menuBar.getMenuCount(); mbi<nMbi; mbi++)\r
-    {\r
-      Menu mi = menuBar.getMenu(mbi);\r
-      Label elab = new Label(mi.getLabel());\r
-      elab.setFont(new java.awt.Font(fn, fstyle, fsz));\r
-      // add the menu entries\r
-      PopupMenu popup = new PopupMenu();\r
-      int m, mSize = mi.getItemCount();\r
-      for (m = 0; m < mSize; m++)\r
-      {\r
-        popup.add(mi.getItem(m));\r
-        mSize--;\r
-        m--;\r
-      }\r
-      embeddedPopup.put(elab, popup);\r
-      embeddedMenu.add(elab);\r
-      elab.addMouseListener(clickHandler);\r
-    }\r
-    flowLayout1.setAlignment(FlowLayout.LEFT);\r
-    flowLayout1.setHgap(2);\r
-    flowLayout1.setVgap(0);\r
-    return embeddedMenu;\r
-  }\r
-\r
-  public void mousePressed(MouseEvent evt)\r
-  {\r
-    PopupMenu popup = null;\r
-    Label source = (Label) evt.getSource();\r
-    popup = getPopupMenu(source);\r
-    if (popup!=null)\r
-    {\r
-      embeddedMenu.add(popup);\r
-      popup.show(embeddedMenu,\r
-               source.getBounds().x,\r
-               source.getBounds().y + source.getBounds().getSize().height);\r
-    }\r
-  }\r
-\r
-  /**\r
-   * get the menu for source from the hash.\r
-   * @param source what was clicked on.\r
-   */\r
-  PopupMenu getPopupMenu(Label source)\r
-  {\r
-    return (PopupMenu) embeddedPopup.get(source);\r
-  }\r
-\r
-  public void mouseClicked(MouseEvent evt)\r
-  {}\r
-\r
-  public void mouseReleased(MouseEvent evt)\r
-  {}\r
-\r
-  public void mouseEntered(MouseEvent evt)\r
-  {}\r
-\r
-  public void mouseExited(MouseEvent evt)\r
-  {}\r
-\r
-  /**\r
-   * called to clear the GUI resources taken up for embedding\r
-   * and remove any self references so we can be garbage collected.\r
-   */\r
-  public void destroyMenus()\r
-  {\r
-    if (embeddedPopup!=null)\r
-    {\r
-      Enumeration e = embeddedPopup.keys();\r
-      while (e.hasMoreElements())\r
-      {\r
-        Label lb = (Label) e.nextElement();\r
-        lb.removeMouseListener(this);\r
-      }\r
-      embeddedPopup.clear();\r
-    }\r
-    if (embeddedMenu!=null)\r
-    {\r
-      embeddedMenu.removeAll();\r
-    }\r
-  }\r
-  /**\r
-   * calls destroyMenus()\r
-   */\r
-  public void finalize() throws Throwable {\r
-    destroyMenus();\r
-    embeddedPopup=null;\r
-    embeddedMenu=null;\r
-    super.finalize();\r
-  }\r
-}
\ No newline at end of file
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.appletgui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.HeadlessException;
+import java.awt.Label;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.Panel;
+import java.awt.PopupMenu;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class implements a pattern for embedding toolbars as a panel with popups
+ * for situations where the system menu bar is either invisible or
+ * inappropriate. It was derived from the code for embedding the jalview applet
+ * alignFrame as a component on the web-page, which requires the local
+ * alignFrame menu to be attached to that panel rather than placed on the parent
+ * (which isn't allowed anyhow). TODO: try to modify the embeddedMenu display so
+ * it looks like a real toolbar menu TODO: modify click/mouse handler for
+ * embeddedMenu so it behaves more like a real pulldown menu toolbar
+ * 
+ * @author Jim Procter and Andrew Waterhouse
+ * 
+ */
+public class EmbmenuFrame extends Frame implements MouseListener
+{
+  protected static final Font FONT_ARIAL_PLAIN_11 = new Font("Arial",
+          Font.PLAIN, 11);
+
+  public static final Font DEFAULT_MENU_FONT = FONT_ARIAL_PLAIN_11;
+
+  /**
+   * map from labels to popup menus for the embedded menubar
+   */
+  protected Map<Label, PopupMenu> embeddedPopup = new HashMap<Label, PopupMenu>();
+
+  /**
+   * the embedded menu is built on this and should be added to the frame at the
+   * appropriate position.
+   * 
+   */
+  protected Panel embeddedMenu;
+
+  public EmbmenuFrame() throws HeadlessException
+  {
+    super();
+  }
+
+  public EmbmenuFrame(String title) throws HeadlessException
+  {
+    super(title);
+  }
+
+  /**
+   * Check if the applet is running on a platform that requires the Frame
+   * menuBar to be embedded, and if so, embeds it.
+   * 
+   * @param tobeAdjusted
+   *          the panel that is to be reduced to make space for the embedded
+   *          menu bar
+   * @return true if menuBar was embedded and tobeAdjusted's height modified
+   */
+  protected boolean embedMenuIfNeeded(Panel tobeAdjusted)
+  {
+    MenuBar topMenuBar = getMenuBar();
+    if (topMenuBar == null)
+    {
+      return false;
+    }
+    // DEBUG Hint: can test embedded menus by inserting true here.
+    if (new jalview.util.Platform().isAMac())
+    {
+      // Build the embedded menu panel, allowing override with system font
+      embeddedMenu = makeEmbeddedPopupMenu(topMenuBar, true, false);
+      setMenuBar(null);
+      // add the components to the Panel area.
+      add(embeddedMenu, BorderLayout.NORTH);
+      tobeAdjusted.setSize(getSize().width,
+              getSize().height - embeddedMenu.getHeight());
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Create or add elements to the embedded menu from menuBar. This removes all
+   * menu from menuBar and it is up to the caller to remove the now useless
+   * menuBar from the Frame if it is already attached.
+   * 
+   * @param menuBar
+   * @param overrideFonts
+   * @param append
+   *          true means existing menu will be emptied before adding new
+   *          elements
+   * @return
+   */
+  protected Panel makeEmbeddedPopupMenu(MenuBar menuBar,
+          boolean overrideFonts, boolean append)
+  {
+    if (!append)
+    {
+      embeddedPopup.clear(); // TODO: check if j1.1
+      if (embeddedMenu != null)
+      {
+        embeddedMenu.removeAll();
+      }
+    }
+    embeddedMenu = makeEmbeddedPopupMenu(menuBar, DEFAULT_MENU_FONT,
+            overrideFonts, new Panel(), this);
+    return embeddedMenu;
+  }
+
+  /**
+   * Generic method to move elements from menubar onto embeddedMenu using the
+   * existing or the supplied font, and adds binding from panel to attached
+   * menus in embeddedPopup This removes all menu from menuBar and it is up to
+   * the caller to remove the now useless menuBar from the Frame if it is
+   * already attached.
+   * 
+   * @param menuBar
+   *          must be non-null
+   * @param font
+   * @param overrideFonts
+   * @param embeddedMenu
+   *          if null, a new panel will be created and returned
+   * @param clickHandler
+   *          - usually the instance of EmbmenuFrame that holds references to
+   *          embeddedPopup and embeddedMenu
+   * @return the panel instance for convenience.
+   */
+  protected Panel makeEmbeddedPopupMenu(MenuBar menuBar, Font font,
+          boolean overrideFonts, Panel embeddedMenu,
+          MouseListener clickHandler)
+  {
+    if (overrideFonts)
+    {
+      Font mbf = menuBar.getFont();
+      if (mbf != null)
+      {
+        font = mbf;
+      }
+    }
+    if (embeddedMenu == null)
+    {
+      embeddedMenu = new Panel();
+    }
+    FlowLayout flowLayout1 = new FlowLayout();
+    embeddedMenu.setBackground(Color.lightGray);
+    embeddedMenu.setLayout(flowLayout1);
+    // loop thru
+    for (int mbi = 0, nMbi = menuBar.getMenuCount(); mbi < nMbi; mbi++)
+    {
+      Menu mi = menuBar.getMenu(mbi);
+      Label elab = new Label(mi.getLabel());
+      elab.setFont(font);
+      // add the menu entries
+      PopupMenu popup = new PopupMenu();
+      int m, mSize = mi.getItemCount();
+      for (m = 0; m < mSize; m++)
+      {
+        popup.add(mi.getItem(m));
+        mSize--;
+        m--;
+      }
+      embeddedPopup.put(elab, popup);
+      embeddedMenu.add(elab);
+      elab.addMouseListener(clickHandler);
+    }
+    flowLayout1.setAlignment(FlowLayout.LEFT);
+    flowLayout1.setHgap(2);
+    flowLayout1.setVgap(0);
+    return embeddedMenu;
+  }
+
+  public void mousePressed(MouseEvent evt)
+  {
+    PopupMenu popup = null;
+    Label source = (Label) evt.getSource();
+    popup = getPopupMenu(source);
+    if (popup != null)
+    {
+      embeddedMenu.add(popup);
+      popup.show(embeddedMenu, source.getBounds().x, source.getBounds().y
+              + source.getBounds().getSize().height);
+    }
+  }
+
+  /**
+   * get the menu for source from the hash.
+   * 
+   * @param source
+   *          what was clicked on.
+   */
+  PopupMenu getPopupMenu(Label source)
+  {
+    return embeddedPopup.get(source);
+  }
+
+  public void mouseClicked(MouseEvent evt)
+  {
+  }
+
+  public void mouseReleased(MouseEvent evt)
+  {
+  }
+
+  public void mouseEntered(MouseEvent evt)
+  {
+  }
+
+  public void mouseExited(MouseEvent evt)
+  {
+  }
+
+  /**
+   * called to clear the GUI resources taken up for embedding and remove any
+   * self references so we can be garbage collected.
+   */
+  public void destroyMenus()
+  {
+    if (embeddedPopup != null)
+    {
+      for (Label lb : embeddedPopup.keySet())
+      {
+        lb.removeMouseListener(this);
+      }
+      embeddedPopup.clear();
+    }
+    if (embeddedMenu != null)
+    {
+      embeddedMenu.removeAll();
+    }
+  }
+
+  /**
+   * calls destroyMenus()
+   */
+  public void finalize() throws Throwable
+  {
+    destroyMenus();
+    embeddedPopup = null;
+    embeddedMenu = null;
+    super.finalize();
+  }
+}