diff --git a/apps/regression/app.cpp b/apps/regression/app.cpp index 34fd83ef0..131618259 100644 --- a/apps/regression/app.cpp +++ b/apps/regression/app.cpp @@ -6,7 +6,7 @@ namespace Regression { App::App(Container * container) : TextFieldDelegateApp(container, &m_tabViewController, "Resgression", ImageStore::RegressionIcon), m_data(), - m_calculationController(CalculationController(&m_calculationAlternateEmptyViewController)), + m_calculationController(CalculationController(&m_calculationAlternateEmptyViewController, &m_data)), m_calculationAlternateEmptyViewController(AlternateEmptyViewController(&m_tabViewController, &m_calculationController, &m_calculationController)), m_graphController(GraphController(&m_graphHeader, &m_graphHeader, &m_data)), m_graphHeader(HeaderViewController(&m_graphAlternateEmptyViewController, &m_graphController, &m_graphController)), diff --git a/apps/regression/calculation_controller.cpp b/apps/regression/calculation_controller.cpp index 8918e87a2..981847ada 100644 --- a/apps/regression/calculation_controller.cpp +++ b/apps/regression/calculation_controller.cpp @@ -1,44 +1,253 @@ #include "calculation_controller.h" +#include "../constant.h" +#include +#include namespace Regression { -CalculationController::CalculationController(Responder * parentResponder) : +CalculationController::CalculationController(Responder * parentResponder, Data * data) : ViewController(parentResponder), - m_view(SolidColorView(KDColorGreen)) + m_selectableTableView(SelectableTableView(this, this, Metric::TopMargin, Metric::RightMargin, Metric::BottomMargin, Metric::LeftMargin, this)), + m_data(data) { + m_columnTitleCell.setParentResponder(&m_selectableTableView); + for (int k = 0; k < k_maxNumberOfDisplayableRows/2; k++) { + m_calculationCells[k].setTextColor(Palette::DesactiveTextColor); + m_doubleCalculationCells[k].setTextColor(Palette::DesactiveTextColor); + m_doubleCalculationCells[k].setParentResponder(&m_selectableTableView); + } } const char * CalculationController::title() const { - return "Stats"; + return "Statistics"; } View * CalculationController::view() { - return &m_view; + return &m_selectableTableView; } bool CalculationController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::Up) { + m_selectableTableView.deselectTable(); app()->setFirstResponder(tabController()); return true; } return false; } +void CalculationController::didBecomeFirstResponder() { + if (m_selectableTableView.selectedRow() == -1) { + m_selectableTableView.selectCellAtLocation(1, 0); + } else { + m_selectableTableView.selectCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); + } + app()->setFirstResponder(&m_selectableTableView); +} + +void CalculationController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) { + // Avoid selecting empty cell + if (t->selectedRow() == 0 && t->selectedColumn() == 0) { + if (previousSelectedCellX == 0 && previousSelectedCellY == 1) { + m_selectableTableView.deselectTable(); + app()->setFirstResponder(tabController()); + } else { + t->selectCellAtLocation(previousSelectedCellX, previousSelectedCellY); + } + } + if (t->selectedColumn() == 1 && t->selectedRow() >= 0 && t->selectedRow() < 6) { + EvenOddDoubleBufferTextCell * myCell = (EvenOddDoubleBufferTextCell *)t->cellAtLocation(t->selectedColumn(), t->selectedRow()); + bool firstSubCellSelected = true; + if (previousSelectedCellX == 1 && previousSelectedCellY >= 0 && previousSelectedCellY < 6) { + EvenOddDoubleBufferTextCell * myPreviousCell = (EvenOddDoubleBufferTextCell *)t->cellAtLocation(previousSelectedCellX, previousSelectedCellY); + firstSubCellSelected = myPreviousCell->firstTextSelected(); + } + myCell->selectFirstText(firstSubCellSelected); + app()->setFirstResponder(myCell); + } else { + if (previousSelectedCellX == 1 && previousSelectedCellY >= 0 && previousSelectedCellY < 6) { + app()->setFirstResponder(t); + } + } +} + bool CalculationController::isEmpty() { + if (m_data->numberOfPairs() == 0) { + return true; + } return false; } const char * CalculationController::emptyMessage() { - return "Aucune donnée à tracer"; + return "Aucune grandeur a calculer"; } Responder * CalculationController::defaultController() { return tabController(); } +int CalculationController::numberOfRows() { + return k_totalNumberOfRows; +} + +int CalculationController::numberOfColumns() { + return k_totalNumberOfColumns; +} + +void CalculationController::willDisplayCellAtLocation(TableViewCell * cell, int i, int j) { + EvenOddCell * myCell = (EvenOddCell *)cell; + myCell->setEven(j%2 == 0); + myCell->setHighlighted(i == m_selectableTableView.selectedColumn() && j == m_selectableTableView.selectedRow()); + if (j == 0 && i > 0) { + EvenOddDoubleBufferTextCell * myCell = (EvenOddDoubleBufferTextCell *)cell; + myCell->setFirstText("x"); + myCell->setSecondText("y"); + return; + } + if (i == 0) { + EvenOddPointerTextCell * myCell = (EvenOddPointerTextCell *)cell; + if (j == 0) { + myCell->setText(""); + return; + } + const char * titles[k_totalNumberOfRows-1] = {"Moyenne", "Somme", "Somme des carres", "Ecart-type", "Variance", + "Nombre de points", "Covariance", "Sxy", "r", "r2"}; + myCell->setAlignment(1.0f, 0.5f); + myCell->setText(titles[j-1]); + return; + } + if (i == 1 && j > 0 && j < 6) { + float calculation1 = 0.0f; + float calculation2 = 0.0f; + switch (j) { + case 1: + calculation1 = m_data->xMean(); + calculation2 = m_data->yMean(); + break; + case 2: + calculation1 = m_data->xSum(); + calculation2 = m_data->ySum(); + break; + case 3: + calculation1 = m_data->xSquaredValueSum(); + calculation2 = m_data->ySquaredValueSum(); + break; + case 4: + calculation1 = m_data->xStandardDeviation(); + calculation2 = m_data->yStandardDeviation(); + break; + case 5: + calculation1 = m_data->xVariance(); + calculation2 = m_data->yVariance(); + break; + default: + break; + } + EvenOddDoubleBufferTextCell * myCell = (EvenOddDoubleBufferTextCell *)cell; + char buffer[Constant::FloatBufferSizeInScientificMode]; + Float(calculation1).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + myCell->setFirstText(buffer); + Float(calculation2).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + myCell->setSecondText(buffer); + return; + } + if (i == 1 && j > 5) { + float calculation = 0.0f; + switch (j) { + case 6: + calculation = m_data->numberOfPairs(); + break; + case 7: + calculation = m_data->covariance(); + break; + case 8: + calculation = m_data->xyProductSum(); + break; + case 9: + calculation = m_data->correlationCoefficient(); + break; + case 10: + calculation = m_data->squaredCorrelationCoefficient(); + break; + default: + break; + } + EvenOddBufferTextCell * myCell = (EvenOddBufferTextCell *)cell; + char buffer[Constant::FloatBufferSizeInScientificMode]; + Float(calculation).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + myCell->setText(buffer); + return; + } +} + +KDCoordinate CalculationController::columnWidth(int i) { + return k_cellWidth; +} + +KDCoordinate CalculationController::rowHeight(int j) { + return k_cellHeight; +} + +KDCoordinate CalculationController::cumulatedWidthFromIndex(int i) { + return i*k_cellWidth; +} + +KDCoordinate CalculationController::cumulatedHeightFromIndex(int j) { + return j*k_cellHeight; +} + +int CalculationController::indexFromCumulatedWidth(KDCoordinate offsetX) { + return (offsetX-1) / k_cellWidth; +} + +int CalculationController::indexFromCumulatedHeight(KDCoordinate offsetY) { + return (offsetY-1) / k_cellHeight; +} + +TableViewCell * CalculationController::reusableCell(int index, int type) { + if (type == 0) { + assert(index < k_totalNumberOfRows + 2); + return &m_titleCells[index]; + } + if (type == 1) { + assert(index == 0); + return &m_columnTitleCell; + } + if (type == 2) { + assert(index < k_totalNumberOfRows/2); + return &m_doubleCalculationCells[index]; + } + assert(index < k_totalNumberOfRows/2); + return &m_calculationCells[index]; +} + +int CalculationController::reusableCellCount(int type) { + if (type == 0) { + return k_maxNumberOfDisplayableRows; + } + if (type == 1) { + return 1; + } + if (type == 2) { + return k_maxNumberOfDisplayableRows/2; + } + return k_maxNumberOfDisplayableRows/2; +} + +int CalculationController::typeAtLocation(int i, int j) { + if (i == 0) { + return 0; + } + if (j == 0) { + return 1; + } + if (j > 0 && j < 6) { + return 2; + } + return 3; +} + Responder * CalculationController::tabController() const { return (parentResponder()->parentResponder()->parentResponder()); } } - diff --git a/apps/regression/calculation_controller.h b/apps/regression/calculation_controller.h index e36089604..2cd9c65d5 100644 --- a/apps/regression/calculation_controller.h +++ b/apps/regression/calculation_controller.h @@ -2,25 +2,52 @@ #define REGRESSION_CALCULATION_CONTROLLER_H #include +#include "data.h" +#include "even_odd_double_buffer_text_cell.h" namespace Regression { -class CalculationController : public ViewController, public AlternateEmptyViewDelegate { +class CalculationController : public ViewController, public AlternateEmptyViewDelegate, public TableViewDataSource, public SelectableTableViewDelegate { public: - CalculationController(Responder * parentResponder); + CalculationController(Responder * parentResponder, Data * data); const char * title() const override; View * view() override; bool handleEvent(Ion::Events::Event event) override; + void didBecomeFirstResponder() override; + void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override; + bool isEmpty() override; const char * emptyMessage() override; Responder * defaultController() override; + + int numberOfRows() override; + int numberOfColumns() override; + void willDisplayCellAtLocation(TableViewCell * cell, int i, int j) override; + KDCoordinate columnWidth(int i) override; + KDCoordinate rowHeight(int j) override; + KDCoordinate cumulatedWidthFromIndex(int i) override; + KDCoordinate cumulatedHeightFromIndex(int j) override; + int indexFromCumulatedWidth(KDCoordinate offsetX) override; + int indexFromCumulatedHeight(KDCoordinate offsetY) override; + TableViewCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + int typeAtLocation(int i, int j) override; private: Responder * tabController() const; - SolidColorView m_view; + constexpr static int k_totalNumberOfRows = 11; + constexpr static int k_totalNumberOfColumns = 2; + constexpr static int k_maxNumberOfDisplayableRows = 10; + static constexpr KDCoordinate k_cellHeight = 25; + static constexpr KDCoordinate k_cellWidth = 320/2 - Metric::RightMargin/2 - Metric::LeftMargin/2; + EvenOddPointerTextCell m_titleCells[k_maxNumberOfDisplayableRows]; + EvenOddDoubleBufferTextCell m_columnTitleCell; + EvenOddDoubleBufferTextCell m_doubleCalculationCells[k_maxNumberOfDisplayableRows/2]; + EvenOddBufferTextCell m_calculationCells[k_maxNumberOfDisplayableRows/2]; + SelectableTableView m_selectableTableView; + Data * m_data; }; } - -#endif \ No newline at end of file +#endif