mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1078 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1078 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* BasicSplitPaneDivider.java --
 | |
|    Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| 
 | |
| package javax.swing.plaf.basic;
 | |
| 
 | |
| import java.awt.Color;
 | |
| import java.awt.Component;
 | |
| import java.awt.Container;
 | |
| import java.awt.Dimension;
 | |
| import java.awt.Graphics;
 | |
| import java.awt.Insets;
 | |
| import java.awt.LayoutManager;
 | |
| import java.awt.event.ActionEvent;
 | |
| import java.awt.event.ActionListener;
 | |
| import java.awt.event.MouseAdapter;
 | |
| import java.awt.event.MouseEvent;
 | |
| import java.awt.event.MouseMotionListener;
 | |
| import java.beans.PropertyChangeEvent;
 | |
| import java.beans.PropertyChangeListener;
 | |
| 
 | |
| import javax.swing.JButton;
 | |
| import javax.swing.JSplitPane;
 | |
| import javax.swing.UIManager;
 | |
| import javax.swing.border.Border;
 | |
| 
 | |
| /**
 | |
|  * The divider that separates the two parts of a JSplitPane in the Basic look
 | |
|  * and feel.
 | |
|  *
 | |
|  * <p>
 | |
|  * Implementation status: We do not have a real implementation yet. Currently,
 | |
|  * it is mostly a stub to allow compiling other parts of the
 | |
|  * javax.swing.plaf.basic package, although some parts are already
 | |
|  * functional.
 | |
|  * </p>
 | |
|  *
 | |
|  * @author Sascha Brawer (brawer_AT_dandelis.ch)
 | |
|  */
 | |
| public class BasicSplitPaneDivider extends Container
 | |
|   implements PropertyChangeListener
 | |
| {
 | |
|   /**
 | |
|    * The buttons used as one touch buttons.
 | |
|    */
 | |
|   private class BasicOneTouchButton
 | |
|     extends JButton
 | |
|   {
 | |
|     /**
 | |
|      * Denotes a left button.
 | |
|      */
 | |
|     static final int LEFT = 0;
 | |
| 
 | |
|     /**
 | |
|      * Denotes a right button.
 | |
|      */
 | |
|     static final int RIGHT = 1;
 | |
| 
 | |
|     /**
 | |
|      * The x points for the arrow.
 | |
|      */
 | |
|     private int[] xpoints;
 | |
| 
 | |
|     /**
 | |
|      * The y points for the arrow.
 | |
|      */
 | |
|     private int[] ypoints;
 | |
| 
 | |
|     /**
 | |
|      * Either LEFT or RIGHT.
 | |
|      */
 | |
|     private int direction;
 | |
| 
 | |
|     /**
 | |
|      * Creates a new instance.
 | |
|      *
 | |
|      * @param dir either LEFT or RIGHT
 | |
|      */
 | |
|     BasicOneTouchButton(int dir)
 | |
|     {
 | |
|       direction = dir;
 | |
|       xpoints = new int[3];
 | |
|       ypoints = new int[3];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Never allow borders.
 | |
|      */
 | |
|     public void setBorder(Border b)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Never allow focus traversal.
 | |
|      */
 | |
|     public boolean isFocusTraversable()
 | |
|     {
 | |
|       return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Paints the one touch button.
 | |
|      */
 | |
|     public void paint(Graphics g)
 | |
|     {
 | |
|       if (splitPane != null)
 | |
|         {
 | |
|           // Fill background.
 | |
|           g.setColor(splitPane.getBackground());
 | |
|           g.fillRect(0, 0, getWidth(), getHeight());
 | |
| 
 | |
|           // Draw arrow.
 | |
|           int size;
 | |
|           if (direction == LEFT)
 | |
|             {
 | |
|               if (orientation == JSplitPane.VERTICAL_SPLIT)
 | |
|                 {
 | |
|                   size = Math.min(getHeight(), ONE_TOUCH_SIZE);
 | |
|                   xpoints[0] = 0;
 | |
|                   xpoints[1] = size / 2;
 | |
|                   xpoints[2] = size;
 | |
|                   ypoints[0] = size;
 | |
|                   ypoints[1] = 0;
 | |
|                   ypoints[2] = size;
 | |
|                 }
 | |
|               else
 | |
|                 {
 | |
|                   size = Math.min(getWidth(), ONE_TOUCH_SIZE);
 | |
|                   xpoints[0] = size;
 | |
|                   xpoints[1] = 0;
 | |
|                   xpoints[2] = size;
 | |
|                   ypoints[0] = 0;
 | |
|                   ypoints[1] = size / 2;
 | |
|                   ypoints[2] = size;
 | |
|                 }
 | |
|             }
 | |
|           else
 | |
|             {
 | |
|               if (orientation == JSplitPane.VERTICAL_SPLIT)
 | |
|                 {
 | |
|                   size = Math.min(getHeight(), ONE_TOUCH_SIZE);
 | |
|                   xpoints[0] = 0;
 | |
|                   xpoints[1] = size / 2;
 | |
|                   xpoints[2] = size;
 | |
|                   ypoints[0] = 0;
 | |
|                   ypoints[1] = size;
 | |
|                   ypoints[2] = 0;
 | |
|                 }
 | |
|               else
 | |
|                 {
 | |
|                   size = Math.min(getWidth(), ONE_TOUCH_SIZE);
 | |
|                   xpoints[0] = 0;
 | |
|                   xpoints[1] = size;
 | |
|                   xpoints[2] = 0;
 | |
|                   ypoints[0] = 0;
 | |
|                   ypoints[1] = size / 2;
 | |
|                   ypoints[2] = size;
 | |
|                 }
 | |
|             }
 | |
|           g.setColor(Color.BLACK);
 | |
|           g.fillPolygon(xpoints, ypoints, 3);
 | |
|         }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Listens for actions on the one touch buttons.
 | |
|    */
 | |
|   private class OneTouchAction
 | |
|     implements ActionListener
 | |
|   {
 | |
| 
 | |
|     public void actionPerformed(ActionEvent ev)
 | |
|     {
 | |
|       Insets insets = splitPane.getInsets();
 | |
|       int lastLoc = splitPane.getLastDividerLocation();
 | |
|       int currentLoc = splitPaneUI.getDividerLocation(splitPane);
 | |
|       int newLoc;
 | |
| 
 | |
|       if (ev.getSource() == leftButton)
 | |
|         {
 | |
|           if (orientation == JSplitPane.VERTICAL_SPLIT)
 | |
|             {
 | |
|               if (currentLoc
 | |
|                   >= splitPane.getHeight() - insets.bottom - getHeight())
 | |
|                 {
 | |
|                   newLoc = Math.min(splitPane.getMaximumDividerLocation(),
 | |
|                                     lastLoc);
 | |
|                 }
 | |
|               else
 | |
|                 {
 | |
|                   newLoc = insets.top;
 | |
|                 }
 | |
|             }
 | |
|           else
 | |
|             {
 | |
|               if (currentLoc
 | |
|                   >= splitPane.getWidth() - insets.right - getWidth())
 | |
|                 {
 | |
|                   newLoc = Math.min(splitPane.getMaximumDividerLocation(),
 | |
|                                     lastLoc);
 | |
|                 }
 | |
|               else
 | |
|                 {
 | |
|                   newLoc = insets.left;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|       else
 | |
|         {
 | |
|           if (orientation == JSplitPane.VERTICAL_SPLIT)
 | |
|             {
 | |
|               if (currentLoc == insets.top)
 | |
|                 {
 | |
|                   newLoc = Math.min(splitPane.getMaximumDividerLocation(),
 | |
|                                     lastLoc);
 | |
|                 }
 | |
|               else
 | |
|                 {
 | |
|                   newLoc = splitPane.getHeight() - insets.top - getHeight();
 | |
|                 }
 | |
|             }
 | |
|           else
 | |
|             {
 | |
|               if (currentLoc == insets.left)
 | |
|                 {
 | |
|                   newLoc = Math.min(splitPane.getMaximumDividerLocation(),
 | |
|                                     lastLoc);
 | |
|                 }
 | |
|               else
 | |
|                 {
 | |
|                   newLoc = splitPane.getWidth() - insets.left - getWidth();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|       if (currentLoc != newLoc)
 | |
|         {
 | |
|           splitPane.setDividerLocation(newLoc);
 | |
|           splitPane.setLastDividerLocation(currentLoc);
 | |
|         }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Determined using the <code>serialver</code> tool of Apple/Sun JDK 1.3.1
 | |
|    * on MacOS X 10.1.5.
 | |
|    */
 | |
|   static final long serialVersionUID = 1463404307042803342L;
 | |
| 
 | |
|   /**
 | |
|    * The width and height of the little buttons for showing and hiding parts
 | |
|    * of a JSplitPane in a single mouse click.
 | |
|    */
 | |
|   protected static final int ONE_TOUCH_SIZE = 6;
 | |
| 
 | |
|   /** The distance the one touch buttons will sit from the divider's edges. */
 | |
|   protected static final int ONE_TOUCH_OFFSET = 2;
 | |
| 
 | |
|   /**
 | |
|    * An object that performs the tasks associated with an ongoing drag
 | |
|    * operation, or <code>null</code> if the user is currently not dragging
 | |
|    * the divider.
 | |
|    */
 | |
|   protected DragController dragger;
 | |
| 
 | |
|   /**
 | |
|    * The delegate object that is responsible for the UI of the
 | |
|    * <code>JSplitPane</code> that contains this divider.
 | |
|    */
 | |
|   protected BasicSplitPaneUI splitPaneUI;
 | |
| 
 | |
|   /** The thickness of the divider in pixels. */
 | |
|   protected int dividerSize;
 | |
| 
 | |
|   /** A divider that is used for layout purposes. */
 | |
|   protected Component hiddenDivider;
 | |
| 
 | |
|   /** The JSplitPane containing this divider. */
 | |
|   protected JSplitPane splitPane;
 | |
| 
 | |
|   /**
 | |
|    * The listener for handling mouse events from both the divider and the
 | |
|    * containing <code>JSplitPane</code>.
 | |
|    *
 | |
|    * <p>
 | |
|    * The reason for also handling MouseEvents from the containing
 | |
|    * <code>JSplitPane</code> is that users should be able to start a drag
 | |
|    * gesture from inside the JSplitPane, but slightly outisde the divider.
 | |
|    * </p>
 | |
|    */
 | |
|   protected MouseHandler mouseHandler = new MouseHandler();
 | |
| 
 | |
|   /**
 | |
|    * The current orientation of the containing <code>JSplitPane</code>, which
 | |
|    * is either {@link javax.swing.JSplitPane#HORIZONTAL_SPLIT} or {@link
 | |
|    * javax.swing.JSplitPane#VERTICAL_SPLIT}.
 | |
|    */
 | |
|   protected int orientation;
 | |
| 
 | |
|   /**
 | |
|    * The button for showing and hiding the left (or top) component of the
 | |
|    * <code>JSplitPane</code>.
 | |
|    */
 | |
|   protected JButton leftButton;
 | |
| 
 | |
|   /**
 | |
|    * The button for showing and hiding the right (or bottom) component of the
 | |
|    * <code>JSplitPane</code>.
 | |
|    */
 | |
|   protected JButton rightButton;
 | |
| 
 | |
|   /**
 | |
|    * The border of this divider. Typically, this will be an instance of {@link
 | |
|    * javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder}.
 | |
|    *
 | |
|    * @see #getBorder()
 | |
|    * @see #setBorder(javax.swing.border.Border)
 | |
|    */
 | |
|   private Border border;
 | |
| 
 | |
|   // This is not a pixel count.
 | |
|   // This int should be able to take 3 values.
 | |
|   // left (top), middle, right(bottom)
 | |
|   //    0          1          2
 | |
| 
 | |
|   /**
 | |
|    * Keeps track of where the divider should be placed when using one touch
 | |
|    * expand buttons.
 | |
|    * This is package-private to avoid an accessor method.
 | |
|    */
 | |
|   transient int currentDividerLocation = 1;
 | |
| 
 | |
|   /**
 | |
|    * Indicates if the ont touch buttons are laid out centered or at the
 | |
|    * top/left.
 | |
|    *
 | |
|    * Package private to avoid accessor method.
 | |
|    */
 | |
|   boolean centerOneTouchButtons;
 | |
| 
 | |
|   /**
 | |
|    * Constructs a new divider.
 | |
|    *
 | |
|    * @param ui the UI delegate of the enclosing <code>JSplitPane</code>.
 | |
|    */
 | |
|   public BasicSplitPaneDivider(BasicSplitPaneUI ui)
 | |
|   {
 | |
|     setLayout(new DividerLayout());
 | |
|     setBasicSplitPaneUI(ui);
 | |
|     setDividerSize(splitPane.getDividerSize());
 | |
|     centerOneTouchButtons =
 | |
|       UIManager.getBoolean("SplitPane.centerOneTouchButtons");
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the delegate object that is responsible for the UI of the {@link
 | |
|    * javax.swing.JSplitPane} containing this divider.
 | |
|    *
 | |
|    * @param newUI the UI delegate, or <code>null</code> to release the
 | |
|    *        connection to the current delegate.
 | |
|    */
 | |
|   public void setBasicSplitPaneUI(BasicSplitPaneUI newUI)
 | |
|   {
 | |
|     /* Remove the connection to the existing JSplitPane. */
 | |
|     if (splitPane != null)
 | |
|       {
 | |
|         splitPane.removePropertyChangeListener(this);
 | |
|         removeMouseListener(mouseHandler);
 | |
|         removeMouseMotionListener(mouseHandler);
 | |
|         splitPane = null;
 | |
|         hiddenDivider = null;
 | |
|       }
 | |
| 
 | |
|     /* Establish the connection to the new JSplitPane. */
 | |
|     splitPaneUI = newUI;
 | |
|     if (splitPaneUI != null)
 | |
|       splitPane = newUI.getSplitPane();
 | |
|     if (splitPane != null)
 | |
|       {
 | |
|         splitPane.addPropertyChangeListener(this);
 | |
|         addMouseListener(mouseHandler);
 | |
|         addMouseMotionListener(mouseHandler);
 | |
|         hiddenDivider = splitPaneUI.getNonContinuousLayoutDivider();
 | |
|         orientation = splitPane.getOrientation();
 | |
|         if (splitPane.isOneTouchExpandable())
 | |
|           oneTouchExpandableChanged();
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the delegate object that is responsible for the UI of the {@link
 | |
|    * javax.swing.JSplitPane} containing this divider.
 | |
|    *
 | |
|    * @return The UI for the JSplitPane.
 | |
|    */
 | |
|   public BasicSplitPaneUI getBasicSplitPaneUI()
 | |
|   {
 | |
|     return splitPaneUI;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the thickness of the divider.
 | |
|    *
 | |
|    * @param newSize the new width or height in pixels.
 | |
|    */
 | |
|   public void setDividerSize(int newSize)
 | |
|   {
 | |
|     this.dividerSize = newSize;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Retrieves the thickness of the divider.
 | |
|    *
 | |
|    * @return The thickness of the divider.
 | |
|    */
 | |
|   public int getDividerSize()
 | |
|   {
 | |
|     return dividerSize;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the border of this divider.
 | |
|    *
 | |
|    * @param border the new border. Typically, this will be an instance of
 | |
|    *        {@link
 | |
|    *        javax.swing.plaf.basic.BasicBorders.SplitPaneBorder}.
 | |
|    *
 | |
|    * @since 1.3
 | |
|    */
 | |
|   public void setBorder(Border border)
 | |
|   {
 | |
|     if (border != this.border)
 | |
|       {
 | |
|         Border oldValue = this.border;
 | |
|         this.border = border;
 | |
|         firePropertyChange("border", oldValue, border);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Retrieves the border of this divider.
 | |
|    *
 | |
|    * @return the current border, or <code>null</code> if no border has been
 | |
|    *         set.
 | |
|    *
 | |
|    * @since 1.3
 | |
|    */
 | |
|   public Border getBorder()
 | |
|   {
 | |
|     return border;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Retrieves the insets of the divider. If a border has been installed on
 | |
|    * the divider, the result of calling its <code>getBorderInsets</code>
 | |
|    * method is returned. Otherwise, the inherited implementation will be
 | |
|    * invoked.
 | |
|    *
 | |
|    * @see javax.swing.border.Border#getBorderInsets(java.awt.Component)
 | |
|    */
 | |
|   public Insets getInsets()
 | |
|   {
 | |
|     if (border != null)
 | |
|       return border.getBorderInsets(this);
 | |
|     else
 | |
|       return super.getInsets();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the preferred size of this divider, which is
 | |
|    * <code>dividerSize</code> by <code>dividerSize</code> pixels.
 | |
|    *
 | |
|    * @return The preferred size of the divider.
 | |
|    */
 | |
|   public Dimension getPreferredSize()
 | |
|   {
 | |
|     Dimension d;
 | |
|     if (orientation == JSplitPane.HORIZONTAL_SPLIT)
 | |
|       d = new Dimension(getDividerSize(), 1);
 | |
|     else
 | |
|       d = new Dimension(1, getDividerSize());
 | |
|     return d;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the minimal size of this divider, which is
 | |
|    * <code>dividerSize</code> by <code>dividerSize</code> pixels.
 | |
|    *
 | |
|    * @return The minimal size of the divider.
 | |
|    */
 | |
|   public Dimension getMinimumSize()
 | |
|   {
 | |
|     return getPreferredSize();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Processes events from the <code>JSplitPane</code> that contains this
 | |
|    * divider.
 | |
|    *
 | |
|    * @param e The PropertyChangeEvent.
 | |
|    */
 | |
|   public void propertyChange(PropertyChangeEvent e)
 | |
|   {
 | |
|     if (e.getPropertyName().equals(JSplitPane.ONE_TOUCH_EXPANDABLE_PROPERTY))
 | |
|       oneTouchExpandableChanged();
 | |
|     else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY))
 | |
|       {
 | |
|         orientation = splitPane.getOrientation();
 | |
|         invalidate();
 | |
|         if (splitPane != null)
 | |
|           splitPane.revalidate();
 | |
|       }
 | |
|     else if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY))
 | |
|       dividerSize = splitPane.getDividerSize();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Paints the divider by painting its border.
 | |
|    *
 | |
|    * @param g The Graphics Object to paint with.
 | |
|    */
 | |
|   public void paint(Graphics g)
 | |
|   {
 | |
|     Dimension dividerSize;
 | |
| 
 | |
|     super.paint(g);
 | |
|     if (border != null)
 | |
|       {
 | |
|         dividerSize = getSize();
 | |
|         border.paintBorder(this, g, 0, 0, dividerSize.width, dividerSize.height);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Reacts to changes of the <code>oneToughExpandable</code> property of the
 | |
|    * containing <code>JSplitPane</code>.
 | |
|    */
 | |
|   protected void oneTouchExpandableChanged()
 | |
|   {
 | |
|     if (splitPane.isOneTouchExpandable())
 | |
|       {
 | |
|         leftButton = createLeftOneTouchButton();
 | |
|         if (leftButton != null)
 | |
|           leftButton.addActionListener(new OneTouchAction());
 | |
| 
 | |
|         rightButton = createRightOneTouchButton();
 | |
|         if (rightButton != null)
 | |
|           rightButton.addActionListener(new OneTouchAction());
 | |
| 
 | |
|         // Only add them when both are non-null.
 | |
|         if (leftButton != null && rightButton != null)
 | |
|           {
 | |
|             add(leftButton);
 | |
|             add(rightButton);
 | |
|           }
 | |
|       }
 | |
|     invalidate();
 | |
|     if (splitPane != null)
 | |
|       splitPane.revalidate();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a button for showing and hiding the left (or top) part of a
 | |
|    * <code>JSplitPane</code>.
 | |
|    *
 | |
|    * @return The left one touch button.
 | |
|    */
 | |
|   protected JButton createLeftOneTouchButton()
 | |
|   {
 | |
|     JButton button = new BasicOneTouchButton(BasicOneTouchButton.LEFT);
 | |
|     button.setMinimumSize(new Dimension(ONE_TOUCH_SIZE, ONE_TOUCH_SIZE));
 | |
|     button.setRequestFocusEnabled(false);
 | |
|     return button;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a button for showing and hiding the right (or bottom) part of a
 | |
|    * <code>JSplitPane</code>.
 | |
|    *
 | |
|    * @return The right one touch button.
 | |
|    */
 | |
|   protected JButton createRightOneTouchButton()
 | |
|   {
 | |
|     JButton button = new BasicOneTouchButton(BasicOneTouchButton.RIGHT);
 | |
|     button.setMinimumSize(new Dimension(ONE_TOUCH_SIZE, ONE_TOUCH_SIZE));
 | |
|     button.setRequestFocusEnabled(false);
 | |
|     return button;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Prepares the divider for dragging by calling the
 | |
|    * <code>startDragging</code> method of the UI delegate of the enclosing
 | |
|    * <code>JSplitPane</code>.
 | |
|    *
 | |
|    * @see BasicSplitPaneUI#startDragging()
 | |
|    */
 | |
|   protected void prepareForDragging()
 | |
|   {
 | |
|     if (splitPaneUI != null)
 | |
|       splitPaneUI.startDragging();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Drags the divider to a given location by calling the
 | |
|    * <code>dragDividerTo</code> method of the UI delegate of the enclosing
 | |
|    * <code>JSplitPane</code>.
 | |
|    *
 | |
|    * @param location the new location of the divider.
 | |
|    *
 | |
|    * @see BasicSplitPaneUI#dragDividerTo(int location)
 | |
|    */
 | |
|   protected void dragDividerTo(int location)
 | |
|   {
 | |
|     if (splitPaneUI != null)
 | |
|       splitPaneUI.dragDividerTo(location);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Finishes a dragging gesture by calling the <code>finishDraggingTo</code>
 | |
|    * method of the UI delegate of the enclosing <code>JSplitPane</code>.
 | |
|    *
 | |
|    * @param location the new, final location of the divider.
 | |
|    *
 | |
|    * @see BasicSplitPaneUI#finishDraggingTo(int location)
 | |
|    */
 | |
|   protected void finishDraggingTo(int location)
 | |
|   {
 | |
|     if (splitPaneUI != null)
 | |
|       splitPaneUI.finishDraggingTo(location);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This helper method moves the divider to one of the  three locations when
 | |
|    * using one touch expand buttons. Location 0 is the left (or top) most
 | |
|    * location. Location 1 is the middle. Location 2 is the right (or bottom)
 | |
|    * most location.
 | |
|    * This is package-private to avoid an accessor method.
 | |
|    *
 | |
|    * @param locationIndex The location to move to.
 | |
|    */
 | |
|   void moveDividerTo(int locationIndex)
 | |
|   {
 | |
|     Insets insets = splitPane.getInsets();
 | |
|     switch (locationIndex)
 | |
|       {
 | |
|       case 1:
 | |
|         splitPane.setDividerLocation(splitPane.getLastDividerLocation());
 | |
|         break;
 | |
|       case 0:
 | |
|         int top = (orientation == JSplitPane.HORIZONTAL_SPLIT) ? insets.left
 | |
|                                                                : insets.top;
 | |
|         splitPane.setDividerLocation(top);
 | |
|         break;
 | |
|       case 2:
 | |
|         int bottom;
 | |
|         if (orientation == JSplitPane.HORIZONTAL_SPLIT)
 | |
|           bottom = splitPane.getBounds().width - insets.right - dividerSize;
 | |
|         else
 | |
|           bottom = splitPane.getBounds().height - insets.bottom - dividerSize;
 | |
|         splitPane.setDividerLocation(bottom);
 | |
|         break;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * The listener for handling mouse events from both the divider and the
 | |
|    * containing <code>JSplitPane</code>.
 | |
|    *
 | |
|    * <p>
 | |
|    * The reason for also handling MouseEvents from the containing
 | |
|    * <code>JSplitPane</code> is that users should be able to start a drag
 | |
|    * gesture from inside the JSplitPane, but slightly outisde the divider.
 | |
|    * </p>
 | |
|    *
 | |
|    * @author Sascha Brawer (brawer_AT_dandelis.ch)
 | |
|    */
 | |
|   protected class MouseHandler extends MouseAdapter
 | |
|     implements MouseMotionListener
 | |
|   {
 | |
|     /** Keeps track of whether a drag is occurring. */
 | |
|     private transient boolean isDragging;
 | |
| 
 | |
|     /**
 | |
|      * This method is called when the mouse is pressed.
 | |
|      *
 | |
|      * @param e The MouseEvent.
 | |
|      */
 | |
|     public void mousePressed(MouseEvent e)
 | |
|     {
 | |
|       isDragging = true;
 | |
|       currentDividerLocation = 1;
 | |
|       if (orientation == JSplitPane.HORIZONTAL_SPLIT)
 | |
|         dragger = new DragController(e);
 | |
|       else
 | |
|         dragger = new VerticalDragController(e);
 | |
|       prepareForDragging();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method is called when the mouse is released.
 | |
|      *
 | |
|      * @param e The MouseEvent.
 | |
|      */
 | |
|     public void mouseReleased(MouseEvent e)
 | |
|     {
 | |
|       if (isDragging)
 | |
|         dragger.completeDrag(e);
 | |
|       isDragging = false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Repeatedly invoked when the user is dragging the mouse cursor while
 | |
|      * having pressed a mouse button.
 | |
|      *
 | |
|      * @param e The MouseEvent.
 | |
|      */
 | |
|     public void mouseDragged(MouseEvent e)
 | |
|     {
 | |
|       if (dragger != null)
 | |
|         dragger.continueDrag(e);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Repeatedly invoked when the user is dragging the mouse cursor without
 | |
|      * having pressed a mouse button.
 | |
|      *
 | |
|      * @param e The MouseEvent.
 | |
|      */
 | |
|     public void mouseMoved(MouseEvent e)
 | |
|     {
 | |
|       // Do nothing.
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Performs the tasks associated with an ongoing drag operation.
 | |
|    *
 | |
|    * @author Sascha Brawer (brawer_AT_dandelis.ch)
 | |
|    */
 | |
|   protected class DragController
 | |
|   {
 | |
|     /**
 | |
|      * The difference between where the mouse is clicked and the  initial
 | |
|      * divider location.
 | |
|      */
 | |
|     transient int offset;
 | |
| 
 | |
|     /**
 | |
|      * Creates a new DragController object.
 | |
|      *
 | |
|      * @param e The MouseEvent to initialize with.
 | |
|      */
 | |
|     protected DragController(MouseEvent e)
 | |
|     {
 | |
|       offset = e.getX();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method returns true if the divider can move.
 | |
|      *
 | |
|      * @return True if dragging is allowed.
 | |
|      */
 | |
|     protected boolean isValid()
 | |
|     {
 | |
|       // Views can always be resized?
 | |
|       return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns a position for the divider given the MouseEvent.
 | |
|      *
 | |
|      * @param e MouseEvent.
 | |
|      *
 | |
|      * @return The position for the divider to move to.
 | |
|      */
 | |
|     protected int positionForMouseEvent(MouseEvent e)
 | |
|     {
 | |
|       return e.getX() + getX() - offset;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method returns one of the two paramters for the orientation. In
 | |
|      * this case, it returns x.
 | |
|      *
 | |
|      * @param x The x coordinate.
 | |
|      * @param y The y coordinate.
 | |
|      *
 | |
|      * @return The x coordinate.
 | |
|      */
 | |
|     protected int getNeededLocation(int x, int y)
 | |
|     {
 | |
|       return x;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method is called to pass on the drag information to the UI through
 | |
|      * dragDividerTo.
 | |
|      *
 | |
|      * @param newX The x coordinate of the MouseEvent.
 | |
|      * @param newY The y coordinate of the MouseEvent.
 | |
|      */
 | |
|     protected void continueDrag(int newX, int newY)
 | |
|     {
 | |
|       if (isValid())
 | |
|         dragDividerTo(adjust(newX, newY));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method is called to pass on the drag information  to the UI
 | |
|      * through dragDividerTo.
 | |
|      *
 | |
|      * @param e The MouseEvent.
 | |
|      */
 | |
|     protected void continueDrag(MouseEvent e)
 | |
|     {
 | |
|       if (isValid())
 | |
|         dragDividerTo(positionForMouseEvent(e));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method is called to finish the drag session  by calling
 | |
|      * finishDraggingTo.
 | |
|      *
 | |
|      * @param x The x coordinate of the MouseEvent.
 | |
|      * @param y The y coordinate of the MouseEvent.
 | |
|      */
 | |
|     protected void completeDrag(int x, int y)
 | |
|     {
 | |
|       finishDraggingTo(adjust(x, y));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method is called to finish the drag session  by calling
 | |
|      * finishDraggingTo.
 | |
|      *
 | |
|      * @param e The MouseEvent.
 | |
|      */
 | |
|     protected void completeDrag(MouseEvent e)
 | |
|     {
 | |
|       finishDraggingTo(positionForMouseEvent(e));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This is a helper method that includes the offset in the needed
 | |
|      * location.
 | |
|      *
 | |
|      * @param x The x coordinate of the MouseEvent.
 | |
|      * @param y The y coordinate of the MouseEvent.
 | |
|      *
 | |
|      * @return The needed location adjusted by the offsets.
 | |
|      */
 | |
|     int adjust(int x, int y)
 | |
|     {
 | |
|       return getNeededLocation(x, y) + getX() - offset;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This is a helper class that controls dragging when  the orientation is
 | |
|    * VERTICAL_SPLIT.
 | |
|    */
 | |
|   protected class VerticalDragController extends DragController
 | |
|   {
 | |
|     /**
 | |
|      * Creates a new VerticalDragController object.
 | |
|      *
 | |
|      * @param e The MouseEvent to initialize with.
 | |
|      */
 | |
|     protected VerticalDragController(MouseEvent e)
 | |
|     {
 | |
|       super(e);
 | |
|       offset = e.getY();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method returns one of the two parameters given the orientation. In
 | |
|      * this case, it returns y.
 | |
|      *
 | |
|      * @param x The x coordinate of the MouseEvent.
 | |
|      * @param y The y coordinate of the MouseEvent.
 | |
|      *
 | |
|      * @return The y coordinate.
 | |
|      */
 | |
|     protected int getNeededLocation(int x, int y)
 | |
|     {
 | |
|       return y;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method returns the new location of the divider given a MouseEvent.
 | |
|      *
 | |
|      * @param e The MouseEvent.
 | |
|      *
 | |
|      * @return The new location of the divider.
 | |
|      */
 | |
|     protected int positionForMouseEvent(MouseEvent e)
 | |
|     {
 | |
|       return e.getY() + getY() - offset;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This is a helper method that includes the offset in the needed
 | |
|      * location.
 | |
|      *
 | |
|      * @param x The x coordinate of the MouseEvent.
 | |
|      * @param y The y coordinate of the MouseEvent.
 | |
|      *
 | |
|      * @return The needed location adjusted by the offsets.
 | |
|      */
 | |
|     int adjust(int x, int y)
 | |
|     {
 | |
|       return getNeededLocation(x, y) + getY() - offset;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This helper class acts as the Layout Manager for the divider.
 | |
|    */
 | |
|   protected class DividerLayout implements LayoutManager
 | |
|   {
 | |
|     /**
 | |
|      * Creates a new DividerLayout object.
 | |
|      */
 | |
|     protected DividerLayout()
 | |
|     {
 | |
|       // Nothing to do here.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method is called when a Component is added.
 | |
|      *
 | |
|      * @param string The constraints string.
 | |
|      * @param c The Component to add.
 | |
|      */
 | |
|     public void addLayoutComponent(String string, Component c)
 | |
|     {
 | |
|       // Do nothing.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method is called to lay out the container.
 | |
|      *
 | |
|      * @param c The container to lay out.
 | |
|      */
 | |
|     public void layoutContainer(Container c)
 | |
|     {
 | |
|       if (leftButton != null && rightButton != null
 | |
|           && c == BasicSplitPaneDivider.this)
 | |
|         {
 | |
|           if (splitPane.isOneTouchExpandable())
 | |
|             {
 | |
|               Insets insets = getInsets();
 | |
|               if (orientation == JSplitPane.HORIZONTAL_SPLIT)
 | |
|                 {
 | |
|                   int size = getWidth() - insets.left - insets.right;
 | |
|                   size = Math.max(size, 0);
 | |
|                   size = Math.min(size, ONE_TOUCH_SIZE);
 | |
|                   int x, y;
 | |
|                   if (centerOneTouchButtons)
 | |
|                     {
 | |
|                       y = insets.top;
 | |
|                       x = (getWidth() - size) / 2;
 | |
|                     }
 | |
|                   else
 | |
|                     {
 | |
|                       x = insets.left;
 | |
|                       y = 0;
 | |
|                     }
 | |
| 
 | |
|                   leftButton.setBounds(x, y + ONE_TOUCH_OFFSET, size,
 | |
|                                        size * 2);
 | |
|                   rightButton.setBounds(x, y + ONE_TOUCH_OFFSET
 | |
|                                         + ONE_TOUCH_SIZE * 2, size, size * 2);
 | |
|                 }
 | |
|               else
 | |
|                 {
 | |
|                   int size = getHeight() - insets.top - insets.bottom;
 | |
|                   size = Math.max(size, 0);
 | |
|                   size = Math.min(size, ONE_TOUCH_SIZE);
 | |
|                   int x, y;
 | |
|                   if (centerOneTouchButtons)
 | |
|                     {
 | |
|                       x = insets.left;
 | |
|                       y = (getHeight() - size) / 2;
 | |
|                     }
 | |
|                   else
 | |
|                     {
 | |
|                       x = 0;
 | |
|                       y = insets.top;
 | |
|                     }
 | |
|                   leftButton.setBounds(x + ONE_TOUCH_OFFSET, y, size * 2,
 | |
|                                        size);
 | |
|                   rightButton.setBounds(x + ONE_TOUCH_OFFSET
 | |
|                                         + ONE_TOUCH_SIZE * 2, y, size * 2,
 | |
|                                         size);
 | |
|                 }
 | |
|             }
 | |
|           else
 | |
|             {
 | |
|               // The JDK sets this bounds for disabled one touch buttons, so
 | |
|               // do we.
 | |
|               leftButton.setBounds(-5, -5, 1, 1);
 | |
|               rightButton.setBounds(-5, -5, 1, 1);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method returns the minimum layout size.
 | |
|      *
 | |
|      * @param c The container to calculate for.
 | |
|      *
 | |
|      * @return The minimum layout size.
 | |
|      */
 | |
|     public Dimension minimumLayoutSize(Container c)
 | |
|     {
 | |
|       return preferredLayoutSize(c);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method returns the preferred layout size.
 | |
|      *
 | |
|      * @param c The container to calculate for.
 | |
|      *
 | |
|      * @return The preferred layout size.
 | |
|      */
 | |
|     public Dimension preferredLayoutSize(Container c)
 | |
|     {
 | |
|       return new Dimension(dividerSize, dividerSize);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method is called when a component is removed.
 | |
|      *
 | |
|      * @param c The component to remove.
 | |
|      */
 | |
|     public void removeLayoutComponent(Component c)
 | |
|     {
 | |
|       // Do nothing.
 | |
|     }
 | |
| 
 | |
|   }
 | |
| }
 |