Merge branch 'develop' into features/JAL-845splitPaneMergeDevelop
[jalview.git] / src / jalview / appletgui / SplitFrame.java
1 package jalview.appletgui;
2
3 import jalview.analysis.AlignmentUtils;
4 import jalview.analysis.AlignmentUtils.MappingResult;
5 import jalview.api.ViewStyleI;
6 import jalview.bin.JalviewLite;
7 import jalview.datamodel.AlignmentI;
8 import jalview.structure.StructureSelectionManager;
9
10 import java.awt.BorderLayout;
11 import java.awt.Component;
12 import java.awt.GridLayout;
13 import java.awt.MouseInfo;
14 import java.awt.Panel;
15 import java.awt.Point;
16 import java.awt.Rectangle;
17
18 public class SplitFrame extends EmbmenuFrame
19 {
20   private static final long serialVersionUID = 1L;
21
22   private AlignFrame topFrame;
23
24   private AlignFrame bottomFrame;
25
26   private Panel outermost;
27
28   /**
29    * Constructor
30    */
31   public SplitFrame(AlignFrame af1, AlignFrame af2)
32   {
33     topFrame = af1;
34     bottomFrame = af2;
35     init();
36   }
37
38   /**
39    * Creates a Panel containing two Panels, and adds the first and second
40    * AlignFrame's components to each. At this stage we have not yet committed to
41    * whether the enclosing panel will be added to this frame, for display as a
42    * separate frame, or added to the applet (embedded mode).
43    */
44   public void init()
45   {
46     constructSplit();
47
48     /*
49      * Try to make and add dna/protein sequence mappings
50      */
51     final AlignViewport topViewport = topFrame.viewport;
52     final AlignViewport bottomViewport = bottomFrame.viewport;
53     final AlignmentI topAlignment = topViewport.getAlignment();
54     final AlignmentI bottomAlignment = bottomViewport.getAlignment();
55     AlignViewport cdna = topAlignment.isNucleotide() ? topViewport
56             : (bottomAlignment.isNucleotide() ? bottomViewport : null);
57     AlignViewport protein = !topAlignment.isNucleotide() ? topViewport
58             : (!bottomAlignment.isNucleotide() ? bottomViewport : null);
59
60     MappingResult mapped = AlignmentUtils.mapProteinToCdna(
61             protein.getAlignment(), cdna.getAlignment());
62     if (mapped != MappingResult.NotMapped)
63     {
64       final StructureSelectionManager ssm = StructureSelectionManager
65               .getStructureSelectionManager(topViewport.applet);
66       ssm.addMappings(protein.getAlignment().getCodonFrames());
67       topViewport.setCodingComplement(bottomViewport);
68       ssm.addCommandListener(cdna);
69       ssm.addCommandListener(protein);
70     }
71
72     setCharacterWidth(protein, cdna);
73   }
74
75   /**
76    * 
77    */
78   protected void constructSplit()
79   {
80     setMenuBar(null);
81     outermost = new Panel(new GridLayout(2, 1));
82
83     Panel topPanel = new Panel();
84     Panel bottomPanel = new Panel();
85     outermost.add(topPanel);
86     outermost.add(bottomPanel);
87
88     addAlignFrameComponents(topFrame, topPanel);
89     addAlignFrameComponents(bottomFrame, bottomPanel);
90   }
91
92   /**
93    * Expand protein to 3 times character width of dna
94    * 
95    * @param protein
96    * @param cdna
97    */
98   protected void setCharacterWidth(AlignViewport protein, AlignViewport cdna)
99   {
100     if (protein != null && cdna != null)
101     {
102       ViewStyleI vs = protein.getViewStyle();
103       vs.setCharWidth(3 * vs.getCharWidth());
104       protein.setViewStyle(vs);
105     }
106   }
107
108   /**
109    * Add the menu bar, alignment panel and status bar from the AlignFrame to the
110    * panel. The menu bar is a panel 'reconstructed' from the AlignFrame's frame
111    * menu bar. This allows each half of the SplitFrame to have its own menu bar.
112    * 
113    * @param af
114    * @param panel
115    */
116   private void addAlignFrameComponents(AlignFrame af, Panel panel)
117   {
118     panel.setLayout(new BorderLayout());
119     Panel menuPanel = af
120             .makeEmbeddedPopupMenu(af.getMenuBar(), true, false);
121     panel.add(menuPanel, BorderLayout.NORTH);
122     panel.add(af.statusBar, BorderLayout.SOUTH);
123     panel.add(af.alignPanel, BorderLayout.CENTER);
124   }
125
126   /**
127    * Display the content panel either as a new frame or embedded in the applet.
128    * 
129    * @param embedded
130    * @param applet
131    */
132   public void addToDisplay(boolean embedded, JalviewLite applet)
133   {
134     createAlignFrameWindow(embedded, applet);
135     validate();
136     topFrame.alignPanel.adjustAnnotationHeight();
137     topFrame.alignPanel.paintAlignment(true);
138     bottomFrame.alignPanel.adjustAnnotationHeight();
139     bottomFrame.alignPanel.paintAlignment(true);
140   }
141
142   /**
143    * Either show the content panel in this frame as a new frame, or (if
144    * embed=true) add it to the applet container instead.
145    * 
146    * @param embed
147    * @param applet
148    */
149   public void createAlignFrameWindow(boolean embed, JalviewLite applet)
150   {
151     if (embed)
152     {
153       applet.add(outermost);
154       applet.validate();
155     }
156     else
157     {
158       this.add(outermost);
159       int width = Math.max(topFrame.DEFAULT_WIDTH,
160               bottomFrame.DEFAULT_WIDTH);
161       int height = topFrame.DEFAULT_HEIGHT + bottomFrame.DEFAULT_HEIGHT;
162       jalview.bin.JalviewLite
163               .addFrame(this, this.getTitle(), width, height);
164     }
165   }
166 }