1 7 8 package javax.swing.plaf.metal; 9 10 import java.awt.event.*; 11 import java.beans.PropertyChangeEvent ; 12 import java.beans.PropertyChangeListener ; 13 import javax.swing.*; 14 import javax.swing.border.*; 15 import javax.swing.event.*; 16 import javax.swing.plaf.*; 17 import javax.swing.plaf.basic.*; 18 import java.awt.*; 19 import java.io.*; 20 import java.security.*; 21 22 49 public class MetalRootPaneUI extends BasicRootPaneUI 50 { 51 54 private static final String [] borderKeys = new String [] { 55 null, "RootPane.frameBorder", "RootPane.plainDialogBorder", 56 "RootPane.informationDialogBorder", 57 "RootPane.errorDialogBorder", "RootPane.colorChooserDialogBorder", 58 "RootPane.fileChooserDialogBorder", "RootPane.questionDialogBorder", 59 "RootPane.warningDialogBorder" 60 }; 61 64 private static final int CORNER_DRAG_WIDTH = 16; 65 66 69 private static final int BORDER_DRAG_THICKNESS = 5; 70 71 74 private Window window; 75 76 80 private JComponent titlePane; 81 82 86 private MouseInputListener mouseInputListener; 87 88 92 private LayoutManager layoutManager; 93 94 98 private LayoutManager savedOldLayout; 99 100 103 private JRootPane root; 104 105 109 private Cursor lastCursor = 110 Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); 111 112 118 public static ComponentUI createUI(JComponent c) { 119 return new MetalRootPaneUI (); 120 } 121 122 136 public void installUI(JComponent c) { 137 super.installUI(c); 138 root = (JRootPane)c; 139 int style = root.getWindowDecorationStyle(); 140 if (style != JRootPane.NONE) { 141 installClientDecorations(root); 142 } 143 } 144 145 146 157 public void uninstallUI(JComponent c) { 158 super.uninstallUI(c); 159 uninstallClientDecorations(root); 160 161 layoutManager = null; 162 mouseInputListener = null; 163 root = null; 164 } 165 166 170 void installBorder(JRootPane root) { 171 int style = root.getWindowDecorationStyle(); 172 173 if (style == JRootPane.NONE) { 174 LookAndFeel.uninstallBorder(root); 175 } 176 else { 177 LookAndFeel.installBorder(root, borderKeys[style]); 178 } 179 } 180 181 184 private void uninstallBorder(JRootPane root) { 185 LookAndFeel.uninstallBorder(root); 186 } 187 188 198 private void installWindowListeners(JRootPane root, Component parent) { 199 if (parent instanceof Window) { 200 window = (Window)parent; 201 } 202 else { 203 window = SwingUtilities.getWindowAncestor(parent); 204 } 205 if (window != null) { 206 if (mouseInputListener == null) { 207 mouseInputListener = createWindowMouseInputListener(root); 208 } 209 window.addMouseListener(mouseInputListener); 210 window.addMouseMotionListener(mouseInputListener); 211 } 212 } 213 214 218 private void uninstallWindowListeners(JRootPane root) { 219 if (window != null) { 220 window.removeMouseListener(mouseInputListener); 221 window.removeMouseMotionListener(mouseInputListener); 222 } 223 } 224 225 229 private void installLayout(JRootPane root) { 230 if (layoutManager == null) { 231 layoutManager = createLayoutManager(); 232 } 233 savedOldLayout = root.getLayout(); 234 root.setLayout(layoutManager); 235 } 236 237 240 private void uninstallLayout(JRootPane root) { 241 if (savedOldLayout != null) { 242 root.setLayout(savedOldLayout); 243 savedOldLayout = null; 244 } 245 } 246 247 252 private void installClientDecorations(JRootPane root) { 253 installBorder(root); 254 255 JComponent titlePane = createTitlePane(root); 256 257 setTitlePane(root, titlePane); 258 installWindowListeners(root, root.getParent()); 259 installLayout(root); 260 if (window != null) { 261 root.revalidate(); 262 root.repaint(); 263 } 264 } 265 266 273 private void uninstallClientDecorations(JRootPane root) { 274 uninstallBorder(root); 275 uninstallWindowListeners(root); 276 setTitlePane(root, null); 277 uninstallLayout(root); 278 int style = root.getWindowDecorationStyle(); 284 if (style == JRootPane.NONE) { 285 root.repaint(); 286 root.revalidate(); 287 } 288 if (window != null) { 290 window.setCursor(Cursor.getPredefinedCursor 291 (Cursor.DEFAULT_CURSOR)); 292 } 293 window = null; 294 } 295 296 300 private JComponent createTitlePane(JRootPane root) { 301 return new MetalTitlePane (root, this); 302 } 303 304 308 private MouseInputListener createWindowMouseInputListener(JRootPane root) { 309 return new MouseInputHandler(); 310 } 311 312 316 private LayoutManager createLayoutManager() { 317 return new MetalRootLayout(); 318 } 319 320 329 private void setTitlePane(JRootPane root, JComponent titlePane) { 330 JLayeredPane layeredPane = root.getLayeredPane(); 331 JComponent oldTitlePane = getTitlePane(); 332 333 if (oldTitlePane != null) { 334 oldTitlePane.setVisible(false); 335 layeredPane.remove(oldTitlePane); 336 } 337 if (titlePane != null) { 338 layeredPane.add(titlePane, JLayeredPane.FRAME_CONTENT_LAYER); 339 titlePane.setVisible(true); 340 } 341 this.titlePane = titlePane; 342 } 343 344 351 private JComponent getTitlePane() { 352 return titlePane; 353 } 354 355 359 private JRootPane getRootPane() { 360 return root; 361 } 362 363 381 public void propertyChange(PropertyChangeEvent e) { 382 super.propertyChange(e); 383 384 String propertyName = e.getPropertyName(); 385 if(propertyName == null) { 386 return; 387 } 388 389 if(propertyName.equals("windowDecorationStyle")) { 390 JRootPane root = (JRootPane) e.getSource(); 391 int style = root.getWindowDecorationStyle(); 392 393 uninstallClientDecorations(root); 398 if (style != JRootPane.NONE) { 399 installClientDecorations(root); 400 } 401 } 402 else if (propertyName.equals("ancestor")) { 403 uninstallWindowListeners(root); 404 if (((JRootPane)e.getSource()).getWindowDecorationStyle() != 405 JRootPane.NONE) { 406 installWindowListeners(root, root.getParent()); 407 } 408 } 409 return; 410 } 411 412 417 private static class MetalRootLayout implements LayoutManager2 { 420 426 public Dimension preferredLayoutSize(Container parent) { 427 Dimension cpd, mbd, tpd; 428 int cpWidth = 0; 429 int cpHeight = 0; 430 int mbWidth = 0; 431 int mbHeight = 0; 432 int tpWidth = 0; 433 int tpHeight = 0; 434 Insets i = parent.getInsets(); 435 JRootPane root = (JRootPane) parent; 436 437 if(root.getContentPane() != null) { 438 cpd = root.getContentPane().getPreferredSize(); 439 } else { 440 cpd = root.getSize(); 441 } 442 if (cpd != null) { 443 cpWidth = cpd.width; 444 cpHeight = cpd.height; 445 } 446 447 if(root.getMenuBar() != null) { 448 mbd = root.getMenuBar().getPreferredSize(); 449 if (mbd != null) { 450 mbWidth = mbd.width; 451 mbHeight = mbd.height; 452 } 453 } 454 455 if (root.getWindowDecorationStyle() != JRootPane.NONE && 456 (root.getUI() instanceof MetalRootPaneUI )) { 457 JComponent titlePane = ((MetalRootPaneUI )root.getUI()). 458 getTitlePane(); 459 if (titlePane != null) { 460 tpd = titlePane.getPreferredSize(); 461 if (tpd != null) { 462 tpWidth = tpd.width; 463 tpHeight = tpd.height; 464 } 465 } 466 } 467 468 return new Dimension(Math.max(Math.max(cpWidth, mbWidth), tpWidth) + i.left + i.right, 469 cpHeight + mbHeight + tpWidth + i.top + i.bottom); 470 } 471 472 478 public Dimension minimumLayoutSize(Container parent) { 479 Dimension cpd, mbd, tpd; 480 int cpWidth = 0; 481 int cpHeight = 0; 482 int mbWidth = 0; 483 int mbHeight = 0; 484 int tpWidth = 0; 485 int tpHeight = 0; 486 Insets i = parent.getInsets(); 487 JRootPane root = (JRootPane) parent; 488 489 if(root.getContentPane() != null) { 490 cpd = root.getContentPane().getMinimumSize(); 491 } else { 492 cpd = root.getSize(); 493 } 494 if (cpd != null) { 495 cpWidth = cpd.width; 496 cpHeight = cpd.height; 497 } 498 499 if(root.getMenuBar() != null) { 500 mbd = root.getMenuBar().getMinimumSize(); 501 if (mbd != null) { 502 mbWidth = mbd.width; 503 mbHeight = mbd.height; 504 } 505 } 506 if (root.getWindowDecorationStyle() != JRootPane.NONE && 507 (root.getUI() instanceof MetalRootPaneUI )) { 508 JComponent titlePane = ((MetalRootPaneUI )root.getUI()). 509 getTitlePane(); 510 if (titlePane != null) { 511 tpd = titlePane.getMinimumSize(); 512 if (tpd != null) { 513 tpWidth = tpd.width; 514 tpHeight = tpd.height; 515 } 516 } 517 } 518 519 return new Dimension(Math.max(Math.max(cpWidth, mbWidth), tpWidth) + i.left + i.right, 520 cpHeight + mbHeight + tpWidth + i.top + i.bottom); 521 } 522 523 529 public Dimension maximumLayoutSize(Container target) { 530 Dimension cpd, mbd, tpd; 531 int cpWidth = Integer.MAX_VALUE; 532 int cpHeight = Integer.MAX_VALUE; 533 int mbWidth = Integer.MAX_VALUE; 534 int mbHeight = Integer.MAX_VALUE; 535 int tpWidth = Integer.MAX_VALUE; 536 int tpHeight = Integer.MAX_VALUE; 537 Insets i = target.getInsets(); 538 JRootPane root = (JRootPane) target; 539 540 if(root.getContentPane() != null) { 541 cpd = root.getContentPane().getMaximumSize(); 542 if (cpd != null) { 543 cpWidth = cpd.width; 544 cpHeight = cpd.height; 545 } 546 } 547 548 if(root.getMenuBar() != null) { 549 mbd = root.getMenuBar().getMaximumSize(); 550 if (mbd != null) { 551 mbWidth = mbd.width; 552 mbHeight = mbd.height; 553 } 554 } 555 556 if (root.getWindowDecorationStyle() != JRootPane.NONE && 557 (root.getUI() instanceof MetalRootPaneUI )) { 558 JComponent titlePane = ((MetalRootPaneUI )root.getUI()). 559 getTitlePane(); 560 if (titlePane != null) 561 { 562 tpd = titlePane.getMaximumSize(); 563 if (tpd != null) { 564 tpWidth = tpd.width; 565 tpHeight = tpd.height; 566 } 567 } 568 } 569 570 int maxHeight = Math.max(Math.max(cpHeight, mbHeight), tpHeight); 571 if (maxHeight != Integer.MAX_VALUE) { 574 maxHeight = cpHeight + mbHeight + tpHeight + i.top + i.bottom; 575 } 576 577 int maxWidth = Math.max(Math.max(cpWidth, mbWidth), tpWidth); 578 if (maxWidth != Integer.MAX_VALUE) { 580 maxWidth += i.left + i.right; 581 } 582 583 return new Dimension(maxWidth, maxHeight); 584 } 585 586 592 public void layoutContainer(Container parent) { 593 JRootPane root = (JRootPane) parent; 594 Rectangle b = root.getBounds(); 595 Insets i = root.getInsets(); 596 int nextY = 0; 597 int w = b.width - i.right - i.left; 598 int h = b.height - i.top - i.bottom; 599 600 if(root.getLayeredPane() != null) { 601 root.getLayeredPane().setBounds(i.left, i.top, w, h); 602 } 603 if(root.getGlassPane() != null) { 604 root.getGlassPane().setBounds(i.left, i.top, w, h); 605 } 606 if (root.getWindowDecorationStyle() != JRootPane.NONE && 609 (root.getUI() instanceof MetalRootPaneUI )) { 610 JComponent titlePane = ((MetalRootPaneUI )root.getUI()). 611 getTitlePane(); 612 if (titlePane != null) { 613 Dimension tpd = titlePane.getPreferredSize(); 614 if (tpd != null) { 615 int tpHeight = tpd.height; 616 titlePane.setBounds(0, 0, w, tpHeight); 617 nextY += tpHeight; 618 } 619 } 620 } 621 if(root.getMenuBar() != null) { 622 Dimension mbd = root.getMenuBar().getPreferredSize(); 623 root.getMenuBar().setBounds(0, nextY, w, mbd.height); 624 nextY += mbd.height; 625 } 626 if(root.getContentPane() != null) { 627 Dimension cpd = root.getContentPane().getPreferredSize(); 628 root.getContentPane().setBounds(0, nextY, w, 629 h < nextY ? 0 : h - nextY); 630 } 631 } 632 633 public void addLayoutComponent(String name, Component comp) {} 634 public void removeLayoutComponent(Component comp) {} 635 public void addLayoutComponent(Component comp, Object constraints) {} 636 public float getLayoutAlignmentX(Container target) { return 0.0f; } 637 public float getLayoutAlignmentY(Container target) { return 0.0f; } 638 public void invalidateLayout(Container target) {} 639 } 640 641 642 646 private static final int[] cursorMapping = new int[] 647 { Cursor.NW_RESIZE_CURSOR, Cursor.NW_RESIZE_CURSOR, Cursor.N_RESIZE_CURSOR, 648 Cursor.NE_RESIZE_CURSOR, Cursor.NE_RESIZE_CURSOR, 649 Cursor.NW_RESIZE_CURSOR, 0, 0, 0, Cursor.NE_RESIZE_CURSOR, 650 Cursor.W_RESIZE_CURSOR, 0, 0, 0, Cursor.E_RESIZE_CURSOR, 651 Cursor.SW_RESIZE_CURSOR, 0, 0, 0, Cursor.SE_RESIZE_CURSOR, 652 Cursor.SW_RESIZE_CURSOR, Cursor.SW_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR, 653 Cursor.SE_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR 654 }; 655 656 661 private class MouseInputHandler implements MouseInputListener { 662 665 private boolean isMovingWindow; 666 667 670 private int dragCursor; 671 672 675 private int dragOffsetX; 676 677 680 private int dragOffsetY; 681 682 685 private int dragWidth; 686 687 690 private int dragHeight; 691 692 696 private final PrivilegedExceptionAction getLocationAction = new PrivilegedExceptionAction(){ 697 public Object run() throws HeadlessException{ 698 return MouseInfo.getPointerInfo().getLocation(); 699 }}; 700 701 public void mousePressed(MouseEvent ev) { 702 JRootPane rootPane = getRootPane(); 703 704 if (rootPane.getWindowDecorationStyle() == JRootPane.NONE) { 705 return; 706 } 707 Point dragWindowOffset = ev.getPoint(); 708 Window w = (Window)ev.getSource(); 709 if (w != null) { 710 w.toFront(); 711 } 712 Point convertedDragWindowOffset = SwingUtilities.convertPoint( 713 w, dragWindowOffset, getTitlePane()); 714 715 Frame f = null; 716 Dialog d = null; 717 718 if (w instanceof Frame) { 719 f = (Frame)w; 720 } else if (w instanceof Dialog) { 721 d = (Dialog)w; 722 } 723 724 int frameState = (f != null) ? f.getExtendedState() : 0; 725 726 if (getTitlePane() != null && 727 getTitlePane().contains(convertedDragWindowOffset)) { 728 if ((f != null && ((frameState & Frame.MAXIMIZED_BOTH) == 0) 729 || (d != null)) 730 && dragWindowOffset.y >= BORDER_DRAG_THICKNESS 731 && dragWindowOffset.x >= BORDER_DRAG_THICKNESS 732 && dragWindowOffset.x < w.getWidth() 733 - BORDER_DRAG_THICKNESS) { 734 isMovingWindow = true; 735 dragOffsetX = dragWindowOffset.x; 736 dragOffsetY = dragWindowOffset.y; 737 } 738 } 739 else if (f != null && f.isResizable() 740 && ((frameState & Frame.MAXIMIZED_BOTH) == 0) 741 || (d != null && d.isResizable())) { 742 dragOffsetX = dragWindowOffset.x; 743 dragOffsetY = dragWindowOffset.y; 744 dragWidth = w.getWidth(); 745 dragHeight = w.getHeight(); 746 dragCursor = getCursor(calculateCorner( 747 w, dragWindowOffset.x, dragWindowOffset.y)); 748 } 749 } 750 751 public void mouseReleased(MouseEvent ev) { 752 if (dragCursor != 0 && window != null && !window.isValid()) { 753 window.validate(); 756 getRootPane().repaint(); 757 } 758 isMovingWindow = false; 759 dragCursor = 0; 760 } 761 762 public void mouseMoved(MouseEvent ev) { 763 JRootPane root = getRootPane(); 764 765 if (root.getWindowDecorationStyle() == JRootPane.NONE) { 766 return; 767 } 768 769 Window w = (Window)ev.getSource(); 770 771 Frame f = null; 772 Dialog d = null; 773 774 if (w instanceof Frame) { 775 f = (Frame)w; 776 } else if (w instanceof Dialog) { 777 d = (Dialog)w; 778 } 779 780 int cursor = getCursor(calculateCorner(w, ev.getX(), ev.getY())); 782 783 if (cursor != 0 && ((f != null && (f.isResizable() && 784 (f.getExtendedState() & Frame.MAXIMIZED_BOTH) == 0)) 785 || (d != null && d.isResizable()))) { 786 w.setCursor(Cursor.getPredefinedCursor(cursor)); 787 } 788 else { 789 w.setCursor(lastCursor); 790 } 791 } 792 793 private void adjust(Rectangle bounds, Dimension min, int deltaX, 794 int deltaY, int deltaWidth, int deltaHeight) { 795 bounds.x += deltaX; 796 bounds.y += deltaY; 797 bounds.width += deltaWidth; 798 bounds.height += deltaHeight; 799 if (min != null) { 800 if (bounds.width < min.width) { 801 int correction = min.width - bounds.width; 802 if (deltaX != 0) { 803 bounds.x -= correction; 804 } 805 bounds.width = min.width; 806 } 807 if (bounds.height < min.height) { 808 int correction = min.height - bounds.height; 809 if (deltaY != 0) { 810 bounds.y -= correction; 811 } 812 bounds.height = min.height; 813 } 814 } 815 } 816 817 public void mouseDragged(MouseEvent ev) { 818 Window w = (Window)ev.getSource(); 819 Point pt = ev.getPoint(); 820 821 if (isMovingWindow) { 822 Point windowPt; 823 try { 824 windowPt = (Point) AccessController.doPrivileged(getLocationAction); 825 windowPt.x = windowPt.x - dragOffsetX; 826 windowPt.y = windowPt.y - dragOffsetY; 827 w.setLocation(windowPt); 828 }catch (PrivilegedActionException e) { 829 } 830 } 831 else if (dragCursor != 0) { 832 Rectangle r = w.getBounds(); 833 Rectangle startBounds = new Rectangle(r); 834 Dimension min = w.getMinimumSize(); 835 836 switch (dragCursor) { 837 case Cursor.E_RESIZE_CURSOR: 838 adjust(r, min, 0, 0, pt.x + (dragWidth - dragOffsetX) - 839 r.width, 0); 840 break; 841 case Cursor.S_RESIZE_CURSOR: 842 adjust(r, min, 0, 0, 0, pt.y + (dragHeight - dragOffsetY) - 843 r.height); 844 break; 845 case Cursor.N_RESIZE_CURSOR: 846 adjust(r, min, 0, pt.y -dragOffsetY, 0, 847 -(pt.y - dragOffsetY)); 848 break; 849 case Cursor.W_RESIZE_CURSOR: 850 adjust(r, min, pt.x - dragOffsetX, 0, 851 -(pt.x - dragOffsetX), 0); 852 break; 853 case Cursor.NE_RESIZE_CURSOR: 854 adjust(r, min, 0, pt.y - dragOffsetY, 855 pt.x + (dragWidth - dragOffsetX) - r.width, 856 -(pt.y - dragOffsetY)); 857 break; 858 case Cursor.SE_RESIZE_CURSOR: 859 adjust(r, min, 0, 0, 860 pt.x + (dragWidth - dragOffsetX) - r.width, 861 pt.y + (dragHeight - dragOffsetY) - 862 r.height); 863 break; 864 case Cursor.NW_RESIZE_CURSOR: 865 adjust(r, min, pt.x - dragOffsetX, 866 pt.y - dragOffsetY, 867 -(pt.x - dragOffsetX), 868 -(pt.y - dragOffsetY)); 869 break; 870 case Cursor.SW_RESIZE_CURSOR: 871 adjust(r, min, pt.x - dragOffsetX, 0, 872 -(pt.x - dragOffsetX), 873 pt.y + (dragHeight - dragOffsetY) - r.height); 874 break; 875 default: 876 break; 877 } 878 if (!r.equals(startBounds)) { 879 w.setBounds(r); 880 if (Toolkit.getDefaultToolkit().isDynamicLayoutActive()) { 883 w.validate(); 884 getRootPane().repaint(); 885 } 886 } 887 } 888 } 889 890 public void mouseEntered(MouseEvent ev) { 891 Window w = (Window)ev.getSource(); 892 lastCursor = w.getCursor(); 893 mouseMoved(ev); 894 } 895 896 public void mouseExited(MouseEvent ev) { 897 Window w = (Window)ev.getSource(); 898 w.setCursor(lastCursor); 899 } 900 901 public void mouseClicked(MouseEvent ev) { 902 Window w = (Window)ev.getSource(); 903 Frame f = null; 904 905 if (w instanceof Frame) { 906 f = (Frame)w; 907 } else { 908 return; 909 } 910 911 Point convertedPoint = SwingUtilities.convertPoint( 912 w, ev.getPoint(), getTitlePane()); 913 914 int state = f.getExtendedState(); 915 if (getTitlePane() != null && 916 getTitlePane().contains(convertedPoint)) { 917 if ((ev.getClickCount() % 2) == 0 && 918 ((ev.getModifiers() & InputEvent.BUTTON1_MASK) != 0)) { 919 if (f.isResizable()) { 920 if ((state & Frame.MAXIMIZED_BOTH) != 0) { 921 f.setExtendedState(state & ~Frame.MAXIMIZED_BOTH); 922 } 923 else { 924 f.setExtendedState(state | Frame.MAXIMIZED_BOTH); 925 } 926 return; 927 } 928 } 929 } 930 } 931 932 936 private int calculateCorner(Window w, int x, int y) { 937 Insets insets = w.getInsets(); 938 int xPosition = calculatePosition(x - insets.left, 939 w.getWidth() - insets.left - insets.right); 940 int yPosition = calculatePosition(y - insets.top, 941 w.getHeight() - insets.top - insets.bottom); 942 943 if (xPosition == -1 || yPosition == -1) { 944 return -1; 945 } 946 return yPosition * 5 + xPosition; 947 } 948 949 953 private int getCursor(int corner) { 954 if (corner == -1) { 955 return 0; 956 } 957 return cursorMapping[corner]; 958 } 959 960 970 private int calculatePosition(int spot, int width) { 971 if (spot < BORDER_DRAG_THICKNESS) { 972 return 0; 973 } 974 if (spot < CORNER_DRAG_WIDTH) { 975 return 1; 976 } 977 if (spot >= (width - BORDER_DRAG_THICKNESS)) { 978 return 4; 979 } 980 if (spot >= (width - CORNER_DRAG_WIDTH)) { 981 return 3; 982 } 983 return 2; 984 } 985 } 986 } 987 | Popular Tags |