File indexing completed on 2024-05-19 05:28:49

0001 //////////////////////////////////////////////////////////////////////////////
0002 // breezetransitionwidget.h
0003 // stores event filters and maps widgets to transitions for transitions
0004 //
0005 // SPDX-FileCopyrightText: 2007 Thomas Luebking <thomas.luebking@web.de>
0006 // SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0007 //
0008 // SPDX-License-Identifier: MIT
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #pragma once
0012 
0013 #include "breeze.h"
0014 #include "breezeanimation.h"
0015 
0016 #include <QWidget>
0017 
0018 #include <cmath>
0019 
0020 namespace Breeze
0021 {
0022 //* temporary widget used to perform smooth transition between one widget state and another
0023 class TransitionWidget : public QWidget
0024 {
0025     Q_OBJECT
0026 
0027     //* declare opacity property
0028     Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
0029 
0030 public:
0031     //* shortcut to painter
0032     typedef WeakPointer<TransitionWidget> Pointer;
0033 
0034     //* constructor
0035     TransitionWidget(QWidget *parent, int duration);
0036 
0037     //*@name flags
0038     //@{
0039     enum Flag {
0040         None = 0,
0041         GrabFromWindow = 1 << 0,
0042         Transparent = 1 << 1,
0043         PaintOnWidget = 1 << 2,
0044     };
0045 
0046     Q_DECLARE_FLAGS(Flags, Flag)
0047 
0048     void setFlags(Flags value)
0049     {
0050         _flags = value;
0051     }
0052 
0053     void setFlag(Flag flag, bool value = true)
0054     {
0055         if (value) {
0056             _flags |= flag;
0057         } else {
0058             _flags &= (~flag);
0059         }
0060     }
0061 
0062     bool testFlag(Flag flag) const
0063     {
0064         return _flags.testFlag(flag);
0065     }
0066 
0067     //@}
0068 
0069     //* duration
0070     void setDuration(int duration)
0071     {
0072         if (_animation) {
0073             _animation.data()->setDuration(duration);
0074         }
0075     }
0076 
0077     //* duration
0078     int duration() const
0079     {
0080         return (_animation) ? _animation.data()->duration() : 0;
0081     }
0082 
0083     //* steps
0084     static void setSteps(int value)
0085     {
0086         _steps = value;
0087     }
0088 
0089     //*@name opacity
0090     //@{
0091 
0092     qreal opacity() const
0093     {
0094         return _opacity;
0095     }
0096 
0097     void setOpacity(qreal value)
0098     {
0099         value = digitize(value);
0100         if (_opacity == value) {
0101             return;
0102         }
0103         _opacity = value;
0104         update();
0105     }
0106 
0107     //@}
0108 
0109     //@name pixmaps handling
0110     //@{
0111 
0112     //* start
0113     void resetStartPixmap()
0114     {
0115         setStartPixmap(QPixmap());
0116     }
0117 
0118     //* start
0119     void setStartPixmap(QPixmap pixmap)
0120     {
0121         _startPixmap = pixmap;
0122     }
0123 
0124     //* start
0125     const QPixmap &startPixmap() const
0126     {
0127         return _startPixmap;
0128     }
0129 
0130     //* end
0131     void resetEndPixmap()
0132     {
0133         setEndPixmap(QPixmap());
0134     }
0135 
0136     //* end
0137     void setEndPixmap(QPixmap pixmap)
0138     {
0139         _endPixmap = pixmap;
0140         _currentPixmap = pixmap;
0141     }
0142 
0143     //* start
0144     const QPixmap &endPixmap() const
0145     {
0146         return _endPixmap;
0147     }
0148 
0149     //* current
0150     const QPixmap &currentPixmap() const
0151     {
0152         return _currentPixmap;
0153     }
0154 
0155     //@}
0156 
0157     //* grap pixmap
0158     QPixmap grab(QWidget * = nullptr, QRect = QRect());
0159 
0160     //* true if animated
0161     bool isAnimated() const
0162     {
0163         return _animation.data()->isRunning();
0164     }
0165 
0166     //* end animation
0167     void endAnimation()
0168     {
0169         if (_animation.data()->isRunning()) {
0170             _animation.data()->stop();
0171         }
0172     }
0173 
0174     //* animate transition
0175     void animate()
0176     {
0177         if (_animation.data()->isRunning()) {
0178             _animation.data()->stop();
0179         }
0180         _animation.data()->start();
0181     }
0182 
0183     //* true if paint is enabled
0184     static bool paintEnabled();
0185 
0186 protected:
0187     //* generic event filter
0188     bool event(QEvent *) override;
0189 
0190     //* paint event
0191     void paintEvent(QPaintEvent *) override;
0192 
0193     //* grab widget background
0194     /*!
0195     Background is not rendered properly using QWidget::render.
0196     Use home-made grabber instead. This is directly inspired from bespin.
0197     */
0198     void grabBackground(QPixmap &, QWidget *, QRect &) const;
0199 
0200     //* grab widget
0201     void grabWidget(QPixmap &, QWidget *, QRect &) const;
0202 
0203     //* fade pixmap
0204     void fade(const QPixmap &source, QPixmap &target, qreal opacity, const QRect &) const;
0205 
0206     //* apply step
0207     qreal digitize(const qreal &value) const
0208     {
0209         if (_steps > 0) {
0210             return std::floor(value * _steps) / _steps;
0211         } else {
0212             return value;
0213         }
0214     }
0215 
0216 private:
0217     //* Flags
0218     Flags _flags = None;
0219 
0220     //* paint enabled
0221     static bool _paintEnabled;
0222 
0223     //* internal transition animation
0224     Animation::Pointer _animation;
0225 
0226     //* animation starting pixmap
0227     QPixmap _startPixmap;
0228 
0229     //* animation starting pixmap
0230     QPixmap _localStartPixmap;
0231 
0232     //* animation starting pixmap
0233     QPixmap _endPixmap;
0234 
0235     //* current pixmap
0236     QPixmap _currentPixmap;
0237 
0238     //* current state opacity
0239     qreal _opacity = 0;
0240 
0241     //* steps
0242     static int _steps;
0243 };
0244 
0245 }