mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-28 01:59:59 +01:00
[poincare] Factorize Parenthesis/SquareBracket layout in BracketLayout.
Change-Id: I2aeddb950803f460b75e6e9a0efd3c0e2f16164e
This commit is contained in:
@@ -91,6 +91,7 @@ objs += $(addprefix poincare/src/layout/,\
|
||||
absolute_value_layout.o\
|
||||
binomial_coefficient_layout.o\
|
||||
bounded_static_layout_hierarchy.o\
|
||||
bracket_layout.o\
|
||||
bracket_pair_layout.o\
|
||||
ceiling_layout.o\
|
||||
char_layout.o\
|
||||
@@ -108,12 +109,10 @@ objs += $(addprefix poincare/src/layout/,\
|
||||
left_square_bracket_layout.o\
|
||||
matrix_layout.o\
|
||||
nth_root_layout.o\
|
||||
parenthesis_layout.o\
|
||||
product_layout.o\
|
||||
right_parenthesis_layout.o\
|
||||
right_square_bracket_layout.o\
|
||||
sequence_layout.o\
|
||||
square_bracket_layout.o\
|
||||
static_layout_hierarchy.o\
|
||||
sum_layout.o\
|
||||
vertical_offset_layout.o\
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <poincare/src/layout/absolute_value_layout.h>
|
||||
#include <poincare/src/layout/binomial_coefficient_layout.h>
|
||||
#include <poincare/src/layout/bracket_pair_layout.h>
|
||||
#include <poincare/src/layout/left_square_bracket_layout.h>
|
||||
#include <poincare/src/layout/right_square_bracket_layout.h>
|
||||
#include <poincare/src/layout/ceiling_layout.h>
|
||||
#include <poincare/src/layout/char_layout.h>
|
||||
#include <poincare/src/layout/condensed_sum_layout.h>
|
||||
@@ -17,10 +15,12 @@
|
||||
#include <poincare/src/layout/grid_layout.h>
|
||||
#include <poincare/src/layout/horizontal_layout.h>
|
||||
#include <poincare/src/layout/integral_layout.h>
|
||||
#include <poincare/src/layout/left_parenthesis_layout.h>
|
||||
#include <poincare/src/layout/left_square_bracket_layout.h>
|
||||
#include <poincare/src/layout/matrix_layout.h>
|
||||
#include <poincare/src/layout/nth_root_layout.h>
|
||||
#include <poincare/src/layout/left_parenthesis_layout.h>
|
||||
#include <poincare/src/layout/right_parenthesis_layout.h>
|
||||
#include <poincare/src/layout/right_square_bracket_layout.h>
|
||||
#include <poincare/src/layout/product_layout.h>
|
||||
#include <poincare/src/layout/sequence_layout.h>
|
||||
#include <poincare/src/layout/sum_layout.h>
|
||||
|
||||
164
poincare/src/layout/bracket_layout.cpp
Normal file
164
poincare/src/layout/bracket_layout.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
#include "bracket_layout.h"
|
||||
#include <escher/metric.h>
|
||||
#include <poincare/expression_layout_cursor.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
}
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
static inline KDCoordinate max(KDCoordinate x, KDCoordinate y) { return (x>y ? x : y); }
|
||||
|
||||
BracketLayout::BracketLayout() :
|
||||
StaticLayoutHierarchy<0>(),
|
||||
m_operandHeightComputed(false)
|
||||
{
|
||||
}
|
||||
|
||||
void BracketLayout::invalidAllSizesPositionsAndBaselines() {
|
||||
m_operandHeightComputed = false;
|
||||
ExpressionLayout::invalidAllSizesPositionsAndBaselines();
|
||||
}
|
||||
|
||||
ExpressionLayoutCursor BracketLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) {
|
||||
assert(cursor->pointedExpressionLayout() == this);
|
||||
// Case: Right. Go Left.
|
||||
if (cursor->position() == ExpressionLayoutCursor::Position::Right) {
|
||||
return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left);
|
||||
}
|
||||
assert(cursor->position() == ExpressionLayoutCursor::Position::Left);
|
||||
// Case: Left. Ask the parent.
|
||||
if (m_parent) {
|
||||
return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout);
|
||||
}
|
||||
return ExpressionLayoutCursor();
|
||||
}
|
||||
|
||||
ExpressionLayoutCursor BracketLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) {
|
||||
assert(cursor->pointedExpressionLayout() == this);
|
||||
// Case: Left. Go Right.
|
||||
if (cursor->position() == ExpressionLayoutCursor::Position::Left) {
|
||||
return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right);
|
||||
}
|
||||
assert(cursor->position() == ExpressionLayoutCursor::Position::Right);
|
||||
// Case: Right. Ask the parent.
|
||||
if (m_parent) {
|
||||
return m_parent->cursorRightOf(cursor, shouldRecomputeLayout);
|
||||
}
|
||||
return ExpressionLayoutCursor();
|
||||
}
|
||||
|
||||
void BracketLayout::computeBaseline() {
|
||||
assert(m_parent != nullptr);
|
||||
int indexInParent = m_parent->indexOfChild(this);
|
||||
int numberOfSiblings = m_parent->numberOfChildren();
|
||||
if (((isLeftParenthesis() || isLeftBracket()) && indexInParent == numberOfSiblings - 1)
|
||||
|| ((isRightParenthesis() || isRightBracket()) && indexInParent == 0)
|
||||
|| ((isLeftParenthesis() || isLeftBracket()) && indexInParent < numberOfSiblings - 1 && m_parent->child(indexInParent + 1)->isVerticalOffset()))
|
||||
{
|
||||
/* The bracket does not have siblings on its open direction, or it is a left
|
||||
* bracket that is base of a superscript layout. In the latter case, it
|
||||
* should have a default baseline, else it creates an infinite loop as the
|
||||
* bracket needs the superscript baseline, which needs the bracket baseline.*/
|
||||
m_baseline = size().height()/2;
|
||||
m_baselined = true;
|
||||
return;
|
||||
}
|
||||
|
||||
int currentNumberOfOpenBrackets = 1;
|
||||
m_baseline = 0;
|
||||
int increment = (isLeftParenthesis() || isLeftBracket()) ? 1 : -1;
|
||||
for (int i = indexInParent + increment; i >= 0 && i < numberOfSiblings; i+=increment) {
|
||||
ExpressionLayout * sibling = m_parent->editableChild(i);
|
||||
if ((isLeftParenthesis() && sibling->isRightParenthesis())
|
||||
|| (isLeftBracket() && sibling->isRightBracket())
|
||||
|| (isRightParenthesis() && sibling->isLeftParenthesis())
|
||||
|| (isRightBracket() && sibling->isLeftBracket()))
|
||||
{
|
||||
if (i == indexInParent + increment) {
|
||||
/* If the bracket is immediately closed, we set the baseline to half the
|
||||
* bracket height. */
|
||||
m_baseline = size().height()/2;
|
||||
m_baselined = true;
|
||||
return;
|
||||
}
|
||||
currentNumberOfOpenBrackets--;
|
||||
if (currentNumberOfOpenBrackets == 0) {
|
||||
break;
|
||||
}
|
||||
} else if ((isLeftParenthesis() && sibling->isLeftParenthesis())
|
||||
|| (isLeftBracket() && sibling->isLeftBracket())
|
||||
|| (isRightParenthesis() && sibling->isRightParenthesis())
|
||||
|| (isRightBracket() && sibling->isRightBracket()))
|
||||
{
|
||||
currentNumberOfOpenBrackets++;
|
||||
}
|
||||
m_baseline = max(m_baseline, sibling->baseline());
|
||||
}
|
||||
m_baseline += (size().height() - operandHeight()) / 2;
|
||||
m_baselined = true;
|
||||
}
|
||||
|
||||
KDCoordinate BracketLayout::operandHeight() {
|
||||
if (!m_operandHeightComputed) {
|
||||
computeOperandHeight();
|
||||
}
|
||||
return m_operandHeight;
|
||||
}
|
||||
|
||||
void BracketLayout::computeOperandHeight() {
|
||||
assert(m_parent != nullptr);
|
||||
m_operandHeight = Metric::MinimalBracketAndParenthesisHeight;
|
||||
int indexInParent = m_parent->indexOfChild(this);
|
||||
int numberOfSiblings = m_parent->numberOfChildren();
|
||||
if ((isLeftParenthesis() || isLeftBracket())
|
||||
&& indexInParent < numberOfSiblings - 1
|
||||
&& m_parent->child(indexInParent + 1)->isVerticalOffset())
|
||||
{
|
||||
/* If a left bracket is the base of a superscript layout, it should have a
|
||||
* a default height, else it creates an infinite loop because the bracket
|
||||
* needs the superscript height, which needs the bracket height. */
|
||||
m_operandHeightComputed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
KDCoordinate maxUnderBaseline = 0;
|
||||
KDCoordinate maxAboveBaseline = 0;
|
||||
|
||||
int currentNumberOfOpenBrackets = 1;
|
||||
int increment = (isLeftParenthesis() || isLeftBracket()) ? 1 : -1;
|
||||
for (int i = indexInParent + increment; i >= 0 && i < numberOfSiblings; i+= increment) {
|
||||
ExpressionLayout * sibling = m_parent->editableChild(i);
|
||||
if ((isLeftParenthesis() && sibling->isRightParenthesis())
|
||||
|| (isLeftBracket() && sibling->isRightBracket())
|
||||
|| (isRightParenthesis() && sibling->isLeftParenthesis())
|
||||
|| (isRightBracket() && sibling->isLeftBracket()))
|
||||
{
|
||||
currentNumberOfOpenBrackets--;
|
||||
if (currentNumberOfOpenBrackets == 0) {
|
||||
break;
|
||||
}
|
||||
} else if ((isLeftParenthesis() && sibling->isLeftParenthesis())
|
||||
|| (isLeftBracket() && sibling->isLeftBracket())
|
||||
|| (isRightParenthesis() && sibling->isRightParenthesis())
|
||||
|| (isRightBracket() && sibling->isRightBracket()))
|
||||
{
|
||||
currentNumberOfOpenBrackets++;
|
||||
}
|
||||
KDCoordinate siblingHeight = sibling->size().height();
|
||||
KDCoordinate siblingBaseline = sibling->baseline();
|
||||
maxUnderBaseline = max(maxUnderBaseline, siblingHeight - siblingBaseline);
|
||||
maxAboveBaseline = max(maxAboveBaseline, siblingBaseline);
|
||||
}
|
||||
m_operandHeight = max(m_operandHeight, maxUnderBaseline + maxAboveBaseline);
|
||||
m_operandHeightComputed = true;
|
||||
|
||||
}
|
||||
|
||||
KDPoint BracketLayout::positionOfChild(ExpressionLayout * child) {
|
||||
assert(false);
|
||||
return KDPointZero;
|
||||
}
|
||||
|
||||
}
|
||||
24
poincare/src/layout/bracket_layout.h
Normal file
24
poincare/src/layout/bracket_layout.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef POINCARE_BRACKET_LAYOUT_H
|
||||
#define POINCARE_BRACKET_LAYOUT_H
|
||||
|
||||
#include <poincare/static_layout_hierarchy.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class BracketLayout : public StaticLayoutHierarchy<0> {
|
||||
public:
|
||||
BracketLayout();
|
||||
void invalidAllSizesPositionsAndBaselines() override;
|
||||
ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override;
|
||||
ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override;
|
||||
protected:
|
||||
void computeBaseline() override;
|
||||
KDCoordinate operandHeight();
|
||||
void computeOperandHeight();
|
||||
KDPoint positionOfChild(ExpressionLayout * child) override;
|
||||
bool m_operandHeightComputed;
|
||||
uint16_t m_operandHeight;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,174 +0,0 @@
|
||||
#include "parenthesis_layout.h"
|
||||
#include <escher/metric.h>
|
||||
#include <poincare/expression_layout_cursor.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
}
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
static inline int max(int x, int y) { return (x>y ? x : y); }
|
||||
|
||||
|
||||
ParenthesisLayout::ParenthesisLayout() :
|
||||
StaticLayoutHierarchy<0>(),
|
||||
m_operandHeightComputed(false)
|
||||
{
|
||||
}
|
||||
|
||||
void ParenthesisLayout::invalidAllSizesPositionsAndBaselines() {
|
||||
m_operandHeightComputed = false;
|
||||
ExpressionLayout::invalidAllSizesPositionsAndBaselines();
|
||||
}
|
||||
|
||||
ExpressionLayoutCursor ParenthesisLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) {
|
||||
assert(cursor->pointedExpressionLayout() == this);
|
||||
// Case: Right. Go Left.
|
||||
if (cursor->position() == ExpressionLayoutCursor::Position::Right) {
|
||||
return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left);
|
||||
}
|
||||
assert(cursor->position() == ExpressionLayoutCursor::Position::Left);
|
||||
// Case: Left. Ask the parent.
|
||||
if (m_parent) {
|
||||
return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout);
|
||||
}
|
||||
return ExpressionLayoutCursor();
|
||||
}
|
||||
|
||||
ExpressionLayoutCursor ParenthesisLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) {
|
||||
assert(cursor->pointedExpressionLayout() == this);
|
||||
// Case: Left. Go Right.
|
||||
if (cursor->position() == ExpressionLayoutCursor::Position::Left) {
|
||||
return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right);
|
||||
}
|
||||
assert(cursor->position() == ExpressionLayoutCursor::Position::Right);
|
||||
// Case: Right. Ask the parent.
|
||||
if (m_parent) {
|
||||
return m_parent->cursorRightOf(cursor, shouldRecomputeLayout);
|
||||
}
|
||||
return ExpressionLayoutCursor();
|
||||
}
|
||||
|
||||
KDSize ParenthesisLayout::computeSize() {
|
||||
return KDSize(parenthesisWidth(), operandHeight() + k_verticalMargin);
|
||||
}
|
||||
|
||||
void ParenthesisLayout::computeBaseline() {
|
||||
assert(m_parent != nullptr);
|
||||
bool isParenthesisLeft = isLeftParenthesis();
|
||||
int indexInParent = m_parent->indexOfChild(this);
|
||||
int numberOfSiblings = m_parent->numberOfChildren();
|
||||
if ((isParenthesisLeft && indexInParent == numberOfSiblings - 1)
|
||||
|| (!isParenthesisLeft && indexInParent == 0)
|
||||
|| (isParenthesisLeft && indexInParent < numberOfSiblings - 1 && m_parent->child(indexInParent + 1)->isVerticalOffset()))
|
||||
{
|
||||
/* The parenthesis does not have siblings on its open direction, or it is a
|
||||
* left parenthesis that is base of a superscript layout. In the latter
|
||||
* case, it should have a default baseline, else it creates an infinite loop
|
||||
* because the parenthesis needs the superscript height, which needs the
|
||||
* parenthesis baseline. */
|
||||
m_baseline = size().height()/2;
|
||||
m_baselined = true;
|
||||
return;
|
||||
}
|
||||
|
||||
int currentNumberOfOpenParentheses = 1;
|
||||
m_baseline = 0;
|
||||
int increment = isParenthesisLeft ? 1 : -1;
|
||||
for (int i = indexInParent + increment; i >= 0 && i <= numberOfSiblings - 1; i+= increment) {
|
||||
ExpressionLayout * sibling = m_parent->editableChild(i);
|
||||
if ((isParenthesisLeft && sibling->isRightParenthesis())
|
||||
|| (!isParenthesisLeft && sibling->isLeftParenthesis()))
|
||||
{
|
||||
if (i == indexInParent + increment) {
|
||||
/* If the parenthesis is immediately closed, we set the baseline to half
|
||||
* the parenthesis height. */
|
||||
m_baseline = size().height()/2;
|
||||
m_baselined = true;
|
||||
return;
|
||||
}
|
||||
currentNumberOfOpenParentheses--;
|
||||
if (currentNumberOfOpenParentheses == 0) {
|
||||
break;
|
||||
}
|
||||
} else if ((isParenthesisLeft && sibling->isLeftParenthesis())
|
||||
|| (!isParenthesisLeft && sibling->isRightParenthesis()))
|
||||
{
|
||||
currentNumberOfOpenParentheses++;
|
||||
}
|
||||
if (sibling->baseline() > m_baseline) {
|
||||
m_baseline = sibling->baseline();
|
||||
}
|
||||
}
|
||||
m_baseline += (size().height() - operandHeight()) / 2;
|
||||
m_baselined = true;
|
||||
}
|
||||
|
||||
KDCoordinate ParenthesisLayout::operandHeight() {
|
||||
if (!m_operandHeightComputed) {
|
||||
computeOperandHeight();
|
||||
m_operandHeightComputed = true;
|
||||
}
|
||||
return m_operandHeight;
|
||||
}
|
||||
|
||||
void ParenthesisLayout::computeOperandHeight() {
|
||||
assert(m_parent != nullptr);
|
||||
m_operandHeight = Metric::MinimalBracketAndParenthesisHeight;
|
||||
bool isParenthesisLeft = isLeftParenthesis();
|
||||
int indexInParent = m_parent->indexOfChild(this);
|
||||
int numberOfSiblings = m_parent->numberOfChildren();
|
||||
if (isParenthesisLeft
|
||||
&& indexInParent < numberOfSiblings - 1
|
||||
&& m_parent->child(indexInParent + 1)->isVerticalOffset())
|
||||
{
|
||||
/* If a left parenthesis is the base of a superscript layout, it should have
|
||||
* a default height, else it creates an infinite loop because the
|
||||
* parenthesis needs the superscript height, which needs the parenthesis
|
||||
* height. */
|
||||
return;
|
||||
}
|
||||
|
||||
KDCoordinate max_under_baseline = 0;
|
||||
KDCoordinate max_above_baseline = 0;
|
||||
|
||||
int currentNumberOfOpenParentheses = 1;
|
||||
int increment = isParenthesisLeft ? 1 : -1;
|
||||
for (int i = indexInParent + increment; i >= 0 && i < numberOfSiblings; i+= increment) {
|
||||
ExpressionLayout * sibling = m_parent->editableChild(i);
|
||||
if ((!isParenthesisLeft && sibling->isLeftParenthesis())
|
||||
|| (isParenthesisLeft && sibling->isRightParenthesis()))
|
||||
{
|
||||
currentNumberOfOpenParentheses--;
|
||||
if (currentNumberOfOpenParentheses == 0) {
|
||||
if (max_under_baseline + max_above_baseline > m_operandHeight) {
|
||||
m_operandHeight = max_under_baseline + max_above_baseline;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if ((isParenthesisLeft && sibling->isLeftParenthesis())
|
||||
|| (!isParenthesisLeft && sibling->isRightParenthesis()))
|
||||
{
|
||||
currentNumberOfOpenParentheses++;
|
||||
}
|
||||
KDCoordinate siblingHeight = sibling->size().height();
|
||||
KDCoordinate siblingBaseline = sibling->baseline();
|
||||
if (siblingHeight - siblingBaseline > max_under_baseline) {
|
||||
max_under_baseline = siblingHeight - siblingBaseline ;
|
||||
}
|
||||
if (siblingBaseline > max_above_baseline) {
|
||||
max_above_baseline = siblingBaseline;
|
||||
}
|
||||
}
|
||||
if (max_under_baseline + max_above_baseline > m_operandHeight) {
|
||||
m_operandHeight = max_under_baseline + max_above_baseline;
|
||||
}
|
||||
}
|
||||
|
||||
KDPoint ParenthesisLayout::positionOfChild(ExpressionLayout * child) {
|
||||
assert(false);
|
||||
return KDPointZero;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,13 @@
|
||||
#ifndef POINCARE_PARENTHESIS_LAYOUT_H
|
||||
#define POINCARE_PARENTHESIS_LAYOUT_H
|
||||
|
||||
#include <poincare/static_layout_hierarchy.h>
|
||||
#include "bracket_layout.h"
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class ParenthesisLayout : public StaticLayoutHierarchy<0> {
|
||||
class ParenthesisLayout : public BracketLayout {
|
||||
public:
|
||||
ParenthesisLayout();
|
||||
void invalidAllSizesPositionsAndBaselines() override;
|
||||
ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override;
|
||||
ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override;
|
||||
using BracketLayout::BracketLayout;
|
||||
constexpr static KDCoordinate parenthesisWidth() { return k_widthMargin + k_lineThickness + k_externWidthMargin; }
|
||||
constexpr static KDCoordinate k_parenthesisCurveWidth = 5;
|
||||
constexpr static KDCoordinate k_parenthesisCurveHeight = 7;
|
||||
@@ -21,14 +18,11 @@ public:
|
||||
constexpr static KDCoordinate k_verticalMargin = 4;
|
||||
protected:
|
||||
KDColor s_parenthesisWorkingBuffer[k_parenthesisCurveHeight*k_parenthesisCurveWidth];
|
||||
KDSize computeSize() override;
|
||||
void computeBaseline() override;
|
||||
KDCoordinate operandHeight();
|
||||
void computeOperandHeight();
|
||||
KDPoint positionOfChild(ExpressionLayout * child) override;
|
||||
bool m_operandHeightComputed;
|
||||
uint16_t m_operandHeight;
|
||||
KDSize computeSize() override {
|
||||
return KDSize(parenthesisWidth(), operandHeight() + k_verticalMargin);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
#include "square_bracket_layout.h"
|
||||
#include <escher/metric.h>
|
||||
#include <poincare/expression_layout_cursor.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
}
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
SquareBracketLayout::SquareBracketLayout() :
|
||||
StaticLayoutHierarchy<0>(),
|
||||
m_operandHeightComputed(false)
|
||||
{
|
||||
}
|
||||
|
||||
void SquareBracketLayout::invalidAllSizesPositionsAndBaselines() {
|
||||
m_operandHeightComputed = false;
|
||||
ExpressionLayout::invalidAllSizesPositionsAndBaselines();
|
||||
}
|
||||
|
||||
ExpressionLayoutCursor SquareBracketLayout::cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) {
|
||||
assert(cursor->pointedExpressionLayout() == this);
|
||||
// Case: Right. Go Left.
|
||||
if (cursor->position() == ExpressionLayoutCursor::Position::Right) {
|
||||
return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left);
|
||||
}
|
||||
assert(cursor->position() == ExpressionLayoutCursor::Position::Left);
|
||||
// Case: Left. Ask the parent.
|
||||
if (m_parent) {
|
||||
return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout);
|
||||
}
|
||||
return ExpressionLayoutCursor();
|
||||
}
|
||||
|
||||
ExpressionLayoutCursor SquareBracketLayout::cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) {
|
||||
assert(cursor->pointedExpressionLayout() == this);
|
||||
// Case: Left. Go Right.
|
||||
if (cursor->position() == ExpressionLayoutCursor::Position::Left) {
|
||||
return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right);
|
||||
}
|
||||
assert(cursor->position() == ExpressionLayoutCursor::Position::Right);
|
||||
// Case: Right. Ask the parent.
|
||||
if (m_parent) {
|
||||
return m_parent->cursorRightOf(cursor, shouldRecomputeLayout);
|
||||
}
|
||||
return ExpressionLayoutCursor();
|
||||
}
|
||||
|
||||
KDSize SquareBracketLayout::computeSize() {
|
||||
return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight() + k_lineThickness);
|
||||
}
|
||||
|
||||
void SquareBracketLayout::computeBaseline() {
|
||||
assert(m_parent != nullptr);
|
||||
m_baseline = operandHeight()/2;
|
||||
int currentNumberOfOpenBrackets = 1;
|
||||
int increment = isLeftBracket() ? 1 : -1;
|
||||
int numberOfSiblings = m_parent->numberOfChildren();
|
||||
for (int i = m_parent->indexOfChild(this) + increment; i >= 0 && i < numberOfSiblings; i+=increment) {
|
||||
ExpressionLayout * sibling = m_parent->editableChild(i);
|
||||
if ((isRightBracket() && sibling->isLeftBracket())
|
||||
|| (isLeftBracket() && sibling->isRightBracket()))
|
||||
{
|
||||
currentNumberOfOpenBrackets--;
|
||||
if (currentNumberOfOpenBrackets == 0) {
|
||||
break;
|
||||
}
|
||||
} else if ((isRightBracket() && sibling->isRightBracket())
|
||||
|| (isLeftBracket() && sibling->isLeftBracket()))
|
||||
{
|
||||
currentNumberOfOpenBrackets++;
|
||||
}
|
||||
if (sibling->baseline() > m_baseline) {
|
||||
m_baseline = sibling->baseline();
|
||||
}
|
||||
}
|
||||
m_baselined = true;
|
||||
}
|
||||
|
||||
KDCoordinate SquareBracketLayout::operandHeight() {
|
||||
if (!m_operandHeightComputed) {
|
||||
computeOperandHeight();
|
||||
}
|
||||
return m_operandHeight;
|
||||
}
|
||||
|
||||
void SquareBracketLayout::computeOperandHeight() {
|
||||
assert(m_parent != nullptr);
|
||||
m_operandHeight = Metric::MinimalBracketAndParenthesisHeight;
|
||||
int currentNumberOfOpenBrackets = 1;
|
||||
int increment = isLeftBracket() ? 1 : -1;
|
||||
int numberOfSiblings = m_parent->numberOfChildren();
|
||||
for (int i = m_parent->indexOfChild(this) + increment; i >= 0 && i < numberOfSiblings; i+=increment) {
|
||||
ExpressionLayout * sibling = m_parent->editableChild(i);
|
||||
if ((isRightBracket() && sibling->isLeftBracket())
|
||||
|| (isLeftBracket() && sibling->isRightBracket()))
|
||||
{
|
||||
currentNumberOfOpenBrackets--;
|
||||
if (currentNumberOfOpenBrackets == 0) {
|
||||
break;
|
||||
}
|
||||
} else if ((isRightBracket() && sibling->isRightBracket())
|
||||
|| (isLeftBracket() && sibling->isLeftBracket()))
|
||||
{
|
||||
currentNumberOfOpenBrackets++;
|
||||
}
|
||||
KDCoordinate siblingHeight = sibling->size().height();
|
||||
if (siblingHeight > m_operandHeight) {
|
||||
m_operandHeight = siblingHeight;
|
||||
}
|
||||
}
|
||||
m_operandHeightComputed = true;
|
||||
}
|
||||
|
||||
KDPoint SquareBracketLayout::positionOfChild(ExpressionLayout * child) {
|
||||
assert(false);
|
||||
return KDPointZero;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +1,21 @@
|
||||
#ifndef POINCARE_SQUARE_BRACKET_LAYOUT_H
|
||||
#define POINCARE_SQUARE_BRACKET_LAYOUT_H
|
||||
|
||||
#include <poincare/static_layout_hierarchy.h>
|
||||
#include "bracket_layout.h"
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class SquareBracketLayout : public StaticLayoutHierarchy<0> {
|
||||
class SquareBracketLayout : public BracketLayout {
|
||||
public:
|
||||
SquareBracketLayout();
|
||||
void invalidAllSizesPositionsAndBaselines() override;
|
||||
ExpressionLayoutCursor cursorLeftOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override;
|
||||
ExpressionLayoutCursor cursorRightOf(ExpressionLayoutCursor * cursor, bool * shouldRecomputeLayout) override;
|
||||
using BracketLayout::BracketLayout;
|
||||
protected:
|
||||
constexpr static KDCoordinate k_bracketWidth = 5;
|
||||
constexpr static KDCoordinate k_lineThickness = 1;
|
||||
constexpr static KDCoordinate k_widthMargin = 5;
|
||||
constexpr static KDCoordinate k_externWidthMargin = 2;
|
||||
KDSize computeSize() override;
|
||||
void computeBaseline() override;
|
||||
KDCoordinate operandHeight();
|
||||
void computeOperandHeight();
|
||||
KDPoint positionOfChild(ExpressionLayout * child) override;
|
||||
bool m_operandHeightComputed;
|
||||
uint16_t m_operandHeight;
|
||||
KDSize computeSize() override {
|
||||
return KDSize(k_externWidthMargin + k_lineThickness + k_widthMargin, operandHeight() + k_lineThickness);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user