#ifndef SOLVER_SOLUTIONS_CONTROLLER_H #define SOLVER_SOLUTIONS_CONTROLLER_H #include #include "equation_store.h" #include "../shared/scrollable_two_expressions_cell.h" #include namespace Solver { class SolutionsController : public ViewController, public AlternateEmptyViewDefaultDelegate, public SelectableTableViewDataSource, public TableViewDataSource, public SelectableTableViewDelegate { public: SolutionsController(Responder * parentResponder, EquationStore * equationStore); /* ViewController */ const char * title() override; View * view() override { return &m_contentView; } void viewWillAppear() override; void viewDidDisappear() override; void didEnterResponderChain(Responder * previousFirstResponder) override; TELEMETRY_ID("Solutions"); /* AlternateEmptyViewDefaultDelegate */ bool isEmpty() const override; I18n::Message emptyMessage() override; Responder * defaultController() override; /* TableViewDataSource */ int numberOfRows() const override; int numberOfColumns() const override { return 2; } void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; KDCoordinate columnWidth(int i) override; KDCoordinate rowHeight(int j) override; KDCoordinate cumulatedWidthFromIndex(int i) override; int indexFromCumulatedWidth(KDCoordinate offsetX) override; HighlightCell * reusableCell(int index, int type) override; int reusableCellCount(int type) override; int typeAtLocation(int i, int j) override; /* Responder */ void didBecomeFirstResponder() override; /* SelectableTableViewDelegate */ void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) override; private: class ContentView : public View { public: constexpr static KDCoordinate k_topMargin = 50; constexpr static KDColor k_backgroundColor = Palette::WallScreenDark; ContentView(SolutionsController * controller); void drawRect(KDContext * ctx, KDRect rect) const override; void setWarning(bool warning); void setWarningMessages(I18n::Message message0, I18n::Message message1); SelectableTableView * selectableTableView() { return &m_selectableTableView; } private: constexpr static KDCoordinate k_middleMargin = 50; int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews(bool force = false) override; MessageTextView m_warningMessageView0; MessageTextView m_warningMessageView1; SelectableTableView m_selectableTableView; bool m_displayWarningMoreSolutions; }; class MessageCell : public HighlightCell { public: MessageCell() : m_messageView(KDFont::SmallFont, (I18n::Message)0, 0.0f, k_verticalAlignment, KDColorBlack, SolutionsController::ContentView::k_backgroundColor) {} void setBackgroundColor(KDColor color) { m_messageView.setBackgroundColor(color); } void setHorizontalAlignment(float alignment) { m_messageView.setAlignment(alignment, k_verticalAlignment); } void setMessage(I18n::Message message) { m_messageView.setMessage(message); } private: constexpr static float k_verticalAlignment = 0.8f; int numberOfSubviews() const override { return 1; } View * subviewAtIndex(int index) override { assert(index == 0); return &m_messageView; } void layoutSubviews(bool force = false) override { m_messageView.setFrame(bounds(), force); } MessageTextView m_messageView; }; // Cell types constexpr static int k_symbolCellType = 0; constexpr static int k_deltaCellType = 1; constexpr static int k_exactValueCellType = 2; constexpr static int k_approximateValueCellType = 3; constexpr static int k_messageCellType = 4; // Heights and widths constexpr static KDCoordinate k_defaultCellHeight = 20; constexpr static int k_symbolCellWidth = 90; constexpr static int k_valueCellWidth = 190; // Number of cells constexpr static int k_maxNumberOfVisibleCells = (Ion::Display::Height - 3 * Metric::TitleBarHeight) / k_defaultCellHeight + 1; // When displaying approximate solutions for cos(x) = 0 between 0 and 1800 and scrolling down static_assert(k_maxNumberOfVisibleCells == 10, "k_maxNumberOfVisibleCells has changed"); //This assert is just for information purposes static_assert(k_maxNumberOfVisibleCells <= EquationStore::k_maxNumberOfSolutions + Poincare::Expression::k_maxNumberOfVariables, "We can reduce the number of cells in Solver:SolutionsController."); constexpr static int k_maxNumberOfSymbols = EquationStore::k_maxNumberOfSolutions + Poincare::Expression::k_maxNumberOfVariables; constexpr static int k_numberOfSymbolCells = k_maxNumberOfVisibleCells < k_maxNumberOfSymbols ? k_maxNumberOfVisibleCells : k_maxNumberOfSymbols; constexpr static int k_maxNumberOfExactValues = EquationStore::k_maxNumberOfExactSolutions + Poincare::Expression::k_maxNumberOfVariables; constexpr static int k_numberOfExactValueCells = k_maxNumberOfVisibleCells < k_maxNumberOfExactValues ? k_maxNumberOfVisibleCells : k_maxNumberOfExactValues; constexpr static int k_numberOfApproximateValueCells = 1 + (k_maxNumberOfVisibleCells < EquationStore::k_maxNumberOfApproximateSolutions ? k_maxNumberOfVisibleCells : EquationStore::k_maxNumberOfApproximateSolutions); constexpr static int k_numberOfMessageCells = 2; bool usedUserVariables() const { return m_equationStore->userVariablesUsed(); } int userVariablesMessageRow() const; EquationStore * m_equationStore; EvenOddBufferTextCell m_symbolCells[k_numberOfSymbolCells]; EvenOddExpressionCell m_deltaCell; Poincare::Layout m_delta2Layout; Shared::ScrollableTwoExpressionsCell m_exactValueCells[k_numberOfExactValueCells]; EvenOddBufferTextCell m_approximateValueCells[k_numberOfApproximateValueCells]; MessageCell m_messageCells[k_numberOfMessageCells]; ContentView m_contentView; }; } #endif