JAL-2388 Minor refactoring
[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.api.AlignViewportI;
24
25 import java.awt.Graphics;
26
27 public class OverviewDimensions
28 {
29   // Default width and height values
30   private static final int DEFAULT_GRAPH_HEIGHT = 20;
31
32   private static final int MAX_WIDTH = 400;
33
34   private static final int MIN_WIDTH = 120;
35
36   private static final int MIN_SEQ_HEIGHT = 40;
37
38   private static final int MAX_SEQ_HEIGHT = 300;
39
40   private AlignViewportI av;
41
42   private float scalew = 1f;
43
44   private float scaleh = 1f;
45
46   // width of the overview panel
47   private int width;
48
49   // height of sequences part of the overview panel
50   private int sequencesHeight;
51
52   // height of the graphs part of the overview panel
53   private int graphHeight = DEFAULT_GRAPH_HEIGHT;
54
55   // dimensions of box outlining current extent of view in alignment panel
56   // location of left side of box
57   private int boxX = -1;
58
59   // location of bottom of box
60   private int boxY = -1;
61
62   // width of box
63   private int boxWidth = -1;
64
65   // height of box
66   private int boxHeight = -1;
67
68   private int scrollCol = -1;
69
70   private int scrollRow = -1;
71
72   public OverviewDimensions(AlignViewportI avi)
73   {
74     this.av = avi;
75
76     // scale the initial size of overviewpanel to shape of alignment
77     float initialScale = (float) av.getAlignment().getWidth()
78             / (float) av.getAlignment().getHeight();
79
80     // TODO: in applet this was getSequenceConsensusHash()
81     // check if it makes any functional difference
82     if (av.getAlignmentConservationAnnotation() == null)
83     {
84       graphHeight = 0;
85     }
86
87     if (av.getAlignment().getWidth() > av.getAlignment().getHeight())
88     {
89       // wider
90       width = MAX_WIDTH;
91       sequencesHeight = (int) (MAX_WIDTH / initialScale);
92       if (sequencesHeight < MIN_SEQ_HEIGHT)
93       {
94         sequencesHeight = MIN_SEQ_HEIGHT;
95       }
96     }
97     else
98     {
99       // taller
100       width = (int) (MAX_WIDTH * initialScale);
101       sequencesHeight = MAX_SEQ_HEIGHT;
102
103       if (width < MIN_WIDTH)
104       {
105         width = MIN_WIDTH;
106       }
107     }
108   }
109
110   /**
111    * Check box dimensions and scroll positions and correct if necessary
112    */
113   public void setBoxPositionByMouse(int x, int y)
114   {
115     boxX = x;
116     boxY = y;
117     if (boxY < 0)
118     {
119       boxY = 0;
120     }
121     else if (boxY > (sequencesHeight - boxHeight))
122     {
123       boxY = sequencesHeight - boxHeight + 1;
124     }
125
126     if (boxX < 0)
127     {
128       boxX = 0;
129     }
130     else if (boxX > (width - boxWidth))
131     {
132       if (av.hasHiddenColumns())
133       {
134         // Try smallest possible box
135         boxWidth = (int) ((av.getEndRes() - av.getStartRes() + 1)
136                 * av.getCharWidth() * scalew);
137       }
138       boxX = width - boxWidth;
139     }
140
141     scrollCol = (int) (boxX / scalew / av.getCharWidth());
142     scrollRow = (int) (boxY / scaleh / av.getCharHeight());
143
144     if (av.hasHiddenColumns())
145     {
146       if (!av.getColumnSelection().isVisible(scrollCol))
147       {
148         return;
149       }
150
151       scrollCol = av.getColumnSelection().findColumnPosition(scrollCol);
152     }
153
154     if (av.hasHiddenRows())
155     {
156       scrollRow = av.getAlignment().getHiddenSequences()
157               .findIndexWithoutHiddenSeqs(scrollRow);
158     }
159   }
160
161   /**
162    * Update the overview panel box when the associated alignment panel is
163    * changed
164    * 
165    */
166   public void setBoxPosition()
167   {
168     updateScales();
169
170     int startRes = av.getStartRes();
171     int endRes = av.getEndRes();
172
173     if (av.hasHiddenColumns())
174     {
175       startRes = av.getColumnSelection().adjustForHiddenColumns(startRes);
176       endRes = av.getColumnSelection().adjustForHiddenColumns(endRes);
177     }
178
179     int startSeq = av.getStartSeq();
180     int endSeq = av.getEndSeq();
181
182     if (av.hasHiddenRows())
183     {
184       startSeq = av.getAlignment().getHiddenSequences()
185               .adjustForHiddenSeqs(startSeq);
186
187       endSeq = av.getAlignment().getHiddenSequences()
188               .adjustForHiddenSeqs(endSeq);
189     }
190
191     boxX = (int) (startRes * av.getCharWidth() * scalew);
192     boxY = (int) (startSeq * av.getCharHeight() * scaleh);
193
194     boxWidth = (int) ((endRes - startRes + 1) * av.getCharWidth() * scalew);
195     boxHeight = (int) ((endSeq - startSeq) * av.getCharHeight() * scaleh);
196   }
197
198   /**
199    * Update width and height scales in terms of the alignment width and height
200    */
201   public void updateScales()
202   {
203     int alwidth = av.getAlignment().getWidth();
204     int alheight = av.getAlignment().getHeight()
205             + av.getAlignment().getHiddenSequences().getSize();
206
207     int fullsizeWidth = alwidth * av.getCharWidth();
208     int fullsizeHeight = alheight * av.getCharHeight();
209
210     scalew = (float) width / fullsizeWidth;
211     scaleh = (float) sequencesHeight / fullsizeHeight;
212   }
213
214   /**
215    * Draw the overview panel's viewport box on a graphics object
216    * 
217    * @param g
218    *          the graphics object to draw on
219    */
220   public void drawBox(Graphics g)
221   {
222     g.drawRect(boxX, boxY, boxWidth, boxHeight);
223     g.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2);
224   }
225
226   // don't like this, scroll vals are separate from setting code
227   public int getScrollCol()
228   {
229     return scrollCol;
230   }
231
232   public int getScrollRow()
233   {
234     return scrollRow;
235   }
236
237   // TODO should be removed, when unit test has mock Graphics object available
238   // to check boxX/boxY
239   public int getBoxX()
240   {
241     return boxX;
242   }
243
244   // TODO should be removed, when unit test has mock Graphics object available
245   // to check boxX/boxY
246   public int getBoxY()
247   {
248     return boxY;
249   }
250
251   public int getBoxWidth()
252   {
253     return boxWidth;
254   }
255
256   public int getBoxHeight()
257   {
258     return boxHeight;
259   }
260
261   public void setBoxX(int x)
262   {
263     boxX = x;
264   }
265
266   public void setBoxY(int y)
267   {
268     boxY = y;
269   }
270
271   public void setWidth(int w)
272   {
273     width = w;
274   }
275
276   public void setHeight(int h)
277   {
278     sequencesHeight = h - graphHeight;
279   }
280
281   public int getWidth()
282   {
283     return width;
284   }
285
286   public int getHeight()
287   {
288     return sequencesHeight + graphHeight;
289   }
290
291   public int getSequencesHeight()
292   {
293     return sequencesHeight;
294   }
295
296   public int getGraphHeight()
297   {
298     return graphHeight;
299   }
300 }