From fd06d428e5ff751cde75c1f86dcbf76b4ec597f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 21 Dec 2017 17:34:15 +0100 Subject: [PATCH] [apps] Redesign Probability Calculation page --- apps/probability/Makefile | 6 +- apps/probability/calculation_cell.cpp | 75 ++++++ apps/probability/calculation_cell.h | 33 +++ apps/probability/calculation_controller.cpp | 203 +++++++++++++-- apps/probability/calculation_controller.h | 54 +++- .../calculation_type_controller.cpp | 91 +++++++ .../probability/calculation_type_controller.h | 38 +++ apps/probability/calculation_view.cpp | 234 ------------------ apps/probability/calculation_view.h | 58 ----- apps/probability/image_cell.cpp | 42 ++++ apps/probability/image_cell.h | 26 ++ apps/probability/image_table_view.cpp | 164 ------------ apps/probability/image_table_view.h | 62 ----- apps/probability/responder_image_cell.cpp | 53 ++++ apps/probability/responder_image_cell.h | 37 +++ escher/include/escher/list_view_data_source.h | 2 +- 16 files changed, 623 insertions(+), 555 deletions(-) create mode 100644 apps/probability/calculation_cell.cpp create mode 100644 apps/probability/calculation_cell.h create mode 100644 apps/probability/calculation_type_controller.cpp create mode 100644 apps/probability/calculation_type_controller.h delete mode 100644 apps/probability/calculation_view.cpp delete mode 100644 apps/probability/calculation_view.h create mode 100644 apps/probability/image_cell.cpp create mode 100644 apps/probability/image_cell.h delete mode 100644 apps/probability/image_table_view.cpp delete mode 100644 apps/probability/image_table_view.h create mode 100644 apps/probability/responder_image_cell.cpp create mode 100644 apps/probability/responder_image_cell.h diff --git a/apps/probability/Makefile b/apps/probability/Makefile index 00cb1496f..f352864b4 100644 --- a/apps/probability/Makefile +++ b/apps/probability/Makefile @@ -9,9 +9,10 @@ app_objs += $(addprefix apps/probability/,\ calculation/right_integral_calculation.o\ calculation/finite_integral_calculation.o\ calculation_controller.o\ - calculation_view.o\ + calculation_cell.o\ + calculation_type_controller.o\ cell.o\ - image_table_view.o\ + image_cell.o\ law/binomial_law.o\ law/exponential_law.o\ law/law.o\ @@ -23,6 +24,7 @@ app_objs += $(addprefix apps/probability/,\ law_controller.o\ law_curve_view.o\ parameters_controller.o\ + responder_image_cell.o\ ) i18n_files += $(addprefix apps/probability/,\ diff --git a/apps/probability/calculation_cell.cpp b/apps/probability/calculation_cell.cpp new file mode 100644 index 000000000..71b7f8f03 --- /dev/null +++ b/apps/probability/calculation_cell.cpp @@ -0,0 +1,75 @@ +#include "calculation_cell.h" +#include "responder_image_cell.h" +#include "../i18n.h" +#include + +namespace Probability { + +CalculationCell::CalculationCell(Responder * parentResponder, char * draftTextBuffer, TextFieldDelegate * textFieldDelegate) : + m_text(KDText::FontSize::Large, I18n::Message::Default, 0.5f, 0.5f), + m_calculation(parentResponder, textFieldDelegate, draftTextBuffer), + m_isResponder(true) +{ +} + +Responder * CalculationCell::responder() { + if (m_isResponder) { + return &m_calculation; + } + return nullptr; +} + +void CalculationCell::setResponder(bool shouldBeResponder) { + m_isResponder = shouldBeResponder; +} + +void CalculationCell::setHighlighted(bool highlight) { + HighlightCell::setHighlighted(highlight); + m_calculation.setHighlighted(highlight); +} + +KDSize CalculationCell::minimalSizeForOptimalDisplay() const { + KDSize textSize = m_text.minimalSizeForOptimalDisplay(); + return KDSize(2*k_margin+textSize.width()+calculationCellWidth()+ResponderImageCell::k_outline, KDText::charSize().height()); +} + +void CalculationCell::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect(bounds(), KDColorWhite); + if (m_isResponder) { + KDSize textSize = m_text.minimalSizeForOptimalDisplay(); + ctx->strokeRect(KDRect(2*k_margin+textSize.width()-ResponderImageCell::k_outline, ResponderImageCell::k_margin, calculationCellWidth()+2*ResponderImageCell::k_outline, ImageCell::k_height+2*ResponderImageCell::k_outline), Palette::GreyMiddle); + } +} + +EditableTextCell * CalculationCell::editableTextCell() { + return &m_calculation; +} + +MessageTextView * CalculationCell::messageTextView() { + return &m_text; +} + +int CalculationCell::numberOfSubviews() const { + return 2; +} + +View * CalculationCell::subviewAtIndex(int index) { + assert(index >= 0 && index < 2); + if (index == 0) { + return &m_text; + } + return &m_calculation; +} + +void CalculationCell::layoutSubviews() { + KDSize textSize = m_text.minimalSizeForOptimalDisplay(); + m_text.setFrame(KDRect(k_margin, 0, textSize.width(), bounds().height())); + m_calculation.setFrame(KDRect(2*k_margin+textSize.width(), ResponderImageCell::k_totalMargin, calculationCellWidth(), ImageCell::k_height)); +} + +KDCoordinate CalculationCell::calculationCellWidth() const { + KDCoordinate calculationCellWidth = m_calculation.minimalSizeForOptimalDisplay().width(); + return min(k_maxTextFieldWidth, max(k_minTextFieldWidth, calculationCellWidth)); +} + +} diff --git a/apps/probability/calculation_cell.h b/apps/probability/calculation_cell.h new file mode 100644 index 000000000..37343380f --- /dev/null +++ b/apps/probability/calculation_cell.h @@ -0,0 +1,33 @@ +#ifndef PROBABILITY_CALCULATION_CELL_H +#define PROBABILITY_CALCULATION_CELL_H + +#include + +namespace Probability { + +class CalculationCell : public HighlightCell { +public: + CalculationCell(Responder * parentResponder = nullptr, char * draftTextBuffer = nullptr, TextFieldDelegate * textFieldDelegate = nullptr); + Responder * responder() override; + void setResponder(bool shouldbeResponder); + void setHighlighted(bool highlight) override; + KDSize minimalSizeForOptimalDisplay() const override; + void drawRect(KDContext * ctx, KDRect rect) const override; + EditableTextCell * editableTextCell(); + MessageTextView * messageTextView(); +private: + constexpr static KDCoordinate k_margin = 5; + constexpr static KDCoordinate k_minTextFieldWidth = 4*KDText::charSize().width(); + constexpr static KDCoordinate k_maxTextFieldWidth = 10*KDText::charSize().width(); + int numberOfSubviews() const override; + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + KDCoordinate calculationCellWidth() const; + MessageTextView m_text; + EditableTextCell m_calculation; + bool m_isResponder; +}; + +} + +#endif diff --git a/apps/probability/calculation_controller.cpp b/apps/probability/calculation_controller.cpp index 14adf9f6a..9d972d0df 100644 --- a/apps/probability/calculation_controller.cpp +++ b/apps/probability/calculation_controller.cpp @@ -6,6 +6,14 @@ #include "calculation/left_integral_calculation.h" #include "calculation/right_integral_calculation.h" #include "calculation/finite_integral_calculation.h" +#include "images/calcul1_icon.h" +#include "images/calcul2_icon.h" +#include "images/calcul3_icon.h" +#include "images/calcul4_icon.h" +#include "images/focused_calcul1_icon.h" +#include "images/focused_calcul2_icon.h" +#include "images/focused_calcul3_icon.h" +#include "images/focused_calcul4_icon.h" #include #include @@ -14,9 +22,9 @@ using namespace Shared; namespace Probability { -CalculationController::ContentView::ContentView(Responder * parentResponder, CalculationController * calculationController, Calculation * calculation, Law * law) : +CalculationController::ContentView::ContentView(SelectableTableView * selectableTableView, Law * law, Calculation * calculation) : m_titleView(KDText::FontSize::Small, I18n::Message::ComputeProbability, 0.5f, 0.5f, Palette::GreyDark, Palette::WallScreen), - m_calculationView(parentResponder, calculationController, calculation, law), + m_selectableTableView(selectableTableView), m_lawCurveView(law, calculation) { } @@ -33,25 +41,45 @@ View * CalculationController::ContentView::subviewAtIndex(int index) { if (index == 1) { return &m_lawCurveView; } - return &m_calculationView; + return m_selectableTableView; } void CalculationController::ContentView::layoutSubviews() { KDCoordinate titleHeight = KDText::charSize(KDText::FontSize::Small).height()+k_titleHeightMargin; m_titleView.setFrame(KDRect(0, 0, bounds().width(), titleHeight)); - KDCoordinate calculationHeight = m_calculationView.minimalSizeForOptimalDisplay().height(); - m_calculationView.setFrame(KDRect(0, titleHeight, bounds().width(), bounds().height()-titleHeight)); + KDCoordinate calculationHeight = ResponderImageCell::k_oneCellHeight; + m_selectableTableView->setFrame(KDRect(0, titleHeight, bounds().width(), calculationHeight)); m_lawCurveView.setFrame(KDRect(0, titleHeight+calculationHeight, bounds().width(), bounds().height() - calculationHeight - titleHeight)); } CalculationController::CalculationController(Responder * parentResponder, Law * law, Calculation * calculation) : ViewController(parentResponder), - m_contentView(this, this, calculation, law), + m_contentView(&m_selectableTableView, law, calculation), + m_selectableTableView(this, this, 0, 0, 0, 0, 0, 0, this, nullptr, false, true, KDColorWhite), + m_imageCell(&m_selectableTableView, law, calculation, this), + m_draftTextBuffer{}, m_calculation(calculation), m_law(law) { assert(law != nullptr); assert(calculation != nullptr); + for (int i = 0; i < k_numberOfCalculationCells; i++) { + m_calculationCells[i].editableTextCell()->setParentResponder(&m_selectableTableView); + m_calculationCells[i].editableTextCell()->textField()->setDelegate(this); + m_calculationCells[i].editableTextCell()->textField()->setDraftTextBuffer(m_draftTextBuffer); + } +} + +void CalculationController::didEnterResponderChain(Responder * previousResponder) { + App::Snapshot * snapshot = (App::Snapshot *)app()->snapshot(); + snapshot->setActivePage(App::Snapshot::Page::Calculations); + updateTitle(); + reloadLawCurveView(); + m_selectableTableView.reloadData(); +} + +void CalculationController::didBecomeFirstResponder() { + app()->setFirstResponder(&m_selectableTableView); } View * CalculationController::view() { @@ -62,12 +90,157 @@ const char * CalculationController::title() { return m_titleBuffer; } +void CalculationController::viewWillAppear() { + ViewController::viewWillAppear(); + selectCellAtLocation(1, 0); +} + +void CalculationController::viewDidDisappear() { + m_selectableTableView.deselectTable(); + ViewController::viewDidDisappear(); +} + +int CalculationController::numberOfRows() { + return 1; +} + +int CalculationController::numberOfColumns() { + return m_calculation->numberOfParameters()+1; +} + +KDCoordinate CalculationController::columnWidth(int i) { + if (i == 0) { + return m_imageCell.minimalSizeForOptimalDisplay().width(); + } + return m_calculationCells[i-1].minimalSizeForOptimalDisplay().width(); +} + +KDCoordinate CalculationController::rowHeight(int j) { + return ResponderImageCell::k_oneCellHeight; +} + +KDCoordinate CalculationController::cumulatedWidthFromIndex(int j) { + int result = 0; + for (int k = 0; k < j; k++) { + result += columnWidth(k); + } + return result; +} + +int CalculationController::indexFromCumulatedWidth(KDCoordinate offsetX) { + int result = 0; + int i = 0; + while (result < offsetX && i < numberOfColumns()) { + result += columnWidth(i++); + } + return (result < offsetX || offsetX == 0) ? i : i - 1; +} + +KDCoordinate CalculationController::cumulatedHeightFromIndex(int j) { + return rowHeight(0) * j; +} + +int CalculationController::indexFromCumulatedHeight(KDCoordinate offsetY) { + KDCoordinate height = rowHeight(0); + if (height == 0) { + return 0; + } + return (offsetY - 1) / height; +} + +HighlightCell * CalculationController::reusableCell(int index, int type) { + if (type == 0) { + assert(index == 0); + return &m_imageCell; + } + assert(index >= 0 && index < k_numberOfCalculationCells); + return &m_calculationCells[index]; +} + +int CalculationController::reusableCellCount(int type) { + if (type == 0) { + return 1; + } + return k_numberOfCalculationCells; +} + +int CalculationController::typeAtLocation(int i, int j) { + if (i == 0 && j == 0) { + return 0; + } + return 1; +} + +void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { + if (i == 0) { + ResponderImageCell * myCell = static_cast(cell); + const Image * images[CalculationTypeController::k_numberOfImages] = {ImageStore::Calcul1Icon, ImageStore::Calcul2Icon, ImageStore::Calcul3Icon, ImageStore::Calcul4Icon}; + const Image * focusedImages[CalculationTypeController::k_numberOfImages] = {ImageStore::FocusedCalcul1Icon, ImageStore::FocusedCalcul2Icon, ImageStore::FocusedCalcul3Icon, ImageStore::FocusedCalcul4Icon}; + myCell->setImage(images[(int)m_calculation->type()], focusedImages[(int)m_calculation->type()]); + } else { + CalculationCell * myCell = static_cast(cell); + myCell->messageTextView()->setMessage(m_calculation->legendForParameterAtIndex(i-1)); + bool calculationCellIsResponder = true; + if ((m_law->type() != Law::Type::Normal && i == 3) || (m_calculation->type() == Calculation::Type::Discrete && i == 2)) { + calculationCellIsResponder = false; + } + myCell->setResponder(calculationCellIsResponder); + TextField * field = static_cast(cell)->editableTextCell()->textField(); + if (field->isEditing()) { + return; + } + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Complex::convertFloatToText(m_calculation->parameterAtIndex(i-1), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); + field->setText(buffer); + } +} + +bool CalculationController::textFieldDidHandleEvent(::TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) { + if (returnValue && textHasChanged) { + m_selectableTableView.reloadData(); //TODO: optimize with reloadCell at index? + } + return returnValue; +} + +bool CalculationController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) { + return TextFieldDelegate::textFieldShouldFinishEditing(textField, event) + || (event == Ion::Events::Right && textField->cursorLocation() == textField->draftTextLength() && selectedColumn() < m_calculation->numberOfParameters()) + || (event == Ion::Events::Left && textField->cursorLocation() == 0); +} + +bool CalculationController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { + App * probaApp = (App *)app(); + Context * globalContext = probaApp->container()->globalContext(); + double floatBody = Expression::approximateToScalar(text, *globalContext); + if (std::isnan(floatBody) || std::isinf(floatBody)) { + app()->displayWarning(I18n::Message::UndefinedValue); + return false; + } + if (m_calculation->type() != Calculation::Type::FiniteIntegral && selectedColumn() == 2) { + if (floatBody < 0.0) { + floatBody = 0.0; + } + if (floatBody > 1.0) { + floatBody = 1.0; + } + } + if (!m_law->isContinuous() && (selectedColumn() == 1 || m_calculation->type() == Calculation::Type::FiniteIntegral)) { + floatBody = std::round(floatBody); + } + m_calculation->setParameterAtIndex(floatBody, selectedColumn()-1); + if (event == Ion::Events::Right || event == Ion::Events::Left) { + m_selectableTableView.handleEvent(event); + } + reload(); + return true; +} + void CalculationController::reloadLawCurveView() { m_contentView.lawCurveView()->reload(); } void CalculationController::reload() { - m_contentView.calculationView()->reload(); + m_selectableTableView.reloadData(); reloadLawCurveView(); } @@ -93,22 +266,10 @@ void CalculationController::setCalculationAccordingToIndex(int index, bool force return; } m_calculation->setLaw(m_law); - reload(); } -void CalculationController::viewWillAppear() { - reloadLawCurveView(); - m_contentView.calculationView()->selectSubview(1); -} - -void CalculationController::didEnterResponderChain(Responder * previousResponder) { - App::Snapshot * snapshot = (App::Snapshot *)app()->snapshot(); - snapshot->setActivePage(App::Snapshot::Page::Calculations); - updateTitle(); -} - -void CalculationController::didBecomeFirstResponder() { - app()->setFirstResponder(m_contentView.calculationView()); +TextFieldDelegateApp * CalculationController::textFieldDelegateApp() { + return (App *)app(); } void CalculationController::updateTitle() { diff --git a/apps/probability/calculation_controller.h b/apps/probability/calculation_controller.h index 73dd02b63..89ba34911 100644 --- a/apps/probability/calculation_controller.h +++ b/apps/probability/calculation_controller.h @@ -4,44 +4,72 @@ #include #include "law/law.h" #include "law_curve_view.h" -#include "calculation_view.h" +#include "calculation_cell.h" +#include "responder_image_cell.h" #include "calculation/calculation.h" #include "../shared/parameter_text_field_delegate.h" namespace Probability { -class CalculationController : public ViewController { +class CalculationController : public ViewController, public TableViewDataSource, public SelectableTableViewDataSource, public Shared::ParameterTextFieldDelegate { public: CalculationController(Responder * parentResponder, Law * law, Calculation * calculation); - View * view() override; - const char * title() override; - void reload(); - void reloadLawCurveView(); - void setCalculationAccordingToIndex(int index, bool forceReinitialisation = false); - void viewWillAppear() override; + /* Responder */ void didEnterResponderChain(Responder * previousResponder) override; void didBecomeFirstResponder() override; + + /* ViewController */ + View * view() override; + const char * title() override; + void viewWillAppear() override; + void viewDidDisappear() override; + + /* TableViewDataSource */ + int numberOfRows() override; + int numberOfColumns() 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; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + int typeAtLocation(int i, int j) override; + void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; + + /* TextField delegate */ + bool textFieldDidHandleEvent(TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) override; + bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; + bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; + + void reloadLawCurveView(); + void reload(); + void setCalculationAccordingToIndex(int index, bool forceReinitialisation = false); private: + constexpr static int k_numberOfCalculationCells = 3; + Shared::TextFieldDelegateApp * textFieldDelegateApp() override; void updateTitle(); class ContentView : public View { public: - ContentView(Responder * parentResponder, CalculationController * calculationController, Calculation * Calculation, Law * law); + ContentView(SelectableTableView * selectableTableView, Law * law, Calculation * calculation); LawCurveView * lawCurveView() { return &m_lawCurveView; } - CalculationView * calculationView() { - return &m_calculationView; - } private: constexpr static KDCoordinate k_titleHeightMargin = 5; int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews() override; MessageTextView m_titleView; - CalculationView m_calculationView; + SelectableTableView * m_selectableTableView; LawCurveView m_lawCurveView; }; ContentView m_contentView; + SelectableTableView m_selectableTableView; + ResponderImageCell m_imageCell; + char m_draftTextBuffer[TextField::maxBufferSize()]; + CalculationCell m_calculationCells[k_numberOfCalculationCells]; Calculation * m_calculation; Law * m_law; constexpr static int k_maxNumberOfTitleCharacters = 30; diff --git a/apps/probability/calculation_type_controller.cpp b/apps/probability/calculation_type_controller.cpp new file mode 100644 index 000000000..7a39294ca --- /dev/null +++ b/apps/probability/calculation_type_controller.cpp @@ -0,0 +1,91 @@ +#include "calculation_type_controller.h" +#include +#include "app.h" +#include "images/calcul1_icon.h" +#include "images/calcul2_icon.h" +#include "images/calcul3_icon.h" +#include "images/calcul4_icon.h" +#include "images/focused_calcul1_icon.h" +#include "images/focused_calcul2_icon.h" +#include "images/focused_calcul3_icon.h" +#include "images/focused_calcul4_icon.h" + +namespace Probability { + +CalculationTypeController::CalculationTypeController(Responder * parentResponder, Law * law, Calculation * calculation, CalculationController * calculationController) : + ViewController(parentResponder), + m_selectableTableView(this, this, 0, 0, 0, 0, 0, 0, this, nullptr, false, false), + m_law(law), + m_calculation(calculation), + m_calculationController(calculationController) +{ + assert(m_calculation != nullptr); +} + +View * CalculationTypeController::view() { + return &m_selectableTableView; +} + +void CalculationTypeController::viewWillAppear() { + selectCellAtLocation(0, (int)m_calculation->type()); +} + + +void CalculationTypeController::viewDidDisappear() { + m_selectableTableView.deselectTable(); +} + +void CalculationTypeController::didBecomeFirstResponder() { + app()->setFirstResponder(&m_selectableTableView); +} + +bool CalculationTypeController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + m_calculationController->setCalculationAccordingToIndex(selectedRow()); + m_calculationController->reload(); + app()->dismissModalViewController(); + return true; + } + if (event == Ion::Events::Back || event == Ion::Events::Right) { + if (event == Ion::Events::Right) { + m_calculationController->selectCellAtLocation(1,0); + } + app()->dismissModalViewController(); + return true; + } + return false; +} + +int CalculationTypeController::numberOfRows() { + if (m_law->isContinuous()) { + return k_numberOfImages-1; + } + return k_numberOfImages; +} + +KDCoordinate CalculationTypeController::cellWidth() { + return ImageCell::k_width; +} + +KDCoordinate CalculationTypeController::cellHeight() { + return ImageCell::k_height; +} + +HighlightCell * CalculationTypeController::reusableCell(int index) { + assert(index >= 0); + assert(index < k_numberOfImages); + return &m_imageCells[index]; +} + +int CalculationTypeController::reusableCellCount() { + return k_numberOfImages; +} + +void CalculationTypeController::willDisplayCellForIndex(HighlightCell * cell, int index) { + ImageCell * myCell = (ImageCell *)cell; + const Image * images[k_numberOfImages] = {ImageStore::Calcul1Icon, ImageStore::Calcul2Icon, ImageStore::Calcul3Icon, ImageStore::Calcul4Icon}; + const Image * focusedImages[k_numberOfImages] = {ImageStore::FocusedCalcul1Icon, ImageStore::FocusedCalcul2Icon, ImageStore::FocusedCalcul3Icon, ImageStore::FocusedCalcul4Icon}; + myCell->setImage(images[index], focusedImages[index]); +} + +} diff --git a/apps/probability/calculation_type_controller.h b/apps/probability/calculation_type_controller.h new file mode 100644 index 000000000..440a7d3f8 --- /dev/null +++ b/apps/probability/calculation_type_controller.h @@ -0,0 +1,38 @@ +#ifndef PROBABILITY_CALCULATION_TYPE_CONTROLLER_H +#define PROBABILITY_CALCULATION_TYPE_CONTROLLER_H + +#include +#include "calculation/calculation.h" +#include "law/law.h" +#include "image_cell.h" + +namespace Probability { + +class CalculationController; + +class CalculationTypeController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource { +public: + CalculationTypeController(Responder * parentResponder, Law * law, Calculation * calculation, CalculationController * calculationController); + View * view() override; + void viewWillAppear() override; + void viewDidDisappear() override; + void didBecomeFirstResponder() override; + bool handleEvent(Ion::Events::Event event) override; + int numberOfRows() override; + KDCoordinate cellWidth() override; + KDCoordinate cellHeight() override; + HighlightCell * reusableCell(int index) override; + int reusableCellCount() override; + void willDisplayCellForIndex(HighlightCell * cell, int index) override; + constexpr static int k_numberOfImages = 4; +private: + ImageCell m_imageCells[k_numberOfImages]; + SelectableTableView m_selectableTableView; + Law * m_law; + Calculation * m_calculation; + CalculationController * m_calculationController; +}; + +} + +#endif diff --git a/apps/probability/calculation_view.cpp b/apps/probability/calculation_view.cpp deleted file mode 100644 index 4dec63b46..000000000 --- a/apps/probability/calculation_view.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include "calculation_view.h" -#include "app.h" -#include "../apps_container.h" -#include "calculation_controller.h" -#include - -using namespace Poincare; -using namespace Shared; - -namespace Probability { - -CalculationView::CalculationView(Responder * parentResponder, CalculationController * calculationController, Calculation * calculation, Law * law) : - Responder(parentResponder), - m_imageTableView(this, law, calculation, calculationController), - m_draftTextBuffer{}, - m_law(law), - m_calculation(calculation), - m_highlightedSubviewIndex(1), - m_calculationController(calculationController) -{ - for (int i = 0; i < k_maxNumberOfEditableFields; i++) { - m_calculationCell[i].setParentResponder(this); - m_calculationCell[i].textField()->setDelegate(this); - m_calculationCell[i].textField()->setDraftTextBuffer(m_draftTextBuffer); - m_text[i].setAlignment(0.5f, 0.5f); - } -} - -void CalculationView::didBecomeFirstResponder() { - if (m_highlightedSubviewIndex > 0) { - app()->setFirstResponder(&m_calculationCell[m_highlightedSubviewIndex-1]); - } else { - app()->setFirstResponder(&m_imageTableView); - } -} - -bool CalculationView::handleEvent(Ion::Events::Event event) { - if ((event == Ion::Events::Left && m_highlightedSubviewIndex > 0) || (event == Ion::Events::Right && m_highlightedSubviewIndex < m_calculation->numberOfEditableParameters())) { - if (m_highlightedSubviewIndex == 0) { - m_imageTableView.select(false); - } else { - m_calculationCell[m_highlightedSubviewIndex-1].setHighlighted(false); - } - m_highlightedSubviewIndex = event == Ion::Events::Left ? m_highlightedSubviewIndex - 1 : m_highlightedSubviewIndex + 1; - if (m_highlightedSubviewIndex > 0) { - m_calculationCell[m_highlightedSubviewIndex-1].setHighlighted(true); - app()->setFirstResponder(&m_calculationCell[m_highlightedSubviewIndex-1]); - } else { - app()->setFirstResponder(&m_imageTableView); - } - return true; - } - return false; -} - -void CalculationView::selectSubview(int subviewIndex) { - m_highlightedSubviewIndex = subviewIndex; -} - -bool CalculationView::textFieldDidHandleEvent(::TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) { - if (returnValue && textHasChanged) { - updateCalculationLayoutFromIndex(m_highlightedSubviewIndex-1); - } - return returnValue; -} - -bool CalculationView::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) { - return TextFieldDelegate::textFieldShouldFinishEditing(textField, event) - || (event == Ion::Events::Right && textField->cursorLocation() == textField->draftTextLength() && m_highlightedSubviewIndex < m_calculation->numberOfEditableParameters()) - || (event == Ion::Events::Left && textField->cursorLocation() == 0); -} - -bool CalculationView::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { - App * probaApp = (App *)app(); - Context * globalContext = probaApp->container()->globalContext(); - double floatBody = Expression::approximateToScalar(text, *globalContext); - if (std::isnan(floatBody) || std::isinf(floatBody)) { - app()->displayWarning(I18n::Message::UndefinedValue); - return false; - } - if (m_calculation->type() != Calculation::Type::FiniteIntegral && m_highlightedSubviewIndex == 2) { - if (floatBody < 0.0) { - floatBody = 0.0; - } - if (floatBody > 1.0) { - floatBody = 1.0; - } - } - if (!m_law->isContinuous() && (m_highlightedSubviewIndex == 1 || m_calculation->type() == Calculation::Type::FiniteIntegral)) { - floatBody = std::round(floatBody); - } - m_calculation->setParameterAtIndex(floatBody, m_highlightedSubviewIndex-1); - if (event == Ion::Events::Right || event == Ion::Events::Left) { - handleEvent(event); - } - reloadData(); - updateCalculationLayoutFromIndex(0); - m_calculationController->reloadLawCurveView(); - return true; -} - -void CalculationView::reload() { - markRectAsDirty(bounds()); - layoutSubviews(); -} - -void CalculationView::drawRect(KDContext * ctx, KDRect rect) const { - ctx->fillRect(KDRect(0,0, bounds().width(), ImageTableView::k_oneCellHeight), KDColorWhite); - KDSize charSize = KDText::charSize(); - int numberOfCharacters; - KDCoordinate xCoordinate = ImageTableView::k_oneCellWidth + k_textWidthMargin; - for (int i = 0; i < k_maxNumberOfEditableFields; i++) { - if (m_calculation->numberOfEditableParameters() == i) { - return; - } - numberOfCharacters = strlen(I18n::translate(m_calculation->legendForParameterAtIndex(i))); - xCoordinate += numberOfCharacters*charSize.width() + k_textWidthMargin; - - ctx->strokeRect(KDRect(xCoordinate-ImageTableView::k_outline, ImageTableView::k_margin, calculationCellWidth(i)+2*ImageTableView::k_outline, ImageCell::k_height+2*ImageTableView::k_outline), Palette::GreyMiddle); - xCoordinate += calculationCellWidth(i) + k_textWidthMargin; - } -} - -void CalculationView::willDisplayEditableCellAtIndex(int index) { - m_calculationCell[index].setHighlighted(index == m_highlightedSubviewIndex-1); - char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(m_calculation->parameterAtIndex(index), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); - m_calculationCell[index].textField()->setText(buffer); -} - -KDSize CalculationView::minimalSizeForOptimalDisplay() const { - //xCoordinate += tableSize.width() + k_textWidthMargin; - return KDSize(0, ImageTableView::k_oneCellHeight); -} - -TextFieldDelegateApp * CalculationView::textFieldDelegateApp() { - return (App *)app(); -} - -void CalculationView::updateCalculationLayoutFromIndex(int index) { - KDSize charSize = KDText::charSize(); - KDCoordinate numberOfCharacters = strlen(I18n::translate(m_calculation->legendForParameterAtIndex(0))); - KDCoordinate xCoordinate = m_imageTableView.minimalSizeForOptimalDisplay().width() + 2*k_textWidthMargin+numberOfCharacters*charSize.width(); - KDCoordinate calculationWidth = calculationCellWidth(0); - if (index == 0) { - markRectAsDirty(KDRect(xCoordinate, ImageTableView::k_totalMargin-1, bounds().width() - xCoordinate, ImageCell::k_height+2)); - m_calculationCell[0].setFrame(KDRect(xCoordinate, ImageTableView::k_totalMargin, calculationWidth, ImageCell::k_height)); - } - - xCoordinate += calculationWidth + k_textWidthMargin; - numberOfCharacters = strlen(I18n::translate(m_calculation->legendForParameterAtIndex(1))); - if (index == 0) { - m_text[1].setFrame(KDRect(xCoordinate, ImageTableView::k_totalMargin, numberOfCharacters*charSize.width(), ImageCell::k_height)); - } - xCoordinate += numberOfCharacters*charSize.width() + k_textWidthMargin; - calculationWidth = calculationCellWidth(1); - if (index <= 1) { - markRectAsDirty(KDRect(xCoordinate, ImageTableView::k_totalMargin-1, bounds().width() - xCoordinate, ImageCell::k_height+2)); - m_calculationCell[1].setFrame(KDRect(xCoordinate, ImageTableView::k_totalMargin, calculationWidth, ImageCell::k_height)); - } - xCoordinate += calculationWidth + k_textWidthMargin; - if (m_calculation->numberOfParameters() > 2) { - numberOfCharacters = strlen(I18n::translate(m_calculation->legendForParameterAtIndex(2)));; - m_text[2].setFrame(KDRect(xCoordinate, ImageTableView::k_totalMargin, numberOfCharacters*charSize.width(), ImageCell::k_height)); - xCoordinate += numberOfCharacters*charSize.width() + k_textWidthMargin; - calculationWidth = calculationCellWidth(2); - markRectAsDirty(KDRect(xCoordinate, ImageTableView::k_totalMargin-1, bounds().width() - xCoordinate, ImageCell::k_height+2)); - m_calculationCell[2].setFrame(KDRect(xCoordinate, ImageTableView::k_totalMargin, calculationWidth, ImageCell::k_height)); - } -} - -void CalculationView::reloadData() { - for (int k = 0; k < m_calculation->numberOfParameters(); k++) { - willDisplayEditableCellAtIndex(k); - } -} - -int CalculationView::numberOfSubviews() const { - return 2*m_calculation->numberOfParameters() + 1; -} - -View * CalculationView::subviewAtIndex(int index) { - assert(index >= 0 && index < 7); - if (index == 0) { - return &m_imageTableView; - } - if (index == 1) { - m_text[0].setMessage(m_calculation->legendForParameterAtIndex(0)); - m_text[0].setAlignment(0.5f, 0.5f); - return &m_text[0]; - } - if (index == 3) { - m_text[1].setMessage(m_calculation->legendForParameterAtIndex(1)); - m_text[1].setAlignment(0.5f, 0.5f); - return &m_text[1]; - } - if (index == 5) { - m_text[2].setMessage(m_calculation->legendForParameterAtIndex(2)); - m_text[2].setAlignment(0.5f, 0.5f); - return &m_text[2]; - } - if (index == 2 || index == 4 || index == 6) { - return &m_calculationCell[(index - 2)/2]; - } - return nullptr; -} - -void CalculationView::layoutSubviews() { - // Reload values in textFields - reloadData(); - // Reload messages - m_text[0].setMessage(m_calculation->legendForParameterAtIndex(0)); - m_text[1].setMessage(m_calculation->legendForParameterAtIndex(1)); - if (m_calculation->numberOfParameters() == 3) { - m_text[2].setMessage(m_calculation->legendForParameterAtIndex(2)); - } - // Layout - KDSize charSize = KDText::charSize(); - KDCoordinate xCoordinate = 0; - KDSize tableSize = m_imageTableView.minimalSizeForOptimalDisplay(); - m_imageTableView.setFrame(KDRect(xCoordinate, 0, tableSize)); - xCoordinate += tableSize.width() + k_textWidthMargin; - KDCoordinate numberOfCharacters = strlen(I18n::translate(m_calculation->legendForParameterAtIndex(0))); - m_text[0].setFrame(KDRect(xCoordinate, ImageTableView::k_totalMargin, numberOfCharacters*charSize.width(), ImageCell::k_height)); - - updateCalculationLayoutFromIndex(0); -} - -KDCoordinate CalculationView::calculationCellWidth(int index) const { - KDCoordinate calculationCellWidth = m_calculationCell[index].minimalSizeForOptimalDisplay().width(); - return min(k_maxTextFieldWidth, max(k_minTextFieldWidth, calculationCellWidth)); -} - -} diff --git a/apps/probability/calculation_view.h b/apps/probability/calculation_view.h deleted file mode 100644 index e7bfb957e..000000000 --- a/apps/probability/calculation_view.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef PROBABILITY_CALCULATION_VIEW_H -#define PROBABILITY_CALCULATION_VIEW_H - -#include -#include "law/law.h" -#include "image_table_view.h" -#include "calculation/calculation.h" -#include "../shared/parameter_text_field_delegate.h" - -namespace Probability { - -class CalculationController; - -class CalculationView : public View, public Responder, public Shared::ParameterTextFieldDelegate { -public: - CalculationView(Responder * parentResponder, CalculationController * calculationController, Calculation * Calculation, Law * law); - /* Responder */ - void didBecomeFirstResponder() override; - bool handleEvent(Ion::Events::Event event) override; - void selectSubview(int subviewIndex); - - /* TextField delegate */ - bool textFieldDidHandleEvent(TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) override; - bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override; - bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; - - /* View */ - void reload(); - void drawRect(KDContext * ctx, KDRect rect) const override; - void willDisplayEditableCellAtIndex(int index); - KDSize minimalSizeForOptimalDisplay() const override; - constexpr static int k_maxNumberOfEditableFields = 3; -private: - constexpr static KDCoordinate k_minTextFieldWidth = 4*KDText::charSize().width(); - constexpr static KDCoordinate k_maxTextFieldWidth = 10*KDText::charSize().width(); - constexpr static KDCoordinate k_textWidthMargin = 5; - Shared::TextFieldDelegateApp * textFieldDelegateApp() override; - void updateCalculationLayoutFromIndex(int index); - void reloadData(); - int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; - KDCoordinate calculationCellWidth(int index) const; - ImageTableView m_imageTableView; - MessageTextView m_text[k_maxNumberOfEditableFields]; - char m_draftTextBuffer[TextField::maxBufferSize()]; - EditableTextCell m_calculationCell[k_maxNumberOfEditableFields]; - Law * m_law; - Calculation * m_calculation; - int m_highlightedSubviewIndex; - CalculationController * m_calculationController; -}; - -/*class ScrollableCalculationView : public ScrollableView, public ScrollView -}*/ -} - -#endif diff --git a/apps/probability/image_cell.cpp b/apps/probability/image_cell.cpp new file mode 100644 index 000000000..dae9db792 --- /dev/null +++ b/apps/probability/image_cell.cpp @@ -0,0 +1,42 @@ +#include "image_cell.h" +#include + +namespace Probability { + +ImageCell::ImageCell() : + HighlightCell(), + m_icon(nullptr), + m_focusedIcon(nullptr) +{ +} + +void ImageCell::setHighlighted(bool highlight) { + HighlightCell::setHighlighted(highlight); + if (isHighlighted()) { + m_iconView.setImage(m_focusedIcon); + } else { + m_iconView.setImage(m_icon); + } +} + +void ImageCell::setImage(const Image * image, const Image * focusedImage) { + m_icon = image; + m_focusedIcon = focusedImage; + setHighlighted(isHighlighted()); + markRectAsDirty(bounds()); +} + +int ImageCell::numberOfSubviews() const { + return 1; +} + +View * ImageCell::subviewAtIndex(int index) { + assert(index == 0); + return &m_iconView; +} + +void ImageCell::layoutSubviews() { + m_iconView.setFrame(bounds()); +} + +} diff --git a/apps/probability/image_cell.h b/apps/probability/image_cell.h new file mode 100644 index 000000000..bb65869c4 --- /dev/null +++ b/apps/probability/image_cell.h @@ -0,0 +1,26 @@ +#ifndef PROBABILITY_IMAGE_CELL_H +#define PROBABILITY_IMAGE_CELL_H + +#include + +namespace Probability { + +class ImageCell : public HighlightCell { +public: + ImageCell(); + void setHighlighted(bool highlight) override; + void setImage(const Image * image, const Image * focusedImage); + constexpr static KDCoordinate k_width = 39; + constexpr static KDCoordinate k_height = 23; +private: + int numberOfSubviews() const override; + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + ImageView m_iconView; + const Image * m_icon; + const Image * m_focusedIcon; +}; + +} + +#endif diff --git a/apps/probability/image_table_view.cpp b/apps/probability/image_table_view.cpp deleted file mode 100644 index 379f4d627..000000000 --- a/apps/probability/image_table_view.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include "image_table_view.h" -#include -#include "app.h" -#include "images/calcul1_icon.h" -#include "images/calcul2_icon.h" -#include "images/calcul3_icon.h" -#include "images/calcul4_icon.h" -#include "images/focused_calcul1_icon.h" -#include "images/focused_calcul2_icon.h" -#include "images/focused_calcul3_icon.h" -#include "images/focused_calcul4_icon.h" - -namespace Probability { - -ImageCell::ImageCell() : - HighlightCell(), - m_icon(nullptr), - m_focusedIcon(nullptr) -{ -} - -int ImageCell::numberOfSubviews() const { - return 1; -} - -View * ImageCell::subviewAtIndex(int index) { - assert(index == 0); - return &m_iconView; -} - -void ImageCell::layoutSubviews() { - m_iconView.setFrame(bounds()); -} - -void ImageCell::reloadCell() { - HighlightCell::reloadCell(); - if (isHighlighted()) { - m_iconView.setImage(m_focusedIcon); - } else { - m_iconView.setImage(m_icon); - } -} - -void ImageCell::setImage(const Image * image, const Image * focusedImage) { - m_icon = image; - m_focusedIcon = focusedImage; -} - -ImageTableView::ImageTableView(Responder * parentResponder, Law * law, Calculation * calculation, CalculationController * calculationController) : - View(), - Responder(parentResponder), - m_selectableTableView(this, this, 0, 0, 0, 0, 0, 0, this, nullptr, false, false), - m_isSelected(false), - m_law(law), - m_calculation(calculation), - m_calculationController(calculationController) -{ - assert(m_calculation != nullptr); -} - -void ImageTableView::drawRect(KDContext * ctx, KDRect rect) const { - ctx->strokeRect(KDRect(k_margin, k_margin, ImageCell::k_width+2*k_outline, ImageCell::k_height+2*k_outline), Palette::GreyMiddle); -} - -KDSize ImageTableView::minimalSizeForOptimalDisplay() const { - return KDSize(2*k_totalMargin+ImageCell::k_width, k_totalMargin+k_numberOfImages*ImageCell::k_height); -} - -void ImageTableView::didBecomeFirstResponder() { - m_selectableTableView.reloadData(); - app()->setFirstResponder(&m_selectableTableView); -} - -void ImageTableView::didEnterResponderChain(Responder * previousFirstResponder) { - selectCellAtLocation(0, 0); -} - -void ImageTableView::willExitResponderChain(Responder * nextFirstResponder) { - m_selectableTableView.deselectTable(); -} - -bool ImageTableView::handleEvent(Ion::Events::Event event) { - if ((event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Down) && !m_isSelected) { - select(true); - return true; - } - if ((event == Ion::Events::OK || event == Ion::Events::EXE) && m_isSelected) { - m_calculationController->setCalculationAccordingToIndex(selectedRow()); - select(false); - return true; - } - if (event == Ion::Events::Back) { - select(false); - return true; - } - return false; -} - -void ImageTableView::select(bool select) { - if (!select) { - m_selectableTableView.deselectTable(); - m_isSelected = select; - m_selectableTableView.reloadData(); - /* The dropdown menu is drawn on the law curve view, so when we deselect - * the dropdown menu, we need to redraw the law curve view */ - m_calculationController->reload(); - m_selectableTableView.selectCellAtLocation(0, 0); - } else { - m_isSelected = select; - m_selectableTableView.reloadData(); - m_selectableTableView.selectCellAtLocation(0, (int)m_calculation->type()); - } -} - -int ImageTableView::numberOfRows() { - if (m_isSelected) { - if (m_law->isContinuous()) { - return k_numberOfImages-1; - } - return k_numberOfImages; - } - return 1; -} - -KDCoordinate ImageTableView::cellHeight() { - return ImageCell::k_height; -} - -HighlightCell * ImageTableView::reusableCell(int index) { - assert(index >= 0); - assert(index < k_numberOfImages); - return &m_imageCells[index]; -} - -int ImageTableView::reusableCellCount() { - return k_numberOfImages; -} - -void ImageTableView::willDisplayCellForIndex(HighlightCell * cell, int index) { - ImageCell * myCell = (ImageCell *)cell; - const Image * images[k_numberOfImages] = {ImageStore::Calcul1Icon, ImageStore::Calcul2Icon, ImageStore::Calcul3Icon, ImageStore::Calcul4Icon}; - const Image * focusedImages[k_numberOfImages] = {ImageStore::FocusedCalcul1Icon, ImageStore::FocusedCalcul2Icon, ImageStore::FocusedCalcul3Icon, ImageStore::FocusedCalcul4Icon}; - if (!m_isSelected) { - myCell->setImage(images[(int)m_calculation->type()], focusedImages[(int)m_calculation->type()]); - } else { - myCell->setImage(images[index], focusedImages[index]); - } - myCell->reloadCell(); -} - -int ImageTableView::numberOfSubviews() const { - return 1; -} - -View * ImageTableView::subviewAtIndex(int index) { - assert(index == 0); - return &m_selectableTableView; -} - -void ImageTableView::layoutSubviews() { - m_selectableTableView.setFrame(KDRect(k_totalMargin, k_totalMargin, bounds().width()-2*k_totalMargin, bounds().height()-k_totalMargin)); -} - -} diff --git a/apps/probability/image_table_view.h b/apps/probability/image_table_view.h deleted file mode 100644 index 1b303e5d4..000000000 --- a/apps/probability/image_table_view.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef PROBABILITY_IMAGE_TABLE_VIEW_H -#define PROBABILITY_IMAGE_TABLE_VIEW_H - -#include -#include "calculation/calculation.h" - -namespace Probability { - -class CalculationController; - -class ImageCell : public HighlightCell { -public: - ImageCell(); - void reloadCell() override; - void setImage(const Image * image, const Image * focusedImage); - constexpr static KDCoordinate k_width = 39; - constexpr static KDCoordinate k_height = 23; -private: - int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; - ImageView m_iconView; - const Image * m_icon; - const Image * m_focusedIcon; -}; - -class ImageTableView : public View, public Responder, public SimpleListViewDataSource, public SelectableTableViewDataSource { -public: - ImageTableView(Responder * parentResponder, Law * law, Calculation * calculation, CalculationController * calculationController); - void drawRect(KDContext * ctx, KDRect rect) const override; - KDSize minimalSizeForOptimalDisplay() const override; - void didBecomeFirstResponder() override; - void didEnterResponderChain(Responder * previousFirstResponder) override; - void willExitResponderChain(Responder * nextFirstResponder) override; - bool handleEvent(Ion::Events::Event event) override; - void select(bool select); - int numberOfRows() override; - KDCoordinate cellHeight() override; - HighlightCell * reusableCell(int index) override; - int reusableCellCount() override; - void willDisplayCellForIndex(HighlightCell * cell, int index) override; - constexpr static KDCoordinate k_outline = 1; - constexpr static KDCoordinate k_margin = 3; - constexpr static KDCoordinate k_totalMargin = k_outline+k_margin; - constexpr static KDCoordinate k_oneCellWidth = 2*k_totalMargin+ImageCell::k_width; - constexpr static KDCoordinate k_oneCellHeight = 2*k_totalMargin+ImageCell::k_height; -private: - int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; - constexpr static int k_numberOfImages = 4; - ImageCell m_imageCells[k_numberOfImages]; - SelectableTableView m_selectableTableView; - bool m_isSelected; - Law * m_law; - Calculation * m_calculation; - CalculationController * m_calculationController; -}; - -} - -#endif diff --git a/apps/probability/responder_image_cell.cpp b/apps/probability/responder_image_cell.cpp new file mode 100644 index 000000000..5d84e50a0 --- /dev/null +++ b/apps/probability/responder_image_cell.cpp @@ -0,0 +1,53 @@ +#include "responder_image_cell.h" +#include + +namespace Probability { + +ResponderImageCell::ResponderImageCell(Responder * parentResponder, Law * law, Calculation * calculation, CalculationController * calculationController) : + HighlightCell(), + Responder(parentResponder), + m_calculationTypeController(nullptr, law, calculation, calculationController) +{ +} + +void ResponderImageCell::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect(bounds(), KDColorWhite); + ctx->strokeRect(KDRect(k_margin, k_margin, ImageCell::k_width+2*k_outline, ImageCell::k_height+2*k_outline), Palette::GreyMiddle); +} + +KDSize ResponderImageCell::minimalSizeForOptimalDisplay() const { + return KDSize(2*k_totalMargin+ImageCell::k_width, 2*k_totalMargin*ImageCell::k_height); +} + +bool ResponderImageCell::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Down) { + KDPoint topLeftAngle = app()->modalView()->pointFromPointInView(this, KDPoint(k_totalMargin, k_totalMargin)); + app()->displayModalViewController(&m_calculationTypeController, 0.0f, 0.0f, topLeftAngle.y(), topLeftAngle.x()); + return true; + } + return false; +} + +void ResponderImageCell::setHighlighted(bool highlight) { + HighlightCell::setHighlighted(highlight); + m_imageCell.setHighlighted(highlight); +} + +void ResponderImageCell::setImage(const Image * image, const Image * focusedImage) { + m_imageCell.setImage(image, focusedImage); +} + +int ResponderImageCell::numberOfSubviews() const { + return 1; +} + +View * ResponderImageCell::subviewAtIndex(int index) { + assert(index == 0); + return &m_imageCell; +} + +void ResponderImageCell::layoutSubviews() { + m_imageCell.setFrame(KDRect(k_totalMargin, k_totalMargin, bounds().width()-2*k_totalMargin, bounds().height()-2*k_totalMargin)); +} + +} diff --git a/apps/probability/responder_image_cell.h b/apps/probability/responder_image_cell.h new file mode 100644 index 000000000..0d59ea6eb --- /dev/null +++ b/apps/probability/responder_image_cell.h @@ -0,0 +1,37 @@ +#ifndef PROBABILITY_RESPONDER_IMAGE_CELL_H +#define PROBABILITY_RESPONDER_IMAGE_CELL_H + +#include +#include "calculation/calculation.h" +#include "calculation_type_controller.h" +#include "image_cell.h" + +namespace Probability { + +class ResponderImageCell : public HighlightCell, public Responder { +public: + ResponderImageCell(Responder * parentResponder, Law * law, Calculation * calculation, CalculationController * calculationController); + Responder * responder() override { + return this; + } + void drawRect(KDContext * ctx, KDRect rect) const override; + KDSize minimalSizeForOptimalDisplay() const override; + bool handleEvent(Ion::Events::Event event) override; + void setHighlighted(bool highlight) override; + void setImage(const Image * image, const Image * focusedImage); + constexpr static KDCoordinate k_outline = 1; + constexpr static KDCoordinate k_margin = 3; + constexpr static KDCoordinate k_totalMargin = k_outline+k_margin; + constexpr static KDCoordinate k_oneCellWidth = 2*k_totalMargin+ImageCell::k_width; + constexpr static KDCoordinate k_oneCellHeight = 2*k_totalMargin+ImageCell::k_height; +private: + int numberOfSubviews() const override; + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + ImageCell m_imageCell; + CalculationTypeController m_calculationTypeController; +}; + +} + +#endif diff --git a/escher/include/escher/list_view_data_source.h b/escher/include/escher/list_view_data_source.h index 0a8feba3c..f2c5a174d 100644 --- a/escher/include/escher/list_view_data_source.h +++ b/escher/include/escher/list_view_data_source.h @@ -6,7 +6,7 @@ class ListViewDataSource : public TableViewDataSource { public: - KDCoordinate cellWidth(); + virtual KDCoordinate cellWidth(); KDCoordinate columnWidth(int i) override; int numberOfColumns() override; void willDisplayCellAtLocation(HighlightCell * cell, int x, int y) override;