Package muntjac :: Package ui :: Module drag_and_drop_wrapper
[hide private]
[frames] | no frames]

Source Code for Module muntjac.ui.drag_and_drop_wrapper

  1  # Copyright (C) 2012 Vaadin Ltd.  
  2  # Copyright (C) 2012 Richard Lincoln 
  3  #  
  4  # Licensed under the Apache License, Version 2.0 (the "License");  
  5  # you may not use this file except in compliance with the License.  
  6  # You may obtain a copy of the License at  
  7  #  
  8  #     http://www.apache.org/licenses/LICENSE-2.0  
  9  #  
 10  # Unless required by applicable law or agreed to in writing, software  
 11  # distributed under the License is distributed on an "AS IS" BASIS,  
 12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
 13  # See the License for the specific language governing permissions and  
 14  # limitations under the License. 
 15   
 16  from muntjac.event.transferable_impl import TransferableImpl 
 17  from muntjac.event.dd.drag_source import IDragSource 
 18  from muntjac.event.dd.drop_target import IDropTarget 
 19  from muntjac.event.dd.target_details_impl import TargetDetailsImpl 
 20  from muntjac.ui.html5_file import Html5File 
 21  from muntjac.ui.custom_component import CustomComponent 
 22  from muntjac.terminal.gwt.client.mouse_event_details import MouseEventDetails 
 23   
 24  from muntjac.terminal.stream_variable import \ 
 25      (IStreamVariable, IStreamingEndEvent, IStreamingErrorEvent, 
 26      IStreamingProgressEvent, IStreamingStartEvent) 
 27   
 28   
 29  from muntjac.terminal.gwt.client.ui.dd.horizontal_drop_location import \ 
 30      HorizontalDropLocation 
 31   
 32  from muntjac.terminal.gwt.client.ui.dd.vertical_drop_location import \ 
 33      VerticalDropLocation 
34 35 36 -class DragAndDropWrapper(CustomComponent, IDropTarget, IDragSource):
37 38 CLIENT_WIDGET = None #ClientWidget(VDragAndDropWrapper, LoadStyle.EAGER) 39
40 - def __init__(self, root):
41 """Wraps given component in a L{DragAndDropWrapper}. 42 43 @param root: the component to be wrapped 44 """ 45 super(DragAndDropWrapper, self).__init__(root) 46 47 self._receivers = dict() 48 49 self._dragStartMode = DragStartMode.NONE 50 51 self._dropHandler = None
52 53
54 - def paintContent(self, target):
55 super(DragAndDropWrapper, self).paintContent(target) 56 target.addAttribute('dragStartMode', 57 DragStartMode.ordinal(self._dragStartMode)) 58 59 if self.getDropHandler() is not None: 60 self.getDropHandler().getAcceptCriterion().paint(target) 61 62 if self._receivers is not None and len(self._receivers) > 0: 63 for idd, html5File in self._receivers.iteritems(): 64 if html5File.getStreamVariable() is not None: 65 target.addVariable(self, 'rec-' + idd, 66 ProxyReceiver(html5File)) 67 # these are cleaned from receivers once the upload 68 # has started 69 else: 70 # instructs the client side not to send the file 71 target.addVariable(self, 'rec-' + idd, None) 72 # forget the file from subsequent paints 73 del self._receivers[idd]
74 75
76 - def getDropHandler(self):
77 return self._dropHandler
78 79
80 - def setDropHandler(self, dropHandler):
81 self._dropHandler = dropHandler 82 self.requestRepaint()
83 84
85 - def translateDropTargetDetails(self, clientVariables):
86 return WrapperTargetDetails(clientVariables, self)
87 88
89 - def getTransferable(self, rawVariables):
90 return WrapperTransferable(self, rawVariables)
91 92
93 - def setDragStartMode(self, dragStartMode):
94 self._dragStartMode = dragStartMode 95 self.requestRepaint()
96 97
98 - def getDragStartMode(self):
99 return self._dragStartMode
100
101 102 -class WrapperTransferable(TransferableImpl):
103
104 - def __init__(self, sourceComponent, rawVariables):
105 super(WrapperTransferable, self).__init__(sourceComponent, rawVariables) 106 107 self._files = None 108 109 fc = rawVariables.get('filecount') 110 if fc is not None: 111 self._files = [None] * fc 112 for i in range(fc): 113 fd = Html5File(rawVariables.get('fn%d' % i), # name 114 rawVariables.get('fs%d' % i), # size 115 rawVariables.get('ft%d' % i)) # mime 116 idd = rawVariables.get('fi%d' % i) 117 self._files[i] = fd 118 self._sourceComponent._receivers[idd] = fd 119 self._sourceComponent.requestRepaint() # paint receivers
120 121
122 - def getDraggedComponent(self):
123 """The component in wrapper that is being dragged or null if the 124 transferrable is not a component (most likely an html5 drag). 125 """ 126 return self.getData('component')
127 128
129 - def getMouseDownEvent(self):
130 """@return: the mouse down event that started the drag and drop 131 operation 132 """ 133 return MouseEventDetails.deSerialize(self.getData('mouseDown'))
134 135
136 - def getFiles(self):
137 return self._files
138 139
140 - def getText(self):
141 data = self.getData('Text') # IE, html5 142 143 if data is None: 144 # check for "text/plain" (webkit) 145 data = self.getData('text/plain') 146 147 return data
148 149
150 - def getHtml(self):
151 data = self.getData('Html') # IE, html5 152 153 if data is None: 154 # check for "text/plain" (webkit) 155 data = self.getData('text/html') 156 157 return data
158
159 160 -class WrapperTargetDetails(TargetDetailsImpl):
161
162 - def __init__(self, rawDropData, wrapper):
163 super(WrapperTargetDetails, self).__init__(rawDropData, wrapper)
164 165
166 - def getAbsoluteLeft(self):
167 """@return: the absolute position of wrapper on the page""" 168 return self.getData('absoluteLeft')
169 170
171 - def getAbsoluteTop(self):
172 """@return: the absolute position of wrapper on the page""" 173 return self.getData('absoluteTop')
174 175
176 - def getMouseEvent(self):
177 """@return: details about the actual event that caused the event 178 details. Practically mouse move or mouse up. 179 """ 180 return MouseEventDetails.deSerialize(self.getData('mouseEvent'))
181 182
183 - def getVerticalDropLocation(self):
184 """@return: a detail about the drags vertical position over the 185 wrapper. 186 """ 187 data = self.getData('verticalLocation') 188 return VerticalDropLocation.valueOf[data]
189 190
192 """@return: a detail about the drags horizontal position over the 193 wrapper. 194 """ 195 data = self.getData('horizontalLocation') 196 return HorizontalDropLocation.valueOf[data]
197 198
199 - def verticalDropLocation(self):
200 """@deprecated: use L{getVerticalDropLocation} instead""" 201 return self.getVerticalDropLocation()
202 203
204 - def horizontalDropLocation(self):
205 """@deprecated: use L{getHorizontalDropLocation} instead""" 206 return self.getHorizontalDropLocation()
207
208 209 -class DragStartMode(object):
210 #: L{DragAndDropWrapper} does not start drag events at all 211 NONE = 'NONE' 212 213 #: The component on which the drag started will be shown as drag image. 214 COMPONENT = 'COMPONENT' 215 216 #: The whole wrapper is used as a drag image when dragging. 217 WRAPPER = 'WRAPPER' 218 219 _values = [NONE, COMPONENT, WRAPPER] 220 221 @classmethod
222 - def values(cls):
223 return cls._values[:]
224 225 @classmethod
226 - def ordinal(cls, val):
227 return cls._values.index(val)
228
229 230 -class ProxyReceiver(IStreamVariable):
231
232 - def __init__(self, fd):
233 self._file = fd 234 self._listenProgressOfUploadedFile = None
235 236
237 - def getOutputStream(self):
238 if self._file.getStreamVariable() is None: 239 return None 240 return self._file.getStreamVariable().getOutputStream()
241 242
243 - def listenProgress(self):
244 return self._file.getStreamVariable().listenProgress()
245 246
247 - def onProgress(self, event):
248 wrapper = ReceivingEventWrapper(event, self._file, self) 249 self._file.getStreamVariable().onProgress(wrapper)
250 251
252 - def streamingStarted(self, event):
253 self._listenProgressOfUploadedFile = \ 254 self._file.getStreamVariable() is not None 255 256 if self._listenProgressOfUploadedFile: 257 wrapper = ReceivingEventWrapper(event, self._file, self) 258 self._file.getStreamVariable().streamingStarted(wrapper) 259 260 # no need tell to the client about this receiver on next paint 261 self.receivers.remove(self._file) 262 263 # let the terminal GC the stream variable and not to accept 264 # other file uploads to this variable 265 event.disposeStreamVariable()
266 267
268 - def streamingFinished(self, event):
269 if self._listenProgressOfUploadedFile: 270 wrapper = ReceivingEventWrapper(event, self._file, self) 271 self._file.getStreamVariable().streamingFinished(wrapper)
272 273
274 - def streamingFailed(self, event):
275 if self._listenProgressOfUploadedFile: 276 wrapper = ReceivingEventWrapper(event, self._file, self) 277 self._file.getStreamVariable().streamingFailed(wrapper)
278 279
280 - def isInterrupted(self):
281 return self._file.getStreamVariable().isInterrupted()
282
283 284 -class ReceivingEventWrapper(IStreamingErrorEvent, IStreamingEndEvent, 285 IStreamingStartEvent, IStreamingProgressEvent):
286 # With XHR2 file posts we can't provide as much information from the 287 # terminal as with multipart request. This helper class wraps the 288 # terminal event and provides the lacking information from the 289 # Html5File. 290
291 - def __init__(self, e, fd, receiver):
292 self._wrappedEvent = e 293 self._file = fd 294 self._receiver = receiver
295 296
297 - def getMimeType(self):
298 return self._file.getType()
299 300
301 - def getFileName(self):
302 return self._file.getFileName()
303 304
305 - def getContentLength(self):
306 return self._file.getFileSize()
307 308
309 - def getReceiver(self):
310 return self._receiver
311
312 - def getException(self):
313 if isinstance(self._wrappedEvent, IStreamingErrorEvent): 314 return self._wrappedEvent.getException() 315 return None
316 317
318 - def getBytesReceived(self):
319 return self._wrappedEvent.getBytesReceived()
320 321
322 - def disposeStreamVariable(self):
323 """Calling this method has no effect. DD files are receive only 324 once anyway. 325 """ 326 pass
327