diff --git a/poincare/include/poincare/absolute_value_layout.h b/poincare/include/poincare/absolute_value_layout.h index d1cab825d..6e9c71ff3 100644 --- a/poincare/include/poincare/absolute_value_layout.h +++ b/poincare/include/poincare/absolute_value_layout.h @@ -29,7 +29,7 @@ public: private: KDCoordinate widthMargin() const override { return 2; } - virtual KDCoordinate verticalExternMargin() const override { return 1; } + KDCoordinate verticalExternMargin() const override { return 1; } bool renderTopBar() const override { return false; } bool renderBottomBar() const override { return false; } }; diff --git a/poincare/include/poincare/bracket_pair_layout.h b/poincare/include/poincare/bracket_pair_layout.h index f1fcd0879..2196c7be9 100644 --- a/poincare/include/poincare/bracket_pair_layout.h +++ b/poincare/include/poincare/bracket_pair_layout.h @@ -49,6 +49,7 @@ private: virtual KDCoordinate verticalExternMargin() const { return k_verticalExternMargin; } virtual bool renderTopBar() const { return true; } virtual bool renderBottomBar() const { return true; } + virtual bool renderDoubleBar() const { return false; } void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor, Layout * selectionStart = nullptr, Layout * selectionEnd = nullptr, KDColor selectionColor = KDColorRed) override; }; diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index a6a0f670f..8e7959cc0 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -39,6 +39,7 @@ public: RightParenthesisLayout, RightSquareBracketLayout, SumLayout, + VectorNormLayout, VerticalOffsetLayout }; diff --git a/poincare/include/poincare/vector_norm.h b/poincare/include/poincare/vector_norm.h index f0572ada4..c13a6a1d8 100644 --- a/poincare/include/poincare/vector_norm.h +++ b/poincare/include/poincare/vector_norm.h @@ -25,8 +25,7 @@ private: int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; // Simplification Expression shallowReduce(ReductionContext reductionContext) override; - LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; }; - LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; } + LayoutShape leftLayoutShape() const override { return LayoutShape::BoundaryPunctuation; } // Evaluation Evaluation approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } Evaluation approximate(DoublePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } diff --git a/poincare/include/poincare/vector_norm_layout.h b/poincare/include/poincare/vector_norm_layout.h new file mode 100644 index 000000000..5c10dac87 --- /dev/null +++ b/poincare/include/poincare/vector_norm_layout.h @@ -0,0 +1,46 @@ +#ifndef POINCARE_VECTOR_NORM_LAYOUT_NODE_H +#define POINCARE_VECTOR_NORM_LAYOUT_NODE_H + +#include +#include +#include + +namespace Poincare { + +class VectorNormLayoutNode final : public BracketPairLayoutNode { +public: + using BracketPairLayoutNode::BracketPairLayoutNode; + + // Layout + Type type() const override { return Type::VectorNormLayout; } + + // SerializationHelperInterface + int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { + return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, VectorNorm::s_functionHelper.name(), true); + } + + // TreeNode + size_t size() const override { return sizeof(VectorNormLayoutNode); } +#if POINCARE_TREE_LOG + void logNodeName(std::ostream & stream) const override { + stream << "VectorNormLayout"; + } +#endif + +private: + KDCoordinate widthMargin() const override { return 2; } + KDCoordinate verticalExternMargin() const override { return 1; } + bool renderTopBar() const override { return false; } + bool renderBottomBar() const override { return false; } + bool renderDoubleBar() const override { return true; } +}; + +class VectorNormLayout final : public Layout { +public: + static VectorNormLayout Builder(Layout child) { return TreeHandle::FixedArityBuilder({child}); } + VectorNormLayout() = delete; +}; + +} + +#endif diff --git a/poincare/include/poincare_layouts.h b/poincare/include/poincare_layouts.h index 071880507..72cb49ac6 100644 --- a/poincare/include/poincare_layouts.h +++ b/poincare/include/poincare_layouts.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #endif diff --git a/poincare/src/bracket_pair_layout.cpp b/poincare/src/bracket_pair_layout.cpp index b42a930b5..67ccbf53b 100644 --- a/poincare/src/bracket_pair_layout.cpp +++ b/poincare/src/bracket_pair_layout.cpp @@ -114,22 +114,41 @@ int BracketPairLayoutNode::serialize(char * buffer, int bufferSize, Preferences: void BracketPairLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor, Layout * selectionStart, Layout * selectionEnd, KDColor selectionColor) { KDSize childSize = childLayout()->layoutSize(); KDCoordinate verticalBarHeight = childSize.height() + 2*k_verticalMargin; - ctx->fillRect(KDRect(p.x()+externWidthMargin(), p.y()+verticalExternMargin(), k_lineThickness, verticalBarHeight), expressionColor); - ctx->fillRect(KDRect(p.x()+externWidthMargin()+childSize.width()+2*widthMargin()+k_lineThickness, p.y()+verticalExternMargin(), k_lineThickness, verticalBarHeight), expressionColor); + KDCoordinate horizontalPosition = p.x() + externWidthMargin(); + KDCoordinate verticalPosition = p.y() + verticalExternMargin(); + if (renderDoubleBar()) { + ctx->fillRect(KDRect(horizontalPosition, verticalPosition, k_lineThickness, verticalBarHeight), expressionColor); + horizontalPosition += k_lineThickness + widthMargin(); + } + ctx->fillRect(KDRect(horizontalPosition, verticalPosition, k_lineThickness, verticalBarHeight), expressionColor); if (renderTopBar()) { - ctx->fillRect(KDRect(p.x()+externWidthMargin(), p.y()+verticalExternMargin(), k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+externWidthMargin()+2*k_lineThickness+childSize.width()+2*widthMargin()-k_bracketWidth, p.y() + verticalExternMargin(), k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(horizontalPosition, verticalPosition, k_bracketWidth, k_lineThickness), expressionColor); } if (renderBottomBar()) { - ctx->fillRect(KDRect(p.x()+externWidthMargin(), p.y()+verticalExternMargin()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); - ctx->fillRect(KDRect(p.x()+externWidthMargin()+2*k_lineThickness+childSize.width()+2*widthMargin()-k_bracketWidth, p.y()+verticalExternMargin()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(horizontalPosition, verticalPosition + verticalBarHeight - k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + } + horizontalPosition += k_lineThickness + widthMargin() + childSize.width() + widthMargin(); + ctx->fillRect(KDRect(horizontalPosition, verticalPosition, k_lineThickness, verticalBarHeight), expressionColor); + horizontalPosition += k_lineThickness; + if (renderTopBar()) { + ctx->fillRect(KDRect(horizontalPosition - k_bracketWidth, verticalPosition, k_bracketWidth, k_lineThickness), expressionColor); + } + if (renderBottomBar()) { + ctx->fillRect(KDRect(horizontalPosition - k_bracketWidth, verticalPosition + verticalBarHeight - k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor); + } + if (renderDoubleBar()) { + horizontalPosition += widthMargin(); + ctx->fillRect(KDRect(horizontalPosition, verticalPosition, k_lineThickness, verticalBarHeight), expressionColor); } } KDSize BracketPairLayoutNode::computeSize() { KDSize childSize = childLayout()->layoutSize(); - KDSize result = KDSize(childSize.width() + 2*externWidthMargin() + 2*widthMargin() + 2*k_lineThickness, childSize.height() + 2 * k_verticalMargin + 2*verticalExternMargin()); - return result; + KDCoordinate horizontalCoordinates = childSize.width() + 2*externWidthMargin() + 2*widthMargin() + 2*k_lineThickness; + if (renderDoubleBar()) { + horizontalCoordinates += 2*k_lineThickness + 2*widthMargin(); + } + return KDSize(horizontalCoordinates, childSize.height() + 2 * k_verticalMargin + 2*verticalExternMargin()); } KDCoordinate BracketPairLayoutNode::computeBaseline() { @@ -138,7 +157,11 @@ KDCoordinate BracketPairLayoutNode::computeBaseline() { KDPoint BracketPairLayoutNode::positionOfChild(LayoutNode * child) { assert(child == childLayout()); - return KDPoint(widthMargin() + externWidthMargin() + k_lineThickness, k_verticalMargin + verticalExternMargin()); + KDCoordinate horizontalCoordinates = widthMargin() + externWidthMargin() + k_lineThickness; + if (renderDoubleBar()) { + horizontalCoordinates += k_lineThickness + widthMargin(); + } + return KDPoint(horizontalCoordinates, k_verticalMargin + verticalExternMargin()); } } diff --git a/poincare/src/horizontal_layout.cpp b/poincare/src/horizontal_layout.cpp index 0f743904b..7ec6f4fe2 100644 --- a/poincare/src/horizontal_layout.cpp +++ b/poincare/src/horizontal_layout.cpp @@ -217,7 +217,8 @@ int HorizontalLayoutNode::serializeChildrenBetweenIndexes(char * buffer, int buf || (nextChildType == LayoutNode::Type::NthRootLayout && !static_cast(nextChild)->isSquareRoot()) || nextChildType == LayoutNode::Type::ProductLayout - || nextChildType == LayoutNode::Type::SumLayout) + || nextChildType == LayoutNode::Type::SumLayout + || nextChildType == LayoutNode::Type::VectorNormLayout) && currentChild->canBeOmittedMultiplicationLeftFactor()) { assert(nextChildType != LayoutNode::Type::HorizontalLayout); diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index 4e1d2c511..992e22cee 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -372,6 +372,7 @@ template Unreal TreeHandle::FixedArityBuilder(const Tuple &) template VectorCross TreeHandle::FixedArityBuilder(const Tuple &); template VectorDot TreeHandle::FixedArityBuilder(const Tuple &); template VectorNorm TreeHandle::FixedArityBuilder(const Tuple &); +template VectorNormLayout TreeHandle::FixedArityBuilder(const Tuple &); template MatrixLayout TreeHandle::NAryBuilder(const Tuple &); } diff --git a/poincare/src/vector_norm.cpp b/poincare/src/vector_norm.cpp index aeef1f8a3..85a3ff59b 100644 --- a/poincare/src/vector_norm.cpp +++ b/poincare/src/vector_norm.cpp @@ -1,9 +1,10 @@ -#include #include #include #include #include #include +#include +#include namespace Poincare { @@ -16,7 +17,7 @@ Expression VectorNormNode::shallowReduce(ReductionContext reductionContext) { } Layout VectorNormNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return LayoutHelper::Prefix(VectorNorm(this), floatDisplayMode, numberOfSignificantDigits, VectorNorm::s_functionHelper.name()); + return VectorNormLayout::Builder(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } int VectorNormNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {