[poincare] Added UneditableHorizontalTrioLayout.

Change-Id: Ifd9fd6a0a0714853c1a8cd428b65076b704a8211
This commit is contained in:
Léa Saviot
2017-12-22 13:19:15 +01:00
parent 2c261f7ea9
commit fccd9b484b
4 changed files with 200 additions and 0 deletions

View File

@@ -114,6 +114,7 @@ objs += $(addprefix poincare/src/layout/,\
static_layout_hierarchy.o\
string_layout.o\
sum_layout.o\
uneditable_horizontal_trio_layout.o\
uneditable_parenthesis_left_layout.o\
uneditable_parenthesis_right_layout.o\
)

View File

@@ -28,5 +28,6 @@
#include <poincare/src/layout/sequence_layout.h>
#include <poincare/src/layout/string_layout.h>
#include <poincare/src/layout/sum_layout.h>
#include <poincare/src/layout/uneditable_horizontal_trio_layout.h>
#endif

View File

@@ -0,0 +1,156 @@
#include "uneditable_horizontal_trio_layout.h"
#include "empty_visible_layout.h"
#include <poincare/expression_layout_cursor.h>
extern "C" {
#include <assert.h>
}
namespace Poincare {
ExpressionLayout * UneditableHorizontalTrioLayout::clone() const {
UneditableHorizontalTrioLayout * layout = new UneditableHorizontalTrioLayout(
const_cast<UneditableHorizontalTrioLayout *>(this)->leftLayout(),
const_cast<UneditableHorizontalTrioLayout *>(this)->centerLayout(),
const_cast<UneditableHorizontalTrioLayout *>(this)->rightLayout(),
true);
return layout;
}
void UneditableHorizontalTrioLayout::backspaceAtCursor(ExpressionLayoutCursor * cursor) {
if (cursor->pointedExpressionLayout() == this
&& cursor->position() == ExpressionLayoutCursor::Position::Right)
{
ExpressionLayout * previousParent = m_parent;
int indexInParent = previousParent->indexOfChild(this);
replaceWith(new EmptyVisibleLayout(), true);
if (indexInParent == 0) {
cursor->setPointedExpressionLayout(previousParent);
return;
}
cursor->setPointedExpressionLayout(previousParent->editableChild(indexInParent - 1));
cursor->setPosition(ExpressionLayoutCursor::Position::Right);
return;
}
ExpressionLayout::backspaceAtCursor(cursor);
}
bool UneditableHorizontalTrioLayout::moveLeft(ExpressionLayoutCursor * cursor) {
if (cursor->pointedExpressionLayout() == centerLayout()) {
// Case: Center layout.
// Go Left.
assert(cursor->position() == ExpressionLayoutCursor::Position::Left);
cursor->setPointedExpressionLayout(this);
return true;
}
assert(cursor->pointedExpressionLayout() == this);
if (cursor->position() == ExpressionLayoutCursor::Position::Right) {
// Case: Right.
// Go Right of the center layout's last child if it has one, else go Right
// of the center layout.
ExpressionLayout * grandChild = centerLayout()->editableChild(centerLayout()->numberOfChildren()-1);
if (grandChild != nullptr) {
cursor->setPointedExpressionLayout(grandChild);
return true;
}
cursor->setPointedExpressionLayout(centerLayout());
return true;
}
assert(cursor->position() == ExpressionLayoutCursor::Position::Left);
// Case: Left.
// Ask the parent.
if (m_parent) {
return m_parent->moveLeft(cursor);
}
return false;
}
bool UneditableHorizontalTrioLayout::moveRight(ExpressionLayoutCursor * cursor) {
if (cursor->pointedExpressionLayout() == centerLayout()) {
// Case: Center layout.
// Go Right.
assert(cursor->position() == ExpressionLayoutCursor::Position::Right);
cursor->setPointedExpressionLayout(this);
return true;
}
assert(cursor->pointedExpressionLayout() == this);
if (cursor->position() == ExpressionLayoutCursor::Position::Left) {
// Case: Left.
// Go Left of the center layout's first child if it has one, else go Left of
// the center layout.
ExpressionLayout * grandChild = centerLayout()->editableChild(0);
if (grandChild != nullptr) {
cursor->setPointedExpressionLayout(grandChild);
return true;
}
cursor->setPointedExpressionLayout(centerLayout());
return true;
}
assert(cursor->position() == ExpressionLayoutCursor::Position::Right);
// Case: Right.
// Ask the parent.
if (m_parent) {
return m_parent->moveRight(cursor);
}
return false;
}
void UneditableHorizontalTrioLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) {
}
KDSize UneditableHorizontalTrioLayout::computeSize() {
// TODO: This code is duplicated from horizontal_layout.cpp.
KDCoordinate totalWidth = 0;
int i = 0;
KDCoordinate max_under_baseline = 0;
KDCoordinate max_above_baseline = 0;
while (ExpressionLayout * c = editableChild(i++)) {
KDSize childSize = c->size();
totalWidth += childSize.width();
if (childSize.height() - c->baseline() > max_under_baseline) {
max_under_baseline = childSize.height() - c->baseline() ;
}
if (c->baseline() > max_above_baseline) {
max_above_baseline = c->baseline();
}
}
return KDSize(totalWidth, max_under_baseline + max_above_baseline);
}
void UneditableHorizontalTrioLayout::computeBaseline() {
// TODO: This code is duplicated from horizontal_layout.cpp.
m_baseline = 0;
for (int i = 0; i < numberOfChildren(); i++) {
if (editableChild(i)->baseline() > m_baseline) {
m_baseline = editableChild(i)->baseline();
}
}
m_baselined = true;
}
KDPoint UneditableHorizontalTrioLayout::positionOfChild(ExpressionLayout * child) {
// TODO: This code is duplicated from horizontal_layout.cpp.
KDCoordinate x = 0;
KDCoordinate y = 0;
int index = indexOfChild(child);
if (index > 0) {
ExpressionLayout * previousChild = editableChild(index-1);
assert(previousChild != nullptr);
x = previousChild->origin().x() + previousChild->size().width();
}
y = baseline() - child->baseline();
return KDPoint(x, y);
}
ExpressionLayout * UneditableHorizontalTrioLayout::leftLayout() {
return editableChild(0);
}
ExpressionLayout * UneditableHorizontalTrioLayout::centerLayout() {
return editableChild(1);
}
ExpressionLayout * UneditableHorizontalTrioLayout::rightLayout() {
return editableChild(2);
}
}

View File

@@ -0,0 +1,42 @@
#ifndef POINCARE_UNEDITABLE_HORIZONTAL_TRIO_LAYOUT_H
#define POINCARE_UNEDITABLE_HORIZONTAL_TRIO_LAYOUT_H
#include <poincare/static_layout_hierarchy.h>
namespace Poincare {
/* UneditableHorizontalTrioLayout has 3 children: a left and a right layout
* (usually parentheses or brackets), and a central layout.
* The cursor can only be:
* - Left or Right of the UneditableHorizontalTrioLayout,
* - Left or Right of the central layout if it is not an horizontal layout,
* - Inside the central layout if it is an horizontal layout.
* This way, the lateral children of an UneditableHorizontalTrioLayout cannot be
* edited, and it it will always have only 3 children.
* This layout can be used to create binomial coefficient layouts, matrix
* layouts or the argument of sum and product layouts. */
class UneditableHorizontalTrioLayout : public StaticLayoutHierarchy<3> {
public:
using StaticLayoutHierarchy::StaticLayoutHierarchy;
ExpressionLayout * clone() const override;
void backspaceAtCursor(ExpressionLayoutCursor * cursor) override;
/* Navigation */
bool moveLeft(ExpressionLayoutCursor * cursor) override;
bool moveRight(ExpressionLayoutCursor * cursor) override;
protected:
void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override;
KDSize computeSize() override;
void computeBaseline() override;
KDPoint positionOfChild(ExpressionLayout * child) override;
private:
ExpressionLayout * leftLayout();
ExpressionLayout * centerLayout();
ExpressionLayout * rightLayout();
};
}
#endif