mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-19 22:00:28 +01:00
[apps] Redesign Probability Calculation page
This commit is contained in:
committed by
EmilieNumworks
parent
e8793c429c
commit
fd06d428e5
@@ -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/,\
|
||||
|
||||
75
apps/probability/calculation_cell.cpp
Normal file
75
apps/probability/calculation_cell.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "calculation_cell.h"
|
||||
#include "responder_image_cell.h"
|
||||
#include "../i18n.h"
|
||||
#include <assert.h>
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
33
apps/probability/calculation_cell.h
Normal file
33
apps/probability/calculation_cell.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef PROBABILITY_CALCULATION_CELL_H
|
||||
#define PROBABILITY_CALCULATION_CELL_H
|
||||
|
||||
#include <escher.h>
|
||||
|
||||
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
|
||||
@@ -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 <assert.h>
|
||||
#include <cmath>
|
||||
|
||||
@@ -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<ResponderImageCell *>(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<CalculationCell *>(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<CalculationCell *>(cell)->editableTextCell()->textField();
|
||||
if (field->isEditing()) {
|
||||
return;
|
||||
}
|
||||
char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
|
||||
Complex<double>::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<double>(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() {
|
||||
|
||||
@@ -4,44 +4,72 @@
|
||||
#include <escher.h>
|
||||
#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;
|
||||
|
||||
91
apps/probability/calculation_type_controller.cpp
Normal file
91
apps/probability/calculation_type_controller.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#include "calculation_type_controller.h"
|
||||
#include <assert.h>
|
||||
#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]);
|
||||
}
|
||||
|
||||
}
|
||||
38
apps/probability/calculation_type_controller.h
Normal file
38
apps/probability/calculation_type_controller.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef PROBABILITY_CALCULATION_TYPE_CONTROLLER_H
|
||||
#define PROBABILITY_CALCULATION_TYPE_CONTROLLER_H
|
||||
|
||||
#include <escher.h>
|
||||
#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
|
||||
@@ -1,234 +0,0 @@
|
||||
#include "calculation_view.h"
|
||||
#include "app.h"
|
||||
#include "../apps_container.h"
|
||||
#include "calculation_controller.h"
|
||||
#include <assert.h>
|
||||
|
||||
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<double>(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<double>::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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
#ifndef PROBABILITY_CALCULATION_VIEW_H
|
||||
#define PROBABILITY_CALCULATION_VIEW_H
|
||||
|
||||
#include <escher.h>
|
||||
#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
|
||||
42
apps/probability/image_cell.cpp
Normal file
42
apps/probability/image_cell.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "image_cell.h"
|
||||
#include <assert.h>
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
26
apps/probability/image_cell.h
Normal file
26
apps/probability/image_cell.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef PROBABILITY_IMAGE_CELL_H
|
||||
#define PROBABILITY_IMAGE_CELL_H
|
||||
|
||||
#include <escher.h>
|
||||
|
||||
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
|
||||
@@ -1,164 +0,0 @@
|
||||
#include "image_table_view.h"
|
||||
#include <assert.h>
|
||||
#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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
#ifndef PROBABILITY_IMAGE_TABLE_VIEW_H
|
||||
#define PROBABILITY_IMAGE_TABLE_VIEW_H
|
||||
|
||||
#include <escher.h>
|
||||
#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
|
||||
53
apps/probability/responder_image_cell.cpp
Normal file
53
apps/probability/responder_image_cell.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "responder_image_cell.h"
|
||||
#include <assert.h>
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
37
apps/probability/responder_image_cell.h
Normal file
37
apps/probability/responder_image_cell.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef PROBABILITY_RESPONDER_IMAGE_CELL_H
|
||||
#define PROBABILITY_RESPONDER_IMAGE_CELL_H
|
||||
|
||||
#include <escher.h>
|
||||
#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
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user