[apps] Cell heights memoized in ExprModelListCtrler, not FunctionLC

This commit is contained in:
Léa Saviot
2018-10-26 10:09:22 +02:00
committed by Émilie Feral
parent f259b84874
commit c428a4e94b
4 changed files with 126 additions and 101 deletions

View File

@@ -6,11 +6,104 @@ namespace Shared {
StorageExpressionModelListController::StorageExpressionModelListController(Responder * parentResponder, I18n::Message text) :
ViewController(parentResponder),
m_addNewModel()
m_addNewModel(),
m_memoizedCellHeight {-1, -1, -1, -1, -1},
m_cumulatedHeightForSelectedIndex(-1)
{
m_addNewModel.setMessage(text);
}
void StorageExpressionModelListController::tableSelectionDidChange(int previousSelectedRow) {
constexpr int currentSelectedMemoizedIndex = k_memoizedCellHeightsCount/2 + 1; // Needs k_memoizedCellHeightsCount to be odd, which is static asserted in the header file
int currentSelectedRow = selectedRow();
// The previously selected cell's height might have changed.
m_memoizedCellHeight[currentSelectedMemoizedIndex] = -1;
// Update m_cumulatedHeightForSelectedIndex if we scrolled one cell up/down
if (currentSelectedRow == previousSelectedRow + 1) {
/* We selected the cell under the previous cell. Shift the memoized cell
* heights. */
for (int i = 0; i < k_memoizedCellHeightsCount - 1; i++) {
m_memoizedCellHeight[i] = m_memoizedCellHeight[i+1];
}
m_memoizedCellHeight[k_memoizedCellHeightsCount-1] = -1;
// Update m_cumulatedHeightForSelectedIndex
if (previousSelectedRow >= 0) {
m_cumulatedHeightForSelectedIndex+= memoizedRowHeight(previousSelectedRow);
} else {
assert(currentSelectedRow == 0);
m_cumulatedHeightForSelectedIndex = 0;
}
} else if (currentSelectedRow == previousSelectedRow - 1) {
/* We selected the cell above the previous cell. Shift the memoized cell
* heights. */
for (int i = k_memoizedCellHeightsCount - 1; i > 0; i--) {
m_memoizedCellHeight[i] = m_memoizedCellHeight[i-1];
}
m_memoizedCellHeight[0] = -1;
// Update m_cumulatedHeightForSelectedIndex
if (currentSelectedRow >= 0) {
m_cumulatedHeightForSelectedIndex-= memoizedRowHeight(currentSelectedRow);
} else {
m_cumulatedHeightForSelectedIndex = 0;
}
} else if (previousSelectedRow != currentSelectedRow) {
resetMemoization();
}
}
KDCoordinate StorageExpressionModelListController::memoizedRowHeight(int j) {
if (j < 0) {
return 0;
}
int currentSelectedRow = selectedRow();
constexpr int halfMemoizationCount = k_memoizedCellHeightsCount/2;
if (j >= currentSelectedRow - halfMemoizationCount && j <= currentSelectedRow + halfMemoizationCount) {
int memoizedIndex = j - (currentSelectedRow - halfMemoizationCount);
if (m_memoizedCellHeight[memoizedIndex] < 0) {
m_memoizedCellHeight[memoizedIndex] = expressionRowHeight(j);
}
return m_memoizedCellHeight[memoizedIndex];
}
return expressionRowHeight(j);
}
KDCoordinate StorageExpressionModelListController::memoizedCumulatedHeightFromIndex(int j) {
if (j <= 0) {
return 0;
}
int currentSelectedRow = selectedRow();
constexpr int halfMemoizationCount = k_memoizedCellHeightsCount/2;
/* If j is not easily computable from the memoized values, compute it the hard
* way. */
if (j < currentSelectedRow - halfMemoizationCount || j > currentSelectedRow + halfMemoizationCount) {
return notMemoizedCumulatedHeightFromIndex(j);
}
// Recompute the memoized cumulatedHeight if needed
if (m_cumulatedHeightForSelectedIndex < 0) {
m_cumulatedHeightForSelectedIndex = notMemoizedCumulatedHeightFromIndex(currentSelectedRow);
}
/* Compute the wanted cumulated height by adding/removing memoized cell
* heights */
KDCoordinate result = m_cumulatedHeightForSelectedIndex;
if (j <= currentSelectedRow) {
/* If j is smaller than the selected row, remove cell heights from the
* memoized value */
for (int i = j; i < currentSelectedRow; i++) {
result -= memoizedRowHeight(i);
}
} else {
/* If j is bigger than the selected row, add cell heights to the memoized
* value */
assert(j > currentSelectedRow && j <= currentSelectedRow + halfMemoizationCount);
for (int i = currentSelectedRow; i < j; i++) {
result += memoizedRowHeight(i);
}
}
return result;
}
int StorageExpressionModelListController::numberOfExpressionRows() {
return 1 + modelStore()->numberOfModels();
}
@@ -122,4 +215,11 @@ bool StorageExpressionModelListController::isAddEmptyRow(int j) {
return j == modelStore()->numberOfModels();
}
void StorageExpressionModelListController::resetMemoization() {
m_cumulatedHeightForSelectedIndex = -1;
for (int i = 0; i < k_memoizedCellHeightsCount; i++) {
m_memoizedCellHeight[i] = -1;
}
}
}

View File

@@ -12,11 +12,15 @@ public:
StorageExpressionModelListController(Responder * parentResponder, I18n::Message text);
protected:
static constexpr KDCoordinate k_expressionMargin = 5;
/* Table Data Source */
// Memoization of cell heights
void tableSelectionDidChange(int previousSelectedRow);
KDCoordinate memoizedRowHeight(int j);
KDCoordinate memoizedCumulatedHeightFromIndex(int j);
// TableViewDataSource
virtual int numberOfExpressionRows();
virtual KDCoordinate expressionRowHeight(int j);
virtual void willDisplayExpressionCellAtIndex(HighlightCell * cell, int j);
/* Responder */
// Responder
bool handleEventOnExpression(Ion::Events::Event event);
virtual void addEmptyModel();
virtual void didChangeModelsList() {}
@@ -26,11 +30,20 @@ protected:
virtual bool removeModelRow(Ion::Storage::Record record);
virtual int modelIndexForRow(int j) { return j; }
virtual bool isAddEmptyRow(int j);
/* View Controller */
// ViewController
virtual SelectableTableView * selectableTableView() = 0;
virtual StorageExpressionModelStore * modelStore() = 0;
virtual InputViewController * inputController() = 0;
EvenOddMessageTextCell m_addNewModel;
private:
// Memoization
static constexpr int k_memoizedCellHeightsCount = 5;
static_assert(StorageExpressionModelListController::k_memoizedCellHeightsCount == 5, "Wrong array size in initialization of StorageExpressionModelListController::m_memoizedCellHeight.");
static_assert(StorageExpressionModelListController::k_memoizedCellHeightsCount % 2 == 1, "StorageExpressionModelListController::k_memoizedCellHeightsCount should be odd to be able to compute the middle element.");
void resetMemoization();
virtual KDCoordinate notMemoizedCumulatedHeightFromIndex(int j) = 0;
KDCoordinate m_memoizedCellHeight[k_memoizedCellHeightsCount];
KDCoordinate m_cumulatedHeightForSelectedIndex;
};
}

View File

@@ -20,9 +20,7 @@ StorageFunctionListController::StorageFunctionListController(Responder * parentR
TabViewController * tabController = list->tabController();
tabController->setActiveTab(2);
}, this), KDFont::SmallFont, Palette::PurpleBright),
m_titlesColumnWidth(k_minTitleColumnWidth),
m_memoizedCellHeight {-1, -1, -1, -1, -1},
m_cumulatedHeightForSelectedIndex(-1)
m_titlesColumnWidth(k_minTitleColumnWidth)
{
m_selectableTableView.setMargins(0);
m_selectableTableView.setVerticalCellOverlap(0);
@@ -36,54 +34,11 @@ void StorageFunctionListController::viewWillAppear() {
}
KDCoordinate StorageFunctionListController::rowHeight(int j) {
if (j < 0) {
return 0;
}
int currentSelectedRow = selectedRow();
constexpr int halfMemoizationCount = k_memoizedCellHeightsCount/2;
if (j >= currentSelectedRow - halfMemoizationCount && j <= currentSelectedRow + halfMemoizationCount) {
int memoizedIndex = j - (currentSelectedRow - halfMemoizationCount);
if (m_memoizedCellHeight[memoizedIndex] < 0) {
m_memoizedCellHeight[memoizedIndex] = expressionRowHeight(j);
}
return m_memoizedCellHeight[memoizedIndex];
}
return expressionRowHeight(j);
return StorageExpressionModelListController::memoizedRowHeight(j);
}
KDCoordinate StorageFunctionListController::cumulatedHeightFromIndex(int j) {
if (j <= 0) {
return 0;
}
int currentSelectedRow = selectedRow();
constexpr int halfMemoizationCount = k_memoizedCellHeightsCount/2;
/* If j is not easily computable from the memoized values, compute it the hard
* way. */
if (j < currentSelectedRow - halfMemoizationCount || j > currentSelectedRow + halfMemoizationCount) {
return TableViewDataSource::cumulatedHeightFromIndex(j);
}
// Recompute the memoized cumulatedHeight if needed
if (m_cumulatedHeightForSelectedIndex < 0) {
m_cumulatedHeightForSelectedIndex = TableViewDataSource::cumulatedHeightFromIndex(currentSelectedRow);
}
/* Compute the wanted cumulated height by adding/removing memoized cell
* heights */
KDCoordinate result = m_cumulatedHeightForSelectedIndex;
if (j <= currentSelectedRow) {
/* If j is smaller than the selected row, remove cell heights from the
* memoized value */
for (int i = j; i < currentSelectedRow; i++) {
result -= rowHeight(i);
}
} else {
/* If j is bigger than the selected row, add cell heights to the memoized
* value */
assert(j > currentSelectedRow && j <= currentSelectedRow + halfMemoizationCount);
for (int i = currentSelectedRow; i < j; i++) {
result += rowHeight(i);
}
}
return result;
return StorageExpressionModelListController::memoizedCumulatedHeightFromIndex(j);
}
KDCoordinate StorageFunctionListController::columnWidth(int i) {
@@ -260,44 +215,9 @@ void StorageFunctionListController::willExitResponderChain(Responder * nextFirst
/* SelectableTableViewDelegate */
void StorageFunctionListController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) {
constexpr int currentSelectedMemoizedIndex = k_memoizedCellHeightsCount/2 + 1; // Needs k_memoizedCellHeightsCount to be odd, which is static asserted in storage_function_list_controller.h
int currentSelectedY = selectedRow();
// The previously selected cell's height might have changed.
m_memoizedCellHeight[currentSelectedMemoizedIndex] = -1;
// Update m_cumulatedHeightForSelectedIndex if we scrolled one cell up/down
if (currentSelectedY == previousSelectedCellY + 1) {
/* We selected the cell under the previous cell. Shift the memoized cell
* heights. */
for (int i = 0; i < k_memoizedCellHeightsCount - 1; i++) {
m_memoizedCellHeight[i] = m_memoizedCellHeight[i+1];
}
m_memoizedCellHeight[k_memoizedCellHeightsCount-1] = -1;
// Update m_cumulatedHeightForSelectedIndex
if (previousSelectedCellY >= 0) {
m_cumulatedHeightForSelectedIndex+= rowHeight(previousSelectedCellY);
} else {
assert(currentSelectedY == 0);
m_cumulatedHeightForSelectedIndex = 0;
}
} else if (currentSelectedY == previousSelectedCellY - 1) {
/* We selected the cell above the previous cell. Shift the memoized cell
* heights. */
for (int i = k_memoizedCellHeightsCount - 1; i > 0; i--) {
m_memoizedCellHeight[i] = m_memoizedCellHeight[i-1];
}
m_memoizedCellHeight[0] = -1;
// Update m_cumulatedHeightForSelectedIndex
if (currentSelectedY >= 0) {
m_cumulatedHeightForSelectedIndex-= rowHeight(currentSelectedY);
} else {
m_cumulatedHeightForSelectedIndex = 0;
}
} else if (previousSelectedCellY != currentSelectedY) {
resetMemoization();
}
// Update memoization of cell heights
StorageExpressionModelListController::tableSelectionDidChange(previousSelectedCellY);
// Do not select the cell left of the "addEmptyFunction" cell
if (isAddEmptyRow(selectedRow()) && selectedColumn() == 0) {
t->selectCellAtLocation(1, numberOfRows()-1);
}
@@ -351,11 +271,8 @@ void StorageFunctionListController::didChangeModelsList() {
computeTitlesColumnWidth();
}
void StorageFunctionListController::resetMemoization() {
m_cumulatedHeightForSelectedIndex = -1;
for (int i = 0; i < k_memoizedCellHeightsCount; i++) {
m_memoizedCellHeight[i] = -1;
}
KDCoordinate StorageFunctionListController::notMemoizedCumulatedHeightFromIndex(int j) {
return TableViewDataSource::cumulatedHeightFromIndex(j);
}
}

View File

@@ -58,25 +58,20 @@ protected:
private:
static constexpr KDCoordinate k_minTitleColumnWidth = 65;
static constexpr KDCoordinate k_functionTitleSumOfMargins = 2*Metric::HistoryHorizontalMargin;
static constexpr int k_memoizedCellHeightsCount = 5;
static_assert(StorageFunctionListController::k_memoizedCellHeightsCount == 5, "Wrong array size in initialization of StorageFunctionListController::m_memoizedCellHeight.");
static_assert(StorageFunctionListController::k_memoizedCellHeightsCount % 2 == 1, "StorageFunctionListController::k_memoizedCellHeightsCount should be odd to be able to compute the middle element.");
TabViewController * tabController() const;
InputViewController * inputController() override;
KDCoordinate maxFunctionNameWidth();
void didChangeModelsList() override;
KDCoordinate notMemoizedCumulatedHeightFromIndex(int j) override;
virtual StorageListParameterController * parameterController() = 0;
virtual int maxNumberOfDisplayableRows() = 0;
virtual FunctionTitleCell * titleCells(int index) = 0;
virtual HighlightCell * expressionCells(int index) = 0;
virtual void willDisplayTitleCellAtIndex(HighlightCell * cell, int j) = 0;
void resetMemoization();
EvenOddCell m_emptyCell;
Button m_plotButton;
Button m_valuesButton;
KDCoordinate m_titlesColumnWidth;
KDCoordinate m_memoizedCellHeight[k_memoizedCellHeightsCount];
KDCoordinate m_cumulatedHeightForSelectedIndex;
};
}