1 7 8 9 10 package javax.swing.plaf.basic; 11 12 13 14 import java.awt.*; 15 import java.awt.event.*; 16 import javax.swing.*; 17 import javax.swing.event.*; 18 import javax.swing.plaf.*; 19 import javax.swing.border.Border ; 20 import java.beans.*; 21 import sun.swing.DefaultLookup; 22 23 24 25 45 public class BasicSplitPaneDivider extends Container 46 implements PropertyChangeListener 47 { 48 52 protected static final int ONE_TOUCH_SIZE = 6; 53 protected static final int ONE_TOUCH_OFFSET = 2; 54 55 58 protected DragController dragger; 59 60 63 protected BasicSplitPaneUI splitPaneUI; 64 65 68 protected int dividerSize = 0; 70 73 protected Component hiddenDivider; 74 75 78 protected JSplitPane splitPane; 79 80 86 protected MouseHandler mouseHandler; 87 88 91 protected int orientation; 92 93 96 protected JButton leftButton; 97 98 101 protected JButton rightButton; 102 103 104 private Border border; 105 106 109 private boolean mouseOver; 110 111 private int oneTouchSize; 112 private int oneTouchOffset; 113 114 117 private boolean centerOneTouchButtons; 118 119 120 124 public BasicSplitPaneDivider(BasicSplitPaneUI ui) { 125 oneTouchSize = DefaultLookup.getInt(ui.getSplitPane(), ui, 126 "SplitPane.oneTouchButtonSize", ONE_TOUCH_SIZE); 127 oneTouchOffset = DefaultLookup.getInt(ui.getSplitPane(), ui, 128 "SplitPane.oneTouchButtonOffset", ONE_TOUCH_OFFSET); 129 centerOneTouchButtons = DefaultLookup.getBoolean(ui.getSplitPane(), 130 ui, "SplitPane.centerOneTouchButtons", true); 131 setLayout(new DividerLayout()); 132 setBasicSplitPaneUI(ui); 133 orientation = splitPane.getOrientation(); 134 setCursor((orientation == JSplitPane.HORIZONTAL_SPLIT) ? 135 Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR) : 136 Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); 137 setBackground(UIManager.getColor("SplitPane.background")); 138 } 139 140 private void revalidate() { 141 invalidate(); 142 if (splitPane != null) { 143 splitPane.revalidate(); 144 } 145 } 146 147 150 public void setBasicSplitPaneUI(BasicSplitPaneUI newUI) { 151 if (splitPane != null) { 152 splitPane.removePropertyChangeListener(this); 153 if (mouseHandler != null) { 154 splitPane.removeMouseListener(mouseHandler); 155 splitPane.removeMouseMotionListener(mouseHandler); 156 removeMouseListener(mouseHandler); 157 removeMouseMotionListener(mouseHandler); 158 mouseHandler = null; 159 } 160 } 161 splitPaneUI = newUI; 162 if (newUI != null) { 163 splitPane = newUI.getSplitPane(); 164 if (splitPane != null) { 165 if (mouseHandler == null) mouseHandler = new MouseHandler(); 166 splitPane.addMouseListener(mouseHandler); 167 splitPane.addMouseMotionListener(mouseHandler); 168 addMouseListener(mouseHandler); 169 addMouseMotionListener(mouseHandler); 170 splitPane.addPropertyChangeListener(this); 171 if (splitPane.isOneTouchExpandable()) { 172 oneTouchExpandableChanged(); 173 } 174 } 175 } 176 else { 177 splitPane = null; 178 } 179 } 180 181 182 186 public BasicSplitPaneUI getBasicSplitPaneUI() { 187 return splitPaneUI; 188 } 189 190 191 196 public void setDividerSize(int newSize) { 197 dividerSize = newSize; 198 } 199 200 201 205 public int getDividerSize() { 206 return dividerSize; 207 } 208 209 210 214 public void setBorder(Border border) { 215 Border oldBorder = this.border; 216 217 this.border = border; 218 } 219 220 228 public Border getBorder() { 229 return border; 230 } 231 232 239 public Insets getInsets() { 240 Border border = getBorder(); 241 242 if (border != null) { 243 return border.getBorderInsets(this); 244 } 245 return super.getInsets(); 246 } 247 248 254 protected void setMouseOver(boolean mouseOver) { 255 this.mouseOver = mouseOver; 256 } 257 258 263 public boolean isMouseOver() { 264 return mouseOver; 265 } 266 267 270 public Dimension getPreferredSize() { 271 if (orientation == JSplitPane.HORIZONTAL_SPLIT) { 276 return new Dimension(getDividerSize(), 1); 277 } 278 return new Dimension(1, getDividerSize()); 279 } 280 281 284 public Dimension getMinimumSize() { 285 return getPreferredSize(); 286 } 287 288 289 293 public void propertyChange(PropertyChangeEvent e) { 294 if (e.getSource() == splitPane) { 295 if (e.getPropertyName() == JSplitPane.ORIENTATION_PROPERTY) { 296 orientation = splitPane.getOrientation(); 297 setCursor((orientation == JSplitPane.HORIZONTAL_SPLIT) ? 298 Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR) : 299 Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); 300 revalidate(); 301 } 302 else if (e.getPropertyName() == JSplitPane. 303 ONE_TOUCH_EXPANDABLE_PROPERTY) { 304 oneTouchExpandableChanged(); 305 } 306 } 307 } 308 309 310 313 public void paint(Graphics g) { 314 super.paint(g); 315 316 Border border = getBorder(); 318 319 if (border != null) { 320 Dimension size = getSize(); 321 322 border.paintBorder(this, g, 0, 0, size.width, size.height); 323 } 324 } 325 326 327 333 protected void oneTouchExpandableChanged() { 334 if (!DefaultLookup.getBoolean(splitPane, splitPaneUI, 335 "SplitPane.supportsOneTouchButtons", true)) { 336 return; 338 } 339 if (splitPane.isOneTouchExpandable() && 340 leftButton == null && 341 rightButton == null) { 342 344 leftButton = createLeftOneTouchButton(); 345 if (leftButton != null) 346 leftButton.addActionListener(new OneTouchActionHandler(true)); 347 348 349 351 rightButton = createRightOneTouchButton(); 352 if (rightButton != null) 353 rightButton.addActionListener(new OneTouchActionHandler 354 (false)); 355 356 if (leftButton != null && rightButton != null) { 357 add(leftButton); 358 add(rightButton); 359 } 360 } 361 revalidate(); 362 } 363 364 365 369 protected JButton createLeftOneTouchButton() { 370 JButton b = new JButton() { 371 public void setBorder(Border b) { 372 } 373 public void paint(Graphics g) { 374 if (splitPane != null) { 375 int[] xs = new int[3]; 376 int[] ys = new int[3]; 377 int blockSize; 378 379 g.setColor(this.getBackground()); 381 g.fillRect(0, 0, this.getWidth(), 382 this.getHeight()); 383 384 g.setColor(Color.black); 386 if (orientation == JSplitPane.VERTICAL_SPLIT) { 387 blockSize = Math.min(getHeight(), oneTouchSize); 388 xs[0] = blockSize; 389 xs[1] = 0; 390 xs[2] = blockSize << 1; 391 ys[0] = 0; 392 ys[1] = ys[2] = blockSize; 393 g.drawPolygon(xs, ys, 3); } 396 else { 397 blockSize = Math.min(getWidth(), oneTouchSize); 398 xs[0] = xs[2] = blockSize; 399 xs[1] = 0; 400 ys[0] = 0; 401 ys[1] = blockSize; 402 ys[2] = blockSize << 1; 403 } 404 g.fillPolygon(xs, ys, 3); 405 } 406 } 407 public boolean isFocusTraversable() { 409 return false; 410 } 411 }; 412 b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize)); 413 b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 414 b.setFocusPainted(false); 415 b.setBorderPainted(false); 416 b.setRequestFocusEnabled(false); 417 return b; 418 } 419 420 421 425 protected JButton createRightOneTouchButton() { 426 JButton b = new JButton() { 427 public void setBorder(Border border) { 428 } 429 public void paint(Graphics g) { 430 if (splitPane != null) { 431 int[] xs = new int[3]; 432 int[] ys = new int[3]; 433 int blockSize; 434 435 g.setColor(this.getBackground()); 437 g.fillRect(0, 0, this.getWidth(), 438 this.getHeight()); 439 440 if (orientation == JSplitPane.VERTICAL_SPLIT) { 442 blockSize = Math.min(getHeight(), oneTouchSize); 443 xs[0] = blockSize; 444 xs[1] = blockSize << 1; 445 xs[2] = 0; 446 ys[0] = blockSize; 447 ys[1] = ys[2] = 0; 448 } 449 else { 450 blockSize = Math.min(getWidth(), oneTouchSize); 451 xs[0] = xs[2] = 0; 452 xs[1] = blockSize; 453 ys[0] = 0; 454 ys[1] = blockSize; 455 ys[2] = blockSize << 1; 456 } 457 g.setColor(Color.black); 458 g.fillPolygon(xs, ys, 3); 459 } 460 } 461 public boolean isFocusTraversable() { 463 return false; 464 } 465 }; 466 b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize)); 467 b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 468 b.setFocusPainted(false); 469 b.setBorderPainted(false); 470 b.setRequestFocusEnabled(false); 471 return b; 472 } 473 474 475 479 protected void prepareForDragging() { 480 splitPaneUI.startDragging(); 481 } 482 483 484 488 protected void dragDividerTo(int location) { 489 splitPaneUI.dragDividerTo(location); 490 } 491 492 493 497 protected void finishDraggingTo(int location) { 498 splitPaneUI.finishDraggingTo(location); 499 } 500 501 502 508 protected class MouseHandler extends MouseAdapter 509 implements MouseMotionListener 510 { 511 515 public void mousePressed(MouseEvent e) { 516 if ((e.getSource() == BasicSplitPaneDivider.this || 517 e.getSource() == splitPane) && 518 dragger == null &&splitPane.isEnabled()) { 519 Component newHiddenDivider = splitPaneUI. 520 getNonContinuousLayoutDivider(); 521 522 if (hiddenDivider != newHiddenDivider) { 523 if (hiddenDivider != null) { 524 hiddenDivider.removeMouseListener(this); 525 hiddenDivider.removeMouseMotionListener(this); 526 } 527 hiddenDivider = newHiddenDivider; 528 if (hiddenDivider != null) { 529 hiddenDivider.addMouseMotionListener(this); 530 hiddenDivider.addMouseListener(this); 531 } 532 } 533 if (splitPane.getLeftComponent() != null && 534 splitPane.getRightComponent() != null) { 535 if (orientation == JSplitPane.HORIZONTAL_SPLIT) { 536 dragger = new DragController(e); 537 } 538 else { 539 dragger = new VerticalDragController(e); 540 } 541 if (!dragger.isValid()) { 542 dragger = null; 543 } 544 else { 545 prepareForDragging(); 546 dragger.continueDrag(e); 547 } 548 } 549 e.consume(); 550 } 551 } 552 553 554 557 public void mouseReleased(MouseEvent e) { 558 if (dragger != null) { 559 if (e.getSource() == splitPane) { 560 dragger.completeDrag(e.getX(), e.getY()); 561 } 562 else if (e.getSource() == BasicSplitPaneDivider.this) { 563 Point ourLoc = getLocation(); 564 565 dragger.completeDrag(e.getX() + ourLoc.x, 566 e.getY() + ourLoc.y); 567 } 568 else if (e.getSource() == hiddenDivider) { 569 Point hDividerLoc = hiddenDivider.getLocation(); 570 int ourX = e.getX() + hDividerLoc.x; 571 int ourY = e.getY() + hDividerLoc.y; 572 573 dragger.completeDrag(ourX, ourY); 574 } 575 dragger = null; 576 e.consume(); 577 } 578 } 579 580 581 585 588 public void mouseDragged(MouseEvent e) { 589 if (dragger != null) { 590 if (e.getSource() == splitPane) { 591 dragger.continueDrag(e.getX(), e.getY()); 592 } 593 else if (e.getSource() == BasicSplitPaneDivider.this) { 594 Point ourLoc = getLocation(); 595 596 dragger.continueDrag(e.getX() + ourLoc.x, 597 e.getY() + ourLoc.y); 598 } 599 else if (e.getSource() == hiddenDivider) { 600 Point hDividerLoc = hiddenDivider.getLocation(); 601 int ourX = e.getX() + hDividerLoc.x; 602 int ourY = e.getY() + hDividerLoc.y; 603 604 dragger.continueDrag(ourX, ourY); 605 } 606 e.consume(); 607 } 608 } 609 610 611 614 public void mouseMoved(MouseEvent e) { 615 } 616 617 623 public void mouseEntered(MouseEvent e) { 624 if (e.getSource() == BasicSplitPaneDivider.this) { 625 setMouseOver(true); 626 } 627 } 628 629 635 public void mouseExited(MouseEvent e) { 636 if (e.getSource() == BasicSplitPaneDivider.this) { 637 setMouseOver(false); 638 } 639 } 640 } 641 642 643 660 protected class DragController 661 { 662 665 int initialX; 666 667 670 int maxX, minX; 671 672 675 int offset; 676 677 678 protected DragController(MouseEvent e) { 679 JSplitPane splitPane = splitPaneUI.getSplitPane(); 680 Component leftC = splitPane.getLeftComponent(); 681 Component rightC = splitPane.getRightComponent(); 682 683 initialX = getLocation().x; 684 if (e.getSource() == BasicSplitPaneDivider.this) { 685 offset = e.getX(); 686 } 687 else { offset = e.getX() - initialX; 689 } 690 if (leftC == null || rightC == null || offset < -1 || 691 offset >= getSize().width) { 692 maxX = -1; 694 } 695 else { 696 Insets insets = splitPane.getInsets(); 697 698 if (leftC.isVisible()) { 699 minX = leftC.getMinimumSize().width; 700 if (insets != null) { 701 minX += insets.left; 702 } 703 } 704 else { 705 minX = 0; 706 } 707 if (rightC.isVisible()) { 708 int right = (insets != null) ? insets.right : 0; 709 maxX = Math.max(0, splitPane.getSize().width - 710 (getSize().width + right) - 711 rightC.getMinimumSize().width); 712 } 713 else { 714 int right = (insets != null) ? insets.right : 0; 715 maxX = Math.max(0, splitPane.getSize().width - 716 (getSize().width + right)); 717 } 718 if (maxX < minX) minX = maxX = 0; 719 } 720 } 721 722 723 726 protected boolean isValid() { 727 return (maxX > 0); 728 } 729 730 731 735 protected int positionForMouseEvent(MouseEvent e) { 736 int newX = (e.getSource() == BasicSplitPaneDivider.this) ? 737 (e.getX() + getLocation().x) : e.getX(); 738 739 newX = Math.min(maxX, Math.max(minX, newX - offset)); 740 return newX; 741 } 742 743 744 748 protected int getNeededLocation(int x, int y) { 749 int newX; 750 751 newX = Math.min(maxX, Math.max(minX, x - offset)); 752 return newX; 753 } 754 755 756 protected void continueDrag(int newX, int newY) { 757 dragDividerTo(getNeededLocation(newX, newY)); 758 } 759 760 761 765 protected void continueDrag(MouseEvent e) { 766 dragDividerTo(positionForMouseEvent(e)); 767 } 768 769 770 protected void completeDrag(int x, int y) { 771 finishDraggingTo(getNeededLocation(x, y)); 772 } 773 774 775 779 protected void completeDrag(MouseEvent e) { 780 finishDraggingTo(positionForMouseEvent(e)); 781 } 782 } 784 785 793 protected class VerticalDragController extends DragController 794 { 795 796 protected VerticalDragController(MouseEvent e) { 797 super(e); 798 JSplitPane splitPane = splitPaneUI.getSplitPane(); 799 Component leftC = splitPane.getLeftComponent(); 800 Component rightC = splitPane.getRightComponent(); 801 802 initialX = getLocation().y; 803 if (e.getSource() == BasicSplitPaneDivider.this) { 804 offset = e.getY(); 805 } 806 else { 807 offset = e.getY() - initialX; 808 } 809 if (leftC == null || rightC == null || offset < -1 || 810 offset > getSize().height) { 811 maxX = -1; 813 } 814 else { 815 Insets insets = splitPane.getInsets(); 816 817 if (leftC.isVisible()) { 818 minX = leftC.getMinimumSize().height; 819 if (insets != null) { 820 minX += insets.top; 821 } 822 } 823 else { 824 minX = 0; 825 } 826 if (rightC.isVisible()) { 827 int bottom = (insets != null) ? insets.bottom : 0; 828 829 maxX = Math.max(0, splitPane.getSize().height - 830 (getSize().height + bottom) - 831 rightC.getMinimumSize().height); 832 } 833 else { 834 int bottom = (insets != null) ? insets.bottom : 0; 835 836 maxX = Math.max(0, splitPane.getSize().height - 837 (getSize().height + bottom)); 838 } 839 if (maxX < minX) minX = maxX = 0; 840 } 841 } 842 843 844 848 protected int getNeededLocation(int x, int y) { 849 int newY; 850 851 newY = Math.min(maxX, Math.max(minX, y - offset)); 852 return newY; 853 } 854 855 856 860 protected int positionForMouseEvent(MouseEvent e) { 861 int newY = (e.getSource() == BasicSplitPaneDivider.this) ? 862 (e.getY() + getLocation().y) : e.getY(); 863 864 865 newY = Math.min(maxX, Math.max(minX, newY - offset)); 866 return newY; 867 } 868 } 870 871 877 protected class DividerLayout implements LayoutManager 878 { 879 public void layoutContainer(Container c) { 880 if (leftButton != null && rightButton != null && 881 c == BasicSplitPaneDivider.this) { 882 if (splitPane.isOneTouchExpandable()) { 883 Insets insets = getInsets(); 884 885 if (orientation == JSplitPane.VERTICAL_SPLIT) { 886 int extraX = (insets != null) ? insets.left : 0; 887 int blockSize = getHeight(); 888 889 if (insets != null) { 890 blockSize -= (insets.top + insets.bottom); 891 blockSize = Math.max(blockSize, 0); 892 } 893 blockSize = Math.min(blockSize, oneTouchSize); 894 895 int y = (c.getSize().height - blockSize) / 2; 896 897 if (!centerOneTouchButtons) { 898 y = (insets != null) ? insets.top : 0; 899 extraX = 0; 900 } 901 leftButton.setBounds(extraX + oneTouchOffset, y, 902 blockSize * 2, blockSize); 903 rightButton.setBounds(extraX + oneTouchOffset + 904 oneTouchSize * 2, y, 905 blockSize * 2, blockSize); 906 } 907 else { 908 int extraY = (insets != null) ? insets.top : 0; 909 int blockSize = getWidth(); 910 911 if (insets != null) { 912 blockSize -= (insets.left + insets.right); 913 blockSize = Math.max(blockSize, 0); 914 } 915 blockSize = Math.min(blockSize, oneTouchSize); 916 917 int x = (c.getSize().width - blockSize) / 2; 918 919 if (!centerOneTouchButtons) { 920 x = (insets != null) ? insets.left : 0; 921 extraY = 0; 922 } 923 924 leftButton.setBounds(x, extraY + oneTouchOffset, 925 blockSize, blockSize * 2); 926 rightButton.setBounds(x, extraY + oneTouchOffset + 927 oneTouchSize * 2, blockSize, 928 blockSize * 2); 929 } 930 } 931 else { 932 leftButton.setBounds(-5, -5, 1, 1); 933 rightButton.setBounds(-5, -5, 1, 1); 934 } 935 } 936 } 937 938 939 public Dimension minimumLayoutSize(Container c) { 940 if (c != BasicSplitPaneDivider.this || splitPane == null) { 944 return new Dimension(0,0); 945 } 946 Dimension buttonMinSize = null; 947 948 if (splitPane.isOneTouchExpandable() && leftButton != null) { 949 buttonMinSize = leftButton.getMinimumSize(); 950 } 951 952 Insets insets = getInsets(); 953 int width = getDividerSize(); 954 int height = width; 955 956 if (orientation == JSplitPane.VERTICAL_SPLIT) { 957 if (buttonMinSize != null) { 958 int size = buttonMinSize.height; 959 if (insets != null) { 960 size += insets.top + insets.bottom; 961 } 962 height = Math.max(height, size); 963 } 964 width = 1; 965 } 966 else { 967 if (buttonMinSize != null) { 968 int size = buttonMinSize.width; 969 if (insets != null) { 970 size += insets.left + insets.right; 971 } 972 width = Math.max(width, size); 973 } 974 height = 1; 975 } 976 return new Dimension(width, height); 977 } 978 979 980 public Dimension preferredLayoutSize(Container c) { 981 return minimumLayoutSize(c); 982 } 983 984 985 public void removeLayoutComponent(Component c) {} 986 987 public void addLayoutComponent(String string, Component c) {} 988 } 990 991 994 private class OneTouchActionHandler implements ActionListener { 995 998 private boolean toMinimum; 999 1000 OneTouchActionHandler(boolean toMinimum) { 1001 this.toMinimum = toMinimum; 1002 } 1003 1004 public void actionPerformed(ActionEvent e) { 1005 Insets insets = splitPane.getInsets(); 1006 int lastLoc = splitPane.getLastDividerLocation(); 1007 int currentLoc = splitPaneUI.getDividerLocation(splitPane); 1008 int newLoc; 1009 1010 if (toMinimum) { 1013 if (orientation == JSplitPane.VERTICAL_SPLIT) { 1014 if (currentLoc >= (splitPane.getHeight() - 1015 insets.bottom - getHeight())) { 1016 int maxLoc = splitPane.getMaximumDividerLocation(); 1017 newLoc = Math.min(lastLoc, maxLoc); 1018 splitPaneUI.setKeepHidden(false); 1019 } 1020 else { 1021 newLoc = insets.top; 1022 splitPaneUI.setKeepHidden(true); 1023 } 1024 } 1025 else { 1026 if (currentLoc >= (splitPane.getWidth() - 1027 insets.right - getWidth())) { 1028 int maxLoc = splitPane.getMaximumDividerLocation(); 1029 newLoc = Math.min(lastLoc, maxLoc); 1030 splitPaneUI.setKeepHidden(false); 1031 } 1032 else { 1033 newLoc = insets.left; 1034 splitPaneUI.setKeepHidden(true); 1035 } 1036 } 1037 } 1038 else { 1039 if (orientation == JSplitPane.VERTICAL_SPLIT) { 1040 if (currentLoc == insets.top) { 1041 int maxLoc = splitPane.getMaximumDividerLocation(); 1042 newLoc = Math.min(lastLoc, maxLoc); 1043 splitPaneUI.setKeepHidden(false); 1044 } 1045 else { 1046 newLoc = splitPane.getHeight() - getHeight() - 1047 insets.top; 1048 splitPaneUI.setKeepHidden(true); 1049 } 1050 } 1051 else { 1052 if (currentLoc == insets.left) { 1053 int maxLoc = splitPane.getMaximumDividerLocation(); 1054 newLoc = Math.min(lastLoc, maxLoc); 1055 splitPaneUI.setKeepHidden(false); 1056 } 1057 else { 1058 newLoc = splitPane.getWidth() - getWidth() - 1059 insets.left; 1060 splitPaneUI.setKeepHidden(true); 1061 } 1062 } 1063 } 1064 if (currentLoc != newLoc) { 1065 splitPane.setDividerLocation(newLoc); 1066 splitPane.setLastDividerLocation(currentLoc); 1069 } 1070 } 1071 } } 1073 | Popular Tags |