001    /*
002     * Copyright (c) 2005, romain guy (romain.guy@jext.org) and craig wickesser (craig@codecraig.com)
003     * All rights reserved.
004     * 
005     * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
006     * 
007     *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
008     *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
009     *     * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
010     * 
011     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
012     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
013     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
014     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
015     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
016     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
017     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
018     * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
019     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
020     * POSSIBILITY OF SUCH DAMAGE.
021     */
022    
023    package net.java.swingfx.jdraggable;
024    
025    import java.awt.Component;
026    import java.awt.Container;
027    import java.awt.Point;
028    import java.awt.Rectangle;
029    import java.awt.event.MouseEvent;
030    
031    import javax.swing.SwingUtilities;
032    import javax.swing.event.MouseInputAdapter;
033    
034    /**
035     * A listener which receives {@link java.awt.event.MouseEvent}'s to aid
036     * in the "dragging" of a {@link java.awt.Component}
037     * 
038     * @author craig
039     * @since v0.1
040     * <br>
041     * $Header: /cvs/swingfx/docs/api/src-html/net/java/swingfx/jdraggable/DraggableListener.html,v 1.1 2005/06/23 00:24:44 codecraig Exp $
042     */
043    public class DraggableListener extends MouseInputAdapter {
044        private Point componentTopLeft;
045        private Point componentTopRight;
046        private Point componentBottomLeft;
047        private Point componentBottomRight;
048        private Point containerTopLeft;
049        private Point containerTopRight;
050        private Point containerBottomLeft;
051        private Point containerBottomRight;
052            
053            private DraggableManager dragManager;
054            private Component draggableComponent;
055            private Container draggableContainer;
056            private int offsetX;
057            private int offsetY;
058            
059            /**
060             * Creates a new listener which communicates with the given {@link DraggableManager}
061             * during "dragging"
062             * 
063             * @param dragManager   the <code>DraggableManager</code> to communicate with
064             */
065            public DraggableListener(DraggableManager dragManager) {
066                    this.dragManager = dragManager;
067                    this.draggableContainer = dragManager.getDraggableContainer();
068            }
069            
070            /**
071             * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
072             */
073            public void mouseDragged(MouseEvent e) {
074                    if (dragManager.dragging()) {
075                            //TODO: come up with a better solution than this, and once we do, remove
076                            // shouldNullifyLayout() from the interface
077                            if (dragManager.shouldNullifyLayout() && draggableContainer.getLayout() != null) {
078                                    draggableContainer.setLayout(null);
079                            }
080                            int x = e.getX();
081                    int y = e.getY();
082                    Point pt = SwingUtilities.convertPoint(draggableComponent, x, y, draggableContainer);
083                    draggableComponent.setLocation(pt.x - offsetX, pt.y - offsetY);
084                    stayInContainer();
085                    }
086            }
087            
088            /**
089             * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
090             */
091            public void mousePressed(MouseEvent e) {
092                    draggableComponent = e.getComponent();
093                    if (dragManager.startDrag(draggableComponent)) {
094                            offsetX = e.getX();
095                            offsetY = e.getY();
096                    }
097            }
098    
099            /**
100             * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
101             */
102            public void mouseReleased(MouseEvent e) {
103                    dragManager.stopDrag();
104                    draggableComponent = null;
105            }
106            
107            /**
108             * Determines if the current "draggable component" is in the 
109             * "draggable container"
110             * 
111             * @return      <code>true</code> if the component is in the container,
112             *                      <code>false</code> otherwise
113             */
114            private boolean isInContainer() {
115            Rectangle r = new Rectangle( draggableContainer.getWidth(), draggableContainer.getHeight() );
116            int wC = (int)r.getWidth();
117            int hC = (int)r.getHeight();
118            containerTopLeft = r.getLocation();
119            containerTopRight = new Point( (int)containerTopLeft.getX()+wC, (int)containerTopLeft.getY() );
120            containerBottomLeft = new Point( (int)containerTopLeft.getX(), (int)containerTopLeft.getY()+hC );
121            containerBottomRight = new Point( (int)containerTopLeft.getX()+wC, (int)containerTopLeft.getY()+hC );
122            int w = draggableComponent.getWidth();
123            int h = draggableComponent.getHeight();
124            componentTopLeft = draggableComponent.getLocation();
125            componentTopRight = new Point( (int)componentTopLeft.getX()+w, (int)componentTopLeft.getY() );
126            componentBottomLeft = new Point( (int)componentTopLeft.getX(), (int)componentTopLeft.getY()+h );
127            componentBottomRight = new Point( (int)componentTopLeft.getX()+w, (int)componentTopLeft.getY()+h );
128            if( !r.contains(componentTopLeft) ) return false;
129            if( !r.contains(componentTopRight) ) return false;
130            if( !r.contains(componentBottomLeft) ) return false;
131            if( !r.contains(componentBottomRight) ) return false;
132            return true;
133        }
134            
135            /**
136             * Assures that the "draggable component" stays within the "draggable container"
137             */
138        private void stayInContainer(){
139            /* if the plate goes is too far in right-direction, shift it back*/
140            if( !isInContainer() ){    
141                double x = componentTopRight.getX();
142                double xC = containerTopRight.getX();
143                if( x > xC ){
144                    draggableComponent.setLocation( (int)(componentTopLeft.getX()+xC-x), (int)componentTopLeft.getY());
145                }
146            }
147            /* if the plate goes is too far in left-direction, shift it back */
148            if( !isInContainer() ){
149                double x = componentTopLeft.getX();
150                double xC = containerTopLeft.getX();
151                if( x < xC ){
152                    draggableComponent.setLocation( (int)(componentTopLeft.getX()+xC-x), (int)componentTopLeft.getY());
153                }
154            }
155            /* if the plate goes is too far in top-direction, shift it back */
156            if( !isInContainer() ){
157                double y = componentTopLeft.getY();
158                double yC = containerTopLeft.getY();
159                if( y < yC ){
160                    draggableComponent.setLocation( (int)componentTopLeft.getX(), (int)(componentTopLeft.getY()+yC-y));
161                }
162            }
163            /* if the plate goes is too far in bottom-direction, shift it back */
164            if( !isInContainer() ){
165                double y = componentBottomLeft.getY();
166                double yC = containerBottomLeft.getY();
167                if( y > yC ){
168                    draggableComponent.setLocation( (int)componentTopLeft.getX(), (int)( componentTopLeft.getY()+yC-y) );
169                }
170            }
171        }
172    }