3 import jalview.math.*;
\r
4 import jalview.datamodel.*;
\r
5 import jalview.util.*;
\r
8 import java.awt.event.*;
\r
9 import javax.swing.*;
\r
13 public class RotatableCanvas extends JPanel implements MouseListener,
\r
14 MouseMotionListener,
\r
16 //RubberbandListener,
\r
17 //SequenceSelectionListener
\r
19 RotatableMatrix idmat = new RotatableMatrix(3,3);
\r
20 RotatableMatrix objmat = new RotatableMatrix(3,3);
\r
21 RotatableMatrix rotmat = new RotatableMatrix(3,3);
\r
23 //RubberbandRectangle rubberband;
\r
25 boolean drawAxes = true;
\r
37 float centre[] = new float[3];
\r
38 float width[] = new float[3];
\r
40 float max[] = new float[3];
\r
41 float min[] = new float[3];
\r
63 float scalefactor = 1;
\r
66 // Controller controller;
\r
69 public RotatableCanvas(AlignViewport av,
\r
70 Vector points, int npoint) {
\r
71 this.points = points;
\r
72 this.npoint = npoint;
\r
74 ToolTipManager.sharedInstance().registerComponent(this);
\r
75 PaintRefresher.Register(this);
\r
77 prefsize = getPreferredSize();
\r
78 orig = new float[npoint][3];
\r
80 for (int i=0; i < npoint; i++) {
\r
81 SequencePoint sp = (SequencePoint)points.elementAt(i);
\r
82 for (int j=0; j < 3; j++) {
\r
83 orig[i][j] = sp.coord[j];
\r
86 //Initialize the matrices to identity
\r
88 for (int i = 0; i < 3; i++) {
\r
89 for (int j = 0; j < 3 ; j++) {
\r
91 idmat.addElement(i,j,0);
\r
92 objmat.addElement(i,j,0);
\r
93 rotmat.addElement(i,j,0);
\r
95 idmat.addElement(i,j,0);
\r
96 objmat.addElement(i,j,0);
\r
97 rotmat.addElement(i,j,0);
\r
102 axes = new float[3][3];
\r
108 scale = findScale();
\r
110 // System.out.println("Scale factor = " + scale);
\r
112 addMouseListener(this);
\r
113 addKeyListener(this);
\r
114 // if (getParent() != null) {
\r
115 // getParent().addKeyListener(this);
\r
117 addMouseMotionListener(this);
\r
120 // rubberband = new RubberbandRectangle(this);
\r
121 // rubberband.setActive(true);
\r
122 // rubberband.addListener(this);
\r
125 /* public boolean handleSequenceSelectionEvent(SequenceSelectionEvent evt) {
\r
126 redrawneeded = true;
\r
131 public void removeNotify() {
\r
132 controller.removeListener(this);
\r
133 super.removeNotify();
\r
136 public void initAxes() {
\r
137 for (int i = 0; i < 3; i++) {
\r
138 for (int j=0; j < 3; j++) {
\r
148 public void findWidth() {
\r
149 max = new float[3];
\r
150 min = new float[3];
\r
152 max[0] = (float)-1e30;
\r
153 max[1] = (float)-1e30;
\r
154 max[2] = (float)-1e30;
\r
156 min[0] = (float)1e30;
\r
157 min[1] = (float)1e30;
\r
158 min[2] = (float)1e30;
\r
160 for (int i = 0; i < 3; i++) {
\r
161 for (int j = 0; j < npoint; j++) {
\r
162 SequencePoint sp = (SequencePoint)points.elementAt(j);
\r
163 if (sp.coord[i] >= max[i]) {
\r
164 max[i] = sp.coord[i];
\r
166 if (sp.coord[i] <= min[i]) {
\r
167 min[i] = sp.coord[i];
\r
172 // System.out.println("xmax " + max[0] + " min " + min[0]);
\r
173 //System.out.println("ymax " + max[1] + " min " + min[1]);
\r
174 //System.out.println("zmax " + max[2] + " min " + min[2]);
\r
176 width[0] = Math.abs(max[0] - min[0]);
\r
177 width[1] = Math.abs(max[1] - min[1]);
\r
178 width[2] = Math.abs(max[2] - min[2]);
\r
180 maxwidth = width[0];
\r
182 if (width[1] > width[0])
\r
183 maxwidth = width[1];
\r
184 if (width[2] > width[1])
\r
185 maxwidth = width[2];
\r
187 //System.out.println("Maxwidth = " + maxwidth);
\r
190 public float findScale() {
\r
191 int dim, width, height;
\r
192 if (getWidth() != 0) {
\r
193 width = getWidth();
\r
194 height = getHeight();
\r
196 width = prefsize.width;
\r
197 height = prefsize.height;
\r
200 if (width < height) {
\r
206 return (float)(dim*scalefactor/(2*maxwidth));
\r
209 public void findCentre() {
\r
210 //Find centre coordinate
\r
213 centre[0] = (max[0] + min[0])/2;
\r
214 centre[1] = (max[1] + min[1])/2;
\r
215 centre[2] = (max[2] + min[2])/2;
\r
217 // System.out.println("Centre x " + centre[0]);
\r
218 //System.out.println("Centre y " + centre[1]);
\r
219 //System.out.println("Centre z " + centre[2]);
\r
222 public Dimension getPreferredSize() {
\r
223 if (prefsize != null) {
\r
226 return new Dimension(400,400);
\r
230 public Dimension getMinimumSize() {
\r
231 return getPreferredSize();
\r
234 public void paintComponent(Graphics g) {
\r
235 //Only create the image at the beginning -
\r
236 if ((img == null) || (prefsize.width != getWidth()) || (prefsize.height != getHeight())) {
\r
237 prefsize.width = getWidth();
\r
238 prefsize.height = getHeight();
\r
240 scale = findScale();
\r
242 // System.out.println("New scale = " + scale);
\r
243 img = createImage(getWidth(),getHeight());
\r
244 ig = img.getGraphics();
\r
249 drawBackground(ig,Color.black);
\r
251 if (drawAxes == true)
\r
257 g.drawImage(img,0,0,this);
\r
260 public void drawAxes(Graphics g) {
\r
262 g.setColor(Color.yellow);
\r
263 for (int i=0; i < 3 ; i++) {
\r
264 g.drawLine(getWidth()/2,getHeight()/2,
\r
265 (int)(axes[i][0]*scale*max[0] + getWidth()/2),
\r
266 (int)(axes[i][1]*scale*max[1] + getHeight()/2));
\r
270 public void drawBackground(Graphics g, Color col) {
\r
272 g.fillRect(0,0,prefsize.width,prefsize.height);
\r
276 public void drawScene(Graphics g) {
\r
277 boolean darker = false;
\r
279 int halfwidth = getWidth()/2;
\r
280 int halfheight = getHeight()/2;
\r
282 for (int i = 0; i < npoint; i++) {
\r
283 SequencePoint sp = (SequencePoint)points.elementAt(i);
\r
284 int x = (int)((float)(sp.coord[0] - centre[0])*scale) + halfwidth;
\r
285 int y = (int)((float)(sp.coord[1] - centre[1])*scale) + halfheight;
\r
286 float z = sp.coord[1] - centre[2];
\r
291 if (sp.sequence.getColor() == Color.black)
\r
292 g.setColor(Color.white);
\r
294 g.setColor(sp.sequence.getColor());
\r
299 if (av.getSelection().contains(((SequencePoint)points.elementAt(i)).sequence))
\r
300 g.setColor(Color.gray);
\r
303 g.setColor(g.getColor().darker());
\r
306 g.fillRect(x-3,y-3,6,6);
\r
307 g.setColor(Color.red);
\r
309 // //Now the rectangle
\r
310 // if (rectx2 != -1 && recty2 != -1) {
\r
311 // g.setColor(Color.white);
\r
313 // g.drawRect(rectx1,recty1,rectx2-rectx1,recty2-recty1);
\r
317 public Dimension minimumsize() {
\r
321 public Dimension preferredsize() {
\r
325 public void keyTyped(KeyEvent evt) { }
\r
326 public void keyReleased(KeyEvent evt) { }
\r
328 public void keyPressed(KeyEvent evt) {
\r
330 if (evt.getKeyCode() == KeyEvent.VK_UP) {
\r
331 scalefactor = (float)(scalefactor * 1.1);
\r
332 scale = findScale();
\r
333 } else if (evt.getKeyCode() == KeyEvent.VK_DOWN) {
\r
334 scalefactor = (float)(scalefactor * 0.9);
\r
335 scale = findScale();
\r
336 } else if (evt.getKeyChar() == 's') {
\r
337 System.out.println("Rectangle selection");
\r
338 if (rectx2 != -1 && recty2 != -1) {
\r
339 rectSelect(rectx1,recty1,rectx2,recty2);
\r
346 public void printPoints() {
\r
347 for (int i=0; i < npoint; i++) {
\r
348 SequencePoint sp = (SequencePoint)points.elementAt(i);
\r
349 Format.print(System.out,"%5d ", i);
\r
350 for (int j=0; j < 3;j++) {
\r
351 Format.print(System.out,"%13.3f ",sp.coord[j]);
\r
353 System.out.println();
\r
357 public void mouseClicked(MouseEvent evt) { }
\r
358 public void mouseEntered(MouseEvent evt) { }
\r
359 public void mouseExited(MouseEvent evt) { }
\r
360 public void mouseReleased(MouseEvent evt) { }
\r
362 public void mousePressed(MouseEvent evt) {
\r
363 int x = evt.getX();
\r
364 int y = evt.getY();
\r
381 SequenceI found = findPoint(x,y);
\r
383 if (found != null) {
\r
386 if (av.getSelection().contains(found)) {
\r
387 av.getSelection().removeElement(found);
\r
389 av.getSelection().addElement(found);
\r
391 PaintRefresher.Refresh(this);
\r
397 // private void fireSequenceSelectionEvent(Selection sel) {
\r
398 // controller.handleSequenceSelectionEvent(new SequenceSelectionEvent(this,sel));
\r
401 public void mouseMoved(MouseEvent evt)
\r
403 SequenceI found = findPoint(evt.getX(), evt.getY());
\r
405 this.setToolTipText(found.getName());
\r
407 this.setToolTipText(null);
\r
410 public void mouseDragged(MouseEvent evt) {
\r
413 //Check if this is a rectangle drawing drag
\r
414 if ((evt.getModifiers() & InputEvent.BUTTON2_MASK) != 0) {
\r
415 // rectx2 = evt.getX();
\r
416 // recty2 = evt.getY();
\r
418 rotmat.setIdentity();
\r
420 rotmat.rotate((float)(my-omy),'x');
\r
421 rotmat.rotate((float)(mx-omx),'y');
\r
423 for (int i = 0; i < npoint; i++) {
\r
424 SequencePoint sp = (SequencePoint)points.elementAt(i);
\r
425 sp.coord[0] -= centre[0];
\r
426 sp.coord[1] -= centre[1];
\r
427 sp.coord[2] -= centre[2];
\r
429 //Now apply the rotation matrix
\r
430 sp.coord= rotmat.vectorMultiply(sp.coord);
\r
432 //Now translate back again
\r
433 sp.coord[0] += centre[0];
\r
434 sp.coord[1] += centre[1];
\r
435 sp.coord[2] += centre[2];
\r
438 for (int i=0; i < 3; i++) {
\r
439 axes[i] = rotmat.vectorMultiply(axes[i]);
\r
444 paint(this.getGraphics());
\r
449 public void rectSelect(int x1, int y1, int x2, int y2) {
\r
450 boolean changedSel = false;
\r
451 for (int i=0; i < npoint; i++) {
\r
452 SequencePoint sp = (SequencePoint)points.elementAt(i);
\r
453 int tmp1 = (int)((sp.coord[0] - centre[0])*scale + (float)getWidth()/2.0);
\r
454 int tmp2 = (int)((sp.coord[1] - centre[1])*scale + (float)getHeight()/2.0);
\r
456 if (tmp1 > x1 && tmp1 < x2 && tmp2 > y1 && tmp2 < y2) {
\r
458 if (!av.getSelection().contains(sp.sequence)) {
\r
460 av.getSelection().addElement(sp.sequence);
\r
465 // if (changedSel) {
\r
466 // fireSequenceSelectionEvent(av.getSelection());
\r
469 public SequenceI findPoint(int x, int y) {
\r
471 int halfwidth = getWidth()/2;
\r
472 int halfheight = getHeight()/2;
\r
476 for (int i=0; i < npoint; i++) {
\r
478 SequencePoint sp = (SequencePoint)points.elementAt(i);
\r
479 int px = (int)((float)(sp.coord[0] - centre[0])*scale) + halfwidth;
\r
480 int py = (int)((float)(sp.coord[1] - centre[1])*scale) + halfheight;
\r
483 if (Math.abs(px-x)<3 && Math.abs(py - y) < 3 ) {
\r
488 return ((SequencePoint)points.elementAt(found)).sequence;
\r
493 /* public boolean handleRubberbandEvent(RubberbandEvent evt) {
\r
494 System.out.println("Rubberband handler called in RotatableCanvas with " +
\r
497 Rubberband rb = (Rubberband)evt.getSource();
\r
499 // Clear the current selection (instance variable)
\r
500 //if ((rb.getModifiers() & Event.SHIFT_MASK) == 0) {
\r
501 // clearSelection();
\r
504 if (rb.getComponent() == this) {
\r
505 Rectangle bounds = evt.getBounds();
\r
506 rectSelect(bounds.x,bounds.y,bounds.x+bounds.width,bounds.y+bounds.height);
\r
509 redrawneeded = true;
\r
510 paint(this.getGraphics());
\r