Source for javax.swing.plaf.basic.BasicSplitPaneUI

   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: }