~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kwin/clients/aurorae/src/lib/auroraebutton.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Library for Aurorae window decoration themes.
 
3
    Copyright (C) 2009, 2010 Martin Gräßlin <kde@martin-graesslin.com>
 
4
 
 
5
    This program is free software; you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation; either version 2 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License along
 
16
    with this program; if not, write to the Free Software Foundation, Inc.,
 
17
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
18
 
 
19
*/
 
20
 
 
21
#include "auroraebutton.h"
 
22
#include "auroraescene.h"
 
23
#include "auroraetheme.h"
 
24
#include "themeconfig.h"
 
25
// Qt
 
26
#include <QtCore/QEasingCurve>
 
27
#include <QtCore/QPropertyAnimation>
 
28
#include <QtCore/QTimer>
 
29
#include <QtGui/QGraphicsSceneEvent>
 
30
#include <QtGui/QPainter>
 
31
// KDE
 
32
#include <KDE/KIcon>
 
33
#include <KDE/KIconLoader>
 
34
#include <KDE/KIconEffect>
 
35
#include <KDE/Plasma/FrameSvg>
 
36
#include <KDE/Plasma/PaintUtils>
 
37
 
 
38
namespace Aurorae {
 
39
 
 
40
AuroraeButtonGroup::AuroraeButtonGroup(AuroraeTheme *theme, AuroraeButtonGroup::ButtonGroup group)
 
41
    : QGraphicsWidget()
 
42
    , m_theme(theme)
 
43
    , m_group(group)
 
44
{
 
45
}
 
46
 
 
47
void AuroraeButtonGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
 
48
{
 
49
    Q_UNUSED(option)
 
50
    Q_UNUSED(widget)
 
51
    Plasma::FrameSvg *decoration = m_theme->decoration();
 
52
    QString basePrefix;
 
53
    QString prefix;
 
54
    AuroraeScene *s = static_cast<AuroraeScene*>(scene());
 
55
    switch (m_group) {
 
56
    case LeftGroup:
 
57
        basePrefix = "buttongroup-left";
 
58
        break;
 
59
    case RightGroup:
 
60
        basePrefix = "buttongroup-right";
 
61
        break;
 
62
    }
 
63
    if (!decoration->hasElementPrefix(basePrefix)) {
 
64
        return;
 
65
    }
 
66
    if (!s->isActive() && decoration->hasElementPrefix(basePrefix + "-inactive")) {
 
67
        prefix = basePrefix + "-inactive";
 
68
    } else {
 
69
        prefix = basePrefix;
 
70
    }
 
71
    decoration->setElementPrefix(prefix);
 
72
    decoration->setEnabledBorders(Plasma::FrameSvg::AllBorders);
 
73
    decoration->resizeFrame(size());
 
74
    if (s->isAnimating() && decoration->hasElementPrefix(basePrefix + "-inactive")) {
 
75
        QPixmap target = decoration->framePixmap();
 
76
        decoration->setElementPrefix(basePrefix + "-inactive");
 
77
        if (!s->isActive()) {
 
78
            decoration->setElementPrefix(basePrefix);
 
79
        }
 
80
        decoration->resizeFrame(size());
 
81
        QPixmap result = Plasma::PaintUtils::transition(decoration->framePixmap(),
 
82
                                                        target, s->animationProgress());
 
83
        painter->drawPixmap(0, 0, result);
 
84
    } else {
 
85
        decoration->paintFrame(painter);
 
86
    }
 
87
}
 
88
 
 
89
AuroraeButton::AuroraeButton(AuroraeTheme* theme, AuroraeButtonType type)
 
90
    : QGraphicsWidget()
 
91
    , m_theme(theme)
 
92
    , m_type(type)
 
93
    , m_pressed(false)
 
94
    , m_hovered(false)
 
95
    , m_animationProgress(0.0)
 
96
    , m_animation(new QPropertyAnimation(this, "animation", this))
 
97
    , m_checkable(false)
 
98
    , m_checked(false)
 
99
{
 
100
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
 
101
    setAcceptHoverEvents(true);
 
102
    setAcceptedMouseButtons(Qt::LeftButton);
 
103
    connect(m_theme, SIGNAL(buttonSizesChanged()), SLOT(buttonSizesChanged()));
 
104
}
 
105
 
 
106
AuroraeButton::~AuroraeButton()
 
107
{
 
108
}
 
109
 
 
110
void AuroraeButton::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
 
111
{
 
112
    Q_UNUSED(option)
 
113
    Q_UNUSED(widget)
 
114
    if (m_theme->hasButton(m_type)) {
 
115
        ButtonStates state;
 
116
        if (static_cast<AuroraeScene*>(scene())->isActive()) {
 
117
            state |= Active;
 
118
        }
 
119
        if (m_hovered) {
 
120
            state |= Hover;
 
121
        }
 
122
        if (m_pressed) {
 
123
            state |= Pressed;
 
124
        }
 
125
        if (isCheckable() && isChecked()) {
 
126
            state |= Pressed;
 
127
        }
 
128
        paintButton(painter, m_theme->button(currentType()), state);
 
129
    }
 
130
}
 
131
 
 
132
AuroraeButtonType AuroraeButton::currentType() const
 
133
{
 
134
    return m_type;
 
135
}
 
136
 
 
137
QSizeF AuroraeButton::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
 
138
{
 
139
    Q_UNUSED(which)
 
140
    Q_UNUSED(constraint)
 
141
    const qreal factor = m_theme->buttonSizeFactor();
 
142
    qreal width = m_theme->themeConfig().buttonWidth()*factor;
 
143
    qreal height = m_theme->themeConfig().buttonHeight()*factor;
 
144
    switch (m_type) {
 
145
    case MinimizeButton:
 
146
        width = m_theme->themeConfig().buttonWidthMinimize()*factor;
 
147
        break;
 
148
    case MaximizeButton:
 
149
    case RestoreButton:
 
150
        width = m_theme->themeConfig().buttonWidthMaximizeRestore()*factor;
 
151
        break;
 
152
    case CloseButton:
 
153
        width = m_theme->themeConfig().buttonWidthClose()*factor;
 
154
        break;
 
155
    case AllDesktopsButton:
 
156
        width = m_theme->themeConfig().buttonWidthAllDesktops()*factor;
 
157
        break;
 
158
    case KeepAboveButton:
 
159
        width = m_theme->themeConfig().buttonWidthKeepAbove()*factor;
 
160
        break;
 
161
    case KeepBelowButton:
 
162
        width = m_theme->themeConfig().buttonWidthKeepBelow()*factor;
 
163
        break;
 
164
    case ShadeButton:
 
165
        width = m_theme->themeConfig().buttonWidthShade()*factor;
 
166
        break;
 
167
    case HelpButton:
 
168
        width = m_theme->themeConfig().buttonWidthHelp()*factor;
 
169
        break;
 
170
    default:
 
171
        break; // nothing
 
172
    }
 
173
    if (m_theme->themeConfig().decorationPosition() == DecorationLeft ||
 
174
        m_theme->themeConfig().decorationPosition() == DecorationRight) {
 
175
        qSwap(width, height);
 
176
    }
 
177
    return QSizeF(width, height);
 
178
}
 
179
void AuroraeButton::mousePressEvent(QGraphicsSceneMouseEvent* event)
 
180
{
 
181
    Q_UNUSED(event)
 
182
    m_pressed = true;
 
183
    update();
 
184
}
 
185
 
 
186
void AuroraeButton::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
 
187
{
 
188
    Q_UNUSED(event)
 
189
    if (m_pressed) {
 
190
        emit clicked();
 
191
    }
 
192
    m_pressed = false;
 
193
    update();
 
194
    QGraphicsItem::mouseReleaseEvent(event);
 
195
}
 
196
 
 
197
void AuroraeButton::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
 
198
{
 
199
    Q_UNUSED(event)
 
200
    m_hovered = true;
 
201
    if (isAnimating()) {
 
202
        m_animation->stop();
 
203
    }
 
204
    m_animationProgress = 0.0;
 
205
    int time = m_theme->themeConfig().animationTime();
 
206
    if (time != 0) {
 
207
        m_animation->setDuration(time);
 
208
        m_animation->setEasingCurve(QEasingCurve::InQuad);
 
209
        m_animation->setStartValue(0.0);
 
210
        m_animation->setEndValue(1.0);
 
211
        m_animation->start();
 
212
    }
 
213
    update();
 
214
}
 
215
 
 
216
void AuroraeButton::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
 
217
{
 
218
    Q_UNUSED(event)
 
219
    m_hovered = false;
 
220
    if (isAnimating()) {
 
221
        m_animation->stop();
 
222
    }
 
223
    m_animationProgress = 0.0;
 
224
    int time = m_theme->themeConfig().animationTime();
 
225
    if (time != 0) {
 
226
        m_animation->setDuration(time);
 
227
        m_animation->setEasingCurve(QEasingCurve::OutQuad);
 
228
        m_animation->setStartValue(0.0);
 
229
        m_animation->setEndValue(1.0);
 
230
        m_animation->start();
 
231
    }
 
232
    update();
 
233
}
 
234
 
 
235
void AuroraeButton::paintButton(QPainter *painter, Plasma::FrameSvg *frame, ButtonStates states)
 
236
{
 
237
    QString prefix = "active";
 
238
    QString animationPrefix = "active";
 
239
    bool hasInactive = false;
 
240
    // check for inactive prefix
 
241
    if (!states.testFlag(Active) && frame->hasElementPrefix("inactive")) {
 
242
        // we have inactive, so we use it
 
243
        hasInactive = true;
 
244
        prefix = "inactive";
 
245
        animationPrefix = "inactive";
 
246
    }
 
247
 
 
248
    if (states.testFlag(Hover)) {
 
249
        if (states.testFlag(Active)) {
 
250
            if (frame->hasElementPrefix("hover")) {
 
251
                prefix = "hover";
 
252
            }
 
253
        } else {
 
254
            if (hasInactive) {
 
255
                if (frame->hasElementPrefix("hover-inactive")) {
 
256
                    prefix = "hover-inactive";
 
257
                }
 
258
            } else {
 
259
                if (frame->hasElementPrefix("hover")) {
 
260
                    prefix = "hover";
 
261
                }
 
262
            }
 
263
        }
 
264
    }
 
265
    if (states.testFlag(Pressed)) {
 
266
        if (states.testFlag(Active)) {
 
267
            if (frame->hasElementPrefix("pressed")) {
 
268
                prefix = "pressed";
 
269
            }
 
270
        } else {
 
271
            if (hasInactive) {
 
272
                if (frame->hasElementPrefix("pressed-inactive")) {
 
273
                    prefix = "pressed-inactive";
 
274
                }
 
275
            } else {
 
276
                if (frame->hasElementPrefix("pressed")) {
 
277
                    prefix = "pressed";
 
278
                }
 
279
            }
 
280
        }
 
281
    }
 
282
    if (states.testFlag(Deactivated)) {
 
283
        if (states.testFlag(Active)) {
 
284
            if (frame->hasElementPrefix("deactivated")) {
 
285
                prefix = "deactivated";
 
286
            }
 
287
        } else {
 
288
            if (hasInactive) {
 
289
                if (frame->hasElementPrefix("deactivated-inactive")) {
 
290
                    prefix = "deactivated-inactive";
 
291
                }
 
292
            } else {
 
293
                if (frame->hasElementPrefix("deactivated")) {
 
294
                    prefix = "deactivated";
 
295
                }
 
296
            }
 
297
        }
 
298
    }
 
299
    frame->setElementPrefix(prefix);
 
300
    frame->resizeFrame(size());
 
301
    if (isAnimating()) {
 
302
        // there is an animation so we have to use it
 
303
        // the animation is definately a hover animation as currently nothing else is supported
 
304
        if (!states.testFlag(Hover)) {
 
305
            // only have to set for not hover state as animationPrefix is set to (in)active by default
 
306
            if (states.testFlag(Active)) {
 
307
                if (frame->hasElementPrefix("hover")) {
 
308
                    animationPrefix = "hover";
 
309
                }
 
310
            } else {
 
311
                if (hasInactive) {
 
312
                    if (frame->hasElementPrefix("hover-inactive")) {
 
313
                        animationPrefix = "hover-inactive";
 
314
                    }
 
315
                } else {
 
316
                    if (frame->hasElementPrefix("hover")) {
 
317
                        animationPrefix = "hover";
 
318
                    }
 
319
                }
 
320
            }
 
321
        }
 
322
        QPixmap target = frame->framePixmap();
 
323
        frame->setElementPrefix(animationPrefix);
 
324
        frame->resizeFrame(size());
 
325
        QPixmap result = Plasma::PaintUtils::transition(frame->framePixmap(),
 
326
                                                        target, m_animationProgress);
 
327
        painter->drawPixmap(QRect(QPoint(0, 0), size().toSize()), result);
 
328
    } else {
 
329
        bool animation = false;
 
330
        AuroraeScene *s = static_cast<AuroraeScene*>(scene());
 
331
        if (s->isAnimating()) {
 
332
            animationPrefix = prefix;
 
333
            if (prefix.endsWith(QLatin1String("-inactive"))) {
 
334
                animationPrefix.remove("-inactive");
 
335
            } else {
 
336
                animationPrefix = animationPrefix + "-inactive";
 
337
            }
 
338
            if (frame->hasElementPrefix(animationPrefix)) {
 
339
                animation = true;
 
340
                QPixmap target = frame->framePixmap();
 
341
                frame->setElementPrefix(animationPrefix);
 
342
                frame->resizeFrame(size());
 
343
                QPixmap result = Plasma::PaintUtils::transition(frame->framePixmap(),
 
344
                                                                target, s->animationProgress());
 
345
                painter->drawPixmap(0, 0, result);
 
346
            }
 
347
        }
 
348
        if (!animation) {
 
349
            frame->paintFrame(painter);
 
350
        }
 
351
    }
 
352
}
 
353
 
 
354
bool AuroraeButton::isAnimating() const
 
355
{
 
356
    return (m_animation->state() == QAbstractAnimation::Running);
 
357
}
 
358
 
 
359
qreal AuroraeButton::animationProgress() const
 
360
{
 
361
    return m_animationProgress;
 
362
}
 
363
 
 
364
void AuroraeButton::setAnimationProgress(qreal progress)
 
365
{
 
366
    m_animationProgress = progress;
 
367
    update();
 
368
}
 
369
 
 
370
void AuroraeButton::buttonSizesChanged()
 
371
{
 
372
    updateGeometry();
 
373
    static_cast<AuroraeScene*>(scene())->updateLayout();
 
374
}
 
375
 
 
376
/***********************************************
 
377
* AuroraeMaximizeButton
 
378
***********************************************/
 
379
AuroraeMaximizeButton::AuroraeMaximizeButton(AuroraeTheme* theme)
 
380
    : AuroraeButton(theme, MaximizeButton)
 
381
    , m_maximizeMode(KDecorationDefines::MaximizeRestore)
 
382
{
 
383
    setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton|Qt::MidButton);
 
384
}
 
385
 
 
386
void AuroraeMaximizeButton::mousePressEvent(QGraphicsSceneMouseEvent* event)
 
387
{
 
388
    AuroraeButton::mousePressEvent(event);
 
389
    m_pressedButton = event->button();
 
390
}
 
391
 
 
392
void AuroraeMaximizeButton::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
 
393
{
 
394
    if (isPressed() && m_pressedButton == event->button()) {
 
395
        emit clicked(m_pressedButton);
 
396
    }
 
397
    setPressed(false);
 
398
    update();
 
399
    QGraphicsItem::mouseReleaseEvent(event);
 
400
}
 
401
 
 
402
AuroraeButtonType AuroraeMaximizeButton::currentType() const
 
403
{
 
404
    if (m_maximizeMode == KDecorationDefines::MaximizeFull &&
 
405
        theme()->hasButton(RestoreButton)) {
 
406
        return RestoreButton;
 
407
    } else {
 
408
        return MaximizeButton;
 
409
    }
 
410
}
 
411
 
 
412
void AuroraeMaximizeButton::setMaximizeMode(KDecorationDefines::MaximizeMode mode)
 
413
{
 
414
    m_maximizeMode = mode;
 
415
    update();
 
416
}
 
417
 
 
418
/************************************************
 
419
* AuroraeMenuButton
 
420
************************************************/
 
421
AuroraeMenuButton::AuroraeMenuButton(AuroraeTheme* theme)
 
422
    : AuroraeButton(theme, MenuButton)
 
423
{
 
424
    m_timer = new QTimer(this);
 
425
    m_timer->setSingleShot(true);
 
426
    m_timer->setInterval(QApplication::doubleClickInterval());
 
427
    connect(m_timer, SIGNAL(timeout()), SIGNAL(clicked()));
 
428
}
 
429
 
 
430
void AuroraeMenuButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
 
431
{
 
432
    Q_UNUSED(option)
 
433
    Q_UNUSED(widget)
 
434
    if (m_icon.isNull()) {
 
435
        return;
 
436
    }
 
437
    QPixmap iconPix = m_icon;
 
438
    KIconEffect *effect = KIconLoader::global()->iconEffect();
 
439
    AuroraeScene *s = static_cast<AuroraeScene*>(scene());
 
440
    if (s->isActive()) {
 
441
        if (isHovered()) {
 
442
            iconPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::ActiveState);
 
443
        }
 
444
    } else {
 
445
        iconPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::DisabledState);
 
446
    }
 
447
    if (s->isAnimating()) {
 
448
        // animation
 
449
        QPixmap oldPix = m_icon;
 
450
        if (!s->isActive()) {
 
451
            if (isHovered()) {
 
452
                oldPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::ActiveState);
 
453
            }
 
454
        } else {
 
455
            oldPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::DisabledState);
 
456
        }
 
457
        iconPix = Plasma::PaintUtils::transition(oldPix, iconPix, s->animationProgress());
 
458
    }
 
459
    painter->drawPixmap(0, 0, iconPix);
 
460
}
 
461
 
 
462
void AuroraeMenuButton::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
 
463
{
 
464
    Q_UNUSED(event)
 
465
    emit doubleClicked();
 
466
}
 
467
 
 
468
void AuroraeMenuButton::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
 
469
{
 
470
    Q_UNUSED(event)
 
471
    if (isPressed()) {
 
472
        if (m_timer->isActive()) {
 
473
            m_timer->stop();
 
474
        } else {
 
475
            m_timer->start();
 
476
        }
 
477
    }
 
478
    setPressed(false);
 
479
    update();
 
480
    QGraphicsItem::mouseReleaseEvent(event);
 
481
}
 
482
 
 
483
void AuroraeMenuButton::setIcon(const QPixmap& icon)
 
484
{
 
485
    m_icon = icon;
 
486
    update();
 
487
}
 
488
 
 
489
/************************************************
 
490
* AuroraeSpacer
 
491
************************************************/
 
492
AuroraeSpacer::AuroraeSpacer(AuroraeTheme *theme)
 
493
    : QGraphicsWidget()
 
494
    , m_theme(theme)
 
495
{
 
496
}
 
497
 
 
498
QSizeF AuroraeSpacer::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
 
499
{
 
500
    Q_UNUSED(which)
 
501
    Q_UNUSED(constraint)
 
502
    return QSizeF(m_theme->themeConfig().explicitButtonSpacer(),
 
503
                  m_theme->themeConfig().buttonHeight());
 
504
}
 
505
 
 
506
} // namespace