Jalview 2.6 source licence
[jalview.git] / src / jalview / appletgui / ScalePanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.6)
3  * Copyright (C) 2010 J Procter, AM Waterhouse, 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   }
177
178   public void mouseReleased(MouseEvent evt)
179   {
180     mouseDragging = false;
181
182     int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
183
184     if (res > av.alignment.getWidth())
185     {
186       res = av.alignment.getWidth() - 1;
187     }
188
189     if (av.hasHiddenColumns)
190     {
191       res = av.getColumnSelection().adjustForHiddenColumns(res);
192     }
193
194     if (!stretchingGroup)
195     {
196       ap.paintAlignment(false);
197
198       return;
199     }
200
201     SequenceGroup sg = av.getSelectionGroup();
202
203     if (res > sg.getStartRes())
204     {
205       sg.setEndRes(res);
206     }
207     else if (res < sg.getStartRes())
208     {
209       sg.setStartRes(res);
210     }
211
212     stretchingGroup = false;
213     ap.paintAlignment(false);
214   }
215
216   public void mouseDragged(MouseEvent evt)
217   {
218     mouseDragging = true;
219
220     int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
221     if (res < 0)
222     {
223       res = 0;
224     }
225
226     if (av.hasHiddenColumns)
227     {
228       res = av.getColumnSelection().adjustForHiddenColumns(res);
229     }
230
231     if (res > av.alignment.getWidth())
232     {
233       res = av.alignment.getWidth() - 1;
234     }
235
236     if (res < min)
237     {
238       min = res;
239     }
240
241     if (res > max)
242     {
243       max = res;
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       int col;
267       for (int i = min; i <= max; i++)
268       {
269         col = av.getColumnSelection().adjustForHiddenColumns(i);
270
271         if ((col < sg.getStartRes()) || (col > sg.getEndRes()))
272         {
273           av.getColumnSelection().removeElement(col);
274         }
275         else
276         {
277           av.getColumnSelection().addElement(col);
278         }
279       }
280
281       ap.paintAlignment(false);
282     }
283   }
284
285   public void mouseEntered(MouseEvent evt)
286   {
287     if (mouseDragging)
288     {
289       ap.seqPanel.scrollCanvas(null);
290     }
291   }
292
293   public void mouseExited(MouseEvent evt)
294   {
295     if (mouseDragging)
296     {
297       ap.seqPanel.scrollCanvas(evt);
298     }
299   }
300
301   public void mouseClicked(MouseEvent evt)
302   {
303
304   }
305
306   public void mouseMoved(MouseEvent evt)
307   {
308     if (!av.hasHiddenColumns)
309     {
310       return;
311     }
312
313     int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
314
315     res = av.getColumnSelection().adjustForHiddenColumns(res);
316
317     reveal = null;
318     for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size(); i++)
319     {
320       int[] region = (int[]) av.getColumnSelection().getHiddenColumns()
321               .elementAt(i);
322       if (res + 1 == region[0] || res - 1 == region[1])
323       {
324         reveal = region;
325         break;
326       }
327     }
328
329     repaint();
330   }
331
332   public void update(Graphics g)
333   {
334     paint(g);
335   }
336
337   public void paint(Graphics g)
338   {
339     drawScale(g, av.getStartRes(), av.getEndRes(), getSize().width,
340             getSize().height);
341   }
342
343   // scalewidth will normally be screenwidth,
344   public void drawScale(Graphics gg, int startx, int endx, int width,
345           int height)
346   {
347     gg.setFont(av.getFont());
348
349     // Fill in the background
350     gg.setColor(Color.white);
351     gg.fillRect(0, 0, width, height);
352     gg.setColor(Color.black);
353
354     // Fill the selected columns
355     ColumnSelection cs = av.getColumnSelection();
356     gg.setColor(new Color(220, 0, 0));
357
358     for (int i = 0; i < cs.size(); i++)
359     {
360       int sel = cs.columnAt(i);
361       if (av.hasHiddenColumns)
362       {
363         sel = av.getColumnSelection().findColumnPosition(sel);
364       }
365
366       if ((sel >= startx) && (sel <= endx))
367       {
368         gg.fillRect((sel - startx) * av.charWidth, 0, av.charWidth,
369                 getSize().height);
370       }
371     }
372
373     // Draw the scale numbers
374     gg.setColor(Color.black);
375
376     int scalestartx = (startx / 10) * 10;
377
378     FontMetrics fm = gg.getFontMetrics(av.getFont());
379     int y = av.charHeight - fm.getDescent();
380
381     if ((scalestartx % 10) == 0)
382     {
383       scalestartx += 5;
384     }
385
386     String string;
387     int maxX = 0;
388
389     for (int i = scalestartx; i < endx; i += 5)
390     {
391       if ((i % 10) == 0)
392       {
393         string = String.valueOf(av.getColumnSelection()
394                 .adjustForHiddenColumns(i));
395         if ((i - startx - 1) * av.charWidth > maxX)
396         {
397           gg.drawString(string, (i - startx - 1) * av.charWidth, y);
398           maxX = (i - startx + 1) * av.charWidth + fm.stringWidth(string);
399         }
400
401         gg
402                 .drawLine(
403                         (int) (((i - startx - 1) * av.charWidth) + (av.charWidth / 2)),
404                         y + 2,
405                         (int) (((i - startx - 1) * av.charWidth) + (av.charWidth / 2)),
406                         y + (fm.getDescent() * 2));
407
408       }
409       else
410       {
411         gg
412                 .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 }