JAL-1807 update
[jalviewjs.git] / unused / appletgui / EmbmenuFrame.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.appletgui;
22
23 import jalview.util.Platform;
24
25 import java.awt.BorderLayout;
26 import java.awt.Color;
27 import java.awt.FlowLayout;
28 import java.awt.Font;
29 import java.awt.HeadlessException;
30 import java.awt.event.MouseEvent;
31 import java.awt.event.MouseListener;
32 import java.util.HashMap;
33 import java.util.Map;
34
35 import javax.swing.JFrame;
36 import javax.swing.JLabel;
37 import javax.swing.JMenu;
38 import javax.swing.JMenuBar;
39 import javax.swing.JPanel;
40 import javax.swing.JPopupMenu;
41
42 /**
43  * This class implements a pattern for embedding toolbars as a panel with popups
44  * for situations where the system menu bar is either invisible or
45  * inappropriate. It was derived from the code for embedding the jalview applet
46  * alignFrame as a component on the web-page, which requires the local
47  * alignFrame menu to be attached to that panel rather than placed on the parent
48  * (which isn't allowed anyhow). TODO: try to modify the embeddedMenu display so
49  * it looks like a real toolbar menu TODO: modify click/mouse handler for
50  * embeddedMenu so it behaves more like a real pulldown menu toolbar
51  * 
52  * @author Jim Procter and Andrew Waterhouse
53  * 
54  */
55 public class EmbmenuFrame extends JFrame implements MouseListener
56 {
57   protected static final Font FONT_ARIAL_PLAIN_11 = new Font(
58             "Arial", Font.PLAIN, 11);
59
60   public static final Font DEFAULT_MENU_FONT = FONT_ARIAL_PLAIN_11;
61
62   /**
63    * map from labels to popup menus for the embedded menubar
64    */
65   protected Map<JLabel, JPopupMenu> embeddedPopup = new HashMap<JLabel, JPopupMenu>();
66
67   /**
68    * the embedded menu is built on this and should be added to the frame at the
69    * appropriate position.
70    * 
71    */
72   protected JPanel embeddedMenu;
73
74   public EmbmenuFrame() throws HeadlessException
75   {
76     super();
77   }
78
79   public EmbmenuFrame(String title) throws HeadlessException
80   {
81     //super(title);
82   }
83
84   /**
85    * Check if the applet is running on a platform that requires the Frame
86    * menuBar to be embedded, and if so, embeds it.
87    * 
88    * @param tobeAdjusted
89    *          the panel that is to be reduced to make space for the embedded
90    *          menu bar
91    * @return true if menuBar was embedded and tobeAdjusted's height modified
92    */
93   protected boolean embedMenuIfNeeded(JPanel tobeAdjusted)
94   {
95     JMenuBar topMenuBar = getJMenuBar();
96     if (topMenuBar == null)
97     {
98       return false;
99     }
100     // DEBUG Hint: can test embedded menus by inserting true here.
101     if (Platform.isAMac())
102     {
103       // Build the embedded menu panel, allowing override with system font
104       embeddedMenu = makeEmbeddedPopupMenu(topMenuBar, true, false);
105       setJMenuBar(null);
106       // add the components to the Panel area.
107       add(embeddedMenu, BorderLayout.NORTH);
108       tobeAdjusted.setSize(getSize().width,
109               getSize().height - embeddedMenu.getHeight());
110       return true;
111     }
112     return false;
113   }
114
115   /**
116    * Create or add elements to the embedded menu from menuBar. This removes all
117    * menu from menuBar and it is up to the caller to remove the now useless
118    * menuBar from the Frame if it is already attached.
119    * 
120    * @param menuBar
121    * @param overrideFonts
122    * @param append
123    *          true means existing menu will be emptied before adding new
124    *          elements
125    * @return
126    */
127   protected JPanel makeEmbeddedPopupMenu(JMenuBar menuBar,
128           boolean overrideFonts, boolean append)
129   {
130     if (!append)
131     {
132       embeddedPopup.clear(); // TODO: check if j1.1
133       if (embeddedMenu != null)
134       {
135         embeddedMenu.removeAll();
136       }
137     }
138     embeddedMenu = makeEmbeddedPopupMenu(menuBar, DEFAULT_MENU_FONT,
139             overrideFonts, new JPanel(), this);
140     return embeddedMenu;
141   }
142
143   /**
144    * Generic method to move elements from menubar onto embeddedMenu using the
145    * existing or the supplied font, and adds binding from panel to attached
146    * menus in embeddedPopup This removes all menu from menuBar and it is up to
147    * the caller to remove the now useless menuBar from the Frame if it is
148    * already attached.
149    * 
150    * @param menuBar
151    *          must be non-null
152    * @param font
153    * @param overrideFonts
154    * @param embeddedMenu
155    *          if null, a new panel will be created and returned
156    * @param clickHandler
157    *          - usually the instance of EmbmenuFrame that holds references to
158    *          embeddedPopup and embeddedMenu
159    * @return the panel instance for convenience.
160    */
161   protected JPanel makeEmbeddedPopupMenu(JMenuBar menuBar, Font font,
162           boolean overrideFonts,
163           JPanel embeddedMenu,
164           MouseListener clickHandler)
165   {
166     if (overrideFonts)
167     {
168       Font mbf = menuBar.getFont();
169       if (mbf != null)
170       {
171         font = mbf;
172       }
173     }
174     if (embeddedMenu == null)
175     {
176       embeddedMenu = new JPanel();
177     }
178     FlowLayout flowLayout1 = new FlowLayout();
179     embeddedMenu.setBackground(Color.lightGray);
180     embeddedMenu.setLayout(flowLayout1);
181     // loop thru
182     for (int mbi = 0, nMbi = menuBar.getMenuCount(); mbi < nMbi; mbi++)
183     {
184       JMenu mi = menuBar.getMenu(mbi);
185       JLabel elab = new JLabel(mi.getLabel());
186       elab.setFont(font);
187       // add the menu entries
188       JPopupMenu popup = new JPopupMenu();
189       int m, mSize = mi.getItemCount();
190       for (m = 0; m < mSize; m++)
191       {
192         popup.add(mi.getItem(m));
193         mSize--;
194         m--;
195       }
196       embeddedPopup.put(elab, popup);
197       embeddedMenu.add(elab);
198       elab.addMouseListener(clickHandler);
199     }
200     flowLayout1.setAlignment(FlowLayout.LEFT);
201     flowLayout1.setHgap(2);
202     flowLayout1.setVgap(0);
203     return embeddedMenu;
204   }
205
206   public void mousePressed(MouseEvent evt)
207   {
208     JPopupMenu popup = null;
209     JLabel source = (JLabel) evt.getSource();
210     popup = getPopupMenu(source);
211     if (popup != null)
212     {
213       embeddedMenu.add(popup);
214       popup.show(embeddedMenu, source.getBounds().x, source.getBounds().y
215               + source.getBounds().getSize().height);
216     }
217   }
218
219   /**
220    * get the menu for source from the hash.
221    * 
222    * @param source
223    *          what was clicked on.
224    */
225   JPopupMenu getPopupMenu(JLabel source)
226   {
227     return embeddedPopup.get(source);
228   }
229
230   public void mouseClicked(MouseEvent evt)
231   {
232   }
233
234   public void mouseReleased(MouseEvent evt)
235   {
236   }
237
238   public void mouseEntered(MouseEvent evt)
239   {
240   }
241
242   public void mouseExited(MouseEvent evt)
243   {
244   }
245
246   /**
247    * called to clear the GUI resources taken up for embedding and remove any
248    * self references so we can be garbage collected.
249    */
250   public void destroyMenus()
251   {
252     if (embeddedPopup != null)
253     {
254       for (JLabel lb : embeddedPopup.keySet())
255       {
256         lb.removeMouseListener(this);
257       }
258       embeddedPopup.clear();
259     }
260     if (embeddedMenu != null)
261     {
262       embeddedMenu.removeAll();
263     }
264   }
265
266   /**
267    * calls destroyMenus()
268    */
269   public void finalize() throws Throwable
270   {
271     destroyMenus();
272     embeddedPopup = null;
273     embeddedMenu = null;
274     super.finalize();
275   }
276 }