[apps/calculation] Add a "ctrl-z" system

This commit is contained in:
Laury
2022-02-15 22:24:50 +01:00
parent 893a2a550d
commit f3d632c462
8 changed files with 55 additions and 13 deletions

View File

@@ -16,14 +16,24 @@ CalculationStore::CalculationStore(char * buffer, int size) :
m_buffer(buffer), m_buffer(buffer),
m_bufferSize(size), m_bufferSize(size),
m_calculationAreaEnd(m_buffer), m_calculationAreaEnd(m_buffer),
m_numberOfCalculations(0) m_numberOfCalculations(0),
m_trashIndex(-1)
{ {
assert(m_buffer != nullptr); assert(m_buffer != nullptr);
assert(m_bufferSize > 0); assert(m_bufferSize > 0);
} }
// Returns an expiring pointer to the calculation of index i // Returns an expiring pointer to the calculation of index i, and ignore the trash
ExpiringPointer<Calculation> CalculationStore::calculationAtIndex(int i) { ExpiringPointer<Calculation> CalculationStore::calculationAtIndex(int i) {
if (m_trashIndex == -1 || i < m_trashIndex) {
return realCalculationAtIndex(i);
} else {
return realCalculationAtIndex(i + 1);
}
}
// Returns an expiring pointer to the real calculation of index i
ExpiringPointer<Calculation> CalculationStore::realCalculationAtIndex(int i) {
assert(i >= 0 && i < m_numberOfCalculations); assert(i >= 0 && i < m_numberOfCalculations);
// m_buffer is the address of the oldest calculation in calculation store // m_buffer is the address of the oldest calculation in calculation store
Calculation * c = (Calculation *) m_buffer; Calculation * c = (Calculation *) m_buffer;
@@ -36,12 +46,13 @@ ExpiringPointer<Calculation> CalculationStore::calculationAtIndex(int i) {
// Pushes an expression in the store // Pushes an expression in the store
ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context * context, HeightComputer heightComputer) { ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context * context, HeightComputer heightComputer) {
emptyTrash();
/* Compute ans now, before the buffer is updated and before the calculation /* Compute ans now, before the buffer is updated and before the calculation
* might be deleted */ * might be deleted */
Expression ans = ansExpression(context); Expression ans = ansExpression(context);
/* Prepare the buffer for the new calculation /* Prepare the buffer for the new calculation
*The minimal size to store the new calculation is the minimal size of a calculation plus the pointer to its end */ * The minimal size to store the new calculation is the minimal size of a calculation plus the pointer to its end */
int minSize = Calculation::MinimalSize() + sizeof(Calculation *); int minSize = Calculation::MinimalSize() + sizeof(Calculation *);
assert(m_bufferSize > minSize); assert(m_bufferSize > minSize);
while (remainingBufferSize() < minSize) { while (remainingBufferSize() < minSize) {
@@ -132,15 +143,23 @@ ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context *
// Delete the calculation of index i // Delete the calculation of index i
void CalculationStore::deleteCalculationAtIndex(int i) { void CalculationStore::deleteCalculationAtIndex(int i) {
if (m_trashIndex != -1) {
emptyTrash();
}
m_trashIndex = i;
}
// Delete the calculation of index i, internal algorithm
void CalculationStore::realDeleteCalculationAtIndex(int i) {
assert(i >= 0 && i < m_numberOfCalculations); assert(i >= 0 && i < m_numberOfCalculations);
if (i == 0) { if (i == 0) {
ExpiringPointer<Calculation> lastCalculationPointer = calculationAtIndex(0); ExpiringPointer<Calculation> lastCalculationPointer = realCalculationAtIndex(0);
m_calculationAreaEnd = (char *)(lastCalculationPointer.pointer()); m_calculationAreaEnd = (char *)(lastCalculationPointer.pointer());
m_numberOfCalculations--; m_numberOfCalculations--;
return; return;
} }
char * calcI = (char *)calculationAtIndex(i).pointer(); char * calcI = (char *)realCalculationAtIndex(i).pointer();
char * nextCalc = (char *) calculationAtIndex(i-1).pointer(); char * nextCalc = (char *) realCalculationAtIndex(i-1).pointer();
assert(m_calculationAreaEnd >= nextCalc); assert(m_calculationAreaEnd >= nextCalc);
size_t slidingSize = m_calculationAreaEnd - nextCalc; size_t slidingSize = m_calculationAreaEnd - nextCalc;
// Slide the i-1 most recent calculations right after the i+1'th // Slide the i-1 most recent calculations right after the i+1'th
@@ -200,6 +219,12 @@ bool CalculationStore::pushSerializeExpression(Expression e, char * location, ch
return expressionIsPushed; return expressionIsPushed;
} }
void CalculationStore::emptyTrash() {
if (m_trashIndex != -1) {
realDeleteCalculationAtIndex(m_trashIndex);
m_trashIndex = -1;
}
}
Shared::ExpiringPointer<Calculation> CalculationStore::emptyStoreAndPushUndef(Context * context, HeightComputer heightComputer) { Shared::ExpiringPointer<Calculation> CalculationStore::emptyStoreAndPushUndef(Context * context, HeightComputer heightComputer) {
@@ -211,9 +236,9 @@ Shared::ExpiringPointer<Calculation> CalculationStore::emptyStoreAndPushUndef(Co
// Recompute memoized pointers to the calculations after index i // Recompute memoized pointers to the calculations after index i
void CalculationStore::recomputeMemoizedPointersAfterCalculationIndex(int index) { void CalculationStore::recomputeMemoizedPointersAfterCalculationIndex(int index) {
assert(index < m_numberOfCalculations); assert(index < numberOfCalculations());
// Clear pointer and recompute new ones // Clear pointer and recompute new ones
Calculation * c = calculationAtIndex(index).pointer(); Calculation * c = realCalculationAtIndex(index).pointer();
Calculation * nextCalc; Calculation * nextCalc;
while (index != 0) { while (index != 0) {
nextCalc = c->next(); nextCalc = c->next();

View File

@@ -41,11 +41,15 @@ public:
void deleteCalculationAtIndex(int i); void deleteCalculationAtIndex(int i);
void deleteAll(); void deleteAll();
int remainingBufferSize() const { assert(m_calculationAreaEnd >= m_buffer); return m_bufferSize - (m_calculationAreaEnd - m_buffer) - m_numberOfCalculations*sizeof(Calculation*); } int remainingBufferSize() const { assert(m_calculationAreaEnd >= m_buffer); return m_bufferSize - (m_calculationAreaEnd - m_buffer) - m_numberOfCalculations*sizeof(Calculation*); }
int numberOfCalculations() const { return m_numberOfCalculations; } int numberOfCalculations() const { return m_numberOfCalculations - (m_trashIndex != -1); }
Poincare::Expression ansExpression(Poincare::Context * context); Poincare::Expression ansExpression(Poincare::Context * context);
int bufferSize() { return m_bufferSize; } int bufferSize() { return m_bufferSize; }
void reinsertTrash() { m_trashIndex = -1; }
private: private:
void emptyTrash();
Shared::ExpiringPointer<Calculation> realCalculationAtIndex(int i);
void realDeleteCalculationAtIndex(int i);
class CalculationIterator { class CalculationIterator {
public: public:
@@ -70,6 +74,7 @@ private:
int m_bufferSize; int m_bufferSize;
const char * m_calculationAreaEnd; const char * m_calculationAreaEnd;
int m_numberOfCalculations; int m_numberOfCalculations;
int m_trashIndex;
size_t deleteOldestCalculation(); size_t deleteOldestCalculation();
char * addressOfPointerToCalculationOfIndex(int i) {return m_buffer + m_bufferSize - (m_numberOfCalculations - i)*sizeof(Calculation *);} char * addressOfPointerToCalculationOfIndex(int i) {return m_buffer + m_bufferSize - (m_numberOfCalculations - i)*sizeof(Calculation *);}

View File

@@ -68,6 +68,15 @@ void EditExpressionController::memoizeInput() {
*m_cacheBufferInformation = m_contentView.expressionField()->moveCursorAndDumpContent(m_cacheBuffer, k_cacheBufferSize); *m_cacheBufferInformation = m_contentView.expressionField()->moveCursorAndDumpContent(m_cacheBuffer, k_cacheBufferSize);
} }
bool EditExpressionController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::ShiftBack) {
m_historyController->reinsertTrash();
m_historyController->reload();
return true;
}
return false;
}
void EditExpressionController::viewWillAppear() { void EditExpressionController::viewWillAppear() {
m_historyController->viewWillAppear(); m_historyController->viewWillAppear();
} }

View File

@@ -31,6 +31,7 @@ public:
void insertTextBody(const char * text); void insertTextBody(const char * text);
void restoreInput(); void restoreInput();
void memoizeInput(); void memoizeInput();
bool handleEvent(Ion::Events::Event event) override;
/* TextFieldDelegate */ /* TextFieldDelegate */
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;

View File

@@ -35,6 +35,7 @@ public:
int typeAtLocation(int i, int j) override; int typeAtLocation(int i, int j) override;
void setSelectedSubviewType(SubviewType subviewType, bool sameCell, int previousSelectedX = -1, int previousSelectedY = -1) override; void setSelectedSubviewType(SubviewType subviewType, bool sameCell, int previousSelectedX = -1, int previousSelectedY = -1) override;
void tableViewDidChangeSelectionAndDidScroll(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) override; void tableViewDidChangeSelectionAndDidScroll(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) override;
void reinsertTrash() { m_calculationStore->reinsertTrash(); }
private: private:
int storeIndex(int i) { return numberOfRows() - i - 1; } int storeIndex(int i) { return numberOfRows() - i - 1; }
Shared::ExpiringPointer<Calculation> calculationAtIndex(int i); Shared::ExpiringPointer<Calculation> calculationAtIndex(int i);

View File

@@ -142,6 +142,7 @@ constexpr Event ShiftRight = Event::ShiftKey(Keyboard::Key::Right);
constexpr Event ShiftUp = Event::ShiftKey(Keyboard::Key::Up); constexpr Event ShiftUp = Event::ShiftKey(Keyboard::Key::Up);
constexpr Event ShiftDown = Event::ShiftKey(Keyboard::Key::Down); constexpr Event ShiftDown = Event::ShiftKey(Keyboard::Key::Down);
constexpr Event ShiftOK = Event::ShiftKey(Keyboard::Key::OK); constexpr Event ShiftOK = Event::ShiftKey(Keyboard::Key::OK);
constexpr Event ShiftBack = Event::ShiftKey(Keyboard::Key::Back);
constexpr Event AlphaLock = Event::ShiftKey(Keyboard::Key::Alpha); constexpr Event AlphaLock = Event::ShiftKey(Keyboard::Key::Alpha);
constexpr Event Cut = Event::ShiftKey(Keyboard::Key::XNT); constexpr Event Cut = Event::ShiftKey(Keyboard::Key::XNT);

View File

@@ -16,7 +16,7 @@ const EventData s_dataForEvent[4 * Event::PageSize] = {
T("1"), T("2"), T("3"), T("+"), T("-"), U(), T("1"), T("2"), T("3"), T("+"), T("-"), U(),
T("0"), T("."), T(""), TL(), TL(), U(), T("0"), T("."), T(""), TL(), TL(), U(),
// Shift // Shift
TL(), TL(), TL(), TL(), TL(), U(), TL(), TL(), TL(), TL(), TL(), TL(),
TL(), U(), U(), U(), U(), U(), TL(), U(), U(), U(), U(), U(),
U(), U(), TL(), TL(), TL(), TL(), U(), U(), TL(), TL(), TL(), TL(),
T("["), T("]"), T("{"), T("}"), T("_"), T(""), T("["), T("]"), T("{"), T("}"), T("_"), T(""),
@@ -61,7 +61,7 @@ const char * const s_nameForEvent[255] = {
"One", "Two", "Three", "Plus", "Minus", nullptr, "One", "Two", "Three", "Plus", "Minus", nullptr,
"Zero", "Dot", "EE", "Ans", "EXE", nullptr, "Zero", "Dot", "EE", "Ans", "EXE", nullptr,
//Shift, //Shift,
"ShiftLeft", "ShiftUp", "ShiftDown", "ShiftRight", "ShiftOK", nullptr, "ShiftLeft", "ShiftUp", "ShiftDown", "ShiftRight", "ShiftOK", "ShiftBack",
"ShiftHome", nullptr, nullptr, nullptr, nullptr, nullptr, "ShiftHome", nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, "AlphaLock", "Cut", "Copy", "Paste", "Clear", nullptr, "AlphaLock", "Cut", "Copy", "Paste", "Clear",
"LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Underscore", "Sto", "LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Underscore", "Sto",

View File

@@ -16,7 +16,7 @@ const EventData s_dataForEvent[4 * Event::PageSize] = {
T("1"), T("2"), T("3"), T("+"), T("-"), U(), T("1"), T("2"), T("3"), T("+"), T("-"), U(),
T("0"), T("."), T(""), TL(), TL(), U(), T("0"), T("."), T(""), TL(), TL(), U(),
// Shift // Shift
TL(), TL(), TL(), TL(), TL(), U(), TL(), TL(), TL(), TL(), TL(), TL(),
TL(), U(), U(), U(), U(), U(), TL(), U(), U(), U(), U(), U(),
U(), U(), TL(), TL(), TL(), TL(), U(), U(), TL(), TL(), TL(), TL(),
T("["), T("]"), T("{"), T("}"), T("_"), T(""), T("["), T("]"), T("{"), T("}"), T("_"), T(""),
@@ -61,7 +61,7 @@ const char * const s_nameForEvent[255] = {
"One", "Two", "Three", "Plus", "Minus", nullptr, "One", "Two", "Three", "Plus", "Minus", nullptr,
"Zero", "Dot", "EE", "Ans", "EXE", nullptr, "Zero", "Dot", "EE", "Ans", "EXE", nullptr,
//Shift, //Shift,
"ShiftLeft", "ShiftUp", "ShiftDown", "ShiftRight", "ShiftOK", nullptr, "ShiftLeft", "ShiftUp", "ShiftDown", "ShiftRight", "ShiftOK", "ShiftBack",
"ShiftHome", nullptr, nullptr, nullptr, nullptr, nullptr, "ShiftHome", nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, "AlphaLock", "Cut", "Copy", "Paste", "Clear", nullptr, "AlphaLock", "Cut", "Copy", "Paste", "Clear",
"LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Underscore", "Sto", "LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Underscore", "Sto",