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