Salome HOME
Fix for the problem that selection of sub-elements of compsolids for concealment...
[modules/shaper.git] / src / Model / Model_ResultCompSolid.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        Model_ResultCompSolid.cpp
4 // Created:     20 Jul 2015
5 // Author:      Natalia ERMOLAEVA
6
7 #include <Model_ResultCompSolid.h>
8
9 #include <Model_Document.h>
10 #include <Model_Objects.h>
11 #include <Model_BodyBuilder.h>
12 #include <Model_Document.h>
13 #include <ModelAPI_AttributeRefList.h>
14 #include <ModelAPI_AttributeIntArray.h>
15 #include <ModelAPI_Object.h>
16 #include <ModelAPI_Events.h>
17 #include <Events_Loop.h>
18
19 #include <TopoDS_Shape.hxx>
20 #include <TopExp_Explorer.hxx>
21
22
23 Model_ResultCompSolid::Model_ResultCompSolid()
24 {
25   myBuilder = new Model_BodyBuilder(this);
26   myLastConcealed = false;
27   setIsConcealed(myLastConcealed);
28   myIsDisabled = true; // by default it is not initialized and false to be after created
29   updateSubs(shape()); // in case of open, etc.
30 }
31
32 Model_ResultCompSolid::~Model_ResultCompSolid()
33 {
34   updateSubs(std::shared_ptr<GeomAPI_Shape>()); // erase sub-results
35 }
36
37 void Model_ResultCompSolid::initAttributes()
38 {
39   DataPtr aData = data();
40   aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId());
41 }
42
43 void Model_ResultCompSolid::store(const std::shared_ptr<GeomAPI_Shape>& theShape)
44 {
45   ModelAPI_ResultCompSolid::store(theShape);
46   updateSubs(theShape);
47 }
48
49 void Model_ResultCompSolid::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& theFromShape,
50     const std::shared_ptr<GeomAPI_Shape>& theToShape)
51 {
52   ModelAPI_ResultCompSolid::storeGenerated(theFromShape, theToShape);
53   updateSubs(theToShape);
54 }
55
56 void Model_ResultCompSolid::storeModified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
57     const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theDecomposeSolidsTag)
58 {
59   ModelAPI_ResultCompSolid::storeModified(theOldShape, theNewShape, theDecomposeSolidsTag);
60   updateSubs(theNewShape);
61 }
62
63 int Model_ResultCompSolid::numberOfSubs(bool forTree) const
64 {
65   return mySubs.size();
66 }
67
68 std::shared_ptr<ModelAPI_ResultBody> Model_ResultCompSolid::subResult(const int theIndex,
69                                                                       bool forTree) const
70 {
71   return mySubs.at(theIndex);
72 }
73
74 bool Model_ResultCompSolid::isSub(ObjectPtr theObject) const
75 {
76   std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
77   for(; aSubIter != mySubs.cend(); aSubIter++)
78     if (*aSubIter == theObject)
79       return true;
80   return false;
81 }
82
83 void Model_ResultCompSolid::colorConfigInfo(std::string& theSection, std::string& theName,
84   std::string& theDefault)
85 {
86   theSection = "Visualization";
87   theName = "result_body_color";
88   theDefault = DEFAULT_COLOR();
89 }
90
91 bool Model_ResultCompSolid::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
92 {
93   bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag);
94   if (aChanged) { // state is changed, so modifications are needed
95     myBuilder->evolutionToSelection(theFlag);
96     updateSubs(shape()); // to set disabled/enabled 
97   }
98   return aChanged;
99 }
100
101 bool Model_ResultCompSolid::isConcealed()
102 {
103   bool aResult = false;;
104   if (ModelAPI_ResultCompSolid::isConcealed()) {
105     aResult = true;
106   } else {
107     std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
108     for(; aSubIter != mySubs.cend(); aSubIter++)
109       if ((*aSubIter)->isConcealed())
110         aResult = true;
111   }
112   if (myLastConcealed != aResult) {
113     myLastConcealed = aResult;
114     setIsConcealed(aResult); // set for all subs the same result
115   }
116   return aResult;
117 }
118
119 void Model_ResultCompSolid::setIsConcealed(const bool theValue)
120 {
121   ModelAPI_ResultCompSolid::setIsConcealed(theValue);
122   std::vector<std::shared_ptr<ModelAPI_ResultBody> >::const_iterator aSubIter = mySubs.cbegin();
123   for(; aSubIter != mySubs.cend(); aSubIter++) {
124     if ((*aSubIter)->isConcealed() != theValue) {
125       (*aSubIter)->setIsConcealed(theValue);
126       if (theValue) { // hidden unit must be redisplayed (hidden)
127         ModelAPI_EventCreator::get()->sendDeleted(document(), (*aSubIter)->groupName());
128         // redisplay for the viewer (it must be disappeared also)
129         static Events_ID EVENT_DISP = 
130           Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
131         ModelAPI_EventCreator::get()->sendUpdated(*aSubIter, EVENT_DISP);
132       } else { // was not concealed become concealed => delete event
133         static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
134         ModelAPI_EventCreator::get()->sendUpdated(*aSubIter, anEvent);
135       }
136     }
137   }
138 }
139
140 void Model_ResultCompSolid::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisShape)
141 {
142   static Events_Loop* aLoop = Events_Loop::loop();
143   static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
144   static Events_ID EVENT_UPD = aLoop->eventByName(EVENT_OBJECT_UPDATED);
145   static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
146   // iterate all sub-solids of compsolid to make sub-results synchronized with them
147   TopoDS_Shape aThisShape;
148   if (theThisShape.get()) aThisShape = theThisShape->impl<TopoDS_Shape>();
149   if (!aThisShape.IsNull() && (aThisShape.ShapeType() == TopAbs_COMPSOLID ||
150        aThisShape.ShapeType() == TopAbs_COMPOUND)) {
151     bool aWasEmpty = mySubs.empty();
152     Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
153     unsigned int aSubIndex = 0;
154     TopExp_Explorer aSolids(aThisShape, TopAbs_SOLID);
155     for(; aSolids.More(); aSolids.Next(), aSubIndex++) {
156       std::shared_ptr<GeomAPI_Shape> aSolidShape(new GeomAPI_Shape);
157       aSolidShape->setImpl(new TopoDS_Shape(aSolids.Current()));
158       ResultBodyPtr aSub;
159       if (mySubs.size() <= aSubIndex) { // it is needed to create a new sub-result
160         aSub = anObjects->createBody(this->data(), aSubIndex);
161         mySubs.push_back(aSub);
162       } else { // just update shape of this result
163         aSub = mySubs[aSubIndex];
164       }
165       if (!aSolidShape->isEqual(aSub->shape())) {
166         aSub->store(aSolidShape);
167         aECreator->sendUpdated(aSub, EVENT_DISP);
168         aECreator->sendUpdated(aSub, EVENT_UPD);
169       }
170       aSub->setDisabled(aSub, isDisabled());
171       aSub->setIsConcealed(myLastConcealed);
172     }
173     // erase left, unused results
174     while(mySubs.size() > aSubIndex) {
175       ResultBodyPtr anErased = *(mySubs.rbegin());
176       anErased->setDisabled(anErased, true);
177       mySubs.pop_back();
178     }
179     if (aWasEmpty) { // erase all subs
180       // redisplay this because result with and without subs are displayed differently
181       aECreator->sendUpdated(data()->owner(), EVENT_DISP);
182     }
183   } else if (!mySubs.empty()) { // erase all subs
184     while(!mySubs.empty()) {
185       ResultBodyPtr anErased = *(mySubs.rbegin());
186       anErased->setDisabled(anErased, true);
187       mySubs.pop_back();
188     }
189     // redisplay this because result with and without subs are displayed differently
190     aECreator->sendUpdated(data()->owner(), EVENT_DISP);
191   }
192 }