GNU Classpath (0.18) | ||
Frames | No Frames |
1: /* BasicSplitPaneUI.java -- 2: Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing.plaf.basic; 40: 41: import java.awt.Canvas; 42: import java.awt.Color; 43: import java.awt.Component; 44: import java.awt.Container; 45: import java.awt.Dimension; 46: import java.awt.Graphics; 47: import java.awt.Insets; 48: import java.awt.LayoutManager2; 49: import java.awt.Point; 50: import java.awt.event.ActionEvent; 51: import java.awt.event.ActionListener; 52: import java.awt.event.FocusAdapter; 53: import java.awt.event.FocusEvent; 54: import java.awt.event.FocusListener; 55: import java.beans.PropertyChangeEvent; 56: import java.beans.PropertyChangeListener; 57: 58: import javax.swing.JComponent; 59: import javax.swing.JSplitPane; 60: import javax.swing.KeyStroke; 61: import javax.swing.UIDefaults; 62: import javax.swing.UIManager; 63: import javax.swing.plaf.ComponentUI; 64: import javax.swing.plaf.SplitPaneUI; 65: 66: /** 67: * This is the Basic Look and Feel implementation of the SplitPaneUI class. 68: */ 69: public class BasicSplitPaneUI extends SplitPaneUI 70: { 71: /** 72: * This Layout Manager controls the position and size of the components when 73: * the JSplitPane's orientation is HORIZONTAL_SPLIT. 74: * 75: * @specnote Apparently this class was intended to be protected, 76: * but was made public by a compiler bug and is now 77: * public for compatibility. 78: */ 79: public class BasicHorizontalLayoutManager implements LayoutManager2 80: { 81: // 3 components at a time. 82: // LEFT/TOP = 0 83: // RIGHT/BOTTOM = 1 84: // DIVIDER = 2 85: 86: /** 87: * This array contains the components in the JSplitPane. The left/top 88: * component is at index 0, the right/bottom is at 1, and the divider is 89: * at 2. 90: */ 91: protected Component[] components = new Component[3]; 92: 93: // These are the _current_ widths of the associated component. 94: 95: /** 96: * This array contains the current width (for HORIZONTAL_SPLIT) or height 97: * (for VERTICAL_SPLIT) of the components. The indices are the same as 98: * for components. 99: */ 100: protected int[] sizes = new int[3]; 101: 102: /** 103: * This method adds the component given to the JSplitPane. The position of 104: * the component is given by the constraints object. 105: * 106: * @param comp The Component to add. 107: * @param constraints The constraints that bind the object. 108: */ 109: public void addLayoutComponent(Component comp, Object constraints) 110: { 111: addLayoutComponent((String) constraints, comp); 112: } 113: 114: /** 115: * This method is called to add a Component to the JSplitPane. The 116: * placement string determines where the Component will be placed. The 117: * string should be one of LEFT, RIGHT, TOP, BOTTOM or null (signals that 118: * the component is the divider). 119: * 120: * @param place The placement of the Component. 121: * @param component The Component to add. 122: * 123: * @throws IllegalArgumentException DOCUMENT ME! 124: */ 125: public void addLayoutComponent(String place, Component component) 126: { 127: int i = 0; 128: if (place == null) 129: i = 2; 130: else if (place.equals(JSplitPane.TOP) || place.equals(JSplitPane.LEFT)) 131: i = 0; 132: else if (place.equals(JSplitPane.BOTTOM) 133: || place.equals(JSplitPane.RIGHT)) 134: i = 1; 135: else 136: throw new IllegalArgumentException("Illegal placement in JSplitPane"); 137: components[i] = component; 138: resetSizeAt(i); 139: splitPane.revalidate(); 140: splitPane.repaint(); 141: } 142: 143: /** 144: * This method returns the width of the JSplitPane minus the insets. 145: * 146: * @param containerSize The Dimensions of the JSplitPane. 147: * @param insets The Insets of the JSplitPane. 148: * 149: * @return The width of the JSplitPane minus the insets. 150: */ 151: protected int getAvailableSize(Dimension containerSize, Insets insets) 152: { 153: return containerSize.width - insets.left - insets.right; 154: } 155: 156: /** 157: * This method returns the given insets left value. If the given inset is 158: * null, then 0 is returned. 159: * 160: * @param insets The Insets to use with the JSplitPane. 161: * 162: * @return The inset's left value. 163: */ 164: protected int getInitialLocation(Insets insets) 165: { 166: if (insets != null) 167: return insets.left; 168: return 0; 169: } 170: 171: /** 172: * This specifies how a component is aligned with respect to other 173: * components in the x fdirection. 174: * 175: * @param target The container. 176: * 177: * @return The component's alignment. 178: */ 179: public float getLayoutAlignmentX(Container target) 180: { 181: return target.getAlignmentX(); 182: } 183: 184: /** 185: * This specifies how a component is aligned with respect to other 186: * components in the y direction. 187: * 188: * @param target The container. 189: * 190: * @return The component's alignment. 191: */ 192: public float getLayoutAlignmentY(Container target) 193: { 194: return target.getAlignmentY(); 195: } 196: 197: /** 198: * This method returns the preferred width of the component. 199: * 200: * @param c The component to measure. 201: * 202: * @return The preferred width of the component. 203: */ 204: protected int getPreferredSizeOfComponent(Component c) 205: { 206: Dimension dims = c.getPreferredSize(); 207: if (dims != null) 208: return dims.width; 209: return 0; 210: } 211: 212: /** 213: * This method returns the current width of the component. 214: * 215: * @param c The component to measure. 216: * 217: * @return The width of the component. 218: */ 219: protected int getSizeOfComponent(Component c) 220: { 221: return c.getWidth(); 222: } 223: 224: /** 225: * This method returns the sizes array. 226: * 227: * @return The sizes array. 228: */ 229: protected int[] getSizes() 230: { 231: return sizes; 232: } 233: 234: /** 235: * This method invalidates the layout. It does nothing. 236: * 237: * @param c The container to invalidate. 238: */ 239: public void invalidateLayout(Container c) 240: { 241: // DO NOTHING 242: } 243: 244: /** 245: * This method lays out the components in the container. 246: * 247: * @param container The container to lay out. 248: */ 249: public void layoutContainer(Container container) 250: { 251: if (container instanceof JSplitPane) 252: { 253: JSplitPane split = (JSplitPane) container; 254: distributeExtraSpace(); 255: Insets insets = split.getInsets(); 256: int width = getInitialLocation(insets); 257: Dimension dims = split.getSize(); 258: for (int i = 0; i < components.length; i += 2) 259: { 260: if (components[i] == null) 261: continue; 262: setComponentToSize(components[i], sizes[i], width, insets, dims); 263: width += sizes[i]; 264: } 265: if (components[1] != null) 266: { 267: setComponentToSize(components[1], sizes[1], width, insets, dims); 268: width += sizes[1]; 269: } 270: } 271: } 272: 273: /** 274: * This method returns the maximum size for the container given the 275: * components. It returns a new Dimension object that has width and 276: * height equal to Integer.MAX_VALUE. 277: * 278: * @param target The container to measure. 279: * 280: * @return The maximum size. 281: */ 282: public Dimension maximumLayoutSize(Container target) 283: { 284: return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 285: } 286: 287: /** 288: * This method returns the container's minimum size. The minimum width is 289: * the sum of all the component's minimum widths. The minimum height is 290: * the maximum of all the components' minimum heights. 291: * 292: * @param target The container to measure. 293: * 294: * @return The minimum size. 295: */ 296: public Dimension minimumLayoutSize(Container target) 297: { 298: if (target instanceof JSplitPane) 299: { 300: JSplitPane split = (JSplitPane) target; 301: Insets insets = target.getInsets(); 302: 303: int height = 0; 304: int width = 0; 305: for (int i = 0; i < components.length; i++) 306: { 307: if (components[i] == null) 308: continue; 309: Dimension dims = components[i].getMinimumSize(); 310: if (dims != null) 311: { 312: width += dims.width; 313: height = Math.max(height, dims.height); 314: } 315: } 316: return new Dimension(width, height); 317: } 318: return null; 319: } 320: 321: /** 322: * This method returns the container's preferred size. The preferred width 323: * is the sum of all the component's preferred widths. The preferred 324: * height is the maximum of all the components' preferred heights. 325: * 326: * @param target The container to measure. 327: * 328: * @return The preferred size. 329: */ 330: public Dimension preferredLayoutSize(Container target) 331: { 332: if (target instanceof JSplitPane) 333: { 334: JSplitPane split = (JSplitPane) target; 335: Insets insets = target.getInsets(); 336: 337: int height = 0; 338: int width = 0; 339: for (int i = 0; i < components.length; i++) 340: { 341: if (components[i] == null) 342: continue; 343: Dimension dims = components[i].getPreferredSize(); 344: if (dims != null) 345: { 346: width += dims.width; 347: if (! (components[i] instanceof BasicSplitPaneDivider)) 348: height = Math.max(height, dims.height); 349: } 350: } 351: return new Dimension(width, height); 352: } 353: return null; 354: } 355: 356: /** 357: * This method removes the component from the layout. 358: * 359: * @param component The component to remove from the layout. 360: */ 361: public void removeLayoutComponent(Component component) 362: { 363: for (int i = 0; i < components.length; i++) 364: { 365: if (component == components[i]) 366: { 367: components[i] = null; 368: sizes[i] = 0; 369: } 370: } 371: } 372: 373: /** 374: * This method resets the size of Component to the preferred size. 375: * 376: * @param index The index of the component to reset. 377: */ 378: protected void resetSizeAt(int index) 379: { 380: if (components[index] != null) 381: sizes[index] = getPreferredSizeOfComponent(components[index]); 382: } 383: 384: /** 385: * This method resets the sizes of all the components. 386: */ 387: public void resetToPreferredSizes() 388: { 389: for (int i = 0; i < components.length; i++) 390: resetSizeAt(i); 391: } 392: 393: /** 394: * This methods sets the bounds of the given component. The width is the 395: * size. The height is the container size minus the top and bottom 396: * inset. The x coordinate is the location given. The y coordinate is 397: * the top inset. 398: * 399: * @param c The component to set. 400: * @param size The width of the component. 401: * @param location The x coordinate. 402: * @param insets The insets to use. 403: * @param containerSize The height of the container. 404: */ 405: protected void setComponentToSize(Component c, int size, int location, 406: Insets insets, Dimension containerSize) 407: { 408: int w = size; 409: int h = containerSize.height - insets.top - insets.bottom; 410: int x = location; 411: int y = insets.top; 412: c.setBounds(x, y, w, h); 413: } 414: 415: /** 416: * This method stores the given int array as the new sizes array. 417: * 418: * @param newSizes The array to use as sizes. 419: */ 420: protected void setSizes(int[] newSizes) 421: { 422: sizes = newSizes; 423: } 424: 425: /** 426: * This method determines the size of each component. It should be called 427: * when a new Layout Manager is created for an existing JSplitPane. 428: */ 429: protected void updateComponents() 430: { 431: Component left = splitPane.getLeftComponent(); 432: Component right = splitPane.getRightComponent(); 433: 434: if (left != null) 435: { 436: components[0] = left; 437: resetSizeAt(0); 438: } 439: if (right != null) 440: { 441: components[1] = right; 442: resetSizeAt(1); 443: } 444: components[2] = divider; 445: resetSizeAt(2); 446: } 447: 448: /** 449: * This method resizes the left and right components to fit inside the 450: * JSplitPane when there is extra space. 451: */ 452: void distributeExtraSpace() 453: { 454: int availSize = getAvailableSize(splitPane.getSize(), 455: splitPane.getInsets()); 456: int[] newSizes = new int[3]; 457: double weight = splitPane.getResizeWeight(); 458: 459: int oldLen = sizes[0] + sizes[1]; 460: 461: // dividers don't change size. 462: availSize -= sizes[2] + oldLen; 463: 464: int rightAlloc = (int) (availSize * (1 - weight)); 465: int leftAlloc = availSize - rightAlloc; 466: 467: sizes[0] += leftAlloc; 468: sizes[1] += rightAlloc; 469: } 470: 471: /** 472: * This method returns the minimum width of the component at the given 473: * index. 474: * 475: * @param index The index to check. 476: * 477: * @return The minimum width. 478: */ 479: int minimumSizeOfComponent(int index) 480: { 481: Dimension dims = components[index].getMinimumSize(); 482: if (dims != null) 483: return dims.width; 484: else 485: return 0; 486: } 487: } //end BasicHorizontalLayoutManager 488: 489: /** 490: * This class is the Layout Manager for the JSplitPane when the orientation 491: * is VERTICAL_SPLIT. 492: * 493: * @specnote Apparently this class was intended to be protected, 494: * but was made public by a compiler bug and is now 495: * public for compatibility. 496: */ 497: public class BasicVerticalLayoutManager 498: extends BasicHorizontalLayoutManager 499: { 500: /** 501: * This method returns the height of the container minus the top and 502: * bottom inset. 503: * 504: * @param containerSize The size of the container. 505: * @param insets The insets of the container. 506: * 507: * @return The height minus top and bottom inset. 508: */ 509: protected int getAvailableSize(Dimension containerSize, Insets insets) 510: { 511: return containerSize.height - insets.top - insets.bottom; 512: } 513: 514: /** 515: * This method returns the top inset. 516: * 517: * @param insets The Insets to use. 518: * 519: * @return The top inset. 520: */ 521: protected int getInitialLocation(Insets insets) 522: { 523: return insets.top; 524: } 525: 526: /** 527: * This method returns the preferred height of the component. 528: * 529: * @param c The component to measure. 530: * 531: * @return The preferred height of the component. 532: */ 533: protected int getPreferredSizeOfComponent(Component c) 534: { 535: Dimension dims = c.getPreferredSize(); 536: if (dims != null) 537: return dims.height; 538: return 0; 539: } 540: 541: /** 542: * This method returns the current height of the component. 543: * 544: * @param c The component to measure. 545: * 546: * @return The current height of the component. 547: */ 548: protected int getSizeOfComponent(Component c) 549: { 550: return c.getHeight(); 551: } 552: 553: /** 554: * This method returns the minimum layout size. The minimum height is the 555: * sum of all the components' minimum heights. The minimum width is the 556: * maximum of all the components' minimum widths. 557: * 558: * @param container The container to measure. 559: * 560: * @return The minimum size. 561: */ 562: public Dimension minimumLayoutSize(Container container) 563: { 564: if (container instanceof JSplitPane) 565: { 566: JSplitPane split = (JSplitPane) container; 567: Insets insets = container.getInsets(); 568: 569: int height = 0; 570: int width = 0; 571: for (int i = 0; i < components.length; i++) 572: { 573: if (components[i] == null) 574: continue; 575: Dimension dims = components[i].getMinimumSize(); 576: if (dims != null) 577: { 578: height += dims.height; 579: width = Math.max(width, dims.width); 580: } 581: } 582: return new Dimension(width, height); 583: } 584: return null; 585: } 586: 587: /** 588: * This method returns the preferred layout size. The preferred height is 589: * the sum of all the components' preferred heights. The preferred width 590: * is the maximum of all the components' preferred widths. 591: * 592: * @param container The container to measure. 593: * 594: * @return The preferred size. 595: */ 596: public Dimension preferredLayoutSize(Container container) 597: { 598: if (container instanceof JSplitPane) 599: { 600: JSplitPane split = (JSplitPane) container; 601: Insets insets = container.getInsets(); 602: 603: int height = 0; 604: int width = 0; 605: for (int i = 0; i < components.length; i++) 606: { 607: if (components[i] == null) 608: continue; 609: Dimension dims = components[i].getPreferredSize(); 610: if (dims != null) 611: { 612: height += dims.height; 613: width = Math.max(width, dims.width); 614: } 615: } 616: return new Dimension(width, height); 617: } 618: return null; 619: } 620: 621: /** 622: * This method sets the bounds of the given component. The y coordinate is 623: * the location given. The x coordinate is the left inset. The height is 624: * the size given. The width is the container size minus the left and 625: * right inset. 626: * 627: * @param c The component to set bounds for. 628: * @param size The height. 629: * @param location The y coordinate. 630: * @param insets The insets to use. 631: * @param containerSize The container's size. 632: */ 633: protected void setComponentToSize(Component c, int size, int location, 634: Insets insets, Dimension containerSize) 635: { 636: int y = location; 637: int x = insets.left; 638: int h = size; 639: int w = containerSize.width - insets.left - insets.right; 640: 641: c.setBounds(x, y, w, h); 642: } 643: 644: /** 645: * This method returns the minimum height of the component at the given 646: * index. 647: * 648: * @param index The index of the component to check. 649: * 650: * @return The minimum height of the given component. 651: */ 652: int minimumSizeOfComponent(int index) 653: { 654: Dimension dims = components[index].getMinimumSize(); 655: if (dims != null) 656: return dims.height; 657: else 658: return 0; 659: } 660: } 661: 662: /** 663: * This class handles FocusEvents from the JComponent. 664: * 665: * @specnote Apparently this class was intended to be protected, 666: * but was made public by a compiler bug and is now 667: * public for compatibility. 668: */ 669: public class FocusHandler extends FocusAdapter 670: { 671: /** 672: * This method is called when the JSplitPane gains focus. 673: * 674: * @param ev The FocusEvent. 675: */ 676: public void focusGained(FocusEvent ev) 677: { 678: // FIXME: implement. 679: } 680: 681: /** 682: * This method is called when the JSplitPane loses focus. 683: * 684: * @param ev The FocusEvent. 685: */ 686: public void focusLost(FocusEvent ev) 687: { 688: // FIXME: implement. 689: } 690: } 691: 692: /** 693: * This is a deprecated class. It is supposed to be used for handling down 694: * and right key presses. 695: * 696: * @specnote Apparently this class was intended to be protected, 697: * but was made public by a compiler bug and is now 698: * public for compatibility. 699: */ 700: public class KeyboardDownRightHandler implements ActionListener 701: { 702: /** 703: * This method is called when the down or right keys are pressed. 704: * 705: * @param ev The ActionEvent 706: */ 707: public void actionPerformed(ActionEvent ev) 708: { 709: // FIXME: implement. 710: } 711: } 712: 713: /** 714: * This is a deprecated class. It is supposed to be used for handling end 715: * key presses. 716: * 717: * @specnote Apparently this class was intended to be protected, 718: * but was made public by a compiler bug and is now 719: * public for compatibility. 720: */ 721: public class KeyboardEndHandler implements ActionListener 722: { 723: /** 724: * This method is called when the end key is pressed. 725: * 726: * @param ev The ActionEvent. 727: */ 728: public void actionPerformed(ActionEvent ev) 729: { 730: // FIXME: implement. 731: } 732: } 733: 734: /** 735: * This is a deprecated class. It is supposed to be used for handling home 736: * key presses. 737: * 738: * @specnote Apparently this class was intended to be protected, 739: * but was made public by a compiler bug and is now 740: * public for compatibility. 741: */ 742: public class KeyboardHomeHandler implements ActionListener 743: { 744: /** 745: * This method is called when the home key is pressed. 746: * 747: * @param ev The ActionEvent. 748: */ 749: public void actionPerformed(ActionEvent ev) 750: { 751: // FIXME: implement. 752: } 753: } 754: 755: /** 756: * This is a deprecated class. It is supposed to be used for handling resize 757: * toggles. 758: * 759: * @specnote Apparently this class was intended to be protected, 760: * but was made public by a compiler bug and is now 761: * public for compatibility. 762: */ 763: public class KeyboardResizeToggleHandler implements ActionListener 764: { 765: /** 766: * This method is called when a resize is toggled. 767: * 768: * @param ev The ActionEvent. 769: */ 770: public void actionPerformed(ActionEvent ev) 771: { 772: // FIXME: implement. 773: } 774: } 775: 776: /** 777: * This is a deprecated class. It is supposed to be used for handler up and 778: * left key presses. 779: * 780: * @specnote Apparently this class was intended to be protected, 781: * but was made public by a compiler bug and is now 782: * public for compatibility. 783: */ 784: public class KeyboardUpLeftHandler implements ActionListener 785: { 786: /** 787: * This method is called when the left or up keys are pressed. 788: * 789: * @param ev The ActionEvent. 790: */ 791: public void actionPerformed(ActionEvent ev) 792: { 793: // FIXME: implement. 794: } 795: } 796: 797: /** 798: * This helper class handles PropertyChangeEvents from the JSplitPane. When 799: * a property changes, this will update the UI accordingly. 800: * 801: * @specnote Apparently this class was intended to be protected, 802: * but was made public by a compiler bug and is now 803: * public for compatibility. 804: */ 805: public class PropertyHandler implements PropertyChangeListener 806: { 807: /** 808: * This method is called whenever one of the JSplitPane's properties 809: * change. 810: * 811: * @param e DOCUMENT ME! 812: */ 813: public void propertyChange(PropertyChangeEvent e) 814: { 815: if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY)) 816: { 817: int newSize = splitPane.getDividerSize(); 818: int[] tmpSizes = layoutManager.getSizes(); 819: dividerSize = tmpSizes[2]; 820: Component left = splitPane.getLeftComponent(); 821: Component right = splitPane.getRightComponent(); 822: int newSpace = newSize - tmpSizes[2]; 823: 824: tmpSizes[2] = newSize; 825: 826: tmpSizes[0] += newSpace / 2; 827: tmpSizes[1] += newSpace / 2; 828: 829: layoutManager.setSizes(tmpSizes); 830: } 831: else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY)) 832: { 833: int max = layoutManager.getAvailableSize(splitPane.getSize(), 834: splitPane.getInsets()); 835: int dividerLoc = getDividerLocation(splitPane); 836: double prop = ((double) dividerLoc) / max; 837: 838: resetLayoutManager(); 839: if (prop <= 1 && prop >= 0) 840: splitPane.setDividerLocation(prop); 841: } 842: layoutManager.layoutContainer(splitPane); 843: splitPane.repaint(); 844: // Don't have to deal with continuous_layout - only 845: // necessary in dragging modes (and it's checked 846: // every time you drag there) 847: // Don't have to deal with resize_weight (as there 848: // will be no extra space associated with this 849: // event - the changes to the weighting will 850: // be taken into account the next time the 851: // sizes change.) 852: // Don't have to deal with divider_location 853: // The method in JSplitPane calls our setDividerLocation 854: // so we'll know about those anyway. 855: // Don't have to deal with last_divider_location 856: // Although I'm not sure why, it doesn't seem to 857: // have any effect on Sun's JSplitPane. 858: // one_touch_expandable changes are dealt with 859: // by our divider. 860: } 861: } 862: 863: /** The location of the divider when dragging began. */ 864: protected int beginDragDividerLocation; 865: 866: /** The size of the divider while dragging. */ 867: protected int dividerSize; 868: 869: /** The location where the last drag location ended. */ 870: transient int lastDragLocation = -1; 871: 872: /** The distance the divider is moved when moved by keyboard actions. */ 873: // Sun defines this as 3 874: protected static int KEYBOARD_DIVIDER_MOVE_OFFSET = 3; 875: 876: /** The divider that divides this JSplitPane. */ 877: protected BasicSplitPaneDivider divider; 878: 879: /** The listener that listens for PropertyChangeEvents from the JSplitPane. */ 880: protected PropertyChangeListener propertyChangeListener; 881: 882: /** The JSplitPane's focus handler. */ 883: protected FocusListener focusListener; 884: 885: /** @deprecated The handler for down and right key presses. */ 886: protected ActionListener keyboardDownRightListener; 887: 888: /** @deprecated The handler for end key presses. */ 889: protected ActionListener keyboardEndListener; 890: 891: /** @deprecated The handler for home key presses. */ 892: protected ActionListener keyboardHomeListener; 893: 894: /** @deprecated The handler for toggling resizes. */ 895: protected ActionListener keyboardResizeToggleListener; 896: 897: /** @deprecated The handler for up and left key presses. */ 898: protected ActionListener keyboardUpLeftListener; 899: 900: /** The JSplitPane's current layout manager. */ 901: protected BasicHorizontalLayoutManager layoutManager; 902: 903: /** @deprecated The divider resize toggle key. */ 904: protected KeyStroke dividerResizeToggleKey; 905: 906: /** @deprecated The down key. */ 907: protected KeyStroke downKey; 908: 909: /** @deprecated The end key. */ 910: protected KeyStroke endKey; 911: 912: /** @deprecated The home key. */ 913: protected KeyStroke homeKey; 914: 915: /** @deprecated The left key. */ 916: protected KeyStroke leftKey; 917: 918: /** @deprecated The right key. */ 919: protected KeyStroke rightKey; 920: 921: /** @deprecated The up key. */ 922: protected KeyStroke upKey; 923: 924: /** Set to true when dragging heavy weight components. */ 925: protected boolean draggingHW; 926: 927: /** 928: * The constraints object used when adding the non-continuous divider to the 929: * JSplitPane. 930: */ 931: protected static final String NON_CONTINUOUS_DIVIDER 932: = "nonContinuousDivider"; 933: 934: /** The dark divider used when dragging in non-continuous layout mode. */ 935: protected Component nonContinuousLayoutDivider; 936: 937: /** The JSplitPane that this UI draws. */ 938: protected JSplitPane splitPane; 939: 940: /** 941: * Creates a new BasicSplitPaneUI object. 942: */ 943: public BasicSplitPaneUI() 944: { 945: } 946: 947: /** 948: * This method creates a new BasicSplitPaneUI for the given JComponent. 949: * 950: * @param x The JComponent to create a UI for. 951: * 952: * @return A new BasicSplitPaneUI. 953: */ 954: public static ComponentUI createUI(JComponent x) 955: { 956: return new BasicSplitPaneUI(); 957: } 958: 959: /** 960: * This method installs the BasicSplitPaneUI for the given JComponent. 961: * 962: * @param c The JComponent to install the UI for. 963: */ 964: public void installUI(JComponent c) 965: { 966: if (c instanceof JSplitPane) 967: { 968: splitPane = (JSplitPane) c; 969: installDefaults(); 970: installListeners(); 971: installKeyboardActions(); 972: } 973: } 974: 975: /** 976: * This method uninstalls the BasicSplitPaneUI for the given JComponent. 977: * 978: * @param c The JComponent to uninstall the UI for. 979: */ 980: public void uninstallUI(JComponent c) 981: { 982: uninstallKeyboardActions(); 983: uninstallListeners(); 984: uninstallDefaults(); 985: 986: splitPane = null; 987: } 988: 989: /** 990: * This method installs the defaults given by the Look and Feel. 991: */ 992: protected void installDefaults() 993: { 994: divider = createDefaultDivider(); 995: resetLayoutManager(); 996: nonContinuousLayoutDivider = createDefaultNonContinuousLayoutDivider(); 997: splitPane.add(divider, JSplitPane.DIVIDER); 998: 999: // There is no need to add the nonContinuousLayoutDivider 1000: UIDefaults defaults = UIManager.getLookAndFeelDefaults(); 1001: splitPane.setBackground(defaults.getColor("SplitPane.background")); 1002: splitPane.setBorder(defaults.getBorder("SplitPane.border")); 1003: splitPane.setDividerSize(defaults.getInt("SplitPane.dividerSize")); 1004: splitPane.setOpaque(true); 1005: } 1006: 1007: /** 1008: * This method uninstalls the defaults and nulls any objects created during 1009: * install. 1010: */ 1011: protected void uninstallDefaults() 1012: { 1013: layoutManager = null; 1014: splitPane.remove(divider); 1015: divider = null; 1016: nonContinuousLayoutDivider = null; 1017: 1018: splitPane.setBackground(null); 1019: splitPane.setBorder(null); 1020: } 1021: 1022: /** 1023: * This method installs the listeners needed for this UI to function. 1024: */ 1025: protected void installListeners() 1026: { 1027: propertyChangeListener = createPropertyChangeListener(); 1028: focusListener = createFocusListener(); 1029: 1030: splitPane.addPropertyChangeListener(propertyChangeListener); 1031: splitPane.addFocusListener(focusListener); 1032: } 1033: 1034: /** 1035: * This method uninstalls all listeners registered for the UI. 1036: */ 1037: protected void uninstallListeners() 1038: { 1039: splitPane.removePropertyChangeListener(propertyChangeListener); 1040: splitPane.removeFocusListener(focusListener); 1041: 1042: focusListener = null; 1043: propertyChangeListener = null; 1044: } 1045: 1046: /** 1047: * This method installs the keyboard actions for the JSplitPane. 1048: */ 1049: protected void installKeyboardActions() 1050: { 1051: // FIXME: implement. 1052: } 1053: 1054: /** 1055: * This method reverses the work done in installKeyboardActions. 1056: */ 1057: protected void uninstallKeyboardActions() 1058: { 1059: // FIXME: implement. 1060: } 1061: 1062: /** 1063: * This method creates a new PropertyChangeListener. 1064: * 1065: * @return A new PropertyChangeListener. 1066: */ 1067: protected PropertyChangeListener createPropertyChangeListener() 1068: { 1069: return new PropertyHandler(); 1070: } 1071: 1072: /** 1073: * This method creates a new FocusListener. 1074: * 1075: * @return A new FocusListener. 1076: */ 1077: protected FocusListener createFocusListener() 1078: { 1079: return new FocusHandler(); 1080: } 1081: 1082: /** 1083: * This method creates a new ActionListener for up and left key presses. 1084: * 1085: * @return A new ActionListener for up and left keys. 1086: * 1087: * @deprecated 1.3 1088: */ 1089: protected ActionListener createKeyboardUpLeftListener() 1090: { 1091: return new KeyboardUpLeftHandler(); 1092: } 1093: 1094: /** 1095: * This method creates a new ActionListener for down and right key presses. 1096: * 1097: * @return A new ActionListener for down and right keys. 1098: * 1099: * @deprecated 1.3 1100: */ 1101: protected ActionListener createKeyboardDownRightListener() 1102: { 1103: return new KeyboardDownRightHandler(); 1104: } 1105: 1106: /** 1107: * This method creates a new ActionListener for home key presses. 1108: * 1109: * @return A new ActionListener for home keys. 1110: * 1111: * @deprecated 1112: */ 1113: protected ActionListener createKeyboardHomeListener() 1114: { 1115: return new KeyboardHomeHandler(); 1116: } 1117: 1118: /** 1119: * This method creates a new ActionListener for end key presses.i 1120: * 1121: * @return A new ActionListener for end keys. 1122: * 1123: * @deprecated 1.3 1124: */ 1125: protected ActionListener createKeyboardEndListener() 1126: { 1127: return new KeyboardEndHandler(); 1128: } 1129: 1130: /** 1131: * This method creates a new ActionListener for resize toggle key events. 1132: * 1133: * @return A new ActionListener for resize toggle keys. 1134: * 1135: * @deprecated 1.3 1136: */ 1137: protected ActionListener createKeyboardResizeToggleListener() 1138: { 1139: return new KeyboardResizeToggleHandler(); 1140: } 1141: 1142: /** 1143: * This method returns the orientation of the JSplitPane. 1144: * 1145: * @return The orientation of the JSplitPane. 1146: */ 1147: public int getOrientation() 1148: { 1149: return splitPane.getOrientation(); 1150: } 1151: 1152: /** 1153: * This method sets the orientation of the JSplitPane. 1154: * 1155: * @param orientation The new orientation of the JSplitPane. 1156: */ 1157: public void setOrientation(int orientation) 1158: { 1159: splitPane.setOrientation(orientation); 1160: } 1161: 1162: /** 1163: * This method returns true if the JSplitPane is using continuous layout. 1164: * 1165: * @return True if the JSplitPane is using continuous layout. 1166: */ 1167: public boolean isContinuousLayout() 1168: { 1169: return splitPane.isContinuousLayout(); 1170: } 1171: 1172: /** 1173: * This method sets the continuous layout property of the JSplitPane. 1174: * 1175: * @param b True if the JsplitPane is to use continuous layout. 1176: */ 1177: public void setContinuousLayout(boolean b) 1178: { 1179: splitPane.setContinuousLayout(b); 1180: } 1181: 1182: /** 1183: * This method returns the last location the divider was dragged to. 1184: * 1185: * @return The last location the divider was dragged to. 1186: */ 1187: public int getLastDragLocation() 1188: { 1189: return lastDragLocation; 1190: } 1191: 1192: /** 1193: * This method sets the last location the divider was dragged to. 1194: * 1195: * @param l The last location the divider was dragged to. 1196: */ 1197: public void setLastDragLocation(int l) 1198: { 1199: lastDragLocation = l; 1200: } 1201: 1202: /** 1203: * This method returns the BasicSplitPaneDivider that divides this 1204: * JSplitPane. 1205: * 1206: * @return The divider for the JSplitPane. 1207: */ 1208: public BasicSplitPaneDivider getDivider() 1209: { 1210: return divider; 1211: } 1212: 1213: /** 1214: * This method creates a nonContinuousLayoutDivider for use with the 1215: * JSplitPane in nonContinousLayout mode. The default divider is a gray 1216: * Canvas. 1217: * 1218: * @return The default nonContinousLayoutDivider. 1219: */ 1220: protected Component createDefaultNonContinuousLayoutDivider() 1221: { 1222: if (nonContinuousLayoutDivider == null) 1223: { 1224: nonContinuousLayoutDivider = new Canvas(); 1225: nonContinuousLayoutDivider.setBackground(Color.DARK_GRAY); 1226: } 1227: return nonContinuousLayoutDivider; 1228: } 1229: 1230: /** 1231: * This method sets the component to use as the nonContinuousLayoutDivider. 1232: * 1233: * @param newDivider The component to use as the nonContinuousLayoutDivider. 1234: */ 1235: protected void setNonContinuousLayoutDivider(Component newDivider) 1236: { 1237: setNonContinuousLayoutDivider(newDivider, true); 1238: } 1239: 1240: /** 1241: * This method sets the component to use as the nonContinuousLayoutDivider. 1242: * 1243: * @param newDivider The component to use as the nonContinuousLayoutDivider. 1244: * @param rememberSizes FIXME: document. 1245: */ 1246: protected void setNonContinuousLayoutDivider(Component newDivider, 1247: boolean rememberSizes) 1248: { 1249: // FIXME: use rememberSizes for something 1250: nonContinuousLayoutDivider = newDivider; 1251: } 1252: 1253: /** 1254: * This method returns the nonContinuousLayoutDivider. 1255: * 1256: * @return The nonContinuousLayoutDivider. 1257: */ 1258: public Component getNonContinuousLayoutDivider() 1259: { 1260: return nonContinuousLayoutDivider; 1261: } 1262: 1263: /** 1264: * This method returns the JSplitPane that this BasicSplitPaneUI draws. 1265: * 1266: * @return The JSplitPane. 1267: */ 1268: public JSplitPane getSplitPane() 1269: { 1270: return splitPane; 1271: } 1272: 1273: /** 1274: * This method creates the divider used normally with the JSplitPane. 1275: * 1276: * @return The default divider. 1277: */ 1278: public BasicSplitPaneDivider createDefaultDivider() 1279: { 1280: if (divider == null) 1281: divider = new BasicSplitPaneDivider(this); 1282: return divider; 1283: } 1284: 1285: /** 1286: * This method is called when JSplitPane's resetToPreferredSizes is called. 1287: * It resets the sizes of all components in the JSplitPane. 1288: * 1289: * @param jc The JSplitPane to reset. 1290: */ 1291: public void resetToPreferredSizes(JSplitPane jc) 1292: { 1293: layoutManager.resetToPreferredSizes(); 1294: } 1295: 1296: /** 1297: * This method sets the location of the divider. 1298: * 1299: * @param jc The JSplitPane to set the divider location in. 1300: * @param location The new location of the divider. 1301: */ 1302: public void setDividerLocation(JSplitPane jc, int location) 1303: { 1304: setLastDragLocation(getDividerLocation(splitPane)); 1305: splitPane.setLastDividerLocation(getDividerLocation(splitPane)); 1306: int[] tmpSizes = layoutManager.getSizes(); 1307: tmpSizes[0] = location 1308: - layoutManager.getInitialLocation(splitPane.getInsets()); 1309: tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(), 1310: splitPane.getInsets()) 1311: - tmpSizes[0] - tmpSizes[1]; 1312: 1313: layoutManager.setSizes(tmpSizes); 1314: splitPane.revalidate(); 1315: splitPane.repaint(); 1316: } 1317: 1318: /** 1319: * This method returns the location of the divider. 1320: * 1321: * @param jc The JSplitPane to retrieve the location for. 1322: * 1323: * @return The location of the divider. 1324: */ 1325: public int getDividerLocation(JSplitPane jc) 1326: { 1327: return layoutManager.sizes[0] 1328: + layoutManager.getInitialLocation(splitPane.getInsets()); 1329: } 1330: 1331: /** 1332: * This method returns the smallest value possible for the location of the 1333: * divider. 1334: * 1335: * @param jc The JSplitPane. 1336: * 1337: * @return The minimum divider location. 1338: */ 1339: public int getMinimumDividerLocation(JSplitPane jc) 1340: { 1341: int value = layoutManager.getInitialLocation(jc.getInsets()) 1342: - layoutManager.getAvailableSize(jc.getSize(), jc.getInsets()) 1343: + splitPane.getDividerSize(); 1344: if (layoutManager.components[1] != null) 1345: value += layoutManager.minimumSizeOfComponent(1); 1346: return value; 1347: } 1348: 1349: /** 1350: * This method returns the largest value possible for the location of the 1351: * divider. 1352: * 1353: * @param jc The JSplitPane. 1354: * 1355: * @return The maximum divider location. 1356: */ 1357: public int getMaximumDividerLocation(JSplitPane jc) 1358: { 1359: int value = layoutManager.getInitialLocation(jc.getInsets()) 1360: + layoutManager.getAvailableSize(jc.getSize(), jc.getInsets()) 1361: - splitPane.getDividerSize(); 1362: if (layoutManager.components[1] != null) 1363: value -= layoutManager.minimumSizeOfComponent(1); 1364: return value; 1365: } 1366: 1367: /** 1368: * This method is called after the children of the JSplitPane are painted. 1369: * 1370: * @param jc The JSplitPane. 1371: * @param g The Graphics object to paint with. 1372: */ 1373: public void finishedPaintingChildren(JSplitPane jc, Graphics g) 1374: { 1375: if (! splitPane.isContinuousLayout() && nonContinuousLayoutDivider != null 1376: && nonContinuousLayoutDivider.isVisible()) 1377: javax.swing.SwingUtilities.paintComponent(g, nonContinuousLayoutDivider, 1378: null, 1379: nonContinuousLayoutDivider 1380: .getBounds()); 1381: } 1382: 1383: /** 1384: * This method is called to paint the JSplitPane. 1385: * 1386: * @param g The Graphics object to paint with. 1387: * @param jc The JSplitPane to paint. 1388: */ 1389: public void paint(Graphics g, JComponent jc) 1390: { 1391: } 1392: 1393: /** 1394: * This method returns the preferred size of the JSplitPane. 1395: * 1396: * @param jc The JSplitPane. 1397: * 1398: * @return The preferred size of the JSplitPane. 1399: */ 1400: public Dimension getPreferredSize(JComponent jc) 1401: { 1402: return layoutManager.preferredLayoutSize((Container) jc); 1403: } 1404: 1405: /** 1406: * This method returns the minimum size of the JSplitPane. 1407: * 1408: * @param jc The JSplitPane. 1409: * 1410: * @return The minimum size of the JSplitPane. 1411: */ 1412: public Dimension getMinimumSize(JComponent jc) 1413: { 1414: return layoutManager.minimumLayoutSize((Container) jc); 1415: } 1416: 1417: /** 1418: * This method returns the maximum size of the JSplitPane. 1419: * 1420: * @param jc The JSplitPane. 1421: * 1422: * @return The maximum size of the JSplitPane. 1423: */ 1424: public Dimension getMaximumSize(JComponent jc) 1425: { 1426: return layoutManager.maximumLayoutSize((Container) jc); 1427: } 1428: 1429: /** 1430: * This method returns the border insets of the current border. 1431: * 1432: * @param jc The JSplitPane. 1433: * 1434: * @return The current border insets. 1435: */ 1436: public Insets getInsets(JComponent jc) 1437: { 1438: return splitPane.getBorder().getBorderInsets(splitPane); 1439: } 1440: 1441: /** 1442: * This method resets the current layout manager. The type of layout manager 1443: * is dependent on the current orientation. 1444: */ 1445: protected void resetLayoutManager() 1446: { 1447: if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) 1448: layoutManager = new BasicHorizontalLayoutManager(); 1449: else 1450: layoutManager = new BasicVerticalLayoutManager(); 1451: getSplitPane().setLayout(layoutManager); 1452: layoutManager.updateComponents(); 1453: 1454: // invalidating by itself does not invalidate the layout. 1455: getSplitPane().revalidate(); 1456: } 1457: 1458: /** 1459: * This method is called when dragging starts. It resets lastDragLocation 1460: * and dividerSize. 1461: */ 1462: protected void startDragging() 1463: { 1464: dividerSize = divider.getDividerSize(); 1465: setLastDragLocation(-1); 1466: 1467: if (! splitPane.getLeftComponent().isLightweight() 1468: || ! splitPane.getRightComponent().isLightweight()) 1469: draggingHW = true; 1470: 1471: if (splitPane.isContinuousLayout()) 1472: nonContinuousLayoutDivider.setVisible(false); 1473: else 1474: { 1475: nonContinuousLayoutDivider.setVisible(true); 1476: nonContinuousLayoutDivider.setBounds(divider.getBounds()); 1477: } 1478: splitPane.revalidate(); 1479: splitPane.repaint(); 1480: } 1481: 1482: /** 1483: * This method is called whenever the divider is dragged. If the JSplitPane 1484: * is in continuousLayout mode, the divider needs to be moved and the 1485: * JSplitPane needs to be laid out. 1486: * 1487: * @param location The new location of the divider. 1488: */ 1489: protected void dragDividerTo(int location) 1490: { 1491: location = validLocation(location); 1492: if (beginDragDividerLocation == -1) 1493: beginDragDividerLocation = location; 1494: 1495: if (splitPane.isContinuousLayout()) 1496: splitPane.setDividerLocation(location); 1497: else 1498: { 1499: Point p = nonContinuousLayoutDivider.getLocation(); 1500: if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) 1501: p.x = location; 1502: else 1503: p.y = location; 1504: nonContinuousLayoutDivider.setLocation(p); 1505: } 1506: setLastDragLocation(location); 1507: splitPane.repaint(); 1508: } 1509: 1510: /** 1511: * This method is called when the dragging is finished. 1512: * 1513: * @param location The location where the drag finished. 1514: */ 1515: protected void finishDraggingTo(int location) 1516: { 1517: if (nonContinuousLayoutDivider != null) 1518: nonContinuousLayoutDivider.setVisible(false); 1519: draggingHW = false; 1520: location = validLocation(location); 1521: dragDividerTo(location); 1522: splitPane.setDividerLocation(location); 1523: splitPane.setLastDividerLocation(beginDragDividerLocation); 1524: beginDragDividerLocation = -1; 1525: splitPane.repaint(); 1526: } 1527: 1528: /** 1529: * This method returns the width of one of the sides of the divider's border. 1530: * 1531: * @return The width of one side of the divider's border. 1532: * 1533: * @deprecated 1.3 1534: */ 1535: protected int getDividerBorderSize() 1536: { 1537: if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) 1538: return divider.getBorder().getBorderInsets(divider).left; 1539: else 1540: return divider.getBorder().getBorderInsets(divider).top; 1541: } 1542: 1543: /** 1544: * This is a helper method that returns a valid location for the divider 1545: * when dragging. 1546: * 1547: * @param location The location to check. 1548: * 1549: * @return A valid location. 1550: */ 1551: private int validLocation(int location) 1552: { 1553: if (location < getMinimumDividerLocation(splitPane)) 1554: return getMinimumDividerLocation(splitPane); 1555: if (location > getMaximumDividerLocation(splitPane)) 1556: return getMaximumDividerLocation(splitPane); 1557: return location; 1558: } 1559: }
GNU Classpath (0.18) |