Merge branch 'features/JAL-845splitPaneMergeDevelop' into develop
[jalview.git] / src / jalview / appletgui / SplitFrame.java
diff --git a/src/jalview/appletgui/SplitFrame.java b/src/jalview/appletgui/SplitFrame.java
new file mode 100644 (file)
index 0000000..fb11a5c
--- /dev/null
@@ -0,0 +1,166 @@
+package jalview.appletgui;
+
+import jalview.analysis.AlignmentUtils;
+import jalview.analysis.AlignmentUtils.MappingResult;
+import jalview.api.ViewStyleI;
+import jalview.bin.JalviewLite;
+import jalview.datamodel.AlignmentI;
+import jalview.structure.StructureSelectionManager;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.GridLayout;
+import java.awt.MouseInfo;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.Rectangle;
+
+public class SplitFrame extends EmbmenuFrame
+{
+  private static final long serialVersionUID = 1L;
+
+  private AlignFrame topFrame;
+
+  private AlignFrame bottomFrame;
+
+  private Panel outermost;
+
+  /**
+   * Constructor
+   */
+  public SplitFrame(AlignFrame af1, AlignFrame af2)
+  {
+    topFrame = af1;
+    bottomFrame = af2;
+    init();
+  }
+
+  /**
+   * Creates a Panel containing two Panels, and adds the first and second
+   * AlignFrame's components to each. At this stage we have not yet committed to
+   * whether the enclosing panel will be added to this frame, for display as a
+   * separate frame, or added to the applet (embedded mode).
+   */
+  public void init()
+  {
+    constructSplit();
+
+    /*
+     * Try to make and add dna/protein sequence mappings
+     */
+    final AlignViewport topViewport = topFrame.viewport;
+    final AlignViewport bottomViewport = bottomFrame.viewport;
+    final AlignmentI topAlignment = topViewport.getAlignment();
+    final AlignmentI bottomAlignment = bottomViewport.getAlignment();
+    AlignViewport cdna = topAlignment.isNucleotide() ? topViewport
+            : (bottomAlignment.isNucleotide() ? bottomViewport : null);
+    AlignViewport protein = !topAlignment.isNucleotide() ? topViewport
+            : (!bottomAlignment.isNucleotide() ? bottomViewport : null);
+
+    MappingResult mapped = AlignmentUtils.mapProteinToCdna(
+            protein.getAlignment(), cdna.getAlignment());
+    if (mapped != MappingResult.NotMapped)
+    {
+      final StructureSelectionManager ssm = StructureSelectionManager
+              .getStructureSelectionManager(topViewport.applet);
+      ssm.addMappings(protein.getAlignment().getCodonFrames());
+      topViewport.setCodingComplement(bottomViewport);
+      ssm.addCommandListener(cdna);
+      ssm.addCommandListener(protein);
+    }
+
+    setCharacterWidth(protein, cdna);
+  }
+
+  /**
+   * 
+   */
+  protected void constructSplit()
+  {
+    setMenuBar(null);
+    outermost = new Panel(new GridLayout(2, 1));
+
+    Panel topPanel = new Panel();
+    Panel bottomPanel = new Panel();
+    outermost.add(topPanel);
+    outermost.add(bottomPanel);
+
+    addAlignFrameComponents(topFrame, topPanel);
+    addAlignFrameComponents(bottomFrame, bottomPanel);
+  }
+
+  /**
+   * Expand protein to 3 times character width of dna
+   * 
+   * @param protein
+   * @param cdna
+   */
+  protected void setCharacterWidth(AlignViewport protein, AlignViewport cdna)
+  {
+    if (protein != null && cdna != null)
+    {
+      ViewStyleI vs = protein.getViewStyle();
+      vs.setCharWidth(3 * vs.getCharWidth());
+      protein.setViewStyle(vs);
+    }
+  }
+
+  /**
+   * Add the menu bar, alignment panel and status bar from the AlignFrame to the
+   * panel. The menu bar is a panel 'reconstructed' from the AlignFrame's frame
+   * menu bar. This allows each half of the SplitFrame to have its own menu bar.
+   * 
+   * @param af
+   * @param panel
+   */
+  private void addAlignFrameComponents(AlignFrame af, Panel panel)
+  {
+    panel.setLayout(new BorderLayout());
+    Panel menuPanel = af
+            .makeEmbeddedPopupMenu(af.getMenuBar(), true, false);
+    panel.add(menuPanel, BorderLayout.NORTH);
+    panel.add(af.statusBar, BorderLayout.SOUTH);
+    panel.add(af.alignPanel, BorderLayout.CENTER);
+  }
+
+  /**
+   * Display the content panel either as a new frame or embedded in the applet.
+   * 
+   * @param embedded
+   * @param applet
+   */
+  public void addToDisplay(boolean embedded, JalviewLite applet)
+  {
+    createAlignFrameWindow(embedded, applet);
+    validate();
+    topFrame.alignPanel.adjustAnnotationHeight();
+    topFrame.alignPanel.paintAlignment(true);
+    bottomFrame.alignPanel.adjustAnnotationHeight();
+    bottomFrame.alignPanel.paintAlignment(true);
+  }
+
+  /**
+   * Either show the content panel in this frame as a new frame, or (if
+   * embed=true) add it to the applet container instead.
+   * 
+   * @param embed
+   * @param applet
+   */
+  public void createAlignFrameWindow(boolean embed, JalviewLite applet)
+  {
+    if (embed)
+    {
+      applet.add(outermost);
+      applet.validate();
+    }
+    else
+    {
+      this.add(outermost);
+      int width = Math.max(topFrame.DEFAULT_WIDTH,
+              bottomFrame.DEFAULT_WIDTH);
+      int height = topFrame.DEFAULT_HEIGHT + bottomFrame.DEFAULT_HEIGHT;
+      jalview.bin.JalviewLite
+              .addFrame(this, this.getTitle(), width, height);
+    }
+  }
+}