2 * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3 * Copyright (C) 2009 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 extends JPanel implements MouseListener,
37 MouseMotionListener, KeyListener
39 RotatableMatrix idmat = new RotatableMatrix(3, 3);
41 RotatableMatrix objmat = new RotatableMatrix(3, 3);
43 RotatableMatrix rotmat = new RotatableMatrix(3, 3);
45 // RubberbandRectangle rubberband;
46 boolean drawAxes = true;
62 float[] centre = new float[3];
64 float[] width = new float[3];
66 float[] max = new float[3];
68 float[] min = new float[3];
98 float scalefactor = 1;
104 boolean showLabels = false;
106 Color bgColour = Color.black;
108 boolean applyToAllViews = false;
110 // Controller controller;
111 public RotatableCanvas(AlignmentPanel ap)
116 addMouseWheelListener(new MouseWheelListener()
118 public void mouseWheelMoved(MouseWheelEvent e)
120 if (e.getWheelRotation() > 0)
122 scale = (float) (scale * 1.1);
128 scale = (float) (scale * 0.9);
136 public void showLabels(boolean b)
142 public void setPoints(Vector points, int npoint)
144 this.points = points;
145 this.npoint = npoint;
146 ToolTipManager.sharedInstance().registerComponent(this);
147 ToolTipManager.sharedInstance().setInitialDelay(0);
148 ToolTipManager.sharedInstance().setDismissDelay(10000);
150 prefsize = getPreferredSize();
151 orig = new float[npoint][3];
153 for (int i = 0; i < npoint; i++)
155 SequencePoint sp = (SequencePoint) points.elementAt(i);
157 for (int j = 0; j < 3; j++)
159 orig[i][j] = sp.coord[j];
163 // Initialize the matrices to identity
164 for (int i = 0; i < 3; i++)
166 for (int j = 0; j < 3; j++)
170 idmat.addElement(i, j, 0);
171 objmat.addElement(i, j, 0);
172 rotmat.addElement(i, j, 0);
176 idmat.addElement(i, j, 0);
177 objmat.addElement(i, j, 0);
178 rotmat.addElement(i, j, 0);
183 axes = new float[3][3];
191 addMouseListener(this);
193 addMouseMotionListener(this);
197 public void initAxes()
199 for (int i = 0; i < 3; i++)
201 for (int j = 0; j < 3; j++)
218 public void findWidth()
223 max[0] = (float) -1e30;
224 max[1] = (float) -1e30;
225 max[2] = (float) -1e30;
227 min[0] = (float) 1e30;
228 min[1] = (float) 1e30;
229 min[2] = (float) 1e30;
231 for (int i = 0; i < 3; i++)
233 for (int j = 0; j < npoint; j++)
235 SequencePoint sp = (SequencePoint) points.elementAt(j);
237 if (sp.coord[i] >= max[i])
239 max[i] = sp.coord[i];
242 if (sp.coord[i] <= min[i])
244 min[i] = sp.coord[i];
249 // System.out.println("xmax " + max[0] + " min " + min[0]);
250 // System.out.println("ymax " + max[1] + " min " + min[1]);
251 // System.out.println("zmax " + max[2] + " min " + min[2]);
252 width[0] = Math.abs(max[0] - min[0]);
253 width[1] = Math.abs(max[1] - min[1]);
254 width[2] = Math.abs(max[2] - min[2]);
258 if (width[1] > width[0])
263 if (width[2] > width[1])
268 // System.out.println("Maxwidth = " + maxwidth);
274 * @return DOCUMENT ME!
276 public float findScale()
285 height = getHeight();
289 width = prefsize.width;
290 height = prefsize.height;
302 return (float) ((dim * scalefactor) / (2 * maxwidth));
308 public void findCentre()
310 // Find centre coordinate
313 centre[0] = (max[0] + min[0]) / 2;
314 centre[1] = (max[1] + min[1]) / 2;
315 centre[2] = (max[2] + min[2]) / 2;
317 // System.out.println("Centre x " + centre[0]);
318 // System.out.println("Centre y " + centre[1]);
319 // System.out.println("Centre z " + centre[2]);
325 * @return DOCUMENT ME!
327 public Dimension getPreferredSize()
329 if (prefsize != null)
335 return new Dimension(400, 400);
342 * @return DOCUMENT ME!
344 public Dimension getMinimumSize()
346 return getPreferredSize();
355 public void paintComponent(Graphics g1)
358 Graphics2D g = (Graphics2D) g1;
360 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
361 RenderingHints.VALUE_ANTIALIAS_ON);
364 g.setFont(new Font("Verdana", Font.PLAIN, 18));
365 g.drawString("Calculating PCA....", 20, getHeight() / 2);
369 // Only create the image at the beginning -
370 if ((img == null) || (prefsize.width != getWidth())
371 || (prefsize.height != getHeight()))
373 prefsize.width = getWidth();
374 prefsize.height = getHeight();
378 // System.out.println("New scale = " + scale);
379 img = createImage(getWidth(), getHeight());
380 ig = img.getGraphics();
383 drawBackground(ig, bgColour);
386 if (drawAxes == true)
391 g.drawImage(img, 0, 0, this);
401 public void drawAxes(Graphics g)
404 g.setColor(Color.yellow);
406 for (int i = 0; i < 3; i++)
408 g.drawLine(getWidth() / 2, getHeight() / 2, (int) ((axes[i][0]
409 * scale * max[0]) + (getWidth() / 2)), (int) ((axes[i][1]
410 * scale * max[1]) + (getHeight() / 2)));
422 public void drawBackground(Graphics g, Color col)
425 g.fillRect(0, 0, prefsize.width, prefsize.height);
434 public void drawScene(Graphics g1)
437 Graphics2D g = (Graphics2D) g1;
439 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
440 RenderingHints.VALUE_ANTIALIAS_ON);
442 int halfwidth = getWidth() / 2;
443 int halfheight = getHeight() / 2;
445 for (int i = 0; i < npoint; i++)
447 SequencePoint sp = (SequencePoint) points.elementAt(i);
448 int x = (int) ((float) (sp.coord[0] - centre[0]) * scale) + halfwidth;
449 int y = (int) ((float) (sp.coord[1] - centre[1]) * scale)
451 float z = sp.coord[1] - centre[2];
453 if (av.getSequenceColour(sp.sequence) == Color.black)
455 g.setColor(Color.white);
459 g.setColor(av.getSequenceColour(sp.sequence));
462 if (av.getSelectionGroup() != null)
464 if (av.getSelectionGroup().getSequences(null).contains(
465 ((SequencePoint) points.elementAt(i)).sequence))
467 g.setColor(Color.gray);
473 g.setColor(g.getColor().darker());
476 g.fillRect(x - 3, y - 3, 6, 6);
479 g.setColor(Color.red);
480 g.drawString(((SequencePoint) points.elementAt(i)).sequence
481 .getName(), x - 3, y - 4);
485 // //Now the rectangle
486 // if (rectx2 != -1 && recty2 != -1) {
487 // g.setColor(Color.white);
489 // g.drawRect(rectx1,recty1,rectx2-rectx1,recty2-recty1);
496 * @return DOCUMENT ME!
498 public Dimension minimumsize()
506 * @return DOCUMENT ME!
508 public Dimension preferredsize()
519 public void keyTyped(KeyEvent evt)
529 public void keyReleased(KeyEvent evt)
539 public void keyPressed(KeyEvent evt)
541 if (evt.getKeyCode() == KeyEvent.VK_UP)
543 scalefactor = (float) (scalefactor * 1.1);
546 else if (evt.getKeyCode() == KeyEvent.VK_DOWN)
548 scalefactor = (float) (scalefactor * 0.9);
551 else if (evt.getKeyChar() == 's')
553 System.err.println("DEBUG: Rectangle selection"); // log.debug
555 if ((rectx2 != -1) && (recty2 != -1))
557 rectSelect(rectx1, recty1, rectx2, recty2);
570 public void mouseClicked(MouseEvent evt)
580 public void mouseEntered(MouseEvent evt)
590 public void mouseExited(MouseEvent evt)
600 public void mouseReleased(MouseEvent evt)
610 public void mousePressed(MouseEvent evt)
630 SequenceI found = findPoint(x, y);
634 AlignmentPanel[] aps = getAssociatedPanels();
636 for (int a = 0; a < aps.length; a++)
638 if (aps[a].av.getSelectionGroup() != null)
640 aps[a].av.getSelectionGroup().addOrRemove(found, true);
644 aps[a].av.setSelectionGroup(new SequenceGroup());
645 aps[a].av.getSelectionGroup().addOrRemove(found, true);
646 aps[a].av.getSelectionGroup().setEndRes(
647 aps[a].av.alignment.getWidth() - 1);
650 PaintRefresher.Refresh(this, av.getSequenceSetId());
651 // canonical selection is sent to other listeners
658 // private void fireSequenceSelectionEvent(Selection sel) {
659 // controller.handleSequenceSelectionEvent(new
660 // SequenceSelectionEvent(this,sel));
662 public void mouseMoved(MouseEvent evt)
664 SequenceI found = findPoint(evt.getX(), evt.getY());
668 this.setToolTipText(found.getName());
672 this.setToolTipText(null);
682 public void mouseDragged(MouseEvent evt)
687 // Check if this is a rectangle drawing drag
688 if ((evt.getModifiers() & InputEvent.BUTTON2_MASK) != 0)
690 // rectx2 = evt.getX();
691 // recty2 = evt.getY();
695 rotmat.setIdentity();
697 rotmat.rotate((float) (my - omy), 'x');
698 rotmat.rotate((float) (mx - omx), 'y');
700 for (int i = 0; i < npoint; i++)
702 SequencePoint sp = (SequencePoint) points.elementAt(i);
703 sp.coord[0] -= centre[0];
704 sp.coord[1] -= centre[1];
705 sp.coord[2] -= centre[2];
707 // Now apply the rotation matrix
708 sp.coord = rotmat.vectorMultiply(sp.coord);
710 // Now translate back again
711 sp.coord[0] += centre[0];
712 sp.coord[1] += centre[1];
713 sp.coord[2] += centre[2];
716 for (int i = 0; i < 3; i++)
718 axes[i] = rotmat.vectorMultiply(axes[i]);
724 paint(this.getGraphics());
740 public void rectSelect(int x1, int y1, int x2, int y2)
742 for (int i = 0; i < npoint; i++)
744 SequencePoint sp = (SequencePoint) points.elementAt(i);
745 int tmp1 = (int) (((sp.coord[0] - centre[0]) * scale) + ((float) getWidth() / 2.0));
746 int tmp2 = (int) (((sp.coord[1] - centre[1]) * scale) + ((float) getHeight() / 2.0));
748 if ((tmp1 > x1) && (tmp1 < x2) && (tmp2 > y1) && (tmp2 < y2))
752 if (!av.getSelectionGroup().getSequences(null).contains(
755 av.getSelectionGroup().addSequence(sp.sequence, true);
762 // fireSequenceSelectionEvent(av.getSelection());
774 * @return DOCUMENT ME!
776 public SequenceI findPoint(int x, int y)
778 int halfwidth = getWidth() / 2;
779 int halfheight = getHeight() / 2;
783 for (int i = 0; i < npoint; i++)
785 SequencePoint sp = (SequencePoint) points.elementAt(i);
786 int px = (int) ((float) (sp.coord[0] - centre[0]) * scale)
788 int py = (int) ((float) (sp.coord[1] - centre[1]) * scale)
791 if ((Math.abs(px - x) < 3) && (Math.abs(py - y) < 3))
799 return ((SequencePoint) points.elementAt(found)).sequence;
807 AlignmentPanel[] getAssociatedPanels()
811 return PaintRefresher.getAssociatedPanels(av.getSequenceSetId());
815 return new AlignmentPanel[]