Salome HOME
Fix of crash on initialization of the Viewer in SALOME
[modules/shaper.git] / src / ModuleBase / ModuleBase_Tools.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "ModuleBase_Tools.h"
22
23 #include <ModuleBase_ParamIntSpinBox.h>
24 #include <ModuleBase_ParamSpinBox.h>
25 #include <ModuleBase_WidgetFactory.h>
26 #include <ModuleBase_IWorkshop.h>
27 #include <ModuleBase_IModule.h>
28 #include <ModuleBase_IViewer.h>
29 #include <ModuleBase_IconFactory.h>
30 #include <ModuleBase_ResultPrs.h>
31 #include <ModuleBase_ViewerPrs.h>
32
33 #include <ModelAPI_Attribute.h>
34 #include <ModelAPI_AttributeRefAttr.h>
35 #include <ModelAPI_AttributeReference.h>
36 #include <ModelAPI_AttributeSelection.h>
37 #include <ModelAPI_AttributeSelectionList.h>
38 #include <ModelAPI_AttributeRefList.h>
39 #include <ModelAPI_AttributeRefAttrList.h>
40 #include <ModelAPI_ResultPart.h>
41 #include <ModelAPI_ResultConstruction.h>
42 #include <Events_Loop.h>
43
44 #include <ModelAPI_Data.h>
45 #include <ModelAPI_Result.h>
46 #include <ModelAPI_ResultCompSolid.h>
47 #include <ModelAPI_ResultParameter.h>
48 #include <ModelAPI_Tools.h>
49 #include <ModelAPI_Session.h>
50 #include <ModelAPI_Events.h>
51 #include <ModelAPI_Folder.h>
52
53 #include <ModelGeomAlgo_Point2D.h>
54
55 #include <StdSelect_BRepOwner.hxx>
56 #include <TopoDS_Iterator.hxx>
57 #include <AIS_InteractiveContext.hxx>
58 #include <Prs3d_LineAspect.hxx>
59 #include <Prs3d_PlaneAspect.hxx>
60
61 #include <GeomDataAPI_Point2D.h>
62 #include <Events_InfoMessage.h>
63 #include <GeomAPI_ShapeExplorer.h>
64
65 #include <Config_PropManager.h>
66 #include <Config_Translator.h>
67
68 #include <Prs3d_PointAspect.hxx>
69 #include <Graphic3d_AspectMarker3d.hxx>
70
71 #include <Image_AlienPixMap.hxx>
72
73 #include <QWidget>
74 #include <QLayout>
75 #include <QPainter>
76 #include <QBitmap>
77 #include <QDoubleSpinBox>
78 #include <QGraphicsDropShadowEffect>
79 #include <QColor>
80 #include <QApplication>
81 #include <QMessageBox>
82 #include <QAction>
83 #include <QTextCodec>
84
85 #include <sstream>
86 #include <string>
87
88 #ifdef WIN32
89 #pragma warning(disable : 4996) // for getenv
90 #endif
91
92 const double tolerance = 1e-7;
93 const double DEFAULT_DEVIATION_COEFFICIENT = 1.e-4;
94
95 //#define DEBUG_ACTIVATE_WINDOW
96 //#define DEBUG_SET_FOCUS
97
98 #ifdef WIN32
99 # define FSEP "\\"
100 #else
101 # define FSEP "/"
102 #endif
103
104 namespace ModuleBase_Tools {
105
106 //******************************************************************
107
108 //******************************************************************
109
110 void adjustMargins(QWidget* theWidget)
111 {
112   if(!theWidget)
113     return;
114   adjustMargins(theWidget->layout());
115 }
116
117 void adjustMargins(QLayout* theLayout)
118 {
119   if(!theLayout)
120     return;
121   theLayout->setContentsMargins(2, 5, 2, 5);
122   theLayout->setSpacing(4);
123 }
124
125 void zeroMargins(QWidget* theWidget)
126 {
127   if(!theWidget)
128     return;
129   zeroMargins(theWidget->layout());
130 }
131
132 void zeroMargins(QLayout* theLayout)
133 {
134   if(!theLayout)
135     return;
136   theLayout->setContentsMargins(0, 0, 0, 0);
137   theLayout->setSpacing(5);
138 }
139
140 void activateWindow(QWidget* theWidget, const QString& theInfo)
141 {
142   if (theWidget) {
143     theWidget->activateWindow();
144     theWidget->raise();
145   }
146
147 #ifdef DEBUG_ACTIVATE_WINDOW
148   qDebug(QString("activateWindow: %1").arg(theInfo).toStdString().c_str());
149 #endif
150 }
151
152 void setFocus(QWidget* theWidget, const QString& theInfo)
153 {
154   activateWindow(theWidget);
155   theWidget->setFocus();
156   // rectangle of focus is not visible on tool button widgets
157   theWidget->repaint();
158 #ifdef DEBUG_SET_FOCUS
159   qDebug(QString("setFocus: %1").arg(theInfo).toStdString().c_str());
160 #endif
161 }
162
163 void setShadowEffect(QWidget* theWidget, const bool isSetEffect)
164 {
165   if (isSetEffect) {
166     QGraphicsDropShadowEffect* aGlowEffect = new QGraphicsDropShadowEffect();
167     aGlowEffect->setOffset(.0);
168     aGlowEffect->setBlurRadius(10.0);
169     aGlowEffect->setColor(QColor(0, 170, 255)); // Light-blue color, #00AAFF
170     theWidget->setGraphicsEffect(aGlowEffect);
171   }
172   else {
173     QGraphicsEffect* anEffect = theWidget->graphicsEffect();
174     if(anEffect)
175       anEffect->deleteLater();
176     theWidget->setGraphicsEffect(NULL);
177   }
178 }
179
180 QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon)
181 {
182   QImage anIcon = ModuleBase_IconFactory::loadImage(theIcon);
183   QImage anAditional(theAdditionalIcon);
184
185   if (anIcon.isNull())
186     return QPixmap();
187
188   int anAddWidth = anAditional.width();
189   int anAddHeight = anAditional.height();
190
191   int aWidth = anIcon.width();
192   int aHeight = anIcon.height();
193
194   int aStartWidthPos = aWidth - anAddWidth - 1;
195   int aStartHeightPos = aHeight - anAddHeight - 1;
196
197   for (int i = 0; i < anAddWidth && i + aStartWidthPos < aWidth; i++)
198   {
199     for (int j = 0; j < anAddHeight && j + aStartHeightPos < aHeight; j++)
200     {
201       if (qAlpha(anAditional.pixel(i, j)) > 0)
202         anIcon.setPixel(i + aStartWidthPos, j + aStartHeightPos, anAditional.pixel(i, j));
203     }
204   }
205   return QPixmap::fromImage(anIcon);
206 }
207
208 QPixmap lighter(const QString& theIcon, const int theLighterValue)
209 {
210   QImage anIcon = ModuleBase_IconFactory::loadImage(theIcon);
211   if (anIcon.isNull())
212     return QPixmap();
213
214   QImage aResult = ModuleBase_IconFactory::loadImage(theIcon);
215   for (int i = 0; i < anIcon.width(); i++)
216   {
217     for (int j = 0; j < anIcon.height(); j++)
218     {
219       QRgb anRgb = anIcon.pixel(i, j);
220       QColor aPixelColor(qRed(anRgb), qGreen(anRgb), qBlue(anRgb),
221                          qAlpha(aResult.pixel(i, j)));
222
223       QColor aLighterColor = aPixelColor.lighter(theLighterValue);
224       aResult.setPixel(i, j, qRgba(aLighterColor.red(), aLighterColor.green(),
225                                     aLighterColor.blue(), aLighterColor.alpha()));
226     }
227   }
228   return QPixmap::fromImage(aResult);
229 }
230
231 void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText)
232 {
233   if (theSpin->text() == theText)
234     return;
235   // In order to avoid extra text setting because it will
236   // reset cursor position in control
237   bool isBlocked = theSpin->blockSignals(true);
238   theSpin->setText(theText);
239   theSpin->blockSignals(isBlocked);
240 }
241
242 void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
243 {
244   if (fabs(theSpin->value() - theValue) < tolerance)
245     return;
246   bool isBlocked = theSpin->blockSignals(true);
247   theSpin->setValue(theValue);
248   theSpin->blockSignals(isBlocked);
249 }
250
251 void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double theValue)
252 {
253   if (fabs(theSpin->value() - theValue) < tolerance)
254     return;
255   bool isBlocked = theSpin->blockSignals(true);
256   theSpin->setValue(theValue);
257   theSpin->blockSignals(isBlocked);
258 }
259
260 void setSpinText(ModuleBase_ParamIntSpinBox* theSpin, const QString& theText)
261 {
262   // In order to avoid extra text setting because it will
263   // reset cursor position in control
264   if (theSpin->text() == theText)
265     return;
266   bool isBlocked = theSpin->blockSignals(true);
267   theSpin->setText(theText);
268   theSpin->blockSignals(isBlocked);
269 }
270
271 void setSpinValue(ModuleBase_ParamIntSpinBox* theSpin, int theValue)
272 {
273   if (theSpin->value() == theValue)
274     return;
275   bool isBlocked = theSpin->blockSignals(true);
276   theSpin->setValue(theValue);
277   theSpin->blockSignals(isBlocked);
278 }
279
280 QAction* createAction(const QIcon& theIcon, const QString& theText,
281                       QObject* theParent, const QObject* theReceiver,
282                       const char* theMember, const QString& theToolTip,
283                       const QString& theStatusTip)
284 {
285   QAction* anAction = new QAction(theIcon, theText, theParent);
286   anAction->setToolTip(theToolTip.isEmpty() ? theText : theToolTip);
287   anAction->setStatusTip(!theStatusTip.isEmpty() ? theStatusTip :
288                                                    (!theToolTip.isEmpty() ? theToolTip : theText));
289   if (theReceiver)
290     QObject::connect(anAction, SIGNAL(triggered(bool)), theReceiver, theMember);
291
292   return anAction;
293 }
294
295 #ifdef _DEBUG
296 QString objectName(const ObjectPtr& theObj)
297 {
298   if (!theObj.get())
299     return "";
300
301   return theObj->data()->name().c_str();
302 }
303
304 QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
305 {
306   QString aFeatureStr = "feature";
307   if (!theObj.get())
308     return aFeatureStr;
309
310   std::ostringstream aPtrStr;
311   aPtrStr << "[" << theObj.get() << "]";
312
313   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
314   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
315   if(aRes.get()) {
316     aFeatureStr.append(QString("(result%1)").arg(aPtrStr.str().c_str()).toStdString() .c_str());
317     if (aRes->isDisabled())
318       aFeatureStr.append("[disabled]");
319     if (aRes->isConcealed())
320       aFeatureStr.append("[concealed]");
321     if (ModelAPI_Tools::hasSubResults(aRes))
322       aFeatureStr.append("[hasSubResults]");
323
324     aFeature = ModelAPI_Feature::feature(aRes);
325   }
326   else
327     aFeatureStr.append(aPtrStr.str().c_str());
328
329   if (aFeature.get()) {
330     aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
331     if (aFeature->data()->isValid()) {
332       aFeatureStr.append(QString(", name=%1").arg(theObj->data()->name().c_str()).toStdString()
333                                                                                        .c_str());
334     }
335     if (isUseAttributesInfo) {
336       std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
337       std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(aFeature,
338                                                                           anAttributes).c_str();
339       if (!aPointsInfo.empty())
340         aFeatureStr.append(QString(", attributes: %1")
341           .arg(aPointsInfo.c_str()).toStdString().c_str());
342     }
343   }
344
345   return aFeatureStr;
346 }
347 #endif
348
349 typedef QMap<QString, int> ShapeTypes;
350 static ShapeTypes myShapeTypes;
351
352 int shapeType(const QString& theType)
353 {
354   if (myShapeTypes.count() == 0) {
355     myShapeTypes["compound"]   = TopAbs_COMPOUND;
356     myShapeTypes["compounds"]  = TopAbs_COMPOUND;
357     myShapeTypes["compsolid"]  = TopAbs_COMPSOLID;
358     myShapeTypes["compsolids"] = TopAbs_COMPSOLID;
359     myShapeTypes["solid"]      = TopAbs_SOLID;
360     myShapeTypes["solids"]     = TopAbs_SOLID;
361     myShapeTypes["shell"]      = TopAbs_SHELL;
362     myShapeTypes["shells"]     = TopAbs_SHELL;
363     myShapeTypes["face"]       = TopAbs_FACE;
364     myShapeTypes["faces"]      = TopAbs_FACE;
365     myShapeTypes["wire"]       = TopAbs_WIRE;
366     myShapeTypes["wires"]      = TopAbs_WIRE;
367     myShapeTypes["edge"]       = TopAbs_EDGE;
368     myShapeTypes["edges"]      = TopAbs_EDGE;
369     myShapeTypes["vertex"]     = TopAbs_VERTEX;
370     myShapeTypes["vertices"]   = TopAbs_VERTEX;
371     myShapeTypes["object"]     = ModuleBase_ResultPrs::Sel_Result;
372     myShapeTypes["objects"]    = ModuleBase_ResultPrs::Sel_Result;
373   }
374   QString aType = theType.toLower();
375   if(myShapeTypes.contains(aType))
376     return myShapeTypes[aType];
377   Events_InfoMessage("ModuleBase_Tools", "Shape type defined in XML is not implemented!").send();
378   return TopAbs_SHAPE;
379 }
380
381 void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature,
382                   bool& hasParameter, bool& hasCompositeOwner, bool& hasResultInHistory,
383                   bool& hasFolder)
384 {
385   hasResult = false;
386   hasFeature = false;
387   hasParameter = false;
388   hasCompositeOwner = false;
389   hasResultInHistory = false;
390   hasFolder = false;
391   foreach(ObjectPtr aObj, theObjects) {
392     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
393     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
394     FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(aObj);
395     ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
396
397     hasResult |= (aResult.get() != NULL);
398     hasFeature |= (aFeature.get() != NULL);
399     hasFolder |= (aFolder.get() != NULL);
400     hasParameter |= (aConstruction.get() != NULL);
401     if (hasFeature)
402       hasCompositeOwner |= (ModelAPI_Tools::compositeOwner(aFeature) != NULL);
403
404     if (!hasResultInHistory && aResult.get()) {
405       FeaturePtr aFeature = ModelAPI_Feature::feature(aResult);
406       hasResultInHistory = aFeature.get() && aFeature->isInHistory();
407     }
408
409     if (hasFeature && hasResult  && hasParameter && hasCompositeOwner && hasFeature)
410       break;
411   }
412 }
413
414 /*bool setDefaultDeviationCoefficient(std::shared_ptr<GeomAPI_Shape> theGeomShape)
415 {
416   if (!theGeomShape.get())
417     return false;
418   // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
419   // correction of deviation for them should not influence to the application performance
420   GeomAPI_ShapeExplorer anExp(theGeomShape, GeomAPI_Shape::FACE);
421   bool anEmpty = anExp.empty();
422   return !anExp.more();
423 }*/
424
425 /*void setDefaultDeviationCoefficient(const std::shared_ptr<ModelAPI_Result>& theResult,
426                                     const Handle(Prs3d_Drawer)& theDrawer)
427 {
428   if (!theResult.get())
429     return;
430   bool aUseDeviation = false;
431
432   std::string aResultGroup = theResult->groupName();
433   if (aResultGroup == ModelAPI_ResultConstruction::group())
434     aUseDeviation = true;
435   else if (aResultGroup == ModelAPI_ResultBody::group()) {
436     GeomShapePtr aGeomShape = theResult->shape();
437     if (aGeomShape.get())
438       aUseDeviation = setDefaultDeviationCoefficient(aGeomShape);
439   }
440   if (aUseDeviation)
441     theDrawer->SetDeviationCoefficient(DEFAULT_DEVIATION_COEFFICIENT);
442 }
443 */
444 void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
445                                     const Handle(Prs3d_Drawer)& theDrawer)
446 {
447   if (theShape.IsNull())
448     return;
449
450   std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape());
451   aGeomShape->setImpl(new TopoDS_Shape(theShape));
452
453   // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
454   // correction of deviation for them should not influence to the application performance
455   GeomAPI_ShapeExplorer anExp(aGeomShape, GeomAPI_Shape::FACE);
456   bool isConstruction = !anExp.more();
457
458   double aDeflection;
459   if (isConstruction)
460     aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
461   else
462     aDeflection = Config_PropManager::real("Visualization", "body_deflection");
463
464   theDrawer->SetDeviationCoefficient(aDeflection);
465 }
466
467 Quantity_Color color(const std::string& theSection,
468                      const std::string& theName)
469 {
470   std::vector<int> aColor = Config_PropManager::color(theSection, theName);
471   return Quantity_Color(aColor[0] / 255., aColor[1] / 255., aColor[2] / 255., Quantity_TOC_RGB);
472 }
473
474 ObjectPtr getObject(const AttributePtr& theAttribute)
475 {
476   ObjectPtr anObject;
477   std::string anAttrType = theAttribute->attributeType();
478   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
479     AttributeRefAttrPtr anAttr =
480       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
481     if (anAttr != NULL && anAttr->isObject())
482       anObject = anAttr->object();
483   }
484   if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
485     AttributeSelectionPtr anAttr =
486       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
487     if (anAttr != NULL)
488       anObject = anAttr->context();
489   }
490   if (anAttrType == ModelAPI_AttributeReference::typeId()) {
491     AttributeReferencePtr anAttr =
492       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
493     if (anAttr.get() != NULL)
494       anObject = anAttr->value();
495   }
496   return anObject;
497 }
498
499 TopAbs_ShapeEnum getCompoundSubType(const TopoDS_Shape& theShape)
500 {
501   TopAbs_ShapeEnum aShapeType = theShape.ShapeType();
502
503   // for compounds check sub-shapes: it may be compound of needed type:
504   // Booleans may produce compounds of Solids
505   if (aShapeType == TopAbs_COMPOUND) {
506     for(TopoDS_Iterator aSubs(theShape); aSubs.More(); aSubs.Next()) {
507       if (!aSubs.Value().IsNull()) {
508         TopAbs_ShapeEnum aSubType = aSubs.Value().ShapeType();
509         if (aSubType == TopAbs_COMPOUND) { // compound of compound(s)
510           aShapeType = TopAbs_COMPOUND;
511           break;
512         }
513         if (aShapeType == TopAbs_COMPOUND) {
514           aShapeType = aSubType;
515         } else if (aShapeType != aSubType) { // compound of shapes of different types
516           aShapeType = TopAbs_COMPOUND;
517           break;
518         }
519       }
520     }
521   }
522   return aShapeType;
523 }
524
525 TopoDS_Shape getSelectedShape(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs)
526 {
527   if (thePrs->shape().get())
528     return thePrs->shape()->impl<TopoDS_Shape>();
529
530   Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(thePrs->owner());
531   if (!anOwner.IsNull())
532     return anOwner->Shape();
533
534   return TopoDS_Shape();
535 }
536
537 void getParameters(QStringList& theParameters)
538 {
539   theParameters.clear();
540
541   SessionPtr aSession = ModelAPI_Session::get();
542   std::list<DocumentPtr> aDocList;
543   DocumentPtr anActiveDocument = aSession->activeDocument();
544   DocumentPtr aRootDocument = aSession->moduleDocument();
545   aDocList.push_back(anActiveDocument);
546   if (anActiveDocument != aRootDocument) {
547     aDocList.push_back(aRootDocument);
548   }
549   std::string aGroupId = ModelAPI_ResultParameter::group();
550   for(std::list<DocumentPtr>::const_iterator it = aDocList.begin(); it != aDocList.end(); ++it) {
551     DocumentPtr aDocument = *it;
552     int aSize = aDocument->size(aGroupId);
553     for (int i = 0; i < aSize; i++) {
554       ObjectPtr anObject = aDocument->object(aGroupId, i);
555       std::string aParameterName = anObject->data()->name();
556       theParameters.append(aParameterName.c_str());
557     }
558   }
559 }
560
561 std::string findGreedAttribute(ModuleBase_IWorkshop* theWorkshop,
562                                const FeaturePtr& theFeature)
563 {
564   std::string anAttributeId;
565
566   std::string aXmlCfg, aDescription;
567   theWorkshop->module()->getXMLRepresentation(theFeature->getKind(), aXmlCfg, aDescription);
568
569   ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
570   std::string anAttributeTitle;
571   aFactory.getGreedAttribute(anAttributeId);
572
573   return anAttributeId;
574 }
575
576 bool hasObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
577                const std::shared_ptr<GeomAPI_Shape>& theShape,
578                ModuleBase_IWorkshop* theWorkshop,
579                const bool theTemporarily)
580 {
581   bool aHasObject = false;
582   if (!theAttribute.get())
583     return aHasObject;
584
585   std::string aType = theAttribute->attributeType();
586   if (aType == ModelAPI_AttributeReference::typeId()) {
587     AttributeReferencePtr aRef =
588       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
589     ObjectPtr aObject = aRef->value();
590     aHasObject = aObject && aObject->isSame(theObject);
591     //if (!(aObject && aObject->isSame(theObject))) {
592     //  aRef->setValue(theObject);
593     //}
594   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
595     AttributeRefAttrPtr aRefAttr =
596       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
597
598     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
599     if (anAttribute.get()) {
600       //aRefAttr->setAttr(anAttribute);
601     }
602     else {
603       ObjectPtr aObject = aRefAttr->object();
604       aHasObject = aObject && aObject->isSame(theObject);
605       //if (!(aObject && aObject->isSame(theObject))) {
606       //  aRefAttr->setObject(theObject);
607       //}
608     }
609   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
610     /*AttributeSelectionPtr aSelectAttr =
611                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
612     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
613     if (aSelectAttr.get() != NULL) {
614       aSelectAttr->setValue(aResult, theShape, theTemporarily);
615     }*/
616   }
617   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
618     AttributeSelectionListPtr aSelectionListAttr =
619                          std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
620     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
621     aHasObject = aSelectionListAttr->isInList(aResult, theShape, theTemporarily);
622   }
623   else if (aType == ModelAPI_AttributeRefList::typeId()) {
624     AttributeRefListPtr aRefListAttr =
625       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
626     aHasObject = aRefListAttr->isInList(theObject);
627     //if (!theCheckIfAttributeHasObject || !aRefListAttr->isInList(theObject))
628     //  aRefListAttr->append(theObject);
629   }
630   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
631     AttributeRefAttrListPtr aRefAttrListAttr =
632       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
633     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
634
635     if (anAttribute.get()) {
636       aHasObject = aRefAttrListAttr->isInList(anAttribute);
637       //if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(anAttribute))
638       //  aRefAttrListAttr->append(anAttribute);
639     }
640     else {
641       aHasObject = aRefAttrListAttr->isInList(theObject);
642       //if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(theObject))
643       //  aRefAttrListAttr->append(theObject);
644     }
645   }
646   return aHasObject;
647 }
648
649 bool setObject(const AttributePtr& theAttribute, const ObjectPtr& theObject,
650                const GeomShapePtr& theShape, ModuleBase_IWorkshop* theWorkshop,
651                const bool theTemporarily, const bool theCheckIfAttributeHasObject)
652 {
653   if (!theAttribute.get())
654     return false;
655
656   bool isDone = true;
657   std::string aType = theAttribute->attributeType();
658   if (aType == ModelAPI_AttributeReference::typeId()) {
659     AttributeReferencePtr aRef =
660       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
661     ObjectPtr aObject = aRef->value();
662     if (!(aObject && aObject->isSame(theObject))) {
663       aRef->setValue(theObject);
664     }
665   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
666     AttributeRefAttrPtr aRefAttr =
667       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
668
669     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
670     if (anAttribute.get())
671       aRefAttr->setAttr(anAttribute);
672     else {
673       ObjectPtr aObject = aRefAttr->object();
674       if (!(aObject && aObject->isSame(theObject))) {
675         aRefAttr->setObject(theObject);
676       }
677     }
678   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
679     AttributeSelectionPtr aSelectAttr =
680                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
681     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
682     if (aSelectAttr.get() != NULL) {
683       aSelectAttr->setValue(aResult, theShape, theTemporarily);
684     }
685   }
686   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
687     AttributeSelectionListPtr aSelectionListAttr =
688                          std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
689     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
690     if (!theCheckIfAttributeHasObject ||
691         !aSelectionListAttr->isInList(aResult, theShape, theTemporarily))
692       aSelectionListAttr->append(aResult, theShape, theTemporarily);
693   }
694   else if (aType == ModelAPI_AttributeRefList::typeId()) {
695     AttributeRefListPtr aRefListAttr =
696       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
697     if (!theCheckIfAttributeHasObject || !aRefListAttr->isInList(theObject)) {
698       if (theObject.get())
699         aRefListAttr->append(theObject);
700       else
701         isDone = false;
702     }
703   }
704   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
705     AttributeRefAttrListPtr aRefAttrListAttr =
706       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
707     AttributePtr anAttribute = theWorkshop->module()->findAttribute(theObject, theShape);
708
709     if (anAttribute.get()) {
710       if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(anAttribute))
711         aRefAttrListAttr->append(anAttribute);
712     }
713     else {
714       if (!theCheckIfAttributeHasObject || !aRefAttrListAttr->isInList(theObject)) {
715         if (theObject.get())
716           aRefAttrListAttr->append(theObject);
717         else
718           isDone = false;
719       }
720     }
721   }
722   return isDone;
723 }
724
725 GeomShapePtr getShape(const AttributePtr& theAttribute, ModuleBase_IWorkshop* theWorkshop)
726 {
727   GeomShapePtr aShape;
728   if (!theAttribute.get())
729     return aShape;
730
731   std::string aType = theAttribute->attributeType();
732   if (aType == ModelAPI_AttributeReference::typeId()) {
733   } else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
734     AttributeRefAttrPtr aRefAttr =
735       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
736     if (aRefAttr.get() && !aRefAttr->isObject()) {
737       AttributePtr anAttribute = aRefAttr->attr();
738       aShape = theWorkshop->module()->findShape(anAttribute);
739     }
740   } else if (aType == ModelAPI_AttributeSelection::typeId()) {
741     AttributeSelectionPtr aSelectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
742                                                                                  (theAttribute);
743     aShape = aSelectAttr->value();
744   }
745   else // Geom2D point processing
746     aShape = theWorkshop->module()->findShape(theAttribute);
747   return aShape;
748 }
749
750 void flushUpdated(ObjectPtr theObject)
751 {
752   blockUpdateViewer(true);
753
754   // Fix the problem of not previewed results of constraints applied. Flush Create/Delete
755   // (for the sketch result) to start processing of the sketch in the solver.
756   // TODO: these flushes should be moved in a separate method provided by Model
757   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
758   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
759   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
760
761   blockUpdateViewer(false);
762 }
763
764 void blockUpdateViewer(const bool theValue)
765 {
766   // the viewer update should be blocked in order to avoid the temporary feature content
767   // when the solver processes the feature, the redisplay message can be flushed
768   // what caused the display in the viewer preliminary states of object
769   // e.g. fillet feature, angle value change
770   std::shared_ptr<Events_Message> aMsg;
771   if (theValue) {
772     aMsg = std::shared_ptr<Events_Message>(
773         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED)));
774   }
775   else {
776     // the viewer update should be unblocked
777     aMsg = std::shared_ptr<Events_Message>(
778         new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED)));
779   }
780   Events_Loop::loop()->send(aMsg);
781 }
782
783 QString wrapTextByWords(const QString& theValue, QWidget* theWidget,
784                                           int theMaxLineInPixels)
785 {
786   static QFontMetrics tfm(theWidget ? theWidget->font() : QApplication::font());
787   static qreal phi = 2.618;
788
789   QRect aBounds = tfm.boundingRect(theValue);
790   if(aBounds.width() <= theMaxLineInPixels)
791     return theValue;
792
793   qreal s = aBounds.width() * aBounds.height();
794   qreal aGoldWidth = sqrt(s*phi);
795
796   QStringList aWords = theValue.split(" ", QString::SkipEmptyParts);
797   QStringList aLines;
798   int n = aWords.count();
799   QString aLine;
800   for (int i = 0; i < n; i++) {
801     QString aLineExt = aLine + " " + aWords[i];
802     qreal anWidthNonExt = tfm.boundingRect(aLine).width();
803     qreal anWidthExt = tfm.boundingRect(aLineExt).width();
804     qreal aDeltaNonExt = fabs(anWidthNonExt-aGoldWidth);
805     qreal aDeltaExt    = fabs(anWidthExt-aGoldWidth);
806     if(aDeltaNonExt < aDeltaExt) {
807       // new line
808       aLines.append(aLine);
809       aLine = aWords[i];
810     }
811     else
812       aLine = aLineExt;
813   }
814
815   if(!aLine.isEmpty())
816     aLines.append(aLine);
817
818   QString aResult = aLines.join("\n");
819   return aResult;
820 }
821
822 //**************************************************************
823 QLocale doubleLocale()
824 {
825   // VSR 01/07/2010: Disable thousands separator for spin box
826   // (to avoid inconsistency of double-2-string and string-2-double conversion)
827   QLocale aLocale;
828   aLocale.setNumberOptions(aLocale.numberOptions() |
829                            QLocale::OmitGroupSeparator |
830                            QLocale::RejectGroupSeparator);
831   return aLocale;
832 }
833
834 //**************************************************************
835 void refsToFeatureInFeatureDocument(const ObjectPtr& theObject,
836                                     std::set<FeaturePtr>& theRefFeatures)
837 {
838   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
839   if (aFeature.get()) {
840     DocumentPtr aFeatureDoc = aFeature->document();
841     // 1. find references in the current document
842     aFeatureDoc->refsToFeature(aFeature, theRefFeatures, false);
843   }
844 }
845
846
847 //**************************************************************
848 /*bool isSubOfComposite(const ObjectPtr& theObject)
849 {
850   bool isSub = false;
851   std::set<FeaturePtr> aRefFeatures;
852   refsToFeatureInFeatureDocument(theObject, aRefFeatures);
853   std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
854                                        aLast = aRefFeatures.end();
855   for (; anIt != aLast && !isSub; anIt++) {
856     isSub = isSubOfComposite(theObject, *anIt);
857   }
858   return isSub;
859 }*/
860
861 //**************************************************************
862 /*bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature)
863 {
864   bool isSub = false;
865   CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
866   if (aComposite.get()) {
867     isSub = aComposite->isSub(theObject);
868     // the recursive is possible, the parameters are sketch circle and extrusion cut. They are
869     // separated by composite sketch feature
870     if (!isSub) {
871       int aNbSubs = aComposite->numberOfSubs();
872       for (int aSub = 0; aSub < aNbSubs && !isSub; aSub++) {
873         isSub = isSubOfComposite(theObject, aComposite->subFeature(aSub));
874       }
875     }
876   }
877   return isSub;
878 }*/
879
880 //**************************************************************
881 ResultPtr firstResult(const ObjectPtr& theObject)
882 {
883   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
884   if (!aResult.get()) {
885     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
886     if (aFeature.get())
887       aResult = aFeature->firstResult();
888   }
889   return aResult;
890 }
891
892 //**************************************************************
893 bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroupOfResult)
894 {
895   bool isResult = false;
896
897   if (!theFeature->data()->isValid())
898     return isResult;
899
900   ResultPtr aFirstResult = theFeature->firstResult();
901   if (!aFirstResult.get())
902     return isResult;
903
904   return aFirstResult->groupName() == theGroupOfResult;
905 }
906
907 //**************************************************************
908 bool hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures)
909 {
910   bool aFoundModuleDocumentObject = false;
911   DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
912
913   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(), aLast = theFeatures.end();
914   for (; anIt != aLast && !aFoundModuleDocumentObject; anIt++) {
915     FeaturePtr aFeature = *anIt;
916     ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
917     if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
918       continue;
919     aFoundModuleDocumentObject = aFeature->document() == aModuleDoc;
920   }
921
922   return aFoundModuleDocumentObject;
923 }
924
925 //**************************************************************
926 bool askToDelete(const std::set<FeaturePtr> theFeatures,
927                  const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
928                  QWidget* theParent,
929                  std::set<FeaturePtr>& theReferencesToDelete,
930                  const std::string& thePrefixInfo)
931 {
932   QString aNotActivatedDocWrn;
933   std::string aNotActivatedNames;
934   if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
935     if (ModuleBase_Tools::hasModuleDocumentFeature(theFeatures))
936       aNotActivatedDocWrn =
937         QObject::tr("Selected objects can be used in Part documents which are not loaded:%1.\n")
938                             .arg(aNotActivatedNames.c_str());
939   }
940
941   std::set<FeaturePtr> aFeaturesRefsTo;
942   std::set<FeaturePtr> aFeaturesRefsToParameter;
943   std::set<FeaturePtr> aParameterFeatures;
944   QStringList aPartFeatureNames;
945   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
946                                        aLast = theFeatures.end();
947   // separate features to references to parameter features and references to others
948   for (; anIt != aLast; anIt++) {
949     FeaturePtr aFeature = *anIt;
950     if (theReferences.find(aFeature) == theReferences.end())
951       continue;
952
953     if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
954       aPartFeatureNames.append(aFeature->name().c_str());
955
956     std::set<FeaturePtr> aRefFeatures;
957     std::set<FeaturePtr> aRefList = theReferences.at(aFeature);
958     std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
959     for (; aRefIt != aRefLast; aRefIt++) {
960       FeaturePtr aRefFeature = *aRefIt;
961       if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected
962           aRefFeatures.find(aRefFeature) == aRefFeatures.end()) // it is not added
963         aRefFeatures.insert(aRefFeature);
964     }
965
966     if (isFeatureOfResult(aFeature, ModelAPI_ResultParameter::group())) {
967       aFeaturesRefsToParameter.insert(aRefFeatures.begin(), aRefFeatures.end());
968       aParameterFeatures.insert(aFeature);
969     }
970     else {
971       theReferencesToDelete.insert(aRefFeatures.begin(), aRefFeatures.end());
972     }
973   }
974
975   std::set<FeaturePtr> aFeaturesRefsToParameterOnly;
976   anIt = aFeaturesRefsToParameter.begin();
977   aLast = aFeaturesRefsToParameter.end();
978   // separate features to references to parameter features and references to others
979   QStringList aParamFeatureNames;
980   for (; anIt != aLast; anIt++) {
981     FeaturePtr aFeature = *anIt;
982     if (theReferencesToDelete.find(aFeature) == theReferencesToDelete.end()) {
983       aFeaturesRefsToParameterOnly.insert(aFeature);
984       aParamFeatureNames.append(aFeature->name().c_str());
985     }
986   }
987   aParamFeatureNames.sort();
988   QStringList anOtherFeatureNames;
989   anIt = theReferencesToDelete.begin();
990   aLast = theReferencesToDelete.end();
991   for (; anIt != aLast; anIt++) {
992     FeaturePtr aFeature = *anIt;
993     if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
994       aPartFeatureNames.append(aFeature->name().c_str());
995     else
996       anOtherFeatureNames.append(aFeature->name().c_str());
997   }
998   aPartFeatureNames.sort();
999   anOtherFeatureNames.sort();
1000
1001   bool aCanReplaceParameters = !aFeaturesRefsToParameterOnly.empty();
1002
1003   QMessageBox aMessageBox(theParent);
1004   aMessageBox.setWindowTitle(QObject::tr("Delete features"));
1005   aMessageBox.setIcon(QMessageBox::Warning);
1006   aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1007   aMessageBox.setDefaultButton(QMessageBox::No);
1008
1009   QString aText;
1010   if (!thePrefixInfo.empty())
1011     aText = thePrefixInfo.c_str();
1012   QString aSep = ", ";
1013   if (!aPartFeatureNames.empty()) {
1014     aText += QString(QObject::tr("The following parts will be deleted: %1.\n"))
1015              .arg(aPartFeatureNames.join(aSep));
1016   }
1017   if (!aNotActivatedDocWrn.isEmpty())
1018     aText += aNotActivatedDocWrn;
1019   if (!anOtherFeatureNames.empty()) {
1020     const char* aMsg = "Features are used in the following features: %1.\nThese "
1021                        "features will be deleted.\n";
1022     aText += QString(QObject::tr(aMsg))
1023                      .arg(anOtherFeatureNames.join(aSep));
1024   }
1025   if (!aParamFeatureNames.empty()) {
1026     const char* aMsg = "Parameters are used in the following features: %1.\nThese features will "
1027                        "be deleted.\nOr parameters could be replaced by their values.\n";
1028     aText += QString(QObject::tr(aMsg))
1029                      .arg(aParamFeatureNames.join(aSep));
1030     QPushButton *aReplaceButton =
1031       aMessageBox.addButton(QObject::tr("Replace"), QMessageBox::ActionRole);
1032   }
1033
1034   if (!aText.isEmpty()) {
1035     aText += "Would you like to continue?";
1036     aMessageBox.setText(aText);
1037     aMessageBox.exec();
1038     QMessageBox::ButtonRole aButtonRole = aMessageBox.buttonRole(aMessageBox.clickedButton());
1039
1040     if (aButtonRole == QMessageBox::NoRole)
1041       return false;
1042
1043     if (aButtonRole == QMessageBox::ActionRole) {
1044       foreach (FeaturePtr aObj, aParameterFeatures)
1045         ModelAPI_ReplaceParameterMessage::send(aObj, 0);
1046     }
1047     else
1048       theReferencesToDelete.insert(aFeaturesRefsToParameterOnly.begin(),
1049                                    aFeaturesRefsToParameterOnly.end());
1050   }
1051   return true;
1052 }
1053
1054 //**************************************************************
1055 void convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& theFeatures)
1056 {
1057   QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1058   for(; anIt != aLast; anIt++) {
1059     ObjectPtr anObject = *anIt;
1060     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
1061     // for parameter result, use the corresponded reature to be removed
1062     if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) {
1063       aFeature = ModelAPI_Feature::feature(anObject);
1064     }
1065     if (aFeature.get())
1066       theFeatures.insert(aFeature);
1067   }
1068 }
1069
1070 //**************************************************************
1071 void convertToFolders(const QObjectPtrList& theObjects,
1072                                          std::set<FolderPtr>& theFolders)
1073 {
1074   QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
1075   for(; anIt != aLast; anIt++) {
1076     ObjectPtr anObject = *anIt;
1077     FolderPtr aFeature = std::dynamic_pointer_cast<ModelAPI_Folder>(anObject);
1078     if (aFeature.get())
1079       theFolders.insert(aFeature);
1080   }
1081 }
1082
1083
1084 //**************************************************************
1085 QString translate(const Events_InfoMessage& theMessage)
1086 {
1087   QString aMessage;
1088
1089   if (!theMessage.empty()) {
1090     std::string aStr = Config_Translator::translate(theMessage);
1091     if (!aStr.empty()) {
1092       std::string aCodec = Config_Translator::codec(theMessage);
1093       aMessage = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str());
1094     }
1095   }
1096
1097   return aMessage;
1098 }
1099
1100 QString translate(const std::string& theContext, const std::string& theMessage)
1101 {
1102   QString aMessage;
1103
1104   if (!theMessage.empty()) {
1105     std::string aStr = Config_Translator::translate(theContext, theMessage);
1106     if (!aStr.empty()) {
1107       std::string aCodec = Config_Translator::codec(theContext);
1108       aMessage = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aStr.c_str());
1109     }
1110   }
1111
1112   return aMessage;
1113 }
1114
1115 void setPointBallHighlighting(AIS_Shape* theAIS)
1116 {
1117   static Handle(Image_AlienPixMap) aPixMap;
1118   if(aPixMap.IsNull()) {
1119     // Load icon for the presentation
1120     std::string aFile;
1121     char* anEnv = getenv("SHAPER_ROOT_DIR");
1122     if(anEnv) {
1123       aFile = std::string(anEnv) +
1124         FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
1125     } else {
1126       anEnv = getenv("OPENPARTS_ROOT_DIR");
1127       if (anEnv)
1128         aFile = std::string(anEnv) + FSEP + "resources";
1129     }
1130
1131     aFile += FSEP;
1132     static const std::string aMarkerName = "marker_dot.png";
1133     aFile += aMarkerName;
1134     aPixMap = new Image_AlienPixMap();
1135     if(!aPixMap->Load(aFile.c_str())) {
1136       // The icon for constraint is not found
1137       static const std::string aMsg =
1138         "Error: Point market not found by path: \"" + aFile + "\". Falling back.";
1139       //Events_InfoMessage("ModuleBase_Tools::setPointBallHighlighting", aMsg).send();
1140     }
1141   }
1142
1143   Handle(Graphic3d_AspectMarker3d) anAspect;
1144   Handle(Prs3d_Drawer) aDrawer = theAIS->DynamicHilightAttributes();
1145   if (aDrawer.IsNull()) {
1146     if (ModuleBase_IViewer::DefaultHighlightDrawer.IsNull())
1147       return;
1148     aDrawer = new Prs3d_Drawer(*ModuleBase_IViewer::DefaultHighlightDrawer);
1149     if (!aDrawer->HasOwnPointAspect()) {
1150       aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_BALL, Quantity_NOC_BLACK, 2.0));
1151     }
1152   }
1153   if(aDrawer->HasOwnPointAspect()) {
1154     Handle(Prs3d_PointAspect) aPntAspect = aDrawer->PointAspect();
1155     if(aPixMap->IsEmpty()) {
1156       anAspect = aPntAspect->Aspect();
1157       anAspect->SetType(Aspect_TOM_BALL);
1158     } else {
1159       if(aPixMap->Format() == Image_PixMap::ImgGray) {
1160         aPixMap->SetFormat (Image_PixMap::ImgAlpha);
1161       } else if(aPixMap->Format() == Image_PixMap::ImgGrayF) {
1162         aPixMap->SetFormat (Image_PixMap::ImgAlphaF);
1163       }
1164       anAspect = new Graphic3d_AspectMarker3d(aPixMap);
1165       aPntAspect->SetAspect(anAspect);
1166     }
1167     aDrawer->SetPointAspect(aPntAspect);
1168           theAIS->SetDynamicHilightAttributes(aDrawer);
1169   }
1170 }
1171
1172 } // namespace ModuleBase_Tools
1173
1174