All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alee.extended.behavior.ComponentMoveBehavior Maven / Gradle / Ivy

/*
 * This file is part of WebLookAndFeel library.
 *
 * WebLookAndFeel library 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 3 of the License, or
 * (at your option) any later version.
 *
 * WebLookAndFeel library 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 WebLookAndFeel library.  If not, see .
 */

package com.alee.extended.behavior;

import com.alee.managers.style.BoundsType;
import com.alee.utils.CoreSwingUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

/**
 * This {@link Behavior} enables dragging {@link Component} or {@link Window} around using {@link #gripper}.
 * You can explicitely specify {@link #target} {@link Component} or {@link Window} to be dragged.
 * Otherwise behavior will use {@link #gripper}'s ancestor {@link Window}.
 *
 * This is basically simplified version of {@link ComponentResizeBehavior} as that one also allows dragging {@link #target}.
 * Although this behavior is more flavorful and convenient to use when dragging is the only thing required.
 *
 * Use {@link #install()} and {@link #uninstall()} methods to setup and remove this behavior.
 * You don't need to explicitely store this behavior if your only intent is to install it once and keep forever.
 * Although if you want to uninstall this behavior at some point you might want to keep its instance.
 *
 * @author Mikle Garin
 * @see #install()
 * @see #uninstall()
 */
public class ComponentMoveBehavior extends MouseAdapter implements Behavior
{
    /**
     * todo 1. Fix incorrect behavior on Unix systems
     */

    /**
     * {@link Component} that controls movement.
     */
    protected final Component gripper;

    /**
     * {@link Component} that is dragged using this behavior.
     * If set to {@code null} - {@link #gripper}'s parent {@link Window} will be used instead.
     */
    protected final Component target;

    /**
     * Whether or not this behavior is currently enabled.
     */
    protected boolean enabled;

    /**
     * Whether component is being dragged or not.
     */
    protected boolean dragging;

    /**
     * Currently dragged component.
     */
    protected Component dragged;

    /**
     * Drag start point.
     */
    protected Point initialPoint;

    /**
     * Dragged component initial bounds.
     */
    protected Rectangle initialBounds = null;

    /**
     * Constructs new component move adapter that alows source component parent window dragging.
     *
     * @param gripper component that will act as gripper
     */
    public ComponentMoveBehavior ( final Component gripper )
    {
        this ( gripper, null );
    }

    /**
     * Constructs new component move adapter that allows specified component dragging.
     *
     * @param gripper component that will act as gripper
     * @param target  component to be moved by the gripper component
     */
    public ComponentMoveBehavior ( final Component gripper, final Component target )
    {
        super ();
        this.gripper = gripper;
        this.target = target;
        this.enabled = true;
        this.dragging = false;
        this.dragged = null;
        this.initialPoint = null;
        this.initialBounds = null;
    }

    /**
     * Installs behavior into component.
     */
    public void install ()
    {
        gripper.addMouseListener ( this );
        gripper.addMouseMotionListener ( this );
    }

    /**
     * Uninstalls behavior from the component.
     */
    public void uninstall ()
    {
        gripper.removeMouseMotionListener ( this );
        gripper.removeMouseListener ( this );
    }

    /**
     * Returns whether or not this behavior is currently enabled.
     *
     * @return {@code true} if this behavior is currently enabled, {@code false} otherwise
     */
    public boolean isEnabled ()
    {
        return enabled;
    }

    /**
     * Sets whether or not this behavior is currently enabled.
     *
     * @param enabled whether or not this behavior is currently enabled
     */
    public void setEnabled ( final boolean enabled )
    {
        this.enabled = enabled;
    }

    @Override
    public void mousePressed ( final MouseEvent e )
    {
        if ( !e.isConsumed () && SwingUtilities.isLeftMouseButton ( e ) &&
                e.getSource () == gripper && isEnabled () && gripper.isEnabled () )
        {
            dragged = getDraggedComponent ( e );
            if ( dragged != null )
            {
                final Rectangle dragStartBounds = getDragStartBounds ( e );
                if ( dragStartBounds != null && dragStartBounds.contains ( e.getPoint () ) )
                {
                    dragging = true;
                    initialPoint = CoreSwingUtils.getMouseLocation ();
                    initialBounds = dragged.getBounds ();
                    componentMoveStarted ( initialPoint, initialBounds.getLocation () );

                    // Consume event
                    e.consume ();
                }
                else
                {
                    dragged = null;
                }
            }
        }
    }

    @Override
    public void mouseDragged ( final MouseEvent e )
    {
        if ( !e.isConsumed () && SwingUtilities.isLeftMouseButton ( e ) && dragging )
        {
            final Point mouse = CoreSwingUtils.getMouseLocation ();
            final int x = initialBounds.x + mouse.x - initialPoint.x;
            final int y = initialBounds.y + mouse.y - initialPoint.y;
            final Point location = new Point ( x, y );
            dragged.setLocation ( location );
            componentMoved ( mouse, location );

            // Consume event
            e.consume ();
        }
    }

    @Override
    public void mouseReleased ( final MouseEvent e )
    {
        if ( !e.isConsumed () && SwingUtilities.isLeftMouseButton ( e ) && dragging )
        {
            final Point mouse = CoreSwingUtils.getMouseLocation ();
            final Point location = dragged.getLocation ();
            dragging = false;
            dragged = null;
            initialPoint = null;
            initialBounds = null;
            componentMoveEnded ( mouse, location );

            // Consume event
            e.consume ();
        }
    }

    /**
     * Informs about component move start.
     *
     * @param mouse    mouse location
     * @param location component location
     */
    protected void componentMoveStarted ( final Point mouse, final Point location )
    {
        // Do nothing by default
    }

    /**
     * Informs about component being moved due to drag.
     *
     * @param mouse    new mouse location
     * @param location new component location
     */
    protected void componentMoved ( final Point mouse, final Point location )
    {
        // Do nothing by default
    }

    /**
     * Informs about component move end.
     *
     * @param mouse    mouse location
     * @param location component location
     */
    protected void componentMoveEnded ( final Point mouse, final Point location )
    {
        // Do nothing by default
    }

    /**
     * Returns actual dragged component.
     *
     * @param e occured mouse event
     * @return actual dragged component
     */
    protected Component getDraggedComponent ( final MouseEvent e )
    {
        return target != null ? target : CoreSwingUtils.getWindowAncestor ( gripper );
    }

    /**
     * Returns bounds within which component will act as a gripper.
     *
     * @param e occured mouse event
     * @return bounds within which component will act as a gripper
     */
    protected Rectangle getDragStartBounds ( final MouseEvent e )
    {
        return BoundsType.margin.bounds ( gripper );
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy