Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
CutAndPasteTransfer | 58 | 153 | 59 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.appletgui; | |
22 | ||
23 | import jalview.analysis.AlignmentUtils; | |
24 | import jalview.api.ComplexAlignFile; | |
25 | import jalview.api.FeaturesSourceI; | |
26 | import jalview.bin.JalviewLite; | |
27 | import jalview.datamodel.AlignmentI; | |
28 | import jalview.datamodel.HiddenColumns; | |
29 | import jalview.datamodel.PDBEntry; | |
30 | import jalview.datamodel.SequenceI; | |
31 | import jalview.io.AlignmentFileReaderI; | |
32 | import jalview.io.AnnotationFile; | |
33 | import jalview.io.AppletFormatAdapter; | |
34 | import jalview.io.DataSourceType; | |
35 | import jalview.io.FileFormatI; | |
36 | import jalview.io.IdentifyFile; | |
37 | import jalview.io.NewickFile; | |
38 | import jalview.io.TCoffeeScoreFile; | |
39 | import jalview.json.binding.biojson.v1.ColourSchemeMapper; | |
40 | import jalview.schemes.ColourSchemeI; | |
41 | import jalview.schemes.TCoffeeColourScheme; | |
42 | import jalview.util.MessageManager; | |
43 | ||
44 | import java.awt.BorderLayout; | |
45 | import java.awt.Button; | |
46 | import java.awt.Dialog; | |
47 | import java.awt.Font; | |
48 | import java.awt.Frame; | |
49 | import java.awt.Label; | |
50 | import java.awt.Panel; | |
51 | import java.awt.TextArea; | |
52 | import java.awt.event.ActionEvent; | |
53 | import java.awt.event.ActionListener; | |
54 | import java.awt.event.MouseEvent; | |
55 | import java.awt.event.MouseListener; | |
56 | import java.io.IOException; | |
57 | ||
58 | public class CutAndPasteTransfer extends Panel | |
59 | implements ActionListener, MouseListener | |
60 | { | |
61 | boolean pdbImport = false; | |
62 | ||
63 | boolean treeImport = false; | |
64 | ||
65 | boolean annotationImport = false; | |
66 | ||
67 | SequenceI seq; | |
68 | ||
69 | AlignFrame alignFrame; | |
70 | ||
71 | AlignmentFileReaderI source = null; | |
72 | ||
73 | 0 | public CutAndPasteTransfer(boolean forImport, AlignFrame alignFrame) |
74 | { | |
75 | 0 | try |
76 | { | |
77 | 0 | jbInit(); |
78 | } catch (Exception e) | |
79 | { | |
80 | 0 | e.printStackTrace(); |
81 | } | |
82 | ||
83 | 0 | this.alignFrame = alignFrame; |
84 | ||
85 | 0 | if (!forImport) |
86 | { | |
87 | 0 | buttonPanel.setVisible(false); |
88 | } | |
89 | } | |
90 | ||
91 | 0 | public String getText() |
92 | { | |
93 | 0 | return textarea.getText(); |
94 | } | |
95 | ||
96 | 0 | public void setText(String text) |
97 | { | |
98 | 0 | textarea.setText(text); |
99 | } | |
100 | ||
101 | 0 | public void setPDBImport(SequenceI seq) |
102 | { | |
103 | 0 | this.seq = seq; |
104 | 0 | accept.setLabel(MessageManager.getString("action.accept")); |
105 | 0 | addSequences.setVisible(false); |
106 | 0 | pdbImport = true; |
107 | } | |
108 | ||
109 | 0 | public void setTreeImport() |
110 | { | |
111 | 0 | treeImport = true; |
112 | 0 | accept.setLabel(MessageManager.getString("action.accept")); |
113 | 0 | addSequences.setVisible(false); |
114 | } | |
115 | ||
116 | 0 | public void setAnnotationImport() |
117 | { | |
118 | 0 | annotationImport = true; |
119 | 0 | accept.setLabel(MessageManager.getString("action.accept")); |
120 | 0 | addSequences.setVisible(false); |
121 | } | |
122 | ||
123 | 0 | @Override |
124 | public void actionPerformed(ActionEvent evt) | |
125 | { | |
126 | 0 | if (evt.getSource() == accept) |
127 | { | |
128 | 0 | ok(true); |
129 | } | |
130 | 0 | else if (evt.getSource() == addSequences) |
131 | { | |
132 | 0 | ok(false); |
133 | } | |
134 | 0 | else if (evt.getSource() == cancel) |
135 | { | |
136 | 0 | cancel(); |
137 | } | |
138 | } | |
139 | ||
140 | 0 | protected void ok(boolean newWindow) |
141 | { | |
142 | 0 | String text = getText(); |
143 | 0 | int length = text.length(); |
144 | 0 | textarea.append("\n"); |
145 | 0 | if (textarea.getText().length() == length) |
146 | { | |
147 | 0 | String warning = "\n\n#################################################\n" |
148 | + "WARNING!! THIS IS THE MAXIMUM SIZE OF TEXTAREA!!\n" | |
149 | + "\nCAN'T INPUT FULL ALIGNMENT" | |
150 | + "\n\nYOU MUST DELETE THIS WARNING TO CONTINUE" | |
151 | + "\n\nMAKE SURE LAST SEQUENCE PASTED IS COMPLETE" | |
152 | + "\n#################################################\n"; | |
153 | 0 | textarea.setText(text.substring(0, text.length() - warning.length()) |
154 | + warning); | |
155 | ||
156 | 0 | textarea.setCaretPosition(text.length()); |
157 | } | |
158 | ||
159 | 0 | if (pdbImport) |
160 | { | |
161 | 0 | openPdbViewer(text); |
162 | ||
163 | } | |
164 | 0 | else if (treeImport) |
165 | { | |
166 | 0 | if (!loadTree()) |
167 | { | |
168 | 0 | return; |
169 | } | |
170 | } | |
171 | 0 | else if (annotationImport) |
172 | { | |
173 | 0 | loadAnnotations(); |
174 | } | |
175 | 0 | else if (alignFrame != null) |
176 | { | |
177 | 0 | loadAlignment(text, newWindow, alignFrame.getAlignViewport()); |
178 | } | |
179 | ||
180 | // TODO: dialog should indicate if data was parsed correctly or not - see | |
181 | // JAL-1102 | |
182 | 0 | if (this.getParent() instanceof Frame) |
183 | { | |
184 | 0 | ((Frame) this.getParent()).setVisible(false); |
185 | } | |
186 | else | |
187 | { | |
188 | 0 | ((Dialog) this.getParent()).setVisible(false); |
189 | } | |
190 | } | |
191 | ||
192 | /** | |
193 | * Parses text as Newick Tree format, and loads on to the alignment. Returns | |
194 | * true if successful, else false. | |
195 | */ | |
196 | 0 | protected boolean loadTree() |
197 | { | |
198 | 0 | try |
199 | { | |
200 | 0 | NewickFile fin = new NewickFile(textarea.getText(), |
201 | DataSourceType.PASTE); | |
202 | ||
203 | 0 | fin.parse(); |
204 | 0 | if (fin.getTree() != null) |
205 | { | |
206 | 0 | alignFrame.loadTree(fin, "Pasted tree file"); |
207 | 0 | return true; |
208 | } | |
209 | } catch (Exception ex) | |
210 | { | |
211 | // TODO: JAL-1102 - should have a warning message in dialog, not simply | |
212 | // overwrite the broken input data with the exception | |
213 | 0 | textarea.setText(MessageManager.formatMessage( |
214 | "label.could_not_parse_newick_file", new Object[] | |
215 | { ex.getMessage() })); | |
216 | 0 | return false; |
217 | } | |
218 | 0 | return false; |
219 | } | |
220 | ||
221 | /** | |
222 | * Parse text as an alignment file and add to the current or a new window. | |
223 | * | |
224 | * @param text | |
225 | * @param newWindow | |
226 | */ | |
227 | 0 | protected void loadAlignment(String text, boolean newWindow, |
228 | AlignViewport viewport) | |
229 | { | |
230 | 0 | AlignmentI al = null; |
231 | ||
232 | 0 | try |
233 | { | |
234 | 0 | FileFormatI format = new IdentifyFile().identify(text, |
235 | DataSourceType.PASTE); | |
236 | 0 | AppletFormatAdapter afa = new AppletFormatAdapter( |
237 | alignFrame.alignPanel); | |
238 | 0 | al = afa.readFile(text, DataSourceType.PASTE, format); |
239 | 0 | source = afa.getAlignFile(); |
240 | ||
241 | 0 | if (al != null) |
242 | { | |
243 | 0 | al.setDataset(null); // set dataset on alignment/sequences |
244 | ||
245 | /* | |
246 | * SplitFrame option dependent on applet parameter for now. | |
247 | */ | |
248 | 0 | boolean allowSplitFrame = alignFrame.viewport.applet |
249 | .getDefaultParameter("enableSplitFrame", false); | |
250 | 0 | if (allowSplitFrame && openSplitFrame(al, format)) |
251 | { | |
252 | 0 | return; |
253 | } | |
254 | 0 | if (newWindow) |
255 | { | |
256 | 0 | AlignFrame af; |
257 | ||
258 | 0 | if (source instanceof ComplexAlignFile) |
259 | { | |
260 | 0 | HiddenColumns colSel = ((ComplexAlignFile) source) |
261 | .getHiddenColumns(); | |
262 | 0 | SequenceI[] hiddenSeqs = ((ComplexAlignFile) source) |
263 | .getHiddenSequences(); | |
264 | 0 | boolean showSeqFeatures = ((ComplexAlignFile) source) |
265 | .isShowSeqFeatures(); | |
266 | 0 | String colourSchemeName = ((ComplexAlignFile) source) |
267 | .getGlobalColourScheme(); | |
268 | 0 | af = new AlignFrame(al, hiddenSeqs, colSel, |
269 | alignFrame.viewport.applet, | |
270 | "Cut & Paste input - " + format, false); | |
271 | 0 | af.getAlignViewport().setShowSequenceFeatures(showSeqFeatures); |
272 | 0 | ColourSchemeI cs = ColourSchemeMapper |
273 | .getJalviewColourScheme(colourSchemeName, al); | |
274 | 0 | if (cs != null) |
275 | { | |
276 | 0 | af.changeColour(cs); |
277 | } | |
278 | } | |
279 | else | |
280 | { | |
281 | 0 | af = new AlignFrame(al, alignFrame.viewport.applet, |
282 | "Cut & Paste input - " + format, false); | |
283 | 0 | if (source instanceof FeaturesSourceI) |
284 | { | |
285 | 0 | af.getAlignViewport().setShowSequenceFeatures(true); |
286 | } | |
287 | } | |
288 | ||
289 | 0 | af.statusBar.setText(MessageManager.getString( |
290 | "label.successfully_pasted_annotation_to_alignment")); | |
291 | } | |
292 | else | |
293 | { | |
294 | 0 | alignFrame.addSequences(al.getSequencesArray()); |
295 | 0 | alignFrame.statusBar.setText(MessageManager |
296 | .getString("label.successfully_pasted_alignment_file")); | |
297 | } | |
298 | } | |
299 | } catch (IOException ex) | |
300 | { | |
301 | 0 | ex.printStackTrace(); |
302 | } | |
303 | } | |
304 | ||
305 | /** | |
306 | * Check whether the new alignment could be mapped to the current one as | |
307 | * cDNA/protein, if so offer the option to open as split frame view. Returns | |
308 | * true if a split frame view is opened, false if not. | |
309 | * | |
310 | * @param al | |
311 | * @return | |
312 | */ | |
313 | 0 | protected boolean openSplitFrame(AlignmentI al, FileFormatI format) |
314 | { | |
315 | 0 | final AlignmentI thisAlignment = this.alignFrame.getAlignViewport() |
316 | .getAlignment(); | |
317 | 0 | if (thisAlignment.isNucleotide() == al.isNucleotide()) |
318 | { | |
319 | // both nucleotide or both protein | |
320 | 0 | return false; |
321 | } | |
322 | 0 | AlignmentI protein = thisAlignment.isNucleotide() ? al : thisAlignment; |
323 | 0 | AlignmentI dna = thisAlignment.isNucleotide() ? thisAlignment : al; |
324 | 0 | boolean mapped = AlignmentUtils.mapProteinAlignmentToCdna(protein, dna); |
325 | 0 | if (!mapped) |
326 | { | |
327 | 0 | return false; |
328 | } | |
329 | ||
330 | /* | |
331 | * A mapping is possible; ask user if they want a split frame. | |
332 | */ | |
333 | 0 | String title = MessageManager.getString("label.open_split_window"); |
334 | 0 | final JVDialog dialog = new JVDialog((Frame) this.getParent(), title, |
335 | true, 100, 400); | |
336 | 0 | dialog.ok.setLabel(MessageManager.getString("action.yes")); |
337 | 0 | dialog.cancel.setLabel(MessageManager.getString("action.no")); |
338 | 0 | Panel question = new Panel(new BorderLayout()); |
339 | 0 | final String text = MessageManager |
340 | .getString("label.open_split_window?"); | |
341 | 0 | question.add(new Label(text, Label.CENTER), BorderLayout.CENTER); |
342 | 0 | dialog.setMainPanel(question); |
343 | 0 | dialog.setVisible(true); |
344 | 0 | dialog.toFront(); |
345 | ||
346 | 0 | if (!dialog.accept) |
347 | { | |
348 | 0 | return false; |
349 | } | |
350 | ||
351 | /* | |
352 | * 'align' the added alignment to match the current one | |
353 | */ | |
354 | 0 | al.alignAs(thisAlignment); |
355 | ||
356 | /* | |
357 | * Open SplitFrame with DNA above and protein below, including the alignment | |
358 | * from textbox and a copy of the original. | |
359 | */ | |
360 | 0 | final JalviewLite applet = this.alignFrame.viewport.applet; |
361 | 0 | AlignFrame copyFrame = new AlignFrame( |
362 | this.alignFrame.viewport.getAlignment(), applet, | |
363 | alignFrame.getTitle(), false, false); | |
364 | 0 | AlignFrame newFrame = new AlignFrame(al, alignFrame.viewport.applet, |
365 | "Cut & Paste input - " + format, false, false); | |
366 | 0 | AlignFrame dnaFrame = al.isNucleotide() ? newFrame : copyFrame; |
367 | 0 | AlignFrame proteinFrame = al.isNucleotide() ? copyFrame : newFrame; |
368 | 0 | SplitFrame sf = new SplitFrame(dnaFrame, proteinFrame); |
369 | 0 | sf.addToDisplay(false, applet); |
370 | 0 | return true; |
371 | } | |
372 | ||
373 | /** | |
374 | * Parse the text as a TCoffee score file, if successful add scores as | |
375 | * alignment annotations. | |
376 | */ | |
377 | 0 | protected void loadAnnotations() |
378 | { | |
379 | 0 | TCoffeeScoreFile tcf = null; |
380 | 0 | try |
381 | { | |
382 | 0 | tcf = new TCoffeeScoreFile(textarea.getText(), |
383 | jalview.io.DataSourceType.PASTE); | |
384 | 0 | if (tcf.isValid()) |
385 | { | |
386 | 0 | if (tcf.annotateAlignment(alignFrame.viewport.getAlignment(), true)) |
387 | { | |
388 | 0 | alignFrame.tcoffeeColour.setEnabled(true); |
389 | 0 | alignFrame.alignPanel.fontChanged(); |
390 | 0 | alignFrame.changeColour(new TCoffeeColourScheme( |
391 | alignFrame.viewport.getAlignment())); | |
392 | 0 | alignFrame.statusBar.setText(MessageManager.getString( |
393 | "label.successfully_pasted_tcoffee_scores_to_alignment")); | |
394 | } | |
395 | else | |
396 | { | |
397 | // file valid but didn't get added to alignment for some reason | |
398 | 0 | alignFrame.statusBar.setText(MessageManager.formatMessage( |
399 | "label.failed_add_tcoffee_scores", new Object[] | |
400 | 0 | { (tcf.getWarningMessage() != null |
401 | ? tcf.getWarningMessage() | |
402 | : "") })); | |
403 | } | |
404 | } | |
405 | else | |
406 | { | |
407 | 0 | tcf = null; |
408 | } | |
409 | } catch (Exception x) | |
410 | { | |
411 | 0 | tcf = null; |
412 | } | |
413 | 0 | if (tcf == null) |
414 | { | |
415 | 0 | if (new AnnotationFile().annotateAlignmentView(alignFrame.viewport, |
416 | textarea.getText(), jalview.io.DataSourceType.PASTE)) | |
417 | { | |
418 | 0 | alignFrame.alignPanel.fontChanged(); |
419 | 0 | alignFrame.alignPanel.setScrollValues(0, 0); |
420 | 0 | alignFrame.statusBar.setText(MessageManager.getString( |
421 | "label.successfully_pasted_annotation_to_alignment")); | |
422 | ||
423 | } | |
424 | else | |
425 | { | |
426 | 0 | if (!alignFrame.parseFeaturesFile(textarea.getText(), |
427 | jalview.io.DataSourceType.PASTE)) | |
428 | { | |
429 | 0 | alignFrame.statusBar.setText(MessageManager.getString( |
430 | "label.couldnt_parse_pasted_text_as_valid_annotation_feature_GFF_tcoffee_file")); | |
431 | } | |
432 | } | |
433 | } | |
434 | } | |
435 | ||
436 | /** | |
437 | * Open a Jmol viewer (if available), failing that the built-in PDB viewer, | |
438 | * passing the input text as the PDB file data. | |
439 | * | |
440 | * @param text | |
441 | */ | |
442 | 0 | protected void openPdbViewer(String text) |
443 | { | |
444 | 0 | PDBEntry pdb = new PDBEntry(); |
445 | 0 | pdb.setFile(text); |
446 | ||
447 | 0 | if (alignFrame.alignPanel.av.applet.jmolAvailable) |
448 | { | |
449 | 0 | new jalview.appletgui.AppletJmol(pdb, new SequenceI[] { seq }, null, |
450 | alignFrame.alignPanel, DataSourceType.PASTE); | |
451 | } | |
452 | else | |
453 | { | |
454 | 0 | new mc_view.AppletPDBViewer(pdb, new SequenceI[] { seq }, null, |
455 | alignFrame.alignPanel, DataSourceType.PASTE); | |
456 | } | |
457 | } | |
458 | ||
459 | 0 | protected void cancel() |
460 | { | |
461 | 0 | textarea.setText(""); |
462 | 0 | if (this.getParent() instanceof Frame) |
463 | { | |
464 | 0 | ((Frame) this.getParent()).setVisible(false); |
465 | } | |
466 | else | |
467 | { | |
468 | 0 | ((Dialog) this.getParent()).setVisible(false); |
469 | } | |
470 | } | |
471 | ||
472 | protected TextArea textarea = new TextArea(); | |
473 | ||
474 | Button accept = new Button("New Window"); | |
475 | ||
476 | Button addSequences = new Button("Add to Current Alignment"); | |
477 | ||
478 | Button cancel = new Button("Close"); | |
479 | ||
480 | protected Panel buttonPanel = new Panel(); | |
481 | ||
482 | BorderLayout borderLayout1 = new BorderLayout(); | |
483 | ||
484 | 0 | private void jbInit() throws Exception |
485 | { | |
486 | 0 | textarea.setFont(new java.awt.Font("Monospaced", Font.PLAIN, 10)); |
487 | 0 | textarea.setText( |
488 | MessageManager.getString("label.paste_your_alignment_file")); | |
489 | 0 | textarea.addMouseListener(this); |
490 | 0 | this.setLayout(borderLayout1); |
491 | 0 | accept.addActionListener(this); |
492 | 0 | addSequences.addActionListener(this); |
493 | 0 | cancel.addActionListener(this); |
494 | 0 | this.add(buttonPanel, BorderLayout.SOUTH); |
495 | 0 | buttonPanel.add(accept, null); |
496 | 0 | buttonPanel.add(addSequences); |
497 | 0 | buttonPanel.add(cancel, null); |
498 | 0 | this.add(textarea, java.awt.BorderLayout.CENTER); |
499 | } | |
500 | ||
501 | 0 | @Override |
502 | public void mousePressed(MouseEvent evt) | |
503 | { | |
504 | 0 | if (textarea.getText() |
505 | .startsWith(MessageManager.getString("label.paste_your"))) | |
506 | { | |
507 | 0 | textarea.setText(""); |
508 | } | |
509 | } | |
510 | ||
511 | 0 | @Override |
512 | public void mouseReleased(MouseEvent evt) | |
513 | { | |
514 | } | |
515 | ||
516 | 0 | @Override |
517 | public void mouseClicked(MouseEvent evt) | |
518 | { | |
519 | } | |
520 | ||
521 | 0 | @Override |
522 | public void mouseEntered(MouseEvent evt) | |
523 | { | |
524 | } | |
525 | ||
526 | 0 | @Override |
527 | public void mouseExited(MouseEvent evt) | |
528 | { | |
529 | } | |
530 | } |