From ff6eb7525f80c9dfef14723645e453460539cd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 26 Sep 2019 10:35:11 +0200 Subject: [PATCH] [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 --- apps/graph/values/values_controller.cpp | 41 +++++++++++++++++++++- apps/graph/values/values_controller.h | 13 +++++++ apps/sequence/values/values_controller.cpp | 3 +- apps/sequence/values/values_controller.h | 2 ++ apps/shared/values_controller.cpp | 12 +++---- apps/shared/values_controller.h | 4 +-- 6 files changed, 64 insertions(+), 11 deletions(-) diff --git a/apps/graph/values/values_controller.cpp b/apps/graph/values/values_controller.cpp index 1520f1b68..c0e506f43 100644 --- a/apps/graph/values/values_controller.cpp +++ b/apps/graph/values/values_controller.cpp @@ -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; +} + } diff --git a/apps/graph/values/values_controller.h b/apps/graph/values/values_controller.h index ac7f34bc5..dbcad5c8d 100644 --- a/apps/graph/values/values_controller.h +++ b/apps/graph/values/values_controller.h @@ -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]; diff --git a/apps/sequence/values/values_controller.cpp b/apps/sequence/values/values_controller.cpp index 43d99f029..16c5f546a 100644 --- a/apps/sequence/values/values_controller.cpp +++ b/apps/sequence/values/values_controller.cpp @@ -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) { diff --git a/apps/sequence/values/values_controller.h b/apps/sequence/values/values_controller.h index b46723f5c..403c55ec4 100644 --- a/apps/sequence/values/values_controller.h +++ b/apps/sequence/values/values_controller.h @@ -33,6 +33,7 @@ private: SequenceStore * functionStore() const override { return static_cast(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; diff --git a/apps/shared/values_controller.cpp b/apps/shared/values_controller.cpp index ad167915b..2528e2356 100644 --- a/apps/shared/values_controller.cpp +++ b/apps/shared/values_controller.cpp @@ -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); } diff --git a/apps/shared/values_controller.h b/apps/shared/values_controller.h index a892bcb3d..ad691e669 100644 --- a/apps/shared/values_controller.h +++ b/apps/shared/values_controller.h @@ -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;