X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FSplitFrame.java;h=588948937c4d8c0fb87fa3eb2ea67ba9f329b0f4;hb=b7014049e421026d0f2d57179af9688472cd78f2;hp=617224f2a3179c712f80d14c21209440ad5d771c;hpb=9c6f9bb69f694cb37db088c8fca6582169efcb05;p=jalview.git diff --git a/src/jalview/gui/SplitFrame.java b/src/jalview/gui/SplitFrame.java index 617224f..5889489 100644 --- a/src/jalview/gui/SplitFrame.java +++ b/src/jalview/gui/SplitFrame.java @@ -21,7 +21,6 @@ package jalview.gui; import jalview.api.SplitContainerI; -import jalview.api.ViewStyleI; import jalview.datamodel.AlignmentI; import jalview.jbgui.GAlignFrame; import jalview.jbgui.GSplitFrame; @@ -30,18 +29,21 @@ import jalview.util.Platform; import jalview.viewmodel.AlignmentViewport; import java.awt.Component; -import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.beans.PropertyVetoException; +import java.util.Arrays; +import java.util.List; import java.util.Map.Entry; import javax.swing.AbstractAction; import javax.swing.InputMap; import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JInternalFrame; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import javax.swing.event.InternalFrameAdapter; @@ -68,7 +70,9 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI private static final int WINDOWS_INSETS_HEIGHT = 50; // tbc private static final int MAC_INSETS_HEIGHT = 50; + private static final int DESKTOP_DECORATORS_HEIGHT = 65; + private static final long serialVersionUID = 1L; public SplitFrame(GAlignFrame top, GAlignFrame bottom) @@ -128,8 +132,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI { // allow about 65 pixels for Desktop decorators on Windows - int newHeight = Math.min(height, Desktop.instance.getHeight() - - DESKTOP_DECORATORS_HEIGHT); + int newHeight = Math.min(height, + Desktop.instance.getHeight() - DESKTOP_DECORATORS_HEIGHT); if (newHeight != height) { int oldDividerLocation = getDividerLocation(); @@ -185,33 +189,69 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI : (!bottomAlignment.isNucleotide() ? bottomViewport : null); if (protein != null && cdna != null) { - ViewStyleI vs = protein.getViewStyle(); - int scale = vs.isScaleProteinAsCdna() ? 3 : 1; - vs.setCharWidth(scale * cdna.getViewStyle().getCharWidth()); - protein.setViewStyle(vs); + int scale = protein.isScaleProteinAsCdna() ? 3 : 1; + protein.setCharWidth(scale * cdna.getViewStyle().getCharWidth()); } } /** - * Adjust the divider for a sensible split of the real estate (for example, + * Adjusts the divider for a sensible split of the real estate (for example, * when many transcripts are shown with a single protein). This should only be * called after the split pane has been laid out (made visible) so it has a - * height. + * height. The aim is to avoid unnecessary vertical scroll bars, while + * ensuring that at least 2 sequences are visible in each panel. + *

+ * Once laid out, the user may choose to customise as they wish, so this + * method is not called again after the initial layout. */ - protected void adjustDivider() + protected void adjustInitialLayout() { - final AlignViewport topViewport = ((AlignFrame) getTopFrame()).viewport; - final AlignViewport bottomViewport = ((AlignFrame) getBottomFrame()).viewport; + AlignFrame topFrame = (AlignFrame) getTopFrame(); + AlignFrame bottomFrame = (AlignFrame) getBottomFrame(); + + /* + * recompute layout of top and bottom panels to reflect their + * actual (rather than requested) height + */ + topFrame.alignPanel.adjustAnnotationHeight(); + bottomFrame.alignPanel.adjustAnnotationHeight(); + + final AlignViewport topViewport = topFrame.viewport; + final AlignViewport bottomViewport = bottomFrame.viewport; final AlignmentI topAlignment = topViewport.getAlignment(); final AlignmentI bottomAlignment = bottomViewport.getAlignment(); boolean topAnnotations = topViewport.isShowAnnotation(); boolean bottomAnnotations = bottomViewport.isShowAnnotation(); + // TODO need number of visible sequences here, not #sequences - how? int topCount = topAlignment.getHeight(); int bottomCount = bottomAlignment.getHeight(); int topCharHeight = topViewport.getViewStyle().getCharHeight(); int bottomCharHeight = bottomViewport.getViewStyle().getCharHeight(); /* + * calculate the minimum ratio that leaves at least the height + * of two sequences (after rounding) visible in the top panel + */ + int topPanelHeight = topFrame.getHeight(); + int bottomPanelHeight = bottomFrame.getHeight(); + int topSequencesHeight = topFrame.alignPanel.getSeqPanel().seqCanvas + .getHeight(); + int topPanelMinHeight = topPanelHeight + - Math.max(0, topSequencesHeight - 3 * topCharHeight); + double totalHeight = (double) topPanelHeight + bottomPanelHeight; + double minRatio = topPanelMinHeight / totalHeight; + + /* + * calculate the maximum ratio that leaves at least the height + * of two sequences (after rounding) visible in the bottom panel + */ + int bottomSequencesHeight = bottomFrame.alignPanel.getSeqPanel().seqCanvas + .getHeight(); + int bottomPanelMinHeight = bottomPanelHeight + - Math.max(0, bottomSequencesHeight - 3 * bottomCharHeight); + double maxRatio = (totalHeight - bottomPanelMinHeight) / totalHeight; + + /* * estimate ratio of (topFrameContent / bottomFrameContent) */ int insets = Platform.isAMac() ? MAC_INSETS_HEIGHT @@ -221,8 +261,14 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI + (topAnnotations ? topViewport.calcPanelHeight() : 0); int bottomHeight = insets + (3 + bottomCount) * bottomCharHeight + (bottomAnnotations ? bottomViewport.calcPanelHeight() : 0); - double ratio = ((double) topHeight) / (topHeight + bottomHeight); + double ratio = ((double) topHeight) + / (double) (topHeight + bottomHeight); + /* + * limit ratio to avoid concealing all sequences + */ + ratio = Math.min(ratio, maxRatio); + ratio = Math.max(ratio, minRatio); setRelativeDividerLocation(ratio); } @@ -328,6 +374,7 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI actioned = true; e.consume(); } + break; default: } return actioned; @@ -365,8 +412,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI /* * Ctrl-W / Cmd-W - close view or window */ - KeyStroke key_cmdW = KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit - .getDefaultToolkit().getMenuShortcutKeyMask(), false); + KeyStroke key_cmdW = KeyStroke.getKeyStroke(KeyEvent.VK_W, + jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx(), false); action = new AbstractAction() { @Override @@ -386,8 +433,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI /* * Ctrl-T / Cmd-T open new view */ - KeyStroke key_cmdT = KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit - .getDefaultToolkit().getMenuShortcutKeyMask(), false); + KeyStroke key_cmdT = KeyStroke.getKeyStroke(KeyEvent.VK_T, + jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx(), false); AbstractAction action = new AbstractAction() { @Override @@ -440,8 +487,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI Component c = getFrameAtMouse(); if (c != null && c instanceof AlignFrame) { - for (ActionListener a : ((AlignFrame) c).getAccelerators() - .get(ks).getActionListeners()) + for (ActionListener a : ((AlignFrame) c).getAccelerators().get(ks) + .getActionListeners()) { a.actionPerformed(null); } @@ -493,7 +540,7 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI topFrame.setDisplayedView(newTopPanel); } - newBottomPanel.av.viewName = newTopPanel.av.viewName; + newBottomPanel.av.setViewName(newTopPanel.av.getViewName()); newTopPanel.av.setCodingComplement(newBottomPanel.av); /* @@ -704,6 +751,19 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI } /** + * return the AlignFrames held by this container + * + * @return { Top alignFrame (Usually CDS), Bottom AlignFrame (Usually + * Protein)} + */ + public List getAlignFrames() + { + return Arrays + .asList(new AlignFrame[] + { (AlignFrame) getTopFrame(), (AlignFrame) getBottomFrame() }); + } + + /** * Replace Cmd-F Find action with our version. This is necessary because the * 'default' Finder searches in the first AlignFrame it finds. We need it to * search in the half of the SplitFrame that has the mouse. @@ -713,8 +773,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI /* * Ctrl-F / Cmd-F open Finder dialog, 'focused' on the right alignment */ - KeyStroke key_cmdF = KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit - .getDefaultToolkit().getMenuShortcutKeyMask(), false); + KeyStroke key_cmdF = KeyStroke.getKeyStroke(KeyEvent.VK_F, + jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx(), false); AbstractAction action = new AbstractAction() { @Override @@ -724,10 +784,35 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI if (c != null && c instanceof AlignFrame) { AlignFrame af = (AlignFrame) c; - new Finder(af.viewport, af.alignPanel); + new Finder(af.alignPanel); } } }; overrideKeyBinding(key_cmdF, action); } + + /** + * Override to do nothing if triggered from one of the child frames + */ + @Override + public void setSelected(boolean selected) throws PropertyVetoException + { + JDesktopPane desktopPane = getDesktopPane(); + JInternalFrame fr = desktopPane == null ? null + : desktopPane.getSelectedFrame(); + if (fr == getTopFrame() || fr == getBottomFrame()) + { + /* + * patch for JAL-3288 (deselecting top/bottom frame closes popup menu); + * it may be possible to remove this method in future + * if the underlying Java behaviour changes + */ + if (selected) + { + moveToFront(); + } + return; + } + super.setSelected(selected); + } }