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
297 if (av.getSelectionGroup() != null)
\r
299 if (av.getSelectionGroup().sequences.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
385 if (av.getSelectionGroup() != null)
\r
387 av.getSelectionGroup().addOrRemove(found);
\r
388 PaintRefresher.Refresh(this);
\r
392 av.setSelectionGroup(new SequenceGroup());
\r
393 av.getSelectionGroup().addOrRemove(found);
\r
394 av.getSelectionGroup().setEndRes(av.alignment.getWidth());
\r
401 // private void fireSequenceSelectionEvent(Selection sel) {
\r
402 // controller.handleSequenceSelectionEvent(new SequenceSelectionEvent(this,sel));
\r
405 public void mouseMoved(MouseEvent evt)
\r
407 SequenceI found = findPoint(evt.getX(), evt.getY());
\r
409 this.setToolTipText(found.getName());
\r
411 this.setToolTipText(null);
\r
414 public void mouseDragged(MouseEvent evt) {
\r
417 //Check if this is a rectangle drawing drag
\r
418 if ((evt.getModifiers() & InputEvent.BUTTON2_MASK) != 0) {
\r
419 // rectx2 = evt.getX();
\r
420 // recty2 = evt.getY();
\r
422 rotmat.setIdentity();
\r
424 rotmat.rotate((float)(my-omy),'x');
\r
425 rotmat.rotate((float)(mx-omx),'y');
\r
427 for (int i = 0; i < npoint; i++) {
\r
428 SequencePoint sp = (SequencePoint)points.elementAt(i);
\r
429 sp.coord[0] -= centre[0];
\r
430 sp.coord[1] -= centre[1];
\r
431 sp.coord[2] -= centre[2];
\r
433 //Now apply the rotation matrix
\r
434 sp.coord= rotmat.vectorMultiply(sp.coord);
\r
436 //Now translate back again
\r
437 sp.coord[0] += centre[0];
\r
438 sp.coord[1] += centre[1];
\r
439 sp.coord[2] += centre[2];
\r
442 for (int i=0; i < 3; i++) {
\r
443 axes[i] = rotmat.vectorMultiply(axes[i]);
\r
448 paint(this.getGraphics());
\r
453 public void rectSelect(int x1, int y1, int x2, int y2) {
\r
454 boolean changedSel = false;
\r
455 for (int i=0; i < npoint; i++) {
\r
456 SequencePoint sp = (SequencePoint)points.elementAt(i);
\r
457 int tmp1 = (int)((sp.coord[0] - centre[0])*scale + (float)getWidth()/2.0);
\r
458 int tmp2 = (int)((sp.coord[1] - centre[1])*scale + (float)getHeight()/2.0);
\r
460 if (tmp1 > x1 && tmp1 < x2 && tmp2 > y1 && tmp2 < y2) {
\r
462 if (!av.getSelectionGroup().sequences.contains(sp.sequence))
\r
465 av.getSelectionGroup().addSequence(sp.sequence);
\r
470 // if (changedSel) {
\r
471 // fireSequenceSelectionEvent(av.getSelection());
\r
474 public SequenceI findPoint(int x, int y) {
\r
476 int halfwidth = getWidth()/2;
\r
477 int halfheight = getHeight()/2;
\r
481 for (int i=0; i < npoint; i++) {
\r
483 SequencePoint sp = (SequencePoint)points.elementAt(i);
\r
484 int px = (int)((float)(sp.coord[0] - centre[0])*scale) + halfwidth;
\r
485 int py = (int)((float)(sp.coord[1] - centre[1])*scale) + halfheight;
\r
488 if (Math.abs(px-x)<3 && Math.abs(py - y) < 3 ) {
\r
493 return ((SequencePoint)points.elementAt(found)).sequence;
\r
498 /* public boolean handleRubberbandEvent(RubberbandEvent evt) {
\r
499 System.out.println("Rubberband handler called in RotatableCanvas with " +
\r
502 Rubberband rb = (Rubberband)evt.getSource();
\r
504 // Clear the current selection (instance variable)
\r
505 //if ((rb.getModifiers() & Event.SHIFT_MASK) == 0) {
\r
506 // clearSelection();
\r
509 if (rb.getComponent() == this) {
\r
510 Rectangle bounds = evt.getBounds();
\r
511 rectSelect(bounds.x,bounds.y,bounds.x+bounds.width,bounds.y+bounds.height);
\r
514 redrawneeded = true;
\r
515 paint(this.getGraphics());
\r