CustomDragAndDrop.py :  » GUI » wxPython » wxPython-src-2.8.11.0 » wxPython » demo » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » GUI » wxPython 
wxPython » wxPython src 2.8.11.0 » wxPython » demo » CustomDragAndDrop.py

import  cPickle
import  wx

#----------------------------------------------------------------------


class DoodlePad(wx.Window):
    def __init__(self, parent, log):
        wx.Window.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
        self.log = log
        self.SetBackgroundColour(wx.WHITE)
        self.lines = []
        self.x = self.y = 0
        self.SetMode("Draw")

        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.Bind(wx.EVT_LEFT_UP,  self.OnLeftUp)
        self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
        self.Bind(wx.EVT_MOTION, self.OnMotion)
        self.Bind(wx.EVT_PAINT, self.OnPaint)


    def SetMode(self, mode):
        self.mode = mode
        if self.mode == "Draw":
            self.SetCursor(wx.StockCursor(wx.CURSOR_PENCIL))
        else:
            self.SetCursor(wx.STANDARD_CURSOR)


    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.DrawSavedLines(dc)

    def DrawSavedLines(self, dc):
        dc.BeginDrawing()
        dc.SetPen(wx.Pen(wx.BLUE, 3))
        for line in self.lines:
            for coords in line:
                dc.DrawLine(*coords)
        dc.EndDrawing()


    def OnLeftDown(self, event):
        if self.mode == "Drag":
            self.StartDragOpperation()
        elif self.mode == "Draw":
            self.curLine = []
            self.x, self.y = event.GetPositionTuple()
            self.CaptureMouse()
        else:
            wx.Bell()
            self.log.write("unknown mode!\n")


    def OnLeftUp(self, event):
        if self.HasCapture():
            self.lines.append(self.curLine)
            self.curLine = []
            self.ReleaseMouse()

    def OnRightUp(self, event):
        self.lines = []
        self.Refresh()

    def OnMotion(self, event):
        if self.HasCapture() and event.Dragging() and not self.mode == "Drag":
            dc = wx.ClientDC(self)
            dc.BeginDrawing()
            dc.SetPen(wx.Pen(wx.BLUE, 3))
            coords = (self.x, self.y) + event.GetPositionTuple()
            self.curLine.append(coords)
            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 = wx.CustomDataObject("DoodleLines")
        ldata.SetData(linesdata)

        # Also create a Bitmap version of the drawing
        size = self.GetSize()
        bmp = wx.EmptyBitmap(size.width, size.height)
        dc = wx.MemoryDC()
        dc.SelectObject(bmp)
        dc.SetBackground(wx.WHITE_BRUSH)
        dc.Clear()
        self.DrawSavedLines(dc)
        dc.SelectObject(wx.NullBitmap)

        # Now make a data object for the bitmap and also a composite
        # data object holding both of the others.
        bdata = wx.BitmapDataObject(bmp)
        data = wx.DataObjectComposite()
        data.Add(ldata)
        data.Add(bdata)

        # And finally, create the drop source and begin the drag
        # and drop opperation
        dropSource = wx.DropSource(self)
        dropSource.SetData(data)
        self.log.WriteText("Begining DragDrop\n")
        result = dropSource.DoDragDrop(wx.Drag_AllowMove)
        self.log.WriteText("DragDrop completed: %d\n" % result)

        if result == wx.DragMove:
            self.lines = []
            self.Refresh()


#----------------------------------------------------------------------


class DoodleDropTarget(wx.PyDropTarget):
    def __init__(self, window, log):
        wx.PyDropTarget.__init__(self)
        self.log = log
        self.dv = window

        # specify the type of data we will accept
        self.data = wx.CustomDataObject("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 d

    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))

        # The value returned here tells the source what kind of visual
        # feedback to give.  For example, if wxDragCopy is returned then
        # only the copy cursor will be shown, even if the source allows
        # moves.  You can use the passed in (x,y) to determine what kind
        # of feedback to give.  In this case we return the suggested value
        # which is based on whether the Ctrl key is pressed.
        return d



    # 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 our 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)
            
        # what is returned signals the source what to do
        # with the original data (move, copy, etc.)  In this
        # case we just return the suggested value given to us.
        return d  
        


class DoodleViewer(wx.Window):
    def __init__(self, parent, log):
        wx.Window.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
        self.log = log
        self.SetBackgroundColour(wx.WHITE)
        self.lines = []
        self.x = self.y = 0
        dt = DoodleDropTarget(self, log)
        self.SetDropTarget(dt)
        self.Bind(wx.EVT_PAINT, self.OnPaint)


    def SetLines(self, lines):
        self.lines = lines
        self.Refresh()

    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.DrawSavedLines(dc)

    def DrawSavedLines(self, dc):
        dc.BeginDrawing()
        dc.SetPen(wx.Pen(wx.RED, 3))

        for line in self.lines:
            for coords in line:
                dc.DrawLine(*coords)
        dc.EndDrawing()

#----------------------------------------------------------------------

class CustomDnDPanel(wx.Panel):
    def __init__(self, parent, log):
        wx.Panel.__init__(self, parent, -1)

        self.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, False))

        # Make the controls
        text1 = wx.StaticText(self, -1,
                            "Draw a little picture in this window\n"
                            "then switch the mode below and drag the\n"
                            "picture to the lower window or to another\n"
                            "application that accepts Bitmaps as a\n"
                             "drop target.\n"
                            )

        rb1 = wx.RadioButton(self, -1, "Draw", style=wx.RB_GROUP)
        rb1.SetValue(True)
        rb2 = wx.RadioButton(self, -1, "Drag")
        rb2.SetValue(False)

        text2 = wx.StaticText(self, -1,
                             "The lower window is accepting a\n"
                             "custom data type that is a pickled\n"
                             "Python list of lines data.")

        self.pad = DoodlePad(self, log)
        view = DoodleViewer(self, log)

        # put them in sizers
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        box = wx.BoxSizer(wx.VERTICAL)
        rbox = wx.BoxSizer(wx.HORIZONTAL)

        rbox.Add(rb1)
        rbox.Add(rb2)
        box.Add(text1, 0, wx.ALL, 10)
        box.Add(rbox, 0, wx.ALIGN_CENTER)
        box.Add((10,90))
        box.Add(text2, 0, wx.ALL, 10)

        sizer.Add(box)

        dndsizer = wx.BoxSizer(wx.VERTICAL)
        dndsizer.Add(self.pad, 1, wx.EXPAND|wx.ALL, 5)
        dndsizer.Add(view, 1, wx.EXPAND|wx.ALL, 5)

        sizer.Add(dndsizer, 1, wx.EXPAND)

        self.SetAutoLayout(True)
        self.SetSizer(sizer)

        # Events
        self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioButton, rb1)
        self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioButton, rb2)


    def OnRadioButton(self, evt):
        rb = self.FindWindowById(evt.GetId())
        self.pad.SetMode(rb.GetLabel())


#----------------------------------------------------------------------
#----------------------------------------------------------------------

class TestPanel(wx.Panel):
    def __init__(self, parent, log):
        wx.Panel.__init__(self, parent, -1)

        self.SetAutoLayout(True)
        sizer = wx.BoxSizer(wx.VERTICAL)

        msg = "Custom Drag-And-Drop"
        text = wx.StaticText(self, -1, "", style=wx.ALIGN_CENTRE)
        text.SetFont(wx.Font(24, wx.SWISS, wx.NORMAL, wx.BOLD, False))
        text.SetLabel(msg)
        w,h = text.GetTextExtent(msg)
        text.SetSize(wx.Size(w,h+1))
        text.SetForegroundColour(wx.BLUE)
        sizer.Add(text, 0, wx.EXPAND|wx.ALL, 5)
        sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)

        sizer.Add(CustomDnDPanel(self, log), 1, wx.EXPAND)

        self.SetSizer(sizer)


#----------------------------------------------------------------------

def runTest(frame, nb, log):
    #win = TestPanel(nb, log)
    win = CustomDnDPanel(nb, log)
    return win


if __name__ == '__main__':
    import sys
    
    class DummyLog:
        def WriteText(self, text):
            sys.stdout.write(text)

    class TestApp(wx.App):
        def OnInit(self):
            wx.InitAllImageHandlers()
            self.MakeFrame()
            return True

        def MakeFrame(self, event=None):
            frame = wx.Frame(None, -1, "Custom Drag and Drop", size=(550,400))
            menu = wx.Menu()
            item = menu.Append(-1, "Window")
            mb = wx.MenuBar()
            mb.Append(menu, "New")
            frame.SetMenuBar(mb)
            frame.Bind(wx.EVT_MENU, self.MakeFrame, item)
            panel = TestPanel(frame, DummyLog())
            frame.Show(True)
            self.SetTopWindow(frame)

    #----------------------------------------------------------------------

    app = TestApp(0)
    app.MainLoop()

#----------------------------------------------------------------------


overview = """<html><body>
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 wx.DataObjectComposite and the
rest is handled by the framework.
</body></html>
"""

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.