Merge changes I95c569cc,I2a891e6a,Icaec669c,I13696462

* changes:
  [apps/sequence/list] Create a class list controller
  [apps/sequence] Create a class sequence title cell
  [apps/sequence/list] Create a class sequence expression cell inheriting from function expression cell
  [apps/sequence] Improve sequence model
This commit is contained in:
Émilie Feral
2017-02-16 14:29:43 +01:00
committed by Gerrit
16 changed files with 505 additions and 17 deletions

View File

@@ -1,8 +1,11 @@
app_objs += $(addprefix apps/sequence/,\
app.o\
list/list_controller.o\
list/sequence_expression_cell.o\
values/values_controller.o\
sequence.o\
sequence_store.o\
sequence_title_cell.o\
)
app_images += apps/sequence/sequence_icon.png

View File

@@ -0,0 +1,56 @@
#include "list_controller.h"
#include <assert.h>
using namespace Shared;
namespace Sequence {
ListController::ListController(Responder * parentResponder, SequenceStore * sequenceStore, HeaderViewController * header) :
Shared::ListController(parentResponder, sequenceStore, header),
m_parameterController(ListParameterController(this, sequenceStore))
{
}
const char * ListController::title() const {
return "Suites";
}
bool ListController::handleEvent(Ion::Events::Event event) {
if (Shared::ListController::handleEvent(event)) {
return true;
}
if (event == Ion::Events::OK && m_selectableTableView.selectedColumn() == 1
&& m_selectableTableView.selectedRow() == numberOfRows() - 1) {
return addFunction();
}
return false;
}
void ListController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) {
if (t->selectedRow() < numberOfRows() - 1) {
Responder * myCell = (Responder *)t->cellAtLocation(t->selectedColumn(), t->selectedRow());
app()->setFirstResponder(myCell);
} else {
app()->setFirstResponder(t);
}
}
ListParameterController * ListController::parameterController() {
return &m_parameterController;
}
int ListController::maxNumberOfRows() {
return k_maxNumberOfRows;
}
TableViewCell * ListController::titleCells(int index) {
assert(index >= 0 && index < k_maxNumberOfRows);
return &m_functionTitleCells[index];
}
TableViewCell * ListController::expressionCells(int index) {
assert(index >= 0 && index < k_maxNumberOfRows);
return &m_expressionCells[index];
}
}

View File

@@ -0,0 +1,33 @@
#ifndef SEQUENCE_LIST_CONTROLLER_H
#define SEQUENCE_LIST_CONTROLLER_H
#include <escher.h>
#include "../sequence_title_cell.h"
#include "../sequence_store.h"
#include "sequence_expression_cell.h"
#include "../../shared/new_function_cell.h"
#include "../../shared/list_controller.h"
#include "../../shared/list_parameter_controller.h"
namespace Sequence {
class ListController : public Shared::ListController, public SelectableTableViewDelegate {
public:
ListController(Responder * parentResponder, SequenceStore * sequenceStore, HeaderViewController * header);
const char * title() const override;
bool handleEvent(Ion::Events::Event event) override;
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override;
private:
Shared::ListParameterController * parameterController() override;
int maxNumberOfRows() override;
TableViewCell * titleCells(int index) override;
TableViewCell * expressionCells(int index) override;
constexpr static int k_maxNumberOfRows = 3;
SequenceTitleCell m_functionTitleCells[k_maxNumberOfRows];
SequenceExpressionCell m_expressionCells[k_maxNumberOfRows];
Shared::ListParameterController m_parameterController;
};
}
#endif

View File

@@ -0,0 +1,116 @@
#include "sequence_expression_cell.h"
using namespace Shared;
namespace Sequence {
SequenceExpressionCell::SequenceExpressionCell(Responder * parentResponder) :
FunctionExpressionCell(),
Responder(parentResponder),
m_sequence(nullptr),
m_numberOfSubCells(1),
m_selectedSubCell(0),
m_firstInitialConditionView(EvenOddExpressionCell()),
m_secondInitialConditionView(EvenOddExpressionCell())
{
}
int SequenceExpressionCell::selectedSubCell() {
return m_selectedSubCell;
}
void SequenceExpressionCell::selectSubCell(int selectedSubCell) {
m_selectedSubCell = selectedSubCell;
m_expressionView.setHighlighted(selectedSubCell == 0);
m_firstInitialConditionView.setHighlighted(selectedSubCell == 1);
m_secondInitialConditionView.setHighlighted(selectedSubCell == 2);
reloadCell();
}
void SequenceExpressionCell::setFunction(Function * f) {
FunctionExpressionCell::setFunction(f);
m_sequence = (Sequence *)f;
m_numberOfSubCells = (int)m_sequence->type()+1;
if (m_numberOfSubCells > 1) {
m_firstInitialConditionView.setExpression(m_sequence->firstInitialConditionLayout());
}
if (m_numberOfSubCells > 2) {
m_secondInitialConditionView.setExpression(m_sequence->secondInitialConditionLayout());
}
}
void SequenceExpressionCell::reloadCell() {
FunctionExpressionCell::reloadCell();
m_firstInitialConditionView.setBackgroundColor(backgroundColor());
m_secondInitialConditionView.setBackgroundColor(backgroundColor());
if (m_numberOfSubCells > 1 && m_sequence) {
bool active = m_sequence->isActive();
KDColor textColor = active ? KDColorBlack : Palette::GreyDark;
m_firstInitialConditionView.setTextColor(textColor);
m_secondInitialConditionView.setTextColor(textColor);
}
}
void SequenceExpressionCell::setHighlighted(bool highlight) {
m_expressionView.setHighlighted(false);
m_firstInitialConditionView.setHighlighted(false);
m_secondInitialConditionView.setHighlighted(false);
TableViewCell::setHighlighted(highlight);
if (isHighlighted()) {
if (m_selectedSubCell == 0) {
m_expressionView.setHighlighted(true);
}
if (m_selectedSubCell == 1) {
m_firstInitialConditionView.setHighlighted(true);
}
if (m_selectedSubCell == 2) {
m_secondInitialConditionView.setHighlighted(true);
}
}
reloadCell();
}
void SequenceExpressionCell::setEven(bool even) {
m_expressionView.setEven(even);
m_firstInitialConditionView.setEven(even);
m_secondInitialConditionView.setEven(even);
reloadCell();
}
int SequenceExpressionCell::numberOfSubviews() const {
return m_numberOfSubCells;
}
View * SequenceExpressionCell::subviewAtIndex(int index) {
if (index == 0) {
return &m_expressionView;
}
if (index == 1) {
return &m_firstInitialConditionView;
}
return &m_secondInitialConditionView;
}
void SequenceExpressionCell::layoutSubviews() {
KDCoordinate cellHeight = bounds().height()/m_numberOfSubCells;
KDRect expressionFrame(k_separatorThickness, 0, bounds().width() - k_separatorThickness, cellHeight);
m_expressionView.setFrame(expressionFrame);
expressionFrame = KDRect(k_separatorThickness, cellHeight, bounds().width() - k_separatorThickness, cellHeight);
m_firstInitialConditionView.setFrame(expressionFrame);
expressionFrame = KDRect(k_separatorThickness, 2*cellHeight, bounds().width() - k_separatorThickness, cellHeight);
m_secondInitialConditionView.setFrame(expressionFrame);
}
bool SequenceExpressionCell::handleEvent(Ion::Events::Event event) {
if (m_selectedSubCell < 2 && event == Ion::Events::Down) {
selectSubCell(m_selectedSubCell+1);
return true;
}
if (m_selectedSubCell > 0 && event == Ion::Events::Up) {
selectSubCell(m_selectedSubCell-1);
return true;
}
return false;
}
}

View File

@@ -0,0 +1,32 @@
#ifndef SEQUENCE_SEQUENCE_EXPRESSION_CELL_H
#define SEQUENCE_SEQUENCE_EXPRESSION_CELL_H
#include "../sequence.h"
#include "../../shared/function_expression_cell.h"
namespace Sequence {
class SequenceExpressionCell : public Shared::FunctionExpressionCell, public Responder {
public:
SequenceExpressionCell(Responder * parentResponder = nullptr);
void setFunction(Shared::Function * f) override;
int selectedSubCell();
void selectSubCell(int index);
void reloadCell() override;
void setHighlighted(bool highlight) override;
void setEven(bool even) override;
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews() override;
bool handleEvent(Ion::Events::Event event) override;
private:
Sequence * m_sequence;
int m_numberOfSubCells;
int m_selectedSubCell;
EvenOddExpressionCell m_firstInitialConditionView;
EvenOddExpressionCell m_secondInitialConditionView;
};
}
#endif

View File

@@ -1,7 +1,92 @@
#include "sequence.h"
#include <string.h>
using namespace Shared;
namespace Sequence {
Sequence::Sequence(const char * text, KDColor color) :
Function(text, color),
m_type(Type::Explicite),
m_firstInitialConditionText(""),
m_secondInitialConditionText(""),
m_firstInitialConditionExpression(nullptr),
m_secondInitialConditionExpression(nullptr),
m_firstInitialConditionLayout(nullptr),
m_secondInitialConditionLayout(nullptr)
{
}
Sequence::~Sequence() {
((Function *)this)->Shared::Function::~Function();
if (m_firstInitialConditionLayout != nullptr) {
delete m_firstInitialConditionLayout;
}
if (m_secondInitialConditionLayout != nullptr) {
delete m_secondInitialConditionLayout;
}
if (m_firstInitialConditionExpression != nullptr) {
delete m_firstInitialConditionExpression;
}
if (m_secondInitialConditionExpression != nullptr) {
delete m_secondInitialConditionExpression;
}
}
Sequence::Type Sequence::type() {
return m_type;
}
void Sequence::setType(Type type) {
m_type = type;
}
Poincare::Expression * Sequence::firstInitialConditionExpression() {
return m_firstInitialConditionExpression;
}
Poincare::Expression * Sequence::secondInitialConditionExpression() {
return m_secondInitialConditionExpression;
}
Poincare::ExpressionLayout * Sequence::firstInitialConditionLayout() {
return m_firstInitialConditionLayout;
}
Poincare::ExpressionLayout * Sequence::secondInitialConditionLayout() {
return m_secondInitialConditionLayout;
}
void Sequence::setFirstInitialConditionContent(const char * c) {
strlcpy(m_firstInitialConditionText, c, sizeof(m_firstInitialConditionText));
if (m_firstInitialConditionExpression != nullptr) {
delete m_firstInitialConditionExpression;
}
m_firstInitialConditionExpression = Poincare::Expression::parse(m_firstInitialConditionText);
if (m_firstInitialConditionLayout != nullptr) {
delete m_firstInitialConditionLayout;
}
m_firstInitialConditionLayout = nullptr;
if (m_firstInitialConditionExpression) {
m_firstInitialConditionLayout = expression()->createLayout();
}
}
void Sequence::setSecondInitialConditionContent(const char * c) {
strlcpy(m_secondInitialConditionText, c, sizeof(m_secondInitialConditionText));
if (m_secondInitialConditionExpression != nullptr) {
delete m_secondInitialConditionExpression;
}
m_secondInitialConditionExpression = Poincare::Expression::parse(m_secondInitialConditionText);
if (m_secondInitialConditionLayout != nullptr) {
delete m_secondInitialConditionLayout;
}
m_secondInitialConditionLayout = nullptr;
if (m_secondInitialConditionExpression) {
m_secondInitialConditionLayout = expression()->createLayout();
}
}
char Sequence::symbol() const {
return 'n';
}

View File

@@ -7,9 +7,30 @@ namespace Sequence {
class Sequence : public Shared::Function {
public:
using Shared::Function::Function;
enum class Type {
Explicite = 0,
SingleRecurrence = 1,
DoubleRecurrence = 2
};
Sequence(const char * text = nullptr, KDColor color = KDColorBlack);
~Sequence();
Type type();
void setType(Type type);
Poincare::Expression * firstInitialConditionExpression();
Poincare::Expression * secondInitialConditionExpression();
Poincare::ExpressionLayout * firstInitialConditionLayout();
Poincare::ExpressionLayout * secondInitialConditionLayout();
void setFirstInitialConditionContent(const char * c);
void setSecondInitialConditionContent(const char * c);
private:
char symbol() const override;
Type m_type;
char m_firstInitialConditionText[Shared::Function::k_bodyLength];
char m_secondInitialConditionText[Shared::Function::k_bodyLength];
Poincare::Expression * m_firstInitialConditionExpression;
Poincare::Expression * m_secondInitialConditionExpression;
Poincare::ExpressionLayout * m_firstInitialConditionLayout;
Poincare::ExpressionLayout * m_secondInitialConditionLayout;
};
}

View File

@@ -0,0 +1,91 @@
#include "sequence_title_cell.h"
using namespace Shared;
namespace Sequence {
SequenceTitleCell::SequenceTitleCell(Responder * parentResponder) :
FunctionTitleCell(FunctionTitleCell::Orientation::VerticalIndicator),
Responder(parentResponder),
m_numberOfSubCells(1),
m_selectedSubCell(0),
m_firstInitialConditionView(KDText::FontSize::Large, 0.5f, 0.5f),
m_secondInitialConditionView(KDText::FontSize::Large, 0.5f, 0.5f)
{
}
int SequenceTitleCell::selectedSubCell() {
return m_selectedSubCell;
}
void SequenceTitleCell::selectSubCell(int selectedSubCell) {
m_selectedSubCell = selectedSubCell;
m_bufferTextView.setHighlighted(selectedSubCell == 0);
m_firstInitialConditionView.setHighlighted(selectedSubCell == 1);
m_secondInitialConditionView.setHighlighted(selectedSubCell == 2);
reloadCell();
}
void SequenceTitleCell::setHighlighted(bool highlight) {
m_bufferTextView.setHighlighted(false);
m_firstInitialConditionView.setHighlighted(false);
m_secondInitialConditionView.setHighlighted(false);
TableViewCell::setHighlighted(highlight);
if (isHighlighted()) {
if (m_selectedSubCell == 0) {
m_bufferTextView.setHighlighted(true);
}
if (m_selectedSubCell == 1) {
m_firstInitialConditionView.setHighlighted(true);
}
if (m_selectedSubCell == 2) {
m_secondInitialConditionView.setHighlighted(true);
}
}
reloadCell();
}
void SequenceTitleCell::setEven(bool even) {
m_bufferTextView.setEven(even);
m_firstInitialConditionView.setEven(even);
m_secondInitialConditionView.setEven(even);
reloadCell();
}
int SequenceTitleCell::numberOfSubviews() const {
return m_numberOfSubCells;
}
View * SequenceTitleCell::subviewAtIndex(int index) {
if (index == 0) {
return &m_bufferTextView;
}
if (index == 1) {
return &m_firstInitialConditionView;
}
return &m_secondInitialConditionView;
}
void SequenceTitleCell::layoutSubviews() {
KDCoordinate cellHeight = bounds().height()/m_numberOfSubCells;
KDRect expressionFrame(k_colorIndicatorThickness, 0, bounds().width() - k_separatorThickness, cellHeight);
m_bufferTextView.setFrame(expressionFrame);
expressionFrame = KDRect(k_colorIndicatorThickness, cellHeight, bounds().width() - k_separatorThickness, cellHeight);
m_firstInitialConditionView.setFrame(expressionFrame);
expressionFrame = KDRect(k_colorIndicatorThickness, 2*cellHeight, bounds().width() - k_separatorThickness, cellHeight);
m_secondInitialConditionView.setFrame(expressionFrame);
}
bool SequenceTitleCell::handleEvent(Ion::Events::Event event) {
if (m_selectedSubCell < 2 && event == Ion::Events::Down) {
selectSubCell(m_selectedSubCell+1);
return true;
}
if (m_selectedSubCell > 0 && event == Ion::Events::Up) {
selectSubCell(m_selectedSubCell-1);
return true;
}
return false;
}
}

View File

@@ -0,0 +1,32 @@
#ifndef SEQUENCE_SEQUENCE_TITLE_CELL_H
#define SEQUENCE_SEQUENCE_TITLE_CELL_H
#include "../shared/function_title_cell.h"
namespace Sequence {
class SequenceTitleCell : public Shared::FunctionTitleCell, public Responder {
public:
SequenceTitleCell(Responder * parentResponder = nullptr);
void setFirstInitialConditionText(const char * textContent);
void setSecondInitialConditionText(const char * textContent);
int selectedSubCell();
void selectSubCell(int index);
void setHighlighted(bool highlight) override;
void setEven(bool even) override;
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews() override;
bool handleEvent(Ion::Events::Event event) override;
private:
static constexpr KDCoordinate k_emptyRowHeight = 50;
constexpr static KDCoordinate k_separatorThickness = 1;
int m_numberOfSubCells;
int m_selectedSubCell;
EvenOddBufferTextCell m_firstInitialConditionView;
EvenOddBufferTextCell m_secondInitialConditionView;
};
}
#endif

View File

@@ -21,10 +21,10 @@ public:
void setColor(KDColor m_color);
float evaluateAtAbscissa(float x, Poincare::Context * context, Poincare::Expression::AngleUnit angleUnit) const;
protected:
constexpr static int k_bodyLength = 255;
Poincare::Expression * m_expression;
private:
virtual char symbol() const = 0;
constexpr static int k_bodyLength = 255;
char m_text[k_bodyLength];
const char * m_name;
KDColor m_color;

View File

@@ -6,7 +6,7 @@ namespace Shared {
FunctionExpressionCell::FunctionExpressionCell() :
EvenOddCell(),
m_function(nullptr),
m_expressionView(ExpressionView())
m_expressionView(EvenOddExpressionCell())
{
}
@@ -17,7 +17,6 @@ void FunctionExpressionCell::setFunction(Function * f) {
void FunctionExpressionCell::reloadCell() {
EvenOddCell::reloadCell();
m_expressionView.setBackgroundColor(backgroundColor());
if (m_function) {
bool active = m_function->isActive();
KDColor textColor = active ? KDColorBlack : Palette::GreyDark;
@@ -25,6 +24,16 @@ void FunctionExpressionCell::reloadCell() {
}
}
void FunctionExpressionCell::setEven(bool even) {
EvenOddCell::setEven(even);
m_expressionView.setEven(even);
}
void FunctionExpressionCell::setHighlighted(bool highlight) {
EvenOddCell::setHighlighted(highlight);
m_expressionView.setHighlighted(highlight);
}
Function * FunctionExpressionCell::function() {
return m_function;
}

View File

@@ -9,18 +9,21 @@ namespace Shared {
class FunctionExpressionCell : public EvenOddCell {
public:
FunctionExpressionCell();
void setFunction(Function * f);
virtual void setFunction(Function * f);
Function * function();
void reloadCell() override;
void setEven(bool even) override;
void setHighlighted(bool highlight) override;
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews() override;
void drawRect(KDContext * ctx, KDRect rect) const override;
private:
static constexpr KDCoordinate k_emptyRowHeight = 50;
protected:
constexpr static KDCoordinate k_separatorThickness = 1;
Function * m_function;
ExpressionView m_expressionView;
EvenOddExpressionCell m_expressionView;
private:
static constexpr KDCoordinate k_emptyRowHeight = 50;
};
}

View File

@@ -10,9 +10,14 @@ FunctionTitleCell::FunctionTitleCell(Orientation orientation, KDText::FontSize s
{
}
void FunctionTitleCell::reloadCell() {
EvenOddCell::reloadCell();
m_bufferTextView.setBackgroundColor(backgroundColor());
void FunctionTitleCell::setHighlighted(bool highlight) {
EvenOddCell::setHighlighted(highlight);
m_bufferTextView.setHighlighted(highlight);
}
void FunctionTitleCell::setEven(bool even) {
EvenOddCell::setEven(even);
m_bufferTextView.setEven(even);
}
void FunctionTitleCell::setText(const char * title) {

View File

@@ -15,14 +15,16 @@ public:
void setColor(KDColor color);
void setText(const char * textContent);
void drawRect(KDContext * ctx, KDRect rect) const override;
void reloadCell() override;
void setEven(bool even) override;
void setHighlighted(bool highlight) override;
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews() override;
private:
protected:
constexpr static KDCoordinate k_colorIndicatorThickness = 2;
EvenOddBufferTextCell m_bufferTextView;
private:
KDColor m_functionColor;
BufferTextView m_bufferTextView;
Orientation m_orientation;
};

View File

@@ -6,7 +6,7 @@
class EvenOddBufferTextCell : public EvenOddCell {
public:
EvenOddBufferTextCell(KDText::FontSize size = KDText::FontSize::Small);
EvenOddBufferTextCell(KDText::FontSize size = KDText::FontSize::Small, float horizontalAlignment = 1.0f, float verticalAlignment = 0.5f);
void reloadCell() override;
void setText(const char * textContent);
void setTextColor(KDColor textColor);

View File

@@ -1,9 +1,9 @@
#include <escher/even_odd_buffer_text_cell.h>
#include <assert.h>
EvenOddBufferTextCell::EvenOddBufferTextCell(KDText::FontSize size) :
EvenOddBufferTextCell::EvenOddBufferTextCell(KDText::FontSize size, float horizontalAlignment, float verticalAlignment) :
EvenOddCell(),
m_bufferTextView(BufferTextView(size, 1.0f, 0.5f))
m_bufferTextView(BufferTextView(size, horizontalAlignment, verticalAlignment))
{
}