001 /** 002 * Created by IntelliJ IDEA. 003 * User: Wei Wang 004 * Date: Mar 2, 2003 005 * Time: 9:05:11 PM 006 */ 007 008 package EVolve.visualization; 009 010 import java.awt.Color; 011 import java.awt.Font; 012 import java.awt.Graphics; 013 import java.awt.Graphics2D; 014 import java.awt.Point; 015 import java.awt.event.MouseAdapter; 016 import java.awt.event.MouseEvent; 017 import java.awt.event.MouseMotionAdapter; 018 import java.awt.geom.AffineTransform; 019 import java.awt.geom.Point2D; 020 import java.awt.geom.Rectangle2D; 021 import java.awt.image.BufferedImage; 022 import java.util.ArrayList; 023 024 import javax.swing.JPanel; 025 import javax.swing.JScrollPane; 026 027 import EVolve.exceptions.NoDataPlotException; 028 029 public class AxesPanel extends JPanel{ 030 public final static int Axis_Enabled = 0x00001; 031 public final static int Scale_Image = 0x11000000; 032 public final static int Flip_Image = 0x00100; 033 public final static int Pointer_Enabled = 0x01000; 034 public final static int Box_Enabled = 0x10000; 035 public final static int Null = 0x0; 036 public final static int Scale_X = 0x10000000; 037 public final static int Scale_Y = 0x01000000; 038 039 private int flag; 040 private String xName=" ", yName=" "; 041 private Point origin, imageAdjustment, pointerPosition; 042 private Point boxStart, boxEnd; 043 private Point2D.Double mousePos; 044 private int zoomingWidth, zoomingHeight, shapeSize; 045 private BufferedImage image; 046 private JScrollPane parent = null; 047 private ArrayList phases, stringList; 048 049 private AutoImage autoImage; 050 private double factorX, factorY; 051 052 public AxesPanel(int flag) { 053 this.flag = flag; 054 origin = new Point(0,0); 055 imageAdjustment = new Point(0,0); 056 pointerPosition = new Point(0,0); 057 boxStart = new Point(0,0); 058 boxEnd = new Point(0,0); 059 mousePos = new Point2D.Double(0,0); 060 zoomingWidth = zoomingHeight = 20; 061 shapeSize = 1; 062 stringList = new ArrayList(); 063 factorX = factorY = 1; 064 if ((flag & 0x000f) == Axis_Enabled) { 065 origin.setLocation(20,20); 066 imageAdjustment.x = 60; 067 imageAdjustment.y = 60; 068 } 069 addMouseListener(new MouseAdapter() { 070 public void mousePressed(MouseEvent e) { 071 if (e.getButton() == MouseEvent.BUTTON1) { 072 mPressed(e.getX(), e.getY()); 073 } 074 } 075 }); 076 077 addMouseListener(new MouseAdapter() { 078 public void mouseReleased(MouseEvent e) { 079 if (e.getButton() == MouseEvent.BUTTON1) { 080 mReleased(); 081 } 082 } 083 }); 084 085 addMouseMotionListener(new MouseMotionAdapter() { 086 public void mouseDragged(MouseEvent e) { 087 mDragged(e.getX(), e.getY()); 088 } 089 }); 090 } 091 092 private void drawAxis(Graphics2D g2) { 093 094 if ((flag & 0x000f)==Axis_Enabled) {//axis is enabled 095 int w = getWidth(), h = getHeight(); 096 g2.setColor(Color.black); 097 g2.drawLine(origin.x, h - origin.y, w - origin.x, h - origin.x); 098 g2.drawLine(w - origin.x, h - origin.y, w - 30, h - 15); 099 g2.drawLine(w - origin.x, h - origin.y, w - 30, h - 25); 100 g2.drawLine(origin.x, h - origin.y, origin.x, origin.y); 101 g2.drawLine(origin.x, origin.y, 15, 30); 102 g2.drawLine(origin.x, origin.y, 25, 30); 103 104 105 Font font = new Font("Arial", Font.PLAIN, 12); 106 g2.setFont(font); 107 g2.drawString(xName, w - g2.getFontMetrics().stringWidth(xName) - 40, h - 5); 108 g2.rotate(-Math.PI / 2.0); 109 g2.drawString(yName, -40 - g2.getFontMetrics().stringWidth(yName), 15); 110 g2.rotate(Math.PI / 2.0); 111 } 112 } 113 114 private void drawImage(Graphics2D g2) { 115 int h = getHeight(), flip = 1; 116 AffineTransform tf = g2.getTransform(); 117 118 if ((flag&0x0f00)==Flip_Image) { 119 flip = -1; 120 g2.translate(origin.x+1, h - origin.y); 121 } 122 123 calcScaleFactors(); 124 125 g2.scale(factorX,(double)flip*factorY); 126 g2.drawImage(image, 0, 0, null); 127 g2.setTransform(tf); 128 } 129 130 private void drawBox(Graphics2D g2) { 131 g2.setColor(Color.blue); 132 int x1 = (boxStart.x < boxEnd.x) ? boxStart.x : boxEnd.x; 133 int x2 = (boxStart.x > boxEnd.x) ? boxStart.x : boxEnd.x; 134 int y1 = (boxStart.y < boxEnd.y) ? boxStart.y : boxEnd.y; 135 int y2 = (boxStart.y > boxEnd.y) ? boxStart.y : boxEnd.y; 136 g2.drawRect(x1, y1, x2 - x1, y2 - y1); 137 } 138 139 private void drawPhases(Graphics2D g2) { 140 int w = getWidth(), h = getHeight(); 141 142 if ((phases == null)||(phases.size() == 0)) return; 143 144 calcScaleFactors(); 145 146 g2.setColor(Color.black); 147 148 int lastX = 0, currentX = 0; 149 for (int i=0; i<phases.size(); i++) { 150 int phaseEnd = ((Integer)phases.get(i)).intValue(); 151 152 if (phaseEnd <= 0) continue; 153 154 currentX = (int)(phaseEnd*factorX)+origin.x; 155 g2.drawString(String.valueOf(phaseEnd),currentX,10+(i%2)*10); 156 g2.drawString("("+i+")", (currentX + lastX)/2-5, 30); 157 g2.drawLine(currentX, h-origin.y, (int)(phaseEnd*factorX)+origin.x, origin.y); 158 lastX = currentX; 159 } 160 g2.drawString("("+phases.size()+")", (currentX + w)/2-5, 30); 161 162 } 163 164 private void drawPointer(Graphics2D g2) { 165 if ((flag&0xf000)==Pointer_Enabled) { 166 int x = pointerPosition.x, y = pointerPosition.y; 167 g2.setColor(Color.black); 168 g2.drawLine(x,y,x+20,y+20); 169 g2.drawLine(x,y,x+10,y+5); 170 g2.drawLine(x,y,x+5,y+10); 171 } 172 } 173 174 private void setPreferredPanelSize() { 175 if (parent == null) return; 176 int width = image.getWidth()+imageAdjustment.x; 177 int height = image.getHeight()+imageAdjustment.y; 178 179 if ((flag&0xf0000000) == Scale_X) 180 width = parent.getWidth() - 14; 181 if ((flag&0x0f000000) == Scale_Y) 182 height = parent.getHeight()-14; 183 184 setPreferredSize(new java.awt.Dimension(width, height)); 185 /*if ((flag&0xff000000) != Scale_Image) { 186 setPreferredSize(new java.awt.Dimension(image.getWidth()+imageAdjustment.x,image.getHeight()+imageAdjustment.y)); 187 } else { 188 setPreferredSize(new java.awt.Dimension(parent.getWidth()-14, parent.getHeight()-14)); 189 }*/ 190 revalidate(); 191 } 192 193 private void drawStrings(Graphics2D g2) { 194 for (int i=0; i<stringList.size(); i++) { 195 Object[] values = (Object[])stringList.get(i); 196 int x = ((Integer)values[0]).intValue() - origin.x; 197 int y = ((Integer)values[1]).intValue(); 198 String content = (String)values[2]; 199 200 if ((flag & 0xf0000000) == Scale_X) 201 x = (int) ((float)x*(float)(getWidth()-imageAdjustment.x)/(float)image.getWidth()+origin.x); 202 else 203 x = x + origin.x; 204 205 if ((flag & 0x0f000000) == Scale_Y) { 206 if ((flag & 0x00f00) == Flip_Image) 207 y = (int)((float)getHeight()-(float)origin.y-(float)y*(float)(getHeight()-imageAdjustment.y)/(float)image.getHeight()); 208 else 209 y = (int)((float)y*(float)(getHeight()-imageAdjustment.y)/(float)image.getHeight()+(float)origin.y); 210 } 211 else { 212 if ((flag & 0x00f00) == Flip_Image) 213 y = getHeight()-origin.y-y; 214 else 215 y = y + origin.y; 216 } 217 g2.drawString(content,x,y); 218 } 219 } 220 221 public void paintComponent(Graphics g) { 222 super.paintComponent(g); 223 224 Graphics2D g2 = (Graphics2D)g; 225 226 int w = getWidth(); 227 int h = getHeight(); 228 229 g2.setColor(Color.white); 230 g2.fillRect(0, 0, w, h); 231 232 drawAxis(g2); 233 234 if (image != null) { 235 setPreferredPanelSize(); 236 drawImage(g2); 237 drawPhases(g2); 238 drawBox(g2); 239 drawStrings(g2); 240 } 241 drawPointer(g2); 242 243 } 244 245 protected void mPressed(int x, int y) { 246 if (image != null) { 247 boxStart.x = x; 248 boxStart.y = y; 249 boxEnd.x = x; 250 boxEnd.y = y; 251 flag = flag | Box_Enabled; 252 repaint(); 253 } 254 } 255 256 protected void mReleased() { 257 if (image != null) { 258 flag = flag & 0xff00ffff; 259 } 260 } 261 262 protected void mDragged(int x, int y) { 263 if ((image != null)&&((flag &0xf0000) == Box_Enabled)) { 264 boxEnd.x = x; 265 boxEnd.y = y; 266 repaint(); 267 } 268 } 269 270 public void setName(String xName, String yName) { 271 this.xName = xName; 272 this.yName = yName; 273 } 274 275 public void setImage(BufferedImage image) { 276 this.image = image; 277 278 boxStart.x = 0; 279 boxStart.y = 0; 280 boxEnd.x = 0; 281 boxEnd.y = 0; 282 flag = flag & 0xff00ffff; 283 } 284 285 public void setAutoImage(AutoImage autoImage) throws NoDataPlotException{ 286 this.autoImage = null; 287 this.autoImage = autoImage; 288 this.autoImage.setPhases(phases); 289 image = autoImage.getImage(); 290 } 291 292 public int getImageX(int x) { 293 if (image == null) return -1; 294 295 if ((flag & 0xf0000000) == Scale_X) 296 return (int)((float)(x-origin.x)*((float)image.getWidth()/(float)(getWidth()-imageAdjustment.x))); 297 else 298 return x - origin.x; 299 } 300 301 public int getImageY(int y) { 302 if (image == null) return -1; 303 304 if ((flag & 0x0f000000) == Scale_Y) { 305 if ((flag & 0x00f00) == Flip_Image) 306 return (int)((float)(getHeight()-origin.y-y)*((float)image.getHeight()/(float)(getHeight()-imageAdjustment.y))); 307 else 308 return (int)((float)(y-origin.y)*((float)image.getHeight()/(float)(getHeight()-imageAdjustment.y))); 309 } 310 else { 311 if ((flag & 0x00f00) == Flip_Image) 312 return getHeight()-origin.y-y; 313 else 314 return y - origin.y; 315 } 316 } 317 318 public int getStartX() { 319 int x = (boxStart.x < boxEnd.x) ? boxStart.x : boxEnd.x; 320 return getImageX(x); 321 } 322 323 public int getEndX() { 324 int x = (boxStart.x > boxEnd.x) ? boxStart.x : boxEnd.x; 325 return getImageX(x); 326 } 327 328 public int getStartY() { 329 int y = (boxStart.y < boxEnd.y) ? boxStart.y : boxEnd.y; 330 return getImageY(y); 331 } 332 333 public int getEndY() { 334 int y = (boxStart.y > boxEnd.y) ? boxStart.y : boxEnd.y; 335 return getImageY(y); 336 } 337 338 public void setPointerPosition(int x, int y) { 339 pointerPosition.x = x; 340 pointerPosition.y = y; 341 } 342 343 public void enablePointer(boolean draw) { 344 if (draw) 345 flag = flag | Pointer_Enabled; 346 else 347 flag = flag & (~Pointer_Enabled); 348 } 349 350 private Rectangle2D.Double calcZoomingArea(int x, int y) { 351 int w = image.getWidth(), h = image.getHeight(); 352 353 double x1=x,y1=y,w1,h1; 354 355 x1 = x1 - (double)zoomingWidth*shapeSize/2; 356 y1 = y1 - (double)zoomingHeight*shapeSize/2; 357 358 w1 = zoomingWidth*shapeSize; 359 h1 = zoomingHeight*shapeSize; 360 361 mousePos.setLocation(shapeSize*zoomingWidth/2,shapeSize*zoomingHeight/2); 362 if (x1 < 0) { 363 mousePos.x+=x1; 364 w1 = w1+x1; 365 x1 = 0; 366 } 367 if (x1 + w1 > w) { 368 w1 = w - x1; 369 } 370 371 if (y1 < 0) { 372 mousePos.y+=y1; 373 h1 = h1+y1; 374 y1 = 0; 375 } 376 if (y1 + h1 > h) { 377 h1 = h - y1; 378 } 379 380 Rectangle2D.Double ret = new Rectangle2D.Double(); 381 ret.x = x1; 382 ret.y = y1; 383 ret.width = w1; 384 ret.height = h1; 385 return ret; 386 } 387 388 public BufferedImage getSubImage(int x, int y) { 389 int w = image.getWidth(), h = image.getHeight(); 390 Rectangle2D.Double zooming = calcZoomingArea(x,y); 391 392 if ((image == null)||(zooming.x>w)||(zooming.y>h)) 393 return null; 394 395 if ((zooming.width<=0) || (zooming.height<=0)) return null; 396 397 return image.getSubimage((int)zooming.x,(int)zooming.y,(int)zooming.width,(int)zooming.height); 398 } 399 400 public void drawZoomingArea(int x, int y) { 401 double coX = 1, coY = 1; 402 403 if ((flag & 0xf0000000) == Scale_X) { 404 coX = (double)(getWidth() - imageAdjustment.x)/(double)image.getWidth(); 405 } 406 if ((flag & 0x0f0000000) == Scale_Y) { 407 coY = (double)(getHeight() - imageAdjustment.y)/(double)image.getHeight(); 408 } 409 int deltaX = (int)(coX*zoomingWidth*shapeSize/2); 410 int deltaY = (int)(coY*zoomingHeight*shapeSize/2); 411 412 boxStart.x = x - deltaX; 413 boxStart.y = y - deltaY; 414 boxEnd.x = x + deltaX; 415 boxEnd.y = y + deltaY; 416 flag = flag | Box_Enabled; 417 repaint(); 418 flag = flag & (~Box_Enabled); 419 } 420 421 public void setShapeSize(int shapeSize) { 422 this.shapeSize = shapeSize; 423 } 424 425 public void setZoomingSize(int w, int h) { 426 zoomingWidth = w; 427 zoomingHeight = h; 428 } 429 430 public Point2D.Double getMouseMovement() { 431 return mousePos; 432 } 433 434 public void scaleImage(boolean scaled) { 435 if (scaled) 436 flag = flag | Scale_Image; 437 else 438 flag = flag & (~Scale_Image); 439 } 440 441 public void setParent(JScrollPane parent) { 442 this.parent = parent; 443 } 444 445 public void setPanelFlag(int flag) { 446 this.flag = flag; 447 if ((flag & 0x000f) != Axis_Enabled) { 448 origin.setLocation(0,0); 449 imageAdjustment.x = 0; 450 imageAdjustment.y = 0; 451 } 452 } 453 454 public Point getOrigin() { 455 return origin; 456 } 457 458 public void setPhases(ArrayList phases) { 459 this.phases = phases; 460 if (autoImage == null) return; 461 autoImage.setPhases(phases); 462 try { 463 image = autoImage.getImage(); 464 } catch (NoDataPlotException e) { 465 // fall through 466 } 467 } 468 469 public void addString(int x, int y, String content) { 470 Object[] aString = new Object[3]; 471 472 aString[0] = new Integer(x); 473 aString[1] = new Integer(y); 474 aString[2] = content; 475 stringList.add(aString); 476 } 477 478 public void reset() { 479 stringList.clear(); 480 } 481 482 public int getFlag() { 483 return flag; 484 } 485 486 public Object clone() { 487 AxesPanel o = new AxesPanel(flag); 488 489 o.xName = xName; 490 o.yName = yName; 491 o.zoomingWidth = zoomingWidth; 492 o.zoomingHeight = zoomingHeight; 493 o.shapeSize = shapeSize; 494 return o; 495 } 496 497 private void calcScaleFactors() { 498 int w = getWidth(), h = getHeight(); 499 factorX = factorY = 1; 500 if ((flag&0xf0000000) == Scale_X) 501 factorX = (double)(w - imageAdjustment.x) / (double)(image.getWidth()); 502 if ((flag&0x0f000000) == Scale_Y) 503 factorY = (double)(h - imageAdjustment.y) / (double)(image.getHeight()); 504 } 505 }