[ion/storage] Added the "ctrl-z" system everywhere

This commit is contained in:
Laury
2022-02-19 12:09:02 +01:00
parent f3d632c462
commit af5f9ea578
13 changed files with 128 additions and 28 deletions

View File

@@ -180,6 +180,7 @@ size_t CalculationStore::deleteOldestCalculation() {
// Delete all calculations
void CalculationStore::deleteAll() {
m_trashIndex = -1;
m_calculationAreaEnd = m_buffer;
m_numberOfCalculations = 0;
}

View File

@@ -90,6 +90,11 @@ bool MenuController::handleEvent(Ion::Events::Event event) {
footer()->setSelectedButton(0);
return true;
}
if (event == Ion::Events::ShiftBack) {
Ion::Storage::sharedStorage()->reinsertTrash("py");
m_selectableTableView.reloadData();
return true;
}
if (event == Ion::Events::Up) {
if (footer()->selectedButton() == 0) {
footer()->setSelectedButton(-1);

View File

@@ -21,6 +21,8 @@ public:
bool textFieldDidAbortEditing(TextField * textField) override;
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
protected:
virtual const char * recordExtension() const override { return Ion::Storage::funcExtension; }
private:
constexpr static int k_maxNumberOfDisplayableRows = 5;
Shared::ListParameterController * parameterController() override;

View File

@@ -25,6 +25,8 @@ public:
Toolbox * toolboxForInputEventHandler(InputEventHandler * handler) override;
void selectPreviousNewSequenceCell();
void editExpression(int sequenceDefinitionIndex, Ion::Events::Event event);
protected:
virtual const char * recordExtension() const override { return Ion::Storage::seqExtension; }
private:
static constexpr KDCoordinate k_expressionCellVerticalMargin = 3;
bool editInitialConditionOfSelectedRecordWithText(const char * text, bool firstInitialCondition);

View File

@@ -23,7 +23,6 @@ public:
* not defined. We thus have to keep both methods. */
virtual bool isDefined();
virtual bool isEmpty();
virtual bool shouldBeClearedBeforeRemove() { return !isEmpty(); }
/* tidy is responsible to tidy the whole model whereas tidyExpressionModel
* tidies only the members associated with the ExpressionModel. In
* ExpressionModel, tidy and tidyExpressionModel trigger the same

View File

@@ -184,18 +184,19 @@ bool ExpressionModelListController::handleEventOnExpression(Ion::Events::Event e
}
if (event == Ion::Events::Backspace && !isAddEmptyRow(selectedRow())) {
Ion::Storage::Record record = modelStore()->recordAtIndex(modelIndexForRow(selectedRow()));
ExpiringPointer<ExpressionModelHandle> model = modelStore()->modelForRecord(record);
if (model->shouldBeClearedBeforeRemove()) {
reinitSelectedExpression(model);
} else {
if (removeModelRow(record)) {
int newSelectedRow = selectedRow() >= numberOfExpressionRows() ? numberOfExpressionRows()-1 : selectedRow();
selectCellAtLocation(selectedColumn(), newSelectedRow);
selectableTableView()->reloadData();
}
ExpiringPointer<ExpressionModelHandle> model = modelStore()->modelForRecord(record);
if (removeModelRow(record)) {
int newSelectedRow = selectedRow() >= numberOfExpressionRows() ? numberOfExpressionRows()-1 : selectedRow();
selectCellAtLocation(selectedColumn(), newSelectedRow);
selectableTableView()->reloadData();
}
return true;
}
if (event == Ion::Events::ShiftBack) {
Ion::Storage::sharedStorage()->reinsertTrash(recordExtension());
selectableTableView()->reloadData();
return true;
}
if ((event.hasText() || event == Ion::Events::XNT || event == Ion::Events::Paste || event == Ion::Events::Toolbox || event == Ion::Events::Var)
&& !isAddEmptyRow(selectedRow())) {
editExpression(event);

View File

@@ -11,6 +11,7 @@ class ExpressionModelListController : public ViewController, public SelectableTa
public:
ExpressionModelListController(Responder * parentResponder, I18n::Message text);
protected:
virtual const char * recordExtension() const = 0;
static constexpr KDCoordinate k_expressionMargin = 5;
// SelectableTableViewDelegate
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) override;

View File

@@ -200,6 +200,11 @@ bool FunctionListController::handleEvent(Ion::Events::Event event) {
}
return true;
}
if (event == Ion::Events::ShiftBack) {
Ion::Storage::sharedStorage()->reinsertTrash(recordExtension());
selectableTableView()->reloadData();
return true;
}
return false;
}

View File

@@ -7,6 +7,7 @@
#include "list_parameter_controller.h"
#include "expression_model_list_controller.h"
#include <apps/i18n.h>
#include <ion/storage.h>
namespace Shared {

View File

@@ -8,9 +8,6 @@ namespace Solver {
class Equation : public Shared::ExpressionModelHandle {
public:
Equation(Ion::Storage::Record record = Record()) : ExpressionModelHandle(record) {}
bool shouldBeClearedBeforeRemove() override {
return false;
}
Poincare::Expression standardForm(Poincare::Context * context, bool replaceFunctionsButNotSymbols, Poincare::ExpressionNode::ReductionTarget reductionTarget) const { return m_model.standardForm(this, context, replaceFunctionsButNotSymbols, reductionTarget); }
bool containsIComplex(Poincare::Context * context) const;

View File

@@ -9,6 +9,7 @@
#include "equation_list_view.h"
#include "equation_models_parameter_controller.h"
#include <apps/i18n.h>
#include <ion/storage.h>
namespace Solver {
@@ -45,6 +46,8 @@ public:
bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::Layout layout, Ion::Events::Event event) override;
/* Specific to Solver */
void resolveEquations();
protected:
virtual const char * recordExtension() const override { return Ion::Storage::eqExtension; }
private:
constexpr static int k_maxNumberOfRows = 5; // Ion::Display::Height / Metric::StoreRowHeight = 4.8;
SelectableTableView * selectableTableView() override;

View File

@@ -125,7 +125,10 @@ public:
// Used by Python OS module
int numberOfRecords();
Record recordAtIndex(int index);
Record recordAtIndex(int index); // Unlike realRecordAtIndex, this ignore trash
// Trash
void reinsertTrash(const char * extension);
private:
constexpr static uint32_t Magic = 0xEE0BDDBA;
@@ -140,6 +143,7 @@ private:
Record::Data valueOfRecord(const Record record);
Record::ErrorStatus setValueOfRecord(const Record record, Record::Data data);
void destroyRecord(const Record record);
void realDestroyRecord(const Record record);
/* Getters on address in buffer */
char * pointerOfRecord(const Record record) const;
@@ -147,12 +151,18 @@ private:
const char * fullNameOfRecordStarting(char * start) const;
const void * valueOfRecordStarting(char * start) const;
/* Trash */
void emptyTrash();
Storage::Record realRecordAtIndex(int index);
int realNumberOfRecords();
/* Overriders */
size_t overrideSizeAtPosition(char * position, record_size_t size);
size_t overrideFullNameAtPosition(char * position, const char * fullName);
size_t overrideBaseNameWithExtensionAtPosition(char * position, const char * baseName, const char * extension);
size_t overrideValueAtPosition(char * position, const void * data, record_size_t size);
size_t realAvailableSize();
bool isFullNameTaken(const char * fullName, const Record * recordToExclude = nullptr);
bool isBaseNameWithExtensionTaken(const char * baseName, const char * extension, Record * recordToExclude = nullptr);
bool isNameOfRecordTaken(Record r, const Record * recordToExclude);
@@ -182,6 +192,7 @@ private:
uint32_t m_magicHeader;
char m_buffer[k_storageSize];
Record m_trashRecord;
uint32_t m_magicFooter;
StorageDelegate * m_delegate;
mutable Record m_lastRecordRetrieved;

View File

@@ -97,6 +97,14 @@ void Storage::log() {
#endif
size_t Storage::availableSize() {
if (m_trashRecord != NULL) {
return realAvailableSize() + sizeof(record_size_t) + m_trashRecord.value().size;
} else {
return realAvailableSize();
}
}
size_t Storage::realAvailableSize() {
/* TODO maybe do: availableSize(char ** endBuffer) to get the endBuffer if it
* is needed after calling availableSize */
assert(k_storageSize >= (endBuffer() - m_buffer) + sizeof(record_size_t));
@@ -106,7 +114,7 @@ size_t Storage::availableSize() {
size_t Storage::putAvailableSpaceAtEndOfRecord(Storage::Record r) {
char * p = pointerOfRecord(r);
size_t previousRecordSize = sizeOfRecordStarting(p);
size_t availableStorageSize = availableSize();
size_t availableStorageSize = realAvailableSize();
char * nextRecord = p + previousRecordSize;
memmove(nextRecord + availableStorageSize,
nextRecord,
@@ -146,6 +154,7 @@ Storage::Record::ErrorStatus Storage::notifyFullnessToDelegate() const {
}
Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * fullName, const void * data, size_t size) {
emptyTrash();
size_t recordSize = sizeOfRecordWithFullName(fullName, size);
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
return notifyFullnessToDelegate();
@@ -172,6 +181,7 @@ Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * full
}
Storage::Record::ErrorStatus Storage::createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size) {
emptyTrash();
size_t recordSize = sizeOfRecordWithBaseNameAndExtension(baseName, extension, size);
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
return notifyFullnessToDelegate();
@@ -202,7 +212,7 @@ int Storage::numberOfRecordsWithExtension(const char * extension) {
size_t extensionLength = strlen(extension);
for (char * p : *this) {
const char * name = fullNameOfRecordStarting(p);
if (FullNameHasExtension(name, extension, extensionLength)) {
if (FullNameHasExtension(name, extension, extensionLength) && Record(name) != m_trashRecord) {
count++;
}
}
@@ -210,6 +220,10 @@ int Storage::numberOfRecordsWithExtension(const char * extension) {
}
int Storage::numberOfRecords() {
return realNumberOfRecords() - (m_trashRecord == NULL ? 0 : 1);
}
int Storage::realNumberOfRecords() {
int count = 0;
for (char * p : *this) {
const char * name = fullNameOfRecordStarting(p);
@@ -218,7 +232,7 @@ int Storage::numberOfRecords() {
return count;
}
Storage::Record Storage::recordAtIndex(int index) {
Storage::Record Storage::realRecordAtIndex(int index) {
int currentIndex = -1;
const char * name = nullptr;
char * recordAddress = nullptr;
@@ -240,6 +254,40 @@ Storage::Record Storage::recordAtIndex(int index) {
return Record(name);
}
Storage::Record Storage::recordAtIndex(int index) {
int currentIndex = -1;
const char * name = nullptr;
char * recordAddress = nullptr;
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
Record r = Record(currentName);
if (r == m_trashRecord) {
continue;
}
currentIndex++;
if (currentIndex == index) {
recordAddress = p;
name = currentName;
break;
}
}
if (name == nullptr) {
return Record();
}
Record r = Record(name);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = recordAddress;
return Record(name);
}
void Storage::emptyTrash() {
if (m_trashRecord != NULL) {
realDestroyRecord(m_trashRecord);
m_trashRecord = NULL;
}
}
Storage::Record Storage::recordWithExtensionAtIndex(const char * extension, int index) {
int currentIndex = -1;
const char * name = nullptr;
@@ -247,13 +295,13 @@ Storage::Record Storage::recordWithExtensionAtIndex(const char * extension, int
char * recordAddress = nullptr;
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
if (FullNameHasExtension(currentName, extension, extensionLength)) {
if (FullNameHasExtension(currentName, extension, extensionLength) && Record(currentName) != m_trashRecord) {
currentIndex++;
}
if (currentIndex == index) {
recordAddress = p;
name = currentName;
break;
if (currentIndex == index) {
recordAddress = p;
name = currentName;
break;
}
}
}
if (name == nullptr) {
@@ -328,7 +376,8 @@ Storage::Storage() :
m_magicFooter(Magic),
m_delegate(nullptr),
m_lastRecordRetrieved(nullptr),
m_lastRecordRetrievedPointer(nullptr)
m_lastRecordRetrievedPointer(nullptr),
m_trashRecord(NULL)
{
assert(m_magicHeader == Magic);
assert(m_magicFooter == Magic);
@@ -430,7 +479,24 @@ Storage::Record::ErrorStatus Storage::setValueOfRecord(Record record, Record::Da
return Record::ErrorStatus::RecordDoesNotExist;
}
void Storage::reinsertTrash(const char * extension) {
if (m_trashRecord != NULL) {
char * p = pointerOfRecord(m_trashRecord);
const char * fullName = fullNameOfRecordStarting(p);
if (FullNameHasExtension(fullName, extension, strlen(extension))) {
m_trashRecord = NULL;
}
}
}
void Storage::destroyRecord(Record record) {
emptyTrash();
m_trashRecord = record;
}
void Storage::realDestroyRecord(Record record) {
if (record.isNull()) {
return;
}
@@ -520,7 +586,7 @@ bool Storage::isNameOfRecordTaken(Record r, const Record * recordToExclude) {
if (recordToExclude && s == *recordToExclude) {
continue;
}
if (s == r) {
if (s == r && s != m_trashRecord) {
return true;
}
}
@@ -576,8 +642,11 @@ size_t Storage::sizeOfRecordWithFullName(const char * fullName, size_t dataSize)
}
bool Storage::slideBuffer(char * position, int delta) {
if (delta > (int)availableSize()) {
return false;
if (delta > (int)realAvailableSize()) {
emptyTrash();
if (delta > (int)realAvailableSize()) {
return false;
}
}
memmove(position+delta, position, endBuffer()+sizeof(record_size_t)-position);
return true;
@@ -587,7 +656,7 @@ Storage::Record Storage::privateRecordAndExtensionOfRecordBaseNamedWithExtension
size_t nameLength = baseNameLength < 0 ? strlen(baseName) : baseNameLength;
{
const char * lastRetrievedRecordFullName = fullNameOfRecordStarting(m_lastRecordRetrievedPointer);
if (m_lastRecordRetrievedPointer != nullptr && strncmp(baseName, lastRetrievedRecordFullName, nameLength) == 0) {
if (m_lastRecordRetrievedPointer != nullptr && strncmp(baseName, lastRetrievedRecordFullName, nameLength) == 0 && Record(lastRetrievedRecordFullName) == m_trashRecord) {
for (size_t i = 0; i < numberOfExtensions; i++) {
if (strcmp(lastRetrievedRecordFullName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
assert(UTF8Helper::CodePointIs(lastRetrievedRecordFullName + nameLength, '.'));
@@ -602,6 +671,9 @@ Storage::Record Storage::privateRecordAndExtensionOfRecordBaseNamedWithExtension
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
if (strncmp(baseName, currentName, nameLength) == 0) {
if (Record(currentName) == m_trashRecord) {
continue;
}
for (size_t i = 0; i < numberOfExtensions; i++) {
if (strcmp(currentName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
assert(UTF8Helper::CodePointIs(currentName + nameLength, '.'));