2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
\r
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
\r
5 * This file is part of Jalview.
\r
7 * Jalview is free software: you can redistribute it and/or
\r
8 * modify it under the terms of the GNU General Public License
\r
9 * as published by the Free Software Foundation, either version 3
\r
10 * of the License, or (at your option) any later version.
\r
12 * Jalview is distributed in the hope that it will be useful, but
\r
13 * WITHOUT ANY WARRANTY; without even the implied warranty
\r
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
\r
15 * PURPOSE. See the GNU General Public License for more details.
\r
17 * You should have received a copy of the GNU General Public License
\r
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
\r
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
\r
21 package jalview.appletgui;
\r
23 import jalview.util.Platform;
\r
25 import java.awt.BorderLayout;
\r
26 import java.awt.Color;
\r
27 import java.awt.FlowLayout;
\r
28 import java.awt.Font;
\r
29 import java.awt.HeadlessException;
\r
30 import java.awt.event.MouseEvent;
\r
31 import java.awt.event.MouseListener;
\r
32 import java.util.HashMap;
\r
33 import java.util.Map;
\r
35 import javax.swing.JFrame;
\r
36 import javax.swing.JLabel;
\r
37 import javax.swing.JMenu;
\r
38 import javax.swing.JMenuBar;
\r
39 import javax.swing.JPanel;
\r
40 import javax.swing.JPopupMenu;
\r
43 * This class implements a pattern for embedding toolbars as a panel with popups
\r
44 * for situations where the system menu bar is either invisible or
\r
45 * inappropriate. It was derived from the code for embedding the jalview applet
\r
46 * alignFrame as a component on the web-page, which requires the local
\r
47 * alignFrame menu to be attached to that panel rather than placed on the parent
\r
48 * (which isn't allowed anyhow). TODO: try to modify the embeddedMenu display so
\r
49 * it looks like a real toolbar menu TODO: modify click/mouse handler for
\r
50 * embeddedMenu so it behaves more like a real pulldown menu toolbar
\r
52 * @author Jim Procter and Andrew Waterhouse
\r
55 public class EmbmenuFrame extends JFrame implements MouseListener
\r
57 protected static final Font FONT_ARIAL_PLAIN_11 = new Font(
\r
58 "Arial", Font.PLAIN, 11);
\r
60 public static final Font DEFAULT_MENU_FONT = FONT_ARIAL_PLAIN_11;
\r
63 * map from labels to popup menus for the embedded menubar
\r
65 protected Map<JLabel, JPopupMenu> embeddedPopup = new HashMap<JLabel, JPopupMenu>();
\r
68 * the embedded menu is built on this and should be added to the frame at the
\r
69 * appropriate position.
\r
72 protected JPanel embeddedMenu;
\r
74 public EmbmenuFrame() throws HeadlessException
\r
79 public EmbmenuFrame(String title) throws HeadlessException
\r
85 * Check if the applet is running on a platform that requires the Frame
\r
86 * menuBar to be embedded, and if so, embeds it.
\r
88 * @param tobeAdjusted
\r
89 * the panel that is to be reduced to make space for the embedded
\r
91 * @return true if menuBar was embedded and tobeAdjusted's height modified
\r
93 protected boolean embedMenuIfNeeded(JPanel tobeAdjusted)
\r
95 JMenuBar topMenuBar = getJMenuBar();
\r
96 if (topMenuBar == null)
\r
100 // DEBUG Hint: can test embedded menus by inserting true here.
\r
101 if (Platform.isAMac())
\r
103 // Build the embedded menu panel, allowing override with system font
\r
104 embeddedMenu = makeEmbeddedPopupMenu(topMenuBar, true, false);
\r
106 // add the components to the Panel area.
\r
107 add(embeddedMenu, BorderLayout.NORTH);
\r
108 tobeAdjusted.setSize(getSize().width,
\r
109 getSize().height - embeddedMenu.getHeight());
\r
116 * Create or add elements to the embedded menu from menuBar. This removes all
\r
117 * menu from menuBar and it is up to the caller to remove the now useless
\r
118 * menuBar from the Frame if it is already attached.
\r
121 * @param overrideFonts
\r
123 * true means existing menu will be emptied before adding new
\r
127 protected JPanel makeEmbeddedPopupMenu(JMenuBar menuBar,
\r
128 boolean overrideFonts, boolean append)
\r
132 embeddedPopup.clear(); // TODO: check if j1.1
\r
133 if (embeddedMenu != null)
\r
135 embeddedMenu.removeAll();
\r
138 embeddedMenu = makeEmbeddedPopupMenu(menuBar, DEFAULT_MENU_FONT,
\r
139 overrideFonts, new JPanel(), this);
\r
140 return embeddedMenu;
\r
144 * Generic method to move elements from menubar onto embeddedMenu using the
\r
145 * existing or the supplied font, and adds binding from panel to attached
\r
146 * menus in embeddedPopup This removes all menu from menuBar and it is up to
\r
147 * the caller to remove the now useless menuBar from the Frame if it is
\r
148 * already attached.
\r
153 * @param overrideFonts
\r
154 * @param embeddedMenu
\r
155 * if null, a new panel will be created and returned
\r
156 * @param clickHandler
\r
157 * - usually the instance of EmbmenuFrame that holds references to
\r
158 * embeddedPopup and embeddedMenu
\r
159 * @return the panel instance for convenience.
\r
161 protected JPanel makeEmbeddedPopupMenu(JMenuBar menuBar, Font font,
\r
162 boolean overrideFonts,
\r
163 JPanel embeddedMenu,
\r
164 MouseListener clickHandler)
\r
168 Font mbf = menuBar.getFont();
\r
174 if (embeddedMenu == null)
\r
176 embeddedMenu = new JPanel();
\r
178 FlowLayout flowLayout1 = new FlowLayout();
\r
179 embeddedMenu.setBackground(Color.lightGray);
\r
180 embeddedMenu.setLayout(flowLayout1);
\r
182 for (int mbi = 0, nMbi = menuBar.getMenuCount(); mbi < nMbi; mbi++)
\r
184 JMenu mi = menuBar.getMenu(mbi);
\r
185 JLabel elab = new JLabel(mi.getLabel());
\r
186 elab.setFont(font);
\r
187 // add the menu entries
\r
188 JPopupMenu popup = new JPopupMenu();
\r
189 int m, mSize = mi.getItemCount();
\r
190 for (m = 0; m < mSize; m++)
\r
192 popup.add(mi.getItem(m));
\r
196 embeddedPopup.put(elab, popup);
\r
197 embeddedMenu.add(elab);
\r
198 elab.addMouseListener(clickHandler);
\r
200 flowLayout1.setAlignment(FlowLayout.LEFT);
\r
201 flowLayout1.setHgap(2);
\r
202 flowLayout1.setVgap(0);
\r
203 return embeddedMenu;
\r
206 public void mousePressed(MouseEvent evt)
\r
208 JPopupMenu popup = null;
\r
209 JLabel source = (JLabel) evt.getSource();
\r
210 popup = getPopupMenu(source);
\r
213 embeddedMenu.add(popup);
\r
214 popup.show(embeddedMenu, source.getBounds().x, source.getBounds().y
\r
215 + source.getBounds().getSize().height);
\r
220 * get the menu for source from the hash.
\r
223 * what was clicked on.
\r
225 JPopupMenu getPopupMenu(JLabel source)
\r
227 return embeddedPopup.get(source);
\r
230 public void mouseClicked(MouseEvent evt)
\r
234 public void mouseReleased(MouseEvent evt)
\r
238 public void mouseEntered(MouseEvent evt)
\r
242 public void mouseExited(MouseEvent evt)
\r
247 * called to clear the GUI resources taken up for embedding and remove any
\r
248 * self references so we can be garbage collected.
\r
250 public void destroyMenus()
\r
252 if (embeddedPopup != null)
\r
254 for (JLabel lb : embeddedPopup.keySet())
\r
256 lb.removeMouseListener(this);
\r
258 embeddedPopup.clear();
\r
260 if (embeddedMenu != null)
\r
262 embeddedMenu.removeAll();
\r
267 * calls destroyMenus()
\r
269 public void finalize() throws Throwable
\r
272 embeddedPopup = null;
\r
273 embeddedMenu = null;
\r