1 #ifndef oxygenmenubardata_imp_h
2 #define oxygenmenubardata_imp_h
3 
4 //////////////////////////////////////////////////////////////////////////////
5 // oxygenmenubardata_imp.h
6 // implements menubar data templatized methods
7 // -------------------
8 //
9 // SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
10 //
11 // SPDX-License-Identifier: MIT
12 //////////////////////////////////////////////////////////////////////////////
13 
14 namespace Oxygen
15 {
16 
17     //________________________________________________________________________
enterEvent(const QObject * object)18     template< typename T > void MenuBarDataV1::enterEvent( const QObject* object )
19     {
20 
21         const T* local = qobject_cast<const T*>( object );
22         if( !local ) return;
23 
24         // if the current action is still active, one does nothing
25         if( local->activeAction() == currentAction().data() ) return;
26 
27         if( currentAnimation().data()->isRunning() ) currentAnimation().data()->stop();
28         clearCurrentAction();
29         clearCurrentRect();
30 
31     }
32 
33     //________________________________________________________________________
leaveEvent(const QObject * object)34     template< typename T > void MenuBarDataV1::leaveEvent( const QObject* object )
35     {
36 
37         const T* local = qobject_cast<const T*>( object );
38         if( !local ) return;
39 
40         // if the current action is still active, one does nothing
41         if( local->activeAction() == currentAction().data() ) return;
42 
43         if( currentAnimation().data()->isRunning() ) currentAnimation().data()->stop();
44         if( previousAnimation().data()->isRunning() ) previousAnimation().data()->stop();
45         if( currentAction() )
46         {
47             setPreviousRect( currentRect() );
48             clearCurrentAction();
49             clearCurrentRect();
50             previousAnimation().data()->start();
51         }
52 
53         // trigger update
54         setDirty();
55 
56     }
57 
58     //________________________________________________________________________
mouseMoveEvent(const QObject * object)59     template< typename T > void MenuBarDataV1::mouseMoveEvent( const QObject* object )
60     {
61 
62         const T* local = qobject_cast<const T*>( object );
63         if( !local ) return;
64 
65         // check action
66         if( local->activeAction() == currentAction().data() ) return;
67 
68         bool hasCurrentAction( currentAction() );
69 
70         // check current action
71         if( currentAction() )
72         {
73             if( currentAnimation().data()->isRunning() ) currentAnimation().data()->stop();
74             if( previousAnimation().data()->isRunning() ) {
75                 previousAnimation().data()->setCurrentTime(0);
76                 previousAnimation().data()->stop();
77             }
78 
79             // only start fadeout effect if there is no new selected action
80             //if( !activeActionValid )
81             if( !local->activeAction() )
82             {
83                 setPreviousRect( currentRect() );
84                 previousAnimation().data()->start();
85             }
86 
87             clearCurrentAction();
88             clearCurrentRect();
89 
90         }
91 
92         // check if local current actions is valid
93         bool activeActionValid( local->activeAction() && local->activeAction()->isEnabled() && !local->activeAction()->isSeparator() );
94         if( activeActionValid )
95         {
96             if( currentAnimation().data()->isRunning() ) currentAnimation().data()->stop();
97 
98             setCurrentAction( local->activeAction() );
99             setCurrentRect( local->actionGeometry( currentAction().data() ) );
100             if( !hasCurrentAction )
101             { currentAnimation().data()->start(); }
102 
103         }
104 
105     }
106 
107     //________________________________________________________________________
mousePressEvent(const QObject * object)108     template< typename T > void MenuBarDataV1::mousePressEvent( const QObject* object )
109     {
110 
111         const T* local = qobject_cast<const T*>( object );
112         if( !local ) return;
113 
114         // check action
115         if( local->activeAction() == currentAction().data() ) return;
116 
117         // check current action
118         bool activeActionValid( local->activeAction() && local->activeAction()->isEnabled() && !local->activeAction()->isSeparator() );
119         if( currentAction() && !activeActionValid )
120         {
121 
122             if( currentAnimation().data()->isRunning() ) currentAnimation().data()->stop();
123             if( previousAnimation().data()->isRunning() ) previousAnimation().data()->stop();
124 
125             setPreviousRect( currentRect() );
126             previousAnimation().data()->start();
127 
128             clearCurrentAction();
129             clearCurrentRect();
130 
131         }
132 
133     }
134 
135     //________________________________________________________________________
enterEvent(const QObject * object)136     template< typename T > void MenuBarDataV2::enterEvent( const QObject* object )
137     {
138 
139         // cast widget
140         const T* local = qobject_cast<const T*>( object );
141         if( !local ) return;
142 
143         if( _timer.isActive() ) _timer.stop();
144 
145         // if the current action is still active, one does nothing
146         if( currentAction() && local->activeAction() == currentAction().data() ) return;
147 
148         if( animation().data()->isRunning() ) animation().data()->stop();
149         if( progressAnimation().data()->isRunning() ) progressAnimation().data()->stop();
150         clearPreviousRect();
151         clearAnimatedRect();
152 
153         if( local->activeAction() &&  local->activeAction()->isEnabled() && !local->activeAction()->isSeparator() )
154         {
155             setCurrentAction( local->activeAction() );
156             setCurrentRect( local->actionGeometry( currentAction().data() ) );
157             animation().data()->setDirection( Animation::Forward );
158             animation().data()->start();
159 
160         } else {
161 
162             clearCurrentAction();
163             clearCurrentRect();
164 
165         }
166 
167         return;
168     }
169 
170     //________________________________________________________________________
leaveEvent(const QObject * object)171     template< typename T > void MenuBarDataV2::leaveEvent( const QObject* object )
172     {
173 
174         const T* local = qobject_cast<const T*>( object );
175         if( !local ) return;
176 
177         // if the current action is still active, one does nothing
178         if( local->activeAction() && local->activeAction() == currentAction().data() )
179         { return; }
180 
181         if( progressAnimation().data()->isRunning() ) progressAnimation().data()->stop();
182         if( animation().data()->isRunning() ) animation().data()->stop();
183         clearAnimatedRect();
184         clearPreviousRect();
185         if( currentAction() )
186         {
187             clearCurrentAction();
188             animation().data()->setDirection( Animation::Backward );
189             animation().data()->start();
190         }
191 
192         // trigger update
193         setDirty();
194 
195         return;
196 
197     }
198 
199     //________________________________________________________________________
mouseMoveEvent(const QObject * object)200     template< typename T > void MenuBarDataV2::mouseMoveEvent( const QObject* object )
201     {
202         const T* local = qobject_cast<const T*>( object );
203         if( !local ) return;
204         if( local->activeAction() == currentAction().data() ) return;
205 
206         // check if current position match another action
207         if( local->activeAction() && local->activeAction()->isEnabled() && !local->activeAction()->isSeparator())
208         {
209 
210             if( _timer.isActive() ) _timer.stop();
211 
212             QAction* activeAction( local->activeAction() );
213 
214             // update previous rect if the current action is valid
215             QRect activeRect( local->actionGeometry( activeAction ) );
216             if( currentAction() )
217             {
218                 if( !progressAnimation().data()->isRunning() )
219                 {
220 
221                     setPreviousRect( currentRect() );
222 
223                 } else if( progress() < 1 && currentRect().isValid() && previousRect().isValid() ) {
224 
225                     // re-calculate previous rect so that animatedRect
226                     // is unchanged after currentRect is updated
227                     // this prevents from having jumps in the animation
228                     qreal ratio = progress()/(1.0-progress());
229                     _previousRect.adjust(
230                         ratio*( currentRect().left() - activeRect.left() ),
231                         ratio*( currentRect().top() - activeRect.top() ),
232                         ratio*( currentRect().right() - activeRect.right() ),
233                         ratio*( currentRect().bottom() - activeRect.bottom() ) );
234 
235                 }
236 
237                 // update current action
238                 setCurrentAction( activeAction );
239                 setCurrentRect( activeRect );
240                 if( animation().data()->isRunning() ) animation().data()->stop();
241                 if( !progressAnimation().data()->isRunning() ) progressAnimation().data()->start();
242 
243             } else {
244 
245                 // update current action
246                 setCurrentAction( activeAction );
247                 setCurrentRect( activeRect );
248                 if( !_entered )
249                 {
250 
251                     _entered = true;
252                     if( animation().data()->isRunning() ) animation().data()->stop();
253                     if( !progressAnimation().data()->isRunning() ) progressAnimation().data()->start();
254 
255                 } else {
256 
257                     setPreviousRect( activeRect );
258                     clearAnimatedRect();
259                     if( progressAnimation().data()->isRunning() ) progressAnimation().data()->stop();
260                     animation().data()->setDirection( Animation::Forward );
261                     if( !animation().data()->isRunning() ) animation().data()->start();
262                 }
263 
264             }
265 
266         } else if( currentAction() ) {
267 
268             _timer.start( 150, this );
269 
270         }
271 
272         return;
273 
274     }
275 
276 }
277 
278 #endif
279