Merge pull request #22227 from kadet1090/refactor-tool-hints

Sketcher: Refactor Tool Hints
This commit is contained in:
Chris Hennes
2025-07-20 12:05:15 -05:00
committed by GitHub
29 changed files with 766 additions and 940 deletions

View File

@@ -253,6 +253,16 @@ struct InputHint
InputSequence(const std::initializer_list<UserInput> keys)
: keys(keys)
{}
friend bool operator==(const InputSequence& lhs, const InputSequence& rhs)
{
return lhs.keys == rhs.keys;
}
friend bool operator!=(const InputSequence& lhs, const InputSequence& rhs)
{
return !(lhs == rhs);
}
};
/**
@@ -270,8 +280,41 @@ struct InputHint
* @brief List of sequences to be substituted.
*/
std::list<InputSequence> sequences;
friend bool operator==(const InputHint& lhs, const InputHint& rhs)
{
return lhs.message == rhs.message && lhs.sequences == rhs.sequences;
}
friend bool operator!=(const InputHint& lhs, const InputHint& rhs)
{
return !(lhs == rhs);
}
};
template <typename T>
struct StateHints
{
T state;
std::list<InputHint> hints;
};
template <typename T>
using HintTable = std::vector<StateHints<T>>;
template <typename T>
static std::list<InputHint> lookupHints(T state, HintTable<T> table, const std::list<InputHint>& fallback = {}) {
const auto stateMatches = [&state](const StateHints<T>& entry) {
return entry.state == state;
};
if (auto it = std::ranges::find_if(table, stateMatches); it != table.end()) {
return it->hints;
}
return fallback;
}
} // namespace Gui
#endif // GUI_INPUTHINT_H

View File

@@ -23,8 +23,8 @@
#ifndef SKETCHERGUI_DrawSketchHandler_H
#define SKETCHERGUI_DrawSketchHandler_H
#include <QCursor>
#include <QPixmap>
#include <QCoreApplication>
#include <Inventor/SbString.h>
@@ -142,6 +142,8 @@ private:
*/
class SketcherGuiExport DrawSketchHandler: public Gui::ToolHandler
{
Q_DECLARE_TR_FUNCTIONS(DrawSketchHandler)
public:
DrawSketchHandler();
virtual ~DrawSketchHandler();
@@ -162,10 +164,11 @@ public:
return false;
}
virtual std::list<Gui::InputHint> getToolHints() const
std::list<Gui::InputHint> getToolHints() const override
{
return {};
}
void quit() override;
friend class ViewProviderSketch;

View File

@@ -90,7 +90,54 @@ public:
private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupArcHints(constructionMethod(), state());
using State = std::pair<ConstructionMethod, SelectMode>;
using enum Gui::InputHint::UserInput;
const Gui::InputHint switchModeHint {tr("%1 switch mode"), {KeyM}};
return Gui::lookupHints<State>(
{constructionMethod(), state()},
{
// Center method
{.state = {ConstructionMethod::Center, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick arc center"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::Center, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick arc start point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::Center, SelectMode::SeekThird},
.hints =
{
{tr("%1 pick arc end point"), {MouseLeft}},
switchModeHint,
}},
// ThreeRim method
{.state = {ConstructionMethod::ThreeRim, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first arc point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::ThreeRim, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick second arc point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::ThreeRim, SelectMode::SeekThird},
.hints =
{
{tr("%1 pick third arc point"), {MouseLeft}},
switchModeHint,
}},
});
}
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
@@ -342,7 +389,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Arc parameters"));
return QString(tr("Arc parameters"));
}
bool canGoToNextMode() override
@@ -432,21 +479,6 @@ private:
}
}
// Hint table structures
struct HintEntry
{
ConstructionMethod method;
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
// Static declaration
static Gui::InputHint switchModeHint();
static HintTable getArcHintTable();
static std::list<Gui::InputHint> lookupArcHints(ConstructionMethod method, SelectMode state);
private:
Base::Vector2d centerPoint, firstPoint, secondPoint;
double radius, startAngle, endAngle, arcAngle;
@@ -928,60 +960,6 @@ void DSHArcController::doConstructionMethodChanged()
handler->updateHint();
}
// Static member definitions
Gui::InputHint DrawSketchHandlerArc::switchModeHint()
{
return {QObject::tr("%1 switch mode"), {Gui::InputHint::UserInput::KeyM}};
}
DrawSketchHandlerArc::HintTable DrawSketchHandlerArc::getArcHintTable()
{
const auto switchHint = switchModeHint();
return {
// Structure: {ConstructionMethod, SelectMode, {hints...}}
// Center method
{ConstructionMethod::Center,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick arc center"), {Gui::InputHint::UserInput::MouseLeft}}, switchHint}},
{ConstructionMethod::Center,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick arc start point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethod::Center,
SelectMode::SeekThird,
{{QObject::tr("%1 pick arc end point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
// ThreeRim method
{ConstructionMethod::ThreeRim,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick first arc point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethod::ThreeRim,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick second arc point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethod::ThreeRim,
SelectMode::SeekThird,
{{QObject::tr("%1 pick third arc point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}}};
}
std::list<Gui::InputHint> DrawSketchHandlerArc::lookupArcHints(ConstructionMethod method,
SelectMode state)
{
const auto arcHintTable = getArcHintTable();
auto it = std::find_if(arcHintTable.begin(),
arcHintTable.end(),
[method, state](const HintEntry& entry) {
return entry.method == method && entry.state == state;
});
return (it != arcHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -407,48 +407,35 @@ protected:
private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupArcOfEllipseHints(Mode);
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
Mode,
{
{.state = STATUS_SEEK_First,
.hints =
{
{tr("%1 pick ellipse center"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Second,
.hints =
{
{tr("%1 pick axis point"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Third,
.hints =
{
{tr("%1 pick arc start point"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Fourth,
.hints =
{
{tr("%1 pick arc end point"), {MouseLeft}},
}},
});
}
private:
struct HintEntry
{
int mode;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getArcOfEllipseHintTable();
static std::list<Gui::InputHint> lookupArcOfEllipseHints(int mode);
};
DrawSketchHandlerArcOfEllipse::HintTable DrawSketchHandlerArcOfEllipse::getArcOfEllipseHintTable()
{
return {// Structure: {mode, {hints...}}
{STATUS_SEEK_First,
{{QObject::tr("%1 pick ellipse center"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Second,
{{QObject::tr("%1 pick axis point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Third,
{{QObject::tr("%1 pick arc start point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Fourth,
{{QObject::tr("%1 pick arc end point"), {Gui::InputHint::UserInput::MouseLeft}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerArcOfEllipse::lookupArcOfEllipseHints(int mode)
{
const auto arcOfEllipseHintTable = getArcOfEllipseHintTable();
auto it = std::find_if(arcOfEllipseHintTable.begin(),
arcOfEllipseHintTable.end(),
[mode](const HintEntry& entry) {
return entry.mode == mode;
});
return (it != arcOfEllipseHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -404,6 +404,35 @@ private:
return QStringLiteral("Sketcher_Pointer_Create_ArcOfHyperbola");
}
std::list<Gui::InputHint> getToolHints() const override
{
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
Mode,
{
{.state = STATUS_SEEK_First,
.hints =
{
{tr("%1 pick center point"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Second,
.hints =
{
{tr("%1 pick axis point"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Third,
.hints =
{
{tr("%1 pick arc start point"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Fourth,
.hints =
{
{tr("%1 pick arc end point"), {MouseLeft}},
}},
});
}
protected:
SelectMode Mode;
@@ -411,53 +440,8 @@ protected:
Base::Vector2d centerPoint, axisPoint, startingPoint, endPoint;
double arcAngle, arcAngle_t;
std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3, sugConstr4;
private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupArcOfHyperbolaHints(Mode);
}
private:
struct HintEntry
{
int mode;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getArcOfHyperbolaHintTable();
static std::list<Gui::InputHint> lookupArcOfHyperbolaHints(int mode);
};
DrawSketchHandlerArcOfHyperbola::HintTable
DrawSketchHandlerArcOfHyperbola::getArcOfHyperbolaHintTable()
{
return {// Structure: {mode, {hints...}}
{STATUS_SEEK_First,
{{QObject::tr("%1 pick center point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Second,
{{QObject::tr("%1 pick axis point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Third,
{{QObject::tr("%1 pick arc start point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Fourth,
{{QObject::tr("%1 pick arc end point"), {Gui::InputHint::UserInput::MouseLeft}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerArcOfHyperbola::lookupArcOfHyperbolaHints(int mode)
{
const auto arcOfHyperbolaHintTable = getArcOfHyperbolaHintTable();
auto it = std::find_if(arcOfHyperbolaHintTable.begin(),
arcOfHyperbolaHintTable.end(),
[mode](const HintEntry& entry) {
return entry.mode == mode;
});
return (it != arcOfHyperbolaHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -336,48 +336,35 @@ protected:
private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupParabolaHints(Mode);
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
Mode,
{
{.state = STATUS_SEEK_First,
.hints =
{
{tr("%1 pick focus point"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Second,
.hints =
{
{tr("%1 pick axis point"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Third,
.hints =
{
{tr("%1 pick starting point"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Fourth,
.hints =
{
{tr("%1 pick end point"), {MouseLeft}},
}},
});
}
private:
struct HintEntry
{
int mode;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getParabolaHintTable();
static std::list<Gui::InputHint> lookupParabolaHints(int mode);
};
DrawSketchHandlerArcOfParabola::HintTable DrawSketchHandlerArcOfParabola::getParabolaHintTable()
{
return {// Structure: {mode, {hints...}}
{STATUS_SEEK_First,
{{QObject::tr("%1 pick focus point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Second,
{{QObject::tr("%1 pick axis point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Third,
{{QObject::tr("%1 pick starting point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Fourth,
{{QObject::tr("%1 pick end point"), {Gui::InputHint::UserInput::MouseLeft}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerArcOfParabola::lookupParabolaHints(int mode)
{
const auto parabolaHintTable = getParabolaHintTable();
auto it = std::find_if(parabolaHintTable.begin(),
parabolaHintTable.end(),
[mode](const HintEntry& entry) {
return entry.mode == mode;
});
return (it != parabolaHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui
#endif // SKETCHERGUI_DrawSketchHandlerArcOfParabola_H

View File

@@ -93,24 +93,36 @@ public:
~DrawSketchHandlerArcSlot() override = default;
private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupArcSlotHints(state());
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(state(),
{
{.state = SelectMode::SeekFirst,
.hints =
{
{tr("%1 pick slot center"), {MouseLeft}},
}},
{.state = SelectMode::SeekSecond,
.hints =
{
{tr("%1 pick slot radius"), {MouseLeft}},
}},
{.state = SelectMode::SeekThird,
.hints =
{
{tr("%1 pick slot angle"), {MouseLeft}},
}},
{.state = SelectMode::SeekFourth,
.hints =
{
{tr("%1 pick slot width"), {MouseLeft}},
}},
});
}
private:
struct HintEntry
{
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getArcSlotHintTable();
static std::list<Gui::InputHint> lookupArcSlotHints(SelectMode state);
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
{
switch (state()) {
@@ -284,7 +296,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Arc Slot parameters"));
return QString(tr("Arc Slot parameters"));
}
bool canGoToNextMode() override
@@ -976,32 +988,6 @@ void DSHArcSlotController::addConstraints()
}
}
DrawSketchHandlerArcSlot::HintTable DrawSketchHandlerArcSlot::getArcSlotHintTable()
{
return {// Structure: {SelectMode, {hints...}}
{SelectMode::SeekFirst,
{{QObject::tr("%1 pick slot center"), {Gui::InputHint::UserInput::MouseLeft}}}},
{SelectMode::SeekSecond,
{{QObject::tr("%1 pick slot radius"), {Gui::InputHint::UserInput::MouseLeft}}}},
{SelectMode::SeekThird,
{{QObject::tr("%1 pick slot angle"), {Gui::InputHint::UserInput::MouseLeft}}}},
{SelectMode::SeekFourth,
{{QObject::tr("%1 pick slot width"), {Gui::InputHint::UserInput::MouseLeft}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerArcSlot::lookupArcSlotHints(SelectMode state)
{
const auto arcSlotHintTable = getArcSlotHintTable();
auto it = std::find_if(arcSlotHintTable.begin(),
arcSlotHintTable.end(),
[state](const HintEntry& entry) {
return entry.state == state;
});
return (it != arcSlotHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -95,10 +95,6 @@ public:
}
private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupBSplineHints(constructionMethod(), state());
}
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
{
prevCursorPosition = onSketchPos;
@@ -408,6 +404,48 @@ private:
sugConstraints[1].clear();
}
std::list<Gui::InputHint> getToolHints() const override
{
using State = std::pair<ConstructionMethod, SelectMode>;
using enum Gui::InputHint::UserInput;
const Gui::InputHint switchModeHint {tr("%1 switch mode"), {KeyM}};
return Gui::lookupHints<State>(
{constructionMethod(), state()},
{
// ControlPoints method
{.state = {ConstructionMethod::ControlPoints, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first control point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::ControlPoints, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick next control point"), {MouseLeft}},
{tr("%1 finish B-spline"), {MouseRight}},
switchModeHint,
}},
// Knots method
{.state = {ConstructionMethod::Knots, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first knot"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::Knots, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick next knot"), {MouseLeft}},
{tr("%1 finish B-spline"), {MouseRight}},
switchModeHint,
}},
});
}
std::string getToolName() const override
{
return "DSH_BSpline";
@@ -450,7 +488,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("B-spline parameters"));
return QString(tr("B-spline parameters"));
}
bool canGoToNextMode() override
@@ -792,21 +830,6 @@ private:
}
}
}
private:
struct HintEntry
{
ConstructionMethod method;
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static Gui::InputHint switchModeHint();
static HintTable getBSplineHintTable();
static std::list<Gui::InputHint> lookupBSplineHints(ConstructionMethod method,
SelectMode state);
};
template<>
@@ -1226,55 +1249,6 @@ void DSHBSplineController::addConstraints()
}
}
Gui::InputHint DrawSketchHandlerBSpline::switchModeHint()
{
return {QObject::tr("%1 switch mode"), {Gui::InputHint::UserInput::KeyM}};
}
DrawSketchHandlerBSpline::HintTable DrawSketchHandlerBSpline::getBSplineHintTable()
{
const auto switchHint = switchModeHint();
return {
// Structure: {ConstructionMethod, SelectMode, {hints...}}
// ControlPoints method
{ConstructionMethod::ControlPoints,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick first control point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethod::ControlPoints,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick next control point"), {Gui::InputHint::UserInput::MouseLeft}},
{QObject::tr("%1 finish B-spline"), {Gui::InputHint::UserInput::MouseRight}},
switchHint}},
// Knots method
{ConstructionMethod::Knots,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick first knot"), {Gui::InputHint::UserInput::MouseLeft}}, switchHint}},
{ConstructionMethod::Knots,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick next knot"), {Gui::InputHint::UserInput::MouseLeft}},
{QObject::tr("%1 finish B-spline"), {Gui::InputHint::UserInput::MouseRight}},
switchHint}}};
}
std::list<Gui::InputHint> DrawSketchHandlerBSpline::lookupBSplineHints(ConstructionMethod method,
SelectMode state)
{
const auto bSplineHintTable = getBSplineHintTable();
auto it = std::find_if(bSplineHintTable.begin(),
bSplineHintTable.end(),
[method, state](const HintEntry& entry) {
return entry.method == method && entry.state == state;
});
return (it != bSplineHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
// TODO: On pressing, say, W, modify last pole's weight
// TODO: On pressing, say, M, modify next knot's multiplicity
} // namespace SketcherGui

View File

@@ -223,8 +223,10 @@ private:
public:
std::list<Gui::InputHint> getToolHints() const override
{
return {{QObject::tr("%1 pick sketch to copy", "Sketcher CarbonCopy: hint"),
{Gui::InputHint::UserInput::MouseLeft}}};
return {
{tr("%1 pick sketch to copy", "Sketcher CarbonCopy: hint"),
{Gui::InputHint::UserInput::MouseLeft}},
};
}
};

View File

@@ -80,7 +80,48 @@ public:
private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupCircleHints(constructionMethod(), state());
using State = std::pair<ConstructionMethod, SelectMode>;
using enum Gui::InputHint::UserInput;
const Gui::InputHint switchModeHint = {tr("%1 switch mode"), {KeyM}};
return Gui::lookupHints<State>(
{constructionMethod(), state()},
{
// Center method
{.state = {ConstructionMethod::Center, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick circle center"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::Center, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick rim point"), {MouseLeft}},
switchModeHint,
}},
// ThreeRim method
{.state = {ConstructionMethod::ThreeRim, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first rim point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::ThreeRim, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick second rim point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::ThreeRim, SelectMode::SeekThird},
.hints =
{
{tr("%1 pick third rim point"), {MouseLeft}},
switchModeHint,
}},
});
}
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
@@ -266,7 +307,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Circle parameters"));
return QString(tr("Circle parameters"));
}
bool canGoToNextMode() override
@@ -308,19 +349,6 @@ private:
}
private:
struct HintEntry
{
ConstructionMethod method;
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static Gui::InputHint switchModeHint();
static HintTable getCircleHintTable();
static std::list<Gui::InputHint> lookupCircleHints(ConstructionMethod method, SelectMode state);
Base::Vector2d centerPoint, firstPoint, secondPoint;
double radius;
bool isDiameter;
@@ -742,54 +770,6 @@ void DSHCircleController::addConstraints()
// No constraint possible for 3 rim circle.
}
Gui::InputHint DrawSketchHandlerCircle::switchModeHint()
{
return {QObject::tr("%1 switch mode"), {Gui::InputHint::UserInput::KeyM}};
}
DrawSketchHandlerCircle::HintTable DrawSketchHandlerCircle::getCircleHintTable()
{
const auto switchHint = switchModeHint();
return {
// Structure: {ConstructionMethod, SelectMode, {hints...}}
// Center method
{ConstructionMethod::Center,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick circle center"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethod::Center,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick rim point"), {Gui::InputHint::UserInput::MouseLeft}}, switchHint}},
// ThreeRim method
{ConstructionMethod::ThreeRim,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick first rim point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethod::ThreeRim,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick second rim point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethod::ThreeRim,
SelectMode::SeekThird,
{{QObject::tr("%1 pick third rim point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}}};
}
std::list<Gui::InputHint> DrawSketchHandlerCircle::lookupCircleHints(ConstructionMethod method,
SelectMode state)
{
const auto circleHintTable = getCircleHintTable();
auto it = std::find_if(circleHintTable.begin(),
circleHintTable.end(),
[method, state](const HintEntry& entry) {
return entry.method == method && entry.state == state;
});
return (it != circleHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -84,22 +84,56 @@ public:
~DrawSketchHandlerEllipse() override = default;
private:
struct HintEntry
{
ConstructionMethod method;
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getEllipseHintTable();
static std::list<Gui::InputHint> lookupEllipseHints(ConstructionMethod method,
SelectMode state);
std::list<Gui::InputHint> getToolHints() const override
{
return lookupEllipseHints(constructionMethod(), state());
using State = std::pair<ConstructionMethod, SelectMode>;
using enum Gui::InputHint::UserInput;
const Gui::InputHint switchModeHint {tr("%1 switch mode"), {KeyM}};
return Gui::lookupHints<State>(
{constructionMethod(), state()},
{
// Center method
{.state = {ConstructionMethod::Center, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick ellipse center"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::Center, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick axis endpoint"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::Center, SelectMode::SeekThird},
.hints =
{
{tr("%1 pick minor axis endpoint"), {MouseLeft}},
switchModeHint,
}},
// ThreeRim method
{.state = {ConstructionMethod::ThreeRim, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first rim point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::ThreeRim, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick second rim point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::ThreeRim, SelectMode::SeekThird},
.hints =
{
{tr("%1 pick third rim point"), {MouseLeft}},
switchModeHint,
}},
});
}
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
@@ -291,7 +325,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Ellipse parameters"));
return QString(tr("Ellipse parameters"));
}
bool canGoToNextMode() override
@@ -978,48 +1012,6 @@ void DSHEllipseController::addConstraints()
}
// No constraint possible for 3 rim ellipse.
}
DrawSketchHandlerEllipse::HintTable DrawSketchHandlerEllipse::getEllipseHintTable()
{
return {
// Structure: {ConstructionMethod, SelectMode, {hints...}}
// Center method
{ConstructionMethod::Center,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick ellipse center"), {Gui::InputHint::UserInput::MouseLeft}}}},
{ConstructionMethod::Center,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick axis endpoint"), {Gui::InputHint::UserInput::MouseLeft}}}},
{ConstructionMethod::Center,
SelectMode::SeekThird,
{{QObject::tr("%1 pick minor axis endpoint"), {Gui::InputHint::UserInput::MouseLeft}}}},
// ThreeRim method
{ConstructionMethod::ThreeRim,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick first rim point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{ConstructionMethod::ThreeRim,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick second rim point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{ConstructionMethod::ThreeRim,
SelectMode::SeekThird,
{{QObject::tr("%1 pick third rim point"), {Gui::InputHint::UserInput::MouseLeft}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerEllipse::lookupEllipseHints(ConstructionMethod method,
SelectMode state)
{
const auto ellipseHintTable = getEllipseHintTable();
auto it = std::find_if(ellipseHintTable.begin(),
ellipseHintTable.end(),
[method, state](const HintEntry& entry) {
return entry.method == method && entry.state == state;
});
return (it != ellipseHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -373,22 +373,25 @@ protected:
double Increment;
std::vector<AutoConstraint> SugConstr;
// Add hint structures here
struct HintEntry
{
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getExtendHintTable();
static std::list<Gui::InputHint> lookupExtendHints(SelectMode state);
public:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupExtendHints(Mode);
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
Mode,
{
{.state = STATUS_SEEK_First,
.hints =
{
{tr("%1 pick edge to extend", "Sketcher Extend: hint"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Second,
.hints =
{
{tr("%1 set extension length", "Sketcher Extend: hint"), {MouseLeft}},
}},
});
}
private:
@@ -398,29 +401,6 @@ private:
}
};
DrawSketchHandlerExtend::HintTable DrawSketchHandlerExtend::getExtendHintTable()
{
using enum Gui::InputHint::UserInput;
return {
{.state = STATUS_SEEK_First,
.hints = {{QObject::tr("%1 pick edge to extend", "Sketcher Extend: hint"), {MouseLeft}}}},
{.state = STATUS_SEEK_Second,
.hints = {
{QObject::tr("%1 set extension length", "Sketcher Extend: hint"), {MouseLeft}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerExtend::lookupExtendHints(SelectMode state)
{
const auto extendHintTable = getExtendHintTable();
auto it = std::ranges::find_if(extendHintTable, [state](const HintEntry& entry) {
return entry.state == state;
});
return (it != extendHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui
#endif // SKETCHERGUI_DrawSketchHandlerExtend_H

View File

@@ -248,8 +248,10 @@ private:
public:
std::list<Gui::InputHint> getToolHints() const override
{
return {{QObject::tr("%1 pick external geometry", "Sketcher External: hint"),
{Gui::InputHint::UserInput::MouseLeft}}};
return {
{tr("%1 pick external geometry", "Sketcher External: hint"),
{Gui::InputHint::UserInput::MouseLeft}},
};
}
};

View File

@@ -277,16 +277,14 @@ private:
catch (const Base::CADKernelError& e) {
if (e.getTranslatable()) {
Gui::TranslatedUserError(sketchgui,
QObject::tr("CAD Kernel Error"),
QObject::tr(e.getMessage().c_str()));
tr("CAD Kernel Error"),
tr(e.getMessage().c_str()));
}
Gui::Selection().clearSelection();
Gui::Command::abortCommand();
}
catch (const Base::ValueError& e) {
Gui::TranslatedUserError(sketchgui,
QObject::tr("Value Error"),
QObject::tr(e.getMessage().c_str()));
Gui::TranslatedUserError(sketchgui, tr("Value Error"), tr(e.getMessage().c_str()));
Gui::Selection().clearSelection();
Gui::Command::abortCommand();
}
@@ -347,7 +345,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Fillet/Chamfer parameters"));
return QString(tr("Fillet/Chamfer parameters"));
}
bool canGoToNextMode() override
@@ -411,21 +409,23 @@ private:
int vtId, geoId1, geoId2;
Base::Vector2d firstPos, secondPos;
struct HintEntry
{
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getFilletHintTable();
static std::list<Gui::InputHint> lookupFilletHints(SelectMode state);
public:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupFilletHints(state());
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
state(),
{
{.state = SelectMode::SeekFirst,
.hints = {{tr("%1 pick first edge or point", "Sketcher Fillet/Chamfer: hint"),
{MouseLeft}}}},
{.state = SelectMode::SeekSecond,
.hints = {{tr("%1 pick second edge", "Sketcher Fillet/Chamfer: hint"),
{MouseLeft}}}},
{.state = SelectMode::End,
.hints = {{tr("%1 create fillet", "Sketcher Fillet/Chamfer: hint"), {MouseLeft}}}},
});
}
};
@@ -474,33 +474,6 @@ void DSHFilletController::adaptDrawingToCheckboxChange(int checkboxindex, bool v
handler->updateCursor();
}
DrawSketchHandlerFillet::HintTable DrawSketchHandlerFillet::getFilletHintTable()
{
using enum Gui::InputHint::UserInput;
return {{.state = SelectMode::SeekFirst,
.hints = {{QObject::tr("%1 pick first edge or point", "Sketcher Fillet/Chamfer: hint"),
{MouseLeft}}}},
{.state = SelectMode::SeekSecond,
.hints = {{QObject::tr("%1 pick second edge", "Sketcher Fillet/Chamfer: hint"),
{MouseLeft}}}},
{.state = SelectMode::End,
.hints = {
{QObject::tr("%1 create fillet", "Sketcher Fillet/Chamfer: hint"), {MouseLeft}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerFillet::lookupFilletHints(SelectMode state)
{
const auto filletHintTable = getFilletHintTable();
auto it = std::ranges::find_if(filletHintTable, [state](const HintEntry& entry) {
return entry.state == state;
});
return (it != filletHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui
#endif // SKETCHERGUI_DrawSketchHandlerFillet_H

View File

@@ -214,7 +214,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Line parameters"));
return QString(tr("Line parameters"));
}
bool canGoToNextMode() override
@@ -258,21 +258,57 @@ private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupLineHints(static_cast<int>(constructionMethod()), static_cast<int>(state()));
using State = std::pair<ConstructionMethod, SelectMode>;
using enum Gui::InputHint::UserInput;
const Gui::InputHint switchModeHint {tr("%1 switch mode"), {KeyM}};
return Gui::lookupHints<State>(
{constructionMethod(), state()},
{
// OnePointLengthAngle method
{.state = {ConstructionMethod::OnePointLengthAngle, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::OnePointLengthAngle, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick second point"), {MouseLeft}},
switchModeHint,
}},
// OnePointWidthHeight method
{.state = {ConstructionMethod::OnePointWidthHeight, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::OnePointWidthHeight, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick second point"), {MouseLeft}},
switchModeHint,
}},
// TwoPoints method
{.state = {ConstructionMethod::TwoPoints, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first point"), {MouseLeft}},
switchModeHint,
}},
{.state = {ConstructionMethod::TwoPoints, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick second point"), {MouseLeft}},
switchModeHint,
}},
});
}
struct HintEntry
{
int constructionMethod;
int state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static Gui::InputHint switchModeHint();
static HintTable getLineHintTable();
static std::list<Gui::InputHint> lookupLineHints(int method, int state);
};
template<>
@@ -802,66 +838,6 @@ void DSHLineController::addConstraints()
}
}
Gui::InputHint DrawSketchHandlerLine::switchModeHint()
{
return {QObject::tr("%1 switch mode"), {Gui::InputHint::UserInput::KeyM}};
}
DrawSketchHandlerLine::HintTable DrawSketchHandlerLine::getLineHintTable()
{
const auto switchHint = switchModeHint();
return {// Structure: {constructionMethod, state, {hints...}}
// OnePointLengthAngle (0)
{0,
0,
{// SeekFirst
{QObject::tr("%1 pick first point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{0,
1,
{// SeekSecond
{QObject::tr("%1 pick second point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
// OnePointWidthHeight (1)
{1,
0,
{// SeekFirst
{QObject::tr("%1 pick first point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{1,
1,
{// SeekSecond
{QObject::tr("%1 pick second point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
// TwoPoints (2)
{2,
0,
{// SeekFirst
{QObject::tr("%1 pick first point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{2,
1,
{// SeekSecond
{QObject::tr("%1 pick second point"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}}};
}
std::list<Gui::InputHint> DrawSketchHandlerLine::lookupLineHints(int method, int state)
{
const auto lineHintTable = getLineHintTable();
auto it = std::find_if(lineHintTable.begin(),
lineHintTable.end(),
[method, state](const HintEntry& entry) {
return entry.constructionMethod == method && entry.state == state;
});
return (it != lineHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -760,17 +760,6 @@ public:
}
private:
struct HintEntry
{
int mode;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getLineSetHintTable();
static std::list<Gui::InputHint> lookupLineSetHints(int mode);
QString getCrosshairCursorSVGName() const override
{
return QStringLiteral("Sketcher_Pointer_Create_Lineset");
@@ -778,7 +767,26 @@ private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupLineSetHints(Mode);
using enum Gui::InputHint::UserInput;
// clang-format off
return Gui::lookupHints<SELECT_MODE>(
Mode,
{
{.state = STATUS_SEEK_First,
.hints =
{
{tr("%1 pick first point"), {MouseLeft}},
}},
{.state = STATUS_SEEK_Second,
.hints =
{
{tr("%1 pick next point"), {MouseLeft}},
{tr("%1 finish"), {MouseRight}},
{tr("%1 switch mode"), {KeyM}},
}},
});
// clang-format on
}
protected:
@@ -840,30 +848,6 @@ protected:
dirVec.Normalize();
}
};
DrawSketchHandlerLineSet::HintTable DrawSketchHandlerLineSet::getLineSetHintTable()
{
return {// Structure: {mode, {hints...}}
{STATUS_SEEK_First,
{{QObject::tr("%1 pick first point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{STATUS_SEEK_Second,
{{QObject::tr("%1 pick next point"), {Gui::InputHint::UserInput::MouseLeft}},
{QObject::tr("%1 finish"), {Gui::InputHint::UserInput::MouseRight}},
{QObject::tr("%1 switch mode"), {Gui::InputHint::UserInput::KeyM}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerLineSet::lookupLineSetHints(int mode)
{
const auto lineSetHintTable = getLineSetHintTable();
auto it = std::find_if(lineSetHintTable.begin(),
lineSetHintTable.end(),
[mode](const HintEntry& entry) {
return entry.mode == mode;
});
return (it != lineSetHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -179,7 +179,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Offset parameters"));
return QString(tr("Offset parameters"));
}
void activated() override
@@ -196,8 +196,9 @@ public:
{
using enum Gui::InputHint::UserInput;
return {{QObject::tr("%1 set offset direction and distance", "Sketcher Offset: hint"),
{MouseLeft}}};
return {
{tr("%1 set offset direction and distance", "Sketcher Offset: hint"), {MouseLeft}},
};
}
private:

View File

@@ -66,7 +66,9 @@ private:
std::list<Gui::InputHint> getToolHints() const override
{
using enum Gui::InputHint::UserInput;
return {{QObject::tr("%1 place a point", "Sketcher Point: hint"), {MouseLeft}}};
return {
{tr("%1 place a point", "Sketcher Point: hint"), {MouseLeft}},
};
}
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override

View File

@@ -200,7 +200,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Polygon parameters"));
return QString(tr("Polygon parameters"));
}
bool canGoToNextMode() override
@@ -265,20 +265,26 @@ private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupPolygonHints(state());
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
state(),
{
{.state = SelectMode::SeekFirst,
.hints =
{
{tr("%1 pick polygon center"), {MouseLeft}},
{tr("%1/%2 increase / decrease number of sides"), {KeyU, KeyJ}},
}},
{.state = SelectMode::SeekSecond,
.hints =
{
{tr("%1 pick rotation and size"), {MouseMove}},
{tr("%1 confirm"), {MouseLeft}},
{tr("%1/%2 increase / decrease number of sides"), {KeyU, KeyJ}},
}},
});
}
private:
struct HintEntry
{
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getPolygonHintTable();
static std::list<Gui::InputHint> lookupPolygonHints(SelectMode state);
};
template<>
@@ -558,33 +564,6 @@ void DSHPolygonController::addConstraints()
}
}
DrawSketchHandlerPolygon::HintTable DrawSketchHandlerPolygon::getPolygonHintTable()
{
return {// Structure: {SelectMode, {hints...}}
{SelectMode::SeekFirst,
{{QObject::tr("%1 pick polygon center"), {Gui::InputHint::UserInput::MouseLeft}},
{QObject::tr("%1/%2 increase / decrease number of sides"),
{Gui::InputHint::UserInput::KeyU, Gui::InputHint::UserInput::KeyJ}}}},
{SelectMode::SeekSecond,
{{QObject::tr("%1 pick rotation and size"), {Gui::InputHint::UserInput::MouseMove}},
{QObject::tr("%1 confirm"), {Gui::InputHint::UserInput::MouseLeft}},
{QObject::tr("%1/%2 increase / decrease number of sides"),
{Gui::InputHint::UserInput::KeyU, Gui::InputHint::UserInput::KeyJ}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerPolygon::lookupPolygonHints(SelectMode state)
{
const auto polygonHintTable = getPolygonHintTable();
auto it = std::find_if(polygonHintTable.begin(),
polygonHintTable.end(),
[state](const HintEntry& entry) {
return entry.state == state;
});
return (it != polygonHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -111,23 +111,121 @@ public:
private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupRectangleHints(constructionMethod(), state());
using State = std::pair<ConstructionMethod, SelectMode>;
using enum Gui::InputHint::UserInput;
const Gui::InputHint switchHint {.message = tr("%1 switch mode"), .sequences = {KeyM}};
return Gui::lookupHints<State>(
{constructionMethod(), state()},
{
// Diagonal method
{.state = {ConstructionMethod::Diagonal, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first corner"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::Diagonal, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick opposite corner"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::Diagonal, SelectMode::SeekThird},
.hints =
{
{tr("%1 set corner radius or frame thickness"), {MouseMove}},
switchHint,
}},
{.state = {ConstructionMethod::Diagonal, SelectMode::SeekFourth},
.hints =
{
{tr("%1 set frame thickness"), {MouseMove}},
switchHint,
}},
// CenterAndCorner method
{.state = {ConstructionMethod::CenterAndCorner, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick center"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::CenterAndCorner, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick corner"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::CenterAndCorner, SelectMode::SeekThird},
.hints =
{
{tr("%1 set corner radius or frame thickness"), {MouseMove}},
switchHint,
}},
{.state = {ConstructionMethod::CenterAndCorner, SelectMode::SeekFourth},
.hints =
{
{tr("%1 set frame thickness"), {MouseMove}},
switchHint,
}},
// ThreePoints method
{.state = {ConstructionMethod::ThreePoints, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick first corner"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::ThreePoints, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick second corner"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::ThreePoints, SelectMode::SeekThird},
.hints =
{
{tr("%1 pick third corner"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::ThreePoints, SelectMode::SeekFourth},
.hints =
{
{tr("%1 set corner radius or frame thickness"), {MouseMove}},
switchHint,
}},
// CenterAnd3Points method
{.state = {ConstructionMethod::CenterAnd3Points, SelectMode::SeekFirst},
.hints =
{
{tr("%1 pick center"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::CenterAnd3Points, SelectMode::SeekSecond},
.hints =
{
{tr("%1 pick first corner"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::CenterAnd3Points, SelectMode::SeekThird},
.hints =
{
{tr("%1 pick second corner"), {MouseLeft}},
switchHint,
}},
{.state = {ConstructionMethod::CenterAnd3Points, SelectMode::SeekFourth},
.hints =
{
{tr("%1 set corner radius or frame thickness"), {MouseMove}},
switchHint,
}},
});
}
private:
struct HintEntry
{
ConstructionMethods::RectangleConstructionMethod method;
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static Gui::InputHint switchModeHint();
static HintTable getRectangleHintTable();
static std::list<Gui::InputHint>
lookupRectangleHints(ConstructionMethods::RectangleConstructionMethod method, SelectMode state);
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
{
using std::numbers::pi;
@@ -605,7 +703,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Rectangle parameters"));
return QString(tr("Rectangle parameters"));
}
void angleSnappingControl() override
@@ -2675,104 +2773,6 @@ void DSHRectangleController::doConstructionMethodChanged()
handler->updateHint();
}
Gui::InputHint DrawSketchHandlerRectangle::switchModeHint()
{
return {QObject::tr("%1 switch mode"), {Gui::InputHint::UserInput::KeyM}};
}
DrawSketchHandlerRectangle::HintTable DrawSketchHandlerRectangle::getRectangleHintTable()
{
const auto switchHint = switchModeHint();
return {// Structure: {ConstructionMethod, SelectMode, {hints...}}
// Diagonal method
{ConstructionMethods::RectangleConstructionMethod::Diagonal,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick first corner"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethods::RectangleConstructionMethod::Diagonal,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick opposite corner"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethods::RectangleConstructionMethod::Diagonal,
SelectMode::SeekThird,
{{QObject::tr("%1 set corner radius or frame thickness"),
{Gui::InputHint::UserInput::MouseMove}},
switchHint}},
{ConstructionMethods::RectangleConstructionMethod::Diagonal,
SelectMode::SeekFourth,
{{QObject::tr("%1 set frame thickness"), {Gui::InputHint::UserInput::MouseMove}},
switchHint}},
// CenterAndCorner method
{ConstructionMethods::RectangleConstructionMethod::CenterAndCorner,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick center"), {Gui::InputHint::UserInput::MouseLeft}}, switchHint}},
{ConstructionMethods::RectangleConstructionMethod::CenterAndCorner,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick corner"), {Gui::InputHint::UserInput::MouseLeft}}, switchHint}},
{ConstructionMethods::RectangleConstructionMethod::CenterAndCorner,
SelectMode::SeekThird,
{{QObject::tr("%1 set corner radius or frame thickness"),
{Gui::InputHint::UserInput::MouseMove}},
switchHint}},
{ConstructionMethods::RectangleConstructionMethod::CenterAndCorner,
SelectMode::SeekFourth,
{{QObject::tr("%1 set frame thickness"), {Gui::InputHint::UserInput::MouseMove}},
switchHint}},
// ThreePoints method
{ConstructionMethods::RectangleConstructionMethod::ThreePoints,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick first corner"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethods::RectangleConstructionMethod::ThreePoints,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick second corner"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethods::RectangleConstructionMethod::ThreePoints,
SelectMode::SeekThird,
{{QObject::tr("%1 pick third corner"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethods::RectangleConstructionMethod::ThreePoints,
SelectMode::SeekFourth,
{{QObject::tr("%1 set corner radius or frame thickness"),
{Gui::InputHint::UserInput::MouseMove}},
switchHint}},
// CenterAnd3Points method
{ConstructionMethods::RectangleConstructionMethod::CenterAnd3Points,
SelectMode::SeekFirst,
{{QObject::tr("%1 pick center"), {Gui::InputHint::UserInput::MouseLeft}}, switchHint}},
{ConstructionMethods::RectangleConstructionMethod::CenterAnd3Points,
SelectMode::SeekSecond,
{{QObject::tr("%1 pick first corner"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethods::RectangleConstructionMethod::CenterAnd3Points,
SelectMode::SeekThird,
{{QObject::tr("%1 pick second corner"), {Gui::InputHint::UserInput::MouseLeft}},
switchHint}},
{ConstructionMethods::RectangleConstructionMethod::CenterAnd3Points,
SelectMode::SeekFourth,
{{QObject::tr("%1 set corner radius or frame thickness"),
{Gui::InputHint::UserInput::MouseMove}},
switchHint}}};
}
std::list<Gui::InputHint> DrawSketchHandlerRectangle::lookupRectangleHints(
ConstructionMethods::RectangleConstructionMethod method,
SelectMode state)
{
const auto rectangleHintTable = getRectangleHintTable();
auto it = std::find_if(rectangleHintTable.begin(),
rectangleHintTable.end(),
[method, state](const HintEntry& entry) {
return entry.method == method && entry.state == state;
});
return (it != rectangleHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -83,6 +83,31 @@ public:
~DrawSketchHandlerRotate() override = default;
std::list<Gui::InputHint> getToolHints() const override
{
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
state(),
{
{.state = SelectMode::SeekFirst,
.hints =
{
{tr("%1 pick center point", "Sketcher Rotate: hint"), {MouseLeft}},
}},
{.state = SelectMode::SeekSecond,
.hints =
{
{tr("%1 set start angle", "Sketcher Rotate: hint"), {MouseLeft}},
}},
{.state = SelectMode::SeekThird,
.hints =
{
{tr("%1 set rotation angle", "Sketcher Rotate: hint"), {MouseLeft}},
}},
});
}
private:
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
{
@@ -175,7 +200,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Rotate parameters"));
return QString(tr("Rotate parameters"));
}
void activated() override
@@ -455,49 +480,8 @@ private:
return pointToRotate;
}
struct HintEntry
{
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getRotateHintTable();
static std::list<Gui::InputHint> lookupRotateHints(SelectMode state);
public:
std::list<Gui::InputHint> 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<Gui::InputHint> 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<Gui::InputHint> {};
}
template<>
auto DSHRotateControllerBase::getState(int labelindex) const
{

View File

@@ -135,7 +135,22 @@ public:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupScaleHints(state());
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
state(),
{
{.state = SelectMode::SeekFirst,
.hints =
{
{tr("%1 pick reference point"), {MouseLeft}},
}},
{.state = SelectMode::SeekSecond,
.hints =
{
{tr("%1 set scale factor"), {MouseLeft}},
}},
});
}
private:
@@ -196,7 +211,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Scale parameters"));
return QString(tr("Scale parameters"));
}
void activated() override
@@ -235,18 +250,6 @@ private:
bool allowOriginConstraint; // Conserve constraints with origin
double refLength, length, scaleFactor;
struct HintEntry
{
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getScaleHintTable();
static std::list<Gui::InputHint> lookupScaleHints(SelectMode state);
void deleteOriginalGeos()
{
std::stringstream stream;
@@ -487,30 +490,6 @@ 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<Gui::InputHint> 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<Gui::InputHint> {};
}
template<>
auto DSHScaleControllerBase::getState(int labelindex) const
{

View File

@@ -83,7 +83,27 @@ public:
private:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupSlotHints(state());
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
state(),
{
{.state = SelectMode::SeekFirst,
.hints =
{
{tr("%1 pick slot start point"), {MouseLeft}},
}},
{.state = SelectMode::SeekSecond,
.hints =
{
{tr("%1 pick slot end point"), {MouseLeft}},
}},
{.state = SelectMode::SeekThird,
.hints =
{
{tr("%1 pick slot width"), {MouseLeft}},
}},
});
}
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
@@ -349,17 +369,6 @@ private:
double radius, length, angle;
bool isHorizontal, isVertical;
int firstCurve;
struct HintEntry
{
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getSlotHintTable();
static std::list<Gui::InputHint> lookupSlotHints(SelectMode state);
};
template<>
@@ -706,29 +715,6 @@ void DSHSlotController::addConstraints()
}
}
DrawSketchHandlerSlot::HintTable DrawSketchHandlerSlot::getSlotHintTable()
{
return {// Structure: {SelectMode, {hints...}}
{SelectMode::SeekFirst,
{{QObject::tr("%1 pick slot start point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{SelectMode::SeekSecond,
{{QObject::tr("%1 pick slot end point"), {Gui::InputHint::UserInput::MouseLeft}}}},
{SelectMode::SeekThird,
{{QObject::tr("%1 set slot radius"), {Gui::InputHint::UserInput::MouseMove}}}}};
}
std::list<Gui::InputHint> DrawSketchHandlerSlot::lookupSlotHints(SelectMode state)
{
const auto slotHintTable = getSlotHintTable();
auto it =
std::find_if(slotHintTable.begin(), slotHintTable.end(), [state](const HintEntry& entry) {
return entry.state == state;
});
return (it != slotHintTable.end()) ? it->hints : std::list<Gui::InputHint> {};
}
} // namespace SketcherGui

View File

@@ -200,8 +200,10 @@ private:
public:
std::list<Gui::InputHint> getToolHints() const override
{
return {{QObject::tr("%1 pick location on edge to split", "Sketcher Splitting: hint"),
{Gui::InputHint::UserInput::MouseLeft}}};
return {
{tr("%1 pick location on edge to split", "Sketcher Splitting: hint"),
{Gui::InputHint::UserInput::MouseLeft}},
};
}
};

View File

@@ -191,7 +191,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Symmetry parameters"));
return QString(tr("Symmetry parameters"));
}
void activated() override
@@ -221,7 +221,8 @@ public:
using enum Gui::InputHint::UserInput;
return {
{QObject::tr("%1 pick axis, edge, or point", "Sketcher Symmetry: hint"), {MouseLeft}}};
{tr("%1 pick axis, edge, or point", "Sketcher Symmetry: hint"), {MouseLeft}},
};
}
void deleteOriginalGeos()

View File

@@ -172,7 +172,7 @@ private:
QString getToolWidgetText() const override
{
return QString(QObject::tr("Translate parameters"));
return QString(tr("Translate parameters"));
}
void onButtonPressed(Base::Vector2d onSketchPos) override
@@ -427,50 +427,24 @@ private:
}
}
struct HintEntry
{
SelectMode state;
std::list<Gui::InputHint> hints;
};
using HintTable = std::vector<HintEntry>;
static HintTable getTranslateHintTable();
static std::list<Gui::InputHint> lookupTranslateHints(SelectMode state);
public:
std::list<Gui::InputHint> getToolHints() const override
{
return lookupTranslateHints(state());
using enum Gui::InputHint::UserInput;
return Gui::lookupHints<SelectMode>(
state(),
{{.state = SelectMode::SeekFirst,
.hints = {{tr("%1 pick reference point", "Sketcher Translate: hint"), {MouseLeft}}}},
{.state = SelectMode::SeekSecond,
.hints = {{tr("%1 set translation vector", "Sketcher Translate: hint"),
{MouseLeft}}}},
{.state = SelectMode::SeekThird,
.hints = {{tr("%1 set second translation vector", "Sketcher Translate: hint"),
{MouseLeft}}}}});
}
};
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<Gui::InputHint> 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<Gui::InputHint> {};
}
template<>
auto DSHTranslateControllerBase::getState(int labelindex) const
{

View File

@@ -212,8 +212,10 @@ private:
public:
std::list<Gui::InputHint> getToolHints() const override
{
return {{QObject::tr("%1 pick edge to trim", "Sketcher Trimming: hint"),
{Gui::InputHint::UserInput::MouseLeft}}};
return {
{tr("%1 pick edge to trim", "Sketcher Trimming: hint"),
{Gui::InputHint::UserInput::MouseLeft}},
};
}
};

View File

@@ -5,12 +5,12 @@ add_executable(Gui_tests_run
StyleParameters/StyleParametersApplicationTest.cpp
StyleParameters/ParserTest.cpp
StyleParameters/ParameterManagerTest.cpp
InputHintTest.cpp
)
# Qt tests
setup_qt_test(QuantitySpinBox)
target_link_libraries(Gui_tests_run PRIVATE
GTest::gtest_main
GTest::gmock_main

View File

@@ -0,0 +1,85 @@
#include <gtest/gtest.h>
#include "Gui/InputHint.h"
using namespace Gui;
using enum InputHint::UserInput;
class InputHintTest: public ::testing::Test
{
protected:
enum class State : std::uint8_t
{
SeekFirst,
SeekSecond
};
enum class Method : std::uint8_t
{
FirstMethod,
SecondMethod
};
using StateMethod = std::pair<State, Method>;
// Constants for hints
static const InputHint firstHint;
static const InputHint secondHint;
static const InputHint firstMethodHint;
static const InputHint secondMethodHint;
static const InputHint thirdMethodHint;
static const InputHint fourthMethodHint;
};
// Define the constants
const InputHint InputHintTest::firstHint = {QString("First hint"), {{KeySpace}}};
const InputHint InputHintTest::secondHint = {QString("Second hint"), {{KeyEnter}}};
const InputHint InputHintTest::firstMethodHint = {QString("First method hint"), {{KeyA}}};
const InputHint InputHintTest::secondMethodHint = {QString("Second method hint"), {{KeyB}}};
const InputHint InputHintTest::thirdMethodHint = {QString("Third method hint"), {{KeyC}}};
const InputHint InputHintTest::fourthMethodHint = {QString("Fourth method hint"), {{KeyD}}};
TEST_F(InputHintTest, LookupHintsSimpleState)
{
// Arrange
std::list<InputHint> hintsSeekFirst = {firstHint};
std::list<InputHint> hintsSeekSecond = {secondHint};
HintTable<State> table = {{.state = State::SeekFirst, .hints = hintsSeekFirst},
{.state = State::SeekSecond, .hints = hintsSeekSecond}};
// Act
auto resultFirst = lookupHints(State::SeekFirst, table);
auto resultSecond = lookupHints(State::SeekSecond, table);
// Assert
EXPECT_EQ(resultFirst, hintsSeekFirst);
EXPECT_EQ(resultSecond, hintsSeekSecond);
}
TEST_F(InputHintTest, LookupHintsPairState)
{
// Arrange
std::list<InputHint> firstFirstHints = {firstMethodHint};
std::list<InputHint> firstSecondHints = {secondMethodHint};
std::list<InputHint> secondFirstHints = {thirdMethodHint};
std::list<InputHint> secondSecondHints = {fourthMethodHint};
HintTable<StateMethod> table = {
{.state = {State::SeekFirst, Method::FirstMethod}, .hints = firstFirstHints},
{.state = {State::SeekFirst, Method::SecondMethod}, .hints = firstSecondHints},
{.state = {State::SeekSecond, Method::FirstMethod}, .hints = secondFirstHints},
{.state = {State::SeekSecond, Method::SecondMethod}, .hints = secondSecondHints}};
// Act
auto resultFirstFirst = lookupHints({State::SeekFirst, Method::FirstMethod}, table);
auto resultFirstSecond = lookupHints({State::SeekFirst, Method::SecondMethod}, table);
auto resultSecondFirst = lookupHints({State::SeekSecond, Method::FirstMethod}, table);
auto resultSecondSecond = lookupHints({State::SeekSecond, Method::SecondMethod}, table);
// Assert
EXPECT_EQ(resultFirstFirst, firstFirstHints);
EXPECT_EQ(resultFirstSecond, firstSecondHints);
EXPECT_EQ(resultSecondFirst, secondFirstHints);
EXPECT_EQ(resultSecondSecond, secondSecondHints);
}