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