Home | History | Annotate | Download | only in qt
      1 /*
      2  * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved.
      3  * Copyright (C) 2007 Staikos Computing Services Inc. <info (at) staikos.net>
      4  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "config.h"
     29 #include "ScrollbarThemeQt.h"
     30 
     31 #include "GraphicsContext.h"
     32 #include "PlatformMouseEvent.h"
     33 #include "RenderThemeQt.h"
     34 #include "ScrollView.h"
     35 #include "Scrollbar.h"
     36 
     37 #include <QApplication>
     38 #include <QDebug>
     39 #include <QMenu>
     40 #include <QPainter>
     41 #include <QStyle>
     42 #include <QStyleOptionSlider>
     43 
     44 namespace WebCore {
     45 
     46 ScrollbarTheme* ScrollbarTheme::nativeTheme()
     47 {
     48     static ScrollbarThemeQt theme;
     49     return &theme;
     50 }
     51 
     52 ScrollbarThemeQt::~ScrollbarThemeQt()
     53 {
     54 }
     55 
     56 static QStyle::SubControl scPart(const ScrollbarPart& part)
     57 {
     58     switch (part) {
     59     case NoPart:
     60         return QStyle::SC_None;
     61     case BackButtonStartPart:
     62     case BackButtonEndPart:
     63         return QStyle::SC_ScrollBarSubLine;
     64     case BackTrackPart:
     65         return QStyle::SC_ScrollBarSubPage;
     66     case ThumbPart:
     67         return QStyle::SC_ScrollBarSlider;
     68     case ForwardTrackPart:
     69         return QStyle::SC_ScrollBarAddPage;
     70     case ForwardButtonStartPart:
     71     case ForwardButtonEndPart:
     72         return QStyle::SC_ScrollBarAddLine;
     73     }
     74 
     75     return QStyle::SC_None;
     76 }
     77 
     78 static ScrollbarPart scrollbarPart(const QStyle::SubControl& sc)
     79 {
     80     switch (sc) {
     81     case QStyle::SC_None:
     82         return NoPart;
     83     case QStyle::SC_ScrollBarSubLine:
     84         return BackButtonStartPart;
     85     case QStyle::SC_ScrollBarSubPage:
     86         return BackTrackPart;
     87     case QStyle::SC_ScrollBarSlider:
     88         return ThumbPart;
     89     case QStyle::SC_ScrollBarAddPage:
     90         return ForwardTrackPart;
     91     case QStyle::SC_ScrollBarAddLine:
     92         return ForwardButtonStartPart;
     93     }
     94     return NoPart;
     95 }
     96 
     97 static QStyleOptionSlider* styleOptionSlider(Scrollbar* scrollbar, QWidget* widget = 0)
     98 {
     99     static QStyleOptionSlider opt;
    100     if (widget)
    101         opt.initFrom(widget);
    102     else
    103         opt.state |= QStyle::State_Active;
    104 
    105     opt.state &= ~QStyle::State_HasFocus;
    106 
    107     opt.rect = scrollbar->frameRect();
    108     if (scrollbar->enabled())
    109         opt.state |= QStyle::State_Enabled;
    110     if (scrollbar->controlSize() != RegularScrollbar)
    111         opt.state |= QStyle::State_Mini;
    112     opt.orientation = (scrollbar->orientation() == VerticalScrollbar) ? Qt::Vertical : Qt::Horizontal;
    113 
    114     if (scrollbar->orientation() == HorizontalScrollbar)
    115         opt.state |= QStyle::State_Horizontal;
    116     else
    117         opt.state &= ~QStyle::State_Horizontal;
    118 
    119     opt.sliderValue = scrollbar->value();
    120     opt.sliderPosition = opt.sliderValue;
    121     opt.pageStep = scrollbar->pageStep();
    122     opt.singleStep = scrollbar->lineStep();
    123     opt.minimum = 0;
    124     opt.maximum = qMax(0, scrollbar->maximum());
    125     ScrollbarPart pressedPart = scrollbar->pressedPart();
    126     ScrollbarPart hoveredPart = scrollbar->hoveredPart();
    127     if (pressedPart != NoPart) {
    128         opt.activeSubControls = scPart(scrollbar->pressedPart());
    129         if (pressedPart == BackButtonStartPart || pressedPart == ForwardButtonStartPart
    130             || pressedPart == BackButtonEndPart || pressedPart == ForwardButtonEndPart
    131             || pressedPart == ThumbPart)
    132             opt.state |= QStyle::State_Sunken;
    133     } else
    134         opt.activeSubControls = scPart(hoveredPart);
    135     if (hoveredPart != NoPart)
    136         opt.state |= QStyle::State_MouseOver;
    137     return &opt;
    138 }
    139 
    140 bool ScrollbarThemeQt::paint(Scrollbar* scrollbar, GraphicsContext* graphicsContext, const IntRect& damageRect)
    141 {
    142     if (graphicsContext->updatingControlTints()) {
    143        scrollbar->invalidateRect(damageRect);
    144        return false;
    145     }
    146 
    147     StylePainter p(this, graphicsContext);
    148     if (!p.isValid())
    149       return true;
    150 
    151     p.painter->save();
    152     QStyleOptionSlider* opt = styleOptionSlider(scrollbar, p.widget);
    153 
    154     p.painter->setClipRect(opt->rect.intersected(damageRect), Qt::IntersectClip);
    155 
    156 #ifdef Q_WS_MAC
    157     p.drawComplexControl(QStyle::CC_ScrollBar, *opt);
    158 #else
    159     const QPoint topLeft = opt->rect.topLeft();
    160     p.painter->translate(topLeft);
    161     opt->rect.moveTo(QPoint(0, 0));
    162 
    163     // The QStyle expects the background to be already filled
    164     p.painter->fillRect(opt->rect, opt->palette.background());
    165 
    166     p.drawComplexControl(QStyle::CC_ScrollBar, *opt);
    167     opt->rect.moveTo(topLeft);
    168 #endif
    169     p.painter->restore();
    170 
    171     return true;
    172 }
    173 
    174 ScrollbarPart ScrollbarThemeQt::hitTest(Scrollbar* scrollbar, const PlatformMouseEvent& evt)
    175 {
    176     QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
    177     const QPoint pos = scrollbar->convertFromContainingWindow(evt.pos());
    178     opt->rect.moveTo(QPoint(0, 0));
    179     QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ScrollBar, opt, pos, 0);
    180     return scrollbarPart(sc);
    181 }
    182 
    183 bool ScrollbarThemeQt::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
    184 {
    185     // Middle click centers slider thumb (if supported)
    186     return style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition) && evt.button() == MiddleButton;
    187 }
    188 
    189 void ScrollbarThemeQt::invalidatePart(Scrollbar* scrollbar, ScrollbarPart)
    190 {
    191     // FIXME: Do more precise invalidation.
    192     scrollbar->invalidate();
    193 }
    194 
    195 int ScrollbarThemeQt::scrollbarThickness(ScrollbarControlSize controlSize)
    196 {
    197 #if USE(QT_MOBILE_THEME)
    198     return 0;
    199 #endif
    200     QStyleOptionSlider o;
    201     o.orientation = Qt::Vertical;
    202     o.state &= ~QStyle::State_Horizontal;
    203     if (controlSize != RegularScrollbar)
    204         o.state |= QStyle::State_Mini;
    205     return style()->pixelMetric(QStyle::PM_ScrollBarExtent, &o, 0);
    206 }
    207 
    208 int ScrollbarThemeQt::thumbPosition(Scrollbar* scrollbar)
    209 {
    210     if (scrollbar->enabled())
    211         return (int)((float)scrollbar->currentPos() * (trackLength(scrollbar) - thumbLength(scrollbar)) / scrollbar->maximum());
    212     return 0;
    213 }
    214 
    215 int ScrollbarThemeQt::thumbLength(Scrollbar* scrollbar)
    216 {
    217     QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
    218     IntRect thumb = style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarSlider, 0);
    219     return scrollbar->orientation() == HorizontalScrollbar ? thumb.width() : thumb.height();
    220 }
    221 
    222 int ScrollbarThemeQt::trackPosition(Scrollbar* scrollbar)
    223 {
    224     QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
    225     IntRect track = style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0);
    226     return scrollbar->orientation() == HorizontalScrollbar ? track.x() - scrollbar->x() : track.y() - scrollbar->y();
    227 }
    228 
    229 int ScrollbarThemeQt::trackLength(Scrollbar* scrollbar)
    230 {
    231     QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
    232     IntRect track = style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0);
    233     return scrollbar->orientation() == HorizontalScrollbar ? track.width() : track.height();
    234 }
    235 
    236 void ScrollbarThemeQt::paintScrollCorner(ScrollView* scrollView, GraphicsContext* context, const IntRect& rect)
    237 {
    238     if (context->updatingControlTints()) {
    239        scrollView->invalidateRect(rect);
    240        return;
    241     }
    242 
    243     StylePainter p(this, context);
    244     if (!p.isValid())
    245         return;
    246 
    247     QStyleOption option;
    248     option.rect = rect;
    249     p.drawPrimitive(QStyle::PE_PanelScrollAreaCorner, option);
    250 }
    251 
    252 QStyle* ScrollbarThemeQt::style() const
    253 {
    254     return QApplication::style();
    255 }
    256 
    257 }
    258 
    259