]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/wxDragImage.py
1 # 11/15/2003 - Jeff Grimmett (grimmtooth@softhome.net)
3 # o Updated for wx namespace
9 #----------------------------------------------------------------------
12 def __init__(self
, bmp
):
17 self
.fullscreen
= False
19 def HitTest(self
, pt
):
21 return rect
.InsideXY(pt
.x
, pt
.y
)
24 return wx
.Rect(self
.pos
[0], self
.pos
[1],
25 self
.bmp
.GetWidth(), self
.bmp
.GetHeight())
27 def Draw(self
, dc
, op
= wx
.COPY
):
30 memDC
.SelectObject(self
.bmp
)
32 dc
.Blit((self
.pos
[0], self
.pos
[1]),
33 (self
.bmp
.GetWidth(), self
.bmp
.GetHeight()),
34 memDC
, (0, 0), op
, True)
42 #----------------------------------------------------------------------
44 class DragCanvas(wx
.ScrolledWindow
):
45 def __init__(self
, parent
, ID
):
46 wx
.ScrolledWindow
.__init
__(self
, parent
, ID
)
50 self
.hiliteShape
= None
52 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
53 self
.bg_bmp
= images
.getBackgroundBitmap()
55 # Make a shape from an image and mask. This one will demo
56 # dragging outside the window
57 bmp
= images
.getTestStarBitmap()
58 shape
= DragShape(bmp
)
60 shape
.fullscreen
= True
61 self
.shapes
.append(shape
)
63 # Make a shape from some text
65 bg_colour
= wx
.Colour(57, 115, 57) # matches the bg image
66 font
= wx
.Font(15, wx
.ROMAN
, wx
.NORMAL
, wx
.BOLD
)
67 textExtent
= self
.GetFullTextExtent(text
, font
)
69 # create a bitmap the same size as our text
70 bmp
= wx
.EmptyBitmap(textExtent
[0], textExtent
[1])
72 # 'draw' the text onto the bitmap
75 dc
.SetBackground(wx
.Brush(bg_colour
, wx
.SOLID
))
77 dc
.SetTextForeground(wx
.RED
)
79 dc
.DrawText(text
, (0, 0))
80 dc
.SelectObject(wx
.NullBitmap
)
81 mask
= wx
.MaskColour(bmp
, bg_colour
)
83 shape
= DragShape(bmp
)
85 shape
.text
= "Some dragging text"
86 self
.shapes
.append(shape
)
89 # Make some shapes from some playing card images.
92 for card
in ['_01c_', '_12h_', '_13d_', '_10s_']:
93 bmpFunc
= getattr(images
, "get%sBitmap" % card
)
95 shape
= DragShape(bmp
)
97 self
.shapes
.append(shape
)
101 self
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnEraseBackground
)
102 self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
)
103 self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftDown
)
104 self
.Bind(wx
.EVT_LEFT_UP
, self
.OnLeftUp
)
105 self
.Bind(wx
.EVT_MOTION
, self
.OnMotion
)
106 self
.Bind(wx
.EVT_LEAVE_WINDOW
, self
.OnLeaveWindow
)
109 # We're not doing anything here, but you might have reason to.
110 # for example, if you were dragging something, you might elect to
111 # 'drop it' when the cursor left the window.
112 def OnLeaveWindow(self
, evt
):
116 # tile the background bitmap
117 def TileBackground(self
, dc
):
118 sz
= self
.GetClientSize()
119 w
= self
.bg_bmp
.GetWidth()
120 h
= self
.bg_bmp
.GetHeight()
128 dc
.DrawBitmap(self
.bg_bmp
, (x
, y
))
134 # Go through our list of shapes and draw them in whatever place they are.
135 def DrawShapes(self
, dc
):
136 for shape
in self
.shapes
:
140 # This is actually a sophisticated 'hit test', but in this
141 # case we're also determining which shape, if any, was 'hit'.
142 def FindShape(self
, pt
):
143 for shape
in self
.shapes
:
144 if shape
.HitTest(pt
):
148 # Remove a shape from the display
149 def EraseShape(self
, shape
, dc
):
151 dc
.SetClippingRect(r
)
152 self
.TileBackground(dc
)
154 dc
.DestroyClippingRegion()
156 # Clears the background, then redraws it. If the DC is passed, then
157 # we only do so in the area so designated. Otherwise, it's the whole thing.
158 def OnEraseBackground(self
, evt
):
162 dc
= wxClientDC(self
)
163 rect
= self
.GetUpdateRegion().GetBox()
164 dc
.SetClippingRect(rect
)
165 self
.TileBackground(dc
)
167 # Fired whenever a paint event occurs
168 def OnPaint(self
, evt
):
169 dc
= wx
.PaintDC(self
)
173 # Left mouse button is down.
174 def OnLeftDown(self
, evt
):
175 # Did the mouse go down on one of our shapes?
176 shape
= self
.FindShape(evt
.GetPosition())
178 # If a shape was 'hit', then set that as the shape we're going to
179 # drag around. Get our start position. Dragging has not yet started.
180 # That will happen once the mouse moves, OR the mouse is released.
182 self
.dragShape
= shape
183 self
.dragStartPos
= evt
.GetPosition()
185 # Left mouse button up.
186 def OnLeftUp(self
, evt
):
187 if not self
.dragImage
or not self
.dragShape
:
188 self
.dragImage
= None
189 self
.dragShape
= None
192 # Hide the image, end dragging, and nuke out the drag image.
193 self
.dragImage
.Hide()
194 self
.dragImage
.EndDrag()
195 self
.dragImage
= None
197 dc
= wx
.ClientDC(self
)
200 self
.hiliteShape
.Draw(dc
)
201 self
.hiliteShape
= None
203 # reposition and draw the shape
205 # Note by jmg 11/28/03
206 # Here's the original:
208 # self.dragShape.pos = self.dragShape.pos + evt.GetPosition() - self.dragStartPos
210 # So if there are any problems associated with this, use that as
211 # a starting place in your investigation. I've tried to simulate the
212 # wx.Point __add__ method here -- it won't work for tuples as we
213 # have now from the various methods
215 # There must be a better way to do this :-)
218 self
.dragShape
.pos
= (
219 self
.dragShape
.pos
[0] + evt
.GetPosition()[0] - self
.dragStartPos
[0],
220 self
.dragShape
.pos
[1] + evt
.GetPosition()[1] - self
.dragStartPos
[1]
223 self
.dragShape
.shown
= True
224 self
.dragShape
.Draw(dc
)
225 self
.dragShape
= None
227 # The mouse is moving
228 def OnMotion(self
, evt
):
229 # Ignore mouse movement if we're not dragging.
230 if not self
.dragShape
or not evt
.Dragging() or not evt
.LeftIsDown():
233 # if we have a shape, but haven't started dragging yet
234 if self
.dragShape
and not self
.dragImage
:
236 # only start the drag after having moved a couple pixels
238 pt
= evt
.GetPosition()
239 dx
= abs(pt
.x
- self
.dragStartPos
.x
)
240 dy
= abs(pt
.y
- self
.dragStartPos
.y
)
241 if dx
<= tolerance
and dy
<= tolerance
:
244 # erase the shape since it will be drawn independently now
245 dc
= wx
.ClientDC(self
)
246 self
.dragShape
.shown
= False
247 self
.EraseShape(self
.dragShape
, dc
)
250 if self
.dragShape
.text
:
251 self
.dragImage
= wx
.DragString(self
.dragShape
.text
,
252 wx
.StockCursor(wx
.CURSOR_HAND
))
254 self
.dragImage
= wx
.DragImage(self
.dragShape
.bmp
,
255 wx
.StockCursor(wx
.CURSOR_HAND
))
257 hotspot
= self
.dragStartPos
- self
.dragShape
.pos
258 self
.dragImage
.BeginDrag(hotspot
, self
, self
.dragShape
.fullscreen
)
260 self
.dragImage
.Move(pt
)
261 self
.dragImage
.Show()
264 # if we have shape and image then move it, posibly highlighting another shape.
265 elif self
.dragShape
and self
.dragImage
:
266 onShape
= self
.FindShape(evt
.GetPosition())
270 # figure out what to hilite and what to unhilite
272 if onShape
is None or self
.hiliteShape
is not onShape
:
275 if onShape
and onShape
is not self
.hiliteShape
and onShape
.shown
:
278 # if needed, hide the drag image so we can update the window
279 if unhiliteOld
or hiliteNew
:
280 self
.dragImage
.Hide()
283 dc
= wx
.ClientDC(self
)
284 self
.hiliteShape
.Draw(dc
)
285 self
.hiliteShape
= None
288 dc
= wx
.ClientDC(self
)
289 self
.hiliteShape
= onShape
290 self
.hiliteShape
.Draw(dc
, wx
.INVERT
)
292 # now move it and show it again if needed
293 self
.dragImage
.Move(evt
.GetPosition())
294 if unhiliteOld
or hiliteNew
:
295 self
.dragImage
.Show()
298 #----------------------------------------------------------------------
300 def runTest(frame
, nb
, log
):
302 win
= wx
.Panel(nb
, -1)
303 canvas
= DragCanvas(win
, -1)
305 def onSize(evt
, panel
=win
, canvas
=canvas
):
306 canvas
.SetSize(panel
.GetSize())
308 win
.Bind(wx
.EVT_SIZE
, onSize
)
311 #----------------------------------------------------------------------
316 DragImage is used when you wish to drag an object on the screen, and a simple
317 cursor is not enough.
319 On Windows, the WIN32 API is used to do achieve smooth dragging. On other
320 platforms, <code>GenericDragImage</code> is used. Applications may also prefer to use
321 <code>GenericDragImage</code> on Windows, too.
323 <b>wxPython note</b>: wxPython uses <code>GenericDragImage</code> on all
324 platforms, but uses the <code>DragImage</code> name.
326 To use this class, when you wish to start dragging an image, create a
327 <code>DragImage</code> object and store it somewhere you can access it as the
328 drag progresses. Call BeginDrag to start, and EndDrag to stop the drag. To move
329 the image, initially call Show and then Move. If you wish to update the screen
330 contents during the drag (for example, highlight an item as in the example), first
331 call Hide, update the screen, call Move, and then call Show.
333 You can drag within one window, or you can use full-screen dragging either across
334 the whole screen, or just restricted to one area of the screen to save resources.
335 If you want the user to drag between two windows, then you will need to use
336 full-screen dragging.
341 if __name__
== '__main__':
344 run
.main(['', os
.path
.basename(sys
.argv
[0])])