diff --git a/lcUI/dialogs/textdialog.cpp b/lcUI/dialogs/textdialog.cpp index 1caf55510..baa984e72 100644 --- a/lcUI/dialogs/textdialog.cpp +++ b/lcUI/dialogs/textdialog.cpp @@ -90,9 +90,9 @@ TextDialog::~TextDialog() void TextDialog::okButtonClicked() { kaguya::State state(_mainWindow->luaInterface()->luaState()); - _mainWindow->runOperation(state["TextOperations"]); + _mainWindow->runOperation(state["MTextOperations"]); state.dostring("updateTextOp = function(textEntity) mainWindow:currentOperation():copyEntity(textEntity) end"); - lc::builder::TextBuilder textBuilder; + lc::builder::MTextBuilder textBuilder; textBuilder.setLayer(_mainWindow->cadMdiChild()->activeLayer()); textBuilder.setMetaInfo(_mainWindow->cadMdiChild()->metaInfoManager()->metaInfo()); textBuilder.setBlock(_mainWindow->cadMdiChild()->activeViewport()); diff --git a/lcUI/dialogs/textdialog.h b/lcUI/dialogs/textdialog.h index 49563bde0..1d1234137 100644 --- a/lcUI/dialogs/textdialog.h +++ b/lcUI/dialogs/textdialog.h @@ -5,7 +5,8 @@ #include #include -#include +#include +#include namespace Ui { class TextDialog; diff --git a/lcUI/widgets/guiAPI/entitynamevisitor.cpp b/lcUI/widgets/guiAPI/entitynamevisitor.cpp index f98146242..fdec8e23d 100644 --- a/lcUI/widgets/guiAPI/entitynamevisitor.cpp +++ b/lcUI/widgets/guiAPI/entitynamevisitor.cpp @@ -26,6 +26,10 @@ void EntityNameVisitor::visit(entity::Text_CSPtr){ entityInfo = "Text"; } +void EntityNameVisitor::visit(entity::MText_CSPtr) { + entityInfo = "MText"; +} + void EntityNameVisitor::visit(entity::Spline_CSPtr){ entityInfo = "Spline"; } diff --git a/lcUI/widgets/guiAPI/entitynamevisitor.h b/lcUI/widgets/guiAPI/entitynamevisitor.h index 2e50dc024..60438d6bc 100644 --- a/lcUI/widgets/guiAPI/entitynamevisitor.h +++ b/lcUI/widgets/guiAPI/entitynamevisitor.h @@ -16,6 +16,7 @@ namespace lc void visit(entity::Arc_CSPtr) override; void visit(entity::Ellipse_CSPtr) override; void visit(entity::Text_CSPtr) override; + void visit(entity::MText_CSPtr) override; void visit(entity::Spline_CSPtr) override; void visit(entity::DimAligned_CSPtr) override; void visit(entity::DimAngular_CSPtr) override; diff --git a/lcUILua/createActions/mtextoperations.lua b/lcUILua/createActions/mtextoperations.lua new file mode 100644 index 000000000..b127feb00 --- /dev/null +++ b/lcUILua/createActions/mtextoperations.lua @@ -0,0 +1,109 @@ +MTextOperations = { + name = "MTextOperations", + command_line = "MTEXT", + context_transitions = { + enterTextValue = {"enterInsertionPoint", "enterHeight", "enterAngle"}, + enterInsertionPoint = {"enterTextValue", "enterHeight", "enterAngle"}, + enterHeight = {"enterTextValue", "enterInsertionPoint", "enterAngle"}, + enterAngle = {"enterTextValue", "enterInsertionPoint", "enterHeight"} + } +} +MTextOperations.__index = MTextOperations + +setmetatable(MTextOperations, { + __index = CreateOperations, + __call = function (o, ...) + local self = setmetatable({}, o) + self:_init(...) + return self + end, +}) + +function MTextOperations:_init() + CreateOperations._init(self, lc.builder.MTextBuilder, "enterTextValue") + message("Enter mtext value") + self.builder:setTextValue("MText") + mainWindow:cliCommand():commandActive(true) +end + +function MTextOperations:enterTextValue(eventName, data) + if(eventName == "mouseMove") then + self.builder:setInsertionPoint(data["position"]) + elseif(eventName == "text") then + self.builder:setTextValue(data["text"]) + self.textValue = data["text"] + self:determineNextStep() + end +end + +function MTextOperations:enterInsertionPoint(eventName, data) + if(eventName == "mouseMove") then + self.builder:setInsertionPoint(data["position"]) + elseif(eventName == "point") then + self.builder:setInsertionPoint(data["position"]) + if self.byTextDialog ~= nil and self.byTextDialog then + self:createEntity() + else + self.insertionPoint = data["position"] + self:determineNextStep() + end + end +end + +function MTextOperations:enterHeight(eventName, data) + if(eventName == "mouseMove") then + local dist = self.builder:insertionPoint():distanceTo(data["position"]) + self.builder:setHeight(dist) + elseif(eventName == "point") then + local dist = self.builder:insertionPoint():distanceTo(data["position"]) + self.builder:setHeight(dist) + self.height = dist + self:determineNextStep() + elseif(eventName == "number") then + self.builder:setHeight(data["number"]) + self.height = data["number"] + self:determineNextStep() + end +end + +function MTextOperations:enterAngle(eventName, data) + if(eventName == "mouseMove") then + local ang = self.builder:insertionPoint():distanceTo(data["position"]) * 0.05 + self.builder:setAngle(ang) + elseif(eventName == "point") then + local ang = self.builder:insertionPoint():distanceTo(data["position"]) * 0.05 + self.builder:setAngle(ang) + self.angle = ang + self:determineNextStep() + elseif(eventName == "number") then + self.builder:setAngle(data["number"] * 3.1416/180) + self.angle = self.builder:angle() + self:determineNextStep() + end +end + +function MTextOperations:copyEntity(textEntity) + self.builder:copy(textEntity) + self.byTextDialog = true + self.step = "enterInsertionPoint" + message("Enter insertion point") +end + +function MTextOperations:determineNextStep() + if(self.textValue == nil) then + message("Enter text value") + self.step = "enterTextValue" + elseif(self.insertionPoint == nil) then + message("Enter insertion point") + self.step = "enterInsertionPoint" + elseif(self.height == nil) then + message("Enter height of text") + self.step = "enterHeight" + elseif(self.angle == nil) then + message("Enter angle of text (in degrees)") + self.step = "enterAngle" + else + message("Done") + self:createEntity() + end +end diff --git a/lcadluascript/bridge/lc.cpp b/lcadluascript/bridge/lc.cpp index 2b6c88891..3a70e7741 100644 --- a/lcadluascript/bridge/lc.cpp +++ b/lcadluascript/bridge/lc.cpp @@ -26,7 +26,7 @@ void import_lc_namespace(kaguya::State& state) { ); state["lc"]["EntityDispatch"].setClass(kaguya::UserdataMetatable() - .addOverloadedFunctions("visit", static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit)) + .addOverloadedFunctions("visit", static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit), static_cast(&lc::EntityDispatch::visit)) ); state["lc"]["EntityCoordinate"].setClass(kaguya::UserdataMetatable() diff --git a/lcadluascript/bridge/lc_builder.cpp b/lcadluascript/bridge/lc_builder.cpp index 389794cf4..9be80ddbb 100644 --- a/lcadluascript/bridge/lc_builder.cpp +++ b/lcadluascript/bridge/lc_builder.cpp @@ -12,8 +12,11 @@ #include #include #include +#include +#include #include #include +#include #include "lc_builder.h" void import_lc_builder_namespace(kaguya::State& state) { @@ -280,17 +283,27 @@ void import_lc_builder_namespace(kaguya::State& state) { .addFunction("setDocument", &lc::builder::InsertBuilder::setDocument) ); - state["lc"]["builder"]["TextBuilder"].setClass(kaguya::UserdataMetatable() + state["lc"]["builder"]["TextBaseBuilder"].setClass(kaguya::UserdataMetatable() + .setConstructors() + .addFunction("insertionPoint", &lc::builder::TextBaseBuilder::insertionPoint) + .addFunction("setInsertionPoint", &lc::builder::TextBaseBuilder::setInsertionPoint) + .addFunction("textValue", &lc::builder::TextBaseBuilder::textValue) + .addFunction("setTextValue", &lc::builder::TextBaseBuilder::setTextValue) + .addFunction("height", &lc::builder::TextBaseBuilder::height) + .addFunction("setHeight", &lc::builder::TextBaseBuilder::setHeight) + .addFunction("angle", &lc::builder::TextBaseBuilder::angle) + .addFunction("setAngle", &lc::builder::TextBaseBuilder::setAngle) + ); + + state["lc"]["builder"]["TextBuilder"].setClass(kaguya::UserdataMetatable() .setConstructors() .addFunction("build", &lc::builder::TextBuilder::build) - .addFunction("insertionPoint", &lc::builder::TextBuilder::insertionPoint) - .addFunction("setInsertionPoint", &lc::builder::TextBuilder::setInsertionPoint) - .addFunction("textValue", &lc::builder::TextBuilder::textValue) - .addFunction("setTextValue", &lc::builder::TextBuilder::setTextValue) - .addFunction("height", &lc::builder::TextBuilder::height) - .addFunction("setHeight", &lc::builder::TextBuilder::setHeight) - .addFunction("angle", &lc::builder::TextBuilder::angle) - .addFunction("setAngle", &lc::builder::TextBuilder::setAngle) .addFunction("copy", &lc::builder::TextBuilder::copy) ); + + state["lc"]["builder"]["MTextBuilder"].setClass(kaguya::UserdataMetatable() + .setConstructors() + .addFunction("build", &lc::builder::MTextBuilder::build) + .addFunction("copy", &lc::builder::MTextBuilder::copy) + ); } diff --git a/lcadluascript/bridge/lc_entity.cpp b/lcadluascript/bridge/lc_entity.cpp index 07be5b8e2..258a33691 100644 --- a/lcadluascript/bridge/lc_entity.cpp +++ b/lcadluascript/bridge/lc_entity.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -296,28 +297,45 @@ void import_lc_entity_namespace(kaguya::State& state) { .addFunction("snapPoints", &lc::entity::Spline::snapPoints) ); - state["lc"]["entity"]["Text"].setClass(kaguya::UserdataMetatable>() + state["lc"]["entity"]["TextBase"].setClass(kaguya::UserdataMetatable() + .addFunction("angle", &lc::entity::TextBase::angle) + .addFunction("height", &lc::entity::TextBase::height) + .addFunction("insertion_point", &lc::entity::TextBase::insertion_point) + .addFunction("style", &lc::entity::TextBase::style) + .addFunction("text_value", &lc::entity::TextBase::text_value) + .addFunction("textgeneration", &lc::entity::Text::textgeneration) + .addFunction("halign", &lc::entity::Text::halign) + .addFunction("valign", &lc::entity::Text::valign) + ); + + state["lc"]["entity"]["Text"].setClass(kaguya::UserdataMetatable>() .addFunction("accept", &lc::entity::Text::accept) - .addFunction("angle", &lc::entity::Text::angle) .addFunction("boundingBox", &lc::entity::Text::boundingBox) .addFunction("copy", &lc::entity::Text::copy) .addFunction("dispatch", &lc::entity::Text::dispatch) .addFunction("dragPoints", &lc::entity::Text::dragPoints) - .addFunction("halign", &lc::entity::Text::halign) - .addFunction("height", &lc::entity::Text::height) - .addFunction("insertion_point", &lc::entity::Text::insertion_point) .addFunction("mirror", &lc::entity::Text::mirror) .addFunction("modify", &lc::entity::Text::modify) .addFunction("move", &lc::entity::Text::move) .addFunction("rotate", &lc::entity::Text::rotate) .addFunction("scale", &lc::entity::Text::scale) .addFunction("setDragPoints", &lc::entity::Text::setDragPoints) - .addFunction("style", &lc::entity::Text::style) - .addFunction("text_value", &lc::entity::Text::text_value) - .addFunction("textgeneration", &lc::entity::Text::textgeneration) - .addFunction("valign", &lc::entity::Text::valign) ); + state["lc"]["entity"]["MText"].setClass(kaguya::UserdataMetatable>() + .addFunction("accept", &lc::entity::MText::accept) + .addFunction("boundingBox", &lc::entity::MText::boundingBox) + .addFunction("copy", &lc::entity::MText::copy) + .addFunction("dispatch", &lc::entity::MText::dispatch) + .addFunction("dragPoints", &lc::entity::MText::dragPoints) + .addFunction("mirror", &lc::entity::MText::mirror) + .addFunction("modify", &lc::entity::MText::modify) + .addFunction("move", &lc::entity::MText::move) + .addFunction("rotate", &lc::entity::MText::rotate) + .addFunction("scale", &lc::entity::MText::scale) + .addFunction("setDragPoints", &lc::entity::MText::setDragPoints) + ); + state["lc"]["entity"]["Image"].setClass(kaguya::UserdataMetatable>() .addFunction("accept", &lc::entity::Image::accept) .addFunction("base", &lc::entity::Image::base) diff --git a/lckernel/CMakeLists.txt b/lckernel/CMakeLists.txt index e9f70ceac..8341388fd 100644 --- a/lckernel/CMakeLists.txt +++ b/lckernel/CMakeLists.txt @@ -62,6 +62,8 @@ cad/primitive/ellipse.cpp cad/primitive/line.cpp cad/primitive/spline.cpp cad/primitive/text.cpp +cad/primitive/mtext.cpp +cad/primitive/textbase.cpp cad/primitive/dimension.cpp cad/primitive/dimradial.cpp cad/primitive/dimdiametric.cpp @@ -90,6 +92,8 @@ cad/builders/linepattern.cpp cad/builders/spline.cpp cad/builders/lwpolyline.cpp cad/builders/text.cpp +cad/builders/mtext.cpp +cad/builders/textbase.cpp cad/meta/customentitystorage.cpp cad/operations/blockops.cpp cad/operations/builder.cpp @@ -176,6 +180,8 @@ cad/primitive/ellipse.h cad/primitive/line.h cad/primitive/spline.h cad/primitive/text.h +cad/primitive/mtext.h +cad/primitive/textbase.h cad/primitive/lwpolyline.h cad/primitive/dimension.h cad/primitive/dimradial.h @@ -202,6 +208,8 @@ cad/builders/ellipse.cpp cad/builders/point.h cad/builders/spline.h cad/builders/text.h +cad/builders/mtext.h +cad/builders/textbase.h cad/primitive/insert.h cad/builders/insert.h cad/builders/layer.h diff --git a/lckernel/cad/base/visitor.h b/lckernel/cad/base/visitor.h index bd692320a..7cc631e1a 100644 --- a/lckernel/cad/base/visitor.h +++ b/lckernel/cad/base/visitor.h @@ -42,6 +42,9 @@ DECLARE_SHORT_SHARED_PTR(Line) class Text; DECLARE_SHORT_SHARED_PTR(Text) +class MText; +DECLARE_SHORT_SHARED_PTR(MText) + class Spline; DECLARE_SHORT_SHARED_PTR(Spline) diff --git a/lckernel/cad/builders/mtext.cpp b/lckernel/cad/builders/mtext.cpp new file mode 100644 index 000000000..a63091907 --- /dev/null +++ b/lckernel/cad/builders/mtext.cpp @@ -0,0 +1,71 @@ +#include "mtext.h" +#include + +using namespace lc::builder; + +MTextBuilder::MTextBuilder() + : + _underlined(false), + _strikethrough(false), + _bold(false), + _italic(false) +{ +} + +MTextBuilder* MTextBuilder::setUnderlined(bool underline) { + _underlined = underline; + return this; +} + +bool MTextBuilder::underlined() const { + return _underlined; +} + +MTextBuilder* MTextBuilder::setStrikethrough(bool strikethrough) { + _strikethrough = strikethrough; + return this; +} + +bool MTextBuilder::strikethrough() const { + return _strikethrough; +} + +MTextBuilder* MTextBuilder::setBold(bool bold) { + _bold = bold; + return this; +} + +bool MTextBuilder::bold() const { + return _bold; +} + +MTextBuilder* MTextBuilder::setItalic(bool italic) { + _italic = italic; + return this; +} + +bool MTextBuilder::italic() const { + return _italic; +} + +lc::entity::MText_CSPtr MTextBuilder::build() { + checkValues(true); + return entity::MText_CSPtr(new entity::MText(*this)); +} + +void MTextBuilder::copy(lc::entity::MText_CSPtr entity) { + CADEntityBuilder::copy(entity); + + setInsertionPoint(entity->insertion_point()); + setTextValue(entity->text_value()); + setTextFont(entity->style()); + setHeight(entity->height()); + setAngle(entity->angle()); + setDrawingDirection(entity->textgeneration()); + setHorizontalAlign(entity->halign()); + setVerticalAlign(entity->valign()); + setUnderlined(entity->underlined()); + setStrikethrough(entity->strikethrough()); + setBold(entity->bold()); + setItalic(entity->italic()); +} diff --git a/lckernel/cad/builders/mtext.h b/lckernel/cad/builders/mtext.h new file mode 100644 index 000000000..dd33728b4 --- /dev/null +++ b/lckernel/cad/builders/mtext.h @@ -0,0 +1,41 @@ +#pragma once + +#include "cadentity.h" +#include "textbase.h" +#include + +namespace lc { + namespace builder { + class MTextBuilder : public TextBaseBuilder + { + public: + MTextBuilder(); + + entity::MText_CSPtr build(); + + MTextBuilder* setUnderlined(bool underline); + + bool underlined() const; + + MTextBuilder* setStrikethrough(bool strikethrough); + + bool strikethrough() const; + + MTextBuilder* setBold(bool bold); + + bool bold() const; + + MTextBuilder* setItalic(bool italic); + + bool italic() const; + + void copy(lc::entity::MText_CSPtr entity); + + private: + bool _underlined; + bool _strikethrough; + bool _bold; + bool _italic; + }; + } +} diff --git a/lckernel/cad/builders/text.cpp b/lckernel/cad/builders/text.cpp index c3bd00fce..00b339405 100644 --- a/lckernel/cad/builders/text.cpp +++ b/lckernel/cad/builders/text.cpp @@ -5,125 +5,8 @@ using namespace lc::builder; TextBuilder::TextBuilder() : - _height(100), - _angle(0), - _drawingDirection(lc::TextConst::DrawingDirection::None), - _hAlign(lc::TextConst::HAlign::HACenter), - _vAlign(lc::TextConst::VAlign::VAMiddle), - _underlined(false), - _strikethrough(false), - _bold(false), - _italic(false) -{ -} - -const lc::geo::Coordinate& TextBuilder::insertionPoint() const { - return _insertionPoint; -} - -TextBuilder* TextBuilder::setInsertionPoint(const lc::geo::Coordinate& coord) { - _insertionPoint = coord; - return this; -} - -const std::string& TextBuilder::textValue() const { - return _textValue; -} - -TextBuilder* TextBuilder::setTextValue(const std::string& text) { - _textValue = text; - return this; -} - -double TextBuilder::height() const { - return _height; -} - -TextBuilder* TextBuilder::setHeight(double heightIn) { - _height = heightIn; - return this; -} - -double TextBuilder::angle() const { - return _angle; -} - -TextBuilder* TextBuilder::setAngle(double angleIn) { - _angle = angleIn; - return this; -} - -TextBuilder* TextBuilder::setDrawingDirection(lc::TextConst::DrawingDirection drawingDirectionIn) { - _drawingDirection = drawingDirectionIn; - return this; -} - -lc::TextConst::DrawingDirection TextBuilder::drawingDirection() const { - return _drawingDirection; -} - -TextBuilder* TextBuilder::setHorizontalAlign(lc::TextConst::HAlign halignin) { - _hAlign = halignin; - return this; -} - -lc::TextConst::HAlign TextBuilder::horizontalAlign() const { - return _hAlign; -} - -TextBuilder* TextBuilder::setVerticalAlign(lc::TextConst::VAlign valignin) { - _vAlign = valignin; - return this; -} - -lc::TextConst::VAlign TextBuilder::verticalAlign() const { - return _vAlign; -} - -TextBuilder* TextBuilder::setTextFont(std::string font) { - _textStyle = font; - return this; -} - -std::string TextBuilder::textStyle() const { - return _textStyle; -} - -TextBuilder* TextBuilder::setUnderlined(bool underline) { - _underlined = underline; - return this; -} - -bool TextBuilder::underlined() const { - return _underlined; -} - -TextBuilder* TextBuilder::setStrikethrough(bool strikethrough) { - _strikethrough = strikethrough; - return this; -} - -bool TextBuilder::strikethrough() const { - return _strikethrough; -} - -TextBuilder* TextBuilder::setBold(bool bold) { - _bold = bold; - return this; -} - -bool TextBuilder::bold() const { - return _bold; -} - -TextBuilder* TextBuilder::setItalic(bool italic) { - _italic = italic; - return this; -} - -bool TextBuilder::italic() const { - return _italic; -} + TextBaseBuilder() +{} lc::entity::Text_CSPtr TextBuilder::build() { checkValues(true); @@ -141,8 +24,4 @@ void TextBuilder::copy(lc::entity::Text_CSPtr entity) { setDrawingDirection(entity->textgeneration()); setHorizontalAlign(entity->halign()); setVerticalAlign(entity->valign()); - setUnderlined(entity->underlined()); - setStrikethrough(entity->strikethrough()); - setBold(entity->bold()); - setItalic(entity->italic()); } diff --git a/lckernel/cad/builders/text.h b/lckernel/cad/builders/text.h index 66e72be40..819248e97 100644 --- a/lckernel/cad/builders/text.h +++ b/lckernel/cad/builders/text.h @@ -1,80 +1,20 @@ #pragma once #include "cadentity.h" +#include "textbase.h" #include namespace lc { namespace builder { -class TextBuilder : public CADEntityBuilder +class TextBuilder : public TextBaseBuilder { public: TextBuilder(); - const lc::geo::Coordinate& insertionPoint() const; - - TextBuilder* setInsertionPoint(const lc::geo::Coordinate& coord); - - const std::string& textValue() const; - - TextBuilder* setTextValue(const std::string& text); - - double height() const; - - TextBuilder* setHeight(double heightIn); - - double angle() const; - - TextBuilder* setAngle(double angleIn); - entity::Text_CSPtr build(); - TextBuilder* setDrawingDirection(lc::TextConst::DrawingDirection drawingDirectionIn); - - lc::TextConst::DrawingDirection drawingDirection() const; - - TextBuilder* setHorizontalAlign(lc::TextConst::HAlign halignin); - - lc::TextConst::HAlign horizontalAlign() const; - - TextBuilder* setVerticalAlign(lc::TextConst::VAlign valignin); - - lc::TextConst::VAlign verticalAlign() const; - - TextBuilder* setTextFont(std::string font); - - std::string textStyle() const; - - TextBuilder* setUnderlined(bool underline); - - bool underlined() const; - - TextBuilder* setStrikethrough(bool strikethrough); - - bool strikethrough() const; - - TextBuilder* setBold(bool bold); - - bool bold() const; - - TextBuilder* setItalic(bool italic); - - bool italic() const; - void copy(lc::entity::Text_CSPtr entity); -private: - lc::geo::Coordinate _insertionPoint; - std::string _textValue; - std::string _textStyle; - double _height; - double _angle; - lc::TextConst::DrawingDirection _drawingDirection; - lc::TextConst::HAlign _hAlign; - lc::TextConst::VAlign _vAlign; - bool _underlined; - bool _strikethrough; - bool _bold; - bool _italic; }; } } diff --git a/lckernel/cad/builders/textbase.cpp b/lckernel/cad/builders/textbase.cpp new file mode 100644 index 000000000..2e6e4555a --- /dev/null +++ b/lckernel/cad/builders/textbase.cpp @@ -0,0 +1,85 @@ +#include "textbase.h" + +using namespace lc::builder; + +TextBaseBuilder::TextBaseBuilder() + : + _drawingDirection(lc::TextConst::DrawingDirection::None), + _hAlign(lc::TextConst::HAlign::HACenter), + _vAlign(lc::TextConst::VAlign::VAMiddle), + _height(100), + _angle(0) +{ +} + +const lc::geo::Coordinate& TextBaseBuilder::insertionPoint() const { + return _insertionPoint; +} + +TextBaseBuilder* TextBaseBuilder::setInsertionPoint(const lc::geo::Coordinate& coord) { + _insertionPoint = coord; + return this; +} + +const std::string& TextBaseBuilder::textValue() const { + return _textValue; +} + +TextBaseBuilder* TextBaseBuilder::setTextValue(const std::string& text) { + _textValue = text; + return this; +} + +double TextBaseBuilder::height() const { + return _height; +} + +TextBaseBuilder* TextBaseBuilder::setHeight(double heightIn) { + _height = heightIn; + return this; +} + +double TextBaseBuilder::angle() const { + return _angle; +} + +TextBaseBuilder* TextBaseBuilder::setAngle(double angleIn) { + _angle = angleIn; + return this; +} + +TextBaseBuilder* TextBaseBuilder::setTextFont(std::string font) { + _textStyle = font; + return this; +} + +std::string TextBaseBuilder::textStyle() const { + return _textStyle; +} + +TextBaseBuilder* TextBaseBuilder::setDrawingDirection(lc::TextConst::DrawingDirection drawingDirectionIn) { + _drawingDirection = drawingDirectionIn; + return this; +} + +lc::TextConst::DrawingDirection TextBaseBuilder::drawingDirection() const { + return _drawingDirection; +} + +TextBaseBuilder* TextBaseBuilder::setHorizontalAlign(lc::TextConst::HAlign halignin) { + _hAlign = halignin; + return this; +} + +lc::TextConst::HAlign TextBaseBuilder::horizontalAlign() const { + return _hAlign; +} + +TextBaseBuilder* TextBaseBuilder::setVerticalAlign(lc::TextConst::VAlign valignin) { + _vAlign = valignin; + return this; +} + +lc::TextConst::VAlign TextBaseBuilder::verticalAlign() const { + return _vAlign; +} diff --git a/lckernel/cad/builders/textbase.h b/lckernel/cad/builders/textbase.h new file mode 100644 index 000000000..459c19bd5 --- /dev/null +++ b/lckernel/cad/builders/textbase.h @@ -0,0 +1,56 @@ +#pragma once + +#include "cadentity.h" +#include + +namespace lc { + namespace builder { + class TextBaseBuilder : public CADEntityBuilder + { + public: + TextBaseBuilder(); + + const lc::geo::Coordinate& insertionPoint() const; + + TextBaseBuilder* setInsertionPoint(const lc::geo::Coordinate& coord); + + const std::string& textValue() const; + + TextBaseBuilder* setTextValue(const std::string& text); + + double height() const; + + TextBaseBuilder* setHeight(double heightIn); + + double angle() const; + + TextBaseBuilder* setAngle(double angleIn); + + TextBaseBuilder* setTextFont(std::string font); + + std::string textStyle() const; + + TextBaseBuilder* setDrawingDirection(lc::TextConst::DrawingDirection drawingDirectionIn); + + lc::TextConst::DrawingDirection drawingDirection() const; + + TextBaseBuilder* setHorizontalAlign(lc::TextConst::HAlign halignin); + + lc::TextConst::HAlign horizontalAlign() const; + + TextBaseBuilder* setVerticalAlign(lc::TextConst::VAlign valignin); + + lc::TextConst::VAlign verticalAlign() const; + + protected: + lc::geo::Coordinate _insertionPoint; + std::string _textValue; + std::string _textStyle; + double _height; + double _angle; + lc::TextConst::DrawingDirection _drawingDirection; + lc::TextConst::HAlign _hAlign; + lc::TextConst::VAlign _vAlign; + }; + } +} diff --git a/lckernel/cad/interface/entitydispatch.h b/lckernel/cad/interface/entitydispatch.h index f360ca849..60c80235d 100644 --- a/lckernel/cad/interface/entitydispatch.h +++ b/lckernel/cad/interface/entitydispatch.h @@ -12,6 +12,7 @@ class EntityDispatch { virtual void visit(entity::Arc_CSPtr) = 0; virtual void visit(entity::Ellipse_CSPtr) = 0; virtual void visit(entity::Text_CSPtr) = 0; + virtual void visit(entity::MText_CSPtr) = 0; virtual void visit(entity::Spline_CSPtr) = 0; virtual void visit(entity::DimAligned_CSPtr) = 0; virtual void visit(entity::DimAngular_CSPtr) = 0; diff --git a/lckernel/cad/primitive/mtext.cpp b/lckernel/cad/primitive/mtext.cpp new file mode 100644 index 000000000..227057c2c --- /dev/null +++ b/lckernel/cad/primitive/mtext.cpp @@ -0,0 +1,241 @@ +#include "mtext.h" +#include "textbase.h" + + +using namespace lc; +using namespace entity; + +MText::MText(geo::Coordinate insertion_point, + std::string text_value, + double height, + double angle, + std::string style, + const TextConst::DrawingDirection textgeneration, + const TextConst::HAlign halign, + const TextConst::VAlign valign, + bool underlined, + bool strikethrough, + bool bold, + bool italic, + meta::Layer_CSPtr layer, + meta::MetaInfo_CSPtr metaInfo, + meta::Block_CSPtr block) : + CADEntity(std::move(layer), std::move(metaInfo), std::move(block)), + TextBase(insertion_point, text_value, height, angle, style, textgeneration, halign, valign), + _underlined(underlined), + _strikethrough(strikethrough), + _bold(bold), + _italic(italic) +{ +} + +MText::MText(const builder::MTextBuilder& builder) + : + CADEntity(builder), + TextBase(builder), + _underlined(builder.underlined()), + _strikethrough(builder.strikethrough()), + _bold(builder.bold()), + _italic(builder.italic()) +{ +} + +MText::MText(const MText_CSPtr& other, bool sameID) : + CADEntity(other, sameID), + TextBase(*other), + _underlined(other->_underlined), + _strikethrough(other->_strikethrough), + _bold(other->_bold), + _italic(other->_italic) +{ +} + +CADEntity_CSPtr MText::move(const geo::Coordinate& offset) const { + auto newMText = std::make_shared(this->_insertion_point + offset, + this->_text_value, + this->_height, + this->_angle, + this->_style, + this->_textgeneration, + this->_halign, + this->_valign, + this->_underlined, + this->_strikethrough, + this->_bold, + this->_italic, + layer() + , metaInfo(), block() + ); + newMText->setID(this->id()); + return newMText; +} + +CADEntity_CSPtr MText::copy(const geo::Coordinate& offset) const { + auto newMText = std::make_shared( + this->_insertion_point + offset, + this->_text_value, + this->_height, + this->_angle, + this->_style, + this->_textgeneration, + this->_halign, + this->_valign, + this->_underlined, + this->_strikethrough, + this->_bold, + this->_italic, + layer() + , metaInfo(), block()); + newMText->setID(this->id()); + return newMText; +} + +CADEntity_CSPtr MText::rotate(const geo::Coordinate& rotation_center, double rotation_angle) const { + auto newMText = std::make_shared( + this->_insertion_point.rotate(rotation_center, rotation_angle), + this->_text_value, + this->_height, + this->_angle, + this->_style, + this->_textgeneration, + this->_halign, + this->_valign, + this->_underlined, + this->_strikethrough, + this->_bold, + this->_italic, + layer() + , metaInfo(), block()); + return newMText; +} + +CADEntity_CSPtr MText::scale(const geo::Coordinate& scale_center, const geo::Coordinate& scale_factor) const { + auto newMText = std::make_shared( + this->_insertion_point.scale(scale_center, scale_factor), + this->_text_value, + this->_height * std::sqrt(scale_factor.x() * scale_factor.y()), // Does this make sense? + this->_angle, + this->_style, + this->_textgeneration, + this->_halign, + this->_valign, + this->_underlined, + this->_strikethrough, + this->_bold, + this->_italic, + this->layer() + , metaInfo(), block()); + newMText->setID(this->id()); + return newMText; +} + +const geo::Area MText::boundingBox() const { + /// @todo Fix this + // Rough bounding box + // Assume that the font has char max. width equal to height + // Assume single line + double width = this->_height * (this->_text_value).size() / 2; + return geo::Area(this->_insertion_point - geo::Coordinate(width, width), this->_insertion_point + geo::Coordinate(width, width)); +} + +CADEntity_CSPtr MText::modify(meta::Layer_CSPtr layer, const meta::MetaInfo_CSPtr metaInfo, meta::Block_CSPtr block) const { + auto newMText = std::make_shared( + this->_insertion_point, + this->_text_value, + this->_height, + this->_angle, + this->_style, + this->_textgeneration, + this->_halign, + this->_valign, + this->_underlined, + this->_strikethrough, + this->_bold, + this->_italic, + layer, + metaInfo, + block + ); + newMText->setID(this->id()); + + return newMText; +} + +std::map MText::dragPoints() const { + std::map dragPoints; + + dragPoints[0] = _insertion_point; + + return dragPoints; +} + +CADEntity_CSPtr MText::setDragPoints(std::map dragPoints) const { + try { + auto newEntity = std::make_shared(dragPoints.at(0), + text_value(), + height(), + angle(), + style(), + textgeneration(), + halign(), + valign(), + underlined(), + strikethrough(), + bold(), + italic(), + layer(), + metaInfo(), block() + ); + newEntity->setID(id()); + return newEntity; + } + catch (std::out_of_range& e) { + return shared_from_this(); + } +} + +PropertiesMap MText::availableProperties() const { + PropertiesMap propertyValues; + + getTextProperties(propertyValues); + propertyValues["bold"] = this->bold(); + propertyValues["italic"] = this->italic(); + propertyValues["underlined"] = this->underlined(); + propertyValues["strikethrough"] = this->strikethrough(); + + return propertyValues; +} + +CADEntity_CSPtr MText::setProperties(const PropertiesMap& propertiesMap) const { + lc::geo::Coordinate insertionPointp; + std::string textValuep; + double heightp; + double anglep; + bool boldp = this->bold(); + bool italicp = this->italic(); + bool underlinedp = this->underlined(); + bool strikethroughp = this->strikethrough(); + + setTextProperties(propertiesMap, insertionPointp, textValuep, heightp, anglep); + for (auto iter = propertiesMap.begin(); iter != propertiesMap.end(); ++iter) { + if (iter->first == "bold") { + boldp = boost::get(iter->second); + } + + if (iter->first == "italic") { + italicp = boost::get(iter->second); + } + + if (iter->first == "underlined") { + underlinedp = boost::get(iter->second); + } + + if (iter->first == "strikethrough") { + strikethroughp = boost::get(iter->second); + } + } + + auto textEntity = std::make_shared(insertionPointp, textValuep, heightp, anglep, style(), textgeneration(), halign(), valign(), underlinedp, strikethroughp, boldp, italicp, layer(), metaInfo(), block()); + textEntity->setID(this->id()); + return textEntity; +} diff --git a/lckernel/cad/primitive/mtext.h b/lckernel/cad/primitive/mtext.h new file mode 100644 index 000000000..9905728a2 --- /dev/null +++ b/lckernel/cad/primitive/mtext.h @@ -0,0 +1,113 @@ +#pragma once + +#include "cad/const.h" +#include "cad/interface/entitydispatch.h" +#include "textbase.h" + +#include "cad/geometry/geocoordinate.h" +#include "cad/base/cadentity.h" +#include "cad/vo/entitycoordinate.h" +#include "cad/math/lcmath.h" +#include "cad/primitive/textconst.h" +#include +#include "cad/interface/draggable.h" +#include + +namespace lc { + namespace entity { + class MText : public std::enable_shared_from_this, public CADEntity, public TextBase, virtual public Visitable, public Draggable { + friend class builder::MTextBuilder; + + public: + /** + * @brief MText, default constructor + * @param geo::Coordinate insertion_point, insertion_point of the text + * @param double height, height of the text + * @param string text_value, the text itself + * @param double angle, angle of obliqueness + * @param string style, name of text style + * @param MTextConst::DrawingDirection textgeneration, MText drawing direction + * @param MTextConst::HAlign halign, Horizontal alignment + * @param MTextConst::VAlign valign, Vertical alignment + * @param Layer_CSPtr layer, Layer of the entity + * @param metatypes metatypes of the cad entity + */ + MText(geo::Coordinate insertion_point, + std::string text_value, + double height, + double angle, + std::string style, + const TextConst::DrawingDirection textgeneration, + const TextConst::HAlign halign, + const TextConst::VAlign valign, + bool underlined, + bool strikethrough, + bool bold, + bool italic, + meta::Layer_CSPtr layer, + meta::MetaInfo_CSPtr metaInfo = nullptr, + meta::Block_CSPtr block = nullptr + ); + + MText(const MText_CSPtr& other, bool sameID); + + private: + MText(const builder::MTextBuilder& builder); + + public: + const bool _underlined; + const bool _strikethrough; + const bool _bold; + const bool _italic; + + bool underlined() const { + return _underlined; + } + + bool strikethrough() const { + return _strikethrough; + } + + bool bold() const { + return _bold; + } + + bool italic() const { + return _italic; + } + + /** + * @brief move, moves by an offset + * @param geo::Coordinate offset + * @return CADEntity_CSPtr moved entity + */ + public: + // Methods from CADEntity + CADEntity_CSPtr move(const geo::Coordinate& offset) const override; + CADEntity_CSPtr copy(const geo::Coordinate& offset) const override; + CADEntity_CSPtr rotate(const geo::Coordinate& rotation_center, double rotation_angle) const override; + CADEntity_CSPtr scale(const geo::Coordinate& scale_center, + const geo::Coordinate& scale_factor) const override; + CADEntity_CSPtr mirror(const geo::Coordinate& axis1, const geo::Coordinate& axis2) const override { + return NULL; /// @todo no return statement, not implemented in lwpolyline.cpp + } + const geo::Area boundingBox() const override; + CADEntity_CSPtr modify(meta::Layer_CSPtr layer, meta::MetaInfo_CSPtr metaInfo, meta::Block_CSPtr block) const override; + void accept(GeoEntityVisitor& v) const override { + v.visit(*this); + } + void dispatch(EntityDispatch& ed) const override { + ed.visit(shared_from_this()); + } + std::map dragPoints() const override; + CADEntity_CSPtr setDragPoints(std::map dragPoints) const override; + + PropertiesMap availableProperties() const override; + + CADEntity_CSPtr setProperties(const PropertiesMap& propertiesMap) const override; + }; + + DECLARE_SHORT_SHARED_PTR(MText) + } +} + diff --git a/lckernel/cad/primitive/text.cpp b/lckernel/cad/primitive/text.cpp index a05aa8504..46f2bffe3 100644 --- a/lckernel/cad/primitive/text.cpp +++ b/lckernel/cad/primitive/text.cpp @@ -1,4 +1,5 @@ #include "text.h" +#include "textbase.h" using namespace lc; @@ -12,61 +13,24 @@ Text::Text(geo::Coordinate insertion_point, const TextConst::DrawingDirection textgeneration, const TextConst::HAlign halign, const TextConst::VAlign valign, - bool underlined, - bool strikethrough, - bool bold, - bool italic, meta::Layer_CSPtr layer, meta::MetaInfo_CSPtr metaInfo, meta::Block_CSPtr block) : CADEntity(std::move(layer), std::move(metaInfo), std::move(block)), - _insertion_point(std::move(insertion_point)), - _text_value(std::move(text_value)), - _height(height), - _angle(angle), - _style(std::move(style)), - _textgeneration(textgeneration), - _valign(valign), - _halign(halign), - _underlined(underlined), - _strikethrough(strikethrough), - _bold(bold), - _italic(italic) + TextBase(insertion_point, text_value, height, angle, style, textgeneration, halign, valign) { } Text::Text(const builder::TextBuilder& builder) : CADEntity(builder), - _insertion_point(builder.insertionPoint()), - _text_value(builder.textValue()), - _height(builder.height()), - _angle(builder.angle()), - _style(builder.textStyle()), - _textgeneration(builder.drawingDirection()), - _halign(builder.horizontalAlign()), - _valign(builder.verticalAlign()), - _underlined(builder.underlined()), - _strikethrough(builder.strikethrough()), - _bold(builder.bold()), - _italic(builder.italic()) + TextBase(builder) { } Text::Text(const Text_CSPtr& other, bool sameID) : CADEntity(other, sameID), - _insertion_point(other->_insertion_point), - _text_value(other->_text_value), - _height(other->_height), - _angle(other->_angle), - _style(other->_style), - _textgeneration(other->_textgeneration), - _valign(other->_valign), - _halign(other->_halign), - _underlined(other->_underlined), - _strikethrough(other->_strikethrough), - _bold(other->_bold), - _italic(other->_italic) + TextBase(*other) { } @@ -79,10 +43,6 @@ CADEntity_CSPtr Text::move(const geo::Coordinate& offset) const { this->_textgeneration, this->_halign, this->_valign, - this->_underlined, - this->_strikethrough, - this->_bold, - this->_italic, layer() , metaInfo(), block() ); @@ -100,10 +60,6 @@ CADEntity_CSPtr Text::copy(const geo::Coordinate& offset) const { this->_textgeneration, this->_halign, this->_valign, - this->_underlined, - this->_strikethrough, - this->_bold, - this->_italic, layer() , metaInfo(), block()); newText->setID(this->id()); @@ -120,10 +76,6 @@ CADEntity_CSPtr Text::rotate(const geo::Coordinate& rotation_center, double rota this->_textgeneration, this->_halign, this->_valign, - this->_underlined, - this->_strikethrough, - this->_bold, - this->_italic, layer() , metaInfo(), block()); return newText; @@ -139,10 +91,6 @@ CADEntity_CSPtr Text::scale(const geo::Coordinate& scale_center, const geo::Coor this->_textgeneration, this->_halign, this->_valign, - this->_underlined, - this->_strikethrough, - this->_bold, - this->_italic, this->layer() , metaInfo(), block()); newText->setID(this->id()); @@ -168,10 +116,6 @@ CADEntity_CSPtr Text::modify(meta::Layer_CSPtr layer, const meta::MetaInfo_CSPtr this->_textgeneration, this->_halign, this->_valign, - this->_underlined, - this->_strikethrough, - this->_bold, - this->_italic, layer, metaInfo, block @@ -199,10 +143,6 @@ CADEntity_CSPtr Text::setDragPoints(std::map textgeneration(), halign(), valign(), - underlined(), - strikethrough(), - bold(), - italic(), layer(), metaInfo(), block() ); @@ -217,63 +157,18 @@ CADEntity_CSPtr Text::setDragPoints(std::map PropertiesMap Text::availableProperties() const { PropertiesMap propertyValues; - propertyValues["insertionPoint"] = this->insertion_point(); - propertyValues["textValue"] = this->text_value(); - propertyValues["height"] = this->height(); - propertyValues["angle"] = AngleProperty(this->angle()); - propertyValues["bold"] = this->bold(); - propertyValues["italic"] = this->italic(); - propertyValues["underlined"] = this->underlined(); - propertyValues["strikethrough"] = this->strikethrough(); - + getTextProperties(propertyValues); return propertyValues; } CADEntity_CSPtr Text::setProperties(const PropertiesMap& propertiesMap) const { - lc::geo::Coordinate insertionPointp = this->insertion_point(); - std::string textValuep = this->text_value(); - double heightp = this->height(); - double anglep = this->angle(); - bool boldp = this->bold(); - bool italicp = this->italic(); - bool underlinedp = this->underlined(); - bool strikethroughp = this->strikethrough(); - - for(auto iter = propertiesMap.begin(); iter != propertiesMap.end(); ++iter) { - if (iter->first == "insertionPoint") { - insertionPointp = boost::get(iter->second); - } - - if (iter->first == "textValue") { - textValuep = boost::get(iter->second); - } - - if (iter->first == "height") { - heightp = boost::get(iter->second); - } - - if (iter->first == "angle") { - anglep = boost::get(iter->second).Get(); - } - - if (iter->first == "bold") { - boldp = boost::get(iter->second); - } - - if (iter->first == "italic") { - italicp = boost::get(iter->second); - } - - if (iter->first == "underlined") { - underlinedp = boost::get(iter->second); - } - - if (iter->first == "strikethrough") { - strikethroughp = boost::get(iter->second); - } - } + lc::geo::Coordinate insertionPointp; + std::string textValuep; + double heightp; + double anglep; - auto textEntity = std::make_shared(insertionPointp, textValuep, heightp, anglep, style(), textgeneration(), halign(), valign(), underlinedp, strikethroughp, boldp, italicp, layer(), metaInfo(), block()); + setTextProperties(propertiesMap, insertionPointp, textValuep, heightp, anglep); + auto textEntity = std::make_shared(insertionPointp, textValuep, heightp, anglep, style(), textgeneration(), halign(), valign(), layer(), metaInfo(), block()); textEntity->setID(this->id()); return textEntity; } diff --git a/lckernel/cad/primitive/text.h b/lckernel/cad/primitive/text.h index 021252b10..953de9341 100644 --- a/lckernel/cad/primitive/text.h +++ b/lckernel/cad/primitive/text.h @@ -2,7 +2,7 @@ #include "cad/const.h" #include "cad/interface/entitydispatch.h" - +#include "textbase.h" #include "cad/geometry/geocoordinate.h" #include "cad/base/cadentity.h" @@ -15,9 +15,8 @@ namespace lc { namespace entity { -class Text : public std::enable_shared_from_this, public CADEntity, virtual public Visitable, public Draggable { +class Text : public std::enable_shared_from_this, public CADEntity, public TextBase, virtual public Visitable, public Draggable { friend class builder::TextBuilder; - public: /** * @brief Text, default constructor @@ -40,10 +39,6 @@ class Text : public std::enable_shared_from_this, public CADEntity, virtua const TextConst::DrawingDirection textgeneration, const TextConst::HAlign halign, const TextConst::VAlign valign, - bool underlined, - bool strikethrough, - bool bold, - bool italic, meta::Layer_CSPtr layer, meta::MetaInfo_CSPtr metaInfo = nullptr, meta::Block_CSPtr block = nullptr @@ -54,68 +49,6 @@ class Text : public std::enable_shared_from_this, public CADEntity, virtua private: Text(const builder::TextBuilder& builder); -public: - const geo::Coordinate _insertion_point; - const std::string _text_value; - const double _height; - const double _angle; - const std::string _style; - const TextConst::DrawingDirection _textgeneration; - const TextConst::VAlign _valign; - const TextConst::HAlign _halign; - const bool _underlined; - const bool _strikethrough; - const bool _bold; - const bool _italic; - - geo::Coordinate insertion_point() const { - return _insertion_point; - } - - std::string const &text_value() const { - return _text_value; - } - - double const angle() const { - return _angle; - } - - std::string const &style() const { - return _style; - } - - TextConst::DrawingDirection const &textgeneration() const { - return _textgeneration; - } - - TextConst::VAlign const &valign() const { - return _valign; - } - - TextConst::HAlign const &halign() const { - return _halign; - } - - double height() const { - return _height; - } - - bool underlined() const { - return _underlined; - } - - bool strikethrough() const { - return _strikethrough; - } - - bool bold() const { - return _bold; - } - - bool italic() const { - return _italic; - } - /** * @brief move, moves by an offset * @param geo::Coordinate offset diff --git a/lckernel/cad/primitive/textbase.cpp b/lckernel/cad/primitive/textbase.cpp new file mode 100644 index 000000000..5c4e04cbd --- /dev/null +++ b/lckernel/cad/primitive/textbase.cpp @@ -0,0 +1,83 @@ +#include "textbase.h" + + +using namespace lc; +using namespace entity; + +TextBase::TextBase(geo::Coordinate insertion_point, + std::string text_value, + double height, + double angle, + std::string style, + const TextConst::DrawingDirection textgeneration, + const TextConst::HAlign halign, + const TextConst::VAlign valign) + : + _insertion_point(std::move(insertion_point)), + _text_value(std::move(text_value)), + _height(height), + _angle(angle), + _style(std::move(style)), + _textgeneration(textgeneration), + _halign(halign), + _valign(valign) +{ +} + +TextBase::TextBase(const builder::TextBaseBuilder& builder) + : + _insertion_point(builder.insertionPoint()), + _text_value(builder.textValue()), + _height(builder.height()), + _angle(builder.angle()), + _style(builder.textStyle()), + _textgeneration(builder.drawingDirection()), + _halign(builder.horizontalAlign()), + _valign(builder.verticalAlign()) +{ +} + +TextBase::TextBase(const TextBase& other) : + _insertion_point(other._insertion_point), + _text_value(other._text_value), + _height(other._height), + _angle(other._angle), + _style(other._style), + _textgeneration(other._textgeneration), + _valign(other._valign), + _halign(other._halign) +{ +} + +void TextBase::getTextProperties(PropertiesMap& propertyValues) const { + propertyValues["insertionPoint"] = this->insertion_point(); + propertyValues["textValue"] = this->text_value(); + propertyValues["height"] = this->height(); + propertyValues["angle"] = AngleProperty(this->angle()); +} + +void TextBase::setTextProperties(const PropertiesMap& propertiesMap, geo::Coordinate& insertionPointp, std::string& textValuep, + double& heightp, double& anglep) const { + insertionPointp = this->insertion_point(); + textValuep = this->text_value(); + heightp = this->height(); + anglep = this->angle(); + + for (auto iter = propertiesMap.begin(); iter != propertiesMap.end(); ++iter) { + if (iter->first == "insertionPoint") { + insertionPointp = boost::get(iter->second); + } + + if (iter->first == "textValue") { + textValuep = boost::get(iter->second); + } + + if (iter->first == "height") { + heightp = boost::get(iter->second); + } + + if (iter->first == "angle") { + anglep = boost::get(iter->second).Get(); + } + } +} diff --git a/lckernel/cad/primitive/textbase.h b/lckernel/cad/primitive/textbase.h new file mode 100644 index 000000000..4b7a49d91 --- /dev/null +++ b/lckernel/cad/primitive/textbase.h @@ -0,0 +1,94 @@ +#pragma once + +#include "cad/const.h" +#include "cad/interface/entitydispatch.h" + + +#include "cad/base/cadentity.h" +#include "cad/math/lcmath.h" +#include "cad/interface/draggable.h" +#include + +namespace lc { + namespace entity { + class TextBase { + public: + /** + * @brief TextBase, default constructor + * @param geo::Coordinate insertion_point, insertion_point of the text + * @param string text_value, the text itself + * @param double height, height of the text + * @param double rotation, angle of rotation + * @param string style, name of text style + * @param Layer_CSPtr layer, Layer of the entity + * @param metatypes, metatypes of the cad entity + * @param Block_CSPtr, block of the cad entity + */ + TextBase(geo::Coordinate insertion_point, + std::string text_value, + double height, + double angle, + std::string style, + const TextConst::DrawingDirection textgeneration, + const TextConst::HAlign halign, + const TextConst::VAlign valign + ); + + TextBase(const TextBase& other); + + protected: + TextBase(const builder::TextBaseBuilder& builder); + + public: + const geo::Coordinate _insertion_point; + const std::string _text_value; + const double _height; + const double _angle; + const std::string _style; + const TextConst::DrawingDirection _textgeneration; + const TextConst::VAlign _valign; + const TextConst::HAlign _halign; + + geo::Coordinate insertion_point() const { + return _insertion_point; + } + + std::string const& text_value() const { + return _text_value; + } + + double const angle() const { + return _angle; + } + + std::string const& style() const { + return _style; + } + + double height() const { + return _height; + } + + TextConst::DrawingDirection const& textgeneration() const { + return _textgeneration; + } + + TextConst::VAlign const& valign() const { + return _valign; + } + + TextConst::HAlign const& halign() const { + return _halign; + } + + public: + void getTextProperties(PropertiesMap& propertyValues) const; + + void setTextProperties(const PropertiesMap& propertiesMap, geo::Coordinate& insertionPointp, std::string& textValuep, + double& heightp, double& anglep) const; + }; + + DECLARE_SHORT_SHARED_PTR(TextBase) + } +} + diff --git a/lcviewernoqt/CMakeLists.txt b/lcviewernoqt/CMakeLists.txt index 564080584..2c8ee0448 100644 --- a/lcviewernoqt/CMakeLists.txt +++ b/lcviewernoqt/CMakeLists.txt @@ -17,6 +17,7 @@ drawitems/lcvdrawitem.cpp drawitems/lcvellipse.cpp drawitems/lcvline.cpp drawitems/lcvtext.cpp +drawitems/lcvmtext.cpp drawitems/lcvspline.cpp drawables/grid.cpp drawitems/endcaps.cpp @@ -72,6 +73,7 @@ drawitems/lcvdrawitem.h drawitems/lcvellipse.h drawitems/lcvline.h drawitems/lcvtext.h +drawitems/lcvmtext.h drawitems/lcvspline.h drawables/grid.h drawitems/endcaps.h diff --git a/lcviewernoqt/documentcanvas.cpp b/lcviewernoqt/documentcanvas.cpp index d12aa0b1b..fc8163c20 100644 --- a/lcviewernoqt/documentcanvas.cpp +++ b/lcviewernoqt/documentcanvas.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include "lcdrawoptions.h" @@ -17,6 +18,7 @@ #include "drawitems/lcvline.h" #include "drawitems/lcvellipse.h" #include "drawitems/lcvtext.h" +#include "drawitems/lcvmtext.h" #include "drawitems/lcvpoint.h" #include "drawitems/lcdimradial.h" #include "drawitems/lcdimdiametric.h" @@ -699,6 +701,13 @@ LCVDrawItem_SPtr DocumentCanvas::asDrawable(const lc::entity::CADEntity_CSPtr& e return std::make_shared(text); } + // Add MText + auto mtext = std::dynamic_pointer_cast(entity); + + if (mtext != nullptr) { + return std::make_shared(mtext); + } + // Add 'Point' or 'Coordinate' auto coord = std::dynamic_pointer_cast(entity); diff --git a/lcviewernoqt/drawitems/lcvmtext.cpp b/lcviewernoqt/drawitems/lcvmtext.cpp new file mode 100644 index 000000000..76343e394 --- /dev/null +++ b/lcviewernoqt/drawitems/lcvmtext.cpp @@ -0,0 +1,156 @@ +#include "lcvmtext.h" +#include "../painters/lcpainter.h" +#include "../lcdrawoptions.h" +#include + +using namespace lc::viewer; + +LCVMText::LCVMText(const lc::entity::MText_CSPtr& mtext) : + LCVDrawItem(mtext, true), + _mtext(mtext) { +} + +/** +* TODO items for text: +* 1) Test multi-line text rendering +* 2) Accept color codes during text rendering in the form of \Cx (x is the index color) +* 3) Font selection +* For testing there is a lua script +* +* We can increase performance if we pre-calculate some values and cache them so that we +* don't have to keep calling text_extends and do some of the calculations +* also we shouldn't draw text smaller then XX pixels when rendered on screen. +*/ +void LCVMText::draw(LcPainter& painter, const LcDrawOptions& options, const lc::geo::Area& rect) const { + setFontFace(painter); + TextExtends te = painter.text_extends(_mtext->text_value().c_str()); + double alignX = 0.0; + double alignY = 0.0; + setAlignment(alignX, alignY, te.width); + + std::string textval = _mtext->text_value(); + std::vector lines; + std::string::size_type pos = 0; + std::string::size_type prev = 0; + while ((pos = textval.find('\n', prev)) != std::string::npos) + { + lines.push_back(textval.substr(prev, pos - prev)); + prev = pos + 1; + } + + // To get the last substring (or only, if delimiter is not found) + lines.push_back(textval.substr(prev)); + + double heightOffset = 0; + for (const std::string& line : lines) { + painter.font_size(_mtext->height(), false); + painter.save(); + painter.translate(_mtext->insertion_point().x(), -_mtext->insertion_point().y() + heightOffset); + painter.rotate(-_mtext->angle()); + painter.translate(alignX, -alignY); + painter.move_to(0., 0.); + painter.text(line.c_str()); + painter.stroke(); + painter.restore(); + + if (_mtext->strikethrough()) { + painter.save(); + painter.translate(_mtext->insertion_point().x(), -_mtext->insertion_point().y() - (te.height / 6.0)); + painter.rotate(-_mtext->angle()); + painter.translate(alignX, -alignY); + painter.move_to(0., 0); + painter.line_to(te.width, 0); + painter.stroke(); + painter.restore(); + } + + if (_mtext->underlined()) { + painter.save(); + painter.translate(_mtext->insertion_point().x(), -_mtext->insertion_point().y() + 8.0); + painter.rotate(-_mtext->angle()); + painter.translate(alignX, -alignY); + painter.move_to(0., 0); + painter.line_to(te.width, 0); + painter.stroke(); + painter.restore(); + } + + heightOffset += _mtext->height(); + } +} + +void LCVMText::setAlignment(double& alignX, double& alignY, const double textExtendsWidth) const { + switch (_mtext->valign()) { + case lc::TextConst::VAMiddle: + alignX += 0.0; + alignY += -_mtext->height() / 2. + (_mtext->height() * .2); + break; + + case lc::TextConst::VABottom: + alignX += 0.0; + alignY += 0.0 + (_mtext->height() * .2); + break; + + case lc::TextConst::VABaseline: + alignX += 0.0; + alignY += 0.0; + break; + + case lc::TextConst::VATop: + alignX += 0.0; + alignY += -_mtext->height() + (_mtext->height() * .2); + break; + + default: + break; + } + + // Horizontal Align: + switch (_mtext->halign()) { + case lc::TextConst::HALeft: + alignX += 0; + alignY += 0.; + break; + + case lc::TextConst::HACenter: + alignX += -textExtendsWidth / 2.0; + alignY += 0.; + break; + + case lc::TextConst::HAMiddle: + alignX += -textExtendsWidth / 2.0; + alignY += 0.; + break; + + case lc::TextConst::HARight: + alignX += -textExtendsWidth; + alignY += 0.; + break; + + default: + break; + } +} + +void LCVMText::setFontFace(LcPainter& painter) const { + if (_mtext->style() != "" && _mtext->style() != "STANDARD") { + if (_mtext->bold() && _mtext->italic()) { + painter.select_font_face(_mtext->style().c_str(), "BOLD_ITALIC"); + } + else if (_mtext->bold()) { + painter.select_font_face(_mtext->style().c_str(), "BOLD"); + } + else if (_mtext->italic()) { + painter.select_font_face(_mtext->style().c_str(), "ITALIC"); + } + else { + painter.select_font_face(_mtext->style().c_str(), "REGULAR"); + } + } +} + +lc::entity::CADEntity_CSPtr LCVMText::entity() const { + return _mtext; +} + + diff --git a/lcviewernoqt/drawitems/lcvmtext.h b/lcviewernoqt/drawitems/lcvmtext.h new file mode 100644 index 000000000..94a85b7db --- /dev/null +++ b/lcviewernoqt/drawitems/lcvmtext.h @@ -0,0 +1,37 @@ +#pragma once + +#include "lcvdrawitem.h" +#include "cad/primitive/mtext.h" + +namespace lc { + namespace viewer { + class LcDrawOptions; + + class LcPainter; + + class LCVMText : public LCVDrawItem { + public: + LCVMText(const lc::entity::MText_CSPtr& text); + + virtual ~LCVMText() = default; + + /** + * @brief draw, Drawing the text + * @param LcPainter painter, surface to be painted + * @param LcDrawOptions options + * @param geo::Area rect + */ + void draw(LcPainter& painter, const LcDrawOptions& options, const lc::geo::Area& rect) const override; + + lc::entity::CADEntity_CSPtr entity() const override; + + private: + void setAlignment(double& alignX, double& alignY, const double textExtendsWidth) const; + + void setFontFace(LcPainter& painter) const; + + private: + lc::entity::MText_CSPtr _mtext; + }; + } +} diff --git a/lcviewernoqt/drawitems/lcvtext.cpp b/lcviewernoqt/drawitems/lcvtext.cpp index 7dbd72d6e..1e79584e9 100644 --- a/lcviewernoqt/drawitems/lcvtext.cpp +++ b/lcviewernoqt/drawitems/lcvtext.cpp @@ -24,18 +24,7 @@ LCVText::LCVText(const lc::entity::Text_CSPtr& text) : void LCVText::draw(LcPainter& painter, const LcDrawOptions &options, const lc::geo::Area& rect) const { painter.font_size(_text->height(), false); if (_text->style() != "" && _text->style() != "STANDARD") { - if (_text->bold() && _text->italic()) { - painter.select_font_face(_text->style().c_str(), "BOLD_ITALIC"); - } - else if (_text->bold()) { - painter.select_font_face(_text->style().c_str(), "BOLD"); - } - else if (_text->italic()) { - painter.select_font_face(_text->style().c_str(), "ITALIC"); - } - else { - painter.select_font_face(_text->style().c_str(), "REGULAR"); - } + painter.select_font_face(_text->style().c_str(), "REGULAR"); } TextExtends te = painter.text_extends(_text->text_value().c_str()); @@ -104,28 +93,6 @@ void LCVText::draw(LcPainter& painter, const LcDrawOptions &options, const lc::g painter.text(_text->text_value().c_str()); painter.stroke(); painter.restore(); - - if (_text->strikethrough()) { - painter.save(); - painter.translate(_text->insertion_point().x(), -_text->insertion_point().y() - (te.height / 6.0)); - painter.rotate(-_text->angle()); - painter.translate(alignX, -alignY); - painter.move_to(0., 0); - painter.line_to(te.width, 0); - painter.stroke(); - painter.restore(); - } - - if (_text->underlined()) { - painter.save(); - painter.translate(_text->insertion_point().x(), -_text->insertion_point().y() + 8.0); - painter.rotate(-_text->angle()); - painter.translate(alignX, -alignY); - painter.move_to(0., 0); - painter.line_to(te.width, 0); - painter.stroke(); - painter.restore(); - } } lc::entity::CADEntity_CSPtr LCVText::entity() const { diff --git a/persistence/libdxfrw/dxfimpl.cpp b/persistence/libdxfrw/dxfimpl.cpp index a78f80293..9df7b8c42 100644 --- a/persistence/libdxfrw/dxfimpl.cpp +++ b/persistence/libdxfrw/dxfimpl.cpp @@ -2,12 +2,14 @@ #include "../generic/helpers.h" #include "../patternLoader/patternProvider.h" +#include #include #include #include #include #include +#include #include #include #include @@ -291,10 +293,6 @@ void DXFimpl::addText(const DRW_Text& data) { lc::TextConst::DrawingDirection(data.textgen), lc::TextConst::HAlign(data.alignH), lc::TextConst::VAlign(data.alignV), - false, - false, - false, - false, layer, mf, getBlock(data) @@ -546,7 +544,7 @@ void DXFimpl::addMText(const DRW_MText& data) { lineSpacingStyle = lc::TextConst::LineSpacingStyle::Exact; }*/ - auto lcText = std::make_shared(coord(data.basePoint), + auto lcMText = std::make_shared(coord(data.basePoint), data.text, data.height, data.angle * M_PI / 180, data.style, lc::TextConst::DrawingDirection(drawingDir), @@ -561,7 +559,7 @@ void DXFimpl::addMText(const DRW_MText& data) { getBlock(data) ); - _entityBuilder->appendEntity(lcText); + _entityBuilder->appendEntity(lcMText); } void DXFimpl::addHatch(const DRW_Hatch* data) { @@ -1348,9 +1346,12 @@ void DXFimpl::writeText(const lc::entity::Text_CSPtr& t) { DRW_Text tex; getEntityAttributes(&tex, t); + std::string correctedText = t->text_value(); + std::replace(correctedText.begin(), correctedText.end(), '\n', '\\'); + tex.basePoint.x = t->insertion_point().x(); tex.basePoint.y = t->insertion_point().y(); - tex.text = t->text_value(); + tex.text = correctedText; tex.textgen = t->textgeneration(); tex.height = t->height(); tex.angle = t->angle() * 180 / M_PI; @@ -1360,6 +1361,29 @@ void DXFimpl::writeText(const lc::entity::Text_CSPtr& t) { dxfW->writeText(&tex); } +void DXFimpl::writeMText(const lc::entity::MText_CSPtr& t) { + DRW_MText tex; + getEntityAttributes(&tex, t); + + std::string correctedText = t->text_value(); + size_t index = 0; + while (correctedText.find('\n', index) != std::string::npos) { + index = correctedText.find('\n'); + correctedText.replace(index, 1, "\\P"); + } + + tex.basePoint.x = t->insertion_point().x(); + tex.basePoint.y = t->insertion_point().y(); + tex.text = correctedText; + tex.textgen = t->textgeneration(); + tex.height = t->height(); + tex.angle = t->angle() * 180 / M_PI; + tex.alignH = DRW_Text::HAlign(t->halign()); + tex.alignV = DRW_Text::VAlign(t->valign()); + + dxfW->writeMText(&tex); +} + void DXFimpl::writeEntities() { for(const auto& e :_document->entityContainer().asVector()) { if(e->block() != nullptr) { @@ -1407,6 +1431,12 @@ void DXFimpl::writeEntity(const lc::entity::CADEntity_CSPtr& entity) { return; } + auto mtext = std::dynamic_pointer_cast(entity); + if (mtext != nullptr) { + writeMText(mtext); + return; + } + auto ellipse = std::dynamic_pointer_cast(entity); if (ellipse != nullptr) { writeEllipse(ellipse); diff --git a/persistence/libdxfrw/dxfimpl.h b/persistence/libdxfrw/dxfimpl.h index f34f090d0..faa5b9636 100644 --- a/persistence/libdxfrw/dxfimpl.h +++ b/persistence/libdxfrw/dxfimpl.h @@ -88,6 +88,8 @@ class DXFimpl : public DRW_Interface { void addText(const DRW_Text& data) override; + void addMText(const DRW_MText& data) override; + void addDimAlign(const DRW_DimAligned* data) override; void addDimLinear(const DRW_DimLinear* data) override; @@ -110,8 +112,6 @@ class DXFimpl : public DRW_Interface { void addPoint(const DRW_Point& data) override; - void addMText(const DRW_MText& data) override; - void addHatch(const DRW_Hatch* data) override; void addBlock(const DRW_Block& data) override; @@ -172,6 +172,8 @@ class DXFimpl : public DRW_Interface { void writeText(const lc::entity::Text_CSPtr& t); + void writeMText(const lc::entity::MText_CSPtr& t); + void writeInsert(const lc::entity::Insert_CSPtr& i); void writeLayer(const std::shared_ptr& layer);