Salome HOME
Issue #662 Warning on remove or rename of (may be) used object in PartSet
[modules/shaper.git] / src / XGUI / XGUI_Workshop.cpp
index ee91afe7628823881dfc65949ecb442f1443d709..3f044f918a247debc6135b072a2395a1321cc827 100644 (file)
 #include "XGUI_PropertyPanel.h"
 #include "XGUI_ContextMenuMgr.h"
 #include "XGUI_ModuleConnector.h"
+#include "XGUI_WorkshopListener.h"
+
 #include <XGUI_QtEvents.h>
 #include <XGUI_HistoryMenu.h>
+#include <XGUI_CustomPrs.h>
 
 #include <AppElements_Workbench.h>
 #include <AppElements_Viewer.h>
@@ -49,7 +52,6 @@
 #include <Events_Error.h>
 #include <Events_LongOp.h>
 
-#include <ModuleBase_Operation.h>
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_OperationDescription.h>
 #include <ModuleBase_SelectionValidator.h>
@@ -67,6 +69,8 @@
 #include <Config_PropManager.h>
 #include <Config_SelectionFilterMessage.h>
 
+#include <SUIT_ResourceMgr.h>
+
 #include <QApplication>
 #include <QFileDialog>
 #include <QMessageBox>
@@ -79,6 +83,7 @@
 #include <QMenu>
 #include <QToolButton>
 #include <QAction>
+#include <QDesktopWidget>
 
 #ifdef _DEBUG
 #include <QDebug>
@@ -91,9 +96,7 @@
 #include <dlfcn.h>
 #endif
 
-//#define DEBUG_FEATURE_CREATED
-//#define DEBUG_FEATURE_REDISPLAY
-
+//#define DEBUG_DELETE
 
 XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
     : QObject(),
@@ -102,21 +105,27 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
       mySalomeConnector(theConnector),
       myPropertyPanel(0),
       myObjectBrowser(0),
-      myDisplayer(0),
-      myUpdatePrefs(false),
-      myPartActivating(false),
-      myIsLoadingData(false)
+      myDisplayer(0)
 {
   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);
   //connect(mySelector, SIGNAL(selectionChanged()), this, SLOT(updateModuleCommands()));
 
-  myOperationMgr = new XGUI_OperationMgr(this);
+  myOperationMgr = new XGUI_OperationMgr(this, 0);
   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)));
@@ -127,6 +136,11 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
 
   myModuleConnector = new XGUI_ModuleConnector(this);
 
+  ModuleBase_IWorkshop* aWorkshop = moduleConnector();
+  myOperationMgr->setWorkshop(aWorkshop);
+
+  myEventsListener = new XGUI_WorkshopListener(aWorkshop);
+
   connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)), 
           SLOT(onOperationStarted(ModuleBase_Operation*)));
   connect(myOperationMgr, SIGNAL(operationResumed(ModuleBase_Operation*)),
@@ -137,8 +151,23 @@ 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&)));
+  connect(myEventsListener, SIGNAL(errorOccurred(const QString&)),
+          myErrorDlg, SLOT(addError(const QString&)));
+
+  //Config_PropManager::registerProp("Visualization", "object_default_color", "Object color",
+  //                                 Config_Prop::Color, "225,225,225");
+
+  Config_PropManager::registerProp("Visualization", "result_body_color", "Body color",
+                                   Config_Prop::Color, ModelAPI_ResultBody::DEFAULT_COLOR());
+  Config_PropManager::registerProp("Visualization", "result_group_color", "Group color",
+                                   Config_Prop::Color, ModelAPI_ResultGroup::DEFAULT_COLOR());
+  Config_PropManager::registerProp("Visualization", "result_construction_color", "Construction color",
+                                   Config_Prop::Color, ModelAPI_ResultConstruction::DEFAULT_COLOR());
+  Config_PropManager::registerProp("Visualization", "result_part_color", "Part color",
+                                   Config_Prop::Color, ModelAPI_ResultPart::DEFAULT_COLOR());
 }
 
 //******************************************************
@@ -156,28 +185,14 @@ void XGUI_Workshop::startApplication()
                                    Config_Prop::Directory, "");
 
   //Initialize event listening
-  Events_Loop* aLoop = Events_Loop::loop();
-  aLoop->registerListener(this, Events_Error::errorID());  //!< Listening application errors.
-  aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT()));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OPERATION_LAUNCHED));
-  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_LongOp::eventID());
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED));
-  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));
+  myEventsListener->initializeEventListening();
 
   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();
@@ -188,6 +203,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()
 {
@@ -233,7 +271,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();
@@ -295,124 +333,6 @@ AppElements_Workbench* XGUI_Workshop::addWorkbench(const QString& theName)
   return aMenuBar->addWorkbench(theName);
 }
 
-//******************************************************
-void XGUI_Workshop::processEvent(const std::shared_ptr<Events_Message>& theMessage)
-{
-  if (QApplication::instance()->thread() != QThread::currentThread()) {
-    #ifdef _DEBUG
-    std::cout << "XGUI_Workshop::processEvent: " << "Working in another thread." << std::endl;
-    #endif
-    SessionPtr aMgr = ModelAPI_Session::get();
-    PostponeMessageQtEvent* aPostponeEvent = new PostponeMessageQtEvent(theMessage);
-    QApplication::postEvent(this, aPostponeEvent);
-    return;
-  }
-
-  //A message to start feature creation received.
-  if (theMessage->eventID() == Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) {
-    std::shared_ptr<Config_FeatureMessage> aFeatureMsg =
-       std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
-    if (!aFeatureMsg->isInternal()) {
-      addFeature(aFeatureMsg);
-    }
-  }
-  // Process creation of Part
-  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    onFeatureCreatedMsg(aUpdMsg);
-    if (myUpdatePrefs) {
-      if (mySalomeConnector)
-        mySalomeConnector->createPreferences();
-      myUpdatePrefs = false;
-    }
-  }
-  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_PLUGIN_LOADED)) {
-    myUpdatePrefs = true;
-  }
-  // Redisplay feature
-  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    onFeatureRedisplayMsg(aUpdMsg);
-  }
-  //Update property panel on corresponding message. If there is no current operation (no
-  //property panel), or received message has different feature to the current - do nothing.
-  else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    onFeatureUpdatedMsg(anUpdateMsg);
-  } 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)) {
-    std::shared_ptr<Config_PointerMessage> aPartSetMsg =
-        std::dynamic_pointer_cast<Config_PointerMessage>(theMessage);
-    //myPropertyPanel->cleanContent();
-    ModuleBase_Operation* anOperation = (ModuleBase_Operation*) aPartSetMsg->pointer();
-
-    if (myOperationMgr->startOperation(anOperation)) {
-      myPropertyPanel->updateContentWidget(anOperation->feature());
-      if (!anOperation->getDescription()->hasXmlRepresentation()) {
-        if (anOperation->commit())
-          updateCommandStatus();
-      }
-    }
-  } 
-  else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SELFILTER_LOADED)) {
-    std::shared_ptr<Config_SelectionFilterMessage> aMsg = 
-      std::dynamic_pointer_cast<Config_SelectionFilterMessage>(theMessage);
-    if (aMsg) {
-      ModuleBase_FilterFactory* aFactory = moduleConnector()->selectionFilters();
-      if (!aMsg->attributeId().empty()) {
-        aFactory->assignFilter(aMsg->selectionFilterId(), aMsg->featureId(), aMsg->attributeId(),
-                               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);
-  } else {
-    //Show error dialog if error message received.
-    std::shared_ptr<Events_Error> anAppError = std::dynamic_pointer_cast<Events_Error>(theMessage);
-    if (anAppError) {
-      emit errorOccurred(QString::fromLatin1(anAppError->description()));
-    }
-    return;
-  }
-  if (!isSalomeMode()) {
-    SessionPtr aMgr = ModelAPI_Session::get();
-    if (aMgr->isModified() != myMainWindow->isModifiedState())
-      myMainWindow->setModifiedState(aMgr->isModified());
-  }
-}
-
 //******************************************************
 QMainWindow* XGUI_Workshop::desktop() const
 {
@@ -427,130 +347,14 @@ void XGUI_Workshop::onStartWaiting()
   }
 }
 
-//******************************************************
-void XGUI_Workshop::onFeatureUpdatedMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
-{
-  std::set<ObjectPtr> aFeatures = theMsg->objects();
-  if (myOperationMgr->hasOperation()) {
-    FeaturePtr aCurrentFeature = myOperationMgr->currentOperation()->feature();
-    std::set<ObjectPtr>::const_iterator aIt;
-    for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) {
-      ObjectPtr aNewFeature = (*aIt);
-      if (aNewFeature == aCurrentFeature) {
-        myPropertyPanel->updateContentWidget(aCurrentFeature);
-        break;
-      }
-    }
-  }
-  myOperationMgr->onValidateOperation();
-  //if (myObjectBrowser)
-  //  myObjectBrowser->processEvent(theMsg);
-}
 
 //******************************************************
-void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
+void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer)
 {
-  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)));
+  if (!myModule->canActivateSelection(theObject)) {
+    if (myDisplayer->isActive(theObject))
+      myDisplayer->deactivate(theObject, theUpdateViewer);
   }
-  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);
-
-    // Hide the object if it is invalid or concealed one
-    bool aHide = !aObj->data() || !aObj->data()->isValid();
-    if (!aHide) { // check that this is not hidden result
-      ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
-      aHide = aRes && aRes->isConcealed();
-    }
-    if (aHide)
-      myDisplayer->erase(aObj, false);
-    else {
-      // 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);
-        if (myOperationMgr->hasOperation()) {
-          ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
-          if (!aOperation->isEditOperation() &&
-              aOperation->hasObject(aObj) && myDisplayer->isActive(aObj))
-            myDisplayer->deactivate(aObj);
-        }
-      } else { // display object if the current operation has it
-        ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
-        if (aOperation && aOperation->hasObject(aObj)) {
-          ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
-          #ifdef DEBUG_FEATURE_REDISPLAY
-            QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
-            qDebug(QString("  display object = %1").arg(anObjInfo).toStdString().c_str());
-          #endif
-          if (displayObject(aObj)) {
-            // Deactivate object of current operation from selection
-            if (myDisplayer->isActive(aObj))
-              myDisplayer->deactivate(aObj);
-          }
-        }
-      }
-    }
-  }
-  myDisplayer->updateViewer();
-}
-
-//******************************************************
-void XGUI_Workshop::onFeatureCreatedMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& theMsg)
-{
-  std::set<ObjectPtr> aObjects = theMsg->objects();
-  std::set<ObjectPtr>::const_iterator aIt;
-#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
-
-  //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
-    if (!anObject->data() || !anObject->data()->isValid())
-      continue;
-    //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 {
-    isDisplayed = displayObject(*aIt);
-    //}
-  }
-  //if (myObjectBrowser)
-  //  myObjectBrowser->processEvent(theMsg);
-  if (isDisplayed)
-    myDisplayer->updateViewer();
-  //if (aHasPart) { // TODO: Avoid activate last part on loading of document
-  //  activateLastPart();
-  //}
 }
 
 //******************************************************
@@ -564,7 +368,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();
 }
 
 //******************************************************
@@ -578,7 +397,7 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation)
   }
   updateCommandStatus();
 
-  myModule->operationResumed(theOperation);
+  myModule->onOperationResumed(theOperation);
 }
 
 
@@ -592,39 +411,36 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
   hidePropertyPanel();
   myPropertyPanel->cleanContent();
 
-  // Activate objects created by current operation 
-  // in order to clean selection modes
-  // the deactivation should be pefromed in the same place, where the mode is activated,
-  // e.g. activation in the current widget activation, deactivation - in the widget's deactivation
-  //QIntList aModes;
-  //myDisplayer->activateObjects(aModes);
-  myModule->operationStopped(theOperation);
-
-  // if the operation is nested, do not deactivate objects
-  //if (myOperationMgr->operationsCount() == 0) {
-    // Activate selection mode for all objects
+  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;
-  // TODO: check on OCC_6.9.0
-  // the module current active modes should not be deactivated in order to save the objects selected
-  // the deactivate object in the mode of selection leads to the object is deselected in the viewer.
-  // But, in OCC_6.8.0 this deselection does not happened automatically. It is necessary to call
-  // ClearOutdatedSelection, but this method has an error in the realization, which should be fixed in
-  // the OCC_6.9.0 release. Moreother, it is possible that ClearOutdatedSelection will be called inside
-  // Deactivate method of AIS_InteractiveContext. In this case, we need not call it.
   module()->activeSelectionModes(aModes);
-  myDisplayer->activateObjects(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)
@@ -662,95 +478,6 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation)
   myPropertyPanel->setWindowTitle(theOperation->getDescription()->description());
 }
 
-bool XGUI_Workshop::event(QEvent * theEvent)
-{
-  PostponeMessageQtEvent* aPostponedEv = dynamic_cast<PostponeMessageQtEvent*>(theEvent);
-  if (aPostponedEv) {
-    std::shared_ptr<Events_Message> aEventPtr = aPostponedEv->postponedMessage();
-    processEvent(aEventPtr);
-    return true;
-  }
-  return false;
-}
-
-/*
- *
- */
-void XGUI_Workshop::addFeature(const std::shared_ptr<Config_FeatureMessage>& theMessage)
-{
-  if (!theMessage) {
-#ifdef _DEBUG
-    qDebug() << "XGUI_Workshop::addFeature: NULL message.";
-#endif
-    return;
-  }
-  ActionInfo aFeatureInfo;
-  aFeatureInfo.initFrom(theMessage);
-
-  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;
-    if (isColumnButton) {
-      aAction = salomeConnector()->addNestedFeature(aWchName, aFeatureInfo, aNestedActList);
-    } else {
-      aAction = salomeConnector()->addFeature(aWchName, aFeatureInfo);
-    }
-    salomeConnector()->setNestedActions(aFeatureInfo.id, aNestedFeatures);
-    salomeConnector()->setDocumentKind(aFeatureInfo.id, aDocKind);
-
-    myActionsMgr->addCommand(aAction);
-    myModule->actionCreated(aAction);
-  } else {
-    //Find or create Workbench
-    AppElements_MainMenu* aMenuBar = myMainWindow->menuObject();
-    AppElements_Workbench* aPage = aMenuBar->findWorkbench(aWchName);
-    if (!aPage) {
-      aPage = addWorkbench(aWchName);
-    }
-    //Find or create Group
-    QString aGroupName = QString::fromStdString(theMessage->groupId());
-    AppElements_MenuGroupPanel* aGroup = aPage->findGroup(aGroupName);
-    if (!aGroup) {
-      aGroup = aPage->addGroup(aGroupName);
-    }
-    // Check if hotkey sequence is already defined:
-    QKeySequence aHotKey = myActionsMgr->registerShortcut(aFeatureInfo.shortcut);
-    if(aHotKey != aFeatureInfo.shortcut) {
-      aFeatureInfo.shortcut = aHotKey;
-    }
-    // Create feature...
-    AppElements_Command* aCommand = aGroup->addFeature(aFeatureInfo,
-                                                       aDocKind,
-                                                       aNestedFeatures);
-    // Enrich created button with accept/abort buttons if necessary
-    AppElements_Button* aButton = aCommand->button();
-    if (aButton->isColumnButton()) {
-      aButton->setAdditionalButtons(aNestedActList);
-    }
-    myActionsMgr->addCommand(aCommand);
-    myModule->actionCreated(aCommand);
-  }
-}
-
 /*
  * Makes a signal/slot connections between Property Panel
  * and given operation. The given operation becomes a
@@ -847,12 +574,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 directory"));
   if (myCurrentDir.isEmpty())
     return;
   QFileInfo aFileInfo(myCurrentDir);
@@ -862,12 +588,11 @@ 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();
 }
 
@@ -895,13 +620,14 @@ bool XGUI_Workshop::onSaveAs()
   QFileDialog dialog(mainWindow());
   dialog.setWindowTitle(tr("Select directory to save files..."));
   dialog.setFileMode(QFileDialog::Directory);
-  dialog.setFilter(tr("Folders (*)"));
+  dialog.setFilter(tr("Directories (*)"));
   dialog.setOptions(QFileDialog::HideNameFilterDetails | QFileDialog::ShowDirsOnly);
   dialog.setViewMode(QFileDialog::Detail);
 
   if (!dialog.exec()) {
     return false;
   }
+
   QString aTempDir = dialog.selectedFiles().first();
   QDir aDir(aTempDir);
   if (aDir.exists() && !aDir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).isEmpty()) {
@@ -909,7 +635,7 @@ bool XGUI_Workshop::onSaveAs()
         myMainWindow,
         //: Title of the dialog which asks user if he wants to save study in existing non-empty folder
         tr("Save"),
-        tr("The folder already contains some files, save anyway?"),
+        tr("The directory already contains some files, save anyway?"),
         QMessageBox::Save | QMessageBox::Cancel);
     if (answer == QMessageBox::Cancel) {
       return false;
@@ -933,6 +659,7 @@ void XGUI_Workshop::onUndo(int theTimes)
   for (int i = 0; i < theTimes; ++i) {
     aMgr->undo();
   }
+  updateCompositeActionState();
   updateCommandStatus();
 }
 
@@ -952,6 +679,7 @@ void XGUI_Workshop::onRedo(int theTimes)
   for (int i = 0; i < theTimes; ++i) {
     aMgr->redo();
   }
+  updateCompositeActionState();
   updateCommandStatus();
 
   // unblock the viewer update functionality and make update on purpose
@@ -1057,7 +785,7 @@ 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());
@@ -1065,13 +793,13 @@ bool XGUI_Workshop::activateModule()
   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)));
+  //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;
 }
 
@@ -1088,20 +816,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) {
@@ -1118,6 +842,18 @@ void XGUI_Workshop::updateCommandStatus()
   emit commandStatusUpdated();
 }
 
+//******************************************************
+void XGUI_Workshop::updateCompositeActionState()
+{
+  // in order to apply is enabled only if there are modifications in the model
+  // e.g. sketch can be applyed only if at least one nested element create is finished
+  bool aCanUndo = ModelAPI_Session::get()->canUndo();
+  bool aParentValid = operationMgr()->isParentOperationValid();
+
+  QAction* aAcceptAllAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptAll);
+  aAcceptAllAct->setEnabled(aParentValid && aCanUndo);
+}
+
 void XGUI_Workshop::updateHistory()
 {
   std::list<std::string> aUndoList = ModelAPI_Session::get()->undoList();
@@ -1139,8 +875,7 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent)
       "::title { position: relative; padding-left: 5px; text-align: left center }");
   myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock);
   myObjectBrowser->setDataModel(myModule->dataModel());
-  //connect(myObjectBrowser, SIGNAL(activePartChanged(ObjectPtr)), this,
-  //        SLOT(changeCurrentDocument(ObjectPtr)));
+  myModule->customizeObjectBrowser(myObjectBrowser);
   aObjDock->setWidget(myObjectBrowser);
 
   myContextMenuMgr->connectObjectBrowser();
@@ -1213,15 +948,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::onFeatureTriggered()
+//{
+//  QAction* aCmd = dynamic_cast<QAction*>(sender());
+//  if (aCmd) {
+//    QString aId = salomeConnector()->commandId(aCmd);
+//    if (!aId.isNull())
+//      myModule->launchOperation(aId);
+//  }
+//}
 
 //******************************************************
 void XGUI_Workshop::salomeViewerSelectionChanged()
@@ -1241,6 +976,8 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
   QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
   if (theId == "DELETE_CMD")
     deleteObjects();
+  if (theId == "MOVE_CMD")
+    moveObjects();
   else if (theId == "COLOR_CMD")
     changeColor(aObjects);
   else if (theId == "SHOW_CMD")
@@ -1253,8 +990,12 @@ 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 == "HIDEALL_CMD") {
+    QObjectPtrList aList = myDisplayer->displayedObjects();
+    foreach (ObjectPtr aObj, aList)
+      aObj->setDisplayed(false);
+    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+  }
 }
 
 //**************************************************************
@@ -1270,10 +1011,15 @@ void XGUI_Workshop::deleteObjects()
   if (!isActiveOperationAborted())
     return;
   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
+  // check whether the object can be deleted. There should not be parts which are not loaded
+  if (!XGUI_Tools::canRemoveOrRename(myMainWindow, anObjects))
+    return;
+
   bool hasResult = false;
   bool hasFeature = false;
   bool hasParameter = false;
-  ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter);
+  bool hasSubFeature = false;
+  ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter, hasSubFeature);
   if (!(hasFeature || hasParameter))
     return;
 
@@ -1282,7 +1028,7 @@ void XGUI_Workshop::deleteObjects()
   aDescription += tr(" %1");
   QStringList aObjectNames;
   foreach (ObjectPtr aObj, anObjects) {
-    if (!aObj->data().get())
+    if (!aObj->data()->isValid())
       continue;
     aObjectNames << QString::fromStdString(aObj->data()->name());
   }
@@ -1291,7 +1037,8 @@ void XGUI_Workshop::deleteObjects()
   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
-  foreach (ObjectPtr aObj, anObjects)
+  // this is performed in the RemoveFeature of Part object.
+  /*foreach (ObjectPtr aObj, anObjects)
   {
     ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
     if (aPart) {
@@ -1300,7 +1047,7 @@ void XGUI_Workshop::deleteObjects()
         aDoc->close();
       }
     }
-  }
+  }*/
   // 3. delete objects
   QMainWindow* aDesktop = isSalomeMode() ? salomeConnector()->desktop() : myMainWindow;
   std::set<FeaturePtr> anIgnoredFeatures;
@@ -1314,19 +1061,135 @@ void XGUI_Workshop::deleteObjects()
   }
 }
 
+//**************************************************************
+void XGUI_Workshop::moveObjects()
+{
+  if (!isActiveOperationAborted())
+    return;
+
+  SessionPtr aMgr = ModelAPI_Session::get();
+
+  QString aDescription = contextMenuMgr()->action("MOVE_CMD")->text();
+  aMgr->startOperation(aDescription.toStdString());
+
+  QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
+  DocumentPtr anActiveDocument = aMgr->activeDocument();
+
+  FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true);
+  foreach (ObjectPtr aObj, anObjects) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+    if (aFeature.get()) {
+      anActiveDocument->moveFeature(aFeature, aCurrentFeature);
+      aCurrentFeature = anActiveDocument->currentFeature(true);
+    }
+  }
+  aMgr->finishOperation();
+}
+
+//**************************************************************
+std::set<FeaturePtr> refFeatures(const ObjectPtr& theObject, 
+                                 bool checkAllDocuments = true,
+                                 bool useRecursion = false)
+{
+  std::set<FeaturePtr> aRefFeatures;
+  FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+  if (!aFeature.get())
+    return aRefFeatures;
+
+  DocumentPtr aFeatureDoc = aFeature->document();
+  // 1. find references in the current document
+  aFeatureDoc->refsToFeature(aFeature, aRefFeatures, false);
+
+  // 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
+  if (checkAllDocuments) {
+    SessionPtr aMgr = ModelAPI_Session::get();
+    DocumentPtr aModuleDoc = aMgr->moduleDocument();
+    if (aFeatureDoc == aModuleDoc) {
+      // the feature and results of the feature should be found in references
+      std::list<ObjectPtr> aObjects;
+      aObjects.push_back(aFeature);
+      typedef std::list<std::shared_ptr<ModelAPI_Result> > ResultsList;
+      const ResultsList& aResults = aFeature->results();
+      ResultsList::const_iterator aRIter = aResults.begin();
+      for (; aRIter != aResults.cend(); aRIter++) {
+        ResultPtr aRes = *aRIter;
+        if (aRes.get())
+          aObjects.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.
+    SessionPtr aMgr = ModelAPI_Session::get();
+      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 == aFeatureDoc)
+          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 aHasReferenceToObjetc = false;
+          for(; aRef != aRefs.end() && !aHasReferenceToObjetc; aRef++) {
+            std::list<ObjectPtr>::iterator aRefObj = aRef->second.begin();
+            for(; aRefObj != aRef->second.end() && !aHasReferenceToObjetc; aRefObj++) {
+              std::list<ObjectPtr>::const_iterator aObjIt = aObjects.begin();
+              for(; aObjIt != aObjects.end() && !aHasReferenceToObjetc; aObjIt++) {
+                aHasReferenceToObjetc = *aObjIt == *aRefObj;
+              }
+            }
+          }
+          if (aHasReferenceToObjetc)
+            aRefFeatures.insert(aFeature);
+        }
+      }
+    }
+  }
+
+  // Run recursion 
+  if (useRecursion) {
+    std::set<FeaturePtr>::const_iterator aFeatureIt = aRefFeatures.begin();
+    for (; aFeatureIt != aRefFeatures.end(); ++aFeatureIt) {
+      std::set<FeaturePtr> aRecursiveRefFeatures = refFeatures(*aFeatureIt, checkAllDocuments, useRecursion);
+      aRefFeatures.insert(aRecursiveRefFeatures.begin(), aRecursiveRefFeatures.end());
+    } 
+  }
+
+  return aRefFeatures;
+}
+
 //**************************************************************
 bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
-                                   std::set<FeaturePtr> theIgnoredFeatures,
+                                   const std::set<FeaturePtr>& theIgnoredFeatures,
                                    QWidget* theParent,
                                    const bool theAskAboutDeleteReferences)
 {
+#ifdef DEBUG_DELETE
+  QStringList aDInfo;
+  QObjectPtrList::const_iterator aDIt = theList.begin(), aDLast = theList.end();
+  for (; aDIt != aDLast; ++aDIt) {
+    aDInfo.append(ModuleBase_Tools::objectInfo((*aDIt)));
+  }
+  QString anInfoStr = aDInfo.join(", ");
+  qDebug(QString("deleteFeatures: %1, %2").arg(theList.size()).arg(anInfoStr).toStdString().c_str());
+#endif
+
   // 1. find all referenced features
   std::set<FeaturePtr> aRefFeatures;
-  foreach (ObjectPtr aObj, theList) {
-    FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
-    if (aFeature.get() != NULL) {
-      aObj->document()->refsToFeature(aFeature, aRefFeatures, false);
-    }
+  foreach (ObjectPtr aDeletedObj, theList) {
+    std::set<FeaturePtr> aFeatures = refFeatures(aDeletedObj, true, true);
+    aRefFeatures.insert(aFeatures.begin(), aFeatures.end());
   }
   // 2. warn about the references remove, break the delete operation if the user chose it
   if (theAskAboutDeleteReferences && !aRefFeatures.empty()) {
@@ -1350,22 +1213,55 @@ These features will be deleted also. Would you like to continue?")).arg(aNames),
   // 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 aFeature = (*anIt);
     DocumentPtr aDoc = aFeature->document();
-    if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end())
+    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
 
+  QString anId = QString::fromStdString("DELETE_CMD");
+  QStringList anObjectGroups = contextMenuMgr()->actionObjectGroups(anId);
   // 4. remove the parameter features
   foreach (ObjectPtr aObj, theList) {
+    // features and parameters can be removed here,
+    // the results are removed only by a corresponded feature remove
+    std::string aGroupName = aObj->groupName();
+    if (!anObjectGroups.contains(aGroupName.c_str()))
+      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())
+      if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) {
+#ifdef DEBUG_DELETE
+        QString anInfoStr = ModuleBase_Tools::objectInfo(aFeature);
+        anInfo.append(anInfoStr);
+        qDebug(QString("remove feature :%1").arg(anInfoStr).toStdString().c_str());
+#endif
         aDoc->removeFeature(aFeature);
+      }
     }
   }
+#ifdef DEBUG_DELETE
+  qDebug(QString("remove features:%1").arg(anInfo.join("; ")).toStdString().c_str());
+#endif
   return true;
 }
 
@@ -1385,6 +1281,58 @@ bool hasResults(QObjectPtrList theObjects, const std::set<std::string>& theTypes
   return isFoundResultType;
 }
 
+//**************************************************************
+// Returns the list of features placed between theObject and the current feature
+// in the same document. Excludes theObject, includes the current feature.
+std::list<FeaturePtr> toCurrentFeatures(const ObjectPtr& theObject)
+{
+  std::list<FeaturePtr> aResult;
+  DocumentPtr aDocument = theObject->document();
+  std::list<FeaturePtr> anAllFeatures = aDocument->allFeatures();
+  // find the object iterator
+  std::list<FeaturePtr>::iterator aObjectIt = std::find(anAllFeatures.begin(), anAllFeatures.end(), theObject);
+  if (aObjectIt == anAllFeatures.end()) 
+    return aResult;
+  // find the current feature iterator
+  std::list<FeaturePtr>::iterator aCurrentIt = std::find(anAllFeatures.begin(), anAllFeatures.end(), aDocument->currentFeature(true));
+  if (aCurrentIt == anAllFeatures.end()) 
+    return aResult;
+  // check the right order
+  if (std::distance(aObjectIt, anAllFeatures.end()) <= std::distance(aCurrentIt, anAllFeatures.end()))
+    return aResult;
+  // exclude the object
+  std::advance(aObjectIt, 1);
+  // include the current feature
+  std::advance(aCurrentIt, 1);
+  return std::list<FeaturePtr>(aObjectIt, aCurrentIt);
+}
+
+bool XGUI_Workshop::canMoveFeature()
+{
+  QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
+  foreach (ObjectPtr aObject, aObjects) {
+    // 1. Get features placed between selected and current in the document 
+    std::list<FeaturePtr> aFeaturesBetween = toCurrentFeatures(aObject);
+    // if aFeaturesBetween is empty it means wrong order or aObject is the current feature
+    if (aFeaturesBetween.empty())
+      return false;
+    std::set<FeaturePtr> aPlacedFeatures(aFeaturesBetween.begin(), aFeaturesBetween.end());
+    // 2. Get all reference features to the selected object in the document 
+    std::set<FeaturePtr> aRefFeatures = refFeatures(aObject, false);
+    if (aRefFeatures.empty())
+      continue;
+    // 3. Find any placed features in all reference features
+    std::set<FeaturePtr> aIntersectionFeatures;
+    std::set_intersection(aRefFeatures.begin(), aRefFeatures.end(),
+                          aPlacedFeatures.begin(), aPlacedFeatures.end(),
+                          std::inserter(aIntersectionFeatures, aIntersectionFeatures.begin()));
+    // 4. Return false if any reference feature is placed before curent feature
+    if (!aIntersectionFeatures.empty())
+      return false;
+  }
+  return true;
+}
+
 //**************************************************************
 bool XGUI_Workshop::canChangeColor() const
 {
@@ -1423,29 +1371,14 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
   // The objects are iterated until a first valid color is found 
   std::vector<int> aColor;
   foreach(ObjectPtr anObject, theObjects) {
-    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()) {
-            std::string aSection, aName, aDefault;
-            aBody->colorConfigInfo(aSection, aName, aDefault);
-            if (!aSection.empty() && !aName.empty()) {
-              aColor = Config_PropManager::color(aSection, aName, aDefault);
-            }
-          }
-        }
-      }
-    }
+    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);
@@ -1480,24 +1413,8 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
   foreach(ObjectPtr anObj, theObjects) {
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
     if (aResult.get() != NULL) {
-      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);
-          }
-        }
-      }
-      else {
-        std::vector<int> aColorResult = aDlg->getColor();
-        setColor(aResult, aColorResult);
-      }
+      std::vector<int> aColorResult = aDlg->getColor();
+      setColor(aResult, aColorResult);
     }
   }
   if (!aWasOperation)
@@ -1506,23 +1423,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));
+
 }
 
 
@@ -1534,7 +1480,7 @@ void XGUI_Workshop::registerValidators() const
 }
 
 //**************************************************************
-void XGUI_Workshop::displayAllResults()
+/*void XGUI_Workshop::displayAllResults()
 {
   SessionPtr aMgr = ModelAPI_Session::get();
   DocumentPtr aRootDoc = aMgr->moduleDocument();
@@ -1545,7 +1491,7 @@ void XGUI_Workshop::displayAllResults()
     displayDocumentResults(aPart->partDoc());
   }
   myDisplayer->updateViewer();
-}
+}*/
 
 //**************************************************************
 void XGUI_Workshop::displayDocumentResults(DocumentPtr theDoc)
@@ -1559,8 +1505,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));
 }
 
 //**************************************************************
@@ -1587,25 +1535,6 @@ void XGUI_Workshop::closeDocument()
 
   SessionPtr aMgr = ModelAPI_Session::get();
   aMgr->closeAll();
-  objectBrowser()->clearContent();
-}
-
-//**************************************************************
-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 if (!(myIsLoadingData || myPartActivating))
-    myDisplayer->display(theObj, false);
-
-  return true;
 }
 
 void XGUI_Workshop::addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot)