JAL-2388 Initial removal of hidden cols/seqs out of overview
[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) posProps.getAlignmentWidthInCols()
81             / (float) posProps.getAlignmentHeightInRows();
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     int alwidth = av.getAlignment().getWidth();
120     int alheight = av.getAlignment().getAbsoluteHeight();
121
122     boxX = x;
123     boxY = y;
124     if (boxY < 0)
125     {
126       boxY = 0;
127     }
128     else if (boxY > (sequencesHeight - boxHeight))
129     {
130       boxY = sequencesHeight - boxHeight;
131     }
132
133     if (boxX < 0)
134     {
135       boxX = 0;
136     }
137     else if (boxX > (width - boxWidth))
138     {
139       if (av.hasHiddenColumns())
140       {
141         // Try smallest possible box
142         boxWidth = Math.round((float) (posProps.getEndRes()
143                 - posProps.getStartRes() + 1)
144                 * width / alwidth);
145       }
146       boxX = width - boxWidth;
147     }
148
149     scrollCol = Math.round((float) boxX * alwidth / width);
150     scrollRow = Math.round((float) boxY * alheight / sequencesHeight);
151
152     if (av.hasHiddenColumns())
153     {
154       // doesn't seem to do anything useful
155       /*if (!av.getColumnSelection().isVisible(scrollCol))
156       {
157         return;
158       }*/
159
160       scrollCol = av.getColumnSelection().findColumnPosition(scrollCol);
161     }
162
163     if (av.hasHiddenRows())
164     {
165       scrollRow = av.getAlignment().getHiddenSequences()
166               .findIndexWithoutHiddenSeqs(scrollRow);
167     }
168   }
169
170   /**
171    * Update the overview panel box when the associated alignment panel is
172    * changed
173    * 
174    */
175   public void setBoxPosition()
176   {
177     int alwidth = av.getAlignment().getWidth();
178     int alheight = av.getAlignment().getAbsoluteHeight();
179
180     int startRes = av.getPosProps().getAbsoluteStartRes();
181     int endRes = av.getPosProps().getAbsoluteEndRes();
182
183     int startSeq = av.getPosProps().getAbsoluteStartSeq();
184     int endSeq = av.getPosProps().getAbsoluteEndSeq();
185
186     boxX = Math.round((float) startRes * width / alwidth);
187     boxY = Math.round((float) startSeq * sequencesHeight / alheight);
188
189     boxWidth = Math
190             .round((float) (endRes - startRes + 1) * width / alwidth);
191     boxHeight = Math.round((float) (endSeq - startSeq) * sequencesHeight
192             / alheight);
193   }
194
195   /**
196    * Draw the overview panel's viewport box on a graphics object
197    * 
198    * @param g
199    *          the graphics object to draw on
200    */
201   public void drawBox(Graphics g)
202   {
203     g.drawRect(boxX, boxY, boxWidth, boxHeight);
204     g.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2);
205   }
206
207   // don't like this, scroll vals are separate from setting code
208   public int getScrollCol()
209   {
210     return scrollCol;
211   }
212
213   public int getScrollRow()
214   {
215     return scrollRow;
216   }
217
218   // TODO should be removed, when unit test has mock Graphics object available
219   // to check boxX/boxY
220   public int getBoxX()
221   {
222     return boxX;
223   }
224
225   // TODO should be removed, when unit test has mock Graphics object available
226   // to check boxX/boxY
227   public int getBoxY()
228   {
229     return boxY;
230   }
231
232   // TODO should be removed, when unit test has mock Graphics object available
233   public int getBoxWidth()
234   {
235     return boxWidth;
236   }
237
238   // TODO should be removed, when unit test has mock Graphics object available
239   public int getBoxHeight()
240   {
241     return boxHeight;
242   }
243
244   public void setBoxX(int x)
245   {
246     boxX = x;
247   }
248
249   public void setBoxY(int y)
250   {
251     boxY = y;
252   }
253
254   public void setWidth(int w)
255   {
256     width = w;
257   }
258
259   public void setHeight(int h)
260   {
261     sequencesHeight = h - graphHeight;
262   }
263
264   public int getWidth()
265   {
266     return width;
267   }
268
269   public int getHeight()
270   {
271     return sequencesHeight + graphHeight;
272   }
273
274   public int getSequencesHeight()
275   {
276     return sequencesHeight;
277   }
278
279   public int getGraphHeight()
280   {
281     return graphHeight;
282   }
283 }