1
/***************************************************************************
2
* Copyright (c) 2010 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
31
# include <TopTools_IndexedMapOfShape.hxx>
33
# include <Inventor/actions/SoSearchAction.h>
34
# include <Inventor/draggers/SoDragger.h>
35
# include <Inventor/manips/SoCenterballManip.h>
36
# include <Inventor/nodes/SoCoordinate3.h>
37
# include <Inventor/nodes/SoFaceSet.h>
38
# include <Inventor/nodes/SoMaterial.h>
39
# include <Inventor/nodes/SoSeparator.h>
42
#include <Gui/Application.h>
43
#include <Gui/Control.h>
44
#include <Gui/Document.h>
45
#include <Mod/Part/App/FeatureChamfer.h>
46
#include <Mod/Part/App/FeatureFillet.h>
47
#include <Mod/Part/App/FeatureMirroring.h>
48
#include <Mod/Part/App/FeatureOffset.h>
49
#include <Mod/Part/App/FeatureRevolution.h>
50
#include <Mod/Part/App/PartFeatures.h>
52
#include "ViewProviderMirror.h"
53
#include "DlgFilletEdges.h"
54
#include "TaskOffset.h"
55
#include "TaskThickness.h"
58
using namespace PartGui;
60
PROPERTY_SOURCE(PartGui::ViewProviderMirror, PartGui::ViewProviderPart)
62
ViewProviderMirror::ViewProviderMirror()
64
sPixmap = "Part_Mirror";
65
pcEditNode = new SoSeparator();
69
ViewProviderMirror::~ViewProviderMirror()
74
void ViewProviderMirror::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
76
// don't add plane editor to context menu if MirrorPlane is set because it would override any changes, anyway
77
Part::Mirroring* mf = static_cast<Part::Mirroring*>(getObject());
78
Part::Feature* ref = static_cast<Part::Feature*>(mf->MirrorPlane.getValue());
84
act = menu->addAction(QObject::tr("Edit mirror plane"), receiver, member);
85
act->setEnabled(enabled);
86
act->setData(QVariant((int)ViewProvider::Default));
88
ViewProviderPart::setupContextMenu(menu, receiver, member);
91
bool ViewProviderMirror::setEdit(int ModNum)
93
if (ModNum == ViewProvider::Default) {
94
// get the properties from the mirror feature
95
Part::Mirroring* mf = static_cast<Part::Mirroring*>(getObject());
96
Part::Feature* ref = static_cast<Part::Feature*>(mf->MirrorPlane.getValue());
97
if (ref) { //skip this editor if MirrorPlane property is set
100
Base::BoundBox3d bbox = mf->Shape.getBoundingBox();
101
float len = (float)bbox.CalcDiagonalLength();
102
Base::Vector3d base = mf->Base.getValue();
103
Base::Vector3d norm = mf->Normal.getValue();
104
Base::Vector3d cent = bbox.GetCenter();
105
base = cent.ProjectToPlane(base, norm);
107
// setup the graph for editing the mirror plane
108
SoTransform* trans = new SoTransform;
109
SbRotation rot(SbVec3f(0,0,1), SbVec3f(norm.x,norm.y,norm.z));
110
trans->rotation.setValue(rot);
111
trans->translation.setValue(base.x,base.y,base.z);
112
trans->center.setValue(0.0f,0.0f,0.0f);
114
SoMaterial* color = new SoMaterial();
115
color->diffuseColor.setValue(0,0,1);
116
color->transparency.setValue(0.5);
117
SoCoordinate3* points = new SoCoordinate3();
118
points->point.setNum(4);
119
points->point.set1Value(0, -len/2,-len/2,0);
120
points->point.set1Value(1, len/2,-len/2,0);
121
points->point.set1Value(2, len/2, len/2,0);
122
points->point.set1Value(3, -len/2, len/2,0);
123
SoFaceSet* face = new SoFaceSet();
124
pcEditNode->addChild(trans);
125
pcEditNode->addChild(color);
126
pcEditNode->addChild(points);
127
pcEditNode->addChild(face);
129
// Now we replace the SoTransform node by a manipulator
130
// Note: Even SoCenterballManip inherits from SoTransform
131
// we cannot use it directly (in above code) because the
132
// translation and center fields are overridden.
134
sa.setInterest(SoSearchAction::FIRST);
135
sa.setSearchingAll(false);
137
sa.apply(pcEditNode);
138
SoPath * path = sa.getPath();
140
SoCenterballManip * manip = new SoCenterballManip;
141
manip->replaceNode(path);
143
SoDragger* dragger = manip->getDragger();
144
dragger->addStartCallback(dragStartCallback, this);
145
dragger->addFinishCallback(dragFinishCallback, this);
146
dragger->addMotionCallback(dragMotionCallback, this);
148
pcRoot->addChild(pcEditNode);
151
ViewProviderPart::setEdit(ModNum);
157
void ViewProviderMirror::unsetEdit(int ModNum)
159
if (ModNum == ViewProvider::Default) {
160
SoCenterballManip* manip = static_cast<SoCenterballManip *>(pcEditNode->getChild(0));
162
SbVec3f move = manip->translation.getValue();
163
SbVec3f center = manip->center.getValue();
164
SbRotation rot = manip->rotation.getValue();
166
// get the whole translation
168
rot.multVec(center,center);
171
// the new axis of the plane
173
rot.multVec(norm,norm);
175
// apply the new values
176
Part::Mirroring* mf = static_cast<Part::Mirroring*>(getObject());
177
mf->Base.setValue(move[0],move[1],move[2]);
178
mf->Normal.setValue(norm[0],norm[1],norm[2]);
180
pcRoot->removeChild(pcEditNode);
181
Gui::coinRemoveAllChildren(pcEditNode);
184
ViewProviderPart::unsetEdit(ModNum);
188
std::vector<App::DocumentObject*> ViewProviderMirror::claimChildren() const
190
// Make the input object a child (see also #0001482)
191
std::vector<App::DocumentObject*> temp;
192
temp.push_back(static_cast<Part::Mirroring*>(getObject())->Source.getValue());
196
bool ViewProviderMirror::onDelete(const std::vector<std::string> &)
198
// get the input shape
199
Part::Mirroring* pMirroring = static_cast<Part::Mirroring*>(getObject());
200
App::DocumentObject *pSource = pMirroring->Source.getValue();
202
Gui::Application::Instance->showViewProvider(pSource);
207
void ViewProviderMirror::dragStartCallback(void *, SoDragger *)
209
// This is called when a manipulator is about to manipulating
210
Gui::Application::Instance->activeDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Edit Mirror"));
213
void ViewProviderMirror::dragFinishCallback(void *, SoDragger *)
215
// This is called when a manipulator has done manipulating
216
Gui::Application::Instance->activeDocument()->commitCommand();
219
void ViewProviderMirror::dragMotionCallback(void *data, SoDragger *drag)
221
ViewProviderMirror* that = static_cast<ViewProviderMirror*>(data);
222
const SbMatrix& mat = drag->getMotionMatrix();
223
// the new axis of the plane
226
rot.multVec(norm,norm);
227
Part::Mirroring* mf = static_cast<Part::Mirroring*>(that->getObject());
228
mf->Base.setValue(mat[3][0],mat[3][1],mat[3][2]);
229
mf->Normal.setValue(norm[0],norm[1],norm[2]);
232
// ----------------------------------------------------------------------------
234
PROPERTY_SOURCE(PartGui::ViewProviderFillet, PartGui::ViewProviderPart)
236
ViewProviderFillet::ViewProviderFillet()
238
sPixmap = "Part_Fillet";
241
ViewProviderFillet::~ViewProviderFillet() = default;
243
void ViewProviderFillet::updateData(const App::Property* prop)
245
PartGui::ViewProviderPart::updateData(prop);
246
if (prop->is<Part::PropertyShapeHistory>()) {
247
const std::vector<Part::ShapeHistory>& hist = static_cast<const Part::PropertyShapeHistory*>
249
if (hist.size() != 1)
251
Part::Fillet* objFill = dynamic_cast<Part::Fillet*>(getObject());
254
Part::Feature* objBase = dynamic_cast<Part::Feature*>(
255
Part::Feature::getShapeOwner(objFill->Base.getValue()));
257
const TopoDS_Shape& baseShape = objBase->Shape.getValue();
258
const TopoDS_Shape& fillShape = objFill->Shape.getValue();
260
TopTools_IndexedMapOfShape baseMap, fillMap;
261
TopExp::MapShapes(baseShape, TopAbs_FACE, baseMap);
262
TopExp::MapShapes(fillShape, TopAbs_FACE, fillMap);
264
auto vpBase = dynamic_cast<PartGui::ViewProviderPart*>(Gui::Application::Instance->getViewProvider(objBase));
266
auto colBase = static_cast<PartGui::ViewProviderPart*>(vpBase)->ShapeAppearance.getValues();
267
std::vector<App::Material> colFill;
268
colFill.resize(fillMap.Extent(), colBase[0]);
269
applyTransparency(static_cast<PartGui::ViewProviderPart*>(vpBase)->Transparency.getValue(), colBase);
271
if (static_cast<int>(colBase.size()) == baseMap.Extent()) {
272
applyMaterial(hist[0], colBase, colFill);
274
else if (!colBase.empty() && colBase[0] != this->ShapeAppearance[0]) {
275
colBase.resize(baseMap.Extent(), colBase[0]);
276
applyMaterial(hist[0], colBase, colFill);
279
// If the view provider has set a transparency then override the values
280
// of the input shapes
281
if (Transparency.getValue() > 0) {
282
applyTransparency(Transparency.getValue(), colFill);
285
this->ShapeAppearance.setValues(colFill);
291
void ViewProviderFillet::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
294
act = menu->addAction(QObject::tr("Edit fillet edges"), receiver, member);
295
act->setData(QVariant((int)ViewProvider::Default));
296
PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member);
299
bool ViewProviderFillet::setEdit(int ModNum)
301
if (ModNum == ViewProvider::Default ) {
302
if (Gui::Control().activeDialog())
304
Part::Fillet* fillet = static_cast<Part::Fillet*>(getObject());
305
Gui::Control().showDialog(new PartGui::TaskFilletEdges(fillet));
309
ViewProviderPart::setEdit(ModNum);
314
void ViewProviderFillet::unsetEdit(int ModNum)
316
if (ModNum == ViewProvider::Default) {
317
Gui::Control().closeDialog();
320
ViewProviderPart::unsetEdit(ModNum);
324
std::vector<App::DocumentObject*> ViewProviderFillet::claimChildren() const
326
std::vector<App::DocumentObject*> temp;
327
temp.push_back(static_cast<Part::Fillet*>(getObject())->Base.getValue());
331
bool ViewProviderFillet::onDelete(const std::vector<std::string> &)
333
// get the input shape
334
Part::Fillet* pFillet = static_cast<Part::Fillet*>(getObject());
335
App::DocumentObject *pBase = pFillet->Base.getValue();
337
Gui::Application::Instance->showViewProvider(pBase);
342
// ---------------------------------------
344
PROPERTY_SOURCE(PartGui::ViewProviderChamfer, PartGui::ViewProviderPart)
346
ViewProviderChamfer::ViewProviderChamfer()
348
sPixmap = "Part_Chamfer";
351
ViewProviderChamfer::~ViewProviderChamfer() = default;
353
void ViewProviderChamfer::updateData(const App::Property* prop)
355
PartGui::ViewProviderPart::updateData(prop);
356
if (prop->is<Part::PropertyShapeHistory>()) {
357
const std::vector<Part::ShapeHistory>& hist = static_cast<const Part::PropertyShapeHistory*>
359
if (hist.size() != 1)
361
Part::Chamfer* objCham = dynamic_cast<Part::Chamfer*>(getObject());
364
Part::Feature* objBase = dynamic_cast<Part::Feature*>(
365
Part::Feature::getShapeOwner(objCham->Base.getValue()));
367
const TopoDS_Shape& baseShape = objBase->Shape.getValue();
368
const TopoDS_Shape& chamShape = objCham->Shape.getValue();
370
TopTools_IndexedMapOfShape baseMap, chamMap;
371
TopExp::MapShapes(baseShape, TopAbs_FACE, baseMap);
372
TopExp::MapShapes(chamShape, TopAbs_FACE, chamMap);
374
auto vpBase = dynamic_cast<PartGui::ViewProviderPart*>(Gui::Application::Instance->getViewProvider(objBase));
376
auto colBase = static_cast<PartGui::ViewProviderPart*>(vpBase)->ShapeAppearance.getValues();
377
std::vector<App::Material> colCham;
378
colCham.resize(chamMap.Extent(), colBase[0]);
379
applyTransparency(static_cast<PartGui::ViewProviderPart*>(vpBase)->Transparency.getValue(), colBase);
381
if (static_cast<int>(colBase.size()) == baseMap.Extent()) {
382
applyMaterial(hist[0], colBase, colCham);
384
else if (!colBase.empty() && colBase[0] != this->ShapeAppearance[0]) {
385
colBase.resize(baseMap.Extent(), colBase[0]);
386
applyMaterial(hist[0], colBase, colCham);
389
// If the view provider has set a transparency then override the values
390
// of the input shapes
391
if (Transparency.getValue() > 0) {
392
applyTransparency(Transparency.getValue(), colCham);
395
this->ShapeAppearance.setValues(colCham);
401
void ViewProviderChamfer::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
404
act = menu->addAction(QObject::tr("Edit chamfer edges"), receiver, member);
405
act->setData(QVariant((int)ViewProvider::Default));
406
PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member);
409
bool ViewProviderChamfer::setEdit(int ModNum)
411
if (ModNum == ViewProvider::Default ) {
412
if (Gui::Control().activeDialog())
414
Part::Chamfer* chamfer = static_cast<Part::Chamfer*>(getObject());
415
Gui::Control().showDialog(new PartGui::TaskChamferEdges(chamfer));
419
ViewProviderPart::setEdit(ModNum);
424
void ViewProviderChamfer::unsetEdit(int ModNum)
426
if (ModNum == ViewProvider::Default) {
427
Gui::Control().closeDialog();
430
ViewProviderPart::unsetEdit(ModNum);
434
std::vector<App::DocumentObject*> ViewProviderChamfer::claimChildren() const
436
std::vector<App::DocumentObject*> temp;
437
temp.push_back(static_cast<Part::Chamfer*>(getObject())->Base.getValue());
441
bool ViewProviderChamfer::onDelete(const std::vector<std::string> &)
443
// get the input shape
444
Part::Chamfer* pChamfer = static_cast<Part::Chamfer*>(getObject());
445
App::DocumentObject *pBase = pChamfer->Base.getValue();
447
Gui::Application::Instance->showViewProvider(pBase);
452
// ---------------------------------------
454
PROPERTY_SOURCE(PartGui::ViewProviderRevolution, PartGui::ViewProviderPart)
456
ViewProviderRevolution::ViewProviderRevolution()
458
sPixmap = "Part_Revolve";
461
ViewProviderRevolution::~ViewProviderRevolution() = default;
463
std::vector<App::DocumentObject*> ViewProviderRevolution::claimChildren() const
465
std::vector<App::DocumentObject*> temp;
466
temp.push_back(static_cast<Part::Revolution*>(getObject())->Source.getValue());
470
bool ViewProviderRevolution::onDelete(const std::vector<std::string> &)
472
// get the input shape
473
Part::Revolution* pRevolve = static_cast<Part::Revolution*>(getObject());
474
App::DocumentObject *pBase = pRevolve->Source.getValue();
476
Gui::Application::Instance->showViewProvider(pBase);
481
// ---------------------------------------
483
PROPERTY_SOURCE(PartGui::ViewProviderLoft, PartGui::ViewProviderPart)
485
ViewProviderLoft::ViewProviderLoft()
487
sPixmap = "Part_Loft";
490
ViewProviderLoft::~ViewProviderLoft() = default;
492
std::vector<App::DocumentObject*> ViewProviderLoft::claimChildren() const
494
return static_cast<Part::Loft*>(getObject())->Sections.getValues();
497
bool ViewProviderLoft::onDelete(const std::vector<std::string> &)
502
// ---------------------------------------
504
PROPERTY_SOURCE(PartGui::ViewProviderSweep, PartGui::ViewProviderPart)
506
ViewProviderSweep::ViewProviderSweep()
508
sPixmap = "Part_Sweep";
511
ViewProviderSweep::~ViewProviderSweep() = default;
513
std::vector<App::DocumentObject*> ViewProviderSweep::claimChildren() const
515
auto obj = static_cast<Part::Sweep*>(getObject());
516
auto children = obj->Sections.getValues();
517
if(obj->Spine.getValue())
518
children.push_back(obj->Spine.getValue());
522
bool ViewProviderSweep::onDelete(const std::vector<std::string> &)
527
// ---------------------------------------
529
PROPERTY_SOURCE(PartGui::ViewProviderOffset, PartGui::ViewProviderPart)
531
ViewProviderOffset::ViewProviderOffset()
533
sPixmap = "Part_Offset";
536
ViewProviderOffset::~ViewProviderOffset() = default;
538
void ViewProviderOffset::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
540
addDefaultAction(menu, QObject::tr("Edit offset"));
541
PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member);
544
bool ViewProviderOffset::setEdit(int ModNum)
546
if (ModNum == ViewProvider::Default ) {
547
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
548
TaskOffset* offsetDlg = qobject_cast<TaskOffset*>(dlg);
549
if (offsetDlg && offsetDlg->getObject() != this->getObject())
550
offsetDlg = nullptr; // another pad left open its task panel
551
if (dlg && !offsetDlg) {
553
Gui::Control().closeDialog();
558
// clear the selection (convenience)
559
Gui::Selection().clearSelection();
561
// start the edit dialog
563
Gui::Control().showDialog(offsetDlg);
565
Gui::Control().showDialog(new TaskOffset(static_cast<Part::Offset*>(getObject())));
570
return ViewProviderPart::setEdit(ModNum);
574
void ViewProviderOffset::unsetEdit(int ModNum)
576
if (ModNum == ViewProvider::Default) {
577
// when pressing ESC make sure to close the dialog
578
Gui::Control().closeDialog();
581
PartGui::ViewProviderPart::unsetEdit(ModNum);
585
std::vector<App::DocumentObject*> ViewProviderOffset::claimChildren() const
587
std::vector<App::DocumentObject*> child;
588
child.push_back(static_cast<Part::Offset*>(getObject())->Source.getValue());
592
bool ViewProviderOffset::onDelete(const std::vector<std::string> &)
594
// get the support and Sketch
595
Part::Offset* offset = static_cast<Part::Offset*>(getObject());
596
App::DocumentObject* source = offset->Source.getValue();
598
Gui::Application::Instance->getViewProvider(source)->show();
604
// ---------------------------------------
606
PROPERTY_SOURCE(PartGui::ViewProviderOffset2D, PartGui::ViewProviderOffset)
609
// ---------------------------------------
611
PROPERTY_SOURCE(PartGui::ViewProviderThickness, PartGui::ViewProviderPart)
613
ViewProviderThickness::ViewProviderThickness()
615
sPixmap = "Part_Thickness";
618
ViewProviderThickness::~ViewProviderThickness() = default;
620
void ViewProviderThickness::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
622
addDefaultAction(menu, QObject::tr("Edit thickness"));
623
PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member);
626
bool ViewProviderThickness::setEdit(int ModNum)
628
if (ModNum == ViewProvider::Default ) {
629
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
630
TaskThickness* thicknessDlg = qobject_cast<TaskThickness*>(dlg);
631
if (thicknessDlg && thicknessDlg->getObject() != this->getObject())
632
thicknessDlg = nullptr; // another pad left open its task panel
633
if (dlg && !thicknessDlg) {
635
Gui::Control().closeDialog();
640
// clear the selection (convenience)
641
Gui::Selection().clearSelection();
643
// start the edit dialog
645
Gui::Control().showDialog(thicknessDlg);
647
Gui::Control().showDialog(new TaskThickness(static_cast<Part::Thickness*>(getObject())));
652
return ViewProviderPart::setEdit(ModNum);
656
void ViewProviderThickness::unsetEdit(int ModNum)
658
if (ModNum == ViewProvider::Default) {
659
// when pressing ESC make sure to close the dialog
660
QTimer::singleShot(0, &Gui::Control(), &Gui::ControlSingleton::closeDialog);
663
PartGui::ViewProviderPart::unsetEdit(ModNum);
667
std::vector<App::DocumentObject*> ViewProviderThickness::claimChildren() const
669
std::vector<App::DocumentObject*> child;
670
child.push_back(static_cast<Part::Thickness*>(getObject())->Faces.getValue());
674
bool ViewProviderThickness::onDelete(const std::vector<std::string> &)
676
// get the support and Sketch
677
Part::Thickness* thickness = static_cast<Part::Thickness*>(getObject());
678
App::DocumentObject* source = thickness->Faces.getValue();
680
Gui::Application::Instance->getViewProvider(source)->show();
686
// ---------------------------------------
688
PROPERTY_SOURCE(PartGui::ViewProviderRefine, PartGui::ViewProviderPart)
690
ViewProviderRefine::ViewProviderRefine()
692
sPixmap = "Part_Refine_Shape";
695
ViewProviderRefine::~ViewProviderRefine() = default;
697
// ---------------------------------------
699
PROPERTY_SOURCE(PartGui::ViewProviderReverse, PartGui::ViewProviderPart)
701
ViewProviderReverse::ViewProviderReverse()
703
//TODO: Need a specific icon here!
704
//sPixmap = "Part_Reverse_Shape";
707
ViewProviderReverse::~ViewProviderReverse() = default;