Salome HOME
Initial part document shapes management implementation.
[modules/shaper.git] / src / XGUI / XGUI_Workshop.cpp
index 6100b9ecf43cc37efde993545ed6e9db1067a45d..bbcef0e89cf857a8122008490661e4f6fae4eca7 100644 (file)
 #include "XGUI_SalomeConnector.h"
 #include "XGUI_ActionsMgr.h"
 #include "XGUI_ErrorDialog.h"
+#include "XGUI_ColorDialog.h"
 #include "XGUI_ViewerProxy.h"
 #include "XGUI_PropertyPanel.h"
 #include "XGUI_ContextMenuMgr.h"
 #include "XGUI_ModuleConnector.h"
 #include <XGUI_QtEvents.h>
 #include <XGUI_HistoryMenu.h>
+#include <XGUI_CustomPrs.h>
 
 #include <AppElements_Workbench.h>
 #include <AppElements_Viewer.h>
@@ -40,6 +42,7 @@
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeIntArray.h>
+#include <ModelAPI_ResultParameter.h>
 
 //#include <PartSetPlugin_Part.h>
 
@@ -54,8 +57,9 @@
 #include <ModuleBase_WidgetFactory.h>
 #include <ModuleBase_Tools.h>
 #include <ModuleBase_IViewer.h>
-#include<ModuleBase_FilterFactory.h>
+#include <ModuleBase_FilterFactory.h>
 #include <ModuleBase_PageBase.h>
+#include <ModuleBase_Tools.h>
 
 #include <Config_Common.h>
 #include <Config_FeatureMessage.h>
@@ -64,6 +68,8 @@
 #include <Config_PropManager.h>
 #include <Config_SelectionFilterMessage.h>
 
+#include <SUIT_ResourceMgr.h>
+
 #include <QApplication>
 #include <QFileDialog>
 #include <QMessageBox>
 #include <QMenu>
 #include <QToolButton>
 #include <QAction>
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QHBoxLayout>
-#include <QtxColorButton.h>
+#include <QDesktopWidget>
 
 #ifdef _DEBUG
 #include <QDebug>
 #include <dlfcn.h>
 #endif
 
-QMap<QString, QString> XGUI_Workshop::myIcons;
-
-
-QIcon XGUI_Workshop::featureIcon(const FeaturePtr& theFeature)
-{
-  QIcon anIcon;
-
-  std::string aKind = theFeature->getKind();
-  QString aId(aKind.c_str());
-  if (!myIcons.contains(aId))
-    return anIcon;
-
-  QString anIconString = myIcons[aId];
-
-  ModelAPI_ExecState aState = theFeature->data()->execState();
-  switch(aState) {
-    case ModelAPI_StateDone:
-    case ModelAPI_StateNothing: {
-      anIcon = QIcon(anIconString);
-    }
-    break;
-    case ModelAPI_StateMustBeUpdated: {
-      anIcon = ModuleBase_Tools::lighter(anIconString);
-    }
-    break;
-    case ModelAPI_StateExecFailed: {
-      anIcon = ModuleBase_Tools::composite(":pictures/exec_state_failed.png", anIconString);
-    }
-    break;
-    case ModelAPI_StateInvalidArgument: {
-      anIcon = ModuleBase_Tools::composite(":pictures/exec_state_invalid_parameters.png",
-                                           anIconString);
-    }
-    break;
-    default: break;  
-  }
-  return anIcon;  
-}
+//#define DEBUG_FEATURE_CREATED
+//#define DEBUG_FEATURE_REDISPLAY
+//#define DEBUG_DELETE
 
 XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
     : QObject(),
@@ -140,10 +108,20 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
       myObjectBrowser(0),
       myDisplayer(0),
       myUpdatePrefs(false),
-      myPartActivating(false)
+      myPartActivating(false),
+      myIsLoadingData(false)
 {
   myMainWindow = mySalomeConnector ? 0 : new AppElements_MainWindow();
 
+  if (myMainWindow) {
+    SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
+    bool aCloc = aResMgr->booleanValue("language", "locale", true);
+    if (aCloc)
+      QLocale::setDefault( QLocale::c() );
+    else 
+      QLocale::setDefault( QLocale::system() );
+  }
+
   myDisplayer = new XGUI_Displayer(this);
 
   mySelector = new XGUI_SelectionMgr(this);
@@ -151,7 +129,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
 
   myOperationMgr = new XGUI_OperationMgr(this);
   myActionsMgr = new XGUI_ActionsMgr(this);
-  myErrorDlg = new XGUI_ErrorDialog(myMainWindow);
+  myErrorDlg = new XGUI_ErrorDialog(QApplication::desktop());
   myContextMenuMgr = new XGUI_ContextMenuMgr(this);
   connect(myContextMenuMgr, SIGNAL(actionTriggered(const QString&, bool)), this,
           SLOT(onContextMenuCommand(const QString&, bool)));
@@ -172,7 +150,8 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
           SLOT(onOperationCommitted(ModuleBase_Operation*)));
   connect(myOperationMgr, SIGNAL(operationAborted(ModuleBase_Operation*)), 
           SLOT(onOperationAborted(ModuleBase_Operation*)));
-  connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
+  if (myMainWindow)
+    connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
   connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&)));
 }
 
@@ -198,20 +177,19 @@ void XGUI_Workshop::startApplication()
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
   aLoop->registerListener(this, Events_LongOp::eventID());
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TOSHOW));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TOHIDE));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SELFILTER_LOADED));
 
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED));
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED));
+
   registerValidators();
 
   // Calling of  loadCustomProps before activating module is required
   // by Config_PropManger to restore user-defined path to plugins
   ModuleBase_Preferences::loadCustomProps();
-  activateModule();
+  createModule();
   if (myMainWindow) {
     myMainWindow->show();
     updateCommandStatus();
@@ -222,6 +200,29 @@ void XGUI_Workshop::startApplication()
   emit applicationStarted();
 }
 
+void XGUI_Workshop::activateModule()
+{
+  myModule->activateSelectionFilters();
+
+  connect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
+    myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
+  connect(myDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)),
+    myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr)));
+
+  myActionsMgr->update();
+
+}
+
+void XGUI_Workshop::deactivateModule()
+{
+  myModule->deactivateSelectionFilters();
+
+  disconnect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
+    myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
+  disconnect(myDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)),
+    myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr)));
+}
+
 //******************************************************
 void XGUI_Workshop::initMenu()
 {
@@ -267,7 +268,7 @@ void XGUI_Workshop::initMenu()
 
   AppElements_Command* aCommand;
 
-  aCommand = aGroup->addFeature("SAVE_CMD", tr("Save..."), tr("Save the document"),
+  aCommand = aGroup->addFeature("SAVE_CMD", tr("Save"), tr("Save the document"),
                                 QIcon(":pictures/save.png"), QKeySequence::Save);
   aCommand->connectTo(this, SLOT(onSave()));
   //aCommand->disable();
@@ -376,34 +377,12 @@ void XGUI_Workshop::processEvent(const std::shared_ptr<Events_Message>& theMessa
     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
     onFeatureUpdatedMsg(anUpdateMsg);
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
-    std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDelMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
-    onObjectDeletedMsg(aDelMsg);
   } else if (theMessage->eventID() == Events_LongOp::eventID()) {
     if (Events_LongOp::isPerformed()) {
       QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
     } else {
       QApplication::restoreOverrideCursor();
     }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOSHOW)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    const std::set<ObjectPtr>& aObjList = anUpdateMsg->objects();
-    QObjectPtrList aList;
-    std::set<ObjectPtr>::const_iterator aIt;
-    for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt)
-      aList.append(*aIt);
-    showObjects(aList, true);
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    const std::set<ObjectPtr>& aObjList = anUpdateMsg->objects();
-    QObjectPtrList aList;
-    std::set<ObjectPtr>::const_iterator aIt;
-    for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt)
-      aList.append(*aIt);
-    showObjects(aList, false);
   }
   //An operation passed by message. Start it, process and commit.
   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OPERATION_LAUNCHED)) {
@@ -419,30 +398,7 @@ void XGUI_Workshop::processEvent(const std::shared_ptr<Events_Message>& theMessa
           updateCommandStatus();
       }
     }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
-    myActionsMgr->update();
-    // Find and Activate active part
-    if (myPartActivating)
-      return;
-    SessionPtr aMgr = ModelAPI_Session::get();
-    DocumentPtr aActiveDoc = aMgr->activeDocument();
-    DocumentPtr aDoc = aMgr->moduleDocument();
-    if (aActiveDoc == aDoc) {
-      activatePart(ResultPartPtr()); 
-      return;
-    }
-    std::string aGrpName = ModelAPI_ResultPart::group();
-    for (int i = 0; i < aDoc->size(aGrpName); i++) {
-      ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aDoc->object(aGrpName, i));
-      if (aPart->partDoc() == aActiveDoc) {
-        activatePart(aPart); // Activate a part which corresponds to active Doc
-        return;
-      }
-    }
-    // If not found then activate global document
-    activatePart(ResultPartPtr()); 
-
-  }
+  } 
   else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SELFILTER_LOADED)) {
     std::shared_ptr<Config_SelectionFilterMessage> aMsg = 
       std::dynamic_pointer_cast<Config_SelectionFilterMessage>(theMessage);
@@ -453,6 +409,13 @@ void XGUI_Workshop::processEvent(const std::shared_ptr<Events_Message>& theMessa
                                aMsg->parameters());
       }
     }
+  } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)) {
+    // the viewer's update context will not happens until viewer updated is emitted
+    myDisplayer->enableUpdateViewer(false);
+  } else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)) {
+    // the viewer's update context is unblocked, the viewer's update works
+    myDisplayer->enableUpdateViewer(true);
+    myDisplayer->updateViewer();
   } else {
     //Show error dialog if error message received.
     std::shared_ptr<Events_Error> anAppError = std::dynamic_pointer_cast<Events_Error>(theMessage);
@@ -498,8 +461,8 @@ void XGUI_Workshop::onFeatureUpdatedMsg(const std::shared_ptr<ModelAPI_ObjectUpd
     }
   }
   myOperationMgr->onValidateOperation();
-  if (myObjectBrowser)
-    myObjectBrowser->processEvent(theMsg);
+  //if (myObjectBrowser)
+  //  myObjectBrowser->processEvent(theMsg);
 }
 
 //******************************************************
@@ -507,10 +470,22 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectU
 {
   std::set<ObjectPtr> aObjects = theMsg->objects();
   std::set<ObjectPtr>::const_iterator aIt;
+
+#ifdef DEBUG_FEATURE_REDISPLAY
+  QStringList anInfo;
+  for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
+    anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
+  }
+  QString anInfoStr = anInfo.join(", ");
+  qDebug(QString("onFeatureRedisplayMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str());
+#endif
+
   for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
     ObjectPtr aObj = (*aIt);
 
-    bool aHide = !aObj->data() || !aObj->data()->isValid();
+    // Hide the object if it is invalid or concealed one
+    bool aHide = !aObj->data() || !aObj->data()->isValid() || 
+      aObj->isDisabled() || (!aObj->isDisplayed());
     if (!aHide) { // check that this is not hidden result
       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
       aHide = aRes && aRes->isConcealed();
@@ -518,23 +493,25 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectU
     if (aHide)
       myDisplayer->erase(aObj, false);
     else {
-      if (myDisplayer->isVisible(aObj))  {
-        displayObject(aObj);  // In order to update presentation
-        if (myOperationMgr->hasOperation()) {
-          ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
-          if (!aOperation->isEditOperation() &&
-              aOperation->hasObject(aObj) && myDisplayer->isActive(aObj))
-            myDisplayer->deactivate(aObj);
-        }
-      } else {
-        if (myOperationMgr->hasOperation()) {
-          ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
-          if (myModule->canDisplayObject(aObj)) {
-            displayObject(aObj);
-            // Deactivate object of current operation from selection
-            if (myDisplayer->isActive(aObj))
-              myDisplayer->deactivate(aObj);
-          }
+      // Redisplay the visible object or the object of the current operation
+      bool isVisibleObject = myDisplayer->isVisible(aObj);
+      #ifdef DEBUG_FEATURE_REDISPLAY
+      //QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
+      //qDebug(QString("visible=%1 : display= %2").arg(isVisibleObject).arg(anObjInfo).toStdString().c_str());
+      #endif
+
+      if (isVisibleObject)  { // redisplay visible object
+        //displayObject(aObj);  // In order to update presentation
+        // in order to avoid the check whether the object can be redisplayed, the exact method
+        // of redisplay is called. This modification is made in order to have the line is updated
+        // by creation of a horizontal constraint on the line by preselection
+        myDisplayer->redisplay(aObj, false);
+        // Deactivate object of current operation from selection
+        deactivateActiveObject(aObj, false);
+      } else { // display object if the current operation has it
+        if (displayObject(aObj)) {
+          // Deactivate object of current operation from selection
+          deactivateActiveObject(aObj, false);
         }
       }
     }
@@ -542,28 +519,51 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectU
   myDisplayer->updateViewer();
 }
 
+//******************************************************
+void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer)
+{
+  if (!myModule->canActivateSelection(theObject)) {
+    if (myDisplayer->isActive(theObject))
+      myDisplayer->deactivate(theObject, theUpdateViewer);
+  }
+}
+
 //******************************************************
 void XGUI_Workshop::onFeatureCreatedMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
 {
   std::set<ObjectPtr> aObjects = theMsg->objects();
-
   std::set<ObjectPtr>::const_iterator aIt;
-  bool aHasPart = false;
-  bool isDisplayed = false;
+#ifdef DEBUG_FEATURE_CREATED
+  QStringList anInfo;
   for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
+    anInfo.append(ModuleBase_Tools::objectInfo((*aIt)));
+  }
+  QString anInfoStr = anInfo.join(", ");
+  qDebug(QString("onFeatureCreatedMsg: %1, %2").arg(aObjects.size()).arg(anInfoStr).toStdString().c_str());
+#endif
 
-    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aIt);
-    if (aPart) {
-      aHasPart = true;
-      // If a feature is created from the aplication's python console  
-      // it doesn't stored in the operation mgr and doesn't displayed
-    } else if (myModule->canDisplayObject(*aIt)) {
-      displayObject(*aIt);
-      isDisplayed = true;
+  //bool aHasPart = false;
+  bool isDisplayed = false;
+  for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
+    ObjectPtr anObject = *aIt;
+    // the validity of the data should be checked here in order to avoid display of the objects,
+    // which were created, then deleted, but flush for the creation event happens after that
+    // we should not display disabled objects
+    bool aHide = !anObject->data()->isValid() || 
+                 anObject->isDisabled() ||
+                 !anObject->isDisplayed();
+    if (!aHide) {
+      // setDisplayed has to be called in order to synchronize internal state of the object 
+      // with list of displayed objects
+      if (myModule->canDisplayObject(anObject)) {
+        anObject->setDisplayed(true);
+        isDisplayed = displayObject(*aIt);
+      } else 
+        anObject->setDisplayed(false);
     }
   }
-  if (myObjectBrowser)
-    myObjectBrowser->processEvent(theMsg);
+  //if (myObjectBrowser)
+  //  myObjectBrowser->processEvent(theMsg);
   if (isDisplayed)
     myDisplayer->updateViewer();
   //if (aHasPart) { // TODO: Avoid activate last part on loading of document
@@ -571,14 +571,6 @@ void XGUI_Workshop::onFeatureCreatedMsg(const std::shared_ptr<ModelAPI_ObjectUpd
   //}
 }
 
-//******************************************************
-void XGUI_Workshop::onObjectDeletedMsg(const std::shared_ptr<ModelAPI_ObjectDeletedMessage>& theMsg)
-{
-  if (myObjectBrowser)
-    myObjectBrowser->processEvent(theMsg);
-  //std::set<ObjectPtr> aFeatures = theMsg->objects();
-}
-
 //******************************************************
 void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation)
 {
@@ -590,7 +582,22 @@ void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation)
   }
   updateCommandStatus();
 
-  myModule->operationStarted(theOperation);
+  myModule->onOperationStarted(theOperation);
+
+  // the objects of the current operation should be deactivated
+  QObjectPtrList anObjects;
+  FeaturePtr aFeature = theOperation->feature();
+  anObjects.append(aFeature);
+  std::list<ResultPtr> aResults = aFeature->results();
+  std::list<ResultPtr>::const_iterator aIt;
+  for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
+    anObjects.append(*aIt);
+  }
+  QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
+  for (; anIt != aLast; anIt++)
+    deactivateActiveObject(*anIt, false);
+  if (anObjects.size() > 0)
+    myDisplayer->updateViewer();
 }
 
 //******************************************************
@@ -604,7 +611,7 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation)
   }
   updateCommandStatus();
 
-  myModule->operationResumed(theOperation);
+  myModule->onOperationResumed(theOperation);
 }
 
 
@@ -618,22 +625,36 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
   hidePropertyPanel();
   myPropertyPanel->cleanContent();
 
-  // Activate objects created by current operation 
-  // in order to clean selection modes
+  myModule->onOperationStopped(theOperation);
+
+  // the deactivated objects of the current operation should be activated back.
+  // They were deactivated on operation start or an object redisplay
+  QObjectPtrList anObjects;
+  FeaturePtr aFeature = theOperation->feature();
+  if (myDisplayer->isVisible(aFeature) && !myDisplayer->isActive(aFeature))
+    anObjects.append(aFeature);
+  std::list<ResultPtr> aResults = aFeature->results();
+  std::list<ResultPtr>::const_iterator aIt;
+  for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
+    ResultPtr anObject = *aIt;
+    if (myDisplayer->isVisible(anObject) && !myDisplayer->isActive(anObject)) {
+      anObjects.append(anObject);
+    }
+  }
   QIntList aModes;
-  myDisplayer->activateObjects(aModes);
-  myModule->operationStopped(theOperation);
+  module()->activeSelectionModes(aModes);
+  myDisplayer->activateObjects(aModes, anObjects);
 }
 
 
 void XGUI_Workshop::onOperationCommitted(ModuleBase_Operation* theOperation)
 {
-  myModule->operationCommitted(theOperation);
+  myModule->onOperationCommitted(theOperation);
 }
 
 void XGUI_Workshop::onOperationAborted(ModuleBase_Operation* theOperation)
 {
-  myModule->operationAborted(theOperation);
+  myModule->onOperationAborted(theOperation);
 }
 
 void XGUI_Workshop::setNestedFeatures(ModuleBase_Operation* theOperation)
@@ -695,15 +716,34 @@ void XGUI_Workshop::addFeature(const std::shared_ptr<Config_FeatureMessage>& the
   }
   ActionInfo aFeatureInfo;
   aFeatureInfo.initFrom(theMessage);
-  // Remember features icons
-  myIcons[QString::fromStdString(theMessage->id())] = aFeatureInfo.iconFile;
 
   QString aWchName = QString::fromStdString(theMessage->workbenchId());
   QStringList aNestedFeatures =
       QString::fromStdString(theMessage->nestedFeatures()).split(" ", QString::SkipEmptyParts);
   QString aDocKind = QString::fromStdString(theMessage->documentKind());
+  QList<QAction*> aNestedActList;
+  bool isColumnButton = !aNestedFeatures.isEmpty();
+  if (isColumnButton) {
+    QString aNestedActions = QString::fromStdString(theMessage->actionsWhenNested());
+    if (aNestedActions.contains("accept")) {
+      QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL);
+      connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(commitAllOperations()));
+      aNestedActList << anAction;
+    }
+    if (aNestedActions.contains("abort")) {
+      QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll, NULL);
+      connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(abortAllOperations()));
+      aNestedActList << anAction;
+    }
+  }
+
   if (isSalomeMode()) {
-    QAction* aAction = salomeConnector()->addFeature(aWchName, aFeatureInfo);
+    QAction* aAction;
+    if (isColumnButton) {
+      aAction = salomeConnector()->addNestedFeature(aWchName, aFeatureInfo, aNestedActList);
+    } else {
+      aAction = salomeConnector()->addFeature(aWchName, aFeatureInfo);
+    }
     salomeConnector()->setNestedActions(aFeatureInfo.id, aNestedFeatures);
     salomeConnector()->setDocumentKind(aFeatureInfo.id, aDocKind);
 
@@ -734,19 +774,7 @@ void XGUI_Workshop::addFeature(const std::shared_ptr<Config_FeatureMessage>& the
     // Enrich created button with accept/abort buttons if necessary
     AppElements_Button* aButton = aCommand->button();
     if (aButton->isColumnButton()) {
-      QString aNestedActions = QString::fromStdString(theMessage->actionsWhenNested());
-      QList<QAction*> anActList;
-      if (aNestedActions.contains("accept")) {
-        QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll, aButton);
-        connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(commitAllOperations()));
-        anActList << anAction;
-      }
-      if (aNestedActions.contains("abort")) {
-        QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll, aButton);
-        connect(anAction, SIGNAL(triggered()), myOperationMgr, SLOT(abortAllOperations()));
-        anActList << anAction;
-      }
-      aButton->setAdditionalButtons(anActList);
+      aButton->setAdditionalButtons(aNestedActList);
     }
     myActionsMgr->addCommand(aCommand);
     myModule->actionCreated(aCommand);
@@ -849,12 +877,11 @@ void XGUI_Workshop::onOpen()
     } else if (anAnswer == QMessageBox::Cancel) {
       return;
     }
-    aSession->closeAll();
     myCurrentDir = "";
   }
 
   //show file dialog, check if readable and open
-  myCurrentDir = QFileDialog::getExistingDirectory(mainWindow());
+  myCurrentDir = QFileDialog::getExistingDirectory(mainWindow(), tr("Select folder"));
   if (myCurrentDir.isEmpty())
     return;
   QFileInfo aFileInfo(myCurrentDir);
@@ -864,10 +891,13 @@ void XGUI_Workshop::onOpen()
     return;
   }
   QApplication::setOverrideCursor(Qt::WaitCursor);
+  myIsLoadingData = true;
+  aSession->closeAll();
   aSession->load(myCurrentDir.toLatin1().constData());
   myObjectBrowser->rebuildDataTree();
-  displayAllResults();
+  //displayAllResults();
   updateCommandStatus();
+  myIsLoadingData = false;
   QApplication::restoreOverrideCursor();
 }
 
@@ -893,7 +923,7 @@ bool XGUI_Workshop::onSaveAs()
   if(!isActiveOperationAborted())
     return false;
   QFileDialog dialog(mainWindow());
-  dialog.setWindowTitle(tr("Select directory to save files..."));
+  dialog.setWindowTitle(tr("Select folder to save files..."));
   dialog.setFileMode(QFileDialog::Directory);
   dialog.setFilter(tr("Folders (*)"));
   dialog.setOptions(QFileDialog::HideNameFilterDetails | QFileDialog::ShowDirsOnly);
@@ -902,6 +932,7 @@ bool XGUI_Workshop::onSaveAs()
   if (!dialog.exec()) {
     return false;
   }
+
   QString aTempDir = dialog.selectedFiles().first();
   QDir aDir(aTempDir);
   if (aDir.exists() && !aDir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).isEmpty()) {
@@ -939,6 +970,12 @@ void XGUI_Workshop::onUndo(int theTimes)
 //******************************************************
 void XGUI_Workshop::onRedo(int theTimes)
 {
+  // the viewer update should be blocked in order to avoid the features blinking. For the created
+  // feature a results are created, the flush of the created signal caused the viewer redisplay for
+  // each created result. After a redisplay signal is flushed. So, the viewer update is blocked until
+  // redo of all possible objects happens
+  bool isUpdateEnabled = myDisplayer->enableUpdateViewer(false);
+
   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
   SessionPtr aMgr = ModelAPI_Session::get();
   if (aMgr->isOperation())
@@ -947,6 +984,10 @@ void XGUI_Workshop::onRedo(int theTimes)
     aMgr->redo();
   }
   updateCommandStatus();
+
+  // unblock the viewer update functionality and make update on purpose
+  myDisplayer->enableUpdateViewer(isUpdateEnabled);
+  myDisplayer->updateViewer();
 }
 
 //******************************************************
@@ -963,6 +1004,7 @@ void XGUI_Workshop::onRebuild()
   if (!aWasOperation) {
     aMgr->finishOperation();
   }
+  updateCommandStatus();
 }
 
 //******************************************************
@@ -1046,15 +1088,21 @@ ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule)
 }
 
 //******************************************************
-bool XGUI_Workshop::activateModule()
+bool XGUI_Workshop::createModule()
 {
   Config_ModuleReader aModuleReader;
   QString moduleName = QString::fromStdString(aModuleReader.getModuleName());
   myModule = loadModule(moduleName);
   if (!myModule)
     return false;
+
+  //connect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
+  //  myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
+  //connect(myDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)),
+  //  myModule, SLOT(onBeforeObjectErase(ObjectPtr, AISObjectPtr)));
+
   myModule->createFeatures();
-  myActionsMgr->update();
+  //myActionsMgr->update();
   return true;
 }
 
@@ -1071,20 +1119,16 @@ void XGUI_Workshop::updateCommandStatus()
   }
   SessionPtr aMgr = ModelAPI_Session::get();
   if (aMgr->hasModuleDocument()) {
-    QAction *aUndoCmd, *aRedoCmd;
     foreach(QAction* aCmd, aCommands) {
       QString aId = aCmd->data().toString();
       if (aId == "UNDO_CMD")
-        aUndoCmd = aCmd;
+        aCmd->setEnabled(myModule->canUndo());
       else if (aId == "REDO_CMD")
-        aRedoCmd = aCmd;
+        aCmd->setEnabled(myModule->canRedo());
       else
         // Enable all commands
         aCmd->setEnabled(true);
     }
-
-    aUndoCmd->setEnabled(myModule->canUndo());
-    aRedoCmd->setEnabled(myModule->canRedo());
     updateHistory();
   } else {
     foreach(QAction* aCmd, aCommands) {
@@ -1121,8 +1165,8 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent)
   aObjDock->setStyleSheet(
       "::title { position: relative; padding-left: 5px; text-align: left center }");
   myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock);
-  connect(myObjectBrowser, SIGNAL(activePartChanged(ObjectPtr)), this,
-          SLOT(changeCurrentDocument(ObjectPtr)));
+  myObjectBrowser->setDataModel(myModule->dataModel());
+  myModule->customizeObjectBrowser(myObjectBrowser);
   aObjDock->setWidget(myObjectBrowser);
 
   myContextMenuMgr->connectObjectBrowser();
@@ -1195,32 +1239,15 @@ void XGUI_Workshop::hideObjectBrowser()
 }
 
 //******************************************************
-void XGUI_Workshop::onFeatureTriggered()
-{
-  QAction* aCmd = dynamic_cast<QAction*>(sender());
-  if (aCmd) {
-    QString aId = salomeConnector()->commandId(aCmd);
-    if (!aId.isNull())
-      myModule->launchOperation(aId);
-  }
-}
-
-//******************************************************
-void XGUI_Workshop::changeCurrentDocument(ObjectPtr theObj)
-{
-  SessionPtr aMgr = ModelAPI_Session::get();
-  if (theObj) {
-    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theObj);
-    if (aPart) {
-      DocumentPtr aPartDoc = aPart->partDoc();
-      if (aPartDoc) {
-        aMgr->setActiveDocument(aPartDoc);
-        return;
-      }
-    }
-  }
-  aMgr->setActiveDocument(aMgr->moduleDocument());
-}
+//void XGUI_Workshop::onFeatureTriggered()
+//{
+//  QAction* aCmd = dynamic_cast<QAction*>(sender());
+//  if (aCmd) {
+//    QString aId = salomeConnector()->commandId(aCmd);
+//    if (!aId.isNull())
+//      myModule->launchOperation(aId);
+//  }
+//}
 
 //******************************************************
 void XGUI_Workshop::salomeViewerSelectionChanged()
@@ -1238,13 +1265,8 @@ ModuleBase_IViewer* XGUI_Workshop::salomeViewer() const
 void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
 {
   QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
-  if ((theId == "ACTIVATE_PART_CMD") && (aObjects.size() > 0)) {
-    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObjects.first());
-    activatePart(aPart);
-  } else if (theId == "DEACTIVATE_PART_CMD")
-    activatePart(ResultPartPtr());
-  else if (theId == "DELETE_CMD")
-    deleteObjects(aObjects);
+  if (theId == "DELETE_CMD")
+    deleteObjects();
   else if (theId == "COLOR_CMD")
     changeColor(aObjects);
   else if (theId == "SHOW_CMD")
@@ -1257,127 +1279,210 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
     setDisplayMode(aObjects, XGUI_Displayer::Shading);
   else if (theId == "WIREFRAME_CMD")
     setDisplayMode(aObjects, XGUI_Displayer::Wireframe);
-  else if (theId == "HIDEALL_CMD")
-    myDisplayer->eraseAll();
-  else if (theId == "EDIT_CMD") {
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObjects.first());
-    if (aFeature)
-      myModule->editFeature(aFeature);
+  else if (theId == "HIDEALL_CMD") {
+    QObjectPtrList aList = myDisplayer->displayedObjects();
+    foreach (ObjectPtr aObj, aList)
+      aObj->setDisplayed(false);
+    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
   }
 }
 
 //**************************************************************
-void XGUI_Workshop::activatePart(ResultPartPtr theFeature)
-{
-  if (!myPartActivating) {
-    myPartActivating = true;
-    if (theFeature)
-      theFeature->activate();
-    changeCurrentDocument(theFeature);
-    myObjectBrowser->activatePart(theFeature);
-    myPartActivating = false;
-  }
-  updateCommandStatus();
-}
-
-//**************************************************************
-//void XGUI_Workshop::activateLastPart()
-//{
-//  SessionPtr aMgr = ModelAPI_Session::get();
-//  DocumentPtr aDoc = aMgr->moduleDocument();
-//  std::string aGrpName = ModelAPI_ResultPart::group();
-//  ObjectPtr aLastPart = aDoc->object(aGrpName, aDoc->size(aGrpName) - 1);
-//  ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aLastPart);
-//  if (aPart) {
-//    activatePart(aPart);
-//  }
-//}
-
-//**************************************************************
-void XGUI_Workshop::deleteObjects(const QObjectPtrList& theList)
+void XGUI_Workshop::deleteObjects()
 {
   ModuleBase_IModule* aModule = module();
-  if (aModule->deleteObjects())
+  // 1. allow the module to delete objects, do nothing if it has succeed
+  if (aModule->deleteObjects()) {
+    updateCommandStatus();
     return;
+  }
 
   if (!isActiveOperationAborted())
     return;
+  QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
+  bool hasResult = false;
+  bool hasFeature = false;
+  bool hasParameter = false;
+  ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter);
+  if (!(hasFeature || hasParameter))
+    return;
 
-  QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow;
-  std::set<FeaturePtr> aRefFeatures;
-  foreach (ObjectPtr aObj, theList)
+  // 1. start operation
+  QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text();
+  aDescription += tr(" %1");
+  QStringList aObjectNames;
+  foreach (ObjectPtr aObj, anObjects) {
+    if (!aObj->data()->isValid())
+      continue;
+    aObjectNames << QString::fromStdString(aObj->data()->name());
+  }
+  aDescription = aDescription.arg(aObjectNames.join(", "));
+
+  SessionPtr aMgr = ModelAPI_Session::get();
+  aMgr->startOperation(aDescription.toStdString());
+  // 2. close the documents of the removed parts if the result part is in a list of selected objects
+  // this is performed in the RemoveFeature of Part object.
+  /*foreach (ObjectPtr aObj, anObjects)
   {
     ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
     if (aPart) {
-      // TODO: check for what there is this condition. It is placed here historicaly because
-      // ther is this condition during remove features.
-    } else {
-      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
-      if (aFeature.get() != NULL) {
-        aObj->document()->refsToFeature(aFeature, aRefFeatures, false);
+      DocumentPtr aDoc = aObj->document();
+      if (aDoc == aMgr->activeDocument()) {
+        aDoc->close();
       }
     }
+  }*/
+  // 3. delete objects
+  QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow;
+  std::set<FeaturePtr> anIgnoredFeatures;
+  if (deleteFeatures(anObjects, anIgnoredFeatures, aDesktop, true)) {
+    myDisplayer->updateViewer();
+    aMgr->finishOperation();
+    updateCommandStatus();
+  }
+  else {
+    aMgr->abortOperation();
   }
+}
 
-  if (!aRefFeatures.empty()) {
+//**************************************************************
+bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
+                                   std::set<FeaturePtr> theIgnoredFeatures,
+                                   QWidget* theParent,
+                                   const bool theAskAboutDeleteReferences)
+{
+  // 1. find all referenced features
+  std::set<FeaturePtr> aRefFeatures;
+  foreach (ObjectPtr aDeletedObj, theList) {
+    FeaturePtr aDeletedFeature = ModelAPI_Feature::feature(aDeletedObj);
+    if (aDeletedFeature.get() != NULL) {
+      DocumentPtr aDeletedFeatureDoc = aDeletedObj->document();
+      // 1.1 find references in the current document
+      aDeletedFeatureDoc->refsToFeature(aDeletedFeature, aRefFeatures, false);
+      // 1.2 find references in all documents if the document of the feature is
+      // "PartSet". Features of this document can be used in all other documents
+      SessionPtr aMgr = ModelAPI_Session::get();
+      DocumentPtr aModuleDoc = aMgr->moduleDocument();
+      if (aDeletedFeatureDoc == aModuleDoc) {
+        // the deleted feature and results of the feature should be found in references
+        std::list<ObjectPtr> aDeletedObjects;
+        aDeletedObjects.push_back(aDeletedFeature);
+        typedef std::list<std::shared_ptr<ModelAPI_Result> > ResultsList;
+        const ResultsList& aDeletedResults = aDeletedFeature->results();
+        ResultsList::const_iterator aRIter = aDeletedResults.begin();
+        for (; aRIter != aDeletedResults.cend(); aRIter++) {
+          ResultPtr aRes = *aRIter;
+          if (aRes.get())
+            aDeletedObjects.push_back(aRes);
+        }
+        // get all opened documents; found features in the documents;
+        // get a list of objects where a feature refers;
+        // search in these objects the deleted objects.
+        std::list<DocumentPtr> anOpenedDocs = aMgr->allOpenedDocuments();
+        std::list<DocumentPtr>::const_iterator anIt = anOpenedDocs.begin(),
+                                               aLast = anOpenedDocs.end();
+        std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+        for (; anIt != aLast; anIt++) {
+          DocumentPtr aDocument = *anIt;
+          if (aDocument == aDeletedFeatureDoc)
+            continue; // this document has been already processed in 1.1
+
+          int aFeaturesCount = aDocument->size(ModelAPI_Feature::group());
+          for (int aId = 0; aId < aFeaturesCount; aId++) {
+            ObjectPtr anObject = aDocument->object(ModelAPI_Feature::group(), aId);
+            FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+            if (!aFeature.get())
+              continue;
+
+            aRefs.clear();
+            aFeature->data()->referencesToObjects(aRefs);
+            std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRef = aRefs.begin();
+            bool aHasReferenceToDeleted = false;
+            for(; aRef != aRefs.end() && !aHasReferenceToDeleted; aRef++) {
+              std::list<ObjectPtr>::iterator aRefObj = aRef->second.begin();
+              for(; aRefObj != aRef->second.end() && !aHasReferenceToDeleted; aRefObj++) {
+                std::list<ObjectPtr>::const_iterator aDelIt = aDeletedObjects.begin();
+                for(; aDelIt != aDeletedObjects.end() && !aHasReferenceToDeleted; aDelIt++) {
+                  aHasReferenceToDeleted = *aDelIt == *aRefObj;
+                }
+              }
+            }
+            if (aHasReferenceToDeleted)
+              aRefFeatures.insert(aFeature);
+          }
+        }
+      }
+    }
+  }
+  // 2. warn about the references remove, break the delete operation if the user chose it
+  if (theAskAboutDeleteReferences && !aRefFeatures.empty()) {
     QStringList aRefNames;
     std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
                                          aLast = aRefFeatures.end();
     for (; anIt != aLast; anIt++) {
-      FeaturePtr aFeature = (*anIt);
-      std::string aFName = aFeature->data()->name().c_str();
-      std::string aName = (*anIt)->name().c_str();
       aRefNames.append((*anIt)->name().c_str());
     }
     QString aNames = aRefNames.join(", ");
 
     QMessageBox::StandardButton aRes = QMessageBox::warning(
-        aDesktop, tr("Delete features"),
+        theParent, tr("Delete features"),
         QString(tr("Selected features are used in the following features: %1.\
 These features will be deleted also. Would you like to continue?")).arg(aNames),
         QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
     if (aRes != QMessageBox::Yes)
-      return;
+      return false;
   }
 
-  QString aDescription = tr("Delete %1");
-  QStringList aObjectNames;
-  foreach (ObjectPtr aObj, theList) {
-    if (!aObj->data().get())
-      continue;
-    aObjectNames << QString::fromStdString(aObj->data()->name());
-  }
-  aDescription = aDescription.arg(aObjectNames.join(", "));
-  SessionPtr aMgr = ModelAPI_Session::get();
-  aMgr->startOperation(aDescription.toStdString());
+  // 3. remove referenced features
   std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
                                        aLast = aRefFeatures.end();
+#ifdef DEBUG_DELETE
+  QStringList anInfo;
+#endif
   for (; anIt != aLast; anIt++) {
-    FeaturePtr aRefFeature = (*anIt);
-    DocumentPtr aDoc = aRefFeature->document();
-    aDoc->removeFeature(aRefFeature);
-   }
-
+    FeaturePtr aFeature = (*anIt);
+    DocumentPtr aDoc = aFeature->document();
+    if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) {
+      aDoc->removeFeature(aFeature);
+#ifdef DEBUG_DELETE
+      anInfo.append(ModuleBase_Tools::objectInfo(aFeature).toStdString().c_str());
+#endif
+    }
+  }
+#ifdef DEBUG_DELETE
+  qDebug(QString("remove references:%1").arg(anInfo.join("; ")).toStdString().c_str());
+  anInfo.clear();
+#endif
 
-  foreach (ObjectPtr aObj, theList)
-  {
-    DocumentPtr aDoc = aObj->document();
-    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
-    if (aPart) {
-      if (aDoc == aMgr->activeDocument()) {
-        aDoc->close();
-      }
-    } else {
-      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
-      if (aFeature) {
+  // 4. remove the parameter features
+  foreach (ObjectPtr aObj, theList) {
+    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+    if (aResult.get() != NULL) { // results could not be removed,
+      // they are removed by a corresponded feature remove
+      continue;
+    }
+    FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
+    if (aFeature) {
+      // TODO: to learn the workshop to delegate the Part object deletion to the PartSet module
+      // part features are removed in the PartSet module. This condition should be moved there
+      if (aFeature->getKind() == "Part")
+        continue;
+
+      DocumentPtr aDoc = aObj->document();
+      if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) {
         aDoc->removeFeature(aFeature);
+#ifdef DEBUG_DELETE
+        QString anInfoStr = ModuleBase_Tools::objectInfo(aFeature);
+        anInfo.append(anInfoStr);
+        qDebug(QString("remove feature :%1").arg(anInfoStr).toStdString().c_str());
+#endif
       }
     }
   }
-
-  myDisplayer->updateViewer();
-  aMgr->finishOperation();
-  updateCommandStatus();
+#ifdef DEBUG_DELETE
+  qDebug(QString("remove features:%1").arg(anInfo.join("; ")).toStdString().c_str());
+#endif
+  return true;
 }
 
 bool hasResults(QObjectPtrList theObjects, const std::set<std::string>& theTypes)
@@ -1405,18 +1510,69 @@ bool XGUI_Workshop::canChangeColor() const
   aTypes.insert(ModelAPI_ResultGroup::group());
   aTypes.insert(ModelAPI_ResultConstruction::group());
   aTypes.insert(ModelAPI_ResultBody::group());
+  aTypes.insert(ModelAPI_ResultPart::group());
+
   return hasResults(aObjects, aTypes);
 }
 
+void setColor(ResultPtr theResult, std::vector<int>& theColor)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
+  if (aColorAttr.get() != NULL) {
+    if (!aColorAttr->size()) {
+      aColorAttr->setSize(3);
+    }
+    aColorAttr->setValue(0, theColor[0]);
+    aColorAttr->setValue(1, theColor[1]);
+    aColorAttr->setValue(2, theColor[2]);
+  }
+}
+
 //**************************************************************
 void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
 {
+  AttributeIntArrayPtr aColorAttr;
+  // 1. find the current color of the object. This is a color of AIS presentation
+  // The objects are iterated until a first valid color is found 
   std::vector<int> aColor;
   foreach(ObjectPtr anObject, theObjects) {
-
-    AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject);
-    aColor.resize(3);
-    anAISObj->getColor(aColor[0], aColor[1], aColor[2]);
+    if (anObject->groupName() == ModelAPI_ResultPart::group()) {
+      ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anObject);
+      DocumentPtr aPartDoc = aPart->partDoc();
+      // the document should be checked on null, because in opened document if the part
+      // has not been activated yet, the part document is empty
+      if (!aPartDoc.get()) {
+        emit errorOccurred(QString::fromLatin1("Color can not be changed on a part with an empty document"));
+      }
+      else {
+        if (aPartDoc->size(ModelAPI_ResultBody::group()) > 0) {
+          ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), 0);
+          ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObject);
+          if (aBody.get()) {
+            XGUI_CustomPrs::getResultColor(aBody, aColor);
+          }
+        }
+      }
+    }
+    else {
+      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+      if (aResult.get())
+        XGUI_CustomPrs::getResultColor(aResult, aColor);
+      else {
+        // TODO: remove the obtaining a color from the AIS object
+        // this does not happen never because:
+        // 1. The color can be changed only on results
+        // 2. The result can be not visualized in the viewer(e.g. Origin Construction)
+        AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject);
+        if (anAISObj.get()) {
+          aColor.resize(3);
+          anAISObj->getColor(aColor[0], aColor[1], aColor[2]);
+        }
+      }
+    }
     if (!aColor.empty())
       break;
   }
@@ -1424,55 +1580,44 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
     return;
 
   // 2. show the dialog to change the value
-  QDialog* aDlg = new QDialog();
-  QVBoxLayout* aLay = new QVBoxLayout(aDlg);
-
-  QtxColorButton* aColorBtn = new QtxColorButton(aDlg);
-  aColorBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-
-  aLay->addWidget(aColorBtn);
-  aColorBtn->setColor(QColor(aColor[0], aColor[1], aColor[2]));
-
-  QDialogButtonBox* aButtons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
-                                                    Qt::Horizontal, aDlg);
-  connect(aButtons, SIGNAL(accepted()), aDlg, SLOT(accept()));
-  connect(aButtons, SIGNAL(rejected()), aDlg, SLOT(reject()));
-  aLay->addWidget(aButtons);
-
+  XGUI_ColorDialog* aDlg = new XGUI_ColorDialog(mainWindow());
+  aDlg->setColor(aColor);
   aDlg->move(QCursor::pos());
   bool isDone = aDlg->exec() == QDialog::Accepted;
   if (!isDone)
     return;
 
-  QColor aColorResult = aColorBtn->color();
-  int aRedResult = aColorResult.red(),
-      aGreenResult = aColorResult.green(),
-      aBlueResult = aColorResult.blue();
-
-  if (aRedResult == aColor[0] && aGreenResult == aColor[1] && aBlueResult == aColor[2])
-    return;
+  bool isRandomColor = aDlg->isRandomColor();
 
   // 3. abort the previous operation and start a new one
   SessionPtr aMgr = ModelAPI_Session::get();
   bool aWasOperation = aMgr->isOperation(); // keep this value
   if (!aWasOperation) {
-    QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text();
+    QString aDescription = contextMenuMgr()->action("COLOR_CMD")->text();
     aMgr->startOperation(aDescription.toStdString());
   }
 
   // 4. set the value to all results
-  AttributeIntArrayPtr aColorAttr;
   foreach(ObjectPtr anObj, theObjects) {
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
     if (aResult.get() != NULL) {
-      aColorAttr = aResult->data()->intArray(ModelAPI_Result::COLOR_ID());
-      if (aColorAttr.get() != NULL) {
-        if (!aColorAttr->size()) {
-          aColorAttr->setSize(3);
+      if (aResult->groupName() == ModelAPI_ResultPart::group()) {
+        ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aResult);
+        DocumentPtr aPartDoc = aPart->partDoc();
+        // the document should be checked on null, because in opened document if the part
+        // has not been activated yet, the part document is empty
+        if (aPartDoc.get()) {
+          for (int i = 0; i < aPartDoc->size(ModelAPI_ResultBody::group()); i++) {
+            ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), i);
+            ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObject);
+            std::vector<int> aColorResult = aDlg->getColor();
+            setColor(aBody, aColorResult);
+          }
         }
-        aColorAttr->setValue(0, aRedResult);
-        aColorAttr->setValue(1, aGreenResult);
-        aColorAttr->setValue(2, aBlueResult);
+      }
+      else {
+        std::vector<int> aColorResult = aDlg->getColor();
+        setColor(aResult, aColorResult);
       }
     }
   }
@@ -1482,23 +1627,52 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
 }
 
 //**************************************************************
+#define SET_DISPLAY_GROUP(aGroupName, aDisplay) \
+for (int i = 0; i < aDoc->size(aGroupName); i++) { \
+  aDoc->object(aGroupName, i)->setDisplayed(aDisplay); \
+}
 void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible)
 {
-  foreach (ObjectPtr aObj, theList)
-  {
-    if (isVisible) {
-      displayObject(aObj);
+  foreach (ObjectPtr aObj, theList) {
+    /*
+    ResultPartPtr aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
+    if (aPartRes) {
+      DocumentPtr aDoc = aPartRes->partDoc();
+      SET_DISPLAY_GROUP(ModelAPI_ResultBody::group(), isVisible)
+      SET_DISPLAY_GROUP(ModelAPI_ResultConstruction::group(), isVisible)
+      SET_DISPLAY_GROUP(ModelAPI_ResultGroup::group(), isVisible)
     } else {
-      myDisplayer->erase(aObj, false);
-    }
+    */
+      aObj->setDisplayed(isVisible);
+    //}
   }
-  myDisplayer->updateViewer();
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 }
 
 //**************************************************************
 void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList)
 {
-  myDisplayer->showOnly(theList);
+  // Hide all displayed objects
+  QObjectPtrList aList = myDisplayer->displayedObjects();
+  foreach (ObjectPtr aObj, aList)
+    aObj->setDisplayed(false);
+
+  // Show only objects from the list
+  foreach (ObjectPtr aObj, theList) {
+    /*
+    ResultPartPtr aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
+    if (aPartRes) {
+      DocumentPtr aDoc = aPartRes->partDoc();
+      SET_DISPLAY_GROUP(ModelAPI_ResultBody::group(), true)
+      SET_DISPLAY_GROUP(ModelAPI_ResultConstruction::group(), true)
+      SET_DISPLAY_GROUP(ModelAPI_ResultGroup::group(), true)
+    } else {
+    */
+      aObj->setDisplayed(true);
+    //}
+  }
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+
 }
 
 
@@ -1510,7 +1684,7 @@ void XGUI_Workshop::registerValidators() const
 }
 
 //**************************************************************
-void XGUI_Workshop::displayAllResults()
+/*void XGUI_Workshop::displayAllResults()
 {
   SessionPtr aMgr = ModelAPI_Session::get();
   DocumentPtr aRootDoc = aMgr->moduleDocument();
@@ -1521,7 +1695,7 @@ void XGUI_Workshop::displayAllResults()
     displayDocumentResults(aPart->partDoc());
   }
   myDisplayer->updateViewer();
-}
+}*/
 
 //**************************************************************
 void XGUI_Workshop::displayDocumentResults(DocumentPtr theDoc)
@@ -1535,8 +1709,10 @@ void XGUI_Workshop::displayDocumentResults(DocumentPtr theDoc)
 //**************************************************************
 void XGUI_Workshop::displayGroupResults(DocumentPtr theDoc, std::string theGroup)
 {
-  for (int i = 0; i < theDoc->size(theGroup); i++)
-    displayObject(theDoc->object(theGroup, i));
+  for (int i = 0; i < theDoc->size(theGroup); i++) 
+    theDoc->object(theGroup, i)->setDisplayed(true);
+    //displayObject(theDoc->object(theGroup, i));
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 }
 
 //**************************************************************
@@ -1563,20 +1739,24 @@ void XGUI_Workshop::closeDocument()
 
   SessionPtr aMgr = ModelAPI_Session::get();
   aMgr->closeAll();
-  objectBrowser()->clearContent();
 }
 
 //**************************************************************
-void XGUI_Workshop::displayObject(ObjectPtr theObj)
+bool XGUI_Workshop::displayObject(ObjectPtr theObj)
 {
+  if (!myModule->canDisplayObject(theObj))
+    return false;
+
   ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theObj);
   if (aBody.get() != NULL) {
     int aNb = myDisplayer->objectsCount();
     myDisplayer->display(theObj, false);
     if (aNb == 0)
       viewer()->fitAll();
-  } else 
+  } else if (!(myIsLoadingData || myPartActivating))
     myDisplayer->display(theObj, false);
+
+  return true;
 }
 
 void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot)
@@ -1605,7 +1785,13 @@ QList<ActionInfo> XGUI_Workshop::processHistoryList(const std::list<std::string>
     if (isEditing) {
       anId.chop(ModuleBase_Operation::EditSuffix().size());
     }
-    ActionInfo anInfo = myActionsMgr->actionInfoById(anId);
+    ActionInfo anInfo;
+    QAction* aContextMenuAct = myContextMenuMgr->actionByName(anId);
+    if (aContextMenuAct) {
+      anInfo.initFrom(aContextMenuAct);
+    } else {
+      anInfo = myActionsMgr->actionInfoById(anId);
+    }
     if (isEditing) {
       anInfo.text = anInfo.text.prepend("Modify ");
     }