Exemple #1
0
    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 )
Exemple #2
0
    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 )
Exemple #3
0
    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
Exemple #4
0
 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 ) )