Salome HOME
34b87d99a97e4603d1f51e05ce7e9634158eb341
[modules/shaper.git] / src / XGUI / XGUI_WorkshopListener.cpp
1 // Copyright (C) 2014-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "XGUI_WorkshopListener.h"
21
22 #ifndef HAVE_SALOME
23 #include <AppElements_MainWindow.h>
24 #endif
25
26 #include <Config_FeatureMessage.h>
27 #include <Config_PointerMessage.h>
28 #include <Config_Keywords.h>
29
30 #include <Events_InfoMessage.h>
31 #include <Events_Loop.h>
32 #include <Events_LongOp.h>
33
34 #include <ModelAPI_Object.h>
35 #include <ModelAPI_Events.h>
36 #include <ModelAPI_Session.h>
37 #include <ModelAPI_Result.h>
38 #include <ModelAPI_Feature.h>
39 #include <ModelAPI_Data.h>
40 #include <ModelAPI_Tools.h>
41 #include <ModelAPI_ResultField.h>
42
43 #include <ModuleBase_Events.h>
44 #include <ModuleBase_IModule.h>
45 #include <ModuleBase_IViewer.h>
46 #include <ModuleBase_IWorkshop.h>
47 #include <ModuleBase_Operation.h>
48 #include <ModuleBase_OperationDescription.h>
49 #include <ModuleBase_OperationFeature.h>
50 #include <ModuleBase_Tools.h>
51 #include <ModuleBase_WidgetSelector.h>
52
53 #ifdef HAVE_SALOME
54 #include <SUIT_Application.h>
55 #include <SUIT_Session.h>
56 #endif
57
58 #include "XGUI_ActionsMgr.h"
59 #include "XGUI_Displayer.h"
60 #include "XGUI_ErrorMgr.h"
61 #include "XGUI_FacesPanel.h"
62 #include "XGUI_OperationMgr.h"
63 #include "XGUI_ModuleConnector.h"
64 #include "XGUI_PropertyPanel.h"
65 #include "XGUI_QtEvents.h"
66 #include "XGUI_SalomeConnector.h"
67 #include "XGUI_SelectionMgr.h"
68 #include "XGUI_Workshop.h"
69
70 #include <QAction>
71 #include <QApplication>
72 #include <QMainWindow>
73 #include <QThread>
74
75 #ifdef _DEBUG
76 #include <QDebug>
77 #include <iostream>
78 #endif
79
80 //#define DEBUG_FEATURE_CREATED
81 //#define DEBUG_FEATURE_REDISPLAY
82 //#define DEBUG_FEATURE_UPDATED
83 //#define DEBUG_RESULT_COMPSOLID
84
85 #ifdef DEBUG_FEATURE_REDISPLAY
86 const std::string DebugFeatureKind = "";//"Extrusion";
87 #endif
88
89 XGUI_WorkshopListener::XGUI_WorkshopListener(XGUI_Workshop* theWorkshop)
90   : myWorkshop(theWorkshop),
91     myUpdatePrefs(false)
92 {
93 }
94
95 //******************************************************
96 XGUI_WorkshopListener::~XGUI_WorkshopListener(void)
97 {
98 }
99
100 //******************************************************
101 void XGUI_WorkshopListener::initializeEventListening()
102 {
103   //Initialize event listening
104   Events_Loop* aLoop = Events_Loop::loop();
105   aLoop->registerListener(this, Events_InfoMessage::errorID());  //!< Listening application errors.
106   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
107   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
108   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
109   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES));
110   aLoop->registerListener(this, Events_LongOp::eventID());
111   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED));
112
113   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED));
114   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED));
115   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
116   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION));
117
118   aLoop->registerListener(this, Events_Loop::eventByName("FinishOperation"));
119   aLoop->registerListener(this, Events_Loop::eventByName("AbortOperation"));
120   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_AUTOMATIC_RECOMPUTATION_ENABLE));
121   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_AUTOMATIC_RECOMPUTATION_DISABLE));
122 }
123
124 //******************************************************
125 void XGUI_WorkshopListener::processEvent(const std::shared_ptr<Events_Message>& theMessage)
126 {
127   if (QApplication::instance() &&
128       QApplication::instance()->thread() != QThread::currentThread()) {
129     #ifdef _DEBUG
130     std::cout << "XGUI_Workshop::processEvent: " << "Working in another thread." << std::endl;
131     #endif
132     SessionPtr aMgr = ModelAPI_Session::get();
133     PostponeMessageQtEvent* aPostponeEvent = new PostponeMessageQtEvent(theMessage);
134     QApplication::postEvent(this, aPostponeEvent);
135     return;
136   }
137
138   // Process creation of Part
139   if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
140     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
141         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
142     onFeatureCreatedMsg(aUpdMsg);
143     if (myUpdatePrefs) {
144       XGUI_SalomeConnector* aSalomeConnector = workshop()->salomeConnector();
145       if (aSalomeConnector)
146         aSalomeConnector->createPreferences();
147       myUpdatePrefs = false;
148     }
149   }
150   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_PLUGIN_LOADED)) {
151     myUpdatePrefs = true;
152   }
153   // Redisplay feature
154   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) {
155     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
156       std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
157     onFeatureRedisplayMsg(aUpdMsg);
158   }
159   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_VISUAL_ATTRIBUTES)) {
160     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
161       std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
162     std::set<ObjectPtr> aObjList = aUpdMsg->objects();
163     std::set<ObjectPtr>::const_iterator aIt;
164     std::list<ResultPtr>::const_iterator aResIt;
165     XGUI_Displayer* aDisplayer = workshop()->displayer();
166     AISObjectPtr aAIS;
167     for (aIt = aObjList.begin(); aIt != aObjList.end(); ++aIt) {
168       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*aIt);
169       if (aFeature) {
170         aAIS = aDisplayer->getAISObject(aFeature);
171         if (aAIS.get())
172           workshop()->module()->customizePresentation(aFeature, aAIS);
173
174         std::list<ResultPtr> aResults = aFeature->results();
175         for (aResIt = aResults.begin(); aResIt != aResults.end(); ++aResIt) {
176           aAIS = aDisplayer->getAISObject(*aResIt);
177           if (aAIS.get())
178             workshop()->module()->customizePresentation(*aResIt, aAIS);
179         }
180       }
181     }
182   } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION)) {
183     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
184         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
185     onFeatureEmptyPresentationMsg(aUpdMsg);
186   } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION)) {
187     ModuleBase_ModelWidget* aWidget = workshop()->propertyPanel()->activeWidget();
188     if (aWidget) {
189       ModuleBase_WidgetSelector* aWidgetSelector =
190         dynamic_cast<ModuleBase_WidgetSelector*>(aWidget);
191       if (aWidgetSelector)
192         workshop()->selector()->setSelected(aWidgetSelector->getAttributeSelection());
193     }
194   } else if (theMessage->eventID() == Events_Loop::eventByName("FinishOperation")/* ||
195              theMessage->eventID() == Events_Loop::eventByName("AbortOperation")*/)
196     workshop()->facesPanel()->reset(false); // do not flush redisplay, it is flushed after event
197
198   //Update property panel on corresponding message. If there is no current operation (no
199   //property panel), or received message has different feature to the current - do nothing.
200   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
201     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
202         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
203     onFeatureUpdatedMsg(anUpdateMsg);
204   } else if (theMessage->eventID() == Events_LongOp::eventID()) {
205     if (Events_LongOp::isPerformed()) {
206       QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
207     } else {
208       QApplication::restoreOverrideCursor();
209     }
210   } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)) {
211     // the viewer's update context will not happens until viewer updated is emitted
212       workshop()->displayer()->enableUpdateViewer(false);
213   } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)) {
214     // the viewer's update context is unblocked, the viewer's update works
215     XGUI_Displayer* aDisplayer = workshop()->displayer();
216     aDisplayer->enableUpdateViewer(true);
217   } else if ((theMessage->eventID() ==
218     Events_Loop::eventByName(EVENT_AUTOMATIC_RECOMPUTATION_ENABLE)) ||
219     (theMessage->eventID() ==
220       Events_Loop::eventByName(EVENT_AUTOMATIC_RECOMPUTATION_DISABLE))) {
221     myWorkshop->updateAutoComputeState();
222   } else {
223     //Show error dialog if error message received.
224     std::shared_ptr<Events_InfoMessage> anIngfoMsg =
225       std::dynamic_pointer_cast<Events_InfoMessage>(theMessage);
226     if (anIngfoMsg) {
227       emit errorOccurred(anIngfoMsg);
228     }
229     return;
230   }
231 #ifndef HAVE_SALOME
232     SessionPtr aMgr = ModelAPI_Session::get();
233     AppElements_MainWindow* aMainWindow = workshop()->mainWindow();
234     if (aMgr->isModified() != aMainWindow->isModifiedState())
235       aMainWindow->setModifiedState(aMgr->isModified());
236 #endif
237 }
238
239 //******************************************************
240 void XGUI_WorkshopListener::onFeatureUpdatedMsg(
241                                      const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
242 {
243 #ifdef DEBUG_FEATURE_UPDATED
244   std::set<ObjectPtr> anObjects = theMsg->objects();
245   std::set<ObjectPtr>::const_iterator aIt;
246   QStringList anInfo;
247   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
248     anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
249   }
250   QString anInfoStr = anInfo.join(";\t");
251   qDebug(QString("onFeatureUpdatedMsg: %1, %2")
252     .arg(anObjects.size()).arg(anInfoStr).toStdString().c_str());
253 #endif
254   std::set<ObjectPtr> aFeatures = theMsg->objects();
255   XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr();
256   if (anOperationMgr->hasOperation()) {
257     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
258                                                       (anOperationMgr->currentOperation());
259     if (aFOperation) {
260       FeaturePtr aCurrentFeature = aFOperation->feature();
261       std::set<ObjectPtr>::const_iterator aIt;
262       for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) {
263         ObjectPtr aNewFeature = (*aIt);
264         if (aNewFeature == aCurrentFeature) {
265           workshop()->propertyPanel()->updateContentWidget(aCurrentFeature);
266           break;
267         }
268       }
269     }
270   }
271   //anOperationMgr->onValidateOperation();
272
273   //if (myObjectBrowser)
274   //  myObjectBrowser->processEvent(theMsg);
275 }
276
277 //******************************************************
278 void XGUI_WorkshopListener::
279   onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
280 {
281   std::set<ObjectPtr> anObjects = theMsg->objects();
282   std::set<ObjectPtr>::const_iterator aIt;
283
284 #ifdef DEBUG_FEATURE_REDISPLAY
285   QStringList anInfo;
286   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
287     anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
288   }
289   QString anInfoStr = anInfo.join(";\t");
290   qDebug(QString("onFeatureRedisplayMsg: %1, %2")
291     .arg(anObjects.size()).arg(anInfoStr).toStdString().c_str());
292 #endif
293
294   XGUI_Workshop* aWorkshop = workshop();
295   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
296   bool aRedisplayed = false;
297   //std::list<ObjectPtr> aHiddenObjects;
298   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
299     ObjectPtr aObj = (*aIt);
300
301     // Hide the object if it is invalid or concealed one
302     bool aHide = !aObj->data() || !aObj->data()->isValid() ||
303       aObj->isDisabled() || (!aObj->isDisplayed());
304
305     if (!aHide) { // check that this is not hidden result
306       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
307       aHide = aRes && aRes->isConcealed();
308
309       // Hide the presentation with an empty shape. But isDisplayed state of the object should not
310       // be changed to the object becomes visible when the shape becomes not empty
311       if (!aHide && aRes.get())
312         aHide = !aRes->shape().get() || aRes->shape()->isNull();
313     }
314
315 #ifdef DEBUG_RESULT_COMPSOLID
316     ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
317     if (aRes.get()) {
318       ResultCompSolidPtr aCompSolidRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aRes);
319       if (aCompSolidRes.get()) {
320           qDebug(QString("COMPSOLID, numberOfSubs = %1")
321             .arg(aCompSolidRes->numberOfSubs()).toStdString().c_str());
322       }
323       if (ModelAPI_Tools::compSolidOwner(aRes))
324         qDebug("COMPSOLID sub-object");
325     }
326 #endif
327     #ifdef DEBUG_FEATURE_REDISPLAY
328       QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
329       FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
330       if (aFeature.get()) {
331         std::string aKind = aFeature->getKind();
332         if (aKind == DebugFeatureKind || DebugFeatureKind.empty()) {
333           qDebug(QString("visible=%1, hide=%2 : display= %2").arg(aDisplayer->isVisible(aObj))
334                                             .arg(aHide).arg(anObjInfo).toStdString().c_str());
335         }
336       }
337     #endif
338     if (aHide) {
339       //we should provide objects which are hidden in the viewer, e.g. sketch always should
340       // visualizes all sub-features, if some features are to be hidden, sould be proposed may
341       // be to removed #1223
342       // aHiddenObjects.push_back(aObj);
343       aRedisplayed = aDisplayer->erase(aObj, false) || aRedisplayed;
344       #ifdef DEBUG_FEATURE_REDISPLAY
345         // Redisplay the visible object or the object of the current operation
346         bool isVisibleObject = aDisplayer->isVisible(aObj);
347
348         QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
349       #endif
350     }
351     else {
352       // Redisplay the visible object or the object of the current operation
353       bool isVisibleObject = aDisplayer->isVisible(aObj);
354       #ifdef DEBUG_FEATURE_REDISPLAY
355         QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
356       #endif
357
358       if (isVisibleObject)  { // redisplay visible object
359         //displayObject(aObj);  // In order to update presentation
360         // in order to avoid the check whether the object can be redisplayed, the exact method
361         // of redisplay is called. This modification is made in order to have the line is updated
362         // by creation of a horizontal constraint on the line by preselection
363         if (ModelAPI_Tools::hasSubResults(std::dynamic_pointer_cast<ModelAPI_Result>(aObj))) {
364           aRedisplayed = aDisplayer->erase(aObj, false) || aRedisplayed;
365         }
366         else {
367           aRedisplayed = aDisplayer->redisplay(aObj, false) || aRedisplayed;
368           // Deactivate object of current operation from selection
369           aWorkshop->deactivateActiveObject(aObj, false);
370         }
371       } else { // display object if the current operation has it
372         if (displayObject(aObj)) {
373           aRedisplayed = true;
374           // Deactivate object of current operation from selection
375           aWorkshop->deactivateActiveObject(aObj, false);
376         }
377       }
378     }
379   }
380
381   // this processing should be moved in another place in order to do not cause problems in
382   // flush messages chain
383   //if (aHiddenObjects.size() > 0)
384   //  myWorkshop->module()->processHiddenObject(aHiddenObjects);
385
386   bool isCustomized = customizeFeature(anObjects, aRedisplayed);
387   if (aRedisplayed || isCustomized) {
388     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
389
390     // Do not update viewer here because it can be called in a loop
391     // In this case Update has to be called after redisplay event
392     //aDisplayer->updateViewer();
393   }
394 }
395
396 //******************************************************
397 void XGUI_WorkshopListener::
398   onFeatureCreatedMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
399 {
400   SUIT_Application * app = SUIT_Session::session()->activeApplication();
401
402   QVariant aVar = app->property("IsLoadedScript");
403
404   std::set<ObjectPtr> anObjects = theMsg->objects();
405   std::set<ObjectPtr>::const_iterator aIt;
406 #ifdef DEBUG_FEATURE_CREATED
407   QStringList anInfo;
408   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
409     anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
410   }
411   QString anInfoStr = anInfo.join(";\t");
412   qDebug(QString("onFeatureCreatedMsg: %1, %2")
413     .arg(anObjects.size()).arg(anInfoStr).toStdString().c_str());
414 #endif
415
416   //bool aHasPart = false;
417   bool aDisplayed = false;
418   if (aVar.isNull() || !aVar.toBool()) {
419     for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
420       ObjectPtr anObject = *aIt;
421
422 #ifdef DEBUG_RESULT_COMPSOLID
423       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
424       if (aRes.get()) {
425         ResultCompSolidPtr aCompSolidRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aRes);
426         if (aCompSolidRes.get()) {
427             qDebug(QString("COMPSOLID, numberOfSubs = %1")
428               .arg(aCompSolidRes->numberOfSubs()).toStdString().c_str());
429         }
430         if (ModelAPI_Tools::compSolidOwner(aRes))
431           qDebug("COMPSOLID sub-object");
432       }
433 #endif
434
435       ResultBodyPtr aRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anObject);
436
437       if (aRes.get() && aRes->numberOfSubs() > 0)
438         for (int anIndex = 0; anIndex < aRes->numberOfSubs(); ++anIndex)
439           setDisplayed(aRes->subResult(anIndex), aDisplayed);
440       else
441         setDisplayed(anObject, aDisplayed);
442     }
443   }
444   MAYBE_UNUSED bool isCustomized = customizeFeature(anObjects, aDisplayed);
445
446   //if (myObjectBrowser)
447   //  myObjectBrowser->processEvent(theMsg);
448   if (aDisplayed) {
449     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
450     workshop()->displayer()->updateViewer();
451   }
452   //if (aHasPart) { // TODO: Avoid activate last part on loading of document
453   //  activateLastPart();
454   //}
455 }
456
457 //******************************************************
458 void XGUI_WorkshopListener::onFeatureEmptyPresentationMsg(
459                                       const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
460 {
461   std::set<ObjectPtr> anObjects = theMsg->objects();
462   std::set<ObjectPtr>::const_iterator aIt;
463 #ifdef DEBUG_FEATURE_CREATED
464   QStringList anInfo;
465   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
466     anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
467   }
468   QString anInfoStr = anInfo.join(";\t");
469   qDebug(QString("onFeatureEmptyPresentationMsg: %1, %2")
470     .arg(anObjects.size()).arg(anInfoStr).toStdString().c_str());
471 #endif
472
473   XGUI_Workshop* aWorkshop = workshop();
474   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
475
476   bool aRedisplayed = false;
477   for (aIt = anObjects.begin(); aIt != anObjects.end(); ++aIt) {
478     ObjectPtr anObject = *aIt;
479     aRedisplayed = aDisplayer->erase(anObject, false) || aRedisplayed;
480   }
481
482   if (aRedisplayed)
483     aDisplayer->updateViewer();
484 }
485
486 bool XGUI_WorkshopListener::event(QEvent * theEvent)
487 {
488   PostponeMessageQtEvent* aPostponedEv = dynamic_cast<PostponeMessageQtEvent*>(theEvent);
489   if (aPostponedEv) {
490     std::shared_ptr<Events_Message> aEventPtr = aPostponedEv->postponedMessage();
491     processEvent(aEventPtr);
492     return true;
493   }
494   return false;
495 }
496
497 //**************************************************************
498 bool XGUI_WorkshopListener::displayObject(ObjectPtr theObj)
499 {
500 #ifdef DEBUG_RESULT_COMPSOLID
501   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
502   if (aRes.get() && (ModelAPI_Tools::hasSubResults(aRes) || ModelAPI_Tools::compSolidOwner(aRes))) {
503     ResultCompSolidPtr aCompSolidRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aRes);
504     if (aCompSolidRes.get()) {
505       qDebug("COMPSOLID: displayObject");
506     }
507   }
508 #endif
509
510   bool aDisplayed = false;
511   XGUI_Workshop* aWorkshop = workshop();
512   // do not display the object if it has sub objects. They should be displayed separately.
513   if (!aWorkshop->module()->canDisplayObject(theObj) ||
514       ModelAPI_Tools::hasSubResults(std::dynamic_pointer_cast<ModelAPI_Result>(theObj)))
515     return aDisplayed;
516
517   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
518   return aDisplayer->display(theObj, false);
519 }
520
521 bool XGUI_WorkshopListener::customizeFeature(const std::set<ObjectPtr>& theObjects,
522                                                    bool theForceRedisplay)
523 {
524   XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr();
525   FeaturePtr aCurrentFeature;
526   if (anOperationMgr->hasOperation()) {
527     ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
528                                                       (anOperationMgr->currentOperation());
529     if (aFOperation) {
530       aCurrentFeature = aFOperation->feature();
531     }
532   }
533
534   bool aCustomized = false;
535   if (aCurrentFeature.get()) {
536     // the customize presentation should be redisplayed if force redislayed is true or
537     // if a list of message objects contains the operation feature for case when
538     // the feature is hidden, but arguments of the feature are modified
539     // e.g. extrusion is hidden(h=0) but sketch is chosen
540     if (theForceRedisplay || theObjects.find(aCurrentFeature) != theObjects.end()) {
541       aCustomized = myWorkshop->module()->customizeFeature(aCurrentFeature,
542                                  ModuleBase_IModule::CustomizeArguments, false) || aCustomized;
543       aCustomized = myWorkshop->module()->customizeFeature(aCurrentFeature,
544                                    ModuleBase_IModule::CustomizeResults, false) || aCustomized;
545       aCustomized = myWorkshop->module()->customizeFeature(aCurrentFeature,
546                         ModuleBase_IModule::CustomizeHighlightedObjects, false) || aCustomized;
547     }
548   }
549   return aCustomized;
550 }
551
552 XGUI_Workshop* XGUI_WorkshopListener::workshop() const
553 {
554   return myWorkshop;
555 }
556
557
558 void XGUI_WorkshopListener::setDisplayed(ObjectPtr theObject, bool& theDisplayed)
559 {
560   // the validity of the data should be checked here in order to avoid display of the objects,
561   // which were created, then deleted, but flush for the creation event happens after that
562   // we should not display disabled objects
563   bool aHide = !theObject->data()->isValid() ||
564                 theObject->isDisabled() ||
565                !theObject->isDisplayed();
566   if (!aHide) { // check that this is not hidden result
567     ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
568     aHide = aRes && aRes->isConcealed();
569     // Hide the presentation with an empty shape. But isDisplayed state of the object should not
570     // be changed to the object becomes visible when the shape becomes not empty
571     if (!aHide && aRes.get())
572       aHide = !aRes->shape().get() || aRes->shape()->isNull();
573   }
574   if (!aHide) {
575     // setDisplayed has to be called in order to synchronize internal state of the object
576     // with list of displayed objects
577     if (myWorkshop->module()->canDisplayObject(theObject)) {
578       theObject->setDisplayed(true);
579       theDisplayed = displayObject(theObject);
580     }
581     else
582       theObject->setDisplayed(false);
583   }
584 }