mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[apps/calculation] Add a "ctrl-z" system
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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 *);}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user