[solver] First version of Solver app

This commit is contained in:
Émilie Feral
2018-05-24 11:33:55 +02:00
parent 021262e3aa
commit 5d2079cd9e
15 changed files with 393 additions and 1 deletions

18
apps/solver/Makefile Normal file
View File

@@ -0,0 +1,18 @@
snapshots += Solver::App::Snapshot
snapshot_headers += apps/solver/app.h
app_objs += $(addprefix apps/solver/,\
app.o\
equation_store.o\
list_controller.o\
)
i18n_files += $(addprefix apps/solver/,\
base.de.i18n\
base.en.i18n\
base.es.i18n\
base.fr.i18n\
base.pt.i18n\
)
app_images += apps/solver/solver_icon.png

68
apps/solver/app.cpp Normal file
View File

@@ -0,0 +1,68 @@
#include "app.h"
#include "../i18n.h"
#include "solver_icon.h"
using namespace Shared;
namespace Solver {
I18n::Message App::Descriptor::name() {
return I18n::Message::SolverApp;
}
I18n::Message App::Descriptor::upperName() {
return I18n::Message::SolverAppCapital;
}
const Image * App::Descriptor::icon() {
return ImageStore::SolverIcon;
}
App::Snapshot::Snapshot() :
m_equationStore()
{
}
App * App::Snapshot::unpack(Container * container) {
return new App(container, this);
}
App::Descriptor * App::Snapshot::descriptor() {
static Descriptor descriptor;
return &descriptor;
}
void App::Snapshot::reset() {
// Delete all equations
m_equationStore.removeAll();
}
void App::Snapshot::tidy() {
// Delete all expressions of equations
m_equationStore.tidy();
}
App::App(Container * container, Snapshot * snapshot) :
ExpressionFieldDelegateApp(container, snapshot, &m_inputViewController),
m_listController(&m_stackViewController, snapshot->equationStore(), &m_listFooter),
m_listFooter(&m_stackViewController, &m_listController, &m_listController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGrey),
m_stackViewController(&m_inputViewController, &m_listFooter),
m_inputViewController(&m_modalViewController, &m_stackViewController, this, this)
{
}
void App::willBecomeInactive() {
if (m_modalViewController.isDisplayingModal()) {
m_modalViewController.dismissModalViewController();
}
if (inputViewController()->isDisplayingModal()) {
inputViewController()->abortEditionAndDismiss();
}
::App::willBecomeInactive();
}
const char * App::XNT() {
return "x";
}
}

43
apps/solver/app.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef SOLVER_SOLVER_APP_H
#define SOLVER_SOLVER_APP_H
#include <escher.h>
#include "../shared/expression_field_delegate_app.h"
#include "list_controller.h"
#include "equation_store.h"
namespace Solver {
class App : public Shared::ExpressionFieldDelegateApp {
public:
class Descriptor : public ::App::Descriptor {
public:
I18n::Message name() override;
I18n::Message upperName() override;
const Image * icon() override;
};
class Snapshot : public ::App::Snapshot {
public:
Snapshot();
App * unpack(Container * container) override;
Descriptor * descriptor() override;
void reset() override;
EquationStore * equationStore() { return &m_equationStore; }
private:
void tidy() override;
EquationStore m_equationStore;
};
InputViewController * inputViewController() { return &m_inputViewController; }
void willBecomeInactive() override;
const char * XNT() override;
private:
App(Container * container, Snapshot * snapshot);
ListController m_listController;
ButtonRowController m_listFooter;
StackViewController m_stackViewController;
InputViewController m_inputViewController;
};
}
#endif

4
apps/solver/base.de.i18n Normal file
View File

@@ -0,0 +1,4 @@
SolverApp = "Equation"
SolverAppCapital = "EQUATION"
AddEquation = "Ajouter une équation"
Resolve = "Résoudre"

4
apps/solver/base.en.i18n Normal file
View File

@@ -0,0 +1,4 @@
SolverApp = "Equation"
SolverAppCapital = "EQUATION"
AddEquation = "Ajouter une équation"
Resolve = "Résoudre l'équation"

4
apps/solver/base.es.i18n Normal file
View File

@@ -0,0 +1,4 @@
SolverApp = "Equation"
SolverAppCapital = "EQUATION"
AddEquation = "Ajouter une équation"
Resolve = "Résoudre"

4
apps/solver/base.fr.i18n Normal file
View File

@@ -0,0 +1,4 @@
SolverApp = "Equation"
SolverAppCapital = "EQUATION"
AddEquation = "Ajouter une équation"
Resolve = "Résoudre l'équation"

4
apps/solver/base.pt.i18n Normal file
View File

@@ -0,0 +1,4 @@
SolverApp = "Equation"
SolverAppCapital = "EQUATION"
AddEquation = "Ajouter une équation"
Resolve = "Résoudre"

13
apps/solver/equation.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef SOLVER_EQUATION_h
#define SOLVER_EQUATION_h
#include "../shared/expression_model.h"
namespace Solver {
class Equation : public Shared::ExpressionModel {
};
}
#endif

View File

@@ -0,0 +1,14 @@
#include "equation_store.h"
namespace Solver {
Equation * EquationStore::emptyModel() {
static Equation e;
return &e;
}
void EquationStore::setModelAtIndex(Shared::ExpressionModel * e, int i) {
m_equations[i] = *(static_cast<Equation *>(e));;
}
}

View File

@@ -0,0 +1,30 @@
#ifndef SOLVER_EQUATION_STORE_H
#define SOLVER_EQUATION_STORE_H
#include "equation.h"
#include "../shared/expression_model_store.h"
#include <stdint.h>
namespace Solver {
class EquationStore : public Shared::ExpressionModelStore {
public:
EquationStore() {}
Equation * modelAtIndex(int i) override {
assert(i>=0 && i<m_numberOfModels);
return &m_equations[i];
}
int maxNumberOfModels() const override { return k_maxNumberOfEquations; }
private:
Equation * emptyModel() override;
Equation * nullModel() override {
return emptyModel();
}
void setModelAtIndex(Shared::ExpressionModel * f, int i) override;
static constexpr int k_maxNumberOfEquations = 6;
Equation m_equations[k_maxNumberOfEquations];;
};
}
#endif

View File

@@ -0,0 +1,131 @@
#include "list_controller.h"
#include "app.h"
#include <assert.h>
using namespace Shared;
namespace Solver {
ListController::ListController(Responder * parentResponder, EquationStore * equationStore, ButtonRowController * footer) :
ExpressionModelListController(parentResponder, I18n::Message::AddEquation),
ButtonRowDelegate(nullptr, footer),
m_equationStore(equationStore),
m_resolveButton(this, I18n::Message::Resolve, Invocation([](void * context, void * sender) {
ListController * list = (ListController *)context;
StackViewController * stackController = list->stackController();
// TODO
//stackController->push(list->solutionPage ??)
}, this), KDText::FontSize::Small, Palette::PurpleBright)
{
}
int ListController::numberOfButtons(ButtonRowController::Position position) const {
if (position == ButtonRowController::Position::Bottom) {
return 1;
}
return 0;
}
Button * ListController::buttonAtIndex(int index, ButtonRowController::Position position) const {
if (position == ButtonRowController::Position::Top) {
return nullptr;
}
return const_cast<Button *>(&m_resolveButton);
}
int ListController::typeAtLocation(int i, int j) {
if (j == m_equationStore->numberOfModels()) {
return 1;
}
return 0;
}
HighlightCell * ListController::reusableCell(int index, int type) {
assert(index >= 0);
assert(index < k_maxNumberOfRows);
switch (type) {
case 0:
return m_expressionCells[index];
case 1:
return m_addNewModel;
default:
assert(false);
return nullptr;
}
}
int ListController::reusableCellCount(int type) {
if (type == 1) {
return 1;
}
return k_maxNumberOfRows;
}
void ListController::willDisplayCellForIndex(HighlightCell * cell, int index) {
if (index != m_equationStore->numberOfModels()) {
willDisplayExpressionCellAtIndex(cell, index);
}
EvenOddCell * myCell = (EvenOddCell *)cell;
myCell->setEven(index%2 == 0);
myCell->setHighlighted(index == selectedRow());
}
bool ListController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Up && selectedRow() == -1) {
footer()->setSelectedButton(-1);
selectableTableView()->selectCellAtLocation(0, numberOfRows()-1);
app()->setFirstResponder(selectableTableView());
return true;
}
if (event == Ion::Events::Down) {
if (selectedRow() == -1) {
return false;
}
selectableTableView()->deselectTable();
footer()->setSelectedButton(0);
return true;
}
return handleEventOnExpression(event);
}
void ListController::didBecomeFirstResponder() {
if (selectedRow() == -1) {
selectCellAtLocation(0, 0);
} else {
selectCellAtLocation(selectedColumn(), selectedRow());
}
if (selectedRow() >= numberOfRows()) {
selectCellAtLocation(selectedColumn(), numberOfRows()-1);
}
footer()->setSelectedButton(-1);
app()->setFirstResponder(selectableTableView());
}
void ListController::didEnterResponderChain(Responder * previousFirstResponder) {
selectableTableView()->reloadData();
}
View * ListController::loadView() {
for (int i = 0; i < k_maxNumberOfRows; i++) {
m_expressionCells[i] = new ModelExpressionCell();
}
return Shared::ExpressionModelListController::loadView();
}
void ListController::unloadView(View * view) {
for (int i = 0; i < k_maxNumberOfRows; i++) {
delete m_expressionCells[i];
m_expressionCells[i] = nullptr;
}
Shared::ExpressionModelListController::unloadView(view);
}
StackViewController * ListController::stackController() const {
return static_cast<StackViewController *>(parentResponder()->parentResponder());
}
InputViewController * ListController::inputController() {
return static_cast<App *>(app())->inputViewController();
}
}

View File

@@ -0,0 +1,55 @@
#ifndef SOLVER_LIST_CONTROLLER_H
#define SOLVER_LIST_CONTROLLER_H
#include <escher.h>
#include "../shared/expression_model_list_controller.h"
#include "../shared/model_expression_cell.h"
#include "equation_store.h"
#include "../i18n.h"
namespace Solver {
class ListController : public Shared::ExpressionModelListController, public ButtonRowDelegate, public ListViewDataSource {
public:
ListController(Responder * parentResponder, EquationStore * equationStore, ButtonRowController * footer);
/* ButtonRowDelegate */
int numberOfButtons(ButtonRowController::Position position) const override;
Button * buttonAtIndex(int index, ButtonRowController::Position position) const override;
/* ListViewDataSource */
int numberOfRows() override {
return numberOfExpressionRows();
}
KDCoordinate cumulatedHeightFromIndex(int j) override {
return cumulatedExpressionHeightFromIndex(j);
}
int indexFromCumulatedHeight(KDCoordinate offsetY) override {
return indexFromCumulatedExpressionHeight(offsetY);
}
KDCoordinate rowHeight(int j) override {
return expressionRowHeight(j);
}
int typeAtLocation(int i, int j) override;
HighlightCell * reusableCell(int index, int type) override;
int reusableCellCount(int type) override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
/* Responder */
bool handleEvent(Ion::Events::Event event) override;
void didBecomeFirstResponder() override;
void didEnterResponderChain(Responder * previousFirstResponder) override;
private:
constexpr static int k_maxNumberOfRows = 5; // Ion::Display::Height / Metric::StoreRowHeight = 4.8;
View * loadView() override;
void unloadView(View * view) override;
Shared::ExpressionModelStore * modelStore() override { return m_equationStore; }
StackViewController * stackController() const;
InputViewController * inputController() override;
TableViewDataSource * tableDataSource() override { return this; }
SelectableTableViewDelegate * selectableTableDelegate() override { return nullptr; }
EquationStore * m_equationStore;
Shared::ModelExpressionCell * m_expressionCells[k_maxNumberOfRows];
Button m_resolveButton;
};
}
#endif

BIN
apps/solver/solver_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -6,7 +6,7 @@ DEBUG ?= 0
EPSILON_VERSION ?= 1.5.0
EPSILON_ONBOARDING_APP ?= 1
EPSILON_SOFTWARE_UPDATE_PROMPT ?= 1
EPSILON_APPS ?= calculation statistics graph probability sequence regression settings code
EPSILON_APPS ?= calculation statistics graph probability sequence regression settings code solver
EPSILON_I18N ?= en fr es de pt
EPSILON_GETOPT ?= 0