Cant have col less than 0
[jalview.git] / src / jalview / gui / ScalePanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.datamodel.*;\r
22 \r
23 import java.awt.*;\r
24 import java.awt.event.*;\r
25 \r
26 import javax.swing.*;\r
27 \r
28 \r
29 /**\r
30  * DOCUMENT ME!\r
31  *\r
32  * @author $author$\r
33  * @version $Revision$\r
34  */\r
35 public class ScalePanel extends JPanel implements MouseMotionListener, MouseListener\r
36 {\r
37     protected int offy = 4;\r
38 \r
39     /** DOCUMENT ME!! */\r
40     public int width;\r
41     protected AlignViewport av;\r
42     AlignmentPanel ap;\r
43     boolean stretchingGroup = false;\r
44     int min; //used by mouseDragged to see if user\r
45     int max; //used by mouseDragged to see if user\r
46     boolean mouseDragging = false;\r
47 \r
48     // wants to delete columns\r
49     public ScalePanel(AlignViewport av, AlignmentPanel ap)\r
50     {\r
51         this.av = av;\r
52         this.ap = ap;\r
53 \r
54         addMouseListener(this);\r
55         addMouseMotionListener(this);\r
56     }\r
57 \r
58     /**\r
59      * DOCUMENT ME!\r
60      *\r
61      * @param evt DOCUMENT ME!\r
62      */\r
63     public void mousePressed(MouseEvent evt)\r
64     {\r
65         int x = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
66         final int res;\r
67 \r
68         if(av.hasHiddenColumns)\r
69           res = av.getColumnSelection().adjustForHiddenColumns(x);\r
70         else\r
71           res = x;\r
72 \r
73         min = res;\r
74         max = res;\r
75 \r
76         if(reveal != null && SwingUtilities.isRightMouseButton(evt))\r
77           {\r
78             JPopupMenu pop = new JPopupMenu();\r
79             JMenuItem item = new JMenuItem("Reveal");\r
80             item.addActionListener(new ActionListener()\r
81             {\r
82               public void actionPerformed(ActionEvent e)\r
83               {\r
84                 av.showColumn(reveal[0]);\r
85                 reveal = null;\r
86                 ap.repaint();\r
87                 if(ap.overviewPanel != null)\r
88                     ap.overviewPanel.updateOverviewImage();\r
89               }\r
90             });\r
91             pop.add(item);\r
92 \r
93             if(av.getColumnSelection().size()>1)\r
94             {\r
95               item = new JMenuItem("Reveal All");\r
96               item.addActionListener(new ActionListener()\r
97               {\r
98                 public void actionPerformed(ActionEvent e)\r
99                 {\r
100                   av.showAllHiddenColumns();\r
101                   reveal = null;\r
102                   ap.repaint();\r
103                   if(ap.overviewPanel != null)\r
104                     ap.overviewPanel.updateOverviewImage();\r
105                 }\r
106               });\r
107               pop.add(item);\r
108             }\r
109 \r
110             pop.show(this, evt.getX(), evt.getY());\r
111 \r
112           }\r
113         else\r
114       if (av.getColumnSelection().contains(res))\r
115         {\r
116           if( SwingUtilities.isRightMouseButton(evt))\r
117           {\r
118             JPopupMenu pop = new JPopupMenu();\r
119             JMenuItem item = new JMenuItem("Hide Columns");\r
120             item.addActionListener(new ActionListener()\r
121             {\r
122               public void actionPerformed(ActionEvent e)\r
123               {\r
124                 av.hideColumns(res, res);\r
125                 ap.repaint();\r
126                 if(ap.overviewPanel != null)\r
127                   ap.overviewPanel.updateOverviewImage();\r
128               }\r
129             });\r
130             pop.add(item);\r
131             pop.show(this, evt.getX(), evt.getY());\r
132 \r
133           }\r
134           else\r
135           {\r
136             av.getColumnSelection().removeElement(res);\r
137             av.setSelectionGroup(null);\r
138           }\r
139         }\r
140         else\r
141         {\r
142             av.getColumnSelection().addElement(res);\r
143             SequenceGroup sg = new SequenceGroup();\r
144 \r
145             for (int i = 0; i < av.alignment.getSequences().size(); i++)\r
146             {\r
147                 sg.addSequence(av.alignment.getSequenceAt(i), false);\r
148             }\r
149 \r
150             sg.setStartRes(res);\r
151             sg.setEndRes(res);\r
152             av.setSelectionGroup(sg);\r
153         }\r
154 \r
155 \r
156         ap.repaint();\r
157     }\r
158 \r
159     /**\r
160      * DOCUMENT ME!\r
161      *\r
162      * @param evt DOCUMENT ME!\r
163      */\r
164     public void mouseReleased(MouseEvent evt)\r
165     {\r
166         mouseDragging = false;\r
167 \r
168         int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
169 \r
170         if(res> av.alignment.getWidth())\r
171         {\r
172           res = av.alignment.getWidth()-1;\r
173         }\r
174 \r
175         if(av.hasHiddenColumns)\r
176           res = av.getColumnSelection().adjustForHiddenColumns(res);\r
177 \r
178         if (!stretchingGroup)\r
179         {\r
180             ap.repaint();\r
181 \r
182             return;\r
183         }\r
184 \r
185         SequenceGroup sg = av.getSelectionGroup();\r
186 \r
187         if (res > sg.getStartRes())\r
188         {\r
189             sg.setEndRes(res);\r
190         }\r
191         else if (res < sg.getStartRes())\r
192         {\r
193             sg.setStartRes(res);\r
194         }\r
195 \r
196         stretchingGroup = false;\r
197         ap.repaint();\r
198     }\r
199 \r
200     /**\r
201      * DOCUMENT ME!\r
202      *\r
203      * @param evt DOCUMENT ME!\r
204      */\r
205     public void mouseDragged(MouseEvent evt)\r
206     {\r
207         mouseDragging = true;\r
208 \r
209         int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
210         if(res<0)\r
211           res = 0;\r
212 \r
213         if(av.hasHiddenColumns)\r
214           res = av.getColumnSelection().adjustForHiddenColumns(res);\r
215 \r
216 \r
217         if(res> av.alignment.getWidth())\r
218         {\r
219           res = av.alignment.getWidth()-1;\r
220         }\r
221 \r
222         if (res < min)\r
223         {\r
224             min = res;\r
225         }\r
226 \r
227         if (res > max)\r
228         {\r
229             max = res;\r
230         }\r
231 \r
232 \r
233 \r
234         SequenceGroup sg = av.getSelectionGroup();\r
235 \r
236         if (sg != null)\r
237         {\r
238             stretchingGroup = true;\r
239 \r
240             if (!av.getColumnSelection().contains(res))\r
241             {\r
242                 av.getColumnSelection().addElement(res);\r
243             }\r
244 \r
245             if (res > sg.getStartRes())\r
246             {\r
247                 sg.setEndRes(res);\r
248             }\r
249             if (res < sg.getStartRes())\r
250             {\r
251                 sg.setStartRes(res);\r
252             }\r
253 \r
254             for (int i = min; i <= max; i++)\r
255             {\r
256                 if ((i < sg.getStartRes()) || (i > sg.getEndRes()))\r
257                 {\r
258                     av.getColumnSelection().removeElement(i);\r
259                 }\r
260                 else\r
261                 {\r
262                     av.getColumnSelection().addElement(i);\r
263                 }\r
264             }\r
265 \r
266             ap.repaint();\r
267         }\r
268     }\r
269 \r
270     public void mouseEntered(MouseEvent evt)\r
271     {\r
272       if(mouseDragging)\r
273         ap.seqPanel.scrollCanvas(null);\r
274     }\r
275 \r
276     public void mouseExited(MouseEvent evt)\r
277     {\r
278       if(mouseDragging)\r
279         ap.seqPanel.scrollCanvas(evt);\r
280     }\r
281 \r
282     public void mouseClicked(MouseEvent evt){}\r
283 \r
284     public void mouseMoved(MouseEvent evt)\r
285     {\r
286       if(!av.hasHiddenColumns)\r
287         return;\r
288 \r
289       int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
290 \r
291       res = av.getColumnSelection().adjustForHiddenColumns(res);\r
292 \r
293       reveal = null;\r
294       for(int i=0; i<av.getColumnSelection().getHiddenColumns().size(); i++)\r
295       {\r
296         int [] region = (int[])av.getColumnSelection().getHiddenColumns().elementAt(i);\r
297         if(res+1==region[0] || res-1==region[1])\r
298         {\r
299           reveal = region;\r
300           ToolTipManager.sharedInstance().registerComponent(this);\r
301           this.setToolTipText("Reveal Hidden Columns with Right Mouse Button");\r
302           break;\r
303         }\r
304         else\r
305           this.setToolTipText(null);\r
306 \r
307       }\r
308 \r
309       repaint();\r
310     }\r
311 \r
312     int [] reveal;\r
313 \r
314     /**\r
315      * DOCUMENT ME!\r
316      *\r
317      * @param g DOCUMENT ME!\r
318      */\r
319     public void paintComponent(Graphics g)\r
320     {\r
321         drawScale(g, av.getStartRes(), av.getEndRes(), getWidth(), getHeight());\r
322     }\r
323 \r
324     // scalewidth will normally be screenwidth,\r
325     public void drawScale(Graphics g, int startx, int endx, int width,\r
326         int height)\r
327     {\r
328         Graphics2D gg = (Graphics2D) g;\r
329         gg.setFont(av.getFont());\r
330 \r
331         if(av.antiAlias)\r
332           gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
333                               RenderingHints.VALUE_ANTIALIAS_ON);\r
334 \r
335         //Fill in the background\r
336         gg.setColor(Color.white);\r
337         gg.fillRect(0, 0, width, height);\r
338         gg.setColor(Color.black);\r
339 \r
340         //Fill the selected columns\r
341         ColumnSelection cs = av.getColumnSelection();\r
342         gg.setColor(new Color(220, 0, 0));\r
343 \r
344         for (int i = 0; i < cs.size(); i++)\r
345         {\r
346             int sel = cs.columnAt(i);\r
347             if(av.hasHiddenColumns)\r
348                 sel = av.getColumnSelection().findColumnPosition(sel);\r
349 \r
350             if ((sel >= startx) && (sel <= endx))\r
351             {\r
352                 gg.fillRect((sel - startx) * av.charWidth, 0, av.charWidth,\r
353                     getHeight());\r
354             }\r
355         }\r
356 \r
357         // Draw the scale numbers\r
358         gg.setColor(Color.black);\r
359 \r
360         int scalestartx = (startx / 10) * 10;\r
361 \r
362         FontMetrics fm = gg.getFontMetrics(av.getFont());\r
363         int y = av.charHeight - fm.getDescent();\r
364 \r
365         if ((scalestartx % 10) == 0)\r
366         {\r
367             scalestartx += 5;\r
368         }\r
369 \r
370         String string;\r
371         int maxX=0;\r
372 \r
373         for (int i = scalestartx; i < endx; i += 5)\r
374         {\r
375             if ((i % 10) == 0)\r
376             {\r
377                 string = String.valueOf(av.getColumnSelection().adjustForHiddenColumns(i));\r
378                 if ( (i - startx - 1) * av.charWidth > maxX)\r
379                 {\r
380                   gg.drawString(string,\r
381                                 (i - startx - 1) * av.charWidth, y);\r
382                   maxX = (i - startx + 1) * av.charWidth + fm.stringWidth(string);\r
383                 }\r
384 \r
385                 gg.drawLine( (int) ( ( (i - startx - 1) * av.charWidth) +\r
386                                     (av.charWidth / 2)), y + 2,\r
387                             (int) ( ( (i - startx - 1) * av.charWidth) +\r
388                                    (av.charWidth / 2)),\r
389                             y + (fm.getDescent() * 2));\r
390 \r
391             }\r
392             else\r
393             {\r
394                 gg.drawLine((int) (((i - startx - 1) * av.charWidth) +\r
395                     (av.charWidth / 2)), y + fm.getDescent(),\r
396                     (int) (((i - startx - 1) * av.charWidth) +\r
397                     (av.charWidth / 2)), y + (fm.getDescent() * 2));\r
398             }\r
399         }\r
400 \r
401         if (av.hasHiddenColumns)\r
402         {\r
403           gg.setColor(Color.blue);\r
404           int res;\r
405           if(av.getShowHiddenMarkers())\r
406           {\r
407             for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size();\r
408                  i++)\r
409             {\r
410 \r
411               res = av.getColumnSelection().findHiddenRegionPosition(i) -\r
412                   startx;\r
413 \r
414               if(res < 0 || res > endx-scalestartx)\r
415                 continue;\r
416 \r
417               gg.fillPolygon(new int[]\r
418                              {res * av.charWidth - av.charHeight / 4,\r
419                              res * av.charWidth + av.charHeight / 4,\r
420                              res * av.charWidth},\r
421                              new int[]\r
422                              {\r
423                              y - av.charHeight / 2, y - av.charHeight / 2,\r
424                              y + 8\r
425               }, 3);\r
426 \r
427             }\r
428           }\r
429 \r
430           if (reveal != null && reveal[0] > startx && reveal[0] < endx)\r
431           {\r
432             gg.drawString("Reveal Columns", reveal[0] * av.charWidth, 0);\r
433           }\r
434         }\r
435 \r
436 \r
437     }\r
438 }\r