Skip to content

Commit

Permalink
Example of use, plus re-work based on actually using the code...
Browse files Browse the repository at this point in the history
  • Loading branch information
corranwebster committed Aug 25, 2014
1 parent 757b820 commit 608d243
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 9 deletions.
89 changes: 80 additions & 9 deletions enable/tools/drop_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,110 @@

from __future__ import absolute_import, print_function, division

from traits.api import Enum

from enable.base_tool import BaseTool


class BaseDropTool(BaseTool):
""" Abstract base class for tools that handle drag and drop """

default_drag_result = Enum("copy", "move", "link", "cancel",
"error", "none")

def normal_drag_over(self, event):
""" Handle dragging over the component """
if event.handled:
return
try:
result = self.accepts_drop(event.obj)
self.component.window.set_drag_result(result)
result = self.get_drag_result((event.x, event.y), event.obj)
if result is not None:
self.component.window.set_drag_result(result)
event.handled = True
except Exception:
self.component.window.set_drag_result("error")
raise

def normal_dropped_on(self, event):
if self.accepts_drop(event.obj) != "none":
self.handle_drop(event.obj)
if event.handled:
return
position = (event.x, event.y)
if self.accept_drop(position, event.obj):
self.handle_drop(position, event.obj)
event.handled = True

def get_drag_result(self, position, obj):
""" The type of drag that will happen
By default, if the dragged objects are available this method calls
accept_drop() and returns "none" if the result is False, otherwise
it returns the value of default_drag_result.
Parameters
----------
position :
The coordinates of the drag over event
obj : any
The object(s) being dragged, if available. Some backends (such as
Wx) may not be able to provide the object being dragged, in which
case `obj` will be `None`.
Returns
-------
Either None, if the drop should be ignored by this tool and not
handled, or one of the keys of DRAG_RESULTS_MAP: "none", "copy, "move",
"link", "cancel" or "error".
"""
if obj is not None:
# if we have the object, see if we can accept
if not self.accept_drop(position, obj):
return None

def accepts_drop(self, urls):
""" Whether or not to accept the drag, and the type of drag
return self.default_drag_result

The return value is either "none", if the drag is refused for the
dragged object types, or one of "copy", "move", or "link".
def accept_drop(self, position, obj):
""" Whether or not to accept the drop
Subclasses should override this method.
Parameters
----------
position :
The coordinates of the drag over event
obj : any
The object(s) being dragged, if available. Some backends (such as
Wx) may not be able to provide the object being dragged, in which
case `obj` will be `None`.
Returns
-------
True if the drop should be accepted, False otherwise.
"""
raise NotImplementedError

def handle_drop(self, urls):
def handle_drop(self, position, obj):
""" Handle objects being dropped on the component
Subclasses should override this method.
Parameters
----------
position :
The coordinates of the drag over event
obj : any
The object(s) being dragged, if available. Some backends (such as
Wx) may not be able to provide the object being dragged, in which
case `obj` will be `None`.
"""
raise NotImplementedError
50 changes: 50 additions & 0 deletions examples/enable/tools/drop_tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
This demonstrates the use of the drop tool.
"""
from enable.example_support import DemoFrame, demo_main
from enable.api import Component, Container, Label, Window
from enable.tools.drop_tool import BaseDropTool

class Box(Component):

resizable = ""

def _draw_mainlayer(self, gc, view_bounds=None, mode="default"):
with gc:
gc.set_fill_color((1.0, 0.0, 0.0, 1.0))
dx, dy = self.bounds
x, y = self.position
gc.rect(x, y, dx, dy)
gc.fill_path()

class TextDropTool(BaseDropTool):
""" Example implementation of a drop tool """

def accept_drop(self, location, obj):
return True

def handle_drop(self, location, objs):
if not isinstance(objs, list):
objs = [objs]
x, y = location
for obj in objs:
label = Label(text=str(obj), position=[x, y], bounds=[100, 50])
self.component.add(label)
self.component.request_redraw()
y += 15


class MyFrame(DemoFrame):

def _create_window(self):
box = Box(bounds=[100.0, 100.0], position=[50.0, 50.0])
container = Container(bounds=[500,500])
container.add(box)
drop_tool = TextDropTool(component=container)
container.tools.append(drop_tool)
return Window(self, -1, component=container)

if __name__ == "__main__":
demo_main(MyFrame)

# EOF

0 comments on commit 608d243

Please sign in to comment.