X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FSplitFrame.java;h=73744b37d28758264fa03819cfa93acf6f5be2dc;hb=155a17a423e980849fd4dc5f857da1a72b0010b9;hp=617224f2a3179c712f80d14c21209440ad5d771c;hpb=9c6f9bb69f694cb37db088c8fca6582169efcb05;p=jalview.git diff --git a/src/jalview/gui/SplitFrame.java b/src/jalview/gui/SplitFrame.java index 617224f..73744b3 100644 --- a/src/jalview/gui/SplitFrame.java +++ b/src/jalview/gui/SplitFrame.java @@ -20,33 +20,47 @@ */ package jalview.gui; -import jalview.api.SplitContainerI; -import jalview.api.ViewStyleI; -import jalview.datamodel.AlignmentI; -import jalview.jbgui.GAlignFrame; -import jalview.jbgui.GSplitFrame; -import jalview.structure.StructureSelectionManager; -import jalview.util.Platform; -import jalview.viewmodel.AlignmentViewport; - +import java.awt.BorderLayout; import java.awt.Component; -import java.awt.Toolkit; +import java.awt.Dimension; 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.JButton; import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JInternalFrame; +import javax.swing.JLayeredPane; import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; import javax.swing.KeyStroke; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; +import jalview.api.AlignViewControllerGuiI; +import jalview.api.FeatureSettingsControllerI; +import jalview.api.SplitContainerI; +import jalview.controller.FeatureSettingsControllerGuiI; +import jalview.datamodel.AlignmentI; +import jalview.jbgui.GAlignFrame; +import jalview.jbgui.GSplitFrame; +import jalview.structure.StructureSelectionManager; +import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.viewmodel.AlignmentViewport; + /** * An internal frame on the desktop that hosts a horizontally split view of * linked DNA and Protein alignments. Additional views can be created in linked @@ -68,9 +82,18 @@ 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; + /** + * geometry for Feature Settings Holder + */ + private static final int FS_MIN_WIDTH = 400; + + private static final int FS_MIN_HEIGHT = 400; + public SplitFrame(GAlignFrame top, GAlignFrame bottom) { super(top, bottom); @@ -82,6 +105,7 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI */ protected void init() { + setFrameIcon(null); getTopFrame().setSplitFrame(this); getBottomFrame().setSplitFrame(this); getTopFrame().setVisible(true); @@ -94,9 +118,9 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI * estimate width and height of SplitFrame; this.getInsets() doesn't seem to * give the full additional size (a few pixels short) */ - int widthFudge = Platform.isAMac() ? MAC_INSETS_WIDTH + int widthFudge = Platform.isAMacAndNotJS() ? MAC_INSETS_WIDTH : WINDOWS_INSETS_WIDTH; - int heightFudge = Platform.isAMac() ? MAC_INSETS_HEIGHT + int heightFudge = Platform.isAMacAndNotJS() ? MAC_INSETS_HEIGHT : WINDOWS_INSETS_HEIGHT; int width = ((AlignFrame) getTopFrame()).getWidth() + widthFudge; int height = ((AlignFrame) getTopFrame()).getHeight() @@ -128,8 +152,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(); @@ -157,26 +181,21 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI */ public void adjustLayout() { + final AlignViewport topViewport = ((AlignFrame) getTopFrame()).viewport; + final AlignViewport bottomViewport = ((AlignFrame) getBottomFrame()).viewport; + /* * Ensure sequence ids are the same width so sequences line up */ - int w1 = ((AlignFrame) getTopFrame()).getViewport().getIdWidth(); - int w2 = ((AlignFrame) getBottomFrame()).getViewport().getIdWidth(); + int w1 = topViewport.getIdWidth(); + int w2 = bottomViewport.getIdWidth(); int w3 = Math.max(w1, w2); - if (w1 != w3) - { - ((AlignFrame) getTopFrame()).getViewport().setIdWidth(w3); - } - if (w2 != w3) - { - ((AlignFrame) getBottomFrame()).getViewport().setIdWidth(w3); - } + topViewport.setIdWidth(w3); + bottomViewport.setIdWidth(w3); /* * Scale protein to either 1 or 3 times character width of dna */ - final AlignViewport topViewport = ((AlignFrame) getTopFrame()).viewport; - final AlignViewport bottomViewport = ((AlignFrame) getBottomFrame()).viewport; final AlignmentI topAlignment = topViewport.getAlignment(); final AlignmentI bottomAlignment = bottomViewport.getAlignment(); AlignmentViewport cdna = topAlignment.isNucleotide() ? topViewport @@ -185,44 +204,86 @@ 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
+ int insets = Platform.isAMacAndNotJS() ? MAC_INSETS_HEIGHT
: WINDOWS_INSETS_HEIGHT;
// allow 3 'rows' for scale, scrollbar, status bar
int topHeight = insets + (3 + topCount) * topCharHeight
+ (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 +389,7 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
actioned = true;
e.consume();
}
+ break;
default:
}
return actioned;
@@ -365,8 +427,10 @@ 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 +450,10 @@ 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 +506,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 +559,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 +770,35 @@ 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