Salome HOME
Fixing a bug : Salome GUI style needs addLibraryPath() method to be called
[modules/gui.git] / src / Event / SALOME_Event.hxx
1 //  KERNEL SALOME_Event : Define event posting mechanism
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SALOME_Event.hxx
25 //  Author : Sergey ANIKIN
26 //  Module : KERNEL
27 //  $Header$
28
29
30 #ifndef SALOME_Event_HeaderFile
31 #define SALOME_Event_HeaderFile
32
33 #include <qevent.h>
34
35 #define SALOME_EVENT QEvent::Type( QEvent::User + 10000 )
36
37 class QSemaphore;
38
39 //===========================================================
40 /*!
41  *  Class: SALOME_Event
42  *  Description: 
43  *  This class encapsulates data and functionality required for 
44  *  posting component-specific events to perform arbitrary operations in main GUI thread. 
45  *  SALOME_Event objects can be posted by any thread belonging to the GUI process.
46  *
47  *  It is necessary to derive a custom event class from SALOME_Event and 
48  *  re-implement virtual Execute() method. This method should actually perform 
49  *  the desirable operation. To pass all the required data to Execute() and store a return value,
50  *  arbitrary data fields can be added to the custom event class. There is 
51  *  no need to protect such fields with a mutex, for only one thread working with
52  *  a SALOME_Event object is active at any moment.
53  *
54  *  Usage:
55  *  - create SALOME_Event. 
56  *    Components can derive their own event class from SALOME_Event
57  *    in order to pass custom data to the event handler.
58  *  - call process() method to post the event. After process() execution
59  *    it is possible to examine fields of your custom event object.
60  *  - perform delete operator on the event to wake up the desktop (you can also set <autoRelease>
61  *    parameter to TRUE to automatically wake up desktop after process()
62  * 
63  *  processed() method is used by the desktop to signal that event processing 
64  *  has been completed.
65  *  
66  *  Caveats: 
67  *    There is no.
68  */
69 //===========================================================
70
71 #include <Event.h>
72
73 class EVENT_EXPORT SALOME_Event{
74 public:
75   SALOME_Event();
76   virtual ~SALOME_Event();
77
78   // To do real work
79   virtual void Execute() = 0;
80
81   static bool IsSessionThread();
82   void process();
83
84 protected:
85   void processed();
86   friend class SalomeApp_EventFilter;
87
88   static void GetSessionThread();
89   friend int main(int, char **);
90
91 private:
92   QSemaphore* mySemaphore;
93 };
94
95
96 // Template classes for member function
97 //-------------------------------------
98 template<class TObject, typename TRes>
99 class EVENT_EXPORT TMemFunEvent: public SALOME_Event{
100 public:
101   typedef TRes TResult;
102   TResult myResult;
103   typedef TResult (TObject::* TAction)();
104   TMemFunEvent(TObject* theObject, TAction theAction, 
105                TResult theResult = TResult()):
106     myObject(theObject),
107     myAction(theAction),
108     myResult(theResult)
109   {}
110   virtual void Execute(){
111     myResult = (myObject->*myAction)();
112   }
113 private:
114   TObject* myObject;
115   TAction myAction;
116 };
117
118
119 template<class TObject>
120 class EVENT_EXPORT TVoidMemFunEvent: public SALOME_Event{
121 public:
122   typedef void (TObject::* TAction)();
123   TVoidMemFunEvent(TObject* theObject, TAction theAction):
124     myObject(theObject),
125     myAction(theAction)
126   {}
127   virtual void Execute(){
128     (myObject->*myAction)();
129   }
130 private:
131   TObject* myObject;
132   TAction myAction;
133 };
134
135
136 // Template for member function with one argument
137 //-----------------------------------------------
138 template<class TObject, typename TRes, 
139          typename TArg, typename TStoreArg = TArg>
140 class EVENT_EXPORT TMemFun1ArgEvent: public SALOME_Event{
141 public:
142   typedef TRes TResult;
143   TResult myResult;
144   typedef TResult (TObject::* TAction)(TArg);
145   TMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg, 
146                    TResult theResult = TResult()):
147     myObject(theObject),
148     myAction(theAction),
149     myResult(theResult),
150     myArg(theArg)
151   {}
152   virtual void Execute(){
153     myResult = (myObject->*myAction)(myArg);
154   }
155 private:
156   TObject* myObject;
157   TAction myAction;
158   TStoreArg myArg;
159 };
160
161
162 template<class TObject, typename TArg, typename TStoreArg = TArg>
163 class EVENT_EXPORT TVoidMemFun1ArgEvent: public SALOME_Event{
164 public:
165   typedef void (TObject::* TAction)(TArg);
166   TVoidMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg):
167     myObject(theObject),
168     myAction(theAction),
169     myArg(theArg)
170   {}
171   virtual void Execute(){
172     (myObject->*myAction)(myArg);
173   }
174 private:
175   TObject* myObject;
176   TAction myAction;
177   TStoreArg myArg;
178 };
179
180
181 // Template for member function with one argument
182 //-----------------------------------------------
183 template<class TObject, typename TRes,
184          typename TArg, typename TArg1, 
185          typename TStoreArg = TArg, typename TStoreArg1 = TArg1>
186 class EVENT_EXPORT TMemFun2ArgEvent: public SALOME_Event{
187 public:
188   typedef TRes TResult;
189   TResult myResult;
190   typedef TResult (TObject::* TAction)(TArg,TArg1);
191   TMemFun2ArgEvent(TObject* theObject, TAction theAction, 
192                    TArg theArg, TArg1 theArg1,
193                    TResult theResult = TResult()):
194     myObject(theObject),
195     myAction(theAction),
196     myResult(theResult),
197     myArg(theArg),
198     myArg1(theArg1)
199   {}
200   virtual void Execute(){
201     myResult = (myObject->*myAction)(myArg,myArg1);
202   }
203 private:
204   TObject* myObject;
205   TAction myAction;
206   TStoreArg myArg;
207   TStoreArg1 myArg1;
208 };
209
210
211 template<class TObject, typename TArg, typename TArg1, 
212          typename TStoreArg = TArg, typename TStoreArg1 = TArg1>
213 class EVENT_EXPORT TVoidMemFun2ArgEvent: public SALOME_Event{
214 public:
215   typedef void (TObject::* TAction)(TArg,TArg1);
216   TVoidMemFun2ArgEvent(TObject* theObject, TAction theAction, TArg theArg, TArg1 theArg1):
217     myObject(theObject),
218     myAction(theAction),
219     myArg(theArg),
220     myArg1(theArg1)
221   {}
222   virtual void Execute(){
223     (myObject->*myAction)(myArg,myArg1);
224   }
225 private:
226   TObject* myObject;
227   TAction myAction;
228   TStoreArg myArg;
229   TStoreArg1 myArg1;
230 };
231
232
233 // Template function for processing events with result returing
234 template<class TEvent> inline typename TEvent::TResult ProcessEvent(TEvent* theEvent){
235   typename TEvent::TResult aResult;
236   if(SALOME_Event::IsSessionThread()){
237     theEvent->Execute();
238     aResult = theEvent->myResult;
239   }else{
240     theEvent->process();
241     aResult = theEvent->myResult;
242   }
243   delete theEvent;
244   return aResult;
245 }
246
247
248 // Template function for processing events without result
249 inline void ProcessVoidEvent(SALOME_Event* theEvent){
250   if(SALOME_Event::IsSessionThread()){
251     theEvent->Execute();
252   }else{
253     theEvent->process();
254   }
255   delete theEvent;
256 }
257
258
259 #endif