]> git.saurik.com Git - wxWidgets.git/blame - wxPython/demo/CustomDragAndDrop.py
added wxStringBuffer helper
[wxWidgets.git] / wxPython / demo / CustomDragAndDrop.py
CommitLineData
b1462dfa
RD
1
2from wxPython.wx import *
3
4import cPickle
5
6#----------------------------------------------------------------------
7
8
9class DoodlePad(wxWindow):
10 def __init__(self, parent, log):
11 wxWindow.__init__(self, parent, -1, style=wxSUNKEN_BORDER)
12 self.log = log
13 self.SetBackgroundColour(wxWHITE)
14 self.lines = []
15 self.x = self.y = 0
163f2606 16 self.SetMode("Draw")
b1462dfa
RD
17
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)
f6bcfd97 22 EVT_PAINT(self, self.OnPaint)
b1462dfa
RD
23
24
163f2606
RD
25 def SetMode(self, mode):
26 self.mode = mode
27 if self.mode == "Draw":
28 self.SetCursor(wxStockCursor(wxCURSOR_PENCIL))
29 else:
30 self.SetCursor(wxSTANDARD_CURSOR)
31
32
b1462dfa
RD
33 def OnPaint(self, event):
34 dc = wxPaintDC(self)
35 self.DrawSavedLines(dc)
36
37 def DrawSavedLines(self, dc):
38 dc.BeginDrawing()
39 dc.SetPen(wxPen(wxBLUE, 3))
40 for line in self.lines:
41 for coords in line:
42 apply(dc.DrawLine, coords)
43 dc.EndDrawing()
44
45
46 def OnLeftDown(self, event):
163f2606 47 if self.mode == "Drag":
b1462dfa 48 self.StartDragOpperation()
163f2606 49 elif self.mode == "Draw":
b1462dfa
RD
50 self.curLine = []
51 self.x, self.y = event.GetPositionTuple()
52 self.CaptureMouse()
163f2606
RD
53 else:
54 wxBell()
55 self.log.write("unknown mode!\n")
b1462dfa
RD
56
57
58 def OnLeftUp(self, event):
59 self.lines.append(self.curLine)
60 self.curLine = []
61 self.ReleaseMouse()
62
63 def OnRightUp(self, event):
64 self.lines = []
65 self.Refresh()
66
67 def OnMotion(self, event):
163f2606 68 if event.Dragging() and not self.mode == "Drag":
b1462dfa
RD
69 dc = wxClientDC(self)
70 dc.BeginDrawing()
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()
76 dc.EndDrawing()
77
78
79 def StartDragOpperation(self):
80 # pickle the lines list
81 linesdata = cPickle.dumps(self.lines, 1)
82
83 # create our own data format and use it in a
84 # custom data object
85 ldata = wxCustomDataObject(wxCustomDataFormat("DoodleLines"))
86 ldata.SetData(linesdata)
87
88 # Also create a Bitmap version of the drawing
89 size = self.GetSize()
90 bmp = wxEmptyBitmap(size.width, size.height)
91 dc = wxMemoryDC()
92 dc.SelectObject(bmp)
93 dc.SetBackground(wxWHITE_BRUSH)
94 dc.Clear()
95 self.DrawSavedLines(dc)
96 dc.SelectObject(wxNullBitmap)
97
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()
102 data.Add(ldata)
103 data.Add(bdata)
104
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")
163f2606 110 result = dropSource.DoDragDrop(true)
b1462dfa 111 self.log.WriteText("DragDrop completed: %d\n" % result)
163f2606
RD
112 if result == wxDragMove:
113 self.lines = []
114 self.Refresh()
f6bcfd97
BP
115
116
b1462dfa
RD
117#----------------------------------------------------------------------
118
119
120class DoodleDropTarget(wxPyDropTarget):
121 def __init__(self, window, log):
122 wxPyDropTarget.__init__(self)
123 self.log = log
124 self.dv = window
f6bcfd97
BP
125
126 # specify the type of data we will accept
b1462dfa
RD
127 self.data = wxCustomDataObject(wxCustomDataFormat("DoodleLines"))
128 self.SetDataObject(self.data)
129
f6bcfd97
BP
130
131 # some virtual methods that track the progress of the drag
b1462dfa
RD
132 def OnEnter(self, x, y, d):
133 self.log.WriteText("OnEnter: %d, %d, %d\n" % (x, y, d))
163f2606
RD
134 return d
135
b1462dfa
RD
136 def OnLeave(self):
137 self.log.WriteText("OnLeave\n")
163f2606 138
b1462dfa
RD
139 def OnDrop(self, x, y):
140 self.log.WriteText("OnDrop: %d %d\n" % (x, y))
141 return true
163f2606
RD
142
143 def OnDragOver(self, x, y, d):
144 #self.log.WriteText("OnDragOver: %d, %d, %d\n" % (x, y, d))
145
146 # The value returned here tells the source what kind of visual
147 # feedback to give. For example, if wxDragCopy is returned then
148 # only the copy cursor will be shown, even if the source allows
149 # moves. You can use the passed in (x,y) to determine what kind
150 # of feedback to give. In this case we return the suggested value
151 # which is based on whether the Ctrl key is pressed.
152 return d
153
b1462dfa 154
f6bcfd97
BP
155
156 # Called when OnDrop returns true. We need to get the data and
157 # do something with it.
b1462dfa
RD
158 def OnData(self, x, y, d):
159 self.log.WriteText("OnData: %d, %d, %d\n" % (x, y, d))
f6bcfd97 160
163f2606 161 # copy the data from the drag source to our data object
b1462dfa 162 if self.GetData():
f6bcfd97 163 # convert it back to a list of lines and give it to the viewer
b1462dfa
RD
164 linesdata = self.data.GetData()
165 lines = cPickle.loads(linesdata)
166 self.dv.SetLines(lines)
163f2606
RD
167 return d # what is returned signals the source what to do
168 # with the original data (move, copy, etc.) In this
169 # case we just return the suggested value given to us.
b1462dfa 170
b1462dfa
RD
171
172
173
174class DoodleViewer(wxWindow):
175 def __init__(self, parent, log):
176 wxWindow.__init__(self, parent, -1, style=wxSUNKEN_BORDER)
177 self.log = log
178 self.SetBackgroundColour(wxWHITE)
179 self.lines = []
180 self.x = self.y = 0
181 dt = DoodleDropTarget(self, log)
182 self.SetDropTarget(dt)
f6bcfd97 183 EVT_PAINT(self, self.OnPaint)
b1462dfa 184
163f2606 185
b1462dfa
RD
186 def SetLines(self, lines):
187 self.lines = lines
188 self.Refresh()
189
190 def OnPaint(self, event):
191 dc = wxPaintDC(self)
192 self.DrawSavedLines(dc)
193
194 def DrawSavedLines(self, dc):
195 dc.BeginDrawing()
196 dc.SetPen(wxPen(wxRED, 3))
197 for line in self.lines:
198 for coords in line:
199 apply(dc.DrawLine, coords)
200 dc.EndDrawing()
201
202#----------------------------------------------------------------------
203
204class CustomDnDPanel(wxPanel):
205 def __init__(self, parent, log):
206 wxPanel.__init__(self, parent, -1)
207
208 self.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD, false))
209
163f2606
RD
210 # Make the controls
211 text1 = wxStaticText(self, -1,
899493dd 212 "Draw a little picture in this window\n"
7f3d6cbc
RD
213 "then switch the mode below and drag the\n"
214 "picture to the lower window or to another\n"
215 "application that accepts BMP's as a drop\n"
216 "target.\n"
163f2606
RD
217 )
218
219 rb1 = wxRadioButton(self, -1, "Draw", style=wxRB_GROUP)
220 rb1.SetValue(true)
221 rb2 = wxRadioButton(self, -1, "Drag")
222 rb2.SetValue(false)
223
224 text2 = wxStaticText(self, -1,
225 "The lower window is accepting a\n"
226 "custom data type that is a pickled\n"
227 "Python list of lines data.")
228
229 self.pad = DoodlePad(self, log)
230 view = DoodleViewer(self, log)
b1462dfa 231
163f2606
RD
232 # put them in sizers
233 sizer = wxBoxSizer(wxHORIZONTAL)
234 box = wxBoxSizer(wxVERTICAL)
235 rbox = wxBoxSizer(wxHORIZONTAL)
236
237 rbox.Add(rb1)
238 rbox.Add(rb2)
239 box.Add(text1, 0, wxALL, 10)
240 box.Add(rbox, 0, wxALIGN_CENTER)
241 box.Add(10,90)
242 box.Add(text2, 0, wxALL, 10)
243
244 sizer.Add(box)
245
246 dndsizer = wxBoxSizer(wxVERTICAL)
247 dndsizer.Add(self.pad, 1, wxEXPAND|wxALL, 5)
248 dndsizer.Add(view, 1, wxEXPAND|wxALL, 5)
249
250 sizer.Add(dndsizer, 1, wxEXPAND)
b1462dfa 251
b1462dfa
RD
252 self.SetAutoLayout(true)
253 self.SetSizer(sizer)
254
163f2606
RD
255 # Events
256 EVT_RADIOBUTTON(self, rb1.GetId(), self.OnRadioButton)
257 EVT_RADIOBUTTON(self, rb2.GetId(), self.OnRadioButton)
258
b1462dfa 259
163f2606
RD
260 def OnRadioButton(self, evt):
261 rb = self.FindWindowById(evt.GetId())
262 self.pad.SetMode(rb.GetLabel())
b1462dfa
RD
263
264
265#----------------------------------------------------------------------
266#----------------------------------------------------------------------
267
268class TestPanel(wxPanel):
269 def __init__(self, parent, log):
270 wxPanel.__init__(self, parent, -1)
271
272 self.SetAutoLayout(true)
273 sizer = wxBoxSizer(wxVERTICAL)
274
4120ef2b 275 msg = "Custom Drag-And-Drop"
b1462dfa
RD
276 text = wxStaticText(self, -1, "", style=wxALIGN_CENTRE)
277 text.SetFont(wxFont(24, wxSWISS, wxNORMAL, wxBOLD, false))
4120ef2b
RD
278 text.SetLabel(msg)
279 w,h = text.GetTextExtent(msg)
280 text.SetSize(wxSize(w,h+1))
b1462dfa
RD
281 text.SetForegroundColour(wxBLUE)
282 sizer.Add(text, 0, wxEXPAND|wxALL, 5)
283 sizer.Add(wxStaticLine(self, -1), 0, wxEXPAND)
284
285 sizer.Add(CustomDnDPanel(self, log), 1, wxEXPAND)
286
287 self.SetSizer(sizer)
288
289
290#----------------------------------------------------------------------
291
292def runTest(frame, nb, log):
163f2606
RD
293 #win = TestPanel(nb, log)
294 win = CustomDnDPanel(nb, log)
b1462dfa
RD
295 return win
296
899493dd
RD
297
298if __name__ == '__main__':
299 import sys
300 class DummyLog:
301 def WriteText(self, text):
302 sys.stdout.write(text)
303
304 class TestApp(wxApp):
305 def OnInit(self):
306 self.MakeFrame()
307 return true
308
309 def MakeFrame(self, event=None):
310 frame = wxFrame(None, -1, "Custom Drag and Drop", size=(550,400))
311 menu = wxMenu()
312 menu.Append(6543, "Window")
313 mb = wxMenuBar()
314 mb.Append(menu, "New")
315 frame.SetMenuBar(mb)
316 EVT_MENU(frame, 6543, self.MakeFrame)
317 panel = TestPanel(frame, DummyLog())
318 frame.Show(true)
319 self.SetTopWindow(frame)
320
321
322
323 app = TestApp(0)
324 app.MainLoop()
325
b1462dfa
RD
326#----------------------------------------------------------------------
327
328
329
330
331
332
333
334
335
336
337
338
339overview = """\
dafb483b 340This 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.
b1462dfa
RD
341
342A 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.
343
344The two data objects are combined in a wxDataObjectComposite and the rest is handled by the framework.
345"""
899493dd 346