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.viewmodel.AlignmentViewport;
import java.awt.Component;
-import java.awt.MouseInfo;
-import java.awt.Point;
-import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
-public class SplitFrame extends GSplitFrame
+/**
+ * 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
+ * pairs, expanded to separate split frames, or regathered into a single frame.
+ * <p>
+ * (Some) operations on each alignment are automatically mirrored on the other.
+ * These include mouseover (highlighting), sequence and column selection,
+ * sequence ordering and sorting, and grouping, colouring and sorting by tree.
+ *
+ * @author gmcarstairs
+ *
+ */
+public class SplitFrame extends GSplitFrame implements SplitContainerI
{
private static final long serialVersionUID = 1L;
*/
protected void init()
{
+ getTopFrame().setSplitFrame(this);
+ getBottomFrame().setSplitFrame(this);
+ getTopFrame().setVisible(true);
+ getBottomFrame().setVisible(true);
+
+ ((AlignFrame) getTopFrame()).getViewport().setCodingComplement(
+ ((AlignFrame) getBottomFrame()).getViewport());
+
setSize(AlignFrame.DEFAULT_WIDTH, Desktop.instance.getHeight() - 20);
+ adjustLayout();
+
addCloseFrameListener();
addKeyListener();
addKeyBindings();
+
+ addCommandListeners();
+ }
+
+ /**
+ * Set the top and bottom frames to listen to each others Commands (e.g. Edit,
+ * Order).
+ */
+ protected void addCommandListeners()
+ {
+ // TODO if CommandListener is only ever 1:1 for complementary views,
+ // may change broadcast pattern to direct messaging (more efficient)
+ final StructureSelectionManager ssm = StructureSelectionManager
+ .getStructureSelectionManager(Desktop.instance);
+ ssm.addCommandListener(((AlignFrame) getTopFrame()).getViewport());
+ ssm.addCommandListener(((AlignFrame) getBottomFrame()).getViewport());
+ }
+
+ /**
+ * Do any tweaking and twerking of the layout wanted.
+ */
+ public void adjustLayout()
+ {
+ /*
+ * Ensure sequence ids are the same width for good alignment.
+ */
+ int w1 = ((AlignFrame) getTopFrame()).getViewport().getIdWidth();
+ int w2 = ((AlignFrame) getBottomFrame()).getViewport().getIdWidth();
+ int w3 = Math.max(w1, w2);
+ if (w1 != w3)
+ {
+ ((AlignFrame) getTopFrame()).getViewport().setIdWidth(w3);
+ }
+ if (w2 != w3)
+ {
+ ((AlignFrame) getBottomFrame()).getViewport().setIdWidth(w3);
+ }
+
+ /*
+ * Set the character width for protein to 3 times that for dna.
+ */
+ boolean scaleThreeToOne = true; // TODO a new Preference option?
+ if (scaleThreeToOne)
+ {
+ 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
+ : (bottomAlignment.isNucleotide() ? bottomViewport : null);
+ AlignmentViewport protein = !topAlignment.isNucleotide() ? topViewport
+ : (!bottomAlignment.isNucleotide() ? bottomViewport : null);
+ if (protein != null && cdna != null)
+ {
+ ViewStyleI vs = cdna.getViewStyle();
+ ViewStyleI vs2 = protein.getViewStyle();
+ vs2.setCharWidth(3 * vs.getCharWidth());
+ protein.setViewStyle(vs2);
+ }
+ }
}
/**
}
/**
- * Returns the split pane component the mouse is in, or null if neither.
- *
- * @return
- */
- protected GAlignFrame getFrameAtMouse()
- {
- Point loc = MouseInfo.getPointerInfo().getLocation();
-
- if (isIn(loc, getTopFrame()))
- {
- return getTopFrame();
- }
- else if (isIn(loc, getBottomFrame()))
- {
- return getBottomFrame();
- }
- return null;
- }
-
- private boolean isIn(Point loc, JComponent comp)
- {
- Point p = comp.getLocationOnScreen();
- Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(), comp.getHeight());
- return r.contains(loc);
- }
-
- /**
* Set key bindings (recommended for Swing over key accelerators).
*/
private void addKeyBindings()
* Note this is _not_ multiple tabs, each hosting a split pane view, rather it
* is a single split pane with each split holding multiple tabs which are
* linked in pairs.
+ * <p>
+ * TODO implement instead with a tabbed holder in the SplitView, each tab
+ * holding a single JSplitPane. Would avoid a duplicated tab, at the cost of
+ * some additional coding.
*/
protected void newView_actionPerformed()
{
- System.out.println("newView " + this.hashCode());
AlignFrame topFrame = (AlignFrame) getTopFrame();
AlignFrame bottomFrame = (AlignFrame) getBottomFrame();
{
Desktop.instance.gatherViews(this);
}
+
+ /**
+ * Returns the alignment in the complementary frame to the one given.
+ */
+ @Override
+ public AlignmentI getComplement(Object alignFrame)
+ {
+ if (alignFrame == this.getTopFrame())
+ {
+ return ((AlignFrame) getBottomFrame()).viewport.getAlignment();
+ }
+ else if (alignFrame == this.getBottomFrame())
+ {
+ return ((AlignFrame) getTopFrame()).viewport.getAlignment();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the title of the complementary frame to the one given.
+ */
+ @Override
+ public String getComplementTitle(Object alignFrame)
+ {
+ if (alignFrame == this.getTopFrame())
+ {
+ return ((AlignFrame) getBottomFrame()).getTitle();
+ }
+ else if (alignFrame == this.getBottomFrame())
+ {
+ return ((AlignFrame) getTopFrame()).getTitle();
+ }
+ return null;
+ }
+
+ /**
+ * Set the 'other half' to hidden / revealed.
+ */
+ @Override
+ public void setComplementVisible(Object alignFrame, boolean show)
+ {
+ /*
+ * Hiding the AlignPanel suppresses unnecessary repaints
+ */
+ if (alignFrame == getTopFrame())
+ {
+ ((AlignFrame) getBottomFrame()).alignPanel.setVisible(show);
+ }
+ else if (alignFrame == getBottomFrame())
+ {
+ ((AlignFrame) getTopFrame()).alignPanel.setVisible(show);
+ }
+ super.setComplementVisible(alignFrame, show);
+ }
}
+