• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2007 Staikos Computing Services Inc. <info@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 "Scrollbar.h"
35 #include "ScrollView.h"
36 
37 #include <QApplication>
38 #include <QDebug>
39 #include <QPainter>
40 #include <QStyle>
41 #include <QStyleOptionSlider>
42 #include <QMenu>
43 
44 namespace WebCore {
45 
nativeTheme()46 ScrollbarTheme* ScrollbarTheme::nativeTheme()
47 {
48     static ScrollbarThemeQt theme;
49     return &theme;
50 }
51 
~ScrollbarThemeQt()52 ScrollbarThemeQt::~ScrollbarThemeQt()
53 {
54 }
55 
scPart(const ScrollbarPart & part)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 
scrollbarPart(const QStyle::SubControl & sc)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 
styleOptionSlider(Scrollbar * scrollbar,QWidget * widget=0)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     if (scrollbar->orientation() == HorizontalScrollbar)
114         opt.state |= QStyle::State_Horizontal;
115     opt.sliderValue = scrollbar->value();
116     opt.sliderPosition = opt.sliderValue;
117     opt.pageStep = scrollbar->visibleSize();
118     opt.singleStep = scrollbar->lineStep();
119     opt.minimum = 0;
120     opt.maximum = qMax(0, scrollbar->maximum());
121     ScrollbarPart pressedPart = scrollbar->pressedPart();
122     ScrollbarPart hoveredPart = scrollbar->hoveredPart();
123     if (pressedPart != NoPart) {
124         opt.activeSubControls = scPart(scrollbar->pressedPart());
125         if (pressedPart == BackButtonStartPart || pressedPart == ForwardButtonStartPart ||
126             pressedPart == BackButtonEndPart || pressedPart == ForwardButtonEndPart ||
127             pressedPart == ThumbPart)
128             opt.state |= QStyle::State_Sunken;
129     } else
130         opt.activeSubControls = scPart(hoveredPart);
131     if (hoveredPart != NoPart)
132         opt.state |= QStyle::State_MouseOver;
133     return &opt;
134 }
135 
paint(Scrollbar * scrollbar,GraphicsContext * graphicsContext,const IntRect & damageRect)136 bool ScrollbarThemeQt::paint(Scrollbar* scrollbar, GraphicsContext* graphicsContext, const IntRect& damageRect)
137 {
138     if (graphicsContext->updatingControlTints()) {
139        scrollbar->invalidateRect(damageRect);
140        return false;
141     }
142 
143     StylePainter p(graphicsContext);
144     if (!p.isValid())
145       return true;
146 
147     p.painter->save();
148     QStyleOptionSlider* opt = styleOptionSlider(scrollbar, p.widget);
149 
150     p.painter->setClipRect(opt->rect.intersected(damageRect));
151 
152 #ifdef Q_WS_MAC
153     p.drawComplexControl(QStyle::CC_ScrollBar, *opt);
154 #else
155     const QPoint topLeft = opt->rect.topLeft();
156     p.painter->translate(topLeft);
157     opt->rect.moveTo(QPoint(0, 0));
158 
159     // The QStyle expects the background to be already filled
160     p.painter->fillRect(opt->rect, opt->palette.background());
161 
162     p.drawComplexControl(QStyle::CC_ScrollBar, *opt);
163     opt->rect.moveTo(topLeft);
164 #endif
165     p.painter->restore();
166 
167     return true;
168 }
169 
hitTest(Scrollbar * scrollbar,const PlatformMouseEvent & evt)170 ScrollbarPart ScrollbarThemeQt::hitTest(Scrollbar* scrollbar, const PlatformMouseEvent& evt)
171 {
172     QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
173     const QPoint pos = scrollbar->convertFromContainingWindow(evt.pos());
174     opt->rect.moveTo(QPoint(0, 0));
175     QStyle::SubControl sc = QApplication::style()->hitTestComplexControl(QStyle::CC_ScrollBar, opt, pos, 0);
176     return scrollbarPart(sc);
177 }
178 
shouldCenterOnThumb(Scrollbar *,const PlatformMouseEvent & evt)179 bool ScrollbarThemeQt::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
180 {
181     // Middle click centers slider thumb (if supported)
182     return QApplication::style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition) && evt.button() == MiddleButton;
183 }
184 
invalidatePart(Scrollbar * scrollbar,ScrollbarPart)185 void ScrollbarThemeQt::invalidatePart(Scrollbar* scrollbar, ScrollbarPart)
186 {
187     // FIXME: Do more precise invalidation.
188     scrollbar->invalidate();
189 }
190 
scrollbarThickness(ScrollbarControlSize controlSize)191 int ScrollbarThemeQt::scrollbarThickness(ScrollbarControlSize controlSize)
192 {
193     QStyle* s = QApplication::style();
194     QStyleOptionSlider o;
195     o.orientation = Qt::Vertical;
196     o.state &= ~QStyle::State_Horizontal;
197     if (controlSize != RegularScrollbar)
198         o.state |= QStyle::State_Mini;
199     return s->pixelMetric(QStyle::PM_ScrollBarExtent, &o, 0);
200 }
201 
thumbPosition(Scrollbar * scrollbar)202 int ScrollbarThemeQt::thumbPosition(Scrollbar* scrollbar)
203 {
204     if (scrollbar->enabled())
205         return (int)((float)scrollbar->currentPos() * (trackLength(scrollbar) - thumbLength(scrollbar)) / scrollbar->maximum());
206     return 0;
207 }
208 
thumbLength(Scrollbar * scrollbar)209 int ScrollbarThemeQt::thumbLength(Scrollbar* scrollbar)
210 {
211     QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
212     IntRect thumb = QApplication::style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarSlider, 0);
213     return scrollbar->orientation() == HorizontalScrollbar ? thumb.width() : thumb.height();
214 }
215 
trackPosition(Scrollbar * scrollbar)216 int ScrollbarThemeQt::trackPosition(Scrollbar* scrollbar)
217 {
218     QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
219     IntRect track = QApplication::style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0);
220     return scrollbar->orientation() == HorizontalScrollbar ? track.x() - scrollbar->x() : track.y() - scrollbar->y();
221 }
222 
trackLength(Scrollbar * scrollbar)223 int ScrollbarThemeQt::trackLength(Scrollbar* scrollbar)
224 {
225     QStyleOptionSlider* opt = styleOptionSlider(scrollbar);
226     IntRect track = QApplication::style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0);
227     return scrollbar->orientation() == HorizontalScrollbar ? track.width() : track.height();
228 }
229 
paintScrollCorner(ScrollView * scrollView,GraphicsContext * context,const IntRect & rect)230 void ScrollbarThemeQt::paintScrollCorner(ScrollView* scrollView, GraphicsContext* context, const IntRect& rect)
231 {
232     if (context->updatingControlTints()) {
233        scrollView->invalidateRect(rect);
234        return;
235     }
236 
237 #if QT_VERSION < 0x040500
238     context->fillRect(rect, QApplication::palette().color(QPalette::Normal, QPalette::Window));
239 #else
240     StylePainter p(context);
241     if (!p.isValid())
242         return;
243 
244     QStyleOption option;
245     option.rect = rect;
246     p.drawPrimitive(QStyle::PE_PanelScrollAreaCorner, option);
247 #endif
248 }
249 
250 }
251 
252