• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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