mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-28 10:09:53 +01:00
Merge changes Iaf806c1f,I2c54cb11,Iabf36299,I2e2cf0c7,I21a08f18, ...
* changes: [apps] Add a margin around the window when drawing curves [apps] Use curve view window in the abstract class curve view [apps/statistics] Make data model inherit from curve view window [apps/probability] Make the model law inherit from curve view window [apps/graph/graph] Make the model graph window inherit from curve view window [apps] Create an abstract model curve view window [apps/graph/graph] When redrawing the curve, slightly exceed the rect to ensure the continuity of the curve [apps/graph/graph] Add a banner view in the graph view [apps/graph/graph] Create a class banner view [apps/probability] Add a pointer to the data model in the histogram controller [apps/probability] Improve data controller to delete pairs of data [escher] Add a method in even odd editable text cell to access editable text cell [apps/probability] Add method in data model (to delete pairs) [escher] Correct syntax error
This commit is contained in:
@@ -9,6 +9,7 @@ app_objs += $(addprefix apps/,\
|
||||
apps_container.o\
|
||||
constant.o\
|
||||
curve_view.o\
|
||||
curve_view_window.o\
|
||||
editable_cell_table_view_controller.o\
|
||||
expression_text_field_delegate.o\
|
||||
float_parameter_controller.o\
|
||||
|
||||
@@ -7,15 +7,38 @@
|
||||
|
||||
constexpr KDColor CurveView::k_axisColor;
|
||||
|
||||
CurveView::CurveView() :
|
||||
View()
|
||||
CurveView::CurveView(CurveViewWindow * curveViewWindow) :
|
||||
View(),
|
||||
m_curveViewWindow(curveViewWindow)
|
||||
{
|
||||
}
|
||||
|
||||
void CurveView::setCurveViewWindow(CurveViewWindow * curveViewWindow) {
|
||||
m_curveViewWindow = curveViewWindow;
|
||||
}
|
||||
|
||||
void CurveView::reload() {
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
|
||||
float CurveView::min(Axis axis) const {
|
||||
assert(axis == Axis::Horizontal || axis == Axis::Vertical);
|
||||
float range = axis == Axis::Horizontal ? m_curveViewWindow->xMax() - m_curveViewWindow->xMin() : m_curveViewWindow->yMax() - m_curveViewWindow->yMin();
|
||||
float absoluteMin = (axis == Axis::Horizontal ? m_curveViewWindow->xMin(): m_curveViewWindow->yMin());
|
||||
return absoluteMin - k_marginFactor*range;
|
||||
}
|
||||
|
||||
float CurveView::max(Axis axis) const {
|
||||
assert(axis == Axis::Horizontal || axis == Axis::Vertical);
|
||||
float range = axis == Axis::Horizontal ? m_curveViewWindow->xMax() - m_curveViewWindow->xMin() : m_curveViewWindow->yMax() - m_curveViewWindow->yMin();
|
||||
float absoluteMax = (axis == Axis::Horizontal ? m_curveViewWindow->xMax() : m_curveViewWindow->yMax());
|
||||
return absoluteMax + k_marginFactor*range;
|
||||
}
|
||||
|
||||
float CurveView::gridUnit(Axis axis) const {
|
||||
return (axis == Axis::Horizontal ? m_curveViewWindow->xGridUnit() : m_curveViewWindow->yGridUnit());
|
||||
}
|
||||
|
||||
KDCoordinate CurveView::pixelLength(Axis axis) const {
|
||||
assert(axis == Axis::Horizontal || axis == Axis::Vertical);
|
||||
return (axis == Axis::Horizontal ? m_frame.width() : m_frame.height());
|
||||
@@ -131,13 +154,14 @@ const uint8_t stampMask[stampSize+1][stampSize+1] = {
|
||||
|
||||
constexpr static int k_maxNumberOfIterations = 10;
|
||||
constexpr static int k_resolution = 320.0f;
|
||||
constexpr static int k_externRectMargin = 1;
|
||||
|
||||
void CurveView::drawCurve(void * curve, KDColor color, KDContext * ctx, KDRect rect, bool colorUnderCurve, float colorLowerBound, float colorUpperBound, bool continuously) const {
|
||||
float xMin = min(Axis::Horizontal);
|
||||
float xMax = max(Axis::Horizontal);
|
||||
float xStep = (xMax-xMin)/k_resolution;
|
||||
float rectMin = pixelToFloat(Axis::Horizontal, rect.left());
|
||||
float rectMax = pixelToFloat(Axis::Horizontal, rect.right());
|
||||
float rectMin = pixelToFloat(Axis::Horizontal, rect.left() - k_externRectMargin);
|
||||
float rectMax = pixelToFloat(Axis::Horizontal, rect.right() + k_externRectMargin);
|
||||
for (float x = rectMin; x < rectMax; x += xStep) {
|
||||
float y = evaluateCurveAtAbscissa(curve, x);
|
||||
float pxf = floatToPixel(Axis::Horizontal, x);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <escher.h>
|
||||
#include <poincare.h>
|
||||
#include "curve_view_window.h"
|
||||
|
||||
class CurveView : public View {
|
||||
public:
|
||||
@@ -10,16 +11,19 @@ public:
|
||||
Horizontal = 0,
|
||||
Vertical = 1
|
||||
};
|
||||
CurveView();
|
||||
CurveView(CurveViewWindow * curveViewWindow = nullptr);
|
||||
void reload();
|
||||
protected:
|
||||
constexpr static KDColor k_axisColor = KDColor::RGB24(0x000000);
|
||||
constexpr static KDCoordinate k_labelMargin = 4;
|
||||
constexpr static int k_maxNumberOfXLabels = 18;
|
||||
constexpr static int k_maxNumberOfYLabels = 13;
|
||||
virtual float min(Axis axis) const = 0;
|
||||
virtual float max(Axis axis) const = 0;
|
||||
virtual float gridUnit(Axis axis) const = 0;
|
||||
void setCurveViewWindow(CurveViewWindow * curveViewWindow);
|
||||
/* The window bounds are deduced from the model bounds but also take into
|
||||
account a margin (computed with k_marginFactor) */
|
||||
float min(Axis axis) const;
|
||||
float max(Axis axis) const;
|
||||
float gridUnit(Axis axis) const;
|
||||
virtual char * label(Axis axis, int index) const = 0;
|
||||
KDCoordinate pixelLength(Axis axis) const;
|
||||
float pixelToFloat(Axis axis, KDCoordinate p) const;
|
||||
@@ -32,6 +36,7 @@ protected:
|
||||
void computeLabels(Axis axis);
|
||||
void drawLabels(Axis axis, bool shiftOrigin, KDContext * ctx, KDRect rect) const;
|
||||
private:
|
||||
constexpr static float k_marginFactor = 0.2f;
|
||||
int numberOfLabels(Axis axis) const;
|
||||
virtual float evaluateCurveAtAbscissa(void * curve, float t) const = 0;
|
||||
/* Recursively join two dots (dichotomy). The method stops when the
|
||||
@@ -43,6 +48,7 @@ private:
|
||||
* function shifts the stamp (by blending adjacent pixel colors) to draw with
|
||||
* anti alising. */
|
||||
void stampAtLocation(float pxf, float pyf, KDColor color, KDContext * ctx, KDRect rect) const;
|
||||
CurveViewWindow * m_curveViewWindow;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
29
apps/curve_view_window.cpp
Normal file
29
apps/curve_view_window.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "curve_view_window.h"
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
float CurveViewWindow::yGridUnit() {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float CurveViewWindow::computeGridUnit(Axis axis) {
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
float d = xMax() - xMin();
|
||||
float maxNumberOfUnits = k_maxNumberOfXGridUnits;
|
||||
float minNumberOfUnits = k_minNumberOfXGridUnits;
|
||||
if (axis == Axis::Y) {
|
||||
d = yMax() - yMin();
|
||||
maxNumberOfUnits = k_maxNumberOfYGridUnits;
|
||||
minNumberOfUnits = k_minNumberOfYGridUnits;
|
||||
}
|
||||
float units[3] = {k_oneUnit, k_twoUnit, k_fiveUnit};
|
||||
for (int k = 0; k < 3; k++) {
|
||||
float unit = units[k];
|
||||
if (floorf(log10f(d/(unit*maxNumberOfUnits))) != floorf(log10f(d/(unit*minNumberOfUnits)))) {
|
||||
b = floorf(log10f(d/(unit*minNumberOfUnits)));
|
||||
a = unit;
|
||||
}
|
||||
}
|
||||
return a*powf(10,b);
|
||||
}
|
||||
27
apps/curve_view_window.h
Normal file
27
apps/curve_view_window.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef APPS_CURVE_VIEW_WINDOW_H
|
||||
#define APPS_CURVE_VIEW_WINDOW_H
|
||||
|
||||
class CurveViewWindow {
|
||||
public:
|
||||
enum class Axis {
|
||||
X,
|
||||
Y
|
||||
};
|
||||
virtual float xMin() = 0;
|
||||
virtual float xMax() = 0;
|
||||
virtual float yMin() = 0;
|
||||
virtual float yMax() = 0;
|
||||
virtual float xGridUnit() = 0;
|
||||
virtual float yGridUnit();
|
||||
protected:
|
||||
constexpr static float k_minNumberOfXGridUnits = 7.0f;
|
||||
constexpr static float k_maxNumberOfXGridUnits = 18.0f;
|
||||
constexpr static float k_minNumberOfYGridUnits = 5.0f;
|
||||
constexpr static float k_maxNumberOfYGridUnits = 13.0f;
|
||||
constexpr static float k_oneUnit = 1.0f;
|
||||
constexpr static float k_twoUnit = 2.0f;
|
||||
constexpr static float k_fiveUnit = 5.0f;
|
||||
float computeGridUnit(Axis axis);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@ app_objs += $(addprefix apps/graph/,\
|
||||
function.o\
|
||||
function_store.o\
|
||||
function_title_cell.o\
|
||||
graph/banner_view.o\
|
||||
graph/graph_window.o\
|
||||
graph/window_parameter_controller.o\
|
||||
graph/cursor_view.o\
|
||||
|
||||
82
apps/graph/graph/banner_view.cpp
Normal file
82
apps/graph/graph/banner_view.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "banner_view.h"
|
||||
#include <assert.h>
|
||||
#include "../../constant.h"
|
||||
|
||||
namespace Graph {
|
||||
|
||||
BannerView::BannerView() :
|
||||
m_abscissa(0.0f),
|
||||
m_function(nullptr),
|
||||
m_abscissaView(0.0f, 0.5f),
|
||||
m_functionView(0.5f, 0.5f),
|
||||
m_derivativeView(1.0f, 0.5f),
|
||||
m_displayDerivative(false),
|
||||
m_context(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void BannerView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
ctx->fillRect(bounds(), KDColorWhite);
|
||||
}
|
||||
|
||||
void BannerView::setContext(Context * context) {
|
||||
m_context = context;
|
||||
}
|
||||
|
||||
void BannerView::setAbscissa(float x) {
|
||||
markRectAsDirty(bounds());
|
||||
m_abscissa = x;
|
||||
char buffer[4+Constant::FloatBufferSizeInScientificMode] = {'x', ' ', '=', ' ',0};
|
||||
Float(x).convertFloatToText(buffer+4, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode);
|
||||
m_abscissaView.setText(buffer);
|
||||
}
|
||||
|
||||
void BannerView::setFunction(Function * f) {
|
||||
markRectAsDirty(bounds());
|
||||
m_function = f;
|
||||
float y = f->evaluateAtAbscissa(m_abscissa, m_context);
|
||||
char buffer[8+Constant::FloatBufferSizeInScientificMode] = {0, 0, '(', 'x', ')', ' ', '=', ' ',0};
|
||||
buffer[1] = f->name()[0];
|
||||
Float(y).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode);
|
||||
m_functionView.setText(buffer+1);
|
||||
|
||||
y = f->approximateDerivative(m_abscissa, m_context);
|
||||
buffer[0] = f->name()[0];
|
||||
buffer[1] = '\'';
|
||||
Float(y).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaForDerivativeNumberInScientificMode);
|
||||
m_derivativeView.setText(buffer);
|
||||
}
|
||||
|
||||
void BannerView::setDisplayDerivative(bool displayDerivative) {
|
||||
m_displayDerivative = displayDerivative;
|
||||
}
|
||||
|
||||
bool BannerView::displayDerivative() {
|
||||
return m_displayDerivative;
|
||||
}
|
||||
|
||||
int BannerView::numberOfSubviews() const {
|
||||
if (m_displayDerivative) {
|
||||
return 3;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
View * BannerView::subviewAtIndex(int index) {
|
||||
assert(index >= 0);
|
||||
if (index == 0) {
|
||||
return &m_abscissaView;
|
||||
}
|
||||
if (index == 1) {
|
||||
return &m_functionView;
|
||||
}
|
||||
return &m_derivativeView;
|
||||
}
|
||||
|
||||
void BannerView::layoutSubviews() {
|
||||
m_abscissaView.setFrame(bounds());
|
||||
m_functionView.setFrame(bounds());
|
||||
m_derivativeView.setFrame(bounds());
|
||||
}
|
||||
|
||||
}
|
||||
33
apps/graph/graph/banner_view.h
Normal file
33
apps/graph/graph/banner_view.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef GRAPH_BANNER_VIEW_H
|
||||
#define GRAPH_BANNER_VIEW_H
|
||||
|
||||
#include <escher.h>
|
||||
#include "../function.h"
|
||||
|
||||
namespace Graph {
|
||||
|
||||
class BannerView : public View {
|
||||
public:
|
||||
BannerView();
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setContext(Context * context);
|
||||
void setAbscissa(float x);
|
||||
void setFunction(Function * f);
|
||||
void setDisplayDerivative(bool displayDerivative);
|
||||
bool displayDerivative();
|
||||
private:
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews() override;
|
||||
float m_abscissa;
|
||||
Function * m_function;
|
||||
BufferTextView m_abscissaView;
|
||||
BufferTextView m_functionView;
|
||||
BufferTextView m_derivativeView;
|
||||
bool m_displayDerivative;
|
||||
Context * m_context;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -6,7 +6,6 @@ namespace Graph {
|
||||
CurveParameterController::CurveParameterController(GraphView * graphView) :
|
||||
ViewController(nullptr),
|
||||
m_graphView(graphView),
|
||||
m_displayDerivative(false),
|
||||
m_function(nullptr),
|
||||
m_calculationCell(ChevronMenuListCell((char*)"Calculer")),
|
||||
m_goToCell(ChevronMenuListCell((char*)"Aller a")),
|
||||
@@ -33,7 +32,7 @@ void CurveParameterController::didBecomeFirstResponder() {
|
||||
void CurveParameterController::willDisplayCellForIndex(TableViewCell * cell, int index) {
|
||||
if (cell == &m_derivativeCell) {
|
||||
SwitchView * switchView = (SwitchView *)m_derivativeCell.accessoryView();
|
||||
switchView->setState(m_displayDerivative);
|
||||
switchView->setState(m_graphView->bannerView()->displayDerivative());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +49,7 @@ bool CurveParameterController::handleEvent(Ion::Events::Event event) {
|
||||
return true;
|
||||
}
|
||||
case 2:
|
||||
m_displayDerivative = !m_displayDerivative;
|
||||
m_graphView->bannerView()->setDisplayDerivative(!m_graphView->bannerView()->displayDerivative());
|
||||
m_selectableTableView.reloadData();
|
||||
return true;
|
||||
default:
|
||||
@@ -79,10 +78,6 @@ KDCoordinate CurveParameterController::cellHeight() {
|
||||
return 35;
|
||||
}
|
||||
|
||||
bool CurveParameterController::displayDerivative() const {
|
||||
return m_displayDerivative;
|
||||
}
|
||||
|
||||
void CurveParameterController::setFunction(Function * function) {
|
||||
m_function = function;
|
||||
}
|
||||
|
||||
@@ -20,11 +20,9 @@ public:
|
||||
TableViewCell * reusableCell(int index) override;
|
||||
int reusableCellCount() override;
|
||||
void willDisplayCellForIndex(TableViewCell * cell, int index) override;
|
||||
bool displayDerivative() const;
|
||||
void setFunction(Function * function);
|
||||
private:
|
||||
GraphView * m_graphView;
|
||||
bool m_displayDerivative;
|
||||
Function * m_function;
|
||||
constexpr static int k_totalNumberOfCells = 3;
|
||||
ChevronMenuListCell m_calculationCell;
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Graph {
|
||||
constexpr KDColor GraphView::k_gridColor;
|
||||
|
||||
GraphView::GraphView(FunctionStore * functionStore, GraphWindow * graphWindow) :
|
||||
CurveView(),
|
||||
CurveView(graphWindow),
|
||||
m_cursorView(CursorView()),
|
||||
m_xCursorPosition(-1.0f),
|
||||
m_yCursorPosition(-1.0f),
|
||||
@@ -19,17 +19,25 @@ GraphView::GraphView(FunctionStore * functionStore, GraphWindow * graphWindow) :
|
||||
{
|
||||
}
|
||||
|
||||
BannerView * GraphView::bannerView() {
|
||||
return &m_bannerView;
|
||||
}
|
||||
|
||||
int GraphView::numberOfSubviews() const {
|
||||
return 1;
|
||||
return 2;
|
||||
};
|
||||
|
||||
View * GraphView::subviewAtIndex(int index) {
|
||||
assert(index == 0);
|
||||
return &m_cursorView;
|
||||
assert(index >= 0 && index < 2);
|
||||
if (index == 0) {
|
||||
return &m_cursorView;
|
||||
}
|
||||
return &m_bannerView;
|
||||
}
|
||||
|
||||
void GraphView::setContext(Context * context) {
|
||||
m_context = context;
|
||||
m_bannerView.setContext(context);
|
||||
}
|
||||
|
||||
Context * GraphView::context() const {
|
||||
@@ -52,10 +60,6 @@ void GraphView::reloadCursor() {
|
||||
layoutSubviews();
|
||||
}
|
||||
|
||||
float GraphView::gridUnit(Axis axis) const {
|
||||
return (axis == Axis::Horizontal ? m_graphWindow->xGridUnit() : m_graphWindow->yGridUnit());
|
||||
}
|
||||
|
||||
char * GraphView::label(Axis axis, int index) const {
|
||||
return (axis == Axis::Horizontal ? (char *)m_xLabels[index] : (char *)m_yLabels[index]);
|
||||
}
|
||||
@@ -74,6 +78,7 @@ void GraphView::goToAbscissaOnFunction(float abscissa, Function * function) {
|
||||
float ordinate = function->evaluateAtAbscissa(abscissa, m_context);
|
||||
m_graphWindow->centerAxisAround(GraphWindow::Axis::Y, ordinate);
|
||||
m_yCursorPosition = floatToPixel(Axis::Vertical, ordinate);
|
||||
updateBannerView(function);
|
||||
reload();
|
||||
}
|
||||
|
||||
@@ -89,6 +94,7 @@ void GraphView::initCursorPosition() {
|
||||
float fCenter = firstFunction->evaluateAtAbscissa(center, m_context);
|
||||
m_xCursorPosition = (bounds().width()-1.0f)/2.0f;
|
||||
m_yCursorPosition = floatToPixel(Axis::Vertical, fCenter);
|
||||
updateBannerView(firstFunction);
|
||||
}
|
||||
|
||||
void GraphView::moveCursorHorizontally(KDCoordinate xOffset) {
|
||||
@@ -102,6 +108,7 @@ void GraphView::moveCursorHorizontally(KDCoordinate xOffset) {
|
||||
bool windowHasMoved = m_graphWindow->panToMakePointVisible(x, y, xMargin, yMargin);
|
||||
m_xCursorPosition = floatToPixel(Axis::Horizontal, x);
|
||||
m_yCursorPosition = floatToPixel(Axis::Vertical, y);
|
||||
updateBannerView(f);
|
||||
if (windowHasMoved) {
|
||||
reload();
|
||||
} else {
|
||||
@@ -134,6 +141,7 @@ Function * GraphView::moveCursorVertically(int direction) {
|
||||
markRectAsDirty(KDRect(KDPoint(roundf(m_xCursorPosition) - k_cursorSize/2, roundf(m_yCursorPosition)- k_cursorSize/2), k_cursorSize, k_cursorSize));
|
||||
m_xCursorPosition = floatToPixel(Axis::Horizontal, x);
|
||||
m_yCursorPosition = floatToPixel(Axis::Vertical, nextY);
|
||||
updateBannerView(nextFunction);
|
||||
if (windowHasMoved) {
|
||||
reload();
|
||||
} else {
|
||||
@@ -144,10 +152,13 @@ Function * GraphView::moveCursorVertically(int direction) {
|
||||
|
||||
void GraphView::layoutSubviews() {
|
||||
KDRect cursorFrame(roundf(m_xCursorPosition) - k_cursorSize/2, roundf(m_yCursorPosition) - k_cursorSize/2, k_cursorSize, k_cursorSize);
|
||||
KDRect bannerFrame(KDRect(0, bounds().height()- k_bannerHeight, bounds().width(), k_bannerHeight));
|
||||
if (!m_visibleCursor) {
|
||||
cursorFrame = KDRectZero;
|
||||
bannerFrame = KDRectZero;
|
||||
}
|
||||
m_cursorView.setFrame(cursorFrame);
|
||||
m_bannerView.setFrame(bannerFrame);
|
||||
}
|
||||
|
||||
void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
@@ -184,19 +195,14 @@ void GraphView::drawGrid(KDContext * ctx, KDRect rect) const {
|
||||
drawGridLines(ctx, rect, Axis::Vertical, m_graphWindow->yGridUnit(), k_gridColor);
|
||||
}
|
||||
|
||||
float GraphView::min(Axis axis) const {
|
||||
assert(axis == Axis::Horizontal || axis == Axis::Vertical);
|
||||
return (axis == Axis::Horizontal ? m_graphWindow->xMin() : m_graphWindow->yMin());
|
||||
}
|
||||
|
||||
float GraphView::max(Axis axis) const {
|
||||
assert(axis == Axis::Horizontal || axis == Axis::Vertical);
|
||||
return (axis == Axis::Horizontal ? m_graphWindow->xMax() : m_graphWindow->yMax());
|
||||
}
|
||||
|
||||
float GraphView::evaluateCurveAtAbscissa(void * curve, float abscissa) const {
|
||||
Function * f = (Function *)curve;
|
||||
return f->evaluateAtAbscissa(abscissa, m_context);
|
||||
}
|
||||
|
||||
void GraphView::updateBannerView(Function * function) {
|
||||
m_bannerView.setAbscissa(xCursorPosition());
|
||||
m_bannerView.setFunction(function);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define GRAPH_GRAPH_VIEW_H
|
||||
|
||||
#include <escher.h>
|
||||
#include "banner_view.h"
|
||||
#include "cursor_view.h"
|
||||
#include "graph_window.h"
|
||||
#include "../../curve_view.h"
|
||||
@@ -14,6 +15,7 @@ namespace Graph {
|
||||
class GraphView : public CurveView {
|
||||
public:
|
||||
GraphView(FunctionStore * functionStore, GraphWindow * graphWindow);
|
||||
BannerView * bannerView();
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
|
||||
float xPixelCursorPosition();
|
||||
@@ -32,18 +34,19 @@ private:
|
||||
constexpr static KDColor k_gridColor = KDColor::RGB24(0xEEEEEE);
|
||||
constexpr static KDCoordinate k_cursorSize = 9;
|
||||
constexpr static float k_cursorMarginToBorder = 6.0f;
|
||||
constexpr static KDCoordinate k_bannerHeight = 30;
|
||||
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews() override;
|
||||
|
||||
float min(Axis axis) const override;
|
||||
float max(Axis axis) const override;
|
||||
float gridUnit(Axis axis) const override;
|
||||
char * label(Axis axis, int index) const override;
|
||||
float evaluateCurveAtAbscissa(void * expression, float abscissa) const override;
|
||||
void drawGrid(KDContext * ctx, KDRect rect) const;
|
||||
void drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const;
|
||||
void updateBannerView(Function * function);
|
||||
|
||||
BannerView m_bannerView;
|
||||
|
||||
CursorView m_cursorView;
|
||||
float m_xCursorPosition;
|
||||
|
||||
@@ -51,23 +51,23 @@ float GraphWindow::yGridUnit() {
|
||||
void GraphWindow::setXMin(float xMin) {
|
||||
m_xMin = xMin;
|
||||
computeYaxes();
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
}
|
||||
|
||||
void GraphWindow::setXMax(float xMax) {
|
||||
m_xMax = xMax;
|
||||
computeYaxes();
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
}
|
||||
|
||||
void GraphWindow::setYMin(float yMin) {
|
||||
m_yMin = yMin;
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
}
|
||||
|
||||
void GraphWindow::setYMax(float yMax) {
|
||||
m_yMax = yMax;
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
}
|
||||
|
||||
void GraphWindow::setYAuto(bool yAuto) {
|
||||
@@ -104,7 +104,7 @@ bool GraphWindow::computeYaxes() {
|
||||
m_yMax = max + 1;
|
||||
}
|
||||
}
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -123,11 +123,11 @@ void GraphWindow::zoom(float ratio) {
|
||||
float yMax = m_yMax;
|
||||
m_xMin = (xMax+xMin)/2.0f - ratio*fabsf(xMax-xMin);
|
||||
m_xMax = (xMax+xMin)/2.0f + ratio*fabsf(xMax-xMin);
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
m_yAuto = false;
|
||||
m_yMin = (yMax+yMin)/2.0f - ratio*fabsf(yMax-yMin);
|
||||
m_yMax = (yMax+yMin)/2.0f + ratio*fabsf(yMax-yMin);
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
}
|
||||
|
||||
void GraphWindow::centerAxisAround(Axis axis, float position) {
|
||||
@@ -136,13 +136,13 @@ void GraphWindow::centerAxisAround(Axis axis, float position) {
|
||||
m_xMin = position - range/2.0f;
|
||||
m_xMax = position + range/2.0f;
|
||||
computeYaxes();
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
} else {
|
||||
m_yAuto = false;
|
||||
float range = m_yMax - m_yMin;
|
||||
m_yMin = position - range/2.0f;
|
||||
m_yMax = position + range/2.0f;
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,23 +151,23 @@ void GraphWindow::translateWindow(Direction direction) {
|
||||
if (direction == Direction::Up) {
|
||||
m_yMin = m_yMin + m_yGridUnit;
|
||||
m_yMax = m_yMax + m_yGridUnit;
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
}
|
||||
if (direction == Direction::Down) {
|
||||
m_yMin = m_yMin - m_yGridUnit;
|
||||
m_yMax = m_yMax - m_yGridUnit;
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
}
|
||||
if (direction == Direction::Left) {
|
||||
m_xMin = m_xMin - m_xGridUnit;
|
||||
m_xMax = m_xMax - m_xGridUnit;
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
computeYaxes();
|
||||
}
|
||||
if (direction == Direction::Right) {
|
||||
m_xMin = m_xMin + m_xGridUnit;
|
||||
m_xMax = m_xMax + m_xGridUnit;
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
computeYaxes();
|
||||
}
|
||||
}
|
||||
@@ -175,11 +175,11 @@ void GraphWindow::translateWindow(Direction direction) {
|
||||
void GraphWindow::setTrigonometric() {
|
||||
m_xMin = -10.5f;
|
||||
m_xMax = 10.5f;
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
m_yAuto = false;
|
||||
m_yMin = -1.6f;
|
||||
m_yMax = 1.6f;
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
}
|
||||
|
||||
void GraphWindow::roundAbscissa() {
|
||||
@@ -187,7 +187,7 @@ void GraphWindow::roundAbscissa() {
|
||||
float xMax = m_xMax;
|
||||
m_xMin = roundf((xMin+xMax)/2) - 160.0f;
|
||||
m_xMax = roundf((xMin+xMax)/2) + 159.0f;
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
computeYaxes();
|
||||
}
|
||||
|
||||
@@ -198,17 +198,17 @@ void GraphWindow::normalize() {
|
||||
float yMax = m_yMax;
|
||||
m_xMin = (xMin+xMax)/2 - 5.3f;
|
||||
m_xMax = (xMin+xMax)/2 + 5.3f;
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
m_yAuto = false;
|
||||
m_yMin = (yMin+yMax)/2 - 3.1f;
|
||||
m_yMax = (yMin+yMax)/2 + 3.1f;
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
}
|
||||
|
||||
void GraphWindow::setDefault() {
|
||||
m_xMin = -10.0f;
|
||||
m_xMax = 10.0f;
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
setYAuto(true);
|
||||
}
|
||||
|
||||
@@ -219,56 +219,30 @@ bool GraphWindow::panToMakePointVisible(float x, float y, float xMargin, float y
|
||||
if (x < m_xMin + xMargin) {
|
||||
m_xMin = x - xMargin;
|
||||
m_xMax = m_xMin + xRange;
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
computeYaxes();
|
||||
windowMoved = true;
|
||||
}
|
||||
if (x > m_xMax - xMargin) {
|
||||
m_xMax = x + xMargin;
|
||||
m_xMin = m_xMax - xRange;
|
||||
computeGridUnit(Axis::X);
|
||||
m_xGridUnit = computeGridUnit(Axis::X);
|
||||
computeYaxes();
|
||||
windowMoved = true;
|
||||
}
|
||||
if (y < m_yMin + yMargin) {
|
||||
m_yMin = y - yMargin;
|
||||
m_yMax = m_yMin + yRange;
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
windowMoved = true;
|
||||
}
|
||||
if (y > m_yMax - yMargin) {
|
||||
m_yMax = y + yMargin;
|
||||
m_yMin = m_yMax - yRange;
|
||||
computeGridUnit(Axis::Y);
|
||||
m_yGridUnit = computeGridUnit(Axis::Y);
|
||||
windowMoved = true;
|
||||
}
|
||||
return windowMoved;
|
||||
}
|
||||
|
||||
void GraphWindow::computeGridUnit(Axis axis) {
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
float d = m_xMax - m_xMin;
|
||||
float maxNumberOfUnits = k_maxNumberOfXGridUnits;
|
||||
float minNumberOfUnits = k_minNumberOfXGridUnits;
|
||||
if (axis == Axis::Y) {
|
||||
d = m_yMax - m_yMin;
|
||||
maxNumberOfUnits = k_maxNumberOfYGridUnits;
|
||||
minNumberOfUnits = k_minNumberOfYGridUnits;
|
||||
}
|
||||
float units[3] = {k_oneUnit, k_twoUnit, k_fiveUnit};
|
||||
for (int k = 0; k < 3; k++) {
|
||||
float unit = units[k];
|
||||
if (floorf(log10f(d/(unit*maxNumberOfUnits))) != floorf(log10f(d/(unit*minNumberOfUnits)))) {
|
||||
b = floorf(log10f(d/(unit*minNumberOfUnits)));
|
||||
a = unit;
|
||||
}
|
||||
}
|
||||
if (axis == Axis::X) {
|
||||
m_xGridUnit = a*powf(10,b);
|
||||
} else {
|
||||
m_yGridUnit = a*powf(10,b);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,15 +2,12 @@
|
||||
#define GRAPH_GRAPH_AXIS_INTERVAL_H
|
||||
|
||||
#include "../function_store.h"
|
||||
#include "../../curve_view_window.h"
|
||||
|
||||
namespace Graph {
|
||||
|
||||
class GraphWindow {
|
||||
class GraphWindow : public CurveViewWindow {
|
||||
public:
|
||||
enum class Axis {
|
||||
X,
|
||||
Y
|
||||
};
|
||||
enum class Direction {
|
||||
Up,
|
||||
Left,
|
||||
@@ -18,13 +15,13 @@ public:
|
||||
Right
|
||||
};
|
||||
GraphWindow(FunctionStore * functionStore);
|
||||
float xMin();
|
||||
float xMax();
|
||||
float yMin();
|
||||
float yMax();
|
||||
float xMin() override;
|
||||
float xMax() override;
|
||||
float yMin() override;
|
||||
float yMax() override;
|
||||
bool yAuto();
|
||||
float xGridUnit();
|
||||
float yGridUnit();
|
||||
float xGridUnit() override;
|
||||
float yGridUnit() override;
|
||||
void setXMin(float f);
|
||||
void setXMax(float f);
|
||||
void setYMin(float f);
|
||||
@@ -44,14 +41,6 @@ public:
|
||||
void setDefault();
|
||||
bool panToMakePointVisible(float x, float y, float xMargin, float yMargin);
|
||||
private:
|
||||
constexpr static float k_minNumberOfXGridUnits = 7.0f;
|
||||
constexpr static float k_maxNumberOfXGridUnits = 18.0f;
|
||||
constexpr static float k_minNumberOfYGridUnits = 5.0f;
|
||||
constexpr static float k_maxNumberOfYGridUnits = 13.0f;
|
||||
constexpr static float k_oneUnit = 1.0f;
|
||||
constexpr static float k_twoUnit = 2.0f;
|
||||
constexpr static float k_fiveUnit = 5.0f;
|
||||
void computeGridUnit(Axis axis);
|
||||
float m_xMin;
|
||||
float m_xMax;
|
||||
float m_yMin;
|
||||
|
||||
@@ -48,17 +48,12 @@ float BinomialLaw::xMax() {
|
||||
}
|
||||
|
||||
float BinomialLaw::yMin() {
|
||||
int maxAbscissa = m_parameter2 < 1.0f ? (m_parameter1+1)*m_parameter2 : m_parameter1;
|
||||
float result = k_minMarginFactor*evaluateAtAbscissa(maxAbscissa);
|
||||
if (result >= 0.0f || isnan(result)) {
|
||||
result = k_minMarginFactor;
|
||||
}
|
||||
return result;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float BinomialLaw::yMax() {
|
||||
int maxAbscissa = m_parameter2 < 1.0f ? (m_parameter1+1)*m_parameter2 : m_parameter1;
|
||||
float result = k_maxMarginFactor*evaluateAtAbscissa(maxAbscissa);
|
||||
float result = evaluateAtAbscissa(maxAbscissa);
|
||||
if (result <= 0.0f || result == yMin() || isnan(result)) {
|
||||
result = yMin() + 1.0f;
|
||||
}
|
||||
|
||||
@@ -42,11 +42,11 @@ float ExponentialLaw::xMax() {
|
||||
}
|
||||
|
||||
float ExponentialLaw::yMin() {
|
||||
return k_minMarginFactor*m_parameter1;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float ExponentialLaw::yMax() {
|
||||
return k_maxMarginFactor*m_parameter1;
|
||||
return m_parameter1;
|
||||
}
|
||||
|
||||
float ExponentialLaw::evaluateAtAbscissa(float x) const {
|
||||
|
||||
@@ -4,19 +4,8 @@
|
||||
|
||||
namespace Probability {
|
||||
|
||||
float Law::gridUnit() {
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
float d = xMax() - xMin();
|
||||
float units[3] = {k_oneUnit, k_twoUnit, k_fiveUnit};
|
||||
for (int k = 0; k < 3; k++) {
|
||||
float unit = units[k];
|
||||
if (floorf(log10f(d/(unit*k_maxNumberOfXGridUnits))) != floorf(log10f(d/(unit*k_minNumberOfXGridUnits)))) {
|
||||
b = floorf(log10f(d/(unit*k_minNumberOfXGridUnits)));
|
||||
a = unit;
|
||||
}
|
||||
}
|
||||
return a*powf(10,b);
|
||||
float Law::xGridUnit() {
|
||||
return computeGridUnit(Axis::X);
|
||||
}
|
||||
|
||||
float Law::cumulativeDistributiveFunctionAtAbscissa(float x) const {
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
#define PROBABILITE_LAW_H
|
||||
|
||||
#include <poincare.h>
|
||||
#include "../../curve_view_window.h"
|
||||
|
||||
namespace Probability {
|
||||
|
||||
class Law {
|
||||
class Law : public CurveViewWindow {
|
||||
public:
|
||||
enum class Type : uint8_t{
|
||||
Binomial,
|
||||
@@ -18,11 +19,7 @@ public:
|
||||
virtual const char * title() = 0;
|
||||
virtual Type type() const = 0;
|
||||
virtual bool isContinuous() const = 0;
|
||||
virtual float xMin() = 0;
|
||||
virtual float yMin() = 0;
|
||||
virtual float xMax() = 0;
|
||||
virtual float yMax() = 0;
|
||||
float gridUnit();
|
||||
float xGridUnit() override;
|
||||
virtual int numberOfParameter() = 0;
|
||||
virtual float parameterValueAtIndex(int index) = 0;
|
||||
virtual const char * parameterNameAtIndex(int index) = 0;
|
||||
@@ -36,13 +33,6 @@ public:
|
||||
virtual float cumulativeDistributiveInverseForProbability(float * probability);
|
||||
virtual float rightIntegralInverseForProbability(float * probability);
|
||||
protected:
|
||||
constexpr static float k_minNumberOfXGridUnits = 7.0f;
|
||||
constexpr static float k_maxNumberOfXGridUnits = 18.0f;
|
||||
constexpr static float k_oneUnit = 1.0f;
|
||||
constexpr static float k_twoUnit = 2.0f;
|
||||
constexpr static float k_fiveUnit = 5.0f;
|
||||
constexpr static float k_minMarginFactor = -0.2f;
|
||||
constexpr static float k_maxMarginFactor = 1.2f;
|
||||
constexpr static int k_maxNumberOfOperations = 1000000;
|
||||
};
|
||||
|
||||
|
||||
@@ -55,17 +55,12 @@ float NormalLaw::xMax() {
|
||||
}
|
||||
|
||||
float NormalLaw::yMin() {
|
||||
float maxAbscissa = m_parameter1;
|
||||
float result = k_minMarginFactor*evaluateAtAbscissa(maxAbscissa);
|
||||
if (result >= 0.0f) {
|
||||
result = k_minMarginFactor;
|
||||
}
|
||||
return result;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float NormalLaw::yMax() {
|
||||
float maxAbscissa = m_parameter1;
|
||||
float result = k_maxMarginFactor*evaluateAtAbscissa(maxAbscissa);
|
||||
float result = evaluateAtAbscissa(maxAbscissa);
|
||||
if (result <= 0.0f || result == yMin()) {
|
||||
result = yMin() + 1.0f;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ const char * PoissonLaw::parameterDefinitionAtIndex(int index) {
|
||||
}
|
||||
|
||||
float PoissonLaw::xMin() {
|
||||
return -1.0f;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float PoissonLaw::xMax() {
|
||||
@@ -41,13 +41,12 @@ float PoissonLaw::xMax() {
|
||||
}
|
||||
|
||||
float PoissonLaw::yMin() {
|
||||
int maxAbscissa = (int)m_parameter1;
|
||||
return k_minMarginFactor*evaluateAtAbscissa(maxAbscissa);
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float PoissonLaw::yMax() {
|
||||
int maxAbscissa = (int)m_parameter1;
|
||||
return k_maxMarginFactor*evaluateAtAbscissa(maxAbscissa);
|
||||
return evaluateAtAbscissa(maxAbscissa);
|
||||
}
|
||||
|
||||
float PoissonLaw::evaluateAtAbscissa(float x) const {
|
||||
|
||||
@@ -48,11 +48,11 @@ float UniformLaw::xMax() {
|
||||
}
|
||||
|
||||
float UniformLaw::yMin() {
|
||||
return k_minMarginFactor*(1.0f/(m_parameter2-m_parameter1));
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float UniformLaw::yMax() {
|
||||
return k_maxMarginFactor*(1.0f/(m_parameter2-m_parameter1));
|
||||
return (1.0f/(m_parameter2-m_parameter1));
|
||||
}
|
||||
|
||||
float UniformLaw::evaluateAtAbscissa(float t) const {
|
||||
|
||||
@@ -12,6 +12,7 @@ LawCurveView::LawCurveView() :
|
||||
}
|
||||
|
||||
void LawCurveView::setLaw(Law * law) {
|
||||
setCurveViewWindow(law);
|
||||
m_law = law;
|
||||
}
|
||||
|
||||
@@ -45,21 +46,6 @@ void LawCurveView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}
|
||||
}
|
||||
|
||||
float LawCurveView::min(Axis axis) const {
|
||||
assert(axis == Axis::Horizontal || axis == Axis::Vertical);
|
||||
return (axis == Axis::Horizontal ? m_law->xMin() : m_law->yMin());
|
||||
}
|
||||
|
||||
float LawCurveView::max(Axis axis) const {
|
||||
assert(axis == Axis::Horizontal || axis == Axis::Vertical);
|
||||
return (axis == Axis::Horizontal ? m_law->xMax() : m_law->yMax());
|
||||
}
|
||||
|
||||
float LawCurveView::gridUnit(Axis axis) const {
|
||||
assert(axis == Axis::Horizontal);
|
||||
return m_law->gridUnit();
|
||||
}
|
||||
|
||||
char * LawCurveView::label(Axis axis, int index) const {
|
||||
assert(axis == Axis::Horizontal);
|
||||
return (char *)m_labels[index];
|
||||
|
||||
@@ -18,9 +18,6 @@ public:
|
||||
void reload();
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
protected:
|
||||
float min(Axis axis) const override;
|
||||
float max(Axis axis) const override;
|
||||
float gridUnit(Axis axis) const override;
|
||||
char * label(Axis axis, int index) const override;
|
||||
private:
|
||||
char m_labels[k_maxNumberOfXLabels][Constant::FloatBufferSizeInScientificMode];
|
||||
|
||||
@@ -12,7 +12,7 @@ App::App(Container * container) :
|
||||
m_boxController(BoxController(&m_boxAlternateEmptyViewController)),
|
||||
m_boxAlternateEmptyViewController(AlternateEmptyViewController(nullptr, &m_boxController, &m_boxController)),
|
||||
m_boxStackViewController(StackViewController(&m_tabViewController, &m_boxAlternateEmptyViewController)),
|
||||
m_histogramController(HistogramController(&m_histogramHeader, &m_histogramHeader)),
|
||||
m_histogramController(HistogramController(&m_histogramHeader, &m_histogramHeader, &m_data)),
|
||||
m_histogramHeader(HeaderViewController(&m_histogramAlternateEmptyViewController, &m_histogramController, &m_histogramController)),
|
||||
m_histogramAlternateEmptyViewController(AlternateEmptyViewController(nullptr, &m_histogramHeader, &m_histogramController)),
|
||||
m_histogramStackViewController(StackViewController(&m_tabViewController, &m_histogramAlternateEmptyViewController)),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "data.h"
|
||||
#include <float.h>
|
||||
|
||||
namespace Statistics {
|
||||
|
||||
@@ -22,7 +23,7 @@ int Data::sizeAtIndex(int index) {
|
||||
void Data::setValueAtIndex(float value, int index) {
|
||||
m_values[index] = value;
|
||||
if (index >= m_numberOfPairs) {
|
||||
m_sizes[index] = 0;
|
||||
m_sizes[index] = 1;
|
||||
m_numberOfPairs++;
|
||||
}
|
||||
}
|
||||
@@ -35,4 +36,66 @@ void Data::setSizeAtIndex(int size, int index) {
|
||||
}
|
||||
}
|
||||
|
||||
void Data::deletePairAtIndex(int index) {
|
||||
m_numberOfPairs--;
|
||||
for (int k = index; k < m_numberOfPairs; k++) {
|
||||
m_values[k] = m_values[k+1];
|
||||
m_sizes[k] = m_sizes[k+1];
|
||||
}
|
||||
m_values[m_numberOfPairs] = 0.0f;
|
||||
m_sizes[m_numberOfPairs] = 1;
|
||||
}
|
||||
|
||||
int Data::sizeOfValuesBetweenBounds(float lowerBound, float upperBound) const {
|
||||
int result = 0;
|
||||
for (int k = 0; k < m_numberOfPairs; k++) {
|
||||
if (m_values[k] < upperBound && lowerBound <= m_values[k]) {
|
||||
result += m_sizes[k];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float Data::xMin() {
|
||||
float valueMin = FLT_MAX;
|
||||
for (int k = 0; k < m_numberOfPairs; k++) {
|
||||
if (m_values[k] < valueMin) {
|
||||
valueMin = m_values[k];
|
||||
}
|
||||
}
|
||||
return valueMin;
|
||||
}
|
||||
|
||||
float Data::xMax() {
|
||||
float valueMax = -FLT_MAX;
|
||||
for (int k = 0; k < m_numberOfPairs; k++) {
|
||||
if (m_values[k] > valueMax) {
|
||||
valueMax = m_values[k];
|
||||
}
|
||||
}
|
||||
float valueMin = xMin();
|
||||
if (valueMax - valueMin > k_maxRangeValue) {
|
||||
valueMax = valueMin + 10.0f;
|
||||
}
|
||||
return valueMax;
|
||||
}
|
||||
|
||||
float Data::yMin() {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float Data::yMax() {
|
||||
float sizeMax = -FLT_MAX;
|
||||
for (int k = 0; k < m_numberOfPairs; k++) {
|
||||
if (m_sizes[k] > sizeMax) {
|
||||
sizeMax = m_sizes[k];
|
||||
}
|
||||
}
|
||||
return sizeMax;
|
||||
}
|
||||
|
||||
float Data::xGridUnit() {
|
||||
return computeGridUnit(Axis::X);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#ifndef STATISTICS_DATA_H
|
||||
#define STATISTICS_DATA_H
|
||||
|
||||
#include "../curve_view_window.h"
|
||||
|
||||
namespace Statistics {
|
||||
|
||||
class Data {
|
||||
class Data : public CurveViewWindow {
|
||||
public:
|
||||
Data();
|
||||
// Delete the implicit copy constructor: the object is heavy
|
||||
@@ -13,9 +15,18 @@ public:
|
||||
int sizeAtIndex(int index);
|
||||
void setValueAtIndex(float value, int index);
|
||||
void setSizeAtIndex(int size, int index);
|
||||
void deletePairAtIndex(int index);
|
||||
int sizeOfValuesBetweenBounds(float lowerBound, float upperBound) const;
|
||||
float xMin() override;
|
||||
// if the range of value is to wide, value max returns valueMin + 10
|
||||
float xMax() override;
|
||||
float yMin() override;
|
||||
float yMax() override;
|
||||
float xGridUnit() override;
|
||||
// TODO: decide the max number of elements after optimization
|
||||
constexpr static int k_maxNumberOfPairs = 500;
|
||||
private:
|
||||
constexpr static int k_maxRangeValue = 320;
|
||||
int m_sizes[k_maxNumberOfPairs];
|
||||
float m_values[k_maxNumberOfPairs];
|
||||
int m_numberOfPairs;
|
||||
|
||||
@@ -79,6 +79,18 @@ bool DataController::handleEvent(Ion::Events::Event event) {
|
||||
app()->setFirstResponder(tabController());
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Clear) {
|
||||
if (m_selectableTableView.selectedColumn() == 0) {
|
||||
m_data->deletePairAtIndex(m_selectableTableView.selectedRow()-1);
|
||||
m_selectableTableView.reloadData();
|
||||
} else {
|
||||
m_data->setSizeAtIndex(1, m_selectableTableView.selectedRow()-1);
|
||||
EvenOddEditableTextCell * myCell = (EvenOddEditableTextCell *)m_selectableTableView.cellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
|
||||
willDisplayCellAtLocation(myCell, m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
|
||||
myCell->editableTextCell()->textField()->handleEvent(Ion::Events::OK);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
namespace Statistics {
|
||||
|
||||
HistogramController::HistogramController(Responder * parentResponder, HeaderViewController * headerViewController) :
|
||||
HistogramController::HistogramController(Responder * parentResponder, HeaderViewController * headerViewController, Data * data) :
|
||||
ViewController(parentResponder),
|
||||
HeaderViewDelegate(headerViewController),
|
||||
m_view(SolidColorView(KDColorGreen)),
|
||||
m_settingButton(Button(this, "Reglages de l'histogramme",Invocation([](void * context, void * sender) {}, this))),
|
||||
m_selectedBin(0)
|
||||
m_selectedBin(0),
|
||||
m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,11 +50,14 @@ Button * HistogramController::buttonAtIndex(int index) {
|
||||
}
|
||||
|
||||
bool HistogramController::isEmpty() {
|
||||
if (m_data->numberOfPairs() == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char * HistogramController::emptyMessage() {
|
||||
return "Aucune donnée à tracer";
|
||||
return "Aucune donnee à tracer";
|
||||
}
|
||||
|
||||
Responder * HistogramController::defaultController() {
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
#define STATISTICS_HISTOGRAM_CONTROLLER_H
|
||||
|
||||
#include <escher.h>
|
||||
#include "data.h"
|
||||
|
||||
namespace Statistics {
|
||||
|
||||
class HistogramController : public ViewController, public HeaderViewDelegate, public AlternateEmptyViewDelegate {
|
||||
|
||||
public:
|
||||
HistogramController(Responder * parentResponder, HeaderViewController * headerViewController);
|
||||
HistogramController(Responder * parentResponder, HeaderViewController * headerViewController, Data * m_data);
|
||||
const char * title() const override;
|
||||
View * view() override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
@@ -24,6 +25,7 @@ private:
|
||||
SolidColorView m_view;
|
||||
Button m_settingButton;
|
||||
int m_selectedBin;
|
||||
Data * m_data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class EditableTextCell : public TableViewCell, public Responder {
|
||||
public:
|
||||
EditableTextCell(Responder * parentResponder, TextFieldDelegate * delegate, char * draftTextBuffer,
|
||||
float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor = KDColorWhite);
|
||||
TextField * textfield();
|
||||
TextField * textField();
|
||||
void reloadCell() override;
|
||||
const char * text() const;
|
||||
void setText(const char * textContent);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
class EvenOddEditableTextCell : public EvenOddCell, public Responder {
|
||||
public:
|
||||
EvenOddEditableTextCell(Responder * parentResponder, TextFieldDelegate * delegate, char * draftTextBuffer);
|
||||
EditableTextCell * editableTextCell();
|
||||
void reloadCell() override;
|
||||
const char * text() const;
|
||||
void setText(const char * textContent);
|
||||
|
||||
@@ -11,7 +11,7 @@ EditableTextCell::EditableTextCell(Responder * parentResponder, TextFieldDelegat
|
||||
{
|
||||
}
|
||||
|
||||
TextField * EditableTextCell::textfield() {
|
||||
TextField * EditableTextCell::textField() {
|
||||
return &m_textField;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,13 @@ EvenOddEditableTextCell::EvenOddEditableTextCell(Responder * parentResponder, Te
|
||||
{
|
||||
}
|
||||
|
||||
EditableTextCell * EvenOddEditableTextCell::editableTextCell() {
|
||||
return &m_editableCell;
|
||||
}
|
||||
|
||||
void EvenOddEditableTextCell::reloadCell() {
|
||||
EvenOddCell::reloadCell();
|
||||
m_editableCell.textfield()->setBackgroundColor(backgroundColor());
|
||||
m_editableCell.textField()->setBackgroundColor(backgroundColor());
|
||||
}
|
||||
|
||||
const char * EvenOddEditableTextCell::text() const {
|
||||
|
||||
Reference in New Issue
Block a user