2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
25 import java.awt.event.*;
29 import jalview.api.RotatableCanvasI;
30 import jalview.datamodel.*;
31 import jalview.math.*;
32 import jalview.util.MessageManager;
33 import jalview.viewmodel.AlignmentViewport;
41 public class RotatableCanvas extends JPanel implements MouseListener,
42 MouseMotionListener, KeyListener, RotatableCanvasI
44 RotatableMatrix idmat = new RotatableMatrix(3, 3);
46 RotatableMatrix objmat = new RotatableMatrix(3, 3);
48 RotatableMatrix rotmat = new RotatableMatrix(3, 3);
50 // RubberbandRectangle rubberband;
51 boolean drawAxes = true;
67 float[] centre = new float[3];
69 float[] width = new float[3];
71 float[] max = new float[3];
73 float[] min = new float[3];
103 float scalefactor = 1;
105 AlignmentViewport av;
109 boolean showLabels = false;
111 Color bgColour = Color.black;
113 boolean applyToAllViews = false;
115 // Controller controller;
116 public RotatableCanvas(AlignmentPanel ap)
121 addMouseWheelListener(new MouseWheelListener()
123 public void mouseWheelMoved(MouseWheelEvent e)
125 if (e.getWheelRotation() > 0)
127 scale = (float) (scale * 1.1);
133 scale = (float) (scale * 0.9);
141 public void showLabels(boolean b)
147 boolean first = true;
149 public void setPoints(Vector points, int npoint)
151 this.points = points;
152 this.npoint = npoint;
155 ToolTipManager.sharedInstance().registerComponent(this);
156 ToolTipManager.sharedInstance().setInitialDelay(0);
157 ToolTipManager.sharedInstance().setDismissDelay(10000);
159 prefsize = getPreferredSize();
160 orig = new float[npoint][3];
162 for (int i = 0; i < npoint; i++)
164 SequencePoint sp = (SequencePoint) points.elementAt(i);
166 for (int j = 0; j < 3; j++)
168 orig[i][j] = sp.coord[j];
172 // Initialize the matrices to identity
173 for (int i = 0; i < 3; i++)
175 for (int j = 0; j < 3; j++)
179 idmat.addElement(i, j, 0);
180 objmat.addElement(i, j, 0);
181 rotmat.addElement(i, j, 0);
185 idmat.addElement(i, j, 0);
186 objmat.addElement(i, j, 0);
187 rotmat.addElement(i, j, 0);
192 axes = new float[3][3];
202 addMouseListener(this);
204 addMouseMotionListener(this);
209 public void initAxes()
211 for (int i = 0; i < 3; i++)
213 for (int j = 0; j < 3; j++)
230 public void findWidth()
235 max[0] = (float) -1e30;
236 max[1] = (float) -1e30;
237 max[2] = (float) -1e30;
239 min[0] = (float) 1e30;
240 min[1] = (float) 1e30;
241 min[2] = (float) 1e30;
243 for (int i = 0; i < 3; i++)
245 for (int j = 0; j < npoint; j++)
247 SequencePoint sp = (SequencePoint) points.elementAt(j);
249 if (sp.coord[i] >= max[i])
251 max[i] = sp.coord[i];
254 if (sp.coord[i] <= min[i])
256 min[i] = sp.coord[i];
261 // System.out.println("xmax " + max[0] + " min " + min[0]);
262 // System.out.println("ymax " + max[1] + " min " + min[1]);
263 // System.out.println("zmax " + max[2] + " min " + min[2]);
264 width[0] = Math.abs(max[0] - min[0]);
265 width[1] = Math.abs(max[1] - min[1]);
266 width[2] = Math.abs(max[2] - min[2]);
270 if (width[1] > width[0])
275 if (width[2] > width[1])
280 // System.out.println("Maxwidth = " + maxwidth);
286 * @return DOCUMENT ME!
288 public float findScale()
297 height = getHeight();
301 width = prefsize.width;
302 height = prefsize.height;
314 return (float) ((dim * scalefactor) / (2 * maxwidth));
320 public void findCentre()
322 // Find centre coordinate
325 centre[0] = (max[0] + min[0]) / 2;
326 centre[1] = (max[1] + min[1]) / 2;
327 centre[2] = (max[2] + min[2]) / 2;
329 // System.out.println("Centre x " + centre[0]);
330 // System.out.println("Centre y " + centre[1]);
331 // System.out.println("Centre z " + centre[2]);
337 * @return DOCUMENT ME!
339 public Dimension getPreferredSize()
341 if (prefsize != null)
347 return new Dimension(400, 400);
354 * @return DOCUMENT ME!
356 public Dimension getMinimumSize()
358 return getPreferredSize();
367 public void paintComponent(Graphics g1)
370 Graphics2D g = (Graphics2D) g1;
372 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
373 RenderingHints.VALUE_ANTIALIAS_ON);
376 g.setFont(new Font("Verdana", Font.PLAIN, 18));
377 g.drawString(MessageManager.getString("label.calculating_pca")
378 + "....", 20, getHeight() / 2);
382 // Only create the image at the beginning -
383 if ((img == null) || (prefsize.width != getWidth())
384 || (prefsize.height != getHeight()))
386 prefsize.width = getWidth();
387 prefsize.height = getHeight();
391 // System.out.println("New scale = " + scale);
392 img = createImage(getWidth(), getHeight());
393 ig = img.getGraphics();
396 drawBackground(ig, bgColour);
399 if (drawAxes == true)
404 g.drawImage(img, 0, 0, this);
414 public void drawAxes(Graphics g)
417 g.setColor(Color.yellow);
419 for (int i = 0; i < 3; i++)
421 g.drawLine(getWidth() / 2, getHeight() / 2, (int) ((axes[i][0]
422 * scale * max[0]) + (getWidth() / 2)), (int) ((axes[i][1]
423 * scale * max[1]) + (getHeight() / 2)));
435 public void drawBackground(Graphics g, Color col)
438 g.fillRect(0, 0, prefsize.width, prefsize.height);
447 public void drawScene(Graphics g1)
450 Graphics2D g = (Graphics2D) g1;
452 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
453 RenderingHints.VALUE_ANTIALIAS_ON);
455 int halfwidth = getWidth() / 2;
456 int halfheight = getHeight() / 2;
458 for (int i = 0; i < npoint; i++)
460 SequencePoint sp = (SequencePoint) points.elementAt(i);
461 int x = (int) ((float) (sp.coord[0] - centre[0]) * scale) + halfwidth;
462 int y = (int) ((float) (sp.coord[1] - centre[1]) * scale)
464 float z = sp.coord[1] - centre[2];
466 if (av.getSequenceColour(sp.sequence) == Color.black)
468 g.setColor(Color.white);
472 g.setColor(av.getSequenceColour(sp.sequence));
475 if (av.getSelectionGroup() != null)
477 if (av.getSelectionGroup().getSequences(null)
478 .contains(((SequencePoint) points.elementAt(i)).sequence))
480 g.setColor(Color.gray);
486 g.setColor(g.getColor().darker());
489 g.fillRect(x - 3, y - 3, 6, 6);
492 g.setColor(Color.red);
494 ((SequencePoint) points.elementAt(i)).sequence.getName(),
499 // //Now the rectangle
500 // if (rectx2 != -1 && recty2 != -1) {
501 // g.setColor(Color.white);
503 // g.drawRect(rectx1,recty1,rectx2-rectx1,recty2-recty1);
510 * @return DOCUMENT ME!
512 public Dimension minimumsize()
520 * @return DOCUMENT ME!
522 public Dimension preferredsize()
533 public void keyTyped(KeyEvent evt)
543 public void keyReleased(KeyEvent evt)
553 public void keyPressed(KeyEvent evt)
555 if (evt.getKeyCode() == KeyEvent.VK_UP)
557 scalefactor = (float) (scalefactor * 1.1);
560 else if (evt.getKeyCode() == KeyEvent.VK_DOWN)
562 scalefactor = (float) (scalefactor * 0.9);
565 else if (evt.getKeyChar() == 's')
567 System.err.println("DEBUG: Rectangle selection"); // log.debug
569 if ((rectx2 != -1) && (recty2 != -1))
571 rectSelect(rectx1, recty1, rectx2, recty2);
584 public void mouseClicked(MouseEvent evt)
594 public void mouseEntered(MouseEvent evt)
604 public void mouseExited(MouseEvent evt)
614 public void mouseReleased(MouseEvent evt)
624 public void mousePressed(MouseEvent evt)
644 SequenceI found = findPoint(x, y);
648 AlignmentPanel[] aps = getAssociatedPanels();
650 for (int a = 0; a < aps.length; a++)
652 if (aps[a].av.getSelectionGroup() != null)
654 aps[a].av.getSelectionGroup().addOrRemove(found, true);
658 aps[a].av.setSelectionGroup(new SequenceGroup());
659 aps[a].av.getSelectionGroup().addOrRemove(found, true);
660 aps[a].av.getSelectionGroup().setEndRes(
661 aps[a].av.getAlignment().getWidth() - 1);
664 PaintRefresher.Refresh(this, av.getSequenceSetId());
665 // canonical selection is sent to other listeners
672 // private void fireSequenceSelectionEvent(Selection sel) {
673 // controller.handleSequenceSelectionEvent(new
674 // SequenceSelectionEvent(this,sel));
676 public void mouseMoved(MouseEvent evt)
678 SequenceI found = findPoint(evt.getX(), evt.getY());
682 this.setToolTipText(found.getName());
686 this.setToolTipText(null);
696 public void mouseDragged(MouseEvent evt)
701 // Check if this is a rectangle drawing drag
702 if ((evt.getModifiers() & InputEvent.BUTTON2_MASK) != 0)
704 // rectx2 = evt.getX();
705 // recty2 = evt.getY();
709 rotmat.setIdentity();
711 rotmat.rotate((float) (my - omy), 'x');
712 rotmat.rotate((float) (mx - omx), 'y');
714 for (int i = 0; i < npoint; i++)
716 SequencePoint sp = (SequencePoint) points.elementAt(i);
717 sp.coord[0] -= centre[0];
718 sp.coord[1] -= centre[1];
719 sp.coord[2] -= centre[2];
721 // Now apply the rotation matrix
722 sp.coord = rotmat.vectorMultiply(sp.coord);
724 // Now translate back again
725 sp.coord[0] += centre[0];
726 sp.coord[1] += centre[1];
727 sp.coord[2] += centre[2];
730 for (int i = 0; i < 3; i++)
732 axes[i] = rotmat.vectorMultiply(axes[i]);
738 paint(this.getGraphics());
754 public void rectSelect(int x1, int y1, int x2, int y2)
756 for (int i = 0; i < npoint; i++)
758 SequencePoint sp = (SequencePoint) points.elementAt(i);
759 int tmp1 = (int) (((sp.coord[0] - centre[0]) * scale) + ((float) getWidth() / 2.0));
760 int tmp2 = (int) (((sp.coord[1] - centre[1]) * scale) + ((float) getHeight() / 2.0));
762 if ((tmp1 > x1) && (tmp1 < x2) && (tmp2 > y1) && (tmp2 < y2))
766 if (!av.getSelectionGroup().getSequences(null)
767 .contains(sp.sequence))
769 av.getSelectionGroup().addSequence(sp.sequence, true);
776 // fireSequenceSelectionEvent(av.getSelection());
788 * @return DOCUMENT ME!
790 public SequenceI findPoint(int x, int y)
792 int halfwidth = getWidth() / 2;
793 int halfheight = getHeight() / 2;
797 for (int i = 0; i < npoint; i++)
799 SequencePoint sp = (SequencePoint) points.elementAt(i);
800 int px = (int) ((float) (sp.coord[0] - centre[0]) * scale)
802 int py = (int) ((float) (sp.coord[1] - centre[1]) * scale)
805 if ((Math.abs(px - x) < 3) && (Math.abs(py - y) < 3))
813 return ((SequencePoint) points.elementAt(found)).sequence;
821 AlignmentPanel[] getAssociatedPanels()
825 return PaintRefresher.getAssociatedPanels(av.getSequenceSetId());
829 return new AlignmentPanel[]
836 * @return x,y,z positions of point s (index into points) under current
839 public double[] getPointPosition(int s)
841 double pts[] = new double[3];
842 float[] p = ((SequencePoint) points.elementAt(s)).coord;