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 "ScrollbarThemeQStyle.h" 30 31#include "GraphicsContext.h" 32#include "PlatformMouseEvent.h" 33#include "RenderThemeQStyle.h" 34#include "ScrollView.h" 35#include "Scrollbar.h" 36 37namespace WebCore { 38 39ScrollbarThemeQStyle::ScrollbarThemeQStyle() 40{ 41 m_qStyle = adoptPtr(RenderThemeQStyle::styleFactory()(/*page*/ 0)); 42} 43 44ScrollbarThemeQStyle::~ScrollbarThemeQStyle() 45{ 46} 47 48static QStyleFacade::SubControl scPart(const ScrollbarPart& part) 49{ 50 switch (part) { 51 case NoPart: 52 return QStyleFacade::SC_None; 53 case BackButtonStartPart: 54 case BackButtonEndPart: 55 return QStyleFacade::SC_ScrollBarSubLine; 56 case BackTrackPart: 57 return QStyleFacade::SC_ScrollBarSubPage; 58 case ThumbPart: 59 return QStyleFacade::SC_ScrollBarSlider; 60 case ForwardTrackPart: 61 return QStyleFacade::SC_ScrollBarAddPage; 62 case ForwardButtonStartPart: 63 case ForwardButtonEndPart: 64 return QStyleFacade::SC_ScrollBarAddLine; 65 } 66 67 return QStyleFacade::SC_None; 68} 69 70static ScrollbarPart scrollbarPart(const QStyleFacade::SubControl& sc) 71{ 72 switch (sc) { 73 case QStyleFacade::SC_None: 74 return NoPart; 75 case QStyleFacade::SC_ScrollBarSubLine: 76 return BackButtonStartPart; 77 case QStyleFacade::SC_ScrollBarSubPage: 78 return BackTrackPart; 79 case QStyleFacade::SC_ScrollBarSlider: 80 return ThumbPart; 81 case QStyleFacade::SC_ScrollBarAddPage: 82 return ForwardTrackPart; 83 case QStyleFacade::SC_ScrollBarAddLine: 84 return ForwardButtonStartPart; 85 } 86 return NoPart; 87} 88 89static QStyleFacadeOption initSliderStyleOption(ScrollbarThemeClient* scrollbar, QObject* widget = 0) 90{ 91 QStyleFacadeOption opt; 92 if (widget) { 93 opt.palette = widget->property("palette").value<QPalette>(); 94 opt.rect = widget->property("rect").value<QRect>(); 95 opt.direction = static_cast<Qt::LayoutDirection>(widget->property("layoutDirection").toInt()); 96 } else 97 opt.state |= QStyleFacade::State_Active; 98 99 opt.state &= ~QStyleFacade::State_HasFocus; 100 101 opt.rect = scrollbar->frameRect(); 102 if (scrollbar->enabled()) 103 opt.state |= QStyleFacade::State_Enabled; 104 if (scrollbar->controlSize() != RegularScrollbar) 105 opt.state |= QStyleFacade::State_Mini; 106 opt.slider.orientation = (scrollbar->orientation() == VerticalScrollbar) ? Qt::Vertical : Qt::Horizontal; 107 108 if (scrollbar->orientation() == HorizontalScrollbar) 109 opt.state |= QStyleFacade::State_Horizontal; 110 else 111 opt.state &= ~QStyleFacade::State_Horizontal; 112 113 opt.slider.value = scrollbar->value(); 114 opt.slider.position = opt.slider.value; 115 opt.slider.pageStep = scrollbar->pageStep(); 116 opt.slider.singleStep = scrollbar->lineStep(); 117 opt.slider.minimum = 0; 118 opt.slider.maximum = qMax(0, scrollbar->maximum()); 119 ScrollbarPart pressedPart = scrollbar->pressedPart(); 120 ScrollbarPart hoveredPart = scrollbar->hoveredPart(); 121 if (pressedPart != NoPart) { 122 opt.slider.activeSubControls = scPart(scrollbar->pressedPart()); 123 if (pressedPart == BackButtonStartPart || pressedPart == ForwardButtonStartPart 124 || pressedPart == BackButtonEndPart || pressedPart == ForwardButtonEndPart 125 || pressedPart == ThumbPart) 126 opt.state |= QStyleFacade::State_Sunken; 127 } else 128 opt.slider.activeSubControls = scPart(hoveredPart); 129 if (hoveredPart != NoPart) 130 opt.state |= QStyleFacade::State_MouseOver; 131 return opt; 132} 133 134bool ScrollbarThemeQStyle::paint(ScrollbarThemeClient* scrollbar, GraphicsContext* graphicsContext, const IntRect& dirtyRect) 135{ 136 if (graphicsContext->updatingControlTints()) { 137 scrollbar->invalidateRect(dirtyRect); 138 return false; 139 } 140 141 StylePainterQStyle p(this, graphicsContext); 142 if (!p.isValid()) 143 return true; 144 145 p.painter->save(); 146 p.styleOption = initSliderStyleOption(scrollbar, m_qStyle->widgetForPainter(p.painter)); 147 148 p.painter->setClipRect(p.styleOption.rect.intersected(dirtyRect), Qt::IntersectClip); 149 p.paintScrollBar(); 150 p.painter->restore(); 151 return true; 152} 153 154ScrollbarPart ScrollbarThemeQStyle::hitTest(ScrollbarThemeClient* scrollbar, const IntPoint& position) 155{ 156 QStyleFacadeOption opt = initSliderStyleOption(scrollbar); 157 const QPoint pos = scrollbar->convertFromContainingWindow(position); 158 opt.rect.moveTo(QPoint(0, 0)); 159 QStyleFacade::SubControl sc = m_qStyle->hitTestScrollBar(opt, pos); 160 return scrollbarPart(sc); 161} 162 163bool ScrollbarThemeQStyle::shouldCenterOnThumb(ScrollbarThemeClient*, const PlatformMouseEvent& evt) 164{ 165 // Middle click centers slider thumb (if supported). 166 return m_qStyle->scrollBarMiddleClickAbsolutePositionStyleHint() && evt.button() == MiddleButton; 167} 168 169void ScrollbarThemeQStyle::invalidatePart(ScrollbarThemeClient* scrollbar, ScrollbarPart) 170{ 171 // FIXME: Do more precise invalidation. 172 scrollbar->invalidate(); 173} 174 175int ScrollbarThemeQStyle::scrollbarThickness(ScrollbarControlSize controlSize) 176{ 177 const bool mini = controlSize != RegularScrollbar; 178 return m_qStyle->scrollBarExtent(mini); 179} 180 181int ScrollbarThemeQStyle::thumbPosition(ScrollbarThemeClient* scrollbar) 182{ 183 if (scrollbar->enabled()) { 184 float pos = (float)scrollbar->currentPos() * (trackLength(scrollbar) - thumbLength(scrollbar)) / scrollbar->maximum(); 185 return (pos < 1 && pos > 0) ? 1 : pos; 186 } 187 return 0; 188} 189 190int ScrollbarThemeQStyle::thumbLength(ScrollbarThemeClient* scrollbar) 191{ 192 QStyleFacadeOption opt = initSliderStyleOption(scrollbar); 193 QRect thumb = m_qStyle->scrollBarSubControlRect(opt, QStyleFacade::SC_ScrollBarSlider); 194 return scrollbar->orientation() == HorizontalScrollbar ? thumb.width() : thumb.height(); 195} 196 197int ScrollbarThemeQStyle::trackPosition(ScrollbarThemeClient* scrollbar) 198{ 199 QStyleFacadeOption opt = initSliderStyleOption(scrollbar); 200 QRect track = m_qStyle->scrollBarSubControlRect(opt, QStyleFacade::SC_ScrollBarGroove); 201 return scrollbar->orientation() == HorizontalScrollbar ? track.x() - scrollbar->x() : track.y() - scrollbar->y(); 202} 203 204int ScrollbarThemeQStyle::trackLength(ScrollbarThemeClient* scrollbar) 205{ 206 QStyleFacadeOption opt = initSliderStyleOption(scrollbar); 207 QRect track = m_qStyle->scrollBarSubControlRect(opt, QStyleFacade::SC_ScrollBarGroove); 208 return scrollbar->orientation() == HorizontalScrollbar ? track.width() : track.height(); 209} 210 211void ScrollbarThemeQStyle::paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& rect) 212{ 213 StylePainterQStyle p(this, context); 214 if (!p.isValid()) 215 return; 216 217 p.paintScrollCorner(rect); 218} 219 220} 221 222