[poincare] Show grey squares in a matrix only if the cursor is in it.

Change-Id: I2e622de51a9c7af7b676ae9bd7bb3e9681f5d051
This commit is contained in:
Léa Saviot
2018-01-11 14:11:50 +01:00
parent 914b181e06
commit bf4ccd76ea
8 changed files with 155 additions and 8 deletions

View File

@@ -62,6 +62,8 @@ void Controller::insertLayoutAtCursor(ExpressionLayout * layout, ExpressionLayou
bool Controller::privateHandleEvent(Ion::Events::Event event) {
if (handleMoveEvent(event)) {
m_expressionLayout->invalidAllSizesPositionsAndBaselines();
m_view.layoutSubviews();
return true;
}
ExpressionLayout * newPointedLayout = handleAddEvent(event);

View File

@@ -85,8 +85,8 @@ public:
ExpressionLayoutCursor * cursor,
ExpressionLayout * previousLayout = nullptr,
ExpressionLayout * previousPreviousLayout = nullptr);
bool moveUpInside(ExpressionLayoutCursor * cursor);
bool moveDownInside(ExpressionLayoutCursor * cursor);
virtual bool moveUpInside(ExpressionLayoutCursor * cursor);
virtual bool moveDownInside(ExpressionLayoutCursor * cursor);
/* Expression Engine */
virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0;

View File

@@ -20,6 +20,7 @@ public:
bool moveRight(ExpressionLayoutCursor * cursor) override;
int writeTextInBuffer(char * buffer, int bufferSize) const override;
bool isEmpty() const override { return true; }
Color color() const { return m_color; }
void setColor(Color color) { m_color = color; }
protected:
virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override;

View File

@@ -228,6 +228,7 @@ void GridLayout::addEmptyRow(EmptyVisibleLayout::Color color) {
}
addChildrenAtIndex(const_cast<const ExpressionLayout * const *>(const_cast<ExpressionLayout * const *>(newChildren)), m_numberOfColumns, numberOfChildren(), false);
m_numberOfRows++;
invalidAllSizesPositionsAndBaselines();
}
void GridLayout::addEmptyColumn(EmptyVisibleLayout::Color color) {
@@ -235,6 +236,7 @@ void GridLayout::addEmptyColumn(EmptyVisibleLayout::Color color) {
for (int i = 0; i < m_numberOfRows; i++) {
addChildAtIndex(new EmptyVisibleLayout(color), i*m_numberOfColumns + m_numberOfColumns-1);
}
invalidAllSizesPositionsAndBaselines();
}
void GridLayout::deleteRowAtIndex(int index) {
@@ -243,6 +245,7 @@ void GridLayout::deleteRowAtIndex(int index) {
DynamicLayoutHierarchy::removeChildAtIndex(index * m_numberOfColumns, true);
}
m_numberOfRows--;
invalidAllSizesPositionsAndBaselines();
}
void GridLayout::deleteColumnAtIndex(int index) {
@@ -251,6 +254,7 @@ void GridLayout::deleteColumnAtIndex(int index) {
DynamicLayoutHierarchy::removeChildAtIndex(i, true);
}
m_numberOfColumns--;
invalidAllSizesPositionsAndBaselines();
}
bool GridLayout::childIsLeftOfGrid(int index) const {

View File

@@ -38,6 +38,8 @@ protected:
void deleteRowAtIndex(int index);
void deleteColumnAtIndex(int index);
bool childIsRightOfGrid(int index) const;
bool childIsLeftOfGrid(int index) const;
bool childIsTopOfGrid(int index) const;
bool childIsBottomOfGrid(int index) const;
int rowAtChildIndex(int index) const;
int columnAtChildIndex(int index) const;
@@ -51,8 +53,6 @@ private:
KDCoordinate height();
KDCoordinate columnWidth(int j);
KDCoordinate width();
bool childIsLeftOfGrid(int index) const;
bool childIsTopOfGrid(int index) const;
};
}

View File

@@ -63,13 +63,27 @@ void HorizontalLayout::privateReplaceChild(const ExpressionLayout * oldChild, Ex
// replace the horizontal layout with this empty layout (only if this is not
// the main layout, so only if the layout has a parent).
if (m_parent) {
if (!deleteOldChild) {
removeChildAtIndex(indexOfChild(oldChild), false);
}
if (cursor) {
replaceWithAndMoveCursor(newChild, deleteOldChild, cursor);
replaceWithAndMoveCursor(newChild, true, cursor);
return;
}
replaceWith(newChild, deleteOldChild);
return;
}
// If this is the main horizontal layout, the old child its only child and
// the new child is Empty, remove the old child and delete the new child.
assert(m_parent == nullptr);
removeChildAtIndex(0, deleteOldChild);
delete newChild;
if (cursor == nullptr) {
return;
}
cursor->setPointedExpressionLayout(this);
cursor->setPosition(ExpressionLayoutCursor::Position::Left);
return;
}
// If the new child is also an horizontal layout, steal the children of the
// new layout then destroy it.

View File

@@ -17,6 +17,85 @@ ExpressionLayout * MatrixLayout::clone() const {
return layout;
}
bool MatrixLayout::moveLeft(ExpressionLayoutCursor * cursor) {
int childIndex = indexOfChild(cursor->pointedExpressionLayout());
if (childIndex >- 1
&& cursor->position() == ExpressionLayoutCursor::Position::Left
&& childIsLeftOfGrid(childIndex))
{
// Case: Left of a child on the left of the grid.
// Remove the grey squares of the grid, then go left of the grid.
assert(hasGreySquares());
removeGreySquares();
cursor->setPointedExpressionLayout(this);
cursor->setPosition(ExpressionLayoutCursor::Position::Left);
return true;
}
// Case: Right.
// Add the grey squares to the matrix, then move to the bottom right non empty
// nor grey child.
if (cursor->pointedExpressionLayout() == this
&& cursor->position() == ExpressionLayoutCursor::Position::Right)
{
assert(!hasGreySquares());
addGreySquares();
ExpressionLayout * lastChild = editableChild((m_numberOfColumns-1)*(m_numberOfRows-1));
assert(lastChild != nullptr);
cursor->setPointedExpressionLayout(lastChild);
return true;
}
return GridLayout::moveLeft(cursor);
}
bool MatrixLayout::moveRight(ExpressionLayoutCursor * cursor) {
// Case: Left.
// Add the grey squares to the matrix,, then go to the first entry.
if (cursor->pointedExpressionLayout() == this
&& cursor->position() == ExpressionLayoutCursor::Position::Left)
{
assert(!hasGreySquares());
addGreySquares();
assert(m_numberOfColumns*m_numberOfRows >= 1);
ExpressionLayout * firstChild = editableChild(0);
assert(firstChild != nullptr);
cursor->setPointedExpressionLayout(firstChild);
return true;
}
// Case: The cursor points to a grid's child.
int childIndex = indexOfChild(cursor->pointedExpressionLayout());
if (childIndex >- 1
&& cursor->position() == ExpressionLayoutCursor::Position::Right
&& childIsRightOfGrid(childIndex))
{
// Case: Right of a child on the right of the grid.
// Remove the grey squares of the grid, then go left of the grid.
cursor->setPointedExpressionLayout(this);
cursor->setPosition(ExpressionLayoutCursor::Position::Right);
assert(hasGreySquares());
removeGreySquares();
return true;
}
return GridLayout::moveRight(cursor);
}
bool MatrixLayout::moveUpInside(ExpressionLayoutCursor * cursor) {
bool result = GridLayout::moveUpInside(cursor);
if (result) {
assert(!hasGreySquares());
addGreySquares();
}
return result;
}
bool MatrixLayout::moveDownInside(ExpressionLayoutCursor * cursor) {
bool result = GridLayout::moveDownInside(cursor);
if (result) {
assert(!hasGreySquares());
addGreySquares();
}
return result;
}
void MatrixLayout::replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild) {
int oldChildIndex = indexOfChild(oldChild);
GridLayout::replaceChild(oldChild, newChild, deleteOldChild);
@@ -50,11 +129,13 @@ int MatrixLayout::writeTextInBuffer(char * buffer, int bufferSize) const {
buffer[numberOfChar++] = '[';
if (numberOfChar >= bufferSize-1) { return bufferSize-1;}
for (int i = 0; i < m_numberOfRows - 1; i++) {
int maxRowIndex = hasGreySquares() ? m_numberOfRows - 1 : m_numberOfRows;
int maxColumnIndex = hasGreySquares() ? m_numberOfColumns - 2 : m_numberOfColumns - 1;
for (int i = 0; i < maxRowIndex; i++) {
buffer[numberOfChar++] = '[';
if (numberOfChar >= bufferSize-1) { return bufferSize-1;}
numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, i* m_numberOfColumns + m_numberOfColumns - 2);
numberOfChar += LayoutEngine::writeInfixExpressionLayoutTextInBuffer(this, buffer+numberOfChar, bufferSize-numberOfChar, ",", i*m_numberOfColumns, i* m_numberOfColumns + maxColumnIndex);
buffer[numberOfChar++] = ']';
if (numberOfChar >= bufferSize-1) { return bufferSize-1; }
@@ -166,4 +247,32 @@ bool MatrixLayout::isColumnEmpty(int index) const {
return true;
}
void MatrixLayout::addGreySquares() {
if (!hasGreySquares()) {
addEmptyRow(EmptyVisibleLayout::Color::Grey);
addEmptyColumn(EmptyVisibleLayout::Color::Grey);
}
}
void MatrixLayout::removeGreySquares() {
if (hasGreySquares()) {
deleteRowAtIndex(m_numberOfRows - 1);
deleteColumnAtIndex(m_numberOfColumns - 1);
}
}
bool MatrixLayout::hasGreySquares() const {
assert(m_numberOfRows*m_numberOfColumns - 1 >= 0);
const ExpressionLayout * lastChild = child(m_numberOfRows * m_numberOfColumns - 1);
if (lastChild->isEmpty()
&& !lastChild->isHorizontal()
&& (static_cast<const EmptyVisibleLayout *>(lastChild))->color() == EmptyVisibleLayout::Color::Grey)
{
assert(isRowEmpty(m_numberOfColumns - 1));
assert(isColumnEmpty(m_numberOfRows - 1));
return true;
}
return false;
}
}

View File

@@ -9,19 +9,36 @@ class MatrixLayout : public GridLayout {
public:
using GridLayout::GridLayout;
ExpressionLayout * clone() const override;
/* Navigation */
bool moveLeft(ExpressionLayoutCursor * cursor) override;
bool moveRight(ExpressionLayoutCursor * cursor) override;
bool moveUpInside(ExpressionLayoutCursor * cursor) override;
bool moveDownInside(ExpressionLayoutCursor * cursor) override;
/* Dynamic layout */
void replaceChild(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild = true) override;
void replaceChildAndMoveCursor(const ExpressionLayout * oldChild, ExpressionLayout * newChild, bool deleteOldChild, ExpressionLayoutCursor * cursor) override;
/* Expression engine */
int writeTextInBuffer(char * buffer, int bufferSize) const override;
/* Other */
bool isMatrix() const override { return true; }
/* Special matrix method */
void newRowOrColumnAtIndex(int index);
void childWasReplacedAtIndex(int index);
protected:
void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override;
KDSize computeSize() override;
KDPoint positionOfChild(ExpressionLayout * child) override;
private:
void childWasReplacedAtIndex(int index);
bool isRowEmpty(int index) const;
bool isColumnEmpty(int index) const;
void addGreySquares();
void removeGreySquares();
bool hasGreySquares() const;
};
}