1 # -*- coding: utf-8 -*-
11 from threading
import Thread
13 from eventutils
import EventHandlerMixin
, event_handler
14 from itertools
import cycle
16 class WarpingCursor(pygame
.sprite
.DirtySprite
, EventHandlerMixin
):
18 The class for animating the warping cursor
22 def _get_theme_images(name
) :
23 basePath
= os
.path
.abspath(__file__
).split(os
.path
.sep
)[:-1]
24 basePath
.extend(['data', 'cursor'])
26 basePath
= os
.path
.sep
.join(basePath
)
27 images
= [f
for f
in os
.listdir(basePath
) if os
.path
.splitext(f
)[1] == '.png']
28 return basePath
, images
31 def __init__(self
, theme
='black-perforated', duration
=100, blinkMode
=True):
32 pygame
.sprite
.DirtySprite
.__init
__(self
)
33 imagesPath
, images
= WarpingCursor
._get
_theme
_images
(theme
)
34 flashImage
= images
.pop(images
.index('flash.png'))
35 flashImagePath
= os
.path
.sep
.join([imagesPath
, flashImage
])
36 self
.flashImage
= pygame
.image
.load(flashImagePath
).convert_alpha()
37 images
.sort(lambda a
, b
: cmp(*[int(os
.path
.splitext(f
)[0]) for f
in [a
, b
]]))
41 imagePath
= os
.path
.sep
.join([imagesPath
, img
])
42 img
= pygame
.image
.load(imagePath
).convert_alpha()
43 self
.images
.append(img
)
45 # assumes that all images have same dimensions
46 self
.width
= self
.images
[0].get_width()
47 self
.height
= self
.images
[0].get_height()
48 self
.duration
= duration
50 self
.image
= self
.images
[0]
51 # workarround cursor alignement problem
52 pygame
.event
.set_blocked(pygame
.MOUSEMOTION
)
53 pygame
.mouse
.set_pos(pygame
.mouse
.get_pos())
54 pygame
.event
.set_allowed(pygame
.MOUSEMOTION
)
56 x
, y
= pygame
.mouse
.get_pos()
57 left
= x
- self
.width
/ 2
58 top
= y
- self
.height
/ 2
59 self
.rect
= pygame
.Rect((left
, top
), (self
.width
, self
.height
))
61 self
.blinkMode
= blinkMode
65 if hasattr(self
, 'timer') :
66 try : self
.timer
.stop()
69 def _startBlink(self
) :
72 self
.iterator
= self
.iterImages()
73 self
.timer
= ForeverTimer(self
.duration
, self
.loadNext
)
76 def _stopBlink(self
) :
80 def iterImages(self
) :
81 for img
in cycle(self
.images
) :
87 self
.image
= self
.iterator
.next()
89 @event_handler(pygame
.MOUSEBUTTONDOWN
)
90 def flashOn(self
, event
) :
92 self
._blinking
= False
93 self
.image
= self
.flashImage
95 @event_handler(pygame
.MOUSEBUTTONUP
)
96 def flashOff(self
, event
) :
101 self
.image
= self
.images
[0]
103 @event_handler(pygame
.MOUSEMOTION
)
104 def move(self
, event
) :
106 self
.rect
.move_ip(event
.rel
)
108 def setPosition(self
, pos
) :
111 rx
, ry
= self
.rect
.centerx
, self
.rect
.centery
112 self
.rect
.move_ip(x
-rx
, y
-ry
)
115 class ForeverTimer(Thread
) :
116 def __init__(self
, duration
, func
, *args
, **kw
) :
117 Thread
.__init
__(self
)
118 self
.duration
= duration
/ 1000.
126 self
.func(*self
.args
, **self
.kw
)
127 time
.sleep(self
.duration
)