Пример #1
0
class DragBox(Box):
    """A drag drawn box
    """

    ##########################################################################
    # Traits
    ##########################################################################

    ### 'DragBox' interface ############################################

    # Event fired when complete:
    complete = Event

    # Constraints on size:
    x_bounds = Trait(None, None, Tuple(Float, Float))
    y_bounds = Trait(None, None, Tuple(Float, Float))

    #### Pointers. ####

    # Pointer for the complete state:
    complete_pointer = Pointer('cross')

    # Pointer for the drawing state:
    drawing_pointer = Pointer('cross')

    # Pointer for the normal state:
    normal_pointer = Pointer('cross')

    #### Private traits

    # Position of the left down:
    start_x = Float
    start_y = Float

    ##########################################################################
    # 'object' interface
    ##########################################################################

    ##########################################################################
    # 'Component' interface
    ##########################################################################

    #### 'normal' state ######################################################

    def normal_left_down(self, event):
        """ Handle the left button down in the 'normal' state. """

        self.event_state = 'drawing'
        self.pointer = self.drawing_pointer

        self.start_x = event.x
        self.start_y = event.y
        self._set_bounds(event)

        return

    def normal_mouse_move(self, event):
        """ Handle the mouse moving in the 'normal' state. """

        self.pointer = self.normal_pointer

        return

    #### 'drawing' state #####################################################

    def drawing_mouse_move(self, event):
        """ Handle the mouse moving in the 'drawing' state. """

        self._set_bounds(event)

    def drawing_left_up(self, event):
        """ Handle the left mouse button coming up in the 'drawing' state. """

        self.event_state = 'complete'
        self.pointer = self.complete_pointer

        self.complete = True
        self._set_bounds(event)

        return

    ##########################################################################
    # Private interface
    ##########################################################################

    def _set_bounds(self, event):
        """
        Sets the bounds based on start_x, start_y, the event position
        and any constrants.
        """
        if self.x_bounds is not None:
            x, dx = self.x_bounds
        else:
            x = min(self.start_x, event.x)
            dx = abs(event.x - self.start_x)
        if self.y_bounds is not None:
            y, dy = self.y_bounds
        else:
            y = min(self.start_y, event.y)
            dy = abs(event.y - self.start_y)
        self.bounds = (x, y, dx, dy)
Пример #2
0
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ===============================================================================

# ============= enthought library imports =======================
from enable.enable_traits import Pointer
from traits.api import Enum, CArray
from chaco.tools.api import DragTool
# ============= standard library imports ========================
# ============= local library imports  ==========================
normal_pointer = Pointer('normal')
hand_pointer = Pointer('hand')


class PointMoveTool(DragTool):
    event_state = Enum("normal", "dragging")
    _prev_pt = CArray
    constrain = Enum(None, 'x', 'y')

    def is_draggable(self, x, y):
        return self.component.hittest((x, y))

    def drag_start(self, event):
        data_pt = self.component.map_data((event.x, event.y), all_values=True)
        self._prev_pt = data_pt
        event.handled = True
class Shape(Component):
    """ The base class for moveable shapes. """

    #### 'Component' interface ################################################

    # The background color of this component.
    bgcolor = 'transparent'

    #### 'Shape' interface ####################################################

    # The coordinates of the center of the shape.
    center = Property(Tuple)

    # The fill color.
    fill_color = ColorTrait

    # The pointer for the 'normal' event state.
    normal_pointer = Pointer('arrow')

    # The pointer for the 'moving' event state.
    moving_pointer = Pointer('hand')

    # The text color.
    text_color = ColorTrait

    # The text displayed in the shape.
    text = Str

    #### 'Private' interface ##################################################

    # The difference between the location of a mouse-click and the component's
    # origin.
    _offset_x = Float
    _offset_y = Float

    ###########################################################################
    # 'Interactor' interface
    ###########################################################################

    def normal_key_pressed(self, event):
        """ Event handler. """

        print('normal_key_pressed', event.character)

        return

    def normal_left_down(self, event):
        """ Event handler. """

        if self.is_in(event.x, event.y):
            self.event_state = 'moving'

            event.window.mouse_owner = self
            event.window.set_pointer(self.moving_pointer)

            self._offset_x = event.x - self.x
            self._offset_y = event.y - self.y

            # move this shape to the top of the z order. The components are
            # drawn in order, so the last one will be drawn on top
            siblings = self.container.components
            if len(siblings) > 1:
                siblings.remove(self)
                siblings.append(self)

        return

    def moving_mouse_move(self, event):
        """ Event handler. """

        top = event.y + self._offset_y
        bottom = event.y - self._offset_y
        left = event.x - self._offset_x
        right = event.x + self._offset_x

        # Keep the shape fully in the container

        if bottom < 0:
            bottom = 0
        elif top > self.container.height:
            bottom = self.container.height - self.height

        if left < 0:
            left = 0
        elif right > self.container.width:
            left = self.container.width - self.width

        self.position = [left, bottom]
        self.request_redraw()

        return

    def moving_left_up(self, event):
        """ Event handler. """

        self.event_state = 'normal'

        event.window.set_pointer(self.normal_pointer)
        event.window.mouse_owner = None

        self.request_redraw()

        return

    def moving_mouse_leave(self, event):
        """ Event handler. """

        self.moving_left_up(event)

        return

    ###########################################################################
    # 'Shape' interface
    ###########################################################################

    def _get_center(self):
        """ Property getter. """

        dx, dy = self.bounds
        ox, oy = self.position

        cx = ox + dx / 2
        cy = oy + dy / 2

        return cx, cy

    def _text_default(self):
        """ Trait initializer. """

        return type(self).__name__

    ###########################################################################
    # Protected 'Shape' interface
    ###########################################################################

    def _distance_between(self, xxx_todo_changeme, xxx_todo_changeme1):
        """ Return the distance between two points. """
        (x1, y1) = xxx_todo_changeme
        (x2, y2) = xxx_todo_changeme1
        return math.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2))

    def _draw_text(self, gc):
        """ Draw the shape's text. """

        if len(self.text) > 0:
            gc.set_fill_color(self._get_text_color(self.event_state))

            gc.set_font(Font(family=MODERN, size=16))
            tx, ty, tw, th = gc.get_text_extent(self.text)

            dx, dy = self.bounds
            x, y = self.position
            gc.set_text_position(x + (dx - tw) / 2, y + (dy - th) / 2)

            gc.show_text(self.text)

        return

    def _get_fill_color(self, event_state):
        """ Return the fill color based on the event state. """

        if event_state == 'normal':
            fill_color = self.fill_color_

        else:
            r, g, b, a = self.fill_color_
            fill_color = (r, g, b, 0.5)

        return fill_color

    def _get_text_color(self, event_state):
        """ Return the text color based on the event state. """

        if event_state == 'normal':
            text_color = self.text_color_

        else:
            r, g, b, a = self.text_color_
            text_color = (r, g, b, 0.5)

        return text_color
class DesignerExtractionLineCanvas2D(ExtractionLineCanvas2D):
    drag_pointer = Pointer('bullseye')
    snap_to_grid = True
    grid_interval = 0.5
    _constrain = False

    _px = None
    _py = None
    selected_item = None

    def drag_mouse_move(self, event):
        si = self.selected_item

        x, y = event.x, event.y
        dx, dy = self.map_data((x, y))
        w, h = si.width, si.height

        dx -= w / 2.
        dy -= h / 2.

        if self.snap_to_grid:
            dx, dy = snap_to_grid(dx, dy, interval=self.grid_interval)

        if event.shift_down:
            if self._px is not None and not self._constrain:
                xx = abs(x - self._px)
                yy = abs(y - self._py)
                self._constrain = 'v' if yy > xx else 'h'
            else:
                self._px = x
                self._py = y
        else:
            self._constrain = False
            self._px, self._py = None, None

        if self._constrain == 'h':
            si.x = dx
        elif self._constrain == 'v':
            si.y = dy
        else:
            si.x, si.y = dx, dy

        si.request_layout()
        self.invalidate_and_redraw()

    def drag_left_up(self, event):
        self._set_normal_state(event)

    def drag_mouse_leave(self, event):
        self._set_normal_state(event)

    def _set_normal_state(self, event):
        self.event_state = 'normal'
        event.window.set_pointer(self.normal_pointer)

    def select_left_down(self, event):
        self.event_state = 'drag'
        event.window.set_pointer(self.drag_pointer)

    def _over_item(self, event):
        x, y = event.x, event.y
        return next((item for item in self.scene.iteritems(klass=RoundedRectangle)
                     if hasattr(item, 'is_in') and \
                     item.is_in(x, y)), None)

    def normal_mouse_move(self, event):
        item = self._over_item(event)
        if item is not None:
            event.window.set_pointer(self.select_pointer)
            self.selected_item = item
            self.event_state = 'select'
        else:
            event.window.set_pointer(self.normal_pointer)
            self.selected_item = None
Пример #5
0
class ViewportPanTool(DragTool):
    """ A tool that enables the user to pan around a viewport by clicking a
    mouse button and dragging.
    """

    # The cursor to use when panning.
    drag_pointer = Pointer("hand")

    # Scaling factor on the panning "speed".
    speed = Float(1.0)

    # The modifier key that, if depressed when the drag is initiated, constrains
    # the panning to happen in the only direction of largest initial motion.
    # It is possible to permanently restrict this tool to always drag along one
    # direction.  To do so, set constrain=True, constrain_key=None, and
    # constrain_direction to the desired direction.
    constrain_key = Enum(None, "shift", "control", "alt")

    # Constrain the panning to one direction?
    constrain = Bool(False)

    # The direction of constrained draw. A value of None means that the user
    # has initiated the drag and pressed the constrain_key, but hasn't moved
    # the mouse yet; the magnitude of the components of the next mouse_move
    # event will determine the constrain_direction.
    constrain_direction = Enum(None, "x", "y")

    # (x,y) of the point where the mouse button was pressed.
    _original_xy = Tuple

    # Data coordinates of **_original_xy**.  This may be either (index,value)
    # or (value,index) depending on the component's orientation.
    _original_data = Tuple

    # Was constrain=True triggered by the **contrain_key**? If False, it was
    # set programmatically.
    _auto_constrain = Bool(False)

    #------------------------------------------------------------------------
    # Inherited BaseTool traits
    #------------------------------------------------------------------------

    # The tool is not visible (overrides BaseTool).
    visible = False

    def drag_start(self, event):
        self._original_xy = (event.x, event.y)
        if self.constrain_key is not None:
            if getattr(event, self.constrain_key + "_down"):
                self.constrain = True
                self._auto_constrain = True
                self.constrain_direction = None
        event.window.set_pointer(self.drag_pointer)
        event.window.set_mouse_owner(self, event.net_transform())
        event.handled = True
        return

    def dragging(self, event):
        """ Handles the mouse being moved when the tool is in the 'panning'
        state.
        """
        if self._auto_constrain and self.constrain_direction is None:
            # Determine the constraint direction
            if abs(event.x - self._original_xy[0]) > abs(event.y -
                                                         self._original_xy[1]):
                self.constrain_direction = "x"
            else:
                self.constrain_direction = "y"

        new_position = self.component.view_position[:]
        for direction, ndx in [("x", 0), ("y", 1)]:
            if self.constrain and self.constrain_direction != direction:
                continue

            origpos = self._original_xy[ndx]
            eventpos = getattr(event, direction)
            delta = self.speed * (eventpos - origpos)
            if self.component.enable_zoom:
                delta /= self.component.zoom
            new_position[ndx] -= delta

        if self.constrain:
            self.component.view_position[self.constrain_direction] = \
                        new_position[self.constrain_direction]
        else:
            self.component.view_position = new_position
        event.handled = True

        self._original_xy = (event.x, event.y)
        self.component.request_redraw()
        return

    def drag_end(self, event):
        if self._auto_constrain:
            self.constrain = False
            self.constrain_direction = None
        event.window.set_pointer("arrow")
        if event.window.mouse_owner == self:
            event.window.set_mouse_owner(None)
        event.handled = True
        return