Salome HOME
2.17. Improved management of overconstraint situation: dimension constraints are...
[modules/shaper.git] / src / PartSet / PartSet_OverconstraintListener.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        SketcherPrs_Angle.cpp
4 // Created:     20 August 2015
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "PartSet_OverconstraintListener.h"
8
9 #include "XGUI_ModuleConnector.h"
10 #include "XGUI_Workshop.h"
11 #include "XGUI_Displayer.h"
12
13 #include "SketcherPrs_SymbolPrs.h"
14
15 #include "Events_Loop.h"
16
17 #include <GeomAPI_IPresentable.h>
18 #include <ModelAPI_Events.h>
19 #include <ModuleBase_Tools.h>
20
21 #include <QString>
22
23 #define DEBUG_FEATURE_OVERCONSTRAINT_LISTENER
24
25 PartSet_OverconstraintListener::PartSet_OverconstraintListener(ModuleBase_IWorkshop* theWorkshop)
26 : myWorkshop(theWorkshop)
27 {
28   Events_Loop* aLoop = Events_Loop::loop();
29   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED));
30   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED));
31 }
32
33 bool PartSet_OverconstraintListener::isConflictingObject(const ObjectPtr& theObject)
34 {
35   return myConflictingObjects.find(theObject) != myConflictingObjects.end();
36 }
37
38 void PartSet_OverconstraintListener::getConflictingColor(std::vector<int>& theColor)
39 {
40   Quantity_Color aColor = Quantity_Color(Quantity_NameOfColor::Quantity_NOC_RED);
41
42   theColor.push_back(aColor.Red()*255.);
43   theColor.push_back(aColor.Green()*255.);
44   theColor.push_back(aColor.Blue()*255.);
45 }
46
47 void PartSet_OverconstraintListener::processEvent(
48                                                  const std::shared_ptr<Events_Message>& theMessage)
49 {
50
51 #ifdef DEBUG_FEATURE_OVERCONSTRAINT_LISTENER
52
53   /*
54   anIt = theConflictingObjects.begin();
55   aLast = theConflictingObjects.end();
56
57   QStringList anInfo;
58   for (; anIt != aLast; ++anIt) {
59     anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
60   }
61   QString anInfoStr = anInfo.join(";\n");*/
62   bool isRepaired = theMessage->eventID() == Events_Loop::eventByName(EVENT_SOLVER_REPAIRED);
63   qDebug(QString("PartSet_OverconstraintListener::processEvent:\n %1").arg(isRepaired ? "REPAIRED" : "FAILED").toStdString().c_str());
64 #endif
65
66   if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SOLVER_FAILED) ||
67              theMessage->eventID() == Events_Loop::eventByName(EVENT_SOLVER_REPAIRED)) {
68     std::shared_ptr<ModelAPI_SolverFailedMessage> anErrorMsg =
69                    std::dynamic_pointer_cast<ModelAPI_SolverFailedMessage>(theMessage);
70     bool anUpdated = false;
71     if (anErrorMsg.get()) {
72       const std::set<ObjectPtr>& aConflictingObjects = anErrorMsg->objects();
73       anUpdated = updateConflictingObjects(aConflictingObjects);
74     }
75     else
76       anUpdated = updateConflictingObjects(std::set<ObjectPtr>());
77   }
78 }
79
80 bool PartSet_OverconstraintListener::updateConflictingObjects(
81                                                   const std::set<ObjectPtr>& theConflictingObjects)
82 {
83   std::set<ObjectPtr>::const_iterator anIt, aLast;
84
85 #ifdef DEBUG_FEATURE_OVERCONSTRAINT_LISTENER
86   anIt = theConflictingObjects.begin();
87   aLast = theConflictingObjects.end();
88
89   QStringList anInfo;
90   for (; anIt != aLast; ++anIt) {
91     anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
92   }
93   QString anInfoStr = anInfo.join(";\n");
94   qDebug(QString("PartSet_OverconstraintListener::updateConflictingObjects: %1: \n%2").arg(theConflictingObjects.size())
95                                                                                     .arg(anInfoStr).toStdString().c_str());
96 #endif
97
98   bool isUpdated = false;
99   std::set<ObjectPtr> aModifiedObjects;
100   // erase error state of absent current objects in the parameter list
101   for (anIt = myConflictingObjects.begin(), aLast = myConflictingObjects.end() ; anIt != aLast; anIt++) {
102     ObjectPtr anObject = *anIt;
103     if (theConflictingObjects.find(anObject) == theConflictingObjects.end()) { // it is not found
104       //setConflictingObject(anObject, false);
105       aModifiedObjects.insert(anObject);
106     }
107   }
108
109   // erase absent objects from the internal container
110   for (anIt = aModifiedObjects.begin(), aLast = aModifiedObjects.end(); anIt != aLast; anIt++) {
111     myConflictingObjects.erase(*anIt);
112   }
113
114   // set error state for new objects and append them in the internal map of objects
115   for (anIt = theConflictingObjects.begin(), aLast = theConflictingObjects.end() ; anIt != aLast; anIt++) {
116     ObjectPtr anObject = *anIt;
117     if (myConflictingObjects.find(anObject) == myConflictingObjects.end()) { // it is not found
118       //setConflictingObject(anObject, true);
119       aModifiedObjects.insert(anObject);
120       myConflictingObjects.insert(anObject);
121     }
122   }
123   isUpdated = !aModifiedObjects.empty();
124   if (isUpdated)
125     redisplayObjects(aModifiedObjects);
126
127   return isUpdated;
128 }
129
130 void PartSet_OverconstraintListener::redisplayObjects(
131                                               const std::set<ObjectPtr>& theObjects)
132 {
133 /*static Events_Loop* aLoop = Events_Loop::loop();
134   static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_UPDATED);
135
136   static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
137
138   std::set<ObjectPtr>::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
139   for (; anIt != aLast; anIt++) {
140     aECreator->sendUpdated(*anIt, EVENT_DISP);
141
142     //#ifdef DEBUG_FEATURE_OVERCONSTRAINT_LISTENER
143     //  QString anInfoStr = ModuleBase_Tools::objectInfo(*anIt);
144     //  qDebug(QString("PartSet_OverconstraintListener::SEND UPDATED: %1").arg(anInfoStr).toStdString().c_str());
145     //#endif
146   }
147   aLoop->flush(EVENT_DISP);*/
148
149   XGUI_Displayer* aDisplayer = workshop()->displayer();
150   //QObjectPtrList aObjects = aDisplayer->displayedObjects();
151   bool aHidden;
152   std::set<ObjectPtr>::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
153   for (; anIt != aLast; anIt++) {
154     ObjectPtr anObject = *anIt;
155   //foreach(ObjectPtr aObj, aObjects) {
156     //TODO: replace by redisplay event.
157     aHidden = !anObject->data() || !anObject->data()->isValid() || 
158                anObject->isDisabled() || (!anObject->isDisplayed());
159     if (!aHidden)
160       aDisplayer->redisplay(anObject, false);
161   }
162   aDisplayer->updateViewer();
163 }
164
165 void PartSet_OverconstraintListener::setConflictingObject(const ObjectPtr& theObject,
166                                                           const bool theConflicting)
167 {
168   return;
169
170   AISObjectPtr anAISObject;
171   GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
172
173   if (aPrs.get() != NULL) {
174     XGUI_Workshop* aWorkshop = workshop();
175     XGUI_Displayer* aDisplayer = aWorkshop->displayer();
176
177     anAISObject = aPrs->getAISObject(aDisplayer->getAISObject(theObject));
178     if (anAISObject.get()) {
179       Handle(AIS_InteractiveObject) anAISIO = anAISObject->impl<Handle(AIS_InteractiveObject)>();
180       if (!anAISIO.IsNull()) {
181         if (!Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO).IsNull()) {
182           Handle(SketcherPrs_SymbolPrs) aPrs = Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO);
183           //if (!aPrs.IsNull())
184           //  aPrs->setConflictingConstraint(theConflicting);
185         }
186       }
187     }
188   }
189 }
190
191 XGUI_Workshop* PartSet_OverconstraintListener::workshop() const
192 {
193   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
194   return aConnector->workshop();
195 }
196