Hidden representatives moved from sequence to viewport
[jalview.git] / src / jalview / gui / ScalePanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 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 (SwingUtilities.isRightMouseButton(evt))\r
77         {\r
78           JPopupMenu pop = new JPopupMenu();\r
79           if (reveal != null)\r
80           {\r
81             JMenuItem item = new JMenuItem("Reveal");\r
82             item.addActionListener(new ActionListener()\r
83             {\r
84               public void actionPerformed(ActionEvent e)\r
85               {\r
86                 av.showColumn(reveal[0]);\r
87                 reveal = null;\r
88                 ap.repaint();\r
89                 if (ap.overviewPanel != null)\r
90                   ap.overviewPanel.updateOverviewImage();\r
91               }\r
92             });\r
93             pop.add(item);\r
94 \r
95             if (av.getColumnSelection().getHiddenColumns().size() > 1)\r
96             {\r
97               item = new JMenuItem("Reveal All");\r
98               item.addActionListener(new ActionListener()\r
99               {\r
100                 public void actionPerformed(ActionEvent e)\r
101                 {\r
102                   av.showAllHiddenColumns();\r
103                   reveal = null;\r
104                   ap.repaint();\r
105                   if (ap.overviewPanel != null)\r
106                     ap.overviewPanel.updateOverviewImage();\r
107                 }\r
108               });\r
109               pop.add(item);\r
110             }\r
111             pop.show(this, evt.getX(), evt.getY());\r
112           }\r
113           else if (av.getColumnSelection().contains(res))\r
114           {\r
115             JMenuItem item = new JMenuItem("Hide Columns");\r
116             item.addActionListener(new ActionListener()\r
117             {\r
118               public void actionPerformed(ActionEvent e)\r
119               {\r
120                 av.hideColumns(res, res);\r
121                 if(av.getSelectionGroup()!=null\r
122                    && av.getSelectionGroup().getSize()==av.alignment.getHeight())\r
123                   av.setSelectionGroup(null);\r
124 \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 // LEFT MOUSE TO SELECT\r
135         {\r
136           if (!evt.isControlDown() && !evt.isShiftDown())\r
137           {\r
138             av.getColumnSelection().clear();\r
139           }\r
140 \r
141           av.getColumnSelection().addElement(res);\r
142           SequenceGroup sg = new SequenceGroup();\r
143           for (int i = 0; i < av.alignment.getSequences().size(); i++)\r
144           {\r
145             sg.addSequence(av.alignment.getSequenceAt(i), false);\r
146           }\r
147 \r
148           sg.setStartRes(res);\r
149           sg.setEndRes(res);\r
150           av.setSelectionGroup(sg);\r
151 \r
152           if(evt.isShiftDown())\r
153           {\r
154             int min = Math.min(av.getColumnSelection().getMin(), res);\r
155             int max = Math.max(av.getColumnSelection().getMax(), res);\r
156             for (int i = min; i<max; i++)\r
157             {\r
158                 av.getColumnSelection().addElement(i);\r
159             }\r
160             sg.setStartRes(min);\r
161             sg.setEndRes(max);\r
162           }\r
163 \r
164 \r
165         }\r
166 \r
167 \r
168         ap.repaint();\r
169     }\r
170 \r
171     /**\r
172      * DOCUMENT ME!\r
173      *\r
174      * @param evt DOCUMENT ME!\r
175      */\r
176     public void mouseReleased(MouseEvent evt)\r
177     {\r
178         mouseDragging = false;\r
179 \r
180         int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
181 \r
182         if(res> av.alignment.getWidth())\r
183         {\r
184           res = av.alignment.getWidth()-1;\r
185         }\r
186 \r
187         if(av.hasHiddenColumns)\r
188           res = av.getColumnSelection().adjustForHiddenColumns(res);\r
189 \r
190         if (!stretchingGroup)\r
191         {\r
192             ap.repaint();\r
193 \r
194             return;\r
195         }\r
196 \r
197         SequenceGroup sg = av.getSelectionGroup();\r
198 \r
199         if(sg!=null){\r
200           if (res > sg.getStartRes())\r
201           {\r
202             sg.setEndRes(res);\r
203           }\r
204           else if (res < sg.getStartRes())\r
205           {\r
206             sg.setStartRes(res);\r
207           }\r
208         }\r
209         stretchingGroup = false;\r
210         ap.repaint();\r
211     }\r
212 \r
213     /**\r
214      * DOCUMENT ME!\r
215      *\r
216      * @param evt DOCUMENT ME!\r
217      */\r
218     public void mouseDragged(MouseEvent evt)\r
219     {\r
220         mouseDragging = true;\r
221 \r
222         int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
223         if(res<0)\r
224           res = 0;\r
225 \r
226         if(av.hasHiddenColumns)\r
227           res = av.getColumnSelection().adjustForHiddenColumns(res);\r
228 \r
229 \r
230         if(res> av.alignment.getWidth())\r
231         {\r
232           res = av.alignment.getWidth()-1;\r
233         }\r
234 \r
235         if (res < min)\r
236         {\r
237             min = res;\r
238         }\r
239 \r
240         if (res > max)\r
241         {\r
242             max = res;\r
243         }\r
244 \r
245 \r
246 \r
247         SequenceGroup sg = av.getSelectionGroup();\r
248 \r
249         if (sg != null)\r
250         {\r
251             stretchingGroup = true;\r
252 \r
253             if (!av.getColumnSelection().contains(res))\r
254             {\r
255                 av.getColumnSelection().addElement(res);\r
256             }\r
257 \r
258             if (res > sg.getStartRes())\r
259             {\r
260                 sg.setEndRes(res);\r
261             }\r
262             if (res < sg.getStartRes())\r
263             {\r
264                 sg.setStartRes(res);\r
265             }\r
266 \r
267             for (int i = min; i <= max; i++)\r
268             {\r
269                 if ((i < sg.getStartRes()) || (i > sg.getEndRes()))\r
270                 {\r
271                     av.getColumnSelection().removeElement(i);\r
272                 }\r
273                 else\r
274                 {\r
275                     av.getColumnSelection().addElement(i);\r
276                 }\r
277             }\r
278 \r
279             ap.repaint();\r
280         }\r
281     }\r
282 \r
283     public void mouseEntered(MouseEvent evt)\r
284     {\r
285       if(mouseDragging)\r
286         ap.seqPanel.scrollCanvas(null);\r
287     }\r
288 \r
289     public void mouseExited(MouseEvent evt)\r
290     {\r
291       if(mouseDragging)\r
292         ap.seqPanel.scrollCanvas(evt);\r
293     }\r
294 \r
295     public void mouseClicked(MouseEvent evt){}\r
296 \r
297     public void mouseMoved(MouseEvent evt)\r
298     {\r
299       if(!av.hasHiddenColumns)\r
300         return;\r
301 \r
302       int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
303 \r
304       res = av.getColumnSelection().adjustForHiddenColumns(res);\r
305 \r
306       reveal = null;\r
307       for(int i=0; i<av.getColumnSelection().getHiddenColumns().size(); i++)\r
308       {\r
309         int [] region = (int[])av.getColumnSelection().getHiddenColumns().elementAt(i);\r
310         if(res+1==region[0] || res-1==region[1])\r
311         {\r
312           reveal = region;\r
313           ToolTipManager.sharedInstance().registerComponent(this);\r
314           this.setToolTipText("Reveal Hidden Columns with Right Mouse Button");\r
315           break;\r
316         }\r
317         else\r
318           this.setToolTipText(null);\r
319 \r
320       }\r
321 \r
322       repaint();\r
323     }\r
324 \r
325     int [] reveal;\r
326 \r
327     /**\r
328      * DOCUMENT ME!\r
329      *\r
330      * @param g DOCUMENT ME!\r
331      */\r
332     public void paintComponent(Graphics g)\r
333     {\r
334         drawScale(g, av.getStartRes(), av.getEndRes(), getWidth(), getHeight());\r
335     }\r
336 \r
337     // scalewidth will normally be screenwidth,\r
338     public void drawScale(Graphics g, int startx, int endx, int width,\r
339         int height)\r
340     {\r
341         Graphics2D gg = (Graphics2D) g;\r
342         gg.setFont(av.getFont());\r
343 \r
344         if(av.antiAlias)\r
345           gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
346                               RenderingHints.VALUE_ANTIALIAS_ON);\r
347 \r
348         //Fill in the background\r
349         gg.setColor(Color.white);\r
350         gg.fillRect(0, 0, width, height);\r
351         gg.setColor(Color.black);\r
352 \r
353         //Fill the selected columns\r
354         ColumnSelection cs = av.getColumnSelection();\r
355         gg.setColor(new Color(220, 0, 0));\r
356 \r
357         for (int i = 0; i < cs.size(); i++)\r
358         {\r
359             int sel = cs.columnAt(i);\r
360             if(av.hasHiddenColumns)\r
361                 sel = av.getColumnSelection().findColumnPosition(sel);\r
362 \r
363             if ((sel >= startx) && (sel <= endx))\r
364             {\r
365                 gg.fillRect((sel - startx) * av.charWidth, 0, av.charWidth,\r
366                     getHeight());\r
367             }\r
368         }\r
369 \r
370         // Draw the scale numbers\r
371         gg.setColor(Color.black);\r
372 \r
373         int scalestartx = (startx / 10) * 10;\r
374 \r
375         FontMetrics fm = gg.getFontMetrics(av.getFont());\r
376         int y = av.charHeight - fm.getDescent();\r
377 \r
378         if ((scalestartx % 10) == 0)\r
379         {\r
380             scalestartx += 5;\r
381         }\r
382 \r
383         String string;\r
384         int maxX=0;\r
385 \r
386         for (int i = scalestartx; i < endx; i += 5)\r
387         {\r
388             if ((i % 10) == 0)\r
389             {\r
390                 string = String.valueOf(av.getColumnSelection().adjustForHiddenColumns(i));\r
391                 if ( (i - startx - 1) * av.charWidth > maxX)\r
392                 {\r
393                   gg.drawString(string,\r
394                                 (i - startx - 1) * av.charWidth, y);\r
395                   maxX = (i - startx + 1) * av.charWidth + fm.stringWidth(string);\r
396                 }\r
397 \r
398                 gg.drawLine( (int) ( ( (i - startx - 1) * av.charWidth) +\r
399                                     (av.charWidth / 2)), y + 2,\r
400                             (int) ( ( (i - startx - 1) * av.charWidth) +\r
401                                    (av.charWidth / 2)),\r
402                             y + (fm.getDescent() * 2));\r
403 \r
404             }\r
405             else\r
406             {\r
407                 gg.drawLine((int) (((i - startx - 1) * av.charWidth) +\r
408                     (av.charWidth / 2)), y + fm.getDescent(),\r
409                     (int) (((i - startx - 1) * av.charWidth) +\r
410                     (av.charWidth / 2)), y + (fm.getDescent() * 2));\r
411             }\r
412         }\r
413 \r
414         if (av.hasHiddenColumns)\r
415         {\r
416           gg.setColor(Color.blue);\r
417           int res;\r
418           if(av.getShowHiddenMarkers())\r
419           {\r
420             for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size();\r
421                  i++)\r
422             {\r
423 \r
424               res = av.getColumnSelection().findHiddenRegionPosition(i) -\r
425                   startx;\r
426 \r
427               if(res < 0 || res > endx-scalestartx)\r
428                 continue;\r
429 \r
430               gg.fillPolygon(new int[]\r
431                              {res * av.charWidth - av.charHeight / 4,\r
432                              res * av.charWidth + av.charHeight / 4,\r
433                              res * av.charWidth},\r
434                              new int[]\r
435                              {\r
436                              y - av.charHeight / 2, y - av.charHeight / 2,\r
437                              y + 8\r
438               }, 3);\r
439 \r
440             }\r
441           }\r
442 \r
443           if (reveal != null && reveal[0] > startx && reveal[0] < endx)\r
444           {\r
445             gg.drawString("Reveal Columns", reveal[0] * av.charWidth, 0);\r
446           }\r
447         }\r
448 \r
449 \r
450     }\r
451 }\r