2 * Jalview - A Sequence Alignment Editor and Viewer
3 * Copyright (C) 2006 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
20 package jalview.appletgui;
25 import java.awt.event.*;
27 import jalview.datamodel.*;
28 import jalview.math.*;
29 import jalview.util.*;
31 public class RotatableCanvas
32 extends Panel implements MouseListener,
36 RotatableMatrix idmat = new RotatableMatrix(3, 3);
37 RotatableMatrix objmat = new RotatableMatrix(3, 3);
38 RotatableMatrix rotmat = new RotatableMatrix(3, 3);
42 //RubberbandRectangle rubberband;
44 boolean drawAxes = true;
56 float centre[] = new float[3];
57 float width[] = new float[3];
59 float max[] = new float[3];
60 float min[] = new float[3];
82 float scalefactor = 1;
85 boolean showLabels = false;
87 public RotatableCanvas(AlignViewport av)
92 public void showLabels(boolean b)
98 public void setPoints(Vector points, int npoint)
100 this.points = points;
101 this.npoint = npoint;
102 PaintRefresher.Register(this, av.alignment);
104 prefsize = getPreferredSize();
105 orig = new float[npoint][3];
107 for (int i = 0; i < npoint; i++)
109 SequencePoint sp = (SequencePoint) points.elementAt(i);
110 for (int j = 0; j < 3; j++)
112 orig[i][j] = sp.coord[j];
115 //Initialize the matrices to identity
117 for (int i = 0; i < 3; i++)
119 for (int j = 0; j < 3; j++)
123 idmat.addElement(i, j, 0);
124 objmat.addElement(i, j, 0);
125 rotmat.addElement(i, j, 0);
129 idmat.addElement(i, j, 0);
130 objmat.addElement(i, j, 0);
131 rotmat.addElement(i, j, 0);
136 axes = new float[3][3];
144 // System.out.println("Scale factor = " + scale);
146 addMouseListener(this);
147 addKeyListener(this);
148 // if (getParent() != null) {
149 // getParent().addKeyListener(this);
151 addMouseMotionListener(this);
154 // rubberband = new RubberbandRectangle(this);
155 // rubberband.setActive(true);
156 // rubberband.addListener(this);
159 /* public boolean handleSequenceSelectionEvent(SequenceSelectionEvent evt) {
165 public void removeNotify() {
166 controller.removeListener(this);
167 super.removeNotify();
170 public void initAxes()
172 for (int i = 0; i < 3; i++)
174 for (int j = 0; j < 3; j++)
188 public void findWidth()
193 max[0] = (float) - 1e30;
194 max[1] = (float) - 1e30;
195 max[2] = (float) - 1e30;
197 min[0] = (float) 1e30;
198 min[1] = (float) 1e30;
199 min[2] = (float) 1e30;
201 for (int i = 0; i < 3; i++)
203 for (int j = 0; j < npoint; j++)
205 SequencePoint sp = (SequencePoint) points.elementAt(j);
206 if (sp.coord[i] >= max[i])
208 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]);
221 width[0] = Math.abs(max[0] - min[0]);
222 width[1] = Math.abs(max[1] - min[1]);
223 width[2] = Math.abs(max[2] - min[2]);
227 if (width[1] > width[0])
231 if (width[2] > width[1])
236 //System.out.println("Maxwidth = " + maxwidth);
239 public float findScale()
241 int dim, width, height;
242 if (getSize().width != 0)
244 width = getSize().width;
245 height = getSize().height;
249 width = prefsize.width;
250 height = prefsize.height;
262 return (float) (dim * scalefactor / (2 * maxwidth));
265 public void findCentre()
267 //Find centre coordinate
270 centre[0] = (max[0] + min[0]) / 2;
271 centre[1] = (max[1] + min[1]) / 2;
272 centre[2] = (max[2] + min[2]) / 2;
274 // System.out.println("Centre x " + centre[0]);
275 //System.out.println("Centre y " + centre[1]);
276 //System.out.println("Centre z " + centre[2]);
279 public Dimension getPreferredSize()
281 if (prefsize != null)
287 return new Dimension(400, 400);
291 public Dimension getMinimumSize()
293 return getPreferredSize();
296 public void update(Graphics g)
300 public void paint(Graphics g)
304 g.setFont(new Font("Verdana", Font.PLAIN, 18));
305 g.drawString("Calculating PCA....", 20, getSize().height / 2);
310 //Only create the image at the beginning -
311 if ( (img == null) || (prefsize.width != getSize().width) ||
312 (prefsize.height != getSize().height))
314 prefsize.width = getSize().width;
315 prefsize.height = getSize().height;
319 // System.out.println("New scale = " + scale);
320 img = createImage(getSize().width, getSize().height);
321 ig = img.getGraphics();
325 drawBackground(ig, Color.black);
327 if (drawAxes == true)
334 ig.setColor(Color.red);
335 ig.drawString(tooltip, toolx, tooly);
338 g.drawImage(img, 0, 0, this);
342 public void drawAxes(Graphics g)
345 g.setColor(Color.yellow);
346 for (int i = 0; i < 3; i++)
348 g.drawLine(getSize().width / 2, getSize().height / 2,
349 (int) (axes[i][0] * scale * max[0] + getSize().width / 2),
350 (int) (axes[i][1] * scale * max[1] + getSize().height / 2));
354 public void drawBackground(Graphics g, Color col)
357 g.fillRect(0, 0, prefsize.width, prefsize.height);
360 public void drawScene(Graphics g)
362 //boolean darker = false;
364 int halfwidth = getSize().width / 2;
365 int halfheight = getSize().height / 2;
367 for (int i = 0; i < npoint; i++)
369 SequencePoint sp = (SequencePoint) points.elementAt(i);
370 int x = (int) ( (float) (sp.coord[0] - centre[0]) * scale) + halfwidth;
371 int y = (int) ( (float) (sp.coord[1] - centre[1]) * scale) + halfheight;
372 float z = sp.coord[1] - centre[2];
374 if (sp.sequence.getColor() == Color.black)
376 g.setColor(Color.white);
380 g.setColor(sp.sequence.getColor());
383 if (av.getSelectionGroup() != null)
385 if (av.getSelectionGroup().getSequences(false).contains( ( (SequencePoint) points.
386 elementAt(i)).sequence))
388 g.setColor(Color.gray);
393 g.setColor(g.getColor().darker());
396 g.fillRect(x - 3, y - 3, 6, 6);
399 g.setColor(Color.red);
400 g.drawString( ( (SequencePoint) points.elementAt(i)).sequence.
407 public Dimension minimumsize()
412 public Dimension preferredsize()
417 public void keyTyped(KeyEvent evt)
420 public void keyReleased(KeyEvent evt)
423 public void keyPressed(KeyEvent evt)
425 if (evt.getKeyCode() == KeyEvent.VK_UP)
427 scalefactor = (float) (scalefactor * 1.1);
430 else if (evt.getKeyCode() == KeyEvent.VK_DOWN)
432 scalefactor = (float) (scalefactor * 0.9);
435 else if (evt.getKeyChar() == 's')
437 System.err.println("DEBUG: Rectangle selection"); // log.debug
438 if (rectx2 != -1 && recty2 != -1)
440 rectSelect(rectx1, recty1, rectx2, recty2);
447 public void printPoints()
449 for (int i = 0; i < npoint; i++)
451 SequencePoint sp = (SequencePoint) points.elementAt(i);
452 Format.print(System.out, "%5d ", i);
453 for (int j = 0; j < 3; j++)
455 Format.print(System.out, "%13.3f ", sp.coord[j]);
457 System.out.println();
461 public void mouseClicked(MouseEvent evt)
464 public void mouseEntered(MouseEvent evt)
467 public void mouseExited(MouseEvent evt)
470 public void mouseReleased(MouseEvent evt)
473 public void mousePressed(MouseEvent evt)
493 SequenceI found = findPoint(x, y);
497 if (av.getSelectionGroup() != null)
499 av.getSelectionGroup().addOrRemove(found, true);
500 av.getSelectionGroup().setEndRes(av.alignment.getWidth()-1);
501 PaintRefresher.Refresh(this, av.alignment);
505 av.setSelectionGroup(new SequenceGroup());
506 av.getSelectionGroup().addOrRemove(found, true);
507 av.getSelectionGroup().setEndRes(av.alignment.getWidth()-1);
515 public void mouseMoved(MouseEvent evt)
517 SequenceI found = findPoint(evt.getX(), evt.getY());
522 tooltip = found.getName();
529 public void mouseDragged(MouseEvent evt)
534 rotmat.setIdentity();
536 rotmat.rotate( (float) (my - omy), 'x');
537 rotmat.rotate( (float) (mx - omx), 'y');
539 for (int i = 0; i < npoint; i++)
541 SequencePoint sp = (SequencePoint) points.elementAt(i);
542 sp.coord[0] -= centre[0];
543 sp.coord[1] -= centre[1];
544 sp.coord[2] -= centre[2];
546 //Now apply the rotation matrix
547 sp.coord = rotmat.vectorMultiply(sp.coord);
549 //Now translate back again
550 sp.coord[0] += centre[0];
551 sp.coord[1] += centre[1];
552 sp.coord[2] += centre[2];
555 for (int i = 0; i < 3; i++)
557 axes[i] = rotmat.vectorMultiply(axes[i]);
562 paint(this.getGraphics());
565 public void rectSelect(int x1, int y1, int x2, int y2)
567 //boolean changedSel = false;
568 for (int i = 0; i < npoint; i++)
570 SequencePoint sp = (SequencePoint) points.elementAt(i);
571 int tmp1 = (int) ( (sp.coord[0] - centre[0]) * scale +
572 (float) getSize().width / 2.0);
573 int tmp2 = (int) ( (sp.coord[1] - centre[1]) * scale +
574 (float) getSize().height / 2.0);
576 if (tmp1 > x1 && tmp1 < x2 && tmp2 > y1 && tmp2 < y2)
580 if (!av.getSelectionGroup().getSequences(false).contains(sp.sequence))
582 av.getSelectionGroup().addSequence(sp.sequence, true);
589 public SequenceI findPoint(int x, int y)
592 int halfwidth = getSize().width / 2;
593 int halfheight = getSize().height / 2;
597 for (int i = 0; i < npoint; i++)
600 SequencePoint sp = (SequencePoint) points.elementAt(i);
601 int px = (int) ( (float) (sp.coord[0] - centre[0]) * scale) + halfwidth;
602 int py = (int) ( (float) (sp.coord[1] - centre[1]) * scale) + halfheight;
604 if (Math.abs(px - x) < 3 && Math.abs(py - y) < 3)
611 return ( (SequencePoint) points.elementAt(found)).sequence;