15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderScrollbar.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "core/css/PseudoStyleRequest.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Frame.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/FrameView.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderPart.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderScrollbarPart.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderScrollbarTheme.h"
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Scrollbar> RenderScrollbar::createCustomScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, Node* ownerNode, Frame* owningFrame)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new RenderScrollbar(scrollableArea, orientation, ownerNode, owningFrame));
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderScrollbar::RenderScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, Node* ownerNode, Frame* owningFrame)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : Scrollbar(scrollableArea, orientation, RegularScrollbar, RenderScrollbarTheme::renderScrollbarTheme())
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_owner(ownerNode)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_owningFrame(owningFrame)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(ownerNode || owningFrame);
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: We need to do this because RenderScrollbar::styleChanged is called as soon as the scrollbar is created.
5102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Update the scrollbar size.
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int width = 0;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int height = 0;
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(ScrollbarBGPart);
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (RenderScrollbarPart* part = m_parts.get(ScrollbarBGPart)) {
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        part->layout();
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        width = part->width();
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        height = part->height();
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (this->orientation() == HorizontalScrollbar)
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        width = this->width();
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        height = this->height();
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setFrameRect(IntRect(0, 0, width, height));
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderScrollbar::~RenderScrollbar()
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_parts.isEmpty()) {
7102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        // When a scrollbar is detached from its parent (causing all parts removal) and
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // ready to be destroyed, its destruction can be delayed because of RefPtr
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // maintained in other classes such as EventHandler (m_lastScrollbarUnderMouse).
7402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        // Meanwhile, we can have a call to updateScrollbarPart which recreates the
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // scrollbar part. So, we need to destroy these parts since we don't want them
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // to call on a destroyed scrollbar. See webkit bug 68009.
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateScrollbarParts(true);
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderBox* RenderScrollbar::owningRenderer() const
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_owningFrame) {
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderBox* currentRenderer = m_owningFrame->ownerRenderer();
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return currentRenderer;
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_owner && m_owner->renderer() ? m_owner->renderer()->enclosingBox() : 0;
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderScrollbar::setParent(ScrollView* parent)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Scrollbar::setParent(parent);
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!parent) {
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Destroy all of the scrollbar's RenderBoxes.
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateScrollbarParts(true);
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderScrollbar::setEnabled(bool e)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool wasEnabled = enabled();
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Scrollbar::setEnabled(e);
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (wasEnabled != e)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateScrollbarParts();
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderScrollbar::styleChanged()
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarParts();
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderScrollbar::paint(GraphicsContext* context, const IntRect& damageRect)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (context->updatingControlTints()) {
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateScrollbarParts();
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Scrollbar::paint(context, damageRect);
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderScrollbar::setHoveredPart(ScrollbarPart part)
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (part == m_hoveredPart)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ScrollbarPart oldPart = m_hoveredPart;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_hoveredPart = part;
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(oldPart);
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(m_hoveredPart);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(ScrollbarBGPart);
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(TrackBGPart);
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderScrollbar::setPressedPart(ScrollbarPart part)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ScrollbarPart oldPart = m_pressedPart;
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Scrollbar::setPressedPart(part);
14002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(oldPart);
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(part);
14302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(ScrollbarBGPart);
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(TrackBGPart);
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<RenderStyle> RenderScrollbar::getScrollbarPseudoStyle(ScrollbarPart partType, PseudoId pseudoId)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!owningRenderer())
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    RefPtr<RenderStyle> result = owningRenderer()->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId, this, partType), owningRenderer()->style());
15402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // Scrollbars for root frames should always have background color
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // unless explicitly specified as transparent. So we force it.
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This is because WebKit assumes scrollbar to be always painted and missing background
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // causes visual artifact like non-repainted dirty region.
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result && m_owningFrame && m_owningFrame->view() && !m_owningFrame->view()->isTransparent() && !result->hasBackground())
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result->setBackgroundColor(Color::white);
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderScrollbar::updateScrollbarParts(bool destroy)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(ScrollbarBGPart, destroy);
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(BackButtonStartPart, destroy);
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(ForwardButtonStartPart, destroy);
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(BackTrackPart, destroy);
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(ThumbPart, destroy);
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(ForwardTrackPart, destroy);
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(BackButtonEndPart, destroy);
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(ForwardButtonEndPart, destroy);
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScrollbarPart(TrackBGPart, destroy);
17502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (destroy)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // See if the scrollbar's thickness changed.  If so, we need to mark our owning object as needing a layout.
18002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    bool isHorizontal = orientation() == HorizontalScrollbar;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int oldThickness = isHorizontal ? height() : width();
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int newThickness = 0;
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderScrollbarPart* part = m_parts.get(ScrollbarBGPart);
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (part) {
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        part->layout();
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newThickness = isHorizontal ? part->height() : part->width();
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
18802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (newThickness != oldThickness) {
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setFrameRect(IntRect(location(), IntSize(isHorizontal ? width() : newThickness, isHorizontal ? newThickness : height())));
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (RenderBox* box = owningRenderer())
192d24c94b5090b6aa121f0f82325c9379004dc3196Ben Murdoch            box->setChildNeedsLayout();
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static PseudoId pseudoForScrollbarPart(ScrollbarPart part)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (part) {
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case BackButtonStartPart:
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ForwardButtonStartPart:
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case BackButtonEndPart:
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ForwardButtonEndPart:
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return SCROLLBAR_BUTTON;
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case BackTrackPart:
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ForwardTrackPart:
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return SCROLLBAR_TRACK_PIECE;
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ThumbPart:
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return SCROLLBAR_THUMB;
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case TrackBGPart:
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return SCROLLBAR_TRACK;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case ScrollbarBGPart:
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return SCROLLBAR;
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case NoPart:
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case AllParts:
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return SCROLLBAR;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderScrollbar::updateScrollbarPart(ScrollbarPart partType, bool destroy)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (partType == NoPart)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<RenderStyle> partStyle = !destroy ? getScrollbarPseudoStyle(partType,  pseudoForScrollbarPart(partType)) : PassRefPtr<RenderStyle>(0);
22702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool needRenderer = !destroy && partStyle && partStyle->display() != NONE && partStyle->visibility() == VISIBLE;
22902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (needRenderer && partStyle->display() != BLOCK) {
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // See if we are a button that should not be visible according to OS settings.
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ScrollbarButtonsPlacement buttonsPlacement = theme()->buttonsPlacement();
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        switch (partType) {
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            case BackButtonStartPart:
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                needRenderer = (buttonsPlacement == ScrollbarButtonsSingle || buttonsPlacement == ScrollbarButtonsDoubleStart ||
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                buttonsPlacement == ScrollbarButtonsDoubleBoth);
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            case ForwardButtonStartPart:
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                needRenderer = (buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth);
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            case BackButtonEndPart:
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                needRenderer = (buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth);
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            case ForwardButtonEndPart:
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                needRenderer = (buttonsPlacement == ScrollbarButtonsSingle || buttonsPlacement == ScrollbarButtonsDoubleEnd ||
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                buttonsPlacement == ScrollbarButtonsDoubleBoth);
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            default:
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
25202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderScrollbarPart* partRenderer = m_parts.get(partType);
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!partRenderer && needRenderer) {
255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        partRenderer = RenderScrollbarPart::createAnonymous(owningRenderer()->document(), this, partType);
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_parts.set(partType, partRenderer);
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (partRenderer && !needRenderer) {
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_parts.remove(partType);
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        partRenderer->destroy();
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        partRenderer = 0;
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
26202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (partRenderer)
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        partRenderer->setStyle(partStyle.release());
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderScrollbar::paintPart(GraphicsContext* graphicsContext, ScrollbarPart partType, const IntRect& rect)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderScrollbarPart* partRenderer = m_parts.get(partType);
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!partRenderer)
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    partRenderer->paintIntoRect(graphicsContext, location(), rect);
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntRect RenderScrollbar::buttonRect(ScrollbarPart partType)
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderScrollbarPart* partRenderer = m_parts.get(partType);
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!partRenderer)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return IntRect();
28002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    partRenderer->layout();
28202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isHorizontal = orientation() == HorizontalScrollbar;
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (partType == BackButtonStartPart)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return IntRect(location(), IntSize(isHorizontal ? partRenderer->pixelSnappedWidth() : width(), isHorizontal ? height() : partRenderer->pixelSnappedHeight()));
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (partType == ForwardButtonEndPart)
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return IntRect(isHorizontal ? x() + width() - partRenderer->pixelSnappedWidth() : x(),
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                       isHorizontal ? y() : y() + height() - partRenderer->pixelSnappedHeight(),
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                       isHorizontal ? partRenderer->pixelSnappedWidth() : width(),
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                       isHorizontal ? height() : partRenderer->pixelSnappedHeight());
29102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (partType == ForwardButtonStartPart) {
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        IntRect previousButton = buttonRect(BackButtonStartPart);
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return IntRect(isHorizontal ? x() + previousButton.width() : x(),
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                       isHorizontal ? y() : y() + previousButton.height(),
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                       isHorizontal ? partRenderer->pixelSnappedWidth() : width(),
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                       isHorizontal ? height() : partRenderer->pixelSnappedHeight());
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
29902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect followingButton = buttonRect(ForwardButtonEndPart);
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return IntRect(isHorizontal ? x() + width() - followingButton.width() - partRenderer->pixelSnappedWidth() : x(),
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                   isHorizontal ? y() : y() + height() - followingButton.height() - partRenderer->pixelSnappedHeight(),
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                   isHorizontal ? partRenderer->pixelSnappedWidth() : width(),
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                   isHorizontal ? height() : partRenderer->pixelSnappedHeight());
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntRect RenderScrollbar::trackRect(int startLength, int endLength)
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderScrollbarPart* part = m_parts.get(TrackBGPart);
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (part)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        part->layout();
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (orientation() == HorizontalScrollbar) {
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int marginLeft = part ? static_cast<int>(part->marginLeft()) : 0;
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int marginRight = part ? static_cast<int>(part->marginRight()) : 0;
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        startLength += marginLeft;
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        endLength += marginRight;
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int totalLength = startLength + endLength;
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return IntRect(x() + startLength, y(), width() - totalLength, height());
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
32102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int marginTop = part ? static_cast<int>(part->marginTop()) : 0;
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int marginBottom = part ? static_cast<int>(part->marginBottom()) : 0;
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startLength += marginTop;
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    endLength += marginBottom;
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int totalLength = startLength + endLength;
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return IntRect(x(), y() + startLength, width(), height() - totalLength);
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntRect RenderScrollbar::trackPieceRectWithMargins(ScrollbarPart partType, const IntRect& oldRect)
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderScrollbarPart* partRenderer = m_parts.get(partType);
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!partRenderer)
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return oldRect;
33602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    partRenderer->layout();
33802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect rect = oldRect;
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (orientation() == HorizontalScrollbar) {
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.setX(rect.x() + partRenderer->marginLeft());
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.setWidth(rect.width() - partRenderer->marginWidth());
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.setY(rect.y() + partRenderer->marginTop());
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.setHeight(rect.height() - partRenderer->marginHeight());
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return rect;
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int RenderScrollbar::minimumThumbLength()
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderScrollbarPart* partRenderer = m_parts.get(ThumbPart);
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!partRenderer)
35402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        return 0;
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    partRenderer->layout();
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return orientation() == HorizontalScrollbar ? partRenderer->width() : partRenderer->height();
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
360