2 * Jalview - A Sequence Alignment Editor and Viewer
\r
3 * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
\r
5 * This program is free software; you can redistribute it and/or
\r
6 * modify it under the terms of the GNU General Public License
\r
7 * as published by the Free Software Foundation; either version 2
\r
8 * of the License, or (at your option) any later version.
\r
10 * This program is distributed in the hope that it will be useful,
\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 * GNU General Public License for more details.
\r
15 * You should have received a copy of the GNU General Public License
\r
16 * along with this program; if not, write to the Free Software
\r
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
\r
20 package jalview.appletgui;
\r
25 import java.awt.event.*;
\r
27 import jalview.datamodel.*;
\r
28 import jalview.math.*;
\r
29 import jalview.util.*;
\r
31 public class RotatableCanvas
\r
32 extends Panel implements MouseListener,
\r
33 MouseMotionListener,
\r
36 RotatableMatrix idmat = new RotatableMatrix(3, 3);
\r
37 RotatableMatrix objmat = new RotatableMatrix(3, 3);
\r
38 RotatableMatrix rotmat = new RotatableMatrix(3, 3);
\r
42 //RubberbandRectangle rubberband;
\r
44 boolean drawAxes = true;
\r
56 float centre[] = new float[3];
\r
57 float width[] = new float[3];
\r
59 float max[] = new float[3];
\r
60 float min[] = new float[3];
\r
82 float scalefactor = 1;
\r
85 boolean showLabels = false;
\r
87 public RotatableCanvas(AlignViewport av)
\r
92 public void showLabels(boolean b)
\r
98 public void setPoints(Vector points, int npoint)
\r
100 this.points = points;
\r
101 this.npoint = npoint;
\r
102 PaintRefresher.Register(this, av.getSequenceSetId());
\r
104 prefsize = getPreferredSize();
\r
105 orig = new float[npoint][3];
\r
107 for (int i = 0; i < npoint; i++)
\r
109 SequencePoint sp = (SequencePoint) points.elementAt(i);
\r
110 for (int j = 0; j < 3; j++)
\r
112 orig[i][j] = sp.coord[j];
\r
115 //Initialize the matrices to identity
\r
117 for (int i = 0; i < 3; i++)
\r
119 for (int j = 0; j < 3; j++)
\r
123 idmat.addElement(i, j, 0);
\r
124 objmat.addElement(i, j, 0);
\r
125 rotmat.addElement(i, j, 0);
\r
129 idmat.addElement(i, j, 0);
\r
130 objmat.addElement(i, j, 0);
\r
131 rotmat.addElement(i, j, 0);
\r
136 axes = new float[3][3];
\r
142 scale = findScale();
\r
144 // System.out.println("Scale factor = " + scale);
\r
146 addMouseListener(this);
\r
147 addKeyListener(this);
\r
148 // if (getParent() != null) {
\r
149 // getParent().addKeyListener(this);
\r
151 addMouseMotionListener(this);
\r
154 // rubberband = new RubberbandRectangle(this);
\r
155 // rubberband.setActive(true);
\r
156 // rubberband.addListener(this);
\r
159 /* public boolean handleSequenceSelectionEvent(SequenceSelectionEvent evt) {
\r
160 redrawneeded = true;
\r
165 public void removeNotify() {
\r
166 controller.removeListener(this);
\r
167 super.removeNotify();
\r
170 public void initAxes()
\r
172 for (int i = 0; i < 3; i++)
\r
174 for (int j = 0; j < 3; j++)
\r
188 public void findWidth()
\r
190 max = new float[3];
\r
191 min = new float[3];
\r
193 max[0] = (float) - 1e30;
\r
194 max[1] = (float) - 1e30;
\r
195 max[2] = (float) - 1e30;
\r
197 min[0] = (float) 1e30;
\r
198 min[1] = (float) 1e30;
\r
199 min[2] = (float) 1e30;
\r
201 for (int i = 0; i < 3; i++)
\r
203 for (int j = 0; j < npoint; j++)
\r
205 SequencePoint sp = (SequencePoint) points.elementAt(j);
\r
206 if (sp.coord[i] >= max[i])
\r
208 max[i] = sp.coord[i];
\r
210 if (sp.coord[i] <= min[i])
\r
212 min[i] = sp.coord[i];
\r
217 // System.out.println("xmax " + max[0] + " min " + min[0]);
\r
218 //System.out.println("ymax " + max[1] + " min " + min[1]);
\r
219 //System.out.println("zmax " + max[2] + " min " + min[2]);
\r
221 width[0] = Math.abs(max[0] - min[0]);
\r
222 width[1] = Math.abs(max[1] - min[1]);
\r
223 width[2] = Math.abs(max[2] - min[2]);
\r
225 maxwidth = width[0];
\r
227 if (width[1] > width[0])
\r
229 maxwidth = width[1];
\r
231 if (width[2] > width[1])
\r
233 maxwidth = width[2];
\r
236 //System.out.println("Maxwidth = " + maxwidth);
\r
239 public float findScale()
\r
241 int dim, width, height;
\r
242 if (getSize().width != 0)
\r
244 width = getSize().width;
\r
245 height = getSize().height;
\r
249 width = prefsize.width;
\r
250 height = prefsize.height;
\r
253 if (width < height)
\r
262 return (float) (dim * scalefactor / (2 * maxwidth));
\r
265 public void findCentre()
\r
267 //Find centre coordinate
\r
270 centre[0] = (max[0] + min[0]) / 2;
\r
271 centre[1] = (max[1] + min[1]) / 2;
\r
272 centre[2] = (max[2] + min[2]) / 2;
\r
274 // System.out.println("Centre x " + centre[0]);
\r
275 //System.out.println("Centre y " + centre[1]);
\r
276 //System.out.println("Centre z " + centre[2]);
\r
279 public Dimension getPreferredSize()
\r
281 if (prefsize != null)
\r
287 return new Dimension(400, 400);
\r
291 public Dimension getMinimumSize()
\r
293 return getPreferredSize();
\r
296 public void update(Graphics g)
\r
301 public void paint(Graphics g)
\r
303 if (points == null)
\r
305 g.setFont(new Font("Verdana", Font.PLAIN, 18));
\r
306 g.drawString("Calculating PCA....", 20, getSize().height / 2);
\r
311 //Only create the image at the beginning -
\r
312 if ( (img == null) || (prefsize.width != getSize().width) ||
\r
313 (prefsize.height != getSize().height))
\r
315 prefsize.width = getSize().width;
\r
316 prefsize.height = getSize().height;
\r
318 scale = findScale();
\r
320 // System.out.println("New scale = " + scale);
\r
321 img = createImage(getSize().width, getSize().height);
\r
322 ig = img.getGraphics();
\r
326 drawBackground(ig, Color.black);
\r
328 if (drawAxes == true)
\r
333 if (tooltip != null)
\r
335 ig.setColor(Color.red);
\r
336 ig.drawString(tooltip, toolx, tooly);
\r
339 g.drawImage(img, 0, 0, this);
\r
343 public void drawAxes(Graphics g)
\r
346 g.setColor(Color.yellow);
\r
347 for (int i = 0; i < 3; i++)
\r
349 g.drawLine(getSize().width / 2, getSize().height / 2,
\r
350 (int) (axes[i][0] * scale * max[0] + getSize().width / 2),
\r
351 (int) (axes[i][1] * scale * max[1] + getSize().height / 2));
\r
355 public void drawBackground(Graphics g, Color col)
\r
358 g.fillRect(0, 0, prefsize.width, prefsize.height);
\r
361 public void drawScene(Graphics g)
\r
363 //boolean darker = false;
\r
365 int halfwidth = getSize().width / 2;
\r
366 int halfheight = getSize().height / 2;
\r
368 for (int i = 0; i < npoint; i++)
\r
370 SequencePoint sp = (SequencePoint) points.elementAt(i);
\r
371 int x = (int) ( (float) (sp.coord[0] - centre[0]) * scale) + halfwidth;
\r
372 int y = (int) ( (float) (sp.coord[1] - centre[1]) * scale) + halfheight;
\r
373 float z = sp.coord[1] - centre[2];
\r
375 if (av.getSequenceColour(sp.sequence) == Color.black)
\r
377 g.setColor(Color.white);
\r
381 g.setColor(av.getSequenceColour(sp.sequence));
\r
384 if (av.getSelectionGroup() != null)
\r
386 if (av.getSelectionGroup().getSequences(null).contains( ( (
\r
387 SequencePoint) points.
\r
388 elementAt(i)).sequence))
\r
390 g.setColor(Color.gray);
\r
395 g.setColor(g.getColor().darker());
\r
398 g.fillRect(x - 3, y - 3, 6, 6);
\r
401 g.setColor(Color.red);
\r
402 g.drawString( ( (SequencePoint) points.elementAt(i)).sequence.
\r
409 public Dimension minimumsize()
\r
414 public Dimension preferredsize()
\r
419 public void keyTyped(KeyEvent evt)
\r
422 public void keyReleased(KeyEvent evt)
\r
425 public void keyPressed(KeyEvent evt)
\r
427 if (evt.getKeyCode() == KeyEvent.VK_UP)
\r
429 scalefactor = (float) (scalefactor * 1.1);
\r
430 scale = findScale();
\r
432 else if (evt.getKeyCode() == KeyEvent.VK_DOWN)
\r
434 scalefactor = (float) (scalefactor * 0.9);
\r
435 scale = findScale();
\r
437 else if (evt.getKeyChar() == 's')
\r
439 System.err.println("DEBUG: Rectangle selection"); // log.debug
\r
440 if (rectx2 != -1 && recty2 != -1)
\r
442 rectSelect(rectx1, recty1, rectx2, recty2);
\r
449 public void printPoints()
\r
451 for (int i = 0; i < npoint; i++)
\r
453 SequencePoint sp = (SequencePoint) points.elementAt(i);
\r
454 Format.print(System.out, "%5d ", i);
\r
455 for (int j = 0; j < 3; j++)
\r
457 Format.print(System.out, "%13.3f ", sp.coord[j]);
\r
459 System.out.println();
\r
463 public void mouseClicked(MouseEvent evt)
\r
466 public void mouseEntered(MouseEvent evt)
\r
469 public void mouseExited(MouseEvent evt)
\r
472 public void mouseReleased(MouseEvent evt)
\r
475 public void mousePressed(MouseEvent evt)
\r
477 int x = evt.getX();
\r
478 int y = evt.getY();
\r
495 SequenceI found = findPoint(x, y);
\r
499 if (av.getSelectionGroup() != null)
\r
501 av.getSelectionGroup().addOrRemove(found, true);
\r
502 av.getSelectionGroup().setEndRes(av.alignment.getWidth() - 1);
\r
503 PaintRefresher.Refresh(this, av.getSequenceSetId());
\r
507 av.setSelectionGroup(new SequenceGroup());
\r
508 av.getSelectionGroup().addOrRemove(found, true);
\r
509 av.getSelectionGroup().setEndRes(av.alignment.getWidth() - 1);
\r
516 public void mouseMoved(MouseEvent evt)
\r
518 SequenceI found = findPoint(evt.getX(), evt.getY());
\r
525 tooltip = found.getName();
\r
526 toolx = evt.getX();
\r
527 tooly = evt.getY();
\r
532 public void mouseDragged(MouseEvent evt)
\r
537 rotmat.setIdentity();
\r
539 rotmat.rotate( (float) (my - omy), 'x');
\r
540 rotmat.rotate( (float) (mx - omx), 'y');
\r
542 for (int i = 0; i < npoint; i++)
\r
544 SequencePoint sp = (SequencePoint) points.elementAt(i);
\r
545 sp.coord[0] -= centre[0];
\r
546 sp.coord[1] -= centre[1];
\r
547 sp.coord[2] -= centre[2];
\r
549 //Now apply the rotation matrix
\r
550 sp.coord = rotmat.vectorMultiply(sp.coord);
\r
552 //Now translate back again
\r
553 sp.coord[0] += centre[0];
\r
554 sp.coord[1] += centre[1];
\r
555 sp.coord[2] += centre[2];
\r
558 for (int i = 0; i < 3; i++)
\r
560 axes[i] = rotmat.vectorMultiply(axes[i]);
\r
565 paint(this.getGraphics());
\r
568 public void rectSelect(int x1, int y1, int x2, int y2)
\r
570 //boolean changedSel = false;
\r
571 for (int i = 0; i < npoint; i++)
\r
573 SequencePoint sp = (SequencePoint) points.elementAt(i);
\r
574 int tmp1 = (int) ( (sp.coord[0] - centre[0]) * scale +
\r
575 (float) getSize().width / 2.0);
\r
576 int tmp2 = (int) ( (sp.coord[1] - centre[1]) * scale +
\r
577 (float) getSize().height / 2.0);
\r
579 if (tmp1 > x1 && tmp1 < x2 && tmp2 > y1 && tmp2 < y2)
\r
583 if (!av.getSelectionGroup().getSequences(null).contains(sp.sequence))
\r
585 av.getSelectionGroup().addSequence(sp.sequence, true);
\r
592 public SequenceI findPoint(int x, int y)
\r
595 int halfwidth = getSize().width / 2;
\r
596 int halfheight = getSize().height / 2;
\r
600 for (int i = 0; i < npoint; i++)
\r
603 SequencePoint sp = (SequencePoint) points.elementAt(i);
\r
604 int px = (int) ( (float) (sp.coord[0] - centre[0]) * scale) + halfwidth;
\r
605 int py = (int) ( (float) (sp.coord[1] - centre[1]) * scale) + halfheight;
\r
607 if (Math.abs(px - x) < 3 && Math.abs(py - y) < 3)
\r
614 return ( (SequencePoint) points.elementAt(found)).sequence;
\r