+//**************************************************************
+// Returns the list of all features for theDocument and all features of
+// all nested parts.
+std::list<FeaturePtr> allFeatures(const DocumentPtr& theDocument)
+{
+ std::list<FeaturePtr> aResultList;
+ std::list<FeaturePtr> anAllFeatures = theDocument->allFeatures();
+ foreach (const FeaturePtr& aFeature, anAllFeatures) {
+ // The order of appending features of the part and the part itself is important
+
+ // Append features from a part feature
+ std::list<ResultPtr> aResults;
+ ModelAPI_Tools::allResults(aFeature, aResults);
+ foreach (const ResultPtr& aResult, aResults) {
+ ResultPartPtr aResultPart =
+ std::dynamic_pointer_cast<ModelAPI_ResultPart>(aResult);
+ if (aResultPart.get() && aResultPart->partDoc().get()) {
+ // Recursion
+ std::list<FeaturePtr> anAllFeatures = allFeatures(aResultPart->partDoc());
+ aResultList.insert(aResultList.end(), anAllFeatures.begin(), anAllFeatures.end());
+ }
+ }
+
+ aResultList.push_back(aFeature);
+ }
+ return aResultList;
+}
+
+//**************************************************************
+// 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 = allFeatures(aDocument);
+ // 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()
+{
+ QString anActionId = "MOVE_CMD";
+
+ QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
+ QObjectPtrList aValidatedObjects;
+ foreach (ObjectPtr aObject, aObjects) {
+ if (!myModule->canApplyAction(aObject, anActionId))
+ continue;
+ // To be moved feature should be in active document
+ if (aObject->document() != ModelAPI_Session::get()->activeDocument())
+ continue;
+ aValidatedObjects.append(aObject);
+ }
+ if (aValidatedObjects.size() != aObjects.size())
+ aObjects = aValidatedObjects;
+
+ bool aCanMove = !aObjects.empty();
+
+ QObjectPtrList::const_iterator anIt = aObjects.begin(), aLast = aObjects.end();
+ for (; anIt != aLast && aCanMove; anIt++) {
+ ObjectPtr aObject = *anIt;
+ // 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())
+ aCanMove = false;
+ else {
+ std::set<FeaturePtr> aPlacedFeatures(aFeaturesBetween.begin(), aFeaturesBetween.end());
+ // 2. Get all reference features to the selected object in the document
+ std::set<FeaturePtr> aRefFeatures;
+ ModuleBase_Tools::refsToFeatureInFeatureDocument(aObject, aRefFeatures);
+
+ if (aRefFeatures.empty())
+ continue;
+ else {
+ // 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 current feature
+ if (!aIntersectionFeatures.empty())
+ aCanMove = false;
+ }
+ }
+ }
+ return aCanMove;
+}
+
+//**************************************************************
+bool XGUI_Workshop::canBeShaded(const ObjectPtr& theObject) const
+{
+ bool aCanBeShaded = myDisplayer->canBeShaded(theObject);
+ if (!aCanBeShaded) {
+ ResultCompSolidPtr aCompsolidResult =
+ std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
+ if (aCompsolidResult.get() != NULL) { // change colors for all sub-solids
+ for(int i = 0; i < aCompsolidResult->numberOfSubs() && !aCanBeShaded; i++)
+ aCanBeShaded = myDisplayer->canBeShaded(aCompsolidResult->subResult(i));
+ }
+ }
+ return aCanBeShaded;
+}
+