コード例 #1
0
ファイル: ScrolledWindow.py プロジェクト: illume/eyestabs
    def __init__ (self, width, height):
        Bin.__init__ (self)
        self._scrolling = SCROLL_AUTO

        # Scrollbars.
        self._vscroll = VScrollBar (height, height)
        self._vscroll.connect_signal (SIG_VALCHANGED, self._scroll_child)
        self._vscroll.parent = self
        self._hscroll = HScrollBar (width, width)
        self._hscroll.connect_signal (SIG_VALCHANGED, self._scroll_child)
        self._hscroll.parent = self

        self._vscroll_visible = False
        self._hscroll_visible = False

        # Scrolling will be handled directly by the ScrolledWindow.
        self._hscroll.set_focus = lambda self: False
        self._vscroll.set_focus = lambda self: False

        self.controls.append (self._vscroll)
        self.controls.append (self._hscroll)

        self._signals[SIG_KEYDOWN] = None # Dummy
        self._signals[SIG_MOUSEDOWN] = []

        # Respect the size.
        if width < self._hscroll.minsize[0]:
            width = self._hscroll.minsize[0]
        if height < self._vscroll.minsize[1]:
            height = self._vscroll.minsize[1]
        self.minsize = width, height
コード例 #2
0
    def __init__ (self, width, height):
        Bin.__init__ (self)
        self._scrolling = SCROLL_AUTO

        # ScrollBars.
        self._vscroll = VScrollBar (height, height)
        self._vscroll.connect_signal (SIG_VALCHANGE, self.set_dirty, True)
        self._vscroll.parent = self
        self._hscroll = HScrollBar (width, width)
        self._hscroll.connect_signal (SIG_VALCHANGE, self.set_dirty, True)
        self._hscroll.parent = self

        self._hscroll_visible = False
        self._vscroll_visible = False

        # Remove the keyboard events from the scrollbars. We use our own.
        del self._vscroll._signals[SIG_KEYDOWN]
        del self._hscroll._signals[SIG_KEYDOWN]
        
        self.controls.append (self._vscroll)
        self.controls.append (self._hscroll)

        # Respect the scrollbar sizes.
        if width < self._hscroll.size[0]:
            width = self._hscroll.size[0]
        if height < self._vscroll.size[1]:
            height = self._vscroll.size[1]
        self.size = (width, height)

        self._signals[SIG_KEYDOWN] = None # Dummy
        self._signals[SIG_MOUSEDOWN] = []
コード例 #3
0
ファイル: ScrolledWindow.py プロジェクト: illume/eyestabs
class ScrolledWindow (Bin):
    """ScrolledWindow (width, height) -> ScrolledWindow

    A widget class, which supports horizontal and vertical scrolling.

    The ScrolledWindow is a viewport, which enables its child to be
    scrolled horizontally and vertically. It offers various scrolling
    types, which customize the bahviour of the supplied scrollbars.

    The scrolling behaviour of the ScrolledWindow can be adjusted
    through the 'scrolling' attribute or set_scrolling() method and can
    be one of the SCROLL_TYPES constants.

    Default action (invoked by activate()):
    Gives the ScrolledWindow the input focus.
    
    Mnemonic action (invoked by activate_mnemonic()):
    None

    Signals:
    SIG_KEYDOWN   - Invoked, when a key is pressed while the ScrolledWindow
                    has the input focus.
    SIG_MOUSEDOWN - Invoked, when a mouse button is pressed over the
                    ScrolledWindow.
    
    Attributes:
    scrolling  - The scrolling behaviour of the ScrolledWindow.
    vscrollbar - The vertical scrollbar of the ScrolledWindow.
    hscrollbar - The horizontal scrollbar of the ScrolledWindow.
    """
    def __init__ (self, width, height):
        Bin.__init__ (self)
        self._scrolling = SCROLL_AUTO

        # Scrollbars.
        self._vscroll = VScrollBar (height, height)
        self._vscroll.connect_signal (SIG_VALCHANGED, self._scroll_child)
        self._vscroll.parent = self
        self._hscroll = HScrollBar (width, width)
        self._hscroll.connect_signal (SIG_VALCHANGED, self._scroll_child)
        self._hscroll.parent = self

        self._vscroll_visible = False
        self._hscroll_visible = False

        # Scrolling will be handled directly by the ScrolledWindow.
        self._hscroll.set_focus = lambda self: False
        self._vscroll.set_focus = lambda self: False

        self.controls.append (self._vscroll)
        self.controls.append (self._hscroll)

        self._signals[SIG_KEYDOWN] = None # Dummy
        self._signals[SIG_MOUSEDOWN] = []

        # Respect the size.
        if width < self._hscroll.minsize[0]:
            width = self._hscroll.minsize[0]
        if height < self._vscroll.minsize[1]:
            height = self._vscroll.minsize[1]
        self.minsize = width, height

    def set_scrolling (self, scrolling):
        """S.set_scrolling (...) -> None

        Sets the scrolling behaviour for the ScrolledWindow.

        The scrolling can be a value of the SCROLL_TYPES list.
        SCROLL_AUTO causes the ScrolledList to display its scrollbars on
        demand only, SCROLL_ALWAYS will show the scrollbars permanently
        and SCROLL_NEVER will disable the scrollbars.

        Raises a ValueError, if the passed argument is not a value of
        the SCROLL_TYPES tuple.
        """
        if scrolling not in SCROLL_TYPES:
            raise ValueError ("scrolling must be a value from SCROLL_TYPES")
        if self._scrolling != scrolling:
            self._scrolling = scrolling
            self.dirty = True

    def set_child (self, child=None):
        """B.set_child (...) -> None

        Sets the child to display in the ScrolledList.

        Creates a parent-child relationship from the ScrolledList to a
        widget. If the widget does not support native scrolling, it will
        be packed into a ViewPort.
        """
        self.lock ()
        if child and not isinstance (child, ViewPort):
            self.vscrollbar.value = 0
            self.hscrollbar.value = 0
            child = ViewPort (child)
            child.minsize = self.minsize
        Bin.set_child (self, child)
        self.unlock ()
        
    def activate (self):
        """S.activate () -> None

        Activates the ScrolledWindow default action.

        Activates the ScrolledWindow default action. This usually means
        giving the ScrolledWindow the input focus.
        """
        if not self.sensitive:
            return
        self.focus = True
    
    def notify (self, event):
        """S.notify (...) -> None

        Notifies the ScrolledWindow about an event.
        """
        if not self.sensitive:
            return
        
        if event.signal in SIGNALS_MOUSE:
            eventarea = self.rect_to_client ()
            if event.signal == SIG_MOUSEDOWN:
                if eventarea.collidepoint (event.data.pos):
                    self.focus = True
                    self.run_signal_handlers (SIG_MOUSEDOWN, event.data)

                    # Mouse wheel.
                    for c in self.controls:
                        c.notify (event)
                    if not event.handled:
                        if self._vscroll_visible:
                            if event.data.button == 4:
                                self.vscrollbar.decrease ()
                            elif event.data.button == 5:
                                self.vscrollbar.increase ()
                        elif self._hscroll_visible:
                            if event.data.button == 4:
                                self.hscrollbar.decrease ()
                            elif event.data.button == 5:
                                self.hscrollbar.increase ()
                    event.handled = True
        
        elif (event.signal == SIG_KEYDOWN) and self.focus:
            if self._hscroll_visible:
                # Horizontal scrollbar key movement
                if event.data.key == K_RIGHT:
                    self.hscrollbar.increase ()
                    event.handled = True
                elif event.data.key == K_LEFT:
                    self.hscrollbar.decrease ()
                    event.handled = True
                elif event.data.key == K_END:
                    self.hscrollbar.value = self.hscrollbar.maximum
                    event.handled = True
                elif event.data.key == K_HOME:
                    self.hscrollbar.value = self.hscrollbar.minimum
                    event.handled = True
            if self._vscroll_visible:
                # Vertical scrollbar key movement
                if event.data.key == K_DOWN:
                    self.vscrollbar.increase ()
                    event.handled = True
                elif event.data.key == K_UP:
                    self.vscrollbar.decrease ()
                    event.handled = True
                elif event.data.key == K_PAGEUP:
                    val = self.vscrollbar.value - 10 * self.vscrollbar.step
                    if val > self.vscrollbar.minimum:
                        self.vscrollbar.value = val
                    else:
                        self.vscrollbar.value = self.vscrollbar.minimum
                    event.handled = True
                elif event.data.key == K_PAGEDOWN:
                    val = self.vscrollbar.value + 10 * self.vscrollbar.step
                    if val < self.vscrollbar.maximum:
                        self.vscrollbar.value = val
                    else:
                        self.vscrollbar.value = self.vscrollbar.maximum
                    event.handled = True
                elif event.data.key == K_END:
                    self.vscrollbar.value = self.vscrollbar.maximum
                    event.handled = True
                elif event.data.key == K_HOME:
                    self.vscrollbar.value = self.vscrollbar.minimum
                    event.handled = True

        Bin.notify (self, event)

    def _scroll_child (self):
        """S._scroll_child () -> None

        Scrolls the child of the ScrolledWindow.
        """
        if self.child != None:
            self.child.lock ()
            self.child.hadjustment = - int (self.hscrollbar.value)
            self.child.vadjustment = - int (self.vscrollbar.value)
            self.child.unlock ()
    
    def _update_scrollbars (self):
        """S._update_scrollbars (...) -> bool, bool

        Updates the size and maximum values of the attached scrollbars.

        Updates the size and values of the attached scrollbars and
        returns boolean values about their visibility in the order
        hscrollbar, vscrollbar.
        """
        old_vals = self._vscroll_visible, self._hscroll_visible

        if self.scrolling == SCROLL_NEVER:
            if self.child:
                self.child.minsize = self.minsize
            self.hscrollbar.sensitive = False
            self.vscrollbar.sensitive = False
            self._vscroll_visible = False
            self._hscroll_visible = False
            return False, False

        self.hscrollbar.bottom = self.bottom - self.top
        self.vscrollbar.right = self.right - self.left
        
        width = 0
        height = 0

        if self.child:
            width = self.child.real_width + 2 * self.padding
            height = self.child.real_height + 2 * self.padding

        # We are using the draw_border() method for the inner surface,
        # so we have to add the borders to the scrolling maximum.
        if self.scrolling == SCROLL_ALWAYS:
            self.vscrollbar.minsize = (self.vscrollbar.minsize[0],
                                       self.minsize[1] - \
                                       self.hscrollbar.height)
            self.hscrollbar.minsize = (self.minsize[0] - self.vscrollbar.width,
                                       self.hscrollbar.minsize[1])
            if self.child:
                self.child.maxsize = \
                                (self.minsize[0] - self.vscrollbar.size[0],
                                 self.minsize[1] - self.hscrollbar.size[1])
                self.child.minsize = self.child.maxsize
            if width < self.hscrollbar.minsize[0]:
                width = self.hscrollbar.minsize[0]
            self.hscrollbar.maximum = width
            if height < self.vscrollbar.minsize[1]:
                height = self.vscrollbar.minsize[1]
            self.vscrollbar.maximum = height
            self._vscroll_visible = True
            self._hscroll_visible = True
            self.vscrollbar.sensitive = True
            self.hscrollbar.sensitive = True

        elif self.scrolling == SCROLL_AUTO:
            # Check the sizes, so we can determine, how the scrollbars
            # need to be adjusted.
            self._hscroll_visible = self.minsize[0] < width
            self._vscroll_visible = self.minsize[1] < height

            if self._hscroll_visible:
                self._vscroll_visible = (self.minsize[1] -
                                         self.hscrollbar.height) < height
            if self._vscroll_visible:
                self._hscroll_visible = (self.minsize[0] -
                                         self.vscrollbar.width) < width
            
            if self._vscroll_visible and self._hscroll_visible:
                # Both scrollbars need to be shown.
                self.vscrollbar.minsize = (self.vscrollbar.minsize[0],
                                           self.minsize[1] - \
                                           self.hscrollbar.height)
                self.hscrollbar.minsize = (self.minsize[0] - \
                                           self.vscrollbar.width,
                                           self.hscrollbar.minsize[1])
                if self.child:
                    self.child.maxsize = \
                                (self.minsize[0] - self.vscrollbar.size[0],
                                 self.minsize[1] - self.hscrollbar.size[1])
                    self.child.minsize = self.child.maxsize
                self.vscrollbar.maximum = height
                self.hscrollbar.maximum = width
                self.vscrollbar.sensitive = True
                self.hscrollbar.sensitive = True

            elif self._vscroll_visible:
                # Only the vertical.
                self.vscrollbar.minsize = (self.vscrollbar.minsize[0],
                                           self.minsize[1])
                if self.child:
                    self.child.maxsize = \
                                (self.minsize[0] - self.vscrollbar.minsize[0],
                                 self.minsize[1])
                    self.child.minsize = self.child.maxsize
                self.vscrollbar.maximum = height
                self.vscrollbar.sensitive = True
                self.hscrollbar.sensitive = False

            elif self._hscroll_visible:
                # Only the horizontal.
                self.hscrollbar.minsize = (self.minsize[0],
                                           self.hscrollbar.minsize[1])
                if self.child:
                    self.child.maxsize = \
                                (self.minsize[0],
                                 self.minsize[1] - self.hscrollbar.size[1])
                    self.child.minsize = self.child.maxsize
                self.hscrollbar.maximum = width
                self.hscrollbar.sensitive = True
                self.vscrollbar.sensitive = False

            else:
                if self.child:
                    self.child.minsize = self.minsize
                # Neither vertical nor horizontal
                self.hscrollbar.sensitive = False
                self.vscrollbar.sensitive = False

        if not self.sensitive:
            self.hscrollbar.sensitive = False
            self.vscrollbar.sensitive = False

        return self._hscroll_visible, self._vscroll_visible
        
    def draw_bg (self):
        """S.draw_bg () -> Surface

        Draws the ScrolledWindow background surface and returns it.

        Creates the visible background surface of the ScrolledWindow and
        returns it to the caller.
        """
        return base.GlobalStyle.engine.draw_scrolledwindow (self)

    def draw (self):
        """W.draw () -> None

        Draws the ScrolledWindow surface.

        Creates the visible surface of the ScrolledWindow.
        """
        Bin.draw (self)
        blit = self.image.blit

        # Update the srollbars.
        self.hscrollbar.lock ()
        self.vscrollbar.lock ()
        hscroll, vscroll = self._update_scrollbars ()
        self.hscrollbar.unlock ()
        self.vscrollbar.unlock ()

        if hscroll:
            blit (self.hscrollbar.image, self.hscrollbar.rect)

        if vscroll:
            blit (self.vscrollbar.image, self.vscrollbar.rect)

        if self.child:
            blit (self.child.image, self.child.rect)

    scrolling = property (lambda self: self._scrolling,
                          lambda self, var: self.set_scrolling (var),
                          doc = "The scrolling behaviour for the " \
                          "ScrolledWindow.")
    vscrollbar = property (lambda self: self._vscroll,
                           doc = "The vertical scrollbar.")
    hscrollbar = property (lambda self: self._hscroll,
                           doc = "The herizontal scrollbar.")
コード例 #4
0
class ScrolledWindow (Bin):
    """ScrolledWindow (width, height) -> ScrolledWindow

    Creates a new window, which supports horizontal and vertical scrolling.

    The ScrolledWindow is a viewport, which enables its child to be
    scrolled horizontally and vertically. It offers various scrolling
    types, which customize the bahviour of the supplied scrollbars.

    The scrolling behaviour of the ScrolledWindow can be adjusted
    through the 'scrolling' attribute or set_scrolling() method and can
    be one of the SCROLL_TYPES constants.

    Default action (invoked by activate()):
    Gives the ScrolledWindow the input focus.
    
    Mnemonic action (invoked by activate_mnemonic()):
    None

    Signals:
    SIG_KEYDOWN   - Invoked, when a key is pressed while the ScrolledWindow
                    has the input focus.
    SIG_MOUSEDOWN - Invoked, when a mouse button is pressed over the
                    ScrolledWindow.
    
    Attributes:
    scrolling  - The scrolling behaviour of the ScrolledWindow.
    vscrollbar - The vertical scrollbar of the ScrolledWindow.
    hscrollbar - The horizontal scrollbar of the ScrolledWindow.
    """
    def __init__ (self, width, height):
        Bin.__init__ (self)
        self._scrolling = SCROLL_AUTO

        # ScrollBars.
        self._vscroll = VScrollBar (height, height)
        self._vscroll.connect_signal (SIG_VALCHANGE, self.set_dirty, True)
        self._vscroll.parent = self
        self._hscroll = HScrollBar (width, width)
        self._hscroll.connect_signal (SIG_VALCHANGE, self.set_dirty, True)
        self._hscroll.parent = self

        self._hscroll_visible = False
        self._vscroll_visible = False

        # Remove the keyboard events from the scrollbars. We use our own.
        del self._vscroll._signals[SIG_KEYDOWN]
        del self._hscroll._signals[SIG_KEYDOWN]
        
        self.controls.append (self._vscroll)
        self.controls.append (self._hscroll)

        # Respect the scrollbar sizes.
        if width < self._hscroll.size[0]:
            width = self._hscroll.size[0]
        if height < self._vscroll.size[1]:
            height = self._vscroll.size[1]
        self.size = (width, height)

        self._signals[SIG_KEYDOWN] = None # Dummy
        self._signals[SIG_MOUSEDOWN] = []
    
    def set_state (self, state):
        """S.set_state (...) -> None

        Sets the state of the ScrolledWindow.

        Sets the state of the ScrolledWindow. The state of the
        ScrolledWindow is mainly used for the visible or non-visible
        appearance of the ScrolledWindow, so that the user can
        determine the state of the ScrolledWindow easier.
        Usually this method should not be invoked by user code.
        """
        Bin.set_state (self, state)
        if state in (STATE_NORMAL, STATE_INSENSITIVE):
            self.vscrollbar.set_state (state)
            self.hscrollbar.set_state (state)
    
    def set_scrolling (self, scrolling):
        """S.set_scrolling (...) -> None

        Sets the scrolling behaviour for the ScrolledWindow.

        The scrolling can be a value of the SCROLL_TYPES list.
        SCROLL_AUTO causes the ScrolledList to display its scrollbars on
        demand only, SCROLL_ALWAYS will show the scrollbars permanently
        and SCROLL_NEVER will disable the scrollbars.

        Raises a ValueError, if the passed argument is not a value of
        the SCROLL_TYPES tuple.
        """
        if scrolling not in SCROLL_TYPES:
            raise ValueError ("scrolling must be a value from SCROLL_TYPES")
        if self._scrolling != scrolling:
            self.dirty = True
        self._scrolling = scrolling

    def activate (self):
        """S.activate () -> None

        Activates the ScrolledWindow default action.

        Activates the ScrolledWindow default action. This usually means
        giving the ScrolledWindow the input focus.
        """
        if base.debug: print "ScrolledWindow.activate()"
        if not self.sensitive:
            return
        self.focus = True

    def get_scroll_pos (self):
        """S.get_scroll_pos () -> int, int

        Gets the current topleft scrolling position.
        """
        return self.hscrollbar.value, self.vscrollbar.value
    
    def get_scrollable_area (self):
        """S.get_scrollable_area () -> int, int

        Gets the dimensions of the scrollable area.

        The scrollable area is the complete width and height, which are
        _scrollable_. This means the maximum values both scrollbars of
        the ScrolledWindow have.

        This method is especially useful for the scroll_to_pos() method,
        to avoid ValueError exceptions.
        """
        return self.hscrollbar.maximum, self.vscrollbar.maximum
    
    def scroll_to_pos (self, x, y):
        """S.scroll_to_pos (...) -> None

        Causes the ScrolledWindow to scroll to the given position.

        The arguments x and y are a topleft position to scroll to.
        """
        if self._hscroll_visible:
            self.hscrollbar.value = x
        if self._vscroll_visible:
            self.vscrollbar.value = y

    def get_visible_area (self):
        """S.get_visible_area () -> int, int

        Gets the width and height of the inner area of the ScrolledWindow.

        Get the real width and height of the inner area, on which the
        child will be drawn. By default this method respects the
        'shadow' style attribute.
        """
        border = base.GlobalStyle.get_border_size (self.__class__, self.style,
                                                   BORDER_SUNKEN)
        
        width = self.size[0] - 2 * border
        height = self.size[1] - 2 * border
        if self.scrolling != SCROLL_NEVER:
            if self._vscroll_visible:
                width -= self.vscrollbar.width
            if self._hscroll_visible:
                height -= self.hscrollbar.height
        return width, height
    
    def notify (self, event):
        """S.notify (...) -> None

        Notifies the ScrolledWindow about an event.
        """
        if not self.eventarea or not self.sensitive:
            return

        if event.signal == SIG_MOUSEDOWN:
            if self.eventarea.collidepoint (event.data.pos):
                if base.debug: print "ScrolledWindow.MOUSEDOWN"
                self.focus = True
                self.run_signal_handlers (SIG_MOUSEDOWN)
                # Mouse wheel.
                if self._hscroll_visible and \
                   (self.hscrollbar.eventarea.collidepoint (event.data.pos)):
                    # Do not scroll vertical, if the mouse cursor is
                    # over the horizontal scrollbar.
                    pass
                elif self._vscroll_visible:
                    if event.data.button == 4:
                        self.vscrollbar.decrease ()
                    elif event.data.button == 5:
                        self.vscrollbar.increase ()
        
        elif (event.signal == SIG_KEYDOWN) and self.focus:
            if self._hscroll_visible:
                # Horizontal scrollbar key movement
                if event.data.key == pygame.locals.K_RIGHT:
                    self.hscrollbar.increase ()

                elif event.data.key == pygame.locals.K_LEFT:
                    self.hscrollbar.decrease ()

                elif event.data.key == pygame.locals.K_END:
                    self.hscrollbar.value = self.hscrollbar.maximum

                elif event.data.key == pygame.locals.K_HOME:
                    self.hscrollbar.value = self.hscrollbar.minimum

            if self._vscroll_visible:
                # Vertical scrollbar key movement
                if event.data.key == pygame.locals.K_DOWN:
                    self.vscrollbar.increase ()

                elif event.data.key == pygame.locals.K_UP:
                    self.vscrollbar.decrease ()

                elif event.data.key == pygame.locals.K_PAGEUP:
                    val = self.vscrollbar.value - 10 * self.vscrollbar.step
                    if val > self.vscrollbar.minimum:
                        self.vscrollbar.value = val
                    else:
                        self.vscrollbar.value = self.vscrollbar.minimum

                elif event.data.key == pygame.locals.K_PAGEDOWN:
                    val = self.vscrollbar.value + 10 * self.vscrollbar.step
                    if val < self.vscrollbar.maximum:
                        self.vscrollbar.value = val
                    else:
                        self.vscrollbar.value = self.vscrollbar.maximum

                elif event.data.key == pygame.locals.K_END:
                    self.vscrollbar.value = self.vscrollbar.maximum

                elif event.data.key == pygame.locals.K_HOME:
                    self.vscrollbar.value = self.vscrollbar.minimum

        Bin.notify (self, event)
    
    def update_scrollbars (self, border):
        """S.update_scrollbars (...) -> bool, bool

        Updates the size and maximum values of the attached scrollbars.

        Updates the size and values of the attached scrollbars and
        returns boolean values about their visibility in the order
        vscrollbar, hscrollbar.
        """
        old_vals = self._vscroll_visible, self._hscroll_visible

        if self.scrolling == SCROLL_NEVER:
            self.hscrollbar.sensitive = False
            self.vscrollbar.sensitive = False
            self._vscroll_visible = False
            self._hscroll_visible = False
            return False, False

        self.vscrollbar.update ()
        self.hscrollbar.update ()
        
        width = 0
        height = 0
        if self.child:
            width = self.child.width + 2 * self.padding + border
            height = self.child.height + 2 * self.padding + border
        
        # We are using the draw_border() method for the inner surface,
        # so we have to add the borders to the scrolling maximum.
        if self.scrolling == SCROLL_ALWAYS:
            self.vscrollbar.size = (self.vscrollbar.size[0],
                                    self.size[1] - self.hscrollbar.height)
            self.hscrollbar.size = (self.size[0] - self.vscrollbar.width,
                                    self.hscrollbar.size[1])

            if width < self.hscrollbar.size[0]:
                width = self.hscrollbar.size[0]
            else:
                width += border
            self.hscrollbar.maximum = width
            if height < self.vscrollbar.size[1]:
                height = self.vscrollbar.size[1]
            else:
                 height += border
            self.vscrollbar.maximum = height
            self._vscroll_visible = True
            self._hscroll_visible = True
        elif self.scrolling == SCROLL_AUTO:
            # Check the sizes, so we can determine, how the scrollbars
            # need to be adjusted.
            self._hscroll_visible = (self.size[0] - border) < width
            self._vscroll_visible = (self.size[1] - border) < height
            if self._hscroll_visible:
                self._vscroll_visible = (self.size[1] - border -
                                         self.hscrollbar.height) < height
            if self._vscroll_visible:
                self._hscroll_visible = (self.size[0] - border -
                                         self.vscrollbar.width) < width
            
            if self._vscroll_visible and self._hscroll_visible:
                # Both scrollbars need to be shown.
                self.vscrollbar.size = (self.vscrollbar.size[0], self.size[1] -
                                        self.hscrollbar.height)
                self.hscrollbar.size = (self.size[0] - self.vscrollbar.width,
                                        self.hscrollbar.size[1])
                self.vscrollbar.maximum = height + border
                self.hscrollbar.maximum = width + border
                self.vscrollbar.sensitive = True
                self.hscrollbar.sensitive = True
            elif self._vscroll_visible:
                # Only the vertical.
                self.vscrollbar.size = (self.vscrollbar.size[0], self.size[1])
                self.vscrollbar.maximum = height + border
                self.vscrollbar.sensitive = True
                self.hscrollbar.sensitive = False
            elif self._hscroll_visible:
                # Only the horizontal.
                self.hscrollbar.size = (self.size[0], self.hscrollbar.size[1])
                self.hscrollbar.maximum = width + border
                self.hscrollbar.sensitive = True
                self.vscrollbar.sensitive = False
            else:
                # Neither vertical nor horizontal
                self.hscrollbar.sensitive = False
                self.vscrollbar.sensitive = False

        # This is an evil hack[tm] to workaround that lousy dynamic
        # scrollbar behaviour.
        if (old_vals[0] != self._vscroll_visible) or \
           (old_vals[1] != self._hscroll_visible):
            if self.child:
                self.child.dirty = True
                self.child.update ()
            return self.update_scrollbars (border)
        
        return self._vscroll_visible, self._hscroll_visible
    
    def recalculate_child_rect (self):
        """S.recalculate_child_rect () -> None

        Calculates the eventarea size of the child.
        """
        border = base.GlobalStyle.get_border_size (self.__class__, self.style,
                                                   BORDER_SUNKEN)

        if not self.child:
            return
        # Recalculate the visible size of the child rect.
        width, height = self.get_visible_area ()
        re = pygame.Rect (self.position[0] + border, self.position[1] + border,
                          width, height).clip (self.child.rect)
        self.child.eventarea = re

    def draw (self):
        """S.draw () -> Surface

        Draws the ScrolledWindow surface and returns it.

        Creates the visible surface of the ScrolledWindow and returns it
        to the caller.
        """
        return base.GlobalStyle.draw_scrolledwindow (self)
    
    scrolling = property (lambda self: self._scrolling,
                          lambda self, var: self.set_scrolling (var),
                          doc = """The scrolling behaviour for the 
                          ScrolledWindow.""")
    vscrollbar = property (lambda self: self._vscroll,
                           doc = "The vertical scrollbar.")
    hscrollbar = property (lambda self: self._hscroll,
                           doc = "The herizontal scrollbar.")