1 /*
2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20 #include "config.h"
21 #include "QtMobileWebStyle.h"
22
23 #include "QtStyleOptionWebComboBox.h"
24
25 #include <QPainter>
26 #include <QPixmapCache>
27 #include <QStyleOption>
28
QtMobileWebStyle()29 QtMobileWebStyle::QtMobileWebStyle()
30 {
31 }
32
drawRectangularControlBackground(QPainter * painter,const QPen & pen,const QRect & rect,const QBrush & brush)33 static inline void drawRectangularControlBackground(QPainter* painter, const QPen& pen, const QRect& rect, const QBrush& brush)
34 {
35 QPen oldPen = painter->pen();
36 QBrush oldBrush = painter->brush();
37 painter->setRenderHint(QPainter::Antialiasing, true);
38 painter->setPen(pen);
39 painter->setBrush(brush);
40
41 int line = 1;
42 painter->drawRoundedRect(rect.adjusted(line, line, -line, -line),
43 /* xRadius */ 5.0, /* yRadious */ 5.0);
44 painter->setPen(oldPen);
45 painter->setBrush(oldBrush);
46 }
47
drawChecker(QPainter * painter,int size,QColor color) const48 void QtMobileWebStyle::drawChecker(QPainter* painter, int size, QColor color) const
49 {
50 int border = qMin(qMax(1, int(0.2 * size)), 6);
51 int checkerSize = qMax(size - 2 * border, 3);
52 int width = checkerSize / 3;
53 int middle = qMax(3 * checkerSize / 7, 3);
54 int x = ((size - checkerSize) >> 1);
55 int y = ((size - checkerSize) >> 1) + (checkerSize - width - middle);
56 QVector<QLineF> lines(checkerSize + 1);
57 painter->setPen(color);
58 for (int i = 0; i < middle; ++i) {
59 lines[i] = QLineF(x, y, x, y + width);
60 ++x;
61 ++y;
62 }
63 for (int i = middle; i <= checkerSize; ++i) {
64 lines[i] = QLineF(x, y, x, y + width);
65 ++x;
66 --y;
67 }
68 painter->drawLines(lines.constData(), lines.size());
69 }
70
findChecker(const QRect & rect,bool disabled) const71 QPixmap QtMobileWebStyle::findChecker(const QRect& rect, bool disabled) const
72 {
73 int size = qMin(rect.width(), rect.height());
74 QPixmap result;
75 static const QString prefix = QLatin1String("$qt-maemo5-") + QLatin1String(metaObject()->className())+ QLatin1String("-checker-");
76 QString key = prefix + QString::number(size) + QLatin1String("-") + (disabled ? QLatin1String("disabled") : QLatin1String("enabled"));
77 if (!QPixmapCache::find(key, result)) {
78 result = QPixmap(size, size);
79 result.fill(Qt::transparent);
80 QPainter painter(&result);
81 drawChecker(&painter, size, disabled ? Qt::lightGray : Qt::darkGray);
82 QPixmapCache::insert(key, result);
83 }
84 return result;
85 }
86
drawRadio(QPainter * painter,const QSize & size,bool checked,QColor color) const87 void QtMobileWebStyle::drawRadio(QPainter* painter, const QSize& size, bool checked, QColor color) const
88 {
89 painter->setRenderHint(QPainter::Antialiasing, true);
90
91 // get minor size to do not paint a wide elipse
92 qreal squareSize = qMin(size.width(), size.height());
93 // deflate one pixel
94 QRect rect = QRect(QPoint(1, 1), QSize(squareSize - 2, squareSize - 2));
95 const QPoint centerGradient(rect.bottomRight() * 0.7);
96
97 QRadialGradient radialGradient(centerGradient, centerGradient.x() - 1);
98 radialGradient.setColorAt(0.0, Qt::white);
99 radialGradient.setColorAt(0.6, Qt::white);
100 radialGradient.setColorAt(1.0, color);
101
102 painter->setPen(color);
103 painter->setBrush(color);
104 painter->drawEllipse(rect);
105 painter->setBrush(radialGradient);
106 painter->drawEllipse(rect);
107
108 int border = 0.1 * (rect.width() + rect.height());
109 border = qMin(qMax(2, border), 10);
110 rect.adjust(border, border, -border, -border);
111 if (checked) {
112 painter->setPen(Qt::NoPen);
113 painter->setBrush(color);
114 painter->drawEllipse(rect);
115 }
116 }
117
findRadio(const QSize & size,bool checked,bool disabled) const118 QPixmap QtMobileWebStyle::findRadio(const QSize& size, bool checked, bool disabled) const
119 {
120 QPixmap result;
121 static const QString prefix = QLatin1String("$qt-maemo5-") + QLatin1String(metaObject()->className()) + QLatin1String("-radio-");
122 QString key = prefix + QString::number(size.width()) + QLatin1String("-") + QString::number(size.height()) + QLatin1String("-")
123 + (disabled ? QLatin1String("disabled") : QLatin1String("enabled")) + (checked ? QLatin1String("-checked") : QLatin1String(""));
124 if (!QPixmapCache::find(key, result)) {
125 result = QPixmap(size);
126 result.fill(Qt::transparent);
127 QPainter painter(&result);
128 drawRadio(&painter, size, checked, disabled ? Qt::lightGray : Qt::darkGray);
129 QPixmapCache::insert(key, result);
130 }
131 return result;
132 }
133
drawControl(ControlElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const134 void QtMobileWebStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
135 {
136 switch (element) {
137 case CE_CheckBox: {
138 QRect rect = option->rect;
139 const bool disabled = !(option->state & State_Enabled);
140
141 QLinearGradient linearGradient(rect.topLeft(), rect.bottomLeft());
142 if (disabled) {
143 linearGradient.setColorAt(0.0, Qt::lightGray);
144 linearGradient.setColorAt(0.5, Qt::white);
145 } else {
146 linearGradient.setColorAt(0.0, Qt::darkGray);
147 linearGradient.setColorAt(0.5, Qt::white);
148 }
149
150 painter->setPen(QPen(disabled ? Qt::lightGray : Qt::darkGray));
151 painter->setBrush(linearGradient);
152 painter->drawRect(rect);
153 rect.adjust(1, 1, -1, -1);
154
155 if (option->state & State_Off)
156 break;
157
158 QPixmap checker = findChecker(rect, disabled);
159 if (checker.isNull())
160 break;
161
162 int x = (rect.width() - checker.width()) >> 1;
163 int y = (rect.height() - checker.height()) >> 1;
164 painter->drawPixmap(rect.x() + x, rect.y() + y, checker);
165 break;
166 }
167 case CE_RadioButton: {
168 const bool disabled = !(option->state & State_Enabled);
169 QPixmap radio = findRadio(option->rect.size(), option->state & State_On, disabled);
170 if (radio.isNull())
171 break;
172 painter->drawPixmap(option->rect.x(), option->rect.y(), radio);
173 break;
174 }
175 case CE_PushButton: {
176 const bool disabled = !(option->state & State_Enabled);
177 QRect rect = option->rect;
178 QPen pen(Qt::darkGray, 1.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
179 painter->setPen(pen);
180
181 const bool sunken = (option->state & State_Sunken);
182 if (sunken) {
183 drawRectangularControlBackground(painter, pen, rect, QBrush(Qt::darkGray));
184 break;
185 }
186
187 QLinearGradient linearGradient;
188 if (disabled) {
189 linearGradient.setStart(rect.bottomLeft());
190 linearGradient.setFinalStop(rect.topLeft());
191 linearGradient.setColorAt(0.0, Qt::gray);
192 linearGradient.setColorAt(1.0, Qt::white);
193 } else {
194 linearGradient.setStart(rect.bottomLeft());
195 linearGradient.setFinalStop(QPoint(rect.bottomLeft().x(),
196 rect.bottomLeft().y() - /* offset limit for gradient */ 20));
197 linearGradient.setColorAt(0.0, Qt::gray);
198 linearGradient.setColorAt(0.4, Qt::white);
199 }
200
201 drawRectangularControlBackground(painter, pen, rect, linearGradient);
202 break;
203 }
204 default:
205 QWindowsStyle::drawControl(element, option, painter, widget);
206 }
207 }
drawPrimitive(PrimitiveElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const208 void QtMobileWebStyle::drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
209 {
210 switch (element) {
211 case QStyle::PE_PanelLineEdit: {
212 const bool disabled = !(option->state & State_Enabled);
213 const bool sunken = (option->state & State_Sunken);
214 QRect rect = option->rect;
215 QPen pen(Qt::darkGray, 1.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
216 painter->setPen(pen);
217
218 if (sunken) {
219 drawRectangularControlBackground(painter, pen, rect, QBrush(Qt::darkGray));
220 break;
221 }
222
223 QLinearGradient linearGradient;
224 if (disabled) {
225 linearGradient.setStart(rect.topLeft());
226 linearGradient.setFinalStop(rect.bottomLeft());
227 linearGradient.setColorAt(0.0, Qt::lightGray);
228 linearGradient.setColorAt(1.0, Qt::white);
229 } else {
230 linearGradient.setStart(rect.topLeft());
231 linearGradient.setFinalStop(QPoint(rect.topLeft().x(),
232 rect.topLeft().y() + /* offset limit for gradient */ 20));
233 linearGradient.setColorAt(0.0, Qt::darkGray);
234 linearGradient.setColorAt(0.35, Qt::white);
235 }
236
237 drawRectangularControlBackground(painter, pen, rect, linearGradient);
238 break;
239 }
240 default:
241 QWindowsStyle::drawPrimitive(element, option, painter, widget);
242 }
243 }
244
drawMultipleComboButton(QPainter * painter,const QSize & size,QColor color) const245 void QtMobileWebStyle::drawMultipleComboButton(QPainter* painter, const QSize& size, QColor color) const
246 {
247 int rectWidth = size.width() - 1;
248 int width = qMax(2, rectWidth >> 3);
249 int distance = (rectWidth - 3 * width) >> 1;
250 int top = (size.height() - width) >> 1;
251
252 painter->setPen(color);
253 painter->setBrush(color);
254
255 painter->drawRect(0, top, width, width);
256 painter->drawRect(width + distance, top, width, width);
257 painter->drawRect(2 * (width + distance), top, width, width);
258 }
259
drawSimpleComboButton(QPainter * painter,const QSize & size,QColor color) const260 void QtMobileWebStyle::drawSimpleComboButton(QPainter* painter, const QSize& size, QColor color) const
261 {
262 int width = size.width();
263 int midle = width >> 1;
264 QVector<QLine> lines(width + 1);
265
266 for (int x = 0, y = 0; x < midle; x++, y++) {
267 lines[x] = QLine(x, y, x, y + 2);
268 lines[x + midle] = QLine(width - x - 1, y, width - x - 1, y + 2);
269 }
270 // Just to ensure the lines' intersection.
271 lines[width] = QLine(midle, midle, midle, midle + 2);
272
273 painter->setPen(color);
274 painter->setBrush(color);
275 painter->drawLines(lines);
276 }
277
getButtonImageSize(const QSize & buttonSize) const278 QSize QtMobileWebStyle::getButtonImageSize(const QSize& buttonSize) const
279 {
280 const int border = qMax(3, buttonSize.width() >> 3) << 1;
281
282 int width = buttonSize.width() - border;
283 int height = buttonSize.height() - border;
284
285 if (width < 0 || height < 0)
286 return QSize();
287
288 if (height >= (width >> 1))
289 width = width >> 1 << 1;
290 else
291 width = height << 1;
292
293 return QSize(width + 1, width);
294 }
295
findComboButton(const QSize & size,bool multiple,bool disabled) const296 QPixmap QtMobileWebStyle::findComboButton(const QSize& size, bool multiple, bool disabled) const
297 {
298 QPixmap result;
299 QSize imageSize = getButtonImageSize(size);
300
301 if (imageSize.isNull())
302 return QPixmap();
303 static const QString prefix = QLatin1String("$qt-maemo5-") + QLatin1String(metaObject()->className()) + QLatin1String("-combo-");
304 QString key = prefix + (multiple ? QLatin1String("multiple-") : QLatin1String("simple-"))
305 + QString::number(imageSize.width()) + QLatin1String("-") + QString::number(imageSize.height())
306 + QLatin1String("-") + (disabled ? QLatin1String("disabled") : QLatin1String("enabled"));
307 if (!QPixmapCache::find(key, result)) {
308 result = QPixmap(imageSize);
309 result.fill(Qt::transparent);
310 QPainter painter(&result);
311 if (multiple)
312 drawMultipleComboButton(&painter, imageSize, disabled ? Qt::lightGray : Qt::darkGray);
313 else
314 drawSimpleComboButton(&painter, imageSize, disabled ? Qt::lightGray : Qt::darkGray);
315 QPixmapCache::insert(key, result);
316 }
317 return result;
318 }
319
drawComplexControl(ComplexControl control,const QStyleOptionComplex * option,QPainter * painter,const QWidget * widget) const320 void QtMobileWebStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const
321 {
322 switch (control) {
323 case CC_ComboBox: {
324 bool multiple = false;
325 const bool disabled = !(option->state & State_Enabled);
326
327 const QStyleOptionComboBox* cmb = 0;
328 const WebCore::QtStyleOptionWebComboBox* webCombo = static_cast<const WebCore::QtStyleOptionWebComboBox*>(option);
329
330 if (webCombo) {
331 multiple = webCombo->multiple();
332 cmb = webCombo;
333 } else
334 cmb = qstyleoption_cast<const QStyleOptionComboBox*>(option);
335
336 if (!cmb) {
337 QWindowsStyle::drawComplexControl(control, option, painter, widget);
338 break;
339 }
340
341 if (!(cmb->subControls & SC_ComboBoxArrow))
342 break;
343
344 QRect rect = option->rect;
345 QPen pen(Qt::darkGray, 1.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
346 QLinearGradient linearGradient;
347 if (disabled) {
348 linearGradient.setStart(rect.bottomLeft());
349 linearGradient.setFinalStop(rect.topLeft());
350 linearGradient.setColorAt(0.0, Qt::gray);
351 linearGradient.setColorAt(1.0, Qt::white);
352 } else {
353 linearGradient.setStart(rect.bottomLeft());
354 linearGradient.setFinalStop(QPoint(rect.bottomLeft().x(),
355 rect.bottomLeft().y() - /* offset limit for gradient */ 20));
356 linearGradient.setColorAt(0.0, Qt::gray);
357 linearGradient.setColorAt(0.4, Qt::white);
358 }
359
360 drawRectangularControlBackground(painter, pen, rect, linearGradient);
361
362 rect = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget);
363 QPixmap pic = findComboButton(rect.size(), multiple, disabled);
364
365 if (pic.isNull())
366 break;
367
368 int x = (rect.width() - pic.width()) >> 1;
369 int y = (rect.height() - pic.height()) >> 1;
370 painter->drawPixmap(rect.x() + x, rect.y() + y, pic);
371
372 painter->setPen(disabled ? Qt::gray : Qt::darkGray);
373 painter->drawLine(rect.left() - 2, rect.top() + 2, rect.left() - 2, rect.bottom() - 2);
374
375 break;
376 }
377 default:
378 QWindowsStyle::drawComplexControl(control, option, painter, widget);
379 }
380 }
381
382