+ if (theFeatures.empty())
+ return false;
+
+ FolderPtr aFirstFeatureFolder =
+ inFolder(theFeatures.front(), ModelAPI_Folder::FIRST_FEATURE_ID());
+ FolderPtr aLastFeatureFolder =
+ inFolder(theFeatures.back(), ModelAPI_Folder::LAST_FEATURE_ID());
+
+ bool isExtractBeforeFolder = theBefore;
+ FolderPtr aFoundFolder =
+ isExtractionCorrect(aFirstFeatureFolder, aLastFeatureFolder, isExtractBeforeFolder);
+ if (!aFoundFolder)
+ return false; // list of features cannot be extracted
+
+ // references of the current folder
+ ObjectPtr aFolderStartFeature;
+ ObjectPtr aFolderEndFeature;
+ if (aFirstFeatureFolder != aLastFeatureFolder) {
+ aFolderStartFeature = aFoundFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID())->value();
+ aFolderEndFeature = aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID())->value();
+ }
+
+ FeaturePtr aFeatureToFind = isExtractBeforeFolder ? theFeatures.back() : theFeatures.front();
+ std::shared_ptr<Model_Data> aData =
+ std::static_pointer_cast<Model_Data>(aFeatureToFind->data());
+ if (!aData || !aData->isValid())
+ return false;
+ TDF_Label aLabelToFind = aData->label().Father();
+
+ // search the label in the list of references
+ TDF_Label aFeaturesLab = featuresLabel();
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+ return false; // no reference array (something is wrong)
+ int aRefIndex = aRefs->Lower();
+ for (; aRefIndex <= aRefs->Upper(); ++aRefIndex)
+ if (aRefs->Value(aRefIndex) == aLabelToFind)
+ break;
+
+ // update folder position
+ if (isExtractBeforeFolder) {
+ aData = std::dynamic_pointer_cast<Model_Data>(aFoundFolder->data());
+ TDF_Label aFolderLabel = aData->label().Father();
+ TDF_Label aPrevFeatureLabel = aRefs->Value(aRefIndex);
+ // update start reference of the folder
+ if (aFolderStartFeature.get()) {
+ FeaturePtr aNewStartFeature;
+ do { // skip all features placed in the composite features
+ aPrevFeatureLabel = aRefs->Value(aRefIndex++);
+ aNewStartFeature =
+ aRefIndex <= aRefs->Upper() ? feature(aRefs->Value(aRefIndex)) : FeaturePtr();
+ } while (aNewStartFeature && isSkippedFeature(aNewStartFeature));
+ aFolderStartFeature = aNewStartFeature;
+ }
+ // move the folder in the list of references after the last feature from the list
+ RemoveFromRefArray(aFeaturesLab, aFolderLabel);
+ AddToRefArray(aFeaturesLab, aFolderLabel, aPrevFeatureLabel);
+ } else {
+ // update end reference of the folder
+ if (aFolderEndFeature.get()) {
+ FeaturePtr aNewEndFeature;
+ do { // skip all features placed in the composite features
+ --aRefIndex;
+ aNewEndFeature =
+ aRefIndex >= aRefs->Lower() ? feature(aRefs->Value(aRefIndex)) : FeaturePtr();
+ } while (aNewEndFeature && isSkippedFeature(aNewEndFeature));
+ aFolderEndFeature = aNewEndFeature;
+ }
+ }
+
+ // update folder references
+ aFoundFolder->reference(ModelAPI_Folder::FIRST_FEATURE_ID())->setValue(aFolderStartFeature);
+ aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID())->setValue(aFolderEndFeature);
+
+ updateHistory(ModelAPI_Feature::group());
+ return true;
+}
+
+FolderPtr Model_Objects::findContainingFolder(const FeaturePtr& theFeature, int& theIndexInFolder)
+{
+ // search the label in the list of references
+ TDF_Label aFeaturesLab = featuresLabel();
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
+ return FolderPtr(); // no reference array (something is wrong)
+
+ std::shared_ptr<Model_Data> aData =
+ std::static_pointer_cast<Model_Data>(theFeature->data());
+ if (!aData || !aData->isValid())
+ return FolderPtr();
+ TDF_Label aLabelToFind = aData->label().Father();
+
+ theIndexInFolder = -1;
+ FolderPtr aFoundFolder;
+ TDF_Label aLastFeatureLabel;
+
+ for (int aRefIndex = aRefs->Lower(); aRefIndex <= aRefs->Upper(); ++aRefIndex) {
+ TDF_Label aCurLabel = aRefs->Value(aRefIndex);
+
+ if (aFoundFolder)
+ ++theIndexInFolder;
+
+ if (aCurLabel == aLabelToFind) { // the feature is reached
+ if (aFoundFolder) {
+ if (isSkippedFeature(theFeature)) {
+ theIndexInFolder = -1;
+ return FolderPtr();
+ }
+ // decrease the index of the feature in the folder by the number of skipped features
+ for (int anIndex = theIndexInFolder - 1; anIndex > 0; anIndex--) {
+ aCurLabel = aRefs->Value(aRefIndex - anIndex);
+ if (isSkippedFeature(feature(aCurLabel)))
+ theIndexInFolder--;
+ }
+ }
+ return aFoundFolder;
+ }
+
+ if (!aFoundFolder) {
+ // if the current label refers to a folder, feel all necessary data
+ const ObjectPtr& aFolderObj = folder(aCurLabel);
+ if (aFolderObj.get()) {
+ aFoundFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(aFolderObj);
+ theIndexInFolder = -1;
+
+ AttributeReferencePtr aLastRef =
+ aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID());
+ if (aLastRef->value()) {
+ aData = std::static_pointer_cast<Model_Data>(aLastRef->value()->data());
+ if (aData && aData->isValid())
+ aLastFeatureLabel = aData->label().Father();
+ } else // folder is empty
+ aFoundFolder = FolderPtr();
+ }
+ } else if (aLastFeatureLabel == aCurLabel) {
+ // folder is finished, clear all stored data
+ theIndexInFolder = -1;
+ aFoundFolder = FolderPtr();
+ }
+ }
+
+ // folder is not found
+ theIndexInFolder = -1;
+ return FolderPtr();