JAL-2388 Alignment col and row collections with iterators
[jalview.git] / src / jalview / viewmodel / OverviewDimensionsWithHidden.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.viewmodel;
22
23 import jalview.api.AlignmentColsCollectionI;
24 import jalview.api.AlignmentRowsCollectionI;
25 import jalview.datamodel.AlignmentI;
26 import jalview.datamodel.AllColsCollection;
27 import jalview.datamodel.AllRowsCollection;
28 import jalview.datamodel.ColumnSelection;
29 import jalview.datamodel.HiddenSequences;
30
31 public class OverviewDimensionsWithHidden extends OverviewDimensions
32 {
33   private float pixelsPerCol;
34
35   private float pixelsPerSeq;
36
37   /**
38    * Create an OverviewDimensions object
39    * 
40    * @param ranges
41    *          positional properties of the viewport
42    * @param showAnnotationPanel
43    *          true if the annotation panel is to be shown, false otherwise
44    */
45   public OverviewDimensionsWithHidden(ViewportRanges ranges,
46           boolean showAnnotationPanel)
47   {
48     super(ranges, showAnnotationPanel);
49
50     int alwidth = ranges.getAbsoluteAlignmentWidth();
51     int alheight = ranges.getAbsoluteAlignmentHeight();
52
53     pixelsPerCol = (float) width / alwidth;
54     pixelsPerSeq = (float) sequencesHeight / alheight;
55   }
56
57   /**
58    * Check box dimensions and scroll positions and correct if necessary
59    * 
60    * @param mousex
61    *          x position in overview panel
62    * @param mousey
63    *          y position in overview panel
64    * @param hiddenSeqs
65    *          hidden sequences
66    * @param hiddenCols
67    *          hidden columns
68    * @param ranges
69    *          viewport position properties
70    */
71   @Override
72   public void updateViewportFromMouse(int mousex, int mousey,
73           HiddenSequences hiddenSeqs, ColumnSelection hiddenCols,
74           ViewportRanges ranges)
75   {
76     int x = mousex;
77     int y = mousey;
78
79     int alwidth = ranges.getAbsoluteAlignmentWidth();
80     int alheight = ranges.getAbsoluteAlignmentHeight();
81
82     if (x < 0)
83     {
84       x = 0;
85     }
86
87     if (y < 0)
88     {
89       y = 0;
90     }
91
92     //
93     // Convert x value to residue position
94     //
95
96     // need to determine where scrollCol should be, given x
97     // to do this also need to know width of viewport, and some hidden column
98     // correction
99
100     // convert x to residues - this is an absolute position
101     int xAsRes = Math.round((float) x * alwidth / width);
102
103     // get viewport width in residues
104     int vpwidth = ranges.getEndRes() - ranges.getStartRes() + 1;
105
106     // get where x should be when accounting for hidden cols
107     // if x is in a hidden col region, shift to left - but we still need
108     // absolute position
109     // so convert back after getting visible region position
110     int visXAsRes = hiddenCols.findColumnPosition(xAsRes);
111
112     // check in case we went off the edge of the alignment
113     int visAlignWidth = hiddenCols.findColumnPosition(alwidth - 1);
114     if (visXAsRes + vpwidth - 1 > visAlignWidth)
115     {
116       // went past the end of the alignment, adjust backwards
117
118       // if last position was before the end of the alignment, need to update
119       if ((scrollCol + vpwidth - 1) < visAlignWidth)
120       {
121         visXAsRes = hiddenCols.findColumnPosition(hiddenCols
122                 .subtractVisibleColumns(vpwidth - 1, alwidth - 1));
123       }
124       else
125       {
126         visXAsRes = scrollCol;
127       }
128     }
129
130     //
131     // Convert y value to sequence position
132     //
133
134     // convert y to residues
135     int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
136
137     // get viewport height in sequences
138     // add 1 because height includes both endSeq and startSeq
139     int vpheight = ranges.getEndSeq() - ranges.getStartSeq() + 1;
140
141     // get where y should be when accounting for hidden rows
142     // if y is in a hidden row region, shift up - but we still need absolute
143     // position,
144     // so convert back after getting visible region position
145     yAsSeq = hiddenSeqs.adjustForHiddenSeqs(hiddenSeqs
146             .findIndexWithoutHiddenSeqs(yAsSeq));
147
148     // check in case we went off the edge of the alignment
149     int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
150     int visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
151     if (visYAsSeq + vpheight - 1 > visAlignHeight)
152     {
153       // went past the end of the alignment, adjust backwards
154       if ((scrollRow + vpheight - 1) < visAlignHeight)
155       {
156         visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs
157                 .subtractVisibleRows(vpheight - 1, alheight - 1));
158       }
159       else
160       {
161         visYAsSeq = scrollRow;
162       }
163     }
164
165     // update scroll values
166     scrollCol = visXAsRes;
167     scrollRow = visYAsSeq;
168
169   }
170
171   /**
172    * Update the overview panel box when the associated alignment panel is
173    * changed
174    * 
175    * @param hiddenSeqs
176    *          hidden sequences
177    * @param hiddenCols
178    *          hidden columns
179    * @param ranges
180    *          viewport position properties
181    */
182   @Override
183   public void setBoxPosition(HiddenSequences hiddenSeqs,
184           ColumnSelection hiddenCols, ViewportRanges ranges)
185   {
186     int alwidth = ranges.getAbsoluteAlignmentWidth();
187     int alheight = ranges.getAbsoluteAlignmentHeight();
188
189     // work with absolute values of startRes and endRes
190     int startRes = hiddenCols.adjustForHiddenColumns(ranges.getStartRes());
191     int endRes = hiddenCols.adjustForHiddenColumns(ranges.getEndRes());
192
193     // work with absolute values of startSeq and endSeq
194     int startSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getStartSeq());
195     int endSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getEndSeq());
196
197     // boxX, boxY is the x,y location equivalent to startRes, startSeq
198     boxX = Math.round((float) startRes * width / alwidth);
199     boxY = Math.round((float) startSeq * sequencesHeight / alheight);
200
201     // boxWidth is the width in residues translated to pixels
202     // since the box includes both the start and end residues, add 1 to the
203     // difference
204     boxWidth = Math
205             .round((float) (endRes - startRes + 1) * width / alwidth);
206     // boxHeight is the height in sequences translated to pixels
207     boxHeight = Math.round((float) (endSeq - startSeq + 1)
208             * sequencesHeight
209             / alheight);
210   }
211
212   @Override
213   public AlignmentColsCollectionI getColumns(ViewportRanges ranges,
214           ColumnSelection hiddenCols)
215   {
216     return new AllColsCollection(0,
217             ranges.getAbsoluteAlignmentWidth() - 1,
218             hiddenCols);
219   }
220
221   @Override
222   public AlignmentRowsCollectionI getRows(ViewportRanges ranges,
223           AlignmentI al)
224   {
225     return new AllRowsCollection(0,
226             ranges.getAbsoluteAlignmentHeight() - 1,
227             al);
228   }
229
230   @Override
231   public float getPixelsPerCol()
232   {
233     return pixelsPerCol;
234   }
235
236   @Override
237   public float getPixelsPerSeq()
238   {
239     return pixelsPerSeq;
240   }
241 }