コード例 #1
0
class ParameterSuggestionWindow(object):
    """
    Encapsulates the drawing of a single line of text, with optional
    rounded corners and an optional "override width", which overides the
    default width (margins + text width).
    """

    def __init__(self, height, position):
        """
        Creates the underlying TransparentWindow and Cairo context.

        Position and height should be in pixels.
        """

        # Use the maximum width that we can, i.e., the desktop width.
        desk_width, desk_height = graphics.getDesktopSize()
        desk_left, desk_top = graphics.getDesktopOffset()

        xPos, yPos = position
        if yPos + height > desk_height:
            pass
        self.__window = TransparentWindow(
            xPos + desk_left, yPos + desk_top, desk_width, desk_height - desk_top - yPos)
        self.__context = self.__window.makeCairoContext()
        self.__is_visible = False
        self.__animatingShow = False
        self.__animatingHide = False
        self.__timeSinceDismissal = 0
        self.__evtManager = EventManager.get()

    def getHeight(self):
        """
        LONGTERM TODO: Document this.
        """

        return self.__window.getHeight()

    def getPosition(self):
        """
        LONGTERM TODO: Document this.
        """

        return Position(self.__window.getX(), self.__window.getY())

    def setPosition(self, x, y):
        """
        LONGTERM TODO: Document this.
        """
        self.__window.setPosition(x, y)

    def draw(self, document, activeIndex):
        """
        Draws the text described by document.

        An updating call; at the end of this method, the displayed
        window should reflect the drawn content.
        """

        def _computeWidth(doc):
            lines = []
            for b in doc.blocks:
                lines.extend(b.lines)
            if len(lines) == 0:
                return 0
            return max([l.xMax for l in lines])

        def _computeHeight(doc):
            height = 0
            for b in doc.blocks:
                height += b.height
                # for line in b.lines:
                #    height += line.lineHeight
            return height

        width = _computeWidth(document) + layout.L_MARGIN + layout.R_MARGIN
        width = max(width, 300)
        height = document.height  # _computeHeight(document)

        cr = self.__context

        # Clear the areas where the corners of the rounded rectangle will be.

        cr.save()
        cr.set_source_rgba(0, 0, 0, 0)
        cr.set_operator(cairo.OPERATOR_SOURCE)  # IGNORE:E1101 @UndefinedVariable
        cr.rectangle(width - rounded_rect.CORNER_RADIUS,
                     height - rounded_rect.CORNER_RADIUS,
                     rounded_rect.CORNER_RADIUS,
                     rounded_rect.CORNER_RADIUS)
        cr.rectangle(width - rounded_rect.CORNER_RADIUS,
                     0,
                     rounded_rect.CORNER_RADIUS,
                     rounded_rect.CORNER_RADIUS)
        cr.paint()

        """
        # Draw the background rounded rectangle.
        corners = []
        #corners.append( rounded_rect.UPPER_LEFT )
        #if document.roundUpperRight:
        corners.append( rounded_rect.UPPER_RIGHT )
        #if document.roundLowerRight:
        corners.append( rounded_rect.LOWER_RIGHT )
        #if document.roundLowerLeft:
        corners.append( rounded_rect.LOWER_LEFT )
        """
        corners = {
            rounded_rect.UPPER_RIGHT: None,
            rounded_rect.LOWER_RIGHT: 14,
            rounded_rect.LOWER_LEFT: None
        }

        document.background = xmltextlayout.colorHashToRgba(
            layout.MAIN_BACKGROUND_COLOR)

        cr.set_source_rgba(*document.background)
        rounded_rect.drawRoundedRect(context=cr,
                                     rect=(0, 0, width, height),
                                     softenedCorners=corners)
        cr.fill_preserve()

        cr.set_source_rgba(*xmltextlayout.colorHashToRgba("#404040"))
        cr.set_line_width(1.0)

        if activeIndex is not None:
            bar_left = layout.L_MARGIN - 2
            bar_width = width - bar_left - layout.L_MARGIN + 2
            bar_height = document.blocks[0].height
            bar_top = activeIndex * bar_height + document.marginTop

            rounded_rect.drawRoundedRect(context=cr,
                                         rect=(
                                             bar_left,
                                             bar_top,
                                             bar_width,
                                             bar_height),
                                         softenedCorners=rounded_rect.ALL_CORNERS,
                                         radius=2)

        cr.fill_preserve()
        # cr.stroke()

        cr.restore()

        # Next, draw the text.
        document.draw(layout.L_MARGIN,
                      document.shrinkOffset,
                      self.__context)

        width = min(self.__window.getMaxWidth(), width)

        # height = document.blocks[0].height * len(document.blocks) #layout.PARAMETERSUGGESTION_SCALE[-1]*layout.HEIGHT_FACTOR
        #height = min( self.__window.getMaxHeight(), height )

        #self.__window.setSize( width, height )

        if not self.__is_visible and not self.__animatingShow:
            self.__animatingShow = True
            self.__animatingHide = False
            self.__is_visible = True
            self.__timeSinceDismissal = 0
            with suppress(AssertionError):
                self.__evtManager.registerResponder(
                    self.animationTick, "timer")
        else:
            # Just refreshing
            started = time.time()
            self.__window.setOpacity(MAX_OPACITY)
            # print time.time() - started
            self.__window.update()
        # print time.time() - started

    def hide(self, animated=True):
        """
        Clears the window's surface (making it disappear).
        """
        if not self.__is_visible:
            return

        if self.__animatingHide or self.__animatingShow:
            self.__onAnimationFinished()
            return

        # LONGTERM TODO: Clearing the surface, i.e., painting it
        # clear, seems like a potential performance bottleneck.

        #self.__window.setSize( 1, 1 )

        # Frankly, I don't know why this works, but after this
        # function, the resulting window is totally clear. I find it
        # odd, since the alpha value is not being set.  It is a
        # wierdness of Cairo. -- Andrew

        #self.__context.set_operator (cairo.OPERATOR_CLEAR)
        #self.__context.paint ()
        #self.__context.set_operator (cairo.OPERATOR_OVER)

        # self.__window.update()

        if animated:
            self.__timeSinceDismissal = 0
            self.__animatingHide = True
            self.__animatingShow = False
            self.__evtManager.registerResponder(self.animationTick, "timer")
        else:
            self.__window.hide()
            self.__animatingHide = False
            self.__animatingShow = False

    def animationTick(self, msPassed):
        """
        Called on a timer event to animate the window fadeout
        """

        self.__timeSinceDismissal += msPassed
        if self.__timeSinceDismissal > ANIMATION_TIME:
            if self.__animatingShow and self.__is_visible:
                self.__onAnimationFinished()
            return

        timeLeft = ANIMATION_TIME - self.__timeSinceDismissal
        frac = timeLeft / float(ANIMATION_TIME)
        opacity = int(MAX_OPACITY * frac)

        if self.__animatingHide:
            self.__window.setOpacity(opacity)
            if opacity == 0:
                self.__is_visible = False
        elif self.__animatingShow:
            self.__is_visible = True
            self.__window.setOpacity(MAX_OPACITY - opacity)

        self.__window.update()

    def __onAnimationFinished(self):
        self.__evtManager.removeResponder(self.animationTick)
        if self.__animatingHide:
            self.__animatingHide = False
            self.__window.hide()
            self.__is_visible = False
        elif self.__animatingShow:
            self.__animatingShow = False