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.LookAndFeel;
  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:       c.setBounds(x, y, w, h);
 641:     }
 642: 
 643:     /**
 644:      * This method returns the minimum height of the component at the given
 645:      * index.
 646:      *
 647:      * @param index The index of the component to check.
 648:      *
 649:      * @return The minimum height of the given component.
 650:      */
 651:     int minimumSizeOfComponent(int index)
 652:     {
 653:       Dimension dims = components[index].getMinimumSize();
 654:       if (dims != null)
 655:         return dims.height;
 656:       else
 657:         return 0;
 658:     }
 659:   }
 660: 
 661:   /**
 662:    * This class handles FocusEvents from the JComponent.
 663:    *
 664:    * @specnote Apparently this class was intended to be protected,
 665:    *           but was made public by a compiler bug and is now
 666:    *           public for compatibility.
 667:    */
 668:   public class FocusHandler extends FocusAdapter
 669:   {
 670:     /**
 671:      * This method is called when the JSplitPane gains focus.
 672:      *
 673:      * @param ev The FocusEvent.
 674:      */
 675:     public void focusGained(FocusEvent ev)
 676:     {
 677:       // FIXME: implement.
 678:     }
 679: 
 680:     /**
 681:      * This method is called when the JSplitPane loses focus.
 682:      *
 683:      * @param ev The FocusEvent.
 684:      */
 685:     public void focusLost(FocusEvent ev)
 686:     {
 687:       // FIXME: implement.
 688:     }
 689:   }
 690: 
 691:   /**
 692:    * This is a deprecated class. It is supposed to be used for handling down
 693:    * and right key presses.
 694:    *
 695:    * @specnote Apparently this class was intended to be protected,
 696:    *           but was made public by a compiler bug and is now
 697:    *           public for compatibility.
 698:    */
 699:   public class KeyboardDownRightHandler implements ActionListener
 700:   {
 701:     /**
 702:      * This method is called when the down or right keys are pressed.
 703:      *
 704:      * @param ev The ActionEvent
 705:      */
 706:     public void actionPerformed(ActionEvent ev)
 707:     {
 708:       // FIXME: implement.
 709:     }
 710:   }
 711: 
 712:   /**
 713:    * This is a deprecated class. It is supposed to be used for handling end
 714:    * key presses.
 715:    *
 716:    * @specnote Apparently this class was intended to be protected,
 717:    *           but was made public by a compiler bug and is now
 718:    *           public for compatibility.
 719:    */
 720:   public class KeyboardEndHandler implements ActionListener
 721:   {
 722:     /**
 723:      * This method is called when the end key is pressed.
 724:      *
 725:      * @param ev The ActionEvent.
 726:      */
 727:     public void actionPerformed(ActionEvent ev)
 728:     {
 729:       // FIXME: implement.
 730:     }
 731:   }
 732: 
 733:   /**
 734:    * This is a deprecated class. It is supposed to be used for handling home
 735:    * key presses.
 736:    *
 737:    * @specnote Apparently this class was intended to be protected,
 738:    *           but was made public by a compiler bug and is now
 739:    *           public for compatibility.
 740:    */
 741:   public class KeyboardHomeHandler implements ActionListener
 742:   {
 743:     /**
 744:      * This method is called when the home key is pressed.
 745:      *
 746:      * @param ev The ActionEvent.
 747:      */
 748:     public void actionPerformed(ActionEvent ev)
 749:     {
 750:       // FIXME: implement.
 751:     }
 752:   }
 753: 
 754:   /**
 755:    * This is a deprecated class. It is supposed to be used for handling resize
 756:    * toggles.
 757:    *
 758:    * @specnote Apparently this class was intended to be protected,
 759:    *           but was made public by a compiler bug and is now
 760:    *           public for compatibility.
 761:    */
 762:   public class KeyboardResizeToggleHandler implements ActionListener
 763:   {
 764:     /**
 765:      * This method is called when a resize is toggled.
 766:      *
 767:      * @param ev The ActionEvent.
 768:      */
 769:     public void actionPerformed(ActionEvent ev)
 770:     {
 771:       // FIXME: implement.
 772:     }
 773:   }
 774: 
 775:   /**
 776:    * This is a deprecated class. It is supposed to be used for handler up and
 777:    * left key presses.
 778:    *
 779:    * @specnote Apparently this class was intended to be protected,
 780:    *           but was made public by a compiler bug and is now
 781:    *           public for compatibility.
 782:    */
 783:   public class KeyboardUpLeftHandler implements ActionListener
 784:   {
 785:     /**
 786:      * This method is called when the left or up keys are pressed.
 787:      *
 788:      * @param ev The ActionEvent.
 789:      */
 790:     public void actionPerformed(ActionEvent ev)
 791:     {
 792:       // FIXME: implement.
 793:     }
 794:   }
 795: 
 796:   /**
 797:    * This helper class handles PropertyChangeEvents from the JSplitPane. When
 798:    * a property changes, this will update the UI accordingly.
 799:    *
 800:    * @specnote Apparently this class was intended to be protected,
 801:    *           but was made public by a compiler bug and is now
 802:    *           public for compatibility.
 803:    */
 804:   public class PropertyHandler implements PropertyChangeListener
 805:   {
 806:     /**
 807:      * This method is called whenever one of the JSplitPane's properties
 808:      * change.
 809:      *
 810:      * @param e DOCUMENT ME!
 811:      */
 812:     public void propertyChange(PropertyChangeEvent e)
 813:     {
 814:       if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY))
 815:         {
 816:           int newSize = splitPane.getDividerSize();
 817:           int[] tmpSizes = layoutManager.getSizes();
 818:           dividerSize = tmpSizes[2];
 819:           int newSpace = newSize - tmpSizes[2];
 820:           tmpSizes[2] = newSize;
 821: 
 822:           tmpSizes[0] += newSpace / 2;
 823:           tmpSizes[1] += newSpace / 2;
 824:       
 825:           layoutManager.setSizes(tmpSizes);
 826:         }
 827:       else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY))
 828:         {
 829:           int max = layoutManager.getAvailableSize(splitPane.getSize(),
 830:                                                    splitPane.getInsets());
 831:           int dividerLoc = getDividerLocation(splitPane);
 832:           double prop = ((double) dividerLoc) / max;
 833: 
 834:           resetLayoutManager();
 835:           if (prop <= 1 && prop >= 0)
 836:             splitPane.setDividerLocation(prop);
 837:         }
 838:       layoutManager.layoutContainer(splitPane);
 839:       splitPane.repaint();
 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:   /**
 937:    * Creates a new BasicSplitPaneUI object.
 938:    */
 939:   public BasicSplitPaneUI()
 940:   {
 941:     // Nothing to do here.
 942:   }
 943: 
 944:   /**
 945:    * This method creates a new BasicSplitPaneUI for the given JComponent.
 946:    *
 947:    * @param x The JComponent to create a UI for.
 948:    *
 949:    * @return A new BasicSplitPaneUI.
 950:    */
 951:   public static ComponentUI createUI(JComponent x)
 952:   {
 953:     return new BasicSplitPaneUI();
 954:   }
 955: 
 956:   /**
 957:    * This method installs the BasicSplitPaneUI for the given JComponent.
 958:    *
 959:    * @param c The JComponent to install the UI for.
 960:    */
 961:   public void installUI(JComponent c)
 962:   {
 963:     if (c instanceof JSplitPane)
 964:       {
 965:         splitPane = (JSplitPane) c;
 966:         installDefaults();
 967:         installListeners();
 968:         installKeyboardActions();
 969:       }
 970:   }
 971: 
 972:   /**
 973:    * This method uninstalls the BasicSplitPaneUI for the given JComponent.
 974:    *
 975:    * @param c The JComponent to uninstall the UI for.
 976:    */
 977:   public void uninstallUI(JComponent c)
 978:   {
 979:     uninstallKeyboardActions();
 980:     uninstallListeners();
 981:     uninstallDefaults();
 982: 
 983:     splitPane = null;
 984:   }
 985: 
 986:   /**
 987:    * This method installs the defaults given by the Look and Feel.
 988:    */
 989:   protected void installDefaults()
 990:   {
 991:     LookAndFeel.installColors(splitPane, "SplitPane.background",
 992:                               "SplitPane.foreground");
 993:     LookAndFeel.installBorder(splitPane, "SplitPane.border");
 994:     divider = createDefaultDivider();
 995:     resetLayoutManager();
 996:     nonContinuousLayoutDivider = createDefaultNonContinuousLayoutDivider();
 997:     splitPane.add(divider, JSplitPane.DIVIDER);
 998: 
 999:     // There is no need to add the nonContinuousLayoutDivider
1000:     splitPane.setDividerSize(UIManager.getInt("SplitPane.dividerSize"));
1001:     splitPane.setOpaque(true);
1002:   }
1003: 
1004:   /**
1005:    * This method uninstalls the defaults and nulls any objects created during
1006:    * install.
1007:    */
1008:   protected void uninstallDefaults()
1009:   {
1010:     layoutManager = null;
1011:     splitPane.remove(divider);
1012:     divider = null;
1013:     nonContinuousLayoutDivider = null;
1014: 
1015:     splitPane.setBackground(null);
1016:     splitPane.setBorder(null);
1017:   }
1018: 
1019:   /**
1020:    * This method installs the listeners needed for this UI to function.
1021:    */
1022:   protected void installListeners()
1023:   {
1024:     propertyChangeListener = createPropertyChangeListener();
1025:     focusListener = createFocusListener();
1026: 
1027:     splitPane.addPropertyChangeListener(propertyChangeListener);
1028:     splitPane.addFocusListener(focusListener);
1029:   }
1030: 
1031:   /**
1032:    * This method uninstalls all listeners registered for the UI.
1033:    */
1034:   protected void uninstallListeners()
1035:   {
1036:     splitPane.removePropertyChangeListener(propertyChangeListener);
1037:     splitPane.removeFocusListener(focusListener);
1038: 
1039:     focusListener = null;
1040:     propertyChangeListener = null;
1041:   }
1042: 
1043:   /**
1044:    * This method installs the keyboard actions for the JSplitPane.
1045:    */
1046:   protected void installKeyboardActions()
1047:   {
1048:     // FIXME: implement.
1049:   }
1050: 
1051:   /**
1052:    * This method reverses the work done in installKeyboardActions.
1053:    */
1054:   protected void uninstallKeyboardActions()
1055:   {
1056:     // FIXME: implement.
1057:   }
1058: 
1059:   /**
1060:    * This method creates a new PropertyChangeListener.
1061:    *
1062:    * @return A new PropertyChangeListener.
1063:    */
1064:   protected PropertyChangeListener createPropertyChangeListener()
1065:   {
1066:     return new PropertyHandler();
1067:   }
1068: 
1069:   /**
1070:    * This method creates a new FocusListener.
1071:    *
1072:    * @return A new FocusListener.
1073:    */
1074:   protected FocusListener createFocusListener()
1075:   {
1076:     return new FocusHandler();
1077:   }
1078: 
1079:   /**
1080:    * This method creates a new ActionListener for up and left key presses.
1081:    *
1082:    * @return A new ActionListener for up and left keys.
1083:    *
1084:    * @deprecated 1.3
1085:    */
1086:   protected ActionListener createKeyboardUpLeftListener()
1087:   {
1088:     return new KeyboardUpLeftHandler();
1089:   }
1090: 
1091:   /**
1092:    * This method creates a new ActionListener for down and right key presses.
1093:    *
1094:    * @return A new ActionListener for down and right keys.
1095:    *
1096:    * @deprecated 1.3
1097:    */
1098:   protected ActionListener createKeyboardDownRightListener()
1099:   {
1100:     return new KeyboardDownRightHandler();
1101:   }
1102: 
1103:   /**
1104:    * This method creates a new ActionListener for home key presses.
1105:    *
1106:    * @return A new ActionListener for home keys.
1107:    *
1108:    * @deprecated
1109:    */
1110:   protected ActionListener createKeyboardHomeListener()
1111:   {
1112:     return new KeyboardHomeHandler();
1113:   }
1114: 
1115:   /**
1116:    * This method creates a new ActionListener for end key presses.i
1117:    *
1118:    * @return A new ActionListener for end keys.
1119:    *
1120:    * @deprecated 1.3
1121:    */
1122:   protected ActionListener createKeyboardEndListener()
1123:   {
1124:     return new KeyboardEndHandler();
1125:   }
1126: 
1127:   /**
1128:    * This method creates a new ActionListener for resize toggle key events.
1129:    *
1130:    * @return A new ActionListener for resize toggle keys.
1131:    *
1132:    * @deprecated 1.3
1133:    */
1134:   protected ActionListener createKeyboardResizeToggleListener()
1135:   {
1136:     return new KeyboardResizeToggleHandler();
1137:   }
1138: 
1139:   /**
1140:    * This method returns the orientation of the JSplitPane.
1141:    *
1142:    * @return The orientation of the JSplitPane.
1143:    */
1144:   public int getOrientation()
1145:   {
1146:     return splitPane.getOrientation();
1147:   }
1148: 
1149:   /**
1150:    * This method sets the orientation of the JSplitPane.
1151:    *
1152:    * @param orientation The new orientation of the JSplitPane.
1153:    */
1154:   public void setOrientation(int orientation)
1155:   {
1156:     splitPane.setOrientation(orientation);
1157:   }
1158: 
1159:   /**
1160:    * This method returns true if the JSplitPane is using continuous layout.
1161:    *
1162:    * @return True if the JSplitPane is using continuous layout.
1163:    */
1164:   public boolean isContinuousLayout()
1165:   {
1166:     return splitPane.isContinuousLayout();
1167:   }
1168: 
1169:   /**
1170:    * This method sets the continuous layout property of the JSplitPane.
1171:    *
1172:    * @param b True if the JsplitPane is to use continuous layout.
1173:    */
1174:   public void setContinuousLayout(boolean b)
1175:   {
1176:     splitPane.setContinuousLayout(b);
1177:   }
1178: 
1179:   /**
1180:    * This method returns the last location the divider was dragged to.
1181:    *
1182:    * @return The last location the divider was dragged to.
1183:    */
1184:   public int getLastDragLocation()
1185:   {
1186:     return lastDragLocation;
1187:   }
1188: 
1189:   /**
1190:    * This method sets the last location the divider was dragged to.
1191:    *
1192:    * @param l The last location the divider was dragged to.
1193:    */
1194:   public void setLastDragLocation(int l)
1195:   {
1196:     lastDragLocation = l;
1197:   }
1198: 
1199:   /**
1200:    * This method returns the BasicSplitPaneDivider that divides this
1201:    * JSplitPane.
1202:    *
1203:    * @return The divider for the JSplitPane.
1204:    */
1205:   public BasicSplitPaneDivider getDivider()
1206:   {
1207:     return divider;
1208:   }
1209: 
1210:   /**
1211:    * This method creates a nonContinuousLayoutDivider for use with the
1212:    * JSplitPane in nonContinousLayout mode. The default divider is a gray
1213:    * Canvas.
1214:    *
1215:    * @return The default nonContinousLayoutDivider.
1216:    */
1217:   protected Component createDefaultNonContinuousLayoutDivider()
1218:   {
1219:     if (nonContinuousLayoutDivider == null)
1220:       {
1221:         nonContinuousLayoutDivider = new Canvas();
1222:         nonContinuousLayoutDivider.setBackground(Color.DARK_GRAY);
1223:       }
1224:     return nonContinuousLayoutDivider;
1225:   }
1226: 
1227:   /**
1228:    * This method sets the component to use as the nonContinuousLayoutDivider.
1229:    *
1230:    * @param newDivider The component to use as the nonContinuousLayoutDivider.
1231:    */
1232:   protected void setNonContinuousLayoutDivider(Component newDivider)
1233:   {
1234:     setNonContinuousLayoutDivider(newDivider, true);
1235:   }
1236: 
1237:   /**
1238:    * This method sets the component to use as the nonContinuousLayoutDivider.
1239:    *
1240:    * @param newDivider The component to use as the nonContinuousLayoutDivider.
1241:    * @param rememberSizes FIXME: document.
1242:    */
1243:   protected void setNonContinuousLayoutDivider(Component newDivider,
1244:                                                boolean rememberSizes)
1245:   {
1246:     // FIXME: use rememberSizes for something
1247:     nonContinuousLayoutDivider = newDivider;
1248:   }
1249: 
1250:   /**
1251:    * This method returns the nonContinuousLayoutDivider.
1252:    *
1253:    * @return The nonContinuousLayoutDivider.
1254:    */
1255:   public Component getNonContinuousLayoutDivider()
1256:   {
1257:     return nonContinuousLayoutDivider;
1258:   }
1259: 
1260:   /**
1261:    * This method returns the JSplitPane that this BasicSplitPaneUI draws.
1262:    *
1263:    * @return The JSplitPane.
1264:    */
1265:   public JSplitPane getSplitPane()
1266:   {
1267:     return splitPane;
1268:   }
1269: 
1270:   /**
1271:    * This method creates the divider used normally with the JSplitPane.
1272:    *
1273:    * @return The default divider.
1274:    */
1275:   public BasicSplitPaneDivider createDefaultDivider()
1276:   {
1277:     if (divider == null)
1278:       divider = new BasicSplitPaneDivider(this);
1279:     return divider;
1280:   }
1281: 
1282:   /**
1283:    * This method is called when JSplitPane's resetToPreferredSizes is called.
1284:    * It resets the sizes of all components in the JSplitPane.
1285:    *
1286:    * @param jc The JSplitPane to reset.
1287:    */
1288:   public void resetToPreferredSizes(JSplitPane jc)
1289:   {
1290:     layoutManager.resetToPreferredSizes();
1291:   }
1292: 
1293:   /**
1294:    * This method sets the location of the divider.
1295:    *
1296:    * @param jc The JSplitPane to set the divider location in.
1297:    * @param location The new location of the divider.
1298:    */
1299:   public void setDividerLocation(JSplitPane jc, int location)
1300:   {
1301:     location = validLocation(location);
1302:     Container p = jc.getParent();
1303:     Component right = jc.getRightComponent();
1304:     Dimension rightPrefSize = right == null ? new Dimension(0, 0)
1305:                                            : right.getPreferredSize();
1306:     Dimension size = jc.getSize();
1307:     // check if the size has been set for the splitpane
1308:     if (size.width == 0 && size.height == 0)
1309:       size = jc.getPreferredSize();
1310: 
1311:     if (getOrientation() == 0 && location > size.height)
1312:       {
1313:         location = size.height;
1314:         while (p != null)
1315:           {
1316:             p.setSize(p.getWidth(), p.getHeight() + rightPrefSize.height);
1317:             p = p.getParent();
1318:           }
1319:       }
1320:     else if (location > size.width)
1321:       {
1322:         location = size.width;
1323:         while (p != null)
1324:           {
1325:             p.setSize(p.getWidth() + rightPrefSize.width, p.getHeight());
1326:             p = p.getParent();
1327:           }
1328:       }
1329: 
1330:     setLastDragLocation(getDividerLocation(splitPane));
1331:     splitPane.setLastDividerLocation(getDividerLocation(splitPane));
1332:     int[] tmpSizes = layoutManager.getSizes();
1333:     tmpSizes[0] = location
1334:                   - layoutManager.getInitialLocation(splitPane.getInsets());
1335:     tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(),
1336:                                                  splitPane.getInsets())
1337:                   - tmpSizes[0];
1338:     layoutManager.setSizes(tmpSizes);
1339:     splitPane.revalidate();
1340:     splitPane.repaint();
1341:   }
1342: 
1343:   /**
1344:    * This method returns the location of the divider.
1345:    *
1346:    * @param jc The JSplitPane to retrieve the location for.
1347:    *
1348:    * @return The location of the divider.
1349:    */
1350:   public int getDividerLocation(JSplitPane jc)
1351:   {
1352:     return layoutManager.sizes[0]
1353:            + layoutManager.getInitialLocation(splitPane.getInsets());
1354:   }
1355: 
1356:   /**
1357:    * This method returns the smallest value possible for the location of the
1358:    * divider.
1359:    *
1360:    * @param jc The JSplitPane.
1361:    *
1362:    * @return The minimum divider location.
1363:    */
1364:   public int getMinimumDividerLocation(JSplitPane jc)
1365:   {
1366:     int value = layoutManager.getInitialLocation(jc.getInsets());
1367:     if (layoutManager.components[0] != null)
1368:       value -= layoutManager.minimumSizeOfComponent(0);
1369:     return value;
1370:   }
1371: 
1372:   /**
1373:    * This method returns the largest value possible for the location of the
1374:    * divider.
1375:    *
1376:    * @param jc The JSplitPane.
1377:    *
1378:    * @return The maximum divider location.
1379:    */
1380:   public int getMaximumDividerLocation(JSplitPane jc)
1381:   {
1382:     int value = layoutManager.getInitialLocation(jc.getInsets())
1383:                 + layoutManager.getAvailableSize(jc.getSize(), jc.getInsets())
1384:                 - splitPane.getDividerSize();
1385:     if (layoutManager.components[1] != null)
1386:       value -= layoutManager.minimumSizeOfComponent(1);
1387:     return value;
1388:   }
1389: 
1390:   /**
1391:    * This method is called after the children of the JSplitPane are painted.
1392:    *
1393:    * @param jc The JSplitPane.
1394:    * @param g The Graphics object to paint with.
1395:    */
1396:   public void finishedPaintingChildren(JSplitPane jc, Graphics g)
1397:   {
1398:     if (! splitPane.isContinuousLayout() && nonContinuousLayoutDivider != null
1399:         && nonContinuousLayoutDivider.isVisible())
1400:       javax.swing.SwingUtilities.paintComponent(g, nonContinuousLayoutDivider,
1401:                                                 null,
1402:                                                 nonContinuousLayoutDivider
1403:                                                 .getBounds());
1404:   }
1405: 
1406:   /**
1407:    * This method is called to paint the JSplitPane.
1408:    *
1409:    * @param g The Graphics object to paint with.
1410:    * @param jc The JSplitPane to paint.
1411:    */
1412:   public void paint(Graphics g, JComponent jc)
1413:   {
1414:     // TODO: What should be done here?
1415:   }
1416: 
1417:   /**
1418:    * This method returns the preferred size of the JSplitPane.
1419:    *
1420:    * @param jc The JSplitPane.
1421:    *
1422:    * @return The preferred size of the JSplitPane.
1423:    */
1424:   public Dimension getPreferredSize(JComponent jc)
1425:   {
1426:     return layoutManager.preferredLayoutSize((Container) jc);
1427:   }
1428: 
1429:   /**
1430:    * This method returns the minimum size of the JSplitPane.
1431:    *
1432:    * @param jc The JSplitPane.
1433:    *
1434:    * @return The minimum size of the JSplitPane.
1435:    */
1436:   public Dimension getMinimumSize(JComponent jc)
1437:   {
1438:     return layoutManager.minimumLayoutSize((Container) jc);
1439:   }
1440: 
1441:   /**
1442:    * This method returns the maximum size of the JSplitPane.
1443:    *
1444:    * @param jc The JSplitPane.
1445:    *
1446:    * @return The maximum size of the JSplitPane.
1447:    */
1448:   public Dimension getMaximumSize(JComponent jc)
1449:   {
1450:     return layoutManager.maximumLayoutSize((Container) jc);
1451:   }
1452: 
1453:   /**
1454:    * This method returns the border insets of the current border.
1455:    *
1456:    * @param jc The JSplitPane.
1457:    *
1458:    * @return The current border insets.
1459:    */
1460:   public Insets getInsets(JComponent jc)
1461:   {
1462:     return splitPane.getBorder().getBorderInsets(splitPane);
1463:   }
1464: 
1465:   /**
1466:    * This method resets the current layout manager. The type of layout manager
1467:    * is dependent on the current orientation.
1468:    */
1469:   protected void resetLayoutManager()
1470:   {
1471:     if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT)
1472:       layoutManager = new BasicHorizontalLayoutManager();
1473:     else
1474:       layoutManager = new BasicVerticalLayoutManager();
1475:     getSplitPane().setLayout(layoutManager);
1476:     layoutManager.updateComponents();
1477: 
1478:     // invalidating by itself does not invalidate the layout.
1479:     getSplitPane().revalidate();
1480:   }
1481: 
1482:   /**
1483:    * This method is called when dragging starts. It resets lastDragLocation
1484:    * and dividerSize.
1485:    */
1486:   protected void startDragging()
1487:   {
1488:     Component left = splitPane.getLeftComponent();
1489:     Component right = splitPane.getRightComponent();
1490:     dividerSize = divider.getDividerSize();
1491:     setLastDragLocation(-1);
1492: 
1493:     if ((left != null && !left.isLightweight())
1494:         || (right != null && !right.isLightweight()))
1495:       draggingHW = true;
1496: 
1497:     if (splitPane.isContinuousLayout())
1498:       nonContinuousLayoutDivider.setVisible(false);
1499:     else
1500:       {
1501:         nonContinuousLayoutDivider.setVisible(true);
1502:         nonContinuousLayoutDivider.setBounds(divider.getBounds());
1503:       }
1504:     splitPane.revalidate();
1505:     splitPane.repaint();
1506:   }
1507: 
1508:   /**
1509:    * This method is called whenever the divider is dragged. If the JSplitPane
1510:    * is in continuousLayout mode, the divider needs to be moved and the
1511:    * JSplitPane needs to be laid out.
1512:    *
1513:    * @param location The new location of the divider.
1514:    */
1515:   protected void dragDividerTo(int location)
1516:   {
1517:     location = validLocation(location);
1518:     if (beginDragDividerLocation == -1)
1519:       beginDragDividerLocation = location;
1520: 
1521:     if (splitPane.isContinuousLayout())
1522:       splitPane.setDividerLocation(location);
1523:     else
1524:       {
1525:         Point p = nonContinuousLayoutDivider.getLocation();
1526:         if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT)
1527:           p.x = location;
1528:         else
1529:           p.y = location;
1530:         nonContinuousLayoutDivider.setLocation(p);
1531:       }
1532:     setLastDragLocation(location);
1533:     splitPane.repaint();
1534:   }
1535: 
1536:   /**
1537:    * This method is called when the dragging is finished.
1538:    *
1539:    * @param location The location where the drag finished.
1540:    */
1541:   protected void finishDraggingTo(int location)
1542:   {
1543:     if (nonContinuousLayoutDivider != null)
1544:       nonContinuousLayoutDivider.setVisible(false);
1545:     draggingHW = false;
1546:     location = validLocation(location);
1547:     dragDividerTo(location);
1548:     splitPane.setDividerLocation(location);
1549:     splitPane.setLastDividerLocation(beginDragDividerLocation);
1550:     beginDragDividerLocation = -1;
1551:     splitPane.repaint();
1552:   }
1553: 
1554:   /**
1555:    * This method returns the width of one of the sides of the divider's border.
1556:    *
1557:    * @return The width of one side of the divider's border.
1558:    *
1559:    * @deprecated 1.3
1560:    */
1561:   protected int getDividerBorderSize()
1562:   {
1563:     if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT)
1564:       return divider.getBorder().getBorderInsets(divider).left;
1565:     else
1566:       return divider.getBorder().getBorderInsets(divider).top;
1567:   }
1568: 
1569:   /**
1570:    * This is a helper method that returns a valid location for the divider
1571:    * when dragging.
1572:    *
1573:    * @param location The location to check.
1574:    *
1575:    * @return A valid location.
1576:    */
1577:   private int validLocation(int location)
1578:   {
1579:     int min = getMinimumDividerLocation(splitPane);
1580:     int max = getMaximumDividerLocation(splitPane);
1581:     if (min > 0 && location < min)
1582:       return min;
1583:     if (max > 0 && location > max)
1584:       return max;
1585:     return location;
1586:   }
1587: }