Ignore:
Timestamp:
03/18/13 11:52:35 (13 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Added ping and shadow animations for node items.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/OrangeCanvas/canvas/items/nodeitem.py

    r11369 r11411  
    77 
    88from PyQt4.QtGui import ( 
    9     QGraphicsItem, QGraphicsPathItem, QGraphicsObject, 
    10     QGraphicsTextItem, QGraphicsDropShadowEffect, QGraphicsView, 
     9    QGraphicsItem, QGraphicsObject, QGraphicsTextItem, 
     10    QGraphicsDropShadowEffect, QGraphicsView, 
    1111    QPen, QBrush, QColor, QPalette, QIcon, QStyle, QPainter, 
    1212    QPainterPath, QPainterPathStroker, QApplication 
    1313) 
    1414 
    15 from PyQt4.QtCore import Qt, QPointF, QRectF, QSize, QTimer 
     15from PyQt4.QtCore import Qt, QPointF, QRectF, QSize, QTimer, QPropertyAnimation 
    1616from PyQt4.QtCore import pyqtSignal as Signal 
    1717from PyQt4.QtCore import pyqtProperty as Property 
     
    5656 
    5757 
     58def animation_restart(animation): 
     59    if animation.state() == QPropertyAnimation.Running: 
     60        animation.pause() 
     61    animation.start() 
     62 
     63 
    5864SHADOW_COLOR = "#9CACB4" 
    5965FOCUS_OUTLINE_COLOR = "#609ED7" 
    6066 
    6167 
    62 class NodeBodyItem(QGraphicsPathItem): 
     68class NodeBodyItem(GraphicsPathObject): 
    6369    """ 
    6470    The central part (body) of the `NodeItem`. 
    6571    """ 
    6672    def __init__(self, parent=None): 
    67         QGraphicsPathItem.__init__(self, parent) 
     73        GraphicsPathObject.__init__(self, parent) 
    6874        assert(isinstance(parent, NodeItem)) 
    6975 
    7076        self.__processingState = 0 
    7177        self.__progress = -1 
     78        self.__animationEnabled = False 
    7279        self.__isSelected = False 
    7380        self.__hasFocus = False 
     
    8592 
    8693        self.shadow = QGraphicsDropShadowEffect( 
    87             blurRadius=10, 
     94            blurRadius=3, 
    8895            color=QColor(SHADOW_COLOR), 
    8996            offset=QPointF(0, 0), 
     
    9198 
    9299        self.setGraphicsEffect(self.shadow) 
    93         self.shadow.setEnabled(False) 
     100        self.shadow.setEnabled(True) 
     101 
     102        self.__blurAnimation = QPropertyAnimation(self.shadow, "blurRadius", 
     103                                                  self) 
     104        self.__blurAnimation.setDuration(100) 
     105        self.__blurAnimation.finished.connect(self.__on_finished) 
     106 
     107        self.__pingAnimation = QPropertyAnimation(self, "scale", self) 
     108        self.__pingAnimation.setDuration(250) 
     109        self.__pingAnimation.setKeyValues([(0.0, 1.0), (0.5, 1.1), (1.0, 1.0)]) 
    94110 
    95111    # TODO: The body item should allow the setting of arbitrary painter 
     
    113129        self.__updateBrush() 
    114130 
     131    def setAnimationEnabled(self, enabled): 
     132        """ 
     133        Set the node animation enabled. 
     134        """ 
     135        if self.__animationEnabled != enabled: 
     136            self.__animationEnabled = enabled 
     137 
    115138    def setProcessingState(self, state): 
    116139        """ 
    117140        Set the processing state of the node. 
    118141        """ 
    119         self.__processingState = state 
    120         self.update() 
     142        if self.__processingState != state: 
     143            self.__processingState = state 
     144            if not state and self.__animationEnabled: 
     145                self.ping() 
    121146 
    122147    def setProgress(self, progress): 
     
    128153        self.__progress = progress 
    129154        self.update() 
     155 
     156    def ping(self): 
     157        """ 
     158        Trigger a 'ping' animation. 
     159        """ 
     160        animation_restart(self.__pingAnimation) 
    130161 
    131162    def hoverEnterEvent(self, event): 
    132163        self.__hover = True 
    133164        self.__updateShadowState() 
    134         return QGraphicsPathItem.hoverEnterEvent(self, event) 
     165        return GraphicsPathObject.hoverEnterEvent(self, event) 
    135166 
    136167    def hoverLeaveEvent(self, event): 
    137168        self.__hover = False 
    138169        self.__updateShadowState() 
    139         return QGraphicsPathItem.hoverLeaveEvent(self, event) 
     170        return GraphicsPathObject.hoverLeaveEvent(self, event) 
    140171 
    141172    def paint(self, painter, option, widget): 
     
    147178            # Prevent the default bounding rect selection indicator. 
    148179            option.state = option.state ^ QStyle.State_Selected 
    149         QGraphicsPathItem.paint(self, painter, option, widget) 
     180        GraphicsPathObject.paint(self, painter, option, widget) 
    150181 
    151182        if self.__progress >= 0: 
     
    169200            self.setPen(QPen(Qt.NoPen)) 
    170201 
     202        radius = 3 
    171203        enabled = False 
     204 
    172205        if self.__isSelected: 
    173             self.shadow.setBlurRadius(7) 
    174206            enabled = True 
    175         elif self.__hover: 
    176             self.shadow.setBlurRadius(17) 
     207            radius = 7 
     208 
     209        if self.__hover: 
     210            radius = 17 
    177211            enabled = True 
    178         self.shadow.setEnabled(enabled) 
     212 
     213        if enabled and not self.shadow.isEnabled(): 
     214            self.shadow.setEnabled(enabled) 
     215 
     216        if self.__animationEnabled: 
     217            if self.__blurAnimation.state() == QPropertyAnimation.Running: 
     218                self.__blurAnimation.pause() 
     219 
     220            self.__blurAnimation.setStartValue(self.shadow.blurRadius()) 
     221            self.__blurAnimation.setEndValue(radius) 
     222            self.__blurAnimation.start() 
     223        else: 
     224            self.shadow.setBlurRadius(radius) 
    179225 
    180226    def __updateBrush(self): 
     
    215261        self.__hasFocus = focus 
    216262        self.__updateShadowState() 
     263 
     264    def __on_finished(self): 
     265        if self.shadow.blurRadius() == 0: 
     266            self.shadow.setEnabled(False) 
    217267 
    218268 
     
    692742 
    693743        self.__anchorLayout = None 
     744        self.__animationEnabled = False 
    694745 
    695746        self.setZValue(self.Z_VALUE) 
     
    727778        self.shapeItem = NodeBodyItem(self) 
    728779        self.shapeItem.setShapeRect(shape_rect) 
     780        self.shapeItem.setAnimationEnabled(self.__animationEnabled) 
    729781 
    730782        # Rect for widget's 'ears'. 
     
    855907        return self.captionTextItem.font() 
    856908 
     909    def setAnimationEnabled(self, enabled): 
     910        """ 
     911        Set the node animation enabled state. 
     912        """ 
     913        if self.__animationEnabled != enabled: 
     914            self.__animationEnabled = enabled 
     915            self.shapeItem.setAnimationEnabled(enabled) 
     916 
     917    def animationEnabled(self): 
     918        """ 
     919        Are node animations enabled. 
     920        """ 
     921        return self.__animationEnabled 
     922 
    857923    def setProcessingState(self, state): 
    858924        """ 
     
    867933                # Clear the progress meter. 
    868934                self.setProgress(-1) 
     935                if self.__animationEnabled: 
     936                    self.shapeItem.ping() 
    869937 
    870938    def processingState(self): 
Note: See TracChangeset for help on using the changeset viewer.