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 .
19
* The Jalview Authors are detailed in the 'AUTHORS' file.
20
*/
21
package jalview.gui;
22
23
import java.awt.BorderLayout;
24
import java.awt.Color;
25
import java.awt.Component;
26
import java.awt.Rectangle;
27
import java.awt.Toolkit;
28
import java.awt.datatransfer.Clipboard;
29
import java.awt.datatransfer.DataFlavor;
30
import java.awt.datatransfer.StringSelection;
31
import java.awt.datatransfer.Transferable;
32
import java.awt.dnd.DnDConstants;
33
import java.awt.dnd.DropTargetDragEvent;
34
import java.awt.dnd.DropTargetDropEvent;
35
import java.awt.dnd.DropTargetEvent;
36
import java.awt.dnd.DropTargetListener;
37
import java.awt.event.ActionEvent;
38
import java.awt.event.ActionListener;
39
import java.awt.event.FocusAdapter;
40
import java.awt.event.FocusEvent;
41
import java.awt.event.ItemEvent;
42
import java.awt.event.ItemListener;
43
import java.awt.event.KeyAdapter;
44
import java.awt.event.KeyEvent;
45
import java.awt.event.MouseEvent;
46
import java.awt.print.PageFormat;
47
import java.awt.print.PrinterJob;
48
import java.beans.PropertyChangeEvent;
49
import java.io.File;
50
import java.io.FileWriter;
51
import java.io.IOException;
52
import java.io.OutputStreamWriter;
53
import java.io.PrintWriter;
54
import java.net.URL;
55
import java.util.ArrayList;
56
import java.util.Arrays;
57
import java.util.Deque;
58
import java.util.Enumeration;
59
import java.util.HashMap;
60
import java.util.Hashtable;
61
import java.util.List;
62
import java.util.Locale;
63
import java.util.Map;
64
import java.util.Vector;
65
66
import javax.swing.ButtonGroup;
67
import javax.swing.JCheckBoxMenuItem;
68
import javax.swing.JComponent;
69
import javax.swing.JEditorPane;
70
import javax.swing.JInternalFrame;
71
import javax.swing.JLabel;
72
import javax.swing.JLayeredPane;
73
import javax.swing.JMenu;
74
import javax.swing.JMenuItem;
75
import javax.swing.JPanel;
76
import javax.swing.JProgressBar;
77
import javax.swing.JScrollPane;
78
import javax.swing.SwingUtilities;
79
80
import ext.vamsas.ServiceHandle;
81
import jalview.analysis.AlignmentAnnotationUtils;
82
import jalview.analysis.AlignmentSorter;
83
import jalview.analysis.AlignmentUtils;
84
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
85
import jalview.analysis.CrossRef;
86
import jalview.analysis.Dna;
87
import jalview.analysis.GeneticCodeI;
88
import jalview.analysis.ParseProperties;
89
import jalview.analysis.SequenceIdMatcher;
90
import jalview.api.AlignExportSettingsI;
91
import jalview.api.AlignViewControllerGuiI;
92
import jalview.api.AlignViewControllerI;
93
import jalview.api.AlignViewportI;
94
import jalview.api.AlignmentViewPanel;
95
import jalview.api.FeatureSettingsControllerI;
96
import jalview.api.FeatureSettingsModelI;
97
import jalview.api.SplitContainerI;
98
import jalview.api.ViewStyleI;
99
import jalview.api.analysis.SimilarityParamsI;
100
import jalview.bin.Cache;
101
import jalview.bin.Console;
102
import jalview.bin.Jalview;
103
import jalview.bin.groovy.JalviewObjectI;
104
import jalview.commands.CommandI;
105
import jalview.commands.EditCommand;
106
import jalview.commands.EditCommand.Action;
107
import jalview.commands.OrderCommand;
108
import jalview.commands.RemoveGapColCommand;
109
import jalview.commands.RemoveGapsCommand;
110
import jalview.commands.SlideSequencesCommand;
111
import jalview.commands.TrimRegionCommand;
112
import jalview.datamodel.AlignExportSettingsAdapter;
113
import jalview.datamodel.AlignedCodonFrame;
114
import jalview.datamodel.Alignment;
115
import jalview.datamodel.AlignmentAnnotation;
116
import jalview.datamodel.AlignmentExportData;
117
import jalview.datamodel.AlignmentI;
118
import jalview.datamodel.AlignmentOrder;
119
import jalview.datamodel.AlignmentView;
120
import jalview.datamodel.ColumnSelection;
121
import jalview.datamodel.ContactMatrixI;
122
import jalview.datamodel.HiddenColumns;
123
import jalview.datamodel.PDBEntry;
124
import jalview.datamodel.SeqCigar;
125
import jalview.datamodel.Sequence;
126
import jalview.datamodel.SequenceGroup;
127
import jalview.datamodel.SequenceI;
128
import jalview.datamodel.annotations.AlphaFoldAnnotationRowBuilder;
129
import jalview.gui.ColourMenuHelper.ColourChangeListener;
130
import jalview.gui.ViewSelectionMenu.ViewSetProvider;
131
import jalview.io.AlignmentProperties;
132
import jalview.io.AnnotationFile;
133
import jalview.io.BackupFiles;
134
import jalview.io.BioJsHTMLOutput;
135
import jalview.io.DataSourceType;
136
import jalview.io.FileFormat;
137
import jalview.io.FileFormatI;
138
import jalview.io.FileFormats;
139
import jalview.io.FileLoader;
140
import jalview.io.FileParse;
141
import jalview.io.FormatAdapter;
142
import jalview.io.HtmlSvgOutput;
143
import jalview.io.IdentifyFile;
144
import jalview.io.JPredFile;
145
import jalview.io.JalviewFileChooser;
146
import jalview.io.JalviewFileView;
147
import jalview.io.JnetAnnotationMaker;
148
import jalview.io.NewickFile;
149
import jalview.io.ScoreMatrixFile;
150
import jalview.io.TCoffeeScoreFile;
151
import jalview.io.exceptions.ImageOutputException;
152
import jalview.io.vcf.VCFLoader;
153
import jalview.jbgui.GAlignFrame;
154
import jalview.project.Jalview2XML;
155
import jalview.schemes.ColourSchemeI;
156
import jalview.schemes.ColourSchemes;
157
import jalview.schemes.ResidueColourScheme;
158
import jalview.schemes.TCoffeeColourScheme;
159
import jalview.util.Constants;
160
import jalview.util.HttpUtils;
161
import jalview.util.ImageMaker.TYPE;
162
import jalview.util.MessageManager;
163
import jalview.util.Platform;
164
import jalview.util.imagemaker.BitmapImageSizing;
165
import jalview.viewmodel.AlignmentViewport;
166
import jalview.viewmodel.ViewportRanges;
167
import jalview.ws.DBRefFetcher;
168
import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
169
import jalview.ws.jws1.Discoverer;
170
import jalview.ws.jws2.Jws2Discoverer;
171
import jalview.ws.jws2.jabaws2.Jws2Instance;
172
import jalview.ws.seqfetcher.DbSourceProxy;
173
174
/**
175
* DOCUMENT ME!
176
*
177
* @author $author$
178
* @version $Revision$
179
*/
180
@SuppressWarnings("serial")
181
public class AlignFrame extends GAlignFrame implements DropTargetListener,
182
IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
183
{
184
185
public static final int DEFAULT_WIDTH = 700;
186
187
public static final int DEFAULT_HEIGHT = 500;
188
189
/*
190
* The currently displayed panel (selected tabbed view if more than one)
191
*/
192
public AlignmentPanel alignPanel;
193
194
AlignViewport viewport;
195
196
public AlignViewControllerI avc;
197
198
List alignPanels = new ArrayList<>();
199
200
/**
201
* Last format used to load or save alignments in this window
202
*/
203
FileFormatI currentFileFormat = null;
204
205
/**
206
* Current filename for this alignment
207
*/
208
String fileName = null;
209
210
File fileObject;
211
212
/**
213
* Creates a new AlignFrame object with specific width and height.
214
*
215
* @param al
216
* @param width
217
* @param height
218
*/
219
public AlignFrame(AlignmentI al, int width, int height)
220
{
221
this(al, null, width, height);
222
}
223
224
/**
225
* Creates a new AlignFrame object with specific width, height and
226
* sequenceSetId
227
*
228
* @param al
229
* @param width
230
* @param height
231
* @param sequenceSetId
232
*/
233
public AlignFrame(AlignmentI al, int width, int height,
234
String sequenceSetId)
235
{
236
this(al, null, width, height, sequenceSetId);
237
}
238
239
/**
240
* Creates a new AlignFrame object with specific width, height and
241
* sequenceSetId
242
*
243
* @param al
244
* @param width
245
* @param height
246
* @param sequenceSetId
247
* @param viewId
248
*/
249
public AlignFrame(AlignmentI al, int width, int height,
250
String sequenceSetId, String viewId)
251
{
252
this(al, null, width, height, sequenceSetId, viewId);
253
}
254
255
/**
256
* new alignment window with hidden columns
257
*
258
* @param al
259
* AlignmentI
260
* @param hiddenColumns
261
* ColumnSelection or null
262
* @param width
263
* Width of alignment frame
264
* @param height
265
* height of frame.
266
*/
267
public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
268
int height)
269
{
270
this(al, hiddenColumns, width, height, null);
271
}
272
273
/**
274
* Create alignment frame for al with hiddenColumns, a specific width and
275
* height, and specific sequenceId
276
*
277
* @param al
278
* @param hiddenColumns
279
* @param width
280
* @param height
281
* @param sequenceSetId
282
* (may be null)
283
*/
284
public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
285
int height, String sequenceSetId)
286
{
287
this(al, hiddenColumns, width, height, sequenceSetId, null);
288
}
289
290
/**
291
* Create alignment frame for al with hiddenColumns, a specific width and
292
* height, and specific sequenceId
293
*
294
* @param al
295
* @param hiddenColumns
296
* @param width
297
* @param height
298
* @param sequenceSetId
299
* (may be null)
300
* @param viewId
301
* (may be null)
302
*/
303
public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns, int width,
304
int height, String sequenceSetId, String viewId)
305
{
306
setSize(width, height);
307
308
if (al.getDataset() == null)
309
{
310
al.setDataset(null);
311
}
312
313
viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
314
315
alignPanel = new AlignmentPanel(this, viewport);
316
317
addAlignmentPanel(alignPanel, true);
318
init();
319
}
320
321
public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
322
HiddenColumns hiddenColumns, int width, int height)
323
{
324
setSize(width, height);
325
326
if (al.getDataset() == null)
327
{
328
al.setDataset(null);
329
}
330
331
viewport = new AlignViewport(al, hiddenColumns);
332
333
if (hiddenSeqs != null && hiddenSeqs.length > 0)
334
{
335
viewport.hideSequence(hiddenSeqs);
336
}
337
alignPanel = new AlignmentPanel(this, viewport);
338
addAlignmentPanel(alignPanel, true);
339
init();
340
}
341
342
/**
343
* Make a new AlignFrame from existing alignmentPanels
344
*
345
* @param ap
346
* AlignmentPanel
347
* @param av
348
* AlignViewport
349
*/
350
public AlignFrame(AlignmentPanel ap)
351
{
352
viewport = ap.av;
353
alignPanel = ap;
354
addAlignmentPanel(ap, false);
355
init();
356
}
357
358
/**
359
* initalise the alignframe from the underlying viewport data and the
360
* configurations
361
*/
362
void init()
363
{
364
setFrameIcon(null);
365
366
// setBackground(Color.white); // BH 2019
367
368
if (!Jalview.isHeadlessMode())
369
{
370
progressBar = new ProgressBar(this.statusPanel, this.statusBar);
371
}
372
373
avc = new jalview.controller.AlignViewController(this, viewport,
374
alignPanel);
375
if (viewport.getAlignmentConservationAnnotation() == null)
376
{
377
// BLOSUM62Colour.setEnabled(false);
378
conservationMenuItem.setEnabled(false);
379
modifyConservation.setEnabled(false);
380
// PIDColour.setEnabled(false);
381
// abovePIDThreshold.setEnabled(false);
382
// modifyPID.setEnabled(false);
383
}
384
385
String sortby = Cache.getDefault("SORT_ALIGNMENT", "No sort");
386
387
if (sortby.equals("Id"))
388
{
389
sortIDMenuItem_actionPerformed(null);
390
}
391
else if (sortby.equals("Pairwise Identity"))
392
{
393
sortPairwiseMenuItem_actionPerformed(null);
394
}
395
396
this.alignPanel.av
397
.setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
398
399
setMenusFromViewport(viewport);
400
buildSortByAnnotationScoresMenu();
401
calculateTree.addActionListener(new ActionListener()
402
{
403
404
@Override
405
public void actionPerformed(ActionEvent e)
406
{
407
openTreePcaDialog();
408
}
409
});
410
buildColourMenu();
411
412
if (Desktop.desktop != null)
413
{
414
this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
415
if (!Platform.isJS())
416
{
417
addServiceListeners();
418
}
419
setGUINucleotide();
420
}
421
422
if (viewport.getWrapAlignment())
423
{
424
wrapMenuItem_actionPerformed(null);
425
}
426
427
if (Cache.getDefault("SHOW_OVERVIEW", false))
428
{
429
this.overviewMenuItem_actionPerformed(null);
430
}
431
432
addKeyListener();
433
434
final List selviews = new ArrayList<>();
435
final List origview = new ArrayList<>();
436
final String menuLabel = MessageManager
437
.getString("label.copy_format_from");
438
ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
439
new ViewSetProvider()
440
{
441
442
@Override
443
public AlignmentPanel[] getAllAlignmentPanels()
444
{
445
origview.clear();
446
origview.add(alignPanel);
447
// make an array of all alignment panels except for this one
448
List aps = new ArrayList<>(
449
Arrays.asList(Desktop.getAlignmentPanels(null)));
450
aps.remove(AlignFrame.this.alignPanel);
451
return aps.toArray(new AlignmentPanel[aps.size()]);
452
}
453
}, selviews, new ItemListener()
454
{
455
456
@Override
457
public void itemStateChanged(ItemEvent e)
458
{
459
if (origview.size() > 0)
460
{
461
final AlignmentPanel ap = origview.get(0);
462
463
/*
464
* Copy the ViewStyle of the selected panel to 'this one'. Don't change value of
465
* 'scaleProteinAsCdna' unless copying from a SplitFrame.
466
*/
467
ViewStyleI vs = selviews.get(0).getAlignViewport()
468
.getViewStyle();
469
boolean fromSplitFrame = selviews.get(0)
470
.getAlignViewport().getCodingComplement() != null;
471
if (!fromSplitFrame)
472
{
473
vs.setScaleProteinAsCdna(ap.getAlignViewport()
474
.getViewStyle().isScaleProteinAsCdna());
475
}
476
ap.getAlignViewport().setViewStyle(vs);
477
478
/*
479
* Also rescale ViewStyle of SplitFrame complement if there is one _and_ it is
480
* set to 'scaledProteinAsCdna'; we don't copy the whole ViewStyle (allow cDNA
481
* protein to have different fonts)
482
*/
483
AlignViewportI complement = ap.getAlignViewport()
484
.getCodingComplement();
485
if (complement != null && vs.isScaleProteinAsCdna())
486
{
487
AlignFrame af = Desktop.getAlignFrameFor(complement);
488
((SplitFrame) af.getSplitViewContainer())
489
.adjustLayout();
490
af.setMenusForViewport();
491
}
492
493
ap.updateLayout();
494
ap.setSelected(true);
495
ap.alignFrame.setMenusForViewport();
496
497
}
498
}
499
});
500
if (Cache.getDefault("VERSION", "DEVELOPMENT").toLowerCase(Locale.ROOT)
501
.indexOf("devel") > -1
502
|| Cache.getDefault("VERSION", "DEVELOPMENT")
503
.toLowerCase(Locale.ROOT).indexOf("test") > -1)
504
{
505
formatMenu.add(vsel);
506
}
507
addFocusListener(new FocusAdapter()
508
{
509
@Override
510
public void focusGained(FocusEvent e)
511
{
512
Jalview.getInstance().setCurrentAlignFrame(AlignFrame.this);
513
}
514
});
515
516
}
517
518
/**
519
* Change the filename and format for the alignment, and enable the 'reload'
520
* button functionality.
521
*
522
* @param file
523
* valid filename
524
* @param format
525
* format of file
526
*/
527
public void setFileName(String file, FileFormatI format)
528
{
529
fileName = file;
530
setFileFormat(format);
531
reload.setEnabled(true);
532
}
533
534
/**
535
* JavaScript will have this, maybe others. More dependable than a file name
536
* and maintains a reference to the actual bytes loaded.
537
*
538
* @param file
539
*/
540
public void setFileObject(File file)
541
{
542
this.fileObject = file;
543
}
544
545
/**
546
* Add a KeyListener with handlers for various KeyPressed and KeyReleased
547
* events
548
*/
549
void addKeyListener()
550
{
551
addKeyListener(new KeyAdapter()
552
{
553
@Override
554
public void keyPressed(KeyEvent evt)
555
{
556
if (viewport.cursorMode
557
&& ((evt.getKeyCode() >= KeyEvent.VK_0
558
&& evt.getKeyCode() <= KeyEvent.VK_9)
559
|| (evt.getKeyCode() >= KeyEvent.VK_NUMPAD0
560
&& evt.getKeyCode() <= KeyEvent.VK_NUMPAD9))
561
&& Character.isDigit(evt.getKeyChar()))
562
{
563
alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
564
}
565
566
switch (evt.getKeyCode())
567
{
568
569
case 27: // escape key
570
deselectAllSequenceMenuItem_actionPerformed(null);
571
572
break;
573
574
case KeyEvent.VK_DOWN:
575
if (evt.isAltDown() || !viewport.cursorMode)
576
{
577
moveSelectedSequences(false);
578
}
579
if (viewport.cursorMode)
580
{
581
alignPanel.getSeqPanel().moveCursor(0, 1, evt.isShiftDown());
582
}
583
break;
584
585
case KeyEvent.VK_UP:
586
if (evt.isAltDown() || !viewport.cursorMode)
587
{
588
moveSelectedSequences(true);
589
}
590
if (viewport.cursorMode)
591
{
592
alignPanel.getSeqPanel().moveCursor(0, -1, evt.isShiftDown());
593
}
594
595
break;
596
597
case KeyEvent.VK_LEFT:
598
if (evt.isAltDown() || !viewport.cursorMode)
599
{
600
slideSequences(false,
601
alignPanel.getSeqPanel().getKeyboardNo1());
602
}
603
else
604
{
605
alignPanel.getSeqPanel().moveCursor(-1, 0, evt.isShiftDown());
606
}
607
608
break;
609
610
case KeyEvent.VK_RIGHT:
611
if (evt.isAltDown() || !viewport.cursorMode)
612
{
613
slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
614
}
615
else
616
{
617
alignPanel.getSeqPanel().moveCursor(1, 0, evt.isShiftDown());
618
}
619
break;
620
621
case KeyEvent.VK_SPACE:
622
if (viewport.cursorMode)
623
{
624
alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
625
|| evt.isShiftDown() || evt.isAltDown());
626
}
627
break;
628
629
// case KeyEvent.VK_A:
630
// if (viewport.cursorMode)
631
// {
632
// alignPanel.seqPanel.insertNucAtCursor(false,"A");
633
// //jalview.bin.Console.outPrintln("A");
634
// }
635
// break;
636
/*
637
* case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
638
* jalview.bin.Console.outPrintln("closing bracket"); } break;
639
*/
640
case KeyEvent.VK_DELETE:
641
case KeyEvent.VK_BACK_SPACE:
642
if (!viewport.cursorMode)
643
{
644
cut_actionPerformed();
645
}
646
else
647
{
648
alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
649
|| evt.isShiftDown() || evt.isAltDown());
650
}
651
652
break;
653
654
case KeyEvent.VK_S:
655
if (viewport.cursorMode)
656
{
657
alignPanel.getSeqPanel().setCursorRow();
658
}
659
break;
660
case KeyEvent.VK_C:
661
if (viewport.cursorMode && !evt.isControlDown())
662
{
663
alignPanel.getSeqPanel().setCursorColumn();
664
}
665
break;
666
case KeyEvent.VK_P:
667
if (viewport.cursorMode)
668
{
669
alignPanel.getSeqPanel().setCursorPosition();
670
}
671
break;
672
673
case KeyEvent.VK_ENTER:
674
case KeyEvent.VK_COMMA:
675
if (viewport.cursorMode)
676
{
677
alignPanel.getSeqPanel().setCursorRowAndColumn();
678
}
679
break;
680
681
case KeyEvent.VK_Q:
682
if (viewport.cursorMode)
683
{
684
alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
685
}
686
break;
687
case KeyEvent.VK_M:
688
if (viewport.cursorMode)
689
{
690
alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
691
}
692
break;
693
694
case KeyEvent.VK_F2:
695
viewport.cursorMode = !viewport.cursorMode;
696
setStatus(MessageManager
697
.formatMessage("label.keyboard_editing_mode", new String[]
698
{ (viewport.cursorMode ? "on" : "off") }));
699
if (viewport.cursorMode)
700
{
701
ViewportRanges ranges = viewport.getRanges();
702
alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
703
.getStartRes();
704
alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
705
.getStartSeq();
706
}
707
alignPanel.getSeqPanel().seqCanvas.repaint();
708
break;
709
710
case KeyEvent.VK_F1:
711
try
712
{
713
Help.showHelpWindow();
714
} catch (Exception ex)
715
{
716
ex.printStackTrace();
717
}
718
break;
719
case KeyEvent.VK_H:
720
{
721
boolean toggleSeqs = !evt.isControlDown();
722
boolean toggleCols = !evt.isShiftDown();
723
toggleHiddenRegions(toggleSeqs, toggleCols);
724
break;
725
}
726
case KeyEvent.VK_B:
727
{
728
boolean toggleSel = evt.isControlDown() || evt.isMetaDown();
729
boolean modifyExisting = true; // always modify, don't clear
730
// evt.isShiftDown();
731
boolean invertHighlighted = evt.isAltDown();
732
avc.markHighlightedColumns(invertHighlighted, modifyExisting,
733
toggleSel);
734
break;
735
}
736
case KeyEvent.VK_PAGE_UP:
737
viewport.getRanges().pageUp();
738
break;
739
case KeyEvent.VK_PAGE_DOWN:
740
viewport.getRanges().pageDown();
741
break;
742
}
743
}
744
745
@Override
746
public void keyReleased(KeyEvent evt)
747
{
748
switch (evt.getKeyCode())
749
{
750
case KeyEvent.VK_LEFT:
751
if (evt.isAltDown() || !viewport.cursorMode)
752
{
753
viewport.firePropertyChange("alignment", null,
754
viewport.getAlignment().getSequences());
755
}
756
break;
757
758
case KeyEvent.VK_RIGHT:
759
if (evt.isAltDown() || !viewport.cursorMode)
760
{
761
viewport.firePropertyChange("alignment", null,
762
viewport.getAlignment().getSequences());
763
}
764
break;
765
}
766
}
767
});
768
}
769
770
public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
771
{
772
ap.alignFrame = this;
773
avc = new jalview.controller.AlignViewController(this, viewport,
774
alignPanel);
775
776
alignPanels.add(ap);
777
778
PaintRefresher.Register(ap, ap.av.getSequenceSetId());
779
780
int aSize = alignPanels.size();
781
782
tabbedPane.setVisible(aSize > 1 || ap.av.getViewName() != null);
783
784
if (aSize == 1 && ap.av.getViewName() == null)
785
{
786
this.getContentPane().add(ap, BorderLayout.CENTER);
787
}
788
else
789
{
790
if (aSize == 2)
791
{
792
setInitialTabVisible();
793
}
794
795
expandViews.setEnabled(true);
796
gatherViews.setEnabled(true);
797
tabbedPane.addTab(ap.av.getViewName(), ap);
798
799
ap.setVisible(false);
800
}
801
802
if (newPanel)
803
{
804
if (ap.av.isPadGaps())
805
{
806
ap.av.getAlignment().padGaps();
807
}
808
ap.av.updateConservation(ap);
809
ap.av.updateConsensus(ap);
810
ap.av.updateSecondaryStructureConsensus(ap);
811
ap.av.updateStrucConsensus(ap);
812
}
813
}
814
815
public void setInitialTabVisible()
816
{
817
expandViews.setEnabled(true);
818
gatherViews.setEnabled(true);
819
tabbedPane.setVisible(true);
820
AlignmentPanel first = alignPanels.get(0);
821
tabbedPane.addTab(first.av.getViewName(), first);
822
this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
823
}
824
825
public AlignViewport getViewport()
826
{
827
return viewport;
828
}
829
830
/* Set up intrinsic listeners for dynamically generated GUI bits. */
831
private void addServiceListeners()
832
{
833
final java.beans.PropertyChangeListener thisListener;
834
Desktop.instance.addJalviewPropertyChangeListener("services",
835
thisListener = new java.beans.PropertyChangeListener()
836
{
837
@Override
838
public void propertyChange(PropertyChangeEvent evt)
839
{
840
// // jalview.bin.Console.outPrintln("Discoverer property
841
// change.");
842
// if (evt.getPropertyName().equals("services"))
843
{
844
SwingUtilities.invokeLater(new Runnable()
845
{
846
847
@Override
848
public void run()
849
{
850
jalview.bin.Console.errPrintln(
851
"Rebuild WS Menu for service change");
852
BuildWebServiceMenu();
853
}
854
855
});
856
}
857
}
858
});
859
addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
860
{
861
@Override
862
public void internalFrameClosed(
863
javax.swing.event.InternalFrameEvent evt)
864
{
865
// jalview.bin.Console.outPrintln("deregistering discoverer listener");
866
Desktop.instance.removeJalviewPropertyChangeListener("services",
867
thisListener);
868
closeMenuItem_actionPerformed(true);
869
}
870
});
871
// Finally, build the menu once to get current service state
872
new Thread(new Runnable()
873
{
874
@Override
875
public void run()
876
{
877
BuildWebServiceMenu();
878
}
879
}).start();
880
}
881
882
/**
883
* Configure menu items that vary according to whether the alignment is
884
* nucleotide or protein
885
*/
886
public void setGUINucleotide()
887
{
888
AlignmentI al = getViewport().getAlignment();
889
boolean nucleotide = al.isNucleotide();
890
891
loadVcf.setVisible(nucleotide);
892
showTranslation.setVisible(nucleotide);
893
showReverse.setVisible(nucleotide);
894
showReverseComplement.setVisible(nucleotide);
895
conservationMenuItem.setEnabled(!nucleotide);
896
modifyConservation
897
.setEnabled(!nucleotide && conservationMenuItem.isSelected());
898
byConsensusSecondaryStructureMenuItem.setEnabled(!nucleotide);
899
modifyConsensusSecondaryStructureThreshold.setEnabled(!nucleotide
900
&& byConsensusSecondaryStructureMenuItem.isSelected());
901
showGroupConservation.setEnabled(!nucleotide);
902
903
showComplementMenuItem
904
.setText(nucleotide ? MessageManager.getString("label.protein")
905
: MessageManager.getString("label.nucleotide"));
906
}
907
908
/**
909
* set up menus for the current viewport. This may be called after any
910
* operation that affects the data in the current view (selection changed,
911
* etc) to update the menus to reflect the new state.
912
*/
913
@Override
914
public void setMenusForViewport()
915
{
916
setMenusFromViewport(viewport);
917
}
918
919
/**
920
* Need to call this method when tabs are selected for multiple views, or when
921
* loading from Jalview2XML.java
922
*
923
* @param av
924
* AlignViewport
925
*/
926
public void setMenusFromViewport(AlignViewport av)
927
{
928
padGapsMenuitem.setSelected(av.isPadGaps());
929
colourTextMenuItem.setSelected(av.isShowColourText());
930
abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
931
modifyPID.setEnabled(abovePIDThreshold.isSelected());
932
conservationMenuItem.setSelected(av.getConservationSelected());
933
modifyConservation.setEnabled(conservationMenuItem.isSelected());
934
byConsensusSecondaryStructureMenuItem
935
.setSelected(av.getByConsensusSecondaryStructureSelected());
936
modifyConsensusSecondaryStructureThreshold
937
.setEnabled(byConsensusSecondaryStructureMenuItem.isSelected());
938
seqLimits.setSelected(av.getShowJVSuffix());
939
idRightAlign.setSelected(av.isRightAlignIds());
940
centreColumnLabelsMenuItem.setState(av.isCentreColumnLabels());
941
renderGapsMenuItem.setSelected(av.isRenderGaps());
942
wrapMenuItem.setSelected(av.getWrapAlignment());
943
scaleAbove.setVisible(av.getWrapAlignment());
944
scaleLeft.setVisible(av.getWrapAlignment());
945
scaleRight.setVisible(av.getWrapAlignment());
946
annotationPanelMenuItem.setState(av.isShowAnnotation());
947
/*
948
* Show/hide annotations only enabled if annotation panel is shown
949
*/
950
showAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
951
hideAllSeqAnnotations.setEnabled(annotationPanelMenuItem.getState());
952
showAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
953
hideAllAlAnnotations.setEnabled(annotationPanelMenuItem.getState());
954
viewBoxesMenuItem.setSelected(av.getShowBoxes());
955
viewTextMenuItem.setSelected(av.getShowText());
956
showNonconservedMenuItem.setSelected(av.getShowUnconserved());
957
showGroupConsensus.setSelected(av.isShowGroupConsensus());
958
showGroupSSConsensus.setSelected(av.isShowGroupSSConsensus());
959
showStrucProvider.setSelected(av.isShowStructureProvider());
960
showGroupConservation.setSelected(av.isShowGroupConservation());
961
showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
962
showSequenceLogo.setSelected(av.isShowSequenceLogo());
963
normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
964
965
ColourMenuHelper.setColourSelected(colourMenu,
966
av.getGlobalColourScheme());
967
968
showSeqFeatures.setSelected(av.isShowSequenceFeatures());
969
hiddenMarkers.setState(av.getShowHiddenMarkers());
970
applyToAllGroups.setState(av.getColourAppliesToAllGroups());
971
showNpFeatsMenuitem.setSelected(av.isShowNPFeats());
972
showDbRefsMenuitem.setSelected(av.isShowDBRefs());
973
autoCalculate.setSelected(av.autoCalculateConsensus);
974
sortByTree.setSelected(av.sortByTree);
975
listenToViewSelections.setSelected(av.followSelection);
976
977
showProducts.setEnabled(canShowProducts());
978
setGroovyEnabled(Desktop.getGroovyConsole() != null);
979
980
updateEditMenuBar();
981
}
982
983
/**
984
* Set the enabled state of the 'Run Groovy' option in the Calculate menu
985
*
986
* @param b
987
*/
988
public void setGroovyEnabled(boolean b)
989
{
990
runGroovy.setEnabled(b);
991
}
992
993
private IProgressIndicator progressBar;
994
995
/*
996
* (non-Javadoc)
997
*
998
* @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
999
*/
1000
@Override
1001
public void setProgressBar(String message, long id)
1002
{
1003
if (!Platform.isHeadless() && progressBar != null)
1004
progressBar.setProgressBar(message, id);
1005
}
1006
1007
@Override
1008
public JProgressBar getProgressBar(long id)
1009
{
1010
if (progressBar != null)
1011
return progressBar.getProgressBar(id);
1012
return null;
1013
}
1014
1015
@Override
1016
public String getMessage(long id)
1017
{
1018
return progressBar.getMessage(id);
1019
}
1020
1021
@Override
1022
public void setProgressBarMessage(long id, String message)
1023
{
1024
progressBar.setProgressBarMessage(id, message);
1025
}
1026
1027
@Override
1028
public void registerHandler(final long id,
1029
final IProgressIndicatorHandler handler)
1030
{
1031
if (progressBar != null)
1032
progressBar.registerHandler(id, handler);
1033
}
1034
1035
/**
1036
*
1037
* @return true if any progress bars are still active
1038
*/
1039
@Override
1040
public boolean operationInProgress()
1041
{
1042
return progressBar == null ? false : progressBar.operationInProgress();
1043
}
1044
1045
/**
1046
* Sets the text of the status bar. Note that setting a null or empty value
1047
* will cause the status bar to be hidden, with possibly undesirable flicker
1048
* of the screen layout.
1049
*/
1050
@Override
1051
public void setStatus(String text)
1052
{
1053
statusBar.setText(text == null || text.isEmpty() ? " " : text);
1054
}
1055
1056
/*
1057
* Added so Castor Mapping file can obtain Jalview Version
1058
*/
1059
public String getVersion()
1060
{
1061
return Cache.getProperty("VERSION");
1062
}
1063
1064
public FeatureRenderer getFeatureRenderer()
1065
{
1066
return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
1067
}
1068
1069
@Override
1070
public void fetchSequence_actionPerformed()
1071
{
1072
new SequenceFetcher(this);
1073
}
1074
1075
@Override
1076
public void addFromFile_actionPerformed(ActionEvent e)
1077
{
1078
Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
1079
}
1080
1081
@Override
1082
public void reload_actionPerformed(ActionEvent e)
1083
{
1084
if (fileName != null)
1085
{
1086
// TODO: JAL-1108 - ensure all associated frames are closed regardless of
1087
// originating file's format
1088
// TODO: work out how to recover feature settings for correct view(s) when
1089
// file is reloaded.
1090
if (FileFormat.Jalview.equals(currentFileFormat))
1091
{
1092
JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1093
for (int i = 0; i < frames.length; i++)
1094
{
1095
if (frames[i] instanceof AlignFrame && frames[i] != this
1096
&& ((AlignFrame) frames[i]).fileName != null
1097
&& ((AlignFrame) frames[i]).fileName.equals(fileName))
1098
{
1099
try
1100
{
1101
frames[i].setSelected(true);
1102
Desktop.instance.closeAssociatedWindows();
1103
} catch (java.beans.PropertyVetoException ex)
1104
{
1105
}
1106
}
1107
1108
}
1109
Desktop.instance.closeAssociatedWindows();
1110
1111
FileLoader loader = new FileLoader();
1112
DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(fileName)
1113
? DataSourceType.URL
1114
: DataSourceType.FILE;
1115
loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
1116
}
1117
else
1118
{
1119
Rectangle bounds = this.getBounds();
1120
1121
FileLoader loader = new FileLoader();
1122
1123
AlignFrame newframe = null;
1124
1125
if (fileObject == null)
1126
{
1127
1128
DataSourceType protocol = HttpUtils.startsWithHttpOrHttps(
1129
fileName) ? DataSourceType.URL : DataSourceType.FILE;
1130
newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
1131
currentFileFormat);
1132
}
1133
else
1134
{
1135
newframe = loader.LoadFileWaitTillLoaded(fileObject,
1136
DataSourceType.FILE, currentFileFormat);
1137
}
1138
1139
newframe.setBounds(bounds);
1140
if (featureSettings != null && featureSettings.isShowing())
1141
{
1142
final Rectangle fspos = featureSettings.frame.getBounds();
1143
// TODO: need a 'show feature settings' function that takes bounds -
1144
// need to refactor Desktop.addFrame
1145
newframe.featureSettings_actionPerformed(null);
1146
final FeatureSettings nfs = newframe.featureSettings;
1147
SwingUtilities.invokeLater(new Runnable()
1148
{
1149
@Override
1150
public void run()
1151
{
1152
nfs.frame.setBounds(fspos);
1153
}
1154
});
1155
this.featureSettings.close();
1156
this.featureSettings = null;
1157
}
1158
this.closeMenuItem_actionPerformed(true);
1159
}
1160
}
1161
}
1162
1163
@Override
1164
public void addFromText_actionPerformed(ActionEvent e)
1165
{
1166
Desktop.instance
1167
.inputTextboxMenuItem_actionPerformed(viewport.getAlignPanel());
1168
}
1169
1170
@Override
1171
public void addFromURL_actionPerformed(ActionEvent e)
1172
{
1173
Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
1174
}
1175
1176
@Override
1177
public void save_actionPerformed(ActionEvent e)
1178
{
1179
if (fileName == null || (currentFileFormat == null)
1180
|| HttpUtils.startsWithHttpOrHttps(fileName))
1181
{
1182
saveAs_actionPerformed();
1183
}
1184
else
1185
{
1186
saveAlignment(fileName, currentFileFormat);
1187
}
1188
}
1189
1190
/**
1191
* Saves the alignment to a file with a name chosen by the user, if necessary
1192
* warning if a file would be overwritten
1193
*/
1194
@Override
1195
public void saveAs_actionPerformed()
1196
{
1197
JalviewFileChooser chooser = JalviewFileChooser.forWrite(
1198
Cache.getProperty("LAST_DIRECTORY"),
1199
currentFileFormat == null ? null : currentFileFormat.getName(),
1200
true);
1201
1202
chooser.setFileView(new JalviewFileView());
1203
chooser.setDialogTitle(
1204
MessageManager.getString("label.save_alignment_to_file"));
1205
chooser.setToolTipText(MessageManager.getString("action.save"));
1206
1207
int value = chooser.showSaveDialog(this);
1208
1209
if (value != JalviewFileChooser.APPROVE_OPTION)
1210
{
1211
return;
1212
}
1213
currentFileFormat = chooser.getSelectedFormat();
1214
while (currentFileFormat == null)
1215
{
1216
// if the autodetect format from extension failed..
1217
JvOptionPane.showInternalMessageDialog(Desktop.desktop,
1218
MessageManager
1219
.getString("label.select_file_format_before_saving"),
1220
MessageManager.getString("label.file_format_not_specified"),
1221
JvOptionPane.WARNING_MESSAGE);
1222
value = chooser.showSaveDialog(this);
1223
if (value != JalviewFileChooser.APPROVE_OPTION)
1224
{
1225
return;
1226
}
1227
currentFileFormat = chooser.getSelectedFormat();
1228
}
1229
1230
fileName = chooser.getSelectedFile().getPath();
1231
1232
Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
1233
Cache.setProperty("LAST_DIRECTORY", fileName);
1234
saveAlignment(fileName, currentFileFormat);
1235
}
1236
1237
boolean lastSaveSuccessful = false;
1238
1239
FileFormatI lastFormatSaved;
1240
1241
String lastFilenameSaved;
1242
1243
// globalLastFormatSaved across alignment windows (only for alignments with no
1244
// previous format)
1245
private static FileFormatI globalLastFormatSaved = null;
1246
1247
public static void setLastAlignmentSavedFormat(FileFormatI f)
1248
{
1249
globalLastFormatSaved = f;
1250
}
1251
1252
public static FileFormatI getLastAlignmentSavedFormat()
1253
{
1254
return globalLastFormatSaved;
1255
}
1256
1257
/**
1258
* Raise a dialog or status message for the last call to saveAlignment.
1259
*
1260
* @return true if last call to saveAlignment(file, format) was successful.
1261
*/
1262
public boolean isSaveAlignmentSuccessful()
1263
{
1264
1265
if (!lastSaveSuccessful)
1266
{
1267
if (!Platform.isHeadless())
1268
{
1269
JvOptionPane.showInternalMessageDialog(this, MessageManager
1270
.formatMessage("label.couldnt_save_file", new Object[]
1271
{ lastFilenameSaved }),
1272
MessageManager.getString("label.error_saving_file"),
1273
JvOptionPane.WARNING_MESSAGE);
1274
}
1275
else
1276
{
1277
Console.error(MessageManager
1278
.formatMessage("label.couldnt_save_file", new Object[]
1279
{ lastFilenameSaved }));
1280
}
1281
}
1282
else
1283
{
1284
1285
setStatus(MessageManager.formatMessage(
1286
"label.successfully_saved_to_file_in_format", new Object[]
1287
{ lastFilenameSaved, lastFormatSaved }));
1288
1289
}
1290
return lastSaveSuccessful;
1291
}
1292
1293
/**
1294
* Saves the alignment to the specified file path, in the specified format,
1295
* which may be an alignment format, or Jalview project format. If the
1296
* alignment has hidden regions, or the format is one capable of including
1297
* non-sequence data (features, annotations, groups), then the user may be
1298
* prompted to specify what to include in the output.
1299
*
1300
* @param file
1301
* @param format
1302
*/
1303
public void saveAlignment(String file, FileFormatI format)
1304
{
1305
saveAlignment(file, format, false, false);
1306
}
1307
1308
public void saveAlignment(String file, FileFormatI format, boolean stdout,
1309
boolean forceBackup)
1310
{
1311
lastSaveSuccessful = true;
1312
if (!stdout)
1313
{
1314
lastFilenameSaved = file;
1315
}
1316
lastFormatSaved = format;
1317
globalLastFormatSaved = format;
1318
1319
if (FileFormat.Jalview.equals(format))
1320
{
1321
String shortName = title;
1322
if (shortName.indexOf(File.separatorChar) > -1)
1323
{
1324
shortName = shortName
1325
.substring(shortName.lastIndexOf(File.separatorChar) + 1);
1326
}
1327
// TODO deal with stdout=true
1328
lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
1329
shortName);
1330
1331
Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1332
if (lastSaveSuccessful)
1333
{
1334
this.getViewport().setSavedUpToDate(true);
1335
}
1336
1337
statusBar.setText(MessageManager.formatMessage(
1338
"label.successfully_saved_to_file_in_format", new Object[]
1339
{ file, format }));
1340
1341
return;
1342
}
1343
1344
AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1345
Runnable cancelAction = () -> {
1346
lastSaveSuccessful = false;
1347
};
1348
Runnable outputAction = () -> {
1349
// todo defer this to inside formatSequences (or later)
1350
AlignmentExportData exportData = viewport.getAlignExportData(options);
1351
String output = new FormatAdapter(alignPanel, options)
1352
.formatSequences(format, exportData.getAlignment(),
1353
exportData.getOmitHidden(),
1354
exportData.getStartEndPostions(),
1355
viewport.getAlignment().getHiddenColumns());
1356
if (output == null)
1357
{
1358
lastSaveSuccessful = false;
1359
}
1360
else
1361
{
1362
// create backupfiles object and get new temp filename destination
1363
boolean doBackup = forceBackup
1364
|| (BackupFiles.getEnabled() && !stdout);
1365
BackupFiles backupfiles = null;
1366
if (doBackup)
1367
{
1368
Console.trace("ALIGNFRAME making backupfiles object for " + file);
1369
backupfiles = new BackupFiles(file);
1370
}
1371
try
1372
{
1373
String tempFilePath = doBackup ? backupfiles.getTempFilePath()
1374
: file;
1375
Console.trace("ALIGNFRAME setting PrintWriter");
1376
PrintWriter out = stdout
1377
? new PrintWriter(new OutputStreamWriter(System.out))
1378
: new PrintWriter(new FileWriter(tempFilePath));
1379
1380
if (backupfiles != null)
1381
{
1382
Console.trace("ALIGNFRAME about to write to temp file "
1383
+ backupfiles.getTempFilePath());
1384
}
1385
1386
out.print(output);
1387
out.flush();
1388
if (!stdout)
1389
{
1390
Console.trace("ALIGNFRAME about to close file");
1391
out.close();
1392
Console.trace("ALIGNFRAME closed file");
1393
}
1394
AlignFrame.this.setTitle(stdout ? "STDOUT" : file);
1395
if (stdout)
1396
{
1397
statusBar.setText(MessageManager.formatMessage(
1398
"label.successfully_printed_to_stdout_in_format",
1399
new Object[]
1400
{ format.getName() }));
1401
}
1402
else
1403
{
1404
statusBar.setText(MessageManager.formatMessage(
1405
"label.successfully_saved_to_file_in_format",
1406
new Object[]
1407
{ fileName, format.getName() }));
1408
}
1409
lastSaveSuccessful = true;
1410
} catch (IOException e)
1411
{
1412
lastSaveSuccessful = false;
1413
Console.error(
1414
"ALIGNFRAME Something happened writing the temp file");
1415
Console.error(e.getMessage());
1416
Console.debug(Cache.getStackTraceString(e));
1417
} catch (Exception ex)
1418
{
1419
lastSaveSuccessful = false;
1420
Console.error(
1421
"ALIGNFRAME Something unexpected happened writing the temp file");
1422
Console.error(ex.getMessage());
1423
Console.debug(Cache.getStackTraceString(ex));
1424
}
1425
1426
if (doBackup)
1427
{
1428
backupfiles.setWriteSuccess(lastSaveSuccessful);
1429
Console.debug("ALIGNFRAME writing temp file was "
1430
+ (lastSaveSuccessful ? "" : "NOT ") + "successful");
1431
// do the backup file roll and rename the temp file to actual file
1432
Console.trace("ALIGNFRAME about to rollBackupsAndRenameTempFile");
1433
lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile();
1434
Console.debug("ALIGNFRAME performed rollBackupsAndRenameTempFile "
1435
+ (lastSaveSuccessful ? "" : "un") + "successfully");
1436
}
1437
1438
Console.debug("lastSaveSuccessful=" + lastSaveSuccessful);
1439
if (lastSaveSuccessful)
1440
{
1441
AlignFrame.this.getViewport().setSavedUpToDate(true);
1442
}
1443
}
1444
};
1445
1446
/*
1447
* show dialog with export options if applicable; else just do it
1448
*/
1449
if (AlignExportOptions.isNeeded(viewport, format))
1450
{
1451
AlignExportOptions choices = new AlignExportOptions(
1452
alignPanel.getAlignViewport(), format, options);
1453
choices.setResponseAction(0, outputAction);
1454
choices.setResponseAction(1, cancelAction);
1455
choices.showDialog();
1456
}
1457
else
1458
{
1459
try
1460
{
1461
outputAction.run();
1462
} catch (Exception e)
1463
{
1464
// TODO Auto-generated catch block
1465
e.printStackTrace();
1466
}
1467
}
1468
}
1469
1470
/**
1471
* Outputs the alignment to textbox in the requested format, if necessary
1472
* first prompting the user for whether to include hidden regions or
1473
* non-sequence data
1474
*
1475
* @param fileFormatName
1476
*/
1477
@Override
1478
protected void outputText_actionPerformed(String fileFormatName)
1479
{
1480
FileFormatI fileFormat = FileFormats.getInstance()
1481
.forName(fileFormatName);
1482
AlignExportSettingsI options = new AlignExportSettingsAdapter(false);
1483
Runnable outputAction = () -> {
1484
// todo defer this to inside formatSequences (or later)
1485
AlignmentExportData exportData = viewport.getAlignExportData(options);
1486
CutAndPasteTransfer cap = new CutAndPasteTransfer();
1487
cap.setForInput(null);
1488
try
1489
{
1490
FileFormatI format = fileFormat;
1491
cap.setText(new FormatAdapter(alignPanel, options).formatSequences(
1492
format, exportData.getAlignment(),
1493
exportData.getOmitHidden(),
1494
exportData.getStartEndPostions(),
1495
viewport.getAlignment().getHiddenColumns()));
1496
Desktop.addInternalFrame(cap, MessageManager.formatMessage(
1497
"label.alignment_output_command", new Object[]
1498
{ fileFormat.getName() }), 600, 500);
1499
} catch (OutOfMemoryError oom)
1500
{
1501
new OOMWarning("Outputting alignment as " + fileFormat.getName(),
1502
oom);
1503
cap.dispose();
1504
}
1505
};
1506
1507
/*
1508
* show dialog with export options if applicable; else just do it
1509
*/
1510
if (AlignExportOptions.isNeeded(viewport, fileFormat))
1511
{
1512
AlignExportOptions choices = new AlignExportOptions(
1513
alignPanel.getAlignViewport(), fileFormat, options);
1514
choices.setResponseAction(0, outputAction);
1515
choices.showDialog();
1516
}
1517
else
1518
{
1519
try
1520
{
1521
outputAction.run();
1522
} catch (Exception e)
1523
{
1524
e.printStackTrace();
1525
}
1526
}
1527
}
1528
1529
/**
1530
* DOCUMENT ME!
1531
*
1532
* @param e
1533
* DOCUMENT ME!
1534
*/
1535
@Override
1536
protected void htmlMenuItem_actionPerformed(ActionEvent e)
1537
{
1538
HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
1539
try
1540
{
1541
htmlSVG.exportHTML(null);
1542
} catch (ImageOutputException x)
1543
{
1544
// report problem to console and raise dialog
1545
}
1546
}
1547
1548
@Override
1549
public void bioJSMenuItem_actionPerformed(ActionEvent e)
1550
{
1551
BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
1552
try
1553
{
1554
bjs.exportHTML(null);
1555
} catch (ImageOutputException x)
1556
{
1557
// report problem to console and raise dialog
1558
}
1559
}
1560
1561
public void createImageMap(File file, String image)
1562
{
1563
try
1564
{
1565
alignPanel.makePNGImageMap(file, image);
1566
} catch (ImageOutputException x)
1567
{
1568
// report problem to console and raise dialog
1569
}
1570
}
1571
1572
@Override
1573
public void createPNG_actionPerformed(ActionEvent e)
1574
{
1575
try
1576
{
1577
createPNG(null);
1578
} catch (ImageOutputException ioex)
1579
{
1580
// raise dialog, and report via console
1581
}
1582
}
1583
1584
@Override
1585
public void createEPS_actionPerformed(ActionEvent e)
1586
{
1587
try
1588
{
1589
createEPS(null);
1590
} catch (ImageOutputException ioex)
1591
{
1592
// raise dialog, and report via console
1593
}
1594
1595
}
1596
1597
@Override
1598
public void createSVG_actionPerformed(ActionEvent e)
1599
{
1600
try
1601
{
1602
createSVG(null);
1603
} catch (ImageOutputException ioex)
1604
{
1605
// raise dialog, and report via console
1606
}
1607
1608
}
1609
1610
/**
1611
* Creates a PNG image of the alignment and writes it to the given file. If
1612
* the file is null, the user is prompted to choose a file.
1613
*
1614
* @param f
1615
*/
1616
public void createPNG(File f) throws ImageOutputException
1617
{
1618
createPNG(f, null, BitmapImageSizing.defaultBitmapImageSizing());
1619
}
1620
1621
public void createPNG(File f, String renderer, BitmapImageSizing userBis)
1622
throws ImageOutputException
1623
{
1624
alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
1625
}
1626
1627
/**
1628
* Creates an EPS image of the alignment and writes it to the given file. If
1629
* the file is null, the user is prompted to choose a file.
1630
*
1631
* @param f
1632
*/
1633
public void createEPS(File f) throws ImageOutputException
1634
{
1635
createEPS(f, null);
1636
}
1637
1638
public void createEPS(File f, String renderer) throws ImageOutputException
1639
{
1640
alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
1641
}
1642
1643
/**
1644
* Creates an SVG image of the alignment and writes it to the given file. If
1645
* the file is null, the user is prompted to choose a file.
1646
*
1647
* @param f
1648
*/
1649
public void createSVG(File f) throws ImageOutputException
1650
{
1651
createSVG(f, null);
1652
}
1653
1654
public void createSVG(File f, String renderer) throws ImageOutputException
1655
{
1656
alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
1657
}
1658
1659
@Override
1660
public void pageSetup_actionPerformed(ActionEvent e)
1661
{
1662
PrinterJob printJob = PrinterJob.getPrinterJob();
1663
PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
1664
}
1665
1666
/**
1667
* DOCUMENT ME!
1668
*
1669
* @param e
1670
* DOCUMENT ME!
1671
*/
1672
@Override
1673
public void printMenuItem_actionPerformed(ActionEvent e)
1674
{
1675
// Putting in a thread avoids Swing painting problems
1676
PrintThread thread = new PrintThread(alignPanel);
1677
thread.start();
1678
}
1679
1680
@Override
1681
public void exportFeatures_actionPerformed(ActionEvent e)
1682
{
1683
new AnnotationExporter(alignPanel).exportFeatures();
1684
}
1685
1686
@Override
1687
public void exportAnnotations_actionPerformed(ActionEvent e)
1688
{
1689
new AnnotationExporter(alignPanel).exportAnnotations();
1690
}
1691
1692
@Override
1693
public void associatedData_actionPerformed(ActionEvent e)
1694
{
1695
final JalviewFileChooser chooser = new JalviewFileChooser(
1696
Cache.getProperty("LAST_DIRECTORY"));
1697
chooser.setFileView(new JalviewFileView());
1698
String tooltip = MessageManager
1699
.getString("label.load_jalview_annotations");
1700
chooser.setDialogTitle(tooltip);
1701
chooser.setToolTipText(tooltip);
1702
chooser.setResponseHandler(0, () -> {
1703
String choice = chooser.getSelectedFile().getPath();
1704
Cache.setProperty("LAST_DIRECTORY", choice);
1705
loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
1706
});
1707
1708
chooser.showOpenDialog(this);
1709
}
1710
1711
/**
1712
* Close the current view or all views in the alignment frame. If the frame
1713
* only contains one view then the alignment will be removed from memory.
1714
*
1715
* @param closeAllTabs
1716
*/
1717
@Override
1718
public void closeMenuItem_actionPerformed(boolean closeAllTabs)
1719
{
1720
if (alignPanels != null && alignPanels.size() < 2)
1721
{
1722
closeAllTabs = true;
1723
}
1724
1725
Desktop.closeModal(this);
1726
1727
try
1728
{
1729
if (alignPanels != null)
1730
{
1731
if (closeAllTabs)
1732
{
1733
if (this.isClosed())
1734
{
1735
// really close all the windows - otherwise wait till
1736
// setClosed(true) is called
1737
for (int i = 0; i < alignPanels.size(); i++)
1738
{
1739
AlignmentPanel ap = alignPanels.get(i);
1740
ap.closePanel();
1741
}
1742
}
1743
}
1744
else
1745
{
1746
closeView(alignPanel);
1747
}
1748
}
1749
if (closeAllTabs)
1750
{
1751
if (featureSettings != null && featureSettings.isOpen())
1752
{
1753
featureSettings.close();
1754
featureSettings = null;
1755
}
1756
1757
/*
1758
* this will raise an INTERNAL_FRAME_CLOSED event and this method will be called
1759
* recursively, with the frame now in 'closed' state
1760
*/
1761
this.setClosed(true);
1762
}
1763
} catch (Exception ex)
1764
{
1765
ex.printStackTrace();
1766
}
1767
}
1768
1769
/**
1770
* Close the specified panel and close up tabs appropriately.
1771
*
1772
* @param panelToClose
1773
*/
1774
public void closeView(AlignmentPanel panelToClose)
1775
{
1776
int index = tabbedPane.getSelectedIndex();
1777
int closedindex = tabbedPane.indexOfComponent(panelToClose);
1778
alignPanels.remove(panelToClose);
1779
panelToClose.closePanel();
1780
panelToClose = null;
1781
1782
tabbedPane.removeTabAt(closedindex);
1783
tabbedPane.validate();
1784
1785
if (index > closedindex || index == tabbedPane.getTabCount())
1786
{
1787
// modify currently selected tab index if necessary.
1788
index--;
1789
}
1790
1791
this.tabSelectionChanged(index);
1792
}
1793
1794
/**
1795
* DOCUMENT ME!
1796
*/
1797
void updateEditMenuBar()
1798
{
1799
1800
if (viewport.getHistoryList().size() > 0)
1801
{
1802
undoMenuItem.setEnabled(true);
1803
CommandI command = viewport.getHistoryList().peek();
1804
undoMenuItem.setText(MessageManager
1805
.formatMessage("label.undo_command", new Object[]
1806
{ command.getDescription() }));
1807
}
1808
else
1809
{
1810
undoMenuItem.setEnabled(false);
1811
undoMenuItem.setText(MessageManager.getString("action.undo"));
1812
}
1813
1814
if (viewport.getRedoList().size() > 0)
1815
{
1816
redoMenuItem.setEnabled(true);
1817
1818
CommandI command = viewport.getRedoList().peek();
1819
redoMenuItem.setText(MessageManager
1820
.formatMessage("label.redo_command", new Object[]
1821
{ command.getDescription() }));
1822
}
1823
else
1824
{
1825
redoMenuItem.setEnabled(false);
1826
redoMenuItem.setText(MessageManager.getString("action.redo"));
1827
}
1828
}
1829
1830
@Override
1831
public void addHistoryItem(CommandI command)
1832
{
1833
if (command.getSize() > 0)
1834
{
1835
viewport.addToHistoryList(command);
1836
viewport.clearRedoList();
1837
updateEditMenuBar();
1838
viewport.updateHiddenColumns();
1839
// viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
1840
// && viewport.getColumnSelection().getHiddenColumns() != null &&
1841
// viewport.getColumnSelection()
1842
// .getHiddenColumns().size() > 0);
1843
}
1844
}
1845
1846
/**
1847
*
1848
* @return alignment objects for all views
1849
*/
1850
public AlignmentI[] getViewAlignments()
1851
{
1852
if (alignPanels != null)
1853
{
1854
AlignmentI[] als = new AlignmentI[alignPanels.size()];
1855
int i = 0;
1856
for (AlignmentPanel ap : alignPanels)
1857
{
1858
als[i++] = ap.av.getAlignment();
1859
}
1860
return als;
1861
}
1862
if (viewport != null)
1863
{
1864
return new AlignmentI[] { viewport.getAlignment() };
1865
}
1866
return null;
1867
}
1868
1869
/**
1870
* DOCUMENT ME!
1871
*
1872
* @param e
1873
* DOCUMENT ME!
1874
*/
1875
@Override
1876
protected void undoMenuItem_actionPerformed(ActionEvent e)
1877
{
1878
if (viewport.getHistoryList().isEmpty())
1879
{
1880
return;
1881
}
1882
CommandI command = viewport.getHistoryList().pop();
1883
viewport.addToRedoList(command);
1884
command.undoCommand(getViewAlignments());
1885
1886
AlignmentViewport originalSource = getOriginatingSource(command);
1887
updateEditMenuBar();
1888
1889
if (originalSource != null)
1890
{
1891
if (originalSource != viewport)
1892
{
1893
Console.warn(
1894
"Implementation worry: mismatch of viewport origin for undo");
1895
}
1896
originalSource.updateHiddenColumns();
1897
// originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1898
// null
1899
// && viewport.getColumnSelection().getHiddenColumns() != null &&
1900
// viewport.getColumnSelection()
1901
// .getHiddenColumns().size() > 0);
1902
originalSource.firePropertyChange("alignment", null,
1903
originalSource.getAlignment().getSequences());
1904
}
1905
}
1906
1907
/**
1908
* DOCUMENT ME!
1909
*
1910
* @param e
1911
* DOCUMENT ME!
1912
*/
1913
@Override
1914
protected void redoMenuItem_actionPerformed(ActionEvent e)
1915
{
1916
if (viewport.getRedoList().size() < 1)
1917
{
1918
return;
1919
}
1920
1921
CommandI command = viewport.getRedoList().pop();
1922
viewport.addToHistoryList(command);
1923
command.doCommand(getViewAlignments());
1924
1925
AlignmentViewport originalSource = getOriginatingSource(command);
1926
updateEditMenuBar();
1927
1928
if (originalSource != null)
1929
{
1930
1931
if (originalSource != viewport)
1932
{
1933
Console.warn(
1934
"Implementation worry: mismatch of viewport origin for redo");
1935
}
1936
originalSource.updateHiddenColumns();
1937
// originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
1938
// null
1939
// && viewport.getColumnSelection().getHiddenColumns() != null &&
1940
// viewport.getColumnSelection()
1941
// .getHiddenColumns().size() > 0);
1942
originalSource.firePropertyChange("alignment", null,
1943
originalSource.getAlignment().getSequences());
1944
}
1945
}
1946
1947
AlignmentViewport getOriginatingSource(CommandI command)
1948
{
1949
AlignmentViewport originalSource = null;
1950
// For sequence removal and addition, we need to fire
1951
// the property change event FROM the viewport where the
1952
// original alignment was altered
1953
AlignmentI al = null;
1954
if (command instanceof EditCommand)
1955
{
1956
EditCommand editCommand = (EditCommand) command;
1957
al = editCommand.getAlignment();
1958
List comps = PaintRefresher.components
1959
.get(viewport.getSequenceSetId());
1960
1961
for (Component comp : comps)
1962
{
1963
if (comp instanceof AlignmentPanel)
1964
{
1965
if (al == ((AlignmentPanel) comp).av.getAlignment())
1966
{
1967
originalSource = ((AlignmentPanel) comp).av;
1968
break;
1969
}
1970
}
1971
}
1972
}
1973
1974
if (originalSource == null)
1975
{
1976
// The original view is closed, we must validate
1977
// the current view against the closed view first
1978
if (al != null)
1979
{
1980
PaintRefresher.validateSequences(al, viewport.getAlignment());
1981
}
1982
1983
originalSource = viewport;
1984
}
1985
1986
return originalSource;
1987
}
1988
1989
/**
1990
* Calls AlignmentI.moveSelectedSequencesByOne with current sequence selection
1991
* or the sequence under cursor in keyboard mode
1992
*
1993
* @param up
1994
* or down (if !up)
1995
*/
1996
public void moveSelectedSequences(boolean up)
1997
{
1998
SequenceGroup sg = viewport.getSelectionGroup();
1999
2000
if (sg == null)
2001
{
2002
if (viewport.cursorMode)
2003
{
2004
sg = new SequenceGroup();
2005
sg.addSequence(viewport.getAlignment().getSequenceAt(
2006
alignPanel.getSeqPanel().seqCanvas.cursorY), false);
2007
}
2008
else
2009
{
2010
return;
2011
}
2012
}
2013
2014
if (sg.getSize() < 1)
2015
{
2016
return;
2017
}
2018
2019
// TODO: JAL-3733 - add an event to the undo buffer for this !
2020
2021
viewport.getAlignment().moveSelectedSequencesByOne(sg,
2022
viewport.getHiddenRepSequences(), up);
2023
alignPanel.paintAlignment(true, false);
2024
}
2025
2026
synchronized void slideSequences(boolean right, int size)
2027
{
2028
List sg = new ArrayList<>();
2029
if (viewport.cursorMode)
2030
{
2031
sg.add(viewport.getAlignment()
2032
.getSequenceAt(alignPanel.getSeqPanel().seqCanvas.cursorY));
2033
}
2034
else if (viewport.getSelectionGroup() != null
2035
&& viewport.getSelectionGroup().getSize() != viewport
2036
.getAlignment().getHeight())
2037
{
2038
sg = viewport.getSelectionGroup()
2039
.getSequences(viewport.getHiddenRepSequences());
2040
}
2041
2042
if (sg.size() < 1)
2043
{
2044
return;
2045
}
2046
2047
List invertGroup = new ArrayList<>();
2048
2049
for (SequenceI seq : viewport.getAlignment().getSequences())
2050
{
2051
if (!sg.contains(seq))
2052
{
2053
invertGroup.add(seq);
2054
}
2055
}
2056
2057
SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
2058
2059
SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
2060
for (int i = 0; i < invertGroup.size(); i++)
2061
{
2062
seqs2[i] = invertGroup.get(i);
2063
}
2064
2065
SlideSequencesCommand ssc;
2066
if (right)
2067
{
2068
ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1, size,
2069
viewport.getGapCharacter());
2070
}
2071
else
2072
{
2073
ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2, size,
2074
viewport.getGapCharacter());
2075
}
2076
2077
int groupAdjustment = 0;
2078
if (ssc.getGapsInsertedBegin() && right)
2079
{
2080
if (viewport.cursorMode)
2081
{
2082
alignPanel.getSeqPanel().moveCursor(size, 0);
2083
}
2084
else
2085
{
2086
groupAdjustment = size;
2087
}
2088
}
2089
else if (!ssc.getGapsInsertedBegin() && !right)
2090
{
2091
if (viewport.cursorMode)
2092
{
2093
alignPanel.getSeqPanel().moveCursor(-size, 0);
2094
}
2095
else
2096
{
2097
groupAdjustment = -size;
2098
}
2099
}
2100
2101
if (groupAdjustment != 0)
2102
{
2103
viewport.getSelectionGroup().setStartRes(
2104
viewport.getSelectionGroup().getStartRes() + groupAdjustment);
2105
viewport.getSelectionGroup().setEndRes(
2106
viewport.getSelectionGroup().getEndRes() + groupAdjustment);
2107
}
2108
2109
/*
2110
* just extend the last slide command if compatible; but not if in SplitFrame
2111
* mode (to ensure all edits are broadcast - JAL-1802)
2112
*/
2113
boolean appendHistoryItem = false;
2114
Deque historyList = viewport.getHistoryList();
2115
boolean inSplitFrame = getSplitViewContainer() != null;
2116
if (!inSplitFrame && historyList != null && historyList.size() > 0
2117
&& historyList.peek() instanceof SlideSequencesCommand)
2118
{
2119
appendHistoryItem = ssc.appendSlideCommand(
2120
(SlideSequencesCommand) historyList.peek());
2121
}
2122
2123
if (!appendHistoryItem)
2124
{
2125
addHistoryItem(ssc);
2126
}
2127
2128
repaint();
2129
}
2130
2131
/**
2132
* DOCUMENT ME!
2133
*
2134
* @param e
2135
* DOCUMENT ME!
2136
*/
2137
@Override
2138
protected void copy_actionPerformed()
2139
{
2140
if (viewport.getSelectionGroup() == null)
2141
{
2142
return;
2143
}
2144
// TODO: preserve the ordering of displayed alignment annotation in any
2145
// internal paste (particularly sequence associated annotation)
2146
SequenceI[] seqs = viewport.getSelectionAsNewSequence();
2147
String[] omitHidden = null;
2148
2149
if (viewport.hasHiddenColumns())
2150
{
2151
omitHidden = viewport.getViewAsString(true);
2152
}
2153
2154
String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
2155
seqs, omitHidden, null);
2156
2157
StringSelection ss = new StringSelection(output);
2158
2159
try
2160
{
2161
jalview.gui.Desktop.internalCopy = true;
2162
// Its really worth setting the clipboard contents
2163
// to empty before setting the large StringSelection!!
2164
Toolkit.getDefaultToolkit().getSystemClipboard()
2165
.setContents(new StringSelection(""), null);
2166
2167
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss,
2168
Desktop.instance);
2169
} catch (OutOfMemoryError er)
2170
{
2171
new OOMWarning("copying region", er);
2172
return;
2173
}
2174
2175
HiddenColumns hiddenColumns = null;
2176
if (viewport.hasHiddenColumns())
2177
{
2178
int hiddenOffset = viewport.getSelectionGroup().getStartRes();
2179
int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
2180
2181
// create new HiddenColumns object with copy of hidden regions
2182
// between startRes and endRes, offset by startRes
2183
hiddenColumns = new HiddenColumns(
2184
viewport.getAlignment().getHiddenColumns(), hiddenOffset,
2185
hiddenCutoff, hiddenOffset);
2186
}
2187
2188
Desktop.jalviewClipboard = new Object[] { seqs,
2189
viewport.getAlignment().getDataset(), hiddenColumns };
2190
setStatus(MessageManager.formatMessage(
2191
"label.copied_sequences_to_clipboard", new Object[]
2192
{ Integer.valueOf(seqs.length).toString() }));
2193
}
2194
2195
/**
2196
* DOCUMENT ME!
2197
*
2198
* @param e
2199
* DOCUMENT ME!
2200
*/
2201
@Override
2202
protected void pasteNew_actionPerformed(ActionEvent e)
2203
{
2204
paste(true);
2205
}
2206
2207
/**
2208
* DOCUMENT ME!
2209
*
2210
* @param e
2211
* DOCUMENT ME!
2212
*/
2213
@Override
2214
protected void pasteThis_actionPerformed(ActionEvent e)
2215
{
2216
paste(false);
2217
}
2218
2219
/**
2220
* Paste contents of Jalview clipboard
2221
*
2222
* @param newAlignment
2223
* true to paste to a new alignment, otherwise add to this.
2224
*/
2225
void paste(boolean newAlignment)
2226
{
2227
boolean externalPaste = true;
2228
try
2229
{
2230
Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
2231
Transferable contents = c.getContents(this);
2232
2233
if (contents == null)
2234
{
2235
return;
2236
}
2237
2238
String str;
2239
FileFormatI format;
2240
try
2241
{
2242
str = (String) contents.getTransferData(DataFlavor.stringFlavor);
2243
if (str.length() < 1)
2244
{
2245
return;
2246
}
2247
2248
format = new IdentifyFile().identify(str, DataSourceType.PASTE);
2249
2250
} catch (OutOfMemoryError er)
2251
{
2252
new OOMWarning("Out of memory pasting sequences!!", er);
2253
return;
2254
}
2255
2256
SequenceI[] sequences;
2257
boolean annotationAdded = false;
2258
AlignmentI alignment = null;
2259
2260
if (Desktop.jalviewClipboard != null)
2261
{
2262
// The clipboard was filled from within Jalview, we must use the
2263
// sequences
2264
// And dataset from the copied alignment
2265
SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
2266
// be doubly sure that we create *new* sequence objects.
2267
sequences = new SequenceI[newseq.length];
2268
for (int i = 0; i < newseq.length; i++)
2269
{
2270
sequences[i] = new Sequence(newseq[i]);
2271
}
2272
alignment = new Alignment(sequences);
2273
externalPaste = false;
2274
}
2275
else
2276
{
2277
// parse the clipboard as an alignment.
2278
alignment = new FormatAdapter().readFile(str, DataSourceType.PASTE,
2279
format);
2280
sequences = alignment.getSequencesArray();
2281
}
2282
2283
int alwidth = 0;
2284
ArrayList newGraphGroups = new ArrayList<>();
2285
int fgroup = -1;
2286
2287
if (newAlignment)
2288
{
2289
2290
if (Desktop.jalviewClipboard != null)
2291
{
2292
// dataset is inherited
2293
alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
2294
}
2295
else
2296
{
2297
// new dataset is constructed
2298
alignment.setDataset(null);
2299
}
2300
alwidth = alignment.getWidth() + 1;
2301
}
2302
else
2303
{
2304
AlignmentI pastedal = alignment; // preserve pasted alignment object
2305
// Add pasted sequences and dataset into existing alignment.
2306
alignment = viewport.getAlignment();
2307
alwidth = alignment.getWidth() + 1;
2308
// decide if we need to import sequences from an existing dataset
2309
boolean importDs = Desktop.jalviewClipboard != null
2310
&& Desktop.jalviewClipboard[1] != alignment.getDataset();
2311
// importDs==true instructs us to copy over new dataset sequences from
2312
// an existing alignment
2313
Vector newDs = (importDs) ? new Vector<>() : null; // used to
2314
// create
2315
// minimum dataset set
2316
2317
for (int i = 0; i < sequences.length; i++)
2318
{
2319
if (importDs)
2320
{
2321
newDs.addElement(null);
2322
}
2323
SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
2324
// paste
2325
if (importDs && ds != null)
2326
{
2327
if (!newDs.contains(ds))
2328
{
2329
newDs.setElementAt(ds, i);
2330
ds = new Sequence(ds);
2331
// update with new dataset sequence
2332
sequences[i].setDatasetSequence(ds);
2333
}
2334
else
2335
{
2336
ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
2337
}
2338
}
2339
else
2340
{
2341
// copy and derive new dataset sequence
2342
sequences[i] = sequences[i].deriveSequence();
2343
alignment.getDataset()
2344
.addSequence(sequences[i].getDatasetSequence());
2345
// TODO: avoid creation of duplicate dataset sequences with a
2346
// 'contains' method using SequenceI.equals()/SequenceI.contains()
2347
}
2348
alignment.addSequence(sequences[i]); // merges dataset
2349
}
2350
if (newDs != null)
2351
{
2352
newDs.clear(); // tidy up
2353
}
2354
if (alignment.getAlignmentAnnotation() != null)
2355
{
2356
for (AlignmentAnnotation alan : alignment
2357
.getAlignmentAnnotation())
2358
{
2359
if (alan.graphGroup > fgroup)
2360
{
2361
fgroup = alan.graphGroup;
2362
}
2363
}
2364
}
2365
if (pastedal.getAlignmentAnnotation() != null)
2366
{
2367
// Add any annotation attached to alignment.
2368
AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
2369
for (int i = 0; i < alann.length; i++)
2370
{
2371
annotationAdded = true;
2372
if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
2373
{
2374
AlignmentAnnotation newann = new AlignmentAnnotation(
2375
alann[i]);
2376
if (newann.graphGroup > -1)
2377
{
2378
if (newGraphGroups.size() <= newann.graphGroup
2379
|| newGraphGroups.get(newann.graphGroup) == null)
2380
{
2381
for (int q = newGraphGroups
2382
.size(); q <= newann.graphGroup; q++)
2383
{
2384
newGraphGroups.add(q, null);
2385
}
2386
newGraphGroups.set(newann.graphGroup,
2387
Integer.valueOf(++fgroup));
2388
}
2389
newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2390
.intValue();
2391
}
2392
2393
newann.padAnnotation(alwidth);
2394
alignment.addAnnotation(newann);
2395
}
2396
}
2397
}
2398
}
2399
if (!newAlignment)
2400
{
2401
// /////
2402
// ADD HISTORY ITEM
2403
//
2404
addHistoryItem(new EditCommand(
2405
MessageManager.getString("label.add_sequences"),
2406
Action.PASTE, sequences, 0, alignment.getWidth(),
2407
alignment));
2408
}
2409
// Add any annotations attached to sequences
2410
for (int i = 0; i < sequences.length; i++)
2411
{
2412
if (sequences[i].getAnnotation() != null)
2413
{
2414
AlignmentAnnotation newann;
2415
for (int a = 0; a < sequences[i].getAnnotation().length; a++)
2416
{
2417
annotationAdded = true;
2418
newann = sequences[i].getAnnotation()[a];
2419
newann.adjustForAlignment();
2420
newann.padAnnotation(alwidth);
2421
if (newann.graphGroup > -1)
2422
{
2423
if (newann.graphGroup > -1)
2424
{
2425
if (newGraphGroups.size() <= newann.graphGroup
2426
|| newGraphGroups.get(newann.graphGroup) == null)
2427
{
2428
for (int q = newGraphGroups
2429
.size(); q <= newann.graphGroup; q++)
2430
{
2431
newGraphGroups.add(q, null);
2432
}
2433
newGraphGroups.set(newann.graphGroup,
2434
Integer.valueOf(++fgroup));
2435
}
2436
newann.graphGroup = newGraphGroups.get(newann.graphGroup)
2437
.intValue();
2438
}
2439
}
2440
// annotation was duplicated earlier
2441
alignment.addAnnotation(sequences[i].getAnnotation()[a]);
2442
// take care of contact matrix too
2443
ContactMatrixI cm = sequences[i]
2444
.getContactMatrixFor(sequences[i].getAnnotation()[a]);
2445
if (cm != null)
2446
{
2447
alignment.addContactListFor(sequences[i].getAnnotation()[a],
2448
cm);
2449
}
2450
2451
alignment.setAnnotationIndex(sequences[i].getAnnotation()[a],
2452
a);
2453
}
2454
}
2455
}
2456
if (!newAlignment)
2457
{
2458
2459
// propagate alignment changed.
2460
viewport.getRanges().setEndSeq(alignment.getHeight() - 1);
2461
if (annotationAdded)
2462
{
2463
// Duplicate sequence annotation in all views.
2464
AlignmentI[] alview = this.getViewAlignments();
2465
for (int i = 0; i < sequences.length; i++)
2466
{
2467
AlignmentAnnotation sann[] = sequences[i].getAnnotation();
2468
if (sann == null)
2469
{
2470
continue;
2471
}
2472
for (int avnum = 0; avnum < alview.length; avnum++)
2473
{
2474
if (alview[avnum] != alignment)
2475
{
2476
// duplicate in a view other than the one with input focus
2477
int avwidth = alview[avnum].getWidth() + 1;
2478
// this relies on sann being preserved after we
2479
// modify the sequence's annotation array for each duplication
2480
for (int a = 0; a < sann.length; a++)
2481
{
2482
AlignmentAnnotation newann = new AlignmentAnnotation(
2483
sann[a]);
2484
sequences[i].addAlignmentAnnotation(newann);
2485
newann.padAnnotation(avwidth);
2486
alview[avnum].addAnnotation(newann); // annotation was
2487
// duplicated earlier
2488
// TODO JAL-1145 graphGroups are not updated for sequence
2489
// annotation added to several views. This may cause
2490
// strangeness
2491
alview[avnum].setAnnotationIndex(newann, a);
2492
}
2493
}
2494
}
2495
}
2496
buildSortByAnnotationScoresMenu();
2497
}
2498
viewport.firePropertyChange("alignment", null,
2499
alignment.getSequences());
2500
if (alignPanels != null)
2501
{
2502
for (AlignmentPanel ap : alignPanels)
2503
{
2504
ap.validateAnnotationDimensions(false);
2505
}
2506
}
2507
else
2508
{
2509
alignPanel.validateAnnotationDimensions(false);
2510
}
2511
2512
}
2513
else
2514
{
2515
AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2516
DEFAULT_HEIGHT);
2517
String newtitle = new String("Copied sequences");
2518
2519
if (Desktop.jalviewClipboard != null
2520
&& Desktop.jalviewClipboard[2] != null)
2521
{
2522
HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2523
af.viewport.setHiddenColumns(hc);
2524
}
2525
2526
// >>>This is a fix for the moment, until a better solution is
2527
// found!!<<<
2528
af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2529
.transferSettings(alignPanel.getSeqPanel().seqCanvas
2530
.getFeatureRenderer());
2531
2532
// TODO: maintain provenance of an alignment, rather than just make the
2533
// title a concatenation of operations.
2534
if (!externalPaste)
2535
{
2536
if (title.startsWith("Copied sequences"))
2537
{
2538
newtitle = title;
2539
}
2540
else
2541
{
2542
newtitle = newtitle.concat("- from " + title);
2543
}
2544
}
2545
else
2546
{
2547
newtitle = new String("Pasted sequences");
2548
}
2549
2550
Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
2551
DEFAULT_HEIGHT);
2552
2553
}
2554
2555
} catch (Exception ex)
2556
{
2557
ex.printStackTrace();
2558
jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2559
// could be anything being pasted in here
2560
}
2561
2562
}
2563
2564
@Override
2565
protected void expand_newalign(ActionEvent e)
2566
{
2567
try
2568
{
2569
AlignmentI alignment = AlignmentUtils
2570
.expandContext(getViewport().getAlignment(), -1);
2571
AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
2572
DEFAULT_HEIGHT);
2573
String newtitle = new String("Flanking alignment");
2574
2575
if (Desktop.jalviewClipboard != null
2576
&& Desktop.jalviewClipboard[2] != null)
2577
{
2578
HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
2579
af.viewport.setHiddenColumns(hc);
2580
}
2581
2582
// >>>This is a fix for the moment, until a better solution is
2583
// found!!<<<
2584
af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
2585
.transferSettings(alignPanel.getSeqPanel().seqCanvas
2586
.getFeatureRenderer());
2587
2588
// TODO: maintain provenance of an alignment, rather than just make the
2589
// title a concatenation of operations.
2590
{
2591
if (title.startsWith("Copied sequences"))
2592
{
2593
newtitle = title;
2594
}
2595
else
2596
{
2597
newtitle = newtitle.concat("- from " + title);
2598
}
2599
}
2600
2601
Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2602
2603
} catch (Exception ex)
2604
{
2605
ex.printStackTrace();
2606
jalview.bin.Console.outPrintln("Exception whilst pasting: " + ex);
2607
// could be anything being pasted in here
2608
} catch (OutOfMemoryError oom)
2609
{
2610
new OOMWarning("Viewing flanking region of alignment", oom);
2611
}
2612
}
2613
2614
/**
2615
* Action Cut (delete and copy) the selected region
2616
*/
2617
@Override
2618
protected void cut_actionPerformed()
2619
{
2620
copy_actionPerformed();
2621
delete_actionPerformed();
2622
}
2623
2624
/**
2625
* Performs menu option to Delete the currently selected region
2626
*/
2627
@Override
2628
protected void delete_actionPerformed()
2629
{
2630
2631
SequenceGroup sg = viewport.getSelectionGroup();
2632
if (sg == null)
2633
{
2634
return;
2635
}
2636
2637
Runnable okAction = () -> {
2638
SequenceI[] cut = sg.getSequences()
2639
.toArray(new SequenceI[sg.getSize()]);
2640
2641
addHistoryItem(new EditCommand(
2642
MessageManager.getString("label.cut_sequences"), Action.CUT,
2643
cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
2644
viewport.getAlignment()));
2645
2646
viewport.setSelectionGroup(null);
2647
viewport.sendSelection();
2648
viewport.getAlignment().deleteGroup(sg);
2649
2650
viewport.firePropertyChange("alignment", null,
2651
viewport.getAlignment().getSequences());
2652
if (viewport.getAlignment().getHeight() < 1)
2653
{
2654
try
2655
{
2656
AlignFrame.this.setClosed(true);
2657
} catch (Exception ex)
2658
{
2659
}
2660
}
2661
};
2662
2663
/*
2664
* If the cut affects all sequences, prompt for confirmation
2665
*/
2666
boolean wholeHeight = sg.getSize() == viewport.getAlignment()
2667
.getHeight();
2668
boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes())
2669
+ 1) == viewport.getAlignment().getWidth()) ? true : false;
2670
if (wholeHeight && wholeWidth)
2671
{
2672
JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
2673
dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION
2674
Object[] options = new Object[] {
2675
MessageManager.getString("action.ok"),
2676
MessageManager.getString("action.cancel") };
2677
dialog.showDialog(MessageManager.getString("warn.delete_all"),
2678
MessageManager.getString("label.delete_all"),
2679
JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
2680
options, options[0]);
2681
}
2682
else
2683
{
2684
try
2685
{
2686
okAction.run();
2687
} catch (Exception e)
2688
{
2689
e.printStackTrace();
2690
}
2691
}
2692
}
2693
2694
/**
2695
* DOCUMENT ME!
2696
*
2697
* @param e
2698
* DOCUMENT ME!
2699
*/
2700
@Override
2701
protected void deleteGroups_actionPerformed(ActionEvent e)
2702
{
2703
if (avc.deleteGroups())
2704
{
2705
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
2706
alignPanel.updateAnnotation();
2707
alignPanel.paintAlignment(true, true);
2708
}
2709
}
2710
2711
/**
2712
* DOCUMENT ME!
2713
*
2714
* @param e
2715
* DOCUMENT ME!
2716
*/
2717
@Override
2718
public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2719
{
2720
SequenceGroup sg = new SequenceGroup(
2721
viewport.getAlignment().getSequences());
2722
2723
sg.setEndRes(viewport.getAlignment().getWidth() - 1);
2724
viewport.setSelectionGroup(sg);
2725
viewport.isSelectionGroupChanged(true);
2726
viewport.sendSelection();
2727
// JAL-2034 - should delegate to
2728
// alignPanel to decide if overview needs
2729
// updating.
2730
alignPanel.paintAlignment(false, false);
2731
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2732
}
2733
2734
/**
2735
* DOCUMENT ME!
2736
*
2737
* @param e
2738
* DOCUMENT ME!
2739
*/
2740
@Override
2741
public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
2742
{
2743
if (viewport.cursorMode)
2744
{
2745
alignPanel.getSeqPanel().keyboardNo1 = null;
2746
alignPanel.getSeqPanel().keyboardNo2 = null;
2747
}
2748
viewport.setSelectionGroup(null);
2749
viewport.getColumnSelection().clear();
2750
viewport.setSearchResults(null);
2751
alignPanel.getIdPanel().getIdCanvas().searchResults = null;
2752
// JAL-2034 - should delegate to
2753
// alignPanel to decide if overview needs
2754
// updating.
2755
alignPanel.paintAlignment(false, false);
2756
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2757
viewport.sendSelection();
2758
}
2759
2760
/**
2761
* DOCUMENT ME!
2762
*
2763
* @param e
2764
* DOCUMENT ME!
2765
*/
2766
@Override
2767
public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
2768
{
2769
SequenceGroup sg = viewport.getSelectionGroup();
2770
2771
if (sg == null)
2772
{
2773
selectAllSequenceMenuItem_actionPerformed(null);
2774
2775
return;
2776
}
2777
2778
for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
2779
{
2780
sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
2781
}
2782
// JAL-2034 - should delegate to
2783
// alignPanel to decide if overview needs
2784
// updating.
2785
2786
alignPanel.paintAlignment(true, false);
2787
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2788
viewport.sendSelection();
2789
}
2790
2791
@Override
2792
public void invertColSel_actionPerformed(ActionEvent e)
2793
{
2794
viewport.invertColumnSelection();
2795
alignPanel.paintAlignment(true, false);
2796
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
2797
viewport.sendSelection();
2798
}
2799
2800
/**
2801
* DOCUMENT ME!
2802
*
2803
* @param e
2804
* DOCUMENT ME!
2805
*/
2806
@Override
2807
public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
2808
{
2809
trimAlignment(true);
2810
}
2811
2812
/**
2813
* DOCUMENT ME!
2814
*
2815
* @param e
2816
* DOCUMENT ME!
2817
*/
2818
@Override
2819
public void remove2RightMenuItem_actionPerformed(ActionEvent e)
2820
{
2821
trimAlignment(false);
2822
}
2823
2824
void trimAlignment(boolean trimLeft)
2825
{
2826
ColumnSelection colSel = viewport.getColumnSelection();
2827
int column;
2828
2829
if (!colSel.isEmpty())
2830
{
2831
if (trimLeft)
2832
{
2833
column = colSel.getMin();
2834
}
2835
else
2836
{
2837
column = colSel.getMax();
2838
}
2839
2840
SequenceI[] seqs;
2841
if (viewport.getSelectionGroup() != null)
2842
{
2843
seqs = viewport.getSelectionGroup()
2844
.getSequencesAsArray(viewport.getHiddenRepSequences());
2845
}
2846
else
2847
{
2848
seqs = viewport.getAlignment().getSequencesArray();
2849
}
2850
2851
TrimRegionCommand trimRegion;
2852
if (trimLeft)
2853
{
2854
trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
2855
column, viewport.getAlignment());
2856
viewport.getRanges().setStartRes(0);
2857
}
2858
else
2859
{
2860
trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
2861
column, viewport.getAlignment());
2862
}
2863
2864
setStatus(MessageManager.formatMessage("label.removed_columns",
2865
new String[]
2866
{ Integer.valueOf(trimRegion.getSize()).toString() }));
2867
2868
addHistoryItem(trimRegion);
2869
2870
for (SequenceGroup sg : viewport.getAlignment().getGroups())
2871
{
2872
if ((trimLeft && !sg.adjustForRemoveLeft(column))
2873
|| (!trimLeft && !sg.adjustForRemoveRight(column)))
2874
{
2875
viewport.getAlignment().deleteGroup(sg);
2876
}
2877
}
2878
2879
viewport.firePropertyChange("alignment", null,
2880
viewport.getAlignment().getSequences());
2881
}
2882
}
2883
2884
/**
2885
* DOCUMENT ME!
2886
*
2887
* @param e
2888
* DOCUMENT ME!
2889
*/
2890
@Override
2891
public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
2892
{
2893
int start = 0, end = viewport.getAlignment().getWidth() - 1;
2894
2895
SequenceI[] seqs;
2896
if (viewport.getSelectionGroup() != null)
2897
{
2898
seqs = viewport.getSelectionGroup()
2899
.getSequencesAsArray(viewport.getHiddenRepSequences());
2900
start = viewport.getSelectionGroup().getStartRes();
2901
end = viewport.getSelectionGroup().getEndRes();
2902
}
2903
else
2904
{
2905
seqs = viewport.getAlignment().getSequencesArray();
2906
}
2907
2908
RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
2909
"Remove Gapped Columns", seqs, start, end,
2910
viewport.getAlignment());
2911
2912
addHistoryItem(removeGapCols);
2913
2914
setStatus(MessageManager.formatMessage("label.removed_empty_columns",
2915
new Object[]
2916
{ Integer.valueOf(removeGapCols.getSize()).toString() }));
2917
2918
// This is to maintain viewport position on first residue
2919
// of first sequence
2920
SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2921
ViewportRanges ranges = viewport.getRanges();
2922
int startRes = seq.findPosition(ranges.getStartRes());
2923
// ShiftList shifts;
2924
// viewport.getAlignment().removeGaps(shifts=new ShiftList());
2925
// edit.alColumnChanges=shifts.getInverse();
2926
// if (viewport.hasHiddenColumns)
2927
// viewport.getColumnSelection().compensateForEdits(shifts);
2928
ranges.setStartRes(seq.findIndex(startRes) - 1);
2929
viewport.firePropertyChange("alignment", null,
2930
viewport.getAlignment().getSequences());
2931
2932
}
2933
2934
/**
2935
* DOCUMENT ME!
2936
*
2937
* @param e
2938
* DOCUMENT ME!
2939
*/
2940
@Override
2941
public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
2942
{
2943
int start = 0, end = viewport.getAlignment().getWidth() - 1;
2944
2945
SequenceI[] seqs;
2946
if (viewport.getSelectionGroup() != null)
2947
{
2948
seqs = viewport.getSelectionGroup()
2949
.getSequencesAsArray(viewport.getHiddenRepSequences());
2950
start = viewport.getSelectionGroup().getStartRes();
2951
end = viewport.getSelectionGroup().getEndRes();
2952
}
2953
else
2954
{
2955
seqs = viewport.getAlignment().getSequencesArray();
2956
}
2957
2958
// This is to maintain viewport position on first residue
2959
// of first sequence
2960
SequenceI seq = viewport.getAlignment().getSequenceAt(0);
2961
int startRes = seq.findPosition(viewport.getRanges().getStartRes());
2962
2963
addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
2964
viewport.getAlignment()));
2965
2966
viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
2967
2968
viewport.firePropertyChange("alignment", null,
2969
viewport.getAlignment().getSequences());
2970
2971
}
2972
2973
/**
2974
* DOCUMENT ME!
2975
*
2976
* @param e
2977
* DOCUMENT ME!
2978
*/
2979
@Override
2980
public void padGapsMenuitem_actionPerformed(ActionEvent e)
2981
{
2982
viewport.setPadGaps(padGapsMenuitem.isSelected());
2983
viewport.firePropertyChange("alignment", null,
2984
viewport.getAlignment().getSequences());
2985
}
2986
2987
/**
2988
* Opens a Finder dialog
2989
*
2990
* @param e
2991
*/
2992
@Override
2993
public void findMenuItem_actionPerformed(ActionEvent e)
2994
{
2995
new Finder(alignPanel, false, null);
2996
}
2997
2998
/**
2999
* Create a new view of the current alignment.
3000
*/
3001
@Override
3002
public void newView_actionPerformed(ActionEvent e)
3003
{
3004
newView(null, true);
3005
}
3006
3007
/**
3008
* Creates and shows a new view of the current alignment.
3009
*
3010
* @param viewTitle
3011
* title of newly created view; if null, one will be generated
3012
* @param copyAnnotation
3013
* if true then duplicate all annnotation, groups and settings
3014
* @return new alignment panel, already displayed.
3015
*/
3016
public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
3017
{
3018
/*
3019
* Create a new AlignmentPanel (with its own, new Viewport)
3020
*/
3021
AlignmentPanel newap = new jalview.project.Jalview2XML()
3022
.copyAlignPanel(alignPanel);
3023
if (!copyAnnotation)
3024
{
3025
/*
3026
* remove all groups and annotation except for the automatic stuff
3027
*/
3028
newap.av.getAlignment().deleteAllGroups();
3029
newap.av.getAlignment().deleteAllAnnotations(false);
3030
}
3031
3032
newap.av.setGatherViewsHere(false);
3033
3034
if (viewport.getViewName() == null)
3035
{
3036
viewport.setViewName(
3037
MessageManager.getString("label.view_name_original"));
3038
}
3039
3040
/*
3041
* Views share the same edits undo and redo stacks
3042
*/
3043
newap.av.setHistoryList(viewport.getHistoryList());
3044
newap.av.setRedoList(viewport.getRedoList());
3045
3046
/*
3047
* copy any visualisation settings that are not saved in the project
3048
*/
3049
newap.av.setColourAppliesToAllGroups(
3050
viewport.getColourAppliesToAllGroups());
3051
3052
/*
3053
* Views share the same mappings; need to deregister any new mappings created by
3054
* copyAlignPanel, and register the new reference to the shared mappings
3055
*/
3056
newap.av.replaceMappings(viewport.getAlignment());
3057
3058
/*
3059
* start up cDNA consensus (if applicable) now mappings are in place
3060
*/
3061
if (newap.av.initComplementConsensus())
3062
{
3063
newap.refresh(true); // adjust layout of annotations
3064
}
3065
3066
newap.av.setViewName(getNewViewName(viewTitle));
3067
3068
addAlignmentPanel(newap, true);
3069
newap.alignmentChanged();
3070
3071
if (alignPanels.size() == 2)
3072
{
3073
viewport.setGatherViewsHere(true);
3074
}
3075
tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
3076
3077
return newap;
3078
}
3079
3080
/**
3081
* Make a new name for the view, ensuring it is unique within the current
3082
* sequenceSetId. (This used to be essential for Jalview Project archives, but
3083
* these now use viewId. Unique view names are still desirable for usability.)
3084
*
3085
* @param viewTitle
3086
* @return
3087
*/
3088
protected String getNewViewName(String viewTitle)
3089
{
3090
int index = Desktop.getViewCount(viewport.getSequenceSetId());
3091
boolean addFirstIndex = false;
3092
if (viewTitle == null || viewTitle.trim().length() == 0)
3093
{
3094
viewTitle = MessageManager.getString("action.view");
3095
addFirstIndex = true;
3096
}
3097
else
3098
{
3099
index = 1;// we count from 1 if given a specific name
3100
}
3101
String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
3102
3103
List comps = PaintRefresher.components
3104
.get(viewport.getSequenceSetId());
3105
3106
List existingNames = getExistingViewNames(comps);
3107
3108
while (existingNames.contains(newViewName))
3109
{
3110
newViewName = viewTitle + " " + (++index);
3111
}
3112
return newViewName;
3113
}
3114
3115
/**
3116
* Returns a list of distinct view names found in the given list of
3117
* components. View names are held on the viewport of an AlignmentPanel.
3118
*
3119
* @param comps
3120
* @return
3121
*/
3122
protected List getExistingViewNames(List comps)
3123
{
3124
List existingNames = new ArrayList<>();
3125
for (Component comp : comps)
3126
{
3127
if (comp instanceof AlignmentPanel)
3128
{
3129
AlignmentPanel ap = (AlignmentPanel) comp;
3130
if (!existingNames.contains(ap.av.getViewName()))
3131
{
3132
existingNames.add(ap.av.getViewName());
3133
}
3134
}
3135
}
3136
return existingNames;
3137
}
3138
3139
/**
3140
* Explode tabbed views into separate windows.
3141
*/
3142
@Override
3143
public void expandViews_actionPerformed(ActionEvent e)
3144
{
3145
Desktop.explodeViews(this);
3146
}
3147
3148
/**
3149
* Gather views in separate windows back into a tabbed presentation.
3150
*/
3151
@Override
3152
public void gatherViews_actionPerformed(ActionEvent e)
3153
{
3154
Desktop.instance.gatherViews(this);
3155
}
3156
3157
/**
3158
* DOCUMENT ME!
3159
*
3160
* @param e
3161
* DOCUMENT ME!
3162
*/
3163
@Override
3164
public void font_actionPerformed(ActionEvent e)
3165
{
3166
new FontChooser(alignPanel);
3167
}
3168
3169
/**
3170
* DOCUMENT ME!
3171
*
3172
* @param e
3173
* DOCUMENT ME!
3174
*/
3175
@Override
3176
protected void seqLimit_actionPerformed(ActionEvent e)
3177
{
3178
viewport.setShowJVSuffix(seqLimits.isSelected());
3179
3180
alignPanel.getIdPanel().getIdCanvas()
3181
.setPreferredSize(alignPanel.calculateIdWidth());
3182
alignPanel.paintAlignment(true, false);
3183
}
3184
3185
@Override
3186
public void idRightAlign_actionPerformed(ActionEvent e)
3187
{
3188
viewport.setRightAlignIds(idRightAlign.isSelected());
3189
alignPanel.paintAlignment(false, false);
3190
}
3191
3192
@Override
3193
public void centreColumnLabels_actionPerformed(ActionEvent e)
3194
{
3195
viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
3196
alignPanel.paintAlignment(false, false);
3197
}
3198
3199
/*
3200
* (non-Javadoc)
3201
*
3202
* @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
3203
*/
3204
@Override
3205
protected void followHighlight_actionPerformed()
3206
{
3207
/*
3208
* Set the 'follow' flag on the Viewport (and scroll to position if now true).
3209
*/
3210
final boolean state = this.followHighlightMenuItem.getState();
3211
viewport.setFollowHighlight(state);
3212
if (state)
3213
{
3214
alignPanel.scrollToPosition(viewport.getSearchResults());
3215
}
3216
}
3217
3218
/**
3219
* DOCUMENT ME!
3220
*
3221
* @param e
3222
* DOCUMENT ME!
3223
*/
3224
@Override
3225
protected void colourTextMenuItem_actionPerformed(ActionEvent e)
3226
{
3227
viewport.setColourText(colourTextMenuItem.isSelected());
3228
alignPanel.paintAlignment(false, false);
3229
}
3230
3231
/**
3232
* DOCUMENT ME!
3233
*
3234
* @param e
3235
* DOCUMENT ME!
3236
*/
3237
@Override
3238
public void wrapMenuItem_actionPerformed(ActionEvent e)
3239
{
3240
setWrapFormat(wrapMenuItem.isSelected(), false);
3241
}
3242
3243
public void setWrapFormat(boolean b, boolean setMenuItem)
3244
{
3245
scaleAbove.setVisible(b);
3246
scaleLeft.setVisible(b);
3247
scaleRight.setVisible(b);
3248
viewport.setWrapAlignment(b);
3249
alignPanel.updateLayout();
3250
if (setMenuItem)
3251
{
3252
wrapMenuItem.setSelected(b);
3253
}
3254
}
3255
3256
@Override
3257
public void showAllSeqs_actionPerformed(ActionEvent e)
3258
{
3259
viewport.showAllHiddenSeqs();
3260
}
3261
3262
@Override
3263
public void showAllColumns_actionPerformed(ActionEvent e)
3264
{
3265
viewport.showAllHiddenColumns();
3266
alignPanel.paintAlignment(true, true);
3267
viewport.sendSelection();
3268
}
3269
3270
@Override
3271
public void hideSelSequences_actionPerformed(ActionEvent e)
3272
{
3273
viewport.hideAllSelectedSeqs();
3274
}
3275
3276
/**
3277
* called by key handler and the hide all/show all menu items
3278
*
3279
* @param toggleSeqs
3280
* @param toggleCols
3281
*/
3282
protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
3283
{
3284
3285
boolean hide = false;
3286
SequenceGroup sg = viewport.getSelectionGroup();
3287
if (!toggleSeqs && !toggleCols)
3288
{
3289
// Hide everything by the current selection - this is a hack - we do the
3290
// invert and then hide
3291
// first check that there will be visible columns after the invert.
3292
if (viewport.hasSelectedColumns() || (sg != null && sg.getSize() > 0
3293
&& sg.getStartRes() <= sg.getEndRes()))
3294
{
3295
// now invert the sequence set, if required - empty selection implies
3296
// that no hiding is required.
3297
if (sg != null)
3298
{
3299
invertSequenceMenuItem_actionPerformed(null);
3300
sg = viewport.getSelectionGroup();
3301
toggleSeqs = true;
3302
3303
}
3304
viewport.expandColSelection(sg, true);
3305
// finally invert the column selection and get the new sequence
3306
// selection.
3307
invertColSel_actionPerformed(null);
3308
toggleCols = true;
3309
}
3310
}
3311
3312
if (toggleSeqs)
3313
{
3314
if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
3315
{
3316
hideSelSequences_actionPerformed(null);
3317
hide = true;
3318
}
3319
else if (!(toggleCols && viewport.hasSelectedColumns()))
3320
{
3321
showAllSeqs_actionPerformed(null);
3322
}
3323
}
3324
3325
if (toggleCols)
3326
{
3327
if (viewport.hasSelectedColumns())
3328
{
3329
hideSelColumns_actionPerformed(null);
3330
if (!toggleSeqs)
3331
{
3332
viewport.setSelectionGroup(sg);
3333
}
3334
}
3335
else if (!hide)
3336
{
3337
showAllColumns_actionPerformed(null);
3338
}
3339
}
3340
}
3341
3342
/*
3343
* (non-Javadoc)
3344
*
3345
* @see jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
3346
* event.ActionEvent)
3347
*/
3348
@Override
3349
public void hideAllButSelection_actionPerformed(ActionEvent e)
3350
{
3351
toggleHiddenRegions(false, false);
3352
viewport.sendSelection();
3353
}
3354
3355
/*
3356
* (non-Javadoc)
3357
*
3358
* @see
3359
* jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
3360
* .ActionEvent)
3361
*/
3362
@Override
3363
public void hideAllSelection_actionPerformed(ActionEvent e)
3364
{
3365
SequenceGroup sg = viewport.getSelectionGroup();
3366
viewport.expandColSelection(sg, false);
3367
viewport.hideAllSelectedSeqs();
3368
viewport.hideSelectedColumns();
3369
alignPanel.updateLayout();
3370
alignPanel.paintAlignment(true, true);
3371
viewport.sendSelection();
3372
}
3373
3374
/*
3375
* (non-Javadoc)
3376
*
3377
* @see jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
3378
* ActionEvent)
3379
*/
3380
@Override
3381
public void showAllhidden_actionPerformed(ActionEvent e)
3382
{
3383
viewport.showAllHiddenColumns();
3384
viewport.showAllHiddenSeqs();
3385
alignPanel.paintAlignment(true, true);
3386
viewport.sendSelection();
3387
}
3388
3389
@Override
3390
public void hideSelColumns_actionPerformed(ActionEvent e)
3391
{
3392
viewport.hideSelectedColumns();
3393
alignPanel.updateLayout();
3394
alignPanel.paintAlignment(true, true);
3395
viewport.sendSelection();
3396
}
3397
3398
@Override
3399
public void hiddenMarkers_actionPerformed(ActionEvent e)
3400
{
3401
viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
3402
repaint();
3403
}
3404
3405
/**
3406
* DOCUMENT ME!
3407
*
3408
* @param e
3409
* DOCUMENT ME!
3410
*/
3411
@Override
3412
protected void scaleAbove_actionPerformed(ActionEvent e)
3413
{
3414
viewport.setScaleAboveWrapped(scaleAbove.isSelected());
3415
alignPanel.updateLayout();
3416
alignPanel.paintAlignment(true, false);
3417
}
3418
3419
/**
3420
* DOCUMENT ME!
3421
*
3422
* @param e
3423
* DOCUMENT ME!
3424
*/
3425
@Override
3426
protected void scaleLeft_actionPerformed(ActionEvent e)
3427
{
3428
viewport.setScaleLeftWrapped(scaleLeft.isSelected());
3429
alignPanel.updateLayout();
3430
alignPanel.paintAlignment(true, false);
3431
}
3432
3433
/**
3434
* DOCUMENT ME!
3435
*
3436
* @param e
3437
* DOCUMENT ME!
3438
*/
3439
@Override
3440
protected void scaleRight_actionPerformed(ActionEvent e)
3441
{
3442
viewport.setScaleRightWrapped(scaleRight.isSelected());
3443
alignPanel.updateLayout();
3444
alignPanel.paintAlignment(true, false);
3445
}
3446
3447
/**
3448
* DOCUMENT ME!
3449
*
3450
* @param e
3451
* DOCUMENT ME!
3452
*/
3453
@Override
3454
public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
3455
{
3456
viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
3457
alignPanel.paintAlignment(false, false);
3458
}
3459
3460
/**
3461
* DOCUMENT ME!
3462
*
3463
* @param e
3464
* DOCUMENT ME!
3465
*/
3466
@Override
3467
public void viewTextMenuItem_actionPerformed(ActionEvent e)
3468
{
3469
viewport.setShowText(viewTextMenuItem.isSelected());
3470
alignPanel.paintAlignment(false, false);
3471
}
3472
3473
/**
3474
* DOCUMENT ME!
3475
*
3476
* @param e
3477
* DOCUMENT ME!
3478
*/
3479
@Override
3480
protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
3481
{
3482
viewport.setRenderGaps(renderGapsMenuItem.isSelected());
3483
alignPanel.paintAlignment(false, false);
3484
}
3485
3486
public FeatureSettings featureSettings;
3487
3488
@Override
3489
public FeatureSettingsControllerI getFeatureSettingsUI()
3490
{
3491
return featureSettings;
3492
}
3493
3494
@Override
3495
public void featureSettings_actionPerformed(ActionEvent e)
3496
{
3497
showFeatureSettingsUI();
3498
}
3499
3500
@Override
3501
public FeatureSettingsControllerI showFeatureSettingsUI()
3502
{
3503
if (featureSettings != null)
3504
{
3505
featureSettings.closeOldSettings();
3506
featureSettings = null;
3507
}
3508
if (!showSeqFeatures.isSelected())
3509
{
3510
// make sure features are actually displayed
3511
showSeqFeatures.setSelected(true);
3512
showSeqFeatures_actionPerformed(null);
3513
}
3514
featureSettings = new FeatureSettings(this);
3515
return featureSettings;
3516
}
3517
3518
/**
3519
* Set or clear 'Show Sequence Features'
3520
*
3521
* @param evt
3522
* DOCUMENT ME!
3523
*/
3524
@Override
3525
public void showSeqFeatures_actionPerformed(ActionEvent evt)
3526
{
3527
viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
3528
alignPanel.paintAlignment(true, true);
3529
}
3530
3531
/**
3532
* Action on toggle of the 'Show annotations' menu item. This shows or hides
3533
* the annotations panel as a whole.
3534
*
3535
* The options to show/hide all annotations should be enabled when the panel
3536
* is shown, and disabled when the panel is hidden.
3537
*
3538
* @param e
3539
*/
3540
@Override
3541
public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
3542
{
3543
final boolean setVisible = annotationPanelMenuItem.isSelected();
3544
viewport.setShowAnnotation(setVisible);
3545
this.showAllSeqAnnotations.setEnabled(setVisible);
3546
this.hideAllSeqAnnotations.setEnabled(setVisible);
3547
this.showAllAlAnnotations.setEnabled(setVisible);
3548
this.hideAllAlAnnotations.setEnabled(setVisible);
3549
alignPanel.updateLayout();
3550
}
3551
3552
@Override
3553
public void alignmentProperties()
3554
{
3555
JComponent pane;
3556
StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
3557
3558
.formatAsHtml();
3559
String content = MessageManager.formatMessage("label.html_content",
3560
new Object[]
3561
{ contents.toString() });
3562
contents = null;
3563
3564
if (Platform.isJS())
3565
{
3566
JLabel textLabel = new JLabel();
3567
textLabel.setText(content);
3568
textLabel.setBackground(Color.WHITE);
3569
3570
pane = new JPanel(new BorderLayout());
3571
((JPanel) pane).setOpaque(true);
3572
pane.setBackground(Color.WHITE);
3573
((JPanel) pane).add(textLabel, BorderLayout.NORTH);
3574
}
3575
else
3576
/**
3577
* Java only
3578
*
3579
* @j2sIgnore
3580
*/
3581
{
3582
JEditorPane editPane = new JEditorPane("text/html", "");
3583
editPane.setEditable(false);
3584
editPane.setText(content);
3585
pane = editPane;
3586
}
3587
3588
JInternalFrame frame = new JInternalFrame();
3589
frame.setFrameIcon(null);
3590
frame.getContentPane().add(new JScrollPane(pane));
3591
3592
Desktop.addInternalFrame(frame, MessageManager
3593
.formatMessage("label.alignment_properties", new Object[]
3594
{ getTitle() }), 500, 400);
3595
}
3596
3597
/**
3598
* Opens an Overview panel for the alignment, unless one is open already
3599
*
3600
* @param e
3601
*/
3602
@Override
3603
public void overviewMenuItem_actionPerformed(ActionEvent e)
3604
{
3605
boolean showHiddenRegions = Cache
3606
.getDefault(Preferences.SHOW_OV_HIDDEN_AT_START, false);
3607
openOverviewPanel(showHiddenRegions);
3608
}
3609
3610
public OverviewPanel openOverviewPanel(boolean showHidden)
3611
{
3612
if (alignPanel.overviewPanel != null)
3613
{
3614
return alignPanel.overviewPanel;
3615
}
3616
JInternalFrame frame = new JInternalFrame();
3617
frame.setFrameIcon(null);
3618
final OverviewPanel overview = new OverviewPanel(alignPanel, frame,
3619
showHidden);
3620
frame.setContentPane(overview);
3621
3622
alignPanel.setOverviewPanel(overview);
3623
alignPanel.setOverviewTitle(this);
3624
3625
Desktop.addInternalFrame(frame, overview.getTitle(), true,
3626
frame.getWidth(), frame.getHeight(), true, true);
3627
frame.pack();
3628
frame.setLayer(JLayeredPane.PALETTE_LAYER);
3629
final AlignmentPanel thePanel = this.alignPanel;
3630
frame.addInternalFrameListener(
3631
new javax.swing.event.InternalFrameAdapter()
3632
{
3633
@Override
3634
public void internalFrameClosed(
3635
javax.swing.event.InternalFrameEvent evt)
3636
{
3637
overview.dispose();
3638
thePanel.setOverviewPanel(null);
3639
}
3640
});
3641
if (getKeyListeners().length > 0)
3642
{
3643
frame.addKeyListener(getKeyListeners()[0]);
3644
}
3645
3646
return overview;
3647
}
3648
3649
@Override
3650
public void textColour_actionPerformed()
3651
{
3652
new TextColourChooser().chooseColour(alignPanel, null);
3653
}
3654
3655
/*
3656
* public void covariationColour_actionPerformed() { changeColour(new
3657
* CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
3658
* ()[0])); }
3659
*/
3660
@Override
3661
public void annotationColour_actionPerformed()
3662
{
3663
new AnnotationColourChooser(viewport, alignPanel);
3664
}
3665
3666
@Override
3667
public void annotationColumn_actionPerformed(ActionEvent e)
3668
{
3669
new AnnotationColumnChooser(viewport, alignPanel);
3670
}
3671
3672
/**
3673
* Action on the user checking or unchecking the option to apply the selected
3674
* colour scheme to all groups. If unchecked, groups may have their own
3675
* independent colour schemes.
3676
*
3677
* @param selected
3678
*/
3679
@Override
3680
public void applyToAllGroups_actionPerformed(boolean selected)
3681
{
3682
viewport.setColourAppliesToAllGroups(selected);
3683
}
3684
3685
/**
3686
* Action on user selecting a colour from the colour menu
3687
*
3688
* @param name
3689
* the name (not the menu item label!) of the colour scheme
3690
*/
3691
@Override
3692
public void changeColour_actionPerformed(String name)
3693
{
3694
/*
3695
* 'User Defined' opens a panel to configure or load a user-defined colour
3696
* scheme
3697
*/
3698
if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
3699
{
3700
new UserDefinedColours(alignPanel);
3701
return;
3702
}
3703
3704
/*
3705
* otherwise set the chosen colour scheme (or null for 'None')
3706
*/
3707
ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
3708
viewport, viewport.getAlignment(),
3709
viewport.getHiddenRepSequences());
3710
changeColour(cs);
3711
}
3712
3713
/**
3714
* Actions on setting or changing the alignment colour scheme
3715
*
3716
* @param cs
3717
*/
3718
@Override
3719
public void changeColour(ColourSchemeI cs)
3720
{
3721
// TODO: pull up to controller method
3722
ColourMenuHelper.setColourSelected(colourMenu, cs);
3723
3724
viewport.setGlobalColourScheme(cs);
3725
3726
alignPanel.paintAlignment(true, true);
3727
}
3728
3729
/**
3730
* Show the PID threshold slider panel
3731
*/
3732
@Override
3733
protected void modifyPID_actionPerformed()
3734
{
3735
SliderPanel.setPIDSliderSource(alignPanel, viewport.getResidueShading(),
3736
alignPanel.getViewName());
3737
SliderPanel.showPIDSlider();
3738
}
3739
3740
/**
3741
* Show the Conservation slider panel
3742
*/
3743
@Override
3744
protected void modifyConservation_actionPerformed()
3745
{
3746
SliderPanel.setConservationSlider(alignPanel,
3747
viewport.getResidueShading(), alignPanel.getViewName());
3748
SliderPanel.showConservationSlider();
3749
}
3750
3751
@Override
3752
protected void modifyConsensusSecondaryStructureThreshold_actionPerformed()
3753
{
3754
SliderPanel.setConsensusSecondaryStructureSlider(alignPanel,
3755
viewport.getResidueShading(), alignPanel.getViewName());
3756
SliderPanel.showConsensusSecondaryStructureSlider();
3757
}
3758
3759
/**
3760
* Action on selecting or deselecting (Colour) By Conservation
3761
*/
3762
@Override
3763
public void conservationMenuItem_actionPerformed(boolean selected)
3764
{
3765
modifyConservation.setEnabled(selected);
3766
viewport.setConservationSelected(selected);
3767
viewport.getResidueShading().setConservationApplied(selected);
3768
3769
changeColour(viewport.getGlobalColourScheme());
3770
if (selected)
3771
{
3772
modifyConservation_actionPerformed();
3773
}
3774
else
3775
{
3776
SliderPanel.hideConservationSlider();
3777
}
3778
}
3779
3780
@Override
3781
public void colourByConsensusSecondaryStructureMenuItem_actionPerformed(
3782
boolean selected)
3783
{
3784
modifyConsensusSecondaryStructureThreshold.setEnabled(selected);
3785
viewport.setByConsensusSecondaryStructureSelected(selected);
3786
viewport.getResidueShading()
3787
.setConsensusSecondaryStructureColouring(selected);
3788
3789
changeColour(viewport.getGlobalColourScheme());
3790
if (selected)
3791
{
3792
modifyConsensusSecondaryStructureThreshold_actionPerformed();
3793
}
3794
else
3795
{
3796
SliderPanel.hideConsensusSecondaryStructureSlider();
3797
}
3798
}
3799
3800
/**
3801
* Action on selecting or deselecting (Colour) Above PID Threshold
3802
*/
3803
@Override
3804
public void abovePIDThreshold_actionPerformed(boolean selected)
3805
{
3806
modifyPID.setEnabled(selected);
3807
viewport.setAbovePIDThreshold(selected);
3808
if (!selected)
3809
{
3810
viewport.getResidueShading().setThreshold(0,
3811
viewport.isIgnoreGapsConsensus());
3812
}
3813
3814
changeColour(viewport.getGlobalColourScheme());
3815
if (selected)
3816
{
3817
modifyPID_actionPerformed();
3818
}
3819
else
3820
{
3821
SliderPanel.hidePIDSlider();
3822
}
3823
}
3824
3825
/**
3826
* DOCUMENT ME!
3827
*
3828
* @param e
3829
* DOCUMENT ME!
3830
*/
3831
@Override
3832
public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
3833
{
3834
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3835
AlignmentSorter.sortByPID(viewport.getAlignment(),
3836
viewport.getAlignment().getSequenceAt(0));
3837
addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
3838
viewport.getAlignment()));
3839
alignPanel.paintAlignment(true, false);
3840
}
3841
3842
/**
3843
* DOCUMENT ME!
3844
*
3845
* @param e
3846
* DOCUMENT ME!
3847
*/
3848
@Override
3849
public void sortIDMenuItem_actionPerformed(ActionEvent e)
3850
{
3851
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3852
AlignmentSorter.sortByID(viewport.getAlignment());
3853
addHistoryItem(
3854
new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
3855
alignPanel.paintAlignment(true, false);
3856
}
3857
3858
@Override
3859
protected void sortDescriptionMenuItem_actionPerformed(ActionEvent e)
3860
{
3861
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3862
AlignmentSorter.sortByDescription(viewport.getAlignment());
3863
addHistoryItem(new OrderCommand("Description Sort", oldOrder,
3864
viewport.getAlignment()));
3865
alignPanel.paintAlignment(true, false);
3866
}
3867
3868
/**
3869
* DOCUMENT ME!
3870
*
3871
* @param e
3872
* DOCUMENT ME!
3873
*/
3874
@Override
3875
public void sortLengthMenuItem_actionPerformed(ActionEvent e)
3876
{
3877
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3878
AlignmentSorter.sortByLength(viewport.getAlignment());
3879
addHistoryItem(new OrderCommand("Length Sort", oldOrder,
3880
viewport.getAlignment()));
3881
alignPanel.paintAlignment(true, false);
3882
}
3883
3884
/**
3885
* DOCUMENT ME!
3886
*
3887
* @param e
3888
* DOCUMENT ME!
3889
*/
3890
@Override
3891
public void sortGroupMenuItem_actionPerformed(ActionEvent e)
3892
{
3893
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
3894
AlignmentSorter.sortByGroup(viewport.getAlignment());
3895
addHistoryItem(new OrderCommand("Group Sort", oldOrder,
3896
viewport.getAlignment()));
3897
3898
alignPanel.paintAlignment(true, false);
3899
}
3900
3901
/**
3902
* DOCUMENT ME!
3903
*
3904
* @param e
3905
* DOCUMENT ME!
3906
*/
3907
@Override
3908
public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
3909
{
3910
new RedundancyPanel(alignPanel, this);
3911
}
3912
3913
/**
3914
* DOCUMENT ME!
3915
*
3916
* @param e
3917
* DOCUMENT ME!
3918
*/
3919
@Override
3920
public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
3921
{
3922
if ((viewport.getSelectionGroup() == null)
3923
|| (viewport.getSelectionGroup().getSize() < 2))
3924
{
3925
JvOptionPane.showInternalMessageDialog(this,
3926
MessageManager.getString(
3927
"label.you_must_select_least_two_sequences"),
3928
MessageManager.getString("label.invalid_selection"),
3929
JvOptionPane.WARNING_MESSAGE);
3930
}
3931
else
3932
{
3933
new Thread(new Runnable()
3934
{
3935
@Override
3936
public void run()
3937
{
3938
JInternalFrame frame = new JInternalFrame();
3939
frame.setFrameIcon(null);
3940
frame.setContentPane(new PairwiseAlignPanel(viewport));
3941
Desktop.addInternalFrame(frame,
3942
MessageManager.getString("action.pairwise_alignment"),
3943
600, 500);
3944
}
3945
}).start();
3946
3947
}
3948
}
3949
3950
@Override
3951
public void autoCalculate_actionPerformed(ActionEvent e)
3952
{
3953
viewport.autoCalculateConsensus = autoCalculate.isSelected();
3954
if (viewport.autoCalculateConsensus)
3955
{
3956
viewport.firePropertyChange("alignment", null,
3957
viewport.getAlignment().getSequences());
3958
}
3959
}
3960
3961
@Override
3962
public void sortByTreeOption_actionPerformed(ActionEvent e)
3963
{
3964
viewport.sortByTree = sortByTree.isSelected();
3965
}
3966
3967
@Override
3968
protected void listenToViewSelections_actionPerformed(ActionEvent e)
3969
{
3970
viewport.followSelection = listenToViewSelections.isSelected();
3971
}
3972
3973
/**
3974
* Constructs a tree panel and adds it to the desktop
3975
*
3976
* @param type
3977
* tree type (NJ or AV)
3978
* @param modelName
3979
* name of score model used to compute the tree
3980
* @param options
3981
* parameters for the distance or similarity calculation
3982
*/
3983
void newTreePanel(String type, String modelName,
3984
SimilarityParamsI options, boolean isAnnotationBased)
3985
{
3986
String frameTitle = "";
3987
TreePanel tp;
3988
3989
boolean onSelection = false;
3990
if (viewport.getSelectionGroup() != null
3991
&& viewport.getSelectionGroup().getSize() > 0)
3992
{
3993
SequenceGroup sg = viewport.getSelectionGroup();
3994
3995
/* Decide if the selection is a column region */
3996
for (SequenceI _s : sg.getSequences())
3997
{
3998
if (_s.getLength() < sg.getEndRes())
3999
{
4000
JvOptionPane.showMessageDialog(Desktop.desktop,
4001
MessageManager.getString(
4002
"label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
4003
MessageManager.getString(
4004
"label.sequences_selection_not_aligned"),
4005
JvOptionPane.WARNING_MESSAGE);
4006
4007
return;
4008
}
4009
}
4010
onSelection = true;
4011
}
4012
else
4013
{
4014
// Fix for JAL-4521. For annotation based tree, min number of sequence
4015
// required for tree calculation is 1 as multiple annotations can be
4016
// present for a single sequence
4017
if ((viewport.getAlignment().getHeight() < 2 && !isAnnotationBased)
4018
|| (viewport.getAlignment().getHeight() < 1
4019
&& isAnnotationBased))
4020
{
4021
return;
4022
}
4023
}
4024
4025
tp = new TreePanel(alignPanel, type, modelName, options);
4026
4027
frameTitle = formCalculationTitle(tp.getPanelTitle(), onSelection,
4028
this.title);
4029
4030
Desktop.addInternalFrame(tp, frameTitle, 600, 500);
4031
}
4032
4033
/**
4034
*
4035
* @param panelTitle
4036
* - calculation name
4037
* @param onSelection
4038
* - true if a selection was analysed
4039
* @param viewName
4040
* - null or current view name
4041
* @param title
4042
* - alignment frame title
4043
* @return (?on region) from (?viewName of) alignment name
4044
*/
4045
public String formCalculationTitle(String panelTitle, boolean onSelection,
4046
String title)
4047
{
4048
String frameTitle = panelTitle;
4049
4050
frameTitle += (onSelection ? " on region" : "");
4051
4052
frameTitle += " from ";
4053
4054
if (viewport.getViewName() != null)
4055
{
4056
frameTitle += viewport.getViewName() + " of ";
4057
}
4058
4059
frameTitle += title;
4060
return frameTitle;
4061
}
4062
4063
/**
4064
* DOCUMENT ME!
4065
*
4066
* @param title
4067
* DOCUMENT ME!
4068
* @param order
4069
* DOCUMENT ME!
4070
*/
4071
public void addSortByOrderMenuItem(String title,
4072
final AlignmentOrder order)
4073
{
4074
final JMenuItem item = new JMenuItem(MessageManager
4075
.formatMessage("action.by_title_param", new Object[]
4076
{ title }));
4077
sort.add(item);
4078
item.addActionListener(new java.awt.event.ActionListener()
4079
{
4080
@Override
4081
public void actionPerformed(ActionEvent e)
4082
{
4083
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4084
4085
// TODO: JBPNote - have to map order entries to curent SequenceI
4086
// pointers
4087
AlignmentSorter.sortBy(viewport.getAlignment(), order);
4088
4089
addHistoryItem(new OrderCommand(order.getName(), oldOrder,
4090
viewport.getAlignment()));
4091
4092
alignPanel.paintAlignment(true, false);
4093
}
4094
});
4095
}
4096
4097
/**
4098
* Add a new sort by annotation score menu item
4099
*
4100
* @param sort
4101
* the menu to add the option to
4102
* @param scoreLabel
4103
* the label used to retrieve scores for each sequence on the
4104
* alignment
4105
*/
4106
public void addSortByAnnotScoreMenuItem(JMenu sort,
4107
final String scoreLabel)
4108
{
4109
final JMenuItem item = new JMenuItem(scoreLabel);
4110
sort.add(item);
4111
item.addActionListener(new java.awt.event.ActionListener()
4112
{
4113
@Override
4114
public void actionPerformed(ActionEvent e)
4115
{
4116
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4117
AlignmentSorter.sortByAnnotationScore(scoreLabel,
4118
viewport.getAlignment());// ,viewport.getSelectionGroup());
4119
addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
4120
viewport.getAlignment()));
4121
alignPanel.paintAlignment(true, false);
4122
}
4123
});
4124
}
4125
4126
/**
4127
* last hash for alignment's annotation array - used to minimise cost of
4128
* rebuild.
4129
*/
4130
protected int _annotationScoreVectorHash;
4131
4132
/**
4133
* search the alignment and rebuild the sort by annotation score submenu the
4134
* last alignment annotation vector hash is stored to minimize cost of
4135
* rebuilding in subsequence calls.
4136
*
4137
*/
4138
@Override
4139
public void buildSortByAnnotationScoresMenu()
4140
{
4141
if (viewport.getAlignment().getAlignmentAnnotation() == null)
4142
{
4143
return;
4144
}
4145
4146
if (viewport.getAlignment().getAlignmentAnnotation()
4147
.hashCode() != _annotationScoreVectorHash)
4148
{
4149
sortByAnnotScore.removeAll();
4150
// almost certainly a quicker way to do this - but we keep it simple
4151
Hashtable scoreSorts = new Hashtable<>();
4152
AlignmentAnnotation aann[];
4153
for (SequenceI sqa : viewport.getAlignment().getSequences())
4154
{
4155
aann = sqa.getAnnotation();
4156
for (int i = 0; aann != null && i < aann.length; i++)
4157
{
4158
if (aann[i].hasScore() && aann[i].sequenceRef != null)
4159
{
4160
scoreSorts.put(aann[i].label, aann[i].label);
4161
}
4162
}
4163
}
4164
Enumeration labels = scoreSorts.keys();
4165
while (labels.hasMoreElements())
4166
{
4167
addSortByAnnotScoreMenuItem(sortByAnnotScore, labels.nextElement());
4168
}
4169
sortByAnnotScore.setVisible(scoreSorts.size() > 0);
4170
scoreSorts.clear();
4171
4172
_annotationScoreVectorHash = viewport.getAlignment()
4173
.getAlignmentAnnotation().hashCode();
4174
}
4175
}
4176
4177
/**
4178
* Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
4179
* TreePanel with an appropriate jalview.analysis.AlignmentSorter
4180
* call. Listeners are added to remove the menu item when the treePanel is
4181
* closed, and adjust the tree leaf to sequence mapping when the alignment is
4182
* modified.
4183
*/
4184
@Override
4185
public void buildTreeSortMenu()
4186
{
4187
sortByTreeMenu.removeAll();
4188
4189
List comps = PaintRefresher.components
4190
.get(viewport.getSequenceSetId());
4191
List treePanels = new ArrayList<>();
4192
4193
List annotTreePanels = new ArrayList<>();
4194
for (Component comp : comps)
4195
{
4196
if (comp instanceof TreePanel)
4197
{
4198
treePanels.add((TreePanel) comp);
4199
4200
if (((TreePanel) comp).isAnnotationBased())
4201
{
4202
annotTreePanels.add((TreePanel) comp);
4203
}
4204
}
4205
}
4206
4207
if (treePanels.size() < 1)
4208
{
4209
sortByTreeMenu.setVisible(false);
4210
return;
4211
}
4212
4213
sortByTreeMenu.setVisible(true);
4214
4215
for (final TreePanel tp : treePanels)
4216
{
4217
final JMenuItem item = new JMenuItem(tp.getTitle());
4218
item.addActionListener(new java.awt.event.ActionListener()
4219
{
4220
@Override
4221
public void actionPerformed(ActionEvent e)
4222
{
4223
tp.sortByTree_actionPerformed();
4224
addHistoryItem(tp.sortAlignmentIn(alignPanel));
4225
4226
}
4227
});
4228
4229
sortByTreeMenu.add(item);
4230
}
4231
}
4232
4233
@Override
4234
public void buildSortAnnotationByTreeMenu()
4235
{
4236
sortAnnotationByTreeMenu.removeAll();
4237
4238
List comps = PaintRefresher.components
4239
.get(viewport.getSequenceSetId());
4240
4241
List annotTreePanels = new ArrayList<>();
4242
for (Component comp : comps)
4243
{
4244
if (comp instanceof TreePanel)
4245
{
4246
if (((TreePanel) comp).isAnnotationBased())
4247
{
4248
annotTreePanels.add((TreePanel) comp);
4249
}
4250
}
4251
}
4252
4253
if (annotTreePanels.size() < 1)
4254
{
4255
sortAnnotationByTreeMenu.setVisible(false);
4256
return;
4257
}
4258
4259
sortAnnotationByTreeMenu.setVisible(true);
4260
4261
for (final TreePanel tp : annotTreePanels)
4262
{
4263
final JMenuItem item = new JMenuItem(tp.getTitle());
4264
item.addActionListener(new java.awt.event.ActionListener()
4265
{
4266
@Override
4267
public void actionPerformed(ActionEvent e)
4268
{
4269
sortAnnByLabel.setSelected(false);
4270
sortAnnBySequence.setSelected(false);
4271
setAnnotationSortOrder(SequenceAnnotationOrder.NONE);
4272
tp.sortAnnotationByTree_actionPerformed();
4273
}
4274
});
4275
4276
sortAnnotationByTreeMenu.add(item);
4277
}
4278
}
4279
4280
public boolean sortBy(AlignmentOrder alorder, String undoname)
4281
{
4282
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
4283
AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
4284
if (undoname != null)
4285
{
4286
addHistoryItem(new OrderCommand(undoname, oldOrder,
4287
viewport.getAlignment()));
4288
}
4289
alignPanel.paintAlignment(true, false);
4290
return true;
4291
}
4292
4293
/**
4294
* Work out whether the whole set of sequences or just the selected set will
4295
* be submitted for multiple alignment.
4296
*
4297
*/
4298
public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
4299
{
4300
// Now, check we have enough sequences
4301
AlignmentView msa = null;
4302
4303
if ((viewport.getSelectionGroup() != null)
4304
&& (viewport.getSelectionGroup().getSize() > 1))
4305
{
4306
// JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
4307
// some common interface!
4308
/*
4309
* SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
4310
* SequenceI[sz = seqs.getSize(false)];
4311
*
4312
* for (int i = 0; i < sz; i++) { msa[i] = (SequenceI) seqs.getSequenceAt(i); }
4313
*/
4314
msa = viewport.getAlignmentView(true);
4315
}
4316
else if (viewport.getSelectionGroup() != null
4317
&& viewport.getSelectionGroup().getSize() == 1)
4318
{
4319
int option = JvOptionPane.showConfirmDialog(this,
4320
MessageManager.getString("warn.oneseq_msainput_selection"),
4321
MessageManager.getString("label.invalid_selection"),
4322
JvOptionPane.OK_CANCEL_OPTION);
4323
if (option == JvOptionPane.OK_OPTION)
4324
{
4325
msa = viewport.getAlignmentView(false);
4326
}
4327
}
4328
else
4329
{
4330
msa = viewport.getAlignmentView(false);
4331
}
4332
return msa;
4333
}
4334
4335
/**
4336
* Decides what is submitted to a secondary structure prediction service: the
4337
* first sequence in the alignment, or in the current selection, or, if the
4338
* alignment is 'aligned' (ie padded with gaps), then the currently selected
4339
* region or the whole alignment. (where the first sequence in the set is the
4340
* one that the prediction will be for).
4341
*/
4342
public AlignmentView gatherSeqOrMsaForSecStrPrediction()
4343
{
4344
AlignmentView seqs = null;
4345
4346
if ((viewport.getSelectionGroup() != null)
4347
&& (viewport.getSelectionGroup().getSize() > 0))
4348
{
4349
seqs = viewport.getAlignmentView(true);
4350
}
4351
else
4352
{
4353
seqs = viewport.getAlignmentView(false);
4354
}
4355
// limit sequences - JBPNote in future - could spawn multiple prediction
4356
// jobs
4357
// TODO: viewport.getAlignment().isAligned is a global state - the local
4358
// selection may well be aligned - we preserve 2.0.8 behaviour for moment.
4359
if (!viewport.getAlignment().isAligned(false))
4360
{
4361
seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] });
4362
// TODO: if seqs.getSequences().length>1 then should really have warned
4363
// user!
4364
4365
}
4366
return seqs;
4367
}
4368
4369
//// ***************************************************
4370
//// TODO REFACTOR TREE I/O TO CONTROLLER/SEPARATE CLASS
4371
//// ***************************************************
4372
4373
/**
4374
* DOCUMENT ME!
4375
*
4376
* @param e
4377
* DOCUMENT ME!
4378
*/
4379
@Override
4380
protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
4381
{
4382
// Pick the tree file
4383
JalviewFileChooser chooser = new JalviewFileChooser(
4384
Cache.getProperty("LAST_DIRECTORY"));
4385
chooser.setFileView(new JalviewFileView());
4386
chooser.setDialogTitle(
4387
MessageManager.getString("label.select_newick_like_tree_file"));
4388
chooser.setToolTipText(
4389
MessageManager.getString("label.load_tree_file"));
4390
4391
chooser.setResponseHandler(0, () -> {
4392
String filePath = chooser.getSelectedFile().getPath();
4393
Cache.setProperty("LAST_DIRECTORY", filePath);
4394
NewickFile fin = null;
4395
try
4396
{
4397
fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
4398
DataSourceType.FILE));
4399
viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
4400
} catch (Exception ex)
4401
{
4402
JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
4403
MessageManager.getString("label.problem_reading_tree_file"),
4404
JvOptionPane.WARNING_MESSAGE);
4405
ex.printStackTrace();
4406
}
4407
if (fin != null && fin.hasWarningMessage())
4408
{
4409
JvOptionPane.showMessageDialog(Desktop.desktop,
4410
fin.getWarningMessage(),
4411
MessageManager
4412
.getString("label.possible_problem_with_tree_file"),
4413
JvOptionPane.WARNING_MESSAGE);
4414
}
4415
});
4416
chooser.showOpenDialog(this);
4417
}
4418
4419
public TreePanel showNewickTree(NewickFile nf, String treeTitle)
4420
{
4421
return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
4422
}
4423
4424
public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
4425
int h, int x, int y)
4426
{
4427
return showNewickTree(nf, treeTitle, null, w, h, x, y);
4428
}
4429
4430
/**
4431
* Add a treeviewer for the tree extracted from a Newick file object to the
4432
* current alignment view
4433
*
4434
* @param nf
4435
* the tree
4436
* @param title
4437
* tree viewer title
4438
* @param input
4439
* Associated alignment input data (or null)
4440
* @param w
4441
* width
4442
* @param h
4443
* height
4444
* @param x
4445
* position
4446
* @param y
4447
* position
4448
* @return TreePanel handle
4449
*/
4450
public TreePanel showNewickTree(NewickFile nf, String treeTitle,
4451
AlignmentView input, int w, int h, int x, int y)
4452
{
4453
TreePanel tp = null;
4454
4455
try
4456
{
4457
nf.parse();
4458
4459
if (nf.getTree() != null)
4460
{
4461
tp = new TreePanel(alignPanel, nf, treeTitle, input);
4462
4463
layoutTreePanel(tp, treeTitle, w, h, x, y);
4464
}
4465
} catch (Exception ex)
4466
{
4467
ex.printStackTrace();
4468
}
4469
4470
return tp;
4471
}
4472
4473
/**
4474
* called by Jalview2XML only just now - import a tree that should be resolved
4475
* against annotations.
4476
*
4477
* @param nf
4478
* @param annotationIds
4479
* @param treeTitle
4480
* @param input
4481
* @param w
4482
* @param h
4483
* @param x
4484
* @param y
4485
* @return
4486
*/
4487
public TreePanel showNewickTreeForAnnotation(NewickFile nf,
4488
Map annotationIds, String treeTitle,
4489
AlignmentView input, int w, int h, int x, int y)
4490
{
4491
TreePanel tp = null;
4492
4493
try
4494
{
4495
nf.parse();
4496
4497
if (nf.getTree() != null)
4498
{
4499
tp = TreePanel.newTreeForAnnotations(alignPanel, nf, annotationIds,
4500
treeTitle, input);
4501
4502
layoutTreePanel(tp, treeTitle, w, h, x, y);
4503
}
4504
} catch (Exception ex)
4505
{
4506
ex.printStackTrace();
4507
}
4508
4509
return tp;
4510
}
4511
4512
/**
4513
* Applies layout configuration to a TreePanel and add it to the desktop.
4514
*
4515
* @param treePanel
4516
* the TreePanel to configure and display
4517
* @param title
4518
* the title of the tree panel
4519
* @param width
4520
* the width of the tree panel
4521
* @param height
4522
* the height of the tree panel
4523
* @param x
4524
* the x-coordinate of the panel
4525
* @param y
4526
* the y-coordinate of the panel
4527
*/
4528
public static void layoutTreePanel(TreePanel tp, String title, int w,
4529
int h, int x, int y)
4530
{
4531
tp.setSize(w, h);
4532
if (x > 0 && y > 0)
4533
{
4534
tp.setLocation(x, y);
4535
}
4536
Desktop.addInternalFrame(tp, title, w, h);
4537
}
4538
4539
public void showContactMapTree(AlignmentAnnotation aa, ContactMatrixI cm)
4540
{
4541
int x = 4, y = 5;
4542
int w = 400, h = 500;
4543
4544
try
4545
{
4546
NewickFile fin = new NewickFile(
4547
new FileParse(cm.getNewick(), DataSourceType.PASTE));
4548
String title = aa.label + " " + cm.getTreeMethod() + " tree"
4549
+ (aa.sequenceRef != null
4550
? (" for " + aa.sequenceRef.getDisplayId(false))
4551
: "");
4552
4553
showColumnWiseTree(fin, aa, title, w, h, x, y);
4554
} catch (Throwable xx)
4555
{
4556
Console.error("Unexpected exception showing tree for contact matrix",
4557
xx);
4558
}
4559
}
4560
4561
public TreePanel showColumnWiseTree(NewickFile nf, AlignmentAnnotation aa,
4562
String treeTitle, int w, int h, int x, int y)
4563
{
4564
try
4565
{
4566
nf.parse();
4567
if (nf.getTree() == null)
4568
{
4569
return null;
4570
}
4571
TreePanel tp = new TreePanel(alignPanel, nf, aa, treeTitle);
4572
4573
tp.setSize(w, h);
4574
4575
if (x > 0 && y > 0)
4576
{
4577
tp.setLocation(x, y);
4578
}
4579
4580
tp.setLayer(JLayeredPane.PALETTE_LAYER);
4581
4582
Desktop.addInternalFrame(tp, treeTitle, w, h);
4583
return tp;
4584
} catch (Throwable xx)
4585
{
4586
Console.error("Unexpected exception showing tree for contact matrix",
4587
xx);
4588
}
4589
return null;
4590
}
4591
//// ***************************************************
4592
//// TODO REFACTOR TREE I/O TO CONTROLLER/SEPARATE CLASS - END OF METHODS
4593
//// ***************************************************
4594
4595
private boolean buildingMenu = false;
4596
4597
/**
4598
* Generates menu items and listener event actions for web service clients
4599
*
4600
*/
4601
public void BuildWebServiceMenu()
4602
{
4603
while (buildingMenu)
4604
{
4605
try
4606
{
4607
jalview.bin.Console
4608
.errPrintln("Waiting for building menu to finish.");
4609
Thread.sleep(10);
4610
} catch (Exception e)
4611
{
4612
}
4613
}
4614
final AlignFrame me = this;
4615
buildingMenu = true;
4616
new Thread(new Runnable()
4617
{
4618
@Override
4619
public void run()
4620
{
4621
final List legacyItems = new ArrayList<>();
4622
try
4623
{
4624
// jalview.bin.Console.errPrintln("Building ws menu again "
4625
// + Thread.currentThread());
4626
// TODO: add support for context dependent disabling of services based
4627
// on
4628
// alignment and current selection
4629
// TODO: add additional serviceHandle parameter to specify abstract
4630
// handler
4631
// class independently of AbstractName
4632
// TODO: add in rediscovery GUI function to restart discoverer
4633
// TODO: group services by location as well as function and/or
4634
// introduce
4635
// object broker mechanism.
4636
final Vector wsmenu = new Vector<>();
4637
final IProgressIndicator af = me;
4638
4639
/*
4640
* do not i18n these strings - they are hard-coded in class
4641
* compbio.data.msa.Category, Jws2Discoverer.isRecalculable() and
4642
* SequenceAnnotationWSClient.initSequenceAnnotationWSClient()
4643
*/
4644
final JMenu msawsmenu = new JMenu("Alignment");
4645
final JMenu secstrmenu = new JMenu(
4646
"Secondary Structure Prediction");
4647
final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
4648
final JMenu analymenu = new JMenu("Analysis");
4649
final JMenu dismenu = new JMenu("Protein Disorder");
4650
// JAL-940 - only show secondary structure prediction services from
4651
// the legacy server
4652
if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
4653
// &&
4654
Discoverer.services != null && (Discoverer.services.size() > 0))
4655
{
4656
// TODO: refactor to allow list of AbstractName/Handler bindings to
4657
// be
4658
// stored or retrieved from elsewhere
4659
// No MSAWS used any more:
4660
// Vector msaws = null; // (Vector)
4661
// Discoverer.services.get("MsaWS");
4662
Vector secstrpr = Discoverer.services
4663
.get("SecStrPred");
4664
if (secstrpr != null)
4665
{
4666
// Add any secondary structure prediction services
4667
for (int i = 0, j = secstrpr.size(); i < j; i++)
4668
{
4669
final ext.vamsas.ServiceHandle sh = secstrpr.get(i);
4670
jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
4671
.getServiceClient(sh);
4672
int p = secstrmenu.getItemCount();
4673
impl.attachWSMenuEntry(secstrmenu, me);
4674
int q = secstrmenu.getItemCount();
4675
for (int litm = p; litm < q; litm++)
4676
{
4677
legacyItems.add(secstrmenu.getItem(litm));
4678
}
4679
}
4680
}
4681
}
4682
4683
// Add all submenus in the order they should appear on the web
4684
// services menu
4685
wsmenu.add(msawsmenu);
4686
wsmenu.add(secstrmenu);
4687
wsmenu.add(dismenu);
4688
wsmenu.add(analymenu);
4689
// No search services yet
4690
// wsmenu.add(seqsrchmenu);
4691
4692
javax.swing.SwingUtilities.invokeLater(new Runnable()
4693
{
4694
@Override
4695
public void run()
4696
{
4697
try
4698
{
4699
webService.removeAll();
4700
// first, add discovered services onto the webservices menu
4701
if (wsmenu.size() > 0)
4702
{
4703
for (int i = 0, j = wsmenu.size(); i < j; i++)
4704
{
4705
webService.add(wsmenu.get(i));
4706
}
4707
}
4708
else
4709
{
4710
webService.add(me.webServiceNoServices);
4711
}
4712
// TODO: move into separate menu builder class.
4713
{
4714
// logic for 2.11.1.4 is
4715
// always look to see if there is a discover. if there isn't
4716
// we can't show any Jws2 services
4717
// if there are services available, show them - regardless of
4718
// the 'show JWS2 preference'
4719
// if the discoverer is running then say so
4720
// otherwise offer to trigger discovery if 'show JWS2' is not
4721
// enabled
4722
Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
4723
if (jws2servs != null)
4724
{
4725
if (jws2servs.hasServices())
4726
{
4727
jws2servs.attachWSMenuEntry(webService, me);
4728
for (Jws2Instance sv : jws2servs.getServices())
4729
{
4730
if (sv.description.toLowerCase(Locale.ROOT)
4731
.contains("jpred"))
4732
{
4733
for (JMenuItem jmi : legacyItems)
4734
{
4735
jmi.setVisible(false);
4736
}
4737
}
4738
}
4739
}
4740
4741
if (jws2servs.isRunning())
4742
{
4743
JMenuItem tm = new JMenuItem(
4744
"Still discovering JABA Services");
4745
tm.setEnabled(false);
4746
webService.add(tm);
4747
}
4748
else if (!Cache.getDefault("SHOW_JWS2_SERVICES", true))
4749
{
4750
JMenuItem enableJws2 = new JMenuItem(
4751
"Discover Web Services");
4752
enableJws2.setToolTipText(
4753
"Select to start JABA Web Service discovery (or enable option in Web Service preferences)");
4754
enableJws2.setEnabled(true);
4755
enableJws2.addActionListener(new ActionListener()
4756
{
4757
4758
@Override
4759
public void actionPerformed(ActionEvent e)
4760
{
4761
// start service discoverer, but ignore preference
4762
Desktop.instance.startServiceDiscovery(false,
4763
true);
4764
}
4765
});
4766
webService.add(enableJws2);
4767
}
4768
}
4769
}
4770
build_urlServiceMenu(me.webService);
4771
build_fetchdbmenu(webService);
4772
for (JMenu item : wsmenu)
4773
{
4774
if (item.getItemCount() == 0)
4775
{
4776
item.setEnabled(false);
4777
}
4778
else
4779
{
4780
item.setEnabled(true);
4781
}
4782
}
4783
} catch (Exception e)
4784
{
4785
Console.debug(
4786
"Exception during web service menu building process.",
4787
e);
4788
}
4789
}
4790
});
4791
} catch (Exception e)
4792
{
4793
}
4794
buildingMenu = false;
4795
}
4796
}).start();
4797
4798
}
4799
4800
/**
4801
* construct any groupURL type service menu entries.
4802
*
4803
* @param webService
4804
*/
4805
protected void build_urlServiceMenu(JMenu webService)
4806
{
4807
// TODO: remove this code when 2.7 is released
4808
// DEBUG - alignmentView
4809
/*
4810
* JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final AlignFrame
4811
* af = this; testAlView.addActionListener(new ActionListener() {
4812
*
4813
* @Override public void actionPerformed(ActionEvent e) {
4814
* jalview.datamodel.AlignmentView
4815
* .testSelectionViews(af.viewport.getAlignment(),
4816
* af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
4817
*
4818
* }); webService.add(testAlView);
4819
*/
4820
// TODO: refactor to RestClient discoverer and merge menu entries for
4821
// rest-style services with other types of analysis/calculation service
4822
// SHmmr test client - still being implemented.
4823
// DEBUG - alignmentView
4824
4825
for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
4826
.getRestClients())
4827
{
4828
client.attachWSMenuEntry(
4829
JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
4830
this);
4831
}
4832
}
4833
4834
/**
4835
* Searches the alignment sequences for xRefs and builds the Show
4836
* Cross-References menu (formerly called Show Products), with database
4837
* sources for which cross-references are found (protein sources for a
4838
* nucleotide alignment and vice versa)
4839
*
4840
* @return true if Show Cross-references menu should be enabled
4841
*/
4842
public boolean canShowProducts()
4843
{
4844
SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
4845
AlignmentI dataset = viewport.getAlignment().getDataset();
4846
4847
showProducts.removeAll();
4848
final boolean dna = viewport.getAlignment().isNucleotide();
4849
4850
if (seqs == null || seqs.length == 0)
4851
{
4852
// nothing to see here.
4853
return false;
4854
}
4855
4856
boolean showp = false;
4857
try
4858
{
4859
List ptypes = new CrossRef(seqs, dataset)
4860
.findXrefSourcesForSequences(dna);
4861
4862
for (final String source : ptypes)
4863
{
4864
showp = true;
4865
final AlignFrame af = this;
4866
JMenuItem xtype = new JMenuItem(source);
4867
xtype.addActionListener(new ActionListener()
4868
{
4869
@Override
4870
public void actionPerformed(ActionEvent e)
4871
{
4872
showProductsFor(af.viewport.getSequenceSelection(), dna,
4873
source);
4874
}
4875
});
4876
showProducts.add(xtype);
4877
}
4878
showProducts.setVisible(showp);
4879
showProducts.setEnabled(showp);
4880
} catch (Exception e)
4881
{
4882
Console.warn(
4883
"canShowProducts threw an exception - please report to help@jalview.org",
4884
e);
4885
return false;
4886
}
4887
return showp;
4888
}
4889
4890
/**
4891
* Finds and displays cross-references for the selected sequences (protein
4892
* products for nucleotide sequences, dna coding sequences for peptides).
4893
*
4894
* @param sel
4895
* the sequences to show cross-references for
4896
* @param dna
4897
* true if from a nucleotide alignment (so showing proteins)
4898
* @param source
4899
* the database to show cross-references for
4900
*/
4901
protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
4902
final String source)
4903
{
4904
new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
4905
.start();
4906
}
4907
4908
/**
4909
* Construct and display a new frame containing the translation of this
4910
* frame's DNA sequences to their aligned protein (amino acid) equivalents.
4911
*/
4912
@Override
4913
public void showTranslation_actionPerformed(GeneticCodeI codeTable)
4914
{
4915
AlignmentI al = null;
4916
try
4917
{
4918
Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
4919
4920
al = dna.translateCdna(codeTable);
4921
} catch (Exception ex)
4922
{
4923
Console.error("Exception during translation. Please report this !",
4924
ex);
4925
final String msg = MessageManager.getString(
4926
"label.error_when_translating_sequences_submit_bug_report");
4927
final String errorTitle = MessageManager
4928
.getString("label.implementation_error")
4929
+ MessageManager.getString("label.translation_failed");
4930
JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4931
JvOptionPane.ERROR_MESSAGE);
4932
return;
4933
}
4934
if (al == null || al.getHeight() == 0)
4935
{
4936
final String msg = MessageManager.getString(
4937
"label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation");
4938
final String errorTitle = MessageManager
4939
.getString("label.translation_failed");
4940
JvOptionPane.showMessageDialog(Desktop.desktop, msg, errorTitle,
4941
JvOptionPane.WARNING_MESSAGE);
4942
}
4943
else
4944
{
4945
AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
4946
af.setFileFormat(this.currentFileFormat);
4947
final String newTitle = MessageManager
4948
.formatMessage("label.translation_of_params", new Object[]
4949
{ this.getTitle(), codeTable.getId() });
4950
af.setTitle(newTitle);
4951
if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
4952
{
4953
final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
4954
viewport.openSplitFrame(af, new Alignment(seqs));
4955
}
4956
else
4957
{
4958
Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
4959
DEFAULT_HEIGHT);
4960
}
4961
}
4962
}
4963
4964
/**
4965
* Set the file format
4966
*
4967
* @param format
4968
*/
4969
public void setFileFormat(FileFormatI format)
4970
{
4971
this.currentFileFormat = format;
4972
}
4973
4974
/**
4975
* Try to load a features file onto the alignment.
4976
*
4977
* @param file
4978
* contents or path to retrieve file or a File object
4979
* @param sourceType
4980
* access mode of file (see jalview.io.AlignFile)
4981
* @return true if features file was parsed correctly.
4982
*/
4983
public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
4984
{
4985
// BH 2018
4986
return avc.parseFeaturesFile(file, sourceType,
4987
Cache.getDefault("RELAXEDSEQIDMATCHING", false));
4988
4989
}
4990
4991
@Override
4992
public void refreshFeatureUI(boolean enableIfNecessary)
4993
{
4994
// note - currently this is only still here rather than in the controller
4995
// because of the featureSettings hard reference that is yet to be
4996
// abstracted
4997
if (enableIfNecessary)
4998
{
4999
viewport.setShowSequenceFeatures(true);
5000
showSeqFeatures.setSelected(true);
5001
}
5002
5003
}
5004
5005
@Override
5006
public void dragEnter(DropTargetDragEvent evt)
5007
{
5008
}
5009
5010
@Override
5011
public void dragExit(DropTargetEvent evt)
5012
{
5013
}
5014
5015
@Override
5016
public void dragOver(DropTargetDragEvent evt)
5017
{
5018
}
5019
5020
@Override
5021
public void dropActionChanged(DropTargetDragEvent evt)
5022
{
5023
}
5024
5025
@Override
5026
public void drop(DropTargetDropEvent evt)
5027
{
5028
// JAL-1552 - acceptDrop required before getTransferable call for
5029
// Java's Transferable for native dnd
5030
evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
5031
Transferable t = evt.getTransferable();
5032
5033
final AlignFrame thisaf = this;
5034
final List files = new ArrayList<>();
5035
List protocols = new ArrayList<>();
5036
5037
try
5038
{
5039
Desktop.transferFromDropTarget(files, protocols, evt, t);
5040
} catch (Exception e)
5041
{
5042
e.printStackTrace();
5043
}
5044
if (files != null)
5045
{
5046
new Thread(new Runnable()
5047
{
5048
@Override
5049
public void run()
5050
{
5051
try
5052
{
5053
// check to see if any of these files have names matching sequences
5054
// in
5055
// the alignment
5056
SequenceIdMatcher idm = new SequenceIdMatcher(
5057
viewport.getAlignment().getSequencesArray());
5058
/**
5059
* Object[] { String,SequenceI}
5060
*/
5061
ArrayList filesmatched = new ArrayList<>();
5062
ArrayList filesnotmatched = new ArrayList<>();
5063
for (int i = 0; i < files.size(); i++)
5064
{
5065
// BH 2018
5066
Object file = files.get(i);
5067
String fileName = file.toString();
5068
String pdbfn = "";
5069
DataSourceType protocol = (file instanceof File
5070
? DataSourceType.FILE
5071
: FormatAdapter.checkProtocol(fileName));
5072
if (protocol == DataSourceType.FILE)
5073
{
5074
File fl;
5075
if (file instanceof File)
5076
{
5077
fl = (File) file;
5078
Platform.cacheFileData(fl);
5079
}
5080
else
5081
{
5082
fl = new File(fileName);
5083
}
5084
pdbfn = fl.getName();
5085
}
5086
else if (protocol == DataSourceType.URL)
5087
{
5088
URL url = new URL(fileName);
5089
pdbfn = url.getFile();
5090
}
5091
if (pdbfn.length() > 0)
5092
{
5093
// attempt to find a match in the alignment
5094
SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
5095
int l = 0, c = pdbfn.indexOf(".");
5096
while (mtch == null && c != -1)
5097
{
5098
do
5099
{
5100
l = c;
5101
} while ((c = pdbfn.indexOf(".", l)) > l);
5102
if (l > -1)
5103
{
5104
pdbfn = pdbfn.substring(0, l);
5105
}
5106
mtch = idm.findAllIdMatches(pdbfn);
5107
}
5108
FileFormatI type = null;
5109
if (mtch != null)
5110
{
5111
try
5112
{
5113
type = new IdentifyFile().identify(file, protocol);
5114
} catch (Exception ex)
5115
{
5116
type = null;
5117
}
5118
if (type != null && type.isStructureFile())
5119
{
5120
filesmatched.add(new Object[] { file, protocol, mtch });
5121
continue;
5122
}
5123
}
5124
// File wasn't named like one of the sequences or wasn't a PDB
5125
// file.
5126
filesnotmatched.add(new Object[] { file, protocol, type });
5127
}
5128
}
5129
int assocfiles = 0;
5130
if (filesmatched.size() > 0)
5131
{
5132
boolean autoAssociate = Cache
5133
.getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
5134
if (!autoAssociate)
5135
{
5136
String msg = MessageManager.formatMessage(
5137
"label.automatically_associate_structure_files_with_sequences_same_name",
5138
new Object[]
5139
{ Integer.valueOf(filesmatched.size())
5140
.toString() });
5141
String ttl = MessageManager.getString(
5142
"label.automatically_associate_structure_files_by_name");
5143
int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
5144
ttl, JvOptionPane.YES_NO_OPTION);
5145
autoAssociate = choice == JvOptionPane.YES_OPTION;
5146
}
5147
if (autoAssociate)
5148
{
5149
for (Object[] fm : filesmatched)
5150
{
5151
// try and associate
5152
// TODO: may want to set a standard ID naming formalism for
5153
// associating PDB files which have no IDs.
5154
for (SequenceI toassoc : (SequenceI[]) fm[2])
5155
{
5156
PDBEntry pe = new AssociatePdbFileWithSeq()
5157
.associatePdbWithSeq(fm[0].toString(),
5158
(DataSourceType) fm[1], toassoc, false,
5159
Desktop.instance);
5160
if (pe != null)
5161
{
5162
jalview.bin.Console.errPrintln("Associated file : "
5163
+ (fm[0].toString()) + " with "
5164
+ toassoc.getDisplayId(true));
5165
assocfiles++;
5166
}
5167
}
5168
// TODO: do we need to update overview ? only if features are
5169
// shown I guess
5170
alignPanel.paintAlignment(true, false);
5171
}
5172
}
5173
else
5174
{
5175
/*
5176
* add declined structures as sequences
5177
*/
5178
for (Object[] o : filesmatched)
5179
{
5180
filesnotmatched.add(new Object[] { o[0], o[1] });
5181
}
5182
}
5183
}
5184
if (filesnotmatched.size() > 0)
5185
{
5186
if (assocfiles > 0 && (Cache.getDefault(
5187
"AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false)
5188
|| JvOptionPane.showConfirmDialog(thisaf,
5189
"" + MessageManager.formatMessage(
5190
"label.ignore_unmatched_dropped_files_info",
5191
new Object[]
5192
{ Integer.valueOf(
5193
filesnotmatched.size())
5194
.toString() })
5195
+ "",
5196
MessageManager.getString(
5197
"label.ignore_unmatched_dropped_files"),
5198
JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION))
5199
{
5200
return;
5201
}
5202
for (Object[] fn : filesnotmatched)
5203
{
5204
loadJalviewDataFile(fn[0], (DataSourceType) fn[1],
5205
(FileFormatI) fn[2], null);
5206
}
5207
5208
}
5209
} catch (Exception ex)
5210
{
5211
ex.printStackTrace();
5212
}
5213
}
5214
}).start();
5215
}
5216
}
5217
5218
/**
5219
* Attempt to load a "dropped" file or URL string, by testing in turn for
5220
*
5221
* an Annotation file
5222
* a JNet file
5223
* a features file
5224
* else try to interpret as an alignment file
5225
*
5226
*
5227
* @param file
5228
* either a filename or a URL string.
5229
*/
5230
public void loadJalviewDataFile(Object file, DataSourceType sourceType,
5231
FileFormatI format, SequenceI assocSeq)
5232
{
5233
// BH 2018 was String file
5234
try
5235
{
5236
if (sourceType == null)
5237
{
5238
sourceType = FormatAdapter.checkProtocol(file);
5239
}
5240
// if the file isn't identified, or not positively identified as some
5241
// other filetype (PFAM is default unidentified alignment file type) then
5242
// try to parse as annotation.
5243
boolean isAnnotation = (format == null
5244
|| FileFormat.Pfam.equals(format))
5245
? new AnnotationFile().annotateAlignmentView(viewport,
5246
file, sourceType)
5247
: false;
5248
// The 'true' flag checks for annotations
5249
isAnnotation |= new IdentifyFile().identify(file, sourceType,
5250
true) == FileFormat.JalviewAnnotation;
5251
;
5252
5253
if (!isAnnotation)
5254
{
5255
// first see if its a T-COFFEE score file
5256
TCoffeeScoreFile tcf = null;
5257
try
5258
{
5259
tcf = new TCoffeeScoreFile(file, sourceType);
5260
if (tcf.isValid())
5261
{
5262
if (tcf.annotateAlignment(viewport.getAlignment(), true))
5263
{
5264
buildColourMenu();
5265
changeColour(
5266
new TCoffeeColourScheme(viewport.getAlignment()));
5267
isAnnotation = true;
5268
setStatus(MessageManager.getString(
5269
"label.successfully_pasted_tcoffee_scores_to_alignment"));
5270
}
5271
else
5272
{
5273
// some problem - if no warning its probable that the ID matching
5274
// process didn't work
5275
JvOptionPane.showMessageDialog(Desktop.desktop,
5276
tcf.getWarningMessage() == null
5277
? MessageManager.getString(
5278
"label.check_file_matches_sequence_ids_alignment")
5279
: tcf.getWarningMessage(),
5280
MessageManager.getString(
5281
"label.problem_reading_tcoffee_score_file"),
5282
JvOptionPane.WARNING_MESSAGE);
5283
}
5284
}
5285
else
5286
{
5287
tcf = null;
5288
}
5289
} catch (Exception x)
5290
{
5291
Console.debug(
5292
"Exception when processing data source as T-COFFEE score file",
5293
x);
5294
tcf = null;
5295
}
5296
if (tcf == null)
5297
{
5298
// try to see if its a JNet 'concise' style annotation file *before*
5299
// we
5300
// try to parse it as a features file
5301
if (format == null)
5302
{
5303
format = new IdentifyFile().identify(file, sourceType);
5304
}
5305
if (FileFormat.FeatureSettings == format)
5306
{
5307
if (featureSettings != null)
5308
{
5309
featureSettings.load(file, sourceType);
5310
}
5311
else
5312
{
5313
FeatureSettings.loadFeatureSettingsFile(getFeatureRenderer(),
5314
fileObject, sourceType);
5315
}
5316
}
5317
else if (FileFormat.ScoreMatrix == format)
5318
{
5319
ScoreMatrixFile sm = new ScoreMatrixFile(
5320
new FileParse(file, sourceType));
5321
sm.parse();
5322
// todo: i18n this message
5323
setStatus(MessageManager.formatMessage(
5324
"label.successfully_loaded_matrix",
5325
sm.getMatrixName()));
5326
}
5327
else if (FileFormat.Jnet.equals(format))
5328
{
5329
JPredFile predictions = new JPredFile(file, sourceType);
5330
new JnetAnnotationMaker();
5331
JnetAnnotationMaker.add_annotation(predictions,
5332
viewport.getAlignment(), 0, false);
5333
viewport.getAlignment().setupJPredAlignment();
5334
isAnnotation = true;
5335
}
5336
5337
// else if (IdentifyFile.FeaturesFile.equals(format))
5338
else if (FileFormat.Features.equals(format))
5339
{
5340
if (parseFeaturesFile(file, sourceType))
5341
{
5342
SplitFrame splitFrame = (SplitFrame) getSplitViewContainer();
5343
if (splitFrame != null)
5344
{
5345
splitFrame.repaint();
5346
}
5347
else
5348
{
5349
alignPanel.paintAlignment(true, true);
5350
}
5351
}
5352
}
5353
else
5354
{
5355
new FileLoader().LoadFile(viewport, file, sourceType, format);
5356
}
5357
}
5358
}
5359
if (isAnnotation)
5360
{
5361
5362
alignPanel.adjustAnnotationHeight();
5363
viewport.updateSequenceIdColours();
5364
viewport.updateAnnotationColours();
5365
buildSortByAnnotationScoresMenu();
5366
alignPanel.paintAlignment(true, true);
5367
}
5368
} catch (Exception ex)
5369
{
5370
ex.printStackTrace();
5371
} catch (OutOfMemoryError oom)
5372
{
5373
try
5374
{
5375
System.gc();
5376
} catch (Exception x)
5377
{
5378
}
5379
new OOMWarning(
5380
"loading data "
5381
+ (sourceType != null
5382
? (sourceType == DataSourceType.PASTE
5383
? "from clipboard."
5384
: "using " + sourceType + " from "
5385
+ file)
5386
: ".")
5387
+ (format != null
5388
? "(parsing as '" + format + "' file)"
5389
: ""),
5390
oom, Desktop.desktop);
5391
}
5392
}
5393
5394
/**
5395
* Method invoked by the ChangeListener on the tabbed pane, in other words
5396
* when a different tabbed pane is selected by the user or programmatically.
5397
*/
5398
@Override
5399
public void tabSelectionChanged(int index)
5400
{
5401
if (index > -1)
5402
{
5403
/*
5404
* update current Overview window title (if there is one) to add view name
5405
* "Original" if necessary
5406
*/
5407
alignPanel.setOverviewTitle(this);
5408
5409
/*
5410
* switch panels and set Overview title (if there is one because it was opened
5411
* automatically)
5412
*/
5413
alignPanel = alignPanels.get(index);
5414
alignPanel.setOverviewTitle(this);
5415
5416
viewport = alignPanel.av;
5417
avc.setViewportAndAlignmentPanel(viewport, alignPanel);
5418
setMenusFromViewport(viewport);
5419
if (featureSettings != null && featureSettings.isOpen()
5420
&& featureSettings.fr.getViewport() != viewport)
5421
{
5422
if (viewport.isShowSequenceFeatures())
5423
{
5424
// refresh the featureSettings to reflect UI change
5425
showFeatureSettingsUI();
5426
}
5427
else
5428
{
5429
// close feature settings for this view.
5430
featureSettings.close();
5431
}
5432
}
5433
5434
}
5435
5436
/*
5437
* 'focus' any colour slider that is open to the selected viewport
5438
*/
5439
if (viewport.getConservationSelected())
5440
{
5441
SliderPanel.setConservationSlider(alignPanel,
5442
viewport.getResidueShading(), alignPanel.getViewName());
5443
}
5444
else
5445
{
5446
SliderPanel.hideConservationSlider();
5447
}
5448
if (viewport.getByConsensusSecondaryStructureSelected())
5449
{
5450
SliderPanel.setConsensusSecondaryStructureSlider(alignPanel,
5451
viewport.getResidueShading(), alignPanel.getViewName());
5452
}
5453
else
5454
{
5455
SliderPanel.hideConsensusSecondaryStructureSlider();
5456
}
5457
if (viewport.getAbovePIDThreshold())
5458
{
5459
SliderPanel.setPIDSliderSource(alignPanel,
5460
viewport.getResidueShading(), alignPanel.getViewName());
5461
}
5462
else
5463
{
5464
SliderPanel.hidePIDSlider();
5465
}
5466
5467
/*
5468
* If there is a frame linked to this one in a SplitPane, switch it to the same
5469
* view tab index. No infinite recursion of calls should happen, since
5470
* tabSelectionChanged() should not get invoked on setting the selected index to
5471
* an unchanged value. Guard against setting an invalid index before the new
5472
* view peer tab has been created.
5473
*/
5474
final AlignViewportI peer = viewport.getCodingComplement();
5475
if (peer != null)
5476
{
5477
AlignFrame linkedAlignFrame = ((AlignViewport) peer)
5478
.getAlignPanel().alignFrame;
5479
if (linkedAlignFrame.tabbedPane.getTabCount() > index)
5480
{
5481
linkedAlignFrame.tabbedPane.setSelectedIndex(index);
5482
}
5483
}
5484
}
5485
5486
/**
5487
* On right mouse click on view tab, prompt for and set new view name.
5488
*/
5489
@Override
5490
public void tabbedPane_mousePressed(MouseEvent e)
5491
{
5492
if (e.isPopupTrigger())
5493
{
5494
String msg = MessageManager.getString("label.enter_view_name");
5495
String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
5496
String reply = JvOptionPane.showInputDialog(msg, ttl);
5497
5498
if (reply != null)
5499
{
5500
viewport.setViewName(reply);
5501
// TODO warn if reply is in getExistingViewNames()?
5502
tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
5503
}
5504
}
5505
}
5506
5507
public AlignViewport getCurrentView()
5508
{
5509
return viewport;
5510
}
5511
5512
/**
5513
* Open the dialog for regex description parsing.
5514
*/
5515
@Override
5516
protected void extractScores_actionPerformed(ActionEvent e)
5517
{
5518
ParseProperties pp = new jalview.analysis.ParseProperties(
5519
viewport.getAlignment());
5520
// TODO: verify regex and introduce GUI dialog for version 2.5
5521
// if (pp.getScoresFromDescription("col", "score column ",
5522
// "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
5523
// true)>0)
5524
if (pp.getScoresFromDescription("description column",
5525
"score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
5526
{
5527
buildSortByAnnotationScoresMenu();
5528
}
5529
}
5530
5531
/*
5532
* (non-Javadoc)
5533
*
5534
* @see jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.
5535
* ActionEvent )
5536
*/
5537
@Override
5538
protected void showDbRefs_actionPerformed(ActionEvent e)
5539
{
5540
viewport.setShowDBRefs(showDbRefsMenuitem.isSelected());
5541
}
5542
5543
/*
5544
* (non-Javadoc)
5545
*
5546
* @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
5547
* ActionEvent)
5548
*/
5549
@Override
5550
protected void showNpFeats_actionPerformed(ActionEvent e)
5551
{
5552
viewport.setShowNPFeats(showNpFeatsMenuitem.isSelected());
5553
}
5554
5555
/**
5556
* find the viewport amongst the tabs in this alignment frame and close that
5557
* tab
5558
*
5559
* @param av
5560
*/
5561
public boolean closeView(AlignViewportI av)
5562
{
5563
if (viewport == av)
5564
{
5565
this.closeMenuItem_actionPerformed(false);
5566
return true;
5567
}
5568
Component[] comp = tabbedPane.getComponents();
5569
for (int i = 0; comp != null && i < comp.length; i++)
5570
{
5571
if (comp[i] instanceof AlignmentPanel)
5572
{
5573
if (((AlignmentPanel) comp[i]).av == av)
5574
{
5575
// close the view.
5576
closeView((AlignmentPanel) comp[i]);
5577
return true;
5578
}
5579
}
5580
}
5581
return false;
5582
}
5583
5584
protected void build_fetchdbmenu(JMenu webService)
5585
{
5586
// Temporary hack - DBRef Fetcher always top level ws entry.
5587
// TODO We probably want to store a sequence database checklist in
5588
// preferences and have checkboxes.. rather than individual sources selected
5589
// here
5590
final JMenu rfetch = new JMenu(
5591
MessageManager.getString("action.fetch_db_references"));
5592
rfetch.setToolTipText(MessageManager.getString(
5593
"label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));
5594
webService.add(rfetch);
5595
5596
final JCheckBoxMenuItem trimrs = new JCheckBoxMenuItem(
5597
MessageManager.getString("option.trim_retrieved_seqs"));
5598
trimrs.setToolTipText(
5599
MessageManager.getString("label.trim_retrieved_sequences"));
5600
trimrs.setSelected(
5601
Cache.getDefault(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, true));
5602
trimrs.addActionListener(new ActionListener()
5603
{
5604
@Override
5605
public void actionPerformed(ActionEvent e)
5606
{
5607
trimrs.setSelected(trimrs.isSelected());
5608
Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES,
5609
Boolean.valueOf(trimrs.isSelected()).toString());
5610
}
5611
});
5612
rfetch.add(trimrs);
5613
JMenuItem fetchr = new JMenuItem(
5614
MessageManager.getString("label.standard_databases"));
5615
fetchr.setToolTipText(
5616
MessageManager.getString("label.fetch_embl_uniprot"));
5617
fetchr.addActionListener(new ActionListener()
5618
{
5619
5620
@Override
5621
public void actionPerformed(ActionEvent e)
5622
{
5623
new Thread(new Runnable()
5624
{
5625
@Override
5626
public void run()
5627
{
5628
boolean isNucleotide = alignPanel.alignFrame.getViewport()
5629
.getAlignment().isNucleotide();
5630
DBRefFetcher dbRefFetcher = new DBRefFetcher(
5631
alignPanel.av.getSequenceSelection(),
5632
alignPanel.alignFrame, null,
5633
alignPanel.alignFrame.featureSettings, isNucleotide);
5634
dbRefFetcher.addListener(new FetchFinishedListenerI()
5635
{
5636
@Override
5637
public void finished()
5638
{
5639
5640
for (FeatureSettingsModelI srcSettings : dbRefFetcher
5641
.getFeatureSettingsModels())
5642
{
5643
5644
alignPanel.av.mergeFeaturesStyle(srcSettings);
5645
}
5646
AlignFrame.this.setMenusForViewport();
5647
}
5648
});
5649
dbRefFetcher.fetchDBRefs(false);
5650
}
5651
}).start();
5652
5653
}
5654
5655
});
5656
rfetch.add(fetchr);
5657
new Thread(new Runnable()
5658
{
5659
@Override
5660
public void run()
5661
{
5662
final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher
5663
.getSequenceFetcherSingleton();
5664
javax.swing.SwingUtilities.invokeLater(new Runnable()
5665
{
5666
@Override
5667
public void run()
5668
{
5669
String[] dbclasses = sf.getNonAlignmentSources();
5670
List otherdb;
5671
JMenu dfetch = new JMenu();
5672
JMenu ifetch = new JMenu();
5673
JMenuItem fetchr = null;
5674
int comp = 0, icomp = 0, mcomp = 15;
5675
String mname = null;
5676
int dbi = 0;
5677
for (String dbclass : dbclasses)
5678
{
5679
otherdb = sf.getSourceProxy(dbclass);
5680
// add a single entry for this class, or submenu allowing 'fetch
5681
// all' or pick one
5682
if (otherdb == null || otherdb.size() < 1)
5683
{
5684
continue;
5685
}
5686
if (mname == null)
5687
{
5688
mname = "From " + dbclass;
5689
}
5690
if (otherdb.size() == 1)
5691
{
5692
final DbSourceProxy[] dassource = otherdb
5693
.toArray(new DbSourceProxy[0]);
5694
DbSourceProxy src = otherdb.get(0);
5695
fetchr = new JMenuItem(src.getDbSource());
5696
fetchr.addActionListener(new ActionListener()
5697
{
5698
5699
@Override
5700
public void actionPerformed(ActionEvent e)
5701
{
5702
new Thread(new Runnable()
5703
{
5704
5705
@Override
5706
public void run()
5707
{
5708
boolean isNucleotide = alignPanel.alignFrame
5709
.getViewport().getAlignment()
5710
.isNucleotide();
5711
DBRefFetcher dbRefFetcher = new DBRefFetcher(
5712
alignPanel.av.getSequenceSelection(),
5713
alignPanel.alignFrame, dassource,
5714
alignPanel.alignFrame.featureSettings,
5715
isNucleotide);
5716
dbRefFetcher
5717
.addListener(new FetchFinishedListenerI()
5718
{
5719
@Override
5720
public void finished()
5721
{
5722
FeatureSettingsModelI srcSettings = dassource[0]
5723
.getFeatureColourScheme();
5724
alignPanel.av.mergeFeaturesStyle(
5725
srcSettings);
5726
AlignFrame.this.setMenusForViewport();
5727
}
5728
});
5729
dbRefFetcher.fetchDBRefs(false);
5730
}
5731
}).start();
5732
}
5733
5734
});
5735
fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5736
MessageManager.formatMessage(
5737
"label.fetch_retrieve_from", new Object[]
5738
{ src.getDbName() })));
5739
dfetch.add(fetchr);
5740
comp++;
5741
}
5742
else
5743
{
5744
final DbSourceProxy[] dassource = otherdb
5745
.toArray(new DbSourceProxy[0]);
5746
// fetch all entry
5747
DbSourceProxy src = otherdb.get(0);
5748
fetchr = new JMenuItem(MessageManager
5749
.formatMessage("label.fetch_all_param", new Object[]
5750
{ src.getDbSource() }));
5751
fetchr.addActionListener(new ActionListener()
5752
{
5753
@Override
5754
public void actionPerformed(ActionEvent e)
5755
{
5756
new Thread(new Runnable()
5757
{
5758
5759
@Override
5760
public void run()
5761
{
5762
boolean isNucleotide = alignPanel.alignFrame
5763
.getViewport().getAlignment()
5764
.isNucleotide();
5765
DBRefFetcher dbRefFetcher = new DBRefFetcher(
5766
alignPanel.av.getSequenceSelection(),
5767
alignPanel.alignFrame, dassource,
5768
alignPanel.alignFrame.featureSettings,
5769
isNucleotide);
5770
dbRefFetcher
5771
.addListener(new FetchFinishedListenerI()
5772
{
5773
@Override
5774
public void finished()
5775
{
5776
AlignFrame.this.setMenusForViewport();
5777
}
5778
});
5779
dbRefFetcher.fetchDBRefs(false);
5780
}
5781
}).start();
5782
}
5783
});
5784
5785
fetchr.setToolTipText(JvSwingUtils.wrapTooltip(true,
5786
MessageManager.formatMessage(
5787
"label.fetch_retrieve_from_all_sources",
5788
new Object[]
5789
{ Integer.valueOf(otherdb.size())
5790
.toString(),
5791
src.getDbSource(), src.getDbName() })));
5792
dfetch.add(fetchr);
5793
comp++;
5794
// and then build the rest of the individual menus
5795
ifetch = new JMenu(MessageManager.formatMessage(
5796
"label.source_from_db_source", new Object[]
5797
{ src.getDbSource() }));
5798
icomp = 0;
5799
String imname = null;
5800
int i = 0;
5801
for (DbSourceProxy sproxy : otherdb)
5802
{
5803
String dbname = sproxy.getDbName();
5804
String sname = dbname.length() > 5
5805
? dbname.substring(0, 5) + "..."
5806
: dbname;
5807
String msname = dbname.length() > 10
5808
? dbname.substring(0, 10) + "..."
5809
: dbname;
5810
if (imname == null)
5811
{
5812
imname = MessageManager
5813
.formatMessage("label.from_msname", new Object[]
5814
{ sname });
5815
}
5816
fetchr = new JMenuItem(msname);
5817
final DbSourceProxy[] dassrc = { sproxy };
5818
fetchr.addActionListener(new ActionListener()
5819
{
5820
5821
@Override
5822
public void actionPerformed(ActionEvent e)
5823
{
5824
new Thread(new Runnable()
5825
{
5826
5827
@Override
5828
public void run()
5829
{
5830
boolean isNucleotide = alignPanel.alignFrame
5831
.getViewport().getAlignment()
5832
.isNucleotide();
5833
DBRefFetcher dbRefFetcher = new DBRefFetcher(
5834
alignPanel.av.getSequenceSelection(),
5835
alignPanel.alignFrame, dassrc,
5836
alignPanel.alignFrame.featureSettings,
5837
isNucleotide);
5838
dbRefFetcher
5839
.addListener(new FetchFinishedListenerI()
5840
{
5841
@Override
5842
public void finished()
5843
{
5844
AlignFrame.this.setMenusForViewport();
5845
}
5846
});
5847
dbRefFetcher.fetchDBRefs(false);
5848
}
5849
}).start();
5850
}
5851
5852
});
5853
fetchr.setToolTipText(
5854
"" + MessageManager.formatMessage(
5855
"label.fetch_retrieve_from", new Object[]
5856
{ dbname }));
5857
ifetch.add(fetchr);
5858
++i;
5859
if (++icomp >= mcomp || i == (otherdb.size()))
5860
{
5861
ifetch.setText(MessageManager.formatMessage(
5862
"label.source_to_target", imname, sname));
5863
dfetch.add(ifetch);
5864
ifetch = new JMenu();
5865
imname = null;
5866
icomp = 0;
5867
comp++;
5868
}
5869
}
5870
}
5871
++dbi;
5872
if (comp >= mcomp || dbi >= (dbclasses.length))
5873
{
5874
dfetch.setText(MessageManager.formatMessage(
5875
"label.source_to_target", mname, dbclass));
5876
rfetch.add(dfetch);
5877
dfetch = new JMenu();
5878
mname = null;
5879
comp = 0;
5880
}
5881
}
5882
}
5883
5884
});
5885
}
5886
}).start();
5887
5888
}
5889
5890
/**
5891
* Left justify the whole alignment.
5892
*/
5893
@Override
5894
protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
5895
{
5896
avc.justify_Region(true);
5897
}
5898
5899
/**
5900
* Right justify the whole alignment.
5901
*/
5902
@Override
5903
protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
5904
{
5905
avc.justify_Region(false);
5906
}
5907
5908
@Override
5909
public void setShowSeqFeatures(boolean b)
5910
{
5911
showSeqFeatures.setSelected(b);
5912
viewport.setShowSequenceFeatures(b);
5913
}
5914
5915
/*
5916
* (non-Javadoc)
5917
*
5918
* @see jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
5919
* awt.event.ActionEvent)
5920
*/
5921
@Override
5922
protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
5923
{
5924
viewport.setShowUnconserved(showNonconservedMenuItem.getState());
5925
alignPanel.paintAlignment(false, false);
5926
}
5927
5928
@Override
5929
protected void showStructureProvider_actionPerformed(ActionEvent e)
5930
{
5931
viewport.setShowStructureProvider(showStrucProvider.getState());
5932
alignPanel.paintAlignment(false, false);
5933
5934
}
5935
5936
@Override
5937
protected void updateShowSecondaryStructureMenu(JMenu showSS,
5938
ButtonGroup ssButtonGroup)
5939
{
5940
5941
List ssSources = new ArrayList();
5942
AlignmentAnnotation[] anns = alignPanel.getAlignment()
5943
.getAlignmentAnnotation();
5944
Map checkboxMap = getCheckboxesInMenu(
5945
showSS);
5946
5947
ssSources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(anns);
5948
5949
if (ssSources == null)
5950
{
5951
showSS.removeAll();
5952
ssButtonGroup.clearSelection();
5953
return;
5954
}
5955
5956
List selectedCheckBoxes = getSelectedOptions(checkboxMap);
5957
5958
// Add checkboxes for categories
5959
for (String ssSource : ssSources)
5960
{
5961
5962
if (checkboxMap.get(ssSource) == null)
5963
{
5964
JCheckBoxMenuItem checkBox = new JCheckBoxMenuItem(ssSource);
5965
checkBox.setSelected(false);
5966
5967
checkBox.addItemListener(e -> {
5968
if (e.getStateChange() == ItemEvent.SELECTED)
5969
{
5970
5971
showOrHideSecondaryStructureForSource(ssSource, true);
5972
5973
}
5974
else
5975
{
5976
5977
showOrHideSecondaryStructureForSource(ssSource, false);
5978
5979
}
5980
});
5981
showSS.add(checkBox);
5982
}
5983
}
5984
// Iterate over the keys of checkboxMap
5985
for (String key : checkboxMap.keySet())
5986
{
5987
// Check if the key is not in ssSources
5988
if (!ssSources.contains(key))
5989
{
5990
showSS.remove(checkboxMap.get(key));
5991
checkboxMap.remove(key);
5992
selectedCheckBoxes.remove(key);
5993
}
5994
if (selectedCheckBoxes.contains(key))
5995
{
5996
checkboxMap.get(key).setSelected(true);
5997
}
5998
else
5999
{
6000
checkboxMap.get(key).setSelected(false);
6001
}
6002
6003
ssButtonGroup.clearSelection();
6004
}
6005
6006
}
6007
6008
private List getSelectedOptions(
6009
Map checkboxMap)
6010
{
6011
List selectedOptions = new ArrayList<>();
6012
for (String key : checkboxMap.keySet())
6013
{
6014
JCheckBoxMenuItem checkbox = checkboxMap.get(key);
6015
if (checkbox.isSelected())
6016
{
6017
selectedOptions.add(key);
6018
}
6019
}
6020
return selectedOptions;
6021
}
6022
6023
private Map getCheckboxesInMenu(JMenu menu)
6024
{
6025
Map checkboxMap = new HashMap<>();
6026
for (Component component : menu.getMenuComponents())
6027
{
6028
if (component instanceof JCheckBoxMenuItem)
6029
{
6030
JCheckBoxMenuItem checkbox = (JCheckBoxMenuItem) component;
6031
checkboxMap.put(checkbox.getText(), checkbox);
6032
}
6033
}
6034
return checkboxMap;
6035
}
6036
6037
@Override
6038
protected void showOrHideSecondaryStructureForSource(
6039
String ssSourceSelection, boolean visible)
6040
{
6041
6042
String _noneOption = MessageManager
6043
.getString("option.ss_providers_none");
6044
boolean nonOption = ssSourceSelection!=null && ssSourceSelection.equals(_noneOption);
6045
String allOption = MessageManager.getString("option.ss_providers_all");
6046
6047
AlignmentAnnotation[] annotations = alignPanel.getAlignment()
6048
.getAlignmentAnnotation();
6049
6050
for (AlignmentAnnotation aa : annotations)
6051
{
6052
6053
if (aa.groupRef != null)
6054
{
6055
continue;
6056
}
6057
6058
boolean isSSConsensus = aa.label.startsWith(
6059
MessageManager.getString("label.ssconsensus_label"));
6060
boolean matchesSSSourceSelection = aa.description
6061
.startsWith(ssSourceSelection);
6062
6063
if (isSSConsensus && (matchesSSSourceSelection
6064
|| nonOption))
6065
{
6066
6067
if (ssSourceSelection.equals(allOption))
6068
{
6069
aa.visible = true;
6070
break;
6071
}
6072
6073
if (!aa.description.startsWith(allOption))
6074
aa.visible = visible;
6075
6076
}
6077
6078
for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet())
6079
{
6080
6081
if (label.equals(aa.label))
6082
{
6083
6084
String ssSource = AlignmentAnnotationUtils
6085
.extractSSSourceFromAnnotationDescription(aa);
6086
6087
if (nonOption || ssSource != null && (ssSource.equals(ssSourceSelection)))
6088
{
6089
aa.visible = visible;
6090
}
6091
}
6092
}
6093
6094
}
6095
6096
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
6097
alignPanel.updateAnnotation();
6098
alignPanel.paintAlignment(true, true);
6099
6100
}
6101
6102
@Override
6103
protected void showSSConsensus_actionPerformed(ActionEvent e)
6104
{
6105
viewport.setShowSSConsensus(showSSConsensus.getState());
6106
alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
6107
}
6108
6109
/*
6110
* (non-Javadoc)
6111
*
6112
* @see
6113
* jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
6114
* .ActionEvent)
6115
*/
6116
@Override
6117
protected void showGroupConsensus_actionPerformed(ActionEvent e)
6118
{
6119
viewport.setShowGroupConsensus(showGroupConsensus.getState());
6120
alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
6121
6122
}
6123
6124
@Override
6125
protected void showGroupSSConsensus_actionPerformed(ActionEvent e)
6126
{
6127
viewport.setShowGroupSSConsensus(showGroupSSConsensus.getState());
6128
alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
6129
6130
}
6131
6132
/*
6133
* (non-Javadoc)
6134
*
6135
* @see jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
6136
* .event.ActionEvent)
6137
*/
6138
@Override
6139
protected void showGroupConservation_actionPerformed(ActionEvent e)
6140
{
6141
viewport.setShowGroupConservation(showGroupConservation.getState());
6142
alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
6143
}
6144
6145
/*
6146
* (non-Javadoc)
6147
*
6148
* @see
6149
* jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
6150
* .event.ActionEvent)
6151
*/
6152
@Override
6153
protected void showConsensusHistogram_actionPerformed(ActionEvent e)
6154
{
6155
viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
6156
alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
6157
}
6158
6159
/*
6160
* (non-Javadoc)
6161
*
6162
* @see jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
6163
* .event.ActionEvent)
6164
*/
6165
@Override
6166
protected void showSequenceLogo_actionPerformed(ActionEvent e)
6167
{
6168
viewport.setShowSequenceLogo(showSequenceLogo.getState());
6169
alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
6170
}
6171
6172
@Override
6173
protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
6174
{
6175
showSequenceLogo.setState(true);
6176
viewport.setShowSequenceLogo(true);
6177
viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
6178
alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
6179
}
6180
6181
@Override
6182
protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
6183
{
6184
alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
6185
}
6186
6187
/*
6188
* (non-Javadoc)
6189
*
6190
* @see jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
6191
* .event.ActionEvent)
6192
*/
6193
@Override
6194
protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
6195
{
6196
if (avc.makeGroupsFromSelection())
6197
{
6198
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
6199
alignPanel.updateAnnotation();
6200
alignPanel.paintAlignment(true,
6201
viewport.needToUpdateStructureViews());
6202
}
6203
}
6204
6205
public void clearAlignmentSeqRep()
6206
{
6207
// TODO refactor alignmentseqrep to controller
6208
if (viewport.getAlignment().hasSeqrep())
6209
{
6210
viewport.getAlignment().setSeqrep(null);
6211
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
6212
alignPanel.updateAnnotation();
6213
alignPanel.paintAlignment(true, true);
6214
}
6215
}
6216
6217
@Override
6218
protected void createGroup_actionPerformed(ActionEvent e)
6219
{
6220
if (avc.createGroup())
6221
{
6222
if (applyAutoAnnotationSettings.isSelected())
6223
{
6224
alignPanel.updateAnnotation(true, false);
6225
}
6226
alignPanel.alignmentChanged();
6227
}
6228
}
6229
6230
@Override
6231
protected void unGroup_actionPerformed(ActionEvent e)
6232
{
6233
if (avc.unGroup())
6234
{
6235
alignPanel.alignmentChanged();
6236
}
6237
}
6238
6239
/**
6240
* make the given alignmentPanel the currently selected tab
6241
*
6242
* @param alignmentPanel
6243
*/
6244
public void setDisplayedView(AlignmentPanel alignmentPanel)
6245
{
6246
if (!viewport.getSequenceSetId()
6247
.equals(alignmentPanel.av.getSequenceSetId()))
6248
{
6249
throw new Error(MessageManager.getString(
6250
"error.implementation_error_cannot_show_view_alignment_frame"));
6251
}
6252
if (tabbedPane != null && tabbedPane.getTabCount() > 0 && alignPanels
6253
.indexOf(alignmentPanel) != tabbedPane.getSelectedIndex())
6254
{
6255
tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
6256
}
6257
}
6258
6259
/**
6260
* Action on selection of menu options to Show or Hide annotations.
6261
*
6262
* @param visible
6263
* @param forSequences
6264
* update sequence-related annotations
6265
* @param forAlignment
6266
* update non-sequence-related annotations
6267
*/
6268
@Override
6269
public void setAnnotationsVisibility(boolean visible,
6270
boolean forSequences, boolean forAlignment)
6271
{
6272
AlignmentAnnotation[] anns = alignPanel.getAlignment()
6273
.getAlignmentAnnotation();
6274
if (anns == null)
6275
{
6276
return;
6277
}
6278
for (AlignmentAnnotation aa : anns)
6279
{
6280
/*
6281
* don't display non-positional annotations on an alignment
6282
*/
6283
if (aa.annotations == null)
6284
{
6285
continue;
6286
}
6287
boolean apply = (aa.sequenceRef == null && forAlignment)
6288
|| (aa.sequenceRef != null && forSequences);
6289
if (apply)
6290
{
6291
aa.visible = visible;
6292
}
6293
}
6294
alignPanel.validateAnnotationDimensions(true);
6295
// TODO this triggers relayout of annotation panel - otherwise annotation
6296
// label height is different to panel height
6297
alignPanel.fontChanged();
6298
alignPanel.alignmentChanged();
6299
}
6300
6301
/**
6302
* Store selected annotation sort order for the view and repaint.
6303
*/
6304
@Override
6305
protected void sortAnnotations_actionPerformed()
6306
{
6307
this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
6308
this.alignPanel.av
6309
.setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
6310
alignPanel.paintAlignment(false, false);
6311
}
6312
6313
/**
6314
*
6315
* @return alignment panels in this alignment frame
6316
*/
6317
public List extends AlignmentViewPanel> getAlignPanels()
6318
{
6319
// alignPanels is never null
6320
// return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
6321
return alignPanels;
6322
}
6323
6324
/**
6325
* Open a new alignment window, with the cDNA associated with this (protein)
6326
* alignment, aligned as is the protein.
6327
*/
6328
protected void viewAsCdna_actionPerformed()
6329
{
6330
// TODO no longer a menu action - refactor as required
6331
final AlignmentI alignment = getViewport().getAlignment();
6332
List mappings = alignment.getCodonFrames();
6333
if (mappings == null)
6334
{
6335
return;
6336
}
6337
List cdnaSeqs = new ArrayList<>();
6338
for (SequenceI aaSeq : alignment.getSequences())
6339
{
6340
for (AlignedCodonFrame acf : mappings)
6341
{
6342
SequenceI dnaSeq = acf.getDnaForAaSeq(aaSeq.getDatasetSequence());
6343
if (dnaSeq != null)
6344
{
6345
/*
6346
* There is a cDNA mapping for this protein sequence - add to new alignment. It
6347
* will share the same dataset sequence as other mapped cDNA (no new mappings
6348
* need to be created).
6349
*/
6350
final Sequence newSeq = new Sequence(dnaSeq);
6351
newSeq.setDatasetSequence(dnaSeq);
6352
cdnaSeqs.add(newSeq);
6353
}
6354
}
6355
}
6356
if (cdnaSeqs.size() == 0)
6357
{
6358
// show a warning dialog no mapped cDNA
6359
return;
6360
}
6361
AlignmentI cdna = new Alignment(
6362
cdnaSeqs.toArray(new SequenceI[cdnaSeqs.size()]));
6363
GAlignFrame alignFrame = new AlignFrame(cdna, AlignFrame.DEFAULT_WIDTH,
6364
AlignFrame.DEFAULT_HEIGHT);
6365
cdna.alignAs(alignment);
6366
String newtitle = "cDNA " + MessageManager.getString("label.for") + " "
6367
+ this.title;
6368
Desktop.addInternalFrame(alignFrame, newtitle, AlignFrame.DEFAULT_WIDTH,
6369
AlignFrame.DEFAULT_HEIGHT);
6370
}
6371
6372
/**
6373
* Set visibility of dna/protein complement view (available when shown in a
6374
* split frame).
6375
*
6376
* @param show
6377
*/
6378
@Override
6379
protected void showComplement_actionPerformed(boolean show)
6380
{
6381
SplitContainerI sf = getSplitViewContainer();
6382
if (sf != null)
6383
{
6384
sf.setComplementVisible(this, show);
6385
}
6386
}
6387
6388
/**
6389
* Generate the reverse (optionally complemented) of the selected sequences,
6390
* and add them to the alignment
6391
*/
6392
@Override
6393
protected void showReverse_actionPerformed(boolean complement)
6394
{
6395
AlignmentI al = null;
6396
try
6397
{
6398
Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
6399
al = dna.reverseCdna(complement);
6400
viewport.addAlignment(al, "");
6401
addHistoryItem(new EditCommand(
6402
MessageManager.getString("label.add_sequences"), Action.PASTE,
6403
al.getSequencesArray(), 0, al.getWidth(),
6404
viewport.getAlignment()));
6405
} catch (Exception ex)
6406
{
6407
jalview.bin.Console.errPrintln(ex.getMessage());
6408
return;
6409
}
6410
}
6411
6412
/**
6413
* Try to run a script in the Groovy console, having first ensured that this
6414
* AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
6415
* be targeted at this alignment.
6416
*/
6417
@Override
6418
protected void runGroovy_actionPerformed()
6419
{
6420
Jalview.getInstance().setCurrentAlignFrame(this);
6421
groovy.console.ui.Console console = Desktop.getGroovyConsole();
6422
if (console != null)
6423
{
6424
try
6425
{
6426
console.setVariable(JalviewObjectI.currentAlFrameName, this);
6427
console.runScript();
6428
} catch (Exception ex)
6429
{
6430
jalview.bin.Console.errPrintln((ex.toString()));
6431
JvOptionPane.showInternalMessageDialog(Desktop.desktop,
6432
MessageManager.getString("label.couldnt_run_groovy_script"),
6433
MessageManager.getString("label.groovy_support_failed"),
6434
JvOptionPane.ERROR_MESSAGE);
6435
}
6436
}
6437
else
6438
{
6439
jalview.bin.Console
6440
.errPrintln("Can't run Groovy script as console not found");
6441
}
6442
}
6443
6444
/**
6445
* Hides columns containing (or not containing) a specified feature, provided
6446
* that would not leave all columns hidden
6447
*
6448
* @param featureType
6449
* @param columnsContaining
6450
* @return
6451
*/
6452
public boolean hideFeatureColumns(String featureType,
6453
boolean columnsContaining)
6454
{
6455
boolean notForHiding = avc.markColumnsContainingFeatures(
6456
columnsContaining, false, false, featureType);
6457
if (notForHiding)
6458
{
6459
if (avc.markColumnsContainingFeatures(!columnsContaining, false,
6460
false, featureType))
6461
{
6462
getViewport().hideSelectedColumns();
6463
return true;
6464
}
6465
}
6466
return false;
6467
}
6468
6469
@Override
6470
protected void selectHighlightedColumns_actionPerformed(
6471
ActionEvent actionEvent)
6472
{
6473
// include key modifier check in case user selects from menu
6474
avc.markHighlightedColumns(
6475
(actionEvent.getModifiers() & ActionEvent.ALT_MASK) != 0, true,
6476
(actionEvent.getModifiers() & (ActionEvent.META_MASK
6477
| ActionEvent.CTRL_MASK)) != 0);
6478
}
6479
6480
@Override
6481
protected void copyHighlightedColumns_actionPerformed(
6482
ActionEvent actionEvent)
6483
{
6484
avc.copyHighlightedRegionsToClipboard();
6485
}
6486
6487
/**
6488
* Rebuilds the Colour menu, including any user-defined colours which have
6489
* been loaded either on startup or during the session
6490
*/
6491
public void buildColourMenu()
6492
{
6493
colourMenu.removeAll();
6494
6495
colourMenu.add(applyToAllGroups);
6496
colourMenu.add(textColour);
6497
colourMenu.addSeparator();
6498
6499
ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
6500
viewport.getAlignment(), false);
6501
6502
colourMenu.add(annotationColour);
6503
bg.add(annotationColour);
6504
colourMenu.addSeparator();
6505
colourMenu.add(conservationMenuItem);
6506
colourMenu.add(modifyConservation);
6507
colourMenu.add(byConsensusSecondaryStructureMenuItem);
6508
colourMenu.add(modifyConsensusSecondaryStructureThreshold);
6509
colourMenu.add(abovePIDThreshold);
6510
colourMenu.add(modifyPID);
6511
6512
ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
6513
ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
6514
}
6515
6516
/**
6517
* Open a dialog (if not already open) that allows the user to select and
6518
* calculate PCA or Tree analysis
6519
*/
6520
protected void openTreePcaDialog()
6521
{
6522
if (alignPanel.getCalculationDialog() == null)
6523
{
6524
new CalculationChooser(AlignFrame.this);
6525
}
6526
}
6527
6528
@Override
6529
protected void loadVcf_actionPerformed()
6530
{
6531
JalviewFileChooser chooser = new JalviewFileChooser(
6532
Cache.getProperty("LAST_DIRECTORY"));
6533
chooser.setFileView(new JalviewFileView());
6534
chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
6535
chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
6536
final AlignFrame us = this;
6537
chooser.setResponseHandler(0, () -> {
6538
String choice = chooser.getSelectedFile().getPath();
6539
Cache.setProperty("LAST_DIRECTORY", choice);
6540
SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
6541
new VCFLoader(choice).loadVCF(seqs, us);
6542
});
6543
chooser.showOpenDialog(null);
6544
6545
}
6546
6547
private Rectangle lastFeatureSettingsBounds = null;
6548
6549
@Override
6550
public void setFeatureSettingsGeometry(Rectangle bounds)
6551
{
6552
lastFeatureSettingsBounds = bounds;
6553
}
6554
6555
@Override
6556
public Rectangle getFeatureSettingsGeometry()
6557
{
6558
return lastFeatureSettingsBounds;
6559
}
6560
6561
/**
6562
* helper for jalview.bin.Commands and loader that sets annotation visibility in a single call
6563
* @param showSSAnnotations
6564
* @param showAnnotations
6565
* @param hideTFrows
6566
*/
6567
public void showOrHideAnnotations(boolean showSSAnnotations, boolean showAnnotations,
6568
boolean hideTFrows)
6569
{
6570
setAnnotationsVisibility(showSSAnnotations, true, false);
6571
setAnnotationsVisibility(showAnnotations, false, true);
6572
6573
// show temperature factor annotations?
6574
if (hideTFrows)
6575
{
6576
// do this better (annotation types?)
6577
// TODO: JAL-4595
6578
List hideThese = new ArrayList<>();
6579
hideThese.add("Temperature Factor");
6580
hideThese.add(AlphaFoldAnnotationRowBuilder.LABEL);
6581
AlignmentUtils.showOrHideSequenceAnnotations(
6582
getCurrentView().getAlignment(), hideThese, null, false,
6583
false);
6584
}
6585
}
6586
6587
}
6588
6589
class PrintThread extends Thread
6590
{
6591
AlignmentPanel ap;
6592
6593
public PrintThread(AlignmentPanel ap)
6594
{
6595
this.ap = ap;
6596
}
6597
6598
static PageFormat pf;
6599
6600
@Override
6601
public void run()
6602
{
6603
PrinterJob printJob = PrinterJob.getPrinterJob();
6604
6605
if (pf != null)
6606
{
6607
printJob.setPrintable(ap, pf);
6608
}
6609
else
6610
{
6611
printJob.setPrintable(ap);
6612
}
6613
6614
if (printJob.printDialog())
6615
{
6616
try
6617
{
6618
printJob.print();
6619
} catch (Exception PrintException)
6620
{
6621
PrintException.printStackTrace();
6622
}
6623
}
6624
}
6625
}