From c4720e56c115ea5d7e5c456bd46a1bfc0c39b77f Mon Sep 17 00:00:00 2001 From: Paddle Date: Fri, 3 Nov 2023 18:54:27 +0100 Subject: [PATCH 1/4] Translate DSH : A replacement for rectangular array. --- src/Mod/Sketcher/Gui/CMakeLists.txt | 1 + src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 35 + .../Sketcher/Gui/DrawSketchHandlerTranslate.h | 709 ++++++++++++++++++ src/Mod/Sketcher/Gui/Resources/Sketcher.qrc | 2 + .../Sketcher_Pointer_Create_Translate.svg | 91 +++ .../icons/tools/Sketcher_Translate.svg | 585 +++++++++++++++ src/Mod/Sketcher/Gui/Workbench.cpp | 2 + 7 files changed, 1425 insertions(+) create mode 100644 src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_Create_Translate.svg create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/tools/Sketcher_Translate.svg diff --git a/src/Mod/Sketcher/Gui/CMakeLists.txt b/src/Mod/Sketcher/Gui/CMakeLists.txt index f2761d0d50..1b1c42cd93 100644 --- a/src/Mod/Sketcher/Gui/CMakeLists.txt +++ b/src/Mod/Sketcher/Gui/CMakeLists.txt @@ -70,6 +70,7 @@ SET(SketcherGui_SRCS DrawSketchHandlerBSplineByInterpolation.h DrawSketchHandlerPoint.h DrawSketchHandlerFillet.h + DrawSketchHandlerTranslate.h DrawSketchHandlerTrimming.h DrawSketchHandlerExtend.h DrawSketchHandlerSplitting.h diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index 87ef220171..b3d56aa851 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -54,6 +54,7 @@ #include "Utils.h" #include "ViewProviderSketch.h" +#include "DrawSketchHandlerTranslate.h" #include "DrawSketchHandlerOffset.h" #include "DrawSketchHandlerRotate.h" #include "DrawSketchHandlerScale.h" @@ -2622,6 +2623,39 @@ bool CmdSketcherScale::isActive() return isCommandActive(getActiveGuiDocument(), true); } +// Translate / rectangular pattern tool ======================================================= + +DEF_STD_CMD_A(CmdSketcherTranslate) + +CmdSketcherTranslate::CmdSketcherTranslate() + : Command("Sketcher_Translate") +{ + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("Array transform"); + sToolTipText = QT_TR_NOOP("Translate selected geometries. Enable creation of i * j copies."); + sWhatsThis = "Sketcher_Translate"; + sStatusTip = sToolTipText; + sPixmap = "Sketcher_Translate"; + sAccel = "W"; + eType = ForEdit; +} + +void CmdSketcherTranslate::activated(int iMsg) +{ + Q_UNUSED(iMsg); + std::vector listOfGeoIds = getListOfSelectedGeoIds(true); + + if (!listOfGeoIds.empty()) { + ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerTranslate(listOfGeoIds)); + } + getSelection().clearSelection(); +} + +bool CmdSketcherTranslate::isActive() +{ + return isCommandActive(getActiveGuiDocument(), true); +} void CreateSketcherCommandsConstraintAccel() { @@ -2638,6 +2672,7 @@ void CreateSketcherCommandsConstraintAccel() rcCmdMgr.addCommand(new CmdSketcherSelectElementsAssociatedWithConstraints()); rcCmdMgr.addCommand(new CmdSketcherSelectElementsWithDoFs()); rcCmdMgr.addCommand(new CmdSketcherRestoreInternalAlignmentGeometry()); + rcCmdMgr.addCommand(new CmdSketcherTranslate()); rcCmdMgr.addCommand(new CmdSketcherOffset()); rcCmdMgr.addCommand(new CmdSketcherRotate()); rcCmdMgr.addCommand(new CmdSketcherScale()); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h new file mode 100644 index 0000000000..6351fc9f5d --- /dev/null +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h @@ -0,0 +1,709 @@ +/*************************************************************************** + * Copyright (c) 2022 Boyer Pierre-Louis * + * * + * 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 SKETCHERGUI_DrawSketchHandlerTranslate_H +#define SKETCHERGUI_DrawSketchHandlerTranslate_H + +#include + +#include +#include +#include +#include + +#include +#include + +#include "DrawSketchDefaultWidgetController.h" +#include "DrawSketchControllableHandler.h" + +#include "GeometryCreationMode.h" +#include "Utils.h" + + +using namespace Sketcher; + +namespace SketcherGui +{ + +class DrawSketchHandlerTranslate; + +using DSHTranslateController = + DrawSketchDefaultWidgetController, + /*WidgetParametersT =*/WidgetParameters<2>, + /*WidgetCheckboxesT =*/WidgetCheckboxes<1>, + /*WidgetComboboxesT =*/WidgetComboboxes<0>>; + +using DSHTranslateControllerBase = DSHTranslateController::ControllerBase; + +using DrawSketchHandlerTranslateBase = DrawSketchControllableHandler; + +class DrawSketchHandlerTranslate: public DrawSketchHandlerTranslateBase +{ + friend DSHTranslateController; + friend DSHTranslateControllerBase; + +public: + explicit DrawSketchHandlerTranslate(std::vector listOfGeoIds) + : listOfGeoIds(listOfGeoIds) + , deleteOriginal(false) + , cloneConstraints(false) + , numberOfCopies(0) + , secondNumberOfCopies(1) + {} + + DrawSketchHandlerTranslate(const DrawSketchHandlerTranslate&) = delete; + DrawSketchHandlerTranslate(DrawSketchHandlerTranslate&&) = delete; + DrawSketchHandlerTranslate& operator=(const DrawSketchHandlerTranslate&) = delete; + DrawSketchHandlerTranslate& operator=(DrawSketchHandlerTranslate&&) = delete; + + ~DrawSketchHandlerTranslate() override = default; + +private: + void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override + { + switch (state()) { + case SelectMode::SeekFirst: { + referencePoint = onSketchPos; + } break; + case SelectMode::SeekSecond: { + firstTranslationPoint = onSketchPos; + + firstTranslationVector = toVector3d(firstTranslationPoint - referencePoint); + + CreateAndDrawShapeGeometry(); + } break; + case SelectMode::SeekThird: { + secondTranslationPoint = onSketchPos; + + secondTranslationVector = toVector3d(secondTranslationPoint - referencePoint); + + CreateAndDrawShapeGeometry(); + } break; + default: + break; + } + } + + void executeCommands() override + { + try { + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Translate geometries")); + + createShape(false); + + commandAddShapeGeometryAndConstraints(); + + if (deleteOriginal) { + deleteOriginalGeos(); + } + + Gui::Command::commitCommand(); + } + catch (const Base::Exception& e) { + e.ReportException(); + Gui::NotifyError(sketchgui, + QT_TRANSLATE_NOOP("Notifications", "Error"), + QT_TRANSLATE_NOOP("Notifications", "Failed to translate")); + + Gui::Command::abortCommand(); + THROWM(Base::RuntimeError, + QT_TRANSLATE_NOOP( + "Notifications", + "Tool execution aborted") "\n") // This prevents constraints from being + // applied on non existing geometry + } + } + + void createAutoConstraints() override + { + // none + } + + std::string getToolName() const override + { + return "DSH_Translate"; + } + + QString getCrosshairCursorSVGName() const override + { + return QString::fromLatin1("Sketcher_Pointer_Create_Translate"); + } + + std::unique_ptr createWidget() const override + { + return std::make_unique(); + } + + bool isWidgetVisible() const override + { + return true; + }; + + QPixmap getToolIcon() const override + { + return Gui::BitmapFactory().pixmap("Sketcher_Translate"); + } + + QString getToolWidgetText() const override + { + return QString(QObject::tr("Translate parameters")); + } + + void onButtonPressed(Base::Vector2d onSketchPos) override + { + this->updateDataAndDrawToPosition(onSketchPos); + + if (state() == SelectMode::SeekSecond && secondNumberOfCopies == 1) { + setState(SelectMode::End); + } + else { + this->moveToNextMode(); + } + } + + void activated() override + { + DrawSketchDefaultHandler::activated(); + continuousMode = false; + } + + bool canGoToNextMode() override + { + if (state() == SelectMode::SeekSecond + && firstTranslationVector.Length() < Precision::Confusion()) { + // Prevent validation of null translation. + return false; + } + if (state() == SelectMode::SeekThird + && secondTranslationVector.Length() < Precision::Confusion() + && secondNumberOfCopies > 1) { + return false; + } + return true; + } + + void angleSnappingControl() override + { + if (state() == SelectMode::SeekSecond || state() == SelectMode::SeekThird) { + setAngleSnapping(true, referencePoint); + } + + else { + setAngleSnapping(false); + } + } + +private: + std::vector listOfGeoIds; + Base::Vector2d referencePoint, firstTranslationPoint, secondTranslationPoint; + Base::Vector3d firstTranslationVector, secondTranslationVector; + + bool deleteOriginal, cloneConstraints; + int numberOfCopies, secondNumberOfCopies; + + void deleteOriginalGeos() + { + std::stringstream stream; + for (size_t j = 0; j < listOfGeoIds.size() - 1; j++) { + stream << listOfGeoIds[j] << ","; + } + stream << listOfGeoIds[listOfGeoIds.size() - 1]; + try { + Gui::cmdAppObjectArgs(sketchgui->getObject(), + "delGeometries([%s])", + stream.str().c_str()); + } + catch (const Base::Exception& e) { + Base::Console().Error("%s\n", e.what()); + } + } + + void createShape(bool onlyeditoutline) override + { + Sketcher::SketchObject* Obj = sketchgui->getSketchObject(); + + ShapeGeometry.clear(); + + int numberOfCopiesToMake = numberOfCopies; + if (numberOfCopies == 0) { + numberOfCopiesToMake = 1; + deleteOriginal = 1; + } + else { + deleteOriginal = 0; + } + + for (int k = 0; k < secondNumberOfCopies; k++) { + for (int i = 0; i <= numberOfCopiesToMake; i++) { + if ((k == 0 && i == 0)) { + continue; + } + Base::Vector3d vec = firstTranslationVector * i + secondTranslationVector * k; + + for (auto& geoId : listOfGeoIds) { + const Part::Geometry* pGeo = Obj->getGeometry(geoId); + auto geoUniquePtr = std::unique_ptr(pGeo->copy()); + Part::Geometry* geo = geoUniquePtr.get(); + + if (isCircle(*geo)) { + Part::GeomCircle* circle = static_cast(geo); // NOLINT + circle->setCenter(circle->getCenter() + vec); + } + else if (isArcOfCircle(*geo)) { + Part::GeomArcOfCircle* arc = + static_cast(geo); // NOLINT + arc->setCenter(arc->getCenter() + vec); + } + else if (isEllipse(*geo)) { + Part::GeomEllipse* ellipse = + static_cast(geo); // NOLINT + ellipse->setCenter(ellipse->getCenter() + vec); + } + else if (isArcOfEllipse(*geo)) { + Part::GeomArcOfEllipse* aoe = + static_cast(geo); // NOLINT + aoe->setCenter(aoe->getCenter() + vec); + } + else if (isArcOfHyperbola(*geo)) { + Part::GeomArcOfHyperbola* aoh = + static_cast(geo); // NOLINT + aoh->setCenter(aoh->getCenter() + vec); + } + else if (isArcOfParabola(*geo)) { + Part::GeomArcOfParabola* aop = + static_cast(geo); // NOLINT + aop->setCenter(aop->getCenter() + vec); + } + else if (isLineSegment(*geo)) { + auto* line = static_cast(geo); // NOLINT + line->setPoints(line->getStartPoint() + vec, line->getEndPoint() + vec); + } + else if (isBSplineCurve(*geo)) { + auto* bSpline = static_cast(geo); // NOLINT + std::vector poles = bSpline->getPoles(); + for (size_t p = 0; p < poles.size(); p++) { + poles[p] = poles[p] + vec; + } + bSpline->setPoles(poles); + } + else if (isPoint(*geo)) { + auto* point = static_cast(geo); // NOLINT + point->setPoint(point->getPoint() + vec); + } + + ShapeGeometry.emplace_back(std::move(geoUniquePtr)); + } + } + } + + if (onlyeditoutline) { + // Add the lines to show angle + if (firstTranslationVector.Length() > Precision::Confusion()) { + addLineToShapeGeometry(toVector3d(referencePoint), + toVector3d(firstTranslationPoint), + true); + } + + if (secondTranslationVector.Length() > Precision::Confusion()) { + addLineToShapeGeometry(toVector3d(referencePoint), + toVector3d(secondTranslationPoint), + true); + } + } + else { + int firstCurveCreated = getHighestCurveIndex() + 1; + int size = static_cast(listOfGeoIds.size()); + + const std::vector& vals = Obj->Constraints.getValues(); + // avoid applying equal several times if cloning distanceX and distanceY of the + // same part. + std::vector geoIdsWhoAlreadyHasEqual = {}; + + for (auto& cstr : vals) { + int firstIndex = indexOfGeoId(listOfGeoIds, cstr->First); + int secondIndex = indexOfGeoId(listOfGeoIds, cstr->Second); + int thirdIndex = indexOfGeoId(listOfGeoIds, cstr->Third); + + for (int k = 0; k < secondNumberOfCopies; k++) { + for (int i = 0; i <= numberOfCopiesToMake; i++) { + if (k == 0 && i == 0) { + continue; + } + + int firstIndexi = firstCurveCreated + firstIndex + size * (i - 1) + + size * (numberOfCopiesToMake + 1) * k; + int secondIndexi = firstCurveCreated + secondIndex + size * (i - 1) + + size * (numberOfCopiesToMake + 1) * k; + int thirdIndexi = firstCurveCreated + thirdIndex + size * (i - 1) + + size * (numberOfCopiesToMake + 1) * k; + + auto newConstr = std::unique_ptr(cstr->copy()); + newConstr->First = firstIndexi; + + if ((cstr->Type == Symmetric || cstr->Type == Tangent + || cstr->Type == Perpendicular || cstr->Type == Angle) + && firstIndex >= 0 && secondIndex >= 0 && thirdIndex >= 0) { + newConstr->Second = secondIndexi; + newConstr->Third = thirdIndexi; + } + else if ((cstr->Type == Coincident || cstr->Type == Tangent + || cstr->Type == Symmetric || cstr->Type == Perpendicular + || cstr->Type == Parallel || cstr->Type == Equal + || cstr->Type == Angle || cstr->Type == PointOnObject + || cstr->Type == InternalAlignment) + && firstIndex >= 0 && secondIndex >= 0 + && thirdIndex == GeoEnum::GeoUndef) { + newConstr->Second = secondIndexi; + } + else if ((cstr->Type == Radius || cstr->Type == Diameter + || cstr->Type == Weight) + && firstIndex >= 0) { + if (deleteOriginal || !cloneConstraints) { + newConstr->setValue(cstr->getValue()); + } + else { + newConstr->Type = Equal; + newConstr->First = cstr->First; + newConstr->Second = firstIndexi; + } + } + else if ((cstr->Type == Distance || cstr->Type == DistanceX + || cstr->Type == DistanceY) + && firstIndex >= 0 && secondIndex >= 0) { + if (!deleteOriginal && cloneConstraints + && cstr->First == cstr->Second) { // only line distances + if (indexOfGeoId(geoIdsWhoAlreadyHasEqual, secondIndexi) != -1) { + continue; + } + newConstr->Type = Equal; + newConstr->First = cstr->First; + newConstr->Second = secondIndexi; + geoIdsWhoAlreadyHasEqual.push_back(secondIndexi); + } + else { + newConstr->Second = secondIndexi; + } + } + else if ((cstr->Type == Block) && firstIndex >= 0) { + newConstr->First = firstIndexi; + } + else { + continue; + } + + ShapeConstraints.push_back(std::move(newConstr)); + } + } + } + } + } +}; + +template<> +auto DSHTranslateControllerBase::getState(int labelindex) const +{ + switch (labelindex) { + case OnViewParameter::First: + case OnViewParameter::Second: + return SelectMode::SeekFirst; + break; + case OnViewParameter::Third: + case OnViewParameter::Fourth: + return SelectMode::SeekSecond; + break; + case OnViewParameter::Fifth: + case OnViewParameter::Sixth: + return SelectMode::SeekThird; + break; + default: + THROWM(Base::ValueError, "OnViewParameter index without an associated machine state") + } +} + +template<> +void DSHTranslateController::firstKeyShortcut() +{ + auto value = toolWidget->getParameter(WParameter::First); + toolWidget->setParameterWithoutPassingFocus(OnViewParameter::First, value + 1); +} + +template<> +void DSHTranslateController::secondKeyShortcut() +{ + auto value = toolWidget->getParameter(WParameter::First); + if (value > 0.0) { + toolWidget->setParameterWithoutPassingFocus(OnViewParameter::First, value - 1); + } +} + +template<> +void DSHTranslateController::configureToolWidget() +{ + if (!init) { // Code to be executed only upon initialisation + toolWidget->setCheckboxLabel( + WCheckbox::FirstBox, + QApplication::translate("TaskSketcherTool_c1_translate", "Clone constraints")); + toolWidget->setCheckboxToolTip( + WCheckbox::FirstBox, + QApplication::translate( + "TaskSketcherTool_c1_translate", + "This concerns the datum constraints like distances. If you activate Clone, " + "then the tool will copy the datum. Else it will try to replace them with " + "equalities between the initial geometries and the new copies.")); + } + + onViewParameters[OnViewParameter::First]->setLabelType(Gui::SoDatumLabel::DISTANCEX); + onViewParameters[OnViewParameter::Second]->setLabelType(Gui::SoDatumLabel::DISTANCEY); + onViewParameters[OnViewParameter::Third]->setLabelType( + Gui::SoDatumLabel::DISTANCE, + Gui::EditableDatumLabel::Function::Dimensioning); + onViewParameters[OnViewParameter::Fourth]->setLabelType( + Gui::SoDatumLabel::ANGLE, + Gui::EditableDatumLabel::Function::Dimensioning); + + onViewParameters[OnViewParameter::Fifth]->setLabelType( + Gui::SoDatumLabel::DISTANCE, + Gui::EditableDatumLabel::Function::Dimensioning); + onViewParameters[OnViewParameter::Sixth]->setLabelType( + Gui::SoDatumLabel::ANGLE, + Gui::EditableDatumLabel::Function::Dimensioning); + + toolWidget->setParameterLabel( + WParameter::First, + QApplication::translate("TaskSketcherTool_p3_translate", "Copies (+'U'/-'J')")); + toolWidget->setParameterLabel(WParameter::Second, + QApplication::translate("TaskSketcherTool_p5_translate", "Rows")); + + toolWidget->setParameter(OnViewParameter::First, 0.0); + toolWidget->setParameter(OnViewParameter::Second, 1.0); + toolWidget->configureParameterUnit(OnViewParameter::First, Base::Unit()); + toolWidget->configureParameterUnit(OnViewParameter::Second, Base::Unit()); + toolWidget->configureParameterMin(OnViewParameter::First, 0.0); // NOLINT + toolWidget->configureParameterMin(OnViewParameter::Second, 0.0); // NOLINT + toolWidget->configureParameterMax(OnViewParameter::First, 9999.0); // NOLINT + toolWidget->configureParameterMax(OnViewParameter::Second, 9999.0); // NOLINT + toolWidget->configureParameterDecimals(OnViewParameter::First, 0); + toolWidget->configureParameterDecimals(OnViewParameter::Second, 0); +} + +template<> +void DSHTranslateController::adaptDrawingToParameterChange(int parameterindex, double value) +{ + switch (parameterindex) { + case WParameter::First: + handler->numberOfCopies = floor(abs(value)); + break; + case WParameter::Second: + handler->secondNumberOfCopies = floor(abs(value)); + break; + } +} + +template<> +void DSHTranslateController::adaptDrawingToCheckboxChange(int checkboxindex, bool value) +{ + switch (checkboxindex) { + case WCheckbox::FirstBox: { + handler->cloneConstraints = value; + } break; + } +} + +template<> +void DSHTranslateControllerBase::doEnforceControlParameters(Base::Vector2d& onSketchPos) +{ + switch (handler->state()) { + case SelectMode::SeekFirst: { + if (onViewParameters[OnViewParameter::First]->isSet) { + onSketchPos.x = onViewParameters[OnViewParameter::First]->getValue(); + } + + if (onViewParameters[OnViewParameter::Second]->isSet) { + onSketchPos.y = onViewParameters[OnViewParameter::Second]->getValue(); + } + } break; + case SelectMode::SeekSecond: { + Base::Vector2d dir = onSketchPos - handler->referencePoint; + if (dir.Length() < Precision::Confusion()) { + dir.x = 1.0; // if direction null, default to (1,0) + } + double length = dir.Length(); + + if (onViewParameters[OnViewParameter::Third]->isSet) { + length = onViewParameters[OnViewParameter::Third]->getValue(); + if (length < Precision::Confusion()) { + unsetOnViewParameter(onViewParameters[OnViewParameter::Third].get()); + return; + } + + onSketchPos = handler->referencePoint + length * dir.Normalize(); + } + + if (onViewParameters[OnViewParameter::Fourth]->isSet) { + double angle = onViewParameters[OnViewParameter::Fourth]->getValue() * M_PI / 180; + onSketchPos.x = handler->referencePoint.x + cos(angle) * length; + onSketchPos.y = handler->referencePoint.y + sin(angle) * length; + } + } break; + case SelectMode::SeekThird: { + Base::Vector2d dir = onSketchPos - handler->referencePoint; + if (dir.Length() < Precision::Confusion()) { + dir.x = 1.0; // if direction null, default to (1,0) + } + double length = dir.Length(); + + if (onViewParameters[OnViewParameter::Fifth]->isSet) { + length = onViewParameters[OnViewParameter::Fifth]->getValue(); + if (length < Precision::Confusion()) { + unsetOnViewParameter(onViewParameters[OnViewParameter::Fifth].get()); + return; + } + + onSketchPos = handler->referencePoint + length * dir.Normalize(); + } + + if (onViewParameters[OnViewParameter::Sixth]->isSet) { + double angle = onViewParameters[OnViewParameter::Sixth]->getValue() * M_PI / 180; + onSketchPos.x = handler->referencePoint.x + cos(angle) * length; + onSketchPos.y = handler->referencePoint.y + sin(angle) * length; + } + } break; + default: + break; + } +} + +template<> +void DSHTranslateController::adaptParameters(Base::Vector2d onSketchPos) +{ + switch (handler->state()) { + case SelectMode::SeekFirst: { + if (!onViewParameters[OnViewParameter::First]->isSet) { + setOnViewParameterValue(OnViewParameter::First, onSketchPos.x); + } + + if (!onViewParameters[OnViewParameter::Second]->isSet) { + setOnViewParameterValue(OnViewParameter::Second, onSketchPos.y); + } + + bool sameSign = onSketchPos.x * onSketchPos.y > 0.; + onViewParameters[OnViewParameter::First]->setLabelAutoDistanceReverse(!sameSign); + onViewParameters[OnViewParameter::Second]->setLabelAutoDistanceReverse(sameSign); + onViewParameters[OnViewParameter::First]->setPoints(Base::Vector3d(), + toVector3d(onSketchPos)); + onViewParameters[OnViewParameter::Second]->setPoints(Base::Vector3d(), + toVector3d(onSketchPos)); + } break; + case SelectMode::SeekSecond: { + if (!onViewParameters[OnViewParameter::Third]->isSet) { + onViewParameters[OnViewParameter::Third]->setSpinboxValue( + (onSketchPos - handler->referencePoint).Length()); + } + + Base::Vector2d vec2d = Base::Vector2d(handler->firstTranslationVector.x, + handler->firstTranslationVector.y); + double angle = vec2d.Angle(); + double range = angle * 180 / M_PI; + + if (!onViewParameters[OnViewParameter::Fourth]->isSet) { + onViewParameters[OnViewParameter::Fourth]->setSpinboxValue(range, + Base::Unit::Angle); + } + + Base::Vector3d start = toVector3d(handler->referencePoint); + Base::Vector3d end = toVector3d(onSketchPos); + + onViewParameters[OnViewParameter::Third]->setPoints(start, end); + onViewParameters[OnViewParameter::Fourth]->setPoints(start, Base::Vector3d()); + onViewParameters[OnViewParameter::Fourth]->setLabelRange(angle); + } break; + case SelectMode::SeekThird: { + if (!onViewParameters[OnViewParameter::Fifth]->isSet) { + onViewParameters[OnViewParameter::Fifth]->setSpinboxValue( + (onSketchPos - handler->referencePoint).Length()); + } + + Base::Vector2d vec2d = Base::Vector2d(handler->secondTranslationVector.x, + handler->secondTranslationVector.y); + double angle = vec2d.Angle(); + double range = angle * 180 / M_PI; + + if (!onViewParameters[OnViewParameter::Sixth]->isSet) { + setOnViewParameterValue(OnViewParameter::Sixth, range, Base::Unit::Angle); + } + + Base::Vector3d start = toVector3d(handler->referencePoint); + Base::Vector3d end = toVector3d(onSketchPos); + + onViewParameters[OnViewParameter::Fifth]->setPoints(start, end); + onViewParameters[OnViewParameter::Sixth]->setPoints(start, Base::Vector3d()); + onViewParameters[OnViewParameter::Sixth]->setLabelRange(angle); + } break; + default: + break; + } +} + +template<> +void DSHTranslateController::doChangeDrawSketchHandlerMode() +{ + switch (handler->state()) { + case SelectMode::SeekFirst: { + if (onViewParameters[OnViewParameter::First]->isSet + && onViewParameters[OnViewParameter::Second]->isSet) { + + handler->setState(SelectMode::SeekSecond); + } + } break; + case SelectMode::SeekSecond: { + if (onViewParameters[OnViewParameter::Third]->isSet + && onViewParameters[OnViewParameter::Fourth]->isSet) { + + if (handler->secondNumberOfCopies == 1) { + handler->setState(SelectMode::End); + } + else { + handler->setState(SelectMode::SeekThird); + } + } + } break; + case SelectMode::SeekThird: { + if (onViewParameters[OnViewParameter::Fifth]->isSet + && onViewParameters[OnViewParameter::Sixth]->isSet) { + + handler->setState(SelectMode::End); + } + } break; + default: + break; + } +} + +} // namespace SketcherGui + + +#endif // SKETCHERGUI_DrawSketchHandlerTranslate_H diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc index f67b655bb1..936b246e64 100644 --- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc +++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc @@ -239,6 +239,7 @@ icons/pointers/Sketcher_Pointer_Create_Periodic_BSplineByInterpolation.svg icons/pointers/Sketcher_Pointer_Create_Point.svg icons/pointers/Sketcher_Pointer_Create_PointFillet.svg + icons/pointers/Sketcher_Pointer_Create_Translate.svg icons/pointers/Sketcher_Pointer_Create_Offset.svg icons/pointers/Sketcher_Pointer_Create_Rotate.svg icons/pointers/Sketcher_Pointer_Create_Scale.svg @@ -302,6 +303,7 @@ icons/tools/Sketcher_Offset.svg icons/tools/Sketcher_OffsetArc.svg icons/tools/Sketcher_OffsetIntersection.svg + icons/tools/Sketcher_Translate.svg icons/dialogs/Sketcher_Settings.svg diff --git a/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_Create_Translate.svg b/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_Create_Translate.svg new file mode 100644 index 0000000000..0eb4a5457c --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/pointers/Sketcher_Pointer_Create_Translate.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/tools/Sketcher_Translate.svg b/src/Mod/Sketcher/Gui/Resources/icons/tools/Sketcher_Translate.svg new file mode 100644 index 0000000000..1a4dbf3745 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/tools/Sketcher_Translate.svg @@ -0,0 +1,585 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [maxwxyz] + + + https://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg + + + FreeCAD LGPL2+ + + + 2023-12-19 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index 63ba8f4e01..5b36e03459 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -537,6 +537,7 @@ inline void SketcherAddWorkbenchTools(Gui::MenuItem& consaccel) << "Sketcher_Rotate" << "Sketcher_Scale" << "Sketcher_Symmetry" + << "Sketcher_Translate" << "Sketcher_Clone" << "Sketcher_Copy" << "Sketcher_Move" @@ -567,6 +568,7 @@ inline void SketcherAddWorkbenchTools(Gui::ToolBarItem& consac << "Sketcher_Rotate" << "Sketcher_Scale" << "Sketcher_Symmetry" + << "Sketcher_Translate" << "Sketcher_CompCopy" << "Sketcher_RectangularArray" << "Sketcher_RemoveAxesAlignment"; From f8b57283e52a2b597e086e979879934925f09250 Mon Sep 17 00:00:00 2001 From: Paddle Date: Fri, 3 Nov 2023 19:38:01 +0100 Subject: [PATCH 2/4] Remove Copy/clone/move and RectangularArray from the toolbar/menu. But does not remove the code of these. --- src/Mod/Sketcher/Gui/Workbench.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index 5b36e03459..9b6838dc37 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -538,10 +538,6 @@ inline void SketcherAddWorkbenchTools(Gui::MenuItem& consaccel) << "Sketcher_Scale" << "Sketcher_Symmetry" << "Sketcher_Translate" - << "Sketcher_Clone" - << "Sketcher_Copy" - << "Sketcher_Move" - << "Sketcher_RectangularArray" << "Sketcher_RemoveAxesAlignment" << "Separator" << "Sketcher_DeleteAllGeometry" @@ -569,8 +565,6 @@ inline void SketcherAddWorkbenchTools(Gui::ToolBarItem& consac << "Sketcher_Scale" << "Sketcher_Symmetry" << "Sketcher_Translate" - << "Sketcher_CompCopy" - << "Sketcher_RectangularArray" << "Sketcher_RemoveAxesAlignment"; } From b3e4bf103153ebc8155cefd460bd9d303eea511d Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Tue, 6 Feb 2024 14:46:55 +0100 Subject: [PATCH 3/4] Sketcher: DSH: add two shortcuts for DSH to use. Fix a small syntax error in polygon/rotate. --- .../Gui/DrawSketchControllableHandler.h | 8 ++++++ src/Mod/Sketcher/Gui/DrawSketchController.h | 6 +++++ .../Gui/DrawSketchDefaultWidgetController.h | 24 ++++++++++++++++-- .../Sketcher/Gui/DrawSketchHandlerPolygon.h | 4 +-- .../Sketcher/Gui/DrawSketchHandlerRotate.h | 4 +-- .../Sketcher/Gui/DrawSketchHandlerTranslate.h | 25 ++++++++++++++++--- 6 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/Mod/Sketcher/Gui/DrawSketchControllableHandler.h b/src/Mod/Sketcher/Gui/DrawSketchControllableHandler.h index 7e6193d31a..2dd00ad373 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchControllableHandler.h +++ b/src/Mod/Sketcher/Gui/DrawSketchControllableHandler.h @@ -183,6 +183,14 @@ private: toolWidgetManager.secondKeyShortcut(); } + if (key == SoKeyboardEvent::R && !pressed && !this->isLastState()) { + toolWidgetManager.thirdKeyShortcut(); + } + + if (key == SoKeyboardEvent::F && !pressed && !this->isLastState()) { + toolWidgetManager.fourthKeyShortcut(); + } + if (key == SoKeyboardEvent::TAB && !pressed) { toolWidgetManager.tabShortcut(); } diff --git a/src/Mod/Sketcher/Gui/DrawSketchController.h b/src/Mod/Sketcher/Gui/DrawSketchController.h index 9381b3b92d..7e52186c41 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchController.h +++ b/src/Mod/Sketcher/Gui/DrawSketchController.h @@ -444,6 +444,12 @@ public: virtual void secondKeyShortcut() {} + virtual void thirdKeyShortcut() + {} + + virtual void fourthKeyShortcut() + {} + virtual void tabShortcut() { passFocusToNextOnViewParameter(); diff --git a/src/Mod/Sketcher/Gui/DrawSketchDefaultWidgetController.h b/src/Mod/Sketcher/Gui/DrawSketchDefaultWidgetController.h index 4df96a6b4c..30340e6507 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchDefaultWidgetController.h +++ b/src/Mod/Sketcher/Gui/DrawSketchDefaultWidgetController.h @@ -220,7 +220,7 @@ public: Q_UNUSED(onSketchPos) } - /** on first shortcut, it toggles the first checkbox if there is go. Must be specialised if + /** on first shortcut, it toggles the first checkbox if there is one. Must be specialised if * this is not intended */ void firstKeyShortcut() override { @@ -230,7 +230,7 @@ public: } } - /** on second shortcut, it toggles the second checkbox if there is go. Must be specialised if + /** on second shortcut, it toggles the second checkbox if there is one. Must be specialised if * this is not intended */ void secondKeyShortcut() override { @@ -240,6 +240,26 @@ public: } } + /** on third shortcut, it toggles the third checkbox if there is one. Must be specialised if + * this is not intended */ + void thirdKeyShortcut() override + { + if (nCheckbox >= 3) { + auto thirdchecked = toolWidget->getCheckboxChecked(WCheckbox::ThirdBox); + toolWidget->setCheckboxChecked(WCheckbox::ThirdBox, !thirdchecked); + } + } + + /** on fourth shortcut, it toggles the fourth checkbox if there is one. Must be specialised if + * this is not intended */ + void fourthKeyShortcut() override + { + if (nCheckbox >= 4) { + auto fourthchecked = toolWidget->getCheckboxChecked(WCheckbox::FourthBox); + toolWidget->setCheckboxChecked(WCheckbox::FourthBox, !fourthchecked); + } + } + //@} protected: diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerPolygon.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerPolygon.h index afac9a032b..d0fc81fb92 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerPolygon.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerPolygon.h @@ -286,7 +286,7 @@ template<> void DSHPolygonController::firstKeyShortcut() { auto value = toolWidget->getParameter(WParameter::First); - toolWidget->setParameterWithoutPassingFocus(OnViewParameter::First, value + 1); + toolWidget->setParameterWithoutPassingFocus(WParameter::First, value + 1); } template<> @@ -294,7 +294,7 @@ void DSHPolygonController::secondKeyShortcut() { auto value = toolWidget->getParameter(WParameter::First); if (value > 3.0) { // NOLINT - toolWidget->setParameterWithoutPassingFocus(OnViewParameter::First, value - 1); + toolWidget->setParameterWithoutPassingFocus(WParameter::First, value - 1); } } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h index 1138d53096..1232f4e722 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h @@ -456,7 +456,7 @@ template<> void DSHRotateController::firstKeyShortcut() { auto value = toolWidget->getParameter(WParameter::First); - toolWidget->setParameterWithoutPassingFocus(OnViewParameter::First, value + 1); + toolWidget->setParameterWithoutPassingFocus(WParameter::First, value + 1); } template<> @@ -464,7 +464,7 @@ void DSHRotateController::secondKeyShortcut() { auto value = toolWidget->getParameter(WParameter::First); if (value > 0.0) { - toolWidget->setParameterWithoutPassingFocus(OnViewParameter::First, value - 1); + toolWidget->setParameterWithoutPassingFocus(WParameter::First, value - 1); } } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h index 6351fc9f5d..afa230c1ac 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h @@ -448,7 +448,7 @@ template<> void DSHTranslateController::firstKeyShortcut() { auto value = toolWidget->getParameter(WParameter::First); - toolWidget->setParameterWithoutPassingFocus(OnViewParameter::First, value + 1); + toolWidget->setParameterWithoutPassingFocus(WParameter::First, value + 1); } template<> @@ -456,7 +456,23 @@ void DSHTranslateController::secondKeyShortcut() { auto value = toolWidget->getParameter(WParameter::First); if (value > 0.0) { - toolWidget->setParameterWithoutPassingFocus(OnViewParameter::First, value - 1); + toolWidget->setParameterWithoutPassingFocus(WParameter::First, value - 1); + } +} + +template<> +void DSHTranslateController::thirdKeyShortcut() +{ + auto value = toolWidget->getParameter(WParameter::Second); + toolWidget->setParameterWithoutPassingFocus(WParameter::Second, value + 1); +} + +template<> +void DSHTranslateController::fourthKeyShortcut() +{ + auto value = toolWidget->getParameter(WParameter::Second); + if (value > 1.0) { + toolWidget->setParameterWithoutPassingFocus(WParameter::Second, value - 1); } } @@ -495,8 +511,9 @@ void DSHTranslateController::configureToolWidget() toolWidget->setParameterLabel( WParameter::First, QApplication::translate("TaskSketcherTool_p3_translate", "Copies (+'U'/-'J')")); - toolWidget->setParameterLabel(WParameter::Second, - QApplication::translate("TaskSketcherTool_p5_translate", "Rows")); + toolWidget->setParameterLabel( + WParameter::Second, + QApplication::translate("TaskSketcherTool_p5_translate", "Rows (+'R'/-'F')")); toolWidget->setParameter(OnViewParameter::First, 0.0); toolWidget->setParameter(OnViewParameter::Second, 1.0); From b7656abfc52e6890f23cf2b6ec3ecb39420653db Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Tue, 6 Feb 2024 17:02:31 +0100 Subject: [PATCH 4/4] Sketcher: change DSH framework so that tab cycle through OVP and widget parameters. --- src/Mod/Sketcher/Gui/DrawSketchController.h | 67 +++++++++--------- .../Gui/DrawSketchDefaultWidgetController.h | 69 +++++++++++++++++++ .../Gui/SketcherToolDefaultWidget.cpp | 49 ++++--------- .../Sketcher/Gui/SketcherToolDefaultWidget.h | 7 ++ 4 files changed, 122 insertions(+), 70 deletions(-) diff --git a/src/Mod/Sketcher/Gui/DrawSketchController.h b/src/Mod/Sketcher/Gui/DrawSketchController.h index 7e52186c41..e58b53db22 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchController.h +++ b/src/Mod/Sketcher/Gui/DrawSketchController.h @@ -123,7 +123,8 @@ protected: std::vector> onViewParameters; // NOLINTEND - bool init = false; // true if the controls have been initialised. + bool init = false; // true if the controls have been initialised. + int parameterWithFocus = 0; // track the index of the parameter having the focus /** @name Named indices for controlling on-view controls */ //@{ @@ -147,7 +148,6 @@ private: Base::Vector2d prevCursorPosition; Base::Vector2d lastControlEnforcedPosition; - int onViewIndexWithFocus = 0; // track the index of the on-view parameter having the focus int nOnViewParameter = OnViewParametersT::defaultMethodSize(); /// Class to keep track of colors used by the on-view parameters @@ -520,8 +520,8 @@ protected: virtual void afterEnforceControlParameters() { // Give focus to current on-view parameter. In case user interacted outside of 3dview. - if (onViewIndexWithFocus >= 0) { - setFocusToOnViewParameter(onViewIndexWithFocus); + if (parameterWithFocus >= 0) { + setFocusToOnViewParameter(parameterWithFocus); } } @@ -605,7 +605,7 @@ protected: double val, const Base::Unit& unit = Base::Unit::Length) { - bool visible = ovpVisibilityManager.isVisible(onViewParameters[index].get()); + bool visible = isOnViewParameterVisible(index); if (visible) { onViewParameters[index]->setSpinboxValue(val, unit); @@ -620,7 +620,7 @@ protected: ovpVisibilityManager.resetDynamicOverride(); bool firstOfMode = true; - onViewIndexWithFocus = -1; + parameterWithFocus = -1; for (size_t i = 0; i < onViewParameters.size(); i++) { @@ -633,11 +633,11 @@ protected: else { if (firstOfMode) { - onViewIndexWithFocus = static_cast(i); + parameterWithFocus = static_cast(i); firstOfMode = false; } - bool visible = ovpVisibilityManager.isVisible(onViewParameters[i].get()); + bool visible = isOnViewParameterVisible(i); if (visible) { onViewParameters[i]->activate(); @@ -652,52 +652,46 @@ protected: } /// This function gives the focus to a spinbox and tracks the focus. - void setFocusToOnViewParameter(unsigned int onviewparameterindex) + bool setFocusToOnViewParameter(unsigned int onviewparameterindex) { if (onviewparameterindex < onViewParameters.size()) { - bool visible = - ovpVisibilityManager.isVisible(onViewParameters[onviewparameterindex].get()); + bool visible = isOnViewParameterVisible(onviewparameterindex); if (visible) { onViewParameters[onviewparameterindex]->setFocusToSpinbox(); + parameterWithFocus = static_cast(onviewparameterindex); + return true; } - - onViewIndexWithFocus = static_cast(onviewparameterindex); } + return false; } /// Switches focus to the next parameter in the current state machine. void passFocusToNextOnViewParameter() { - unsigned int index = onViewIndexWithFocus + 1; + unsigned int index = parameterWithFocus + 1; if (index >= onViewParameters.size()) { index = 0; } - bool visible = ovpVisibilityManager.isVisible(onViewParameters[index].get()); - - while (index < onViewParameters.size()) { - if (isOnViewParameterOfCurrentMode(index)) { - - if (visible) { - setFocusToOnViewParameter(index); + auto trySetFocus = [this](unsigned int& idx) -> bool { + while (idx < onViewParameters.size()) { + if (isOnViewParameterOfCurrentMode(idx) && isOnViewParameterVisible(idx)) { + setFocusToOnViewParameter(idx); + return true; } - return; + idx++; } - index++; - } - // There is no more onViewParameter after onViewIndexWithFocus + 1 in this mode + return false; + }; - // So we go back to start. - index = 0; - while (index < onViewParameters.size()) { - if (isOnViewParameterOfCurrentMode(index)) { - setFocusToOnViewParameter(index); - return; - } - index++; + if (!trySetFocus(index)) { + // We have not found a parameter in this mode after current. + // So we go back to start and retry. + index = 0; + trySetFocus(index); } // At that point if no onViewParameter is found, there is none. @@ -719,12 +713,17 @@ protected: && getState(onviewparameterindex) < handler->state(); } + bool isOnViewParameterVisible(unsigned int onviewparameterindex) + { + return ovpVisibilityManager.isVisible(onViewParameters[onviewparameterindex].get()); + } + /** Resets the on-view parameter controls */ void resetOnViewParameters() { nOnViewParameter = OnViewParametersT::size(handler->constructionMethod()); initNOnViewParameters(nOnViewParameter); - onViewIndexWithFocus = 0; + parameterWithFocus = 0; configureOnViewParameters(); } diff --git a/src/Mod/Sketcher/Gui/DrawSketchDefaultWidgetController.h b/src/Mod/Sketcher/Gui/DrawSketchDefaultWidgetController.h index 30340e6507..f52ff94594 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchDefaultWidgetController.h +++ b/src/Mod/Sketcher/Gui/DrawSketchDefaultWidgetController.h @@ -100,6 +100,7 @@ private: using Connection = boost::signals2::connection; + Connection connectionParameterFocusOut; Connection connectionParameterValueChanged; Connection connectionCheckboxCheckedChanged; Connection connectionComboboxSelectionChanged; @@ -127,6 +128,7 @@ public: ~DrawSketchDefaultWidgetController() override { + connectionParameterFocusOut.disconnect(); connectionParameterValueChanged.disconnect(); connectionCheckboxCheckedChanged.disconnect(); connectionComboboxSelectionChanged.disconnect(); @@ -148,6 +150,12 @@ public: ControllerBase::finishControlsChanged(); } + void parameterFocusOut(int parameterindex) + { + Q_UNUSED(parameterindex); + passFocusToNextParameter(); + } + /** boost slot triggering when a checkbox has changed in the widget * It is intended to remote control the DrawSketchDefaultWidgetHandler */ @@ -260,6 +268,12 @@ public: } } + /** on tab, we cycle through OVP and widget parameters */ + void tabShortcut() override + { + passFocusToNextParameter(); + } + //@} protected: @@ -282,6 +296,57 @@ protected: /// Automatic default method update in combobox void doConstructionMethodChanged() override {} + + /// here we can pass focus to either OVP or widget parameters. + void setFocusToParameter(unsigned int parameterindex) + { + // To be able to cycle through OVP and widget, we use a parameter index that goes from + // 0 to (onViewParameters.size() + nParameter) + if (!ControllerBase::setFocusToOnViewParameter(parameterindex)) { + parameterindex = parameterindex - ControllerBase::onViewParameters.size(); + + if (parameterindex < static_cast(nParameter)) { + toolWidget->setParameterFocus(parameterindex); + ControllerBase::parameterWithFocus = + ControllerBase::onViewParameters.size() + parameterindex; + } + } + } + + /// Here we can pass focus to either OVP or widget parameters. + void passFocusToNextParameter() + { + unsigned int index = ControllerBase::parameterWithFocus + 1; + + if (index >= ControllerBase::onViewParameters.size() + nParameter) { + index = 0; + } + + auto trySetFocus = [this](unsigned int& idx) -> bool { + while (idx < ControllerBase::onViewParameters.size()) { + if (ControllerBase::isOnViewParameterOfCurrentMode(idx) + && ControllerBase::isOnViewParameterVisible(idx)) { + setFocusToParameter(idx); + return true; + } + idx++; + } + if (idx < ControllerBase::onViewParameters.size() + nParameter) { + setFocusToParameter(idx); + return true; + } + return false; + }; + + if (!trySetFocus(index)) { + // We have not found a parameter in this mode after current. + // So we go back to start and retry. + index = 0; + trySetFocus(index); + } + + // At that point if no onViewParameter is found, there is none. + } //@} private: @@ -290,6 +355,9 @@ private: { toolWidget = static_cast(widget); // NOLINT + connectionParameterFocusOut = toolWidget->registerParameterFocusOut( + std::bind(&DrawSketchDefaultWidgetController::parameterFocusOut, this, sp::_1)); + connectionParameterValueChanged = toolWidget->registerParameterValueChanged( std::bind(&DrawSketchDefaultWidgetController::parameterValueChanged, this, @@ -312,6 +380,7 @@ private: /// Resets the widget void resetDefaultWidget() { + boost::signals2::shared_connection_block parameter_focus_block(connectionParameterFocusOut); boost::signals2::shared_connection_block parameter_block(connectionParameterValueChanged); boost::signals2::shared_connection_block checkbox_block(connectionCheckboxCheckedChanged); boost::signals2::shared_connection_block combobox_block(connectionComboboxSelectionChanged); diff --git a/src/Mod/Sketcher/Gui/SketcherToolDefaultWidget.cpp b/src/Mod/Sketcher/Gui/SketcherToolDefaultWidget.cpp index b509962354..6f89a4867e 100644 --- a/src/Mod/Sketcher/Gui/SketcherToolDefaultWidget.cpp +++ b/src/Mod/Sketcher/Gui/SketcherToolDefaultWidget.cpp @@ -157,6 +157,16 @@ bool SketcherToolDefaultWidget::eventFilter(QObject* object, QEvent* event) } } } + else if (event->type() == QEvent::FocusOut) { + for (int i = 0; i < nParameters; i++) { + auto parameterSpinBox = getParameterSpinBox(i); + + if (object == parameterSpinBox) { + signalParameterFocusOut(i); + break; + } + } + } return false; } @@ -200,10 +210,10 @@ void SketcherToolDefaultWidget::parameterOne_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::First] = true; - setParameterFontStyle(Parameter::First, FontStyle::Bold); + /*setParameterFontStyle(Parameter::First, FontStyle::Bold); if (!blockParameterFocusPassing) { setParameterFocus(Parameter::Second); - } + }*/ signalParameterValueChanged(Parameter::First, val); } } @@ -211,10 +221,6 @@ void SketcherToolDefaultWidget::parameterTwo_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::Second] = true; - setParameterFontStyle(Parameter::Second, FontStyle::Bold); - if (!blockParameterFocusPassing) { - setParameterFocus(Parameter::Third); - } signalParameterValueChanged(Parameter::Second, val); } } @@ -222,10 +228,6 @@ void SketcherToolDefaultWidget::parameterThree_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::Third] = true; - setParameterFontStyle(Parameter::Third, FontStyle::Bold); - if (!blockParameterFocusPassing) { - setParameterFocus(Parameter::Fourth); - } signalParameterValueChanged(Parameter::Third, val); } } @@ -233,10 +235,6 @@ void SketcherToolDefaultWidget::parameterFour_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::Fourth] = true; - setParameterFontStyle(Parameter::Fourth, FontStyle::Bold); - if (!blockParameterFocusPassing) { - setParameterFocus(Parameter::Fifth); - } signalParameterValueChanged(Parameter::Fourth, val); } } @@ -244,10 +242,6 @@ void SketcherToolDefaultWidget::parameterFive_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::Fifth] = true; - setParameterFontStyle(Parameter::Fifth, FontStyle::Bold); - if (!blockParameterFocusPassing) { - setParameterFocus(Parameter::Sixth); - } signalParameterValueChanged(Parameter::Fifth, val); } } @@ -255,10 +249,6 @@ void SketcherToolDefaultWidget::parameterSix_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::Sixth] = true; - setParameterFontStyle(Parameter::Sixth, FontStyle::Bold); - if (!blockParameterFocusPassing) { - setParameterFocus(Parameter::Seventh); - } signalParameterValueChanged(Parameter::Sixth, val); } } @@ -266,10 +256,6 @@ void SketcherToolDefaultWidget::parameterSeven_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::Seventh] = true; - setParameterFontStyle(Parameter::Seventh, FontStyle::Bold); - if (!blockParameterFocusPassing) { - setParameterFocus(Parameter::Eighth); - } signalParameterValueChanged(Parameter::Seventh, val); } } @@ -277,10 +263,6 @@ void SketcherToolDefaultWidget::parameterEight_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::Eighth] = true; - setParameterFontStyle(Parameter::Eighth, FontStyle::Bold); - if (!blockParameterFocusPassing) { - setParameterFocus(Parameter::Ninth); - } signalParameterValueChanged(Parameter::Eighth, val); } } @@ -288,10 +270,6 @@ void SketcherToolDefaultWidget::parameterNine_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::Ninth] = true; - setParameterFontStyle(Parameter::Ninth, FontStyle::Bold); - if (!blockParameterFocusPassing) { - setParameterFocus(Parameter::Tenth); - } signalParameterValueChanged(Parameter::Ninth, val); } } @@ -299,7 +277,6 @@ void SketcherToolDefaultWidget::parameterTen_valueChanged(double val) { if (!blockParameterSlots) { isSet[Parameter::Tenth] = true; - setParameterFontStyle(Parameter::Tenth, FontStyle::Bold); signalParameterValueChanged(Parameter::Tenth, val); } } @@ -316,7 +293,7 @@ void SketcherToolDefaultWidget::initNParameters(int nparameters, QObject* filter setParameterVisible(i, (i < nparameters)); setParameter(i, 0.F); setParameterFilteringObject(i, filteringObject); - setParameterFontStyle(i, FontStyle::Italic); + // setParameterFontStyle(i, FontStyle::Italic); } setParameterFocus(Parameter::First); diff --git a/src/Mod/Sketcher/Gui/SketcherToolDefaultWidget.h b/src/Mod/Sketcher/Gui/SketcherToolDefaultWidget.h index 4349c1715b..d73ea08383 100644 --- a/src/Mod/Sketcher/Gui/SketcherToolDefaultWidget.h +++ b/src/Mod/Sketcher/Gui/SketcherToolDefaultWidget.h @@ -154,6 +154,12 @@ public: void setComboboxPrefEntry(int comboboxindex, const std::string& prefEntry); void restoreComboboxPref(int comboboxindex); + template + boost::signals2::connection registerParameterFocusOut(F&& fn) + { + return signalParameterFocusOut.connect(std::forward(fn)); + } + template boost::signals2::connection registerParameterValueChanged(F&& fn) { @@ -211,6 +217,7 @@ private: private: std::unique_ptr ui; + boost::signals2::signal signalParameterFocusOut; boost::signals2::signal signalParameterValueChanged; boost::signals2::signal signalCheckboxCheckedChanged; boost::signals2::signal signalComboboxSelectionChanged;