def init( self, component, bounds_rect, anchor, unconstrain, drag_event, start_event ): self.component = component self.bounds_rect = bounds_rect self.anchor = anchor self.unconstrain = unconstrain self.drag_event = drag_event self.start_event = start_event self.drag_x = self.start_x = start_event.x self.drag_y = self.start_y = start_event.y # Get the coordinates of the anchor point: xl, yb, xr, yt = bounds_to_coordinates( component.bounds ) if (anchor & LEFT) != 0: self.anchor_x = xl self.float_x = xr else: self.anchor_x = xr self.float_x = xl if (anchor & BOTTOM) != 0: self.anchor_y = yb self.float_y = yt else: self.anchor_y = yt self.float_y = yb # Set up the drag termination handler: self.on_trait_change( self.drag_done, drag_event )
def _mouse_move_changed ( self, event ): # Get the current drag location: x = event.x y = event.y # If the mouse did not actually move, then ignore the event: if (x == self.drag_x) and (y == self.drag_y): return # Save the new position: self.drag_x = x self.drag_y = y # Calculate the distance moved from the original starting point: dx = x - self.start_x dy = y - self.start_y # Calculate the new drag bounds: xl, yb, xr, yt = add_rectangles( self.drag_bounds_rect_start, ( dx, dy, dx, dy ) ) # Adjust the new drag location if it is not completely within the drag # bounds. Exit if the result is the same as the previous location: if self.bounds_rect is not None: bxl, byb, bxr, byt = self.bounds_rect if xl < bxl: xr += bxl - xl xl = bxl elif xr > bxr: xl -= xr - bxr xr = bxr if yb < byb: yt += byb - yb yb = byb elif yt > byt: yb -= yt - byt yt = byt x = xl - self.drag_bounds_rect[0] + self.drag_x y = yb - self.drag_bounds_rect[1] + self.drag_y # If the new drag bounds is the same as the last one, nothing changed: drag_bounds_rect = bounds_to_coordinates( self.drag_validate( event, ( xl, yb, xr - xl, yt - yb ) ) ) if drag_bounds_rect == self.drag_bounds_rect: return # Update the drag bounds and current drag location: self.drag_bounds_rect = drag_bounds_rect # Notify each drag component of its new drag location: dx = drag_bounds_rect[0] - self.drag_bounds_rect_start[0] dy = drag_bounds_rect[1] - self.drag_bounds_rect_start[1] for component in self.components: cx, cy = component.location() component.dragged = DragEvent( x = cx + dx, y = cy + dy, x0 = self.start_x, y0 = self.start_y, copy = self.drag_copy, components = self.components, start_event = self.start_event, window = event.window ) # Process the 'drag_over' events for any objects being dragged over: drag_over_event = DragEvent( x = x, y = y, x0 = self.start_x, y0 = self.start_y, copy = self.drag_copy, components = self.components, start_event = self.start_event, window = event.window ) new_drag_over = [] cur_drag_over = self.drag_over for component in self.drag_root.components_at( x, y ): new_drag_over.append( component ) if component in cur_drag_over: cur_drag_over.remove( component ) component.drag_over = drag_over_event else: component.drag_enter = drag_over_event for component in cur_drag_over: component.drag_leave = drag_over_event self.drag_over = new_drag_over # Tell the Enable window where the drag is now: self.window.set_drag_bounds_rect( drag_bounds_rect )
def drag_done ( self, event ): components = self.components drag_copy = self.drag_copy start_event = self.start_event # 'Unhook' the drag done notification handler: self.on_trait_change( self.drag_done, self.drag_event, remove = True ) # Compute the new drag bounds: x = event.x y = event.y dx = x - self.start_x dy = y - self.start_y xl, yb, xr, yt = add_rectangles( self.drag_bounds_rect_start, ( dx, dy, dx, dy ) ) drag_bounds_rect = bounds_to_coordinates( self.drag_validate( event, ( xl, yb, xr - xl, yt - yb ) ) ) # If the new bounds are not within the drag area, use the last drag # location: if ((self.bounds_rect is not None) and (intersect_coordinates( self.bounds_rect, drag_bounds_rect ) != drag_bounds_rect)): drag_bounds_rect = self.drag_bounds_rect # Notify each dragged component where it was dropped: dx = drag_bounds_rect[0] - self.drag_bounds_rect_start[0] dy = drag_bounds_rect[1] - self.drag_bounds_rect_start[1] for component in components: cx, cy = component.location() component.dropped = DragEvent( x = cx + dx, y = cy + dy, x0 = self.start_x, y0 = self.start_y, copy = drag_copy, components = components, start_event = start_event, window = event.window ) # Process the 'dropped_on' event for the object(s) it was dropped on: components_at = self.drag_root.components_at( x, y ) drag_event = DragEvent( x = self.start_x + dx, y = self.start_y + dy, x0 = self.start_x, y0 = self.start_y, copy = drag_copy, components = components, start_event = start_event, window = event.window ) index = send_event_to( components_at, 'dropped_on', drag_event ) # Send all the runner-ups a 'drag_leave' consolation prize: drag_over = self.drag_over for component in components_at[ 0: index ]: if component in drag_over: component.drag_leave = drag_event # Make sure all of the dragged components are drawable again: if not drag_copy: for component in components: component._drawable = True # Redraw the window to clean-up any drag artifacts: self.window.redraw() # Finally, release any references we have been using: self.components[:] = [] self.drag_over = self.drag_root = self.window = None
def _needs_redraw(self, bounds): "Determine if a specified region intersects the update region" return does_disjoint_intersect_coordinates( self._update_region, bounds_to_coordinates( bounds ) )