]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/CustomDragAndDrop.py
A temporary hDIB was not being unlocked before exiting the function where the lock...
[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.SetCursor(wxStockCursor(wxCURSOR_PENCIL))
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 OnPaint(self, event):
26 dc = wxPaintDC(self)
27 self.DrawSavedLines(dc)
28
29 def DrawSavedLines(self, dc):
30 dc.BeginDrawing()
31 dc.SetPen(wxPen(wxBLUE, 3))
32 for line in self.lines:
33 for coords in line:
34 apply(dc.DrawLine, coords)
35 dc.EndDrawing()
36
37
38 def OnLeftDown(self, event):
39 if event.ControlDown():
40 self.StartDragOpperation()
41 else:
42 self.curLine = []
43 self.x, self.y = event.GetPositionTuple()
44 self.CaptureMouse()
45
46
47 def OnLeftUp(self, event):
48 self.lines.append(self.curLine)
49 self.curLine = []
50 self.ReleaseMouse()
51
52 def OnRightUp(self, event):
53 self.lines = []
54 self.Refresh()
55
56 def OnMotion(self, event):
57 if event.Dragging() and not event.ControlDown():
58 dc = wxClientDC(self)
59 dc.BeginDrawing()
60 dc.SetPen(wxPen(wxBLUE, 3))
61 coords = (self.x, self.y) + event.GetPositionTuple()
62 self.curLine.append(coords)
63 apply(dc.DrawLine, coords)
64 self.x, self.y = event.GetPositionTuple()
65 dc.EndDrawing()
66
67
68 def StartDragOpperation(self):
69 # pickle the lines list
70 linesdata = cPickle.dumps(self.lines, 1)
71
72 # create our own data format and use it in a
73 # custom data object
74 ldata = wxCustomDataObject(wxCustomDataFormat("DoodleLines"))
75 ldata.SetData(linesdata)
76
77 # Also create a Bitmap version of the drawing
78 size = self.GetSize()
79 bmp = wxEmptyBitmap(size.width, size.height)
80 dc = wxMemoryDC()
81 dc.SelectObject(bmp)
82 dc.SetBackground(wxWHITE_BRUSH)
83 dc.Clear()
84 self.DrawSavedLines(dc)
85 dc.SelectObject(wxNullBitmap)
86
87 # Now make a data object for the bitmap and also a composite
88 # data object holding both of the others.
89 bdata = wxBitmapDataObject(bmp)
90 data = wxDataObjectComposite()
91 data.Add(ldata)
92 data.Add(bdata)
93
94 # And finally, create the drop source and begin the drag
95 # and drop opperation
96 dropSource = wxDropSource(self)
97 dropSource.SetData(data)
98 self.log.WriteText("Begining DragDrop\n")
99 result = dropSource.DoDragDrop()
100 self.log.WriteText("DragDrop completed: %d\n" % result)
101
102
103
104 #----------------------------------------------------------------------
105
106
107 class DoodleDropTarget(wxPyDropTarget):
108 def __init__(self, window, log):
109 wxPyDropTarget.__init__(self)
110 self.log = log
111 self.dv = window
112
113 # specify the type of data we will accept
114 self.data = wxCustomDataObject(wxCustomDataFormat("DoodleLines"))
115 self.SetDataObject(self.data)
116
117
118 # some virtual methods that track the progress of the drag
119 def OnEnter(self, x, y, d):
120 self.log.WriteText("OnEnter: %d, %d, %d\n" % (x, y, d))
121 return wxDragCopy
122 def OnLeave(self):
123 self.log.WriteText("OnLeave\n")
124 def OnDrop(self, x, y):
125 self.log.WriteText("OnDrop: %d %d\n" % (x, y))
126 return true
127 #def OnDragOver(self, x, y, d):
128 # self.log.WriteText("OnDragOver: %d, %d, %d\n" % (x, y, d))
129 # return wxDragCopy
130
131
132 # Called when OnDrop returns true. We need to get the data and
133 # do something with it.
134 def OnData(self, x, y, d):
135 self.log.WriteText("OnData: %d, %d, %d\n" % (x, y, d))
136
137 # copy the data from the drag source to out data object
138 if self.GetData():
139 # convert it back to a list of lines and give it to the viewer
140 linesdata = self.data.GetData()
141 lines = cPickle.loads(linesdata)
142 self.dv.SetLines(lines)
143 return d
144
145
146
147
148 class DoodleViewer(wxWindow):
149 def __init__(self, parent, log):
150 wxWindow.__init__(self, parent, -1, style=wxSUNKEN_BORDER)
151 self.log = log
152 self.SetBackgroundColour(wxWHITE)
153 self.lines = []
154 self.x = self.y = 0
155 dt = DoodleDropTarget(self, log)
156 self.SetDropTarget(dt)
157 EVT_PAINT(self, self.OnPaint)
158
159 def SetLines(self, lines):
160 self.lines = lines
161 self.Refresh()
162
163 def OnPaint(self, event):
164 dc = wxPaintDC(self)
165 self.DrawSavedLines(dc)
166
167 def DrawSavedLines(self, dc):
168 dc.BeginDrawing()
169 dc.SetPen(wxPen(wxRED, 3))
170 for line in self.lines:
171 for coords in line:
172 apply(dc.DrawLine, coords)
173 dc.EndDrawing()
174
175 #----------------------------------------------------------------------
176
177 class CustomDnDPanel(wxPanel):
178 def __init__(self, parent, log):
179 wxPanel.__init__(self, parent, -1)
180
181 self.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD, false))
182
183 sizer = wxBoxSizer(wxHORIZONTAL)
184 text = wxStaticText(self, -1,
185 "Draw a little picture in this window\n"
186 "then Ctrl-Drag it to the lower \n"
187 "window or to another application\n"
188 "that accepts BMP's as a drop target.\n\n"
189 "The lower window is accepting a\n"
190 "custom data type that is a pickled\n"
191 "Python list of lines data.")
192 sizer.Add(text, 1, wxALL, 10)
193
194 insizer = wxBoxSizer(wxVERTICAL)
195 insizer.Add(DoodlePad(self, log), 1, wxEXPAND|wxALL, 5)
196 insizer.Add(DoodleViewer(self, log), 1, wxEXPAND|wxALL, 5)
197
198 sizer.Add(insizer, 1, wxEXPAND)
199 self.SetAutoLayout(true)
200 self.SetSizer(sizer)
201
202
203
204
205 #----------------------------------------------------------------------
206 #----------------------------------------------------------------------
207
208 class TestPanel(wxPanel):
209 def __init__(self, parent, log):
210 wxPanel.__init__(self, parent, -1)
211
212 self.SetAutoLayout(true)
213 sizer = wxBoxSizer(wxVERTICAL)
214
215 msg = "Custom Drag-And-Drop"
216 text = wxStaticText(self, -1, "", style=wxALIGN_CENTRE)
217 text.SetFont(wxFont(24, wxSWISS, wxNORMAL, wxBOLD, false))
218 text.SetLabel(msg)
219 w,h = text.GetTextExtent(msg)
220 text.SetSize(wxSize(w,h+1))
221 text.SetForegroundColour(wxBLUE)
222 sizer.Add(text, 0, wxEXPAND|wxALL, 5)
223 sizer.Add(wxStaticLine(self, -1), 0, wxEXPAND)
224
225 sizer.Add(CustomDnDPanel(self, log), 1, wxEXPAND)
226
227 self.SetSizer(sizer)
228
229
230 #----------------------------------------------------------------------
231
232 def runTest(frame, nb, log):
233 win = TestPanel(nb, log)
234 return win
235
236
237 if __name__ == '__main__':
238 import sys
239 class DummyLog:
240 def WriteText(self, text):
241 sys.stdout.write(text)
242
243 class TestApp(wxApp):
244 def OnInit(self):
245 self.MakeFrame()
246 return true
247
248 def MakeFrame(self, event=None):
249 frame = wxFrame(None, -1, "Custom Drag and Drop", size=(550,400))
250 menu = wxMenu()
251 menu.Append(6543, "Window")
252 mb = wxMenuBar()
253 mb.Append(menu, "New")
254 frame.SetMenuBar(mb)
255 EVT_MENU(frame, 6543, self.MakeFrame)
256 panel = TestPanel(frame, DummyLog())
257 frame.Show(true)
258 self.SetTopWindow(frame)
259
260
261
262 app = TestApp(0)
263 app.MainLoop()
264
265 #----------------------------------------------------------------------
266
267
268
269
270
271
272
273
274
275
276
277
278 overview = """\
279 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.
280
281 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.
282
283 The two data objects are combined in a wxDataObjectComposite and the rest is handled by the framework.
284 """
285