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