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

« back to all changes in this revision

Viewing changes to kstyles/oxygen/animations/oxygentoolbardata.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
// oxygentoolbardata.cpp
 
3
// stores event filters and maps widgets to timelines for animations
 
4
// -------------------
 
5
//
 
6
// Copyright (c) 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
 
7
//
 
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
9
// of this software and associated documentation files (the "Software"), to
 
10
// deal in the Software without restriction, including without limitation the
 
11
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 
12
// sell copies of the Software, and to permit persons to whom the Software is
 
13
// furnished to do so, subject to the following conditions:
 
14
//
 
15
// The above copyright notice and this permission notice shall be included in
 
16
// all copies or substantial portions of the Software.
 
17
//
 
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
23
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 
24
// IN THE SOFTWARE.
 
25
//////////////////////////////////////////////////////////////////////////////
 
26
 
 
27
#include "oxygentoolbardata.h"
 
28
#include "oxygentoolbardata.moc"
 
29
 
 
30
#include <QtGui/QToolButton>
 
31
 
 
32
namespace Oxygen
 
33
{
 
34
 
 
35
    //________________________________________________________________________
 
36
    ToolBarData::ToolBarData( QObject* parent, QWidget* target, int duration ):
 
37
        AnimationData( parent, target ),
 
38
        _opacity( 0 ),
 
39
        _progress( 0 ),
 
40
        _currentObject( 0 ),
 
41
        _entered( false )
 
42
    {
 
43
 
 
44
        target->installEventFilter( this );
 
45
 
 
46
        _animation = new Animation( duration, this );
 
47
        animation().data()->setDirection( Animation::Forward );
 
48
        animation().data()->setStartValue( 0.0 );
 
49
        animation().data()->setEndValue( 1.0 );
 
50
        animation().data()->setTargetObject( this );
 
51
        animation().data()->setPropertyName( "opacity" );
 
52
 
 
53
        // progress animation
 
54
        _progressAnimation = new Animation( duration, this );
 
55
        progressAnimation().data()->setDirection( Animation::Forward );
 
56
        progressAnimation().data()->setStartValue( 0 );
 
57
        progressAnimation().data()->setEndValue( 1 );
 
58
        progressAnimation().data()->setTargetObject( this );
 
59
        progressAnimation().data()->setPropertyName( "progress" );
 
60
        progressAnimation().data()->setEasingCurve( QEasingCurve::Linear );
 
61
 
 
62
        // add all children widgets to event handler
 
63
        foreach( QObject* child, target->children() )
 
64
        { if( qobject_cast<QToolButton*>( child ) ) childAddedEvent( child ); }
 
65
 
 
66
    }
 
67
 
 
68
    //______________________________________________
 
69
    bool ToolBarData::eventFilter( QObject* object, QEvent* event )
 
70
    {
 
71
 
 
72
        // check object
 
73
        const QObject *targetData = target().data();
 
74
        if( object ==  targetData )
 
75
        {
 
76
 
 
77
            switch( event->type() )
 
78
            {
 
79
 
 
80
                case QEvent::Enter:
 
81
                {
 
82
                    if( enabled() )
 
83
                    {
 
84
                        object->event( event );
 
85
                        enterEvent( object );
 
86
                        return true;
 
87
                    } else return false;
 
88
                }
 
89
 
 
90
                case QEvent::ChildAdded:
 
91
                {
 
92
 
 
93
                    // add children even in disabled case, to make sure they
 
94
                    // are properly registered when engine is enabled
 
95
                    QChildEvent* childEvent( static_cast<QChildEvent*>( event ) );
 
96
                    childAddedEvent( childEvent->child() );
 
97
                    break;
 
98
                }
 
99
 
 
100
                default: break;
 
101
 
 
102
            }
 
103
 
 
104
        } else if( object->parent() == targetData ) {
 
105
 
 
106
            if( !enabled() ) return false;
 
107
 
 
108
            switch( event->type() )
 
109
            {
 
110
 
 
111
                case QEvent::HoverEnter:
 
112
                childEnterEvent( object );
 
113
                break;
 
114
 
 
115
                case QEvent::HoverLeave:
 
116
                if( currentObject() && !_timer.isActive() ) _timer.start( 100, this );
 
117
                break;
 
118
 
 
119
                default:
 
120
                break;
 
121
 
 
122
            }
 
123
 
 
124
        }
 
125
 
 
126
        return false;
 
127
 
 
128
    }
 
129
 
 
130
    //____________________________________________________________
 
131
    void ToolBarData::updateAnimatedRect( void )
 
132
    {
 
133
 
 
134
        // check rect validity
 
135
        if( currentRect().isNull() || previousRect().isNull() )
 
136
        {
 
137
            _animatedRect = QRect();
 
138
            return;
 
139
        }
 
140
 
 
141
        // compute rect located 'between' previous and current
 
142
        _animatedRect.setLeft( previousRect().left() + progress()*(currentRect().left() - previousRect().left()) );
 
143
        _animatedRect.setRight( previousRect().right() + progress()*(currentRect().right() - previousRect().right()) );
 
144
        _animatedRect.setTop( previousRect().top() + progress()*(currentRect().top() - previousRect().top()) );
 
145
        _animatedRect.setBottom( previousRect().bottom() + progress()*(currentRect().bottom() - previousRect().bottom()) );
 
146
 
 
147
        // trigger update
 
148
        setDirty();
 
149
        return;
 
150
 
 
151
    }
 
152
 
 
153
    //________________________________________________________________________
 
154
    void ToolBarData::enterEvent( const QObject* )
 
155
    {
 
156
 
 
157
        if( _timer.isActive() ) _timer.stop();
 
158
        if( animation().data()->isRunning() ) animation().data()->stop();
 
159
        if( progressAnimation().data()->isRunning() ) progressAnimation().data()->stop();
 
160
        clearPreviousRect();
 
161
        clearAnimatedRect();
 
162
 
 
163
        return;
 
164
 
 
165
    }
 
166
 
 
167
 
 
168
    //________________________________________________________________________
 
169
    void ToolBarData::leaveEvent( const QObject* )
 
170
    {
 
171
 
 
172
        if( progressAnimation().data()->isRunning() ) progressAnimation().data()->stop();
 
173
        if( animation().data()->isRunning() ) animation().data()->stop();
 
174
        clearAnimatedRect();
 
175
        clearPreviousRect();
 
176
 
 
177
        if( currentObject() )
 
178
        {
 
179
 
 
180
            clearCurrentObject();
 
181
            animation().data()->setDirection( Animation::Backward );
 
182
            animation().data()->start();
 
183
 
 
184
        }
 
185
 
 
186
        return;
 
187
 
 
188
    }
 
189
 
 
190
    //________________________________________________________________________
 
191
    void ToolBarData::childEnterEvent( const QObject* object )
 
192
    {
 
193
 
 
194
        if( object == currentObject() ) return;
 
195
 
 
196
        const QToolButton* local = qobject_cast<const QToolButton*>( object );
 
197
 
 
198
        // check if current position match another action
 
199
        if( local && local->isEnabled() )
 
200
        {
 
201
 
 
202
            if( _timer.isActive() ) _timer.stop();
 
203
 
 
204
            // get rect
 
205
            QRect activeRect( local->rect().translated( local->mapToParent( QPoint(0,0) ) ) );
 
206
 
 
207
            // update previous rect if the current action is valid
 
208
            if( currentObject() )
 
209
            {
 
210
 
 
211
                if( !progressAnimation().data()->isRunning() )
 
212
                {
 
213
 
 
214
                    setPreviousRect( currentRect() );
 
215
 
 
216
                } else if( progress() < 1 && currentRect().isValid() && previousRect().isValid() ) {
 
217
 
 
218
                    // re-calculate previous rect so that animatedRect
 
219
                    // is unchanged after currentRect is updated
 
220
                    // this prevents from having jumps in the animation
 
221
                    qreal ratio = progress()/(1.0-progress());
 
222
                    _previousRect.adjust(
 
223
                        ratio*( currentRect().left() - activeRect.left() ),
 
224
                        ratio*( currentRect().top() - activeRect.top() ),
 
225
                        ratio*( currentRect().right() - activeRect.right() ),
 
226
                        ratio*( currentRect().bottom() - activeRect.bottom() ) );
 
227
 
 
228
                }
 
229
 
 
230
                // update current action
 
231
                setCurrentObject( local );
 
232
                setCurrentRect( activeRect );
 
233
                if( animation().data()->isRunning() ) animation().data()->stop();
 
234
                if( !progressAnimation().data()->isRunning() ) progressAnimation().data()->start();
 
235
 
 
236
            } else {
 
237
 
 
238
                setCurrentObject( local );
 
239
                setCurrentRect( activeRect );
 
240
                if( !_entered )
 
241
                {
 
242
 
 
243
                    _entered = true;
 
244
                    if( animation().data()->isRunning() ) animation().data()->stop();
 
245
                    if( !progressAnimation().data()->isRunning() ) progressAnimation().data()->start();
 
246
 
 
247
                } else {
 
248
 
 
249
                    setPreviousRect( activeRect );
 
250
                    clearAnimatedRect();
 
251
                    if( progressAnimation().data()->isRunning() ) progressAnimation().data()->stop();
 
252
                    animation().data()->setDirection( Animation::Forward );
 
253
                    if( !animation().data()->isRunning() ) animation().data()->start();
 
254
                }
 
255
 
 
256
            }
 
257
 
 
258
        } else if( currentObject() ) {
 
259
 
 
260
            if( !_timer.isActive() ) _timer.start( 100, this );
 
261
 
 
262
        }
 
263
 
 
264
        return;
 
265
 
 
266
    }
 
267
 
 
268
    //___________________________________________________________________
 
269
    void ToolBarData::childAddedEvent( QObject* object )
 
270
    {
 
271
        QWidget* widget( qobject_cast<QWidget*>( object ) );
 
272
        if( !widget ) return;
 
273
 
 
274
        // add connections
 
275
        connect( animation().data(), SIGNAL( valueChanged( const QVariant& ) ), widget, SLOT( update() ), Qt::UniqueConnection  );
 
276
        connect( progressAnimation().data(), SIGNAL( valueChanged( const QVariant& ) ), widget, SLOT( update() ), Qt::UniqueConnection  );
 
277
 
 
278
        // add event filter
 
279
        widget->removeEventFilter( this );
 
280
        widget->installEventFilter( this );
 
281
    }
 
282
 
 
283
    //___________________________________________________________
 
284
    void ToolBarData::timerEvent( QTimerEvent *event )
 
285
    {
 
286
 
 
287
        if( event->timerId() != _timer.timerId() ) return AnimationData::timerEvent( event );
 
288
        _timer.stop();
 
289
        leaveEvent( target().data() );
 
290
    }
 
291
 
 
292
}