diff --git a/apps/expression_editor/controller.cpp b/apps/expression_editor/controller.cpp index f29c14c61..625ac72a0 100644 --- a/apps/expression_editor/controller.cpp +++ b/apps/expression_editor/controller.cpp @@ -49,6 +49,7 @@ void Controller::insertLayoutAtCursor(ExpressionLayout * layout, ExpressionLayou m_cursor.setPointedExpressionLayout(pointedLayout); m_cursor.setPosition(ExpressionLayoutCursor::Position::Right); m_cursor.setPositionInside(0); + m_expressionLayout->invalidAllSizesPositionsAndBaselines(); m_view.cursorPositionChanged(); } diff --git a/poincare/include/poincare/expression_layout.h b/poincare/include/poincare/expression_layout.h index 021f891da..5ffac5992 100644 --- a/poincare/include/poincare/expression_layout.h +++ b/poincare/include/poincare/expression_layout.h @@ -31,7 +31,7 @@ public: KDPoint absoluteOrigin(); KDSize size(); KDCoordinate baseline(); - void invalidAllSizesPositionsAndBaselines(); + virtual void invalidAllSizesPositionsAndBaselines(); /* Hierarchy */ virtual const ExpressionLayout * const * children() const = 0; @@ -65,6 +65,8 @@ public: bool moveDownInside(ExpressionLayoutCursor * cursor); /* Other */ + virtual bool isLeftParenthesis() const { return false; } + virtual bool isRightParenthesis() const { return false; } virtual char XNTChar() const; protected: diff --git a/poincare/src/layout/expression_layout.cpp b/poincare/src/layout/expression_layout.cpp index 06321efe7..9f19d4040 100644 --- a/poincare/src/layout/expression_layout.cpp +++ b/poincare/src/layout/expression_layout.cpp @@ -13,7 +13,8 @@ ExpressionLayout::ExpressionLayout() : m_sized(false), m_baselined(false), m_positioned(false), - m_frame(KDRectZero) { + m_frame(KDRectZero) +{ } const ExpressionLayout * const * ExpressionLayout::ExpressionLayoutArray2(const ExpressionLayout * e1, const ExpressionLayout * e2) { diff --git a/poincare/src/layout/parenthesis_left_layout.cpp b/poincare/src/layout/parenthesis_left_layout.cpp index 43e3939db..6af8a7172 100644 --- a/poincare/src/layout/parenthesis_left_layout.cpp +++ b/poincare/src/layout/parenthesis_left_layout.cpp @@ -32,7 +32,6 @@ ExpressionLayout * ParenthesisLeftLayout::clone() const { } void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - //TODO Make sure m_operandHeight is up-to-date. KDRect frame(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, p.y()+ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, @@ -41,7 +40,7 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topLeftCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); frame = KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, - p.y() + m_operandHeight - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, + p.y() + operandHeight() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, ParenthesisLeftRightLayout::k_parenthesisCurveHeight); @@ -50,8 +49,40 @@ void ParenthesisLeftLayout::render(KDContext * ctx, KDPoint p, KDColor expressio ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_externWidthMargin, p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_lineThickness, - m_operandHeight - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + operandHeight() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), expressionColor); } +void ParenthesisLeftLayout::computeOperandHeight() { + assert(m_parent != nullptr); + m_operandHeight = 18; + int numberOfBrothers = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isRightParenthesis()) { + return; + } + KDCoordinate brotherHeight = brother->size().height(); + if (brotherHeight > m_operandHeight) { + m_operandHeight = brotherHeight; + } + } +} + +void ParenthesisLeftLayout::computeBaseline() { + assert(m_parent != nullptr); + m_baseline = operandHeight()/2; + int numberOfBrothers = m_parent->numberOfChildren(); + for (int i = m_parent->indexOfChild(this) + 1; i < numberOfBrothers; i++) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isRightParenthesis()) { + break; + } + if (brother->baseline() > m_baseline) { + m_baseline = brother->baseline(); + } + } + m_baselined = true; +} + } diff --git a/poincare/src/layout/parenthesis_left_layout.h b/poincare/src/layout/parenthesis_left_layout.h index ad0b60906..538d5c2de 100644 --- a/poincare/src/layout/parenthesis_left_layout.h +++ b/poincare/src/layout/parenthesis_left_layout.h @@ -9,8 +9,11 @@ class ParenthesisLeftLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; + bool isLeftParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void computeOperandHeight() override; + void computeBaseline() override; }; } diff --git a/poincare/src/layout/parenthesis_left_right_layout.cpp b/poincare/src/layout/parenthesis_left_right_layout.cpp index 0764efa73..f3b77ee95 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.cpp +++ b/poincare/src/layout/parenthesis_left_right_layout.cpp @@ -9,9 +9,13 @@ namespace Poincare { ParenthesisLeftRightLayout::ParenthesisLeftRightLayout() : StaticLayoutHierarchy<0>(), - m_operandHeight(18) //TODO + m_operandHeightComputed(false) { - computeBaseline(); +} + +void ParenthesisLeftRightLayout::invalidAllSizesPositionsAndBaselines() { + m_operandHeightComputed = false; + ExpressionLayout::invalidAllSizesPositionsAndBaselines(); } bool ParenthesisLeftRightLayout::moveLeft(ExpressionLayoutCursor * cursor) { @@ -49,13 +53,15 @@ bool ParenthesisLeftRightLayout::moveRight(ExpressionLayoutCursor * cursor) { } KDSize ParenthesisLeftRightLayout::computeSize() { - //TODO: compute the operandHeight according to the brothers - return KDSize(k_widthMargin + k_lineThickness + k_externWidthMargin, m_operandHeight); + return KDSize(k_widthMargin + k_lineThickness + k_externWidthMargin, operandHeight()); } -void ParenthesisLeftRightLayout::computeBaseline() { - m_baseline = m_operandHeight/2; //TODO - m_baselined = true; +KDCoordinate ParenthesisLeftRightLayout::operandHeight() { + if (!m_operandHeightComputed) { + computeOperandHeight(); + m_operandHeightComputed = true; + } + return m_operandHeight; } KDPoint ParenthesisLeftRightLayout::positionOfChild(ExpressionLayout * child) { diff --git a/poincare/src/layout/parenthesis_left_right_layout.h b/poincare/src/layout/parenthesis_left_right_layout.h index 67381f10a..3ad0a296b 100644 --- a/poincare/src/layout/parenthesis_left_right_layout.h +++ b/poincare/src/layout/parenthesis_left_right_layout.h @@ -8,6 +8,7 @@ namespace Poincare { class ParenthesisLeftRightLayout : public StaticLayoutHierarchy<0> { public: ParenthesisLeftRightLayout(); + void invalidAllSizesPositionsAndBaselines() override; bool moveLeft(ExpressionLayoutCursor * cursor) override; bool moveRight(ExpressionLayoutCursor * cursor) override; constexpr static KDCoordinate k_parenthesisCurveWidth = 5; @@ -19,8 +20,10 @@ public: protected: KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth]; KDSize computeSize() override; - void computeBaseline() override; + KDCoordinate operandHeight(); + virtual void computeOperandHeight() = 0; KDPoint positionOfChild(ExpressionLayout * child) override; + bool m_operandHeightComputed; uint16_t m_operandHeight; }; } diff --git a/poincare/src/layout/parenthesis_right_layout.cpp b/poincare/src/layout/parenthesis_right_layout.cpp index d9a8d4c6c..55fc71743 100644 --- a/poincare/src/layout/parenthesis_right_layout.cpp +++ b/poincare/src/layout/parenthesis_right_layout.cpp @@ -32,7 +32,6 @@ ExpressionLayout * ParenthesisRightLayout::clone() const { } void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { - //TODO Make sure m_operandHeight is up-to-date. KDRect frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, p.y() + ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, @@ -41,7 +40,7 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi ctx->blendRectWithMask(frame, expressionColor, (const uint8_t *)topRightCurve, (KDColor *)(ParenthesisLeftRightLayout::s_parenthesisWorkingBuffer)); frame = KDRect(p.x() + ParenthesisLeftRightLayout::k_widthMargin + ParenthesisLeftRightLayout::k_lineThickness - ParenthesisLeftRightLayout::k_parenthesisCurveWidth, - p.y() + m_operandHeight - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, + p.y() + operandHeight() - ParenthesisLeftRightLayout::k_parenthesisCurveHeight - ParenthesisLeftRightLayout::k_externHeightMargin, ParenthesisLeftRightLayout::k_parenthesisCurveWidth, ParenthesisLeftRightLayout::k_parenthesisCurveHeight); @@ -50,10 +49,40 @@ void ParenthesisRightLayout::render(KDContext * ctx, KDPoint p, KDColor expressi ctx->fillRect(KDRect(p.x()+ParenthesisLeftRightLayout::k_widthMargin, p.y()+ParenthesisLeftRightLayout::k_parenthesisCurveHeight+2, ParenthesisLeftRightLayout::k_lineThickness, - m_operandHeight - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), + operandHeight() - 2*(ParenthesisLeftRightLayout::k_parenthesisCurveHeight+ParenthesisLeftRightLayout::k_externHeightMargin)), expressionColor); } +void ParenthesisRightLayout::computeOperandHeight() { + m_operandHeight = 18; + assert(m_parent != nullptr); + for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isLeftParenthesis()) { + return; + } + KDCoordinate brotherHeight = brother->size().height(); + if (brotherHeight > m_operandHeight) { + m_operandHeight = brotherHeight; + } + } +} + +void ParenthesisRightLayout::computeBaseline() { + assert(m_parent != nullptr); + m_baseline = operandHeight()/2; + for (int i = m_parent->indexOfChild(this) - 1; i >= 0; i--) { + ExpressionLayout * brother = m_parent->editableChild(i); + if (brother->isLeftParenthesis()) { + break; + } + if (brother->baseline() > m_baseline) { + m_baseline = brother->baseline(); + } + } + m_baselined = true; +} + } diff --git a/poincare/src/layout/parenthesis_right_layout.h b/poincare/src/layout/parenthesis_right_layout.h index 7daba2368..c03d19efd 100644 --- a/poincare/src/layout/parenthesis_right_layout.h +++ b/poincare/src/layout/parenthesis_right_layout.h @@ -9,8 +9,11 @@ class ParenthesisRightLayout : public ParenthesisLeftRightLayout { public: using ParenthesisLeftRightLayout::ParenthesisLeftRightLayout; ExpressionLayout * clone() const override; + bool isRightParenthesis() const override { return true; } protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + void computeOperandHeight() override; + void computeBaseline() override; }; }