Skip to content

Commit

Permalink
Merge pull request #18 from nmichaud/bubble-fade
Browse files Browse the repository at this point in the history
Add fade-out animation to BubbleView when closing it
  • Loading branch information
sccolbert committed May 2, 2013
2 parents 0d1fa08 + 2d55b53 commit 62d5a3a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 3 deletions.
52 changes: 51 additions & 1 deletion enaml/qt/q_bubble_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
from PyQt4.QtCore import Qt, QSize, QPoint, QMargins, QEvent, pyqtSignal
from PyQt4.QtCore import (
Qt, QSize, QPoint, QMargins, QEvent, pyqtSignal, QPropertyAnimation,
)
from PyQt4.QtGui import QWidget, QLayout, QPainter, QPainterPath

from .q_single_widget_layout import QSingleWidgetLayout
Expand All @@ -28,6 +30,9 @@ class QBubbleView(QWidget):
AnchorLeft = 2
AnchorRight = 3

#: close on defocus
_close_on_defocus = True

def __init__(self, parent=None):
super(QBubbleView, self).__init__(parent)
self._central_widget = None
Expand All @@ -47,6 +52,14 @@ def __init__(self, parent=None):
self.setArrowSize(20)
self.setRadius(10)

# Closing animation
self._fade_time = 150
self._close_anim = anim = QPropertyAnimation(self, "windowOpacity", self)
anim.setDuration(self._fade_time)
anim.setStartValue(1)
anim.setEndValue(0)
anim.finished.connect(super(QBubbleView, self).close)

# track parent window movement
parent.window().installEventFilter(self)
parent.destroyed.connect(self.deleteLater)
Expand Down Expand Up @@ -191,6 +204,29 @@ def relativePos(self):
"""
return self._relative_pos

def setCloseOnDefocus(self, do_close):
""" Set whether the bubble view closes when it loses focus
Parameters
----------
do_close : bool
Whether to automatically close the bubble view when it
loses focus
"""
self._close_on_defocus = do_close

def closeOnDefocus(self):
""" Return whether to close on losing focus
Returns
-------
result : bool
Whether to close on losing focus
"""
return self._close_on_defocus

def paintEvent(self, event):
""" Reimplement the paint event
Expand Down Expand Up @@ -230,6 +266,20 @@ def eventFilter(self, obj, event):
self.move(self.pos() + event.pos() - event.oldPos())
return False

def close(self):
""" Fade the popup out
"""
self._close_anim.start()

def event(self, event):
""" Handle focus lost
"""
if self._close_on_defocus and event.type() == QEvent.Leave:
self.close()
return super(QBubbleView, self).event(event)

def _rebuild(self):
""" Rebuild the path used to draw the outline of the popup.
Expand Down
7 changes: 7 additions & 0 deletions enaml/qt/qt_bubble_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def init_widget(self):
self.set_arrow(d.arrow)
self.set_radius(d.radius)
self.set_relative_pos(d.relative_pos)
self.set_close_on_defocus(d.close_on_defocus)
self.widget.closed.connect(self.on_closed)

def init_layout(self):
Expand Down Expand Up @@ -114,3 +115,9 @@ def set_relative_pos(self, relative_pos):
"""
self.widget.setRelativePos(relative_pos)

def set_close_on_defocus(self, do_close):
""" Set whether to close bubble view on losing focus
"""
self.widget.setCloseOnDefocus(do_close)
10 changes: 8 additions & 2 deletions enaml/widgets/bubble_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
from atom.api import (
Enum, Event, Int, Tuple, Typed, ForwardTyped, observe, set_default,
Enum, Event, Int, Tuple, Typed, ForwardTyped, Bool, observe, set_default,
)

from enaml.application import deferred_call
Expand Down Expand Up @@ -38,6 +38,9 @@ def set_arrow(self, arrow):
def set_relative_pos(self, relative_pos):
raise NotImplementedError

def set_close_on_defocus(self, do_close):
raise NotImplementedError

def close(self):
raise NotImplementedError

Expand Down Expand Up @@ -65,6 +68,9 @@ class BubbleView(Widget):
#: bounds
relative_pos = d_(Tuple(float, (0.5, 0.5)))

#: Whether to close on losing focus
close_on_defocus = d_(Bool(True))

#: An event fired when the BubbleView is closed.
closed = d_(Event(), writable=False)

Expand Down Expand Up @@ -110,7 +116,7 @@ def show(self):
#--------------------------------------------------------------------------
# Observers
#--------------------------------------------------------------------------
@observe(('anchor', 'radius', 'arrow', 'relative_pos'))
@observe(('anchor', 'radius', 'arrow', 'relative_pos', 'close_on_defocus'))
def _update_proxy(self, change):
""" Update the ProxyBubbleView when the BubbleView data changes.
Expand Down

0 comments on commit 62d5a3a

Please sign in to comment.