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