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