git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@7748 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			286 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			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.
 | 
						|
"""
 | 
						|
 |