diff --git a/src/Mod/PartDesign/App/AppPartDesign.cpp b/src/Mod/PartDesign/App/AppPartDesign.cpp index 16620762f6..1f9b8136b4 100644 --- a/src/Mod/PartDesign/App/AppPartDesign.cpp +++ b/src/Mod/PartDesign/App/AppPartDesign.cpp @@ -41,8 +41,13 @@ #include "FeatureFace.h" #include "FeatureSubtractive.h" #include "FeatureAdditive.h" +#include "FeatureTransformed.h" +#include "FeatureMirrored.h" +#include "FeatureLinearPattern.h" +#include "FeaturePolarPattern.h" +#include "FeatureScaled.h" +#include "FeatureMultiTransform.h" #include "FeatureHole.h" -#include "FeaturePatternRectangular.h" extern struct PyMethodDef PartDesign_methods[]; @@ -76,14 +81,19 @@ void PartDesignExport initPartDesign() PartDesign::SketchBased ::init(); PartDesign::Subtractive ::init(); PartDesign::Additive ::init(); - PartDesign::PatternRectangular ::init(); + PartDesign::Transformed ::init(); + PartDesign::Mirrored ::init(); + PartDesign::LinearPattern ::init(); + PartDesign::PolarPattern ::init(); + PartDesign::Scaled ::init(); + PartDesign::MultiTransform ::init(); PartDesign::Hole ::init(); PartDesign::Body ::init(); PartDesign::Pad ::init(); PartDesign::Pocket ::init(); PartDesign::Fillet ::init(); PartDesign::Revolution ::init(); - PartDesign::Groove ::init(); + PartDesign::Groove ::init(); PartDesign::Chamfer ::init(); PartDesign::Face ::init(); } diff --git a/src/Mod/PartDesign/App/CMakeLists.txt b/src/Mod/PartDesign/App/CMakeLists.txt index d33676379c..1a3cf0f2e5 100644 --- a/src/Mod/PartDesign/App/CMakeLists.txt +++ b/src/Mod/PartDesign/App/CMakeLists.txt @@ -23,13 +23,27 @@ set(PartDesign_LIBS SET(Features_SRCS Feature.cpp Feature.h - FeaturePatternRectangular.h - FeaturePatternRectangular.cpp Body.cpp Body.h ) SOURCE_GROUP("Features" FILES ${Features_SRCS}) +SET(FeaturesTransformed_SRCS + FeatureTransformed.h + FeatureTransformed.cpp + FeatureMirrored.h + FeatureMirrored.cpp + FeatureLinearPattern.h + FeatureLinearPattern.cpp + FeaturePolarPattern.h + FeaturePolarPattern.cpp + FeatureScaled.h + FeatureScaled.cpp + FeatureMultiTransform.h + FeatureMultiTransform.cpp +) +SOURCE_GROUP("FeaturesTransformed" FILES ${FeaturesTransformed_SRCS}) + SET(FeaturesDressUp_SRCS FeatureDressUp.cpp FeatureDressUp.h @@ -73,6 +87,7 @@ SOURCE_GROUP("Module" FILES ${Module_SRCS}) SET(PartDesign_SRCS ${Features_SRCS} + ${FeaturesTransformed_SRCS} ${FeaturesSketchBased_SRCS} ${FeaturesDressUp_SRCS} ${Module_SRCS} diff --git a/src/Mod/PartDesign/App/Feature.cpp b/src/Mod/PartDesign/App/Feature.cpp index 17d46f4273..e8ccbd849a 100644 --- a/src/Mod/PartDesign/App/Feature.cpp +++ b/src/Mod/PartDesign/App/Feature.cpp @@ -26,6 +26,9 @@ # include # include # include +# include +# include +# include #endif @@ -55,4 +58,19 @@ TopoDS_Shape Feature::getSolid(const TopoDS_Shape& shape) const return TopoDS_Shape(); } +const gp_Pnt Feature::getPointFromFace(const TopoDS_Face& f) const +{ + if (!f.Infinite()) { + TopExp_Explorer exp; + exp.Init(f, TopAbs_VERTEX); + if (exp.More()) + return BRep_Tool::Pnt(TopoDS::Vertex(exp.Current())); + // Else try the other method + } + + // TODO: Other method, e.g. intersect X,Y,Z axis with the (unlimited?) face? + // Or get a "corner" point if the face is limited? + throw Base::Exception("getPointFromFace(): Not implemented yet for this case"); +} + } diff --git a/src/Mod/PartDesign/App/Feature.h b/src/Mod/PartDesign/App/Feature.h index b1b33662a5..f3658c0db2 100644 --- a/src/Mod/PartDesign/App/Feature.h +++ b/src/Mod/PartDesign/App/Feature.h @@ -27,6 +27,8 @@ #include #include +class gp_Pnt; + /// Base class of all additive features in PartDesign namespace PartDesign @@ -48,6 +50,10 @@ protected: * Get a solid of the given shape. If no solid is found an exception is raised. */ TopoDS_Shape getSolid(const TopoDS_Shape&) const; + + /// Grab any point from the given face + const gp_Pnt getPointFromFace(const TopoDS_Face& f) const; + }; } //namespace PartDesign diff --git a/src/Mod/PartDesign/App/FeatureLinearPattern.cpp b/src/Mod/PartDesign/App/FeatureLinearPattern.cpp new file mode 100644 index 0000000000..766a5a0177 --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureLinearPattern.cpp @@ -0,0 +1,169 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +#endif + + +#include "FeatureLinearPattern.h" +#include +#include + +using namespace PartDesign; + +namespace PartDesign { + + +PROPERTY_SOURCE(PartDesign::LinearPattern, PartDesign::Transformed) + +LinearPattern::LinearPattern() +{ + ADD_PROPERTY_TYPE(Direction,(0),"LinearPattern",(App::PropertyType)(App::Prop_None),"Direction"); + ADD_PROPERTY(StdDirection,("")); + ADD_PROPERTY(Reversed,(0)); + ADD_PROPERTY(Length,(100.0)); + ADD_PROPERTY(Occurrences,(3)); +} + +short LinearPattern::mustExecute() const +{ + if (Direction.isTouched() || + StdDirection.isTouched() || + Reversed.isTouched() || + Length.isTouched() || + Occurrences.isTouched()) + return 1; + return Transformed::mustExecute(); +} + +const std::list LinearPattern::getTransformations(const std::vector) +{ + std::string stdDirection = StdDirection.getValue(); + float distance = Length.getValue(); + if (distance < Precision::Confusion()) + throw Base::Exception("Pattern length too small"); + int occurrences = Occurrences.getValue(); + if (occurrences < 2) + throw Base::Exception("At least two occurrences required"); + bool reversed = Reversed.getValue(); + + gp_Dir dir; + double offset = distance / (occurrences - 1); + + if (!stdDirection.empty()) { + // Note: The placement code commented out below had the defect of working always on the + // absolute X,Y,Z direction, not on the relative coordinate system of the Body feature. + // It requires positionBySupport() to be called in Transformed::Execute() AFTER + // the call to getTransformations() + // New code thanks to logari81 + if (stdDirection == "X") { + //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(1,0,0)); + dir = gp_Dir(1,0,0); + } else if (stdDirection == "Y") { + //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,1,0)); + dir = gp_Dir(0,1,0); + } else if(stdDirection == "Z") { + //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,0,1)); + dir = gp_Dir(0,0,1); + } else { + throw Base::Exception("Invalid direction (must be X, Y or Z)"); + } + } else { + App::DocumentObject* refObject = Direction.getValue(); + if (refObject == NULL) + throw Base::Exception("No direction specified"); + if (!refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + throw Base::Exception("Direction reference must be edge or face of a feature"); + std::vector subStrings = Direction.getSubValues(); + if (subStrings.empty() || subStrings[0].empty()) + throw Base::Exception("No direction reference specified"); + + Part::Feature* refFeature = static_cast(refObject); + Part::TopoShape refShape = refFeature->Shape.getShape(); + TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); + + if (ref.ShapeType() == TopAbs_FACE) { + TopoDS_Face refFace = TopoDS::Face(ref); + if (refFace.IsNull()) + throw Base::Exception("Failed to extract direction plane"); + BRepAdaptor_Surface adapt(refFace); + if (adapt.GetType() != GeomAbs_Plane) + throw Base::Exception("Direction face must be planar"); + + dir = adapt.Plane().Axis().Direction(); + //gp_Dir d = adapt.Plane().Axis().Direction(); + //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(d.X(), d.Y(), d.Z())); + } else if (ref.ShapeType() == TopAbs_EDGE) { + TopoDS_Edge refEdge = TopoDS::Edge(ref); + if (refEdge.IsNull()) + throw Base::Exception("Failed to extract direction edge"); + BRepAdaptor_Curve adapt(refEdge); + if (adapt.GetType() != GeomAbs_Line) + throw Base::Exception("Direction edge must be a straight line"); + + //gp_Dir d = adapt.Line().Direction(); + //dir = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(d.X(), d.Y(), d.Z())); + dir = adapt.Line().Direction(); + } else { + throw Base::Exception("Direction reference must be edge or face"); + } + TopLoc_Location invObjLoc = this->getLocation().Inverted(); + dir.Transform(invObjLoc.Transformation()); + } + + // get the support placement + // TODO: Check for NULL pointer + /*Part::Feature* supportFeature = static_cast(originals.front()); + if (supportFeature == NULL) + throw Base::Exception("Cannot work on invalid support shape"); + Base::Placement supportPlacement = supportFeature->Placement.getValue(); + dir *= supportPlacement; + gp_Vec direction(dir.getDirection().x, dir.getDirection().y, dir.getDirection().z);*/ + gp_Vec direction(dir.X(), dir.Y(), dir.Z()); + + if (reversed) + direction.Reverse(); + + // Note: The original feature is NOT included in the list of transformations! Therefore + // we start with occurrence number 1, not number 0 + std::list transformations; + gp_Trsf trans; + transformations.push_back(trans); // identity transformation + + for (int i = 1; i < occurrences; i++) { + trans.SetTranslation(direction * i * offset); + transformations.push_back(trans); + } + + return transformations; +} + +} diff --git a/src/Mod/PartDesign/App/FeatureLinearPattern.h b/src/Mod/PartDesign/App/FeatureLinearPattern.h new file mode 100644 index 0000000000..6877441744 --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureLinearPattern.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef PARTDESIGN_FeatureLinearPattern_H +#define PARTDESIGN_FeatureLinearPattern_H + +#include +#include "FeatureTransformed.h" + + +namespace PartDesign +{ + +class PartDesignExport LinearPattern : public PartDesign::Transformed +{ + PROPERTY_HEADER(PartDesign::LinearPattern); + +public: + LinearPattern(); + + App::PropertyLinkSub Direction; + App::PropertyString StdDirection; + App::PropertyBool Reversed; + App::PropertyFloat Length; + App::PropertyInteger Occurrences; + + /** @name methods override feature */ + //@{ + short mustExecute() const; + + /// returns the type name of the view provider + const char* getViewProviderName(void) const { + return "PartDesignGui::ViewProviderLinearPattern"; + } + //@} + + /** Create transformations + * Returns a list of (Occurrences - 1) transformations since the first, untransformed instance + * is not counted. Each transformation will move the shape it is applied to by the distance + * (Length / (Occurrences - 1)) so that the transformations will cover the total Length. + * If StdDirection is "X", "Y" or "Z" then the transformation direction will be parallel to the + * corresponding axis + * If Direction contains a feature and a face name, then the transformation direction will be + * the normal of the given face, which must be planar. If it contains an edge name, then the + * transformation direction will be parallel to the given edge, which must be linear + * If Reversed is true, the direction of transformation will be opposite + */ + const std::list getTransformations(const std::vector ); +}; + +} //namespace PartDesign + + +#endif // PARTDESIGN_FeatureLinearPattern_H diff --git a/src/Mod/PartDesign/App/FeatureMirrored.cpp b/src/Mod/PartDesign/App/FeatureMirrored.cpp new file mode 100644 index 0000000000..42913f129d --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureMirrored.cpp @@ -0,0 +1,120 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +#endif + + +#include "FeatureMirrored.h" +#include + +using namespace PartDesign; + +namespace PartDesign { + + +PROPERTY_SOURCE(PartDesign::Mirrored, PartDesign::Transformed) + +Mirrored::Mirrored() +{ + ADD_PROPERTY_TYPE(MirrorPlane,(0),"Mirrored",(App::PropertyType)(App::Prop_None),"Mirror plane"); + ADD_PROPERTY(StdMirrorPlane,("")); +} + +short Mirrored::mustExecute() const +{ + if (MirrorPlane.isTouched() || + StdMirrorPlane.isTouched()) + return 1; + return Transformed::mustExecute(); +} + +const std::list Mirrored::getTransformations(const std::vector) +{ + App::DocumentObject* ref = MirrorPlane.getValue(); + std::vector subStrings = MirrorPlane.getSubValues(); + std::string stdPlane = StdMirrorPlane.getValue(); + + gp_Pnt p; + gp_Dir d; + if (!stdPlane.empty()) { + p = gp_Pnt(0,0,0); + if (stdPlane == "XY") { + d = gp_Dir(0,0,1); + } else if (stdPlane == "XZ") { + d = gp_Dir(0,1,0); + } else if(stdPlane == "YZ") { + d = gp_Dir(1,0,0); + } else { + throw Base::Exception("Invalid mirror plane (must be XY, XZ or YZ)"); + } + } else { + if (ref == NULL) + throw Base::Exception("No mirror plane selected"); + if (!ref->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + throw Base::Exception("Mirror plane must be face of a feature"); + Part::TopoShape baseShape = static_cast(ref)->Shape.getShape(); + + if (subStrings.empty() || subStrings[0].empty()) + throw Base::Exception("No mirror plane defined"); + // TODO: Check for multiple mirror planes? + + TopoDS_Face face = TopoDS::Face(baseShape.getSubShape(subStrings[0].c_str())); + if (face.IsNull()) + throw Base::Exception("Failed to extract mirror plane"); + BRepAdaptor_Surface adapt(face); + if (adapt.GetType() != GeomAbs_Plane) + throw Base::Exception("Mirror face must be planar"); + + p = getPointFromFace(face); + d = adapt.Plane().Axis().Direction(); + TopLoc_Location invObjLoc = this->getLocation().Inverted(); + p.Transform(invObjLoc.Transformation()); + d.Transform(invObjLoc.Transformation()); + } + + // get the support placement + // TODO: Check for NULL pointer + /*Part::Feature* supportFeature = static_cast(originals.front()); + if (supportFeature == NULL) + throw Base::Exception("Cannot work on invalid support shape"); + Base::Placement supportPlacement = supportFeature->Placement.getValue(); + ax *= supportPlacement; + gp_Ax2 mirrorAxis(gp_Pnt(ax.getBase().x, ax.getBase().y, ax.getBase().z), gp_Dir(ax.getDirection().x, ax.getDirection().y, ax.getDirection().z));*/ + gp_Ax2 mirrorAxis(p, d); + + std::list transformations; + gp_Trsf trans; + transformations.push_back(trans); // identity transformation + trans.SetMirror(mirrorAxis); + transformations.push_back(trans); // mirrored transformation + return transformations; +} + +} diff --git a/src/Mod/PartDesign/App/FeatureMirrored.h b/src/Mod/PartDesign/App/FeatureMirrored.h new file mode 100644 index 0000000000..b89c0500c2 --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureMirrored.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef PARTDESIGN_FeatureMirrored_H +#define PARTDESIGN_FeatureMirrored_H + +#include +#include "FeatureTransformed.h" + + +namespace PartDesign +{ + +class PartDesignExport Mirrored : public PartDesign::Transformed +{ + PROPERTY_HEADER(PartDesign::Mirrored); + +public: + Mirrored(); + + App::PropertyLinkSub MirrorPlane; + App::PropertyString StdMirrorPlane; + + /** @name methods override feature */ + //@{ + short mustExecute() const; + + /// returns the type name of the view provider + const char* getViewProviderName(void) const { + return "PartDesignGui::ViewProviderMirrored"; + } + //@} + + /** Create transformations + * Returns a list containing one transformation since the first, untransformed instance + * is not counted. The transformation will mirror the shape it is applied to on a plane + * If StdMirrorPlane is "XY", "YZ" or "YZ" then the mirror plane will the corresponding plane + * If MirrorPlane contains a feature and an face name, then the mirror plane will be + * the the given face, which must be planar + */ + const std::list getTransformations(const std::vector); +}; + +} //namespace PartDesign + + +#endif // PARTDESIGN_FeatureMirrored_H diff --git a/src/Mod/PartDesign/App/FeatureMultiTransform.cpp b/src/Mod/PartDesign/App/FeatureMultiTransform.cpp new file mode 100644 index 0000000000..6fd4af46b7 --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureMultiTransform.cpp @@ -0,0 +1,165 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +#endif + +#include "FeatureMultiTransform.h" +#include "FeatureScaled.h" +#include "FeatureAdditive.h" +#include "FeatureSubtractive.h" +#include + +#include + +using namespace PartDesign; + +namespace PartDesign { + + +PROPERTY_SOURCE(PartDesign::MultiTransform, PartDesign::Transformed) + +MultiTransform::MultiTransform() +{ + ADD_PROPERTY(Transformations,(0)); + Transformations.setSize(0); +} + +short MultiTransform::mustExecute() const +{ + if (Transformations.isTouched()) + return 1; + return Transformed::mustExecute(); +} + +const std::list MultiTransform::getTransformations(const std::vector originals) +{ + std::vector transformationFeatures = Transformations.getValues(); + + // Find centre of gravity of first original + // FIXME: This method will NOT give the expected result for more than one original! + Part::Feature* originalFeature = static_cast(originals.front()); + TopoDS_Shape original; + + if (originalFeature->getTypeId().isDerivedFrom(PartDesign::Additive::getClassTypeId())) { + PartDesign::Additive* addFeature = static_cast(originalFeature); + original = addFeature->AddShape.getShape()._Shape; + } else if (originalFeature->getTypeId().isDerivedFrom(PartDesign::Subtractive::getClassTypeId())) { + PartDesign::Subtractive* subFeature = static_cast(originalFeature); + original = subFeature->SubShape.getShape()._Shape; + } + + GProp_GProps props; + BRepGProp::VolumeProperties(original,props); + gp_Pnt cog = props.CentreOfMass(); + + std::list result; + std::list cogs; + std::vector::const_iterator f; + + for (f = transformationFeatures.begin(); f != transformationFeatures.end(); f++) { + if (!((*f)->getTypeId().isDerivedFrom(PartDesign::Transformed::getClassTypeId()))) + throw Base::Exception("Transformation features must be subclasses of Transformed"); + PartDesign::Transformed* transFeature = static_cast(*f); + std::list newTransformations = transFeature->getTransformations(originals); + + if (result.empty()) { + // First transformation Feature + result = newTransformations; + for (std::list::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); nt++) { + cogs.push_back(cog.Transformed(*nt)); + } + } else { + // Retain a copy of the first set of transformations for iterator ot + // We can't iterate through result if we are also adding elements with push_back()! + std::list oldTransformations; + result.swap(oldTransformations); // empty result to receive new transformations + std::list oldCogs; + cogs.swap(oldCogs); // empty cogs to receive new cogs + + if ((*f)->getTypeId() == PartDesign::Scaled::getClassTypeId()) { + // Diagonal method + // Multiply every element in the old transformations' slices with the corresponding + // element in the newTransformations. Example: + // a11 a12 a13 a14 b1 a11*b1 a12*b1 a13*b1 a14*b1 + // a21 a22 a23 a24 diag b2 = a21*b2 a22*b2 a23*b2 a24*b1 + // a31 a23 a33 a34 b3 a31*b3 a23*b3 a33*b3 a34*b1 + // In other words, the length of the result vector is equal to the length of the + // oldTransformations vector + + if (oldTransformations.size() % newTransformations.size() != 0) + throw Base::Exception("Number of occurrences must be a divisor of previous number of occurrences"); + + unsigned sliceLength = oldTransformations.size() / newTransformations.size(); + std::list::const_iterator ot = oldTransformations.begin(); + std::list::const_iterator oc = oldCogs.begin(); + + for (std::list::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); nt++) { + for (unsigned s = 0; s < sliceLength; s++) { + gp_Trsf trans; + double factor = nt->ScaleFactor(); // extract scale factor + + if (factor > Precision::Confusion()) { + trans.SetScale(*oc, factor); // recreate the scaled transformation to use the correct COG + trans = trans * (*ot); + cogs.push_back(*oc); // Scaling does not affect the COG + } else { + trans = (*nt) * (*ot); + cogs.push_back(oc->Transformed(*nt)); + } + result.push_back(trans); + ot++; + oc++; + } + } + } else { + // Multiplication method: Combine the new transformations with the old ones. + // All old transformations are multiplied with all new ones, so that the length of the + // result vector is the length of the old and new transformations multiplied. + // a11 a12 b1 a11*b1 a12*b1 a11*b2 a12*b2 a11*b3 a12*b3 + // a21 a22 mul b2 = a21*b1 a22*b1 a21*b2 a22*b2 a21*b3 a22*b3 + // b3 + for (std::list::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); nt++) { + std::list::const_iterator oc = oldCogs.begin(); + + for (std::list::const_iterator ot = oldTransformations.begin(); ot != oldTransformations.end(); ot++) { + result.push_back((*nt) * (*ot)); + cogs.push_back(oc->Transformed(*nt)); + oc++; + } + } + } + // What about the Additive method: Take the last (set of) transformations and use them as + // "originals" for the next transformationFeature, so that something similar to a sweep + // for transformations could be put together? + } + } + + return result; +} + +} diff --git a/src/Mod/PartDesign/App/FeaturePatternRectangular.h b/src/Mod/PartDesign/App/FeatureMultiTransform.h similarity index 53% rename from src/Mod/PartDesign/App/FeaturePatternRectangular.h rename to src/Mod/PartDesign/App/FeatureMultiTransform.h index 77aafa67db..775624f598 100644 --- a/src/Mod/PartDesign/App/FeaturePatternRectangular.h +++ b/src/Mod/PartDesign/App/FeatureMultiTransform.h @@ -1,62 +1,66 @@ -/*************************************************************************** - * Copyright (c) 2011 Juergen Riegel * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ -#ifndef PARTDESIGN_FeaturePatternRectangular_H -#define PARTDESIGN_FeaturePatternRectangular_H +#ifndef PARTDESIGN_FeatureMultiTransform_H +#define PARTDESIGN_FeatureMultiTransform_H #include -#include "Feature.h" +#include "FeatureTransformed.h" namespace PartDesign { -class PatternRectangular : public PartDesign::Feature +class PartDesignExport MultiTransform : public PartDesign::Transformed { - PROPERTY_HEADER(PartDesign::SketchBased); + PROPERTY_HEADER(PartDesign::MultiTransform); public: - PatternRectangular(); - - App::PropertyLink Base; + MultiTransform(); + App::PropertyLinkList Transformations; /** @name methods override feature */ //@{ - /// recalculate the feature - App::DocumentObjectExecReturn *execute(void); - //short mustExecute() const; - /// returns the type name of the view provider + short mustExecute() const; + /// returns the type name of the view provider const char* getViewProviderName(void) const { - return "PartDesignGui::ViewProviderPatternRectangular"; + return "PartDesignGui::ViewProviderMultiTransform"; } //@} -protected: + std::vector getOriginals() const { return Originals.getValues(); } + + /** Create transformations + * Returns a list containing the product of all transformations of the subfeatures given + * by the Transformations property. Subfeatures can be Mirrored, LinearPattern, PolarPattern and + * Scaled. + */ + const std::list getTransformations(const std::vector originals); }; } //namespace PartDesign -#endif // PARTDESIGN_FeaturePatternRectangular_H +#endif // PARTDESIGN_FeatureMultiTransform_H diff --git a/src/Mod/PartDesign/App/FeaturePatternRectangular.cpp b/src/Mod/PartDesign/App/FeaturePatternRectangular.cpp deleted file mode 100644 index d3249222e1..0000000000 --- a/src/Mod/PartDesign/App/FeaturePatternRectangular.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2011 Juergen Riegel * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" -#ifndef _PreComp_ -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -#endif - - -#include "FeaturePatternRectangular.h" - - -using namespace PartDesign; - -namespace PartDesign { - - -PROPERTY_SOURCE(PartDesign::PatternRectangular, PartDesign::Feature) - -PatternRectangular::PatternRectangular() -{ - ADD_PROPERTY(Base,(0)); -} - -//short PatternRectangular::mustExecute() const -//{ -// if (Sketch.isTouched() || -// Length.isTouched()) -// return 1; -// return 0; -//} - -App::DocumentObjectExecReturn *PatternRectangular::execute(void) -{ - //App::DocumentObject* link = Sketch.getValue(); - //if (!link) - // return new App::DocumentObjectExecReturn("No sketch linked"); - //if (!link->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) - // return new App::DocumentObjectExecReturn("Linked object is not a Sketch or Part2DObject"); - //TopoDS_Shape shape = static_cast(link)->Shape.getShape()._Shape; - //if (shape.IsNull()) - // return new App::DocumentObjectExecReturn("Linked shape object is empty"); - - //// this is a workaround for an obscure OCC bug which leads to empty tessellations - //// for some faces. Making an explicit copy of the linked shape seems to fix it. - //// The error almost happens when re-computing the shape but sometimes also for the - //// first time - //BRepBuilderAPI_Copy copy(shape); - //shape = copy.Shape(); - //if (shape.IsNull()) - // return new App::DocumentObjectExecReturn("Linked shape object is empty"); - - //TopExp_Explorer ex; - //std::vector wires; - //for (ex.Init(shape, TopAbs_WIRE); ex.More(); ex.Next()) { - // wires.push_back(TopoDS::Wire(ex.Current())); - //} - //if (/*shape.ShapeType() != TopAbs_WIRE*/wires.empty()) // there can be several wires - // return new App::DocumentObjectExecReturn("Linked shape object is not a wire"); - - //// get the Sketch plane - //Base::Placement SketchPos = static_cast(link)->Placement.getValue(); - //Base::Rotation SketchOrientation = SketchPos.getRotation(); - //Base::Vector3d SketchVector(0,0,1); - //SketchOrientation.multVec(SketchVector,SketchVector); - - //// get the support of the Sketch if any - //App::DocumentObject* SupportLink = static_cast(link)->Support.getValue(); - //Part::Feature *SupportObject = 0; - //if (SupportLink && SupportLink->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) - // SupportObject = static_cast(SupportLink); - - //if (!SupportObject) - // return new App::DocumentObjectExecReturn("No support in Sketch!"); - - //TopoDS_Shape aFace = makeFace(wires); - //if (aFace.IsNull()) - // return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); - - //// lengthen the vector - //SketchVector *= Length.getValue(); - - //// turn around for pockets - //SketchVector *= -1; - - //// extrude the face to a solid - //gp_Vec vec(SketchVector.x,SketchVector.y,SketchVector.z); - //BRepPrimAPI_MakePrism PrismMaker(aFace,vec,0,1); - //if (PrismMaker.IsDone()) { - // // if the sketch has a support fuse them to get one result object (PAD!) - // if (SupportObject) { - // const TopoDS_Shape& support = SupportObject->Shape.getValue(); - // if (support.IsNull()) - // return new App::DocumentObjectExecReturn("Support shape is invalid"); - // TopExp_Explorer xp (support, TopAbs_SOLID); - // if (!xp.More()) - // return new App::DocumentObjectExecReturn("Support shape is not a solid"); - // // Let's call algorithm computing a fuse operation: - // BRepAlgoAPI_Cut mkCut(support, PrismMaker.Shape()); - // // Let's check if the fusion has been successful - // if (!mkCut.IsDone()) - // return new App::DocumentObjectExecReturn("Cut with support failed"); - // this->Shape.setValue(mkCut.Shape()); - // } - // else{ - // return new App::DocumentObjectExecReturn("Cannot create a tool out of sketch with no support"); - // } - //} - //else - // return new App::DocumentObjectExecReturn("Could not extrude the sketch!"); - - return App::DocumentObject::StdReturn; -} - - - - -} diff --git a/src/Mod/PartDesign/App/FeaturePolarPattern.cpp b/src/Mod/PartDesign/App/FeaturePolarPattern.cpp new file mode 100644 index 0000000000..90e6b228a9 --- /dev/null +++ b/src/Mod/PartDesign/App/FeaturePolarPattern.cpp @@ -0,0 +1,159 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +#endif + + +#include "FeaturePolarPattern.h" +#include +#include +#include + +using namespace PartDesign; + +namespace PartDesign { + + +PROPERTY_SOURCE(PartDesign::PolarPattern, PartDesign::Transformed) + +PolarPattern::PolarPattern() +{ + ADD_PROPERTY_TYPE(Axis,(0),"PolarPattern",(App::PropertyType)(App::Prop_None),"Direction"); + ADD_PROPERTY(StdAxis,("")); + ADD_PROPERTY(Reversed,(0)); + ADD_PROPERTY(Angle,(360.0)); + ADD_PROPERTY(Occurrences,(3)); +} + +short PolarPattern::mustExecute() const +{ + if (Axis.isTouched() || + StdAxis.isTouched() || + Reversed.isTouched() || + Angle.isTouched() || + Occurrences.isTouched()) + return 1; + return Transformed::mustExecute(); +} + +const std::list PolarPattern::getTransformations(const std::vector) +{ + std::string stdAxis = StdAxis.getValue(); + float angle = Angle.getValue(); + if (angle < Precision::Confusion()) + throw Base::Exception("Pattern angle too small"); + int occurrences = Occurrences.getValue(); + if (occurrences < 2) + throw Base::Exception("At least two occurrences required"); + bool reversed = Reversed.getValue(); + + double offset; + if (std::abs(angle - 360.0) < Precision::Confusion()) + offset = Base::toRadians(angle) / occurrences; // Because e.g. two occurrences in 360 degrees need to be 180 degrees apart + else + offset = Base::toRadians(angle) / (occurrences - 1); + + gp_Pnt axbase; + gp_Dir axdir; + if (!stdAxis.empty()) { + axbase = gp_Pnt(0,0,0); + if (stdAxis == "X") { + axdir = gp_Dir(1,0,0); + //ax = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(1,0,0)); + } else if (stdAxis == "Y") { + axdir = gp_Dir(0,1,0); + //ax = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,1,0)); + } else if(stdAxis == "Z") { + axdir = gp_Dir(0,0,1); + //ax = Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(0,0,1)); + } else { + throw Base::Exception("Invalid axis (must be X, Y or Z)"); + } + } else { + App::DocumentObject* refObject = Axis.getValue(); + if (refObject == NULL) + throw Base::Exception("No axis specified"); + if (!refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + throw Base::Exception("Axis reference must be edge of a feature"); + std::vector subStrings = Axis.getSubValues(); + if (subStrings.empty() || subStrings[0].empty()) + throw Base::Exception("No axis reference specified"); + + Part::Feature* refFeature = static_cast(refObject); + Part::TopoShape refShape = refFeature->Shape.getShape(); + TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); + + if (ref.ShapeType() == TopAbs_EDGE) { + TopoDS_Edge refEdge = TopoDS::Edge(ref); + if (refEdge.IsNull()) + throw Base::Exception("Failed to extract axis edge"); + BRepAdaptor_Curve adapt(refEdge); + if (adapt.GetType() != GeomAbs_Line) + throw Base::Exception("Axis edge must be a straight line"); + + axbase = adapt.Value(adapt.FirstParameter()); + axdir = adapt.Line().Direction(); + } else { + throw Base::Exception("Axis reference must be an edge"); + } + + TopLoc_Location invObjLoc = this->getLocation().Inverted(); + axbase.Transform(invObjLoc.Transformation()); + axdir.Transform(invObjLoc.Transformation()); + } + + // get the support placement + // TODO: Check for NULL pointer + /*Part::Feature* supportFeature = static_cast(originals.front()); + if (supportFeature == NULL) + throw Base::Exception("Cannot work on invalid support shape"); + Base::Placement supportPlacement = supportFeature->Placement.getValue(); + ax *= supportPlacement; + gp_Ax2 axis(gp_Pnt(ax.getBase().x, ax.getBase().y, ax.getBase().z), gp_Dir(ax.getDirection().x, ax.getDirection().y, ax.getDirection().z));*/ + gp_Ax2 axis(axbase, axdir); + + if (reversed) + axis.SetDirection(axis.Direction().Reversed()); + + // Note: The original feature is NOT included in the list of transformations! Therefore + // we start with occurrence number 1, not number 0 + std::list transformations; + gp_Trsf trans; + transformations.push_back(trans); // identity transformation + + for (int i = 1; i < occurrences; i++) { + trans.SetRotation(axis.Axis(), i * offset); + transformations.push_back(trans); + } + + return transformations; +} + +} diff --git a/src/Mod/PartDesign/App/FeaturePolarPattern.h b/src/Mod/PartDesign/App/FeaturePolarPattern.h new file mode 100644 index 0000000000..4b05494bfb --- /dev/null +++ b/src/Mod/PartDesign/App/FeaturePolarPattern.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef PARTDESIGN_FeaturePolarPattern_H +#define PARTDESIGN_FeaturePolarPattern_H + +#include +#include "FeatureTransformed.h" + + +namespace PartDesign +{ + +class PartDesignExport PolarPattern : public PartDesign::Transformed +{ + PROPERTY_HEADER(PartDesign::PolarPattern); + +public: + PolarPattern(); + + App::PropertyLinkSub Axis; + App::PropertyString StdAxis; + App::PropertyBool Reversed; + App::PropertyFloat Angle; + App::PropertyInteger Occurrences; + + /** @name methods override feature */ + //@{ + short mustExecute() const; + + /// returns the type name of the view provider + const char* getViewProviderName(void) const { + return "PartDesignGui::ViewProviderPolarPattern"; + } + //@} + + /** Create transformations + * Returns a list of (Occurrences - 1) transformations since the first, untransformed instance + * is not counted. Each transformation will rotate the shape it is applied to by the angle + * (Angle / (Occurrences - 1)) so that the transformations will cover the total Angle. The only + * exception is Angle = 360 degrees in which case the transformation angle will be + * (Angle / Occurrences) so that the last transformed shape is not identical with the original shape + * If StdAxis is "X", "Y" or "Z" then the transformation axis will the corresponding axis + * If Axis contains a feature and an edge name, then the transformation axis will be + * the the given edge, which must be linear + * If Reversed is true, the direction of rotation will be opposite + */ + const std::list getTransformations(const std::vector); +}; + +} //namespace PartDesign + + +#endif // PARTDESIGN_FeaturePolarPattern_H diff --git a/src/Mod/PartDesign/App/FeatureScaled.cpp b/src/Mod/PartDesign/App/FeatureScaled.cpp new file mode 100644 index 0000000000..0473f03942 --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureScaled.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +#endif + +#include "FeatureScaled.h" +#include "FeatureAdditive.h" +#include "FeatureSubtractive.h" +#include + +using namespace PartDesign; + +#include + +namespace PartDesign { + + +PROPERTY_SOURCE(PartDesign::Scaled, PartDesign::Transformed) + +Scaled::Scaled() +{ + ADD_PROPERTY(Factor,(2.0)); + ADD_PROPERTY(Occurrences,(2)); +} + +short Scaled::mustExecute() const +{ + if (Factor.isTouched() || + Occurrences.isTouched()) + return 1; + return Transformed::mustExecute(); +} + +const std::list Scaled::getTransformations(const std::vector originals) +{ + double factor = Factor.getValue(); + if (factor < Precision::Confusion()) + throw Base::Exception("Scaling factor too small"); + int occurrences = Occurrences.getValue(); + if (occurrences < 2) + throw Base::Exception("At least two occurrences required"); + + double f = (factor - 1.0) / double(occurrences - 1); + + // Find centre of gravity of first original + // FIXME: This method will NOT give the expected result for more than one original! + Part::Feature* originalFeature = static_cast(originals.front()); + TopoDS_Shape original; + + if (originalFeature->getTypeId().isDerivedFrom(PartDesign::Additive::getClassTypeId())) { + PartDesign::Additive* addFeature = static_cast(originalFeature); + original = addFeature->AddShape.getShape()._Shape; + } else if (originalFeature->getTypeId().isDerivedFrom(PartDesign::Subtractive::getClassTypeId())) { + PartDesign::Subtractive* subFeature = static_cast(originalFeature); + original = subFeature->SubShape.getShape()._Shape; + } + + GProp_GProps props; + BRepGProp::VolumeProperties(original,props); + gp_Pnt cog = props.CentreOfMass(); + + // Note: The original feature is NOT included in the list of transformations! Therefore + // we start with occurrence number 1, not number 0 + std::list transformations; + gp_Trsf trans; + transformations.push_back(trans); // identity transformation + + for (int i = 1; i < occurrences; i++) { + trans.SetScale(cog, 1.0 + double(i) * f); + transformations.push_back(trans); + } + + return transformations; +} + +} diff --git a/src/Mod/PartDesign/App/FeatureScaled.h b/src/Mod/PartDesign/App/FeatureScaled.h new file mode 100644 index 0000000000..731a432678 --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureScaled.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef PARTDESIGN_FeatureScaled_H +#define PARTDESIGN_FeatureScaled_H + +#include +#include "FeatureTransformed.h" + + +namespace PartDesign +{ + +class PartDesignExport Scaled : public PartDesign::Transformed +{ + PROPERTY_HEADER(PartDesign::Scaled); + +public: + Scaled(); + + App::PropertyFloat Factor; + App::PropertyInteger Occurrences; + + /** @name methods override feature */ + //@{ + short mustExecute() const; + + /// returns the type name of the view provider + const char* getViewProviderName(void) const { + return "PartDesignGui::ViewProviderScaled"; + } + //@} + + /** Create transformations + * Returns a list containing (Occurrences-1) transformation since the first, untransformed instance + * is not counted. Each transformation will scale the shape it is applied to by the factor + * (Factor / (Occurrences - 1)) + * The centre point of the scaling (currently) is the centre of gravity of the first original shape + * for this reason we need to pass the list of originals into the feature + */ + // Note: We can't just use the Originals property because this will fail if the Scaled feature + // is being used inside a MultiTransform feature + const std::list getTransformations(const std::vector originals); +}; + +} //namespace PartDesign + + +#endif // PARTDESIGN_FeatureScaled_H diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp new file mode 100644 index 0000000000..6bef61a1ab --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -0,0 +1,255 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + + +#include "FeatureTransformed.h" +#include "FeatureMultiTransform.h" +#include "FeatureAdditive.h" +#include "FeatureSubtractive.h" +#include "FeatureMirrored.h" + +#include + +using namespace PartDesign; + +namespace PartDesign { + +PROPERTY_SOURCE(PartDesign::Transformed, PartDesign::Feature) + +Transformed::Transformed() +{ + ADD_PROPERTY(Originals,(0)); + Originals.setSize(0); + ADD_PROPERTY(InsideMultiTransform,(0)); +} + +void Transformed::positionBySupport(void) +{ + Part::Feature *support = static_cast(getOriginalObject()); + if ((support != NULL) && support->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + this->Placement.setValue(support->Placement.getValue()); +} + +App::DocumentObject* Transformed::getOriginalObject() const +{ + if (!Originals.getValues().empty()) + return Originals.getValues().front(); + else + return NULL; +} + +short Transformed::mustExecute() const +{ + if (Originals.isTouched()) + return 1; + return PartDesign::Feature::mustExecute(); +} + +App::DocumentObjectExecReturn *Transformed::execute(void) +{ + if (InsideMultiTransform.getValue()) + return App::DocumentObject::StdReturn; + + std::vector originals = Originals.getValues(); + if (originals.empty()) + return new App::DocumentObjectExecReturn("No originals defined"); + + this->positionBySupport(); + + // get transformations from subclass by calling virtual method + std::list transformations; + try { + transformations = getTransformations(originals); + } catch (Base::Exception& e) { + return new App::DocumentObjectExecReturn(e.what()); + } + + if (transformations.empty()) + return new App::DocumentObjectExecReturn("No transformations defined"); + + // Get the support + // NOTE: Because of the way we define the support, FeatureTransformed can only work on + // one Body feature at a time + // TODO: Currently, the support is simply the first Original. Change this to the Body feature later + Part::Feature* supportFeature = static_cast(originals.front()); + const Part::TopoShape& supportTopShape = supportFeature->Shape.getShape(); + if (supportTopShape._Shape.IsNull()) + return new App::DocumentObjectExecReturn("Cannot transform invalid shape"); + + // create an untransformed copy of the support shape + Part::TopoShape supportShape(supportTopShape); + supportShape.setTransform(Base::Matrix4D()); + TopoDS_Shape support = supportShape._Shape; + + // Prepare a bounding box for intersection tests + Bnd_Box support_bb; + BRepBndLib::Add(support, support_bb); + + // NOTE: It would be possible to build a compound from all original addShapes/subShapes and then + // transform the compounds as a whole. But we choose to apply the transformations to each + // Original separately. This way it is easier to discover what feature causes a fuse/cut + // to fail. The downside is that performance suffers when there are many originals. But it seems + // safe to assume that in most cases there are few originals and many transformations + for (std::vector::const_iterator o = originals.begin(); o != originals.end(); o++) + { + TopoDS_Shape shape; + bool fuse; + + if ((*o)->getTypeId().isDerivedFrom(PartDesign::Additive::getClassTypeId())) { + PartDesign::Additive* addFeature = static_cast(*o); + shape = addFeature->AddShape.getShape()._Shape; + fuse = true; + } else if ((*o)->getTypeId().isDerivedFrom(PartDesign::Subtractive::getClassTypeId())) { + PartDesign::Subtractive* subFeature = static_cast(*o); + shape = subFeature->SubShape.getShape()._Shape; + fuse = false; + } else { + return new App::DocumentObjectExecReturn("Only additive and subtractive features can be transformed"); + } + + // Transform the add/subshape and build a compound from the transformations, + BRep_Builder builder; + TopoDS_Compound transformedShapes; + builder.MakeCompound(transformedShapes); + std::vector v_transformedShapes; // collect all the transformed shapes for history building + std::list::const_iterator t = transformations.begin(); + t++; // Skip first transformation, which is always the identity transformation + + for (; t != transformations.end(); t++) + { + // Make an explicit copy of the shape because the "true" parameter to BRepBuilderAPI_Transform + // seems to be pretty broken + BRepBuilderAPI_Copy copy(shape); + shape = copy.Shape(); + if (shape.IsNull()) + throw Base::Exception("Transformed: Linked shape object is empty"); + + BRepBuilderAPI_Transform mkTrf(shape, *t, false); // No need to copy, now + if (!mkTrf.IsDone()) + return new App::DocumentObjectExecReturn("Transformation failed", (*o)); + + // Check for intersection with support + Bnd_Box transformed_bb; + BRepBndLib::Add(mkTrf.Shape(), transformed_bb); + if (support_bb.Distance(transformed_bb) > Precision::Confusion()) { + Base::Console().Warning("Transformed shape does not intersect original %s: Removed\n", (*o)->getNameInDocument()); + // Note: The removal happens in getSolid() after the fuse. If we remove here, + // the histories get messed up and we get a crash + } + builder.Add(transformedShapes, mkTrf.Shape()); + v_transformedShapes.push_back(mkTrf.Shape()); + + /* + // Note: This method is only stable for Linear and Polar transformations. No need to + // make an explicit copy of the shape, either + TopoDS_Shape trfShape = shape.Moved(TopLoc_Location(*t)); + + // Check for intersection with support + Bnd_Box transformed_bb; + BRepBndLib::Add(trfShape, transformed_bb); + if (support_bb.Distance(transformed_bb) > Precision::Confusion()) { + Base::Console().Warning("Transformed shape does not intersect original %s: Removed\n", (*o)->getNameInDocument()); + // Note: The removal happens in getSolid() after the fuse. If we remove here, + // the histories get messed up and we get a crash + } + builder.Add(transformedShapes, trfShape); + v_transformedShapes.push_back(trfShape); + + */ + } + + // Check for intersection of the original and the transformed shape + // Note: For performance reasons, we only check for intersection of bounding boxes + Bnd_Box original_bb; + BRepBndLib::Add(shape, original_bb); + original_bb.SetGap(0); + + for (std::vector::const_iterator s = v_transformedShapes.begin(); s != v_transformedShapes.end(); s++) + { + // If there is only one transformed feature, this check is not necessary (though it might seem + // illogical to the user why we allow overlapping shapes in this case! + if (v_transformedShapes.size() == 1) + break; + + Bnd_Box transformed_bb; + BRepBndLib::Add(*s, transformed_bb); + transformed_bb.SetGap(0); + if (!original_bb.IsOut(transformed_bb)) + // if (original_bb.Distance(transformed_bb) < Precision::Confusion()) + // FIXME: Both tests fail if the objects are touching one another at zero distance + return new App::DocumentObjectExecReturn("Transformed objects are overlapping, try using a higher length or reducing the number of occurrences", (*o)); + // Note: This limitation could be overcome by fusing the transformed features instead of + // compounding them, probably at the expense of quite a bit of performance and complexity + // in this code + + // For MultiTransform, just checking the first transformed shape is not sufficient - any two + // features might overlap, even if the original and the first shape don't overlap! + if (this->getTypeId() != PartDesign::MultiTransform::getClassTypeId()) + break; + } + + // Fuse/Cut the compounded transformed shapes with the support + TopoDS_Shape result; + + if (fuse) { + BRepAlgoAPI_Fuse mkFuse(support, transformedShapes); + if (!mkFuse.IsDone()) + return new App::DocumentObjectExecReturn("Fusion with support failed", *o); + // we have to get the solids (fuse sometimes creates compounds) + // Note: Because getSolid() only returns the first solid in the explorer, all + // solids that are outside the support automatically disappear! + result = this->getSolid(mkFuse.Shape()); + // lets check if the result is a solid + if (result.IsNull()) + return new App::DocumentObjectExecReturn("Transformed: Resulting shape is not a solid", *o); + + } else { + BRepAlgoAPI_Cut mkCut(support, transformedShapes); + if (!mkCut.IsDone()) + return new App::DocumentObjectExecReturn("Cut out of support failed", *o); + result = mkCut.Shape(); + } + + support = result; // Use result of this operation for fuse/cut of next original + } + + this->Shape.setValue(support); + + return App::DocumentObject::StdReturn; +} + +} diff --git a/src/Mod/PartDesign/App/FeatureTransformed.h b/src/Mod/PartDesign/App/FeatureTransformed.h new file mode 100644 index 0000000000..bd07d7bd8f --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureTransformed.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef PARTDESIGN_FeatureTransformed_H +#define PARTDESIGN_FeatureTransformed_H + +#include + +#include +#include "Feature.h" + + +namespace PartDesign +{ + +/** + * Abstract superclass of all features that are created by transformation of another feature + * Transformations are translation, rotation and mirroring + */ +class PartDesignExport Transformed : public PartDesign::Feature +{ + PROPERTY_HEADER(PartDesign::Transformed); + +public: + Transformed(); + + /// The shapes to be transformed + App::PropertyLinkList Originals; + /// Flag indicating that the associated FeatureTransformed instance is just a container for storing transformation data + App::PropertyBool InsideMultiTransform; + + /// Return first original, which serves as "Support" until Body feature becomes functional + App::DocumentObject* getOriginalObject() const; + + /// Get the list of transformations describing the members of the pattern + // Note: Only the Scaled feature requires the originals + virtual const std::list getTransformations(const std::vector originals) { + return std::list(); // Default method + } + + /** @name methods override feature */ + //@{ + /** Recalculate the feature + * Gets the transformations from the virtual getTransformations() method of the sub class + * and applies them to every member of Originals. The total number of copies including + * the untransformed Originals will be sizeof(Originals) times sizeof(getTransformations()) + * If InsideMultiTransform is true, execute() returns immediately without doing anything as + * the actual processing will happen in the MultiTransform feature + */ + App::DocumentObjectExecReturn *execute(void); + short mustExecute() const; + //@} + + void positionBySupport(void); + +protected: + void buildTransformHistory(BRepBuilderAPI_MakeShape& mkFuse, + const TopoDS_Shape& newShape, + const TopoDS_Shape& oldShape, + const int index); +}; + +} //namespace PartDesign + + +#endif // PARTDESIGN_FeatureTransformed_H diff --git a/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp b/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp index 32e7187786..c4ae7118ef 100644 --- a/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp +++ b/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp @@ -38,6 +38,11 @@ #include "ViewProviderFillet.h" #include "ViewProviderRevolution.h" #include "ViewProviderGroove.h" +#include "ViewProviderMirrored.h" +#include "ViewProviderLinearPattern.h" +#include "ViewProviderPolarPattern.h" +//#include "ViewProviderScaled.h" +#include "ViewProviderMultiTransform.h" //#include "resources/qrc_PartDesign.cpp" @@ -79,14 +84,19 @@ void PartDesignGuiExport initPartDesignGui() // instantiating the commands CreatePartDesignCommands(); - PartDesignGui::Workbench ::init(); - PartDesignGui::ViewProvider ::init(); - PartDesignGui::ViewProviderPocket ::init(); - PartDesignGui::ViewProviderPad ::init(); - PartDesignGui::ViewProviderRevolution::init(); - PartDesignGui::ViewProviderGroove ::init(); - PartDesignGui::ViewProviderChamfer ::init(); - PartDesignGui::ViewProviderFillet ::init(); + PartDesignGui::Workbench ::init(); + PartDesignGui::ViewProvider ::init(); + PartDesignGui::ViewProviderPocket ::init(); + PartDesignGui::ViewProviderPad ::init(); + PartDesignGui::ViewProviderRevolution ::init(); + PartDesignGui::ViewProviderGroove ::init(); + PartDesignGui::ViewProviderChamfer ::init(); + PartDesignGui::ViewProviderFillet ::init(); + PartDesignGui::ViewProviderMirrored ::init(); + PartDesignGui::ViewProviderLinearPattern ::init(); + PartDesignGui::ViewProviderPolarPattern ::init(); +// PartDesignGui::ViewProviderScaled ::init(); + PartDesignGui::ViewProviderMultiTransform::init(); // add resources and reloads the translators loadPartDesignResource(); diff --git a/src/Mod/PartDesign/Gui/CMakeLists.txt b/src/Mod/PartDesign/Gui/CMakeLists.txt index 0aa1cb9189..97b9b8e5f2 100644 --- a/src/Mod/PartDesign/Gui/CMakeLists.txt +++ b/src/Mod/PartDesign/Gui/CMakeLists.txt @@ -26,13 +26,18 @@ set(PartDesignGui_LIBS set(PartDesignGui_MOC_HDRS TaskPadParameters.h - TaskPatternRectangularParameters.h TaskPocketParameters.h TaskChamferParameters.h TaskFilletParameters.h TaskHoleParameters.h TaskRevolutionParameters.h TaskGrooveParameters.h + TaskTransformedParameters.h + TaskMirroredParameters.h + TaskLinearPatternParameters.h + TaskPolarPatternParameters.h + TaskScaledParameters.h + TaskMultiTransformParameters.h ) fc_wrap_cpp(PartDesignGui_MOC_SRCS ${PartDesignGui_MOC_HDRS}) SOURCE_GROUP("Moc" FILES ${PartDesignGui_MOC_SRCS}) @@ -41,13 +46,17 @@ qt4_add_resources(PartDesignGui_SRCS Resources/PartDesign.qrc) set(PartDesignGui_UIC_SRCS TaskPadParameters.ui - TaskPatternRectangularParameters.ui TaskPocketParameters.ui TaskChamferParameters.ui TaskFilletParameters.ui TaskHoleParameters.ui TaskRevolutionParameters.ui TaskGrooveParameters.ui + TaskMirroredParameters.ui + TaskLinearPatternParameters.ui + TaskPolarPatternParameters.ui + TaskScaledParameters.ui + TaskMultiTransformParameters.ui ) qt4_wrap_ui(PartDesignGui_UIC_HDRS ${PartDesignGui_UIC_SRCS}) @@ -68,8 +77,18 @@ SET(PartDesignGuiViewProvider_SRCS ViewProviderRevolution.h ViewProviderGroove.cpp ViewProviderGroove.h - ViewProviderPatternRectangular.cpp - ViewProviderPatternRectangular.h + ViewProviderTransformed.cpp + ViewProviderTransformed.h + ViewProviderMirrored.cpp + ViewProviderMirrored.h + ViewProviderLinearPattern.cpp + ViewProviderLinearPattern.h + ViewProviderPolarPattern.cpp + ViewProviderPolarPattern.h + ViewProviderScaled.cpp + ViewProviderScaled.h + ViewProviderMultiTransform.cpp + ViewProviderMultiTransform.h ) SOURCE_GROUP("ViewProvider" FILES ${PartDesignGuiViewProvider_SRCS}) @@ -77,9 +96,6 @@ SET(PartDesignGuiTaskDlgs_SRCS TaskPadParameters.ui TaskPadParameters.cpp TaskPadParameters.h - TaskPatternRectangularParameters.ui - TaskPatternRectangularParameters.cpp - TaskPatternRectangularParameters.h TaskPocketParameters.ui TaskPocketParameters.cpp TaskPocketParameters.h @@ -95,6 +111,23 @@ SET(PartDesignGuiTaskDlgs_SRCS TaskGrooveParameters.ui TaskGrooveParameters.cpp TaskGrooveParameters.h + TaskTransformedParameters.h + TaskTransformedParameters.cpp + TaskMirroredParameters.ui + TaskMirroredParameters.cpp + TaskMirroredParameters.h + TaskLinearPatternParameters.ui + TaskLinearPatternParameters.cpp + TaskLinearPatternParameters.h + TaskPolarPatternParameters.ui + TaskPolarPatternParameters.cpp + TaskPolarPatternParameters.h + TaskScaledParameters.ui + TaskScaledParameters.cpp + TaskScaledParameters.h + TaskMultiTransformParameters.ui + TaskMultiTransformParameters.cpp + TaskMultiTransformParameters.h TaskHoleParameters.ui TaskHoleParameters.cpp TaskHoleParameters.h diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 335d6d5dd6..8fd3b9e673 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -47,7 +47,8 @@ #include #include - +#include +#include using namespace std; @@ -696,6 +697,319 @@ bool CmdPartDesignChamfer::isActive(void) return hasActiveDocument(); } +//=========================================================================== +// PartDesign_Mirrored +//=========================================================================== +DEF_STD_CMD_A(CmdPartDesignMirrored); + +CmdPartDesignMirrored::CmdPartDesignMirrored() + : Command("PartDesign_Mirrored") +{ + sAppModule = "PartDesign"; + sGroup = QT_TR_NOOP("PartDesign"); + sMenuText = QT_TR_NOOP("Mirrored"); + sToolTipText = QT_TR_NOOP("create a mirrored feature"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "PartDesign_Mirrored"; +} + +void CmdPartDesignMirrored::activated(int iMsg) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + if (n < 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select one or more additive/subtractive features, please.")); + return; + } + + std::string FeatName = getUniqueObjectName("Mirrored"); + + std::vector Sel = getSelection().getSelection(); + std::stringstream str; + std::vector tempSelNames; + str << "App.activeDocument()." << FeatName << ".Originals = ["; + for (std::vector::iterator it = Sel.begin(); it != Sel.end(); ++it){ + str << "App.activeDocument()." << it->FeatName << ","; + tempSelNames.push_back(it->FeatName); + } + str << "]"; + + openCommand("Mirrored"); + doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Mirrored\",\"%s\")",FeatName.c_str()); + // FIXME: There seems to be kind of a race condition here, leading to sporadic errors like + // Exception (Thu Sep 6 11:52:01 2012): 'App.Document' object has no attribute 'Mirrored' + updateActive(); // Helps to ensure that the object already exists when the next command comes up + doCommand(Doc,str.str().c_str()); + doCommand(Doc,"App.activeDocument().%s.StdMirrorPlane = \"XY\"", FeatName.c_str()); + for (std::vector::iterator it = tempSelNames.begin(); it != tempSelNames.end(); ++it) + doCommand(Gui,"Gui.activeDocument().%s.Visibility=False",it->c_str()); + + updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + + copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); + copyVisual(FeatName.c_str(), "DisplayMode", tempSelNames.front().c_str()); +} + +bool CmdPartDesignMirrored::isActive(void) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + return n >= 1; +} + +//=========================================================================== +// PartDesign_LinearPattern +//=========================================================================== +DEF_STD_CMD_A(CmdPartDesignLinearPattern); + +CmdPartDesignLinearPattern::CmdPartDesignLinearPattern() + : Command("PartDesign_LinearPattern") +{ + sAppModule = "PartDesign"; + sGroup = QT_TR_NOOP("PartDesign"); + sMenuText = QT_TR_NOOP("LinearPattern"); + sToolTipText = QT_TR_NOOP("create a linear pattern feature"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "PartDesign_LinearPattern"; +} + +void CmdPartDesignLinearPattern::activated(int iMsg) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + if (n < 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select one or more additive/subtractive features, please.")); + return; + } + + std::string FeatName = getUniqueObjectName("LinearPattern"); + + std::vector Sel = getSelection().getSelection(); + std::stringstream str; + std::vector tempSelNames; + str << "App.activeDocument()." << FeatName << ".Originals = ["; + for (std::vector::iterator it = Sel.begin(); it != Sel.end(); ++it){ + str << "App.activeDocument()." << it->FeatName << ","; + tempSelNames.push_back(it->FeatName); + } + str << "]"; + + openCommand("LinearPattern"); + doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::LinearPattern\",\"%s\")",FeatName.c_str()); + updateActive(); + doCommand(Doc,str.str().c_str()); + doCommand(Doc,"App.activeDocument().%s.StdDirection = \"X\"", FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Length = 100", FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Occurrences = 2", FeatName.c_str()); + for (std::vector::iterator it = tempSelNames.begin(); it != tempSelNames.end(); ++it) + doCommand(Gui,"Gui.activeDocument().%s.Visibility=False",it->c_str()); + + updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + + copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); + copyVisual(FeatName.c_str(), "DisplayMode", tempSelNames.front().c_str()); +} + +bool CmdPartDesignLinearPattern::isActive(void) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + return n >= 1; +} + +//=========================================================================== +// PartDesign_PolarPattern +//=========================================================================== +DEF_STD_CMD_A(CmdPartDesignPolarPattern); + +CmdPartDesignPolarPattern::CmdPartDesignPolarPattern() + : Command("PartDesign_PolarPattern") +{ + sAppModule = "PartDesign"; + sGroup = QT_TR_NOOP("PartDesign"); + sMenuText = QT_TR_NOOP("PolarPattern"); + sToolTipText = QT_TR_NOOP("create a polar pattern feature"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "PartDesign_PolarPattern"; +} + +void CmdPartDesignPolarPattern::activated(int iMsg) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + if (n < 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select one or more additive/subtractive features, please.")); + return; + } + + std::string FeatName = getUniqueObjectName("PolarPattern"); + + std::vector Sel = getSelection().getSelection(); + std::stringstream str; + std::vector tempSelNames; + str << "App.activeDocument()." << FeatName << ".Originals = ["; + for (std::vector::iterator it = Sel.begin(); it != Sel.end(); ++it){ + str << "App.activeDocument()." << it->FeatName << ","; + tempSelNames.push_back(it->FeatName); + } + str << "]"; + + openCommand("PolarPattern"); + doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::PolarPattern\",\"%s\")",FeatName.c_str()); + updateActive(); + doCommand(Doc,str.str().c_str()); + doCommand(Doc,"App.activeDocument().%s.StdAxis = \"X\"", FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Angle = 360", FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Occurrences = 2", FeatName.c_str()); + for (std::vector::iterator it = tempSelNames.begin(); it != tempSelNames.end(); ++it) + doCommand(Gui,"Gui.activeDocument().%s.Visibility=False",it->c_str()); + + updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + + copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); + copyVisual(FeatName.c_str(), "DisplayMode", tempSelNames.front().c_str()); +} + +bool CmdPartDesignPolarPattern::isActive(void) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + return n >= 1; +} + +//=========================================================================== +// PartDesign_Scaled +//=========================================================================== +DEF_STD_CMD_A(CmdPartDesignScaled); + +CmdPartDesignScaled::CmdPartDesignScaled() + : Command("PartDesign_Scaled") +{ + sAppModule = "PartDesign"; + sGroup = QT_TR_NOOP("PartDesign"); + sMenuText = QT_TR_NOOP("Scaled"); + sToolTipText = QT_TR_NOOP("create a scaled feature"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "PartDesign_Scaled"; +} + +void CmdPartDesignScaled::activated(int iMsg) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + if (n < 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select one or more additive/subtractive features, please.")); + return; + } + + std::string FeatName = getUniqueObjectName("Scaled"); + + std::vector Sel = getSelection().getSelection(); + std::stringstream str; + std::vector tempSelNames; + str << "App.activeDocument()." << FeatName << ".Originals = ["; + for (std::vector::iterator it = Sel.begin(); it != Sel.end(); ++it){ + str << "App.activeDocument()." << it->FeatName << ","; + tempSelNames.push_back(it->FeatName); + } + str << "]"; + + openCommand("Scaled"); + doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Scaled\",\"%s\")",FeatName.c_str()); + updateActive(); + doCommand(Doc,str.str().c_str()); + doCommand(Doc,"App.activeDocument().%s.Factor = 2", FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Occurrences = 2", FeatName.c_str()); + for (std::vector::iterator it = tempSelNames.begin(); it != tempSelNames.end(); ++it) + doCommand(Gui,"Gui.activeDocument().%s.Visibility=False",it->c_str()); + + updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + + copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); + copyVisual(FeatName.c_str(), "DisplayMode", tempSelNames.front().c_str()); +} + +bool CmdPartDesignScaled::isActive(void) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + return n >= 1; +} + +//=========================================================================== +// PartDesign_MultiTransform +//=========================================================================== +DEF_STD_CMD_A(CmdPartDesignMultiTransform); + +CmdPartDesignMultiTransform::CmdPartDesignMultiTransform() + : Command("PartDesign_MultiTransform") +{ + sAppModule = "PartDesign"; + sGroup = QT_TR_NOOP("PartDesign"); + sMenuText = QT_TR_NOOP("MultiTransform"); + sToolTipText = QT_TR_NOOP("create a multitransform feature"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "PartDesign_MultiTransform"; +} + +void CmdPartDesignMultiTransform::activated(int iMsg) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + if (n < 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select one or more additive/subtractive features, please.")); + return; + } + + std::string FeatName = getUniqueObjectName("MultiTransform"); + + std::vector Sel = getSelection().getSelection(); + std::stringstream str; + std::vector tempSelNames; + str << "App.activeDocument()." << FeatName << ".Originals = ["; + for (std::vector::iterator it = Sel.begin(); it != Sel.end(); ++it){ + str << "App.activeDocument()." << it->FeatName << ","; + tempSelNames.push_back(it->FeatName); + } + str << "]"; + + openCommand("MultiTransform"); + doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::MultiTransform\",\"%s\")",FeatName.c_str()); + updateActive(); + doCommand(Doc,str.str().c_str()); + + updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + + copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); + copyVisual(FeatName.c_str(), "DisplayMode", tempSelNames.front().c_str()); +} + +bool CmdPartDesignMultiTransform::isActive(void) +{ + unsigned n = getSelection().countObjectsOfType(PartDesign::Additive::getClassTypeId()) + + getSelection().countObjectsOfType(PartDesign::Subtractive::getClassTypeId()); + return n >= 1; +} + + +//=========================================================================== +// Initialization +//=========================================================================== void CreatePartDesignCommands(void) { @@ -708,4 +1022,9 @@ void CreatePartDesignCommands(void) rcCmdMgr.addCommand(new CmdPartDesignFillet()); //rcCmdMgr.addCommand(new CmdPartDesignNewSketch()); rcCmdMgr.addCommand(new CmdPartDesignChamfer()); + rcCmdMgr.addCommand(new CmdPartDesignMirrored()); + rcCmdMgr.addCommand(new CmdPartDesignLinearPattern()); + rcCmdMgr.addCommand(new CmdPartDesignPolarPattern()); + //rcCmdMgr.addCommand(new CmdPartDesignScaled()); + rcCmdMgr.addCommand(new CmdPartDesignMultiTransform()); } diff --git a/src/Mod/PartDesign/Gui/Resources/Makefile.am b/src/Mod/PartDesign/Gui/Resources/Makefile.am index 79bee06393..c3463f2fa2 100644 --- a/src/Mod/PartDesign/Gui/Resources/Makefile.am +++ b/src/Mod/PartDesign/Gui/Resources/Makefile.am @@ -41,6 +41,11 @@ EXTRA_DIST = \ icons/PartDesign_Pad.svg \ icons/PartDesign_Pocket.svg \ icons/PartDesign_Revolution.svg \ + icons/PartDesign_Mirrored.svg \ + icons/PartDesign_LinearPattern.svg \ + icons/PartDesign_PolarPattern.svg \ + icons/PartDesign_Scaled.svg \ + icons/PartDesign_MultiTransform.svg \ PartDesign.qrc diff --git a/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc b/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc index 37804e4039..ae4603434a 100644 --- a/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc +++ b/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc @@ -4,6 +4,11 @@ icons/PartDesign_Pad.svg icons/PartDesign_Pocket.svg icons/PartDesign_Revolution.svg + icons/PartDesign_Mirrored.svg + icons/PartDesign_LinearPattern.svg + icons/PartDesign_PolarPattern.svg + icons/PartDesign_Scaled.svg + icons/PartDesign_MultiTransform.svg translations/PartDesign_af.qm translations/PartDesign_de.qm translations/PartDesign_es.qm diff --git a/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_LinearPattern.svg b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_LinearPattern.svg new file mode 100755 index 0000000000..f5728c4acd --- /dev/null +++ b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_LinearPattern.svg @@ -0,0 +1,1817 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Mirrored.svg b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Mirrored.svg new file mode 100644 index 0000000000..beda7d7e39 --- /dev/null +++ b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Mirrored.svg @@ -0,0 +1,429 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_MultiTransform.svg b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_MultiTransform.svg new file mode 100755 index 0000000000..3e1b71fb69 --- /dev/null +++ b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_MultiTransform.svg @@ -0,0 +1,1779 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_PolarPattern.svg b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_PolarPattern.svg new file mode 100755 index 0000000000..0c53abc0cf --- /dev/null +++ b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_PolarPattern.svg @@ -0,0 +1,1580 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Scaled.svg b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Scaled.svg new file mode 100755 index 0000000000..0ba6438ccc --- /dev/null +++ b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Scaled.svg @@ -0,0 +1,1380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.cpp b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.cpp new file mode 100644 index 0000000000..6f2ea98c5a --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.cpp @@ -0,0 +1,420 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +#include "ui_TaskLinearPatternParameters.h" +#include "TaskLinearPatternParameters.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "TaskMultiTransformParameters.h" + +using namespace PartDesignGui; +using namespace Gui; + +/* TRANSLATOR PartDesignGui::TaskLinearPatternParameters */ + +TaskLinearPatternParameters::TaskLinearPatternParameters(ViewProviderTransformed *TransformedView,QWidget *parent) + : TaskTransformedParameters(TransformedView, parent) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskLinearPatternParameters(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + this->groupLayout()->addWidget(proxy); + + ui->buttonOK->hide(); + ui->checkBoxUpdateView->setEnabled(true); + + updateUIinProgress = false; // Hack, sometimes it is NOT false although set to false in Transformed::Transformed()!! + setupUI(); +} + +TaskLinearPatternParameters::TaskLinearPatternParameters(QWidget *parent, TaskMultiTransformParameters *parentTask) + : TaskTransformedParameters(parent, parentTask) +{ + ui = new Ui_TaskLinearPatternParameters(); + ui->setupUi(parent); + connect(ui->buttonOK, SIGNAL(pressed()), + parentTask, SLOT(onSubTaskButtonOK())); + QMetaObject::connectSlotsByName(this); + + ui->buttonOK->setEnabled(true); + ui->listFeatures->hide(); + ui->checkBoxUpdateView->hide(); + + updateUIinProgress = false; // Hack, sometimes it is NOT false although set to false in Transformed::Transformed()!! + setupUI(); +} + +void TaskLinearPatternParameters::setupUI() +{ + connect(ui->buttonX, SIGNAL(pressed()), + this, SLOT(onButtonX())); + connect(ui->buttonY, SIGNAL(pressed()), + this, SLOT(onButtonY())); + connect(ui->buttonZ, SIGNAL(pressed()), + this, SLOT(onButtonZ())); + connect(ui->checkReverse, SIGNAL(toggled(bool)), + this, SLOT(onCheckReverse(bool))); + connect(ui->spinLength, SIGNAL(valueChanged(double)), + this, SLOT(onLength(double))); + connect(ui->spinOccurrences, SIGNAL(valueChanged(int)), + this, SLOT(onOccurrences(int))); + connect(ui->buttonReference, SIGNAL(pressed()), + this, SLOT(onButtonReference())); + connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)), + this, SLOT(onUpdateView(bool))); + + // TODO: The following code could be generic in TaskTransformedParameters + // if it were possible to make ui_TaskLinearPatternParameters a subclass of + // ui_TaskTransformedParameters + // --------------------- + // Add a context menu to the listview of the originals to delete items + QAction* action = new QAction(tr("Delete"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onOriginalDeleted())); + ui->listFeatures->addAction(action); + ui->listFeatures->setContextMenuPolicy(Qt::ActionsContextMenu); + + // Get the feature data + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + std::vector originals = pcLinearPattern->Originals.getValues(); + + // Fill data into dialog elements + ui->listFeatures->setEnabled(true); + ui->listFeatures->clear(); + for (std::vector::const_iterator i = originals.begin(); i != originals.end(); i++) + { + if ((*i) != NULL) + ui->listFeatures->addItem(QString::fromAscii((*i)->getNameInDocument())); + } + QMetaObject::invokeMethod(ui->listFeatures, "setFocus", Qt::QueuedConnection); + // --------------------- + + ui->buttonX->setEnabled(true); + ui->buttonY->setEnabled(true); + ui->buttonZ->setEnabled(true); + ui->checkReverse->setEnabled(true); + ui->spinLength->setEnabled(true); + ui->spinOccurrences->setEnabled(true); + ui->buttonReference->setEnabled(true); + ui->lineReference->setEnabled(false); // This is never enabled since it is for optical feed-back only + updateUI(); +} + +void TaskLinearPatternParameters::updateUI() +{ + if (updateUIinProgress) return; + updateUIinProgress = true; + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + + App::DocumentObject* directionFeature = pcLinearPattern->Direction.getValue(); + std::vector directions = pcLinearPattern->Direction.getSubValues(); + std::string stdDirection = pcLinearPattern->StdDirection.getValue(); + bool reverse = pcLinearPattern->Reversed.getValue(); + double length = pcLinearPattern->Length.getValue(); + unsigned occurrences = pcLinearPattern->Occurrences.getValue(); + + if ((featureSelectionMode || insideMultiTransform) && !stdDirection.empty()) + { + ui->buttonReference->setDown(false); + ui->buttonX->setAutoExclusive(true); + ui->buttonY->setAutoExclusive(true); + ui->buttonZ->setAutoExclusive(true); + ui->buttonX->setChecked(stdDirection == "X"); + ui->buttonY->setChecked(stdDirection == "Y"); + ui->buttonZ->setChecked(stdDirection == "Z"); + ui->lineReference->setText(tr("")); + } else if ((directionFeature != NULL) && !directions.empty()) { + ui->buttonX->setAutoExclusive(false); + ui->buttonY->setAutoExclusive(false); + ui->buttonZ->setAutoExclusive(false); + ui->buttonX->setChecked(false); + ui->buttonY->setChecked(false); + ui->buttonZ->setChecked(false); + ui->buttonReference->setDown(!featureSelectionMode); + ui->lineReference->setText(QString::fromAscii(directions.front().c_str())); + } else { + // Error message? + ui->lineReference->setText(tr("")); + } + + // Note: These three lines would trigger onLength(), on Occurrences() and another updateUI() if we + // didn't check for updateUIinProgress + ui->checkReverse->setChecked(reverse); + ui->spinLength->setValue(length); + ui->spinOccurrences->setValue(occurrences); + + updateUIinProgress = false; +} + +void TaskLinearPatternParameters::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + App::DocumentObject* selectedObject = pcLinearPattern->getDocument()->getActiveObject(); + if ((selectedObject == NULL) || !selectedObject->isDerivedFrom(Part::Feature::getClassTypeId())) + return; + + if (featureSelectionMode) { + if (originalSelected(msg)) + ui->listFeatures->addItem(QString::fromAscii(selectedObject->getNameInDocument())); + } else { + if (!msg.pSubName || msg.pSubName[0] == '\0') + return; + + std::string element(msg.pSubName); + + if (msg.Type == Gui::SelectionChanges::AddSelection) { + // TODO +// if (originalElementName == "") { +// Base::Console().Error("Element created by this pattern cannot be used for direction\n"); +// return; +// } + + std::vector directions; + directions.push_back(element.c_str()); + pcLinearPattern->Direction.setValue(getOriginalObject(), directions); + + if (insideMultiTransform) { + if (parentTask->updateView()) + recomputeFeature(); + } else + if (ui->checkBoxUpdateView->isChecked()) + recomputeFeature(); + + if (!insideMultiTransform) + featureSelectionMode = true; // Jump back to selection of originals + updateUI(); + } + } +} + +void TaskLinearPatternParameters::onOriginalDeleted() +{ + int row = ui->listFeatures->currentIndex().row(); + TaskTransformedParameters::onOriginalDeleted(row); + ui->listFeatures->model()->removeRow(row); +} + +void TaskLinearPatternParameters::onButtonX() { + onStdDirection("X"); +} + +void TaskLinearPatternParameters::onButtonY() { + onStdDirection("Y"); +} + +void TaskLinearPatternParameters::onButtonZ() { + onStdDirection("Z"); +} + +void TaskLinearPatternParameters::onCheckReverse(const bool on) { + if (updateUIinProgress) return; + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + pcLinearPattern->Reversed.setValue(on); + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskLinearPatternParameters::onLength(const double l) { + if (updateUIinProgress) return; + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + pcLinearPattern->Length.setValue(l); + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskLinearPatternParameters::onOccurrences(const int n) { + if (updateUIinProgress) return; + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + pcLinearPattern->Occurrences.setValue(n); + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskLinearPatternParameters::onStdDirection(const std::string& dir) { + if (updateUIinProgress) return; + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + pcLinearPattern->StdDirection.setValue(dir.c_str()); + pcLinearPattern->Direction.setValue(NULL); + if (!insideMultiTransform) + featureSelectionMode = true; + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskLinearPatternParameters::onButtonReference() +{ + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + pcLinearPattern->StdDirection.setValue(""); + featureSelectionMode = false; + updateUI(); +} + +void TaskLinearPatternParameters::onUpdateView(bool on) +{ + ui->buttonX->blockSignals(!on); + ui->buttonY->blockSignals(!on); + ui->buttonZ->blockSignals(!on); + ui->listFeatures->blockSignals(!on); + ui->checkReverse->blockSignals(!on); + ui->spinLength->blockSignals(!on); + ui->spinOccurrences->blockSignals(!on); +} + +const std::string TaskLinearPatternParameters::getStdDirection(void) const +{ + std::string stdDirection; + + if (ui->buttonX->isChecked()) + stdDirection = "X"; + else if (ui->buttonY->isChecked()) + stdDirection = "Y"; + else if (ui->buttonZ->isChecked()) + stdDirection = "Z"; + + if (!stdDirection.empty()) + return std::string("\"") + stdDirection + "\""; + else + return std::string(""); +} + +const QString TaskLinearPatternParameters::getDirection(void) const +{ + PartDesign::LinearPattern* pcLinearPattern = static_cast(getObject()); + App::DocumentObject* feature = pcLinearPattern->Direction.getValue(); + if (feature == NULL) + return QString::fromUtf8(""); + std::vector directions = pcLinearPattern->Direction.getSubValues(); + QString buf; + + if ((feature != NULL) && !directions.empty()) { + buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])"); + buf = buf.arg(QString::fromUtf8(feature->getNameInDocument())); + buf = buf.arg(QString::fromUtf8(directions.front().c_str())); + } + else + buf = QString::fromUtf8(""); + + return buf; +} + +const bool TaskLinearPatternParameters::getReverse(void) const { + return ui->checkReverse->isChecked(); +} + +const double TaskLinearPatternParameters::getLength(void) const { + return ui->spinLength->value(); +} + +const unsigned TaskLinearPatternParameters::getOccurrences(void) const { + return ui->spinOccurrences->value(); +} + +TaskLinearPatternParameters::~TaskLinearPatternParameters() +{ + delete ui; +} + +void TaskLinearPatternParameters::changeEvent(QEvent *e) +{ + TaskBox::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(proxy); + } +} + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgLinearPatternParameters::TaskDlgLinearPatternParameters(ViewProviderLinearPattern *LinearPatternView) + : TaskDlgTransformedParameters(LinearPatternView) +{ + parameter = new TaskLinearPatternParameters(LinearPatternView); + + Content.push_back(parameter); +} +//==== calls from the TaskView =============================================================== + +bool TaskDlgLinearPatternParameters::accept() +{ + std::string name = TransformedView->getObject()->getNameInDocument(); + + try { + //Gui::Command::openCommand("LinearPattern changed"); + // Handle Originals + if (!TaskDlgTransformedParameters::accept()) + return false; + + TaskLinearPatternParameters* linearpatternParameter = static_cast(parameter); + std::string direction = linearpatternParameter->getDirection().toStdString(); + if (!direction.empty()) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Direction = %s", name.c_str(), direction.c_str()); + std::string stdDirection = linearpatternParameter->getStdDirection(); + if (!stdDirection.empty()) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.StdDirection = %s",name.c_str(),stdDirection.c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Reversed = %u",name.c_str(),linearpatternParameter->getReverse()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Length = %f",name.c_str(),linearpatternParameter->getLength()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Occurrences = %u",name.c_str(),linearpatternParameter->getOccurrences()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); + if (!TransformedView->getObject()->isValid()) + throw Base::Exception(TransformedView->getObject()->getStatusString()); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + Gui::Command::commitCommand(); + } + catch (const Base::Exception& e) { + QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what())); + return false; + } + + return true; +} + +#include "moc_TaskLinearPatternParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.h b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.h new file mode 100644 index 0000000000..3aeea8ff83 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.h @@ -0,0 +1,106 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef GUI_TASKVIEW_TaskLinearPatternParameters_H +#define GUI_TASKVIEW_TaskLinearPatternParameters_H + +#include +#include +#include + +#include "TaskTransformedParameters.h" +#include "ViewProviderLinearPattern.h" + +class Ui_TaskLinearPatternParameters; + +namespace App { +class Property; +} + +namespace Gui { +class ViewProvider; +} + +namespace PartDesignGui { + +class TaskMultiTransformParameters; + +class TaskLinearPatternParameters : public TaskTransformedParameters +{ + Q_OBJECT + +public: + /// Constructor for task with ViewProvider + TaskLinearPatternParameters(ViewProviderTransformed *TransformedView, QWidget *parent = 0); + /// Constructor for task with parent task (MultiTransform mode) + TaskLinearPatternParameters(QWidget *parent, TaskMultiTransformParameters *parentTask); + virtual ~TaskLinearPatternParameters(); + + const QString getDirection(void) const; + const std::string getStdDirection(void) const; + const bool getReverse(void) const; + const double getLength(void) const; + const unsigned getOccurrences(void) const; + +private Q_SLOTS: + void onStdDirection(const std::string& dir); + void onButtonX(); + void onButtonY(); + void onButtonZ(); + void onCheckReverse(const bool on); + void onLength(const double l); + void onOccurrences(const int n); + virtual void onButtonReference(); + virtual void onOriginalDeleted(); + virtual void onUpdateView(bool); + +protected: + virtual void changeEvent(QEvent *e); + virtual void onSelectionChanged(const Gui::SelectionChanges& msg); + +private: + void updateUI(); + void setupUI(); + +private: + Ui_TaskLinearPatternParameters* ui; +}; + + +/// simulation dialog for the TaskView +class TaskDlgLinearPatternParameters : public TaskDlgTransformedParameters +{ + Q_OBJECT + +public: + TaskDlgLinearPatternParameters(ViewProviderLinearPattern *LinearPatternView); + virtual ~TaskDlgLinearPatternParameters() {} + +public: + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); +}; + +} //namespace PartDesignGui + +#endif // GUI_TASKVIEW_TASKAPPERANCE_H diff --git a/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.ui b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.ui new file mode 100644 index 0000000000..c5a06ce89e --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskLinearPatternParameters.ui @@ -0,0 +1,139 @@ + + + PartDesignGui::TaskLinearPatternParameters + + + + 0 + 0 + 225 + 402 + + + + Form + + + + + + + + + + + X + + + true + + + + + + + Y + + + + + + + Z + + + + + + + + + + + Direction + + + + + + + + + + + + Reverse direction + + + + + + + + + Length + + + + + + + 3 + + + 999999.000000000000000 + + + 100.000000000000000 + + + + + + + + + + + Occurrences + + + + + + + 2 + + + 99999 + + + + + + + + + + + OK + + + + + + + + + Update view + + + true + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/TaskMirroredParameters.cpp b/src/Mod/PartDesign/Gui/TaskMirroredParameters.cpp new file mode 100644 index 0000000000..0ed762e55c --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskMirroredParameters.cpp @@ -0,0 +1,351 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +#include "ui_TaskMirroredParameters.h" +#include "TaskMirroredParameters.h" +#include "TaskMultiTransformParameters.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace PartDesignGui; +using namespace Gui; + +/* TRANSLATOR PartDesignGui::TaskMirroredParameters */ + +TaskMirroredParameters::TaskMirroredParameters(ViewProviderTransformed *TransformedView, QWidget *parent) + : TaskTransformedParameters(TransformedView, parent) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskMirroredParameters(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + this->groupLayout()->addWidget(proxy); + + ui->buttonOK->hide(); + ui->checkBoxUpdateView->setEnabled(true); + + updateUIinProgress = false; // Hack, sometimes it is NOT false although set to false in Transformed::Transformed()!! + setupUI(); +} + +TaskMirroredParameters::TaskMirroredParameters(QWidget *parent, TaskMultiTransformParameters *parentTask) + : TaskTransformedParameters(parent, parentTask) +{ + ui = new Ui_TaskMirroredParameters(); + ui->setupUi(parent); + connect(ui->buttonOK, SIGNAL(pressed()), + parentTask, SLOT(onSubTaskButtonOK())); + QMetaObject::connectSlotsByName(this); + + ui->buttonOK->setEnabled(true); + ui->listFeatures->hide(); + ui->checkBoxUpdateView->hide(); + + updateUIinProgress = false; // Hack, sometimes it is NOT false although set to false in Transformed::Transformed()!! + setupUI(); +} + +void TaskMirroredParameters::setupUI() +{ + connect(ui->buttonXY, SIGNAL(pressed()), + this, SLOT(onButtonXY())); + connect(ui->buttonXZ, SIGNAL(pressed()), + this, SLOT(onButtonXZ())); + connect(ui->buttonYZ, SIGNAL(pressed()), + this, SLOT(onButtonYZ())); + connect(ui->buttonReference, SIGNAL(pressed()), + this, SLOT(onButtonReference())); + connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)), + this, SLOT(onUpdateView(bool))); + + // TODO: The following code could be generic in TaskTransformedParameters + // if it were possible to make ui_TaskMirroredParameters a subclass of + // ui_TaskTransformedParameters + // --------------------- + // Add a context menu to the listview of the originals to delete items + QAction* action = new QAction(tr("Delete"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onOriginalDeleted())); + ui->listFeatures->addAction(action); + ui->listFeatures->setContextMenuPolicy(Qt::ActionsContextMenu); + + // Get the feature data + PartDesign::Mirrored* pcMirrored = static_cast(getObject()); + std::vector originals = pcMirrored->Originals.getValues(); + + // Fill data into dialog elements + ui->listFeatures->setEnabled(true); + ui->listFeatures->clear(); + for (std::vector::const_iterator i = originals.begin(); i != originals.end(); i++) + { + if ((*i) != NULL) + ui->listFeatures->addItem(QString::fromAscii((*i)->getNameInDocument())); + } + QMetaObject::invokeMethod(ui->listFeatures, "setFocus", Qt::QueuedConnection); + // --------------------- + + ui->buttonXY->setEnabled(true); + ui->buttonXZ->setEnabled(true); + ui->buttonYZ->setEnabled(true); + ui->buttonReference->setEnabled(true); + ui->lineReference->setEnabled(false); // This is never enabled since it is for optical feed-back only + + updateUI(); +} + +void TaskMirroredParameters::updateUI() +{ + if (updateUIinProgress) return; + updateUIinProgress = true; + PartDesign::Mirrored* pcMirrored = static_cast(getObject()); + App::DocumentObject* mirrorPlaneFeature = pcMirrored->MirrorPlane.getValue(); + std::vector mirrorPlanes = pcMirrored->MirrorPlane.getSubValues(); + std::string stdMirrorPlane = pcMirrored->StdMirrorPlane.getValue(); + + if ((featureSelectionMode || insideMultiTransform) && !stdMirrorPlane.empty()) + { + ui->buttonReference->setDown(false); + ui->buttonXY->setAutoExclusive(true); + ui->buttonXZ->setAutoExclusive(true); + ui->buttonYZ->setAutoExclusive(true); + ui->buttonXY->setChecked(stdMirrorPlane == "XY"); + ui->buttonXZ->setChecked(stdMirrorPlane == "XZ"); + ui->buttonYZ->setChecked(stdMirrorPlane == "YZ"); + ui->lineReference->setText(tr("")); + } else if ((mirrorPlaneFeature != NULL) && !mirrorPlanes.empty()) { + ui->buttonXY->setAutoExclusive(false); + ui->buttonXZ->setAutoExclusive(false); + ui->buttonYZ->setAutoExclusive(false); + ui->buttonXY->setChecked(false); + ui->buttonXZ->setChecked(false); + ui->buttonYZ->setChecked(false); + ui->buttonReference->setDown(!featureSelectionMode); + ui->lineReference->setText(QString::fromAscii(mirrorPlanes.front().c_str())); + } else { + // Error message? + ui->lineReference->setText(tr("")); + } + + updateUIinProgress = false; +} + +void TaskMirroredParameters::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + PartDesign::Mirrored* pcMirrored = static_cast(getObject()); + App::DocumentObject* selectedObject = pcMirrored->getDocument()->getActiveObject(); + if ((selectedObject == NULL) || !selectedObject->isDerivedFrom(Part::Feature::getClassTypeId())) + return; + + if (featureSelectionMode) { + if (originalSelected(msg)) + ui->listFeatures->addItem(QString::fromAscii(selectedObject->getNameInDocument())); + } else { + if (!msg.pSubName || msg.pSubName[0] == '\0') + return; + + std::string element(msg.pSubName); + + if (element.substr(0,4) != "Face") + return; + + if (msg.Type == Gui::SelectionChanges::AddSelection) { + std::vector mirrorPlanes; + mirrorPlanes.push_back(element.c_str()); + pcMirrored->MirrorPlane.setValue(getOriginalObject(), mirrorPlanes); + + if (insideMultiTransform) { + if (parentTask->updateView()) + recomputeFeature(); + } else + if (ui->checkBoxUpdateView->isChecked()) + recomputeFeature(); + + if (!insideMultiTransform) + featureSelectionMode = true; // Jump back to selection of originals + updateUI(); + } + } +} + +void TaskMirroredParameters::onOriginalDeleted() +{ + int row = ui->listFeatures->currentIndex().row(); + TaskTransformedParameters::onOriginalDeleted(row); + ui->listFeatures->model()->removeRow(row); +} + +void TaskMirroredParameters::onStdMirrorPlane(const std::string &plane) { + if (updateUIinProgress) return; + PartDesign::Mirrored* pcMirrored = static_cast(getObject()); + pcMirrored->StdMirrorPlane.setValue(plane.c_str()); + pcMirrored->MirrorPlane.setValue(NULL); + if (!insideMultiTransform) + featureSelectionMode = true; + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskMirroredParameters::onButtonXY() { + onStdMirrorPlane("XY"); +} + +void TaskMirroredParameters::onButtonXZ() { + onStdMirrorPlane("XZ"); +} + +void TaskMirroredParameters::onButtonYZ() { + onStdMirrorPlane("YZ"); +} + +void TaskMirroredParameters::onButtonReference() +{ + PartDesign::Mirrored* pcMirrored = static_cast(getObject()); + pcMirrored->StdMirrorPlane.setValue(""); + featureSelectionMode = false; + updateUI(); +} + +void TaskMirroredParameters::onUpdateView(bool on) +{ + ui->buttonXY->blockSignals(!on); + ui->buttonYZ->blockSignals(!on); + ui->buttonXZ->blockSignals(!on); + ui->listFeatures->blockSignals(!on); +} + +const std::string TaskMirroredParameters::getStdMirrorPlane(void) const +{ + std::string stdMirrorPlane; + + if (ui->buttonXY->isChecked()) + stdMirrorPlane = "XY"; + else if (ui->buttonYZ->isChecked()) + stdMirrorPlane = "YZ"; + else if (ui->buttonXZ->isChecked()) + stdMirrorPlane = "XZ"; + + if (!stdMirrorPlane.empty()) + return std::string("\"") + stdMirrorPlane + "\""; + else + return std::string(""); +} + +const QString TaskMirroredParameters::getMirrorPlane(void) const +{ + PartDesign::Mirrored* pcMirrored = static_cast(getObject()); + App::DocumentObject* feature = pcMirrored->MirrorPlane.getValue(); + if (feature == NULL) + return QString::fromUtf8(""); + std::vector mirrorPlanes = pcMirrored->MirrorPlane.getSubValues(); + QString buf; + + if ((feature != NULL) && !mirrorPlanes.empty()) { + buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])"); + buf = buf.arg(QString::fromUtf8(feature->getNameInDocument())); + buf = buf.arg(QString::fromUtf8(mirrorPlanes.front().c_str())); + } + else + buf = QString::fromUtf8(""); + + return buf; +} + +TaskMirroredParameters::~TaskMirroredParameters() +{ + delete ui; +} + +void TaskMirroredParameters::changeEvent(QEvent *e) +{ + TaskBox::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(proxy); + } +} + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgMirroredParameters::TaskDlgMirroredParameters(ViewProviderMirrored *MirroredView) + : TaskDlgTransformedParameters(MirroredView) +{ + parameter = new TaskMirroredParameters(MirroredView); + + Content.push_back(parameter); +} +//==== calls from the TaskView =============================================================== + +bool TaskDlgMirroredParameters::accept() +{ + std::string name = TransformedView->getObject()->getNameInDocument(); + + try { + //Gui::Command::openCommand("Mirrored changed"); + // Handle Originals + if (!TaskDlgTransformedParameters::accept()) + return false; + + TaskMirroredParameters* mirrorParameter = static_cast(parameter); + std::string mirrorPlane = mirrorParameter->getMirrorPlane().toStdString(); + if (!mirrorPlane.empty()) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.MirrorPlane = %s", name.c_str(), mirrorPlane.c_str()); + std::string stdMirrorPlane = mirrorParameter->getStdMirrorPlane(); + if (!stdMirrorPlane.empty()) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.StdMirrorPlane = %s",name.c_str(),stdMirrorPlane.c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); + if (!TransformedView->getObject()->isValid()) + throw Base::Exception(TransformedView->getObject()->getStatusString()); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + Gui::Command::commitCommand(); + } + catch (const Base::Exception& e) { + QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what())); + return false; + } + + return true; +} + +#include "moc_TaskMirroredParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskMirroredParameters.h b/src/Mod/PartDesign/Gui/TaskMirroredParameters.h new file mode 100644 index 0000000000..e129e14fce --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskMirroredParameters.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef GUI_TASKVIEW_TaskMirroredParameters_H +#define GUI_TASKVIEW_TaskMirroredParameters_H + +#include +#include +#include + +#include "TaskTransformedParameters.h" +#include "ViewProviderMirrored.h" + +class Ui_TaskMirroredParameters; + +namespace App { +class Property; +} + +namespace Gui { +class ViewProvider; +} + +namespace PartDesignGui { + +class TaskMultiTransformParameters; + +class TaskMirroredParameters : public TaskTransformedParameters +{ + Q_OBJECT + +public: + /// Constructor for task with ViewProvider + TaskMirroredParameters(ViewProviderTransformed *TransformedView, QWidget *parent = 0); + /// Constructor for task with parent task (MultiTransform mode) + TaskMirroredParameters(QWidget *parent, TaskMultiTransformParameters *parentTask); + + virtual ~TaskMirroredParameters(); + + const QString getMirrorPlane(void) const; + const std::string getStdMirrorPlane(void) const; + +private Q_SLOTS: + void onButtonXY(); + void onButtonXZ(); + void onButtonYZ(); + virtual void onButtonReference(); + virtual void onOriginalDeleted(); + virtual void onUpdateView(bool); + +protected: + virtual void changeEvent(QEvent *e); + virtual void onSelectionChanged(const Gui::SelectionChanges& msg); + +private: + void onStdMirrorPlane(const std::string& plane); + void setupUI(); + void updateUI(); + +private: + Ui_TaskMirroredParameters* ui; +}; + + +/// simulation dialog for the TaskView +class TaskDlgMirroredParameters : public TaskDlgTransformedParameters +{ + Q_OBJECT + +public: + TaskDlgMirroredParameters(ViewProviderMirrored *MirroredView); + virtual ~TaskDlgMirroredParameters() {} + +public: + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); +}; + +} //namespace PartDesignGui + +#endif // GUI_TASKVIEW_TASKAPPERANCE_H diff --git a/src/Mod/PartDesign/Gui/TaskPatternRectangularParameters.ui b/src/Mod/PartDesign/Gui/TaskMirroredParameters.ui similarity index 51% rename from src/Mod/PartDesign/Gui/TaskPatternRectangularParameters.ui rename to src/Mod/PartDesign/Gui/TaskMirroredParameters.ui index 4da4c32831..b5f58835c3 100644 --- a/src/Mod/PartDesign/Gui/TaskPatternRectangularParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskMirroredParameters.ui @@ -1,13 +1,13 @@ - PartDesignGui::TaskPatternRectangularParameters - + PartDesignGui::TaskMirroredParameters + 0 0 - 139 - 178 + 218 + 290 @@ -15,74 +15,70 @@ - - - - - Spacing1: - - - - - - - + - + - Number1: + XY + + + true - + + + XZ + + + + + + + YZ + + - - - Qt::Horizontal - - - - - - - Second extend - - + + + + + Plane + + + + + + + - + - Spacing2: + OK - - - - - - - - Number2: - - - - - - - + + + Update view + + + true + + diff --git a/src/Mod/PartDesign/Gui/TaskMultiTransformParameters.cpp b/src/Mod/PartDesign/Gui/TaskMultiTransformParameters.cpp new file mode 100644 index 0000000000..0f6e6a6675 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskMultiTransformParameters.cpp @@ -0,0 +1,538 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +#include "ui_TaskMultiTransformParameters.h" +#include "TaskMultiTransformParameters.h" +#include "TaskMirroredParameters.h" +#include "TaskLinearPatternParameters.h" +#include "TaskPolarPatternParameters.h" +#include "TaskScaledParameters.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace PartDesignGui; +using namespace Gui; + +/* TRANSLATOR PartDesignGui::TaskMultiTransformParameters */ + +TaskMultiTransformParameters::TaskMultiTransformParameters(ViewProviderTransformed *TransformedView,QWidget *parent) + : TaskTransformedParameters(TransformedView, parent), subTask(NULL) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskMultiTransformParameters(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + this->groupLayout()->addWidget(proxy); + + // Create a context menu for the listview of transformation features + QAction* action = new QAction(tr("Edit"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onTransformEdit())); + ui->listTransformFeatures->addAction(action); + action = new QAction(tr("Delete"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onTransformDelete())); + ui->listTransformFeatures->addAction(action); + action = new QAction(tr("Add mirrored transformation"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onTransformAddMirrored())); + ui->listTransformFeatures->addAction(action); + action = new QAction(tr("Add linear pattern"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onTransformAddLinearPattern())); + ui->listTransformFeatures->addAction(action); + action = new QAction(tr("Add polar pattern"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onTransformAddPolarPattern())); + ui->listTransformFeatures->addAction(action); + action = new QAction(tr("Add scaled transformation"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onTransformAddScaled())); + ui->listTransformFeatures->addAction(action); + action = new QAction(tr("Move up"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onMoveUp())); + ui->listTransformFeatures->addAction(action); + action = new QAction(tr("Move down"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onMoveDown())); + ui->listTransformFeatures->addAction(action); + ui->listTransformFeatures->setContextMenuPolicy(Qt::ActionsContextMenu); + connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)), + this, SLOT(onUpdateView(bool))); + + connect(ui->listTransformFeatures, SIGNAL(activated(QModelIndex)), + this, SLOT(onTransformActivated(QModelIndex))); + + // Get the transformFeatures data + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + std::vector transformFeatures = pcMultiTransform->Transformations.getValues(); + + // Fill data into dialog elements + ui->listTransformFeatures->setEnabled(true); + ui->listTransformFeatures->clear(); + for (std::vector::const_iterator i = transformFeatures.begin(); i != transformFeatures.end(); i++) + { + if ((*i) != NULL) + ui->listTransformFeatures->addItem(QString::fromAscii((*i)->Label.getValue())); + } + if (transformFeatures.size() > 0) { + ui->listTransformFeatures->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); + editHint = false; + } else { + ui->listTransformFeatures->addItem(tr("Right-click to add")); + editHint = true; + } + + // TODO: The following code could be generic in TaskTransformedParameters + // if it were possible to make ui_TaskMultiTransformParameters a subclass of + // ui_TaskTransformedParameters + // --------------------- + // Add a context menu to the listview of the originals to delete items + action = new QAction(tr("Delete"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onOriginalDeleted())); + ui->listFeatures->addAction(action); + ui->listFeatures->setContextMenuPolicy(Qt::ActionsContextMenu); + + // Get the Originals data + std::vector originals = pcMultiTransform->Originals.getValues(); + + // Fill data into dialog elements + ui->listFeatures->setEnabled(true); + ui->listFeatures->clear(); + for (std::vector::const_iterator i = originals.begin(); i != originals.end(); i++) + { + if ((*i) != NULL) + ui->listFeatures->addItem(QString::fromAscii((*i)->getNameInDocument())); + } + QMetaObject::invokeMethod(ui->listFeatures, "setFocus", Qt::QueuedConnection); + // --------------------- +} + +void TaskMultiTransformParameters::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + App::DocumentObject* selectedObject = pcMultiTransform->getDocument()->getActiveObject(); + if ((selectedObject == NULL) || !selectedObject->isDerivedFrom(Part::Feature::getClassTypeId())) + return; + + if (featureSelectionMode) { + if (originalSelected(msg)) + ui->listFeatures->addItem(QString::fromAscii(selectedObject->getNameInDocument())); + } else { + // There is no reference that could be selected... must be an error to arrive here at all! + featureSelectionMode = true; + } +} + +void TaskMultiTransformParameters::closeSubTask() +{ + if (subTask == NULL) + return; // e.g. if user OKs a new subTask and then immediately deletes it + delete subTask; + subTask = NULL; + ui->widgetFeature->close(); + // FIXME: If the layout of the UI changes this code needs to be adapted + // But I couldn't find any other way to free the widget to have a different dialog attached to it + ui->verticalLayout->removeWidget(ui->widgetFeature); + delete ui->widgetFeature; + ui->widgetFeature = new QWidget(this); + ui->widgetFeature->setObjectName(QString::fromUtf8("widgetFeature")); + ui->widgetFeature->setMinimumSize(QSize(0, 180)); + ui->verticalLayout->addWidget(ui->widgetFeature); +} + +void TaskMultiTransformParameters::onTransformDelete() +{ + if (editHint) return; // Can't delete the hint... + int row = ui->listTransformFeatures->currentIndex().row(); + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + std::vector transformFeatures = pcMultiTransform->Transformations.getValues(); + + App::DocumentObject* feature = *(transformFeatures.begin() + row); + pcMultiTransform->getDocument()->remObject(feature->getNameInDocument()); + closeSubTask(); + + transformFeatures.erase(transformFeatures.begin() + row); + pcMultiTransform->Transformations.setValues(transformFeatures); + if (ui->checkBoxUpdateView->isChecked()) + pcMultiTransform->getDocument()->recomputeFeature(pcMultiTransform); + + ui->listTransformFeatures->model()->removeRow(row); + ui->listTransformFeatures->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); +} + +void TaskMultiTransformParameters::onTransformEdit() +{ + if (editHint) return; // Can't edit the hint... + closeSubTask(); // For example if user is editing one subTask and then double-clicks on another without OK'ing first + ui->listTransformFeatures->currentItem()->setSelected(true); + int row = ui->listTransformFeatures->currentIndex().row(); + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + std::vector transformFeatures = pcMultiTransform->Transformations.getValues(); + App::DocumentObject* transformObject = *(transformFeatures.begin() + row); + subFeature = static_cast(transformObject); + + if (transformObject->getTypeId() == PartDesign::Mirrored::getClassTypeId()) + subTask = new TaskMirroredParameters(ui->widgetFeature, this); + else if (transformObject->getTypeId() == PartDesign::LinearPattern::getClassTypeId()) + subTask = new TaskLinearPatternParameters(ui->widgetFeature, this); + else if (transformObject->getTypeId() == PartDesign::PolarPattern::getClassTypeId()) + subTask = new TaskPolarPatternParameters(ui->widgetFeature, this); + else if (transformObject->getTypeId() == PartDesign::Scaled::getClassTypeId()) + subTask = new TaskScaledParameters(ui->widgetFeature, this); + else + return; // TODO: Show an error? + + ui->widgetFeature->show(); + + transformFeatures[row] = subFeature; + pcMultiTransform->Transformations.setValues(transformFeatures); +} + +void TaskMultiTransformParameters::onTransformActivated(const QModelIndex& index) { + onTransformEdit(); +} + +void TaskMultiTransformParameters::onTransformAddMirrored() +{ + closeSubTask(); + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + + App::DocumentObject* newFeature = pcMultiTransform->getDocument()->addObject("PartDesign::Mirrored"); + if (newFeature == NULL) + return; + PartDesign::Mirrored* newMirrored = static_cast(newFeature); + newMirrored->StdMirrorPlane.setValue("XY"); + newMirrored->InsideMultiTransform.setValue(true); + newMirrored->Label.setValue("Mirrored"); // To avoid things like PartDesign__Mirrored001 + + subFeature = newMirrored; + subTask = new TaskMirroredParameters(ui->widgetFeature, this); + ui->widgetFeature->show(); + + finishAdd(newFeature); +} + +void TaskMultiTransformParameters::onTransformAddLinearPattern() +{ + closeSubTask(); + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + + App::DocumentObject* newFeature = pcMultiTransform->getDocument()->addObject("PartDesign::LinearPattern"); + if (newFeature == NULL) + return; + PartDesign::LinearPattern* newLinearPattern = static_cast(newFeature); + newLinearPattern->StdDirection.setValue("X"); + newLinearPattern->Length.setValue(100); + newLinearPattern->Occurrences.setValue(2); + newLinearPattern->InsideMultiTransform.setValue(true); + newLinearPattern->Label.setValue("LinearPattern"); + + subFeature = newLinearPattern; + subTask = new TaskLinearPatternParameters(ui->widgetFeature, this); + ui->widgetFeature->show(); + + finishAdd(newFeature); +} + +void TaskMultiTransformParameters::onTransformAddPolarPattern() +{ + closeSubTask(); + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + + App::DocumentObject* newFeature = pcMultiTransform->getDocument()->addObject("PartDesign::PolarPattern"); + if (newFeature == NULL) + return; + PartDesign::PolarPattern* newPolarPattern = static_cast(newFeature); + newPolarPattern->StdAxis.setValue("Z"); + newPolarPattern->Angle.setValue(360); + newPolarPattern->Occurrences.setValue(2); + newPolarPattern->InsideMultiTransform.setValue(true); + newPolarPattern->Label.setValue("PolarPattern"); + + subFeature = newPolarPattern; + subTask = new TaskPolarPatternParameters(ui->widgetFeature, this); + ui->widgetFeature->show(); + + finishAdd(newFeature); +} + +void TaskMultiTransformParameters::onTransformAddScaled() +{ + closeSubTask(); + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + + App::DocumentObject* newFeature = pcMultiTransform->getDocument()->addObject("PartDesign::Scaled"); + if (newFeature == NULL) + return; + PartDesign::Scaled* newScaled = static_cast(newFeature); + newScaled->Occurrences.setValue(2); + newScaled->InsideMultiTransform.setValue(true); + newScaled->Label.setValue("Scaled"); // To avoid things like PartDesign__Mirrored001 + + subFeature = newScaled; + subTask = new TaskScaledParameters(ui->widgetFeature, this); + ui->widgetFeature->show(); + + finishAdd(newFeature); +} + +void TaskMultiTransformParameters::finishAdd(App::DocumentObject* newFeature) +{ + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + if (editHint) { + // Remove hint, first feature is being added + ui->listTransformFeatures->model()->removeRow(0); + } + int row = ui->listTransformFeatures->currentIndex().row(); + if (row < 0) { + // Happens when first row (first transformation) is created + row = 0; + // Hide all the originals now (hiding them in Command.cpp presents the user with an empty screen!) + std::vector originals = pcMultiTransform->getOriginals(); + for (std::vector::iterator it = originals.begin(); it != originals.end(); ++it) + Gui::Command::doCommand( + Gui::Command::Doc,"Gui.activeDocument().getObject(\"%s\").Visibility=False",(*it)->getNameInDocument()); + } + std::vector transformFeatures = pcMultiTransform->Transformations.getValues(); + + if (row == ui->listTransformFeatures->model()->rowCount() - 1) { + // Note: Inserts always happen before the specified iterator so in order to append at the + // end we need to use push_back() and append() + transformFeatures.push_back(newFeature); + ui->listTransformFeatures->addItem(QString::fromAscii(newFeature->Label.getValue())); + ui->listTransformFeatures->setCurrentRow(row+1, QItemSelectionModel::ClearAndSelect); + } else { + transformFeatures.insert(transformFeatures.begin() + row, newFeature); + ui->listTransformFeatures->insertItem(row, QString::fromAscii(newFeature->Label.getValue())); + ui->listTransformFeatures->setCurrentRow(row, QItemSelectionModel::ClearAndSelect); + } + pcMultiTransform->Transformations.setValues(transformFeatures); + if (ui->checkBoxUpdateView->isChecked()) + pcMultiTransform->getDocument()->recomputeFeature(pcMultiTransform); + + // Set state to hidden - only the MultiTransform should be visible + Gui::Command::doCommand( + Gui::Command::Doc,"Gui.activeDocument().getObject(\"%s\").Visibility=False", newFeature->getNameInDocument()); + editHint = false; +} + +void TaskMultiTransformParameters::moveTransformFeature(const int increment) +{ + int row = ui->listTransformFeatures->currentIndex().row(); + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + std::vector transformFeatures = pcMultiTransform->Transformations.getValues(); + + App::DocumentObject* feature = *(transformFeatures.begin() + row); + transformFeatures.erase(transformFeatures.begin() + row); + QListWidgetItem* item = new QListWidgetItem(*(ui->listTransformFeatures->item(row))); + ui->listTransformFeatures->model()->removeRow(row); + // After this operation, if we were to insert at index row again, things will remain unchanged + + row += increment; + + if (row < 0) + row = 0; + + if (row >= ui->listTransformFeatures->model()->rowCount()) { + // Note: Inserts always happen before the specified iterator so in order to append at the + // end we need to use push_back() and append() + transformFeatures.push_back(feature); + ui->listTransformFeatures->addItem(item); + ui->listTransformFeatures->setCurrentRow(row, QItemSelectionModel::ClearAndSelect); + } else { + transformFeatures.insert(transformFeatures.begin() + row, feature); + ui->listTransformFeatures->insertItem(row, item); + ui->listTransformFeatures->setCurrentRow(row, QItemSelectionModel::ClearAndSelect); + } + + pcMultiTransform->Transformations.setValues(transformFeatures); + if (ui->checkBoxUpdateView->isChecked()) + pcMultiTransform->getDocument()->recomputeFeature(pcMultiTransform); +} + +void TaskMultiTransformParameters::onMoveUp() +{ + moveTransformFeature(-1); +} + +void TaskMultiTransformParameters::onMoveDown() +{ + moveTransformFeature(+1); +} + +void TaskMultiTransformParameters::onSubTaskButtonOK() { + closeSubTask(); +} + +void TaskMultiTransformParameters::onOriginalDeleted() +{ + int row = ui->listFeatures->currentIndex().row(); + TaskTransformedParameters::onOriginalDeleted(row); + ui->listFeatures->model()->removeRow(row); +} + +void TaskMultiTransformParameters::onUpdateView(bool on) +{ + ui->listFeatures->blockSignals(!on); +} + + +const std::vector TaskMultiTransformParameters::getTransformFeatures(void) const +{ + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + return pcMultiTransform->Transformations.getValues(); +} + +TaskMultiTransformParameters::~TaskMultiTransformParameters() +{ + closeSubTask(); + delete ui; +} + +void TaskMultiTransformParameters::changeEvent(QEvent *e) +{ + TaskBox::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(proxy); + } +} + +void TaskMultiTransformParameters::recomputeFeature() { + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + pcMultiTransform->getDocument()->recomputeFeature(pcMultiTransform); +} + +const bool TaskMultiTransformParameters::updateView() const +{ + return ui->checkBoxUpdateView->isChecked(); +} + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgMultiTransformParameters::TaskDlgMultiTransformParameters(ViewProviderMultiTransform *MultiTransformView) + : TaskDlgTransformedParameters(MultiTransformView) +{ + parameter = new TaskMultiTransformParameters(MultiTransformView); + + Content.push_back(parameter); +} +//==== calls from the TaskView =============================================================== + +bool TaskDlgMultiTransformParameters::accept() +{ + std::string name = TransformedView->getObject()->getNameInDocument(); + + try { + //Gui::Command::openCommand("MultiTransform changed"); + // Handle Originals + if (!TaskDlgTransformedParameters::accept()) + return false; + + TaskMultiTransformParameters* mtParameter = static_cast(parameter); + std::vector transformFeatures = mtParameter->getTransformFeatures(); + std::stringstream str; + str << "App.ActiveDocument." << name.c_str() << ".Transformations = ["; + for (std::vector::const_iterator it = transformFeatures.begin(); it != transformFeatures.end(); it++) + { + if ((*it) != NULL) + str << "App.ActiveDocument." << (*it)->getNameInDocument() << ","; + } + str << "]"; + Gui::Command::runCommand(Gui::Command::Doc,str.str().c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); + if (!TransformedView->getObject()->isValid()) + throw Base::Exception(TransformedView->getObject()->getStatusString()); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + Gui::Command::commitCommand(); + } + catch (const Base::Exception& e) { + QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what())); + return false; + } + + return true; +} + +bool TaskDlgMultiTransformParameters::reject() +{ + // Get objects before view is invalidated + // For the same reason we can't delegate showing the originals to TaskDlgTransformedParameters::reject() + PartDesign::MultiTransform* pcMultiTransform = static_cast(TransformedView->getObject()); + std::vector pcOriginals = pcMultiTransform->Originals.getValues(); + std::vector transformFeatures = pcMultiTransform->Transformations.getValues(); + + // Delete the transformation features - must happen before abortCommand()! + for (std::vector::const_iterator it = transformFeatures.begin(); it != transformFeatures.end(); ++it) + { + if ((*it) != NULL) + Gui::Command::doCommand( + Gui::Command::Doc,"App.ActiveDocument.removeObject(\"%s\")", (*it)->getNameInDocument()); + } + + // roll back the done things + Gui::Command::abortCommand(); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + + // if abort command deleted the object the originals are visible again + if (!Gui::Application::Instance->getViewProvider(pcMultiTransform)) { + for (std::vector::const_iterator it = pcOriginals.begin(); it != pcOriginals.end(); ++it) + { + if (((*it) != NULL) && (Gui::Application::Instance->getViewProvider(*it) != NULL)) { + Gui::Application::Instance->getViewProvider(*it)->show(); + } + } + } + + return true; +} + +#include "moc_TaskMultiTransformParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskMultiTransformParameters.h b/src/Mod/PartDesign/Gui/TaskMultiTransformParameters.h new file mode 100644 index 0000000000..eb3d1a4170 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskMultiTransformParameters.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef GUI_TASKVIEW_TaskMultiTransformParameters_H +#define GUI_TASKVIEW_TaskMultiTransformParameters_H + +#include +#include +#include + +#include "TaskTransformedParameters.h" +#include "ViewProviderMultiTransform.h" + +class Ui_TaskMultiTransformParameters; + +namespace PartDesign { +class Transformed; +} + +namespace App { +class Property; +} + +namespace Gui { +class ViewProvider; +} + +namespace PartDesignGui { + + + +class TaskMultiTransformParameters : public TaskTransformedParameters +{ + Q_OBJECT + +public: + TaskMultiTransformParameters(ViewProviderTransformed *TransformedView,QWidget *parent = 0); + virtual ~TaskMultiTransformParameters(); + + const std::vector getTransformFeatures(void) const; + + /// Return the currently active subFeature + PartDesign::Transformed* getSubFeature(void) { return subFeature; } + + /// Recompute the feature associated with this task + void recomputeFeature(); + /// Tell the subtask whether the view should be updated + const bool updateView() const; + +private Q_SLOTS: + void onTransformDelete(); + void onTransformEdit(); + void onTransformActivated(const QModelIndex& index); + void onTransformAddMirrored(); + void onTransformAddLinearPattern(); + void onTransformAddPolarPattern(); + void onTransformAddScaled(); + void onMoveUp(); + void onMoveDown(); + virtual void onButtonReference() {} + virtual void onOriginalDeleted(); + virtual void onUpdateView(bool); + /// User finished editing a subFeature + virtual void onSubTaskButtonOK(); + // Note: There is no Cancel button because I couldn't work out how to save the state of + // a subFeature so as to revert the changes of an edit operation + +protected: + virtual void changeEvent(QEvent *e); + virtual void onSelectionChanged(const Gui::SelectionChanges& msg); + +private: + void updateUI(); + void closeSubTask(); + void moveTransformFeature(const int increment); + void finishAdd(App::DocumentObject *newFeature); + +private: + Ui_TaskMultiTransformParameters* ui; + /// The subTask and subFeature currently active in the UI + TaskTransformedParameters* subTask; + PartDesign::Transformed* subFeature; + bool editHint; +}; + + +/// simulation dialog for the TaskView +class TaskDlgMultiTransformParameters : public TaskDlgTransformedParameters +{ + Q_OBJECT + +public: + TaskDlgMultiTransformParameters(ViewProviderMultiTransform *MultiTransformView); + virtual ~TaskDlgMultiTransformParameters() {} + +public: + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); + /// is called by the framework if the dialog is rejected (Cancel) + virtual bool reject(); +}; + +} //namespace PartDesignGui + +#endif // GUI_TASKVIEW_TASKAPPERANCE_H diff --git a/src/Mod/PartDesign/Gui/TaskMultiTransformParameters.ui b/src/Mod/PartDesign/Gui/TaskMultiTransformParameters.ui new file mode 100644 index 0000000000..7e3ee40272 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskMultiTransformParameters.ui @@ -0,0 +1,61 @@ + + + PartDesignGui::TaskMultiTransformParameters + + + + 0 + 0 + 225 + 559 + + + + Form + + + + + + Originals + + + + + + + + + + Transformations + + + + + + + + + + Update view + + + true + + + + + + + + 0 + 180 + + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/TaskPatternRectangularParameters.cpp b/src/Mod/PartDesign/Gui/TaskPatternRectangularParameters.cpp deleted file mode 100644 index 5ef0a2a963..0000000000 --- a/src/Mod/PartDesign/Gui/TaskPatternRectangularParameters.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2011 Juergen Riegel * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" - -#ifndef _PreComp_ -#endif - -#include "ui_TaskPatternRectangularParameters.h" -#include "TaskPatternRectangularParameters.h" -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace PartDesignGui; -using namespace Gui; - -/* TRANSLATOR PartDesignGui::TaskPatternRectangularParameters */ - -TaskPatternRectangularParameters::TaskPatternRectangularParameters(QWidget *parent) - : TaskBox(Gui::BitmapFactory().pixmap("document-new"),tr("Parameters rectangular pattern"),true, parent) -{ - // we need a separate container widget to add all controls to - proxy = new QWidget(this); - ui = new Ui_TaskPatternRectangularParameters(); - ui->setupUi(proxy); - QMetaObject::connectSlotsByName(this); - - this->groupLayout()->addWidget(proxy); - - Gui::Selection().Attach(this); -} - -TaskPatternRectangularParameters::~TaskPatternRectangularParameters() -{ - delete ui; - Gui::Selection().Detach(this); -} - -void TaskPatternRectangularParameters::changeEvent(QEvent *e) -{ - TaskBox::changeEvent(e); - if (e->type() == QEvent::LanguageChange) { - ui->retranslateUi(proxy); - } -} - -/// @cond DOXERR -void TaskPatternRectangularParameters::OnChange(Gui::SelectionSingleton::SubjectType &rCaller, - Gui::SelectionSingleton::MessageType Reason) -{ - if (Reason.Type == SelectionChanges::AddSelection || - Reason.Type == SelectionChanges::RmvSelection || - Reason.Type == SelectionChanges::SetSelection || - Reason.Type == SelectionChanges::ClrSelection) { - } -} -/// @endcond - -//************************************************************************** -//************************************************************************** -// TaskDialog -//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TaskDlgPatternRectangularParameters::TaskDlgPatternRectangularParameters(ViewProviderPatternRectangular *PatternRectangularView) - : TaskDialog(),PatternRectangularView(PatternRectangularView) -{ - assert(PatternRectangularView); - parameter = new TaskPatternRectangularParameters(); - - Content.push_back(parameter); -} - -TaskDlgPatternRectangularParameters::~TaskDlgPatternRectangularParameters() -{ - -} - -//==== calls from the TaskView =============================================================== - - -void TaskDlgPatternRectangularParameters::open() -{ - -} - -void TaskDlgPatternRectangularParameters::clicked(int) -{ - -} - -bool TaskDlgPatternRectangularParameters::accept() -{ - return true; -} - -bool TaskDlgPatternRectangularParameters::reject() -{ - Gui::Command::openCommand("PatternRectangular changed"); - Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); - Gui::Command::commitCommand(); - - return true; -} - -void TaskDlgPatternRectangularParameters::helpRequested() -{ - -} - - - - -#include "moc_TaskPatternRectangularParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskPatternRectangularParameters.h b/src/Mod/PartDesign/Gui/TaskPatternRectangularParameters.h deleted file mode 100644 index da2d04259a..0000000000 --- a/src/Mod/PartDesign/Gui/TaskPatternRectangularParameters.h +++ /dev/null @@ -1,108 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2011 Juergen Riegel * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#ifndef GUI_TASKVIEW_TaskPatternRectangularParameters_H -#define GUI_TASKVIEW_TaskPatternRectangularParameters_H - -#include -#include -#include - -#include "ViewProviderPatternRectangular.h" - -class Ui_TaskPatternRectangularParameters; - -namespace App { -class Property; -} - -namespace Gui { -class ViewProvider; -} - -namespace PartDesignGui { - - - -class TaskPatternRectangularParameters : public Gui::TaskView::TaskBox, public Gui::SelectionSingleton::ObserverType -{ - Q_OBJECT - -public: - TaskPatternRectangularParameters(QWidget *parent = 0); - ~TaskPatternRectangularParameters(); - /// Observer message from the Selection - void OnChange(Gui::SelectionSingleton::SubjectType &rCaller, - Gui::SelectionSingleton::MessageType Reason); - -private Q_SLOTS: - -protected: - void changeEvent(QEvent *e); - -private: - -private: - QWidget* proxy; - Ui_TaskPatternRectangularParameters* ui; -}; - -/// simulation dialog for the TaskView -class TaskDlgPatternRectangularParameters : public Gui::TaskView::TaskDialog -{ - Q_OBJECT - -public: - TaskDlgPatternRectangularParameters(ViewProviderPatternRectangular *PatternRectangularView); - ~TaskDlgPatternRectangularParameters(); - - ViewProviderPatternRectangular* getPatternRectangularView() const - { return PatternRectangularView; } - -public: - /// is called the TaskView when the dialog is opened - virtual void open(); - /// is called by the framework if an button is clicked which has no accept or reject role - virtual void clicked(int); - /// is called by the framework if the dialog is accepted (Ok) - virtual bool accept(); - /// is called by the framework if the dialog is rejected (Cancel) - virtual bool reject(); - /// is called by the framework if the user presses the help button - virtual void helpRequested(); - virtual bool isAllowedAlterDocument(void) const - { return false; } - - /// returns for Close and Help button - virtual QDialogButtonBox::StandardButtons getStandardButtons(void) const - { return QDialogButtonBox::Close|QDialogButtonBox::Help; } - -protected: - ViewProviderPatternRectangular *PatternRectangularView; - - TaskPatternRectangularParameters *parameter; -}; - -} //namespace PartDesignGui - -#endif // GUI_TASKVIEW_TASKAPPERANCE_H diff --git a/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.cpp b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.cpp new file mode 100644 index 0000000000..a01179893a --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.cpp @@ -0,0 +1,426 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +#include "ui_TaskPolarPatternParameters.h" +#include "TaskPolarPatternParameters.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "TaskMultiTransformParameters.h" + +using namespace PartDesignGui; +using namespace Gui; + +/* TRANSLATOR PartDesignGui::TaskPolarPatternParameters */ + +TaskPolarPatternParameters::TaskPolarPatternParameters(ViewProviderTransformed *TransformedView,QWidget *parent) + : TaskTransformedParameters(TransformedView, parent) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskPolarPatternParameters(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + this->groupLayout()->addWidget(proxy); + + ui->buttonOK->hide(); + ui->checkBoxUpdateView->setEnabled(true); + + updateUIinProgress = false; // Hack, sometimes it is NOT false although set to false in Transformed::Transformed()!! + setupUI(); +} + +TaskPolarPatternParameters::TaskPolarPatternParameters(QWidget *parent, TaskMultiTransformParameters *parentTask) + : TaskTransformedParameters(parent, parentTask) +{ + ui = new Ui_TaskPolarPatternParameters(); + ui->setupUi(parent); + connect(ui->buttonOK, SIGNAL(pressed()), + parentTask, SLOT(onSubTaskButtonOK())); + QMetaObject::connectSlotsByName(this); + + ui->buttonOK->setEnabled(true); + ui->listFeatures->hide(); + ui->checkBoxUpdateView->hide(); + + updateUIinProgress = false; // Hack, sometimes it is NOT false although set to false in Transformed::Transformed()!! + setupUI(); +} + +void TaskPolarPatternParameters::setupUI() +{ + connect(ui->buttonX, SIGNAL(pressed()), + this, SLOT(onButtonX())); + connect(ui->buttonY, SIGNAL(pressed()), + this, SLOT(onButtonY())); + connect(ui->buttonZ, SIGNAL(pressed()), + this, SLOT(onButtonZ())); + connect(ui->checkReverse, SIGNAL(toggled(bool)), + this, SLOT(onCheckReverse(bool))); + connect(ui->spinAngle, SIGNAL(valueChanged(double)), + this, SLOT(onAngle(double))); + connect(ui->spinOccurrences, SIGNAL(valueChanged(int)), + this, SLOT(onOccurrences(int))); + connect(ui->buttonReference, SIGNAL(pressed()), + this, SLOT(onButtonReference())); + connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)), + this, SLOT(onUpdateView(bool))); + + // TODO: The following code could be generic in TaskTransformedParameters + // if it were possible to make ui_TaskPolarPatternParameters a subclass of + // ui_TaskTransformedParameters + // --------------------- + // Add a context menu to the listview of the originals to delete items + QAction* action = new QAction(tr("Delete"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onOriginalDeleted())); + ui->listFeatures->addAction(action); + ui->listFeatures->setContextMenuPolicy(Qt::ActionsContextMenu); + + // Get the feature data + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + std::vector originals = pcPolarPattern->Originals.getValues(); + + // Fill data into dialog elements + ui->listFeatures->setEnabled(true); + ui->listFeatures->clear(); + for (std::vector::const_iterator i = originals.begin(); i != originals.end(); i++) + { + if ((*i) != NULL) + ui->listFeatures->addItem(QString::fromAscii((*i)->getNameInDocument())); + } + QMetaObject::invokeMethod(ui->listFeatures, "setFocus", Qt::QueuedConnection); + // --------------------- + + ui->buttonX->setEnabled(true); + ui->buttonY->setEnabled(true); + ui->buttonZ->setEnabled(true); + ui->checkReverse->setEnabled(true); + ui->spinAngle->setEnabled(true); + ui->spinOccurrences->setEnabled(true); + ui->buttonReference->setEnabled(true); + ui->lineReference->setEnabled(false); // This is never enabled since it is for optical feed-back only + updateUI(); +} + +void TaskPolarPatternParameters::updateUI() +{ + if (updateUIinProgress) return; + updateUIinProgress = true; + + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + + App::DocumentObject* axisFeature = pcPolarPattern->Axis.getValue(); + std::vector axes = pcPolarPattern->Axis.getSubValues(); + std::string stdAxis = pcPolarPattern->StdAxis.getValue(); + bool reverse = pcPolarPattern->Reversed.getValue(); + double angle = pcPolarPattern->Angle.getValue(); + unsigned occurrences = pcPolarPattern->Occurrences.getValue(); + + if ((featureSelectionMode || insideMultiTransform) && !stdAxis.empty()) + { + ui->buttonReference->setDown(false); + ui->buttonX->setAutoExclusive(true); + ui->buttonY->setAutoExclusive(true); + ui->buttonZ->setAutoExclusive(true); + ui->buttonX->setChecked(stdAxis == "X"); + ui->buttonY->setChecked(stdAxis == "Y"); + ui->buttonZ->setChecked(stdAxis == "Z"); + ui->lineReference->setText(tr("")); + } else if ((axisFeature != NULL) && !axes.empty()) { + ui->buttonX->setAutoExclusive(false); + ui->buttonY->setAutoExclusive(false); + ui->buttonZ->setAutoExclusive(false); + ui->buttonX->setChecked(false); + ui->buttonY->setChecked(false); + ui->buttonZ->setChecked(false); + ui->buttonReference->setDown(!featureSelectionMode); + ui->lineReference->setText(QString::fromAscii(axes.front().c_str())); + } else { + // Error message? + ui->lineReference->setText(tr("")); + } + + ui->checkReverse->setChecked(reverse); + ui->spinAngle->setValue(angle); + ui->spinOccurrences->setValue(occurrences); + + updateUIinProgress = false; +} + +void TaskPolarPatternParameters::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + App::DocumentObject* selectedObject = pcPolarPattern->getDocument()->getActiveObject(); + if ((selectedObject == NULL) || !selectedObject->isDerivedFrom(Part::Feature::getClassTypeId())) + return; + + if (featureSelectionMode) { + if (originalSelected(msg)) + ui->listFeatures->addItem(QString::fromAscii(selectedObject->getNameInDocument())); + } else { + if (!msg.pSubName || msg.pSubName[0] == '\0') + return; + + std::string element(msg.pSubName); + + if (msg.Type == Gui::SelectionChanges::AddSelection) { + + if (element.substr(0,4) != "Edge") + return; + + // TODO +// if (originalElementName == "") { +// Base::Console().Error("Element created by this pattern cannot be used for axis\n"); +// return; +// } + + std::vector axes; + axes.push_back(element.c_str()); + pcPolarPattern->Axis.setValue(getOriginalObject(), axes); + + if (insideMultiTransform) { + if (parentTask->updateView()) + recomputeFeature(); + } else + if (ui->checkBoxUpdateView->isChecked()) + recomputeFeature(); + + if (!insideMultiTransform) + featureSelectionMode = true; // Jump back to selection of originals + updateUI(); + } + } +} + +void TaskPolarPatternParameters::onOriginalDeleted() +{ + int row = ui->listFeatures->currentIndex().row(); + TaskTransformedParameters::onOriginalDeleted(row); + ui->listFeatures->model()->removeRow(row); +} + +void TaskPolarPatternParameters::onButtonX() { + onStdAxis("X"); +} + +void TaskPolarPatternParameters::onButtonY() { + onStdAxis("Y"); +} + +void TaskPolarPatternParameters::onButtonZ() { + onStdAxis("Z"); +} + +void TaskPolarPatternParameters::onCheckReverse(const bool on) { + if (updateUIinProgress) return; + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + pcPolarPattern->Reversed.setValue(on); + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskPolarPatternParameters::onAngle(const double a) { + if (updateUIinProgress) return; + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + pcPolarPattern->Angle.setValue(a); + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskPolarPatternParameters::onOccurrences(const int n) { + if (updateUIinProgress) return; + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + pcPolarPattern->Occurrences.setValue(n); + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskPolarPatternParameters::onStdAxis(const std::string& axis) { + if (updateUIinProgress) return; + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + pcPolarPattern->StdAxis.setValue(axis.c_str()); + pcPolarPattern->Axis.setValue(NULL); + if (!insideMultiTransform) + featureSelectionMode = true; + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskPolarPatternParameters::onButtonReference() +{ + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + pcPolarPattern->StdAxis.setValue(""); + featureSelectionMode = false; + updateUI(); +} + +void TaskPolarPatternParameters::onUpdateView(bool on) +{ + ui->buttonX->blockSignals(!on); + ui->buttonY->blockSignals(!on); + ui->buttonZ->blockSignals(!on); + ui->listFeatures->blockSignals(!on); + ui->checkReverse->blockSignals(!on); + ui->spinAngle->blockSignals(!on); + ui->spinOccurrences->blockSignals(!on); +} + +const std::string TaskPolarPatternParameters::getStdAxis(void) const +{ + std::string stdAxis; + + if (ui->buttonX->isChecked()) + stdAxis = "X"; + else if (ui->buttonY->isChecked()) + stdAxis = "Y"; + else if (ui->buttonZ->isChecked()) + stdAxis = "Z"; + + if (!stdAxis.empty()) + return std::string("\"") + stdAxis + "\""; + else + return std::string(""); +} + +const QString TaskPolarPatternParameters::getAxis(void) const +{ + PartDesign::PolarPattern* pcPolarPattern = static_cast(getObject()); + App::DocumentObject* feature = pcPolarPattern->Axis.getValue(); + if (feature == NULL) + return QString::fromUtf8(""); + std::vector axes = pcPolarPattern->Axis.getSubValues(); + QString buf; + + if ((feature != NULL) && !axes.empty()) { + buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])"); + buf = buf.arg(QString::fromUtf8(feature->getNameInDocument())); + buf = buf.arg(QString::fromUtf8(axes.front().c_str())); + } + else + buf = QString::fromUtf8(""); + + return buf; +} + +const bool TaskPolarPatternParameters::getReverse(void) const +{ + return ui->checkReverse->isChecked(); +} + +const double TaskPolarPatternParameters::getAngle(void) const +{ + return ui->spinAngle->value(); +} + +const unsigned TaskPolarPatternParameters::getOccurrences(void) const +{ + return ui->spinOccurrences->value(); +} + +TaskPolarPatternParameters::~TaskPolarPatternParameters() +{ + delete ui; +} + +void TaskPolarPatternParameters::changeEvent(QEvent *e) +{ + TaskBox::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(proxy); + } +} + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgPolarPatternParameters::TaskDlgPolarPatternParameters(ViewProviderPolarPattern *PolarPatternView) + : TaskDlgTransformedParameters(PolarPatternView) +{ + parameter = new TaskPolarPatternParameters(PolarPatternView); + + Content.push_back(parameter); +} +//==== calls from the TaskView =============================================================== + +bool TaskDlgPolarPatternParameters::accept() +{ + std::string name = TransformedView->getObject()->getNameInDocument(); + + try { + //Gui::Command::openCommand("PolarPattern changed"); + // Handle Originals + if (!TaskDlgTransformedParameters::accept()) + return false; + + TaskPolarPatternParameters* polarpatternParameter = static_cast(parameter); + std::string axis = polarpatternParameter->getAxis().toStdString(); + if (!axis.empty()) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Axis = %s", name.c_str(), axis.c_str()); + std::string stdAxis = polarpatternParameter->getStdAxis(); + if (!stdAxis.empty()) + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.StdAxis = %s",name.c_str(),stdAxis.c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Reversed = %u",name.c_str(),polarpatternParameter->getReverse()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Angle = %f",name.c_str(),polarpatternParameter->getAngle()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Occurrences = %u",name.c_str(),polarpatternParameter->getOccurrences()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); + if (!TransformedView->getObject()->isValid()) + throw Base::Exception(TransformedView->getObject()->getStatusString()); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + Gui::Command::commitCommand(); + } + catch (const Base::Exception& e) { + QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what())); + return false; + } + + return true; +} + +#include "moc_TaskPolarPatternParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.h b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.h new file mode 100644 index 0000000000..b6471eeb7a --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.h @@ -0,0 +1,106 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef GUI_TASKVIEW_TaskPolarPatternParameters_H +#define GUI_TASKVIEW_TaskPolarPatternParameters_H + +#include +#include +#include + +#include "TaskTransformedParameters.h" +#include "ViewProviderPolarPattern.h" + +class Ui_TaskPolarPatternParameters; + +namespace App { +class Property; +} + +namespace Gui { +class ViewProvider; +} + +namespace PartDesignGui { + +class TaskMultiTransformParameters; + +class TaskPolarPatternParameters : public TaskTransformedParameters +{ + Q_OBJECT + +public: + /// Constructor for task with ViewProvider + TaskPolarPatternParameters(ViewProviderTransformed *TransformedView, QWidget *parent = 0); + /// Constructor for task with parent task (MultiTransform mode) + TaskPolarPatternParameters(QWidget *parent, TaskMultiTransformParameters *parentTask); + virtual ~TaskPolarPatternParameters(); + + const QString getAxis(void) const; + const std::string getStdAxis(void) const; + const bool getReverse(void) const; + const double getAngle(void) const; + const unsigned getOccurrences(void) const; + +private Q_SLOTS: + void onStdAxis(const std::string& axis); + void onButtonX(); + void onButtonY(); + void onButtonZ(); + void onCheckReverse(const bool on); + void onAngle(const double a); + void onOccurrences(const int n); + virtual void onButtonReference(); + virtual void onOriginalDeleted(); + virtual void onUpdateView(bool); + +protected: + virtual void changeEvent(QEvent *e); + virtual void onSelectionChanged(const Gui::SelectionChanges& msg); + +private: + void updateUI(); + void setupUI(); + +private: + Ui_TaskPolarPatternParameters* ui; +}; + + +/// simulation dialog for the TaskView +class TaskDlgPolarPatternParameters : public TaskDlgTransformedParameters +{ + Q_OBJECT + +public: + TaskDlgPolarPatternParameters(ViewProviderPolarPattern *PolarPatternView); + virtual ~TaskDlgPolarPatternParameters() {} + +public: + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); +}; + +} //namespace PartDesignGui + +#endif // GUI_TASKVIEW_TASKAPPERANCE_H diff --git a/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.ui b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.ui new file mode 100644 index 0000000000..c7dd82965e --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskPolarPatternParameters.ui @@ -0,0 +1,139 @@ + + + PartDesignGui::TaskPolarPatternParameters + + + + 0 + 0 + 225 + 400 + + + + Form + + + + + + + + + + + X + + + true + + + + + + + Y + + + + + + + Z + + + + + + + + + + + Direction + + + + + + + + + + + + Reverse direction + + + + + + + + + Angle + + + + + + + 2 + + + 360.000000000000000 + + + 360.000000000000000 + + + + + + + + + + + Occurrences + + + + + + + 2 + + + 99999 + + + + + + + + + + + OK + + + + + + + + + Update view + + + true + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp b/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp new file mode 100644 index 0000000000..a92bca4ad9 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskScaledParameters.cpp @@ -0,0 +1,256 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +#include "ui_TaskScaledParameters.h" +#include "TaskScaledParameters.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "TaskMultiTransformParameters.h" + +using namespace PartDesignGui; +using namespace Gui; + +/* TRANSLATOR PartDesignGui::TaskScaledParameters */ + +TaskScaledParameters::TaskScaledParameters(ViewProviderTransformed *TransformedView,QWidget *parent) + : TaskTransformedParameters(TransformedView, parent) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskScaledParameters(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + this->groupLayout()->addWidget(proxy); + + ui->buttonOK->hide(); + ui->checkBoxUpdateView->setEnabled(true); + + updateUIinProgress = false; // Hack, sometimes it is NOT false although set to false in Transformed::Transformed()!! + setupUI(); +} + +TaskScaledParameters::TaskScaledParameters(QWidget *parent, TaskMultiTransformParameters *parentTask) + : TaskTransformedParameters(parent, parentTask) +{ + ui = new Ui_TaskScaledParameters(); + ui->setupUi(parent); + connect(ui->buttonOK, SIGNAL(pressed()), + parentTask, SLOT(onSubTaskButtonOK())); + QMetaObject::connectSlotsByName(this); + + ui->buttonOK->setEnabled(true); + ui->listFeatures->hide(); + ui->checkBoxUpdateView->hide(); + + updateUIinProgress = false; // Hack, sometimes it is NOT false although set to false in Transformed::Transformed()!! + setupUI(); +} + +void TaskScaledParameters::setupUI() +{ + connect(ui->spinFactor, SIGNAL(valueChanged(double)), + this, SLOT(onFactor(double))); + connect(ui->spinOccurrences, SIGNAL(valueChanged(int)), + this, SLOT(onOccurrences(int))); + connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)), + this, SLOT(onUpdateView(bool))); + + // TODO: The following code could be generic in TaskTransformedParameters + // if it were possible to make ui_TaskScaledParameters a subclass of + // ui_TaskTransformedParameters + // --------------------- + // Add a context menu to the listview of the originals to delete items + QAction* action = new QAction(tr("Delete"), ui->listFeatures); + action->connect(action, SIGNAL(triggered()), + this, SLOT(onOriginalDeleted())); + ui->listFeatures->addAction(action); + ui->listFeatures->setContextMenuPolicy(Qt::ActionsContextMenu); + + // Get the feature data + PartDesign::Scaled* pcScaled = static_cast(getObject()); + std::vector originals = pcScaled->Originals.getValues(); + + // Fill data into dialog elements + ui->listFeatures->setEnabled(true); + ui->listFeatures->clear(); + for (std::vector::const_iterator i = originals.begin(); i != originals.end(); i++) + { + if ((*i) != NULL) + ui->listFeatures->addItem(QString::fromAscii((*i)->getNameInDocument())); + } + QMetaObject::invokeMethod(ui->listFeatures, "setFocus", Qt::QueuedConnection); + // --------------------- + + ui->spinFactor->setEnabled(true); + ui->spinOccurrences->setEnabled(true); + + updateUI(); +} + +void TaskScaledParameters::updateUI() +{ + if (updateUIinProgress) return; + updateUIinProgress = true; + + PartDesign::Scaled* pcScaled = static_cast(getObject()); + + double factor = pcScaled->Factor.getValue(); + unsigned occurrences = pcScaled->Occurrences.getValue(); + + ui->spinFactor->setValue(factor); + ui->spinOccurrences->setValue(occurrences); + + updateUIinProgress = false; +} + +void TaskScaledParameters::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + PartDesign::Scaled* pcScaled = static_cast(getObject()); + App::DocumentObject* selectedObject = pcScaled->getDocument()->getActiveObject(); + if ((selectedObject == NULL) || !selectedObject->isDerivedFrom(Part::Feature::getClassTypeId())) + return; + + if (featureSelectionMode) { + if (originalSelected(msg)) + ui->listFeatures->addItem(QString::fromAscii(selectedObject->getNameInDocument())); + } else { + return; + } +} + +void TaskScaledParameters::onOriginalDeleted() +{ + int row = ui->listFeatures->currentIndex().row(); + TaskTransformedParameters::onOriginalDeleted(row); + ui->listFeatures->model()->removeRow(row); +} + +void TaskScaledParameters::onFactor(const double f) { + if (updateUIinProgress) return; + PartDesign::Scaled* pcScaled = static_cast(getObject()); + pcScaled->Factor.setValue(f); + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskScaledParameters::onOccurrences(const int n) { + if (updateUIinProgress) return; + PartDesign::Scaled* pcScaled = static_cast(getObject()); + pcScaled->Occurrences.setValue(n); + updateUI(); + if (insideMultiTransform && !parentTask->updateView()) + return; + recomputeFeature(); +} + +void TaskScaledParameters::onUpdateView(bool on) +{ + ui->listFeatures->blockSignals(!on); + ui->spinFactor->blockSignals(!on); + ui->spinOccurrences->blockSignals(!on); +} + +const double TaskScaledParameters::getFactor(void) const +{ + return ui->spinFactor->value(); +} + +const unsigned TaskScaledParameters::getOccurrences(void) const +{ + return ui->spinOccurrences->value(); +} + +TaskScaledParameters::~TaskScaledParameters() +{ + delete ui; +} + +void TaskScaledParameters::changeEvent(QEvent *e) +{ + TaskBox::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(proxy); + } +} + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgScaledParameters::TaskDlgScaledParameters(ViewProviderScaled *ScaledView) + : TaskDlgTransformedParameters(ScaledView) +{ + parameter = new TaskScaledParameters(ScaledView); + + Content.push_back(parameter); +} +//==== calls from the TaskView =============================================================== + +bool TaskDlgScaledParameters::accept() +{ + std::string name = TransformedView->getObject()->getNameInDocument(); + + try { + //Gui::Command::openCommand("Scaled changed"); + // Handle Originals + if (!TaskDlgTransformedParameters::accept()) + return false; + + TaskScaledParameters* scaledParameter = static_cast(parameter); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Factor = %f",name.c_str(),scaledParameter->getFactor()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Occurrences = %u",name.c_str(),scaledParameter->getOccurrences()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); + if (!TransformedView->getObject()->isValid()) + throw Base::Exception(TransformedView->getObject()->getStatusString()); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + Gui::Command::commitCommand(); + } + catch (const Base::Exception& e) { + QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what())); + return false; + } + + return true; +} + +#include "moc_TaskScaledParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskScaledParameters.h b/src/Mod/PartDesign/Gui/TaskScaledParameters.h new file mode 100644 index 0000000000..448e2f6fb4 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskScaledParameters.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef GUI_TASKVIEW_TaskScaledParameters_H +#define GUI_TASKVIEW_TaskScaledParameters_H + +#include +#include +#include + +#include "TaskTransformedParameters.h" +#include "ViewProviderScaled.h" + +class Ui_TaskScaledParameters; + +namespace App { +class Property; +} + +namespace Gui { +class ViewProvider; +} + +namespace PartDesignGui { + +class TaskMultiTransformParameters; + +class TaskScaledParameters : public TaskTransformedParameters +{ + Q_OBJECT + +public: + /// Constructor for task with ViewProvider + TaskScaledParameters(ViewProviderTransformed *TransformedView, QWidget *parent = 0); + /// Constructor for task with parent task (MultiTransform mode) + TaskScaledParameters(QWidget *parent, TaskMultiTransformParameters *parentTask); + virtual ~TaskScaledParameters(); + + const double getFactor(void) const; + const unsigned getOccurrences(void) const; + +private Q_SLOTS: + void onFactor(const double f); + void onOccurrences(const int n); + virtual void onButtonReference() {} + virtual void onOriginalDeleted(); + virtual void onUpdateView(bool); + +protected: + virtual void changeEvent(QEvent *e); + virtual void onSelectionChanged(const Gui::SelectionChanges& msg); + +private: + void updateUI(); + void setupUI(); + +private: + Ui_TaskScaledParameters* ui; +}; + + +/// simulation dialog for the TaskView +class TaskDlgScaledParameters : public TaskDlgTransformedParameters +{ + Q_OBJECT + +public: + TaskDlgScaledParameters(ViewProviderScaled *ScaledView); + virtual ~TaskDlgScaledParameters() {} + +public: + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); +}; + +} //namespace PartDesignGui + +#endif // GUI_TASKVIEW_TASKAPPERANCE_H diff --git a/src/Mod/PartDesign/Gui/TaskScaledParameters.ui b/src/Mod/PartDesign/Gui/TaskScaledParameters.ui new file mode 100644 index 0000000000..c1e336b995 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskScaledParameters.ui @@ -0,0 +1,93 @@ + + + PartDesignGui::TaskScaledParameters + + + + 0 + 0 + 225 + 305 + + + + Form + + + + + + + + + + + Factor + + + + + + + 3 + + + 999999.000000000000000 + + + 0.500000000000000 + + + 2.000000000000000 + + + + + + + + + + + Occurrences + + + + + + + 2 + + + 99999 + + + + + + + + + + + OK + + + + + + + + + Update view + + + true + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp b/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp new file mode 100644 index 0000000000..57da956d60 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp @@ -0,0 +1,211 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +#include "TaskTransformedParameters.h" +#include "TaskMultiTransformParameters.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace PartDesignGui; +using namespace Gui; + +/* TRANSLATOR PartDesignGui::TaskTransformedParameters */ + +TaskTransformedParameters::TaskTransformedParameters(ViewProviderTransformed *TransformedView, QWidget *parent) + : TaskBox(Gui::BitmapFactory().pixmap((std::string("PartDesign_") + TransformedView->featureName).c_str()), + QString::fromAscii((TransformedView->featureName + " parameters").c_str()), + true, + parent), + TransformedView(TransformedView), + parentTask(NULL), + insideMultiTransform(false), + updateUIinProgress(false) +{ + // Start in feature selection mode + featureSelectionMode = true; +} + +TaskTransformedParameters::TaskTransformedParameters(QWidget *parent, TaskMultiTransformParameters *parentTask) + : TaskBox(QPixmap(), tr(""), true, parent), + TransformedView(NULL), + parentTask(parentTask), + insideMultiTransform(true), + updateUIinProgress(false) +{ + // Start in reference selection mode and stay there! Feature selection makes + // no sense inside a MultiTransform + featureSelectionMode = false; +} + +const bool TaskTransformedParameters::originalSelected(const Gui::SelectionChanges& msg) +{ + if (featureSelectionMode && (msg.Type == Gui::SelectionChanges::AddSelection)) { + PartDesign::Transformed* pcTransformed = static_cast(TransformedView->getObject()); + App::DocumentObject* selectedObject = pcTransformed->getDocument()->getActiveObject(); + if (!selectedObject->isDerivedFrom(PartDesign::Additive::getClassTypeId()) && + !selectedObject->isDerivedFrom(PartDesign::Subtractive::getClassTypeId())) + return false; + if (TransformedView->getObject() == pcTransformed) + return false; + + std::vector originals = pcTransformed->Originals.getValues(); + + if (std::find(originals.begin(), originals.end(), selectedObject) == originals.end()) { + originals.push_back(selectedObject); + pcTransformed->Originals.setValues(originals); + pcTransformed->getDocument()->recomputeFeature(pcTransformed); + return true; + } + } + + return false; +} + +void TaskTransformedParameters::onOriginalDeleted(const int row) +{ + PartDesign::Transformed* pcTransformed = static_cast(TransformedView->getObject()); + std::vector originals = pcTransformed->Originals.getValues(); + originals.erase(originals.begin() + row); + pcTransformed->Originals.setValues(originals); + pcTransformed->getDocument()->recomputeFeature(pcTransformed); +} + +const std::vector TaskTransformedParameters::getOriginals(void) const +{ + PartDesign::Transformed* pcTransformed = static_cast(TransformedView->getObject()); + std::vector originals = pcTransformed->Originals.getValues(); + + return originals; +} + +PartDesign::Transformed *TaskTransformedParameters::getObject() const +{ + + if (insideMultiTransform) + return parentTask->getSubFeature(); + else + return static_cast(TransformedView->getObject()); +} + +void TaskTransformedParameters::recomputeFeature() +{ + if (insideMultiTransform) { + parentTask->recomputeFeature(); + } else { + PartDesign::Transformed* pcTransformed = static_cast(TransformedView->getObject()); + pcTransformed->getDocument()->recomputeFeature(pcTransformed); + } +} + +App::DocumentObject* TaskTransformedParameters::getOriginalObject() const +{ + if (insideMultiTransform) { + return parentTask->getOriginalObject(); + } else { + PartDesign::Transformed* pcTransformed = static_cast(TransformedView->getObject()); + return pcTransformed->getOriginalObject(); + } +} + + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgTransformedParameters::TaskDlgTransformedParameters(ViewProviderTransformed *TransformedView) + : TaskDialog(),TransformedView(TransformedView) +{ + assert(TransformedView); +} + +//==== calls from the TaskView =============================================================== + +bool TaskDlgTransformedParameters::accept() +{ + std::string name = TransformedView->getObject()->getNameInDocument(); + + try { + //Gui::Command::openCommand(featureName + " changed"); + std::vector originals = parameter->getOriginals(); + std::stringstream str; + str << "App.ActiveDocument." << name.c_str() << ".Originals = ["; + for (std::vector::const_iterator it = originals.begin(); it != originals.end(); ++it) + { + if ((*it) != NULL) + str << "App.ActiveDocument." << (*it)->getNameInDocument() << ","; + } + str << "]"; + Gui::Command::runCommand(Gui::Command::Doc,str.str().c_str()); + } + catch (const Base::Exception& e) { + QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what())); + return false; + } + + // Continue (usually in virtual method accept()) + return true; +} + +bool TaskDlgTransformedParameters::reject() +{ + // Get object before view is invalidated + PartDesign::Transformed* pcTransformed = static_cast(TransformedView->getObject()); + std::vector pcOriginals = pcTransformed->Originals.getValues(); + + // roll back the done things + Gui::Command::abortCommand(); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + + // if abort command deleted the object the originals are visible again + if (!Gui::Application::Instance->getViewProvider(pcTransformed)) { + for (std::vector::const_iterator it = pcOriginals.begin(); it != pcOriginals.end(); ++it) + { + if (((*it) != NULL) && (Gui::Application::Instance->getViewProvider(*it) != NULL)) { + Gui::Application::Instance->getViewProvider(*it)->show(); + } + } + } + + return true; +} + + + +#include "moc_TaskTransformedParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskTransformedParameters.h b/src/Mod/PartDesign/Gui/TaskTransformedParameters.h new file mode 100644 index 0000000000..7e8921f6b6 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskTransformedParameters.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef GUI_TASKVIEW_TaskTransformedParameters_H +#define GUI_TASKVIEW_TaskTransformedParameters_H + +#include +#include +#include + +#include "ViewProviderTransformed.h" + +namespace PartDesign { +class Transformed; +} + +namespace PartDesignGui { + +class TaskMultiTransformParameters; + +/** + The transformed subclasses will be used in two different modes: + 1. As a stand-alone feature + 2. As a container that stores transformation info for a MultiTransform feature. In this case + the flag insideMultiTransform is set to true. + Because in the second case there is no ViewProvider, some special methods are required to + access the underlying FeatureTransformed object in two different ways. + **/ +class TaskTransformedParameters : public Gui::TaskView::TaskBox, public Gui::SelectionObserver +{ + Q_OBJECT + +public: + /// Constructor for task with ViewProvider + TaskTransformedParameters(ViewProviderTransformed *TransformedView, QWidget *parent = 0); + /// Constructor for task with parent task (MultiTransform mode) + TaskTransformedParameters(QWidget *parent, TaskMultiTransformParameters* parentTask); + virtual ~TaskTransformedParameters() + {} + + const std::vector getOriginals(void) const; + + +protected Q_SLOTS: + virtual void onButtonReference() = 0; + virtual void onOriginalDeleted() = 0; + virtual void onUpdateView(bool) = 0; + + /// Connect the subTask OK button to the MultiTransform task + virtual void onSubTaskButtonOK() {} + +protected: + void onOriginalDeleted(const int row); + const bool originalSelected(const Gui::SelectionChanges& msg); + + /// Get the TransformedFeature object associated with this task + // Either through the ViewProvider or the currently active subFeature of the parentTask + PartDesign::Transformed *getObject() const; + /// Recompute either this feature or the parent feature (MultiTransform mode) + void recomputeFeature(); + /// Get the original object either of the object associated with this feature or with the parent feature (MultiTransform mode) + App::DocumentObject* getOriginalObject() const; + +protected: + virtual void changeEvent(QEvent *e) = 0; + virtual void onSelectionChanged(const Gui::SelectionChanges& msg) = 0; + +protected: + QWidget* proxy; + ViewProviderTransformed *TransformedView; + bool featureSelectionMode; + + /// The MultiTransform parent task of this task + TaskMultiTransformParameters* parentTask; + /// Flag indicating whether this object is a container for MultiTransform + bool insideMultiTransform; + /// Lock updateUI() so that no unnecessary recomputeFeatures() are triggered + bool updateUIinProgress; +}; + +/// simulation dialog for the TaskView +class TaskDlgTransformedParameters : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskDlgTransformedParameters(ViewProviderTransformed *TransformedView); + virtual ~TaskDlgTransformedParameters() {} + + ViewProviderTransformed* getTransformedView() const + { return TransformedView; } + +public: + /// is called the TaskView when the dialog is opened + virtual void open() + {} + /// is called by the framework if an button is clicked which has no accept or reject role + virtual void clicked(int) + {} + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); + /// is called by the framework if the dialog is rejected (Cancel) + virtual bool reject(); + /// is called by the framework if the user presses the help button + virtual bool isAllowedAlterDocument(void) const + { return false; } + + /// returns for Close and Help button + virtual QDialogButtonBox::StandardButtons getStandardButtons(void) const + { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; } + +protected: + ViewProviderTransformed *TransformedView; + + TaskTransformedParameters *parameter; +}; + +} //namespace PartDesignGui + +#endif // GUI_TASKVIEW_TASKAPPERANCE_H diff --git a/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.cpp b/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.cpp new file mode 100644 index 0000000000..393b9f2bfe --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.cpp @@ -0,0 +1,61 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "ViewProviderLinearPattern.h" +#include "TaskLinearPatternParameters.h" +#include +#include +#include +#include +#include + +using namespace PartDesignGui; + +PROPERTY_SOURCE(PartDesignGui::ViewProviderLinearPattern,PartDesignGui::ViewProvider) + +bool ViewProviderLinearPattern::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default ) { + TaskDlgLinearPatternParameters *linearpatternDlg = NULL; + + if (checkDlgOpen(linearpatternDlg)) { + // start the edit dialog + if (linearpatternDlg) + Gui::Control().showDialog(linearpatternDlg); + else + Gui::Control().showDialog(new TaskDlgLinearPatternParameters(this)); + + return true; + } else { + return false; + } + } + else { + return ViewProviderPart::setEdit(ModNum); + } +} diff --git a/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.h b/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.h new file mode 100644 index 0000000000..1644a099d2 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef PARTGUI_ViewProviderLinearPattern_H +#define PARTGUI_ViewProviderLinearPattern_H + +#include "ViewProviderTransformed.h" + +namespace PartDesignGui { + +class PartDesignGuiExport ViewProviderLinearPattern : public ViewProviderTransformed +{ + PROPERTY_HEADER(PartGui::ViewProviderLinearPattern); +public: + ViewProviderLinearPattern() + { featureName = std::string("LinearPattern"); } + +protected: + virtual bool setEdit(int ModNum); + +}; + + +} // namespace PartDesignGui + + +#endif // PARTGUI_ViewProviderLinearPattern_H diff --git a/src/Mod/PartDesign/Gui/ViewProviderMirrored.cpp b/src/Mod/PartDesign/Gui/ViewProviderMirrored.cpp new file mode 100644 index 0000000000..4bb9c794dc --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderMirrored.cpp @@ -0,0 +1,61 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "ViewProviderMirrored.h" +#include "TaskMirroredParameters.h" +#include +#include +#include +#include +#include + +using namespace PartDesignGui; + +PROPERTY_SOURCE(PartDesignGui::ViewProviderMirrored,PartDesignGui::ViewProvider) + +bool ViewProviderMirrored::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default ) { + TaskDlgMirroredParameters *mirroredDlg = NULL; + + if (checkDlgOpen(mirroredDlg)) { + // start the edit dialog + if (mirroredDlg) + Gui::Control().showDialog(mirroredDlg); + else + Gui::Control().showDialog(new TaskDlgMirroredParameters(this)); + + return true; + } else { + return false; + } + } + else { + return ViewProviderPart::setEdit(ModNum); + } +} diff --git a/src/Mod/PartDesign/Gui/ViewProviderPatternRectangular.cpp b/src/Mod/PartDesign/Gui/ViewProviderMirrored.h similarity index 58% rename from src/Mod/PartDesign/Gui/ViewProviderPatternRectangular.cpp rename to src/Mod/PartDesign/Gui/ViewProviderMirrored.h index 4929dcaaea..07cf5353bb 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPatternRectangular.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderMirrored.h @@ -1,43 +1,47 @@ -/*************************************************************************** - * Copyright (c) 2011 Juergen Riegel * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ -#include "PreCompiled.h" +#ifndef PARTGUI_ViewProviderMirrored_H +#define PARTGUI_ViewProviderMirrored_H -#ifndef _PreComp_ -#endif +#include "ViewProviderTransformed.h" -#include "ViewProviderPatternRectangular.h" +namespace PartDesignGui { -using namespace PartDesignGui; - -PROPERTY_SOURCE(PartDesignGui::ViewProviderPatternRectangular,PartDesignGui::ViewProvider) - -ViewProviderPatternRectangular::ViewProviderPatternRectangular() +class PartDesignGuiExport ViewProviderMirrored : public ViewProviderTransformed { -} + PROPERTY_HEADER(PartGui::ViewProviderMirrored); +public: + ViewProviderMirrored() + { featureName = std::string("Mirrored"); } -ViewProviderPatternRectangular::~ViewProviderPatternRectangular() -{ -} +protected: + virtual bool setEdit(int ModNum); + +}; +} // namespace PartDesignGui + + +#endif // PARTGUI_ViewProviderMirrored_H diff --git a/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.cpp b/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.cpp new file mode 100644 index 0000000000..462dfc1af0 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.cpp @@ -0,0 +1,92 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "ViewProviderMultiTransform.h" +#include "TaskMultiTransformParameters.h" +#include +#include +#include +#include +#include + +using namespace PartDesignGui; + +PROPERTY_SOURCE(PartDesignGui::ViewProviderMultiTransform,PartDesignGui::ViewProvider) + +bool ViewProviderMultiTransform::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default ) { + TaskDlgMultiTransformParameters *multitransformDlg = NULL; + + if (checkDlgOpen(multitransformDlg)) { + // start the edit dialog + if (multitransformDlg) + Gui::Control().showDialog(multitransformDlg); + else + Gui::Control().showDialog(new TaskDlgMultiTransformParameters(this)); + + return true; + } else { + return false; + } + } + else { + return ViewProviderPart::setEdit(ModNum); + } +} + +std::vector ViewProviderMultiTransform::claimChildren(void) const +{ + std::vector result = ViewProviderTransformed::claimChildren(); + + PartDesign::MultiTransform* pcMultiTransform = static_cast(getObject()); + if (pcMultiTransform == NULL) + return std::vector(); // TODO: Show error? + + std::vector transformFeatures = pcMultiTransform->Transformations.getValues(); + + result.insert(result.end(), transformFeatures.begin(), transformFeatures.end()); + return result; +} + +bool ViewProviderMultiTransform::onDelete(const std::vector &svec) { + // Delete the transformation features + PartDesign::MultiTransform* pcMultiTransform = static_cast(getObject()); + std::vector transformFeatures = pcMultiTransform->Transformations.getValues(); + + // if abort command deleted the object the transformed features must be deleted, too + for (std::vector::const_iterator it = transformFeatures.begin(); it != transformFeatures.end(); ++it) + { + if ((*it) != NULL) + Gui::Command::doCommand( + Gui::Command::Doc,"App.ActiveDocument.removeObject(\"%s\")", (*it)->getNameInDocument()); + } + + // Handle Originals + return ViewProviderTransformed::onDelete(svec); +} diff --git a/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.h b/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.h new file mode 100644 index 0000000000..a0575903ed --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef PARTGUI_ViewProviderMultiTransform_H +#define PARTGUI_ViewProviderMultiTransform_H + +#include "ViewProviderTransformed.h" + +namespace PartDesignGui { + +class PartDesignGuiExport ViewProviderMultiTransform : public ViewProviderTransformed +{ + PROPERTY_HEADER(PartGui::ViewProviderMultiTransform); +public: + ViewProviderMultiTransform() + { featureName = std::string("MultiTransform"); } + + std::vector claimChildren(void) const; + + virtual bool onDelete(const std::vector &); + +protected: + virtual bool setEdit(int ModNum); + +}; + + +} // namespace PartDesignGui + + +#endif // PARTGUI_ViewProviderMultiTransform_H diff --git a/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.cpp b/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.cpp new file mode 100644 index 0000000000..48bc5d7191 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.cpp @@ -0,0 +1,61 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "ViewProviderPolarPattern.h" +#include "TaskPolarPatternParameters.h" +#include +#include +#include +#include +#include + +using namespace PartDesignGui; + +PROPERTY_SOURCE(PartDesignGui::ViewProviderPolarPattern,PartDesignGui::ViewProvider) + +bool ViewProviderPolarPattern::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default ) { + TaskDlgPolarPatternParameters *polarpatternDlg = NULL; + + if (checkDlgOpen(polarpatternDlg)) { + // start the edit dialog + if (polarpatternDlg) + Gui::Control().showDialog(polarpatternDlg); + else + Gui::Control().showDialog(new TaskDlgPolarPatternParameters(this)); + + return true; + } else { + return false; + } + } + else { + return ViewProviderPart::setEdit(ModNum); + } +} diff --git a/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.h b/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.h new file mode 100644 index 0000000000..c19173618d --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef PARTGUI_ViewProviderPolarPattern_H +#define PARTGUI_ViewProviderPolarPattern_H + +#include "ViewProviderTransformed.h" + +namespace PartDesignGui { + +class PartDesignGuiExport ViewProviderPolarPattern : public ViewProviderTransformed +{ + PROPERTY_HEADER(PartGui::ViewProviderPolarPattern); +public: + ViewProviderPolarPattern() + { featureName = std::string("PolarPattern"); } + +protected: + virtual bool setEdit(int ModNum); + +}; + + +} // namespace PartDesignGui + + +#endif // PARTGUI_ViewProviderPolarPattern_H diff --git a/src/Mod/PartDesign/Gui/ViewProviderScaled.cpp b/src/Mod/PartDesign/Gui/ViewProviderScaled.cpp new file mode 100644 index 0000000000..b704f47161 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderScaled.cpp @@ -0,0 +1,61 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "ViewProviderScaled.h" +#include "TaskScaledParameters.h" +#include +#include +#include +#include +#include + +using namespace PartDesignGui; + +PROPERTY_SOURCE(PartDesignGui::ViewProviderScaled,PartDesignGui::ViewProvider) + +bool ViewProviderScaled::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default ) { + TaskDlgScaledParameters *scaledDlg = NULL; + + if (checkDlgOpen(scaledDlg)) { + // start the edit dialog + if (scaledDlg) + Gui::Control().showDialog(scaledDlg); + else + Gui::Control().showDialog(new TaskDlgScaledParameters(this)); + + return true; + } else { + return false; + } + } + else { + return ViewProviderPart::setEdit(ModNum); + } +} diff --git a/src/Mod/PartDesign/Gui/ViewProviderPatternRectangular.h b/src/Mod/PartDesign/Gui/ViewProviderScaled.h similarity index 61% rename from src/Mod/PartDesign/Gui/ViewProviderPatternRectangular.h rename to src/Mod/PartDesign/Gui/ViewProviderScaled.h index f6d8fecd8f..b2649d64b8 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPatternRectangular.h +++ b/src/Mod/PartDesign/Gui/ViewProviderScaled.h @@ -1,43 +1,42 @@ -/*************************************************************************** - * Copyright (c) 2011 Juergen Riegel * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ -#ifndef PARTGUI_ViewProviderPatternRectangular_H -#define PARTGUI_ViewProviderPatternRectangular_H - -#include "ViewProvider.h" +#ifndef PARTGUI_ViewProviderScaled_H +#define PARTGUI_ViewProviderScaled_H +#include "ViewProviderTransformed.h" namespace PartDesignGui { -class PartDesignGuiExport ViewProviderPatternRectangular : public ViewProvider +class PartDesignGuiExport ViewProviderScaled : public ViewProviderTransformed { - PROPERTY_HEADER(PartGui::ViewProviderPatternRectangular); - + PROPERTY_HEADER(PartGui::ViewProviderScaled); public: - /// constructor - ViewProviderPatternRectangular(); - /// destructor - virtual ~ViewProviderPatternRectangular(); + ViewProviderScaled() + { featureName = std::string("Scaled"); } + +protected: + virtual bool setEdit(int ModNum); }; @@ -45,4 +44,4 @@ public: } // namespace PartDesignGui -#endif // PARTGUI_ViewProviderPad_H +#endif // PARTGUI_ViewProviderScaled_H diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp new file mode 100644 index 0000000000..d413a83729 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp @@ -0,0 +1,114 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "ViewProviderTransformed.h" +#include "TaskTransformedParameters.h" +#include +#include +#include +#include +#include + +using namespace PartDesignGui; + +PROPERTY_SOURCE(PartDesignGui::ViewProviderTransformed,PartDesignGui::ViewProvider) + +std::vector ViewProviderTransformed::claimChildren(void)const +{ + PartDesign::Transformed* pcTransformed = static_cast(getObject()); + if (pcTransformed == NULL) + return std::vector(); // TODO: Show error? + + std::vector originals = pcTransformed->Originals.getValues(); + + return originals; +} + +void ViewProviderTransformed::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) +{ + QAction* act; + act = menu->addAction(QObject::tr((std::string("Edit ") + featureName + " feature").c_str()), receiver, member); + act->setData(QVariant((int)ViewProvider::Default)); + PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member); +} + +void ViewProviderTransformed::unsetEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default) { + // when pressing ESC make sure to close the dialog + Gui::Control().closeDialog(); + } + else { + PartGui::ViewProviderPart::unsetEdit(ModNum); + } +} + +bool ViewProviderTransformed::onDelete(const std::vector &) +{ + PartDesign::Transformed* pcTransformed = static_cast(getObject()); + std::vector originals = pcTransformed->Originals.getValues(); + + // if abort command deleted the object the originals are visible again + for (std::vector::const_iterator it = originals.begin(); it != originals.end(); ++it) + { + if (((*it) != NULL) && Gui::Application::Instance->getViewProvider(*it)) + Gui::Application::Instance->getViewProvider(*it)->show(); + } + + return true; +} + +const bool ViewProviderTransformed::checkDlgOpen(TaskDlgTransformedParameters* transformedDlg) { + // When double-clicking on the item for this feature the + // object unsets and sets its edit mode without closing + // the task panel + Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog(); + transformedDlg = qobject_cast(dlg); + + if ((transformedDlg != NULL) && (transformedDlg->getTransformedView() != this)) + transformedDlg = NULL; // another transformed feature left open its task panel + + if ((dlg != NULL) && (transformedDlg == NULL)) { + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().closeDialog(); + else + return false; + } + + // clear the selection (convenience) + Gui::Selection().clearSelection(); + + // Continue (usually in virtual method setEdit()) + return true; +} diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.h b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h new file mode 100644 index 0000000000..4a29865ee4 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Copyright (c)2012 Jan Rheinlaender * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ******************************************************************************/ + + +#ifndef PARTGUI_ViewProviderTransformed_H +#define PARTGUI_ViewProviderTransformed_H + +#include "ViewProvider.h" + +namespace PartDesignGui { + +class TaskDlgTransformedParameters; + +class PartDesignGuiExport ViewProviderTransformed : public ViewProvider +{ + PROPERTY_HEADER(PartGui::ViewProviderTransformed); + +public: + /// constructor + ViewProviderTransformed() + : featureName("undefined") {} + /// destructor + virtual ~ViewProviderTransformed() + {} + + /// grouping handling + std::vector claimChildren(void) const; + void setupContextMenu(QMenu*, QObject*, const char*); + + virtual bool onDelete(const std::vector &); + + // The feature name of the subclass + std::string featureName; + +protected: + virtual bool setEdit(int ModNum) { return false; } + virtual void unsetEdit(int ModNum); + + const bool checkDlgOpen(TaskDlgTransformedParameters* transformedDlg); +}; + + +} // namespace PartDesignGui + + +#endif // PARTGUI_ViewProviderTransformed_H diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp index b4bbff345b..bbb6494208 100644 --- a/src/Mod/PartDesign/Gui/Workbench.cpp +++ b/src/Mod/PartDesign/Gui/Workbench.cpp @@ -95,6 +95,20 @@ void Workbench::activated() "Part_Box" )); + const char* Transformed[] = { + "PartDesign_Mirrored", + "PartDesign_LinearPattern", + "PartDesign_PolarPattern", +// "PartDesign_Scaled", + "PartDesign_MultiTransform", + 0}; + Watcher.push_back(new Gui::TaskView::TaskWatcherCommands( + "SELECT Part::Feature", + Transformed, + "Transformation tools", + "PartDesign_Mirrored" + )); + const char* Empty[] = { "Sketcher_NewSketch", "Part_Box", @@ -172,7 +186,12 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "PartDesign_Revolution" << "PartDesign_Groove" << "PartDesign_Fillet" - << "PartDesign_Chamfer"; + << "PartDesign_Chamfer" + << "PartDesign_Mirrored" + << "PartDesign_LinearPattern" + << "PartDesign_PolarPattern" +// << "PartDesign_Scaled" + << "PartDesign_MultiTransform"; return root; } @@ -190,7 +209,12 @@ Gui::ToolBarItem* Workbench::setupToolBars() const << "PartDesign_Revolution" << "PartDesign_Groove" << "PartDesign_Fillet" - << "PartDesign_Chamfer"; + << "PartDesign_Chamfer" + << "PartDesign_Mirrored" + << "PartDesign_LinearPattern" + << "PartDesign_PolarPattern" +// << "PartDesign_Scaled" + << "PartDesign_MultiTransform"; part = new Gui::ToolBarItem(root); part->setCommand("Sketcher geometries");