Repository URL to install this package:
Version:
5.3.0 ▾
|
# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
"""
Shows how to implement a simple drag operation with transitory visual
side-effects that get cleaned up when the drag completes. There is a
filled container that contains two filled circles, each of which has a
different kind of "shadow" object that it dynamically adds to the
container when the user clicks and drags the circle around. Because
the shadow objects are "first-class" components in the filled container,
and because containers default to auto-sizing around their components,
the container stretches to the minimum bounding box of its components
as the user drags the circles around.
"""
from numpy import array
from traits.api import Any, Enum, Float, Instance, Tuple
from enable.api import Container, Component, Pointer
from enable.examples._example_support import DemoFrame, demo_main
from kiva.fonttools import str_to_font
class MyFilledContainer(Container):
fit_window = False
border_width = 2
resizable = ""
_font = Any
def _draw_container_mainlayer(self, gc, view_bounds, mode="default"):
'Draws a filled container with the word "Container" in the center'
if not self._font:
self._font = str_to_font("modern 10")
with gc:
gc.set_fill_color(self.bgcolor_)
gc.rect(self.x, self.y, self.width, self.height)
gc.draw_path()
self._draw_border(gc)
gc.set_font(self._font)
gc.set_fill_color((1.0, 1.0, 1.0, 1.0))
tx, ty, tw, th = gc.get_text_extent("Container")
tx = self.x + self.width / 2.0 - tw / 2.0
ty = self.y + self.height / 2.0 - th / 2.0
gc.show_text_at_point("Container", tx, ty)
class Circle(Component):
"""
The circle moves with the mouse cursor but leaves a translucent version of
itself in its original position until the mouse button is released.
"""
color = (0.6, 0.7, 1.0, 1.0)
bgcolor = "none"
normal_pointer = Pointer("arrow")
moving_pointer = Pointer("hand")
prev_x = Float
prev_y = Float
shadow_type = Enum("light", "dashed")
shadow = Instance(Component)
resizable = ""
def __init__(self, **traits):
Component.__init__(self, **traits)
self.pointer = self.normal_pointer
def _draw_mainlayer(self, gc, view_bounds=None, mode="default"):
with gc:
gc.set_fill_color(self.color)
dx, dy = self.bounds
x, y = self.position
radius = min(dx / 2.0, dy / 2.0)
gc.arc(x + dx / 2.0, y + dy / 2.0, radius, 0.0, 2 * 3.14159)
gc.fill_path()
def normal_left_down(self, event):
self.event_state = "moving"
self.pointer = self.moving_pointer
event.window.set_mouse_owner(self, event.net_transform())
# Create our shadow
if self.shadow_type == "light":
klass = LightCircle
else:
klass = DashedCircle
self.shadow = klass(
bounds=self.bounds,
position=self.position,
color=(1.0, 1.0, 1.0, 1.0),
)
self.container.insert(0, self.shadow)
x, y = self.position
self.prev_x = event.x
self.prev_y = event.y
def moving_mouse_move(self, event):
self.position = [
self.x + (event.x - self.prev_x),
self.y + (event.y - self.prev_y),
]
self.prev_x = event.x
self.prev_y = event.y
self.request_redraw()
def moving_left_up(self, event):
self.event_state = "normal"
self.pointer = self.normal_pointer
event.window.set_mouse_owner(None)
event.window.redraw()
# Remove our shadow
self.container.remove(self.shadow)
def moving_mouse_leave(self, event):
self.moving_left_up(event)
class LightCircle(Component):
color = Tuple
bgcolor = "none"
radius = Float(1.0)
resizable = ""
def _draw_mainlayer(self, gc, view_bounds=None, mode="default"):
with gc:
gc.set_fill_color(self.color[0:3] + (self.color[3] * 0.3,))
dx, dy = self.bounds
x, y = self.position
radius = min(dx / 2.0, dy / 2.0)
gc.arc(x + dx / 2.0, y + dy / 2.0, radius, 0.0, 2 * 3.14159)
gc.fill_path()
class DashedCircle(Component):
color = Tuple
bgcolor = "none"
radius = Float(1.0)
line_dash = array([2.0, 2.0])
resizable = ""
def _draw_mainlayer(self, gc, view_bounds=None, mode="default"):
with gc:
gc.set_fill_color(self.color)
dx, dy = self.bounds
x, y = self.position
radius = min(dx / 2.0, dy / 2.0)
gc.arc(x + dx / 2.0, y + dy / 2.0, radius, 0.0, 2 * 3.14159)
gc.set_stroke_color(self.color[0:3] + (self.color[3] * 0.8,))
gc.set_line_dash(self.line_dash)
gc.stroke_path()
class Demo(DemoFrame):
def _create_component(self):
circle1 = Circle(
bounds=[75, 75], position=[50, 50], shadow_type="dashed"
)
circle2 = Circle(
bounds=[75, 75], position=[200, 50], shadow_type="light"
)
container = MyFilledContainer(
bounds=[500, 500], bgcolor=(0.5, 0.5, 0.5, 1.0)
)
container.auto_size = True
container.add(circle1)
container.add(circle2)
return container
if __name__ == "__main__":
# Save demo so that it doesn't get garbage collected when run within
# existing event loop (i.e. from ipython).
demo = demo_main(Demo, title="Click and drag to move the circles")