1 package jimm.datavision.gui; 2 import jimm.datavision.*; 3 import jimm.datavision.field.Field; 4 import jimm.datavision.layout.swing.AbstractSwingField; 5 import jimm.datavision.layout.swing.SwingTextField; 6 import jimm.util.I18N; 7 import java.awt.*; 8 import java.awt.event.*; 9 import java.awt.dnd.*; 10 import java.util.Observable ; 11 import java.util.Observer ; 12 import java.util.HashMap ; 13 import javax.swing.*; 14 import javax.swing.event.MouseInputListener ; 15 16 21 public class FieldWidget 22 implements MouseInputListener , DropTargetListener, ActionListener, 23 KeyListener, Observer 24 { 25 26 protected static final int GRAB_EDGE_WIDTH = 4; 27 28 protected static final int ACTION_INACTION = 0; 29 protected static final int ACTION_MOVE = 1; 30 protected static final int ACTION_STRETCH_LEFT = 2; 31 protected static final int ACTION_STRETCH_RIGHT = 3; 32 protected static final int ACTION_STRETCH_TOP = 4; 33 protected static final int ACTION_STRETCH_BOTTOM = 5; 34 protected static final int ACTION_POPPING_UP_MENU = 6; 35 36 37 protected static final int MIN_SIZE = 2; 38 39 protected static final Font POPUP_FONT = new Font("Serif", Font.PLAIN, 10); 40 41 protected static HashMap componentMap = new HashMap (); 42 43 protected AbstractSwingField swingField; 44 protected SectionWidget sectionWidget; 45 protected int action; 46 protected boolean actionStartedYet; 47 protected boolean selected; 48 protected boolean mouseChangedSelectedState; 49 protected PreMoveInfo preMoveInfo; 50 protected PreStretchInfo preStretchInfo; 51 protected JPopupMenu popup; 52 protected JMenu alignSubmenu; 53 protected JMenu sizeSubmenu; 54 protected JMenuItem nameItem; 55 protected JMenuItem showOrHide; 56 protected JMenuItem formatMenuItem; 57 protected JMenuItem aggregatesMenuItem; 58 59 64 static FieldWidget findFieldWidgetOwning(Object c) { 65 return (FieldWidget)componentMap.get(c); 66 } 67 68 74 public FieldWidget(SectionWidget sw, Field field) { 75 this(sw, new SwingTextField(field, field.designLabel())); 76 } 77 78 84 protected FieldWidget(SectionWidget sw, AbstractSwingField asf) { 85 sectionWidget = sw; 86 swingField = asf; 87 action = ACTION_INACTION; 88 89 jimm.datavision.field.Rectangle b = getField().getBounds(); 90 getComponent().setBounds((int)b.x, (int)b.y, (int)b.width, (int)b.height); 91 92 getComponent().setBorder(new FWBorder(this)); 93 getComponent().addMouseListener(this); 94 getComponent().addMouseMotionListener(this); 95 getComponent().addKeyListener(this); buildPopupMenu(); 97 98 new DropTarget(this.getComponent(), 100 DnDConstants.ACTION_COPY_OR_MOVE, this); 103 setVisibilityLook(); 105 106 getField().addObserver(this); 108 109 componentMap.put(getComponent(), this); 112 } 113 114 117 protected void buildPopupMenu() { 118 popup = new JPopupMenu(); 119 popup.setFont(POPUP_FONT); 120 121 nameItem = MenuUtils.addToMenu(this, popup, 122 "FieldWidget.popup_dummy_title", 123 POPUP_FONT); 124 nameItem.setText(getPopupNameText()); nameItem.setEnabled(false); 126 popup.addSeparator(); 127 128 addCustomPopupItems(); 129 130 showOrHide = 131 MenuUtils.addToMenu(this, popup, "FieldWidget.popup_hide", POPUP_FONT); 132 MenuUtils.addToMenu(this, popup, "FieldWidget.popup_delete", POPUP_FONT); 133 popup.addSeparator(); 134 formatMenuItem = 135 MenuUtils.addToMenu(this, popup, "FieldWidget.popup_format", 136 POPUP_FONT); 137 MenuUtils.addToMenu(this, popup, "FieldWidget.popup_border", POPUP_FONT); 138 MenuUtils.addToMenu(this, popup, "FieldWidget.popup_bounds", POPUP_FONT); 139 popup.addSeparator(); 140 aggregatesMenuItem = 141 MenuUtils.addToMenu(this, popup, "FieldWidget.popup_aggr", 142 POPUP_FONT); 143 popup.addSeparator(); 144 145 alignSubmenu = MenuUtils.buildAlignMenu(this, POPUP_FONT); 146 alignSubmenu.setFont(POPUP_FONT); 147 popup.add(alignSubmenu); 149 sizeSubmenu = MenuUtils.buildSizeMenu(this, POPUP_FONT); 150 sizeSubmenu.setFont(POPUP_FONT); 151 popup.add(sizeSubmenu); } 153 154 158 protected void addCustomPopupItems() {} 159 160 protected void finalize() throws Throwable { 161 getField().deleteObserver(this); 162 } 163 164 public void update(Observable obj, Object arg) { 165 swingField.format(); jimm.datavision.field.Rectangle b = getField().getBounds(); 167 JTextPane textPane = (JTextPane)getComponent(); 168 169 double width = b.width; 170 if (width < MIN_SIZE) width = MIN_SIZE; 171 double height = b.height; 172 if (height < MIN_SIZE) height = MIN_SIZE; 173 174 textPane.setBounds((int)b.x, (int)b.y, (int)width, (int)height); 175 textPane.setText(getField().designLabel()); 176 } 177 178 183 public boolean usesFormat() { 184 return true; 185 } 186 187 191 protected String getPopupNameText() { 192 return getField().designLabel(); 193 } 194 195 200 public SectionWidget getSectionWidget() { return sectionWidget; } 201 202 207 boolean isSelected() { return selected; } 208 209 215 public void align(int which, Field prototype) { 216 jimm.datavision.field.Rectangle b = getField().getBounds(); 217 jimm.datavision.field.Rectangle pb = prototype.getBounds(); 218 switch (which) { 219 case Designer.ALIGN_TOP: 220 b.setY(pb.y); 221 break; 222 case Designer.ALIGN_MIDDLE: 223 double middle = pb.y + pb.height / 2; 224 b.setY(middle - b.height / 2); 225 break; 226 case Designer.ALIGN_BOTTOM: 227 b.setY(pb.y + pb.height - b.height); 228 break; 229 case Designer.ALIGN_LEFT: 230 b.setX(pb.x); 231 break; 232 case Designer.ALIGN_CENTER: 233 double center = pb.x + pb.width / 2; 234 b.setX(center - b.width / 2); 235 break; 236 case Designer.ALIGN_RIGHT: 237 b.setX(pb.x + pb.width - b.width); 238 break; 239 case Designer.ALIGN_SNAP_TO_GRID: 240 sectionWidget.snapToGrid(b); 241 break; 242 } 243 } 244 245 251 public void size(int which, Field prototype) { 252 jimm.datavision.field.Rectangle b = getField().getBounds(); 253 jimm.datavision.field.Rectangle pb = prototype.getBounds(); 254 switch (which) { 255 case Designer.SIZE_SAME_WIDTH: 256 b.setWidth(pb.width); 257 break; 258 case Designer.SIZE_SAME_HEIGHT: 259 b.setHeight(pb.height); 260 break; 261 case Designer.SIZE_SAME_SIZE: 262 b.setWidth(pb.width); 263 b.setHeight(pb.height); 264 break; 265 } 266 } 267 268 276 void select(boolean deselectOthers) { 277 sectionWidget.select(this, !selected, deselectOthers); 278 } 279 280 286 void doSelect(boolean makeSelected) { 287 JTextPane textPane = (JTextPane)getComponent(); 290 textPane.setCaretPosition(0); 291 textPane.moveCaretPosition(0); 292 293 if (selected != makeSelected) { 294 selected = makeSelected; 295 textPane.repaint(); } 297 } 298 299 305 public void mouseClicked(MouseEvent e) { 306 if (sectionWidget.designer.isPlacingNewTextField()) 307 sectionWidget.createNewTextField(e); 308 else { 309 if (!mouseChangedSelectedState) { 310 select(!e.isShiftDown()); 311 } 312 } 313 } 314 315 321 public void mouseDragged(MouseEvent e) { 322 if (action == ACTION_INACTION || action == ACTION_POPPING_UP_MENU) 323 return; 324 325 if (!selected) { 326 select(!e.isShiftDown()); 327 mouseChangedSelectedState = true; 328 } 329 330 java.awt.Point screenMousePos = e.getPoint(); 332 java.awt.Point screenPos = getComponent().getLocationOnScreen(); 333 screenMousePos.translate(screenPos.x, screenPos.y); 334 335 if (!actionStartedYet) { 336 actionStartedYet = true; 337 switch (action) { 338 case ACTION_MOVE: 339 sectionWidget.pickUp(screenMousePos); 341 break; 342 case ACTION_STRETCH_LEFT: 343 case ACTION_STRETCH_RIGHT: 344 case ACTION_STRETCH_TOP: 345 case ACTION_STRETCH_BOTTOM: 346 sectionWidget.startStretching(screenMousePos); 348 break; 349 } 350 } 351 352 sectionWidget.dragSelectedWidgets(action, screenMousePos); 353 } 354 355 360 public void mouseEntered(MouseEvent e) { 361 if (selected && !sectionWidget.designer.isPlacingNewTextField()) 362 cursorForPosition(e); 363 } 364 365 370 public void mouseExited(MouseEvent e) { 371 if (selected && !sectionWidget.designer.isPlacingNewTextField()) 372 resetCursor(); 373 } 374 375 380 public void mouseMoved(MouseEvent e) { 381 if (selected && !sectionWidget.designer.isPlacingNewTextField()) 382 cursorForPosition(e); 383 } 384 385 391 public void mousePressed(MouseEvent e) { 392 mouseChangedSelectedState = false; 393 394 if (mousePressReleaseCommon(e)) 395 return; 396 397 cursorForPosition(e); 398 action = actionFromPosition(e); 399 400 actionStartedYet = false; } 402 403 409 public void mouseReleased(MouseEvent e) { 410 if (mousePressReleaseCommon(e)) 411 return; 412 413 switch (action) { 414 case ACTION_MOVE: 415 if (actionStartedYet) { 416 java.awt.Point screenMousePos = e.getPoint(); 419 java.awt.Point screenPos = getComponent().getLocationOnScreen(); 420 screenMousePos.translate(screenPos.x, screenPos.y); 421 422 sectionWidget.putDown(this, preMoveInfo.screenPos, screenMousePos); 425 } 426 break; 427 case ACTION_STRETCH_LEFT: 428 case ACTION_STRETCH_RIGHT: 429 case ACTION_STRETCH_TOP: 430 case ACTION_STRETCH_BOTTOM: 431 if (actionStartedYet) { 432 sectionWidget.stopStretching(this, preStretchInfo.origBounds); 434 } 435 break; 436 } 437 438 action = ACTION_INACTION; 439 } 440 441 450 protected boolean mousePressReleaseCommon(MouseEvent e) { 451 if (sectionWidget.designer.isPlacingNewTextField()) { 452 sectionWidget.createNewTextField(e); 453 return true; 454 } 455 456 if (e.isPopupTrigger()) { 457 showPopupMenu(e); 458 return true; 459 } 460 461 return false; 462 } 463 464 470 public PreMoveInfo getPreMoveInfo() { return preMoveInfo; } 471 472 476 public void pickUp(java.awt.Point mouseScreenPos) { 477 preMoveInfo = new PreMoveInfo(this, mouseScreenPos); 478 479 sectionWidget.removeField(this); 481 } 482 483 487 public void putDown(SectionWidget sw) { 488 jimm.datavision.field.Rectangle b = getField().getBounds(); 490 b.setBounds(b.x - SectionWidget.LHS_WIDTH, b.y - sw.getBounds().y, 491 b.width, b.height); 492 493 moveToSection(sw); 495 496 preMoveInfo = null; 497 } 498 499 502 void snapBack() { 503 getField().getBounds().setBounds(preMoveInfo.origBounds); 504 moveToSection(preMoveInfo.sectionWidget); 505 } 506 507 512 public void startStretching(java.awt.Point mouseScreenPos) { 513 preStretchInfo = new PreStretchInfo(this, mouseScreenPos); 514 } 515 516 519 public void stopStretching() { 520 preStretchInfo = null; 521 } 522 523 526 protected void showPopupMenu(MouseEvent e) { 527 showOrHide.setText(getField().isVisible() 528 ? I18N.get(I18N.MENU_FILE_PREFIX, 529 "FieldWidget.popup_hide") 530 : I18N.get(I18N.MENU_FILE_PREFIX, 531 "FieldWidget.popup_show")); 532 533 enableMenuItems(); 534 535 action = ACTION_POPPING_UP_MENU; 536 popup.show(e.getComponent(), e.getX(), e.getY()); 537 } 538 539 542 protected void enableMenuItems() { 543 boolean canFormat = usesFormat() 544 || sectionWidget.designer.someSelectedFieldUsesFormat(); 545 formatMenuItem.setEnabled(canFormat); 546 547 int numSelectedFields = sectionWidget.designer.countSelectedFields(); 548 if (numSelectedFields >= 2) { 549 for (int i = 0; i < alignSubmenu.getItemCount(); ++i) 551 alignSubmenu.getItem(i).setEnabled(true); 552 sizeSubmenu.setEnabled(true); 553 aggregatesMenuItem.setEnabled(false); 554 } 555 else { 556 for (int i = 0; i < alignSubmenu.getItemCount() - 1; ++i) 558 alignSubmenu.getItem(i).setEnabled(false); 559 sizeSubmenu.setEnabled(false); 560 561 aggregatesMenuItem.setEnabled(getField().canBeAggregated()); 563 } 564 } 565 566 570 protected int actionFromPosition(MouseEvent e) { 571 int ex = e.getX(); 572 int ey = e.getY(); 573 if (ex <= GRAB_EDGE_WIDTH) 574 return ACTION_STRETCH_LEFT; 575 else if (ex >= getField().getBounds().width - GRAB_EDGE_WIDTH) 576 return ACTION_STRETCH_RIGHT; 577 else if (ey <= GRAB_EDGE_WIDTH) 578 return ACTION_STRETCH_TOP; 579 else if (ey >= getField().getBounds().height - GRAB_EDGE_WIDTH) 580 return ACTION_STRETCH_BOTTOM; 581 else 582 return ACTION_MOVE; 583 } 584 585 591 protected void cursorForPosition(MouseEvent e) { 592 if (!selected) { 593 resetCursor(); 594 return; 595 } 596 597 switch (action == ACTION_INACTION ? actionFromPosition(e) : action) { 598 case ACTION_MOVE: 599 getComponent().setCursor(Cursor 600 .getPredefinedCursor(Cursor.MOVE_CURSOR)); 601 break; 602 case ACTION_STRETCH_LEFT: 603 getComponent().setCursor(Cursor 604 .getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); 605 break; 606 case ACTION_STRETCH_RIGHT: 607 getComponent().setCursor(Cursor 608 .getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); 609 break; 610 case ACTION_STRETCH_TOP: 611 getComponent().setCursor(Cursor 612 .getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); 613 break; 614 case ACTION_STRETCH_BOTTOM: 615 getComponent().setCursor(Cursor 616 .getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); 617 break; 618 } 619 } 620 621 624 protected void resetCursor() { 625 getComponent().setCursor(null); 626 } 627 628 636 void doDrag(int action, java.awt.Point mouseScreenPos) { 637 jimm.datavision.field.Rectangle b = getField().getBounds(); 638 639 if (action == ACTION_MOVE) { 640 int dx = mouseScreenPos.x - preMoveInfo.startMouseScreenPos.x; 641 int dy = mouseScreenPos.y - preMoveInfo.startMouseScreenPos.y; 642 b.setBounds(preMoveInfo.origBounds.x + dx + SectionWidget.LHS_WIDTH, 645 preMoveInfo.origBounds.y + dy 646 + sectionWidget.getBounds().y, 647 preMoveInfo.origBounds.width, 648 preMoveInfo.origBounds.height); 649 return; 650 } 651 652 int dx = mouseScreenPos.x - preStretchInfo.startMouseScreenPos.x; 653 int dy = mouseScreenPos.y - preStretchInfo.startMouseScreenPos.y; 654 java.awt.Rectangle newBounds; 655 656 switch (action) { 657 case ACTION_STRETCH_LEFT: 658 newBounds = 659 new java.awt.Rectangle ((int)preStretchInfo.origBounds.x + dx, 660 (int)preStretchInfo.origBounds.y, 661 (int)preStretchInfo.origBounds.width - dx, 662 (int)preStretchInfo.origBounds.height); 663 break; 664 case ACTION_STRETCH_RIGHT: 665 newBounds = 666 new java.awt.Rectangle ((int)preStretchInfo.origBounds.x, 667 (int)preStretchInfo.origBounds.y, 668 (int)preStretchInfo.origBounds.width + dx, 669 (int)preStretchInfo.origBounds.height); 670 break; 671 case ACTION_STRETCH_TOP: 672 newBounds = 673 new java.awt.Rectangle ((int)preStretchInfo.origBounds.x, 674 (int)preStretchInfo.origBounds.y + dy, 675 (int)preStretchInfo.origBounds.width, 676 (int)preStretchInfo.origBounds.height - dy); 677 break; 678 case ACTION_STRETCH_BOTTOM: 679 newBounds = 680 new java.awt.Rectangle ((int)preStretchInfo.origBounds.x, 681 (int)preStretchInfo.origBounds.y, 682 (int)preStretchInfo.origBounds.width, 683 (int)preStretchInfo.origBounds.height + dy); 684 break; 685 default: 686 return; 687 } 688 689 newBounds = newBounds.intersection(preStretchInfo.sectionBounds); 691 692 switch (action) { 694 case ACTION_STRETCH_LEFT: 695 if (newBounds.width < MIN_SIZE) { 696 dx = MIN_SIZE - newBounds.width; 697 newBounds.x -= dx; 698 newBounds.width = MIN_SIZE; 699 } 700 break; 701 case ACTION_STRETCH_RIGHT: 702 if (newBounds.width < MIN_SIZE) 703 newBounds.width = MIN_SIZE; 704 break; 705 case ACTION_STRETCH_TOP: 706 if (newBounds.height < MIN_SIZE) { 707 dy = MIN_SIZE - newBounds.height; 708 newBounds.y -= dy; 709 newBounds.height = MIN_SIZE; 710 } 711 break; 712 case ACTION_STRETCH_BOTTOM: 713 if (newBounds.height < MIN_SIZE) 714 newBounds.height = MIN_SIZE; 715 break; 716 default: 717 return; 718 } 719 720 b.setBounds(newBounds); 721 } 722 723 726 protected void delete() { 727 sectionWidget.designer.deleteSelectedFieldsAnd(this); 728 } 729 730 735 public void doDelete() { 736 getField().getSection().removeField(getField()); 737 getComponent().getParent().remove(getComponent()); 738 } 739 740 746 public void moveToSection(SectionWidget sw) { 747 749 Section currSection = getField().getSection(); 750 Section newSection = sw.section; 751 if (newSection != currSection) { 752 if (currSection != null) 753 currSection.removeField(getField()); 754 newSection.addField(getField()); 755 } 756 757 sw.addField(this); 761 762 getComponent().repaint(); 764 } 765 766 772 public void drop(DropTargetDropEvent e) { 773 ((DropTargetListener)getComponent().getParent()).drop(e); 774 } 775 776 public void dragEnter(DropTargetDragEvent e) { } 777 public void dragExit(DropTargetEvent e) { } 778 public void dragOver(DropTargetDragEvent e) { } 779 public void dropActionChanged(DropTargetDragEvent e) { } 780 781 785 public void actionPerformed(ActionEvent e) { 786 String command = e.getActionCommand(); 787 if (command == null) return; 788 789 Designer designer = sectionWidget.designer; 790 791 if ("hide".equals(command) || "show".equals(command)) 792 toggleVisibility(); 793 else if ("delete".equals(command)) 794 delete(); 795 796 else if ("align_top".equals(command)) 797 designer.align(Designer.ALIGN_TOP); 798 else if ("align_middle".equals(command)) 799 designer.align(Designer.ALIGN_MIDDLE); 800 else if ("align_bottom".equals(command)) 801 designer.align(Designer.ALIGN_BOTTOM); 802 else if ("align_left".equals(command)) 803 designer.align(Designer.ALIGN_LEFT); 804 else if ("align_center".equals(command)) 805 designer.align(Designer.ALIGN_CENTER); 806 else if ("align_right".equals(command)) 807 designer.align(Designer.ALIGN_RIGHT); 808 else if ("snap_to_grid".equals(command)) { 809 if (designer.countSelectedFields() > 0) 810 designer.align(Designer.ALIGN_SNAP_TO_GRID); 811 else 812 align(Designer.ALIGN_SNAP_TO_GRID, getField()); 813 } 814 815 else if ("size_width".equals(command)) 816 designer.size(Designer.SIZE_SAME_WIDTH); 817 else if ("size_height".equals(command)) 818 designer.size(Designer.SIZE_SAME_HEIGHT); 819 else if ("size_size".equals(command)) 820 designer.size(Designer.SIZE_SAME_SIZE); 821 822 else if ("format".equals(command)) 823 new FormatWin(designer, this.getField(), 0); 824 else if ("border".equals(command)) 825 new FormatWin(designer, this.getField(), 1); 826 else if ("bounds".equals(command)) 827 new BoundsWin(designer, this.getField()); 828 else if ("aggregates".equals(command)) 829 new AggregatesWin(designer, this); 830 } 831 832 public String toString() { 833 return getField().designLabel(); 834 } 835 836 839 void toggleVisibility() { 840 boolean newVisibility = !getField().isVisible(); 841 sectionWidget.setFieldVisibility(newVisibility, this); 842 } 843 844 848 public void doSetVisibility(boolean newVisibility) { 849 getField().setVisible(newVisibility); 850 setVisibilityLook(); 851 } 852 853 858 protected void setVisibilityLook() { 859 swingField.format(); 860 } 861 862 Color getColor() { return swingField.getColor(); } 863 864 public Field getField() { return swingField.getField(); } 865 866 public JComponent getComponent() { return swingField.getComponent(); } 867 868 881 882 public void keyPressed(KeyEvent ke) { return; } 883 public void keyTyped(KeyEvent ke) { return; } 884 public void keyReleased(KeyEvent ke) { 885 if (!sectionWidget.designer.ignoreKeys) { 886 int code = ke.getKeyCode(); 887 if (code == KeyEvent.VK_BACK_SPACE || code == KeyEvent.VK_DELETE) 888 sectionWidget.designer.deleteSelectedFields(); 889 } 890 } 891 892 } 893 | Popular Tags |