/*************************************************************************** * Copyright (c) 2013 Jan Rheinländer * * * * 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 # include # include #endif #include "ViewProviderFemConstraint.h" #include "TaskFemConstraint.h" #include "Gui/Control.h" #include "Gui/MainWindow.h" #include "Gui/Command.h" #include "Gui/Application.h" #include "Gui/Document.h" #include using namespace FemGui; PROPERTY_SOURCE(FemGui::ViewProviderFemConstraint, Gui::ViewProviderDocumentObject) ViewProviderFemConstraint::ViewProviderFemConstraint() { ADD_PROPERTY(TextColor,(0.0f,0.0f,0.0f)); ADD_PROPERTY(FaceColor,(1.0f,0.0f,0.2f)); ADD_PROPERTY(ShapeColor,(1.0f,0.0f,0.2f)); ADD_PROPERTY(FontSize,(18)); ADD_PROPERTY(DistFactor,(1.0)); ADD_PROPERTY(Mirror,(false)); pFont = new SoFontStyle(); pFont->ref(); pLabel = new SoText2(); pLabel->ref(); pTextColor = new SoBaseColor(); pTextColor->ref(); pMaterials = new SoBaseColor(); pMaterials->ref(); pMaterials->rgb.setValue(1.0f, 0.0f, 0.2f); pShapeSep = new SoSeparator(); pShapeSep->ref(); TextColor.touch(); FontSize.touch(); FaceColor.touch(); wizardWidget = NULL; wizardSubLayout = NULL; constraintDialog = NULL; } ViewProviderFemConstraint::~ViewProviderFemConstraint() { pFont->unref(); pLabel->unref(); pTextColor->unref(); pMaterials->unref(); pShapeSep->unref(); } void ViewProviderFemConstraint::attach(App::DocumentObject* pcObject) { ViewProviderDocumentObject::attach(pcObject); SoPickStyle* ps = new SoPickStyle(); ps->style = SoPickStyle::UNPICKABLE; SoSeparator* sep = new SoSeparator(); SoShapeHints* hints = new SoShapeHints(); hints->shapeType.setValue(SoShapeHints::UNKNOWN_SHAPE_TYPE); hints->vertexOrdering.setValue(SoShapeHints::COUNTERCLOCKWISE); sep->addChild(ps); sep->addChild(hints); sep->addChild(pMaterials); sep->addChild(pShapeSep); addDisplayMaskMode(sep, "Base"); } std::vector ViewProviderFemConstraint::getDisplayModes(void) const { // add modes std::vector StrList; StrList.push_back("Base"); return StrList; } void ViewProviderFemConstraint::setDisplayMode(const char* ModeName) { if (strcmp(ModeName, "Base") == 0) setDisplayMaskMode("Base"); ViewProviderDocumentObject::setDisplayMode(ModeName); } std::vector ViewProviderFemConstraint::claimChildren(void)const { return std::vector(); } void ViewProviderFemConstraint::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) { QAction* act; act = menu->addAction(QObject::tr("Edit constraint"), receiver, member); act->setData(QVariant((int)ViewProvider::Default)); ViewProviderDocumentObject::setupContextMenu(menu, receiver, member); } void ViewProviderFemConstraint::onChanged(const App::Property* prop) { if (prop == &Mirror || prop == &DistFactor) { updateData(prop); } else if (prop == &TextColor) { const App::Color& c = TextColor.getValue(); pTextColor->rgb.setValue(c.r,c.g,c.b); } else if (prop == &FaceColor) { const App::Color& c = FaceColor.getValue(); pMaterials->rgb.setValue(c.r,c.g,c.b); } else if (prop == &FontSize) { pFont->size = FontSize.getValue(); } else { ViewProviderDocumentObject::onChanged(prop); } } bool ViewProviderFemConstraint::setEdit(int ModNum) { return Gui::ViewProviderGeometryObject::setEdit(ModNum); } void ViewProviderFemConstraint::unsetEdit(int ModNum) { if ((wizardWidget != NULL) && (wizardSubLayout != NULL) && (constraintDialog != NULL)) { wizardWidget = NULL; wizardSubLayout = NULL; delete constraintDialog; constraintDialog = NULL; // Notify the Shaft Wizard that we have finished editing // See WizardShaft.py on why we do it this way Gui::Command::runCommand(Gui::Command::Doc, "Gui.runCommand('PartDesign_WizardShaftCallBack')"); } else { if (ModNum == ViewProvider::Default) { // when pressing ESC make sure to close the dialog Gui::Control().closeDialog(); } else { ViewProviderDocumentObject::unsetEdit(ModNum); } } } /* // Create a local coordinate system with the z-axis given in dir void getLocalCoordinateSystem(const SbVec3f& z, SbVec3f& y, SbVec3f& x) { // Find the y axis in an arbitrary direction, normal to z // Conditions: // y1 * z1 + y2 * z2 + y3 * z3 = |y| |z| cos(90°) = 0 // |y| = sqrt(y1^2 + y2^2 + y3^2) = 1 float z1, z2, z3; z.getValue(z1, z2, z3); float y1, y2, y3; if (fabs(z1) > Precision::Confusion()) { // Choose: y3 = 0 // Solution: // y1 * z1 + y2 * z2 = 0 // y1 = - z2/z1 y2 // sqrt(z2^2/z1^2 y2^2 + y2^2) = 1 // y2^2 ( 1 + z2^2/z1^2)) = +-1 -> choose +1 otherwise no solution // y2 = +- sqrt(1 / (1 + z2^2/z1^2)) y3 = 0; y2 = sqrt(1 / (1 + z2*z2 / (z1*z1))); y1 = -z2/z1 * y2; // Note: result might be (0, 1, 0) } else if (fabs(z2) > Precision::Confusion()) { // Given: z1 = 0 // Choose: y1 = 0 // Solution: // y2 * z2 + y3 * z3 = 0 // y2 = - z3/z2 y3 // sqrt(z3^2/z2^2 y3^3 + y3^2) = 1 // y3^2 (1 + z3^2/z2^2)) = +1 // y3 = +- sqrt(1 / (1 + z3^2/z2^2)) y1 = 0; y3 = sqrt(1 / (1 + z3*z3 / (z2*z2))); y2 = -z3/z2 * y3; // Note: result might be (0, 0, 1) } else if (fabs(z3) > Precision::Confusion()) { // Given: z1 = z2 = 0 // Choose the remaining possible axis y1 = 1; y2 = 0; y3 = 0; } y = SbVec3f(y1, y2, y3); x = y.cross(z); } */ #define PLACEMENT_CHILDREN 2 void ViewProviderFemConstraint::createPlacement(SoSeparator* sep, const SbVec3f &base, const SbRotation &r) { SoTranslation* trans = new SoTranslation(); trans->translation.setValue(base); sep->addChild(trans); SoRotation* rot = new SoRotation(); rot->rotation.setValue(r); sep->addChild(rot); } void ViewProviderFemConstraint::updatePlacement(const SoSeparator* sep, const int idx, const SbVec3f &base, const SbRotation &r) { SoTranslation* trans = static_cast(sep->getChild(idx)); trans->translation.setValue(base); SoRotation* rot = static_cast(sep->getChild(idx+1)); rot->rotation.setValue(r); } #define CONE_CHILDREN 2 void ViewProviderFemConstraint::createCone(SoSeparator* sep, const double height, const double radius) { // Adjust cone so that the tip is on base SoTranslation* trans = new SoTranslation(); trans->translation.setValue(SbVec3f(0,-height/2,0)); sep->addChild(trans); SoCone* cone = new SoCone(); cone->height.setValue(height); cone->bottomRadius.setValue(radius); sep->addChild(cone); } SoSeparator* ViewProviderFemConstraint::createCone(const double height, const double radius) { // Create a new cone node SoSeparator* sep = new SoSeparator(); createCone(sep, height, radius); return sep; } void ViewProviderFemConstraint::updateCone(const SoNode* node, const int idx, const double height, const double radius) { const SoSeparator* sep = static_cast(node); SoTranslation* trans = static_cast(sep->getChild(idx)); trans->translation.setValue(SbVec3f(0,-height/2,0)); SoCone* cone = static_cast(sep->getChild(idx+1)); cone->height.setValue(height); cone->bottomRadius.setValue(radius); } #define CYLINDER_CHILDREN 1 void ViewProviderFemConstraint::createCylinder(SoSeparator* sep, const double height, const double radius) { SoCylinder* cyl = new SoCylinder(); cyl->height.setValue(height); cyl->radius.setValue(radius); sep->addChild(cyl); } SoSeparator* ViewProviderFemConstraint::createCylinder(const double height, const double radius) { // Create a new cylinder node SoSeparator* sep = new SoSeparator(); createCylinder(sep, height, radius); return sep; } void ViewProviderFemConstraint::updateCylinder(const SoNode* node, const int idx, const double height, const double radius) { const SoSeparator* sep = static_cast(node); SoCylinder* cyl = static_cast(sep->getChild(idx)); cyl->height.setValue(height); cyl->radius.setValue(radius); } #define CUBE_CHILDREN 1 void ViewProviderFemConstraint::createCube(SoSeparator* sep, const double width, const double length, const double height) { SoCube* cube = new SoCube(); cube->width.setValue(width); cube->depth.setValue(length); cube->height.setValue(height); sep->addChild(cube); } SoSeparator* ViewProviderFemConstraint::createCube(const double width, const double length, const double height) { SoSeparator* sep = new SoSeparator(); createCube(sep, width, length, height); return sep; } void ViewProviderFemConstraint::updateCube(const SoNode* node, const int idx, const double width, const double length, const double height) { const SoSeparator* sep = static_cast(node); SoCube* cube = static_cast(sep->getChild(idx)); cube->width.setValue(width); cube->depth.setValue(length); cube->height.setValue(height); } #define ARROW_CHILDREN (CONE_CHILDREN + PLACEMENT_CHILDREN + CYLINDER_CHILDREN) void ViewProviderFemConstraint::createArrow(SoSeparator* sep, const double length, const double radius) { createCone(sep, radius, radius/2); createPlacement(sep, SbVec3f(0, -radius/2-(length-radius)/2, 0), SbRotation()); createCylinder(sep, length-radius, radius/5); } SoSeparator* ViewProviderFemConstraint::createArrow(const double length, const double radius) { SoSeparator* sep = new SoSeparator(); createArrow(sep, length, radius); return sep; } void ViewProviderFemConstraint::updateArrow(const SoNode* node, const int idx, const double length, const double radius) { const SoSeparator* sep = static_cast(node); updateCone(sep, idx, radius, radius/2); updatePlacement(sep, idx+CONE_CHILDREN, SbVec3f(0, -radius/2-(length-radius)/2, 0), SbRotation()); updateCylinder(sep, idx+CONE_CHILDREN+PLACEMENT_CHILDREN, length-radius, radius/5); } #define FIXED_CHILDREN (CONE_CHILDREN + PLACEMENT_CHILDREN + CUBE_CHILDREN) void ViewProviderFemConstraint::createFixed(SoSeparator* sep, const double height, const double width, const bool gap) { createCone(sep, height-width/4, height-width/4); createPlacement(sep, SbVec3f(0, -(height-width/4)/2-width/8 - (gap ? 1.0 : 0.1) * width/8, 0), SbRotation()); createCube(sep, width, width, width/4); } SoSeparator* ViewProviderFemConstraint::createFixed(const double height, const double width, const bool gap) { SoSeparator* sep = new SoSeparator(); createFixed(sep, height, width, gap); return sep; } void ViewProviderFemConstraint::updateFixed(const SoNode* node, const int idx, const double height, const double width, const bool gap) { const SoSeparator* sep = static_cast(node); updateCone(sep, idx, height-width/4, height-width/4); updatePlacement(sep, idx+CONE_CHILDREN, SbVec3f(0, -(height-width/4)/2-width/8 - (gap ? 1.0 : 0.0) * width/8, 0), SbRotation()); updateCube(sep, idx+CONE_CHILDREN+PLACEMENT_CHILDREN, width, width, width/4); } QObject* ViewProviderFemConstraint::findChildByName(const QObject* parent, const QString& name) { for (QObjectList::const_iterator o = parent->children().begin(); o != parent->children().end(); o++) { if ((*o)->objectName() == name) return *o; if (!(*o)->children().empty()) { QObject* result = findChildByName(*o, name); if (result != NULL) return result; } } return NULL; } void ViewProviderFemConstraint::checkForWizard() { wizardWidget= NULL; wizardSubLayout = NULL; Gui::MainWindow* mw = Gui::getMainWindow(); if (mw == NULL) return; QDockWidget* dw = mw->findChild(QObject::tr("Combo View")); if (dw == NULL) return; QWidget* cw = dw->findChild(QObject::tr("Combo View")); if (cw == NULL) return; QTabWidget* tw = cw->findChild(QObject::tr("combiTab")); if (tw == NULL) return; QStackedWidget* sw = tw->findChild(QObject::tr("qt_tabwidget_stackedwidget")); if (sw == NULL) return; QScrollArea* sa = sw->findChild(); if (sa== NULL) return; QWidget* wd = sa->widget(); // This is the reason why we cannot use findChildByName() right away!!! if (wd == NULL) return; QObject* wiz = findChildByName(wd, QObject::tr("ShaftWizard")); // FIXME: Actually, we don't want to translate this... if (wiz != NULL) { wizardWidget = static_cast(wiz); wizardSubLayout = wiz->findChild(QObject::tr("ShaftWizardLayout")); } }