summaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java
blob: ce47c7d13a11f41ca7244c83762dd5ae5fc4dd97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
@VaadinApache2LicenseForJavaFiles@
 */
package com.vaadin.terminal.gwt.client.ui.dd;

import java.util.Iterator;

import com.google.gwt.user.client.Command;
import com.vaadin.event.Transferable;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.UIDL;

public abstract class VAbstractDropHandler implements VDropHandler {

    private UIDL criterioUIDL;
    private VAcceptCriterion acceptCriteria = new VAcceptAll();

    /**
     * Implementor/user of {@link VAbstractDropHandler} must pass the UIDL
     * painted by {@link AcceptCriterion} to this method. Practically the
     * details about {@link AcceptCriterion} are saved.
     * 
     * @param uidl
     */
    public void updateAcceptRules(UIDL uidl) {
        criterioUIDL = uidl;
        /*
         * supports updating the accept rule root directly or so that it is
         * contained in given uidl node
         */
        if (!uidl.getTag().equals("-ac")) {
            Iterator<Object> childIterator = uidl.getChildIterator();
            while (!uidl.getTag().equals("-ac") && childIterator.hasNext()) {
                uidl = (UIDL) childIterator.next();
            }
        }
        acceptCriteria = VAcceptCriteria.get(uidl.getStringAttribute("name"));
        if (acceptCriteria == null) {
            throw new IllegalArgumentException(
                    "No accept criteria found with given name "
                            + uidl.getStringAttribute("name"));
        }
    }

    /**
     * Default implementation does nothing.
     */
    public void dragOver(VDragEvent drag) {

    }

    /**
     * Default implementation does nothing. Implementors should clean possible
     * emphasis or drag icons here.
     */
    public void dragLeave(VDragEvent drag) {

    }

    /**
     * The default implementation in {@link VAbstractDropHandler} checks if the
     * Transferable is accepted.
     * <p>
     * If transferable is accepted (either via server visit or client side
     * rules) the default implementation calls abstract
     * {@link #dragAccepted(VDragEvent)} method.
     * <p>
     * If drop handler has distinct places where some parts may accept the
     * {@link Transferable} and others don't, one should use similar validation
     * logic in dragOver method and replace this method with empty
     * implementation.
     * 
     */
    public void dragEnter(final VDragEvent drag) {
        validate(new VAcceptCallback() {
            public void accepted(VDragEvent event) {
                dragAccepted(drag);
            }
        }, drag);
    }

    /**
     * This method is called when a valid drop location was found with
     * {@link AcceptCriterion} either via client or server side check.
     * <p>
     * Implementations can set some hints for users here to highlight that the
     * drag is on a valid drop location.
     * 
     * @param drag
     */
    abstract protected void dragAccepted(VDragEvent drag);

    protected void validate(final VAcceptCallback cb, final VDragEvent event) {
        Command checkCriteria = new Command() {
            public void execute() {
                acceptCriteria.accept(event, criterioUIDL, cb);
            }
        };

        VDragAndDropManager.get().executeWhenReady(checkCriteria);
    }

    boolean validated = false;

    /**
     * The default implemmentation visits server if {@link AcceptCriterion} 
     * can't be verified on client or if {@link AcceptCriterion} are met on
     * client.
     */
    public boolean drop(VDragEvent drag) {
        if (acceptCriteria.needsServerSideCheck(drag, criterioUIDL)) {
            return true;
        } else {
            validated = false;
            acceptCriteria.accept(drag, criterioUIDL, new VAcceptCallback() {
                public void accepted(VDragEvent event) {
                    validated = true;
                }
            });
            return validated;
        }

    }

    /**
     * Returns the Paintable who owns this {@link VAbstractDropHandler}. Server
     * side counterpart of the Paintable is expected to implement
     * {@link DropTarget} interface.
     */
    public abstract ComponentConnector getConnector();

}