2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
\r
3 * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
\r
5 * This program is free software; you can redistribute it and/or
\r
6 * modify it under the terms of the GNU General Public License
\r
7 * as published by the Free Software Foundation; either version 2
\r
8 * of the License, or (at your option) any later version.
\r
10 * This program is distributed in the hope that it will be useful,
\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 * GNU General Public License for more details.
\r
15 * You should have received a copy of the GNU General Public License
\r
16 * along with this program; if not, write to the Free Software
\r
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
\r
19 package jalview.appletgui;
\r
21 import java.awt.BorderLayout;
\r
22 import java.awt.Color;
\r
23 import java.awt.Container;
\r
24 import java.awt.FlowLayout;
\r
25 import java.awt.Font;
\r
26 import java.awt.Frame;
\r
27 import java.awt.GraphicsConfiguration;
\r
28 import java.awt.HeadlessException;
\r
29 import java.awt.Label;
\r
30 import java.awt.Menu;
\r
31 import java.awt.MenuBar;
\r
32 import java.awt.Panel;
\r
33 import java.awt.PopupMenu;
\r
34 import java.awt.event.ActionListener;
\r
35 import java.awt.event.ItemListener;
\r
36 import java.awt.event.MouseEvent;
\r
37 import java.awt.event.MouseListener;
\r
38 import java.util.Enumeration;
\r
39 import java.util.Hashtable;
\r
42 * This class implements a pattern form embedding toolbars as a panel with
\r
43 * popups for situations where the system menu bar is either invisible or
\r
44 * inappropriate. It was derived from the code for embedding the jalview applet
\r
45 * alignFrame as a component on the web-page, which requires the local
\r
46 * alignFrame menu to be attached to that panel rather than placed on the parent
\r
47 * (which isn't allowed anyhow). TODO: try to modify the embeddedMenu display so
\r
48 * it looks like a real toolbar menu TODO: modify click/mouse handler for
\r
49 * embeddedMenu so it behaves more like a real pulldown menu toolbar
\r
51 * @author Jim Procter and Andrew Waterhouse
\r
54 public class EmbmenuFrame extends Frame implements MouseListener
\r
57 * map from labels to popup menus for the embedded menubar
\r
59 protected Hashtable embeddedPopup;
\r
62 * the embedded menu is built on this and should be added to the frame at the
\r
63 * appropriate position.
\r
66 protected Panel embeddedMenu;
\r
68 public EmbmenuFrame() throws HeadlessException
\r
73 public EmbmenuFrame(String title) throws HeadlessException
\r
79 * Check if the applet is running on a platform that requires the Frame
\r
80 * menuBar to be embedded, and if so, embeds it.
\r
82 * @param tobeAdjusted
\r
83 * the panel that is to be reduced to make space for the
\r
85 * @return true if menuBar was embedded and tobeAdjusted's height modified
\r
87 protected boolean embedMenuIfNeeded(Panel tobeAdjusted)
\r
89 MenuBar topMenuBar = getMenuBar();
\r
90 if (topMenuBar == null)
\r
94 // DEBUG Hint: can test embedded menus by inserting true here.
\r
95 if (new jalview.util.Platform().isAMac())
\r
97 // Build the embedded menu panel
\r
98 embeddedMenu = makeEmbeddedPopupMenu(topMenuBar, "Arial", Font.PLAIN,
\r
99 10, true); // try to pickup system font.
\r
101 // add the components to the TreePanel area.
\r
102 add(embeddedMenu, BorderLayout.NORTH);
\r
103 tobeAdjusted.setSize(getSize().width, getSize().height
\r
104 - embeddedMenu.HEIGHT);
\r
111 * move all menus on menuBar onto embeddedMenu. embeddedPopup is used to store
\r
112 * the popups for each menu removed from the menuBar and added to the panel.
\r
113 * NOTE: it is up to the caller to remove menuBar from the Frame if it is
\r
114 * already attached.
\r
120 * @param overrideFonts
\r
121 * true if we take the menuBar fonts in preference to the
\r
122 * supplied defaults
\r
123 * @return the embedded menu instance to be added to the frame.
\r
125 protected Panel makeEmbeddedPopupMenu(MenuBar menuBar, String fn,
\r
126 int fstyle, int fsz, boolean overrideFonts)
\r
128 return makeEmbeddedPopupMenu(menuBar, fn, fstyle, fsz, overrideFonts,
\r
133 * Create or add elements to the embedded menu from menuBar. This removes all
\r
134 * menu from menuBar and it is up to the caller to remove the now useless
\r
135 * menuBar from the Frame if it is already attached.
\r
141 * @param overrideFonts
\r
143 * true means existing menu will be emptied before adding new
\r
147 protected Panel makeEmbeddedPopupMenu(MenuBar menuBar, String fn,
\r
148 int fstyle, int fsz, boolean overrideFonts, boolean append)
\r
152 if (embeddedPopup != null)
\r
154 embeddedPopup.clear(); // TODO: check if j1.1
\r
156 if (embeddedMenu != null)
\r
158 embeddedMenu.removeAll();
\r
161 if (embeddedPopup == null)
\r
163 embeddedPopup = new Hashtable();
\r
166 embeddedMenu = makeEmbeddedPopupMenu(menuBar, fn, fstyle, fsz,
\r
167 overrideFonts, embeddedPopup, new Panel(), this);
\r
168 return embeddedMenu;
\r
172 * Generic method to move elements from menubar onto embeddedMenu using the
\r
173 * existing or the supplied font, and adds binding from panel to attached
\r
174 * menus in embeddedPopup This removes all menu from menuBar and it is up to
\r
175 * the caller to remove the now useless menuBar from the Frame if it is
\r
176 * already attached.
\r
183 * @param overrideFonts
\r
184 * @param embeddedPopup
\r
186 * @param embeddedMenu
\r
187 * if null, a new panel will be created and returned
\r
188 * @param clickHandler -
\r
189 * usually the instance of EmbmenuFrame that holds references
\r
190 * to embeddedPopup and embeddedMenu
\r
191 * @return the panel instance for convenience.
\r
193 protected Panel makeEmbeddedPopupMenu(MenuBar menuBar, String fn,
\r
194 int fstyle, int fsz, boolean overrideFonts,
\r
195 Hashtable embeddedPopup, Panel embeddedMenu,
\r
196 MouseListener clickHandler)
\r
198 if (embeddedPopup == null)
\r
201 "Implementation error - embeddedPopup must be non-null");
\r
205 Font mbf = menuBar.getFont();
\r
208 fn = mbf.getName();
\r
209 fstyle = mbf.getStyle();
\r
210 fsz = mbf.getSize();
\r
213 if (embeddedMenu == null)
\r
214 embeddedMenu = new Panel();
\r
215 FlowLayout flowLayout1 = new FlowLayout();
\r
216 embeddedMenu.setBackground(Color.lightGray);
\r
217 embeddedMenu.setLayout(flowLayout1);
\r
219 for (int mbi = 0, nMbi = menuBar.getMenuCount(); mbi < nMbi; mbi++)
\r
221 Menu mi = menuBar.getMenu(mbi);
\r
222 Label elab = new Label(mi.getLabel());
\r
223 elab.setFont(new java.awt.Font(fn, fstyle, fsz));
\r
224 // add the menu entries
\r
225 PopupMenu popup = new PopupMenu();
\r
226 int m, mSize = mi.getItemCount();
\r
227 for (m = 0; m < mSize; m++)
\r
229 popup.add(mi.getItem(m));
\r
233 embeddedPopup.put(elab, popup);
\r
234 embeddedMenu.add(elab);
\r
235 elab.addMouseListener(clickHandler);
\r
237 flowLayout1.setAlignment(FlowLayout.LEFT);
\r
238 flowLayout1.setHgap(2);
\r
239 flowLayout1.setVgap(0);
\r
240 return embeddedMenu;
\r
243 public void mousePressed(MouseEvent evt)
\r
245 PopupMenu popup = null;
\r
246 Label source = (Label) evt.getSource();
\r
247 popup = getPopupMenu(source);
\r
250 embeddedMenu.add(popup);
\r
251 popup.show(embeddedMenu, source.getBounds().x, source.getBounds().y
\r
252 + source.getBounds().getSize().height);
\r
257 * get the menu for source from the hash.
\r
260 * what was clicked on.
\r
262 PopupMenu getPopupMenu(Label source)
\r
264 return (PopupMenu) embeddedPopup.get(source);
\r
267 public void mouseClicked(MouseEvent evt)
\r
271 public void mouseReleased(MouseEvent evt)
\r
275 public void mouseEntered(MouseEvent evt)
\r
279 public void mouseExited(MouseEvent evt)
\r
284 * called to clear the GUI resources taken up for embedding and remove any
\r
285 * self references so we can be garbage collected.
\r
287 public void destroyMenus()
\r
289 if (embeddedPopup != null)
\r
291 Enumeration e = embeddedPopup.keys();
\r
292 while (e.hasMoreElements())
\r
294 Label lb = (Label) e.nextElement();
\r
295 lb.removeMouseListener(this);
\r
297 embeddedPopup.clear();
\r
299 if (embeddedMenu != null)
\r
301 embeddedMenu.removeAll();
\r
306 * calls destroyMenus()
\r
308 public void finalize() throws Throwable
\r
311 embeddedPopup = null;
\r
312 embeddedMenu = null;
\r