wicketdnd.DragSource.java Source code

Java tutorial

Introduction

Here is the source code for wicketdnd.DragSource.java

Source

/*
 * Copyright 2009 Sven Meier
 *
 * 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 wicketdnd;

import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.Page;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.protocol.http.PageExpiredException;
import org.apache.wicket.request.Request;
import wicketdnd.util.CollectionFormattable;
import wicketdnd.util.MarkupIdVisitor;

import java.util.Set;

/**
 * A source of drags.
 * 
 * @see #getTypes()
 * @see #onBeforeDrop(Component, Transfer)
 * @see #onAfterDrop(AjaxRequestTarget, Transfer)
 * 
 * @author Sven Meier
 */
public class DragSource extends Behavior {

    private static final long serialVersionUID = 1L;

    private Component component;

    private String selector = Transfer.UNDEFINED;

    private String initiateSelector = Transfer.UNDEFINED;

    private String cloneSelector = Transfer.UNDEFINED;

    private Set<Operation> operations;

    /**
     * Create a source of drags.
     * 
     * @param operations
     *            allowed operations
     * 
     * @see #getOperations()
     */
    public DragSource(Operation... operations) {
        this(Operation.of(operations));
    }

    /**
     * Create a source of drags.
     * 
     * @param operations
     *            allowed operations
     * 
     * @see #getOperations()
     */
    public DragSource(Set<Operation> operations) {
        this.operations = operations;
    }

    /**
     * Get supported types for a transfer.
     * 
     * @return transfers
     * @see Transfer#getType()
     */
    public String[] getTypes() {
        return new String[] { Transfer.ANY };
    }

    /**
     * Allow drag on elements matching the given selector.
     * 
     * Make sure all matching elements are configured to output their markup id.
     * 
     * @param selector
     *            element selector
     * @see Component#setOutputMarkupId(boolean)
     */
    public DragSource drag(String selector) {
        this.selector = selector;

        if (this.initiateSelector.equals(Transfer.UNDEFINED)) {
            this.initiateSelector = selector;
        }

        if (this.cloneSelector.equals(Transfer.UNDEFINED)) {
            this.cloneSelector = selector;
        }

        return this;
    }

    /**
     * Initiate drag on elements matching the given selector.
     * 
     * @param selector
     *            element selector
     */
    public DragSource initiate(String selector) {
        this.initiateSelector = selector;
        return this;
    }

    /**
     * Clone drag on elements matching the given selector.
     * 
     * @param selector
     *            element selector
     */
    public DragSource clone(String selector) {
        this.cloneSelector = selector;
        return this;
    }

    @Override
    public final void bind(Component component) {
        this.component = component;
        component.setOutputMarkupId(true);
    }

    /**
     * Get the identifying path of this drag source.
     * 
     * @return path in page
     */
    public String getPath() {
        return component.getPageRelativePath();
    }

    /**
     * Get the id of this behavior.
     * 
     * @return id
     */
    public int getBehaviorId() {
        return component.getBehaviorId(this);
    }

    @Override
    public final void renderHead(Component c, IHeaderResponse response) {
        super.renderHead(c, response);

        renderDragHead(response);
    }

    private void renderDragHead(IHeaderResponse response) {
        response.renderJavaScriptReference(Transfer.JS);

        final String id = component.getMarkupId();
        final String path = component.getPageRelativePath();
        int behavior = component.getBehaviorId(this);

        String initJS = String.format(
                "wicketdnd.dragSource('%s','%s','%s', %s,%s,{'select':'%s','initiate':'%s','clone':'%s'});", id,
                behavior, path, new CollectionFormattable(getOperations()), new CollectionFormattable(getTypes()),
                selector, initiateSelector, cloneSelector);
        response.renderOnDomReadyJavaScript(initJS);
    }

    @Override
    public void onComponentTag(Component component, ComponentTag tag) {
        super.onComponentTag(component, tag);

        tag.append("class", "dnd-drag-source", " ");
    }

    /**
     * Get supported operations.
     * 
     * @return operations
     * @see Transfer#getOperation()
     */
    public Set<Operation> getOperations() {
        return operations;
    }

    final boolean hasOperation(Operation operation) {
        return getOperations().contains(operation);
    }

    final void beforeDrop(Request request, Transfer transfer) throws Reject {
        Component drag = getDrag(request);

        onBeforeDrop(drag, transfer);
    }

    final void afterDrop(AjaxRequestTarget target, Transfer transfer) {
        onAfterDrop(target, transfer);
    }

    /**
     * Notification that a drop is about to happen - any implementation should
     * set the data on the given transfer or reject it.
     * 
     * The default implementation uses the component's model object as transfer
     * data.
     * 
     * @param drag
     *            component to get data from
     * @param operation
     *            the drag's operation
     * @param transfer
     *            the transfer
     * @throws Reject
     *             may reject the drop
     * @see Transfer#setData(Object)
     * @see Transfer#reject()
     */
    public void onBeforeDrop(Component drag, Transfer transfer) throws Reject {
        transfer.setData(drag.getDefaultModelObject());
    }

    /**
     * Notification that a drop happened of one of this source's transfer datas.
     * 
     * The default implementation does nothing.
     * 
     * @param target
     *            initiating request target
     * @param transfer
     *            the transfer
     */
    public void onAfterDrop(AjaxRequestTarget target, Transfer transfer) {
    }

    private Component getDrag(Request request) {
        String drag = request.getRequestParameters().getParameterValue("drag").toString();

        return MarkupIdVisitor.getComponent((MarkupContainer) component, drag);
    }

    /**
     * Get the drag source of the given request.
     * 
     * @param request
     *            request on which a drag happened
     * @return drag source
     */
    final static DragSource read(Page page, Request request) {
        String path = request.getRequestParameters().getParameterValue("path").toString();
        Component component = page.get(path);
        if (component == null) {
            throw new PageExpiredException("No drag source found " + path);
        }

        int behavior = request.getRequestParameters().getParameterValue("behavior").toInt();
        return (DragSource) component.getBehaviorById(behavior);
    }
}