From c76f068f911f044ff665f4f009e582358b8e8a85 Mon Sep 17 00:00:00 2001 From: George Peden Date: Mon, 23 Jun 2025 09:09:59 -0700 Subject: [PATCH] Sketcher: Add contextual input hints to transform tools (InputHints Phase 4) (#21840) * Add hints to symettry tool * Add hint system for transform tools - Design decision: Keep hints simple and focused on primary mouse actions - Avoid redundancy with dialog UI which already shows keyboard shortcuts clearly - Implements progressive hints for multi-state tools (Rotate, Scale, Translate) using declarative hint tables, and focused hints for single-state tools (Symmetry, Offset) using direct return implementations. * Cleanup unused declarative hint decls * Change hint to 'pick axis, edge, or point" per PR feedback --- .../Sketcher/Gui/DrawSketchHandlerOffset.h | 9 ++++ .../Sketcher/Gui/DrawSketchHandlerRotate.h | 41 ++++++++++++++++++ src/Mod/Sketcher/Gui/DrawSketchHandlerScale.h | 40 +++++++++++++++++ .../Sketcher/Gui/DrawSketchHandlerSymmetry.h | 9 ++++ .../Sketcher/Gui/DrawSketchHandlerTranslate.h | 43 +++++++++++++++++++ 5 files changed, 142 insertions(+) diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h index c143c0223e..30ea54eb0e 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerOffset.h @@ -191,6 +191,15 @@ private: generateSourceWires(); } +public: + std::list getToolHints() const override + { + using enum Gui::InputHint::UserInput; + + return {{QObject::tr("%1 set offset direction and distance", "Sketcher Offset: hint"), + {MouseLeft}}}; + } + private: class CoincidencePointPos { diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h index 4baf4773b1..fb7ce2f00b 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerRotate.h @@ -455,8 +455,49 @@ private: return pointToRotate; } + + struct HintEntry + { + SelectMode state; + std::list hints; + }; + + using HintTable = std::vector; + + static HintTable getRotateHintTable(); + static std::list lookupRotateHints(SelectMode state); + +public: + std::list getToolHints() const override + { + return lookupRotateHints(state()); + } }; +DrawSketchHandlerRotate::HintTable DrawSketchHandlerRotate::getRotateHintTable() +{ + using enum Gui::InputHint::UserInput; + + return { + {.state = SelectMode::SeekFirst, + .hints = {{QObject::tr("%1 pick center point", "Sketcher Rotate: hint"), {MouseLeft}}}}, + {.state = SelectMode::SeekSecond, + .hints = {{QObject::tr("%1 set start angle", "Sketcher Rotate: hint"), {MouseLeft}}}}, + {.state = SelectMode::SeekThird, + .hints = {{QObject::tr("%1 set rotation angle", "Sketcher Rotate: hint"), {MouseLeft}}}}}; +} + +std::list DrawSketchHandlerRotate::lookupRotateHints(SelectMode state) +{ + const auto rotateHintTable = getRotateHintTable(); + + auto it = std::ranges::find_if(rotateHintTable, [state](const HintEntry& entry) { + return entry.state == state; + }); + + return (it != rotateHintTable.end()) ? it->hints : std::list {}; +} + template<> auto DSHRotateControllerBase::getState(int labelindex) const { diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerScale.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerScale.h index 30292f6e78..28e155ea88 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerScale.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerScale.h @@ -132,6 +132,11 @@ public: } + std::list getToolHints() const override + { + return lookupScaleHints(state()); + } + private: void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override { @@ -228,6 +233,17 @@ private: bool allowOriginConstraint; // Conserve constraints with origin double refLength, length, scaleFactor; + struct HintEntry + { + SelectMode state; + std::list hints; + }; + + using HintTable = std::vector; + + static HintTable getScaleHintTable(); + static std::list lookupScaleHints(SelectMode state); + void deleteOriginalGeos() { @@ -447,6 +463,30 @@ private: } }; +DrawSketchHandlerScale::HintTable DrawSketchHandlerScale::getScaleHintTable() +{ + using enum Gui::InputHint::UserInput; + + return { + {.state = SelectMode::SeekFirst, + .hints = {{QObject::tr("%1 pick reference point", "Sketcher Scale: hint"), {MouseLeft}}}}, + {.state = SelectMode::SeekSecond, + .hints = {{QObject::tr("%1 set reference length", "Sketcher Scale: hint"), {MouseLeft}}}}, + {.state = SelectMode::SeekThird, + .hints = {{QObject::tr("%1 set scale factor", "Sketcher Scale: hint"), {MouseLeft}}}}}; +} + +std::list DrawSketchHandlerScale::lookupScaleHints(SelectMode state) +{ + const auto scaleHintTable = getScaleHintTable(); + + auto it = std::ranges::find_if(scaleHintTable, [state](const HintEntry& entry) { + return entry.state == state; + }); + + return (it != scaleHintTable.end()) ? it->hints : std::list {}; +} + template<> auto DSHScaleControllerBase::getState(int labelindex) const { diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerSymmetry.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerSymmetry.h index bda7afdfbf..bb6988c17e 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerSymmetry.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerSymmetry.h @@ -215,6 +215,15 @@ private: Sketcher::PointPos refPosId; bool deleteOriginal, createSymConstraints; +public: + std::list getToolHints() const override + { + using enum Gui::InputHint::UserInput; + + return { + {QObject::tr("%1 pick axis, edge, or point", "Sketcher Symmetry: hint"), {MouseLeft}}}; + } + void deleteOriginalGeos() { std::stringstream stream; diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h index 9e19d89b57..0e524a5e76 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerTranslate.h @@ -426,8 +426,51 @@ private: } } } + + struct HintEntry + { + SelectMode state; + std::list hints; + }; + + using HintTable = std::vector; + + static HintTable getTranslateHintTable(); + static std::list lookupTranslateHints(SelectMode state); + +public: + std::list getToolHints() const override + { + return lookupTranslateHints(state()); + } }; +DrawSketchHandlerTranslate::HintTable DrawSketchHandlerTranslate::getTranslateHintTable() +{ + using enum Gui::InputHint::UserInput; + + return {{.state = SelectMode::SeekFirst, + .hints = {{QObject::tr("%1 pick reference point", "Sketcher Translate: hint"), + {MouseLeft}}}}, + {.state = SelectMode::SeekSecond, + .hints = {{QObject::tr("%1 set translation vector", "Sketcher Translate: hint"), + {MouseLeft}}}}, + {.state = SelectMode::SeekThird, + .hints = {{QObject::tr("%1 set second translation vector", "Sketcher Translate: hint"), + {MouseLeft}}}}}; +} + +std::list DrawSketchHandlerTranslate::lookupTranslateHints(SelectMode state) +{ + const auto translateHintTable = getTranslateHintTable(); + + auto it = std::ranges::find_if(translateHintTable, [state](const HintEntry& entry) { + return entry.state == state; + }); + + return (it != translateHintTable.end()) ? it->hints : std::list {}; +} + template<> auto DSHTranslateControllerBase::getState(int labelindex) const {