[apps/graph] Copy/Cut events on the values controller turn the "(1;3)"

notation into "[[1][3]]" in order to create a matrix layout when paste
into a layout field
This commit is contained in:
Émilie Feral
2019-09-26 10:35:11 +02:00
committed by LeaNumworks
parent c982b4c452
commit ff6eb7525f
6 changed files with 64 additions and 11 deletions

View File

@@ -11,6 +11,7 @@ namespace Graph {
ValuesController::ValuesController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header) :
Shared::ValuesController(parentResponder, header),
m_selectableTableView(this),
m_functionTitleCells{},
m_floatCells{},
m_abscissaTitleCells{},
@@ -38,7 +39,7 @@ ValuesController::ValuesController(Responder * parentResponder, InputEventHandle
m_functionTitleCells[i].setOrientation(FunctionTitleCell::Orientation::HorizontalIndicator);
m_functionTitleCells[i].setFont(KDFont::SmallFont);
}
setupAbscissaCellsAndTitleCells(inputEventHandlerDelegate);
setupSelectableTableViewAndCells(inputEventHandlerDelegate);
m_selectableTableView.setDelegate(this);
}
@@ -286,4 +287,42 @@ void ValuesController::updateNumberOfColumns() const {
}
}
int writeMatrixBrakets(char * buffer, const int bufferSize, int type) {
/* Write the double brackets required in matrix notation.
* - type == 1: "[["
* - type == 0: "]["
* - type == -1: "]]"
*/
int currentChar = 0;
assert(currentChar < bufferSize-1);
buffer[currentChar++] = type < 0 ? '[' : ']';
assert(currentChar < bufferSize-1);
buffer[currentChar++] = type <= 0 ? '[' : ']';
return currentChar;
}
bool ValuesController::ValuesSelectableTableView::handleEvent(Ion::Events::Event event) {
bool handledEvent = SelectableTableView::handleEvent(event);
if (handledEvent && (event == Ion::Events::Copy || event == Ion::Events::Cut)) {
const char * text = Clipboard::sharedClipboard()->storedText();
if (text[0] == '(') {
constexpr int bufferSize = 2*PrintFloat::k_maxFloatCharSize + 6; // "[[a][b]]" gives 6 characters in addition to the 2 floats
char buffer[bufferSize];
int currentChar = 0;
currentChar += writeMatrixBrakets(buffer + currentChar, bufferSize - currentChar, -1);
assert(currentChar < bufferSize-1);
size_t semiColonPosition = UTF8Helper::CopyUntilCodePoint(buffer+currentChar, TextField::maxBufferSize() - currentChar, text+1, ';');
currentChar += semiColonPosition;
currentChar += writeMatrixBrakets(buffer + currentChar, bufferSize - currentChar, 0);
assert(currentChar < bufferSize-1);
currentChar += UTF8Helper::CopyUntilCodePoint(buffer+currentChar, TextField::maxBufferSize() - currentChar, text+1+semiColonPosition+1, ')');
currentChar += writeMatrixBrakets(buffer + currentChar, bufferSize - currentChar, 1);
assert(currentChar < bufferSize-1);
buffer[currentChar] = 0;
Clipboard::sharedClipboard()->store(buffer);
}
}
return handledEvent;
}
}

View File

@@ -63,7 +63,20 @@ private:
int abscissaTitleCellsCount() const override { return Shared::ContinuousFunction::k_numberOfPlotTypes; }
EvenOddMessageTextCell * abscissaTitleCells(int j) override { assert (j >= 0 && j < abscissaTitleCellsCount()); return &m_abscissaTitleCells[j]; }
ViewController * functionParameterController() override;
SelectableTableView * selectableTableView() override { return &m_selectableTableView; }
/* For parametric function, we display the evaluation with the form "(1;2)".
* This form is not parsable so when we store it into the clipboard, we want
* to turn it into a parsable matrix "[[1][2]]". To do so, we use a child
* class of SelectableTableView to override the behaviour of the responder
* when encountering a cut/copy events. */
class ValuesSelectableTableView : public SelectableTableView {
public:
ValuesSelectableTableView(ValuesController * vc) : SelectableTableView(vc, vc, vc) {}
bool handleEvent(Ion::Events::Event event) override;
};
ValuesSelectableTableView m_selectableTableView;
mutable int m_numberOfColumnsForType[Shared::ContinuousFunction::k_numberOfPlotTypes];
Shared::BufferFunctionTitleCell m_functionTitleCells[k_maxNumberOfFunctions];
Shared::HideableEvenOddBufferTextCell m_floatCells[k_maxNumberOfCells];

View File

@@ -10,6 +10,7 @@ namespace Sequence {
ValuesController::ValuesController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header) :
Shared::ValuesController(parentResponder, header),
m_selectableTableView(this),
m_sequenceTitleCells{},
m_floatCells{},
m_abscissaTitleCell(),
@@ -30,7 +31,7 @@ ValuesController::ValuesController(Responder * parentResponder, InputEventHandle
for (int i = 0; i < k_maxNumberOfSequences; i++) {
m_sequenceTitleCells[i].setOrientation(Shared::FunctionTitleCell::Orientation::HorizontalIndicator);
}
setupAbscissaCellsAndTitleCells(inputEventHandlerDelegate);
setupSelectableTableViewAndCells(inputEventHandlerDelegate);
}
KDCoordinate ValuesController::columnWidth(int i) {

View File

@@ -33,6 +33,7 @@ private:
SequenceStore * functionStore() const override { return static_cast<SequenceStore *>(Shared::ValuesController::functionStore()); }
ViewController * functionParameterController() override;
SelectableTableView * selectableTableView() override { return &m_selectableTableView; }
int abscissaCellsCount() const override { return k_maxNumberOfRows; }
EvenOddEditableTextCell * abscissaCells(int j) override {
assert (j >= 0 && j < k_maxNumberOfRows);
@@ -51,6 +52,7 @@ private:
assert(j >= 0 && j < k_maxNumberOfCells);
return &m_floatCells[j];
}
SelectableTableView m_selectableTableView;
SequenceTitleCell m_sequenceTitleCells[k_maxNumberOfSequences];
EvenOddBufferTextCell m_floatCells[k_maxNumberOfCells];
EvenOddMessageTextCell m_abscissaTitleCell;

View File

@@ -12,19 +12,19 @@ ValuesController::ValuesController(Responder * parentResponder, ButtonRowControl
ButtonRowDelegate(header, nullptr),
m_numberOfColumns(0),
m_numberOfColumnsNeedUpdate(true),
m_selectableTableView(this),
m_abscissaParameterController(this)
{
m_selectableTableView.setVerticalCellOverlap(0);
m_selectableTableView.setMargins(k_margin, k_scrollBarMargin, k_scrollBarMargin, k_margin);
m_selectableTableView.setBackgroundColor(Palette::WallScreenDark);
}
void ValuesController::setupAbscissaCellsAndTitleCells(InputEventHandlerDelegate * inputEventHandlerDelegate) {
void ValuesController::setupSelectableTableViewAndCells(InputEventHandlerDelegate * inputEventHandlerDelegate) {
selectableTableView()->setVerticalCellOverlap(0);
selectableTableView()->setMargins(k_margin, k_scrollBarMargin, k_scrollBarMargin, k_margin);
selectableTableView()->setBackgroundColor(Palette::WallScreenDark);
int numberOfAbscissaCells = abscissaCellsCount();
for (int i = 0; i < numberOfAbscissaCells; i++) {
EvenOddEditableTextCell * c = abscissaCells(i);
c->setParentResponder(&m_selectableTableView);
c->setParentResponder(selectableTableView());
c->editableTextCell()->textField()->setDelegates(inputEventHandlerDelegate, this);
c->editableTextCell()->textField()->setFont(k_font);
}

View File

@@ -41,17 +41,15 @@ protected:
constexpr static int k_maxNumberOfRows = 10;
static constexpr const KDFont * k_font = KDFont::SmallFont;
void setupAbscissaCellsAndTitleCells(InputEventHandlerDelegate * inputEventHandlerDelegate);
void setupSelectableTableViewAndCells(InputEventHandlerDelegate * inputEventHandlerDelegate);
StackViewController * stackController() const;
bool setDataAtLocation(double floatBody, int columnIndex, int rowIndex) override;
virtual void updateNumberOfColumns() const;
virtual FunctionStore * functionStore() const;
virtual Ion::Storage::Record recordAtColumn(int i);
int numberOfElementsInColumn(int columnIndex) const override;
SelectableTableView * selectableTableView() override { return &m_selectableTableView; }
mutable int m_numberOfColumns;
mutable bool m_numberOfColumnsNeedUpdate;
SelectableTableView m_selectableTableView;
private:
virtual void setStartEndMessages(Shared::IntervalParameterController * controller, int column) = 0;
Responder * tabController() const override;