2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3 * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
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.
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.
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
24 import java.awt.event.*;
27 import jalview.datamodel.*;
28 import jalview.math.*;
36 public class RotatableCanvas
37 extends JPanel implements MouseListener,
38 MouseMotionListener, KeyListener
40 RotatableMatrix idmat = new RotatableMatrix(3, 3);
41 RotatableMatrix objmat = new RotatableMatrix(3, 3);
42 RotatableMatrix rotmat = new RotatableMatrix(3, 3);
44 //RubberbandRectangle rubberband;
45 boolean drawAxes = true;
53 float[] centre = new float[3];
54 float[] width = new float[3];
55 float[] max = new float[3];
56 float[] min = new float[3];
71 float scalefactor = 1;
74 boolean showLabels = false;
75 Color bgColour = Color.black;
76 boolean applyToAllViews = false;
78 // Controller controller;
79 public RotatableCanvas(AlignmentPanel ap)
84 addMouseWheelListener(new MouseWheelListener()
86 public void mouseWheelMoved(MouseWheelEvent e)
88 if (e.getWheelRotation() > 0)
90 scale = (float) (scale * 1.1);
96 scale = (float) (scale * 0.9);
104 public void showLabels(boolean b)
110 public void setPoints(Vector points, int npoint)
112 this.points = points;
113 this.npoint = npoint;
114 ToolTipManager.sharedInstance().registerComponent(this);
115 ToolTipManager.sharedInstance().setInitialDelay(0);
116 ToolTipManager.sharedInstance().setDismissDelay(10000);
118 prefsize = getPreferredSize();
119 orig = new float[npoint][3];
121 for (int i = 0; i < npoint; i++)
123 SequencePoint sp = (SequencePoint) points.elementAt(i);
125 for (int j = 0; j < 3; j++)
127 orig[i][j] = sp.coord[j];
131 //Initialize the matrices to identity
132 for (int i = 0; i < 3; i++)
134 for (int j = 0; j < 3; j++)
138 idmat.addElement(i, j, 0);
139 objmat.addElement(i, j, 0);
140 rotmat.addElement(i, j, 0);
144 idmat.addElement(i, j, 0);
145 objmat.addElement(i, j, 0);
146 rotmat.addElement(i, j, 0);
151 axes = new float[3][3];
159 addMouseListener(this);
161 addMouseMotionListener(this);
165 public void initAxes()
167 for (int i = 0; i < 3; i++)
169 for (int j = 0; j < 3; j++)
186 public void findWidth()
191 max[0] = (float) - 1e30;
192 max[1] = (float) - 1e30;
193 max[2] = (float) - 1e30;
195 min[0] = (float) 1e30;
196 min[1] = (float) 1e30;
197 min[2] = (float) 1e30;
199 for (int i = 0; i < 3; i++)
201 for (int j = 0; j < npoint; j++)
203 SequencePoint sp = (SequencePoint) points.elementAt(j);
205 if (sp.coord[i] >= max[i])
207 max[i] = sp.coord[i];
210 if (sp.coord[i] <= min[i])
212 min[i] = sp.coord[i];
217 // System.out.println("xmax " + max[0] + " min " + min[0]);
218 //System.out.println("ymax " + max[1] + " min " + min[1]);
219 //System.out.println("zmax " + max[2] + " min " + min[2]);
220 width[0] = Math.abs(max[0] - min[0]);
221 width[1] = Math.abs(max[1] - min[1]);
222 width[2] = Math.abs(max[2] - min[2]);
226 if (width[1] > width[0])
231 if (width[2] > width[1])
236 //System.out.println("Maxwidth = " + maxwidth);
242 * @return DOCUMENT ME!
244 public float findScale()
253 height = getHeight();
257 width = prefsize.width;
258 height = prefsize.height;
270 return (float) ( (dim * scalefactor) / (2 * maxwidth));
276 public void findCentre()
278 //Find centre coordinate
281 centre[0] = (max[0] + min[0]) / 2;
282 centre[1] = (max[1] + min[1]) / 2;
283 centre[2] = (max[2] + min[2]) / 2;
285 // System.out.println("Centre x " + centre[0]);
286 //System.out.println("Centre y " + centre[1]);
287 //System.out.println("Centre z " + centre[2]);
293 * @return DOCUMENT ME!
295 public Dimension getPreferredSize()
297 if (prefsize != null)
303 return new Dimension(400, 400);
310 * @return DOCUMENT ME!
312 public Dimension getMinimumSize()
314 return getPreferredSize();
320 * @param g DOCUMENT ME!
322 public void paintComponent(Graphics g1)
325 Graphics2D g = (Graphics2D) g1;
327 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
328 RenderingHints.VALUE_ANTIALIAS_ON);
331 g.setFont(new Font("Verdana", Font.PLAIN, 18));
332 g.drawString("Calculating PCA....", 20, getHeight() / 2);
336 //Only create the image at the beginning -
337 if ( (img == null) || (prefsize.width != getWidth()) ||
338 (prefsize.height != getHeight()))
340 prefsize.width = getWidth();
341 prefsize.height = getHeight();
345 // System.out.println("New scale = " + scale);
346 img = createImage(getWidth(), getHeight());
347 ig = img.getGraphics();
350 drawBackground(ig, bgColour);
353 if (drawAxes == true)
358 g.drawImage(img, 0, 0, this);
365 * @param g DOCUMENT ME!
367 public void drawAxes(Graphics g)
370 g.setColor(Color.yellow);
372 for (int i = 0; i < 3; i++)
374 g.drawLine(getWidth() / 2, getHeight() / 2,
375 (int) ( (axes[i][0] * scale * max[0]) + (getWidth() / 2)),
376 (int) ( (axes[i][1] * scale * max[1]) + (getHeight() / 2)));
383 * @param g DOCUMENT ME!
384 * @param col DOCUMENT ME!
386 public void drawBackground(Graphics g, Color col)
389 g.fillRect(0, 0, prefsize.width, prefsize.height);
395 * @param g DOCUMENT ME!
397 public void drawScene(Graphics g1)
400 Graphics2D g = (Graphics2D) g1;
402 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
403 RenderingHints.VALUE_ANTIALIAS_ON);
405 int halfwidth = getWidth() / 2;
406 int halfheight = getHeight() / 2;
408 for (int i = 0; i < npoint; i++)
410 SequencePoint sp = (SequencePoint) points.elementAt(i);
411 int x = (int) ( (float) (sp.coord[0] - centre[0]) * scale) +
413 int y = (int) ( (float) (sp.coord[1] - centre[1]) * scale) +
415 float z = sp.coord[1] - centre[2];
417 if (av.getSequenceColour(sp.sequence) == Color.black)
419 g.setColor(Color.white);
423 g.setColor(av.getSequenceColour(sp.sequence));
426 if (av.getSelectionGroup() != null)
428 if (av.getSelectionGroup().getSequences(null).contains(
429 ( (SequencePoint) points.elementAt(i)).sequence))
431 g.setColor(Color.gray);
437 g.setColor(g.getColor().darker());
440 g.fillRect(x - 3, y - 3, 6, 6);
443 g.setColor(Color.red);
444 g.drawString( ( (SequencePoint) points.elementAt(i)).sequence.
450 // //Now the rectangle
451 // if (rectx2 != -1 && recty2 != -1) {
452 // g.setColor(Color.white);
454 // g.drawRect(rectx1,recty1,rectx2-rectx1,recty2-recty1);
461 * @return DOCUMENT ME!
463 public Dimension minimumsize()
471 * @return DOCUMENT ME!
473 public Dimension preferredsize()
481 * @param evt DOCUMENT ME!
483 public void keyTyped(KeyEvent evt)
490 * @param evt DOCUMENT ME!
492 public void keyReleased(KeyEvent evt)
499 * @param evt DOCUMENT ME!
501 public void keyPressed(KeyEvent evt)
503 if (evt.getKeyCode() == KeyEvent.VK_UP)
505 scalefactor = (float) (scalefactor * 1.1);
508 else if (evt.getKeyCode() == KeyEvent.VK_DOWN)
510 scalefactor = (float) (scalefactor * 0.9);
513 else if (evt.getKeyChar() == 's')
515 System.err.println("DEBUG: Rectangle selection"); // log.debug
517 if ( (rectx2 != -1) && (recty2 != -1))
519 rectSelect(rectx1, recty1, rectx2, recty2);
529 * @param evt DOCUMENT ME!
531 public void mouseClicked(MouseEvent evt)
538 * @param evt DOCUMENT ME!
540 public void mouseEntered(MouseEvent evt)
547 * @param evt DOCUMENT ME!
549 public void mouseExited(MouseEvent evt)
556 * @param evt DOCUMENT ME!
558 public void mouseReleased(MouseEvent evt)
565 * @param evt DOCUMENT ME!
567 public void mousePressed(MouseEvent evt)
587 SequenceI found = findPoint(x, y);
591 AlignmentPanel[] aps = getAssociatedPanels();
593 for (int a = 0; a < aps.length; a++)
595 if (aps[a].av.getSelectionGroup() != null)
597 aps[a].av.getSelectionGroup().addOrRemove(found, true);
601 aps[a].av.setSelectionGroup(new SequenceGroup());
602 aps[a].av.getSelectionGroup().addOrRemove(found, true);
603 aps[a].av.getSelectionGroup().setEndRes(
604 aps[a].av.alignment.getWidth() - 1);
608 PaintRefresher.Refresh(this, av.getSequenceSetId());
614 // private void fireSequenceSelectionEvent(Selection sel) {
615 // controller.handleSequenceSelectionEvent(new SequenceSelectionEvent(this,sel));
617 public void mouseMoved(MouseEvent evt)
619 SequenceI found = findPoint(evt.getX(), evt.getY());
623 this.setToolTipText(found.getName());
627 this.setToolTipText(null);
634 * @param evt DOCUMENT ME!
636 public void mouseDragged(MouseEvent evt)
641 //Check if this is a rectangle drawing drag
642 if ( (evt.getModifiers() & InputEvent.BUTTON2_MASK) != 0)
644 // rectx2 = evt.getX();
645 // recty2 = evt.getY();
649 rotmat.setIdentity();
651 rotmat.rotate( (float) (my - omy), 'x');
652 rotmat.rotate( (float) (mx - omx), 'y');
654 for (int i = 0; i < npoint; i++)
656 SequencePoint sp = (SequencePoint) points.elementAt(i);
657 sp.coord[0] -= centre[0];
658 sp.coord[1] -= centre[1];
659 sp.coord[2] -= centre[2];
661 //Now apply the rotation matrix
662 sp.coord = rotmat.vectorMultiply(sp.coord);
664 //Now translate back again
665 sp.coord[0] += centre[0];
666 sp.coord[1] += centre[1];
667 sp.coord[2] += centre[2];
670 for (int i = 0; i < 3; i++)
672 axes[i] = rotmat.vectorMultiply(axes[i]);
678 paint(this.getGraphics());
685 * @param x1 DOCUMENT ME!
686 * @param y1 DOCUMENT ME!
687 * @param x2 DOCUMENT ME!
688 * @param y2 DOCUMENT ME!
690 public void rectSelect(int x1, int y1, int x2, int y2)
692 for (int i = 0; i < npoint; i++)
694 SequencePoint sp = (SequencePoint) points.elementAt(i);
695 int tmp1 = (int) ( ( (sp.coord[0] - centre[0]) * scale) +
696 ( (float) getWidth() / 2.0));
697 int tmp2 = (int) ( ( (sp.coord[1] - centre[1]) * scale) +
698 ( (float) getHeight() / 2.0));
700 if ( (tmp1 > x1) && (tmp1 < x2) && (tmp2 > y1) && (tmp2 < y2))
704 if (!av.getSelectionGroup().getSequences(null).contains(sp.sequence))
706 av.getSelectionGroup().addSequence(sp.sequence, true);
713 // fireSequenceSelectionEvent(av.getSelection());
720 * @param x DOCUMENT ME!
721 * @param y DOCUMENT ME!
723 * @return DOCUMENT ME!
725 public SequenceI findPoint(int x, int y)
727 int halfwidth = getWidth() / 2;
728 int halfheight = getHeight() / 2;
732 for (int i = 0; i < npoint; i++)
734 SequencePoint sp = (SequencePoint) points.elementAt(i);
735 int px = (int) ( (float) (sp.coord[0] - centre[0]) * scale) +
737 int py = (int) ( (float) (sp.coord[1] - centre[1]) * scale) +
740 if ( (Math.abs(px - x) < 3) && (Math.abs(py - y) < 3))
748 return ( (SequencePoint) points.elementAt(found)).sequence;
756 AlignmentPanel[] getAssociatedPanels()
760 return PaintRefresher.getAssociatedPanels(av.getSequenceSetId());
764 return new AlignmentPanel[]