I'll try to take your questions in order:
Naturally, I immediately tried to run the demo you attached. It
presented a tree display which seemed quite functional, other than that
it does not seem to respond to drag attempts at all. It issues "invalid
tree item" messages for each attempt.
The sample I attached does not accept outside data. Since I am trying to
figure out selective dragging between tree nodes of different types, that
example allows you to drag any tree node and drop it only on the
"Collection" nodes. It doesn't accept any other kind of data. I can't seem
to get the "invalid tree item" message you mention, so am not sure what you
are referring to there. Could that be platform-related?
In what sort of environment are you working? What OS, Python, and
wxWindows versions are you using?
OS is Windows 2000. Python is version 2.2. wxPython version is 2.4.1.2.
Are you interested in dragging items within the tree, or dropping items
from other applications, or both?
My particular interest is dragging within the tree only, at least until I
get it figured out. In my application, I use the tree control to represent
a hierarchical data structure, and use drag-and-drop within the tree to
implement a variety of different data manipulations. For example, you can
copy data between parallel nodes, which will trigger the copying of records
in the database and the corresponding addition of nodes in the tree. You
can also drag one type of node onto another as a way of signalling that the
one should be "applied to" the other, which would trigger a new record in
the database that would not be reflected in the tree because it's not a
relationship that is represented visually. So I need to know what kind of
node is being dragged and what kind of node is receiving the drop, and I
need to provide feedback to the user about when drops are legal and when
they aren't. So what I'm working on as a simplified example, which you see
the first iteration of, is something with "series" nodes and "collection"
nodes, and I am trying to enable the dragging of series nodes only onto
collection nodes and the dragging of collection nodes only onto series
nodes. I figure once I've got that figured out, I can develop everything I
need to to write that part of my application. I've got an example finished
that implements the drag-drop behavior and user feedback I want, which I
will post to the wxPython wiki (under wxTreeCtrl) within the next few hours.
I do note that in MainWindow.OnBeginDrag(), you are creating and
converting some data, but I do not see where you associate that data
with a node on the tree. Could this be significant? In a real
application, would this not happen before a drag and drop operation
commenced?
In this simplified example, the only data I'm interested in dragging is the
node's name, which is what gets sent (as tempStr) to SetData() in the
OnBeginDrag() method. When I implement this for real, I have a data
structure attached to each tree node that identifies the proper record in
the database and that is what I will use in the dragged data object
associated with the wxDropSource(). But my example here only drags the node
name and reports it via the print statement when it is dropped, but does
nothing to alter the tree. Gotta walk before I can run.
So take a look at the wiki in a couple of hours to see my new example that
does selective drag-and-drop of nodes within a wxTreeCtrl.
Hope this makes things clearer.
David
-----Original Message-----
From: Paul Yeager [mailto:pyeager@tektone.net]
Sent: Tuesday, September 16, 2003 2:28 PM
To: wxPython-users@lists.wxwindows.org
Subject: Re: [wxPython-users] Drag and Drop Feedback
David:
I have been struggling with drag and drop myself, so I read your message
with interest.
Naturally, I immediately tried to run the demo you attached. It
presented a tree display which seemed quite functional, other than that
it does not seem to respond to drag attempts at all. It issues "invalid
tree item" messages for each attempt.
In what sort of environment are you working? What OS, Python, and
wxWindows versions are you using?
Are you interested in dragging items within the tree, or dropping items
from other applications, or both?
I do note that in MainWindow.OnBeginDrag(), you are creating and
converting some data, but I do not see where you associate that data
with a node on the tree. Could this be significant? In a real
application, would this not happen before a drag and drop operation
commenced?
Best Regards
Paul Yeager
TekTone Sound & Signal Mfg., Inc.
David Woods wrote:
Hello all,
I am trying to implement some subtle drag-and-drop behavior, and am stuck
on
the issue of providing feedback to the user during the drag about whether
their drop will succeed.
Am I right in thinking that there is no way to look at the contents of a
wxCustomDataObject from within the wxPyDropTarget's OnDragOver method?
See, I'm trying to implement a series of behaviors in my application that
get triggered by dragging wxTreeCtrl nodes around. The various Node Types
can only be dropped on some nodes, not others, in ways that are meaningful,
and I have implemented drag-and-drop feedback in other programming
languages
in such a way that my users can see whether the drop will be meaningful
before they let go. (This feedback is pretty important given how my app is
designed.) I've done it by comparing characteristics of the data being
dragged to the characteristics of the potential drop target. However, I
can't seem to access anything about the data being dragged until the drop
has occurred in wxPython.
By way of illustration, I've attached a small app. It shows a tree with
several "Series" nodes and several "Collection" nodes, and at present, I've
got the feedback mechanism working so that only "Collection" nodes will
accept data drops. What I want is to alter the wxPyDropTarget's OnDragOver
method so that "Collections" only receive data picked up from the "Series"
part of the tree and that "Series" can accepts only "Collection" drops.
My actual application has many more node types and much more complex data
acceptance rules. Any suggestions for how I can extract the dragged data
characteristics would be greatly appreciated.
David Woods, Ph.D.
Wisconsin Center for Education Research
University of Wisconsin, Madison
http://www.transana.org
------------------------------------------------------------------------
from wxPython import wx
import cPickle
class MainWindow(wx.wxDialog):
""" This window displays a variety of GUI Widgets. """
def __init__(self,parent,id,title):
wx.wxDialog.__init__(self,parent,-4, title, size = (320,600),
style=wx.wxDEFAULT_FRAME_STYLE|wx.wxNO_FULL_REPAINT_ON_RESIZE)
self.SetBackgroundColour(wx.wxWHITE)
lay = wx.wxLayoutConstraints()
lay.top.SameAs(self, wx.wxTop, 10)
lay.centreX.SameAs(self, wx.wxCentreX)
lay.height.AsIs()
lay.width.AsIs()
self.tree = wx.wxTreeCtrl(self, -1, size=(300, 530),
style=wx.wxTR_HAS_BUTTONS)
self.tree.SetConstraints(lay)
lay = wx.wxLayoutConstraints()
lay.top.SameAs(self, wx.wxBottom, -25)
lay.centreX.SameAs(self, wx.wxCentreX)
lay.height.AsIs()
lay.width.AsIs()
btn = wx.wxButton(self, wx.wxID_OK, "OK")
btn.SetConstraints(lay)
self.treeroot = self.tree.AddRoot('Transana Database')
self.seriesroot = self.tree.AppendItem(self.treeroot, 'Series')
item = self.tree.AppendItem(self.seriesroot, 'Series 1')
item = self.tree.AppendItem(self.seriesroot, 'Series 2')
item = self.tree.AppendItem(self.seriesroot, 'Series 3')
self.collectionsroot = self.tree.AppendItem(self.treeroot,
'Collections')
item = self.tree.AppendItem(self.collectionsroot, 'Collection 1')
item = self.tree.AppendItem(self.collectionsroot, 'Collection 2')
item = self.tree.AppendItem(self.collectionsroot, 'Collection 3')
self.tree.Expand(self.treeroot)
self.tree.Expand(self.seriesroot)
self.tree.Expand(self.collectionsroot)
# Define the Begin Drag Event
wx.EVT_TREE_BEGIN_DRAG(self.tree, self.tree.GetId(),
self.OnBeginDrag)
# Define the Drop Target
dt = TestDropTarget(self.tree)
self.tree.SetDropTarget(dt)
self.Layout()
self.SetAutoLayout(wx.true)
self.ShowModal()
self.Destroy()
def OnBeginDrag(self, event):
""" Left Mouse Button initiates "Drag" for Clips (Sort Order, Copy,
Move) and Keywords (Assign) """
# Items in the tree are not automatically selected with a left click.
# We must select the item that is initially clicked manually!!
# We do this by looking at the screen point clicked and applying the
tree's HitTest method
sel_item, flags = self.tree.HitTest(event.GetPoint())
self.tree.SelectItem(sel_item)
tempStr = "%s" % (self.tree.GetItemText(sel_item))
# Determine what Item is being "dragged", and grab it's data
print "A node called %s is being dragged" % (tempStr)
# Create a custom Data Type for Drag and Drop
ddd = TestDragDropData()
ddd.SetSource(tempStr)
pddd = cPickle.dumps(ddd, 1)
# Now convert it to a wxCustomDataObject for dragging and dropping
cdo = wx.wxCustomDataObject(wx.wxCustomDataFormat('TransanaData'))
cdo.SetData(pddd)
# Now put the CustomDataObject into a DataObjectComposite
tdo = wx.wxDataObjectComposite()
tdo.Add(cdo)
# Create a DropSource Object
tds = wx.wxDropSource(self)
# Associate the Data with the Drop Source Object
tds.SetData(tdo)
# Initiate the Drag Operation
dragResult = tds.DoDragDrop(wx.true)
if dragResult == wx.wxDragCopy:
print "Result indicated successful copy"
elif dragResult == wx.wxDragMove:
print "Result indicated successful move"
else:
print "Result indicated failed drop"
class TestDragDropData(object):
def __init__(self):
self.SourceText = ''
self.DestText = ''
def __repr__(self):
return "SourceText = '%s', DestText = '%s'" % (self.SourceText,
self.DestText)
def SetSource(self, txt):
self.SourceText = txt
def SetDest(self, txt):
self.DestText = txt
class TestDropTarget(wx.wxPyDropTarget):
def __init__(self, tree):
wx.wxPyDropTarget.__init__(self)
self.tree = tree
# specify the data to accept
self.df = wx.wxCustomDataFormat('TransanaData')
self.cdo = wx.wxCustomDataObject(self.df)
self.SetDataObject(self.cdo)
def OnEnter(self, x, y, d):
print "OnEnter %s, %s, %s" % (x, y, d)
return d
def OnLeave(self):
print "OnLeave"
pass
def OnDrop(self, x, y):
print "Drop: x=%s, y=%s" % (x, y)
(id, flag) = self.tree.HitTest((x, y))
tempStr = self.tree.GetItemText(id)
print "Dropped on %s." % tempStr
return(wx.true)
def OnDragOver(self, x, y, d):
# print "OnDragOver %s, %s, %s" % (x, y, d)
# Determine Source Characteristics
# if self.GetData():
# data = cPickle.loads(self.cdo.GetData())
# print data
# Determine Destination Characteristics
(id, flag) = self.tree.HitTest((x, y))
tempStr = self.tree.GetItemText(id)
if (tempStr[0:10] == 'Collection'): # and (data.SourceText[0:7] ==
'Series'):
return d
else:
return wx.wxDragNone
def OnData(self, x, y, d):
print "OnData %s, %s, %s" % (x, y, d)
if self.GetData():
data = cPickle.loads(self.cdo.GetData())
print "Drop Data = '%s'" % (data)
data.SetDest('Set in Destination') # data is a COPY of the data,
not the original, so this has no effect
if d == wx.wxDragCopy:
print "OnData Result indicated successful copy"
elif d == wx.wxDragMove:
print "OnData Result indicated successful move"
else:
print "OnData Result indicated failed drop"
return d
class MyApp(wx.wxApp):
def OnInit(self):
frame = MainWindow(None, -1, "Drag and Drop Test")
self.SetTopWindow(frame)
return wx.true
app = MyApp(0)
app.MainLoop()
------------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org
---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org
---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org