Salome HOME
updated copyright message
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_UseCaseBuilder.cxx
index a7ab40d02460a0c504b32a3c8279f1b0e57409de..6c00f01a73e03e2922ae47457f3ac7a8ccb3ce2f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 #include "DF_ChildIterator.hxx"
 
+#include <list>
+
 #define USE_CASE_LABEL_TAG           2
 #define USE_CASE_GUID                "AA43BB12-D9CD-11d6-945D-0050DA506788"
 
+namespace {
+  // comparator to sort use case nodes in ascending order
+  struct AscSortSOs {
+    bool operator()( SALOMEDSImpl_SObject firstSO, SALOMEDSImpl_SObject secondSO ) const {
+      std::string firstName, secondName;
+      SALOMEDSImpl_SObject refSO;
+      firstSO.ReferencedObject(refSO) ?
+        firstName = refSO.GetName() :
+        firstName = firstSO.GetName();
+      secondSO.ReferencedObject(refSO) ?
+        secondName = refSO.GetName() :
+        secondName = secondSO.GetName();
+      return firstName < secondName;
+    }
+  };
+
+  // comparator to sort use case nodes in descending order
+  struct DescSortSOs {
+    bool operator()( SALOMEDSImpl_SObject firstSO, SALOMEDSImpl_SObject secondSO ) const {
+      std::string firstName, secondName;
+      SALOMEDSImpl_SObject refSO;
+      firstSO.ReferencedObject(refSO) ?
+        firstName = refSO.GetName() :
+        firstName = firstSO.GetName();
+      secondSO.ReferencedObject(refSO) ?
+        secondName = refSO.GetName() :
+        secondName = secondSO.GetName();
+      return firstName > secondName;
+    }
+  };
+}
 
 //============================================================================
 /*! Function : constructor
@@ -42,7 +75,7 @@
  */
 //============================================================================
 SALOMEDSImpl_UseCaseBuilder::SALOMEDSImpl_UseCaseBuilder(DF_Document* theDocument)
-:_doc(theDocument)
+  :_doc(theDocument), _lastChild(0), _childIndex(-1)
 {
   if(!_doc) return;
   
@@ -94,18 +127,19 @@ bool SALOMEDSImpl_UseCaseBuilder::Append(const SALOMEDSImpl_SObject& theObject)
   }  
 
   DF_Label aCurrent = aRef->Get();
-  if(aCurrent.IsNull() || !(aCurrentNode=(SALOMEDSImpl_AttributeTreeNode*)aCurrent.FindAttribute(_root->ID()))) 
+  if(aCurrent.IsNull() || !(aCurrentNode=(SALOMEDSImpl_AttributeTreeNode*)aCurrent.FindAttribute(_root->ID())))
     aCurrentNode = _root;
 
-  aCurrentNode->Append(aNode);
+  aCurrentNode->Append(aNode, &_childIndex);
+  _lastChild = aNode;
 
   // Mantis issue 0020136: Drag&Drop in OB
-  theObject.GetStudy()->addSO_Notification(theObject);
+  SALOMEDSImpl_Study::GetStudyImpl(theObject.GetLabel())->addSO_Notification(theObject);
 
   return true;
 }
 
- //============================================================================
+//============================================================================
 /*! Function : Remove
  *  Purpose  :
  */
@@ -114,12 +148,15 @@ bool SALOMEDSImpl_UseCaseBuilder::Remove(const SALOMEDSImpl_SObject& theObject)
 {
   if(!_root || !theObject) return false;
 
-  DF_Label aLabel = theObject.GetLabel();   
+  DF_Label aLabel = theObject.GetLabel();
   if(aLabel.IsNull()) return false;
 
   SALOMEDSImpl_AttributeTreeNode* aNode = NULL;
   if(!(aNode=(SALOMEDSImpl_AttributeTreeNode*)aLabel.FindAttribute(_root->ID()))) return false;
 
+  if ( _lastChild && aNode->GetFather() == _lastChild->GetFather() )
+    _lastChild = 0;
+
   aNode->Remove();
 
   std::vector<DF_Attribute*> aList;
@@ -127,16 +164,16 @@ bool SALOMEDSImpl_UseCaseBuilder::Remove(const SALOMEDSImpl_SObject& theObject)
 
   SALOMEDSImpl_AttributeReference* aRef = NULL;
   if(!(aRef=(SALOMEDSImpl_AttributeReference*)_root->FindAttribute(SALOMEDSImpl_AttributeReference::GetID()))) {
-    aRef = SALOMEDSImpl_AttributeReference::Set(_root->Label(), _root->Label());  
-  }  
+    aRef = SALOMEDSImpl_AttributeReference::Set(_root->Label(), _root->Label());
+  }
 
   DF_Label aCurrent = aRef->Get();
 
   SALOMEDSImpl_ChildNodeIterator aChildItr(aNode, true);
-  for(; aChildItr.More(); aChildItr.Next()) 
+  for(; aChildItr.More(); aChildItr.Next())
     aList.push_back(aChildItr.Value());
 
-  for(int i = 0, len = aList.size(); i<len; i++) {
+  for(size_t i = 0, len = aList.size(); i<len; i++) {
     if(aList[i]->Label() ==  aCurrent) { //The current node is removed
       aRef->Set(_root->Label()); //Reset the current node to the root
     }
@@ -170,22 +207,93 @@ bool SALOMEDSImpl_UseCaseBuilder::AppendTo(const SALOMEDSImpl_SObject& theFather
     aNode = SALOMEDSImpl_AttributeTreeNode::Set(aLabel, _root->ID());
   }
 
+  if ( aNode == _lastChild && !_lastChild->HasNext() && _lastChild->GetFather() == aFather )
+    return true; // aNode is already the last child
+
   aNode->Remove();
 
-  bool ret = aFather->Append(aNode);
+  bool ret = true;
+  if ( _lastChild && _lastChild->GetFather() == aFather &&
+       !_lastChild->HasNext() ) // _lastChild is the last under aFather
+  {
+    _lastChild->InsertAfter( aNode );
+    _lastChild = aNode;
+    ++_childIndex;
+  }
+  else
+  {
+    ret = aFather->Append(aNode, &_childIndex);
+    _lastChild  = aNode;
+  }
 
   // Mantis issue 0020136: Drag&Drop in OB
-  theObject.GetStudy()->addSO_Notification(theObject);
+  SALOMEDSImpl_Study::GetStudyImpl(theObject.GetLabel())->addSO_Notification(theObject);
 
   return ret;
 }
 
+//============================================================================
+/*! Function : GetIndexInFather
+ *  Purpose  :
+ */
+//============================================================================
+int SALOMEDSImpl_UseCaseBuilder::GetIndexInFather(const SALOMEDSImpl_SObject& theFather, 
+                                                  const SALOMEDSImpl_SObject& theObject)
+{
+  int index = -1;
+  if(!_root || !theFather || !theObject) return index;
+
+  DF_Label aFatherLabel = theFather.GetLabel(), aLabel = theObject.GetLabel();
+  if(aFatherLabel == aLabel) return index;
+
+  SALOMEDSImpl_AttributeTreeNode *aFather = NULL, *aNode = NULL;
+  
+  if(aFatherLabel.IsNull()) return index;
+  if(!(aFather=(SALOMEDSImpl_AttributeTreeNode*)aFatherLabel.FindAttribute(_root->ID()))) return index;
+
+  if(aLabel.IsNull()) return index;
+  if(!(aNode=(SALOMEDSImpl_AttributeTreeNode*)aLabel.FindAttribute(_root->ID()))) {
+    aNode = SALOMEDSImpl_AttributeTreeNode::Set(aLabel, _root->ID());
+  }
+
+  if ( _lastChild && _lastChild->GetFather() == aFather )
+  {
+    if ( aNode == _lastChild )
+      index = _childIndex;
+    else if ( aNode == _lastChild->GetPrevious())
+      index = _childIndex - 1;
+    else if ( aNode == _lastChild->GetNext())
+    {
+      index = ++_childIndex;
+      _lastChild = aNode;
+    }
+  }
+
+  if ( index < 0 )
+  {
+    SALOMEDSImpl_AttributeTreeNode* Last = aFather->GetFirst();
+    for ( index = 0; Last && aNode != Last && Last->HasNext(); ++index )
+    {
+      Last = Last->GetNext();
+    }
+    if ( Last != aNode )
+      index = -1;
+    else if ( !Last->HasNext() )
+    {
+      _lastChild = Last;
+      _childIndex = index;
+    }
+  }
+
+  return index;
+}
+
 //============================================================================
 /*! Function : InsertBefore
  *  Purpose  :
  */
 //============================================================================
-bool SALOMEDSImpl_UseCaseBuilder::InsertBefore(const SALOMEDSImpl_SObject& theFirst, 
+bool SALOMEDSImpl_UseCaseBuilder::InsertBefore(const SALOMEDSImpl_SObject& theFirst,
                                                const SALOMEDSImpl_SObject& theNext)
 {
   if(!_root || !theFirst || !theNext) return false;
@@ -194,7 +302,7 @@ bool SALOMEDSImpl_UseCaseBuilder::InsertBefore(const SALOMEDSImpl_SObject& theFi
   if(aFirstLabel == aLabel) return false;
 
   SALOMEDSImpl_AttributeTreeNode *aFirstNode = NULL, *aNode = NULL;
-  
+
   if(aFirstLabel.IsNull()) return false;
   if((aFirstNode=(SALOMEDSImpl_AttributeTreeNode*)aFirstLabel.FindAttribute(_root->ID()))) {
     aFirstNode->Remove();
@@ -202,16 +310,24 @@ bool SALOMEDSImpl_UseCaseBuilder::InsertBefore(const SALOMEDSImpl_SObject& theFi
   }
 
   aFirstNode = SALOMEDSImpl_AttributeTreeNode::Set(aFirstLabel, _root->ID());
-  
+
   if(aLabel.IsNull()) return false;
-  if(!(aNode=(SALOMEDSImpl_AttributeTreeNode*)aLabel.FindAttribute(_root->ID()))) return false;    
+  if(!(aNode=(SALOMEDSImpl_AttributeTreeNode*)aLabel.FindAttribute(_root->ID()))) return false;
 
   aFirstNode->Remove();
 
   bool ret = aNode->InsertBefore(aFirstNode);
 
+  if ( _lastChild && _lastChild->GetFather() == aNode->GetFather() )
+  {
+    if ( aNode == _lastChild )
+      ++_childIndex;
+    else
+      _lastChild = 0;
+  }
+
   // Mantis issue 0020136: Drag&Drop in OB
-  theFirst.GetStudy()->addSO_Notification(theFirst);
+  SALOMEDSImpl_Study::GetStudyImpl(theFirst.GetLabel())->addSO_Notification(theFirst);
 
   return ret;
 }
@@ -279,6 +395,55 @@ bool SALOMEDSImpl_UseCaseBuilder::HasChildren(const SALOMEDSImpl_SObject& theObj
   return (aNode->GetFirst());
 }
 
+//============================================================================
+/*! Function : SortChildren
+ *  Purpose  :
+ */
+//============================================================================
+bool SALOMEDSImpl_UseCaseBuilder::SortChildren(const SALOMEDSImpl_SObject& theObject, bool theAscendingOrder)
+{
+  if(!_root) return false;
+
+  DF_Label aLabel;
+  if (!theObject) aLabel = _root->Label();
+  else 
+    aLabel = theObject.GetLabel(); 
+  if(aLabel.IsNull()) return false;
+
+  SALOMEDSImpl_AttributeTreeNode* aNode = NULL;
+  if (!(aNode=(SALOMEDSImpl_AttributeTreeNode*)aLabel.FindAttribute(_root->ID()))) return false;
+
+  std::list<SALOMEDSImpl_SObject> aRefSOs;
+  std::list<SALOMEDSImpl_SObject> aNodeSOs;
+  for ( SALOMEDSImpl_AttributeTreeNode* aChildNode=aNode->GetFirst(); aChildNode; aChildNode=aChildNode->GetNext() ) {
+    if ( SALOMEDSImpl_SObject aSO = SALOMEDSImpl_Study::SObject( aChildNode->Label() ) ) {
+      if ( aChildNode->FindAttribute( SALOMEDSImpl_AttributeReference::GetID() ) )
+        aRefSOs.push_back( aSO );      
+      else
+        aNodeSOs.push_back( aSO );
+    }
+  }
+  if ( aRefSOs.empty() && aNodeSOs.empty() ) return false;
+
+  //sort items by names in ascending/descending order
+  _lastChild = 0;
+  std::list<SALOMEDSImpl_SObject>::iterator it;  
+  if ( !aRefSOs.empty() ) {
+    theAscendingOrder ? aRefSOs.sort( AscSortSOs() ) : aRefSOs.sort( DescSortSOs() );
+    for ( it = aRefSOs.begin(); it != aRefSOs.end(); ++it ) {
+      AppendTo( theObject, *it );
+    }
+  }  
+  if ( !aNodeSOs.empty() ) {
+    theAscendingOrder ? aNodeSOs.sort( AscSortSOs() ) : aNodeSOs.sort( DescSortSOs() );
+    for ( it = aNodeSOs.begin(); it != aNodeSOs.end(); ++it ) {
+      AppendTo( theObject, *it );
+    }
+  }
+
+  return true;
+}
+
 //============================================================================
 /*! Function : GetFather
  *  Purpose  :