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

com.alee.extended.tree.AsyncTreeTransferHandler 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.tree;

import java.util.List;

/**
 * Custom TransferHandler for WebAsyncTree that provides a quick and convenient way to implement nodes DnD.
 *
 * @author Mikle Garin
 */

public abstract class AsyncTreeTransferHandler>
        extends AbstractTreeTransferHandler>
{
    /**
     * Whether should allow dropping nodes onto not-yet-loaded node or not.
     * Be aware that if this set to true and your tree might fail loading children - old nodes will still get removed on drop.
     * If set to false tree will try to load child nodes first and then perform the drop operation.
     */
    protected boolean allowUncheckedDrop = false;

    /**
     * Returns whether should allow dropping nodes onto not-yet-loaded node or not.
     *
     * @return true if should allow dropping nodes onto not-yet-loaded node, false otherwise
     */
    public boolean isAllowUncheckedDrop ()
    {
        return allowUncheckedDrop;
    }

    /**
     * Sets whether should allow dropping nodes onto not-yet-loaded node or not
     *
     * @param allowUncheckedDrop whether should allow dropping nodes onto not-yet-loaded node or not
     */
    public void setAllowUncheckedDrop ( final boolean allowUncheckedDrop )
    {
        this.allowUncheckedDrop = allowUncheckedDrop;
    }

    @Override
    protected boolean canDropTo ( final N dropLocation )
    {
        // Do not allow a drop on busy node as that might break tree model
        // Do not allow a drop on a failed node as it is already messed
        return super.canDropTo ( dropLocation ) && !dropLocation.isLoading () && !dropLocation.isFailed ();
    }

    @Override
    protected boolean prepareDropOperation ( final TransferSupport support, final List nodes, final int dropIndex, final N parent,
                                             final T tree, final AsyncTreeModel model )
    {
        if ( allowUncheckedDrop )
        {
            // Acting differently in case parent node children are not yet loaded
            // We don't want to modify model (insert children) before existing children are actually loaded
            if ( parent.isLoaded () )
            {
                // Adding data to model
                performDropOperation ( nodes, parent, tree, model, getAdjustedDropIndex ( dropIndex, support.getDropAction (), parent ) );
            }
            else
            {
                // Loading children first
                tree.addAsyncTreeListener ( new AsyncTreeAdapter ()
                {
                    @Override
                    public void loadCompleted ( final AsyncUniqueNode loadedFor, final List children )
                    {
                        if ( loadedFor == parent )
                        {
                            // Adding data to model
                            performDropOperation ( nodes, parent, tree, model, parent.getChildCount () );

                            // Removing listener
                            tree.removeAsyncTreeListener ( this );
                        }
                    }

                    @Override
                    public void loadFailed ( final AsyncUniqueNode loadedFor, final Throwable cause )
                    {
                        if ( loadedFor == parent )
                        {
                            // Removing listener
                            tree.removeAsyncTreeListener ( this );
                        }
                    }
                } );
                tree.reloadNode ( parent );
            }
            return true;
        }
        else
        {
            // We have to load children synchronously, otherwise we cannot say for sure if drop succeed or not
            if ( !parent.isLoaded () )
            {
                tree.reloadNodeSync ( parent );
            }

            // If children were loaded right away with our attempt - perform the drop
            return parent.isLoaded () && performDropOperation ( nodes, parent, tree, model,
                    getAdjustedDropIndex ( dropIndex, support.getDropAction (), parent ) );
        }
    }

    @Override
    protected void informNodesDropped ( final List nodes, final N parent, final T tree, final AsyncTreeModel model, final int index )
    {
        // Informing about drop in a async tree queue to perform it in a separate non-EDT thread
        AsyncTreeQueue.execute ( tree, new Runnable ()
        {
            @Override
            public void run ()
            {
                AsyncTreeTransferHandler.super.informNodesDropped ( nodes, parent, tree, model, index );
            }
        } );
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy