JAL-3626 from JAL-3253-applet web page embedding
[jalview.git] / src / jalview / viewmodel / OverviewDimensionsShowHidden.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 java.awt.Dimension;
24
25 import jalview.api.AlignmentColsCollectionI;
26 import jalview.api.AlignmentRowsCollectionI;
27 import jalview.datamodel.AlignmentI;
28 import jalview.datamodel.AllColsCollection;
29 import jalview.datamodel.AllRowsCollection;
30 import jalview.datamodel.HiddenColumns;
31 import jalview.datamodel.HiddenSequences;
32
33 public class OverviewDimensionsShowHidden extends OverviewDimensions
34 {
35   private ViewportRanges ranges;
36
37   private int xdiff; // when dragging, difference in alignment units between
38                      // start residue and original mouse click position
39
40   private int ydiff; // when dragging, difference in alignment units between
41                      // start sequence and original mouse click position
42
43   
44   /**
45    * for testng only
46    * 
47    * @param vpranges
48    * @param showAnnotationPanel
49    */  
50   @Deprecated
51   public OverviewDimensionsShowHidden(ViewportRanges vpranges, boolean showAnnotationPanel) {
52     this(vpranges, showAnnotationPanel, null);
53   }
54
55   /**
56    * Create an OverviewDimensions object
57    * 
58    * @param ranges
59    *          positional properties of the viewport
60    * @param showAnnotationPanel
61    *          true if the annotation panel is to be shown, false otherwise
62    */
63   public OverviewDimensionsShowHidden(ViewportRanges vpranges,
64           boolean showAnnotationPanel, Dimension dim)
65   {
66     super(vpranges, showAnnotationPanel, dim);
67     ranges = vpranges;
68     resetAlignmentDims();
69   }
70
71   /**
72    * Check box dimensions and scroll positions and correct if necessary
73    * 
74    * @param mousex
75    *          x position in overview panel
76    * @param mousey
77    *          y position in overview panel
78    * @param hiddenSeqs
79    *          hidden sequences
80    * @param hiddenCols
81    *          hidden columns
82    * @param ranges
83    *          viewport position properties
84    */
85   @Override
86   public void updateViewportFromMouse(int mousex, int mousey,
87           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
88   {
89     resetAlignmentDims();
90
91     // convert mousex and mousey to alignment units as well as
92     // translating to top left corner of viewport - this is an absolute position
93     int xAsRes = getLeftXFromCentreX(mousex, hiddenCols);
94     int yAsSeq = getTopYFromCentreY(mousey, hiddenSeqs);
95
96     // convert to visible positions
97     int visXAsRes = hiddenCols.absoluteToVisibleColumn(xAsRes);
98     yAsSeq = hiddenSeqs.adjustForHiddenSeqs(
99             hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq));
100     yAsSeq = Math.max(yAsSeq, 0); // -1 if before first visible sequence
101     int visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
102     visYAsSeq = Math.max(visYAsSeq, 0); // -1 if before first visible sequence
103
104     // update viewport accordingly
105     updateViewportFromTopLeft(visXAsRes, visYAsSeq, hiddenSeqs, hiddenCols);
106   }
107
108   @Override
109   public void adjustViewportFromMouse(int mousex, int mousey,
110           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
111   {
112     resetAlignmentDims();
113
114     // calculate translation in pixel terms:
115     // get mouse location in viewport coords, add translation in viewport
116     // coords,
117     // convert back to pixel coords
118     int vpx = Math.round((float) mousex * alwidth / width);
119     int visXAsRes = hiddenCols.absoluteToVisibleColumn(vpx) + xdiff;
120
121     int vpy = Math.round(mousey * heightRatio);
122     int visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(vpy) + ydiff;
123
124     // update viewport accordingly
125     updateViewportFromTopLeft(visXAsRes, visYAsRes, hiddenSeqs, hiddenCols);
126   }
127
128   /**
129    * {@inheritDoc} Callers should have already called resetAlignmentDims to
130    * refresh alwidth, alheight and width/height ratios
131    */
132   @Override
133   protected void updateViewportFromTopLeft(int leftx, int topy,
134           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
135   {
136     int visXAsRes = leftx;
137     int visYAsSeq = topy;
138
139     if (visXAsRes < 0)
140     {
141       visXAsRes = 0;
142     }
143
144     if (visYAsSeq < 0)
145     {
146       visYAsSeq = 0;
147     }
148
149     if (ranges.isWrappedMode())
150     {
151       visYAsSeq = 0; // sorry, no vertical scroll when wrapped
152     }
153
154     // Determine where scrollCol should be, given visXAsRes
155
156     // get viewport width in residues
157     int vpwidth = ranges.getViewportWidth();
158
159     // check in case we went off the edge of the alignment
160     int visAlignWidth = hiddenCols.absoluteToVisibleColumn(alwidth - 1);
161     if (visXAsRes + vpwidth - 1 > visAlignWidth)
162     {
163       // went past the end of the alignment, adjust backwards
164
165       // if last position was before the end of the alignment, need to update
166       if (ranges.getEndRes() < visAlignWidth)
167       {
168         visXAsRes = hiddenCols.absoluteToVisibleColumn(hiddenCols
169                 .offsetByVisibleColumns(-(vpwidth - 1), alwidth - 1));
170       }
171       else
172       {
173         visXAsRes = ranges.getStartRes();
174       }
175     }
176
177     // Determine where scrollRow should be, given visYAsSeq
178
179     // get viewport height in sequences
180     int vpheight = ranges.getViewportHeight();
181
182     // check in case we went off the edge of the alignment
183     int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
184
185     if (visYAsSeq + vpheight - 1 > visAlignHeight)
186     {
187       // went past the end of the alignment, adjust backwards
188       if (ranges.getEndSeq() < visAlignHeight)
189       {
190         visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(
191                 hiddenSeqs.subtractVisibleRows(vpheight - 1, alheight - 1));
192       }
193       else
194       {
195         visYAsSeq = ranges.getStartSeq();
196       }
197     }
198
199     // update viewport
200     ranges.setStartResAndSeq(visXAsRes, visYAsSeq);
201   }
202
203   /**
204    * Update the overview panel box when the associated alignment panel is
205    * changed
206    * 
207    * @param hiddenSeqs
208    *          hidden sequences
209    * @param hiddenCols
210    *          hidden columns
211    * @param ranges
212    *          viewport position properties
213    */
214   @Override
215   public void setBoxPosition(HiddenSequences hiddenSeqs,
216           HiddenColumns hiddenCols)
217   {
218     // work with absolute values of startRes and endRes
219     int startRes = hiddenCols.visibleToAbsoluteColumn(ranges.getStartRes());
220     int endRes = hiddenCols.visibleToAbsoluteColumn(ranges.getEndRes());
221
222     // work with absolute values of startSeq and endSeq
223     int startSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getStartSeq());
224     int endSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getEndSeq());
225
226     setBoxPosition(startRes, startSeq, endRes - startRes + 1,
227             endSeq - startSeq + 1);
228   }
229
230   @Override
231   public AlignmentColsCollectionI getColumns(AlignmentI al)
232   {
233     return new AllColsCollection(0, ranges.getAbsoluteAlignmentWidth() - 1,
234             al);
235   }
236
237   @Override
238   public AlignmentRowsCollectionI getRows(AlignmentI al)
239   {
240     return new AllRowsCollection(0, ranges.getAbsoluteAlignmentHeight() - 1,
241             al);
242   }
243
244   @Override
245   protected void resetAlignmentDims()
246   {
247     alwidth = ranges.getAbsoluteAlignmentWidth();
248     alheight = ranges.getAbsoluteAlignmentHeight();
249
250     widthRatio = (float) alwidth / width;
251     heightRatio = (float) alheight / sequencesHeight;
252   }
253
254
255   /**
256    * {@inheritDoc} Callers should have already called resetAlignmentDims to
257    * refresh widthRatio
258    */
259   @Override
260   protected int getLeftXFromCentreX(int mousex, HiddenColumns hidden)
261   {
262     int vpx = Math.round((float) mousex * alwidth / width);
263     return hidden.offsetByVisibleColumns(-ranges.getViewportWidth() / 2,
264             vpx);
265   }
266
267   /**
268    * {@inheritDoc} Callers should have already called resetAlignmentDims to
269    * refresh heightRatio
270    */
271   @Override
272   protected int getTopYFromCentreY(int mousey, HiddenSequences hidden)
273   {
274     int vpy = Math.round(mousey * heightRatio);
275     return hidden.subtractVisibleRows(ranges.getViewportHeight() / 2, vpy);
276   }
277
278   @Override
279   public void setDragPoint(int x, int y, HiddenSequences hiddenSeqs,
280           HiddenColumns hiddenCols)
281   {
282     resetAlignmentDims();
283
284     // get alignment position of x and box (can get directly from vpranges) and
285     // calculate difference between the positions
286     int vpx = Math.round(x * widthRatio);
287     int vpy = Math.round(y * heightRatio);
288
289     xdiff = ranges.getStartRes() - hiddenCols.absoluteToVisibleColumn(vpx);
290     ydiff = ranges.getStartSeq()
291             - hiddenSeqs.findIndexWithoutHiddenSeqs(vpy);
292   }
293
294 }