mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-28 18:20:14 +01:00
[apps] Cell heights memoized in ExprModelListCtrler, not FunctionLC
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user