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