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