8dc7dd86aa0c8b15d1a920c1b17721a75ea73b4e
[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.AlignmentColsCollectionI;
24 import jalview.api.AlignmentRowsCollectionI;
25 import jalview.datamodel.AlignmentI;
26 import jalview.datamodel.HiddenColumns;
27 import jalview.datamodel.HiddenSequences;
28
29 import java.awt.Dimension;
30 import java.awt.Graphics;
31 import java.awt.Rectangle;
32
33 public abstract class OverviewDimensions
34 {
35   protected static final int MAX_WIDTH = 400;
36
37   protected static final int MIN_WIDTH = 120;
38
39   protected static final int MIN_SEQ_HEIGHT = 40;
40
41   protected static final int MAX_SEQ_HEIGHT = 300;
42
43   private static final int DEFAULT_GRAPH_HEIGHT = 20;
44
45   protected int width;
46
47   protected int sequencesHeight;
48
49   protected int graphHeight = DEFAULT_GRAPH_HEIGHT;
50
51   protected int boxX = -1;
52
53   protected int boxY = -1;
54
55   protected int boxWidth = -1;
56
57   protected int boxHeight = -1;
58
59   protected int alwidth;
60
61   protected int alheight;
62
63   protected float widthRatio;
64
65   protected float heightRatio;
66
67   private Rectangle vpbox = new Rectangle();
68
69   /**
70    * Create an OverviewDimensions object
71    * 
72    * @param ranges
73    *          positional properties of the viewport
74    * @param showAnnotationPanel
75    *          true if the annotation panel is to be shown, false otherwise
76    */
77   public OverviewDimensions(ViewportRanges ranges,
78           boolean showAnnotationPanel, Dimension dim)
79   {
80     if (!showAnnotationPanel)
81     {
82       graphHeight = 0;
83     }
84
85     // scale the initial size of overviewpanel to shape of alignment
86     float initialScale = (float) ranges.getAbsoluteAlignmentWidth()
87             / (float) ranges.getAbsoluteAlignmentHeight();
88
89     if (dim != null)
90     {
91       width = dim.width;
92       sequencesHeight = dim.height;
93       return;
94     }
95     if (ranges.getAbsoluteAlignmentWidth() > ranges
96             .getAbsoluteAlignmentHeight())
97     {
98       // wider
99       width = MAX_WIDTH;
100       sequencesHeight = Math.round(MAX_WIDTH / initialScale);
101       if (sequencesHeight < MIN_SEQ_HEIGHT)
102       {
103         sequencesHeight = MIN_SEQ_HEIGHT;
104       }
105     }
106     else
107     {
108       // taller
109       width = Math.round(MAX_WIDTH * initialScale);
110       sequencesHeight = MAX_SEQ_HEIGHT;
111
112       if (width < MIN_WIDTH)
113       {
114         width = MIN_WIDTH;
115       }
116     }
117   }
118
119   /**
120    * Draw the overview panel's viewport box on a graphics object
121    * 
122    * @param g
123    *          the graphics object to draw on
124    */
125   public void drawBox(Graphics g)
126   {
127     // System.out.println("OD drawBox " + boxX + " " + boxY + " " + boxWidth
128     // + " " + boxHeight);
129     updateBox();
130     g.drawRect(boxX, boxY, boxWidth, boxHeight);
131     g.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2);
132   }
133
134   public int getBoxX()
135   {
136     return boxX;
137   }
138
139   public int getBoxY()
140   {
141     return boxY;
142   }
143
144   public int getBoxWidth()
145   {
146     return boxWidth;
147   }
148
149   public int getBoxHeight()
150   {
151     return boxHeight;
152   }
153
154   public int getWidth()
155   {
156     return width;
157   }
158
159   public int getHeight()
160   {
161     return sequencesHeight + graphHeight;
162   }
163
164   public int getSequencesHeight()
165   {
166     return sequencesHeight;
167   }
168
169   public int getGraphHeight()
170   {
171     return graphHeight;
172   }
173
174   public float getPixelsPerCol()
175   {
176     resetAlignmentDims();
177     return 1 / widthRatio;
178   }
179
180   public float getPixelsPerSeq()
181   {
182     resetAlignmentDims();
183     return 1 / heightRatio;
184   }
185
186   public void setWidth(int w)
187   {
188     width = w;
189     widthRatio = (float) alwidth / width;
190   }
191
192   public void setHeight(int h)
193   {
194     // BH 2019 problem was that component.resize() can come
195     // after setBoxPosition().
196     // Solution was to move setting of box dimensions to paint
197     sequencesHeight = h - graphHeight;
198     heightRatio = (float) alheight / sequencesHeight;
199   }
200
201   /**
202    * Update the viewport location from a mouse click in the overview panel
203    * 
204    * @param mousex
205    *          x location of mouse
206    * @param mousey
207    *          y location of mouse
208    * @param hiddenSeqs
209    *          the alignment's hidden sequences
210    * @param hiddenCols
211    *          the alignment's hidden columns
212    */
213   public abstract void updateViewportFromMouse(int mousex, int mousey,
214           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
215
216   /**
217    * Update the viewport location from a mouse drag within the overview's box
218    * 
219    * @param mousex
220    *          x location of mouse
221    * @param mousey
222    *          y location of mouse
223    * @param hiddenSeqs
224    *          the alignment's hidden sequences
225    * @param hiddenCols
226    *          the alignment's hidden columns
227    */
228   public abstract void adjustViewportFromMouse(int mousex, int mousey,
229           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
230
231   /**
232    * Initialise dragging from the mouse - must be called on initial mouse click
233    * before using adjustViewportFromMouse in drag operations
234    * 
235    * @param mousex
236    *          x location of mouse
237    * @param mousey
238    *          y location of mouse
239    * @param hiddenSeqs
240    *          the alignment's hidden sequences
241    * @param hiddenCols
242    *          the alignment's hidden columns
243    */
244   public abstract void setDragPoint(int x, int y,
245           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
246
247   /*
248    * Move the viewport so that the top left corner of the overview's box 
249    * is at the mouse position (leftx, topy)
250    */
251   protected abstract void updateViewportFromTopLeft(int leftx, int topy,
252           HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
253
254   /**
255    * Set the overview panel's box position to match the viewport
256    * 
257    * @param hiddenSeqs
258    *          the alignment's hidden sequences
259    * @param hiddenCols
260    *          the alignment's hidden columns
261    */
262   public abstract void setBoxPosition(HiddenSequences hiddenSeqs,
263           HiddenColumns hiddenCols);
264
265   /**
266    * Get the collection of columns used by this overview dimensions object
267    * 
268    * @param hiddenCols
269    *          the alignment's hidden columns
270    * @return a column collection
271    */
272   public abstract AlignmentColsCollectionI getColumns(AlignmentI al);
273
274   /**
275    * Get the collection of rows used by this overview dimensions object
276    * 
277    * @param al
278    *          the alignment
279    * @return a row collection
280    */
281   public abstract AlignmentRowsCollectionI getRows(AlignmentI al);
282
283   /**
284    * Updates overview dimensions to account for current alignment dimensions
285    */
286   protected abstract void resetAlignmentDims();
287
288   /*
289    * Given the box coordinates in residues and sequences, set the box dimensions in the overview window
290    */
291   protected void setBoxPosition(int startRes, int startSeq, int vpwidth,
292           int vpheight)
293   {
294     resetAlignmentDims();
295     vpbox = new Rectangle(startRes, startSeq, vpwidth, vpheight);
296     updateBox();
297   }
298
299   public void updateBox()
300   {
301     // boxX, boxY is the x,y location equivalent to startRes, startSeq
302     int xPos = Math.min(vpbox.x, alwidth - vpbox.width + 1);
303     boxX = Math.round(xPos / widthRatio);
304     boxY = Math.round(vpbox.y / heightRatio);
305
306     // boxWidth is the width in residues translated to pixels
307     boxWidth = Math.max(1, Math.round(vpbox.width / widthRatio));
308
309     // boxHeight is the height in sequences translated to pixels
310     boxHeight = Math.max(1, Math.round(vpbox.height / heightRatio));
311   }
312
313   /**
314    * Answers if a mouse position is in the overview's red box
315    * 
316    * @param x
317    *          mouse x position
318    * @param y
319    *          mouse y position
320    * @return true if (x,y) is inside the box
321    */
322   public boolean isPositionInBox(int x, int y)
323   {
324     return (x > boxX && y > boxY && x < boxX + boxWidth
325             && y < boxY + boxHeight);
326   }
327
328   /*
329    * Given the centre x position, calculate the box's left x position
330    */
331   protected abstract int getLeftXFromCentreX(int mousex,
332           HiddenColumns hidden);
333
334   /*
335    * Given the centre y position, calculate the box's top y position
336    */
337   protected abstract int getTopYFromCentreY(int mousey,
338           HiddenSequences hidden);
339
340 }