JAL-2491 Tidies and more refactoring
[jalview.git] / src / jalview / viewmodel / ViewportRanges.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.datamodel.AlignmentI;
24
25 /**
26  * Slightly less embryonic class which: Supplies and updates viewport properties
27  * relating to position such as: start and end residues and sequences; ideally
28  * will serve hidden columns/rows too. Intention also to support calculations
29  * for positioning, scrolling etc. such as finding the middle of the viewport,
30  * checking for scrolls off screen
31  */
32 public class ViewportRanges extends ViewportProperties
33 {
34   // start residue of viewport
35   private int startRes;
36
37   // end residue of viewport
38   private int endRes;
39
40   // start sequence of viewport
41   private int startSeq;
42
43   // end sequence of viewport
44   private int endSeq;
45
46   // alignment
47   private AlignmentI al;
48
49   /**
50    * Constructor
51    * 
52    * @param alignment
53    *          the viewport's alignment
54    */
55   public ViewportRanges(AlignmentI alignment)
56   {
57     // initial values of viewport settings
58     this.startRes = 0;
59     this.endRes = alignment.getWidth() - 1;
60     this.startSeq = 0;
61     this.endSeq = alignment.getHeight() - 1;
62     this.al = alignment;
63   }
64
65   /**
66    * Get alignment width in cols, including hidden cols
67    */
68   public int getAbsoluteAlignmentWidth()
69   {
70     return al.getWidth();
71   }
72
73   /**
74    * Get alignment height in rows, including hidden rows
75    */
76   public int getAbsoluteAlignmentHeight()
77   {
78     return al.getHeight() + al.getHiddenSequences().getSize();
79   }
80
81   /**
82    * Set first residue visible in the viewport, and retain the current width.
83    * 
84    * @param res
85    *          residue position
86    */
87   public void setStartRes(int res)
88   {
89     int width = getViewportWidth();
90     setStartEndRes(res, res + width - 1);
91   }
92
93   /**
94    * Set start and end residues at the same time. This method only fires one
95    * event for the two changes, and should be used in preference to separate
96    * calls to setStartRes and setEndRes.
97    * 
98    * @param start
99    *          the start residue
100    * @param end
101    *          the end residue
102    */
103   public void setStartEndRes(int start, int end)
104   {
105     int oldres = this.startRes;
106     if (start > al.getWidth() - 1)
107     {
108       startRes = al.getWidth() - 1;
109     }
110     else if (start < 0)
111     {
112       startRes = 0;
113     }
114     else
115     {
116       startRes = start;
117     }
118
119     if (end < 0)
120     {
121       endRes = 0;
122     }
123     else
124     {
125       endRes = end;
126     }
127
128     changeSupport.firePropertyChange("startres", oldres, start);
129   }
130
131   /**
132    * Set last residue visible in the viewport
133    * 
134    * @param res
135    *          residue position
136    */
137   public void setEndRes(int res)
138   {
139     int width = getViewportWidth();
140     setStartEndRes(res - width + 1, res);
141   }
142
143   /**
144    * Set the first sequence visible in the viewport
145    * 
146    * @param seq
147    *          sequence position
148    */
149   public void setStartSeq(int seq)
150   {
151     int height = getViewportHeight();
152     setStartEndSeq(seq, seq + height - 1);
153   }
154
155   /**
156    * Set start and end sequences at the same time. This method only fires one
157    * event for the two changes, and should be used in preference to separate
158    * calls to setStartSeq and setEndSeq.
159    * 
160    * @param start
161    *          the start sequence
162    * @param end
163    *          the end sequence
164    */
165   public void setStartEndSeq(int start, int end)
166   {
167     int oldseq = this.startSeq;
168     if (start > al.getHeight() - 1)
169     {
170       startSeq = al.getHeight() - 1;
171     }
172     else if (start < 0)
173     {
174       startSeq = 0;
175     }
176     else
177     {
178       startSeq = start;
179     }
180
181     if (end >= al.getHeight())
182     {
183       endSeq = al.getHeight() - 1;
184     }
185     else if (end < 0)
186     {
187       endSeq = 0;
188     }
189     else
190     {
191       endSeq = end;
192     }
193
194     changeSupport.firePropertyChange("startseq", oldseq, start);
195   }
196
197   /**
198    * Set the last sequence visible in the viewport
199    * 
200    * @param seq
201    *          sequence position
202    */
203   public void setEndSeq(int seq)
204   {
205     int height = getViewportHeight();
206     setStartEndSeq(seq - height + 1, seq);
207   }
208
209   /**
210    * Get start residue of viewport
211    */
212   public int getStartRes()
213   {
214     return startRes;
215   }
216
217   /**
218    * Get end residue of viewport
219    */
220   public int getEndRes()
221   {
222     return endRes;
223   }
224
225   /**
226    * Get start sequence of viewport
227    */
228   public int getStartSeq()
229   {
230     return startSeq;
231   }
232
233   /**
234    * Get end sequence of viewport
235    */
236   public int getEndSeq()
237   {
238     return endSeq;
239   }
240
241   /**
242    * Set viewport width in residues, without changing startRes. Use in
243    * preference to calculating endRes from the width, to avoid out by one
244    * errors!
245    * 
246    * @param w
247    *          width in residues
248    */
249   public void setViewportWidth(int w)
250   {
251     setStartEndRes(startRes, startRes + w - 1);
252   }
253
254   /**
255    * Set viewport height in residues, without changing startSeq. Use in
256    * preference to calculating endSeq from the height, to avoid out by one
257    * errors!
258    * 
259    * @param h
260    *          height in sequences
261    */
262   public void setViewportHeight(int h)
263   {
264     setStartEndSeq(startSeq, startSeq + h - 1);
265   }
266
267   /**
268    * Set viewport horizontal start position and width. Use in preference to
269    * calculating endRes from the width, to avoid out by one errors!
270    * 
271    * @param start
272    *          start residue
273    * @param w
274    *          width in residues
275    */
276   public void setViewportStartAndWidth(int start, int w)
277   {
278     setStartEndRes(start, start + w - 1);
279   }
280
281   /**
282    * Set viewport vertical start position and height. Use in preference to
283    * calculating endSeq from the height, to avoid out by one errors!
284    * 
285    * @param start
286    *          start sequence
287    * @param h
288    *          height in sequences
289    */
290   public void setViewportStartAndHeight(int start, int h)
291   {
292     setStartEndSeq(start, start + h - 1);
293   }
294
295   /**
296    * Get width of viewport in residues
297    * 
298    * @return width of viewport
299    */
300   public int getViewportWidth()
301   {
302     return (endRes - startRes + 1);
303   }
304
305   /**
306    * Get height of viewport in residues
307    * 
308    * @return height of viewport
309    */
310   public int getViewportHeight()
311   {
312     return (endSeq - startSeq + 1);
313   }
314
315   /**
316    * Scroll the viewport range vertically
317    * 
318    * @param up
319    *          true if scrolling up, false if down
320    * 
321    * @return true if the scroll is valid
322    */
323   public boolean scrollUp(boolean up)
324   {
325     if (up)
326     {
327       if (startSeq < 1)
328       {
329         return false;
330       }
331
332       setStartSeq(startSeq - 1);
333     }
334     else
335     {
336       if (endSeq >= al.getHeight() - 1)
337       {
338         return false;
339       }
340
341       setStartSeq(startSeq + 1);
342     }
343     return true;
344   }
345
346   /**
347    * Scroll the viewport range horizontally
348    * 
349    * @param right
350    *          true if scrolling right, false if left
351    * 
352    * @return true if the scroll is valid
353    */
354   public boolean scrollRight(boolean right)
355   {
356     if (!right)
357     {
358       if (startRes < 1)
359       {
360         return false;
361       }
362
363       setStartRes(startRes - 1);
364     }
365     else
366     {
367       if (endRes > al.getWidth() - 1)
368       {
369         return false;
370       }
371
372       setStartRes(startRes + 1);
373     }
374
375     return true;
376   }
377
378   /**
379    * Scroll a wrapped alignment so that the specified residue is visible
380    * 
381    * @param res
382    *          residue position to scroll to
383    */
384   public void scrollToWrappedVisible(int res)
385   {
386     // get the start residue of the wrapped row which res is in
387     // and set that as our start residue
388     int width = getViewportWidth();
389     setStartRes((res / width) * width);
390   }
391
392 }