]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/CustomDragAndDrop.py
   5 #---------------------------------------------------------------------- 
   8 class DoodlePad(wx
.Window
): 
   9     def __init__(self
, parent
, log
): 
  10         wx
.Window
.__init
__(self
, parent
, -1, style
=wx
.SUNKEN_BORDER
) 
  12         self
.SetBackgroundColour(wx
.WHITE
) 
  17         wx
.EVT_LEFT_DOWN(self
, self
.OnLeftDown
) 
  18         wx
.EVT_LEFT_UP(self
, self
.OnLeftUp
) 
  19         wx
.EVT_RIGHT_UP(self
, self
.OnRightUp
) 
  20         wx
.EVT_MOTION(self
, self
.OnMotion
) 
  21         wx
.EVT_PAINT(self
, self
.OnPaint
) 
  24     def SetMode(self
, mode
): 
  26         if self
.mode 
== "Draw": 
  27             self
.SetCursor(wx
.StockCursor(wx
.CURSOR_PENCIL
)) 
  29             self
.SetCursor(wx
.STANDARD_CURSOR
) 
  32     def OnPaint(self
, event
): 
  34         self
.DrawSavedLines(dc
) 
  36     def DrawSavedLines(self
, dc
): 
  38         dc
.SetPen(wx
.Pen(wx
.BLUE
, 3)) 
  39         for line 
in self
.lines
: 
  45     def OnLeftDown(self
, event
): 
  46         if self
.mode 
== "Drag": 
  47             self
.StartDragOpperation() 
  48         elif self
.mode 
== "Draw": 
  50             self
.x
, self
.y 
= event
.GetPositionTuple() 
  54             self
.log
.write("unknown mode!\n") 
  57     def OnLeftUp(self
, event
): 
  59             self
.lines
.append(self
.curLine
) 
  63     def OnRightUp(self
, event
): 
  67     def OnMotion(self
, event
): 
  68         if self
.HasCapture() and event
.Dragging() and not self
.mode 
== "Drag": 
  69             dc 
= wx
.ClientDC(self
) 
  71             dc
.SetPen(wx
.Pen(wx
.BLUE
, 3)) 
  72             coords 
= ((self
.x
, self
.y
), event
.GetPositionTuple()) 
  73             self
.curLine
.append(coords
) 
  75             self
.x
, self
.y 
= event
.GetPositionTuple() 
  79     def StartDragOpperation(self
): 
  80         # pickle the lines list 
  81         linesdata 
= cPickle
.dumps(self
.lines
, 1) 
  83         # create our own data format and use it in a 
  85         ldata 
= wx
.CustomDataObject(wx
.CustomDataFormat("DoodleLines")) 
  86         ldata
.SetData(linesdata
) 
  88         # Also create a Bitmap version of the drawing 
  90         bmp 
= wx
.EmptyBitmap(size
.width
, size
.height
) 
  93         dc
.SetBackground(wx
.WHITE_BRUSH
) 
  95         self
.DrawSavedLines(dc
) 
  96         dc
.SelectObject(wx
.NullBitmap
) 
  98         # Now make a data object for the bitmap and also a composite 
  99         # data object holding both of the others. 
 100         bdata 
= wx
.BitmapDataObject(bmp
) 
 101         data 
= wx
.DataObjectComposite() 
 105         # And finally, create the drop source and begin the drag 
 106         # and drop opperation 
 107         dropSource 
= wx
.DropSource(self
) 
 108         dropSource
.SetData(data
) 
 109         self
.log
.WriteText("Begining DragDrop\n") 
 110         result 
= dropSource
.DoDragDrop(wx
.Drag_AllowMove
) 
 111         self
.log
.WriteText("DragDrop completed: %d\n" % result
) 
 113         if result 
== wx
.DragMove
: 
 118 #---------------------------------------------------------------------- 
 121 class DoodleDropTarget(wx
.PyDropTarget
): 
 122     def __init__(self
, window
, log
): 
 123         wx
.PyDropTarget
.__init
__(self
) 
 127         # specify the type of data we will accept 
 128         self
.df 
= wx
.CustomDataFormat("DoodleLines") 
 129         self
.data 
= wx
.CustomDataObject(self
.df
) 
 130         self
.SetDataObject(self
.data
) 
 133     # some virtual methods that track the progress of the drag 
 134     def OnEnter(self
, x
, y
, d
): 
 135         self
.log
.WriteText("OnEnter: %d, %d, %d\n" % (x
, y
, d
)) 
 139         self
.log
.WriteText("OnLeave\n") 
 141     def OnDrop(self
, x
, y
): 
 142         self
.log
.WriteText("OnDrop: %d %d\n" % (x
, y
)) 
 145     def OnDragOver(self
, x
, y
, d
): 
 146         #self.log.WriteText("OnDragOver: %d, %d, %d\n" % (x, y, d)) 
 148         # The value returned here tells the source what kind of visual 
 149         # feedback to give.  For example, if wxDragCopy is returned then 
 150         # only the copy cursor will be shown, even if the source allows 
 151         # moves.  You can use the passed in (x,y) to determine what kind 
 152         # of feedback to give.  In this case we return the suggested value 
 153         # which is based on whether the Ctrl key is pressed. 
 158     # Called when OnDrop returns True.  We need to get the data and 
 159     # do something with it. 
 160     def OnData(self
, x
, y
, d
): 
 161         self
.log
.WriteText("OnData: %d, %d, %d\n" % (x
, y
, d
)) 
 163         # copy the data from the drag source to our data object 
 165             # convert it back to a list of lines and give it to the viewer 
 166             linesdata 
= self
.data
.GetData() 
 167             lines 
= cPickle
.loads(linesdata
) 
 168             self
.dv
.SetLines(lines
) 
 170         # what is returned signals the source what to do 
 171         # with the original data (move, copy, etc.)  In this 
 172         # case we just return the suggested value given to us. 
 177 class DoodleViewer(wx
.Window
): 
 178     def __init__(self
, parent
, log
): 
 179         wx
.Window
.__init
__(self
, parent
, -1, style
=wx
.SUNKEN_BORDER
) 
 181         self
.SetBackgroundColour(wx
.WHITE
) 
 184         dt 
= DoodleDropTarget(self
, log
) 
 185         self
.SetDropTarget(dt
) 
 186         wx
.EVT_PAINT(self
, self
.OnPaint
) 
 189     def SetLines(self
, lines
): 
 193     def OnPaint(self
, event
): 
 194         dc 
= wx
.PaintDC(self
) 
 195         self
.DrawSavedLines(dc
) 
 197     def DrawSavedLines(self
, dc
): 
 199         dc
.SetPen(wx
.Pen(wx
.RED
, 3)) 
 201         for line 
in self
.lines
: 
 206 #---------------------------------------------------------------------- 
 208 class CustomDnDPanel(wx
.Panel
): 
 209     def __init__(self
, parent
, log
): 
 210         wx
.Panel
.__init
__(self
, parent
, -1) 
 212         self
.SetFont(wx
.Font(10, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
, False)) 
 215         text1 
= wx
.StaticText(self
, -1, 
 216                             "Draw a little picture in this window\n" 
 217                             "then switch the mode below and drag the\n" 
 218                             "picture to the lower window or to another\n" 
 219                             "application that accepts BMP's as a drop\n" 
 223         rb1 
= wx
.RadioButton(self
, -1, "Draw", style
=wx
.RB_GROUP
) 
 225         rb2 
= wx
.RadioButton(self
, -1, "Drag") 
 228         text2 
= wx
.StaticText(self
, -1, 
 229                              "The lower window is accepting a\n" 
 230                              "custom data type that is a pickled\n" 
 231                              "Python list of lines data.") 
 233         self
.pad 
= DoodlePad(self
, log
) 
 234         view 
= DoodleViewer(self
, log
) 
 237         sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 238         box 
= wx
.BoxSizer(wx
.VERTICAL
) 
 239         rbox 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 243         box
.Add(text1
, 0, wx
.ALL
, 10) 
 244         box
.Add(rbox
, 0, wx
.ALIGN_CENTER
) 
 246         box
.Add(text2
, 0, wx
.ALL
, 10) 
 250         dndsizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 251         dndsizer
.Add(self
.pad
, 1, wx
.EXPAND|wx
.ALL
, 5) 
 252         dndsizer
.Add(view
, 1, wx
.EXPAND|wx
.ALL
, 5) 
 254         sizer
.Add(dndsizer
, 1, wx
.EXPAND
) 
 256         self
.SetAutoLayout(True) 
 260         wx
.EVT_RADIOBUTTON(self
, rb1
.GetId(), self
.OnRadioButton
) 
 261         wx
.EVT_RADIOBUTTON(self
, rb2
.GetId(), self
.OnRadioButton
) 
 264     def OnRadioButton(self
, evt
): 
 265         rb 
= self
.FindWindowById(evt
.GetId()) 
 266         self
.pad
.SetMode(rb
.GetLabel()) 
 269 #---------------------------------------------------------------------- 
 270 #---------------------------------------------------------------------- 
 272 class TestPanel(wx
.Panel
): 
 273     def __init__(self
, parent
, log
): 
 274         wx
.Panel
.__init
__(self
, parent
, -1) 
 276         self
.SetAutoLayout(True) 
 277         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 279         msg 
= "Custom Drag-And-Drop" 
 280         text 
= wx
.StaticText(self
, -1, "", style
=wx
.ALIGN_CENTRE
) 
 281         text
.SetFont(wx
.Font(24, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
, False)) 
 283         w
,h 
= text
.GetTextExtent(msg
) 
 284         text
.SetSize(wx
.Size(w
,h
+1)) 
 285         text
.SetForegroundColour(wx
.BLUE
) 
 286         sizer
.Add(text
, 0, wx
.EXPAND|wx
.ALL
, 5) 
 287         sizer
.Add(wx
.StaticLine(self
, -1), 0, wx
.EXPAND
) 
 289         sizer
.Add(CustomDnDPanel(self
, log
), 1, wx
.EXPAND
) 
 294 #---------------------------------------------------------------------- 
 296 def runTest(frame
, nb
, log
): 
 297     #win = TestPanel(nb, log) 
 298     win 
= CustomDnDPanel(nb
, log
) 
 302 if __name__ 
== '__main__': 
 306         def WriteText(self
, text
): 
 307             sys
.stdout
.write(text
) 
 309     class TestApp(wx
.App
): 
 311             wx
.InitAllImageHandlers() 
 315         def MakeFrame(self
, event
=None): 
 316             frame 
= wx
.Frame(None, -1, "Custom Drag and Drop", size
=(550,400)) 
 318             menu
.Append(6543, "Window") 
 320             mb
.Append(menu
, "New") 
 322             wx
.EVT_MENU(frame
, 6543, self
.MakeFrame
) 
 323             panel 
= TestPanel(frame
, DummyLog()) 
 325             self
.SetTopWindow(frame
) 
 327     #---------------------------------------------------------------------- 
 332 #---------------------------------------------------------------------- 
 335 overview 
= """<html><body> 
 336 This demo shows Drag and Drop using a custom data type and a custom 
 337 data object.  A type called "DoodleLines" is created and a Python 
 338 Pickle of a list is actually transfered in the drag and drop 
 341 A second data object is also created containing a bitmap of the image 
 342 and is made available to any drop target that accepts bitmaps, such as 
 345 The two data objects are combined in a wx.DataObjectComposite and the 
 346 rest is handled by the framework.