]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/CustomDragAndDrop.py
adjusting to changes in xti.h
[wxWidgets.git] / wxPython / demo / CustomDragAndDrop.py
1
2 from wxPython.wx import *
3
4 import cPickle
5
6 #----------------------------------------------------------------------
7
8
9 class 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
16 self.SetMode("Draw")
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)
22 EVT_PAINT(self, self.OnPaint)
23
24
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
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):
47 if self.mode == "Drag":
48 self.StartDragOpperation()
49 elif self.mode == "Draw":
50 self.curLine = []
51 self.x, self.y = event.GetPositionTuple()
52 self.CaptureMouse()
53 else:
54 wxBell()
55 self.log.write("unknown mode!\n")
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):
68 if event.Dragging() and not self.mode == "Drag":
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")
110 result = dropSource.DoDragDrop(wxDrag_AllowMove)
111 self.log.WriteText("DragDrop completed: %d\n" % result)
112 if result == wxDragMove:
113 self.lines = []
114 self.Refresh()
115
116
117 #----------------------------------------------------------------------
118
119
120 class DoodleDropTarget(wxPyDropTarget):
121 def __init__(self, window, log):
122 wxPyDropTarget.__init__(self)
123 self.log = log
124 self.dv = window
125
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)
130
131
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))
135 return d
136
137 def OnLeave(self):
138 self.log.WriteText("OnLeave\n")
139
140 def OnDrop(self, x, y):
141 self.log.WriteText("OnDrop: %d %d\n" % (x, y))
142 return True
143
144 def OnDragOver(self, x, y, d):
145 #self.log.WriteText("OnDragOver: %d, %d, %d\n" % (x, y, d))
146
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.
153 return d
154
155
156
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))
161
162 # copy the data from the drag source to our data object
163 if self.GetData():
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.
171
172
173
174
175 class DoodleViewer(wxWindow):
176 def __init__(self, parent, log):
177 wxWindow.__init__(self, parent, -1, style=wxSUNKEN_BORDER)
178 self.log = log
179 self.SetBackgroundColour(wxWHITE)
180 self.lines = []
181 self.x = self.y = 0
182 dt = DoodleDropTarget(self, log)
183 self.SetDropTarget(dt)
184 EVT_PAINT(self, self.OnPaint)
185
186
187 def SetLines(self, lines):
188 self.lines = lines
189 self.Refresh()
190
191 def OnPaint(self, event):
192 dc = wxPaintDC(self)
193 self.DrawSavedLines(dc)
194
195 def DrawSavedLines(self, dc):
196 dc.BeginDrawing()
197 dc.SetPen(wxPen(wxRED, 3))
198 for line in self.lines:
199 for coords in line:
200 apply(dc.DrawLine, coords)
201 dc.EndDrawing()
202
203 #----------------------------------------------------------------------
204
205 class CustomDnDPanel(wxPanel):
206 def __init__(self, parent, log):
207 wxPanel.__init__(self, parent, -1)
208
209 self.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD, False))
210
211 # Make the controls
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"
217 "target.\n"
218 )
219
220 rb1 = wxRadioButton(self, -1, "Draw", style=wxRB_GROUP)
221 rb1.SetValue(True)
222 rb2 = wxRadioButton(self, -1, "Drag")
223 rb2.SetValue(False)
224
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.")
229
230 self.pad = DoodlePad(self, log)
231 view = DoodleViewer(self, log)
232
233 # put them in sizers
234 sizer = wxBoxSizer(wxHORIZONTAL)
235 box = wxBoxSizer(wxVERTICAL)
236 rbox = wxBoxSizer(wxHORIZONTAL)
237
238 rbox.Add(rb1)
239 rbox.Add(rb2)
240 box.Add(text1, 0, wxALL, 10)
241 box.Add(rbox, 0, wxALIGN_CENTER)
242 box.Add(10,90)
243 box.Add(text2, 0, wxALL, 10)
244
245 sizer.Add(box)
246
247 dndsizer = wxBoxSizer(wxVERTICAL)
248 dndsizer.Add(self.pad, 1, wxEXPAND|wxALL, 5)
249 dndsizer.Add(view, 1, wxEXPAND|wxALL, 5)
250
251 sizer.Add(dndsizer, 1, wxEXPAND)
252
253 self.SetAutoLayout(True)
254 self.SetSizer(sizer)
255
256 # Events
257 EVT_RADIOBUTTON(self, rb1.GetId(), self.OnRadioButton)
258 EVT_RADIOBUTTON(self, rb2.GetId(), self.OnRadioButton)
259
260
261 def OnRadioButton(self, evt):
262 rb = self.FindWindowById(evt.GetId())
263 self.pad.SetMode(rb.GetLabel())
264
265
266 #----------------------------------------------------------------------
267 #----------------------------------------------------------------------
268
269 class TestPanel(wxPanel):
270 def __init__(self, parent, log):
271 wxPanel.__init__(self, parent, -1)
272
273 self.SetAutoLayout(True)
274 sizer = wxBoxSizer(wxVERTICAL)
275
276 msg = "Custom Drag-And-Drop"
277 text = wxStaticText(self, -1, "", style=wxALIGN_CENTRE)
278 text.SetFont(wxFont(24, wxSWISS, wxNORMAL, wxBOLD, False))
279 text.SetLabel(msg)
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)
285
286 sizer.Add(CustomDnDPanel(self, log), 1, wxEXPAND)
287
288 self.SetSizer(sizer)
289
290
291 #----------------------------------------------------------------------
292
293 def runTest(frame, nb, log):
294 #win = TestPanel(nb, log)
295 win = CustomDnDPanel(nb, log)
296 return win
297
298
299 if __name__ == '__main__':
300 import sys
301 class DummyLog:
302 def WriteText(self, text):
303 sys.stdout.write(text)
304
305 class TestApp(wxApp):
306 def OnInit(self):
307 wxInitAllImageHandlers()
308 self.MakeFrame()
309 return True
310
311 def MakeFrame(self, event=None):
312 frame = wxFrame(None, -1, "Custom Drag and Drop", size=(550,400))
313 menu = wxMenu()
314 menu.Append(6543, "Window")
315 mb = wxMenuBar()
316 mb.Append(menu, "New")
317 frame.SetMenuBar(mb)
318 EVT_MENU(frame, 6543, self.MakeFrame)
319 panel = TestPanel(frame, DummyLog())
320 frame.Show(True)
321 self.SetTopWindow(frame)
322
323
324
325 app = TestApp(0)
326 app.MainLoop()
327
328 #----------------------------------------------------------------------
329
330
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
335 opperation.
336
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
339 MS Word.
340
341 The two data objects are combined in a wxDataObjectComposite and the
342 rest is handled by the framework.
343 </body></html>
344 """
345
346
347