JAL-2491 Tidy
[jalview.git] / src / jalview / viewmodel / OverviewDimensions.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.ColumnSelection;
24 import jalview.datamodel.HiddenSequences;
25
26 import java.awt.Graphics;
27
28 public class OverviewDimensions
29 {
30   // Default width and height values
31   private static final int DEFAULT_GRAPH_HEIGHT = 20;
32
33   private static final int MAX_WIDTH = 400;
34
35   private static final int MIN_WIDTH = 120;
36
37   private static final int MIN_SEQ_HEIGHT = 40;
38
39   private static final int MAX_SEQ_HEIGHT = 300;
40
41   // width of the overview panel
42   private int width;
43
44   // height of sequences part of the overview panel
45   private int sequencesHeight;
46
47   // height of the graphs part of the overview panel
48   private int graphHeight = DEFAULT_GRAPH_HEIGHT;
49
50   // dimensions of box outlining current extent of view in alignment panel
51   // location of left side of box
52   private int boxX = -1;
53
54   // location of bottom of box
55   private int boxY = -1;
56
57   // width of box
58   private int boxWidth = -1;
59
60   // height of box
61   private int boxHeight = -1;
62
63   /**
64    * Create an OverviewDimensions object
65    * 
66    * @param ranges
67    *          positional properties of the viewport
68    * @param showAnnotationPanel
69    *          true if the annotation panel is to be shown, false otherwise
70    */
71   public OverviewDimensions(ViewportRanges ranges,
72           boolean showAnnotationPanel)
73   {
74     // scale the initial size of overviewpanel to shape of alignment
75     float initialScale = (float) ranges.getAbsoluteAlignmentWidth()
76             / (float) ranges.getAbsoluteAlignmentHeight();
77
78     if (!showAnnotationPanel)
79     {
80       graphHeight = 0;
81     }
82
83     if (ranges.getAbsoluteAlignmentWidth() > ranges
84             .getAbsoluteAlignmentHeight())
85     {
86       // wider
87       width = MAX_WIDTH;
88       sequencesHeight = Math.round(MAX_WIDTH / initialScale);
89       if (sequencesHeight < MIN_SEQ_HEIGHT)
90       {
91         sequencesHeight = MIN_SEQ_HEIGHT;
92       }
93     }
94     else
95     {
96       // taller
97       width = Math.round(MAX_WIDTH * initialScale);
98       sequencesHeight = MAX_SEQ_HEIGHT;
99
100       if (width < MIN_WIDTH)
101       {
102         width = MIN_WIDTH;
103       }
104     }
105   }
106
107   /**
108    * Check box dimensions and scroll positions and correct if necessary
109    * 
110    * @param mousex
111    *          x position in overview panel
112    * @param mousey
113    *          y position in overview panel
114    * @param hiddenSeqs
115    *          hidden sequences
116    * @param hiddenCols
117    *          hidden columns
118    * @param ranges
119    *          viewport position properties
120    */
121   public void updateViewportFromMouse(int mousex, int mousey,
122           HiddenSequences hiddenSeqs, ColumnSelection hiddenCols,
123           ViewportRanges ranges)
124   {
125     int x = mousex;
126     int y = mousey;
127
128     int alwidth = ranges.getAbsoluteAlignmentWidth();
129     int alheight = ranges.getAbsoluteAlignmentHeight();
130
131     if (x < 0)
132     {
133       x = 0;
134     }
135
136     if (y < 0)
137     {
138       y = 0;
139     }
140
141     //
142     // Convert x value to residue position
143     //
144
145     // need to determine where scrollCol should be, given x
146     // to do this also need to know width of viewport, and some hidden column
147     // correction
148
149     // convert x to residues - this is an absolute position
150     int xAsRes = Math.round((float) x * alwidth / width);
151
152     // get viewport width in residues
153     int vpwidth = ranges.getViewportWidth();
154
155     // get where x should be when accounting for hidden cols
156     // if x is in a hidden col region, shift to left - but we still need
157     // absolute position
158     // so convert back after getting visible region position
159     int visXAsRes = hiddenCols.findColumnPosition(xAsRes);
160
161     // check in case we went off the edge of the alignment
162     int visAlignWidth = hiddenCols.findColumnPosition(alwidth - 1);
163     if (visXAsRes + vpwidth - 1 > visAlignWidth)
164     {
165       // went past the end of the alignment, adjust backwards
166
167       // if last position was before the end of the alignment, need to update
168       if ((ranges.getStartRes() + vpwidth - 1) < visAlignWidth)
169       {
170         visXAsRes = hiddenCols.findColumnPosition(hiddenCols
171                 .subtractVisibleColumns(vpwidth - 1, alwidth - 1));
172       }
173       else
174       {
175         visXAsRes = ranges.getStartRes();
176       }
177     }
178
179     //
180     // Convert y value to sequence position
181     //
182
183     // convert y to residues
184     int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
185
186     // get viewport height in sequences
187     int vpheight = ranges.getViewportHeight();
188
189     // get where y should be when accounting for hidden rows
190     // if y is in a hidden row region, shift up - but we still need absolute
191     // position,
192     // so convert back after getting visible region position
193     yAsSeq = hiddenSeqs.adjustForHiddenSeqs(hiddenSeqs
194             .findIndexWithoutHiddenSeqs(yAsSeq));
195
196     // check in case we went off the edge of the alignment
197     int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
198     int visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
199     if (visYAsRes + vpheight - 1 > visAlignHeight)
200     {
201       // went past the end of the alignment, adjust backwards
202       if ((ranges.getEndRes() + vpheight - 1) < visAlignHeight)
203       {
204         visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs
205                 .subtractVisibleRows(vpheight - 1, alheight - 1));
206       }
207       else
208       {
209         visYAsRes = ranges.getEndRes();
210       }
211     }
212
213     // update viewport
214     ranges.setStartRes(visXAsRes);
215     ranges.setStartSeq(visYAsRes);
216   }
217
218   /**
219    * Update the overview panel box when the associated alignment panel is
220    * changed
221    * 
222    * @param hiddenSeqs
223    *          hidden sequences
224    * @param hiddenCols
225    *          hidden columns
226    * @param ranges
227    *          viewport position properties
228    */
229   public void setBoxPosition(HiddenSequences hiddenSeqs,
230           ColumnSelection hiddenCols, ViewportRanges ranges)
231   {
232     int alwidth = ranges.getAbsoluteAlignmentWidth();
233     int alheight = ranges.getAbsoluteAlignmentHeight();
234
235     // work with absolute values of startRes and endRes
236     int startRes = hiddenCols.adjustForHiddenColumns(ranges.getStartRes());
237     int endRes = hiddenCols.adjustForHiddenColumns(ranges.getEndRes());
238
239     // work with absolute values of startSeq and endSeq
240     int startSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getStartSeq());
241     int endSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getEndSeq());
242
243     // boxX, boxY is the x,y location equivalent to startRes, startSeq
244     boxX = Math.round((float) startRes * width / alwidth);
245     boxY = Math.round((float) startSeq * sequencesHeight / alheight);
246
247     // boxWidth is the width in residues translated to pixels
248     // since the box includes both the start and end residues, add 1 to the
249     // difference
250     boxWidth = Math
251             .round((float) (endRes - startRes + 1) * width / alwidth);
252     // boxHeight is the height in sequences translated to pixels
253     boxHeight = Math.round((float) (endSeq - startSeq + 1)
254             * sequencesHeight
255             / alheight);
256   }
257
258   /**
259    * Draw the overview panel's viewport box on a graphics object
260    * 
261    * @param g
262    *          the graphics object to draw on
263    */
264   public void drawBox(Graphics g)
265   {
266     g.drawRect(boxX, boxY, boxWidth, boxHeight);
267     g.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2);
268   }
269
270   // TODO should be removed, when unit test has mock Graphics object available
271   // to check boxX/boxY
272   public int getBoxX()
273   {
274     return boxX;
275   }
276
277   // TODO should be removed, when unit test has mock Graphics object available
278   // to check boxX/boxY
279   public int getBoxY()
280   {
281     return boxY;
282   }
283
284   // TODO should be removed, when unit test has mock Graphics object available
285   public int getBoxWidth()
286   {
287     return boxWidth;
288   }
289
290   // TODO should be removed, when unit test has mock Graphics object available
291   public int getBoxHeight()
292   {
293     return boxHeight;
294   }
295
296   public void setWidth(int w)
297   {
298     width = w;
299   }
300
301   public void setHeight(int h)
302   {
303     sequencesHeight = h - graphHeight;
304   }
305
306   public int getWidth()
307   {
308     return width;
309   }
310
311   public int getHeight()
312   {
313     return sequencesHeight + graphHeight;
314   }
315
316   public int getSequencesHeight()
317   {
318     return sequencesHeight;
319   }
320
321   public int getGraphHeight()
322   {
323     return graphHeight;
324   }
325 }