JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / src / jalview / appletgui / SplitFrame.java
1 package jalview.appletgui;
2
3 import jalview.analysis.AlignmentUtils;
4 import jalview.api.AlignmentViewPanel;
5 import jalview.api.ViewStyleI;
6 import jalview.bin.JalviewLite;
7 import jalview.datamodel.AlignmentI;
8 import jalview.structure.StructureSelectionManager;
9 import jalview.viewmodel.AlignmentViewport;
10
11 import java.awt.BorderLayout;
12 import java.awt.Dimension;
13 import java.awt.GridLayout;
14
15 import awt2swing.MenuBar;
16 import awt2swing.Panel;
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     AlignmentViewport cdna = topAlignment.isNucleotide() ? topViewport
56             : (bottomAlignment.isNucleotide() ? bottomViewport : null);
57     AlignmentViewport protein = !topAlignment.isNucleotide() ? topViewport
58             : (!bottomAlignment.isNucleotide() ? bottomViewport : null);
59
60     boolean mapped = AlignmentUtils.mapProteinToCdna(
61             protein.getAlignment(), cdna.getAlignment());
62     if (mapped)
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     /*
73      * Now mappings exist, can compute cDNA consensus on protein alignment
74      */
75     protein.initComplementConsensus();
76     AlignmentViewPanel ap = topAlignment.isNucleotide() ? bottomFrame.alignPanel
77             : topFrame.alignPanel;
78     protein.updateConsensus(ap);
79
80     adjustLayout();
81   }
82
83   /**
84    * 
85    */
86   protected void constructSplit()
87   {
88     unsetMenuBar();
89     outermost = new Panel(new GridLayout(2, 1));
90
91     Panel topPanel = new Panel();
92     Panel bottomPanel = new Panel();
93     outermost.add(topPanel);
94     outermost.add(bottomPanel);
95
96     addAlignFrameComponents(topFrame, topPanel);
97     addAlignFrameComponents(bottomFrame, bottomPanel);
98   }
99
100         /**
101    * Make any adjustments to the layout
102    */
103   protected void adjustLayout()
104   {
105     AlignmentViewport cdna = topFrame.getAlignViewport().getAlignment()
106             .isNucleotide() ? topFrame.viewport : bottomFrame.viewport;
107     AlignmentViewport protein = cdna == topFrame.viewport ? bottomFrame.viewport
108             : topFrame.viewport;
109
110     /*
111      * Ensure sequence ids are the same width for good alignment.
112      */
113     // TODO should do this via av.getViewStyle/setViewStyle
114     // however at present av.viewStyle is not set in IdPanel.fontChanged
115     int w1 = topFrame.alignPanel.idPanel.idCanvas.getWidth();
116     int w2 = bottomFrame.alignPanel.idPanel.idCanvas.getWidth();
117     int w3 = Math.max(w1, w2);
118     if (w1 != w3)
119     {
120       Dimension d = topFrame.alignPanel.idPanel.idCanvas.getSize();
121       topFrame.alignPanel.idPanel.idCanvas.setSize(new Dimension(w3,
122               d.height));
123     }
124     if (w2 != w3)
125     {
126       Dimension d = bottomFrame.alignPanel.idPanel.idCanvas.getSize();
127       bottomFrame.alignPanel.idPanel.idCanvas.setSize(new Dimension(w3,
128               d.height));
129     }
130
131     /*
132      * Scale protein to either 1 or 3 times character width of dna
133      */
134     if (protein != null && cdna != null)
135     {
136       ViewStyleI vs = protein.getViewStyle();
137       int scale = vs.isScaleProteinAsCdna() ? 3 : 1;
138       vs.setCharWidth(scale * cdna.getViewStyle().getCharWidth());
139       protein.setViewStyle(vs);
140     }
141   }
142
143   /**
144    * Add the menu bar, alignment panel and status bar from the AlignFrame to the
145    * panel. The menu bar is a panel 'reconstructed' from the AlignFrame's frame
146    * menu bar. This allows each half of the SplitFrame to have its own menu bar.
147    * 
148    * @param af
149    * @param panel
150    */
151   private void addAlignFrameComponents(AlignFrame af, Panel panel)
152   {
153     panel.setLayout(new BorderLayout());
154     Panel menuPanel = af
155             .makeEmbeddedPopupMenu((MenuBar) af.getJMenuBar(), true, false);
156     panel.add(menuPanel, BorderLayout.NORTH);
157     panel.add(af.statusBar, BorderLayout.SOUTH);
158     panel.add(af.alignPanel, BorderLayout.CENTER);
159
160     af.setSplitFrame(this);
161   }
162
163   /**
164    * Display the content panel either as a new frame or embedded in the applet.
165    * 
166    * @param embedded
167    * @param applet
168    */
169   public void addToDisplay(boolean embedded, JalviewLite applet)
170   {
171     createSplitFrameWindow(embedded, applet);
172     validate();
173     topFrame.alignPanel.adjustAnnotationHeight();
174     topFrame.alignPanel.paintAlignment(true);
175     bottomFrame.alignPanel.adjustAnnotationHeight();
176     bottomFrame.alignPanel.paintAlignment(true);
177   }
178
179   /**
180    * Either show the content panel in this frame as a new frame, or (if
181    * embed=true) add it to the applet container instead.
182    * 
183    * @param embed
184    * @param applet
185    */
186   protected void createSplitFrameWindow(boolean embed, JalviewLite applet)
187   {
188     if (embed)
189     {
190       applet.add(outermost);
191       applet.validate();
192     }
193     else
194     {
195       this.add(outermost);
196       int width = Math.max(topFrame.frameWidth, bottomFrame.frameWidth);
197       int height = topFrame.frameHeight + bottomFrame.frameHeight;
198       JalviewLite.addFrame(this, this.getTitle(), width, height);
199     }
200   }
201
202   /**
203    * Returns the contained AlignFrame complementary to the one given (or null if
204    * no match to top or bottom component).
205    * 
206    * @param af
207    * @return
208    */
209   public AlignFrame getComplement(AlignFrame af)
210   {
211     if (topFrame == af)
212     {
213       return bottomFrame;
214     }
215     else if (bottomFrame == af)
216     {
217       return topFrame;
218     }
219     return null;
220   }
221 }