From 07dde9901f660659e46183f1455fc4dcea720e2d Mon Sep 17 00:00:00 2001 From: jprocter Date: Sat, 27 Oct 2007 13:26:07 +0000 Subject: [PATCH] refactored embedded menu machinery --- src/jalview/appletgui/AlignFrame.java | 177 ++++----------------- src/jalview/appletgui/EmbmenuFrame.java | 261 +++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+), 150 deletions(-) create mode 100644 src/jalview/appletgui/EmbmenuFrame.java diff --git a/src/jalview/appletgui/AlignFrame.java b/src/jalview/appletgui/AlignFrame.java index 7e706d5..22537f6 100755 --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@ -33,8 +33,8 @@ import jalview.io.*; import jalview.schemes.*; public class AlignFrame - extends Frame implements ActionListener, - ItemListener, KeyListener, MouseListener + extends EmbmenuFrame implements ActionListener, + ItemListener, KeyListener { public AlignmentPanel alignPanel; public AlignViewport viewport; @@ -2465,16 +2465,6 @@ public class AlignFrame MenuItem documentation = new MenuItem(); MenuItem about = new MenuItem(); CheckboxMenuItem seqLimits = new CheckboxMenuItem(); - Panel embeddedMenu; - Label embeddedEdit; - Label embeddedSelect; - Label embeddedView; - Label embeddedFormat; - Label embeddedColour; - Label embeddedFile; - Label embeddedHelp; - Label embeddedCalculate; - FlowLayout flowLayout1; private void jbInit() throws Exception @@ -2789,7 +2779,22 @@ public class AlignFrame selectMenu.add(invertColSel); selectMenu.add(deleteGroups); } + MenuItem featureSettings = new MenuItem(); + CheckboxMenuItem sequenceFeatures = new CheckboxMenuItem(); + MenuItem annotationColour = new MenuItem(); + MenuItem invertColSel = new MenuItem(); + Menu menu1 = new Menu(); + MenuItem showColumns = new MenuItem(); + MenuItem showSeqs = new MenuItem(); + Menu menu2 = new Menu(); + MenuItem hideColumns = new MenuItem(); + MenuItem hideSequences = new MenuItem(); + Menu formatMenu = new Menu(); + Menu selectMenu = new Menu(); + MenuItem newView = new MenuItem(); + /** + * Attach the alignFrame panels after embedding menus, if necessary. * This used to be called setEmbedded, but is now creates the * dropdown menus in a platform independent manner * to avoid OSX/Mac menu appendage daftness. @@ -2798,47 +2803,12 @@ public class AlignFrame */ public void createAlignFrameWindow(boolean reallyEmbedded, String title) { - embeddedMenu = new Panel(); - embeddedEdit = new Label("Edit"); - embeddedSelect = new Label("Select"); - embeddedView = new Label("View"); - embeddedFormat = new Label("Format"); - embeddedColour = new Label("Colour"); - embeddedFile = new Label("File"); - embeddedHelp = new Label("Help"); - embeddedCalculate = new Label("Calculate"); - flowLayout1 = new FlowLayout(); - embeddedMenu.setBackground(Color.lightGray); - embeddedMenu.setLayout(flowLayout1); - embeddedEdit.setFont(new java.awt.Font("Arial", Font.PLAIN, 10)); - embeddedSelect.setFont(new java.awt.Font("Arial", Font.PLAIN, 10)); - embeddedView.setFont(new java.awt.Font("Arial", Font.PLAIN, 10)); - embeddedFormat.setFont(new java.awt.Font("Arial", Font.PLAIN, 10)); - embeddedColour.setFont(new java.awt.Font("Arial", Font.PLAIN, 10)); - embeddedFile.setFont(new java.awt.Font("Arial", Font.PLAIN, 10)); - embeddedHelp.setFont(new java.awt.Font("Arial", Font.PLAIN, 10)); - embeddedCalculate.setFont(new java.awt.Font("Arial", Font.PLAIN, 10)); - embeddedMenu.add(embeddedFile); - embeddedMenu.add(embeddedEdit); - embeddedMenu.add(embeddedSelect); - embeddedMenu.add(embeddedView); - embeddedMenu.add(embeddedFormat); - embeddedMenu.add(embeddedColour); - embeddedMenu.add(embeddedCalculate); - embeddedMenu.add(embeddedHelp); - flowLayout1.setAlignment(FlowLayout.LEFT); - flowLayout1.setHgap(2); - flowLayout1.setVgap(0); - embeddedFile.addMouseListener(this); - embeddedEdit.addMouseListener(this); - embeddedSelect.addMouseListener(this); - embeddedView.addMouseListener(this); - embeddedFormat.addMouseListener(this); - embeddedColour.addMouseListener(this); - embeddedCalculate.addMouseListener(this); - embeddedHelp.addMouseListener(this); if (reallyEmbedded) { + ////// + // Explicly build the embedded menu panel for the on-page applet + // + embeddedMenu = makeEmbeddedPopupMenu(alignFrameMenuBar, "Arial", Font.PLAIN, 10, false); // use our own fonts. // view cannot be closed if its actually on the page fileMenu.remove(closeMenuItem); fileMenu.remove(3); // Remove Seperator @@ -2852,17 +2822,14 @@ public class AlignFrame viewport.applet.add(alignPanel, BorderLayout.CENTER); viewport.applet.validate(); } else { - if (new jalview.util.Platform().isAMac()) - { - // 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 - setMenuBar(null);// alignFramMenuBar); - // add the components to the AlignFrame area. - add(embeddedMenu, BorderLayout.NORTH); + //////// + // test and embed menu bar if necessary. + // + if (embedMenuIfNeeded(alignPanel)) { + // adjust for status bar height too alignPanel.setSize(getSize().width, getSize().height - - embeddedMenu.HEIGHT - statusBar.HEIGHT); - + - statusBar.HEIGHT); } add(statusBar, BorderLayout.SOUTH); add(alignPanel, BorderLayout.CENTER); @@ -2871,94 +2838,4 @@ public class AlignFrame DEFAULT_HEIGHT); } } - - PopupMenu filePopup, editPopup, searchPopup, - viewPopup, formatPopup, colourPopup, calculatePopup, helpPopup; - MenuItem featureSettings = new MenuItem(); - CheckboxMenuItem sequenceFeatures = new CheckboxMenuItem(); - MenuItem annotationColour = new MenuItem(); - MenuItem invertColSel = new MenuItem(); - Menu menu1 = new Menu(); - MenuItem showColumns = new MenuItem(); - MenuItem showSeqs = new MenuItem(); - Menu menu2 = new Menu(); - MenuItem hideColumns = new MenuItem(); - MenuItem hideSequences = new MenuItem(); - Menu formatMenu = new Menu(); - Menu selectMenu = new Menu(); - MenuItem newView = new MenuItem(); - - public void mousePressed(MouseEvent evt) - { - PopupMenu popup = null; - Label source = (Label) evt.getSource(); - if (source == embeddedFile) - { - popup = filePopup = genPopupMenu(filePopup, fileMenu); - } - else if (source == embeddedEdit) - { - popup = editPopup = genPopupMenu(editPopup, editMenu); - } - else if (source == embeddedSelect) - { - popup = searchPopup = genPopupMenu(searchPopup, selectMenu); - } - else if (source == embeddedView) - { - popup = viewPopup = genPopupMenu(viewPopup, viewMenu); - } - else if (source == embeddedFormat) - { - popup = formatPopup = genPopupMenu(formatPopup, formatMenu); - } - else if (source == embeddedColour) - { - popup = colourPopup = genPopupMenu(colourPopup, colourMenu); - } - else if (source == embeddedCalculate) - { - popup = calculatePopup = genPopupMenu(calculatePopup, calculateMenu); - } - else if (source == embeddedHelp) - { - popup = helpPopup = genPopupMenu(helpPopup, helpMenu); - } - - embeddedMenu.add(popup); - popup.show(embeddedMenu, - source.getBounds().x, - source.getBounds().y + source.getBounds().getSize().height); - } - - PopupMenu genPopupMenu(PopupMenu popup, Menu original) - { - if (popup != null) - { - return popup; - } - popup = new PopupMenu(); - int m, mSize = original.getItemCount(); - for (m = 0; m < mSize; m++) - { - popup.add(original.getItem(m)); - mSize--; - m--; - } - - return popup; - } - - public void mouseClicked(MouseEvent evt) - {} - - public void mouseReleased(MouseEvent evt) - {} - - public void mouseEntered(MouseEvent evt) - {} - - public void mouseExited(MouseEvent evt) - {} - } diff --git a/src/jalview/appletgui/EmbmenuFrame.java b/src/jalview/appletgui/EmbmenuFrame.java new file mode 100644 index 0000000..23f6aa2 --- /dev/null +++ b/src/jalview/appletgui/EmbmenuFrame.java @@ -0,0 +1,261 @@ +package jalview.appletgui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +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.ActionListener; +import java.awt.event.ItemListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.Enumeration; +import java.util.Hashtable; +/** + * This class implements a pattern form 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 +{ + /** + * map from labels to popup menus for the embedded menubar + */ + protected Hashtable embeddedPopup; + /** + * 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 + embeddedMenu = makeEmbeddedPopupMenu(topMenuBar, "Arial", Font.PLAIN, 10, true); // try to pickup system font. + setMenuBar(null); + // add the components to the TreePanel area. + add(embeddedMenu, BorderLayout.NORTH); + tobeAdjusted.setSize(getSize().width, + getSize().height + - embeddedMenu.HEIGHT); + return true; + } + return false; + } + /** + * move all menus on menuBar onto embeddedMenu. + * embeddedPopup is used to store the popups for each menu removed from the menuBar and added + * to the panel. + * NOTE: it is up to the caller to remove menuBar from the Frame if it is already attached. + * @param menuBar + * @param fn + * @param fstyle + * @param fsz + * @param overrideFonts true if we take the menuBar fonts in preference to the supplied defaults + * @return the embedded menu instance to be added to the frame. + */ + protected Panel makeEmbeddedPopupMenu(MenuBar menuBar, String fn, + int fstyle, int fsz, boolean overrideFonts) + { + return makeEmbeddedPopupMenu(menuBar, fn, fstyle, fsz, overrideFonts, 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 fn + * @param fstyle + * @param fsz + * @param overrideFonts + * @param append true means existing menu will be emptied before adding new elements + * @return + */ + protected Panel makeEmbeddedPopupMenu(MenuBar menuBar, String fn, + int fstyle, int fsz, boolean overrideFonts, boolean append) + { + if (!append) + { + if (embeddedPopup != null) + { + embeddedPopup.clear(); // TODO: check if j1.1 + } + if (embeddedMenu!=null) + { + embeddedMenu.removeAll(); + } + } + if (embeddedPopup==null) + { + embeddedPopup = new Hashtable(); + } + + embeddedMenu = makeEmbeddedPopupMenu(menuBar, fn, fstyle, fsz, overrideFonts, embeddedPopup, 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 fn + * @param fstyle + * @param fsz + * @param overrideFonts + * @param embeddedPopup must be non-null + * @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, String fn, + int fstyle, int fsz, boolean overrideFonts, Hashtable embeddedPopup, Panel embeddedMenu, MouseListener clickHandler) + { + if (embeddedPopup==null) + { + throw new Error("Implementation error - embeddedPopup must be non-null"); + } + if (overrideFonts) + { + Font mbf = menuBar.getFont(); + if (mbf!=null) + { + fn = mbf.getName(); + fstyle = mbf.getStyle(); + fsz = mbf.getSize(); + } + } + 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