-/*\r
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)\r
- * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle\r
- * \r
- * This file is part of Jalview.\r
- * \r
- * Jalview is free software: you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License \r
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\r
- * \r
- * Jalview is distributed in the hope that it will be useful, but \r
- * WITHOUT ANY WARRANTY; without even the implied warranty \r
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
- * PURPOSE. See the GNU General Public License for more details.\r
- * \r
- * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-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
-/**\r
- * This class implements a pattern form embedding toolbars as a panel with\r
- * popups for situations where the system menu bar is either invisible or\r
- * inappropriate. It was derived from the code for embedding the jalview applet\r
- * alignFrame as a component on the web-page, which requires the local\r
- * alignFrame menu to be attached to that panel rather than placed on the parent\r
- * (which isn't allowed anyhow). TODO: try to modify the embeddedMenu display so\r
- * it looks like a real toolbar menu TODO: modify click/mouse handler for\r
- * 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
- /**\r
- * the embedded menu is built on this and should be added to the frame at the\r
- * appropriate position.\r
- * \r
- */\r
- protected Panel embeddedMenu;\r
-\r
- public EmbmenuFrame() throws HeadlessException\r
- {\r
- super();\r
- }\r
-\r
- public EmbmenuFrame(String title) throws HeadlessException\r
- {\r
- super(title);\r
- }\r
-\r
- /**\r
- * Check if the applet is running on a platform that requires the Frame\r
- * menuBar to be embedded, and if so, embeds it.\r
- * \r
- * @param tobeAdjusted\r
- * the panel that is to be reduced to make space for the embedded\r
- * 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,\r
- 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, getSize().height\r
- - embeddedMenu.HEIGHT);\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * move all menus on menuBar onto embeddedMenu. embeddedPopup is used to store\r
- * the popups for each menu removed from the menuBar and added to the panel.\r
- * NOTE: it is up to the caller to remove menuBar from the Frame if it is\r
- * already attached.\r
- * \r
- * @param menuBar\r
- * @param fn\r
- * @param fstyle\r
- * @param fsz\r
- * @param overrideFonts\r
- * true if we take the menuBar fonts in preference to the supplied\r
- * 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,\r
- false);\r
- }\r
-\r
- /**\r
- * Create or add elements to the embedded menu from menuBar. This removes all\r
- * menu from menuBar and it is up to the caller to remove the now useless\r
- * menuBar from the Frame if it is already attached.\r
- * \r
- * @param menuBar\r
- * @param fn\r
- * @param fstyle\r
- * @param fsz\r
- * @param overrideFonts\r
- * @param append\r
- * true means existing menu will be emptied before adding new\r
- * 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,\r
- overrideFonts, embeddedPopup, new Panel(), this);\r
- return embeddedMenu;\r
- }\r
-\r
- /**\r
- * Generic method to move elements from menubar onto embeddedMenu using the\r
- * existing or the supplied font, and adds binding from panel to attached\r
- * menus in embeddedPopup This removes all menu from menuBar and it is up to\r
- * the caller to remove the now useless menuBar from the Frame if it is\r
- * already attached.\r
- * \r
- * @param menuBar\r
- * must be non-null\r
- * @param fn\r
- * @param fstyle\r
- * @param fsz\r
- * @param overrideFonts\r
- * @param embeddedPopup\r
- * must be non-null\r
- * @param embeddedMenu\r
- * if null, a new panel will be created and returned\r
- * @param clickHandler\r
- * - usually the instance of EmbmenuFrame that holds references to\r
- * 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,\r
- Hashtable embeddedPopup, Panel embeddedMenu,\r
- MouseListener clickHandler)\r
- {\r
- if (embeddedPopup == null)\r
- {\r
- throw new Error(\r
- "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, source.getBounds().x, source.getBounds().y\r
- + source.getBounds().getSize().height);\r
- }\r
- }\r
-\r
- /**\r
- * get the menu for source from the hash.\r
- * \r
- * @param source\r
- * 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
-\r
- public void mouseReleased(MouseEvent evt)\r
- {\r
- }\r
-\r
- public void mouseEntered(MouseEvent evt)\r
- {\r
- }\r
-\r
- public void mouseExited(MouseEvent evt)\r
- {\r
- }\r
-\r
- /**\r
- * called to clear the GUI resources taken up for embedding and remove any\r
- * 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
- /**\r
- * calls destroyMenus()\r
- */\r
- public void finalize() throws Throwable\r
- {\r
- destroyMenus();\r
- embeddedPopup = null;\r
- embeddedMenu = null;\r
- super.finalize();\r
- }\r
-}\r
+/*
+ * 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, AutoCloseable
+{
+ 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<>();
+
+ /**
+ * 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;
+ }
+
+ @Override
+ 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);
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent evt)
+ {
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent evt)
+ {
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent evt)
+ {
+ }
+
+ @Override
+ 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()
+ */
+ @Override
+ public void close()
+ {
+ destroyMenus();
+ embeddedPopup = null;
+ embeddedMenu = null;
+ // no close for Frame
+ // super.finalize();
+ }
+}