wxWidgets/wxPython/demo/CustomDragAndDrop.py
Bryan Petty f6bcfd974e merged 2.2 branch
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@7748 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2000-07-15 19:51:35 +00:00

286 lines
8.3 KiB
Python

from wxPython.wx import *
import cPickle
#----------------------------------------------------------------------
class DoodlePad(wxWindow):
def __init__(self, parent, log):
wxWindow.__init__(self, parent, -1, style=wxSUNKEN_BORDER)
self.log = log
self.SetBackgroundColour(wxWHITE)
self.lines = []
self.x = self.y = 0
self.SetCursor(wxStockCursor(wxCURSOR_PENCIL))
EVT_LEFT_DOWN(self, self.OnLeftDown)
EVT_LEFT_UP(self, self.OnLeftUp)
EVT_RIGHT_UP(self, self.OnRightUp)
EVT_MOTION(self, self.OnMotion)
EVT_PAINT(self, self.OnPaint)
def OnPaint(self, event):
dc = wxPaintDC(self)
self.DrawSavedLines(dc)
def DrawSavedLines(self, dc):
dc.BeginDrawing()
dc.SetPen(wxPen(wxBLUE, 3))
for line in self.lines:
for coords in line:
apply(dc.DrawLine, coords)
dc.EndDrawing()
def OnLeftDown(self, event):
if event.ControlDown():
self.StartDragOpperation()
else:
self.curLine = []
self.x, self.y = event.GetPositionTuple()
self.CaptureMouse()
def OnLeftUp(self, event):
self.lines.append(self.curLine)
self.curLine = []
self.ReleaseMouse()
def OnRightUp(self, event):
self.lines = []
self.Refresh()
def OnMotion(self, event):
if event.Dragging() and not event.ControlDown():
dc = wxClientDC(self)
dc.BeginDrawing()
dc.SetPen(wxPen(wxBLUE, 3))
coords = (self.x, self.y) + event.GetPositionTuple()
self.curLine.append(coords)
apply(dc.DrawLine, coords)
self.x, self.y = event.GetPositionTuple()
dc.EndDrawing()
def StartDragOpperation(self):
# pickle the lines list
linesdata = cPickle.dumps(self.lines, 1)
# create our own data format and use it in a
# custom data object
ldata = wxCustomDataObject(wxCustomDataFormat("DoodleLines"))
ldata.SetData(linesdata)
# Also create a Bitmap version of the drawing
size = self.GetSize()
bmp = wxEmptyBitmap(size.width, size.height)
dc = wxMemoryDC()
dc.SelectObject(bmp)
dc.SetBackground(wxWHITE_BRUSH)
dc.Clear()
self.DrawSavedLines(dc)
dc.SelectObject(wxNullBitmap)
# Now make a data object for the bitmap and also a composite
# data object holding both of the others.
bdata = wxBitmapDataObject(bmp)
data = wxDataObjectComposite()
data.Add(ldata)
data.Add(bdata)
# And finally, create the drop source and begin the drag
# and drop opperation
dropSource = wxDropSource(self)
dropSource.SetData(data)
self.log.WriteText("Begining DragDrop\n")
result = dropSource.DoDragDrop()
self.log.WriteText("DragDrop completed: %d\n" % result)
#----------------------------------------------------------------------
class DoodleDropTarget(wxPyDropTarget):
def __init__(self, window, log):
wxPyDropTarget.__init__(self)
self.log = log
self.dv = window
# specify the type of data we will accept
self.data = wxCustomDataObject(wxCustomDataFormat("DoodleLines"))
self.SetDataObject(self.data)
# some virtual methods that track the progress of the drag
def OnEnter(self, x, y, d):
self.log.WriteText("OnEnter: %d, %d, %d\n" % (x, y, d))
return wxDragCopy
def OnLeave(self):
self.log.WriteText("OnLeave\n")
def OnDrop(self, x, y):
self.log.WriteText("OnDrop: %d %d\n" % (x, y))
return true
#def OnDragOver(self, x, y, d):
# self.log.WriteText("OnDragOver: %d, %d, %d\n" % (x, y, d))
# return wxDragCopy
# Called when OnDrop returns true. We need to get the data and
# do something with it.
def OnData(self, x, y, d):
self.log.WriteText("OnData: %d, %d, %d\n" % (x, y, d))
# copy the data from the drag source to out data object
if self.GetData():
# convert it back to a list of lines and give it to the viewer
linesdata = self.data.GetData()
lines = cPickle.loads(linesdata)
self.dv.SetLines(lines)
return d
class DoodleViewer(wxWindow):
def __init__(self, parent, log):
wxWindow.__init__(self, parent, -1, style=wxSUNKEN_BORDER)
self.log = log
self.SetBackgroundColour(wxWHITE)
self.lines = []
self.x = self.y = 0
dt = DoodleDropTarget(self, log)
self.SetDropTarget(dt)
EVT_PAINT(self, self.OnPaint)
def SetLines(self, lines):
self.lines = lines
self.Refresh()
def OnPaint(self, event):
dc = wxPaintDC(self)
self.DrawSavedLines(dc)
def DrawSavedLines(self, dc):
dc.BeginDrawing()
dc.SetPen(wxPen(wxRED, 3))
for line in self.lines:
for coords in line:
apply(dc.DrawLine, coords)
dc.EndDrawing()
#----------------------------------------------------------------------
class CustomDnDPanel(wxPanel):
def __init__(self, parent, log):
wxPanel.__init__(self, parent, -1)
self.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD, false))
sizer = wxBoxSizer(wxHORIZONTAL)
text = wxStaticText(self, -1,
"Draw a little picture in this window\n"
"then Ctrl-Drag it to the lower \n"
"window or to another application\n"
"that accepts BMP's as a drop target.\n\n"
"The lower window is accepting a\n"
"custom data type that is a pickled\n"
"Python list of lines data.")
sizer.Add(text, 1, wxALL, 10)
insizer = wxBoxSizer(wxVERTICAL)
insizer.Add(DoodlePad(self, log), 1, wxEXPAND|wxALL, 5)
insizer.Add(DoodleViewer(self, log), 1, wxEXPAND|wxALL, 5)
sizer.Add(insizer, 1, wxEXPAND)
self.SetAutoLayout(true)
self.SetSizer(sizer)
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class TestPanel(wxPanel):
def __init__(self, parent, log):
wxPanel.__init__(self, parent, -1)
self.SetAutoLayout(true)
sizer = wxBoxSizer(wxVERTICAL)
msg = "Custom Drag-And-Drop"
text = wxStaticText(self, -1, "", style=wxALIGN_CENTRE)
text.SetFont(wxFont(24, wxSWISS, wxNORMAL, wxBOLD, false))
text.SetLabel(msg)
w,h = text.GetTextExtent(msg)
text.SetSize(wxSize(w,h+1))
text.SetForegroundColour(wxBLUE)
sizer.Add(text, 0, wxEXPAND|wxALL, 5)
sizer.Add(wxStaticLine(self, -1), 0, wxEXPAND)
sizer.Add(CustomDnDPanel(self, log), 1, wxEXPAND)
self.SetSizer(sizer)
#----------------------------------------------------------------------
def runTest(frame, nb, log):
win = TestPanel(nb, log)
return win
if __name__ == '__main__':
import sys
class DummyLog:
def WriteText(self, text):
sys.stdout.write(text)
class TestApp(wxApp):
def OnInit(self):
self.MakeFrame()
return true
def MakeFrame(self, event=None):
frame = wxFrame(None, -1, "Custom Drag and Drop", size=(550,400))
menu = wxMenu()
menu.Append(6543, "Window")
mb = wxMenuBar()
mb.Append(menu, "New")
frame.SetMenuBar(mb)
EVT_MENU(frame, 6543, self.MakeFrame)
panel = TestPanel(frame, DummyLog())
frame.Show(true)
self.SetTopWindow(frame)
app = TestApp(0)
app.MainLoop()
#----------------------------------------------------------------------
overview = """\
This demo shows Drag and Drop using a custom data type and a custom data object. A type called "DoodleLines" is created and a Python Pickle of a list is actually transfered in the drag and drop opperation.
A second data object is also created containing a bitmap of the image and is made available to any drop target that accepts bitmaps, such as MS Word.
The two data objects are combined in a wxDataObjectComposite and the rest is handled by the framework.
"""