First attempt at hidden regions
[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 \r
47     // wants to delete columns\r
48     public ScalePanel(AlignViewport av, AlignmentPanel ap)\r
49     {\r
50         this.av = av;\r
51         this.ap = ap;\r
52 \r
53         addMouseListener(this);\r
54         addMouseMotionListener(this);\r
55     }\r
56 \r
57     /**\r
58      * DOCUMENT ME!\r
59      *\r
60      * @param evt DOCUMENT ME!\r
61      */\r
62     public void mousePressed(MouseEvent evt)\r
63     {\r
64         int x = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
65         final int res;\r
66 \r
67         if(av.hasHiddenColumns)\r
68           res = av.getColumnSelection().adjustForHiddenColumns(x);\r
69         else\r
70           res = x;\r
71 \r
72         min = res;\r
73         max = res;\r
74 \r
75         if(reveal != null)\r
76         {\r
77           av.getColumnSelection().revealHiddenColumns(reveal[0], av);\r
78           reveal = null;\r
79           return;\r
80         }\r
81 \r
82         if (av.getColumnSelection().contains(res))\r
83         {\r
84           if( SwingUtilities.isRightMouseButton(evt))\r
85           {\r
86             JPopupMenu pop = new JPopupMenu();\r
87             JMenuItem item = new JMenuItem("Hide Columns");\r
88             item.addActionListener(new ActionListener()\r
89             {\r
90               public void actionPerformed(ActionEvent e)\r
91               {\r
92                 av.getColumnSelection().hideColumns(res, av);\r
93               }\r
94             });\r
95             pop.add(item);\r
96             pop.show(this, evt.getX(), evt.getY());\r
97 \r
98           }\r
99           else\r
100           {\r
101             av.getColumnSelection().removeElement(res);\r
102             ap.annotationPanel.removeEditableColumn(res);\r
103           }\r
104         }\r
105         else\r
106         {\r
107             av.getColumnSelection().addElement(res);\r
108             SequenceGroup sg = new SequenceGroup();\r
109 \r
110             for (int i = 0; i < av.alignment.getSequences().size(); i++)\r
111             {\r
112                 sg.addSequence(av.alignment.getSequenceAt(i), false);\r
113             }\r
114 \r
115             sg.setStartRes(res);\r
116             sg.setEndRes(res);\r
117             av.setSelectionGroup(sg);\r
118         }\r
119 \r
120 \r
121         ap.repaint();\r
122     }\r
123 \r
124     /**\r
125      * DOCUMENT ME!\r
126      *\r
127      * @param evt DOCUMENT ME!\r
128      */\r
129     public void mouseReleased(MouseEvent evt)\r
130     {\r
131         int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
132 \r
133         if(av.hasHiddenColumns)\r
134           res = av.getColumnSelection().adjustForHiddenColumns(res);\r
135 \r
136         if (av.getColumnSelection() != null)\r
137         {\r
138             for (int i = 0; i < av.getColumnSelection().size(); i++)\r
139             {\r
140                 ap.annotationPanel.addEditableColumn(av.getColumnSelection()\r
141                                                        .columnAt(i));\r
142             }\r
143         }\r
144 \r
145         if (!stretchingGroup)\r
146         {\r
147             ap.repaint();\r
148 \r
149             return;\r
150         }\r
151 \r
152         SequenceGroup sg = av.getSelectionGroup();\r
153 \r
154         if (res > sg.getStartRes())\r
155         {\r
156             sg.setEndRes(res);\r
157         }\r
158         else if (res < sg.getStartRes())\r
159         {\r
160             sg.setStartRes(res);\r
161         }\r
162 \r
163         stretchingGroup = false;\r
164         ap.repaint();\r
165     }\r
166 \r
167     /**\r
168      * DOCUMENT ME!\r
169      *\r
170      * @param evt DOCUMENT ME!\r
171      */\r
172     public void mouseDragged(MouseEvent evt)\r
173     {\r
174         int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
175 \r
176         if(av.hasHiddenColumns)\r
177           res = av.getColumnSelection().adjustForHiddenColumns(res);\r
178 \r
179         if (res < min)\r
180         {\r
181             min = res;\r
182         }\r
183 \r
184         if (res > max)\r
185         {\r
186             max = res;\r
187         }\r
188 \r
189         SequenceGroup sg = av.getSelectionGroup();\r
190 \r
191         if (sg != null)\r
192         {\r
193             stretchingGroup = true;\r
194 \r
195             if (!av.getColumnSelection().contains(res))\r
196             {\r
197                 av.getColumnSelection().addElement(res);\r
198             }\r
199 \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             for (int i = min; i <= max; i++)\r
210             {\r
211                 if ((i < sg.getStartRes()) || (i > sg.getEndRes()))\r
212                 {\r
213                     av.getColumnSelection().removeElement(i);\r
214                     ap.annotationPanel.removeEditableColumn(res);\r
215                 }\r
216                 else\r
217                 {\r
218                     av.getColumnSelection().addElement(i);\r
219                 }\r
220             }\r
221 \r
222             ap.repaint();\r
223         }\r
224     }\r
225 \r
226     public void mouseEntered(MouseEvent evt){}\r
227     public void mouseExited(MouseEvent evt){}\r
228     public void mouseClicked(MouseEvent evt){}\r
229 \r
230     public void mouseMoved(MouseEvent evt)\r
231     {\r
232       if(!av.hasHiddenColumns)\r
233         return;\r
234 \r
235       int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
236 \r
237       res = av.getColumnSelection().adjustForHiddenColumns(res);\r
238 \r
239       reveal = null;\r
240       for(int i=0; i<av.getColumnSelection().getHiddenColumns().size(); i++)\r
241       {\r
242         int [] region = (int[])av.getColumnSelection().getHiddenColumns().elementAt(i);\r
243         if(res+1==region[0] || res-1==region[1])\r
244         {\r
245           reveal = region;\r
246           break;\r
247         }\r
248       }\r
249 \r
250       repaint();\r
251     }\r
252 \r
253     int [] reveal;\r
254 \r
255     /**\r
256      * DOCUMENT ME!\r
257      *\r
258      * @param g DOCUMENT ME!\r
259      */\r
260     public void paintComponent(Graphics g)\r
261     {\r
262         drawScale(g, av.getStartRes(), av.getEndRes(), getWidth(), getHeight());\r
263     }\r
264 \r
265     // scalewidth will normally be screenwidth,\r
266     public void drawScale(Graphics g, int startx, int endx, int width,\r
267         int height)\r
268     {\r
269         Graphics2D gg = (Graphics2D) g;\r
270         gg.setFont(av.getFont());\r
271 \r
272         if(av.antiAlias)\r
273           gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
274                               RenderingHints.VALUE_ANTIALIAS_ON);\r
275 \r
276         //Fill in the background\r
277         gg.setColor(Color.white);\r
278         gg.fillRect(0, 0, width, height);\r
279         gg.setColor(Color.black);\r
280 \r
281         //Fill the selected columns\r
282         ColumnSelection cs = av.getColumnSelection();\r
283         gg.setColor(new Color(220, 0, 0));\r
284 \r
285         for (int i = 0; i < cs.size(); i++)\r
286         {\r
287             int sel = cs.columnAt(i);\r
288             if(av.hasHiddenColumns)\r
289                 sel = av.getColumnSelection().findColumnPosition(sel);\r
290 \r
291             if ((sel >= startx) && (sel <= endx))\r
292             {\r
293                 gg.fillRect((sel - startx) * av.charWidth, 0, av.charWidth,\r
294                     getHeight());\r
295             }\r
296         }\r
297 \r
298         // Draw the scale numbers\r
299         gg.setColor(Color.black);\r
300 \r
301         int scalestartx = (startx / 10) * 10;\r
302 \r
303         FontMetrics fm = gg.getFontMetrics(av.getFont());\r
304         int y = av.charHeight - fm.getDescent();\r
305 \r
306         if ((scalestartx % 10) == 0)\r
307         {\r
308             scalestartx += 5;\r
309         }\r
310 \r
311         for (int i = scalestartx; i < endx; i += 5)\r
312         {\r
313             if ((i % 10) == 0)\r
314             {\r
315                 gg.drawString(String.valueOf(av.getColumnSelection().adjustForHiddenColumns(i)),\r
316                     (i - startx - 1) * av.charWidth, y);\r
317                 gg.drawLine((int) (((i - startx - 1) * av.charWidth) +\r
318                     (av.charWidth / 2)), y + 2,\r
319                     (int) (((i - startx - 1) * av.charWidth) +\r
320                     (av.charWidth / 2)), y + (fm.getDescent() * 2));\r
321             }\r
322             else\r
323             {\r
324                 gg.drawLine((int) (((i - startx - 1) * av.charWidth) +\r
325                     (av.charWidth / 2)), y + fm.getDescent(),\r
326                     (int) (((i - startx - 1) * av.charWidth) +\r
327                     (av.charWidth / 2)), y + (fm.getDescent() * 2));\r
328             }\r
329         }\r
330 \r
331         if (av.hasHiddenColumns)\r
332         {\r
333           gg.setColor(Color.blue);\r
334           int res;\r
335           for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size(); i++)\r
336           {\r
337             res = av.getColumnSelection().findHiddenRegionPosition( i )-startx;\r
338 \r
339             gg.fillPolygon(new int[] { res*av.charWidth - 4,\r
340                                          res*av.charWidth + 4,\r
341                                          res*av.charWidth },\r
342                                 new int[]\r
343                                 {\r
344                                     y-av.charHeight/2 , y-av.charHeight/2 ,\r
345                                     y + 8\r
346                                 }, 3);\r
347 \r
348           }\r
349 \r
350           if (reveal != null && reveal[0] > startx && reveal[0] < endx)\r
351           {\r
352             gg.drawString("Reveal Columns", reveal[0] * av.charWidth, 0);\r
353           }\r
354         }\r
355 \r
356 \r
357     }\r
358 }\r