GraphApp: Use a FunctionStore

Change-Id: Ib75947c40167489726fafc493ccb0ebf2862142b
This commit is contained in:
Romain Goyet
2016-08-22 14:40:07 +02:00
parent e1dcffd4ce
commit 00afebbe2d
15 changed files with 166 additions and 36 deletions

View File

@@ -1,5 +1,7 @@
app_objs += $(addprefix apps/graph/,\
graph_app.o\
function.o\
function_store.o\
graph/cursor_view.o\
graph/graph_controller.o\
graph/graph_view.o\

43
apps/graph/function.cpp Normal file
View File

@@ -0,0 +1,43 @@
#include "function.h"
Graph::Function::Function() :
m_text(nullptr),
m_expression(nullptr),
m_layout(nullptr)
{
}
Graph::Function::Function(const char * text) :
m_text(text), // FIXME: Copy !!
m_expression(nullptr),
m_layout(nullptr)
{
}
Graph::Function::~Function() {
//FIXME: Free m_text!
if (m_layout != nullptr) {
delete m_layout;
}
if (m_expression != nullptr) {
delete m_expression;
}
}
const char * Graph::Function::text() {
return m_text;
}
Expression * Graph::Function::expression() {
if (m_expression == nullptr) {
m_expression = Expression::parse(m_text);
}
return m_expression;
}
ExpressionLayout * Graph::Function::layout() {
if (m_layout == nullptr) {
m_layout = expression()->createLayout();
}
return m_layout;
}

24
apps/graph/function.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef GRAPH_FUNCTION_H
#define GRAPH_FUNCTION_H
#include <poincare.h>
namespace Graph {
class Function {
public:
Function();
Function(const char * text);
~Function(); // Delete expression and layout, if needed
const char * text();
Expression * expression();
ExpressionLayout * layout();
private:
const char * m_text;
Expression * m_expression;
ExpressionLayout * m_layout;
};
}
#endif

View File

@@ -0,0 +1,23 @@
#include "function_store.h"
extern "C" {
#include <assert.h>
}
Graph::FunctionStore::FunctionStore() :
m_numberOfFunctions(0)
{
}
Graph::Function * Graph::FunctionStore::functionAtIndex(int i) {
assert(i>=0 && i<m_numberOfFunctions);
return &m_functions[i];
}
void Graph::FunctionStore::pushFunction(const char * functionText) {
assert(m_numberOfFunctions < k_maxNumberOfFunctions);
m_functions[m_numberOfFunctions++] = Function(functionText);
}
int Graph::FunctionStore::numberOfFunctions() {
return m_numberOfFunctions;
}

View File

@@ -0,0 +1,22 @@
#ifndef GRAPH_FUNCTION_STORE_H
#define GRAPH_FUNCTION_STORE_H
#include "function.h"
namespace Graph {
class FunctionStore {
public:
FunctionStore();
Function * functionAtIndex(int i);
void pushFunction(const char * functionText);
int numberOfFunctions();
private:
int m_numberOfFunctions;
static constexpr int k_maxNumberOfFunctions = 8;
Function m_functions[k_maxNumberOfFunctions];
};
}
#endif

View File

@@ -1,8 +1,8 @@
#include "graph_controller.h"
GraphController::GraphController(Responder * parentResponder) :
GraphController::GraphController(Responder * parentResponder, Graph::FunctionStore * functionStore) :
ViewController(parentResponder),
m_view(GraphView())
m_view(GraphView(functionStore))
{
}

View File

@@ -3,10 +3,11 @@
#include <escher.h>
#include "graph_view.h"
#include "../function_store.h"
class GraphController : public ViewController {
public:
GraphController(Responder * parentResponder);
GraphController(Responder * parentResponder, Graph::FunctionStore * functionStore);
View * view() override;
const char * title() const override;
void setFocused(bool focused) override;

View File

@@ -7,7 +7,7 @@ constexpr KDColor kSecondaryGridColor = KDColor(0xEEEEEE);
constexpr int kNumberOfMainGridLines = 5;
constexpr int kNumberOfSecondaryGridLines = 4;
GraphView::GraphView() :
GraphView::GraphView(Graph::FunctionStore * functionStore) :
#if GRAPH_VIEW_IS_TILED
TiledView(),
#else
@@ -18,7 +18,8 @@ GraphView::GraphView() :
m_xMin(-2.0f),
m_xMax(2.0f),
m_yMin(-2.0f),
m_yMax(2.0f)
m_yMax(2.0f),
m_functionStore(functionStore)
{
}
@@ -157,14 +158,18 @@ void GraphView::drawFunction(KDContext * ctx, KDRect rect) const {
KDColor workingBuffer[stampSize*stampSize];
Context plotContext;
for (KDCoordinate px = rect.x()-stampSize; px<rect.right(); px++) {
float x = pixelToFloat(Axis::Horizontal, px);
float y = (x-1)*(x+1)*x;
KDCoordinate py = floatToPixel(Axis::Vertical, y);
KDRect stampRect(px, py, stampSize, stampSize);
//KDColor red = KDColorRed;
ctx->fillRectWithMask(stampRect, KDColorRed, mask, workingBuffer);
//KDBlitRect(stampRect, &red, {1,1}, mask, {stampSize,stampSize});
for (int i=0; i<m_functionStore->numberOfFunctions(); i++) {
Float xExp = Float(x);
plotContext.setExpressionForSymbolName(&xExp, "x");
Graph::Function * f = m_functionStore->functionAtIndex(i);
float y = f->expression()->approximate(plotContext);
KDCoordinate py = floatToPixel(Axis::Vertical, y);
KDRect stampRect(px, py, stampSize, stampSize);
ctx->fillRectWithMask(stampRect, KDColorRed, mask, workingBuffer);
}
}
}

View File

@@ -3,6 +3,7 @@
#include <escher.h>
#include "cursor_view.h"
#include "../function_store.h"
#define GRAPH_VIEW_IS_TILED 1
@@ -14,7 +15,7 @@ class GraphView : public
#endif
{
public:
GraphView();
GraphView(Graph::FunctionStore * functionStore);
#if GRAPH_VIEW_IS_TILED
KDColor * tile() const override;
@@ -64,6 +65,8 @@ private:
float m_xMax;
float m_yMin;
float m_yMax;
Graph::FunctionStore * m_functionStore;
};
#endif

View File

@@ -2,10 +2,13 @@
GraphApp::GraphApp() :
App(),
m_listController(ListController(nullptr)),
m_graphController(GraphController(nullptr)),
m_functionStore(Graph::FunctionStore()),
m_listController(ListController(nullptr, &m_functionStore)),
m_graphController(GraphController(nullptr, &m_functionStore)),
m_tabViewController(this, &m_listController, &m_graphController)
{
m_functionStore.pushFunction("(x-1)*(x+1)*x");
m_functionStore.pushFunction("x*x");
}
ViewController * GraphApp::rootViewController() {

View File

@@ -2,15 +2,17 @@
#define GRAPH_GRAPH_APP_H
#include <escher.h>
#include "function_store.h"
#include "graph/graph_controller.h"
#include "list/list_controller.h"
class GraphApp : public App {
class GraphApp : public ::App {
public:
GraphApp();
protected:
ViewController * rootViewController() override;
private:
Graph::FunctionStore m_functionStore;
ListController m_listController;
GraphController m_graphController;
TabViewController m_tabViewController;

View File

@@ -1,22 +1,29 @@
#include "function_cell.h"
#include <poincare.h>
FunctionCell::FunctionCell() :
ChildlessView(),
Responder(nullptr),
m_function(nullptr),
m_focused(false),
m_even(false)
{
m_message = "NULL";
}
void FunctionCell::drawRect(KDContext * ctx, KDRect rect) const {
KDColor background = m_even ? KDColor(0xEEEEEE) : KDColor(0x777777);
ctx->fillRect(rect, background);
ctx->drawString(m_message, KDPointZero, m_focused);
ctx->drawString(m_function->text(), KDPointZero, m_focused);
m_function->layout()->draw(ctx, KDPointZero);
//Expression * foo = Expression::parse("1+2/3");
//ExpressionLayout * fooLayout = foo->createLayout();
//fooLayout->draw(ctx, KDPointZero);
//delete fooLayout;
//delete foo;
}
void FunctionCell::setMessage(const char * message) {
m_message = message;
void FunctionCell::setFunction(Graph::Function * f) {
m_function = f;
}
void FunctionCell::setFocused(bool focused) {

View File

@@ -2,17 +2,18 @@
#define GRAPH_FUNCTION_CELL_H
#include <escher.h>
#include "../function.h"
class FunctionCell : public ChildlessView, public Responder {
public:
FunctionCell();
void setMessage(const char * message);
void setFunction(Graph::Function * f);
void setEven(bool even);
void drawRect(KDContext * ctx, KDRect rect) const override;
void setFocused(bool focused) override;
private:
const char * m_message;
Graph::Function * m_function;
bool m_focused;
bool m_even;
};

View File

@@ -1,20 +1,13 @@
#include "list_controller.h"
#include <assert.h>
static const char * sMessages[] = {
"AAA 0", "BBB 1", "CCC 2", "DDD 3", "EEE 4",
"FFF 5", "GGG 6", "HHH 7", "III 8", "JJJ 9",
"KKK10", "LLL11", "MMM12", "NNN13", "OOO14",
"PPP15", "QQQ16", "RRR17", "SSS18", "TTT19"
};
ListController::ListController(Responder * parentResponder) :
ListController::ListController(Responder * parentResponder, Graph::FunctionStore * functionStore) :
ViewController(parentResponder),
m_tableView(TableView(this)),
m_activeCell(0),
m_manualScrolling(0)
m_manualScrolling(0),
m_functionStore(functionStore)
{
m_messages = sMessages;
}
View * ListController::view() {
@@ -26,7 +19,7 @@ const char * ListController::title() const {
}
void ListController::setActiveCell(int index) {
if (index < 0 || index >= k_totalNumberOfModels) {
if (index < 0 || index >= m_functionStore->numberOfFunctions()) {
return;
}
@@ -55,7 +48,7 @@ bool ListController::handleEvent(ion_event_t event) {
}
int ListController::numberOfCells() {
return k_totalNumberOfModels;
return m_functionStore->numberOfFunctions();
};
View * ListController::reusableCell(int index) {
@@ -70,7 +63,7 @@ int ListController::reusableCellCount() {
void ListController::willDisplayCellForIndex(View * cell, int index) {
FunctionCell * myCell = (FunctionCell *)cell;
myCell->setMessage(m_messages[index]);
myCell->setFunction(m_functionStore->functionAtIndex(index));
myCell->setEven(index%2 == 0);
}

View File

@@ -2,11 +2,12 @@
#define GRAPH_LIST_CONTROLLER_H
#include <escher.h>
#include "../function_store.h"
#include "function_cell.h"
class ListController : public ViewController, public TableViewDataSource {
public:
ListController(Responder * parentResponder);
ListController(Responder * parentResponder, Graph::FunctionStore * functionStore);
void setActiveCell(int index);
@@ -26,9 +27,9 @@ private:
// The cells should be initialized *before* the tableview!
FunctionCell m_cells[k_maxNumberOfCells];
TableView m_tableView;
const char ** m_messages;
int m_activeCell;
KDCoordinate m_manualScrolling;
Graph::FunctionStore * m_functionStore;
};
#endif