Sketcher: Text: Fixes
This commit is contained in:
@@ -7507,7 +7507,7 @@ void transformAndConvertToGeometry(
|
||||
double baseHeight = ymax - ymin;
|
||||
|
||||
// This transform will move the geometry's bottom-left corner to the origin (0,0,0)
|
||||
gp_Vec initialTranslationVec(-xmin, -ymin, -zmin);
|
||||
gp_Vec initialTranslationVec(-xmin, -ymin, 0.0);
|
||||
|
||||
// 2. Determine scale and rotation
|
||||
double angle;
|
||||
@@ -7536,7 +7536,7 @@ void transformAndConvertToGeometry(
|
||||
gp_Trsf rotateTrsf;
|
||||
rotateTrsf.SetRotation(gp::XOY().Axis(), angle);
|
||||
gp_Trsf finalTranslate;
|
||||
finalTranslate.SetTranslation(gp_Vec(p1.x, p1.y, p1.z));
|
||||
finalTranslate.SetTranslation(gp_Vec(p1.x, p1.y, 0.0));
|
||||
gp_Trsf finalTrsf = finalTranslate * rotateTrsf * scaleTrsf * initialTranslate;
|
||||
|
||||
// 4. Apply transformation and convert to Sketcher geometry
|
||||
|
||||
@@ -5662,7 +5662,7 @@ void Sketch::applyGroupTransformations()
|
||||
Base::Matrix4D T2; // Identity
|
||||
T2[0][3] = postSolveFrame.startPoint.x;
|
||||
T2[1][3] = postSolveFrame.startPoint.y;
|
||||
T2[2][3] = postSolveFrame.startPoint.z;
|
||||
T2[2][3] = 0;
|
||||
|
||||
// 5. Combine the matrices in the correct order: T_final = T2 * R * S * T1
|
||||
Base::Matrix4D transform = T2 * R * S * T1;
|
||||
|
||||
@@ -906,7 +906,7 @@ double SketchObject::getDatum(int ConstrId) const
|
||||
return this->Constraints[ConstrId]->getValue();
|
||||
}
|
||||
|
||||
int SketchObject::setTextAndFont(int ConstrId, std::string& newText, std::string& newFont, bool isConstruction)
|
||||
int SketchObject::setTextAndFont(int ConstrId, std::string& newText, std::string& newFont, bool isHeight, bool isConstruction)
|
||||
{
|
||||
; // no need to check input data validity as this is an sketchobject managed operation.
|
||||
Base::StateLocker lock(managedoperation, true);
|
||||
@@ -926,9 +926,9 @@ int SketchObject::setTextAndFont(int ConstrId, std::string& newText, std::string
|
||||
}
|
||||
|
||||
// First we replace the old geometries by the new text.
|
||||
const bool isHeight = constr->getIsTextHeight();
|
||||
const std::string oldText = constr->getText();
|
||||
const std::string oldFont = constr->getFont();
|
||||
const bool oldIsHeight = constr->getIsTextHeight();
|
||||
int handleGeoId = constr->getGeoId(0);
|
||||
int firstTextGeoId = constr->getGeoId(1);
|
||||
bool hasExistingText = firstTextGeoId != GeoEnum::GeoUndef;
|
||||
@@ -1012,6 +1012,7 @@ int SketchObject::setTextAndFont(int ConstrId, std::string& newText, std::string
|
||||
if (err) {
|
||||
constr->setText(oldText);
|
||||
constr->setFont(oldFont);
|
||||
constr->setIsTextHeight(oldIsHeight);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
@@ -358,6 +358,7 @@ public:
|
||||
int ConstrId,
|
||||
std::string& newText,
|
||||
std::string& newFont,
|
||||
bool isHeight,
|
||||
bool isConstruction = false
|
||||
);
|
||||
/// set the driving status of this constraint and solve
|
||||
|
||||
@@ -409,16 +409,20 @@ class SketchObject(Part2DObject):
|
||||
"""
|
||||
...
|
||||
|
||||
def setTextAndFont(self, constraint: int, text: str, font: str) -> None:
|
||||
def setTextAndFont(
|
||||
self, constraint: int, text: str, font: str, isheight: bool, isConstruction: bool
|
||||
) -> None:
|
||||
"""
|
||||
Set the text and font of a Text constraint.
|
||||
|
||||
setTextAndFont(constraint: int, text: str, font: str)
|
||||
setTextAndFont(constraint: int, text: str, font: str, isHeight: bool, isConstruction: bool)
|
||||
|
||||
Args:
|
||||
constraint: The index of the Text constraint.
|
||||
text: The text string to display.
|
||||
font: The full path to the font file (.ttf, .otf, etc.).
|
||||
isHeight: Is the line handle of the group the height of the text.
|
||||
isConstruction: Are text geometry construction of not.
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
@@ -761,11 +761,21 @@ PyObject* SketchObjectPy::setTextAndFont(PyObject* args, PyObject* kwd)
|
||||
int constrIndex = -1;
|
||||
char* textStr;
|
||||
char* fontStr;
|
||||
char* constrName = nullptr;
|
||||
PyObject* isHeightObj = Py_True;
|
||||
PyObject* isConstrObj = Py_False; // Default to null (parameter not provided)
|
||||
|
||||
// "iss|O" means: int, string, string, | optional Object
|
||||
if (!PyArg_ParseTuple(args, "iss|O!", &constrIndex, &textStr, &fontStr, &PyBool_Type, &isConstrObj)) {
|
||||
// "iss|O!O!" (int, str, str, | bool, bool)
|
||||
if (!PyArg_ParseTuple(
|
||||
args,
|
||||
"iss|O!O!",
|
||||
&constrIndex,
|
||||
&textStr,
|
||||
&fontStr,
|
||||
&PyBool_Type,
|
||||
&isHeightObj,
|
||||
&PyBool_Type,
|
||||
&isConstrObj
|
||||
)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -773,8 +783,13 @@ PyObject* SketchObjectPy::setTextAndFont(PyObject* args, PyObject* kwd)
|
||||
std::string font(fontStr);
|
||||
|
||||
// Call the C++ implementation
|
||||
int err = this->getSketchObjectPtr()
|
||||
->setTextAndFont(constrIndex, text, font, Base::asBoolean(isConstrObj));
|
||||
int err = this->getSketchObjectPtr()->setTextAndFont(
|
||||
constrIndex,
|
||||
text,
|
||||
font,
|
||||
Base::asBoolean(isHeightObj),
|
||||
Base::asBoolean(isConstrObj)
|
||||
);
|
||||
|
||||
// Handle errors returned from the C++ function
|
||||
if (err) {
|
||||
|
||||
@@ -54,20 +54,20 @@ enum class FilterValue
|
||||
Equality = 9,
|
||||
Symmetric = 10,
|
||||
Block = 11,
|
||||
InternalAlignment = 12,
|
||||
Datums = 13,
|
||||
HorizontalDistance = 14,
|
||||
VerticalDistance = 15,
|
||||
Distance = 16,
|
||||
Radius = 17,
|
||||
Weight = 18,
|
||||
Diameter = 19,
|
||||
Angle = 20,
|
||||
SnellsLaw = 21,
|
||||
Named = 22,
|
||||
NonDriving = 23,
|
||||
Group = 24,
|
||||
Text = 25,
|
||||
Group = 12,
|
||||
Text = 13,
|
||||
InternalAlignment = 14,
|
||||
Datums = 15,
|
||||
HorizontalDistance = 16,
|
||||
VerticalDistance = 17,
|
||||
Distance = 18,
|
||||
Radius = 19,
|
||||
Weight = 20,
|
||||
Diameter = 21,
|
||||
Angle = 22,
|
||||
SnellsLaw = 23,
|
||||
Named = 24,
|
||||
NonDriving = 25,
|
||||
NumFilterValue // SpecialFilterValue shall start at the same index as this
|
||||
};
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ private:
|
||||
std::string escFont = escapeForPython(font);
|
||||
bool isHeight = constructionMethod() == ConstructionMethod::Height;
|
||||
const char* constrBoolStr = isConstructionMode() ? "True" : "False";
|
||||
const char* heightBoolStr = isHeight ? "True" : "False";
|
||||
|
||||
// Add the 'Text' Constraint (Empty)
|
||||
// We initialize the constraint containing ONLY the handle (element 0).
|
||||
@@ -156,7 +157,7 @@ private:
|
||||
handleId,
|
||||
escText.c_str(),
|
||||
escFont.c_str(),
|
||||
isHeight ? "True" : "False"
|
||||
heightBoolStr
|
||||
);
|
||||
|
||||
// Generate Text Geometry by calling setTextAndFont on the new constraint.
|
||||
@@ -165,10 +166,11 @@ private:
|
||||
Gui::cmdAppObjectArgs(
|
||||
getSketchObject(),
|
||||
"setTextAndFont(len(App.ActiveDocument.getObject('%s').Constraints)-1, '%s', '%s', "
|
||||
"%s)",
|
||||
"%s, %s)",
|
||||
getSketchObject()->getNameInDocument(),
|
||||
escText.c_str(),
|
||||
escFont.c_str(),
|
||||
heightBoolStr,
|
||||
constrBoolStr
|
||||
);
|
||||
|
||||
@@ -383,7 +385,10 @@ void DSHTextController::configureToolWidget()
|
||||
|
||||
// 3. Set a sensible default font
|
||||
QString defaultFontName;
|
||||
if (fontNames.contains(QString::fromUtf8("DejaVu Sans"), Qt::CaseInsensitive)) {
|
||||
if (fontNames.contains(QString::fromUtf8("osifont-lgpl3fe"), Qt::CaseInsensitive)) {
|
||||
defaultFontName = QString::fromUtf8("osifont-lgpl3fe");
|
||||
}
|
||||
else if (fontNames.contains(QString::fromUtf8("DejaVu Sans"), Qt::CaseInsensitive)) {
|
||||
defaultFontName = QString::fromUtf8("DejaVu Sans");
|
||||
}
|
||||
else if (fontNames.contains(QString::fromUtf8("Arial"), Qt::CaseInsensitive)) {
|
||||
|
||||
@@ -53,6 +53,9 @@ EditTextDialog::EditTextDialog(ViewProviderSketch* viewProvider, int constraintI
|
||||
// Initialize Text
|
||||
ui->lineEdit_text->setText(QString::fromStdString(constraint->getText()));
|
||||
|
||||
ui->radioButton_height->setChecked(constraint->getIsTextHeight());
|
||||
ui->radioButton_width->setChecked(!constraint->getIsTextHeight());
|
||||
|
||||
// Initialize Font
|
||||
populateFontList();
|
||||
QString currentFontName = findFontNameFromPath(QString::fromStdString(constraint->getFont()));
|
||||
@@ -87,11 +90,13 @@ void EditTextDialog::on_buttonBox_accepted()
|
||||
std::string newText = ui->lineEdit_text->text().toStdString();
|
||||
QString selectedFontName = ui->comboBox_font->currentText();
|
||||
std::string newFontPath = fontPathMap.value(selectedFontName).toStdString();
|
||||
bool newIsHeight = ui->radioButton_height->isChecked();
|
||||
|
||||
const Sketcher::Constraint* constraint = sketch->Constraints[constrIndex];
|
||||
|
||||
// Check if anything changed
|
||||
if (newText == constraint->getText() && newFontPath == constraint->getFont()) {
|
||||
if (newText == constraint->getText() && newFontPath == constraint->getFont()
|
||||
&& newIsHeight == constraint->getIsTextHeight()) {
|
||||
return; // Nothing to do
|
||||
}
|
||||
|
||||
@@ -99,7 +104,25 @@ void EditTextDialog::on_buttonBox_accepted()
|
||||
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Modify sketch text constraint"));
|
||||
|
||||
try {
|
||||
Gui::cmdAppObjectArgs(sketch, "setTextAndFont(%i, '%s', '%s')", constrIndex, newText, newFontPath);
|
||||
// Find if it was construction geometry to preserve that state
|
||||
int firstTextGeoId = constraint->getGeoId(1);
|
||||
bool isConstruction = false;
|
||||
if (firstTextGeoId != Sketcher::GeoEnum::GeoUndef) {
|
||||
isConstruction = Sketcher::GeometryFacade::getConstruction(
|
||||
sketch->getGeometry(firstTextGeoId)
|
||||
);
|
||||
}
|
||||
|
||||
// Send the updated 5-parameter call to Python
|
||||
Gui::cmdAppObjectArgs(
|
||||
sketch,
|
||||
"setTextAndFont(%i, '%s', '%s', %s, %s)",
|
||||
constrIndex,
|
||||
newText.c_str(),
|
||||
newFontPath.c_str(),
|
||||
newIsHeight ? "True" : "False",
|
||||
isConstruction ? "True" : "False"
|
||||
);
|
||||
|
||||
Gui::Command::commitCommand();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,24 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBox_font"/>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="layoutType">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_height">
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_width">
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -834,6 +834,10 @@ ConstraintFilterList::ConstraintFilterList(QWidget* parent)
|
||||
it->setCheckState(isChecked ? Qt::Checked : Qt::Unchecked);
|
||||
filterState = filterState >> 1;// shift right to get rid of the used bit.
|
||||
}
|
||||
|
||||
// Text constraint filter is hidden from the user
|
||||
item(static_cast<int>(ConstraintFilter::FilterValue::Text))->setHidden(true);
|
||||
|
||||
languageChange();
|
||||
|
||||
setPartiallyChecked();
|
||||
|
||||
@@ -119,6 +119,8 @@ private:
|
||||
{QT_TR_NOOP("Equality"), 1},
|
||||
{QT_TR_NOOP("Symmetric"), 1},
|
||||
{QT_TR_NOOP("Block"), 1},
|
||||
{QT_TR_NOOP("Group"), 1},
|
||||
{QT_TR_NOOP("Text"), 1},
|
||||
{QT_TR_NOOP("Internal Alignment"), 1},
|
||||
{QT_TR_NOOP("Datums"), 0},
|
||||
{QT_TR_NOOP("Horizontal Distance"), 1},
|
||||
|
||||
@@ -1003,6 +1003,11 @@ QMap<QString, QString> SketcherGui::findAvailableFontFiles()
|
||||
QMap<QString, QString> fontMap;
|
||||
QStringList fontPaths;
|
||||
|
||||
// 0. Include FreeCAD bundled fonts
|
||||
fontPaths << QString::fromStdString(
|
||||
App::Application::getResourceDir() + "Mod/TechDraw/Resources/fonts/"
|
||||
);
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
fontPaths << QString::fromUtf8("C:/Windows/Fonts");
|
||||
#elif defined(Q_OS_MACOS)
|
||||
|
||||
@@ -1336,9 +1336,32 @@ void ViewProviderSketch::editDoubleClicked()
|
||||
Base::Console().log("double click point:%d\n", preselection.PreselectPoint);
|
||||
}
|
||||
else if (preselection.isPreselectCurveValid()) {
|
||||
// We cannot do toggleWireSelelection directly here because the released event with
|
||||
//STATUS_NONE return false which clears the selection.
|
||||
setSketchMode(STATUS_SELECT_Wire);
|
||||
int geoId = preselection.PreselectCurve;
|
||||
Sketcher::SketchObject* sketch = getSketchObject();
|
||||
|
||||
// Check if the preselected edge is the handle of a Text constraint
|
||||
int textConstrId = -1;
|
||||
const auto& constraints = sketch->Constraints.getValues();
|
||||
for (int i = 0; i < static_cast<int>(constraints.size()); ++i) {
|
||||
if (constraints[i]->Type == Sketcher::Text && constraints[i]->hasElement(0)) {
|
||||
if (constraints[i]->getGeoId(0) == geoId) {
|
||||
textConstrId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (textConstrId != -1) {
|
||||
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Modify Text constraint"));
|
||||
EditTextDialog editTextDialog(this, textConstrId);
|
||||
editTextDialog.exec();
|
||||
setSketchMode(STATUS_NONE);
|
||||
}
|
||||
else {
|
||||
// We cannot do toggleWireSelelection directly here because the released event with
|
||||
//STATUS_NONE return false which clears the selection.
|
||||
setSketchMode(STATUS_SELECT_Wire);
|
||||
}
|
||||
}
|
||||
else if (preselection.isCrossPreselected()) {
|
||||
Base::Console().log("double click cross:%d\n",
|
||||
@@ -2499,6 +2522,16 @@ bool ViewProviderSketch::detectAndShowPreselection(SoPickedPoint* Point)
|
||||
}
|
||||
else if (result.GeoIndex != -1
|
||||
&& result.GeoIndex != preselection.PreselectCurve) {// if a new curve is hit
|
||||
|
||||
// If the picked edge is part of a text/group, treat the handle as the preselected item
|
||||
int handleId = getSketchObject()->getGroupHandleIfInGroup(result.GeoIndex);
|
||||
if (handleId != result.GeoIndex) {
|
||||
if (handleId == preselection.PreselectCurve) {
|
||||
return false;
|
||||
}
|
||||
result.GeoIndex = handleId;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
if (result.GeoIndex >= 0)
|
||||
ss << "Edge" << result.GeoIndex + 1;
|
||||
|
||||
Reference in New Issue
Block a user