mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 16:57:31 +01:00
[poincare] Make GridLayout rendering faster
This commit is contained in:
@@ -124,6 +124,7 @@ protected:
|
||||
|
||||
// Tree
|
||||
Direct<LayoutNode> children() { return Direct<LayoutNode>(this); }
|
||||
Direct<LayoutNode> childrenFromIndex(int i) { return Direct<LayoutNode>(this, i); }
|
||||
|
||||
// Sizing and positioning
|
||||
virtual KDSize computeSize() = 0;
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
template <typename T>
|
||||
class Direct final {
|
||||
public:
|
||||
Direct(const T * node) : m_node(const_cast<T *>(node)) {}
|
||||
Direct(const T * node, int firstIndex = 0) : m_node(const_cast<T *>(node)), m_firstIndex(firstIndex) {}
|
||||
class Iterator : public TreeNode::Iterator<T> {
|
||||
public:
|
||||
using TreeNode::Iterator<T>::Iterator;
|
||||
@@ -107,10 +107,17 @@ public:
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
Iterator begin() const { return Iterator(static_cast<T *>(m_node->next())); }
|
||||
Iterator begin() const {
|
||||
TreeNode * n = m_node->next();
|
||||
for (int i = 0; i < m_firstIndex; i++) {
|
||||
n = n->nextSibling();
|
||||
}
|
||||
return Iterator(static_cast<T *>(n));
|
||||
}
|
||||
Iterator end() const { return Iterator(static_cast<T *>(m_node->nextSibling())); }
|
||||
private:
|
||||
T * m_node;
|
||||
int m_firstIndex;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -155,6 +162,7 @@ protected:
|
||||
m_parentIdentifier(NoNodeIdentifier),
|
||||
m_referenceCounter(0)
|
||||
{}
|
||||
|
||||
private:
|
||||
void updateParentIdentifierInChildren() const {
|
||||
changeParentIdentifierInChildren(m_identifier);
|
||||
|
||||
@@ -43,7 +43,8 @@ void GridLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecompu
|
||||
cursor->setLayoutNode(childAtIndex(0));
|
||||
return;
|
||||
}
|
||||
int childIndex = indexOfChild(cursor->layoutNode());
|
||||
LayoutNode * cursorNode = cursor->layoutNode();
|
||||
int childIndex = indexOfChild(cursorNode);
|
||||
if (childIndex >= 0 && cursor->position() == LayoutCursor::Position::Right) {
|
||||
// Case: The cursor points to a grid's child.
|
||||
if (childIsRightOfGrid(childIndex)) {
|
||||
@@ -52,7 +53,7 @@ void GridLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecompu
|
||||
return;
|
||||
}
|
||||
// Case: Right of another child. Go Left of its sibling on the right.
|
||||
cursor->setLayoutNode(childAtIndex(childIndex + 1));
|
||||
cursor->setLayoutNode(static_cast<LayoutNode *>(cursorNode->nextSibling()));
|
||||
cursor->setPosition(LayoutCursor::Position::Left);
|
||||
return;
|
||||
}
|
||||
@@ -66,10 +67,10 @@ void GridLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecompu
|
||||
|
||||
void GridLayoutNode::moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) {
|
||||
/* If the cursor is child that is not on the top row, move it inside its upper
|
||||
* neighbour.*/
|
||||
* neighbour. */
|
||||
int childIndex = m_numberOfColumns;
|
||||
while (childIndex < numberOfChildren()) {
|
||||
if (cursor->layoutNode()->hasAncestor(childAtIndex(childIndex), true)) {
|
||||
for (LayoutNode * l : childrenFromIndex(childIndex)) {
|
||||
if (cursor->layoutNode()->hasAncestor(l, true)) {
|
||||
childAtIndex(childIndex - m_numberOfColumns)->moveCursorUpInDescendants(cursor, shouldRecomputeLayout);
|
||||
return;
|
||||
}
|
||||
@@ -80,12 +81,16 @@ void GridLayoutNode::moveCursorUp(LayoutCursor * cursor, bool * shouldRecomputeL
|
||||
|
||||
void GridLayoutNode::moveCursorDown(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) {
|
||||
int childIndex = 0;
|
||||
while (childIndex < numberOfChildren() - m_numberOfColumns) {
|
||||
if (cursor->layoutNode()->hasAncestor(childAtIndex(childIndex), true)) {
|
||||
int maxIndex = numberOfChildren() - m_numberOfColumns;
|
||||
for (LayoutNode * l : children()) {
|
||||
if (cursor->layoutNode()->hasAncestor(l, true)) {
|
||||
childAtIndex(childIndex + m_numberOfColumns)->moveCursorDownInDescendants(cursor, shouldRecomputeLayout);
|
||||
return;
|
||||
}
|
||||
childIndex++;
|
||||
if (childIndex >= maxIndex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
LayoutNode::moveCursorDown(cursor, shouldRecomputeLayout, equivalentPositionVisited);
|
||||
}
|
||||
@@ -191,17 +196,9 @@ KDCoordinate GridLayoutNode::computeBaseline() {
|
||||
}
|
||||
|
||||
KDPoint GridLayoutNode::positionOfChild(LayoutNode * l) {
|
||||
int rowIndex = 0;
|
||||
int columnIndex = 0;
|
||||
for (int i = 0; i < m_numberOfRows; i++) {
|
||||
for (int j = 0; j < m_numberOfColumns; j++) {
|
||||
if (l == childAtIndex(i*m_numberOfColumns+j)) {
|
||||
rowIndex = i;
|
||||
columnIndex = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int childIndex = indexOfChild(l);
|
||||
int rowIndex = rowAtChildIndex(childIndex);
|
||||
int columnIndex = columnAtChildIndex(childIndex);
|
||||
KDCoordinate x = 0;
|
||||
for (int j = 0; j < columnIndex; j++) {
|
||||
x += columnWidth(j);
|
||||
@@ -218,21 +215,33 @@ KDPoint GridLayoutNode::positionOfChild(LayoutNode * l) {
|
||||
// Private
|
||||
|
||||
KDCoordinate GridLayoutNode::rowBaseline(int i) {
|
||||
assert(m_numberOfColumns > 0);
|
||||
KDCoordinate rowBaseline = 0;
|
||||
for (int j = 0; j < m_numberOfColumns; j++) {
|
||||
rowBaseline = maxCoordinate(rowBaseline, childAtIndex(i*m_numberOfColumns+j)->baseline());
|
||||
int j = 0;
|
||||
for (LayoutNode * l : childrenFromIndex(i*m_numberOfColumns)) {
|
||||
rowBaseline = maxCoordinate(rowBaseline, l->baseline());
|
||||
j++;
|
||||
if (j >= m_numberOfColumns) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rowBaseline;
|
||||
}
|
||||
|
||||
KDCoordinate GridLayoutNode::rowHeight(int i) const {
|
||||
KDCoordinate rowHeight = 0;
|
||||
KDCoordinate baseline = const_cast<GridLayoutNode *>(this)->rowBaseline(i);
|
||||
for (int j = 0; j < m_numberOfColumns; j++) {
|
||||
LayoutNode * currentChild = const_cast<GridLayoutNode *>(this)->childAtIndex(i*m_numberOfColumns+j);
|
||||
rowHeight = maxCoordinate(rowHeight, currentChild->layoutSize().height() - currentChild->baseline());
|
||||
KDCoordinate underBaseline = 0;
|
||||
KDCoordinate aboveBaseline = 0;
|
||||
int j = 0;
|
||||
for (LayoutNode * l : const_cast<GridLayoutNode *>(this)->childrenFromIndex(i*m_numberOfColumns)) {
|
||||
KDCoordinate b = l->baseline();
|
||||
underBaseline = maxCoordinate(underBaseline, l->layoutSize().height() - b);
|
||||
aboveBaseline = maxCoordinate(aboveBaseline, b);
|
||||
j++;
|
||||
if (j >= m_numberOfColumns) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return baseline+rowHeight;
|
||||
return aboveBaseline+underBaseline;
|
||||
}
|
||||
|
||||
KDCoordinate GridLayoutNode::height() const {
|
||||
@@ -240,14 +249,22 @@ KDCoordinate GridLayoutNode::height() const {
|
||||
for (int i = 0; i < m_numberOfRows; i++) {
|
||||
totalHeight += rowHeight(i);
|
||||
}
|
||||
totalHeight += maxCoordinate((m_numberOfRows-1)*k_gridEntryMargin, 0);
|
||||
totalHeight += m_numberOfRows > 0 ? (m_numberOfRows-1)*k_gridEntryMargin : 0;
|
||||
return totalHeight;
|
||||
}
|
||||
|
||||
KDCoordinate GridLayoutNode::columnWidth(int j) const {
|
||||
KDCoordinate columnWidth = 0;
|
||||
for (int i = 0; i < m_numberOfRows; i++) {
|
||||
columnWidth = maxCoordinate(columnWidth, const_cast<GridLayoutNode *>(this)->childAtIndex(i*m_numberOfColumns+j)->layoutSize().width());
|
||||
int childIndex = j;
|
||||
int lastIndex = (m_numberOfRows-1)*m_numberOfColumns + j;
|
||||
for (LayoutNode * l : const_cast<GridLayoutNode *>(this)->childrenFromIndex(j)) {
|
||||
if (childIndex%m_numberOfColumns == j) {
|
||||
columnWidth = maxCoordinate(columnWidth, l->layoutSize().width());
|
||||
if (childIndex >= lastIndex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
childIndex++;
|
||||
}
|
||||
return columnWidth;
|
||||
}
|
||||
@@ -257,7 +274,7 @@ KDCoordinate GridLayoutNode::width() const {
|
||||
for (int j = 0; j < m_numberOfColumns; j++) {
|
||||
totalWidth += columnWidth(j);
|
||||
}
|
||||
totalWidth += maxCoordinate(0, (m_numberOfColumns-1)*k_gridEntryMargin);
|
||||
totalWidth += m_numberOfColumns > 0 ? (m_numberOfColumns-1)*k_gridEntryMargin : 0;
|
||||
return totalWidth;
|
||||
}
|
||||
|
||||
@@ -268,4 +285,4 @@ void GridLayout::setDimensions(int rows, int columns) {
|
||||
setNumberOfColumns(columns);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,12 +142,17 @@ void MatrixLayoutNode::moveCursorVertically(VerticalDirection direction, LayoutC
|
||||
bool shouldRemoveGreySquares = false;
|
||||
int firstIndex = direction == VerticalDirection::Up ? 0 : numberOfChildren() - m_numberOfColumns;
|
||||
int lastIndex = direction == VerticalDirection::Up ? m_numberOfColumns : numberOfChildren();
|
||||
for (int childIndex = firstIndex; childIndex < lastIndex; childIndex++) {
|
||||
if (cursor->layoutReference().hasAncestor(thisRef.childAtIndex(childIndex), true)) {
|
||||
int i = firstIndex;
|
||||
for (LayoutNode * l : childrenFromIndex(firstIndex)) {
|
||||
if (i >= lastIndex) {
|
||||
break;
|
||||
}
|
||||
if (cursor->layoutReference().node()->hasAncestor(l, true)) {
|
||||
// The cursor is leaving the matrix, so remove the grey squares.
|
||||
shouldRemoveGreySquares = true;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
GridLayoutNode::moveCursorVertically(direction, cursor, shouldRecomputeLayout, equivalentPositionVisited);
|
||||
if (cursor->isDefined() && shouldRemoveGreySquares) {
|
||||
@@ -160,30 +165,43 @@ void MatrixLayoutNode::moveCursorVertically(VerticalDirection direction, LayoutC
|
||||
// Private
|
||||
|
||||
void MatrixLayoutNode::newRowOrColumnAtIndex(int index) {
|
||||
assert(index >= 0 && index < m_numberOfColumns*m_numberOfRows);
|
||||
assert(index >= 0 && index < m_numberOfColumns * m_numberOfRows);
|
||||
bool shouldAddNewRow = childIsBottomOfGrid(index); // We need to compute this boolean before modifying the layout
|
||||
int correspondingRow = rowAtChildIndex(index);
|
||||
if (childIsRightOfGrid(index)) {
|
||||
assert(m_numberOfRows >= 2);
|
||||
// Color the grey EmptyLayouts of the column in yellow.
|
||||
int correspondingColumn = m_numberOfColumns - 1;
|
||||
for (int i = 0; i < m_numberOfRows - 1; i++) {
|
||||
LayoutNode * lastLayoutOfRow = childAtIndex(i*m_numberOfColumns+correspondingColumn);
|
||||
if (lastLayoutOfRow->isEmpty()) {
|
||||
if (!lastLayoutOfRow->isHorizontal()) {
|
||||
static_cast<EmptyLayoutNode *>(lastLayoutOfRow)->setColor(EmptyLayoutNode::Color::Yellow);
|
||||
} else {
|
||||
assert(lastLayoutOfRow->numberOfChildren() == 1);
|
||||
static_cast<EmptyLayoutNode *>(lastLayoutOfRow->childAtIndex(0))->setColor(EmptyLayoutNode::Color::Yellow);
|
||||
int childIndex = correspondingColumn;
|
||||
int maxIndex = (m_numberOfRows - 2)*m_numberOfColumns+correspondingColumn;
|
||||
for (LayoutNode * lastLayoutOfRow : childrenFromIndex(correspondingColumn)) {
|
||||
if (childIndex > maxIndex) {
|
||||
break;
|
||||
}
|
||||
if (childIndex % m_numberOfColumns == correspondingColumn) {
|
||||
if (lastLayoutOfRow->isEmpty()) {
|
||||
if (!lastLayoutOfRow->isHorizontal()) {
|
||||
static_cast<EmptyLayoutNode *>(lastLayoutOfRow)->setColor(EmptyLayoutNode::Color::Yellow);
|
||||
} else {
|
||||
assert(lastLayoutOfRow->numberOfChildren() == 1);
|
||||
static_cast<EmptyLayoutNode *>(lastLayoutOfRow->childAtIndex(0))->setColor(EmptyLayoutNode::Color::Yellow);
|
||||
}
|
||||
}
|
||||
}
|
||||
childIndex++;
|
||||
}
|
||||
// Add a column of grey EmptyLayouts on the right.
|
||||
addEmptyColumn(EmptyLayoutNode::Color::Grey);
|
||||
}
|
||||
if (shouldAddNewRow) {
|
||||
assert(m_numberOfColumns >= 2);
|
||||
// Color the grey EmptyLayouts of the row in yellow.
|
||||
for (int i = 0; i < m_numberOfColumns - 1; i++) {
|
||||
LayoutNode * lastLayoutOfColumn = childAtIndex(correspondingRow*m_numberOfColumns+i);
|
||||
int childIndex = correspondingRow * m_numberOfColumns;
|
||||
int maxIndex = correspondingRow * m_numberOfColumns + m_numberOfColumns - 2;
|
||||
for (LayoutNode * lastLayoutOfColumn : childrenFromIndex(correspondingRow*m_numberOfColumns)) {
|
||||
if (childIndex > maxIndex) {
|
||||
break;
|
||||
}
|
||||
if (lastLayoutOfColumn->isEmpty()) {
|
||||
if (!lastLayoutOfColumn->isHorizontal()) {
|
||||
static_cast<EmptyLayoutNode *>(lastLayoutOfColumn)->setColor(EmptyLayoutNode::Color::Yellow);
|
||||
@@ -192,6 +210,7 @@ void MatrixLayoutNode::newRowOrColumnAtIndex(int index) {
|
||||
static_cast<EmptyLayoutNode *>(lastLayoutOfColumn->childAtIndex(0))->setColor(EmptyLayoutNode::Color::Yellow);
|
||||
}
|
||||
}
|
||||
childIndex++;
|
||||
}
|
||||
// Add a row of grey EmptyLayouts at the bottom.
|
||||
addEmptyRow(EmptyLayoutNode::Color::Grey);
|
||||
@@ -200,20 +219,30 @@ void MatrixLayoutNode::newRowOrColumnAtIndex(int index) {
|
||||
|
||||
bool MatrixLayoutNode::isRowEmpty(int index) const {
|
||||
assert(index >= 0 && index < m_numberOfRows);
|
||||
for (int i = index * m_numberOfColumns; i < (index+1) * m_numberOfColumns; i++) {
|
||||
if (!const_cast<MatrixLayoutNode *>(this)->childAtIndex(i)->isEmpty()) {
|
||||
int i = index * m_numberOfColumns;
|
||||
for (LayoutNode * l : const_cast<MatrixLayoutNode *>(this)->childrenFromIndex(index * m_numberOfColumns)) {
|
||||
if (i >= (index + 1) * m_numberOfColumns) {
|
||||
break;
|
||||
}
|
||||
if (!l->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MatrixLayoutNode::isColumnEmpty(int index) const {
|
||||
assert(index >= 0 && index < m_numberOfColumns);
|
||||
for (int i = index; i < m_numberOfRows * m_numberOfColumns; i+= m_numberOfColumns) {
|
||||
if (!const_cast<MatrixLayoutNode *>(this)->childAtIndex(i)->isEmpty()) {
|
||||
int i = index;
|
||||
for (LayoutNode * l : const_cast<MatrixLayoutNode *>(this)->childrenFromIndex(index)) {
|
||||
if (i > index + (m_numberOfRows - 1) * m_numberOfColumns) {
|
||||
break;
|
||||
}
|
||||
if (i % m_numberOfColumns == index && !l->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user