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