X-Git-Url: https://scm.cri.ensmp.fr/git/minwii.git/blobdiff_plain/e7854ed82aa375273bfbf772493739f875817061..46f3ffd7fdde386f41020171b5733e55a8e64a85:/src/minwii/widgets/cursors.py diff --git a/src/minwii/widgets/cursors.py b/src/minwii/widgets/cursors.py new file mode 100755 index 0000000..fa1f673 --- /dev/null +++ b/src/minwii/widgets/cursors.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +""" +Curseurs winwii + +$Id$ +$URL$ +""" + +import pygame +import os +from threading import Thread +import time +from eventutils import EventHandlerMixin, event_handler +from itertools import cycle + +class WarpingCursor(pygame.sprite.DirtySprite, EventHandlerMixin): + ''' + The class for animating the warping cursor + ''' + + @staticmethod + def _get_theme_images(name) : + basePath = os.path.abspath(__file__).split(os.path.sep)[:-1] + basePath.extend(['data', 'cursor']) + basePath.append(name) + basePath = os.path.sep.join(basePath) + images = [f for f in os.listdir(basePath) if os.path.splitext(f)[1] == '.png'] + return basePath, images + + + def __init__(self, theme='black-perforated', duration=100, blinkMode=True): + pygame.sprite.DirtySprite.__init__(self) + imagesPath, images = WarpingCursor._get_theme_images(theme) + flashImage = images.pop(images.index('flash.png')) + flashImagePath = os.path.sep.join([imagesPath, flashImage]) + self.flashImage = pygame.image.load(flashImagePath).convert_alpha() + images.sort(lambda a, b : cmp(*[int(os.path.splitext(f)[0]) for f in [a, b]])) + + self.images = [] + for img in images : + imagePath = os.path.sep.join([imagesPath, img]) + img = pygame.image.load(imagePath).convert_alpha() + self.images.append(img) + + # assumes that all images have same dimensions + self.width = self.images[0].get_width() + self.height = self.images[0].get_height() + self.duration = duration + + self.image = self.images[0] + # workarround cursor alignement problem + pygame.event.set_blocked(pygame.MOUSEMOTION) + pygame.mouse.set_pos(pygame.mouse.get_pos()) + pygame.event.set_allowed(pygame.MOUSEMOTION) + # --- + x, y = pygame.mouse.get_pos() + left = x - self.width / 2 + top = y - self.height / 2 + self.rect = pygame.Rect((left, top), (self.width, self.height)) + + self.blinkMode = blinkMode + self._startBlink() + + def __del__(self) : + if hasattr(self, 'timer') : + try : self.timer.stop() + except : pass + + def _startBlink(self) : + if self.blinkMode : + self._blinking = True + self.iterator = self.iterImages() + self.timer = ForeverTimer(self.duration, self.loadNext) + self.timer.start() + + def _stopBlink(self) : + if self.blinkMode : + self.timer.stop() + + def iterImages(self) : + for img in cycle(self.images) : + yield img + + def loadNext(self) : + if self._blinking : + self.dirty = 1 + self.image = self.iterator.next() + + @event_handler(pygame.MOUSEBUTTONDOWN) + def flashOn(self, event) : + self.dirty = 1 + self._blinking = False + self.image = self.flashImage + + @event_handler(pygame.MOUSEBUTTONUP) + def flashOff(self, event) : + self.dirty = 1 + if self.blinkMode : + self._blinking = True + else : + self.image = self.images[0] + + @event_handler(pygame.MOUSEMOTION) + def move(self, event) : + self.dirty = 1 + self.rect.move_ip(event.rel) + + def setPosition(self, pos) : + self.dirty = 1 + x, y = pos + rx, ry = self.rect.centerx, self.rect.centery + self.rect.move_ip(x-rx, y-ry) + + +class ForeverTimer(Thread) : + def __init__(self, duration, func, *args, **kw) : + Thread.__init__(self) + self.duration = duration / 1000. + self.func = func + self.args = args + self.kw = kw + self.running = True + + def run(self) : + while self.running : + self.func(*self.args, **self.kw) + time.sleep(self.duration) + + def stop(self) : + self.running = False \ No newline at end of file