2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.viewmodel;
23 import jalview.api.ViewStyleI;
24 import jalview.datamodel.AlignmentAnnotation;
25 import jalview.datamodel.AlignmentI;
26 import jalview.datamodel.ColumnSelection;
27 import jalview.datamodel.SequenceCollectionI;
28 import jalview.datamodel.SequenceGroup;
29 import jalview.datamodel.SequenceI;
31 import java.util.ArrayList;
32 import java.util.Hashtable;
33 import java.util.List;
37 * Supplies and updates viewport properties relating to position such as: start
38 * and end residues and sequences, hidden column/row adjustments, ratio of
39 * viewport to alignment etc
41 public class ViewportPositionProps extends ViewportProperties
43 // start residue of viewport
46 // end residue of viewport
49 // start sequence of viewport
52 // end sequence of viewport
56 private int charHeight;
59 private int charWidth;
62 private AlignmentI al;
65 private ViewStyleI viewstyle;
68 protected ColumnSelection colSel = new ColumnSelection();
70 private long colselhash = -1;
72 // hidden sequence data
73 private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
77 * @param alignment TODO
79 public ViewportPositionProps(AlignmentI alignment, ViewStyleI vstyle)
81 // initial values of viewport settings
83 this.endRes = alignment.getWidth() - 1;
85 this.endSeq = alignment.getHeight() - 1;
87 this.viewstyle = vstyle;
90 public void setCharHeight(int h)
92 viewstyle.setCharHeight(h);
95 public void setCharWidth(int w)
97 viewstyle.setCharWidth(w);
100 // ways to update values
102 // ways to notify of changes
104 // ways to supply positional information
107 * Get alignment width
109 public int getAlignmentWidthInCols()
111 return al.getWidth();
115 * Get alignment height
117 public int getAlignmentHeightInRows()
119 return al.getHeight();
122 public void setStartRes(int res)
124 if (res > al.getWidth() - 1)
126 res = al.getWidth() - 1;
135 public void setEndRes(int res)
137 if (res > al.getWidth() - 1)
139 res = al.getWidth() - 1;
148 public void setStartSeq(int seq)
150 if (seq > al.getHeight())
152 seq = al.getHeight();
161 public void setEndSeq(int seq)
163 if (seq > al.getHeight())
165 seq = al.getHeight();
175 * Get start residue of viewport
177 public int getStartRes()
183 * Get end residue of viewport
185 public int getEndRes()
191 * Get start sequence of viewport
193 public int getStartSeq()
199 * Get end sequence of viewport
201 public int getEndSeq()
206 * Get start residue of viewport
208 public int getStartRes(boolean countHidden)
212 return 0; // av.getColumnSelection().adjustForHiddenColumns(startRes);
221 * Convert distance x in viewport pixels to a distance in number of residues
225 * @return number of residues
227 public int convertPixelsToResidues(int x)
229 return Math.round((float) x / viewstyle.getCharWidth());
233 * Convert distance y in viewport pixels to a distance in number of sequences
237 * @return number of sequences
239 public int convertPixelsToSequences(int y)
241 return Math.round((float) y / viewstyle.getCharHeight());
245 * Convert number of sequences s to a height in viewport pixels
248 * number of sequences
249 * @return number of pixels
251 public int convertSequencesToPixels(int s)
253 return (s * viewstyle.getCharHeight());
257 * Convert number of residues r to a width in viewport pixels
261 * @return number of pixels
263 public int convertResiduesToPixels(int r)
265 return (r * viewstyle.getCharWidth());
268 public void setHiddenColumns(ColumnSelection colsel)
270 this.colSel = colsel;
273 public ColumnSelection getColumnSelection()
278 public void setColumnSelection(ColumnSelection colSel)
280 this.colSel = colSel;
283 // updateHiddenColumns(); - does nothing
285 isColSelChanged(true);
288 public boolean hasHiddenColumns()
290 return colSel != null && colSel.hasHiddenColumns();
294 * checks current colsel against record of last hash value, and optionally
298 * update the record of last hash value
299 * @return true if colsel changed since last call (when b is true)
301 public boolean isColSelChanged(boolean b)
303 int hc = (colSel == null || colSel.isEmpty()) ? -1 : colSel.hashCode();
304 if (hc != -1 && hc != colselhash)
315 public void hideColumns(int start, int end)
319 colSel.hideColumns(start);
323 colSel.hideColumns(start, end);
325 isColSelChanged(true);
328 public void showColumn(int col)
330 colSel.revealHiddenColumns(col);
331 isColSelChanged(true);
334 public void showAllHiddenColumns()
336 colSel.revealAllHiddenColumns();
337 isColSelChanged(true);
340 public void invertColumnSelection()
342 colSel.invertColumnSelection(0, al.getWidth());
345 public List<int[]> getVisibleRegionBoundaries(int min, int max)
347 ArrayList<int[]> regions = new ArrayList<int[]>();
353 if (hasHiddenColumns())
357 start = colSel.adjustForHiddenColumns(start);
360 end = colSel.getHiddenBoundaryRight(start);
371 regions.add(new int[] { start, end });
373 if (hasHiddenColumns())
375 start = colSel.adjustForHiddenColumns(end);
376 start = colSel.getHiddenBoundaryLeft(start) + 1;
380 int[][] startEnd = new int[regions.size()][2];
386 * synthesize a column selection if none exists so it covers the given
387 * selection group. if wholewidth is false, no column selection is made if the
388 * selection group covers the whole alignment width.
393 public void expandColSelection(SequenceGroup sg, boolean wholewidth)
396 if (sg != null && (sgs = sg.getStartRes()) >= 0
397 && sg.getStartRes() <= (sge = sg.getEndRes()))
399 if (!wholewidth && al.getWidth() == (1 + sge - sgs))
406 colSel = new ColumnSelection();
408 for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)
410 colSel.addElement(cspos);
415 public List<AlignmentAnnotation> getVisibleAlignmentAnnotation(
416 boolean selectedOnly, SequenceGroup selectionGroup)
418 ArrayList<AlignmentAnnotation> ala = new ArrayList<AlignmentAnnotation>();
419 AlignmentAnnotation[] aa;
420 if ((aa = al.getAlignmentAnnotation()) != null)
422 for (AlignmentAnnotation annot : aa)
424 AlignmentAnnotation clone = new AlignmentAnnotation(annot);
425 if (selectedOnly && selectionGroup != null)
427 colSel.makeVisibleAnnotation(selectionGroup.getStartRes(),
428 selectionGroup.getEndRes(), clone);
432 colSel.makeVisibleAnnotation(clone);
440 public String[] getVisibleSequenceStrings(int start, int end,
443 return colSel.getVisibleSequenceStrings(start, end, seqs);
447 * Set visibility for any annotations for the given sequence.
451 protected void setSequenceAnnotationsVisible(SequenceI sequenceI,
454 AlignmentAnnotation[] anns = al.getAlignmentAnnotation();
457 for (AlignmentAnnotation ann : anns)
459 if (ann.sequenceRef == sequenceI)
461 ann.visible = visible;
467 public void setHiddenRepSequences(
468 Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
470 this.hiddenRepSequences = hiddenRepSequences;
473 public Map<SequenceI, SequenceCollectionI> getHiddenRepSequences()
475 return hiddenRepSequences;
478 // common hide/show seq stuff
479 public SequenceGroup showAllHiddenSeqs(SequenceGroup selectionGroup)
481 if (al.getHiddenSequences().getSize() > 0)
483 if (selectionGroup == null)
485 selectionGroup = new SequenceGroup();
486 selectionGroup.setEndRes(al.getWidth() - 1);
488 List<SequenceI> tmp = al.getHiddenSequences().showAll(
490 for (SequenceI seq : tmp)
492 selectionGroup.addSequence(seq, false);
493 setSequenceAnnotationsVisible(seq, true);
496 hiddenRepSequences = null;
498 firePropertyChange("alignment", null, al.getSequences());
499 // used to set hasHiddenRows/hiddenRepSequences here, after the property
505 public void showSequence(int index, SequenceGroup selectionGroup)
507 List<SequenceI> tmp = al.getHiddenSequences().showSequence(index,
511 if (selectionGroup == null)
513 selectionGroup = new SequenceGroup();
514 selectionGroup.setEndRes(al.getWidth() - 1);
517 for (SequenceI seq : tmp)
519 selectionGroup.addSequence(seq, false);
520 setSequenceAnnotationsVisible(seq, true);
522 firePropertyChange("alignment", null, al.getSequences());
527 public void hideAllSelectedSeqs(SequenceGroup selectionGroup)
529 if (selectionGroup == null || selectionGroup.getSize() < 1)
534 SequenceI[] seqs = selectionGroup.getSequencesInOrder(al);
538 setSelectionGroup(null);
541 public void hideSequence(SequenceI[] seq)
545 for (int i = 0; i < seq.length; i++)
547 al.getHiddenSequences().hideSequence(seq[i]);
548 setSequenceAnnotationsVisible(seq[i], false);
550 firePropertyChange("alignment", null, al.getSequences());
555 * Hides the specified sequence, or the sequences it represents
558 * the sequence to hide, or keep as representative
559 * @param representGroup
560 * if true, hide the current selection group except for the
561 * representative sequence
563 public void hideSequences(SequenceI sequence, boolean representGroup,
564 SequenceGroup selectionGroup)
566 if (selectionGroup == null || selectionGroup.getSize() < 1)
568 hideSequence(new SequenceI[] { sequence });
574 hideRepSequences(sequence, selectionGroup);
575 setSelectionGroup(null);
579 int gsize = selectionGroup.getSize();
580 SequenceI[] hseqs = selectionGroup.getSequences().toArray(
581 new SequenceI[gsize]);
584 setSelectionGroup(null);
588 public void hideRepSequences(SequenceI repSequence, SequenceGroup sg)
590 int sSize = sg.getSize();
596 if (hiddenRepSequences == null)
598 hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
601 hiddenRepSequences.put(repSequence, sg);
603 // Hide all sequences except the repSequence
604 SequenceI[] seqs = new SequenceI[sSize - 1];
606 for (int i = 0; i < sSize; i++)
608 if (sg.getSequenceAt(i) != repSequence)
610 if (index == sSize - 1)
615 seqs[index++] = sg.getSequenceAt(i);
618 sg.setSeqrep(repSequence); // note: not done in 2.7applet
619 sg.setHidereps(true); // note: not done in 2.7applet
627 * @return true if there are sequences represented by this sequence that are
630 public boolean isHiddenRepSequence(SequenceI seq)
632 return (hiddenRepSequences != null && hiddenRepSequences
639 * @return null or a sequence group containing the sequences that seq
642 public SequenceGroup getRepresentedSequences(SequenceI seq)
644 return (SequenceGroup) (hiddenRepSequences == null ? null
645 : hiddenRepSequences.get(seq));
648 public int adjustForHiddenSeqs(int alignmentIndex)
650 return al.getHiddenSequences().adjustForHiddenSeqs(alignmentIndex);