Package org.thechiselgroup.choosel.dnd.client.resources

Source Code of org.thechiselgroup.choosel.dnd.client.resources.ResourceSetAvatarDropController

/*******************************************************************************
* Copyright 2009, 2010 Lars Grammel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*    
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. 
*******************************************************************************/
package org.thechiselgroup.choosel.dnd.client.resources;

import org.thechiselgroup.choosel.core.client.command.CommandManager;
import org.thechiselgroup.choosel.core.client.command.UndoableCommand;
import org.thechiselgroup.choosel.core.client.geometry.Point;
import org.thechiselgroup.choosel.core.client.resources.ui.ResourceSetAvatar;
import org.thechiselgroup.choosel.core.client.ui.CSS;
import org.thechiselgroup.choosel.core.client.ui.popup.DefaultDelayedPopupManager;
import org.thechiselgroup.choosel.core.client.ui.popup.DelayedPopupManager;
import org.thechiselgroup.choosel.core.client.ui.popup.Popup;
import org.thechiselgroup.choosel.core.client.ui.popup.PopupFactory;
import org.thechiselgroup.choosel.core.client.util.HasDescription;
import org.thechiselgroup.choosel.core.client.visualization.View;
import org.thechiselgroup.choosel.core.client.visualization.ViewAccessor;
import org.thechiselgroup.choosel.core.client.visualization.model.VisualizationModel;

import com.allen_sauer.gwt.dnd.client.DragContext;
import com.allen_sauer.gwt.dnd.client.drop.SimpleDropController;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;

public class ResourceSetAvatarDropController extends SimpleDropController {

    private static final int MAX_POPUP_WIDTH = 250;

    private static final int POPUP_HIDE_DELAY = 200;

    private static final int POPUP_SHOW_DELAY = 800;

    private static final int POPUP_X_OFFSET = 15;

    private static final int POPUP_Y_OFFSET = 20;

    private final DropTargetCapabilityChecker capabilityChecker;

    private ResourceSetAvatarDropCommandFactory commandFactory;

    private CommandManager commandManager;

    private UndoableCommand executedCommand;

    private DelayedPopupManager popup = null;

    private ViewAccessor viewAccessor;

    private PopupFactory popupFactory;

    public ResourceSetAvatarDropController(Widget dropTarget,
            ResourceSetAvatarDropCommandFactory commandFactory,
            CommandManager commandManager, ViewAccessor viewAccessor,
            DropTargetCapabilityChecker capabilityChecker,
            PopupFactory popupFactory) {

        super(dropTarget);

        this.commandFactory = commandFactory;
        this.commandManager = commandManager;
        this.viewAccessor = viewAccessor;
        this.capabilityChecker = capabilityChecker;
        this.popupFactory = popupFactory;
    }

    // TODO prevent drag source self-drop
    public boolean canDrop(DragContext context) {
        if (!(context.draggable instanceof ResourceSetAvatar)) {
            return false;
        }

        ResourceSetAvatar avatar = getAvatar(context);

        /*
         * TODO we need the automatic visualization algorithm that takes the
         * current configuration and the new data and gives us a ranked list of
         * possible configurations. If that list is empty, we cannot drop.
         */

        return isValidDrop(avatar) && commandFactory.canDrop(avatar);
    }

    private UndoableCommand createCommand(final DragContext context) {
        return commandFactory.createCommand(getAvatar(context));
    }

    // protected for testing only
    // TODO move to factory
    // TODO refactor
    protected DelayedPopupManager createPopup(final DragContext context,
            String message) {

        Popup popup = popupFactory.createPopup();

        DelayedPopupManager popupManager = new DefaultDelayedPopupManager(
                POPUP_SHOW_DELAY, POPUP_HIDE_DELAY, popup) {

            @Override
            protected void updatePosition() {
                getPopup().setLocation(
                        new Point(context.mouseX + POPUP_X_OFFSET,
                                context.mouseY + POPUP_Y_OFFSET));
            }
        };

        HTML widget = new HTML(message);
        CSS.setMaxWidth(widget, MAX_POPUP_WIDTH);
        popupManager.getPopup().setContentWidget(widget);

        return popupManager;
    }

    private void executeCommand(UndoableCommand command) {
        command.execute();
        executedCommand = command;
    }

    private ResourceSetAvatar getAvatar(DragContext context) {
        return (ResourceSetAvatar) context.draggable;
    }

    private boolean hasCommandBeenExecuted() {
        return executedCommand != null;
    }

    private void hidePopup() {
        if (popup != null) {
            popup.hideDelayed();
            popup = null;
        }
    }

    private boolean isValidDrop(ResourceSetAvatar avatar) {
        View view = viewAccessor.findView(getDropTarget());
        assert view != null;

        VisualizationModel model = view.getModel();
        assert model != null;

        return capabilityChecker.isValidDrop(model.getSlots(),
                avatar.getResourceSet());
    }

    // TODO support dragging multiple widgets?
    @Override
    public void onDrop(DragContext context) {
        // remove popup even if error occurs
        try {
            if (canDrop(context) || hasCommandBeenExecuted()) {
                if (!hasCommandBeenExecuted()) {
                    executeCommand(createCommand(context));
                }

                // add the command to the command stack, and make
                // the manager fire an event.
                commandManager.execute(executedCommand);
                executedCommand = null; // prevent undo from later onLeave
            }
        } finally {
            hidePopup();
            super.onDrop(context);
        }
    }

    @Override
    public void onEnter(final DragContext context) {
        // TODO support dragging multiple widgets?
        super.onEnter(context);

        if (canDrop(context)) {
            UndoableCommand command = createCommand(context);

            if (command instanceof HasDescription) {
                showPopup(context, ((HasDescription) command).getDescription());
            }

            executeCommand(command);
        }
    }

    // TODO support dragging multiple widgets?
    @Override
    public void onLeave(DragContext context) {
        // remove popup even if command execution fails
        try {
            undoCommand();
        } finally {
            hidePopup();
            super.onLeave(context);
        }
    }

    // TODO refactor
    private void showPopup(final DragContext context, String message) {
        popup = createPopup(context, message);
        popup.showDelayed();
    }

    private void undoCommand() {
        if (hasCommandBeenExecuted()) {
            executedCommand.undo();
            executedCommand = null;
        }
    }
}
TOP

Related Classes of org.thechiselgroup.choosel.dnd.client.resources.ResourceSetAvatarDropController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.