Salome HOME
a32267f1a6d72bc230712f4b407776d920e6a0a5
[modules/shaper.git] / src / PartSet / PartSet_WidgetSketchLabel.cpp
1 // Copyright (C) 2014-2019  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include "PartSet_WidgetSketchLabel.h"
21 #include "PartSet_Tools.h"
22 #include "PartSet_Module.h"
23 #include "PartSet_PreviewPlanes.h"
24
25 #include "SketchPlugin_SketchEntity.h"
26
27 #include <XGUI_ActionsMgr.h>
28 #include <XGUI_Displayer.h>
29 #include <XGUI_ModuleConnector.h>
30 #include <XGUI_SelectionActivate.h>
31 #include <XGUI_Selection.h>
32 #include <XGUI_SelectionMgr.h>
33 #include <XGUI_Tools.h>
34 #include <XGUI_ViewerProxy.h>
35 #include <XGUI_Workshop.h>
36
37 #include <ModelAPI_ResultBody.h>
38 #include <ModelAPI_Tools.h>
39
40 #include <ModuleBase_Operation.h>
41 #include <ModuleBase_ViewerPrs.h>
42 #include <ModuleBase_Tools.h>
43 #include <ModuleBase_IModule.h>
44 #include <ModuleBase_IPropertyPanel.h>
45
46 #include <GeomAlgoAPI_FaceBuilder.h>
47 #include <GeomAlgoAPI_ShapeTools.h>
48 #include <GeomDataAPI_Point.h>
49 #include <GeomDataAPI_Dir.h>
50 #include <GeomAPI_XYZ.h>
51 #include <GeomAPI_Face.h>
52 #include <GeomAPI_Edge.h>
53 #include <GeomAPI_ShapeExplorer.h>
54
55 #include <SketchPlugin_Sketch.h>
56 #include <SketcherPrs_Tools.h>
57
58 #include <Precision.hxx>
59 #include <gp_Pln.hxx>
60 #include <gp_Pnt.hxx>
61 #include <gp_Dir.hxx>
62 #include <AIS_Shape.hxx>
63 #include <AIS_DimensionSelectionMode.hxx>
64 #include <Bnd_Box.hxx>
65
66 #include <Config_WidgetAPI.h>
67 #include <Config_PropManager.h>
68
69 #include <QLabel>
70 #include <QApplication>
71 #include <QVBoxLayout>
72 #include <QHBoxLayout>
73 #include <QCheckBox>
74 #include <QGroupBox>
75 #include <QPushButton>
76 #include <QStackedWidget>
77 #include <QLineEdit>
78 #include <QDoubleValidator>
79
80 #ifndef DBL_MAX
81 #define DBL_MAX 1.7976931348623158e+308
82 #endif
83
84 PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
85                         ModuleBase_IWorkshop* theWorkshop,
86                         const Config_WidgetAPI* theData,
87                         const QMap<PartSet_Tools::ConstraintVisibleState, bool>& toShowConstraints)
88 : ModuleBase_WidgetValidated(theParent, theWorkshop, theData), myOpenTransaction(false)
89 {
90   QVBoxLayout* aLayout = new QVBoxLayout(this);
91   ModuleBase_Tools::zeroMargins(aLayout);
92
93   myStackWidget = new QStackedWidget(this);
94   myStackWidget->setContentsMargins(0,0,0,0);
95   aLayout->addWidget(myStackWidget);
96
97   // Define label for plane selection
98   QWidget* aFirstWgt = new QWidget(this);
99
100   // Size of the View control
101   mySizeOfViewWidget = new QWidget(aFirstWgt);
102   QHBoxLayout* aSizeLayout = new QHBoxLayout(mySizeOfViewWidget);
103   aSizeLayout->addWidget(new QLabel("Size of the view", mySizeOfViewWidget));
104   mySizeOfView = new QLineEdit(mySizeOfViewWidget);
105
106   QDoubleValidator* aValidator = new QDoubleValidator(0, DBL_MAX, 12, mySizeOfView);
107   aValidator->setLocale(ModuleBase_Tools::doubleLocale());
108   aValidator->setNotation(QDoubleValidator::StandardNotation);
109   mySizeOfView->setValidator(aValidator);
110   aSizeLayout->addWidget(mySizeOfView);
111
112   QString aText = QString::fromStdString(theData->getProperty("title"));
113   QLabel* aLabel = new QLabel(aText, aFirstWgt);
114   aLabel->setWordWrap(true);
115   QString aTooltip = QString::fromStdString(theData->getProperty("tooltip"));
116   aLabel->setToolTip(aTooltip);
117   aLabel->setIndent(5);
118
119   aLayout = new QVBoxLayout(aFirstWgt);
120   ModuleBase_Tools::zeroMargins(aLayout);
121   aLayout->addWidget(mySizeOfViewWidget);
122   aLayout->addWidget(aLabel);
123
124   myRemoveExternal = new QCheckBox(tr("Remove external dependencies"), aFirstWgt);
125   myRemoveExternal->setChecked(false);
126   aLayout->addWidget(myRemoveExternal);
127   myRemoveExternal->setVisible(false);
128
129   aLayout->addStretch(1);
130
131   myStackWidget->addWidget(aFirstWgt);
132
133   // Define widget for sketch manmagement
134   QWidget* aSecondWgt = new QWidget(this);
135   aLayout = new QVBoxLayout(aSecondWgt);
136   ModuleBase_Tools::zeroMargins(aLayout);
137
138   QGroupBox* aViewBox = new QGroupBox(tr("Sketcher plane"), this);
139   QVBoxLayout* aViewLayout = new QVBoxLayout(aViewBox);
140
141   myViewInverted = new QCheckBox(tr("Reversed"), aViewBox);
142   aViewLayout->addWidget(myViewInverted);
143
144   QPushButton* aSetViewBtn =
145     new QPushButton(QIcon(":icons/plane_view.png"), tr("Set plane view"), aViewBox);
146   connect(aSetViewBtn, SIGNAL(clicked(bool)), this, SLOT(onSetPlaneView()));
147   aViewLayout->addWidget(aSetViewBtn);
148
149   aLayout->addWidget(aViewBox);
150
151   QMap<PartSet_Tools::ConstraintVisibleState, QString> aStates;
152   aStates[PartSet_Tools::Geometrical] = tr("Show geometrical constraints");
153   aStates[PartSet_Tools::Dimensional] = tr("Show dimensional constraints");
154   aStates[PartSet_Tools::Expressions] = tr("Show existing expressions");
155
156   QMap<PartSet_Tools::ConstraintVisibleState, QString>::const_iterator anIt = aStates.begin(),
157                                                         aLast = aStates.end();
158   for (; anIt != aLast; anIt++) {
159     QCheckBox* aShowConstraints = new QCheckBox(anIt.value(), this);
160     connect(aShowConstraints, SIGNAL(toggled(bool)), this, SLOT(onShowConstraint(bool)));
161     aLayout->addWidget(aShowConstraints);
162
163     PartSet_Tools::ConstraintVisibleState aState = anIt.key();
164     myShowConstraints[aState] = aShowConstraints;
165
166     if (toShowConstraints.contains(aState))
167       aShowConstraints->setChecked(toShowConstraints[aState]);
168   }
169
170
171   QPushButton* aPlaneBtn = new QPushButton(tr("Change sketch plane"), aSecondWgt);
172   connect(aPlaneBtn, SIGNAL(clicked(bool)), SLOT(onChangePlane()));
173   aLayout->addWidget(aPlaneBtn);
174
175   myStackWidget->addWidget(aSecondWgt);
176   //setLayout(aLayout);
177
178   myPreviewPlanes = new PartSet_PreviewPlanes();
179 }
180
181 PartSet_WidgetSketchLabel::~PartSet_WidgetSketchLabel()
182 {
183 }
184
185 bool PartSet_WidgetSketchLabel::setSelection(QList<ModuleBase_ViewerPrsPtr>& theValues,
186                                              const bool theToValidate)
187 {
188   // do not use the given selection if the plane of the sketch has been already set.
189   // If this check is absent, a selected plane in the viewer can be set in the sketch
190   // even if the sketch is built on another plane.
191   if (plane().get())
192     return true;
193
194   ModuleBase_ViewerPrsPtr aPrs = theValues.first();
195   bool aDone = setSelectionInternal(theValues, theToValidate);
196   if (aDone)
197     updateByPlaneSelected(aPrs);
198   return aDone;
199 }
200
201 QList<QWidget*> PartSet_WidgetSketchLabel::getControls() const
202 {
203   QList<QWidget*> aResult;
204   aResult << myStackWidget;
205   return aResult;
206 }
207
208 bool PartSet_WidgetSketchLabel::processSelection()
209 {
210   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
211   if (aPlane.get())
212     return false;
213
214   QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
215
216   if (aSelected.empty())
217     return false;
218   ModuleBase_ViewerPrsPtr aPrs = aSelected.first();
219   bool aDone = setSelectionInternal(aSelected, false);
220   if (aDone) {
221     updateByPlaneSelected(aPrs);
222     updateObject(myFeature);
223   }
224
225   return aDone;
226 }
227
228 void PartSet_WidgetSketchLabel::onShowConstraint(bool theOn)
229 {
230   QCheckBox* aSenderCheckBox = qobject_cast<QCheckBox*>(sender());
231
232   QMap<PartSet_Tools::ConstraintVisibleState, QCheckBox*>::const_iterator
233                           anIt = myShowConstraints.begin(), aLast = myShowConstraints.end();
234
235   PartSet_Tools::ConstraintVisibleState aState = PartSet_Tools::Geometrical;
236   bool aFound = false;
237   for (; anIt != aLast && !aFound; anIt++) {
238     aFound = anIt.value() == aSenderCheckBox;
239     if (aFound)
240       aState = anIt.key();
241   }
242   if (aFound)
243     emit showConstraintToggled(aState, theOn);
244 }
245
246 void PartSet_WidgetSketchLabel::blockAttribute(const AttributePtr& theAttribute,
247                                                const bool& theToBlock, bool& isFlushesActived,
248                                                bool& isAttributeSetInitializedBlocked,
249                                                bool& isAttributeSendUpdatedBlocked)
250 {
251   ModuleBase_WidgetValidated::blockAttribute(theAttribute, theToBlock, isFlushesActived,
252                                              isAttributeSetInitializedBlocked,
253                                              isAttributeSendUpdatedBlocked);
254   // We do not restore the previous state of isAttributeSetInitializedBlocked for each of
255   // attributes. It it is necessary, these states should be append to the method attributes
256   // or stored in the widget
257
258   std::list<AttributePtr> anAttributes = myFeature->data()->attributes("");
259   std::list<AttributePtr>::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end();
260   QStringList aValues;
261   for(; anIt != aLast; anIt++) {
262     AttributePtr anAttribute = *anIt;
263     if (theToBlock)
264       anAttribute->blockSetInitialized(true);
265     else
266       anAttribute->blockSetInitialized(isAttributeSetInitializedBlocked);
267   }
268 }
269
270 bool PartSet_WidgetSketchLabel::setSelectionInternal(
271                                           const QList<ModuleBase_ViewerPrsPtr>& theValues,
272                                           const bool theToValidate)
273 {
274   bool aDone = false;
275   if (theValues.empty()) {
276     // In order to make reselection possible, set empty object and shape should be done
277     setSelectionCustom(std::shared_ptr<ModuleBase_ViewerPrs>(
278                               new ModuleBase_ViewerPrs(ObjectPtr(), GeomShapePtr(), NULL)));
279     aDone = false;
280   }
281   else {
282     // it removes the processed value from the parameters list
283     ModuleBase_ViewerPrsPtr aValue = theValues.first();//.takeFirst();
284     if (!theToValidate || isValidInFilters(aValue))
285       aDone = setSelectionCustom(aValue);
286   }
287
288   return aDone;
289 }
290
291 void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrsPtr& thePrs)
292 {
293   GeomPlanePtr aPlane = plane();
294   if (!aPlane.get())
295     return;
296   // 1. hide main planes if they have been displayed and display sketch preview plane
297   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
298
299   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
300   if (aModule) {
301     CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
302     bool isSetSizeOfView = false;
303     double aSizeOfView = 0;
304     QString aSizeOfViewStr = mySizeOfView->text();
305     if (!aSizeOfViewStr.isEmpty()) {
306       aSizeOfView = aSizeOfViewStr.toDouble(&isSetSizeOfView);
307       if (isSetSizeOfView && aSizeOfView <= 0) {
308         isSetSizeOfView = false;
309       }
310     }
311     if (isSetSizeOfView)
312       aModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, true);
313     aModule->sketchMgr()->previewSketchPlane()->createSketchPlane(aSketch, myWorkshop);
314     if (isSetSizeOfView)
315       aModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, false);
316   }
317   // 2. if the planes were displayed, change the view projection
318
319   std::shared_ptr<GeomAPI_Dir> aDir = aPlane->direction();
320   gp_XYZ aXYZ = aDir->impl<gp_Dir>().XYZ();
321   double aTwist = 0.0;
322
323   // Rotate view if the sketcher plane is selected only from preview planes
324   // Preview planes are created only if there is no any shape
325   bool aRotate = Config_PropManager::boolean(SKETCH_TAB_NAME, "rotate_to_plane");
326   if (aRotate) {
327     myWorkshop->viewer()->setViewProjection(aXYZ.X(), aXYZ.Y(), aXYZ.Z(), aTwist);
328   }
329   QString aSizeOfViewStr = mySizeOfView->text();
330   if (!aSizeOfViewStr.isEmpty()) {
331     bool isOk;
332     double aSizeOfView = aSizeOfViewStr.toDouble(&isOk);
333     if (isOk && aSizeOfView > 0) {
334       Handle(V3d_View) aView3d = myWorkshop->viewer()->activeView();
335       if (!aView3d.IsNull()) {
336         Bnd_Box aBndBox;
337         double aHalfSize = aSizeOfView/2.0;
338         aBndBox.Update(-aHalfSize, -aHalfSize, -aHalfSize, aHalfSize, aHalfSize, aHalfSize);
339         aView3d->FitAll(aBndBox, 0.01, false);
340       }
341     }
342   }
343   if (aModule)
344     aModule->onViewTransformed();
345
346   if (myOpenTransaction) {
347     SessionPtr aMgr = ModelAPI_Session::get();
348     aMgr->finishOperation();
349     myOpenTransaction = false;
350   }
351   // 3. Clear text in the label
352   myStackWidget->setCurrentIndex(1);
353   //myLabel->setText("");
354   //myLabel->setToolTip("");
355   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
356
357   // 5. Clear selection mode and define sketching mode
358   emit planeSelected(plane());
359   // after the plane is selected in the sketch, the sketch selection should be activated
360   // it can not be performed in the sketch label widget because, we don't need to switch off
361   // the selection by any label deactivation, but need to switch it off by stop the sketch
362   myWorkshop->selectionActivate()->updateSelectionFilters();
363   myWorkshop->selectionActivate()->updateSelectionModes();
364
365   // 6. Update sketcher actions
366   XGUI_ActionsMgr* anActMgr = aWorkshop->actionsMgr();
367
368   myWorkshop->updateCommandStatus();
369   aWorkshop->selector()->clearSelection();
370   myWorkshop->viewer()->update();
371
372   myRemoveExternal->setVisible(false);
373 }
374
375 std::shared_ptr<GeomAPI_Pln> PartSet_WidgetSketchLabel::plane() const
376 {
377   CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
378   return PartSet_Tools::sketchPlane(aSketch);
379 }
380
381 bool PartSet_WidgetSketchLabel::focusTo()
382 {
383   ModuleBase_Tools::setFocus(myStackWidget, "PartSet_WidgetSketchLabel::focusTo()");
384   return true;
385 }
386
387 void PartSet_WidgetSketchLabel::enableFocusProcessing()
388 {
389   myStackWidget->installEventFilter(this);
390 }
391
392 void PartSet_WidgetSketchLabel::storeAttributeValue(const AttributePtr& theAttribute)
393 {
394   ModuleBase_WidgetValidated::storeAttributeValue(theAttribute);
395 }
396
397 void PartSet_WidgetSketchLabel::restoreAttributeValue(const AttributePtr& theAttribute,
398                                                       const bool theValid)
399 {
400   ModuleBase_WidgetValidated::restoreAttributeValue(theAttribute, theValid);
401
402   // it is not necessary to save the previous plane value because the plane is chosen once
403   DataPtr aData = feature()->data();
404   AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
405     (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
406   if (aSelAttr) {
407     ResultPtr anEmptyResult;
408     GeomShapePtr anEmptyShape;
409     aSelAttr->setValue(anEmptyResult, anEmptyShape);
410   }
411 }
412
413 bool PartSet_WidgetSketchLabel::setSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
414 {
415   if (myRemoveExternal->isVisible()) {
416     if (myRemoveExternal->isChecked()) {
417       myFeature->customAction(SketchPlugin_Sketch::ACTION_REMOVE_EXTERNAL());
418     }
419   }
420   return fillSketchPlaneBySelection(thePrs);
421 }
422
423 bool PartSet_WidgetSketchLabel::canFillSketch(const ModuleBase_ViewerPrsPtr& thePrs)
424 {
425   bool aCanFillSketch = true;
426   // avoid any selection on sketch object
427   ObjectPtr anObject = thePrs->object();
428   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
429   if (aResult.get()) {
430     FeaturePtr aFeature = ModelAPI_Feature::feature(aResult);
431     if (aFeature->getKind() == SketchPlugin_Sketch::ID())
432       aCanFillSketch = false;
433   }
434   // check plane or planar face of any non-sketch object
435   if (aCanFillSketch) {
436     std::shared_ptr<GeomAPI_Face> aGeomFace;
437
438     GeomShapePtr aGeomShape = thePrs->shape();
439     if ((!aGeomShape.get() || aGeomShape->isNull()) && aResult.get()) {
440       aGeomShape = aResult->shape();
441     }
442
443     if (aGeomShape.get() && aGeomShape->shapeType() == GeomAPI_Shape::FACE) {
444       std::shared_ptr<GeomAPI_Face> aGeomFace(new GeomAPI_Face(aGeomShape));
445       aCanFillSketch = aGeomFace.get() && aGeomFace->isPlanar();
446     }
447     else
448       aCanFillSketch = false;
449   }
450   return aCanFillSketch;
451 }
452
453 bool PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(const ModuleBase_ViewerPrsPtr& thePrs)
454 {
455   bool isOwnerSet = false;
456
457   const GeomShapePtr& aShape = thePrs->shape();
458   std::shared_ptr<GeomAPI_Dir> aDir;
459
460   if (aShape.get() && !aShape->isNull()) {
461     const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
462     aDir = setSketchPlane(aTDShape);
463     isOwnerSet = aDir.get();
464   }
465   if (thePrs->object() && (feature() != thePrs->object())) {
466     FeaturePtr aFeature = ModelAPI_Feature::feature(thePrs->object());
467     DataPtr aData = feature()->data();
468     AttributeSelectionPtr aSelAttr =
469       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
470       (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
471     if (aSelAttr.get()) {
472       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(thePrs->object());
473       if (aRes.get()) {
474         GeomShapePtr aShapePtr;
475         if (!aShape.get() || aShape->isNull()) {  // selection happens in the OCC viewer
476           aShapePtr = ModelAPI_Tools::shape(aRes);
477         }
478         else { // selection happens in OB browser
479           aShapePtr = aShape;
480         }
481         if (aShapePtr.get() && aShapePtr->isFace()) {
482           const TopoDS_Shape& aTDShape = aShapePtr->impl<TopoDS_Shape>();
483           setSketchPlane(aTDShape);
484           aSelAttr->setValue(aRes, aShapePtr);
485           isOwnerSet = true;
486         }
487       }
488       else {
489         aSelAttr->setValue(aFeature, GeomShapePtr());
490         GeomShapePtr aShape = aSelAttr->value();
491         if (!aShape.get() && aSelAttr->contextFeature().get() &&
492           aSelAttr->contextFeature()->firstResult().get()) {
493           aShape = aSelAttr->contextFeature()->firstResult()->shape();
494         }
495         if (aShape.get() && aShape->isPlanar()) {
496           const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
497           setSketchPlane(aTDShape);
498           isOwnerSet = true;
499         }
500       }
501     }
502   }
503   return isOwnerSet;
504 }
505
506 void PartSet_WidgetSketchLabel::activateCustom()
507 {
508   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
509   if (aPlane.get()) {
510     myStackWidget->setCurrentIndex(1);
511     return;
512   }
513
514   myStackWidget->setCurrentIndex(0);
515   bool aBodyIsVisualized = myPreviewPlanes->hasVisualizedBodies(myWorkshop);
516
517   // Clear previous selection mode It is necessary for correct activation of preview planes
518   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
519   XGUI_Displayer* aDisp = aWorkshop->displayer();
520   aWorkshop->selectionActivate()->activateObjects(QIntList(), aDisp->displayedObjects(), false);
521
522   if (!aBodyIsVisualized) {
523     // We have to select a plane before any operation
524     myPreviewPlanes->showPreviewPlanes(myWorkshop);
525     mySizeOfViewWidget->setVisible(true);
526   }
527   else
528     mySizeOfViewWidget->setVisible(false);
529 }
530
531 void PartSet_WidgetSketchLabel::deactivate()
532 {
533   ModuleBase_WidgetValidated::deactivate();
534   bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
535   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
536
537   if (aHidePreview)
538     myWorkshop->viewer()->update();
539 }
540
541 void PartSet_WidgetSketchLabel::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
542 {
543   theModuleSelectionModes = -1;
544   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
545   if (!aPlane.get())
546     theModes << TopAbs_FACE;
547 }
548
549 void PartSet_WidgetSketchLabel::selectionFilters(QIntList& theModuleSelectionFilters,
550                                                  SelectMgr_ListOfFilter& theSelectionFilters)
551 {
552   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
553   if (aPlane.get())
554     return;
555   return ModuleBase_WidgetValidated::selectionFilters(theModuleSelectionFilters,
556                                                       theSelectionFilters);
557 }
558
559 std::shared_ptr<GeomAPI_Dir>
560   PartSet_WidgetSketchLabel::setSketchPlane(const TopoDS_Shape& theShape)
561 {
562   if (theShape.IsNull())
563     return std::shared_ptr<GeomAPI_Dir>();
564
565   // get selected shape
566   std::shared_ptr<GeomAPI_Shape> aGShape(new GeomAPI_Shape);
567   aGShape->setImpl(new TopoDS_Shape(theShape));
568
569   // get plane parameters
570   std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(aGShape));
571   std::shared_ptr<GeomAPI_Pln> aPlane = aFace->getPlane();
572   if (!aPlane.get())
573     return std::shared_ptr<GeomAPI_Dir>();
574   return setSketchPlane(aPlane);
575 }
576
577 std::shared_ptr<GeomAPI_Dir>
578   PartSet_WidgetSketchLabel::setSketchPlane(std::shared_ptr<GeomAPI_Pln> thePlane)
579 {
580   // set plane parameters to feature
581   std::shared_ptr<ModelAPI_Data> aData = feature()->data();
582   double anA, aB, aC, aD;
583   thePlane->coefficients(anA, aB, aC, aD);
584
585   // calculate attributes of the sketch
586   std::shared_ptr<GeomAPI_Dir> aNormDir(new GeomAPI_Dir(anA, aB, aC));
587   std::shared_ptr<GeomAPI_XYZ> aCoords = aNormDir->xyz();
588   std::shared_ptr<GeomAPI_XYZ> aZero(new GeomAPI_XYZ(0, 0, 0));
589   aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero));
590   std::shared_ptr<GeomAPI_Pnt> anOrigPnt(new GeomAPI_Pnt(aCoords));
591   // X axis is preferable to be dirX on the sketch
592   const double tol = Precision::Confusion();
593   bool isX = fabs(fabs(anA) - 1.0) < tol && fabs(aB) < tol && fabs(aC) < tol;
594   std::shared_ptr<GeomAPI_Dir> aTempDir(
595       isX ? new GeomAPI_Dir(0, 1, 0) : new GeomAPI_Dir(1, 0, 0));
596   std::shared_ptr<GeomAPI_Dir> aYDir(new GeomAPI_Dir(aNormDir->cross(aTempDir)));
597   std::shared_ptr<GeomAPI_Dir> aXDir(new GeomAPI_Dir(aYDir->cross(aNormDir)));
598
599   std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
600       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
601   anOrigin->setValue(anOrigPnt);
602   std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
603       aData->attribute(SketchPlugin_Sketch::NORM_ID()));
604   aNormal->setValue(aNormDir);
605   std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
606       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
607   aDirX->setValue(aXDir);
608   std::shared_ptr<GeomAPI_Dir> aDir = thePlane->direction();
609   return aDir;
610 }
611
612 void PartSet_WidgetSketchLabel::onSetPlaneView()
613 {
614   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
615   if (aPlane.get()) {
616     std::shared_ptr<GeomAPI_Dir> aDirection = aPlane->direction();
617     gp_Dir aDir = aDirection->impl<gp_Dir>();
618     if (myViewInverted->isChecked())
619       aDir.Reverse();
620     myWorkshop->viewer()->setViewProjection(aDir.X(), aDir.Y(), aDir.Z(), 0.);
621     PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
622     if (aModule)
623       aModule->onViewTransformed();
624   }
625 }
626
627
628 //******************************************************
629 QList<std::shared_ptr<ModuleBase_ViewerPrs>> PartSet_WidgetSketchLabel::findCircularEdgesInPlane()
630 {
631   QList<std::shared_ptr<ModuleBase_ViewerPrs>> aResult;
632   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
633   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
634   QObjectPtrList aDispObjects = aDisplayer->displayedObjects();
635
636   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
637   foreach(ObjectPtr aObj, aDispObjects) {
638     ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
639     if (aResObj.get()) {
640       GeomShapePtr aShape = aResObj->shape();
641       if (aShape.get()) {
642         GeomAPI_ShapeExplorer aExplorer(aShape, GeomAPI_Shape::EDGE);
643         for(; aExplorer.more(); aExplorer.next()) {
644           GeomShapePtr aEdgeShape = aExplorer.current();
645           GeomAPI_Edge anEdge(aEdgeShape);
646           if ((anEdge.isCircle() || anEdge.isArc() || anEdge.isEllipse()) &&
647                anEdge.isInPlane(aPlane)) {
648             bool isContains = false;
649             // Check that edge is not used.
650             // It is possible that the same edge will be taken from different faces
651             foreach(std::shared_ptr<ModuleBase_ViewerPrs> aPrs, aResult) {
652               GeomAPI_Edge aUsedEdge(aPrs->shape());
653               if (aUsedEdge.isEqual(aEdgeShape)) {
654                 isContains = true;
655                 break;
656               }
657             }
658             if (!isContains) {
659               std::shared_ptr<ModuleBase_ViewerPrs>
660                 aPrs(new ModuleBase_ViewerPrs(aResObj, aEdgeShape));
661               aResult.append(aPrs);
662             }
663           }
664         }
665       }
666     }
667   }
668   return aResult;
669 }
670
671 //******************************************************
672 void PartSet_WidgetSketchLabel::onChangePlane()
673 {
674   PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
675   if (aModule) {
676     mySizeOfViewWidget->setVisible(false);
677     myRemoveExternal->setVisible(true);
678     myStackWidget->setCurrentIndex(0);
679
680     CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
681     PartSet_Tools::nullifySketchPlane(aSketch);
682
683     Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_SketchPlaneFilter);
684     if (!aFilter.IsNull()) {
685       std::shared_ptr<GeomAPI_Pln> aPln;
686       Handle(ModuleBase_ShapeInPlaneFilter)::DownCast(aFilter)->setPlane(aPln);
687     }
688     XGUI_Workshop* aWorkshop = aModule->getWorkshop();
689
690     aWorkshop->selectionActivate()->updateSelectionFilters();
691     aWorkshop->selectionActivate()->updateSelectionModes();
692
693     SessionPtr aMgr = ModelAPI_Session::get();
694     aMgr->startOperation();
695     myOpenTransaction = true;
696   }
697 }