source: trunk/demos/qtdemo/textbutton.cpp@ 858

Last change on this file since 858 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 12.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the demonstration applications of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "textbutton.h"
43#include "demoitemanimation.h"
44#include "demotextitem.h"
45#include "colors.h"
46#include "menumanager.h"
47
48#define BUTTON_WIDTH 180
49#define BUTTON_HEIGHT 19
50
51class ButtonBackground : public DemoItem
52{
53public:
54 TextButton::BUTTONTYPE type;
55 bool highlighted;
56 bool pressed;
57 QSize logicalSize;
58
59 ButtonBackground(TextButton::BUTTONTYPE type, bool highlighted, bool pressed, QSize logicalSize,
60 QGraphicsScene *scene, QGraphicsItem *parent) : DemoItem(scene, parent)
61 {
62 this->type = type;
63 this->highlighted = highlighted;
64 this->pressed = pressed;
65 this->logicalSize = logicalSize;
66 useSharedImage(QString(__FILE__) + static_cast<int>(type) + highlighted + pressed);
67 }
68
69protected:
70 QImage *createImage(const QMatrix &matrix) const
71 {
72 if (type == TextButton::SIDEBAR || type == TextButton::PANEL)
73 return createRoundButtonBackground(matrix);
74 else
75 return createArrowBackground(matrix);
76 }
77
78 QImage *createRoundButtonBackground(const QMatrix &matrix) const
79 {
80 QRect scaledRect;
81 scaledRect = matrix.mapRect(QRect(0, 0, this->logicalSize.width(), this->logicalSize.height()));
82
83 QImage *image = new QImage(scaledRect.width(), scaledRect.height(), QImage::Format_ARGB32_Premultiplied);
84 image->fill(QColor(0, 0, 0, 0).rgba());
85 QPainter painter(image);
86 painter.setRenderHint(QPainter::SmoothPixmapTransform);
87 painter.setRenderHint(QPainter::Antialiasing);
88 painter.setPen(Qt::NoPen);
89
90 if (Colors::useEightBitPalette){
91 painter.setPen(QColor(120, 120, 120));
92 if (this->pressed)
93 painter.setBrush(QColor(60, 60, 60));
94 else if (this->highlighted)
95 painter.setBrush(QColor(100, 100, 100));
96 else
97 painter.setBrush(QColor(80, 80, 80));
98 }
99 else {
100 QLinearGradient outlinebrush(0, 0, 0, scaledRect.height());
101 QLinearGradient brush(0, 0, 0, scaledRect.height());
102
103 brush.setSpread(QLinearGradient::PadSpread);
104 QColor highlight(255, 255, 255, 70);
105 QColor shadow(0, 0, 0, 70);
106 QColor sunken(220, 220, 220, 30);
107 QColor normal1(255, 255, 245, 60);
108 QColor normal2(255, 255, 235, 10);
109
110 if (this->type == TextButton::PANEL){
111 normal1 = QColor(200, 170, 160, 50);
112 normal2 = QColor(50, 10, 0, 50);
113 }
114
115 if (pressed) {
116 outlinebrush.setColorAt(0.0f, shadow);
117 outlinebrush.setColorAt(1.0f, highlight);
118 brush.setColorAt(0.0f, sunken);
119 painter.setPen(Qt::NoPen);
120 } else {
121 outlinebrush.setColorAt(1.0f, shadow);
122 outlinebrush.setColorAt(0.0f, highlight);
123 brush.setColorAt(0.0f, normal1);
124 if (!this->highlighted)
125 brush.setColorAt(1.0f, normal2);
126 painter.setPen(QPen(outlinebrush, 1));
127 }
128 painter.setBrush(brush);
129 }
130
131 if (this->type == TextButton::PANEL)
132 painter.drawRect(0, 0, scaledRect.width(), scaledRect.height());
133 else
134 painter.drawRoundedRect(0, 0, scaledRect.width(), scaledRect.height(), 10, 90, Qt::RelativeSize);
135 return image;
136 }
137
138 QImage *createArrowBackground(const QMatrix &matrix) const
139 {
140 QRect scaledRect;
141 scaledRect = matrix.mapRect(QRect(0, 0, this->logicalSize.width(), this->logicalSize.height()));
142
143 QImage *image = new QImage(scaledRect.width(), scaledRect.height(), QImage::Format_ARGB32_Premultiplied);
144 image->fill(QColor(0, 0, 0, 0).rgba());
145 QPainter painter(image);
146 painter.setRenderHint(QPainter::SmoothPixmapTransform);
147 painter.setRenderHint(QPainter::Antialiasing);
148 painter.setPen(Qt::NoPen);
149
150 if (Colors::useEightBitPalette){
151 painter.setPen(QColor(120, 120, 120));
152 if (this->pressed)
153 painter.setBrush(QColor(60, 60, 60));
154 else if (this->highlighted)
155 painter.setBrush(QColor(100, 100, 100));
156 else
157 painter.setBrush(QColor(80, 80, 80));
158 }
159 else {
160 QLinearGradient outlinebrush(0, 0, 0, scaledRect.height());
161 QLinearGradient brush(0, 0, 0, scaledRect.height());
162
163 brush.setSpread(QLinearGradient::PadSpread);
164 QColor highlight(255, 255, 255, 70);
165 QColor shadow(0, 0, 0, 70);
166 QColor sunken(220, 220, 220, 30);
167 QColor normal1 = QColor(200, 170, 160, 50);
168 QColor normal2 = QColor(50, 10, 0, 50);
169
170 if (pressed) {
171 outlinebrush.setColorAt(0.0f, shadow);
172 outlinebrush.setColorAt(1.0f, highlight);
173 brush.setColorAt(0.0f, sunken);
174 painter.setPen(Qt::NoPen);
175 } else {
176 outlinebrush.setColorAt(1.0f, shadow);
177 outlinebrush.setColorAt(0.0f, highlight);
178 brush.setColorAt(0.0f, normal1);
179 if (!this->highlighted)
180 brush.setColorAt(1.0f, normal2);
181 painter.setPen(QPen(outlinebrush, 1));
182 }
183 painter.setBrush(brush);
184 }
185
186 painter.drawRect(0, 0, scaledRect.width(), scaledRect.height());
187
188 float xOff = scaledRect.width() / 2;
189 float yOff = scaledRect.height() / 2;
190 float sizex = 3.0f * matrix.m11();
191 float sizey = 1.5f * matrix.m22();
192 if (this->type == TextButton::UP)
193 sizey *= -1;
194 QPainterPath path;
195 path.moveTo(xOff, yOff + (5 * sizey));
196 path.lineTo(xOff - (4 * sizex), yOff - (3 * sizey));
197 path.lineTo(xOff + (4 * sizex), yOff - (3 * sizey));
198 path.lineTo(xOff, yOff + (5 * sizey));
199 painter.drawPath(path);
200
201 return image;
202 }
203
204};
205
206TextButton::TextButton(const QString &text, ALIGNMENT align, int userCode,
207 QGraphicsScene *scene, QGraphicsItem *parent, BUTTONTYPE type)
208 : DemoItem(scene, parent)
209{
210 this->menuString = text;
211 this->buttonLabel = text;
212 this->alignment = align;
213 this->buttonType = type;
214 this->userCode = userCode;
215 this->bgOn = 0;
216 this->bgOff = 0;
217 this->bgHighlight = 0;
218 this->bgDisabled = 0;
219 this->state = OFF;
220
221 this->setAcceptsHoverEvents(true);
222 this->setCursor(Qt::PointingHandCursor);
223
224 // Calculate button size:
225 const int w = 180;
226 const int h = 19;
227 if (type == SIDEBAR || type == PANEL)
228 this->logicalSize = QSize(w, h);
229 else
230 this->logicalSize = QSize(int((w / 2.0f) - 5), int(h * 1.5f));
231}
232
233void TextButton::setMenuString(const QString &menu)
234{
235 this->menuString = menu;
236}
237
238void TextButton::prepare()
239{
240 if (!this->prepared){
241 this->prepared = true;
242 this->setupHoverText();
243 this->setupScanItem();
244 this->setupButtonBg();
245 }
246}
247
248TextButton::~TextButton()
249{
250 if (this->prepared){
251 if (Colors::useButtonBalls)
252 delete this->scanAnim;
253 }
254}
255
256QRectF TextButton::boundingRect() const
257{
258 return QRectF(0, 0, this->logicalSize.width(), this->logicalSize.height());
259};
260
261void TextButton::setupHoverText()
262{
263 if (this->buttonLabel.isEmpty())
264 return;
265
266 DemoTextItem *textItem = new DemoTextItem(this->buttonLabel, Colors::buttonFont(), Colors::buttonText, -1, this->scene(), this);
267 textItem->setZValue(zValue() + 2);
268 textItem->setPos(16, 0);
269}
270
271void TextButton::setupScanItem()
272{
273 if (Colors::useButtonBalls){
274 ScanItem *scanItem = new ScanItem(0, this);
275 scanItem->setZValue(zValue() + 1);
276
277 this->scanAnim = new DemoItemAnimation(scanItem);
278 this->scanAnim->timeline->setLoopCount(1);
279
280 float x = 1;
281 float y = 1.5f;
282 float stop = BUTTON_WIDTH - scanItem->boundingRect().width() - x;
283 if (this->alignment == LEFT){
284 this->scanAnim->setDuration(2500);
285 this->scanAnim->setPosAt(0.0, QPointF(x, y));
286 this->scanAnim->setPosAt(0.5, QPointF(x, y));
287 this->scanAnim->setPosAt(0.7, QPointF(stop, y));
288 this->scanAnim->setPosAt(1.0, QPointF(x, y));
289 scanItem->setPos(QPointF(x, y));
290 }
291 else {
292 this->scanAnim->setPosAt(0.0, QPointF(stop, y));
293 this->scanAnim->setPosAt(0.5, QPointF(x, y));
294 this->scanAnim->setPosAt(1.0, QPointF(stop, y));
295 scanItem->setPos(QPointF(stop, y));
296 }
297 }
298}
299
300void TextButton::setState(STATE state)
301{
302 this->state = state;
303 this->bgOn->setRecursiveVisible(state == ON);
304 this->bgOff->setRecursiveVisible(state == OFF);
305 this->bgHighlight->setRecursiveVisible(state == HIGHLIGHT);
306 this->bgDisabled->setRecursiveVisible(state == DISABLED);
307 this->setCursor(state == DISABLED ? Qt::ArrowCursor : Qt::PointingHandCursor);
308
309}
310
311void TextButton::setupButtonBg()
312{
313 this->bgOn = new ButtonBackground(this->buttonType, true, true, this->logicalSize, this->scene(), this);
314 this->bgOff = new ButtonBackground(this->buttonType, false, false, this->logicalSize, this->scene(), this);
315 this->bgHighlight = new ButtonBackground(this->buttonType, true, false, this->logicalSize, this->scene(), this);
316 this->bgDisabled = new ButtonBackground(this->buttonType, true, true, this->logicalSize, this->scene(), this);
317 this->setState(OFF);
318}
319
320void TextButton::hoverEnterEvent(QGraphicsSceneHoverEvent *)
321{
322 if (this->locked || this->state == DISABLED)
323 return;
324
325 if (this->state == OFF){
326 this->setState(HIGHLIGHT);
327
328 if (Colors::noAnimations && Colors::useButtonBalls){
329 // wait a bit in the beginning
330 // to enhance the effect. Have to this here
331 // so that the adaption can be dynamic
332 this->scanAnim->setDuration(1000);
333 this->scanAnim->setPosAt(0.2, this->scanAnim->posAt(0));
334 }
335
336 if (MenuManager::instance()->window->fpsMedian > 10
337 || Colors::noAdapt
338 || Colors::noTimerUpdate){
339 if (Colors::useButtonBalls)
340 this->scanAnim->play(true, true);
341 }
342 }
343}
344
345void TextButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
346{
347 Q_UNUSED(event);
348 if (this->state == DISABLED)
349 return;
350
351 this->setState(OFF);
352
353 if (Colors::noAnimations && Colors::useButtonBalls)
354 this->scanAnim->stop();
355}
356
357void TextButton::mousePressEvent(QGraphicsSceneMouseEvent *)
358{
359 if (this->state == DISABLED)
360 return;
361
362 if (this->state == HIGHLIGHT || this->state == OFF)
363 this->setState(ON);
364}
365
366void TextButton::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
367{
368 if (this->state == ON){
369 this->setState(OFF);
370 if (!this->locked && this->boundingRect().contains(event->pos())){
371 MenuManager::instance()->itemSelected(this->userCode, this->menuString);
372 }
373 }
374}
375
376void TextButton::animationStarted(int)
377{
378 if (this->state == DISABLED)
379 return;
380 this->setState(OFF);
381}
382
383
384
Note: See TracBrowser for help on using the repository browser.