class DNDHelper(object): """ DNDHelper is a singleton drag and drop agent. It acts as dragging/dropping agent for platforms that do not support html5 drag and drop. """ def __init__(self): self.dropTargets = [] self.dragging = NOT_DRAGGING self.dragBusy = False self._currentTargetElement = None self.previousDropTarget = None self.draggingImage = None self.origMouseX = 0 self.origMouseY = 0 self.currentDragOperation = 'none' self.data = None self.returnTimer = Timer(notify=self.onReturningWidget) self.mouseEvent = None self.dragDataStore = None def setCurrentTargetElement(self, element): if self._currentTargetElement is not None: if not DOM.compare(self._currentTargetElement, element): # leave_event = self.makeDragEvent(self.mouseEvent, 'dragleave', # self.currentTargetElement) self.fireDNDEvent('dragleave', self.currentTargetElement, self.currentDropWidget) # self.currentDropWidget.onDragLeave(leave_event) # self.finalize(leave_event) self._currentTargetElement = element def getCurrentTargetElement(self): return self._currentTargetElement currentTargetElement = property(getCurrentTargetElement, setCurrentTargetElement) def getElement(self): """ ie6 GlassWidget impl needs this """ return self.dragWidget.getElement() def updateDropEffect(self, dataTransfer, event_type): """ http://dev.w3.org/html5/spec/dnd.html#dragevent """ # default for dragstart, drag, dragleave dropEffect = 'none' if event_type in ['dragover', 'dragenter']: ea = dataTransfer.getEffectAllowed() if ea == 'none': dropEffect = 'none' elif ea.startswith('copy') or ea == 'all': dropEffect = 'copy' elif ea.startswith('link'): dropEffect = 'link' elif ea == 'move': dropEffect = 'move' else: dropEffect = 'copy' elif event_type in ['drop', 'dragend']: dropEffect = self.currentDragOperation dataTransfer.dropEffect = dropEffect def updateDragOperation(self, event): """ http://dev.w3.org/html5/spec/dnd.html """ dataTransfer = event.dataTransfer ea = dataTransfer.effectAllowed de = dataTransfer.dropEffect if (de == 'copy' and ea in ['uninitialized', 'copy', 'copyLink', 'copyMove', 'all']): self.currentDragOperation = 'copy' elif (de == 'link' and ea in ['uninitialized', 'link', 'copyLink', 'linkMove', 'all']): self.currentDragOperation = 'link' elif (de == 'move' and ea in ['uninitialized', 'move', 'copyMove', 'linkMove', 'all']): self.currentDragOperation = 'move' else: self.currentDragOperation = 'none' def updateAllowedEffects(self, drag_event): dt = drag_event.dataTransfer self.dragDataStore.allowed_effects_state = dt.effectAllowed def registerTarget(self, target): """ Rather than searching the entire document for drop target widgets and maybe drop targets within widgets, this implementation holds a list of widgets and searches only within this list for potential drop targets. """ if not target in self.dropTargets: self.dropTargets.append(target) def unregisterTarget(self, target): """ I dont know why, but a widget may no longer want to be registered as a drop target. """ while target in self.dropTargets: self.dropTargets.remove(target) def setDragImage(self, element, x, y): position_absolute = DOM.getStyleAttribute(element, 'position') == 'absolute' if position_absolute: self.dragLeftOffset = x + DOM.getAbsoluteLeft(element.offsetParent) self.dragTopOffset = y + DOM.getAbsoluteTop(element.offsetParent) else: self.dragLeftOffset = x self.dragTopOffset = y if element.tagName.lower().endswith('img'): src = DOM.getAttribute(element, 'src') element = DOM.createElement('img') DOM.setAttribute(element, 'src', src) if not self.draggingImage: self.createDraggingImage(element) else: self.draggingImage.setImage(element) def addFeedbackElement(self, element): """ This is called from DataTransfer """ if self.draggingImage: self.draggingImage.addElement(element) else: self.createDraggingImage(element) def createDraggingImage(self, element): self.draggingImage = DraggingWidget(element) return self.draggingImage def setDragImageLocation(self, x, y): """ Move the dragging image around. """ elt_top = y - self.dragTopOffset elt_left = x - self.dragLeftOffset # if self.absParent: # ap = self.absParent # elt_top -= int(self.absTop) # elt_left -= int(self.absLeft) self.draggingImage.setStyleAttribute('top', elt_top) self.draggingImage.setStyleAttribute('left', elt_left) def getAbsoluteLeft(self): """ GlassWidget wants this """ # return 0 # if self.absParent: # return self.absParent.getAbsoluteLeft() return self.dragWidget.getAbsoluteLeft() #return self.origLeft def getAbsoluteTop(self): """ GlassWidget wants this """ # return 0 # if self.absParent: # return self.absParent.getAbsoluteTop() return self.dragWidget.getAbsoluteTop() #return self.origTop def makeDragEvent(self, event, type, target=None): dt = DataTransfer(self.dragDataStore) self.updateDropEffect(dt, type) drag_event = DragEvent(event, type, dt, target) return drag_event def finalize(self, event): self.dragDataStore.allowed_effects_state = \ event.dataTransfer.effectAllowed if event.type in ['dragstart', 'drop']: self.dragDataStore.setMode(PROTECTED) event.dataTransfer.dataStore = None def fireDNDEvent(self, name, target, widget): if name == 'dragstart': self.dragDataStore.setMode(READ_WRITE) elif name == 'drop': self.dragDataStore.setMode(READ_ONLY) event = self.makeDragEvent(self.mouseEvent, name, target) widget.onBrowserEvent(event) self.finalize(event) return event def initFeedbackImage(self): ds = self.dragDataStore x = 0 y = 0 if ds.bitmap is not None: if ds.hotspot_coordinate is not None: offset = ds.hotspot_coordinate x = offset[0] y = offset[1] self.setDragImage(ds.bitmap, x, y) return if self.dragDataStore.elements: for element in self.dragDataStore.elements: self.addFeedbackElement(element) def onMouseMove(self, sender, x, y): event = DOM.eventGetCurrentEvent() self.mouseEvent = event button = DOM.eventGetButton(event) if not button == Event.BUTTON_LEFT: return ## The following commented code lets the native dnd happen in IE. sucks. ## But it may enable dragging our widgets out of IE into other apps. # else: # try: # self.dragWidget.getElement().dragDrop() # return # except: # pass # Adjust x and y to absolute coordinates. x, y = eventCoordinates(event) if self.dragging == DRAGGING_NO_MOVEMENT_YET: self.origMouseX = x self.origMouseY = y self.currentDragOperation = 'none' fromElement = self.dragWidget.getElement() # Is the widget itself draggable? try: draggable = fromElement.draggable except: draggable = False # if not, find the draggable element at (x, y) in the widget if not draggable: fromElement = findDraggable(sender.getElement(), self.origMouseX, self.origMouseY) # Nothing draggable found. return. if fromElement is None: self.dragging = NOT_DRAGGING return # Get the location for the dragging widget #self.absParent = None #self.absParent = self.dragWidget.getParent() #self.absLeft = DOM.getStyleAttribute(fromElement, 'left') #print self.absLeft #self.absTop = DOM.getStyleAttribute(fromElement, 'top') #print self.absTop #self.origTop = DOM.getAbsoluteTop(fromElement) + parent.getAbsoluteTop() #self.origLeft = DOM.getAbsoluteLeft(fromElement) + parent.getAbsoluteLeft() self.origTop = DOM.getAbsoluteTop(fromElement) self.origLeft = DOM.getAbsoluteLeft(fromElement) #self.glassTop = DOM.getAbsoluteTop(fromElement.offsetParent) #self.glassLeft = DOM.getAbsoluteTop(fromElement.offsetParent) position_absolute = DOM.getStyleAttribute(fromElement, 'position') == 'absolute' if position_absolute: self.dragLeftOffset = ( self.origMouseX - DOM.getAbsoluteLeft(fromElement.offsetParent)) self.dragTopOffset = ( self.origMouseY - DOM.getAbsoluteTop(fromElement.offsetParent)) else: self.dragLeftOffset = self.origMouseX - self.origLeft self.dragTopOffset = self.origMouseY - self.origTop # self.setDragImage(fromElement, # self.origMouseX - self.origLeft, # self.origMouseY - self.origTop) self.dragDataStore.elements = [fromElement] dragStartEvent = self.fireDNDEvent('dragstart', None, self.dragWidget) if not isCanceled(dragStartEvent): self.initFeedbackImage() RootPanel().add(self.draggingImage) self.setDragImageLocation(x, y) self.dragging = ACTIVELY_DRAGGING GlassWidget.show(self) elif self.dragging == ACTIVELY_DRAGGING: try: doc().selection.empty() except: wnd().getSelection().removeAllRanges() self.setDragImageLocation(x, y) # If we are still working on the previous iteration, or if we have # done this recently, we'll wait for the next event. if self.dragBusy or time.time() - self.drag_time < 0.25: return self.doDrag(event, x, y) self.drag_time = time.time() def doDrag(self, event, x, y): self.dragBusy = True #self.dragDataStore.dropEffect = 'none' drag_event = self.fireDNDEvent('drag', None, self.dragWidget) # drag event was not canceled if not isCanceled(drag_event): target = None widget = None # Find the most specific element under the cursor and the widget # with the drop listener for it. for widget in self.dropTargets: target = getElementUnderMouse(widget, x, y) if target is not None: break if target: drop_widget = widget drop_element = target if (not self.currentTargetElement or not DOM.compare( drop_element, self.currentTargetElement)): # enter_event = self.makeDragEvent(event,'dragenter', # drop_element) enter_event = self.fireDNDEvent('dragenter', drop_element, drop_widget) # drop_widget.onDragEnter(enter_event) # self.finalize(enter_event) if isCanceled(enter_event): self.currentTargetElement = drop_element self.currentDropWidget = drop_widget if self.currentTargetElement is not None: # disable dropping if over event is not canceled # over_event = self.makeDragEvent(event, 'dragover', # drop_element) over_event = self.fireDNDEvent('dragover', drop_element, self.currentDropWidget) # self.currentDropWidget.onDragOver(over_event) # self.finalize(over_event) if isCanceled(over_event): self.updateDragOperation(over_event) else: self.currentDragOperation = 'none' self.draggingImage.updateCursor(self.currentDragOperation) else: self.currentTargetElement = None else: self.currentDragOperation = 'none' self.dragBusy = False def onMouseDown(self, sender, x, y): self.dragWidget = sender event = DOM.eventGetCurrentEvent() self.mouseEvent = event button = DOM.eventGetButton(event) if button != Event.BUTTON_LEFT: return # x, y = eventCoordinates(event) # self.origMouseX = x # self.origMouseY = y self.dragging = DRAGGING_NO_MOVEMENT_YET self.drag_time = time.time() self.dragDataStore = DragDataStore() def onMouseUp(self, sender, x, y): # event = DOM.eventGetCurrentEvent() self.dragging = NOT_DRAGGING if self.draggingImage: GlassWidget.hide() if (self.currentDragOperation == 'none' or not self.currentTargetElement): if self.currentTargetElement: # leave_event = self.makeDragEvent(event, 'dragleave', # self.currentTargetElement) self.fireDNDEvent('dragleave', self.currentTargetElement, self.currentDropWidget) # self.currentDropWidget.onDragLeave(leave_event) # self.finalize(leave_event) else: self.currentDragOperation = 'none' self.returnDrag() else: # self.dragDataStore.mode = READ_ONLY # drop_event = self.makeDragEvent(event, 'drop', # self.currentTargetElement) drop_event = self.fireDNDEvent('drop', self.currentTargetElement, self.currentDropWidget) #self.dropEffect = self.currentDragOperation # self.currentDropWidget.onDrop(drop_event) # self.finalize(drop_event) if isCanceled(drop_event): self.currentDragOperation = drop_event.dataTransfer.dropEffect else: self.currentDragOperation = 'none' self.zapDragImage() #self.dropEffect = self.currentDragOperation self.fireDNDEvent('dragend', None, self.dragWidget) # dragEnd_event = self.makeDragEvent(event, 'dragend') # self.dragWidget.onDragEnd(dragEnd_event) # self.finalize(dragEnd_event) def zapDragImage(self): RootPanel().remove(self.draggingImage) self.draggingImage = None def returnDrag(self): self.moveItemTo(self.draggingImage, self.origLeft, self.origTop) def returnXY(self, start, destination, count): start_x, start_y = start destination_x, destination_y = destination diff_x = (start_x - destination_x) / count diff_y = (start_y - destination_y) / count while (abs(start_x - destination_x) > 10 or abs(start_y - destination_y) > 10): start_x -= diff_x start_y -= diff_y yield start_x, start_y raise StopIteration def onReturningWidget(self, timer): try: next_loc = self.return_iterator.next() except StopIteration: self.zapDragImage() return x, y = next_loc self.draggingImage.setStyleAttribute('top', str(y)) self.draggingImage.setStyleAttribute('left', str(x)) self.returnTimer.schedule(50) def moveItemTo(self, widget, x, y): self.returnWidget = widget returnWidgetDestination = x, y widgetStart = widget.getAbsoluteLeft(), widget.getAbsoluteTop() self.return_iterator = self.returnXY(widgetStart, returnWidgetDestination, 10) self.returnTimer.schedule(50) def onMouseEnter(self, sender): pass def onMouseLeave(self, sender): if self.dragging == DRAGGING_NO_MOVEMENT_YET: self.dragging = NOT_DRAGGING def onMouseGlassEnter(self, sender): pass def onMouseGlassLeave(self, sender): pass
class DNDHelper(object): """ DNDHelper is a singleton drag and drop agent. It acts as dragging/dropping agent for platforms that do not support html5 drag and drop. """ def __init__(self): self.dropTargets = [] self.dragging = NOT_DRAGGING self.dragBusy = False self._currentTargetElement = None self.previousDropTarget = None self.draggingImage = None self.origMouseX = 0 self.origMouseY = 0 self.currentDragOperation = 'none' self.data = None self.returnTimer = Timer(notify=self.onReturningWidget) self.mouseEvent = None self.dragDataStore = None def setCurrentTargetElement(self, element): if self._currentTargetElement is not None: if not DOM.compare(self._currentTargetElement, element): # leave_event = self.makeDragEvent(self.mouseEvent, 'dragleave', # self.currentTargetElement) self.fireDNDEvent('dragleave', self.currentTargetElement, self.currentDropWidget) # self.currentDropWidget.onDragLeave(leave_event) # self.finalize(leave_event) self._currentTargetElement = element def getCurrentTargetElement(self): return self._currentTargetElement currentTargetElement = property(getCurrentTargetElement, setCurrentTargetElement) def getElement(self): """ ie6 GlassWidget impl needs this """ return self.dragWidget.getElement() def updateDropEffect(self, dataTransfer, event_type): """ http://dev.w3.org/html5/spec/dnd.html#dragevent """ # default for dragstart, drag, dragleave dropEffect='none' if event_type in ['dragover', 'dragenter']: ea = dataTransfer.getEffectAllowed() if ea == 'none': dropEffect = 'none' elif ea.startswith('copy') or ea == 'all': dropEffect = 'copy' elif ea.startswith('link'): dropEffect = 'link' elif ea == 'move': dropEffect = 'move' else: dropEffect = 'copy' elif event_type in ['drop', 'dragend']: dropEffect = self.currentDragOperation dataTransfer.dropEffect = dropEffect def updateDragOperation(self, event): """ http://dev.w3.org/html5/spec/dnd.html """ dataTransfer = event.dataTransfer ea = dataTransfer.effectAllowed de = dataTransfer.dropEffect if (de == 'copy' and ea in ['uninitialized', 'copy','copyLink', 'copyMove', 'all']): self.currentDragOperation = 'copy' elif (de == 'link' and ea in ['uninitialized', 'link', 'copyLink', 'linkMove', 'all']): self.currentDragOperation = 'link' elif (de == 'move' and ea in ['uninitialized', 'move', 'copyMove', 'linkMove', 'all']): self.currentDragOperation = 'move' else: self.currentDragOperation = 'none' def updateAllowedEffects(self, drag_event): dt = drag_event.dataTransfer self.dragDataStore.allowed_effects_state = dt.effectAllowed def registerTarget(self, target): """ Rather than searching the entire document for drop target widgets and maybe drop targets within widgets, this implementation holds a list of widgets and searches only within this list for potential drop targets. """ if not target in self.dropTargets: self.dropTargets.append(target) def unregisterTarget(self, target): """ I dont know why, but a widget may no longer want to be registered as a drop target. """ while target in self.dropTargets: self.dropTargets.remove(target) def setDragImage(self, element, x, y): position_absolute = DOM.getStyleAttribute(element, 'position') == 'absolute' if position_absolute: self.dragLeftOffset = x + DOM.getAbsoluteLeft( element.offsetParent) self.dragTopOffset = y + DOM.getAbsoluteTop( element.offsetParent) else: self.dragLeftOffset = x self.dragTopOffset = y if element.tagName.lower().endswith('img'): src = DOM.getAttribute(element,'src') element = DOM.createElement('img') DOM.setAttribute(element, 'src', src) if not self.draggingImage: self.createDraggingImage(element) else: self.draggingImage.setImage(element) def addFeedbackElement(self, element): """ This is called from DataTransfer """ if self.draggingImage: self.draggingImage.addElement(element) else: self.createDraggingImage(element) def createDraggingImage(self, element): self.draggingImage = DraggingWidget(element) return self.draggingImage def setDragImageLocation(self, x, y): """ Move the dragging image around. """ elt_top = y - self.dragTopOffset elt_left = x - self.dragLeftOffset # if self.absParent: # ap = self.absParent # elt_top -= int(self.absTop) # elt_left -= int(self.absLeft) self.draggingImage.setStyleAttribute('top', elt_top ) self.draggingImage.setStyleAttribute('left', elt_left) def getAbsoluteLeft(self): """ GlassWidget wants this """ # return 0 # if self.absParent: # return self.absParent.getAbsoluteLeft() return self.dragWidget.getAbsoluteLeft() #return self.origLeft def getAbsoluteTop(self): """ GlassWidget wants this """ # return 0 # if self.absParent: # return self.absParent.getAbsoluteTop() return self.dragWidget.getAbsoluteTop() #return self.origTop def makeDragEvent(self, event, type, target=None): dt = DataTransfer(self.dragDataStore) self.updateDropEffect(dt, type) drag_event = DragEvent(event, type, dt, target) return drag_event def finalize(self, event): self.dragDataStore.allowed_effects_state = \ event.dataTransfer.effectAllowed if event.type in ['dragstart', 'drop']: self.dragDataStore.setMode(PROTECTED) event.dataTransfer.dataStore = None def fireDNDEvent(self, name, target, widget): if name == 'dragstart': self.dragDataStore.setMode(READ_WRITE) elif name == 'drop': self.dragDataStore.setMode(READ_ONLY) event = self.makeDragEvent(self.mouseEvent, name, target) widget.onBrowserEvent(event) self.finalize(event) return event def initFeedbackImage(self): ds = self.dragDataStore x = 0 y = 0 if ds.bitmap is not None: if ds.hotspot_coordinate is not None: offset = ds.hotspot_coordinate x = offset[0] y = offset[1] self.setDragImage(ds.bitmap, x, y) return if self.dragDataStore.elements: for element in self.dragDataStore.elements: self.addFeedbackElement(element) def onMouseMove(self, sender, x, y): event = DOM.eventGetCurrentEvent() self.mouseEvent = event button = DOM.eventGetButton(event) if not button == Event.BUTTON_LEFT: return ## The following commented code lets the native dnd happen in IE. sucks. ## But it may enable dragging our widgets out of IE into other apps. # else: # try: # self.dragWidget.getElement().dragDrop() # return # except: # pass # Adjust x and y to absolute coordinates. x, y = eventCoordinates(event) if self.dragging == DRAGGING_NO_MOVEMENT_YET: self.origMouseX = x self.origMouseY = y self.currentDragOperation = 'none' fromElement = self.dragWidget.getElement() # Is the widget itself draggable? try: draggable = fromElement.draggable except: draggable = False # if not, find the draggable element at (x, y) in the widget if not draggable: fromElement = findDraggable(sender.getElement(), self.origMouseX, self.origMouseY) # Nothing draggable found. return. if fromElement is None: self.dragging = NOT_DRAGGING return # Get the location for the dragging widget #self.absParent = None #self.absParent = self.dragWidget.getParent() #self.absLeft = DOM.getStyleAttribute(fromElement, 'left') #print self.absLeft #self.absTop = DOM.getStyleAttribute(fromElement, 'top') #print self.absTop #self.origTop = DOM.getAbsoluteTop(fromElement) + parent.getAbsoluteTop() #self.origLeft = DOM.getAbsoluteLeft(fromElement) + parent.getAbsoluteLeft() self.origTop = DOM.getAbsoluteTop(fromElement) self.origLeft = DOM.getAbsoluteLeft(fromElement) #self.glassTop = DOM.getAbsoluteTop(fromElement.offsetParent) #self.glassLeft = DOM.getAbsoluteTop(fromElement.offsetParent) position_absolute = DOM.getStyleAttribute(fromElement, 'position') == 'absolute' if position_absolute: self.dragLeftOffset = (self.origMouseX - DOM.getAbsoluteLeft(fromElement.offsetParent)) self.dragTopOffset = (self.origMouseY - DOM.getAbsoluteTop(fromElement.offsetParent)) else: self.dragLeftOffset = self.origMouseX - self.origLeft self.dragTopOffset = self.origMouseY - self.origTop # self.setDragImage(fromElement, # self.origMouseX - self.origLeft, # self.origMouseY - self.origTop) self.dragDataStore.elements = [fromElement] dragStartEvent = self.fireDNDEvent('dragstart', None, self.dragWidget) if not isCanceled(dragStartEvent): self.initFeedbackImage() RootPanel().add(self.draggingImage) self.setDragImageLocation(x, y) self.dragging = ACTIVELY_DRAGGING GlassWidget.show(self) elif self.dragging == ACTIVELY_DRAGGING: try: doc().selection.empty() except: wnd().getSelection().removeAllRanges() self.setDragImageLocation(x, y) # If we are still working on the previous iteration, or if we have # done this recently, we'll wait for the next event. if self.dragBusy or time.time() - self.drag_time < 0.25: return self.doDrag(event, x, y) self.drag_time = time.time() def doDrag(self, event, x, y): self.dragBusy = True #self.dragDataStore.dropEffect = 'none' drag_event = self.fireDNDEvent('drag', None, self.dragWidget) # drag event was not canceled if not isCanceled(drag_event): target = None widget = None # Find the most specific element under the cursor and the widget # with the drop listener for it. for widget in self.dropTargets: target = getElementUnderMouse(widget, x, y) if target is not None: break if target: drop_widget = widget drop_element = target if (not self.currentTargetElement or not DOM.compare(drop_element, self.currentTargetElement)): # enter_event = self.makeDragEvent(event,'dragenter', # drop_element) enter_event = self.fireDNDEvent('dragenter', drop_element, drop_widget) # drop_widget.onDragEnter(enter_event) # self.finalize(enter_event) if isCanceled(enter_event): self.currentTargetElement = drop_element self.currentDropWidget = drop_widget if self.currentTargetElement is not None: # disable dropping if over event is not canceled # over_event = self.makeDragEvent(event, 'dragover', # drop_element) over_event = self.fireDNDEvent('dragover', drop_element, self.currentDropWidget) # self.currentDropWidget.onDragOver(over_event) # self.finalize(over_event) if isCanceled(over_event): self.updateDragOperation(over_event) else: self.currentDragOperation = 'none' self.draggingImage.updateCursor(self.currentDragOperation) else: self.currentTargetElement = None else: self.currentDragOperation = 'none' self.dragBusy = False def onMouseDown(self, sender, x, y): self.dragWidget = sender event = DOM.eventGetCurrentEvent() self.mouseEvent = event button = DOM.eventGetButton(event) if button != Event.BUTTON_LEFT: return # x, y = eventCoordinates(event) # self.origMouseX = x # self.origMouseY = y self.dragging = DRAGGING_NO_MOVEMENT_YET self.drag_time = time.time() self.dragDataStore = DragDataStore() def onMouseUp(self, sender, x, y): # event = DOM.eventGetCurrentEvent() self.dragging = NOT_DRAGGING if self.draggingImage: GlassWidget.hide() if (self.currentDragOperation == 'none' or not self.currentTargetElement): if self.currentTargetElement: # leave_event = self.makeDragEvent(event, 'dragleave', # self.currentTargetElement) self.fireDNDEvent('dragleave', self.currentTargetElement, self.currentDropWidget) # self.currentDropWidget.onDragLeave(leave_event) # self.finalize(leave_event) else: self.currentDragOperation = 'none' self.returnDrag() else: # self.dragDataStore.mode = READ_ONLY # drop_event = self.makeDragEvent(event, 'drop', # self.currentTargetElement) drop_event = self.fireDNDEvent('drop', self.currentTargetElement, self.currentDropWidget) #self.dropEffect = self.currentDragOperation # self.currentDropWidget.onDrop(drop_event) # self.finalize(drop_event) if isCanceled(drop_event): self.currentDragOperation = drop_event.dataTransfer.dropEffect else: self.currentDragOperation = 'none' self.zapDragImage() #self.dropEffect = self.currentDragOperation self.fireDNDEvent('dragend', None, self.dragWidget) # dragEnd_event = self.makeDragEvent(event, 'dragend') # self.dragWidget.onDragEnd(dragEnd_event) # self.finalize(dragEnd_event) def zapDragImage(self): RootPanel().remove(self.draggingImage) self.draggingImage = None def returnDrag(self): self.moveItemTo(self.draggingImage,self.origLeft, self.origTop) def returnXY(self, start, destination, count): start_x, start_y = start destination_x, destination_y = destination diff_x = (start_x - destination_x) / count diff_y = (start_y - destination_y) / count while (abs(start_x - destination_x) > 10 or abs(start_y - destination_y) > 10): start_x -= diff_x start_y -= diff_y yield start_x, start_y raise StopIteration def onReturningWidget(self, timer): try: next_loc = self.return_iterator.next() except StopIteration: self.zapDragImage() return x, y = next_loc self.draggingImage.setStyleAttribute('top', str(y)) self.draggingImage.setStyleAttribute('left', str(x)) self.returnTimer.schedule(50) def moveItemTo(self, widget, x, y): self.returnWidget = widget returnWidgetDestination = x, y widgetStart = widget.getAbsoluteLeft(), widget.getAbsoluteTop() self.return_iterator = self.returnXY(widgetStart, returnWidgetDestination, 10) self.returnTimer.schedule(50) def onMouseEnter(self, sender): pass def onMouseLeave(self, sender): if self.dragging == DRAGGING_NO_MOVEMENT_YET: self.dragging = NOT_DRAGGING def onMouseGlassEnter(self, sender): pass def onMouseGlassLeave(self, sender): pass
def createDraggingImage(self, element): self.draggingImage = DraggingWidget(element) return self.draggingImage