1 package org.convey; 2 3 import java.util.*; 4 import java.awt.*; 5 import java.awt.event.*; 6 import java.awt.geom.*; 7 import javax.swing.event.*; 8 import javax.swing.*; 9 import javax.swing.border.*; 10 import org.jdom.output.*; 11 import org.jdom.*; 12 13 /** 14 * GraphicPanel is a JPanel implementation that manages the Graphic objects. 15 * This class provides the link between the Graphic objects and Java Swing's 16 * painting and input mechanisms. 17 * <p> 18 * The GraphicPanel has a state field indicating which mode of interaction the 19 * GraphicPanel is in. For example, if the state is SELECT, the user may select 20 * existing graphic objects in the panel. One or more graphic objects may be 21 * selected simultaneously by clicking them directly or dragging a rectangular 22 * selection box. 23 * <p> 24 * Additionally, in the SELECT state, the user may move the set of selected 25 * graphics. 26 * <p> 27 * In the RECTANGLE state, the user may create rectangles with the mouse by 28 * dragging a rectangular regon in the graphic panel. This is known as a 29 * graphic creation state. 30 * <p> 31 * All states except SELECT and VERTEX are considered graphic creation states 32 * because these states allow the user to create new graphic objects. When the 33 * graphic panel is in a creation state and the user is creating a new graphic, 34 * the newGraphic field stores a reference to the new graphic. When the user has 35 * completed the graphic creation, the new graphic is added to the Vector of 36 * graphic objects and newGraphic is set to null. 37 * <p> 38 * There are four Vectors of graphic objects: graphics, selectedGraphics, and 39 * clipboardGraphics. 40 * <p> 41 * The graphics Vector consists of all graphic objects that have NOT been sent 42 * across the Jabber network. These graphic objects are painted in the graphic 43 * panel without a selection border nor selection handles. 44 * <p> 45 * The selectedGraphic Vector consists of all graphic objects in the SELECTED 46 * state and have NOT been sent across the Jabber network. These graphic objects 47 * are painted in the graphic panel with a selection border or selection 48 * handles. Graphic objects in this Vector are also stored in the graphics 49 * Vector. 50 * <p> 51 * The clipboardGraphics Vector consists of org.jdom.Element references that 52 * describe the set of graphic objects that have been cut or copied into the 53 * clipboard. This Vector does not actually store Graphic references. 54 * <p> 55 * 56 * @author Andy Ames, Ed Braunhut 57 */ 58 public class GraphicPanel extends JPanel 59 implements MouseInputListener, KeyListener { 60 61 public static final int SELECT = 0; 62 public static final int SCALE = 1; 63 public static final int TEXT = 2; 64 public static final int RECTANGLE = 3; 65 public static final int ELLIPSE = 4; 66 public static final int POLYLINE = 5; 67 public static final int POLYGON = 6; 68 public static final int QUADCURVE = 7; 69 public static final int CUBICCURVE = 8; 70 public static final int FITTEDCURVE = 9; 71 public static final int FREEHANDCURVE = 10; 72 73 private static final int MAX_STATE = 10; 74 75 private transient boolean incoming; 76 77 private transient boolean hasPen; 78 79 protected transient CanvasPanel canvasPanel = null; 80 81 protected transient Graphic newGraphic = null; 82 83 protected Hashtable nameGraphicTable = new Hashtable(); 84 85 /** 86 * Vector of all Graphic objects contained in the GraphicPanel. The Graphic 87 * objects are ordered from back to front. 88 */ 89 protected Vector graphics = new Vector(); 90 91 protected transient Vector selectedGraphics = new Vector(); 92 93 protected Vector graphicEvents = new Vector(); 94 95 protected int lastGraphicEventIndex = -1; 96 97 protected Vector graphicEventStack = new Vector(); 98 99 /** 100 * Stores GraphicEvents when auto send is off. They are then sent when auto 101 * send is turned back on, or when the pen is yielded. 102 */ 103 protected Vector graphicEventQueue = new Vector(); 104 105 /** 106 * State of the graphic panel. One of SELECT, VERTEX, TEXT, RECTANGLE, ELLIPSE, 107 * POLYLINE, POLYGON, QUADCURVE, CUBICCURVE, and FITTEDCURVE. 108 */ 109 protected transient int state; 110 111 /** 112 * Flag indicating if the user is in the process of dragging a rectangular 113 * selection box. This flag is always false when the graphic panel is not in 114 * the SELECT nor the VERTEX state. 115 * 116 * @todo Get rid of this flag. Its redundant. 117 */ 118 protected transient boolean rectSelecting = false; 119 120 /** 121 * Current rectangular selection area. This Rectangle is null when 122 * rectSelecting is false. 123 */ 124 protected transient Rectangle selectRect = null; 125 126 /** 127 * Point indicating the last point captured from a mouseDragged event. 128 */ 129 protected transient Point lastDragPoint; 130 131 /** 132 * Point indicating the last point captured from a mousePressed event. 133 */ 134 protected transient Point pressPoint; 135 136 protected transient Graphic vertexSelected = null; 137 138 protected boolean autoSend; 139 140 /** 141 * Set white for the background color. Set up mouse and key listeners. 142 */ GraphicPanel(CanvasPanel canvasPanel)143 public GraphicPanel(CanvasPanel canvasPanel) { 144 super.setBorder(new SoftBevelBorder(SoftBevelBorder.LOWERED)); 145 this.incoming = false; 146 147 super.setBackground(Color.white); 148 149 this.canvasPanel = canvasPanel; 150 151 super.addMouseListener(this); 152 super.addMouseMotionListener(this); 153 super.addKeyListener(this); 154 155 this.hasPen = true; 156 } 157 setHasPen(boolean value)158 public void setHasPen(boolean value) { 159 CanvasPanel canvasPanel = this.getCanvasPanel(); 160 if(canvasPanel instanceof JabberCanvasPanel) { 161 JabberCanvasPanel jabberCanvasPanel = (JabberCanvasPanel)canvasPanel; 162 jabberCanvasPanel.getConveyFrame().changePenIcon(jabberCanvasPanel, value); 163 } 164 this.hasPen = value; 165 } 166 hasPen()167 public boolean hasPen() { 168 return this.hasPen; 169 } 170 isIncoming()171 public boolean isIncoming() { 172 return this.incoming; 173 } 174 setIncoming(boolean incoming)175 public void setIncoming(boolean incoming) { 176 this.incoming = incoming; 177 } 178 179 /** 180 * Paints the GraphicPanel component by painting all Graphic objects. 181 * <p> 182 * First, the lockedGraphics Vector graphic objects are painted. Second, the 183 * graphics Vector graphic objects are painted. 184 * <p> 185 * Third, if newGraphic is valid, it is painted. Otherwise, the 186 * selectedGraphics Vector graphic objects have their selection painted. 187 * <p> 188 * Finally, if rectSelecting is true, the selectRect rectangle is painted. 189 */ paintComponent(Graphics g)190 public void paintComponent(Graphics g) { 191 super.paintComponent(g); 192 193 Graphics2D g2d = (Graphics2D)g; 194 195 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 196 197 Iterator iter = this.graphics.iterator(); 198 while (iter.hasNext()) { 199 Graphic graphic = (Graphic) iter.next(); 200 graphic.paint(g2d); 201 if (graphic.getState() == Graphic.SELECTED) 202 graphic.paintSelection(g2d); 203 } 204 205 if(this.newGraphic != null) { 206 this.newGraphic.paint(g2d); 207 if(this.newGraphic instanceof TextGraphic) 208 this.newGraphic.paintSelection(g2d); 209 } 210 211 if(rectSelecting) { 212 g2d.setStroke(new BasicStroke(1)); 213 g2d.setColor(Color.gray); 214 g2d.draw(selectRect); 215 } 216 217 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); 218 } 219 graphicIterator()220 public Iterator graphicIterator() { 221 return this.graphics.iterator(); 222 } 223 224 /** 225 * Sets the state of the graphicPanel. Possible states are SELECT, VERTEX, 226 * TEXT, RECTANGLE, ELLIPSE, POLYLINE, POLYGON, QUADCURVE, CUBICCURVE, 227 * FITTEDCURVE and FREEHANDCURVE. 228 * <p> 229 * Currently, we are repainting the entire graphic panel when this happens. 230 * 231 * @todo Identify what needs to be repainted when. Only repaint in those 232 * cases. 233 */ setState(int state)234 void setState(int state) { 235 if(state <= MAX_STATE && state >= 0 && state != this.state) { 236 this.state = state; 237 super.repaint(); 238 } 239 } 240 241 /** 242 * Gets the state of the graphicPanel. Possible states are SELECT, VERTEX, 243 * TEXT, RECTANGLE, ELLIPSE, POLYLINE, POLYGON, QUADCURVE, CUBICCURVE, 244 * FITTEDCURVE and FREEHANDCURVE. 245 */ getState()246 int getState() { 247 return this.state; 248 } 249 deselectAll()250 public void deselectAll() { 251 Vector oldSelectedGraphics = this.selectedGraphics; 252 this.selectedGraphics = new Vector(); 253 254 Iterator iter = oldSelectedGraphics.iterator(); 255 while(iter.hasNext()) { 256 Graphic graphic = (Graphic)iter.next(); 257 graphic.setState(Graphic.DORMANT); 258 } 259 260 this.canvasPanel.getConveyFrame().updateButtons(); 261 } 262 263 /** 264 * Invoked when a mouse button has been pressed on the graphic panel. 265 * <p> 266 * Depending on the state of the graphic panel, this event may or may not 267 * be forwarded to one or more graphic objects. 268 * <p> 269 * For example, if the state is a graphic creation state and the newGraphic 270 * field is non-null, then the newGraphic receives this event. 271 * <p> 272 * If the newGraphic field is null, some graphic creation states will have 273 * a new graphic created in response to this method. Other graphic creation 274 * states have a new graphic created in response to mouseClicked. 275 * <p> 276 * Currently, the following graphic creation states require a mousePressed to 277 * begin the creation process: RECTANGLE, ELLIPSE, FITTEDCURVE and FREEHANDCURVE. 278 */ mousePressed(MouseEvent e)279 public void mousePressed(MouseEvent e) { 280 Iterator iter; 281 282 super.requestFocus(); 283 284 if(this.hasPen && this.newGraphic != null && this.newGraphic instanceof TextGraphic) { 285 if(!this.newGraphic.hitPath(e.getPoint())) { 286 ((TextGraphic)this.newGraphic).setCursor(-1); 287 this.newGraphic.setState(Graphic.DORMANT); 288 this.addGraphic(this.newGraphic); 289 this.addGraphicEvent(new NewGraphicEvent(this.newGraphic)); 290 this.newGraphic = null; 291 } 292 } 293 294 if(this.hasPen && this.newGraphic != null) { 295 this.newGraphic.mousePressed(e); 296 297 if(newGraphic.getState() != Graphic.CREATING) { 298 299 // if newGraphic is no longer in CREATING state after processing event, 300 // add the newGraphic to the graphics Vector 301 this.addGraphic(this.newGraphic); 302 this.newGraphic.setState(Graphic.SELECTED); 303 this.addGraphicEvent(new NewGraphicEvent(this.newGraphic)); 304 this.newGraphic = null; 305 } 306 } else { 307 308 Point p = e.getPoint(); 309 310 // if newGraphic is null... 311 312 if(this.hasPen && this.state != SELECT && this.state != SCALE) { 313 314 // Check if we hit a vertex of a selected graphic. If so, pop ourselves 315 // into SELECT state and carry on. 316 317 Graphic graphic = this.hitGraphic(p); 318 if(graphic != null && graphic.getState() == Graphic.SELECTED && graphic.hitVertex(p)) { 319 this.vertexSelected = graphic; 320 graphic.setOrig(); 321 graphic.mousePressed(e); 322 return; 323 } 324 325 // If we're not in SELECT or VERTEX states (we are in a graphic creation 326 // state) we're about to create a new Graphic, deselect everyone. 327 deselectAll(); 328 } 329 330 switch(this.state) { 331 case SELECT: 332 Graphic selected = null; 333 this.vertexSelected = null; 334 335 if(!e.isControlDown() && !e.isAltDown() && 336 !e.isShiftDown() && !e.isMetaDown()) { 337 338 // If we are single-selecting... 339 340 // What graphic got hit? 341 selected = hitGraphic(p); 342 343 if(selected != null) { 344 // if a graphic was hit... 345 346 if(selected.getState() == Graphic.DORMANT) { 347 348 // If the hit graphic was previously DORMANT, deselect all 349 deselectAll(); 350 351 // select hit graphic 352 selected.setState(Graphic.SELECTED); 353 } else if(selected.hitVertex(p)) 354 this.vertexSelected = selected; 355 } else { 356 357 // If a graphic was not hit, deselect all 358 deselectAll(); 359 360 // Enter rectangular select mode 361 rectSelecting = true; 362 selectRect = new Rectangle(p); 363 lastDragPoint = pressPoint = p; 364 } 365 } else { 366 367 // If we are multi-selecting... 368 369 // What graphic got hit? 370 selected = hitGraphic(p); 371 372 if(selected != null) { 373 374 // If a graphic got hit... 375 376 if(selected.getState() == Graphic.DORMANT) { 377 378 // If the hit graphic was previously DORMANT, add it to the 379 // selectedGraphics Vector. 380 selected.setState(Graphic.SELECTED); 381 } else { 382 383 // If the hit graphic was previously SELECTED, remove it from 384 // the selectedGraphics Vector. 385 selected.setState(Graphic.DORMANT); 386 } 387 } else { 388 389 // If a graphic was NOT hit, enter rectangular select mode 390 rectSelecting = true; 391 selectRect = new Rectangle(p); 392 lastDragPoint = pressPoint = p; 393 } 394 } 395 396 // Finally, we give all selected Graphic objects the mousePressed 397 // event only if vertexOnly is false... 398 if(this.hasPen && this.vertexSelected == null) { 399 iter = this.selectedGraphics.iterator(); 400 while(iter.hasNext()) { 401 Graphic graphic = (Graphic)iter.next(); 402 graphic.setOrig(); 403 graphic.mousePressed(e); 404 } 405 } else if(this.hasPen) { 406 vertexSelected.setOrig(); 407 vertexSelected.mousePressed(e); 408 } 409 410 break; 411 case SCALE: 412 selected = hitGraphic(p); 413 414 deselectAll(); 415 416 if(selected != null) { 417 selected.setState(Graphic.SELECTED); 418 if(this.hasPen) { 419 selected.setOrig(); 420 selected.mousePressed(e); 421 } 422 } 423 break; 424 case RECTANGLE: 425 if(this.hasPen) { 426 QuadGraphic quadGraphic = new QuadGraphic(this, e.getPoint()); 427 this.newGraphic = quadGraphic; 428 } 429 break; 430 case ELLIPSE: 431 if(this.hasPen) { 432 EllipseGraphic ellipseGraphic = new EllipseGraphic(this, e.getPoint()); 433 this.newGraphic = ellipseGraphic; 434 } 435 break; 436 case FITTEDCURVE: 437 if(this.hasPen) { 438 FittedCurveGraphic curveGraphic = new FittedCurveGraphic(this, e.getPoint()); 439 this.newGraphic = curveGraphic; 440 } 441 break; 442 case FREEHANDCURVE: 443 if(this.hasPen) { 444 FreehandGraphic freeGraphic = new FreehandGraphic(this, e.getPoint()); 445 this.newGraphic = freeGraphic; 446 } 447 break; 448 } 449 } 450 451 this.canvasPanel.getConveyFrame().updateButtons(); 452 } 453 454 /** 455 * Invoked when a mouse button has been released. 456 */ mouseReleased(MouseEvent e)457 public void mouseReleased(MouseEvent e) { 458 if(rectSelecting) { 459 460 // If we were selecting a rectangular region... 461 462 Iterator iter = graphics.iterator(); 463 while(iter.hasNext()) { 464 Graphic graphic = (Graphic) iter.next(); 465 if(graphic.hitPath(selectRect) && graphic.getState() != Graphic.SELECTED) 466 graphic.setState(Graphic.SELECTED); 467 } 468 rectSelecting = false; 469 selectRect.grow(5, 5); 470 super.repaint(selectRect); 471 } else if(this.hasPen && newGraphic != null) { 472 newGraphic.mouseReleased(e); 473 if(newGraphic.getState() == Graphic.DELETE) { 474 Graphic graphic = this.newGraphic; 475 this.newGraphic = null; 476 graphic.forceRepaint(); 477 } else if(newGraphic.getState() != Graphic.CREATING) { 478 this.addGraphic(this.newGraphic); 479 this.newGraphic.setState(Graphic.SELECTED); 480 this.addGraphicEvent(new NewGraphicEvent(this.newGraphic)); 481 this.newGraphic = null; 482 } 483 } else if(this.hasPen && this.vertexSelected == null) { 484 Iterator iter = this.selectedGraphics.iterator(); 485 while(iter.hasNext()) { 486 Graphic graphic = (Graphic)iter.next(); 487 graphic.mouseReleased(e); 488 } 489 } else if(this.hasPen) { 490 this.vertexSelected.mouseReleased(e); 491 this.vertexSelected = null; 492 } 493 494 GraphicEvent event = this.popAllGraphicEvents(); 495 if(event != null) 496 this.addGraphicEvent(event); 497 498 this.canvasPanel.getConveyFrame().updateButtons(); 499 } 500 501 /** 502 * Invoked when the mouse has been clicked on a component. 503 */ mouseClicked(MouseEvent e)504 public void mouseClicked(MouseEvent e) { 505 if(!this.hasPen && !this.isIncoming()) 506 return; 507 508 if(newGraphic != null) { 509 newGraphic.mouseClicked(e); 510 if(newGraphic.getState() != Graphic.CREATING) { 511 this.addGraphic(this.newGraphic); 512 this.newGraphic.setState(Graphic.SELECTED); 513 this.addGraphicEvent(new NewGraphicEvent(this.newGraphic)); 514 this.newGraphic = null; 515 } 516 } else { 517 switch(this.state) { 518 case SELECT: 519 case SCALE: 520 Iterator iter = this.selectedGraphics.iterator(); 521 while(iter.hasNext()) { 522 Graphic graphic = (Graphic)iter.next(); 523 graphic.mouseClicked(e); 524 } 525 if(e.getClickCount() == 2) { 526 Graphic hitGraphic = this.hitGraphic(e.getPoint()); 527 if(hitGraphic instanceof TextGraphic) { 528 TextGraphic textGraphic = (TextGraphic)hitGraphic; 529 530 this.deselectAll(); 531 532 this.addSelectedGraphic(textGraphic); 533 534 textGraphic.edit(e.getPoint()); 535 } 536 } 537 break; 538 case TEXT: 539 TextGraphic textGraphic = new TextGraphic(this, new Point(e.getX(), e.getY())); 540 this.newGraphic = textGraphic; 541 break; 542 case POLYGON: 543 PolygonGraphic polygonGraphic = new PolygonGraphic(this, e.getPoint()); 544 this.newGraphic = polygonGraphic; 545 break; 546 case POLYLINE: 547 PolylineGraphic polylineGraphic = new PolylineGraphic(this, e.getPoint()); 548 this.newGraphic = polylineGraphic; 549 break; 550 case QUADCURVE: 551 QuadCurveGraphic quadCurveGraphic = new QuadCurveGraphic(this, e.getPoint()); 552 this.newGraphic = quadCurveGraphic; 553 break; 554 case CUBICCURVE: 555 CubicCurveGraphic cubicCurveGraphic = new CubicCurveGraphic(this, e.getPoint()); 556 this.newGraphic = cubicCurveGraphic; 557 break; 558 } 559 } 560 561 this.canvasPanel.getConveyFrame().updateButtons(); 562 } 563 564 /** 565 * Invoked when a mouse button is pressed on a component and then 566 * dragged. Mouse drag events will continue to be delivered to 567 * the component where the first originated until the mouse button is 568 * released (regardless of whether the mouse position is within the 569 * bounds of the component). 570 */ mouseDragged(MouseEvent e)571 public void mouseDragged(MouseEvent e) { 572 if(rectSelecting) { 573 Point p = e.getPoint(); 574 Rectangle newRectangle = new Rectangle(Math.min(pressPoint.x, p.x), 575 Math.min(pressPoint.y, p.y), 576 Math.abs(pressPoint.x - p.x), 577 Math.abs(pressPoint.y - p.y)); 578 Rectangle dirty = newRectangle.union(selectRect); 579 selectRect = newRectangle; 580 dirty.grow(5, 5); 581 super.repaint(dirty); 582 } else if(this.hasPen) { 583 if(newGraphic != null) { 584 newGraphic.mouseDragged(e); 585 if(newGraphic.getState() != Graphic.CREATING) { 586 this.addGraphic(this.newGraphic); 587 this.newGraphic.setState(Graphic.SELECTED); 588 this.addGraphicEvent(new NewGraphicEvent(this.newGraphic)); 589 this.newGraphic = null; 590 } 591 } else if(this.vertexSelected == null) { 592 Iterator iter = this.selectedGraphics.iterator(); 593 while(iter.hasNext()) { 594 Graphic graphic = (Graphic) iter.next(); 595 graphic.mouseDragged(e); 596 } 597 } else 598 this.vertexSelected.mouseDragged(e); 599 } 600 } 601 602 /** 603 * Invoked when the mouse button has been moved on a component 604 * (with no buttons or mouse buttons pressed) 605 */ mouseMoved(MouseEvent e)606 public void mouseMoved(MouseEvent e) { 607 if(!this.hasPen && !this.isIncoming()) 608 return; 609 610 if(newGraphic != null) { 611 newGraphic.mouseMoved(e); 612 int state = this.newGraphic.getState(); 613 if(state != Graphic.CREATING) { 614 this.addGraphic(this.newGraphic); 615 this.newGraphic.setState(Graphic.SELECTED); 616 this.addGraphicEvent(new NewGraphicEvent(this.newGraphic)); 617 this.newGraphic = null; 618 } 619 } else { 620 Iterator iter = this.selectedGraphics.iterator(); 621 while(iter.hasNext()) { 622 Graphic graphic = (Graphic)iter.next(); 623 graphic.mouseMoved(e); 624 } 625 } 626 } 627 628 /** 629 * Invoked when the mouse exits a component. 630 */ mouseExited(MouseEvent e)631 public void mouseExited(MouseEvent e) {} 632 633 /** 634 * Invoked when the mouse enters a component. 635 */ mouseEntered(MouseEvent e)636 public void mouseEntered(MouseEvent e) {} 637 638 /** 639 * Invoked when a key has been typed. This event occurs when a key press is 640 * followed by a key release. 641 */ keyTyped(KeyEvent e)642 public void keyTyped(KeyEvent e) { 643 if(!this.hasPen && !this.isIncoming()) 644 return; 645 646 if(this.newGraphic != null && this.newGraphic instanceof TextGraphic) { 647 TextGraphic textGraphic = (TextGraphic)this.newGraphic; 648 textGraphic.keyTyped(e); 649 if(textGraphic.getState() != Graphic.CREATING) { 650 this.addGraphic(this.newGraphic); 651 this.addGraphicEvent(new NewGraphicEvent(this.newGraphic)); 652 this.newGraphic.setState(Graphic.SELECTED); 653 this.newGraphic = null; 654 } 655 } else { 656 if(this.selectedGraphics.size() == 1 && this.selectedGraphics.elementAt(0) instanceof TextGraphic) { 657 TextGraphic textGraphic = (TextGraphic)this.selectedGraphics.elementAt(0); 658 textGraphic.keyTyped(e); 659 } 660 } 661 } 662 663 /** 664 * Invoked when a key has been pressed. 665 */ keyPressed(KeyEvent e)666 public void keyPressed(KeyEvent e) { 667 if(!this.hasPen && !this.isIncoming()) 668 return; 669 670 if(this.newGraphic != null && this.newGraphic instanceof TextGraphic) { 671 TextGraphic textGraphic = (TextGraphic)this.newGraphic; 672 textGraphic.keyPressed(e); 673 if(textGraphic.getState() != Graphic.CREATING) { 674 this.addGraphic(this.newGraphic); 675 this.addGraphicEvent(new NewGraphicEvent(this.newGraphic)); 676 this.newGraphic.setState(Graphic.SELECTED); 677 this.newGraphic = null; 678 } 679 } else if(this.selectedGraphics.size() == 1 && this.selectedGraphics.elementAt(0) instanceof TextGraphic) { 680 TextGraphic textGraphic = (TextGraphic)this.selectedGraphics.elementAt(0); 681 textGraphic.keyPressed(e); 682 } 683 } 684 685 /** 686 * Invoked when a key has been released. 687 */ keyReleased(KeyEvent e)688 public void keyReleased(KeyEvent e) { 689 if(!this.hasPen && !this.isIncoming()) 690 return; 691 } 692 693 /** 694 * Method iterates through the vector of all graphics in the graphicPanel 695 * and creates a new vectosr of the selected ones, which replaces the selected 696 * graphics as a single component of the vector of all graphics. 697 */ editGroup()698 public void editGroup() { 699 if(!this.hasPen && !this.isIncoming()) 700 return; 701 702 GroupGraphic group = new GroupGraphic(this); 703 704 Vector oldSelectedGraphics = this.selectedGraphics; 705 this.selectedGraphics = new Vector(); 706 707 Iterator iter = oldSelectedGraphics.iterator(); 708 while (iter.hasNext()) { 709 Graphic graphic = (Graphic) iter.next(); 710 711 graphic.setState(Graphic.DORMANT); 712 this.graphics.remove(graphic); 713 714 group.addGraphic(graphic); 715 } 716 717 this.addGraphic(group); 718 group.setState(Graphic.SELECTED); 719 720 group.updateCache(); 721 722 if(!this.isIncoming()) 723 this.addGraphicEvent(new GroupGraphicEvent(group, GroupGraphicEvent.TYPE_GROUP)); 724 725 this.canvasPanel.getConveyFrame().updateButtons(); 726 } 727 editUngroup()728 public void editUngroup() { 729 if(!this.hasPen && !this.isIncoming()) 730 return; 731 732 GroupGraphic group = (GroupGraphic)this.selectedGraphics.elementAt(0); 733 734 if(this.state == SCALE) 735 this.setState(SELECT); 736 737 // Do the following three in this order so the GroupGraphic gets repainted 738 this.selectedGraphics.clear(); 739 this.removeGraphic(group); 740 741 Iterator iter = group.iterator(); 742 743 while(iter.hasNext()) { 744 Graphic graphic = (Graphic)iter.next(); 745 746 graphic.setState(Graphic.SELECTED); 747 748 this.graphics.add(graphic); 749 } 750 751 this.canvasPanel.getConveyFrame().updateButtons(); 752 753 if(!this.isIncoming()) 754 this.addGraphicEvent(new GroupGraphicEvent(group, GroupGraphicEvent.TYPE_UNGROUP)); 755 } 756 editCut()757 public void editCut() { 758 if(!this.hasPen && !this.isIncoming()) 759 return; 760 761 this.canvasPanel.getConveyFrame().getClipboardGraphics().removeAllElements(); 762 763 Vector oldSelectedGraphics = this.selectedGraphics; 764 this.selectedGraphics = new Vector(); 765 766 Vector graphicEvents = new Vector(); 767 768 Iterator iter = oldSelectedGraphics.iterator(); 769 while(iter.hasNext()) { 770 Graphic graphic = (Graphic)iter.next(); 771 772 // Do the following two in this order so the Graphic gets erased 773 this.removeGraphic(graphic); 774 775 this.canvasPanel.getConveyFrame().getClipboardGraphics().add(graphic.toElement()); 776 777 graphicEvents.add(new DeleteGraphicEvent(graphic)); 778 } 779 780 if(graphicEvents.size() > 1) 781 this.addGraphicEvent(new CompositeGraphicEvent(graphicEvents)); 782 else if(graphicEvents.size() == 1) 783 this.addGraphicEvent((GraphicEvent)graphicEvents.elementAt(0)); 784 785 this.canvasPanel.getConveyFrame().updateButtons(); 786 } 787 editCopy()788 public void editCopy() { 789 Graphic graphic; 790 this.canvasPanel.getConveyFrame().getClipboardGraphics().removeAllElements(); 791 Iterator iter = this.selectedGraphics.iterator(); 792 while (iter.hasNext()) { 793 graphic = (Graphic)iter.next(); 794 this.canvasPanel.getConveyFrame().getClipboardGraphics().add(graphic.toElement()); 795 } 796 this.canvasPanel.getConveyFrame().updateButtons(); 797 } 798 editPaste()799 public void editPaste() { 800 if(!this.hasPen && !this.isIncoming()) 801 return; 802 803 Graphic graphic; 804 805 deselectAll(); 806 807 Vector graphicEvents = new Vector(); 808 809 Iterator iter = this.canvasPanel.getConveyFrame().getClipboardGraphics().iterator(); 810 while(iter.hasNext()) { 811 graphic = this.createGraphicFromSVGElement((Element)iter.next()); 812 813 this.addGraphic(graphic); 814 graphic.setGraphicPanel(this); 815 816 graphic.setState(Graphic.SELECTED); 817 818 graphic.updateCache(); 819 820 graphicEvents.add(new NewGraphicEvent(graphic)); 821 } 822 823 if(graphicEvents.size() > 1) 824 this.addGraphicEvent(new CompositeGraphicEvent(graphicEvents)); 825 else if(graphicEvents.size() == 1) 826 this.addGraphicEvent((GraphicEvent)graphicEvents.elementAt(0)); 827 828 this.canvasPanel.getConveyFrame().updateButtons(); 829 } 830 editDelete()831 public void editDelete() { 832 if(!this.hasPen && !this.isIncoming()) 833 return; 834 835 // Hack to avoid deleting a TextGraphic while it is in edit mode. When in 836 // edit mode, we want the TextGraphic to handle the delete key press. 837 if(this.selectedGraphics.size() == 1 && this.selectedGraphics.elementAt(0) instanceof TextGraphic) 838 if(((TextGraphic)this.selectedGraphics.elementAt(0)).getCursor() != -1) 839 return; 840 841 Vector graphicEvents = new Vector(); 842 843 Vector oldSelectedGraphics = this.selectedGraphics; 844 this.selectedGraphics = new Vector(); 845 846 Iterator iter = oldSelectedGraphics.iterator(); 847 while(iter.hasNext()) { 848 Graphic graphic = (Graphic)iter.next(); 849 850 // Do the following two in this order so the Graphic gets erased 851 this.removeGraphic(graphic); 852 853 graphicEvents.add(new DeleteGraphicEvent(graphic)); 854 } 855 856 if(graphicEvents.size() > 1) 857 this.addGraphicEvent(new CompositeGraphicEvent(graphicEvents)); 858 else if(graphicEvents.size() == 1) 859 this.addGraphicEvent((GraphicEvent)graphicEvents.elementAt(0)); 860 861 this.canvasPanel.getConveyFrame().updateButtons(); 862 } 863 editClear()864 public void editClear() { 865 if(!this.hasPen && !this.isIncoming()) 866 return; 867 868 Vector oldGraphics = this.graphics; 869 this.graphics = new Vector(); 870 871 Vector graphicEvents = new Vector(); 872 873 Iterator iter = oldGraphics.iterator(); 874 while(iter.hasNext()) { 875 Graphic graphic = (Graphic)iter.next(); 876 877 graphic.setState(Graphic.DORMANT); 878 879 graphicEvents.add(new DeleteGraphicEvent(graphic)); 880 } 881 882 if(graphicEvents.size() > 1) 883 this.addGraphicEvent(new CompositeGraphicEvent(graphicEvents)); 884 else if(graphicEvents.size() == 1) 885 this.addGraphicEvent((GraphicEvent)graphicEvents.elementAt(0)); 886 887 this.canvasPanel.getConveyFrame().updateButtons(); 888 889 super.repaint(); 890 } 891 handleConveyElement(Element conveyElement)892 public void handleConveyElement(Element conveyElement) { 893 this.setIncoming(true); 894 Iterator iter = conveyElement.getChildren().iterator(); 895 896 while(iter.hasNext()) { 897 Element element = (Element)iter.next(); 898 899 handleGraphicEventElement(element); 900 } 901 this.setIncoming(false); 902 903 this.canvasPanel.getConveyFrame().updateButtons(); 904 } 905 906 /** 907 * @todo Implement EllipseGraphicEvent and QuadGraphicEvent handling. They 908 * weren't implemented yet because we still cannot even modify them via 909 * vertex manipulation. This are no longer necessary because these events 910 * are implemented via fitToRect(). 911 */ handleGraphicEventElement(Element element)912 public void handleGraphicEventElement(Element element) { 913 String name = element.getName(); 914 915 if(name.equals("new")) { 916 Iterator childIter = element.getChildren().iterator(); 917 while(childIter.hasNext()) { 918 Element svgElement = (Element)childIter.next(); 919 Graphic graphic = this.createGraphicFromSVGElement(svgElement); 920 921 this.addGraphic(graphic); 922 graphic.setState(Graphic.DORMANT); 923 } 924 } else if(name.equals("name")) { 925 Graphic graphic = (Graphic)this.nameGraphicTable.get(element.getAttributeValue("old")); 926 if(graphic == null) 927 return; 928 graphic.setName(element.getAttributeValue("new")); 929 } else if(name.equals("composite")) { 930 Iterator iter = element.getChildren().iterator(); 931 while(iter.hasNext()) 932 this.handleGraphicEventElement((Element)iter.next()); 933 } else if(name.equals("group")) { 934 this.deselectAll(); 935 switch(Integer.parseInt(element.getAttributeValue("type"))) { 936 case GroupGraphicEvent.TYPE_GROUP: 937 Iterator iter = element.getChildren().iterator(); 938 while(iter.hasNext()) { 939 Element childElement = (Element)iter.next(); 940 Graphic g = (Graphic)this.nameGraphicTable.get(childElement.getAttributeValue("name")); 941 if(g == null) 942 return; 943 g.setState(Graphic.SELECTED); 944 } 945 this.editGroup(); 946 break; 947 case GroupGraphicEvent.TYPE_UNGROUP: 948 Graphic g = (Graphic)this.nameGraphicTable.get(element.getAttributeValue("name")); 949 if(g == null) 950 return; 951 g.setState(Graphic.SELECTED); 952 this.editUngroup(); 953 break; 954 } 955 } else { 956 Graphic g = (Graphic)this.nameGraphicTable.get(element.getAttributeValue("name")); 957 if(g == null) 958 return; 959 960 if(name.equals("shape")) { 961 ShapeGraphic graphic = (ShapeGraphic) g; 962 switch (Integer.parseInt(element.getAttributeValue("type"))) { 963 case ShapeGraphicEvent.TYPE_FILL: 964 graphic.setFillColor(ShapeGraphic.stringToColor(element.getAttributeValue("newColor"))); 965 break; 966 case ShapeGraphicEvent.TYPE_STROKE: 967 graphic.setStrokeColor(ShapeGraphic.stringToColor(element.getAttributeValue("newColor"))); 968 break; 969 } 970 } 971 else if(name.equals("delete")) 972 this.removeGraphic(g); 973 else if(name.equals("translate")) 974 g.translate(Integer.parseInt(element.getAttributeValue("x")), 975 Integer.parseInt(element.getAttributeValue("y"))); 976 else if(name.equals("fitToRect")) { 977 Element newRect = element.getChild("new"); 978 g.setOrig(); 979 g.fitToRect(new Rectangle(Integer.parseInt(newRect.getAttributeValue("x")), 980 Integer.parseInt(newRect.getAttributeValue("y")), 981 Integer.parseInt(newRect.getAttributeValue("w")), 982 Integer.parseInt(newRect.getAttributeValue("h")))); 983 } else if (name.equals("polyline")) { 984 PolylineGraphic graphic = (PolylineGraphic) g; 985 Vector points = graphic.getPoints(); 986 Point2D p = (Point2D) points.elementAt(Integer.parseInt(element.getAttributeValue("index"))); 987 Element pElement = element.getChild("new"); 988 p.setLocation(Double.parseDouble(pElement.getAttributeValue("x")), 989 Double.parseDouble(pElement.getAttributeValue("y"))); 990 graphic.setPoints(points); 991 } else if (name.equals("polygon")) { 992 PolygonGraphic graphic = (PolygonGraphic) g; 993 Vector points = graphic.getPoints(); 994 Point2D p = (Point2D) points.elementAt(Integer.parseInt(element.getAttributeValue("index"))); 995 Element pElement = element.getChild("new"); 996 p.setLocation(Double.parseDouble(pElement.getAttributeValue("x")), 997 Double.parseDouble(pElement.getAttributeValue("y"))); 998 graphic.setPoints(points); 999 } else if (name.equals("cubicCurve")) { 1000 CubicCurveGraphic graphic = (CubicCurveGraphic) g; 1001 Element pElement = element.getChild("new"); 1002 CubicCurve2D curve = new CubicCurve2D.Double(Double.parseDouble(pElement.getAttributeValue("x1")), 1003 Double.parseDouble(pElement.getAttributeValue("y1")), 1004 Double.parseDouble(pElement.getAttributeValue("ctrlx1")), 1005 Double.parseDouble(pElement.getAttributeValue("ctrly1")), 1006 Double.parseDouble(pElement.getAttributeValue("ctrlx2")), 1007 Double.parseDouble(pElement.getAttributeValue("ctrly2")), 1008 Double.parseDouble(pElement.getAttributeValue("x2")), 1009 Double.parseDouble(pElement.getAttributeValue("y2"))); 1010 graphic.setCurve(curve); 1011 } else if(name.equals("quadCurve")) { 1012 QuadCurveGraphic graphic = (QuadCurveGraphic) g; 1013 Element pElement = element.getChild("new"); 1014 QuadCurve2D curve = new QuadCurve2D.Double(Double.parseDouble(pElement.getAttributeValue("x1")), 1015 Double.parseDouble(pElement.getAttributeValue("y1")), 1016 Double.parseDouble(pElement.getAttributeValue("ctrlx")), 1017 Double.parseDouble(pElement.getAttributeValue("ctrly")), 1018 Double.parseDouble(pElement.getAttributeValue("x2")), 1019 Double.parseDouble(pElement.getAttributeValue("y2"))); 1020 graphic.setCurve(curve); 1021 } else if(name.equals("text")) { 1022 TextGraphic graphic = (TextGraphic)g; 1023 Element newChild = element.getChild("new"); 1024 graphic.setText(newChild.getText()); 1025 graphic.setTextColor(Graphic.stringToColor(newChild.getAttributeValue("color"))); 1026 } else if(name.equals("position")) { 1027 this.removeGraphic(g); 1028 this.insertGraphic(g, Integer.parseInt(element.getAttributeValue("newIndex"))); 1029 } 1030 } 1031 1032 super.repaint(); 1033 } 1034 createGraphicFromSVGElement(Element element)1035 public Graphic createGraphicFromSVGElement(Element element) { 1036 Graphic graphic = null; 1037 String name = element.getName(); 1038 if(name.equals("g")) 1039 graphic = new GroupGraphic(this); 1040 else if(name.equals("path")) { 1041 String d = element.getAttributeValue("d"); 1042 for(int i = 0; i < d.length(); i++) { 1043 if(d.charAt(i) == 'Q') 1044 graphic = new QuadCurveGraphic(this); 1045 else if(d.charAt(i) == 'C') { 1046 graphic = new CubicCurveGraphic(this); 1047 } else if (d.charAt(i) == 'M') { 1048 graphic = new FreehandGraphic(this); 1049 } 1050 } 1051 } else if(name.equals("rect")) 1052 graphic = new QuadGraphic(this); 1053 else if(name.equals("ellipse")) 1054 graphic = new EllipseGraphic(this); 1055 else if(name.equals("polyline")) 1056 graphic = new PolylineGraphic(this); 1057 else if(name.equals("polygon")) 1058 graphic = new PolygonGraphic(this); 1059 else if(name.equals("text")) 1060 graphic = new TextGraphic(this); 1061 1062 if(graphic != null) 1063 graphic.fromElement(element); 1064 1065 return graphic; 1066 } 1067 hitGraphic(Point p)1068 protected Graphic hitGraphic(Point p) { 1069 if(this.graphics.size() == 0) 1070 return null; 1071 1072 ListIterator iter = this.graphics.listIterator(this.graphics.size()); 1073 while(iter.hasPrevious()) { 1074 Graphic graphic = (Graphic)iter.previous(); 1075 if(graphic.hitPath(p) || graphic.hitVertex(p)) 1076 return graphic; 1077 } 1078 1079 return null; 1080 } 1081 graphicCount()1082 public int graphicCount() { 1083 return this.graphics.size(); 1084 } 1085 selectedGraphicCount()1086 public int selectedGraphicCount() { 1087 return this.selectedGraphics.size(); 1088 } 1089 selectedGraphic(int index)1090 public Graphic selectedGraphic(int index) { 1091 return (Graphic)this.selectedGraphics.elementAt(index); 1092 } 1093 selectAll()1094 public void selectAll() { 1095 Iterator iter = this.graphics.iterator(); 1096 while(iter.hasNext()) { 1097 Graphic graphic = (Graphic)iter.next(); 1098 graphic.setState(Graphic.SELECTED); 1099 } 1100 1101 this.canvasPanel.getConveyFrame().updateButtons(); 1102 } 1103 pushGraphicEvent(GraphicEvent event)1104 public void pushGraphicEvent(GraphicEvent event) { 1105 this.graphicEventStack.add(event); 1106 } 1107 popAllGraphicEvents()1108 public GraphicEvent popAllGraphicEvents() { 1109 if(this.graphicEventStack.size() == 0) 1110 return null; 1111 else if(this.graphicEventStack.size() == 1) { 1112 GraphicEvent event = (GraphicEvent)this.graphicEventStack.elementAt(0); 1113 this.graphicEventStack.clear(); 1114 return event; 1115 } 1116 1117 CompositeGraphicEvent event = new CompositeGraphicEvent(this.graphicEventStack); 1118 this.graphicEventStack = new Vector(); 1119 return event; 1120 } 1121 addGraphicEvent(GraphicEvent event)1122 public void addGraphicEvent(GraphicEvent event) { 1123 if(this.lastGraphicEventIndex < this.graphicEvents.size() - 1) { 1124 while(this.lastGraphicEventIndex < this.graphicEvents.size() - 1) 1125 this.graphicEvents.remove(this.graphicEvents.size() - 1); 1126 } 1127 this.graphicEvents.add(event); 1128 this.lastGraphicEventIndex++; 1129 1130 if(this.getCanvasPanel().getConveyFrame().isAutoSend()) { 1131 if(this.canvasPanel instanceof JabberCanvasPanel) { 1132 JabberCanvasPanel panel = (JabberCanvasPanel)this.canvasPanel; 1133 panel.sendGraphicEvent(event); 1134 } 1135 } else 1136 graphicEventQueue.add(event); 1137 } 1138 flushGraphicEventQueue()1139 public void flushGraphicEventQueue() { 1140 if(this.canvasPanel instanceof JabberCanvasPanel) { 1141 if(this.graphicEventQueue.size() == 0) 1142 return; 1143 else if(this.graphicEventQueue.size() == 1) { 1144 GraphicEvent event = (GraphicEvent)this.graphicEventQueue.elementAt(0); 1145 this.graphicEventQueue.clear(); 1146 JabberCanvasPanel panel = (JabberCanvasPanel)this.canvasPanel; 1147 panel.sendGraphicEvent(event); 1148 } 1149 1150 CompositeGraphicEvent event = new CompositeGraphicEvent(this.graphicEventQueue); 1151 this.graphicEventQueue = new Vector(); 1152 JabberCanvasPanel panel = (JabberCanvasPanel)this.canvasPanel; 1153 panel.sendGraphicEvent(event); 1154 } 1155 } 1156 undoGraphicEvent(GraphicEvent event)1157 protected void undoGraphicEvent(GraphicEvent event) { 1158 if(event instanceof CompositeGraphicEvent) { 1159 Iterator iter = ((CompositeGraphicEvent)event).getGraphicEvents().iterator(); 1160 while(iter.hasNext()) { 1161 event = (GraphicEvent)iter.next(); 1162 this.undoGraphicEvent(event); 1163 } 1164 } else { 1165 Graphic graphic = event.getGraphic(); 1166 graphic.undoGraphicEvent(event); 1167 } 1168 } 1169 editUndo()1170 public void editUndo() { 1171 if(!this.hasPen && !this.isIncoming()) 1172 return; 1173 1174 if(this.lastGraphicEventIndex > -1) { 1175 GraphicEvent event = (GraphicEvent)this.graphicEvents.elementAt(this.lastGraphicEventIndex); 1176 this.undoGraphicEvent(event); 1177 lastGraphicEventIndex--; 1178 } 1179 this.canvasPanel.getConveyFrame().updateButtons(); 1180 } 1181 redoGraphicEvent(GraphicEvent event)1182 protected void redoGraphicEvent(GraphicEvent event) { 1183 if(event instanceof CompositeGraphicEvent) { 1184 Iterator iter = ((CompositeGraphicEvent)event).getGraphicEvents().iterator(); 1185 while(iter.hasNext()) { 1186 event = (GraphicEvent)iter.next(); 1187 this.redoGraphicEvent(event); 1188 } 1189 } else { 1190 Graphic graphic = event.getGraphic(); 1191 graphic.redoGraphicEvent(event); 1192 } 1193 } 1194 editRedo()1195 public void editRedo() { 1196 if(!this.hasPen && !this.isIncoming()) 1197 return; 1198 1199 if(this.lastGraphicEventIndex < this.graphicEvents.size() - 1) { 1200 this.lastGraphicEventIndex++; 1201 GraphicEvent event = (GraphicEvent)this.graphicEvents.elementAt(this.lastGraphicEventIndex); 1202 this.redoGraphicEvent(event); 1203 } 1204 this.canvasPanel.getConveyFrame().updateButtons(); 1205 } 1206 getGraphicEvents()1207 public Vector getGraphicEvents() { 1208 return this.graphicEvents; 1209 } 1210 getLastGraphicEventIndex()1211 public int getLastGraphicEventIndex() { 1212 return this.lastGraphicEventIndex; 1213 } 1214 removeGraphic(Graphic graphic)1215 public void removeGraphic(Graphic graphic) { 1216 if(this.nameGraphicTable.containsKey(graphic.getName())) 1217 this.nameGraphicTable.remove(graphic.getName()); 1218 if(this.graphics.contains(graphic)) 1219 this.graphics.remove(graphic); 1220 1221 graphic.setState(Graphic.DORMANT); 1222 graphic.forceRepaint(); 1223 } 1224 addGraphic(Graphic graphic)1225 public void addGraphic(Graphic graphic) { 1226 this.insertGraphic(graphic, this.graphics.size()); 1227 } 1228 insertGraphic(Graphic graphic, int index)1229 public void insertGraphic(Graphic graphic, int index) { 1230 if(!this.nameGraphicTable.containsKey(graphic.getName())) 1231 this.nameGraphicTable.put(graphic.getName(), graphic); 1232 else { 1233 String origName = graphic.getName(); 1234 int i; 1235 for(i = origName.length() - 1; i >= 0; i--) { 1236 if(!Character.isDigit(origName.charAt(i))) { 1237 origName = origName.substring(0, i + 1); 1238 break; 1239 } 1240 } 1241 if(i == 0) 1242 origName = ""; 1243 for(i = 1; i < Integer.MAX_VALUE; i++) { 1244 String tryName = origName + String.valueOf(i); 1245 if(!this.nameGraphicTable.containsKey(tryName)) { 1246 1247 // This breaks OOP ideology. We are accessing a protected member 1248 // of another class in this package. We are doing this because we 1249 // do not want to send the Name change graphic event across the 1250 // network before we have sent the NewGraphicEvent. 1251 // 1252 // We need a more elegant solution. 1253 graphic.name = tryName; 1254 this.nameGraphicTable.put(tryName, graphic); 1255 break; 1256 } 1257 } 1258 } 1259 1260 if(!this.graphics.contains(graphic)) 1261 this.graphics.insertElementAt(graphic, index); 1262 1263 graphic.setState(Graphic.DORMANT); 1264 graphic.forceRepaint(); 1265 } 1266 addSelectedGraphic(Graphic graphic)1267 public void addSelectedGraphic(Graphic graphic) { 1268 // These must be done in this order to prevent infinite loop 1269 if(!this.selectedGraphics.contains(graphic)) 1270 this.selectedGraphics.add(graphic); 1271 graphic.setState(Graphic.SELECTED); 1272 } 1273 removeSelectedGraphic(Graphic graphic)1274 public void removeSelectedGraphic(Graphic graphic) { 1275 // These must be done in this order to prevent infinite loop 1276 if(this.selectedGraphics.contains(graphic)) 1277 this.selectedGraphics.remove(graphic); 1278 graphic.setState(Graphic.DORMANT); 1279 } 1280 getCanvasPanel()1281 public CanvasPanel getCanvasPanel() { 1282 return this.canvasPanel; 1283 } 1284 getSelectedGraphics()1285 public Vector getSelectedGraphics() { 1286 return this.selectedGraphics; 1287 } 1288 containsName(String name)1289 public boolean containsName(String name) { 1290 return this.nameGraphicTable.containsKey(name); 1291 } 1292 isFocusTraversible()1293 public boolean isFocusTraversible() { 1294 return true; 1295 } 1296 setSelectedFillColors(Color color)1297 public void setSelectedFillColors(Color color) { 1298 if(!this.hasPen && !this.isIncoming()) 1299 return; 1300 1301 Iterator iter = this.selectedGraphics.iterator(); 1302 while(iter.hasNext()) { 1303 Graphic graphic = (Graphic)iter.next(); 1304 if(graphic instanceof ShapeGraphic) 1305 ((ShapeGraphic)graphic).setFillColor(color); 1306 } 1307 } 1308 setSelectedStrokeColors(Color color)1309 public void setSelectedStrokeColors(Color color) { 1310 if(!this.hasPen && !this.isIncoming()) 1311 return; 1312 1313 Iterator iter = this.selectedGraphics.iterator(); 1314 while(iter.hasNext()) { 1315 Graphic graphic = (Graphic)iter.next(); 1316 if(graphic instanceof ShapeGraphic) 1317 ((ShapeGraphic)graphic).setStrokeColor(color); 1318 } 1319 } 1320 setSelectedTextColors(Color color)1321 public void setSelectedTextColors(Color color) { 1322 if(!this.hasPen && !this.isIncoming()) 1323 return; 1324 1325 Iterator iter = this.selectedGraphics.iterator(); 1326 while(iter.hasNext()) { 1327 Graphic graphic = (Graphic)iter.next(); 1328 if(graphic instanceof TextGraphic) 1329 ((TextGraphic)graphic).setTextColor(color); 1330 } 1331 } 1332 editSendToBack()1333 public void editSendToBack() { 1334 if(!this.hasPen && !this.isIncoming()) 1335 return; 1336 1337 Object[] graphics = this.graphics.toArray(); 1338 int index = 0; 1339 for(int i = 0; i < graphics.length; i++) { 1340 Graphic graphic = (Graphic)graphics[i]; 1341 if(graphic.getState() == Graphic.SELECTED) { 1342 this.pushGraphicEvent(new PositionChangeEvent(graphic, i, index)); 1343 this.removeGraphic(graphic); 1344 this.insertGraphic(graphic, index); 1345 graphic.setState(Graphic.SELECTED); 1346 index++; 1347 } 1348 } 1349 GraphicEvent event = this.popAllGraphicEvents(); 1350 if(event != null) 1351 this.addGraphicEvent(event); 1352 } 1353 editBringToFront()1354 public void editBringToFront() { 1355 if(!this.hasPen && !this.isIncoming()) 1356 return; 1357 1358 Object[] graphics = this.graphics.toArray(); 1359 int index = graphics.length - 1; 1360 for(int i = 0; i < graphics.length; i++) { 1361 Graphic graphic = (Graphic)graphics[i]; 1362 if(graphic.getState() == Graphic.SELECTED) { 1363 this.pushGraphicEvent(new PositionChangeEvent(graphic, i, index)); 1364 this.removeGraphic(graphic); 1365 this.addGraphic(graphic); 1366 graphic.setState(Graphic.SELECTED); 1367 index--; 1368 } 1369 } 1370 GraphicEvent event = this.popAllGraphicEvents(); 1371 if(event != null) 1372 this.addGraphicEvent(event); 1373 } 1374 editSendBackward()1375 public void editSendBackward() { 1376 if(!this.hasPen && !this.isIncoming()) 1377 return; 1378 1379 Object[] graphics = this.graphics.toArray(); 1380 1381 int lowestIndex; 1382 for(lowestIndex = 0; lowestIndex < graphics.length; lowestIndex++) { 1383 Graphic graphic = (Graphic)graphics[lowestIndex]; 1384 if(graphic.getState() != Graphic.SELECTED) 1385 break; 1386 } 1387 1388 int begin; 1389 for(begin = lowestIndex; begin < graphics.length; begin++) { 1390 Graphic graphic = (Graphic)graphics[begin]; 1391 if(graphic.getState() == Graphic.SELECTED) { 1392 int end; 1393 for(end = begin + 1; end < graphics.length; end++) { 1394 graphic = (Graphic)graphics[end]; 1395 if(graphic.getState() != Graphic.SELECTED) 1396 break; 1397 } 1398 1399 for(int k = begin; k < end; k++) { 1400 graphic = (Graphic)graphics[k]; 1401 this.pushGraphicEvent(new PositionChangeEvent(graphic, k, k - 1)); 1402 this.removeGraphic(graphic); 1403 this.insertGraphic(graphic, k - 1); 1404 graphic.setState(Graphic.SELECTED); 1405 } 1406 } 1407 } 1408 GraphicEvent event = this.popAllGraphicEvents(); 1409 if(event != null) 1410 this.addGraphicEvent(event); 1411 } 1412 editBringForward()1413 public void editBringForward() { 1414 if(!this.hasPen && !this.isIncoming()) 1415 return; 1416 1417 Object[] graphics = this.graphics.toArray(); 1418 1419 int highestIndex; 1420 for(highestIndex = graphics.length - 1; highestIndex >= 0 ; highestIndex--) { 1421 Graphic graphic = (Graphic)graphics[highestIndex]; 1422 if(graphic.getState() != Graphic.SELECTED) 1423 break; 1424 } 1425 1426 int begin; 1427 for(begin = highestIndex; begin >= 0; begin--) { 1428 Graphic graphic = (Graphic)graphics[begin]; 1429 if(graphic.getState() == Graphic.SELECTED) { 1430 int end; 1431 for(end = begin - 1; end >= 0; end--) { 1432 graphic = (Graphic)graphics[end]; 1433 if(graphic.getState() != Graphic.SELECTED) 1434 break; 1435 } 1436 1437 for(int k = begin; k > end; k--) { 1438 graphic = (Graphic)graphics[k]; 1439 this.pushGraphicEvent(new PositionChangeEvent(graphic, k, k + 1)); 1440 this.removeGraphic(graphic); 1441 this.insertGraphic(graphic, k + 1); 1442 graphic.setState(Graphic.SELECTED); 1443 } 1444 } 1445 } 1446 GraphicEvent event = this.popAllGraphicEvents(); 1447 if(event != null) 1448 this.addGraphicEvent(event); 1449 } 1450 1451 }