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:   protected static int KEYBOARD_DIVIDER_MOVE_OFFSET;
 874: 
 875:   /** The divider that divides this JSplitPane. */
 876:   protected BasicSplitPaneDivider divider;
 877: 
 878:   /** The listener that listens for PropertyChangeEvents from the JSplitPane. */
 879:   protected PropertyChangeListener propertyChangeListener;
 880: 
 881:   /** The JSplitPane's focus handler. */
 882:   protected FocusListener focusListener;
 883: 
 884:   /** @deprecated The handler for down and right key presses. */
 885:   protected ActionListener keyboardDownRightListener;
 886: 
 887:   /** @deprecated The handler for end key presses. */
 888:   protected ActionListener keyboardEndListener;
 889: 
 890:   /** @deprecated The handler for home key presses. */
 891:   protected ActionListener keyboardHomeListener;
 892: 
 893:   /** @deprecated The handler for toggling resizes. */
 894:   protected ActionListener keyboardResizeToggleListener;
 895: 
 896:   /** @deprecated The handler for up and left key presses. */
 897:   protected ActionListener keyboardUpLeftListener;
 898: 
 899:   /** The JSplitPane's current layout manager. */
 900:   protected BasicHorizontalLayoutManager layoutManager;
 901: 
 902:   /** @deprecated The divider resize toggle key. */
 903:   protected KeyStroke dividerResizeToggleKey;
 904: 
 905:   /** @deprecated The down key. */
 906:   protected KeyStroke downKey;
 907: 
 908:   /** @deprecated The end key. */
 909:   protected KeyStroke endKey;
 910: 
 911:   /** @deprecated The home key. */
 912:   protected KeyStroke homeKey;
 913: 
 914:   /** @deprecated The left key. */
 915:   protected KeyStroke leftKey;
 916: 
 917:   /** @deprecated The right key. */
 918:   protected KeyStroke rightKey;
 919: 
 920:   /** @deprecated The up key. */
 921:   protected KeyStroke upKey;
 922: 
 923:   /** Set to true when dragging heavy weight components. */
 924:   protected boolean draggingHW;
 925: 
 926:   /**
 927:    * The constraints object used when adding the non-continuous divider to the
 928:    * JSplitPane.
 929:    */
 930:   protected static final String NON_CONTINUOUS_DIVIDER
 931:     = "nonContinuousDivider";
 932: 
 933:   /** The dark divider used when dragging in non-continuous layout mode. */
 934:   protected Component nonContinuousLayoutDivider;
 935: 
 936:   /** The JSplitPane that this UI draws. */
 937:   protected JSplitPane splitPane;
 938: 
 939:   /**
 940:    * Creates a new BasicSplitPaneUI object.
 941:    */
 942:   public BasicSplitPaneUI()
 943:   {
 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:     divider = createDefaultDivider();
 994:     resetLayoutManager();
 995:     nonContinuousLayoutDivider = createDefaultNonContinuousLayoutDivider();
 996:     splitPane.add(divider, JSplitPane.DIVIDER);
 997: 
 998:     // There is no need to add the nonContinuousLayoutDivider
 999:     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
1000:     splitPane.setBackground(defaults.getColor("SplitPane.background"));
1001:     splitPane.setBorder(defaults.getBorder("SplitPane.border"));
1002:     splitPane.setDividerSize(defaults.getInt("SplitPane.dividerSize"));
1003:     splitPane.setOpaque(true);
1004:   }
1005: 
1006:   /**
1007:    * This method uninstalls the defaults and nulls any objects created during
1008:    * install.
1009:    */
1010:   protected void uninstallDefaults()
1011:   {
1012:     layoutManager = null;
1013:     splitPane.remove(divider);
1014:     divider = null;
1015:     nonContinuousLayoutDivider = null;
1016: 
1017:     splitPane.setBackground(null);
1018:     splitPane.setBorder(null);
1019:   }
1020: 
1021:   /**
1022:    * This method installs the listeners needed for this UI to function.
1023:    */
1024:   protected void installListeners()
1025:   {
1026:     propertyChangeListener = createPropertyChangeListener();
1027:     focusListener = createFocusListener();
1028: 
1029:     splitPane.addPropertyChangeListener(propertyChangeListener);
1030:     splitPane.addFocusListener(focusListener);
1031:   }
1032: 
1033:   /**
1034:    * This method uninstalls all listeners registered for the UI.
1035:    */
1036:   protected void uninstallListeners()
1037:   {
1038:     splitPane.removePropertyChangeListener(propertyChangeListener);
1039:     splitPane.removeFocusListener(focusListener);
1040: 
1041:     focusListener = null;
1042:     propertyChangeListener = null;
1043:   }
1044: 
1045:   /**
1046:    * This method installs the keyboard actions for the JSplitPane.
1047:    */
1048:   protected void installKeyboardActions()
1049:   {
1050:     // FIXME: implement.
1051:   }
1052: 
1053:   /**
1054:    * This method reverses the work done in installKeyboardActions.
1055:    */
1056:   protected void uninstallKeyboardActions()
1057:   {
1058:     // FIXME: implement.
1059:   }
1060: 
1061:   /**
1062:    * This method creates a new PropertyChangeListener.
1063:    *
1064:    * @return A new PropertyChangeListener.
1065:    */
1066:   protected PropertyChangeListener createPropertyChangeListener()
1067:   {
1068:     return new PropertyHandler();
1069:   }
1070: 
1071:   /**
1072:    * This method creates a new FocusListener.
1073:    *
1074:    * @return A new FocusListener.
1075:    */
1076:   protected FocusListener createFocusListener()
1077:   {
1078:     return new FocusHandler();
1079:   }
1080: 
1081:   /**
1082:    * This method creates a new ActionListener for up and left key presses.
1083:    *
1084:    * @return A new ActionListener for up and left keys.
1085:    *
1086:    * @deprecated 1.3
1087:    */
1088:   protected ActionListener createKeyboardUpLeftListener()
1089:   {
1090:     return new KeyboardUpLeftHandler();
1091:   }
1092: 
1093:   /**
1094:    * This method creates a new ActionListener for down and right key presses.
1095:    *
1096:    * @return A new ActionListener for down and right keys.
1097:    *
1098:    * @deprecated 1.3
1099:    */
1100:   protected ActionListener createKeyboardDownRightListener()
1101:   {
1102:     return new KeyboardDownRightHandler();
1103:   }
1104: 
1105:   /**
1106:    * This method creates a new ActionListener for home key presses.
1107:    *
1108:    * @return A new ActionListener for home keys.
1109:    *
1110:    * @deprecated
1111:    */
1112:   protected ActionListener createKeyboardHomeListener()
1113:   {
1114:     return new KeyboardHomeHandler();
1115:   }
1116: 
1117:   /**
1118:    * This method creates a new ActionListener for end key presses.i
1119:    *
1120:    * @return A new ActionListener for end keys.
1121:    *
1122:    * @deprecated 1.3
1123:    */
1124:   protected ActionListener createKeyboardEndListener()
1125:   {
1126:     return new KeyboardEndHandler();
1127:   }
1128: 
1129:   /**
1130:    * This method creates a new ActionListener for resize toggle key events.
1131:    *
1132:    * @return A new ActionListener for resize toggle keys.
1133:    *
1134:    * @deprecated 1.3
1135:    */
1136:   protected ActionListener createKeyboardResizeToggleListener()
1137:   {
1138:     return new KeyboardResizeToggleHandler();
1139:   }
1140: 
1141:   /**
1142:    * This method returns the orientation of the JSplitPane.
1143:    *
1144:    * @return The orientation of the JSplitPane.
1145:    */
1146:   public int getOrientation()
1147:   {
1148:     return splitPane.getOrientation();
1149:   }
1150: 
1151:   /**
1152:    * This method sets the orientation of the JSplitPane.
1153:    *
1154:    * @param orientation The new orientation of the JSplitPane.
1155:    */
1156:   public void setOrientation(int orientation)
1157:   {
1158:     splitPane.setOrientation(orientation);
1159:   }
1160: 
1161:   /**
1162:    * This method returns true if the JSplitPane is using continuous layout.
1163:    *
1164:    * @return True if the JSplitPane is using continuous layout.
1165:    */
1166:   public boolean isContinuousLayout()
1167:   {
1168:     return splitPane.isContinuousLayout();
1169:   }
1170: 
1171:   /**
1172:    * This method sets the continuous layout property of the JSplitPane.
1173:    *
1174:    * @param b True if the JsplitPane is to use continuous layout.
1175:    */
1176:   public void setContinuousLayout(boolean b)
1177:   {
1178:     splitPane.setContinuousLayout(b);
1179:   }
1180: 
1181:   /**
1182:    * This method returns the last location the divider was dragged to.
1183:    *
1184:    * @return The last location the divider was dragged to.
1185:    */
1186:   public int getLastDragLocation()
1187:   {
1188:     return lastDragLocation;
1189:   }
1190: 
1191:   /**
1192:    * This method sets the last location the divider was dragged to.
1193:    *
1194:    * @param l The last location the divider was dragged to.
1195:    */
1196:   public void setLastDragLocation(int l)
1197:   {
1198:     lastDragLocation = l;
1199:   }
1200: 
1201:   /**
1202:    * This method returns the BasicSplitPaneDivider that divides this
1203:    * JSplitPane.
1204:    *
1205:    * @return The divider for the JSplitPane.
1206:    */
1207:   public BasicSplitPaneDivider getDivider()
1208:   {
1209:     return divider;
1210:   }
1211: 
1212:   /**
1213:    * This method creates a nonContinuousLayoutDivider for use with the
1214:    * JSplitPane in nonContinousLayout mode. The default divider is a gray
1215:    * Canvas.
1216:    *
1217:    * @return The default nonContinousLayoutDivider.
1218:    */
1219:   protected Component createDefaultNonContinuousLayoutDivider()
1220:   {
1221:     if (nonContinuousLayoutDivider == null)
1222:       {
1223:     nonContinuousLayoutDivider = new Canvas();
1224:     nonContinuousLayoutDivider.setBackground(Color.DARK_GRAY);
1225:       }
1226:     return nonContinuousLayoutDivider;
1227:   }
1228: 
1229:   /**
1230:    * This method sets the component to use as the nonContinuousLayoutDivider.
1231:    *
1232:    * @param newDivider The component to use as the nonContinuousLayoutDivider.
1233:    */
1234:   protected void setNonContinuousLayoutDivider(Component newDivider)
1235:   {
1236:     setNonContinuousLayoutDivider(newDivider, true);
1237:   }
1238: 
1239:   /**
1240:    * This method sets the component to use as the nonContinuousLayoutDivider.
1241:    *
1242:    * @param newDivider The component to use as the nonContinuousLayoutDivider.
1243:    * @param rememberSizes FIXME: document.
1244:    */
1245:   protected void setNonContinuousLayoutDivider(Component newDivider,
1246:                                                boolean rememberSizes)
1247:   {
1248:     // FIXME: use rememberSizes for something
1249:     nonContinuousLayoutDivider = newDivider;
1250:   }
1251: 
1252:   /**
1253:    * This method returns the nonContinuousLayoutDivider.
1254:    *
1255:    * @return The nonContinuousLayoutDivider.
1256:    */
1257:   public Component getNonContinuousLayoutDivider()
1258:   {
1259:     return nonContinuousLayoutDivider;
1260:   }
1261: 
1262:   /**
1263:    * This method returns the JSplitPane that this BasicSplitPaneUI draws.
1264:    *
1265:    * @return The JSplitPane.
1266:    */
1267:   public JSplitPane getSplitPane()
1268:   {
1269:     return splitPane;
1270:   }
1271: 
1272:   /**
1273:    * This method creates the divider used normally with the JSplitPane.
1274:    *
1275:    * @return The default divider.
1276:    */
1277:   public BasicSplitPaneDivider createDefaultDivider()
1278:   {
1279:     if (divider == null)
1280:       divider = new BasicSplitPaneDivider(this);
1281:     return divider;
1282:   }
1283: 
1284:   /**
1285:    * This method is called when JSplitPane's resetToPreferredSizes is called.
1286:    * It resets the sizes of all components in the JSplitPane.
1287:    *
1288:    * @param jc The JSplitPane to reset.
1289:    */
1290:   public void resetToPreferredSizes(JSplitPane jc)
1291:   {
1292:     layoutManager.resetToPreferredSizes();
1293:   }
1294: 
1295:   /**
1296:    * This method sets the location of the divider.
1297:    *
1298:    * @param jc The JSplitPane to set the divider location in.
1299:    * @param location The new location of the divider.
1300:    */
1301:   public void setDividerLocation(JSplitPane jc, int location)
1302:   {
1303:     setLastDragLocation(getDividerLocation(splitPane));
1304:     splitPane.setLastDividerLocation(getDividerLocation(splitPane));
1305:     int[] tmpSizes = layoutManager.getSizes();
1306:     tmpSizes[0] = location
1307:                   - layoutManager.getInitialLocation(splitPane.getInsets());
1308:     tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(),
1309:                                                  splitPane.getInsets())
1310:                   - tmpSizes[0] - tmpSizes[1];
1311: 
1312:     layoutManager.setSizes(tmpSizes);
1313:     splitPane.revalidate();
1314:     splitPane.repaint();
1315:   }
1316: 
1317:   /**
1318:    * This method returns the location of the divider.
1319:    *
1320:    * @param jc The JSplitPane to retrieve the location for.
1321:    *
1322:    * @return The location of the divider.
1323:    */
1324:   public int getDividerLocation(JSplitPane jc)
1325:   {
1326:     return layoutManager.sizes[0]
1327:            + layoutManager.getInitialLocation(splitPane.getInsets());
1328:   }
1329: 
1330:   /**
1331:    * This method returns the smallest value possible for the location of the
1332:    * divider.
1333:    *
1334:    * @param jc The JSplitPane.
1335:    *
1336:    * @return The minimum divider location.
1337:    */
1338:   public int getMinimumDividerLocation(JSplitPane jc)
1339:   {
1340:     int value = layoutManager.getInitialLocation(jc.getInsets());
1341:     if (layoutManager.components[0] != null)
1342:       value += layoutManager.minimumSizeOfComponent(0);
1343:     return value;
1344:   }
1345: 
1346:   /**
1347:    * This method returns the largest value possible for the location of the
1348:    * divider.
1349:    *
1350:    * @param jc The JSplitPane.
1351:    *
1352:    * @return The maximum divider location.
1353:    */
1354:   public int getMaximumDividerLocation(JSplitPane jc)
1355:   {
1356:     int value = layoutManager.getInitialLocation(jc.getInsets())
1357:                 + layoutManager.getAvailableSize(jc.getSize(), jc.getInsets())
1358:                 - splitPane.getDividerSize();
1359:     if (layoutManager.components[1] != null)
1360:       value -= layoutManager.minimumSizeOfComponent(1);
1361:     return value;
1362:   }
1363: 
1364:   /**
1365:    * This method is called after the children of the JSplitPane are painted.
1366:    *
1367:    * @param jc The JSplitPane.
1368:    * @param g The Graphics object to paint with.
1369:    */
1370:   public void finishedPaintingChildren(JSplitPane jc, Graphics g)
1371:   {
1372:     if (! splitPane.isContinuousLayout() && nonContinuousLayoutDivider != null
1373:         && nonContinuousLayoutDivider.isVisible())
1374:       javax.swing.SwingUtilities.paintComponent(g, nonContinuousLayoutDivider,
1375:                                                 null,
1376:                                                 nonContinuousLayoutDivider
1377:                                                 .getBounds());
1378:   }
1379: 
1380:   /**
1381:    * This method is called to paint the JSplitPane.
1382:    *
1383:    * @param g The Graphics object to paint with.
1384:    * @param jc The JSplitPane to paint.
1385:    */
1386:   public void paint(Graphics g, JComponent jc)
1387:   {
1388:   }
1389: 
1390:   /**
1391:    * This method returns the preferred size of the JSplitPane.
1392:    *
1393:    * @param jc The JSplitPane.
1394:    *
1395:    * @return The preferred size of the JSplitPane.
1396:    */
1397:   public Dimension getPreferredSize(JComponent jc)
1398:   {
1399:     return layoutManager.preferredLayoutSize((Container) jc);
1400:   }
1401: 
1402:   /**
1403:    * This method returns the minimum size of the JSplitPane.
1404:    *
1405:    * @param jc The JSplitPane.
1406:    *
1407:    * @return The minimum size of the JSplitPane.
1408:    */
1409:   public Dimension getMinimumSize(JComponent jc)
1410:   {
1411:     return layoutManager.minimumLayoutSize((Container) jc);
1412:   }
1413: 
1414:   /**
1415:    * This method returns the maximum size of the JSplitPane.
1416:    *
1417:    * @param jc The JSplitPane.
1418:    *
1419:    * @return The maximum size of the JSplitPane.
1420:    */
1421:   public Dimension getMaximumSize(JComponent jc)
1422:   {
1423:     return layoutManager.maximumLayoutSize((Container) jc);
1424:   }
1425: 
1426:   /**
1427:    * This method returns the border insets of the current border.
1428:    *
1429:    * @param jc The JSplitPane.
1430:    *
1431:    * @return The current border insets.
1432:    */
1433:   public Insets getInsets(JComponent jc)
1434:   {
1435:     return splitPane.getBorder().getBorderInsets(splitPane);
1436:   }
1437: 
1438:   /**
1439:    * This method resets the current layout manager. The type of layout manager
1440:    * is dependent on the current orientation.
1441:    */
1442:   protected void resetLayoutManager()
1443:   {
1444:     if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT)
1445:       layoutManager = new BasicHorizontalLayoutManager();
1446:     else
1447:       layoutManager = new BasicVerticalLayoutManager();
1448:     getSplitPane().setLayout(layoutManager);
1449:     layoutManager.updateComponents();
1450: 
1451:     // invalidating by itself does not invalidate the layout.
1452:     getSplitPane().revalidate();
1453:   }
1454: 
1455:   /**
1456:    * This method is called when dragging starts. It resets lastDragLocation
1457:    * and dividerSize.
1458:    */
1459:   protected void startDragging()
1460:   {
1461:     dividerSize = divider.getDividerSize();
1462:     setLastDragLocation(-1);
1463: 
1464:     if (! splitPane.getLeftComponent().isLightweight()
1465:         || ! splitPane.getRightComponent().isLightweight())
1466:       draggingHW = true;
1467: 
1468:     if (splitPane.isContinuousLayout())
1469:       nonContinuousLayoutDivider.setVisible(false);
1470:     else
1471:       {
1472:     nonContinuousLayoutDivider.setVisible(true);
1473:     nonContinuousLayoutDivider.setBounds(divider.getBounds());
1474:       }
1475:     splitPane.revalidate();
1476:     splitPane.repaint();
1477:   }
1478: 
1479:   /**
1480:    * This method is called whenever the divider is dragged. If the JSplitPane
1481:    * is in continuousLayout mode, the divider needs to be moved and the
1482:    * JSplitPane needs to be laid out.
1483:    *
1484:    * @param location The new location of the divider.
1485:    */
1486:   protected void dragDividerTo(int location)
1487:   {
1488:     location = validLocation(location);
1489:     if (beginDragDividerLocation == -1)
1490:       beginDragDividerLocation = location;
1491: 
1492:     if (splitPane.isContinuousLayout())
1493:       splitPane.setDividerLocation(location);
1494:     else
1495:       {
1496:     Point p = nonContinuousLayoutDivider.getLocation();
1497:     if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT)
1498:       p.x = location;
1499:     else
1500:       p.y = location;
1501:     nonContinuousLayoutDivider.setLocation(p);
1502:       }
1503:     setLastDragLocation(location);
1504:     splitPane.repaint();
1505:   }
1506: 
1507:   /**
1508:    * This method is called when the dragging is finished.
1509:    *
1510:    * @param location The location where the drag finished.
1511:    */
1512:   protected void finishDraggingTo(int location)
1513:   {
1514:     if (nonContinuousLayoutDivider != null)
1515:       nonContinuousLayoutDivider.setVisible(false);
1516:     draggingHW = false;
1517:     location = validLocation(location);
1518:     dragDividerTo(location);
1519:     splitPane.setDividerLocation(location);
1520:     splitPane.setLastDividerLocation(beginDragDividerLocation);
1521:     beginDragDividerLocation = -1;
1522:     splitPane.repaint();
1523:   }
1524: 
1525:   /**
1526:    * This method returns the width of one of the sides of the divider's border.
1527:    *
1528:    * @return The width of one side of the divider's border.
1529:    *
1530:    * @deprecated 1.3
1531:    */
1532:   protected int getDividerBorderSize()
1533:   {
1534:     if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT)
1535:       return divider.getBorder().getBorderInsets(divider).left;
1536:     else
1537:       return divider.getBorder().getBorderInsets(divider).top;
1538:   }
1539: 
1540:   /**
1541:    * This is a helper method that returns a valid location for the divider
1542:    * when dragging.
1543:    *
1544:    * @param location The location to check.
1545:    *
1546:    * @return A valid location.
1547:    */
1548:   private int validLocation(int location)
1549:   {
1550:     if (location < getMinimumDividerLocation(splitPane))
1551:       return getMinimumDividerLocation(splitPane);
1552:     if (location > getMaximumDividerLocation(splitPane))
1553:       return getMaximumDividerLocation(splitPane);
1554:     return location;
1555:   }
1556: }