1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.vaadin.ui;
17
18 import java.io.OutputStream;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.LinkedHashMap;
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.Set;
26
27 import org.jsoup.nodes.Element;
28
29 import com.vaadin.event.Transferable;
30 import com.vaadin.event.TransferableImpl;
31 import com.vaadin.event.dd.DragSource;
32 import com.vaadin.event.dd.DropHandler;
33 import com.vaadin.event.dd.DropTarget;
34 import com.vaadin.event.dd.TargetDetails;
35 import com.vaadin.event.dd.TargetDetailsImpl;
36 import com.vaadin.server.PaintException;
37 import com.vaadin.server.PaintTarget;
38 import com.vaadin.server.StreamVariable;
39 import com.vaadin.shared.MouseEventDetails;
40 import com.vaadin.shared.ui.dd.HorizontalDropLocation;
41 import com.vaadin.shared.ui.dd.VerticalDropLocation;
42 import com.vaadin.shared.ui.draganddropwrapper.DragAndDropWrapperConstants;
43 import com.vaadin.shared.ui.draganddropwrapper.DragAndDropWrapperServerRpc;
44 import com.vaadin.ui.declarative.DesignContext;
45
46 @SuppressWarnings("serial")
47 public class DragAndDropWrapper extends CustomComponent implements DropTarget,
48 DragSource, LegacyComponent {
49
50 public class WrapperTransferable extends TransferableImpl {
51
52 private Html5File[] files;
53
54 public WrapperTransferable(Component sourceComponent,
55 Map<String, Object> rawVariables) {
56 super(sourceComponent, rawVariables);
57 Integer fc = (Integer) rawVariables.get("filecount");
58 if (fc != null) {
59 files = new Html5File[fc];
60 for (int i = 0; i < fc; i++) {
61 Html5File file = new Html5File(
62 (String) rawVariables.get("fn" + i),
63 ((Double) rawVariables.get("fs" + i)).longValue(),
64 (String) rawVariables.get("ft" + i));
65 String id = (String) rawVariables.get("fi" + i);
66 files[i] = file;
67 receivers.put(id, new ProxyReceiver(id, file));
68 markAsDirty();
69 }
70 }
71 }
72
73
74
75
76
77
78
79 public Component getDraggedComponent() {
80 Component object = (Component) getData("component");
81 return object;
82 }
83
84
85
86
87 public MouseEventDetails getMouseDownEvent() {
88 return MouseEventDetails.deSerialize((String) getData("mouseDown"));
89 }
90
91 public Html5File[] getFiles() {
92 return files;
93 }
94
95 public String getText() {
96 String data = (String) getData("Text");
97 if (data == null) {
98
99 data = (String) getData("text/plain");
100 }
101 return data;
102 }
103
104 public String getHtml() {
105 String data = (String) getData("Html");
106 if (data == null) {
107
108 data = (String) getData("text/html");
109 }
110 return data;
111 }
112
113 }
114
115 private final DragAndDropWrapperServerRpc rpc = new DragAndDropWrapperServerRpc() {
116
117 @Override
118 public void poll() {
119
120 }
121 };
122
123 private Map<String, ProxyReceiver> receivers = new HashMap<String, ProxyReceiver>();
124
125 public class WrapperTargetDetails extends TargetDetailsImpl {
126
127 public WrapperTargetDetails(Map<String, Object> rawDropData) {
128 super(rawDropData, DragAndDropWrapper.this);
129 }
130
131
132
133
134 public Integer getAbsoluteLeft() {
135 return (Integer) getData("absoluteLeft");
136 }
137
138
139
140
141
142 public Integer getAbsoluteTop() {
143 return (Integer) getData("absoluteTop");
144 }
145
146
147
148
149 public VerticalDropLocation getVerticalDropLocation() {
150 return VerticalDropLocation
151 .valueOf((String) getData("verticalLocation"));
152 }
153
154
155
156
157
158 public HorizontalDropLocation getHorizontalDropLocation() {
159 return HorizontalDropLocation
160 .valueOf((String) getData("horizontalLocation"));
161 }
162
163 }
164
165 public enum DragStartMode {
166
167
168
169 NONE,
170
171
172
173 COMPONENT,
174
175
176
177 WRAPPER,
178
179
180
181
182
183
184
185 HTML5,
186
187
188
189
190
191 COMPONENT_OTHER,
192 }
193
194 private final Map<String, Object> html5DataFlavors = new LinkedHashMap<String, Object>();
195 private DragStartMode dragStartMode = DragStartMode.NONE;
196 private Component dragImageComponent = null;
197
198 private Set<String> sentIds = new HashSet<String>();
199
200
201
202
203
204
205
206 @Deprecated
207 public DragAndDropWrapper() {
208 super();
209 registerRpc(rpc);
210 }
211
212
213
214
215
216
217
218 public DragAndDropWrapper(Component root) {
219 this();
220 setCompositionRoot(root);
221 }
222
223
224
225
226
227
228
229
230
231
232
233
234 public void setHTML5DataFlavor(String type, Object value) {
235 html5DataFlavors.put(type, value);
236 markAsDirty();
237 }
238
239 @Override
240 public void changeVariables(Object source, Map<String, Object> variables) {
241
242 }
243
244 @Override
245 public void paintContent(PaintTarget target) throws PaintException {
246 target.addAttribute(DragAndDropWrapperConstants.DRAG_START_MODE,
247 dragStartMode.ordinal());
248
249 if (dragStartMode.equals(DragStartMode.COMPONENT_OTHER)) {
250 if (dragImageComponent != null) {
251 target.addAttribute(
252 DragAndDropWrapperConstants.DRAG_START_COMPONENT_ATTRIBUTE,
253 dragImageComponent.getConnectorId());
254 } else {
255 throw new IllegalArgumentException(
256 "DragStartMode.COMPONENT_OTHER set but no component "
257 + "was defined. Please set a component using DragAnd"
258 + "DropWrapper.setDragStartComponent(Component).");
259 }
260 }
261 if (getDropHandler() != null) {
262 getDropHandler().getAcceptCriterion().paint(target);
263 }
264 if (receivers != null && receivers.size() > 0) {
265 for (Iterator<Entry<String, ProxyReceiver>> it = receivers
266 .entrySet().iterator(); it.hasNext();) {
267 Entry<String, ProxyReceiver> entry = it.next();
268 String id = entry.getKey();
269 ProxyReceiver proxyReceiver = entry.getValue();
270 Html5File html5File = proxyReceiver.file;
271 if (html5File.getStreamVariable() != null) {
272 if (!sentIds.contains(id)) {
273 target.addVariable(this, "rec-" + id,
274 new ProxyReceiver(id, html5File));
275
276
277
278
279
280
281
282
283
284
285 sentIds.add(id);
286
287
288
289 }
290 } else {
291
292 target.addVariable(this, "rec-" + id, (String) null);
293
294 it.remove();
295 }
296 }
297 }
298 target.addAttribute(DragAndDropWrapperConstants.HTML5_DATA_FLAVORS,
299 html5DataFlavors);
300 }
301
302 private DropHandler dropHandler;
303
304 @Override
305 public DropHandler getDropHandler() {
306 return dropHandler;
307 }
308
309 public void setDropHandler(DropHandler dropHandler) {
310 this.dropHandler = dropHandler;
311 markAsDirty();
312 }
313
314 @Override
315 public TargetDetails translateDropTargetDetails(
316 Map<String, Object> clientVariables) {
317 return new WrapperTargetDetails(clientVariables);
318 }
319
320 @Override
321 public Transferable getTransferable(final Map<String, Object> rawVariables) {
322 return new WrapperTransferable(this, rawVariables);
323 }
324
325 public void setDragStartMode(DragStartMode dragStartMode) {
326 this.dragStartMode = dragStartMode;
327 markAsDirty();
328 }
329
330 public DragStartMode getDragStartMode() {
331 return dragStartMode;
332 }
333
334
335
336
337
338
339
340 public void setDragImageComponent(Component dragImageComponent) {
341 this.dragImageComponent = dragImageComponent;
342 markAsDirty();
343 }
344
345
346
347
348
349
350
351 public Component getDragImageComponent() {
352 return dragImageComponent;
353 }
354
355 final class ProxyReceiver implements StreamVariable {
356
357 private String id;
358 private Html5File file;
359
360 public ProxyReceiver(String id, Html5File file) {
361 this.id = id;
362 this.file = file;
363 }
364
365 private boolean listenProgressOfUploadedFile;
366
367 @Override
368 public OutputStream getOutputStream() {
369 if (file.getStreamVariable() == null) {
370 return null;
371 }
372 return file.getStreamVariable().getOutputStream();
373 }
374
375 @Override
376 public boolean listenProgress() {
377 return file.getStreamVariable().listenProgress();
378 }
379
380 @Override
381 public void onProgress(StreamingProgressEvent event) {
382 file.getStreamVariable().onProgress(
383 new ReceivingEventWrapper(event));
384 }
385
386 @Override
387 public void streamingStarted(StreamingStartEvent event) {
388 listenProgressOfUploadedFile = file.getStreamVariable() != null;
389 if (listenProgressOfUploadedFile) {
390 file.getStreamVariable().streamingStarted(
391 new ReceivingEventWrapper(event));
392 }
393
394 receivers.remove(id);
395 sentIds.remove(id);
396 }
397
398 @Override
399 public void streamingFinished(StreamingEndEvent event) {
400 if (listenProgressOfUploadedFile) {
401 file.getStreamVariable().streamingFinished(
402 new ReceivingEventWrapper(event));
403 }
404 }
405
406 @Override
407 public void streamingFailed(final StreamingErrorEvent event) {
408 if (listenProgressOfUploadedFile) {
409 file.getStreamVariable().streamingFailed(
410 new ReceivingEventWrapper(event));
411 }
412 }
413
414 @Override
415 public boolean isInterrupted() {
416 return file.getStreamVariable().isInterrupted();
417 }
418
419
420
421
422
423
424
425 class ReceivingEventWrapper implements StreamingErrorEvent,
426 StreamingEndEvent, StreamingStartEvent, StreamingProgressEvent {
427
428 private StreamingEvent wrappedEvent;
429
430 ReceivingEventWrapper(StreamingEvent e) {
431 wrappedEvent = e;
432 }
433
434 @Override
435 public String getMimeType() {
436 return file.getType();
437 }
438
439 @Override
440 public String getFileName() {
441 return file.getFileName();
442 }
443
444 @Override
445 public long getContentLength() {
446 return file.getFileSize();
447 }
448
449 public StreamVariable getReceiver() {
450 return ProxyReceiver.this;
451 }
452
453 @Override
454 public Exception getException() {
455 if (wrappedEvent instanceof StreamingErrorEvent) {
456 return ((StreamingErrorEvent) wrappedEvent).getException();
457 }
458 return null;
459 }
460
461 @Override
462 public long getBytesReceived() {
463 return wrappedEvent.getBytesReceived();
464 }
465
466
467
468
469
470 @Override
471 public void disposeStreamVariable() {
472
473 }
474 }
475
476 }
477
478 @Override
479 public void readDesign(Element design, DesignContext designContext) {
480 super.readDesign(design, designContext);
481
482 for (Element child : design.children()) {
483 Component component = designContext.readDesign(child);
484 if (getDragStartMode() == DragStartMode.COMPONENT_OTHER
485 && child.hasAttr(":drag-image")) {
486 setDragImageComponent(component);
487 } else if (getCompositionRoot() == null) {
488 setCompositionRoot(component);
489 }
490 }
491 }
492
493 @Override
494 public void writeDesign(Element design, DesignContext designContext) {
495 super.writeDesign(design, designContext);
496
497 design.appendChild(designContext.createElement(getCompositionRoot()));
498 if (getDragStartMode() == DragStartMode.COMPONENT_OTHER) {
499 Element child = designContext
500 .createElement(getDragImageComponent());
501 child.attr(":drag-image", true);
502 design.appendChild(child);
503 }
504 }
505 }