File indexing completed on 2024-05-19 05:35:26

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