JAL-1807 still testing
[jalviewjs.git] / unused / appletgui / EmbmenuFrame.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)\r
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors\r
4  * \r
5  * This file is part of Jalview.\r
6  * \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
11  *  \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
16  * \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
20  */\r
21 package jalview.appletgui;\r
22 \r
23 import jalview.util.Platform;\r
24 \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
34 \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
41 \r
42 /**\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
51  * \r
52  * @author Jim Procter and Andrew Waterhouse\r
53  * \r
54  */\r
55 public class EmbmenuFrame extends JFrame implements MouseListener\r
56 {\r
57   protected static final Font FONT_ARIAL_PLAIN_11 = new Font(\r
58             "Arial", Font.PLAIN, 11);\r
59 \r
60   public static final Font DEFAULT_MENU_FONT = FONT_ARIAL_PLAIN_11;\r
61 \r
62   /**\r
63    * map from labels to popup menus for the embedded menubar\r
64    */\r
65   protected Map<JLabel, JPopupMenu> embeddedPopup = new HashMap<JLabel, JPopupMenu>();\r
66 \r
67   /**\r
68    * the embedded menu is built on this and should be added to the frame at the\r
69    * appropriate position.\r
70    * \r
71    */\r
72   protected JPanel embeddedMenu;\r
73 \r
74   public EmbmenuFrame() throws HeadlessException\r
75   {\r
76     super();\r
77   }\r
78 \r
79   public EmbmenuFrame(String title) throws HeadlessException\r
80   {\r
81     //super(title);\r
82   }\r
83 \r
84   /**\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
87    * \r
88    * @param tobeAdjusted\r
89    *          the panel that is to be reduced to make space for the embedded\r
90    *          menu bar\r
91    * @return true if menuBar was embedded and tobeAdjusted's height modified\r
92    */\r
93   protected boolean embedMenuIfNeeded(JPanel tobeAdjusted)\r
94   {\r
95     JMenuBar topMenuBar = getJMenuBar();\r
96     if (topMenuBar == null)\r
97     {\r
98       return false;\r
99     }\r
100     // DEBUG Hint: can test embedded menus by inserting true here.\r
101     if (Platform.isAMac())\r
102     {\r
103       // Build the embedded menu panel, allowing override with system font\r
104       embeddedMenu = makeEmbeddedPopupMenu(topMenuBar, true, false);\r
105       setJMenuBar(null);\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
110       return true;\r
111     }\r
112     return false;\r
113   }\r
114 \r
115   /**\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
119    * \r
120    * @param menuBar\r
121    * @param overrideFonts\r
122    * @param append\r
123    *          true means existing menu will be emptied before adding new\r
124    *          elements\r
125    * @return\r
126    */\r
127   protected JPanel makeEmbeddedPopupMenu(JMenuBar menuBar,\r
128           boolean overrideFonts, boolean append)\r
129   {\r
130     if (!append)\r
131     {\r
132       embeddedPopup.clear(); // TODO: check if j1.1\r
133       if (embeddedMenu != null)\r
134       {\r
135         embeddedMenu.removeAll();\r
136       }\r
137     }\r
138     embeddedMenu = makeEmbeddedPopupMenu(menuBar, DEFAULT_MENU_FONT,\r
139             overrideFonts, new JPanel(), this);\r
140     return embeddedMenu;\r
141   }\r
142 \r
143   /**\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
149    * \r
150    * @param menuBar\r
151    *          must be non-null\r
152    * @param font\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
160    */\r
161   protected JPanel makeEmbeddedPopupMenu(JMenuBar menuBar, Font font,\r
162           boolean overrideFonts,\r
163           JPanel embeddedMenu,\r
164           MouseListener clickHandler)\r
165   {\r
166     if (overrideFonts)\r
167     {\r
168       Font mbf = menuBar.getFont();\r
169       if (mbf != null)\r
170       {\r
171         font = mbf;\r
172       }\r
173     }\r
174     if (embeddedMenu == null)\r
175     {\r
176       embeddedMenu = new JPanel();\r
177     }\r
178     FlowLayout flowLayout1 = new FlowLayout();\r
179     embeddedMenu.setBackground(Color.lightGray);\r
180     embeddedMenu.setLayout(flowLayout1);\r
181     // loop thru\r
182     for (int mbi = 0, nMbi = menuBar.getMenuCount(); mbi < nMbi; mbi++)\r
183     {\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
191       {\r
192         popup.add(mi.getItem(m));\r
193         mSize--;\r
194         m--;\r
195       }\r
196       embeddedPopup.put(elab, popup);\r
197       embeddedMenu.add(elab);\r
198       elab.addMouseListener(clickHandler);\r
199     }\r
200     flowLayout1.setAlignment(FlowLayout.LEFT);\r
201     flowLayout1.setHgap(2);\r
202     flowLayout1.setVgap(0);\r
203     return embeddedMenu;\r
204   }\r
205 \r
206   public void mousePressed(MouseEvent evt)\r
207   {\r
208     JPopupMenu popup = null;\r
209     JLabel source = (JLabel) evt.getSource();\r
210     popup = getPopupMenu(source);\r
211     if (popup != null)\r
212     {\r
213       embeddedMenu.add(popup);\r
214       popup.show(embeddedMenu, source.getBounds().x, source.getBounds().y\r
215               + source.getBounds().getSize().height);\r
216     }\r
217   }\r
218 \r
219   /**\r
220    * get the menu for source from the hash.\r
221    * \r
222    * @param source\r
223    *          what was clicked on.\r
224    */\r
225   JPopupMenu getPopupMenu(JLabel source)\r
226   {\r
227     return embeddedPopup.get(source);\r
228   }\r
229 \r
230   public void mouseClicked(MouseEvent evt)\r
231   {\r
232   }\r
233 \r
234   public void mouseReleased(MouseEvent evt)\r
235   {\r
236   }\r
237 \r
238   public void mouseEntered(MouseEvent evt)\r
239   {\r
240   }\r
241 \r
242   public void mouseExited(MouseEvent evt)\r
243   {\r
244   }\r
245 \r
246   /**\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
249    */\r
250   public void destroyMenus()\r
251   {\r
252     if (embeddedPopup != null)\r
253     {\r
254       for (JLabel lb : embeddedPopup.keySet())\r
255       {\r
256         lb.removeMouseListener(this);\r
257       }\r
258       embeddedPopup.clear();\r
259     }\r
260     if (embeddedMenu != null)\r
261     {\r
262       embeddedMenu.removeAll();\r
263     }\r
264   }\r
265 \r
266   /**\r
267    * calls destroyMenus()\r
268    */\r
269   public void finalize() throws Throwable\r
270   {\r
271     destroyMenus();\r
272     embeddedPopup = null;\r
273     embeddedMenu = null;\r
274     super.finalize();\r
275   }\r
276 }\r