]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/CustomDragAndDrop.py
2 from wxPython
.wx
import *
6 #----------------------------------------------------------------------
9 class DoodlePad(wxWindow
):
10 def __init__(self
, parent
, log
):
11 wxWindow
.__init
__(self
, parent
, -1, style
=wxSUNKEN_BORDER
)
13 self
.SetBackgroundColour(wxWHITE
)
18 EVT_LEFT_DOWN(self
, self
.OnLeftDown
)
19 EVT_LEFT_UP(self
, self
.OnLeftUp
)
20 EVT_RIGHT_UP(self
, self
.OnRightUp
)
21 EVT_MOTION(self
, self
.OnMotion
)
22 EVT_PAINT(self
, self
.OnPaint
)
25 def SetMode(self
, mode
):
27 if self
.mode
== "Draw":
28 self
.SetCursor(wxStockCursor(wxCURSOR_PENCIL
))
30 self
.SetCursor(wxSTANDARD_CURSOR
)
33 def OnPaint(self
, event
):
35 self
.DrawSavedLines(dc
)
37 def DrawSavedLines(self
, dc
):
39 dc
.SetPen(wxPen(wxBLUE
, 3))
40 for line
in self
.lines
:
42 apply(dc
.DrawLine
, coords
)
46 def OnLeftDown(self
, event
):
47 if self
.mode
== "Drag":
48 self
.StartDragOpperation()
49 elif self
.mode
== "Draw":
51 self
.x
, self
.y
= event
.GetPositionTuple()
55 self
.log
.write("unknown mode!\n")
58 def OnLeftUp(self
, event
):
59 self
.lines
.append(self
.curLine
)
63 def OnRightUp(self
, event
):
67 def OnMotion(self
, event
):
68 if event
.Dragging() and not self
.mode
== "Drag":
71 dc
.SetPen(wxPen(wxBLUE
, 3))
72 coords
= (self
.x
, self
.y
) + event
.GetPositionTuple()
73 self
.curLine
.append(coords
)
74 apply(dc
.DrawLine
, 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
= wxCustomDataObject(wxCustomDataFormat("DoodleLines"))
86 ldata
.SetData(linesdata
)
88 # Also create a Bitmap version of the drawing
90 bmp
= wxEmptyBitmap(size
.width
, size
.height
)
93 dc
.SetBackground(wxWHITE_BRUSH
)
95 self
.DrawSavedLines(dc
)
96 dc
.SelectObject(wxNullBitmap
)
98 # Now make a data object for the bitmap and also a composite
99 # data object holding both of the others.
100 bdata
= wxBitmapDataObject(bmp
)
101 data
= wxDataObjectComposite()
105 # And finally, create the drop source and begin the drag
106 # and drop opperation
107 dropSource
= wxDropSource(self
)
108 dropSource
.SetData(data
)
109 self
.log
.WriteText("Begining DragDrop\n")
110 result
= dropSource
.DoDragDrop(wxDrag_AllowMove
)
111 self
.log
.WriteText("DragDrop completed: %d\n" % result
)
112 if result
== wxDragMove
:
117 #----------------------------------------------------------------------
120 class DoodleDropTarget(wxPyDropTarget
):
121 def __init__(self
, window
, log
):
122 wxPyDropTarget
.__init
__(self
)
126 # specify the type of data we will accept
127 self
.df
= wxCustomDataFormat("DoodleLines")
128 self
.data
= wxCustomDataObject(self
.df
)
129 self
.SetDataObject(self
.data
)
132 # some virtual methods that track the progress of the drag
133 def OnEnter(self
, x
, y
, d
):
134 self
.log
.WriteText("OnEnter: %d, %d, %d\n" % (x
, y
, d
))
138 self
.log
.WriteText("OnLeave\n")
140 def OnDrop(self
, x
, y
):
141 self
.log
.WriteText("OnDrop: %d %d\n" % (x
, y
))
144 def OnDragOver(self
, x
, y
, d
):
145 #self.log.WriteText("OnDragOver: %d, %d, %d\n" % (x, y, d))
147 # The value returned here tells the source what kind of visual
148 # feedback to give. For example, if wxDragCopy is returned then
149 # only the copy cursor will be shown, even if the source allows
150 # moves. You can use the passed in (x,y) to determine what kind
151 # of feedback to give. In this case we return the suggested value
152 # which is based on whether the Ctrl key is pressed.
157 # Called when OnDrop returns True. We need to get the data and
158 # do something with it.
159 def OnData(self
, x
, y
, d
):
160 self
.log
.WriteText("OnData: %d, %d, %d\n" % (x
, y
, d
))
162 # copy the data from the drag source to our data object
164 # convert it back to a list of lines and give it to the viewer
165 linesdata
= self
.data
.GetData()
166 lines
= cPickle
.loads(linesdata
)
167 self
.dv
.SetLines(lines
)
168 return d
# what is returned signals the source what to do
169 # with the original data (move, copy, etc.) In this
170 # case we just return the suggested value given to us.
175 class DoodleViewer(wxWindow
):
176 def __init__(self
, parent
, log
):
177 wxWindow
.__init
__(self
, parent
, -1, style
=wxSUNKEN_BORDER
)
179 self
.SetBackgroundColour(wxWHITE
)
182 dt
= DoodleDropTarget(self
, log
)
183 self
.SetDropTarget(dt
)
184 EVT_PAINT(self
, self
.OnPaint
)
187 def SetLines(self
, lines
):
191 def OnPaint(self
, event
):
193 self
.DrawSavedLines(dc
)
195 def DrawSavedLines(self
, dc
):
197 dc
.SetPen(wxPen(wxRED
, 3))
198 for line
in self
.lines
:
200 apply(dc
.DrawLine
, coords
)
203 #----------------------------------------------------------------------
205 class CustomDnDPanel(wxPanel
):
206 def __init__(self
, parent
, log
):
207 wxPanel
.__init
__(self
, parent
, -1)
209 self
.SetFont(wxFont(10, wxSWISS
, wxNORMAL
, wxBOLD
, False))
212 text1
= wxStaticText(self
, -1,
213 "Draw a little picture in this window\n"
214 "then switch the mode below and drag the\n"
215 "picture to the lower window or to another\n"
216 "application that accepts BMP's as a drop\n"
220 rb1
= wxRadioButton(self
, -1, "Draw", style
=wxRB_GROUP
)
222 rb2
= wxRadioButton(self
, -1, "Drag")
225 text2
= wxStaticText(self
, -1,
226 "The lower window is accepting a\n"
227 "custom data type that is a pickled\n"
228 "Python list of lines data.")
230 self
.pad
= DoodlePad(self
, log
)
231 view
= DoodleViewer(self
, log
)
234 sizer
= wxBoxSizer(wxHORIZONTAL
)
235 box
= wxBoxSizer(wxVERTICAL
)
236 rbox
= wxBoxSizer(wxHORIZONTAL
)
240 box
.Add(text1
, 0, wxALL
, 10)
241 box
.Add(rbox
, 0, wxALIGN_CENTER
)
243 box
.Add(text2
, 0, wxALL
, 10)
247 dndsizer
= wxBoxSizer(wxVERTICAL
)
248 dndsizer
.Add(self
.pad
, 1, wxEXPAND|wxALL
, 5)
249 dndsizer
.Add(view
, 1, wxEXPAND|wxALL
, 5)
251 sizer
.Add(dndsizer
, 1, wxEXPAND
)
253 self
.SetAutoLayout(True)
257 EVT_RADIOBUTTON(self
, rb1
.GetId(), self
.OnRadioButton
)
258 EVT_RADIOBUTTON(self
, rb2
.GetId(), self
.OnRadioButton
)
261 def OnRadioButton(self
, evt
):
262 rb
= self
.FindWindowById(evt
.GetId())
263 self
.pad
.SetMode(rb
.GetLabel())
266 #----------------------------------------------------------------------
267 #----------------------------------------------------------------------
269 class TestPanel(wxPanel
):
270 def __init__(self
, parent
, log
):
271 wxPanel
.__init
__(self
, parent
, -1)
273 self
.SetAutoLayout(True)
274 sizer
= wxBoxSizer(wxVERTICAL
)
276 msg
= "Custom Drag-And-Drop"
277 text
= wxStaticText(self
, -1, "", style
=wxALIGN_CENTRE
)
278 text
.SetFont(wxFont(24, wxSWISS
, wxNORMAL
, wxBOLD
, False))
280 w
,h
= text
.GetTextExtent(msg
)
281 text
.SetSize(wxSize(w
,h
+1))
282 text
.SetForegroundColour(wxBLUE
)
283 sizer
.Add(text
, 0, wxEXPAND|wxALL
, 5)
284 sizer
.Add(wxStaticLine(self
, -1), 0, wxEXPAND
)
286 sizer
.Add(CustomDnDPanel(self
, log
), 1, wxEXPAND
)
291 #----------------------------------------------------------------------
293 def runTest(frame
, nb
, log
):
294 #win = TestPanel(nb, log)
295 win
= CustomDnDPanel(nb
, log
)
299 if __name__
== '__main__':
302 def WriteText(self
, text
):
303 sys
.stdout
.write(text
)
305 class TestApp(wxApp
):
307 wxInitAllImageHandlers()
311 def MakeFrame(self
, event
=None):
312 frame
= wxFrame(None, -1, "Custom Drag and Drop", size
=(550,400))
314 menu
.Append(6543, "Window")
316 mb
.Append(menu
, "New")
318 EVT_MENU(frame
, 6543, self
.MakeFrame
)
319 panel
= TestPanel(frame
, DummyLog())
321 self
.SetTopWindow(frame
)
328 #----------------------------------------------------------------------
331 overview
= """<html><body>
332 This demo shows Drag and Drop using a custom data type and a custom
333 data object. A type called "DoodleLines" is created and a Python
334 Pickle of a list is actually transfered in the drag and drop
337 A second data object is also created containing a bitmap of the image
338 and is made available to any drop target that accepts bitmaps, such as
341 The two data objects are combined in a wxDataObjectComposite and the
342 rest is handled by the framework.