mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
Compare commits
198 Commits
O1.19.1-E1
...
O1.19.2-E1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
651abf9c7b | ||
|
|
0b83604e3e | ||
|
|
9b1add66a4 | ||
|
|
15ecd45a76 | ||
|
|
0d56576f9c | ||
|
|
511a96f464 | ||
|
|
0f00bdda33 | ||
|
|
244b97e89b | ||
|
|
e5660635d6 | ||
|
|
3987167419 | ||
|
|
28224bd75e | ||
|
|
bc1eae17d7 | ||
|
|
642a7c7f61 | ||
|
|
7c612f35a8 | ||
|
|
d468f5e130 | ||
|
|
84bc46ca8c | ||
|
|
b3b6565410 | ||
|
|
ce33faad11 | ||
|
|
51eabf08e1 | ||
|
|
2c82460470 | ||
|
|
b290bed409 | ||
|
|
d247843da6 | ||
|
|
81284120af | ||
|
|
574eacb69c | ||
|
|
2f4064d92b | ||
|
|
2ac1396dd2 | ||
|
|
b2c95bcbbf | ||
|
|
61e7ec52e6 | ||
|
|
7d5568ff1a | ||
|
|
399cfffc83 | ||
|
|
89ef6ec71b | ||
|
|
f5e69395ee | ||
|
|
1c4f43c665 | ||
|
|
1c714a6ee6 | ||
|
|
6d10e9fdc2 | ||
|
|
bf7c3b1aab | ||
|
|
dc58b9692f | ||
|
|
1895b83251 | ||
|
|
f97f56c021 | ||
|
|
18d59d923a | ||
|
|
9a240bb0b4 | ||
|
|
1b768ba34a | ||
|
|
81170610eb | ||
|
|
8aa1930f80 | ||
|
|
fb3f6ab6f3 | ||
|
|
d0c5ac0343 | ||
|
|
15e5f7a285 | ||
|
|
89b54d424e | ||
|
|
7e73afc654 | ||
|
|
24cd5079d4 | ||
|
|
886fc98350 | ||
|
|
c4847b22cc | ||
|
|
bd3fa60594 | ||
|
|
4022cdfa60 | ||
|
|
d504564334 | ||
|
|
52b6508d6c | ||
|
|
7d48d4e7c4 | ||
|
|
53ec023ea0 | ||
|
|
659da1dff8 | ||
|
|
51da01aa11 | ||
|
|
b5d3070ef5 | ||
|
|
9e822e85e5 | ||
|
|
70335b7a47 | ||
|
|
bc8dc0c59c | ||
|
|
aaf71328ba | ||
|
|
7d60c6554e | ||
|
|
c69ec608e8 | ||
|
|
0ae81374d9 | ||
|
|
373a85f2b7 | ||
|
|
da1c6090b5 | ||
|
|
a0319905d7 | ||
|
|
d71ad9b288 | ||
|
|
3df8018943 | ||
|
|
a062c570d5 | ||
|
|
a3b1b51f75 | ||
|
|
a6773ad73b | ||
|
|
5ada80d03b | ||
|
|
6f3d3f62de | ||
|
|
6a796f5f7c | ||
|
|
c99bed6922 | ||
|
|
2b73c4c9aa | ||
|
|
131df18b00 | ||
|
|
735294b91b | ||
|
|
bd0b9f8a4a | ||
|
|
620ef3f570 | ||
|
|
169d6bf94d | ||
|
|
94fb5815f9 | ||
|
|
764cf1087a | ||
|
|
64c7688866 | ||
|
|
bf9d365ee8 | ||
|
|
6c3261b356 | ||
|
|
b8b3829ea4 | ||
|
|
51b3a007e5 | ||
|
|
df5c0752fb | ||
|
|
8bd01b600b | ||
|
|
d950e37b22 | ||
|
|
64bab33792 | ||
|
|
5e9543e3b7 | ||
|
|
2cdb5d38bf | ||
|
|
b36de49b48 | ||
|
|
fca1dde44d | ||
|
|
693cff1e23 | ||
|
|
964541d645 | ||
|
|
625afcfd42 | ||
|
|
46647cc35c | ||
|
|
3245a0060e | ||
|
|
f84b3dc5c1 | ||
|
|
7c79c70890 | ||
|
|
c0f73e97d2 | ||
|
|
43bf89c6e4 | ||
|
|
62324b9cac | ||
|
|
ca89c06ffe | ||
|
|
fd629de548 | ||
|
|
eadfe4aa56 | ||
|
|
edbd879b4b | ||
|
|
05d24e0c61 | ||
|
|
f31de20039 | ||
|
|
3da284913d | ||
|
|
06905c70e4 | ||
|
|
ea796d9b51 | ||
|
|
5f5636fe4d | ||
|
|
1809037273 | ||
|
|
dab8880fbd | ||
|
|
c5b21cff71 | ||
|
|
81cd18ad67 | ||
|
|
bfe2fc1a04 | ||
|
|
5f8f1d96ee | ||
|
|
8c370b409c | ||
|
|
d2f40130b2 | ||
|
|
a8783fe21f | ||
|
|
e828491171 | ||
|
|
29b4c75227 | ||
|
|
5c70fdc7a6 | ||
|
|
d222d13156 | ||
|
|
da6306cb11 | ||
|
|
f00bd4d1c5 | ||
|
|
1e11650122 | ||
|
|
e636a2c315 | ||
|
|
313cbf6767 | ||
|
|
97d94d9e56 | ||
|
|
13b2deb714 | ||
|
|
576d1dcd6b | ||
|
|
175af27ea9 | ||
|
|
879c1e3bf1 | ||
|
|
d431642e60 | ||
|
|
a2e9d8efd6 | ||
|
|
9936d99411 | ||
|
|
12a5f5499c | ||
|
|
5407709798 | ||
|
|
515405a5df | ||
|
|
eadcf0b6f9 | ||
|
|
ebdac63681 | ||
|
|
d50511f1be | ||
|
|
90f2e5beed | ||
|
|
9ab3558cfe | ||
|
|
1242258992 | ||
|
|
4a4ba52e38 | ||
|
|
18f3054b50 | ||
|
|
a7d419c4bd | ||
|
|
8168a125e6 | ||
|
|
702772a7c9 | ||
|
|
53705fb333 | ||
|
|
aab8974934 | ||
|
|
2bf83c43a8 | ||
|
|
8a27c81a83 | ||
|
|
ef249b0bdb | ||
|
|
79f3ee43bc | ||
|
|
1ca902c129 | ||
|
|
037fa088e9 | ||
|
|
d64e58b9dc | ||
|
|
8337e36f46 | ||
|
|
ed98218e7b | ||
|
|
aa4a33d849 | ||
|
|
afb1d18d65 | ||
|
|
f0ef84b3bc | ||
|
|
55bb3f677a | ||
|
|
0a92579571 | ||
|
|
04794dd26f | ||
|
|
7ee8c31c70 | ||
|
|
24fa8b28a9 | ||
|
|
6b527d3b00 | ||
|
|
e1624c79aa | ||
|
|
7a633b1e75 | ||
|
|
fccd72b757 | ||
|
|
c1215063ee | ||
|
|
cf84a30768 | ||
|
|
ad672f9111 | ||
|
|
d1c8d6f11c | ||
|
|
5ca6b7dbf8 | ||
|
|
bd6f30fda5 | ||
|
|
1dc6e77049 | ||
|
|
dfe51df321 | ||
|
|
035a0377bd | ||
|
|
4f76e4418f | ||
|
|
a06660ee25 | ||
|
|
aae5e49c01 | ||
|
|
8a4e9520f3 | ||
|
|
175e38711e |
2
.github/workflows/ci-workflow.yml
vendored
2
.github/workflows/ci-workflow.yml
vendored
@@ -66,7 +66,7 @@ jobs:
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-simulator-web.zip
|
||||
path: output/release/simulator/web/simulator.zip
|
||||
path: output/release/simulator/web/epsilon.zip
|
||||
- run: make -j2 PLATFORM=simulator TARGET=web test.headless.js
|
||||
build-simulator-linux:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,4 +3,5 @@
|
||||
build/device/**/*.pyc
|
||||
epsilon.elf
|
||||
.vscode
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
.gradle
|
||||
|
||||
@@ -16,7 +16,7 @@ Omega is a fork of Numworks' Epsilon, the OS that runs on their calculator, whic
|
||||
- An app for RPN
|
||||
- A periodic table app + all of the molar masses for the elements in the toolbox
|
||||
- More steps for brightness (16 instead of 5)
|
||||
- 32 KB Python heap instead of 16 KB
|
||||
- ~~32 KB Python heap instead of 16 KB~~ Now available on Epsilon `>=13.2.0`!
|
||||
- And more...
|
||||
|
||||
The main new features are listed [here](https://github.com/Omega-Numworks/Omega/wiki/Main-features), and the complete changelog can be found [here](https://github.com/quentinguidee/Omega/wiki/Complete-changelog).
|
||||
|
||||
@@ -6,7 +6,7 @@ using namespace Poincare;
|
||||
namespace Calculation {
|
||||
|
||||
ComplexGraphView::ComplexGraphView(ComplexModel * complexModel) :
|
||||
CurveView(complexModel),
|
||||
LabeledCurveView(complexModel),
|
||||
m_complex(complexModel)
|
||||
{
|
||||
}
|
||||
@@ -24,13 +24,8 @@ void ComplexGraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
float imag = m_complex->imag();
|
||||
|
||||
assert(!std::isnan(real) && !std::isnan(imag) && !std::isinf(real) && !std::isinf(imag));
|
||||
/* Draw the segment from the origin to the dot (real, imag) of equation
|
||||
* x(t) = t*real and y(t) = t*imag with t in [0,1] */
|
||||
drawCurve(ctx, rect, 0.0f, 1.0f, 0.01f,
|
||||
[](float t, void * model, void * context) {
|
||||
ComplexModel * complexModel = (ComplexModel *)model;
|
||||
return Poincare::Coordinate2D<float>(complexModel->real()*t, complexModel->imag()*t);
|
||||
}, m_complex, nullptr, false, Palette::GreyDark, false);
|
||||
// Draw the segment from the origin to the dot (real, imag)
|
||||
drawSegment(ctx, rect, 0.0f, 0.0f, m_complex->real(), m_complex->imag(), Palette::GreyDark, false);
|
||||
|
||||
/* Draw the partial ellipse indicating the angle θ
|
||||
* - the ellipse parameters are a = |real|/5 and b = |imag|/5,
|
||||
@@ -66,8 +61,8 @@ void ComplexGraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}, ¶meters, &th, false, Palette::GreyDark, false);
|
||||
|
||||
// Draw dashed segment to indicate real and imaginary
|
||||
drawSegment(ctx, rect, Axis::Vertical, real, 0.0f, imag, Palette::Red, 1, 3);
|
||||
drawSegment(ctx, rect, Axis::Horizontal, imag, 0.0f, real, Palette::Red, 1, 3);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, real, 0.0f, imag, Palette::Red, 1, 3);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, imag, 0.0f, real, Palette::Red, 1, 3);
|
||||
|
||||
// Draw complex position on the plan
|
||||
drawDot(ctx, rect, real, imag, Palette::Red, Size::Large);
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
#ifndef CALCULATION_ADDITIONAL_OUTPUTS_COMPLEX_GRAPH_CELL_H
|
||||
#define CALCULATION_ADDITIONAL_OUTPUTS_COMPLEX_GRAPH_CELL_H
|
||||
|
||||
#include "../../shared/curve_view.h"
|
||||
#include "../../shared/labeled_curve_view.h"
|
||||
#include "complex_model.h"
|
||||
#include "illustration_cell.h"
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
class ComplexGraphView : public Shared::CurveView {
|
||||
class ComplexGraphView : public Shared::LabeledCurveView {
|
||||
public:
|
||||
ComplexGraphView(ComplexModel * complexModel);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
private:
|
||||
char * label(Axis axis, int index) const override {
|
||||
return (axis == Axis::Horizontal ? (char *)m_xLabels[index] : (char *)m_yLabels[index]);
|
||||
}
|
||||
// '-' + significant digits + ".E-" + 2 digits (the represented dot is a float, so it is bounded by 1E38 and 1E-38
|
||||
size_t labelMaxGlyphLengthSize() const override { return 1 + Poincare::Preferences::VeryShortNumberOfSignificantDigits + 3 + 2; }
|
||||
char m_xLabels[k_maxNumberOfXLabels][k_labelBufferMaxSize];
|
||||
char m_yLabels[k_maxNumberOfYLabels][k_labelBufferMaxSize];
|
||||
ComplexModel * m_complex;
|
||||
};
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ void TrigonometryGraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
return Poincare::Coordinate2D<float>(std::cos(t), std::sin(t));
|
||||
}, nullptr, nullptr, true, Palette::GreyDark, false);
|
||||
// Draw dashed segment to indicate sine and cosine
|
||||
drawSegment(ctx, rect, Axis::Vertical, c, 0.0f, s, Palette::Red, 1, 3);
|
||||
drawSegment(ctx, rect, Axis::Horizontal, s, 0.0f, c, Palette::Red, 1, 3);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, c, 0.0f, s, Palette::Red, 1, 3);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, s, 0.0f, c, Palette::Red, 1, 3);
|
||||
// Draw angle position on the circle
|
||||
drawDot(ctx, rect, c, s, Palette::Red, Size::Large);
|
||||
// Draw graduations
|
||||
|
||||
@@ -12,7 +12,6 @@ public:
|
||||
TrigonometryGraphView(TrigonometryModel * model);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
private:
|
||||
char * label(Axis axis, int index) const override { return nullptr; }
|
||||
TrigonometryModel * m_model;
|
||||
};
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ KDCoordinate Calculation::height(Context * context, bool expanded, bool allExpre
|
||||
singleLine = exactOutputWidth + inputWidth < maxWidth - 40;
|
||||
if (singleLine && Poincare::Preferences::sharedPreferences()->resultDisplay() == Poincare::Preferences::ResultDisplay::Compact && !allExpressionsInline) {
|
||||
KDCoordinate exactOutputBaseline = exactLayout.baseline();
|
||||
result = maxCoordinate(inputBaseline, exactOutputBaseline) + maxCoordinate(inputHeight - inputBaseline, exactOutputHeight-exactOutputBaseline);
|
||||
result = maxCoordinate(inputBaseline, exactOutputBaseline) + maxCoordinate(inputHeight - inputBaseline, exactOutputHeight-exactOutputBaseline) + singleMargin;
|
||||
} else {
|
||||
if (allExpressionsInline) {
|
||||
KDCoordinate exactOutputBaseline = exactLayout.baseline();
|
||||
|
||||
@@ -13,12 +13,15 @@ PythonAbs = "Absolute/r Wert/Größe"
|
||||
PythonAcos = "Arkuskosinus"
|
||||
PythonAcosh = "Hyperbelkosinus"
|
||||
PythonAppend = "Hängt x an das Ende der Liste"
|
||||
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
|
||||
PythonAsin = "Arkussinus"
|
||||
PythonAsinh = "Hyperbelsinus"
|
||||
PythonAtan = "Arkustangens"
|
||||
PythonAtan2 = "Gib atan(y/x)"
|
||||
PythonAtanh = "Hyperbeltangens"
|
||||
PythonBin = "Ganzzahl nach binär"
|
||||
PythonAxis = "Set axes to (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Draw a bar plot with x values"
|
||||
PythonBin = "Ganzzahl nach binär konvertieren"
|
||||
PythonCeil = "Aufrundung"
|
||||
PythonChoice = "Zufallszahl aus der Liste"
|
||||
PythonClear = "Leere die Liste"
|
||||
@@ -46,12 +49,15 @@ PythonFrExp = "Rest und Exponent von x"
|
||||
PythonGamma = "Gammafunktion"
|
||||
PythonGetPixel = "Farbe von Pixel (x,y)"
|
||||
PythonGetrandbits = "Ganzzahl mit k zufälligen Bits"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
PythonHex = "Ganzzahl zu Hexadecimal"
|
||||
PythonHist = "Draw the histogram of x"
|
||||
PythonImportCmath = "cmath Modul importieren"
|
||||
PythonImportIon = "ion Modul importieren"
|
||||
PythonImportKandinsky = "kandinsky Modul importieren"
|
||||
PythonImportRandom = "random Modul importieren"
|
||||
PythonImportMath = "math Modul importieren"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportTime = "time Modul importieren"
|
||||
PythonImportTurtle = "turtle Modul importieren"
|
||||
PythonIndex = "Index, bei dem x zuerst vorkommt"
|
||||
@@ -117,12 +123,14 @@ PythonLog = "Logarithm to base a"
|
||||
PythonLog10 = "Logarithm to base 10"
|
||||
PythonLog2 = "Logarithm to base 2"
|
||||
PythonMathFunction = "math module function prefix"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Fractional and integer parts of x"
|
||||
PythonMonotonic = "Value of a monotonic clock"
|
||||
PythonOct = "Convert integer to octal"
|
||||
PythonPhase = "Phase of z"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
PythonPolar = "z in polar coordinates"
|
||||
PythonPop = "Remove and return the last item"
|
||||
PythonPower = "x raised to the power y"
|
||||
@@ -138,9 +146,11 @@ PythonRect = "z in cartesian coordinates"
|
||||
PythonRemove = "Remove the first occurrence of x"
|
||||
PythonReverse = "Reverse the elements of the list"
|
||||
PythonRound = "Round to n digits"
|
||||
PythonScatter = "Draw a scatter plot of y versus x"
|
||||
PythonSeed = "Initialize random number generator"
|
||||
PythonSetPixel = "Color pixel (x,y)"
|
||||
PythonSin = "Sinus"
|
||||
PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hyperbolic sine"
|
||||
PythonSleep = "Suspend the execution for t seconds"
|
||||
PythonSort = "Sort the list"
|
||||
@@ -148,6 +158,7 @@ PythonSqrt = "Wurzel"
|
||||
PythonSum = "Sum the items of a list"
|
||||
PythonTan = "Tangens"
|
||||
PythonTanh = "Hyperbolic tangent"
|
||||
PythonText = "Display a text at (x,y) coordinates"
|
||||
PythonTimeFunction = "time module function prefix"
|
||||
PythonTrunc = "x truncated to an integer"
|
||||
PythonTurtleBackward = "Move backward by x pixels"
|
||||
|
||||
@@ -13,11 +13,14 @@ PythonAbs = "Absolute value/Magnitude"
|
||||
PythonAcos = "Arc cosine"
|
||||
PythonAcosh = "Arc hyperbolic cosine"
|
||||
PythonAppend = "Add x to the end of the list"
|
||||
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
|
||||
PythonAsin = "Arc sine"
|
||||
PythonAsinh = "Arc hyperbolic sine"
|
||||
PythonAtan = "Arc tangent"
|
||||
PythonAtan2 = "Return atan(y/x)"
|
||||
PythonAtanh = "Arc hyperbolic tangent"
|
||||
PythonAxis = "Set axes to (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Draw a bar plot with x values"
|
||||
PythonBin = "Convert integer to binary"
|
||||
PythonCeil = "Ceiling"
|
||||
PythonChoice = "Random number in the list"
|
||||
@@ -46,12 +49,15 @@ PythonFrExp = "Mantissa and exponent of x"
|
||||
PythonGamma = "Gamma function"
|
||||
PythonGetPixel = "Return pixel (x,y) color"
|
||||
PythonGetrandbits = "Integer with k random bits"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
PythonHex = "Convert integer to hexadecimal"
|
||||
PythonHist = "Draw the histogram of x"
|
||||
PythonImportCmath = "Import cmath module"
|
||||
PythonImportIon = "Import ion module"
|
||||
PythonImportKandinsky = "Import kandinsky module"
|
||||
PythonImportRandom = "Import random module"
|
||||
PythonImportMath = "Import math module"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportTurtle = "Import turtle module"
|
||||
PythonIndex = "Index of the first x occurrence"
|
||||
@@ -117,12 +123,14 @@ PythonLog = "Logarithm to base a"
|
||||
PythonLog10 = "Logarithm to base 10"
|
||||
PythonLog2 = "Logarithm to base 2"
|
||||
PythonMathFunction = "math module function prefix"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Fractional and integer parts of x"
|
||||
PythonMonotonic = "Value of a monotonic clock"
|
||||
PythonOct = "Convert integer to octal"
|
||||
PythonPhase = "Phase of z"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
PythonPolar = "z in polar coordinates"
|
||||
PythonPop = "Remove and return the last item"
|
||||
PythonPower = "x raised to the power y"
|
||||
@@ -138,8 +146,10 @@ PythonRect = "z in cartesian coordinates"
|
||||
PythonRemove = "Remove the first occurrence of x"
|
||||
PythonReverse = "Reverse the elements of the list"
|
||||
PythonRound = "Round to n digits"
|
||||
PythonScatter = "Draw a scatter plot of y versus x"
|
||||
PythonSeed = "Initialize random number generator"
|
||||
PythonSetPixel = "Color pixel (x,y)"
|
||||
PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hyperbolic sine"
|
||||
PythonSleep = "Suspend the execution for t seconds"
|
||||
@@ -148,6 +158,7 @@ PythonSqrt = "Square root"
|
||||
PythonSum = "Sum the items of a list"
|
||||
PythonTan = "Tangent"
|
||||
PythonTanh = "Hyperbolic tangent"
|
||||
PythonText = "Display a text at (x,y) coordinates"
|
||||
PythonTimeFunction = "time module function prefix"
|
||||
PythonTrunc = "x truncated to an integer"
|
||||
PythonTurtleBackward = "Move backward by x pixels"
|
||||
|
||||
@@ -13,11 +13,14 @@ PythonAbs = "Absolute value/Magnitude"
|
||||
PythonAcos = "Arc cosine"
|
||||
PythonAcosh = "Arc hyperbolic cosine"
|
||||
PythonAppend = "Add x to the end of the list"
|
||||
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
|
||||
PythonAsin = "Arc sine"
|
||||
PythonAsinh = "Arc hyperbolic sine"
|
||||
PythonAtan = "Arc tangent"
|
||||
PythonAtan2 = "Return atan(y/x)"
|
||||
PythonAtanh = "Arc hyperbolic tangent"
|
||||
PythonAxis = "Set axes to (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Draw a bar plot with x values"
|
||||
PythonBin = "Convert integer to binary"
|
||||
PythonCeil = "Ceiling"
|
||||
PythonChoice = "Random number in the list"
|
||||
@@ -46,12 +49,15 @@ PythonFrExp = "Mantissa and exponent of x"
|
||||
PythonGamma = "Gamma function"
|
||||
PythonGetPixel = "Return pixel (x,y) color"
|
||||
PythonGetrandbits = "Integer with k random bits"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
PythonHex = "Convert integer to hexadecimal"
|
||||
PythonHist = "Draw the histogram of x"
|
||||
PythonImportCmath = "Import cmath module"
|
||||
PythonImportIon = "Import ion module"
|
||||
PythonImportKandinsky = "Import kandinsky module"
|
||||
PythonImportRandom = "Import random module"
|
||||
PythonImportMath = "Import math module"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportTurtle = "Import turtle module"
|
||||
PythonIndex = "Index of the first x occurrence"
|
||||
@@ -117,12 +123,14 @@ PythonLog = "Logarithm to base a"
|
||||
PythonLog10 = "Logarithm to base 10"
|
||||
PythonLog2 = "Logarithm to base 2"
|
||||
PythonMathFunction = "math module function prefix"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Fractional and integer parts of x"
|
||||
PythonMonotonic = "Value of a monotonic clock"
|
||||
PythonOct = "Convert integer to octal"
|
||||
PythonPhase = "Phase of z"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
PythonPolar = "z in polar coordinates"
|
||||
PythonPop = "Remove and return the last item"
|
||||
PythonPower = "x raised to the power y"
|
||||
@@ -138,8 +146,10 @@ PythonRect = "z in cartesian coordinates"
|
||||
PythonRemove = "Remove the first occurrence of x"
|
||||
PythonReverse = "Reverse the elements of the list"
|
||||
PythonRound = "Round to n digits"
|
||||
PythonScatter = "Draw a scatter plot of y versus x"
|
||||
PythonSeed = "Initialize random number generator"
|
||||
PythonSetPixel = "Color pixel (x,y)"
|
||||
PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hyperbolic sine"
|
||||
PythonSleep = "Suspend the execution for t seconds"
|
||||
@@ -148,6 +158,7 @@ PythonSqrt = "Square root"
|
||||
PythonSum = "Sum the items of a list"
|
||||
PythonTan = "Tangent"
|
||||
PythonTanh = "Hyperbolic tangent"
|
||||
PythonText = "Display a text at (x,y) coordinates"
|
||||
PythonTimeFunction = "time module function prefix"
|
||||
PythonTrunc = "x truncated to an integer"
|
||||
PythonTurtleBackward = "Move backward by x pixels"
|
||||
|
||||
@@ -13,11 +13,14 @@ PythonAbs = "Valeur absolue/Module"
|
||||
PythonAcos = "Arc cosinus"
|
||||
PythonAcosh = "Arc cosinus hyperbolique"
|
||||
PythonAppend = "Insère x à la fin de la liste"
|
||||
PythonArrow = "Flèche de (x,y) à (x+dx,y+dy)"
|
||||
PythonAsin = "Arc sinus"
|
||||
PythonAsinh = "Arc sinus hyperbolique"
|
||||
PythonAtan = "Arc tangente"
|
||||
PythonAtan2 = "Calcul de atan(y/x)"
|
||||
PythonAtanh = "Arc tangente hyperbolique"
|
||||
PythonAxis = "Met les axes (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Diagramme en barres de la liste x"
|
||||
PythonBin = "Conversion d'un entier en binaire"
|
||||
PythonCeil = "Plafond"
|
||||
PythonChoice = "Nombre aléatoire dans la liste"
|
||||
@@ -46,12 +49,15 @@ PythonFrExp = "Mantisse et exposant de x : (m,e)"
|
||||
PythonGamma = "Fonction gamma"
|
||||
PythonGetPixel = "Renvoie la couleur du pixel (x,y)"
|
||||
PythonGetrandbits = "Nombre aléatoire sur k bits"
|
||||
PythonGrid = "Affiche ou masque la grille"
|
||||
PythonHex = "Conversion entier en hexadécimal"
|
||||
PythonHist = "Histogramme de la liste x"
|
||||
PythonImportCmath = "Importation du module cmath"
|
||||
PythonImportIon = "Importation du module ion"
|
||||
PythonImportKandinsky = "Importation du module kandinsky"
|
||||
PythonImportRandom = "Importation du module random"
|
||||
PythonImportMath = "Importation du module math"
|
||||
PythonImportMatplotlibPyplot = "Importation de matplotlib.pyplot"
|
||||
PythonImportTurtle = "Importation du module turtle"
|
||||
PythonImportTime = "Importation du module time"
|
||||
PythonIndex = "Indice première occurrence de x"
|
||||
@@ -117,12 +123,14 @@ PythonLog = "Logarithme de base a"
|
||||
PythonLog10 = "Logarithme décimal"
|
||||
PythonLog2 = "Logarithme de base 2"
|
||||
PythonMathFunction = "Préfixe fonction du module math"
|
||||
PythonMatplotlibPyplotFunction = "Préfixe du module matplotlib.pyplot"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Parties fractionnaire et entière"
|
||||
PythonMonotonic = "Renvoie la valeur de l'horloge"
|
||||
PythonOct = "Conversion en octal"
|
||||
PythonPhase = "Argument de z"
|
||||
PythonPlot = "Trace y en fonction de x"
|
||||
PythonPolar = "Conversion en polaire"
|
||||
PythonPop = "Supprime le dernier élément"
|
||||
PythonPower = "x à la puissance y"
|
||||
@@ -138,8 +146,10 @@ PythonRect = "Conversion en algébrique"
|
||||
PythonRemove = "Supprime le premier x de la liste"
|
||||
PythonReverse = "Inverse les éléments de la liste"
|
||||
PythonRound = "Arrondi à n décimales"
|
||||
PythonScatter = "Nuage des points (x,y)"
|
||||
PythonSeed = "Initialiser générateur aléatoire"
|
||||
PythonSetPixel = "Colore le pixel (x,y)"
|
||||
PythonShow = "Affiche la figure"
|
||||
PythonSin = "Sinus"
|
||||
PythonSinh = "Sinus hyperbolique"
|
||||
PythonSleep = "Suspend l'exécution t secondes"
|
||||
@@ -148,6 +158,7 @@ PythonSqrt = "Racine carrée"
|
||||
PythonSum = "Somme des éléments de la liste"
|
||||
PythonTan = "Tangente"
|
||||
PythonTanh = "Tangente hyperbolique"
|
||||
PythonText = "Affiche un texte en (x,y)"
|
||||
PythonTimeFunction = "Préfixe fonction module time"
|
||||
PythonTrunc = "Troncature entière"
|
||||
PythonTurtleBackward = "Recule de x pixels"
|
||||
|
||||
@@ -13,11 +13,14 @@ PythonAbs = "Abszolút érték / nagyság"
|
||||
PythonAcos = "Arc koszinusz"
|
||||
PythonAcosh = "Íves hiperbolikus koszinusz"
|
||||
PythonAppend = "x hozzáadása a lista végéhez"
|
||||
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
|
||||
PythonAsin = "Arc szinusz"
|
||||
PythonAsinh = "Íves hiperbolikus szinusz"
|
||||
PythonAtan = "Arc érintö"
|
||||
PythonAtan2 = "Visszatérés atan (y / x)"
|
||||
PythonAtanh = "Arc hiperbolikus érintö"
|
||||
PythonAxis = "Set axes to (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Draw a bar plot with x values"
|
||||
PythonBin = "Egész szám konvertálása binárisra"
|
||||
PythonCeil = "Mennyezet"
|
||||
PythonChoice = "Véletlenszerü szám a listában"
|
||||
@@ -46,12 +49,15 @@ PythonFrExp = "Mantissa és az x exponense"
|
||||
PythonGamma = "Gamma funkció"
|
||||
PythonGetPixel = "Visszatérési pixel (x, y) szín"
|
||||
PythonGetrandbits = "Egész szám k véletlen bittel"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
PythonHex = "Egész szám konvertálása hexadecimálisra"
|
||||
PythonHist = "Draw the histogram of x"
|
||||
PythonImportCmath = "cmath modul importálása"
|
||||
PythonImportIon = "Ion modul importálása"
|
||||
PythonImportKandinsky = "Kandinsky modul importálása"
|
||||
PythonImportRandom = "Véletlenszerü modul importálása"
|
||||
PythonImportMath = "Import matematikai modul"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportTime = "Idömodul importálása"
|
||||
PythonImportTurtle = "Import teknös modul"
|
||||
PythonIndex = "Az elsö x esemény indexe"
|
||||
@@ -117,12 +123,14 @@ PythonLog = "Logaritmus az alap"
|
||||
PythonLog10 = "Logaritmus az alaphoz 10"
|
||||
PythonLog2 = "Logaritmus az alaphoz 2"
|
||||
PythonMathFunction = "matematikai modul funkció elötag"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Az x tört és egész részei"
|
||||
PythonMonotonic = "A monoton óra értéke"
|
||||
PythonOct = "Egész szám konvertálása oktális értékre"
|
||||
PythonPhase = "z fázis"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
PythonPolar = "z poláris koordinátákban"
|
||||
PythonPop = "Az utolsó elem eltávolítása és visszaküldése"
|
||||
PythonPower = "x emelve az y teljesítményre"
|
||||
@@ -138,8 +146,10 @@ PythonRect = "z derékszögü koordinátákban"
|
||||
PythonRemove = "Távolítsa el az x elsö elöfordulását"
|
||||
PythonReverse = "A lista elemeinek megfordítása"
|
||||
PythonRound = "N számjegyre kerekítve"
|
||||
PythonScatter = "Draw a scatter plot of y versus x"
|
||||
PythonSeed = "Inicializálja a véletlenszám-generátort"
|
||||
PythonSetPixel = "Színes pixel (x, y)"
|
||||
PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hiperbolikus szinusz"
|
||||
PythonSleep = "A végrehajtás felfüggesztése t másodpercre"
|
||||
@@ -148,6 +158,7 @@ PythonSqrt = "Négyzetgyök"
|
||||
PythonSum = "Összegzi a lista elemeit"
|
||||
PythonTan = "Érintö"
|
||||
PythonTanh = "Hiperbolikus érintö"
|
||||
PythonText = "Display a text at (x,y) coordinates"
|
||||
PythonTimeFunction = "idömodul funkció elötag"
|
||||
PythonTrunc = "x egészre csonkítva"
|
||||
PythonTurtleBackward = "Visszalépés x pixelrel"
|
||||
|
||||
@@ -13,11 +13,14 @@ PythonAbs = "Absolute value/Magnitude"
|
||||
PythonAcos = "Arc cosine"
|
||||
PythonAcosh = "Arc hyperbolic cosine"
|
||||
PythonAppend = "Add x to the end of the list"
|
||||
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
|
||||
PythonAsin = "Arc sine"
|
||||
PythonAsinh = "Arc hyperbolic sine"
|
||||
PythonAtan = "Arc tangent"
|
||||
PythonAtan2 = "Return atan(y/x)"
|
||||
PythonAtanh = "Arc hyperbolic tangent"
|
||||
PythonAxis = "Set axes to (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Draw a bar plot with x values"
|
||||
PythonBin = "Convert integer to binary"
|
||||
PythonCeil = "Ceiling"
|
||||
PythonChoice = "Random number in the list"
|
||||
@@ -46,12 +49,15 @@ PythonFrExp = "Mantissa and exponent of x"
|
||||
PythonGamma = "Gamma function"
|
||||
PythonGetPixel = "Return pixel (x,y) color"
|
||||
PythonGetrandbits = "Integer with k random bits"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
PythonHex = "Convert integer to hexadecimal"
|
||||
PythonHist = "Draw the histogram of x"
|
||||
PythonImportCmath = "Import cmath module"
|
||||
PythonImportIon = "Import ion module"
|
||||
PythonImportKandinsky = "Import kandinsky module"
|
||||
PythonImportRandom = "Import random module"
|
||||
PythonImportMath = "Import math module"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportTurtle = "Import turtle module"
|
||||
PythonIndex = "Index of the first x occurrence"
|
||||
@@ -117,12 +123,14 @@ PythonLog = "Logarithm to base a"
|
||||
PythonLog10 = "Logarithm to base 10"
|
||||
PythonLog2 = "Logarithm to base 2"
|
||||
PythonMathFunction = "math module function prefix"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Fractional and integer parts of x"
|
||||
PythonMonotonic = "Value of a monotonic clock"
|
||||
PythonOct = "Convert integer to octal"
|
||||
PythonPhase = "Phase of z"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
PythonPolar = "z in polar coordinates"
|
||||
PythonPop = "Remove and return the last item"
|
||||
PythonPower = "x raised to the power y"
|
||||
@@ -138,8 +146,10 @@ PythonRect = "z in cartesian coordinates"
|
||||
PythonRemove = "Remove the first occurrence of x"
|
||||
PythonReverse = "Reverse the elements of the list"
|
||||
PythonRound = "Round to n digits"
|
||||
PythonScatter = "Draw a scatter plot of y versus x"
|
||||
PythonSeed = "Initialize random number generator"
|
||||
PythonSetPixel = "Color pixel (x,y)"
|
||||
PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hyperbolic sine"
|
||||
PythonSleep = "Suspend the execution for t seconds"
|
||||
@@ -148,6 +158,7 @@ PythonSqrt = "Square root"
|
||||
PythonSum = "Sum the items of a list"
|
||||
PythonTan = "Tangent"
|
||||
PythonTanh = "Hyperbolic tangent"
|
||||
PythonText = "Display a text at (x,y) coordinates"
|
||||
PythonTimeFunction = "time module function prefix"
|
||||
PythonTrunc = "x truncated to an integer"
|
||||
PythonTurtleBackward = "Move backward by x pixels"
|
||||
|
||||
@@ -12,11 +12,15 @@ PythonCommandAcos = "acos(x)"
|
||||
PythonCommandAcosh = "acosh(x)"
|
||||
PythonCommandAppend = "list.append(x)"
|
||||
PythonCommandAppendWithoutArg = ".append(\x11)"
|
||||
PythonCommandArrow = "arrow(x,y,dx,dy)"
|
||||
PythonCommandAsin = "asin(x)"
|
||||
PythonCommandAsinh = "asinh(x)"
|
||||
PythonCommandAtan = "atan(x)"
|
||||
PythonCommandAtan2 = "atan2(y,x)"
|
||||
PythonCommandAtanh = "atanh(x)"
|
||||
PythonCommandAxis = "axis((xmin,xmax,ymin,ymax))"
|
||||
PythonCommandAxisWithoutArg = "axis(\x11)"
|
||||
PythonCommandBar = "bar(x,height)"
|
||||
PythonCommandBin = "bin(x)"
|
||||
PythonCommandCeil = "ceil(x)"
|
||||
PythonCommandChoice = "choice(list)"
|
||||
@@ -52,13 +56,16 @@ PythonCommandFrExp = "frexp(x)"
|
||||
PythonCommandGamma = "gamma(x)"
|
||||
PythonCommandGetPixel = "get_pixel(x,y)"
|
||||
PythonCommandGetrandbits = "getrandbits(k)"
|
||||
PythonCommandGrid = "grid()"
|
||||
PythonCommandHex = "hex(x)"
|
||||
PythonCommandHist = "hist(x,bins)"
|
||||
PythonCommandImag = "z.imag"
|
||||
PythonCommandImagWithoutArg = ".imag"
|
||||
PythonCommandImportFromCmath = "from cmath import *"
|
||||
PythonCommandImportFromIon = "from ion import *"
|
||||
PythonCommandImportFromKandinsky = "from kandinsky import *"
|
||||
PythonCommandImportFromMath = "from math import *"
|
||||
PythonCommandImportFromMatplotlibPyplot = "from matplotlib.pyplot import *"
|
||||
PythonCommandImportFromRandom = "from random import *"
|
||||
PythonCommandImportFromTime = "from time import *"
|
||||
PythonCommandImportFromTurtle = "from turtle import *"
|
||||
@@ -66,6 +73,7 @@ PythonCommandImportCmath = "import cmath"
|
||||
PythonCommandImportIon = "import ion"
|
||||
PythonCommandImportKandinsky = "import kandinsky"
|
||||
PythonCommandImportMath = "import math"
|
||||
PythonCommandImportMatplotlibPyplot = "import matplotlib.pyplot"
|
||||
PythonCommandImportRandom = "import random"
|
||||
PythonCommandImportTime = "import time"
|
||||
PythonCommandImportTurtle = "import turtle"
|
||||
@@ -138,12 +146,15 @@ PythonCommandLog2 = "log2(x)"
|
||||
PythonCommandLogComplex = "log(z,a)"
|
||||
PythonCommandMathFunction = "math.function"
|
||||
PythonCommandMathFunctionWithoutArg = "math.\x11"
|
||||
PythonCommandMatplotlibPyplotFunction = "matplotlib.pyplot.function"
|
||||
PythonCommandMatplotlibPyplotFunctionWithoutArg = "matplotlib.pyplot.\x11"
|
||||
PythonCommandMax = "max(list)"
|
||||
PythonCommandMin = "min(list)"
|
||||
PythonCommandModf = "modf(x)"
|
||||
PythonCommandMonotonic = "monotonic()"
|
||||
PythonCommandOct = "oct(x)"
|
||||
PythonCommandPhase = "phase(z)"
|
||||
PythonCommandPlot = "plot(x,y)"
|
||||
PythonCommandPolar = "polar(z)"
|
||||
PythonCommandPop = "list.pop()"
|
||||
PythonCommandPopWithoutArg = ".pop()"
|
||||
@@ -165,8 +176,10 @@ PythonCommandRemoveWithoutArg = ".remove(\x11)"
|
||||
PythonCommandReverse = "list.reverse()"
|
||||
PythonCommandReverseWithoutArg = ".reverse()"
|
||||
PythonCommandRound = "round(x, n)"
|
||||
PythonCommandScatter = "scatter(x,y)"
|
||||
PythonCommandSeed = "seed(x)"
|
||||
PythonCommandSetPixel = "set_pixel(x,y,color)"
|
||||
PythonCommandShow = "show()"
|
||||
PythonCommandSin = "sin(x)"
|
||||
PythonCommandSinComplex = "sin(z)"
|
||||
PythonCommandSinh = "sinh(x)"
|
||||
@@ -179,6 +192,7 @@ PythonCommandSqrtComplex = "sqrt(z)"
|
||||
PythonCommandSum = "sum(list)"
|
||||
PythonCommandTan = "tan(x)"
|
||||
PythonCommandTanh = "tanh(x)"
|
||||
PythonCommandText = "text(x,y,\"text\")"
|
||||
PythonCommandTimeFunction = "time.function"
|
||||
PythonCommandTimeFunctionWithoutArg = "time.\x11"
|
||||
PythonCommandTrunc = "trunc(x)"
|
||||
|
||||
@@ -34,9 +34,8 @@ ConsoleController::ConsoleController(Responder * parentResponder, App * pythonDe
|
||||
m_selectableTableView(this, this, this, this),
|
||||
m_editCell(this, pythonDelegate, this),
|
||||
m_scriptStore(scriptStore),
|
||||
m_sandboxController(this, this),
|
||||
m_inputRunLoopActive(false),
|
||||
m_preventEdition(false)
|
||||
m_sandboxController(this),
|
||||
m_inputRunLoopActive(false)
|
||||
#if EPSILON_GETOPT
|
||||
, m_locked(lockOnConsole)
|
||||
#endif
|
||||
@@ -82,14 +81,12 @@ void ConsoleController::runAndPrintForCommand(const char * command) {
|
||||
assert(m_outputAccumulationBuffer[0] == '\0');
|
||||
|
||||
// Draw the console before running the code
|
||||
m_preventEdition = true;
|
||||
m_editCell.setText("");
|
||||
m_editCell.setPrompt("");
|
||||
refreshPrintOutput();
|
||||
|
||||
runCode(storedCommand);
|
||||
|
||||
m_preventEdition = false;
|
||||
m_editCell.setPrompt(sStandardPromptText);
|
||||
m_editCell.setEditing(true);
|
||||
|
||||
@@ -108,9 +105,7 @@ const char * ConsoleController::inputText(const char * prompt) {
|
||||
m_inputRunLoopActive = true;
|
||||
|
||||
// Hide the sandbox if it is displayed
|
||||
if (sandboxIsDisplayed()) {
|
||||
hideSandbox();
|
||||
}
|
||||
hideAnyDisplayedViewController();
|
||||
|
||||
const char * promptText = prompt;
|
||||
char * s = const_cast<char *>(prompt);
|
||||
@@ -157,8 +152,7 @@ const char * ConsoleController::inputText(const char * prompt) {
|
||||
m_editCell.clearAndReduceSize();
|
||||
|
||||
// Reload the history
|
||||
m_selectableTableView.reloadData();
|
||||
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
|
||||
reloadData(true);
|
||||
appsContainer->redrawWindow();
|
||||
|
||||
// Launch a new input loop
|
||||
@@ -191,14 +185,21 @@ void ConsoleController::viewWillAppear() {
|
||||
m_importScriptsWhenViewAppears = false;
|
||||
autoImport();
|
||||
}
|
||||
m_selectableTableView.reloadData();
|
||||
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
|
||||
m_editCell.setEditing(true);
|
||||
m_editCell.setText("");
|
||||
|
||||
reloadData(true);
|
||||
}
|
||||
|
||||
void ConsoleController::didBecomeFirstResponder() {
|
||||
Container::activeApp()->setFirstResponder(&m_editCell);
|
||||
if (!isDisplayingViewController()) {
|
||||
Container::activeApp()->setFirstResponder(&m_editCell);
|
||||
} else {
|
||||
/* A view controller might be displayed: for example, when pushing the
|
||||
* console on the stack controller, we auto-import scripts during the
|
||||
* 'viewWillAppear' and then we set the console as first responder. The
|
||||
* sandbox or the matplotlib controller might have been pushed in the
|
||||
* auto-import. */
|
||||
Container::activeApp()->setFirstResponder(stackViewController()->topViewController());
|
||||
}
|
||||
}
|
||||
|
||||
bool ConsoleController::handleEvent(Ion::Events::Event event) {
|
||||
@@ -347,11 +348,8 @@ bool ConsoleController::textFieldDidFinishEditing(TextField * textField, const c
|
||||
}
|
||||
telemetryReportEvent("Console", text);
|
||||
runAndPrintForCommand(text);
|
||||
if (!sandboxIsDisplayed()) {
|
||||
m_selectableTableView.reloadData();
|
||||
m_editCell.setEditing(true);
|
||||
textField->setText("");
|
||||
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
|
||||
if (!isDisplayingViewController()) {
|
||||
reloadData(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -378,37 +376,53 @@ bool ConsoleController::textFieldDidAbortEditing(TextField * textField) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConsoleController::displaySandbox() {
|
||||
if (sandboxIsDisplayed()) {
|
||||
return;
|
||||
}
|
||||
stackViewController()->push(&m_sandboxController);
|
||||
}
|
||||
|
||||
void ConsoleController::hideSandbox() {
|
||||
if (!sandboxIsDisplayed()) {
|
||||
return;
|
||||
}
|
||||
m_sandboxController.hide();
|
||||
}
|
||||
|
||||
void ConsoleController::resetSandbox() {
|
||||
if (!sandboxIsDisplayed()) {
|
||||
if (stackViewController()->topViewController() != sandbox()) {
|
||||
return;
|
||||
}
|
||||
m_sandboxController.reset();
|
||||
}
|
||||
|
||||
void ConsoleController::refreshPrintOutput() {
|
||||
if (sandboxIsDisplayed()) {
|
||||
void ConsoleController::displayViewController(ViewController * controller) {
|
||||
if (stackViewController()->topViewController() == controller) {
|
||||
return;
|
||||
}
|
||||
hideAnyDisplayedViewController();
|
||||
stackViewController()->push(controller);
|
||||
}
|
||||
|
||||
void ConsoleController::hideAnyDisplayedViewController() {
|
||||
if (!isDisplayingViewController()) {
|
||||
return;
|
||||
}
|
||||
stackViewController()->pop();
|
||||
}
|
||||
|
||||
bool ConsoleController::isDisplayingViewController() {
|
||||
/* The StackViewController model state is the best way to know wether the
|
||||
* console is displaying a View Controller (Sandbox or Matplotlib). Indeed,
|
||||
* keeping a boolean or a pointer raises the issue of when updating it - when
|
||||
* 'viewWillAppear' or when 'didEnterResponderChain' - in both cases, the
|
||||
* state would be wrong at some point... */
|
||||
return stackViewController()->depth() > 2;
|
||||
}
|
||||
|
||||
void ConsoleController::refreshPrintOutput() {
|
||||
if (!isDisplayingViewController()) {
|
||||
reloadData(false);
|
||||
AppsContainer::sharedAppsContainer()->redrawWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleController::reloadData(bool isEditing) {
|
||||
m_selectableTableView.reloadData();
|
||||
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
|
||||
if (m_preventEdition) {
|
||||
if (isEditing) {
|
||||
m_editCell.setEditing(true);
|
||||
m_editCell.setText("");
|
||||
} else {
|
||||
m_editCell.setEditing(false);
|
||||
}
|
||||
AppsContainer::sharedAppsContainer()->redrawWindow();
|
||||
}
|
||||
|
||||
/* printText is called by the Python machine.
|
||||
@@ -457,12 +471,11 @@ void ConsoleController::printText(const char * text, size_t length) {
|
||||
}
|
||||
|
||||
void ConsoleController::autoImportScript(Script script, bool force) {
|
||||
if (sandboxIsDisplayed()) {
|
||||
/* The sandbox might be displayed, for instance if we are auto-importing
|
||||
* several scripts that draw at importation. In this case, we want to remove
|
||||
* the sandbox. */
|
||||
hideSandbox();
|
||||
}
|
||||
/* The sandbox might be displayed, for instance if we are auto-importing
|
||||
* several scripts that draw at importation. In this case, we want to remove
|
||||
* the sandbox. */
|
||||
hideAnyDisplayedViewController();
|
||||
|
||||
if (script.importationStatus() || force) {
|
||||
// Step 1 - Create the command "from scriptName import *".
|
||||
|
||||
@@ -488,11 +501,8 @@ void ConsoleController::autoImportScript(Script script, bool force) {
|
||||
// Step 2 - Run the command
|
||||
runAndPrintForCommand(command);
|
||||
}
|
||||
if (!sandboxIsDisplayed() && force) {
|
||||
m_selectableTableView.reloadData();
|
||||
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
|
||||
m_editCell.setEditing(true);
|
||||
m_editCell.setText("");
|
||||
if (!isDisplayingViewController() && force) {
|
||||
reloadData(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,9 +61,10 @@ public:
|
||||
bool textFieldDidAbortEditing(TextField * textField) override;
|
||||
|
||||
// MicroPython::ExecutionEnvironment
|
||||
void displaySandbox() override;
|
||||
void hideSandbox() override;
|
||||
ViewController * sandbox() override { return &m_sandboxController; }
|
||||
void resetSandbox() override;
|
||||
void displayViewController(ViewController * controller) override;
|
||||
void hideAnyDisplayedViewController() override;
|
||||
void refreshPrintOutput() override;
|
||||
void printText(const char * text, size_t length) override;
|
||||
const char * inputText(const char * prompt) override;
|
||||
@@ -82,6 +83,8 @@ private:
|
||||
static constexpr int k_numberOfLineCells = (Ion::Display::Height - Metric::TitleBarHeight) / 14 + 2; // 14 = KDFont::SmallFont->glyphSize().height()
|
||||
// k_numberOfLineCells = (240 - 18)/14 ~ 15.9. The 0.1 cell can be above and below the 15 other cells so we add +2 cells.
|
||||
static constexpr int k_outputAccumulationBufferSize = 100;
|
||||
bool isDisplayingViewController();
|
||||
void reloadData(bool isEditing);
|
||||
void flushOutputAccumulationBufferToStore();
|
||||
void appendTextToOutputAccumulationBuffer(const char * text, size_t length);
|
||||
void emptyOutputAccumulationBuffer();
|
||||
@@ -103,7 +106,6 @@ private:
|
||||
SandboxController m_sandboxController;
|
||||
bool m_inputRunLoopActive;
|
||||
bool m_autoImportScripts;
|
||||
bool m_preventEdition;
|
||||
#if EPSILON_GETOPT
|
||||
bool m_locked;
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
namespace Code {
|
||||
|
||||
static inline int minInt(int x, int y) { return x < y ? x : y; }
|
||||
|
||||
ConsoleEditCell::ConsoleEditCell(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, TextFieldDelegate * delegate) :
|
||||
HighlightCell(),
|
||||
Responder(parentResponder),
|
||||
@@ -65,9 +67,12 @@ void ConsoleEditCell::clearAndReduceSize() {
|
||||
const char * ConsoleEditCell::shiftCurrentTextAndClear() {
|
||||
size_t previousBufferSize = m_textField.draftTextBufferSize();
|
||||
m_textField.setDraftTextBufferSize(previousBufferSize + 1);
|
||||
char * textFieldBuffer = m_textField.draftTextBuffer();
|
||||
char * textFieldBuffer = const_cast<char *>(m_textField.text());
|
||||
char * newTextPosition = textFieldBuffer + 1;
|
||||
strlcpy(newTextPosition, textFieldBuffer, previousBufferSize);
|
||||
assert(previousBufferSize > 0);
|
||||
size_t copyLength = minInt(previousBufferSize - 1, strlen(textFieldBuffer));
|
||||
memmove(newTextPosition, textFieldBuffer, copyLength);
|
||||
newTextPosition[copyLength] = 0;
|
||||
textFieldBuffer[0] = 0;
|
||||
return newTextPosition;
|
||||
}
|
||||
|
||||
@@ -92,30 +92,6 @@ const ToolboxMessageTree MathModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandLgamma, I18n::Message::PythonLgamma)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree KandinskyModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportKandinsky, I18n::Message::PythonImportKandinsky, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromKandinsky, I18n::Message::PythonImportKandinsky, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKandinskyFunction, I18n::Message::PythonKandinskyFunction, false, I18n::Message::PythonCommandKandinskyFunctionWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetPixel, I18n::Message::PythonGetPixel),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSetPixel, I18n::Message::PythonSetPixel),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColor, I18n::Message::PythonColor),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandDrawString, I18n::Message::PythonDrawString),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillRect, I18n::Message::PythonFillRect)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree RandomModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportRandom, I18n::Message::PythonImportRandom, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromRandom, I18n::Message::PythonImportRandom, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandomFunction, I18n::Message::PythonRandomFunction, false, I18n::Message::PythonCommandRandomFunctionWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetrandbits, I18n::Message::PythonGetrandbits),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSeed, I18n::Message::PythonSeed),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandrange, I18n::Message::PythonRandrange),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandint, I18n::Message::PythonRandint),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandChoice, I18n::Message::PythonChoice),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandom, I18n::Message::PythonRandom, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandUniform, I18n::Message::PythonUniform)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree CMathModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportCmath, I18n::Message::PythonImportCmath, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromCmath, I18n::Message::PythonImportCmath, false),
|
||||
@@ -132,6 +108,21 @@ const ToolboxMessageTree CMathModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSinComplex, I18n::Message::PythonSin)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree MatplotlibPyplotModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportMatplotlibPyplot, I18n::Message::PythonImportMatplotlibPyplot, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromMatplotlibPyplot, I18n::Message::PythonImportMatplotlibPyplot, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandMatplotlibPyplotFunction, I18n::Message::PythonMatplotlibPyplotFunction, false, I18n::Message::PythonCommandMatplotlibPyplotFunctionWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandArrow, I18n::Message::PythonArrow),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAxis, I18n::Message::PythonAxis, false, I18n::Message::PythonCommandAxisWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBar, I18n::Message::PythonBar),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGrid, I18n::Message::PythonGrid),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandHist, I18n::Message::PythonHist),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPlot, I18n::Message::PythonPlot),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandScatter, I18n::Message::PythonScatter),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandShow, I18n::Message::PythonShow),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandText, I18n::Message::PythonText)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree TurtleModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportTurtle, I18n::Message::PythonImportTurtle, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromTurtle, I18n::Message::PythonImportTurtle, false),
|
||||
@@ -167,6 +158,30 @@ const ToolboxMessageTree TurtleModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandGrey, I18n::Message::PythonTurtleGrey, false)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree RandomModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportRandom, I18n::Message::PythonImportRandom, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromRandom, I18n::Message::PythonImportRandom, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandomFunction, I18n::Message::PythonRandomFunction, false, I18n::Message::PythonCommandRandomFunctionWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetrandbits, I18n::Message::PythonGetrandbits),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSeed, I18n::Message::PythonSeed),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandrange, I18n::Message::PythonRandrange),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandint, I18n::Message::PythonRandint),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandChoice, I18n::Message::PythonChoice),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRandom, I18n::Message::PythonRandom, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandUniform, I18n::Message::PythonUniform)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree KandinskyModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportKandinsky, I18n::Message::PythonImportKandinsky, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromKandinsky, I18n::Message::PythonImportKandinsky, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKandinskyFunction, I18n::Message::PythonKandinskyFunction, false, I18n::Message::PythonCommandKandinskyFunctionWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetPixel, I18n::Message::PythonGetPixel),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSetPixel, I18n::Message::PythonSetPixel),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColor, I18n::Message::PythonColor),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandDrawString, I18n::Message::PythonDrawString),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillRect, I18n::Message::PythonFillRect)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree IonModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportIon, I18n::Message::PythonImportIon, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromIon, I18n::Message::PythonImportIon, false),
|
||||
@@ -231,8 +246,9 @@ const ToolboxMessageTree TimeModuleChildren[] = {
|
||||
const ToolboxMessageTree modulesChildren[] = {
|
||||
ToolboxMessageTree::Node(I18n::Message::MathModule, MathModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::CmathModule, CMathModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::RandomModule, RandomModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::MatplotlibPyplotModule, MatplotlibPyplotModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::TurtleModule, TurtleModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::RandomModule, RandomModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::KandinskyModule, KandinskyModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::IonModule, IonModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::TimeModule, TimeModuleChildren)
|
||||
@@ -251,12 +267,15 @@ const ToolboxMessageTree catalogChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAbs, I18n::Message::PythonAbs),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAcos, I18n::Message::PythonAcos),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAcosh, I18n::Message::PythonAcosh),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandArrow, I18n::Message::PythonArrow),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAsin, I18n::Message::PythonAsin),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAsinh, I18n::Message::PythonAsinh),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAtan, I18n::Message::PythonAtan),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAtan2, I18n::Message::PythonAtan2),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAtanh, I18n::Message::PythonAtanh),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAxis, I18n::Message::PythonAxis, false, I18n::Message::PythonCommandAxisWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBackward, I18n::Message::PythonTurtleBackward),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBar, I18n::Message::PythonBar),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBin, I18n::Message::PythonBin),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBlack, I18n::Message::PythonTurtleBlack, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBlue, I18n::Message::PythonTurtleBlue, false),
|
||||
@@ -290,6 +309,7 @@ const ToolboxMessageTree catalogChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromIon, I18n::Message::PythonImportIon, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromKandinsky, I18n::Message::PythonImportKandinsky, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromMath, I18n::Message::PythonImportMath, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromMatplotlibPyplot, I18n::Message::PythonImportMatplotlibPyplot, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromRandom, I18n::Message::PythonImportRandom, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromTurtle, I18n::Message::PythonImportTurtle, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromTime, I18n::Message::PythonImportTime, false),
|
||||
@@ -299,13 +319,16 @@ const ToolboxMessageTree catalogChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandGoto, I18n::Message::PythonTurtleGoto),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandGreen, I18n::Message::PythonTurtleGreen, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandGrey, I18n::Message::PythonTurtleGrey, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGrid, I18n::Message::PythonGrid),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandHeading, I18n::Message::PythonTurtleHeading, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandHex, I18n::Message::PythonHex),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandHideturtle, I18n::Message::PythonTurtleHideturtle, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandHist, I18n::Message::PythonHist),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportCmath, I18n::Message::PythonImportCmath, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportIon, I18n::Message::PythonImportIon, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportKandinsky, I18n::Message::PythonImportKandinsky, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportMath, I18n::Message::PythonImportMath, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportMatplotlibPyplot, I18n::Message::PythonImportMatplotlibPyplot, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportRandom, I18n::Message::PythonImportRandom, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportTurtle, I18n::Message::PythonImportTurtle, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportTime, I18n::Message::PythonImportTime, false),
|
||||
@@ -335,6 +358,7 @@ const ToolboxMessageTree catalogChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandLog10, I18n::Message::PythonLog10),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandLog2, I18n::Message::PythonLog2),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandMathFunction, I18n::Message::PythonMathFunction, false, I18n::Message::PythonCommandMathFunctionWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandMatplotlibPyplotFunction, I18n::Message::PythonMatplotlibPyplotFunction, false, I18n::Message::PythonCommandMatplotlibPyplotFunctionWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandMax, I18n::Message::PythonMax),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandMin, I18n::Message::PythonMin),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandModf, I18n::Message::PythonModf),
|
||||
@@ -350,6 +374,7 @@ const ToolboxMessageTree catalogChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPolar, I18n::Message::PythonPolar),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPosition, I18n::Message::PythonTurtlePosition, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPower, I18n::Message::PythonPower),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPlot, I18n::Message::PythonPlot),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPrint, I18n::Message::PythonPrint),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandPurple, I18n::Message::PythonTurtlePurple, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRadians, I18n::Message::PythonRadians),
|
||||
@@ -364,9 +389,11 @@ const ToolboxMessageTree catalogChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandReset, I18n::Message::PythonTurtleReset, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandRight, I18n::Message::PythonTurtleRight),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandRound, I18n::Message::PythonRound),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandScatter, I18n::Message::PythonScatter),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandSetheading, I18n::Message::PythonTurtleSetheading),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSetPixel, I18n::Message::PythonSetPixel),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSeed, I18n::Message::PythonSeed),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandShow, I18n::Message::PythonShow),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandShowturtle, I18n::Message::PythonTurtleShowturtle, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSin, I18n::Message::PythonSin),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSinh, I18n::Message::PythonSinh),
|
||||
@@ -377,6 +404,7 @@ const ToolboxMessageTree catalogChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSum, I18n::Message::PythonSum),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandTan, I18n::Message::PythonTan),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandTanh, I18n::Message::PythonTanh),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandText, I18n::Message::PythonText),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandTimeFunction, I18n::Message::PythonTimeFunction, false, I18n::Message::PythonCommandTimeFunctionWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandTrunc, I18n::Message::PythonTrunc),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandTurtleFunction, I18n::Message::PythonTurtleFunction, false, I18n::Message::PythonCommandTurtleFunctionWithoutArg),
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#include "sandbox_controller.h"
|
||||
#include <apps/apps_container.h>
|
||||
|
||||
extern "C" {
|
||||
#include <python/port/mod/turtle/modturtle.h>
|
||||
}
|
||||
|
||||
namespace Code {
|
||||
|
||||
SandboxController::SandboxController(Responder * parentResponder, MicroPython::ExecutionEnvironment * executionEnvironment) :
|
||||
SandboxController::SandboxController(Responder * parentResponder) :
|
||||
ViewController(parentResponder),
|
||||
m_solidColorView(Palette::CodeBackground),
|
||||
m_executionEnvironment(executionEnvironment)
|
||||
m_solidColorView(Palette::CodeBackground)
|
||||
{
|
||||
assert(executionEnvironment != nullptr);
|
||||
}
|
||||
|
||||
StackViewController * SandboxController::stackViewController() {
|
||||
@@ -20,19 +22,12 @@ void SandboxController::reset() {
|
||||
redrawWindow();
|
||||
}
|
||||
|
||||
void SandboxController::hide() {
|
||||
stackViewController()->pop();
|
||||
}
|
||||
|
||||
void SandboxController::viewWillAppear() {
|
||||
assert(m_executionEnvironment != nullptr);
|
||||
m_executionEnvironment->setSandboxIsDisplayed(true);
|
||||
redrawWindow();
|
||||
}
|
||||
|
||||
void SandboxController::viewDidDisappear() {
|
||||
assert(m_executionEnvironment != nullptr);
|
||||
m_executionEnvironment->setSandboxIsDisplayed(false);
|
||||
modturtle_view_did_disappear();
|
||||
}
|
||||
|
||||
bool SandboxController::handleEvent(Ion::Events::Event event) {
|
||||
|
||||
@@ -11,10 +11,9 @@ namespace Code {
|
||||
|
||||
class SandboxController : public ViewController {
|
||||
public:
|
||||
SandboxController(Responder * parentResponder, MicroPython::ExecutionEnvironment * executionEnvironment);
|
||||
SandboxController(Responder * parentResponder);
|
||||
StackViewController * stackViewController();
|
||||
void reset();
|
||||
void hide();
|
||||
|
||||
// ViewController
|
||||
View * view() override { return &m_solidColorView; }
|
||||
@@ -26,7 +25,6 @@ public:
|
||||
private:
|
||||
void redrawWindow();
|
||||
SolidColorView m_solidColorView;
|
||||
MicroPython::ExecutionEnvironment * m_executionEnvironment;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ bool ScriptStore::ScriptNameIsFree(const char * baseName) {
|
||||
ScriptStore::ScriptStore()
|
||||
{
|
||||
addScriptFromTemplate(ScriptTemplate::Squares());
|
||||
addScriptFromTemplate(ScriptTemplate::Parabola());
|
||||
addScriptFromTemplate(ScriptTemplate::Mandelbrot());
|
||||
addScriptFromTemplate(ScriptTemplate::Polynomial());
|
||||
}
|
||||
|
||||
@@ -53,6 +53,37 @@ def roots(a,b,c):
|
||||
else:
|
||||
return None)");
|
||||
|
||||
constexpr ScriptTemplate parabolaScriptTemplate("parabola.py", "\x01" R"(from matplotlib.pyplot import *
|
||||
from math import *
|
||||
|
||||
g=9.81
|
||||
|
||||
def x(t,v_0,alpha):
|
||||
return v_0*cos(alpha)*t
|
||||
def y(t,v_0,alpha,h_0):
|
||||
return -0.5*g*t**2+v_0*sin(alpha)*t+h_0
|
||||
|
||||
def vx(v_0,alpha):
|
||||
return v_0*cos(alpha)
|
||||
def vy(t,v_0,alpha):
|
||||
return -g*t+v_0*sin(alpha)
|
||||
|
||||
def t_max(v_0,alpha,h_0):
|
||||
return (v_0*sin(alpha)+sqrt((v_0**2)*(sin(alpha)**2)+2*g*h_0))/g
|
||||
|
||||
def simulation(v_0=15,alpha=pi/4,h_0=2):
|
||||
tMax=t_max(v_0,alpha,h_0)
|
||||
accuracy=1/10**(floor(log10(tMax))-1)
|
||||
T_MAX=floor(tMax*accuracy)+1
|
||||
X=[x(t/accuracy,v_0,alpha) for t in range(T_MAX)]
|
||||
Y=[y(t/accuracy,v_0,alpha,h_0) for t in range(T_MAX)]
|
||||
VX=[vx(v_0,alpha) for t in range(T_MAX)]
|
||||
VY=[vy(t/accuracy,v_0,alpha) for t in range(T_MAX)]
|
||||
for i in range(T_MAX):
|
||||
arrow(X[i],Y[i],VX[i]/accuracy,VY[i]/accuracy)
|
||||
grid()
|
||||
show())");
|
||||
|
||||
const ScriptTemplate * ScriptTemplate::Empty() {
|
||||
return &emptyScriptTemplate;
|
||||
}
|
||||
@@ -69,4 +100,8 @@ const ScriptTemplate * ScriptTemplate::Polynomial() {
|
||||
return &polynomialScriptTemplate;
|
||||
}
|
||||
|
||||
const ScriptTemplate * ScriptTemplate::Parabola() {
|
||||
return ¶bolaScriptTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ public:
|
||||
static const ScriptTemplate * Squares();
|
||||
static const ScriptTemplate * Mandelbrot();
|
||||
static const ScriptTemplate * Polynomial();
|
||||
static const ScriptTemplate * Parabola();
|
||||
const char * name() const { return m_name; }
|
||||
const char * content() const { return m_value+1; }
|
||||
const char * value() const { return m_value; }
|
||||
|
||||
@@ -2,6 +2,7 @@ CmathModule = "cmath"
|
||||
IonModule = "ion"
|
||||
KandinskyModule = "kandinsky"
|
||||
MathModule = "math"
|
||||
MatplotlibPyplotModule = "matplotlib.pyplot"
|
||||
TimeModule = "time"
|
||||
TurtleModule = "turtle"
|
||||
ForLoopMenu = "For"
|
||||
|
||||
@@ -58,7 +58,7 @@ App::App(Snapshot * snapshot) :
|
||||
m_listFooter(&m_listHeader, &m_listController, &m_listController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGrey),
|
||||
m_listHeader(&m_listStackViewController, &m_listFooter, &m_listController),
|
||||
m_listStackViewController(&m_tabViewController, &m_listHeader),
|
||||
m_graphController(&m_graphAlternateEmptyViewController, this, snapshot->graphRange(), snapshot->cursor(), snapshot->indexFunctionSelectedByCursor(), snapshot->modelVersion(), snapshot->rangeVersion(), snapshot->angleUnitVersion(), &m_graphHeader),
|
||||
m_graphController(&m_graphAlternateEmptyViewController, this, snapshot->graphRange(), snapshot->cursor(), snapshot->indexFunctionSelectedByCursor(), snapshot->modelVersion(), snapshot->previousModelsVersions(), snapshot->rangeVersion(), snapshot->angleUnitVersion(), &m_graphHeader),
|
||||
m_graphAlternateEmptyViewController(&m_graphHeader, &m_graphController, &m_graphController),
|
||||
m_graphHeader(&m_graphStackViewController, &m_graphAlternateEmptyViewController, &m_graphController),
|
||||
m_graphStackViewController(&m_tabViewController, &m_graphHeader),
|
||||
|
||||
@@ -30,7 +30,6 @@ protected:
|
||||
MessageTextView m_defaultBannerView;
|
||||
bool m_isActive;
|
||||
private:
|
||||
bool handleZoom(Ion::Events::Event event) override { return false; }
|
||||
bool handleEnter() override;
|
||||
bool moveCursorHorizontally(int direction, bool fast = false) override;
|
||||
Shared::InteractiveCurveViewRange * interactiveCurveViewRange() override { return m_graphRange; }
|
||||
|
||||
@@ -11,8 +11,8 @@ static inline float maxFloat(float x, float y) { return x > y ? x : y; }
|
||||
static inline double minDouble(double x, double y) { return x < y ? x : y; }
|
||||
static inline double maxDouble(double x, double y) { return x > y ? x : y; }
|
||||
|
||||
GraphController::GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, Shared::InteractiveCurveViewRange * curveViewRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
|
||||
FunctionGraphController(parentResponder, inputEventHandlerDelegate, header, curveViewRange, &m_view, cursor, indexFunctionSelectedByCursor, modelVersion, rangeVersion, angleUnitVersion),
|
||||
GraphController::GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, Shared::InteractiveCurveViewRange * curveViewRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
|
||||
FunctionGraphController(parentResponder, inputEventHandlerDelegate, header, curveViewRange, &m_view, cursor, indexFunctionSelectedByCursor, modelVersion, previousModelsVersions, rangeVersion, angleUnitVersion),
|
||||
m_bannerView(this, inputEventHandlerDelegate, this),
|
||||
m_view(curveViewRange, m_cursor, &m_bannerView, &m_cursorView),
|
||||
m_graphRange(curveViewRange),
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Graph {
|
||||
|
||||
class GraphController : public Shared::FunctionGraphController, public GraphControllerHelper {
|
||||
public:
|
||||
GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header);
|
||||
GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header);
|
||||
I18n::Message emptyMessage() override;
|
||||
void viewWillAppear() override;
|
||||
bool displayDerivativeInBanner() const { return m_displayDerivativeInBanner; }
|
||||
|
||||
@@ -60,13 +60,12 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}, f.operator->(), context(), f->color(), true, record == m_selectedRecord, m_highlightedStart, m_highlightedEnd);
|
||||
/* Draw tangent */
|
||||
if (m_tangent && record == m_selectedRecord) {
|
||||
float tangentParameter[2];
|
||||
tangentParameter[0] = f->approximateDerivative(m_curveViewCursor->x(), context());
|
||||
tangentParameter[1] = -tangentParameter[0]*m_curveViewCursor->x()+f->evaluateXYAtParameter(m_curveViewCursor->x(), context()).x2();
|
||||
drawCartesianCurve(ctx, rect, -INFINITY, INFINITY, [](float t, void * model, void * context) {
|
||||
float * tangent = (float *)model;
|
||||
return Poincare::Coordinate2D<float>(t, tangent[0]*t+tangent[1]);
|
||||
}, tangentParameter, nullptr, Palette::GraphTangent);
|
||||
float tangentParameterA = f->approximateDerivative(m_curveViewCursor->x(), context());
|
||||
float tangentParameterB = -tangentParameterA*m_curveViewCursor->x()+f->evaluateXYAtParameter(m_curveViewCursor->x(), context()).x2();
|
||||
// To represent the tangent, we draw segment from and to abscissas at the extremity of the drawn rect
|
||||
float minAbscissa = pixelToFloat(Axis::Horizontal, rect.left());
|
||||
float maxAbscissa = pixelToFloat(Axis::Horizontal, rect.right());
|
||||
drawSegment(ctx, rect, minAbscissa, tangentParameterA*minAbscissa+tangentParameterB, maxAbscissa, tangentParameterA*maxAbscissa+tangentParameterB, Palette::GraphTangent, false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Apps = "Anwendungen"
|
||||
AppsCapital = "OMEGA"
|
||||
AppsCapital = "STAY HOME(GA)"
|
||||
ForbidenAppInExamMode1 = "Diese Anwendung ist im"
|
||||
ForbidenAppInExamMode2 = "Prüfungsmodus verboten"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Apps = "Applications"
|
||||
AppsCapital = "OMEGA"
|
||||
AppsCapital = "STAY HOME(GA)"
|
||||
ForbidenAppInExamMode1 = "This application is"
|
||||
ForbidenAppInExamMode2 = "forbidden in exam mode"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Apps = "Aplicaciones"
|
||||
AppsCapital = "OMEGA"
|
||||
AppsCapital = "STAY HOME(GA)"
|
||||
ForbidenAppInExamMode1 = "This application is"
|
||||
ForbidenAppInExamMode2 = "forbidden in exam mode"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Apps = "Applications"
|
||||
AppsCapital = "OMEGA"
|
||||
AppsCapital = "STAY HOME(GA)"
|
||||
ForbidenAppInExamMode1 = "This application is"
|
||||
ForbidenAppInExamMode2 = "forbidden in exam mode"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Apps = "Alkalmazások"
|
||||
AppsCapital = "OMEGA"
|
||||
AppsCapital = "STAY HOME(GA)"
|
||||
ForbidenAppInExamMode1 = "Ez az alkalmazás"
|
||||
ForbidenAppInExamMode2 = "tilos vizsga módban"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Apps = "Aplicações"
|
||||
AppsCapital = "OMEGA"
|
||||
AppsCapital = "STAY HOME(GA)"
|
||||
ForbidenAppInExamMode1 = "This application is"
|
||||
ForbidenAppInExamMode2 = "forbidden in exam mode"
|
||||
|
||||
@@ -25,9 +25,12 @@ double Distribution::rightIntegralFromAbscissa(double x) const {
|
||||
}
|
||||
|
||||
double Distribution::finiteIntegralBetweenAbscissas(double a, double b) const {
|
||||
if (b <= a) {
|
||||
if (b < a) {
|
||||
return 0.0;
|
||||
}
|
||||
if (a == b) {
|
||||
return evaluateAtDiscreteAbscissa(a);
|
||||
}
|
||||
if (isContinuous()) {
|
||||
return cumulativeDistributiveFunctionAtAbscissa(b) - cumulativeDistributiveFunctionAtAbscissa(a);
|
||||
}
|
||||
@@ -100,6 +103,7 @@ double Distribution::rightIntegralInverseForProbability(double * probability) {
|
||||
}
|
||||
|
||||
double Distribution::evaluateAtDiscreteAbscissa(int k) const {
|
||||
assert(isContinuous()); // Discrete distributions override this method
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,13 @@ void assert_cumulative_distributive_function_direct_and_inverse_is(Probability::
|
||||
quiz_assert(!std::isnan(r));
|
||||
quiz_assert(!std::isinf(r));
|
||||
quiz_assert(std::fabs(r-x) < FLT_EPSILON || std::fabs(r-x)/x < FLT_EPSILON);
|
||||
}
|
||||
|
||||
void assert_finite_integral_between_abscissas_is(Probability::Distribution * distribution, double a, double b, double result) {
|
||||
double r = distribution->finiteIntegralBetweenAbscissas(a, b);
|
||||
quiz_assert(!std::isnan(r));
|
||||
quiz_assert(!std::isinf(r));
|
||||
quiz_assert(std::fabs(r-result) < FLT_EPSILON || std::fabs(r-result)/result < FLT_EPSILON);
|
||||
}
|
||||
|
||||
//TODO other distributions
|
||||
@@ -37,6 +43,13 @@ QUIZ_CASE(binomial_distribution) {
|
||||
distribution.setParameterAtIndex(0.1, 1);
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 0.0, 0.166771816996665822596668249389040283858776092529296875);
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 1.0, 0.4817852491014791294077213024138472974300384521484375);
|
||||
|
||||
// B(21, 0.2)
|
||||
distribution.setParameterAtIndex(21.0, 0);
|
||||
distribution.setParameterAtIndex(0.2, 1);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 4.0, 4.0, 0.21563235015849934848);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 5.0, 4.0, 0.0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 4.0, 5.0, 0.398919847793223794688);
|
||||
}
|
||||
|
||||
QUIZ_CASE(chi_squared_distribution) {
|
||||
@@ -58,6 +71,12 @@ QUIZ_CASE(chi_squared_distribution) {
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 1.3, 0.047059684573231390369851823152202996425330638885498046875);
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 2.9874567, 0.250530060451470470983537097708904184401035308837890625);
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 4.987, 0.53051693435084168459781039928202517330646514892578125);
|
||||
|
||||
// Chi Squared distribution with 6 degrees of freedom
|
||||
distribution.setParameterAtIndex(6.0, 0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 4.0, 4.0, 0.0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 5.0, 4.0, 0.0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 4.0, 5.0, 0.1328633002997339414718);
|
||||
}
|
||||
|
||||
QUIZ_CASE(student_distribution) {
|
||||
@@ -79,6 +98,12 @@ QUIZ_CASE(student_distribution) {
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, -4.987, 0.00167496657737900025118837898929768925881944596767425537109375);
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 1.3, 0.876837383157582639370275501278229057788848876953125);
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 2.9874567, 0.98612148076325445433809591122553683817386627197265625);
|
||||
|
||||
// Student distribution with 6 degrees of freedom
|
||||
distribution.setParameterAtIndex(6.0, 0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 4.0, 4.0, 0.0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 5.0, 4.0, 0.0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 4.0, 5.0, 0.002333318101494775250);
|
||||
}
|
||||
|
||||
QUIZ_CASE(geometric_distribution) {
|
||||
@@ -92,6 +117,12 @@ QUIZ_CASE(geometric_distribution) {
|
||||
distribution.setParameterAtIndex(0.2, 0);
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 7.0, 0.8322278399999998299563230830244719982147216796875);
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 3.0, 0.5904);
|
||||
|
||||
// Geometric distribution with probability of success 0.4
|
||||
distribution.setParameterAtIndex(0.4, 0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 1.0, 1.0, 0.24);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 2.0, 1.0, 0.0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 1.0, 2.0, 0.384);
|
||||
}
|
||||
|
||||
QUIZ_CASE(fisher_distribution) {
|
||||
@@ -115,4 +146,10 @@ QUIZ_CASE(fisher_distribution) {
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 1.4, 0.94560850441205857);
|
||||
assert_cumulative_distributive_function_direct_and_inverse_is(&distribution, 1.425, 0.95425004959692871775);
|
||||
|
||||
// Fisher distribution with d1 = 4 and d2 = 2
|
||||
distribution.setParameterAtIndex(4.0, 0);
|
||||
distribution.setParameterAtIndex(2.0, 1);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 1.0, 1.0, 0.0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 2.0, 1.0, 0.0);
|
||||
assert_finite_integral_between_abscissas_is(&distribution, 1.0, 2.0, 0.19555555555555555);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ App * App::Snapshot::unpack(Container * container) {
|
||||
}
|
||||
|
||||
void App::Snapshot::reset() {
|
||||
m_store.deleteAllPairs();
|
||||
m_store.reset();
|
||||
m_modelVersion = 0;
|
||||
m_rangeVersion = 0;
|
||||
setActiveTab(0);
|
||||
@@ -59,7 +59,7 @@ App::App(Snapshot * snapshot, Poincare::Context * parentContext) :
|
||||
m_calculationController(&m_calculationAlternateEmptyViewController, &m_calculationHeader, snapshot->store()),
|
||||
m_calculationAlternateEmptyViewController(&m_calculationHeader, &m_calculationController, &m_calculationController),
|
||||
m_calculationHeader(&m_tabViewController, &m_calculationAlternateEmptyViewController, &m_calculationController),
|
||||
m_graphController(&m_graphAlternateEmptyViewController, this, &m_graphHeader, snapshot->store(), snapshot->cursor(), snapshot->modelVersion(), snapshot->rangeVersion(), snapshot->graphSelectedDotIndex(), snapshot->selectedSeriesIndex()),
|
||||
m_graphController(&m_graphAlternateEmptyViewController, this, &m_graphHeader, snapshot->store(), snapshot->cursor(), snapshot->modelVersion(), snapshot->previousModelsVersions(), snapshot->rangeVersion(), snapshot->graphSelectedDotIndex(), snapshot->selectedSeriesIndex()),
|
||||
m_graphAlternateEmptyViewController(&m_graphHeader, &m_graphController, &m_graphController),
|
||||
m_graphHeader(&m_graphStackViewController, &m_graphAlternateEmptyViewController, &m_graphController),
|
||||
m_graphStackViewController(&m_tabViewController, &m_graphHeader),
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
int * graphSelectedDotIndex() { return &m_graphSelectedDotIndex; }
|
||||
int * selectedSeriesIndex() { return &m_selectedSeriesIndex; }
|
||||
uint32_t * modelVersion() { return &m_modelVersion; }
|
||||
uint32_t * previousModelsVersions() { return m_store.seriesChecksum(); }
|
||||
uint32_t * rangeVersion() { return &m_rangeVersion; }
|
||||
private:
|
||||
void tidy() override;
|
||||
|
||||
@@ -168,6 +168,7 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
|
||||
myCell->setFirstText(buffer);
|
||||
buffer[0] = 'Y';
|
||||
myCell->setSecondText(buffer);
|
||||
assert(seriesNumber < Palette::numberOfDataColors());
|
||||
myCell->setColor(Palette::DataColor[seriesNumber]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ static inline int maxInt(int x, int y) { return x > y ? x : y; }
|
||||
|
||||
namespace Regression {
|
||||
|
||||
GraphController::GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, Store * store, CurveViewCursor * cursor, uint32_t * modelVersion, uint32_t * rangeVersion, int * selectedDotIndex, int * selectedSeriesIndex) :
|
||||
InteractiveCurveViewController(parentResponder, inputEventHandlerDelegate, header, store, &m_view, cursor, modelVersion, rangeVersion),
|
||||
GraphController::GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, Store * store, CurveViewCursor * cursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, int * selectedDotIndex, int * selectedSeriesIndex) :
|
||||
InteractiveCurveViewController(parentResponder, inputEventHandlerDelegate, header, store, &m_view, cursor, modelVersion, previousModelsVersions, rangeVersion),
|
||||
m_crossCursorView(),
|
||||
m_roundCursorView(),
|
||||
m_bannerView(this, inputEventHandlerDelegate, this),
|
||||
@@ -351,6 +351,11 @@ uint32_t GraphController::modelVersion() {
|
||||
return m_store->storeChecksum();
|
||||
}
|
||||
|
||||
uint32_t GraphController::modelVersionAtIndex(size_t i) {
|
||||
assert(i < numberOfMemoizedVersions());
|
||||
return *(m_store->seriesChecksum() + i);
|
||||
}
|
||||
|
||||
uint32_t GraphController::rangeVersion() {
|
||||
return m_store->rangeChecksum();
|
||||
}
|
||||
@@ -402,6 +407,7 @@ void GraphController::setRoundCrossCursorView() {
|
||||
bool round = *m_selectedDotIndex < 0;
|
||||
if (round) {
|
||||
// Set the color although the cursor view stays round
|
||||
assert(*m_selectedSeriesIndex < Palette::numberOfDataColors());
|
||||
m_roundCursorView.setColor(Palette::DataColor[*m_selectedSeriesIndex]);
|
||||
}
|
||||
CursorView * nextCursorView = round ? static_cast<Shared::CursorView *>(&m_roundCursorView) : static_cast<Shared::CursorView *>(&m_crossCursorView);
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Regression {
|
||||
class GraphController : public Shared::InteractiveCurveViewController {
|
||||
|
||||
public:
|
||||
GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, Store * store, Shared::CurveViewCursor * cursor, uint32_t * modelVersion, uint32_t * rangeVersion, int * selectedDotIndex, int * selectedSeriesIndex);
|
||||
GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, Store * store, Shared::CurveViewCursor * cursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, int * selectedDotIndex, int * selectedSeriesIndex);
|
||||
ViewController * initialisationParameterController() override;
|
||||
bool isEmpty() const override;
|
||||
I18n::Message emptyMessage() override;
|
||||
@@ -43,7 +43,9 @@ private:
|
||||
// InteractiveCurveViewController
|
||||
void initCursorParameters() override;
|
||||
uint32_t modelVersion() override;
|
||||
uint32_t modelVersionAtIndex(size_t i) override;
|
||||
uint32_t rangeVersion() override;
|
||||
size_t numberOfMemoizedVersions() const override { return Store::k_numberOfSeries; }
|
||||
int selectedCurveIndex() const override { return *m_selectedSeriesIndex; }
|
||||
bool closestCurveIndexIsSuitable(int newIndex, int currentIndex) const override;
|
||||
Poincare::Coordinate2D<double> xyValues(int curveIndex, double x, Poincare::Context * context) const override;
|
||||
|
||||
@@ -9,10 +9,8 @@ using namespace Shared;
|
||||
namespace Regression {
|
||||
|
||||
GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * bannerView, Shared::CursorView * cursorView) :
|
||||
CurveView(store, cursor, bannerView, cursorView),
|
||||
m_store(store),
|
||||
m_xLabels{},
|
||||
m_yLabels{}
|
||||
LabeledCurveView(store, cursor, bannerView, cursorView),
|
||||
m_store(store)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,6 +22,7 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
Poincare::Context * globContext = AppsContainer::sharedAppsContainer()->globalContext();
|
||||
for (int series = 0; series < Store::k_numberOfSeries; series++) {
|
||||
if (!m_store->seriesIsEmpty(series)) {
|
||||
assert(series < Palette::numberOfDataColors());
|
||||
KDColor color = Palette::DataColor[series];
|
||||
Model * seriesModel = m_store->modelForSeries(series);
|
||||
drawCartesianCurve(ctx, rect, -INFINITY, INFINITY, [](float abscissa, void * model, void * context) {
|
||||
@@ -41,13 +40,4 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}
|
||||
}
|
||||
|
||||
char * GraphView::label(Axis axis, int index) const {
|
||||
if (axis == Axis::Vertical) {
|
||||
assert(index < k_maxNumberOfXLabels);
|
||||
return (char *)m_yLabels[index];
|
||||
}
|
||||
assert(index < k_maxNumberOfYLabels);
|
||||
return (char *)m_xLabels[index];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,19 +3,16 @@
|
||||
|
||||
#include "store.h"
|
||||
#include "../constant.h"
|
||||
#include "../shared/curve_view.h"
|
||||
#include "../shared/labeled_curve_view.h"
|
||||
|
||||
namespace Regression {
|
||||
|
||||
class GraphView : public Shared::CurveView {
|
||||
class GraphView : public Shared::LabeledCurveView {
|
||||
public:
|
||||
GraphView(Store * store, Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, Shared::CursorView * cursorView);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
private:
|
||||
char * label(Axis axis, int index) const override;
|
||||
Store * m_store;
|
||||
char m_xLabels[k_maxNumberOfXLabels][k_labelBufferMaxSize];
|
||||
char m_yLabels[k_maxNumberOfYLabels][k_labelBufferMaxSize];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -19,13 +19,14 @@ static_assert(Store::k_numberOfSeries == 3, "Number of series changed, Regressio
|
||||
Store::Store() :
|
||||
InteractiveCurveViewRange(),
|
||||
DoublePairStore(),
|
||||
m_seriesChecksum{0, 0, 0},
|
||||
m_angleUnit(Poincare::Preferences::AngleUnit::Degree)
|
||||
{
|
||||
for (int i = 0; i < k_numberOfSeries; i++) {
|
||||
m_regressionTypes[i] = Model::Type::Linear;
|
||||
m_regressionChanged[i] = false;
|
||||
}
|
||||
resetMemoization();
|
||||
}
|
||||
|
||||
void Store::reset() {
|
||||
deleteAllPairs();
|
||||
resetMemoization();
|
||||
}
|
||||
|
||||
void Store::tidy() {
|
||||
@@ -188,6 +189,13 @@ double Store::doubleCastedNumberOfPairsOfSeries(int series) const {
|
||||
return DoublePairStore::numberOfPairsOfSeries(series);
|
||||
}
|
||||
|
||||
void Store::resetMemoization() {
|
||||
assert(((int)Model::Type::Linear) == 0);
|
||||
memset(m_seriesChecksum, 0, sizeof(m_seriesChecksum));
|
||||
memset(m_regressionTypes, 0, sizeof(m_regressionTypes));
|
||||
memset(m_regressionChanged, 0, sizeof(m_regressionChanged));
|
||||
}
|
||||
|
||||
float Store::maxValueOfColumn(int series, int i) const {
|
||||
float maxColumn = -FLT_MAX;
|
||||
for (int k = 0; k < numberOfPairsOfSeries(series); k++) {
|
||||
|
||||
@@ -22,6 +22,7 @@ class Store : public Shared::InteractiveCurveViewRange, public Shared::DoublePai
|
||||
public:
|
||||
Store();
|
||||
|
||||
void reset();
|
||||
// Clean pool
|
||||
void tidy();
|
||||
|
||||
@@ -35,6 +36,7 @@ public:
|
||||
assert((int)m_regressionTypes[series] >= 0 && (int)m_regressionTypes[series] < Model::k_numberOfModels);
|
||||
return regressionModel((int)m_regressionTypes[series]);
|
||||
}
|
||||
uint32_t * seriesChecksum() { return m_seriesChecksum; }
|
||||
|
||||
// Dots
|
||||
/* Return the closest dot to abscissa x above the regression curve if
|
||||
@@ -70,6 +72,7 @@ public:
|
||||
double squaredCorrelationCoefficient(int series) const;
|
||||
private:
|
||||
constexpr static float k_displayHorizontalMarginRatio = 0.05f;
|
||||
void resetMemoization();
|
||||
float maxValueOfColumn(int series, int i) const; //TODO LEA why float ?
|
||||
float minValueOfColumn(int series, int i) const; //TODO LEA why float ?
|
||||
Model * regressionModel(int index);
|
||||
|
||||
@@ -55,7 +55,7 @@ App::App(Snapshot * snapshot) :
|
||||
m_listFooter(&m_listHeader, &m_listController, &m_listController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGrey),
|
||||
m_listHeader(nullptr, &m_listFooter, &m_listController),
|
||||
m_listStackViewController(&m_tabViewController, &m_listHeader),
|
||||
m_graphController(&m_graphAlternateEmptyViewController, this, snapshot->functionStore(), snapshot->graphRange(), snapshot->cursor(), snapshot->indexFunctionSelectedByCursor(), snapshot->modelVersion(), snapshot->rangeVersion(), snapshot->angleUnitVersion(), &m_graphHeader),
|
||||
m_graphController(&m_graphAlternateEmptyViewController, this, snapshot->functionStore(), snapshot->graphRange(), snapshot->cursor(), snapshot->indexFunctionSelectedByCursor(), snapshot->modelVersion(), snapshot->previousModelsVersions(), snapshot->rangeVersion(), snapshot->angleUnitVersion(), &m_graphHeader),
|
||||
m_graphAlternateEmptyViewController(&m_graphHeader, &m_graphController, &m_graphController),
|
||||
m_graphHeader(&m_graphStackViewController, &m_graphAlternateEmptyViewController, &m_graphController),
|
||||
m_graphStackViewController(&m_tabViewController, &m_graphHeader),
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace Sequence {
|
||||
static inline int minInt(int x, int y) { return (x < y ? x : y); }
|
||||
static inline int maxInt(int x, int y) { return (x > y ? x : y); }
|
||||
|
||||
GraphController::GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
|
||||
FunctionGraphController(parentResponder, inputEventHandlerDelegate, header, graphRange, &m_view, cursor, indexFunctionSelectedByCursor, modelVersion, rangeVersion, angleUnitVersion),
|
||||
GraphController::GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header) :
|
||||
FunctionGraphController(parentResponder, inputEventHandlerDelegate, header, graphRange, &m_view, cursor, indexFunctionSelectedByCursor, modelVersion, previousModelsVersions, rangeVersion, angleUnitVersion),
|
||||
m_bannerView(this, inputEventHandlerDelegate, this),
|
||||
m_view(sequenceStore, graphRange, m_cursor, &m_bannerView, &m_cursorView),
|
||||
m_graphRange(graphRange),
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Sequence {
|
||||
|
||||
class GraphController final : public Shared::FunctionGraphController {
|
||||
public:
|
||||
GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header);
|
||||
GraphController(Responder * parentResponder, ::InputEventHandlerDelegate * inputEventHandlerDelegate, SequenceStore * sequenceStore, CurveViewRange * graphRange, Shared::CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion, ButtonRowController * header);
|
||||
I18n::Message emptyMessage() override;
|
||||
void viewWillAppear() override;
|
||||
TermSumController * termSumController() { return &m_termSumController; }
|
||||
|
||||
@@ -32,9 +32,9 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
if (x >= m_highlightedStart && x <= m_highlightedEnd && record == m_selectedRecord) {
|
||||
KDColor color = m_shouldColorHighlighted ? s->color() : Palette::PrimaryText;
|
||||
if (y >= 0.0f) {
|
||||
drawSegment(ctx, rect, Axis::Vertical, x, 0.0f, y, color, 1);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, x, 0.0f, y, color, 1);
|
||||
} else {
|
||||
drawSegment(ctx, rect, Axis::Vertical, x, y, 0.0f, color, 1);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, x, y, 0.0f, color, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ void Sequence::tidy() {
|
||||
m_firstInitialCondition.tidyName();
|
||||
m_secondInitialCondition.tidy();
|
||||
m_secondInitialCondition.tidyName();
|
||||
m_nameLayout = Layout();
|
||||
}
|
||||
|
||||
Sequence::Type Sequence::type() const {
|
||||
@@ -81,13 +80,10 @@ void Sequence::setInitialRank(int rank) {
|
||||
}
|
||||
|
||||
Poincare::Layout Sequence::nameLayout() {
|
||||
if (m_nameLayout.isUninitialized()) {
|
||||
m_nameLayout = HorizontalLayout::Builder(
|
||||
CodePointLayout::Builder(fullName()[0], KDFont::SmallFont),
|
||||
VerticalOffsetLayout::Builder(CodePointLayout::Builder(symbol(), KDFont::SmallFont), VerticalOffsetLayoutNode::Position::Subscript)
|
||||
);
|
||||
}
|
||||
return m_nameLayout;
|
||||
return HorizontalLayout::Builder(
|
||||
CodePointLayout::Builder(fullName()[0], KDFont::SmallFont),
|
||||
VerticalOffsetLayout::Builder(CodePointLayout::Builder(symbol(), KDFont::SmallFont), VerticalOffsetLayoutNode::Position::Subscript)
|
||||
);
|
||||
}
|
||||
|
||||
bool Sequence::isDefined() {
|
||||
|
||||
@@ -24,8 +24,9 @@ public:
|
||||
DoubleRecurrence = 2
|
||||
};
|
||||
Sequence(Ion::Storage::Record record = Record()) :
|
||||
Function(record),
|
||||
m_nameLayout() {}
|
||||
Function(record)
|
||||
{
|
||||
}
|
||||
I18n::Message parameterMessageName() const override;
|
||||
CodePoint symbol() const override { return 'n'; }
|
||||
void tidy() override;
|
||||
@@ -111,7 +112,7 @@ private:
|
||||
public:
|
||||
SequenceModel() : Shared::ExpressionModel(), m_name() {}
|
||||
void tidyName() { m_name = Poincare::Layout(); }
|
||||
virtual Poincare::Layout name(Sequence * sequence);
|
||||
Poincare::Layout name(Sequence * sequence);
|
||||
protected:
|
||||
virtual void buildName(Sequence * sequence) = 0;
|
||||
Poincare::Layout m_name;
|
||||
@@ -153,7 +154,6 @@ private:
|
||||
DefinitionModel m_definition;
|
||||
FirstInitialConditionModel m_firstInitialCondition;
|
||||
SecondInitialConditionModel m_secondInitialCondition;
|
||||
Poincare::Layout m_nameLayout;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ Ion::Storage::Record::ErrorStatus SequenceStore::addEmptyModel() {
|
||||
const char * name = firstAvailableName(&nameIndex);
|
||||
assert(name);
|
||||
// Choose the corresponding color
|
||||
assert(nameIndex < Palette::numberOfDataColors());
|
||||
KDColor color = Palette::DataColor[nameIndex];
|
||||
Sequence::RecordDataBuffer data(color);
|
||||
// m_sequences
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
app_shared_test_src = $(addprefix apps/shared/,\
|
||||
continuous_function.cpp\
|
||||
curve_view_range.cpp \
|
||||
curve_view.cpp \
|
||||
dots.cpp \
|
||||
double_pair_store.cpp \
|
||||
expression_model.cpp \
|
||||
expression_model_handle.cpp \
|
||||
@@ -9,8 +11,11 @@ app_shared_test_src = $(addprefix apps/shared/,\
|
||||
global_context.cpp \
|
||||
interactive_curve_view_range_delegate.cpp \
|
||||
interactive_curve_view_range.cpp \
|
||||
labeled_curve_view.cpp \
|
||||
memoized_curve_view_range.cpp \
|
||||
range_1D.cpp \
|
||||
zoom_and_pan_curve_view_controller.cpp \
|
||||
zoom_curve_view_controller.cpp \
|
||||
)
|
||||
|
||||
app_shared_src = $(addprefix apps/shared/,\
|
||||
@@ -18,9 +23,7 @@ app_shared_src = $(addprefix apps/shared/,\
|
||||
buffer_function_title_cell.cpp \
|
||||
buffer_text_view_with_text_field.cpp \
|
||||
button_with_separator.cpp \
|
||||
dots.cpp \
|
||||
cursor_view.cpp \
|
||||
curve_view.cpp \
|
||||
curve_view_cursor.cpp \
|
||||
editable_cell_table_view_controller.cpp \
|
||||
expression_field_delegate_app.cpp \
|
||||
|
||||
@@ -57,8 +57,7 @@ ContinuousFunction ContinuousFunction::NewModel(Ion::Storage::Record::ErrorStatu
|
||||
static int s_colorIndex = 0;
|
||||
// Create the record
|
||||
char nameBuffer[SymbolAbstract::k_maxNameSize];
|
||||
int numberOfColors = sizeof(Palette::DataColor)/sizeof(KDColor);
|
||||
RecordDataBuffer data(Palette::DataColor[s_colorIndex++ % numberOfColors]);
|
||||
RecordDataBuffer data(Palette::nextDataColor(&s_colorIndex));
|
||||
if (baseName == nullptr) {
|
||||
DefaultName(nameBuffer, SymbolAbstract::k_maxNameSize);
|
||||
baseName = nameBuffer;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#ifndef SHARED_CURSOR_VIEW_H
|
||||
#define SHARED_CURSOR_VIEW_H
|
||||
|
||||
#include <escher.h>
|
||||
#include <escher/transparent_view.h>
|
||||
#include <escher/palette.h>
|
||||
|
||||
namespace Shared {
|
||||
|
||||
class CursorView : public View {
|
||||
class CursorView : public TransparentView {
|
||||
public:
|
||||
virtual void setCursorFrame(KDRect frame, bool force) { View::setFrame(frame, force); }
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
|
||||
@@ -106,11 +106,11 @@ void CurveView::setOkView(View * okView) {
|
||||
* m_frame.height() - 1 yMin()
|
||||
*/
|
||||
|
||||
const float CurveView::pixelWidth() const {
|
||||
float CurveView::pixelWidth() const {
|
||||
return (m_curveViewRange->xMax() - m_curveViewRange->xMin()) / (m_frame.width() - 1);
|
||||
}
|
||||
|
||||
const float CurveView::pixelHeight() const {
|
||||
float CurveView::pixelHeight() const {
|
||||
return (m_curveViewRange->yMax() - m_curveViewRange->yMin()) / (m_frame.height() - 1);
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ void CurveView::drawLabelsAndGraduations(KDContext * ctx, KDRect rect, Axis axis
|
||||
position = positionLabel(horizontalCoordinate, labelPosition, textSize, RelativePosition::Before, RelativePosition::None);
|
||||
if (floatingLabels == FloatingPosition::Min) {
|
||||
position = KDPoint(k_labelMargin, position.y());
|
||||
} else if (floatingLabels == FloatingPosition::Min) {
|
||||
} else if (floatingLabels == FloatingPosition::Max) {
|
||||
position = KDPoint(Ion::Display::Width - textSize.width() - k_labelMargin, position.y());
|
||||
}
|
||||
}
|
||||
@@ -386,7 +386,7 @@ DrawLabel:
|
||||
}
|
||||
}
|
||||
|
||||
void CurveView::drawSegment(KDContext * ctx, KDRect rect, Axis axis, float coordinate, float lowerBound, float upperBound, KDColor color, KDCoordinate thickness, KDCoordinate dashSize) const {
|
||||
void CurveView::drawHorizontalOrVerticalSegment(KDContext * ctx, KDRect rect, Axis axis, float coordinate, float lowerBound, float upperBound, KDColor color, KDCoordinate thickness, KDCoordinate dashSize) const {
|
||||
KDCoordinate min = (axis == Axis::Horizontal) ? rect.x() : rect.y();
|
||||
KDCoordinate max = (axis == Axis::Horizontal) ? rect.x() + rect.width() : rect.y() + rect.height();
|
||||
KDCoordinate start = std::isinf(lowerBound) ? min : std::round(floatToPixel(axis, lowerBound));
|
||||
@@ -417,6 +417,14 @@ void CurveView::drawSegment(KDContext * ctx, KDRect rect, Axis axis, float coord
|
||||
}
|
||||
}
|
||||
|
||||
void CurveView::drawSegment(KDContext * ctx, KDRect rect, float x, float y, float u, float v, KDColor color, bool thick) const {
|
||||
float pxf = floatToPixel(Axis::Horizontal, x);
|
||||
float pyf = floatToPixel(Axis::Vertical, y);
|
||||
float puf = floatToPixel(Axis::Horizontal, u);
|
||||
float pvf = floatToPixel(Axis::Vertical, v);
|
||||
straightJoinDots(ctx, rect, pxf, pyf, puf, pvf, color, thick);
|
||||
}
|
||||
|
||||
void CurveView::drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor color, Size size) const {
|
||||
KDCoordinate diameter = 0;
|
||||
const uint8_t * mask = nullptr;
|
||||
@@ -444,6 +452,47 @@ void CurveView::drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor
|
||||
ctx->blendRectWithMask(dotRect, color, mask, workingBuffer);
|
||||
}
|
||||
|
||||
|
||||
void CurveView::drawArrow(KDContext * ctx, KDRect rect, float x, float y, float dx, float dy, KDColor color, KDCoordinate pixelArrowLength, float angle) const {
|
||||
/* Let's call the following variables L and l:
|
||||
*
|
||||
* / |
|
||||
* / |
|
||||
* / l
|
||||
* / |
|
||||
* / |
|
||||
* <--------------------------------------------------
|
||||
* \
|
||||
* \
|
||||
* \
|
||||
* \
|
||||
* \
|
||||
*
|
||||
* ----- L -----
|
||||
*
|
||||
**/
|
||||
assert(angle >= 0.0f);
|
||||
/* We compute the arrow segments in pixels in order to correctly size the
|
||||
* arrow without depending on the displayed range.
|
||||
* Warning: the computed values are relative so we need to add/subtract the
|
||||
* pixel position of 0s. */
|
||||
float x0Pixel = floatToPixel(Axis::Horizontal, 0.0f);
|
||||
float y0Pixel = floatToPixel(Axis::Vertical, 0.0f);
|
||||
float dxPixel = floatToPixel(Axis::Horizontal, dx) - x0Pixel;
|
||||
float dyPixel = y0Pixel - floatToPixel(Axis::Vertical, dy);
|
||||
float dx2dy2 = std::sqrt(dxPixel*dxPixel+dyPixel*dyPixel);
|
||||
float L = pixelArrowLength;
|
||||
float l = angle*L;
|
||||
|
||||
float arrow1dx = pixelToFloat(Axis::Horizontal, x0Pixel + L*dxPixel/dx2dy2 + l*dyPixel/dx2dy2);
|
||||
float arrow1dy = pixelToFloat(Axis::Vertical, y0Pixel - (L*dyPixel/dx2dy2 - l*dxPixel/dx2dy2));
|
||||
drawSegment(ctx, rect, x, y, x - arrow1dx, y - arrow1dy, color, false);
|
||||
|
||||
float arrow2dx = pixelToFloat(Axis::Horizontal, x0Pixel + L*dxPixel/dx2dy2 - l*dyPixel/dx2dy2);
|
||||
float arrow2dy = pixelToFloat(Axis::Vertical, y0Pixel - (L*dyPixel/dx2dy2 + l*dxPixel/dx2dy2));
|
||||
drawSegment(ctx, rect, x, y, x - arrow2dx, y - arrow2dy, color, false);
|
||||
}
|
||||
|
||||
void CurveView::drawGrid(KDContext * ctx, KDRect rect) const {
|
||||
KDColor boldColor = Palette::GridPrimaryLine;
|
||||
KDColor lightColor = Palette::GridSecondaryLine;
|
||||
@@ -537,7 +586,7 @@ void CurveView::drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd
|
||||
x = xy.x1();
|
||||
y = xy.x2();
|
||||
if (colorUnderCurve && !std::isnan(x) && colorLowerBound < x && x < colorUpperBound && !(std::isnan(y) || std::isinf(y))) {
|
||||
drawSegment(ctx, rect, Axis::Vertical, x, minFloat(0.0f, y), maxFloat(0.0f, y), color, 1);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, x, minFloat(0.0f, y), maxFloat(0.0f, y), color, 1);
|
||||
}
|
||||
joinDots(ctx, rect, xyEvaluation, model, context, drawStraightLinesEarly, previousT, previousX, previousY, t, x, y, color, thick, k_maxNumberOfIterations);
|
||||
} while (true);
|
||||
|
||||
@@ -38,8 +38,8 @@ public:
|
||||
void setBannerView(View * bannerView);
|
||||
void setOkView(View * okView);
|
||||
void setForceOkDisplay(bool force) { m_forceOkDisplay = force; }
|
||||
const float pixelWidth() const;
|
||||
const float pixelHeight() const;
|
||||
float pixelWidth() const;
|
||||
float pixelHeight() const;
|
||||
protected:
|
||||
CurveViewRange * curveViewRange() const { return m_curveViewRange; }
|
||||
void setCurveViewRange(CurveViewRange * curveViewRange);
|
||||
@@ -59,18 +59,47 @@ protected:
|
||||
float floatToPixel(Axis axis, float f) const;
|
||||
void drawLine(KDContext * ctx, KDRect rect, Axis axis,
|
||||
float coordinate, KDColor color, KDCoordinate thickness = 1, KDCoordinate dashSize = -1) const {
|
||||
return drawSegment(ctx, rect, axis, coordinate, -INFINITY, INFINITY, color,
|
||||
return drawHorizontalOrVerticalSegment(ctx, rect, axis, coordinate, -INFINITY, INFINITY, color,
|
||||
thickness, dashSize);
|
||||
}
|
||||
void drawSegment(KDContext * ctx, KDRect rect, Axis axis,
|
||||
void drawHorizontalOrVerticalSegment(KDContext * ctx, KDRect rect, Axis axis,
|
||||
float coordinate, float lowerBound, float upperBound,
|
||||
KDColor color, KDCoordinate thickness = 1, KDCoordinate dashSize = -1) const;
|
||||
void drawSegment(KDContext * ctx, KDRect rect,
|
||||
float x, float y, float u, float v,
|
||||
KDColor color, bool thick = true
|
||||
) const;
|
||||
enum class Size : uint8_t {
|
||||
Small,
|
||||
Medium,
|
||||
Large
|
||||
};
|
||||
void drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor color, Size size = Size::Small) const;
|
||||
/* 'drawArrow' draws the edge of an arrow pointing to (x,y) with the
|
||||
* orientation (dx,dy).
|
||||
* The parameters defining the shape of the arrow are the length in pixel of
|
||||
* the projection of the arrow on the segment -'pixelArrowLength'- and the
|
||||
* tangent of the angle between the segment and each wing of the arrow called
|
||||
* 'angle'.
|
||||
*
|
||||
* / |
|
||||
* / |
|
||||
* / L
|
||||
* / |
|
||||
* / |
|
||||
* <--------------------------------------------------
|
||||
* \
|
||||
* \
|
||||
* \
|
||||
* \
|
||||
* \
|
||||
*
|
||||
* <--- pl --->
|
||||
*
|
||||
* pl = pixelArrowLength
|
||||
* tan(angle) = L/pl
|
||||
*/
|
||||
void drawArrow(KDContext * ctx, KDRect rect, float x, float y, float dx, float dy, KDColor color, KDCoordinate pixelArrowLength = 10, float angle = 0.4f) const;
|
||||
void drawGrid(KDContext * ctx, KDRect rect) const;
|
||||
void drawAxes(KDContext * ctx, KDRect rect) const;
|
||||
void drawAxis(KDContext * ctx, KDRect rect, Axis axis) const;
|
||||
@@ -100,7 +129,7 @@ private:
|
||||
float min(Axis axis) const;
|
||||
float max(Axis axis) const;
|
||||
float gridUnit(Axis axis) const;
|
||||
virtual char * label(Axis axis, int index) const = 0;
|
||||
virtual char * label(Axis axis, int index) const { return nullptr; }
|
||||
virtual size_t labelMaxGlyphLengthSize() const { return k_labelBufferMaxGlyphLength; }
|
||||
int numberOfLabels(Axis axis) const;
|
||||
/* Recursively join two dots (dichotomy). The method stops when the
|
||||
|
||||
@@ -17,8 +17,8 @@ public:
|
||||
virtual float xMax() const = 0;
|
||||
virtual float yMin() const = 0;
|
||||
virtual float yMax() const = 0;
|
||||
const float xCenter() const { return (xMin() + xMax()) / 2; }
|
||||
const float yCenter() const { return (yMin() + yMax()) / 2; }
|
||||
float xCenter() const { return (xMin() + xMax()) / 2; }
|
||||
float yCenter() const { return (yMin() + yMax()) / 2; }
|
||||
virtual float xGridUnit() const {
|
||||
return computeGridUnit(k_minNumberOfXGridUnits, k_maxNumberOfXGridUnits, xMax() - xMin());
|
||||
}
|
||||
|
||||
@@ -55,10 +55,12 @@ public:
|
||||
// Colors
|
||||
static KDColor colorOfSeriesAtIndex(int i) {
|
||||
assert(i >= 0 && i < k_numberOfSeries);
|
||||
assert(i < Palette::numberOfDataColors());
|
||||
return Palette::DataColor[i];
|
||||
}
|
||||
static KDColor colorLightOfSeriesAtIndex(int i) {
|
||||
assert(i >= 0 && i < k_numberOfSeries);
|
||||
assert(i < Palette::numberOfLightDataColors());
|
||||
return Palette::DataColorLight[i];
|
||||
}
|
||||
protected:
|
||||
|
||||
@@ -11,11 +11,14 @@ FunctionApp::Snapshot::Snapshot() :
|
||||
m_rangeVersion(0),
|
||||
m_angleUnitVersion(Preferences::AngleUnit::Radian)
|
||||
{
|
||||
assert(m_previousModelsVersions[0] == 0);
|
||||
}
|
||||
|
||||
void FunctionApp::Snapshot::reset() {
|
||||
m_indexFunctionSelectedByCursor = 0;
|
||||
m_modelVersion = 0;
|
||||
assert(sizeof(m_previousModelsVersions) == sizeof(uint32_t) * FunctionGraphController::sNumberOfMemoizedModelVersions);
|
||||
memset(m_previousModelsVersions, 0, sizeof(m_previousModelsVersions));
|
||||
m_rangeVersion = 0;
|
||||
setActiveTab(0);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define SHARED_FUNCTION_APP_H
|
||||
|
||||
#include "expression_field_delegate_app.h"
|
||||
#include "function_graph_controller.h"
|
||||
#include "function_store.h"
|
||||
#include "curve_view_cursor.h"
|
||||
#include "values_controller.h"
|
||||
@@ -15,6 +16,7 @@ public:
|
||||
Snapshot();
|
||||
CurveViewCursor * cursor() { return &m_cursor; }
|
||||
uint32_t * modelVersion() { return &m_modelVersion; }
|
||||
uint32_t * previousModelsVersions() { return m_previousModelsVersions; }
|
||||
uint32_t * rangeVersion() { return &m_rangeVersion; }
|
||||
Poincare::Preferences::AngleUnit * angleUnitVersion() { return &m_angleUnitVersion; }
|
||||
virtual FunctionStore * functionStore() = 0;
|
||||
@@ -26,6 +28,7 @@ public:
|
||||
private:
|
||||
int m_indexFunctionSelectedByCursor;
|
||||
uint32_t m_modelVersion;
|
||||
uint32_t m_previousModelsVersions[FunctionGraphController::sNumberOfMemoizedModelVersions];
|
||||
uint32_t m_rangeVersion;
|
||||
Poincare::Preferences::AngleUnit m_angleUnitVersion;
|
||||
};
|
||||
|
||||
@@ -15,8 +15,8 @@ static inline float maxFloat(float x, float y) { return x > y ? x : y; }
|
||||
static inline double minDouble(double x, double y) { return x < y ? x : y; }
|
||||
static inline double maxDouble(double x, double y) { return x > y ? x : y; }
|
||||
|
||||
FunctionGraphController::FunctionGraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, InteractiveCurveViewRange * interactiveRange, CurveView * curveView, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Preferences::AngleUnit * angleUnitVersion) :
|
||||
InteractiveCurveViewController(parentResponder, inputEventHandlerDelegate, header, interactiveRange, curveView, cursor, modelVersion, rangeVersion),
|
||||
FunctionGraphController::FunctionGraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, InteractiveCurveViewRange * interactiveRange, CurveView * curveView, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, Preferences::AngleUnit * angleUnitVersion) :
|
||||
InteractiveCurveViewController(parentResponder, inputEventHandlerDelegate, header, interactiveRange, curveView, cursor, modelVersion, previousModelsVersions, rangeVersion),
|
||||
m_initialisationParameterController(this, interactiveRange),
|
||||
m_angleUnitVersion(angleUnitVersion),
|
||||
m_indexFunctionSelectedByCursor(indexFunctionSelectedByCursor)
|
||||
@@ -183,6 +183,10 @@ uint32_t FunctionGraphController::modelVersion() {
|
||||
return functionStore()->storeChecksum();
|
||||
}
|
||||
|
||||
uint32_t FunctionGraphController::modelVersionAtIndex(size_t i) {
|
||||
return functionStore()->storeChecksumAtIndex(i);
|
||||
}
|
||||
|
||||
uint32_t FunctionGraphController::rangeVersion() {
|
||||
return interactiveCurveViewRange()->rangeChecksum();
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace Shared {
|
||||
|
||||
class FunctionGraphController : public InteractiveCurveViewController, public FunctionBannerDelegate {
|
||||
public:
|
||||
FunctionGraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, InteractiveCurveViewRange * interactiveRange, CurveView * curveView, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion);
|
||||
static constexpr size_t sNumberOfMemoizedModelVersions = 5;
|
||||
FunctionGraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, InteractiveCurveViewRange * interactiveRange, CurveView * curveView, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion);
|
||||
bool isEmpty() const override;
|
||||
ViewController * initialisationParameterController() override;
|
||||
void didBecomeFirstResponder() override;
|
||||
@@ -49,7 +50,9 @@ private:
|
||||
// InteractiveCurveViewController
|
||||
bool moveCursorVertically(int direction) override;
|
||||
uint32_t modelVersion() override;
|
||||
uint32_t modelVersionAtIndex(size_t i) override;
|
||||
uint32_t rangeVersion() override;
|
||||
size_t numberOfMemoizedVersions() const override { return sNumberOfMemoizedModelVersions; }
|
||||
|
||||
InitialisationParameterController m_initialisationParameterController;
|
||||
Poincare::Preferences::AngleUnit * m_angleUnitVersion;
|
||||
|
||||
@@ -8,13 +8,11 @@ namespace Shared {
|
||||
|
||||
FunctionGraphView::FunctionGraphView(InteractiveCurveViewRange * graphRange,
|
||||
CurveViewCursor * cursor, BannerView * bannerView, CursorView * cursorView) :
|
||||
CurveView(graphRange, cursor, bannerView, cursorView),
|
||||
LabeledCurveView(graphRange, cursor, bannerView, cursorView),
|
||||
m_selectedRecord(),
|
||||
m_highlightedStart(NAN),
|
||||
m_highlightedEnd(NAN),
|
||||
m_shouldColorHighlighted(false),
|
||||
m_xLabels{},
|
||||
m_yLabels{},
|
||||
m_context(nullptr)
|
||||
{
|
||||
}
|
||||
@@ -67,10 +65,6 @@ void FunctionGraphView::setAreaHighlightColor(bool highlightColor) {
|
||||
}
|
||||
}
|
||||
|
||||
char * FunctionGraphView::label(Axis axis, int index) const {
|
||||
return (axis == Axis::Horizontal ? (char *)m_xLabels[index] : (char *)m_yLabels[index]);
|
||||
}
|
||||
|
||||
void FunctionGraphView::reloadBetweenBounds(float start, float end) {
|
||||
if (start == end) {
|
||||
return;
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
#define SHARED_FUNCTION_GRAPH_VIEW_H
|
||||
|
||||
#include <escher.h>
|
||||
#include "curve_view.h"
|
||||
#include "labeled_curve_view.h"
|
||||
#include "function.h"
|
||||
#include "../constant.h"
|
||||
#include "interactive_curve_view_range.h"
|
||||
|
||||
namespace Shared {
|
||||
|
||||
class FunctionGraphView : public CurveView {
|
||||
class FunctionGraphView : public LabeledCurveView {
|
||||
public:
|
||||
FunctionGraphView(InteractiveCurveViewRange * graphRange, CurveViewCursor * cursor,
|
||||
BannerView * bannerView, CursorView * cursorView);
|
||||
@@ -26,9 +26,6 @@ protected:
|
||||
float m_highlightedEnd;
|
||||
bool m_shouldColorHighlighted;
|
||||
private:
|
||||
char * label(Axis axis, int index) const override;
|
||||
char m_xLabels[k_maxNumberOfXLabels][k_labelBufferMaxSize];
|
||||
char m_yLabels[k_maxNumberOfYLabels][k_labelBufferMaxSize];
|
||||
Poincare::Context * m_context;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,4 +6,11 @@ uint32_t FunctionStore::storeChecksum() {
|
||||
return Ion::Storage::sharedStorage()->checksum();
|
||||
}
|
||||
|
||||
uint32_t FunctionStore::storeChecksumAtIndex(size_t i) {
|
||||
if (numberOfActiveFunctions() <= i) {
|
||||
return 0;
|
||||
}
|
||||
return activeRecordAtIndex(i).checksum();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ class FunctionStore : public ExpressionModelStore {
|
||||
public:
|
||||
FunctionStore() : ExpressionModelStore() {}
|
||||
uint32_t storeChecksum();
|
||||
uint32_t storeChecksumAtIndex(size_t i);
|
||||
int numberOfActiveFunctions() const {
|
||||
return numberOfModelsSatisfyingTest(&isFunctionActive, nullptr);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,11 @@ using namespace Poincare;
|
||||
|
||||
namespace Shared {
|
||||
|
||||
InteractiveCurveViewController::InteractiveCurveViewController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, InteractiveCurveViewRange * interactiveRange, CurveView * curveView, CurveViewCursor * cursor, uint32_t * modelVersion, uint32_t * rangeVersion) :
|
||||
InteractiveCurveViewController::InteractiveCurveViewController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, InteractiveCurveViewRange * interactiveRange, CurveView * curveView, CurveViewCursor * cursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion) :
|
||||
SimpleInteractiveCurveViewController(parentResponder, cursor),
|
||||
ButtonRowDelegate(header, nullptr),
|
||||
m_modelVersion(modelVersion),
|
||||
m_previousModelsVersions(previousModelsVersions),
|
||||
m_rangeVersion(rangeVersion),
|
||||
m_rangeParameterController(this, inputEventHandlerDelegate, interactiveRange),
|
||||
m_zoomParameterController(this, interactiveRange, curveView),
|
||||
@@ -132,11 +133,43 @@ Responder * InteractiveCurveViewController::defaultController() {
|
||||
return tabController();
|
||||
}
|
||||
|
||||
bool InteractiveCurveViewController::previousModelsWereAllDeleted() {
|
||||
bool result = true;
|
||||
const int modelsCount = numberOfCurves();
|
||||
const int memoizationCount = numberOfMemoizedVersions();
|
||||
|
||||
// Look for a current model that is the same as in the previous version
|
||||
for (int i = 0; i < modelsCount; i++) {
|
||||
uint32_t currentVersion = modelVersionAtIndex(i);
|
||||
for (int j = 0; j < memoizationCount; j++) {
|
||||
uint32_t * previousVersion = m_previousModelsVersions + j;
|
||||
if (currentVersion == *previousVersion) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the memoization
|
||||
for (int i = 0; i < memoizationCount; i++) {
|
||||
uint32_t * previousVersion = m_previousModelsVersions + i;
|
||||
uint32_t newVersion = modelVersionAtIndex(i);
|
||||
if (*previousVersion != newVersion) {
|
||||
*previousVersion = newVersion;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void InteractiveCurveViewController::viewWillAppear() {
|
||||
SimpleInteractiveCurveViewController::viewWillAppear();
|
||||
uint32_t newModelVersion = modelVersion();
|
||||
if (*m_modelVersion != newModelVersion) {
|
||||
if (*m_modelVersion == 0 || numberOfCurves() == 1 || shouldSetDefaultOnModelChange()) {
|
||||
// Put previousModelsWereAllDeleted first to update the model versions
|
||||
if (previousModelsWereAllDeleted() || *m_modelVersion == 0 || numberOfCurves() == 1 || shouldSetDefaultOnModelChange()) {
|
||||
interactiveCurveViewRange()->setDefault();
|
||||
}
|
||||
*m_modelVersion = newModelVersion;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Shared {
|
||||
|
||||
class InteractiveCurveViewController : public SimpleInteractiveCurveViewController, public InteractiveCurveViewRangeDelegate, public ButtonRowDelegate, public AlternateEmptyViewDefaultDelegate {
|
||||
public:
|
||||
InteractiveCurveViewController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, InteractiveCurveViewRange * interactiveRange, CurveView * curveView, CurveViewCursor * cursor, uint32_t * modelVersion, uint32_t * rangeVersion);
|
||||
InteractiveCurveViewController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, InteractiveCurveViewRange * interactiveRange, CurveView * curveView, CurveViewCursor * cursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion);
|
||||
|
||||
const char * title() override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
@@ -28,6 +28,8 @@ public:
|
||||
|
||||
Responder * defaultController() override;
|
||||
|
||||
bool previousModelsWereAllDeleted();
|
||||
|
||||
void viewWillAppear() override;
|
||||
void viewDidDisappear() override;
|
||||
void willExitResponderChain(Responder * nextFirstResponder) override;
|
||||
@@ -39,6 +41,7 @@ protected:
|
||||
virtual void initCursorParameters() = 0;
|
||||
virtual bool moveCursorVertically(int direction) = 0;
|
||||
virtual uint32_t modelVersion() = 0;
|
||||
virtual uint32_t modelVersionAtIndex(size_t i) = 0;
|
||||
virtual uint32_t rangeVersion() = 0;
|
||||
bool isCursorVisible();
|
||||
|
||||
@@ -66,7 +69,9 @@ private:
|
||||
float addMargin(float x, float range, bool isVertical, bool isMin) override;
|
||||
|
||||
virtual bool shouldSetDefaultOnModelChange() const { return false; }
|
||||
virtual size_t numberOfMemoizedVersions() const = 0;
|
||||
uint32_t * m_modelVersion;
|
||||
uint32_t * m_previousModelsVersions;
|
||||
uint32_t * m_rangeVersion;
|
||||
RangeParameterController m_rangeParameterController;
|
||||
ZoomParameterController m_zoomParameterController;
|
||||
|
||||
31
apps/shared/labeled_curve_view.cpp
Normal file
31
apps/shared/labeled_curve_view.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "labeled_curve_view.h"
|
||||
|
||||
namespace Shared {
|
||||
|
||||
char * HorizontallyLabeledCurveView::label(Axis axis, int index) const {
|
||||
if (axis == Axis::Horizontal) {
|
||||
assert(index < k_maxNumberOfXLabels);
|
||||
return m_xLabels[index];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char * VerticallyLabeledCurveView::label(Axis axis, int index) const {
|
||||
if (axis == Axis::Vertical) {
|
||||
assert(index < k_maxNumberOfYLabels);
|
||||
return m_yLabels[index];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char * LabeledCurveView::label(Axis axis, int index) const {
|
||||
if (axis == Axis::Horizontal) {
|
||||
assert(index < k_maxNumberOfXLabels);
|
||||
return m_xLabels[index];
|
||||
} else {
|
||||
assert(index < k_maxNumberOfYLabels);
|
||||
return m_yLabels[index];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
37
apps/shared/labeled_curve_view.h
Normal file
37
apps/shared/labeled_curve_view.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef SHARED_LABELED_CURVE_VIEW_H
|
||||
#define SHARED_LABELED_CURVE_VIEW_H
|
||||
|
||||
#include "curve_view.h"
|
||||
|
||||
/* This CurveView subclass provides label storage for common use cases */
|
||||
|
||||
namespace Shared {
|
||||
|
||||
class HorizontallyLabeledCurveView : public CurveView {
|
||||
public:
|
||||
using CurveView::CurveView;
|
||||
private:
|
||||
char * label(Axis axis, int index) const override;
|
||||
mutable char m_xLabels[k_maxNumberOfXLabels][k_labelBufferMaxSize];
|
||||
};
|
||||
|
||||
class VerticallyLabeledCurveView : public CurveView {
|
||||
public:
|
||||
using CurveView::CurveView;
|
||||
private:
|
||||
char * label(Axis axis, int index) const override;
|
||||
mutable char m_yLabels[k_maxNumberOfYLabels][k_labelBufferMaxSize];
|
||||
};
|
||||
|
||||
class LabeledCurveView : public CurveView {
|
||||
public:
|
||||
using CurveView::CurveView;
|
||||
private:
|
||||
char * label(Axis axis, int index) const override;
|
||||
mutable char m_xLabels[k_maxNumberOfXLabels][k_labelBufferMaxSize];
|
||||
mutable char m_yLabels[k_maxNumberOfYLabels][k_labelBufferMaxSize];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -49,6 +49,14 @@ void RoundCursorView::setCursorFrame(KDRect f, bool force) {
|
||||
CursorView::setCursorFrame(f, force);
|
||||
}
|
||||
|
||||
void RoundCursorView::markRectAsDirty(KDRect rect) {
|
||||
/* The CursorView class inherits from TransparentView, so does
|
||||
* RoundCursorView. The method markRectAsDirty is thus overriden to avoid
|
||||
* marking as dirty the background of the RoundCursorView in its superview.
|
||||
*/
|
||||
View::markRectAsDirty(rect);
|
||||
}
|
||||
|
||||
#ifdef GRAPH_CURSOR_SPEEDUP
|
||||
bool RoundCursorView::eraseCursorIfPossible() {
|
||||
if (!m_underneathPixelBufferLoaded) {
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
void resetMemoization() const { m_underneathPixelBufferLoaded = false; }
|
||||
#endif
|
||||
private:
|
||||
void markRectAsDirty(KDRect rect) override;
|
||||
#ifdef GRAPH_CURSOR_SPEEDUP
|
||||
bool eraseCursorIfPossible();
|
||||
#endif
|
||||
|
||||
@@ -6,16 +6,6 @@ using namespace Poincare;
|
||||
|
||||
namespace Shared {
|
||||
|
||||
SimpleInteractiveCurveViewController::SimpleInteractiveCurveViewController(Responder * parentResponder, CurveViewCursor * cursor) :
|
||||
ViewController(parentResponder),
|
||||
m_cursor(cursor)
|
||||
{
|
||||
}
|
||||
|
||||
View * SimpleInteractiveCurveViewController::view() {
|
||||
return curveView();
|
||||
}
|
||||
|
||||
bool SimpleInteractiveCurveViewController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::Plus || event == Ion::Events::Minus) {
|
||||
return handleZoom(event);
|
||||
@@ -36,13 +26,6 @@ bool SimpleInteractiveCurveViewController::textFieldDidReceiveEvent(TextField *
|
||||
return TextFieldDelegate::textFieldDidReceiveEvent(textField, event);
|
||||
}
|
||||
|
||||
bool SimpleInteractiveCurveViewController::handleZoom(Ion::Events::Event event) {
|
||||
float ratio = event == Ion::Events::Plus ? 2.0f/3.0f : 3.0f/2.0f;
|
||||
interactiveCurveViewRange()->zoom(ratio, m_cursor->x(), m_cursor->y());
|
||||
curveView()->reload();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleInteractiveCurveViewController::handleLeftRightEvent(Ion::Events::Event event) {
|
||||
int direction = event == Ion::Events::Left ? -1 : 1;
|
||||
if (moveCursorHorizontally(direction, Ion::Events::isLongRepetition())) {
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
#ifndef SHARED_SIMPLE_INTERACTIVE_CURVE_VIEW_CONTROLLER_H
|
||||
#define SHARED_SIMPLE_INTERACTIVE_CURVE_VIEW_CONTROLLER_H
|
||||
|
||||
#include <escher/view_controller.h>
|
||||
#include "text_field_delegate.h"
|
||||
#include "interactive_curve_view_range.h"
|
||||
#include "curve_view_cursor.h"
|
||||
#include "curve_view.h"
|
||||
#include "zoom_curve_view_controller.h"
|
||||
|
||||
namespace Shared {
|
||||
|
||||
/* SimpleInteractiveCurveViewController is a View controller with a cursor that
|
||||
* can handles zoom in/out and left and right events. */
|
||||
|
||||
class SimpleInteractiveCurveViewController : public ViewController, public TextFieldDelegate {
|
||||
class SimpleInteractiveCurveViewController : public ZoomCurveViewController, public TextFieldDelegate {
|
||||
public:
|
||||
SimpleInteractiveCurveViewController(Responder * parentResponder, CurveViewCursor * cursor);
|
||||
View * view() override;
|
||||
SimpleInteractiveCurveViewController(Responder * parentResponder, CurveViewCursor * cursor) : ZoomCurveViewController(parentResponder), m_cursor(cursor) {}
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||
protected:
|
||||
@@ -24,15 +20,15 @@ protected:
|
||||
virtual float cursorTopMarginRatio() { return 0.07f; } // (cursorHeight/2)/(graphViewHeight-1)
|
||||
virtual float cursorBottomMarginRatio() = 0; // (cursorHeight/2+bannerHeight)/(graphViewHeight-1)
|
||||
constexpr static float k_numberOfCursorStepsInGradUnit = 5.0f;
|
||||
virtual bool handleZoom(Ion::Events::Event event);
|
||||
// ZoomCurveViewController
|
||||
float xFocus() override { return m_cursor->x(); }
|
||||
float yFocus() override { return m_cursor->y(); }
|
||||
virtual bool handleLeftRightEvent(Ion::Events::Event event);
|
||||
virtual void reloadBannerView() = 0;
|
||||
/* the result of moveCursorVertically/Horizontally means:
|
||||
* false -> the cursor cannot move in this direction
|
||||
* true -> the cursor moved */
|
||||
virtual bool moveCursorHorizontally(int direction, bool fast = false) { return false; }
|
||||
virtual InteractiveCurveViewRange * interactiveCurveViewRange() = 0;
|
||||
virtual CurveView * curveView() = 0;
|
||||
virtual bool handleEnter() = 0;
|
||||
CurveViewCursor * m_cursor;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <poincare/empty_layout.h>
|
||||
#include <poincare/condensed_sum_layout.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/preferences.h>
|
||||
#include "poincare_helpers.h"
|
||||
|
||||
#include <assert.h>
|
||||
@@ -150,14 +149,13 @@ void SumGraphController::reloadBannerView() {
|
||||
m_legendView.setEditableZone(m_cursor->x());
|
||||
result = NAN;
|
||||
}
|
||||
m_legendView.setSumSymbol(m_step, m_startSum, endSum, result, functionLayout);
|
||||
m_legendView.setSumLayout(m_step, m_startSum, endSum, result, functionLayout);
|
||||
}
|
||||
|
||||
/* Legend View */
|
||||
|
||||
SumGraphController::LegendView::LegendView(SumGraphController * controller, InputEventHandlerDelegate * inputEventHandlerDelegate, CodePoint sumSymbol) :
|
||||
m_sum(0.0f, 0.5f, Palette::PrimaryText, Palette::SubMenuBackground),
|
||||
m_sumLayout(),
|
||||
m_legend(k_font, I18n::Message::Default, 0.0f, 0.5f, Palette::PrimaryText, Palette::SubMenuBackground),
|
||||
m_editableZone(controller, m_textBuffer, k_editableZoneBufferSize, TextField::maxBufferSize(), inputEventHandlerDelegate, controller, k_font, 0.0f, 0.5f, Palette::PrimaryText, Palette::SubMenuBackground),
|
||||
m_sumSymbol(sumSymbol)
|
||||
@@ -179,54 +177,41 @@ void SumGraphController::LegendView::setLegendMessage(I18n::Message message, Ste
|
||||
}
|
||||
|
||||
void SumGraphController::LegendView::setEditableZone(double d) {
|
||||
constexpr int precision = Preferences::MediumNumberOfSignificantDigits;
|
||||
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
|
||||
char buffer[bufferSize];
|
||||
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(d, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
|
||||
char buffer[k_valuesBufferSize];
|
||||
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(d, buffer, k_valuesBufferSize, k_valuesPrecision, Preferences::PrintFloatMode::Decimal);
|
||||
m_editableZone.setText(buffer);
|
||||
}
|
||||
|
||||
void SumGraphController::LegendView::setSumSymbol(Step step, double start, double end, double result, Layout functionLayout) {
|
||||
void SumGraphController::LegendView::setSumLayout(Step step, double start, double end, double result, Layout functionLayout) {
|
||||
assert(step == Step::Result || functionLayout.isUninitialized());
|
||||
constexpr int sigmaLength = 2;
|
||||
const CodePoint sigma[sigmaLength] = {' ', m_sumSymbol};
|
||||
if (step == Step::FirstParameter) {
|
||||
m_sumLayout = LayoutHelper::CodePointString(sigma, sigmaLength);
|
||||
} else if (step == Step::SecondParameter) {
|
||||
constexpr int precision = Preferences::MediumNumberOfSignificantDigits;
|
||||
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
|
||||
char buffer[bufferSize];
|
||||
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(start, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
|
||||
m_sumLayout = CondensedSumLayout::Builder(
|
||||
LayoutHelper::CodePointString(sigma, sigmaLength),
|
||||
Poincare::Layout sumLayout = LayoutHelper::CodePointString(sigma, sigmaLength);
|
||||
if (step != Step::FirstParameter) {
|
||||
char buffer[k_valuesBufferSize];
|
||||
Layout endLayout;
|
||||
if (step == Step::SecondParameter) {
|
||||
endLayout = EmptyLayout::Builder(EmptyLayoutNode::Color::Yellow, false, k_font, false);
|
||||
} else {
|
||||
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(end, buffer, k_valuesBufferSize, k_valuesPrecision, Preferences::PrintFloatMode::Decimal);
|
||||
endLayout = LayoutHelper::String(buffer, strlen(buffer), k_font);
|
||||
}
|
||||
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(start, buffer, k_valuesBufferSize, k_valuesPrecision, Preferences::PrintFloatMode::Decimal);
|
||||
sumLayout = CondensedSumLayout::Builder(
|
||||
sumLayout,
|
||||
LayoutHelper::String(buffer, strlen(buffer), k_font),
|
||||
EmptyLayout::Builder(EmptyLayoutNode::Color::Yellow, false, k_font, false));
|
||||
} else {
|
||||
constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
|
||||
constexpr int sizeForPrecision = PrintFloat::charSizeForFloatsWithPrecision(precision);
|
||||
constexpr int bufferSize = 2 + sizeForPrecision;
|
||||
char buffer[bufferSize];
|
||||
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(start, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
|
||||
Layout start = LayoutHelper::String(buffer, strlen(buffer), k_font);
|
||||
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(end, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
|
||||
Layout end = LayoutHelper::String(buffer, strlen(buffer), k_font);
|
||||
m_sumLayout = CondensedSumLayout::Builder(
|
||||
LayoutHelper::CodePointString(sigma, sigmaLength),
|
||||
start,
|
||||
end);
|
||||
strlcpy(buffer, "= ", 3);
|
||||
PoincareHelpers::ConvertFloatToText<double>(result, buffer+2, bufferSize-2, precision);
|
||||
m_sumLayout = HorizontalLayout::Builder(
|
||||
m_sumLayout,
|
||||
functionLayout,
|
||||
LayoutHelper::String(buffer, strlen(buffer), k_font));
|
||||
}
|
||||
m_sum.setLayout(m_sumLayout);
|
||||
if (step == Step::Result) {
|
||||
m_sum.setAlignment(0.5f, 0.5f);
|
||||
} else {
|
||||
m_sum.setAlignment(0.0f, 0.5f);
|
||||
endLayout);
|
||||
if (step == Step::Result) {
|
||||
PoincareHelpers::ConvertFloatToText<double>(result, buffer, k_valuesBufferSize, k_valuesPrecision);
|
||||
sumLayout = HorizontalLayout::Builder(
|
||||
sumLayout,
|
||||
functionLayout,
|
||||
LayoutHelper::String("= ", 2, k_font),
|
||||
LayoutHelper::String(buffer, strlen(buffer), k_font));
|
||||
}
|
||||
}
|
||||
m_sum.setLayout(sumLayout);
|
||||
m_sum.setAlignment(0.5f * (step == Step::Result), 0.5f);
|
||||
layoutSubviews(step, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,9 +55,11 @@ private:
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setLegendMessage(I18n::Message message, Step step);
|
||||
void setEditableZone(double d);
|
||||
void setSumSymbol(Step step, double start, double end, double result, Poincare::Layout functionLayout);
|
||||
void setSumLayout(Step step, double start, double end, double result, Poincare::Layout functionLayout);
|
||||
private:
|
||||
constexpr static KDCoordinate k_editableZoneBufferSize = Poincare::PrintFloat::k_maxFloatCharSize;
|
||||
constexpr static size_t k_editableZoneBufferSize = Poincare::PrintFloat::k_maxFloatCharSize;
|
||||
constexpr static int k_valuesPrecision = Poincare::Preferences::MediumNumberOfSignificantDigits;
|
||||
constexpr static int k_valuesBufferSize = Poincare::PrintFloat::charSizeForFloatsWithPrecision(k_valuesPrecision);
|
||||
constexpr static KDCoordinate k_legendHeight = 35;
|
||||
constexpr static const KDFont * k_font = KDFont::SmallFont;
|
||||
static KDCoordinate editableZoneWidth() { return 12*k_font->glyphSize().width(); }
|
||||
@@ -69,7 +71,6 @@ private:
|
||||
void layoutSubviews(bool force = false) override;
|
||||
void layoutSubviews(Step step, bool force);
|
||||
ExpressionView m_sum;
|
||||
Poincare::Layout m_sumLayout;
|
||||
MessageTextView m_legend;
|
||||
TextField m_editableZone;
|
||||
char m_textBuffer[k_editableZoneBufferSize];
|
||||
|
||||
35
apps/shared/zoom_and_pan_curve_view_controller.cpp
Normal file
35
apps/shared/zoom_and_pan_curve_view_controller.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "zoom_and_pan_curve_view_controller.h"
|
||||
#include <cmath>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace Poincare;
|
||||
|
||||
namespace Shared {
|
||||
|
||||
bool ZoomAndPanCurveViewController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::Left || event == Ion::Events::Right || event == Ion::Events::Up || event == Ion::Events::Down) {
|
||||
return handlePan(event);
|
||||
}
|
||||
return ZoomCurveViewController::handleEvent(event);
|
||||
}
|
||||
|
||||
bool ZoomAndPanCurveViewController::handlePan(Ion::Events::Event event) {
|
||||
float xMove = 0.0f;
|
||||
float yMove = 0.0f;
|
||||
if (event == Ion::Events::Up) {
|
||||
yMove = interactiveCurveViewRange()->yGridUnit();
|
||||
} else if (event == Ion::Events::Down) {
|
||||
yMove = -interactiveCurveViewRange()->yGridUnit();
|
||||
} else if (event == Ion::Events::Left) {
|
||||
xMove = -interactiveCurveViewRange()->xGridUnit();
|
||||
} else {
|
||||
assert(event == Ion::Events::Right);
|
||||
xMove = interactiveCurveViewRange()->xGridUnit();
|
||||
}
|
||||
interactiveCurveViewRange()->panWithVector(xMove, yMove);
|
||||
curveView()->reload();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
23
apps/shared/zoom_and_pan_curve_view_controller.h
Normal file
23
apps/shared/zoom_and_pan_curve_view_controller.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef SHARED_ZOOM_AND_PAN_CURVE_VIEW_CONTROLLER_H
|
||||
#define SHARED_ZOOM_AND_PAN_CURVE_VIEW_CONTROLLER_H
|
||||
|
||||
#include "zoom_curve_view_controller.h"
|
||||
|
||||
namespace Shared {
|
||||
|
||||
/* ZoomAndPanCurveViewController is a View controller with a cursor that can
|
||||
* handles zoom in/out and directional pan events. */
|
||||
|
||||
class ZoomAndPanCurveViewController : public ZoomCurveViewController {
|
||||
public:
|
||||
ZoomAndPanCurveViewController(Responder * parentResponder) : ZoomCurveViewController(parentResponder) {}
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
protected:
|
||||
virtual bool handlePan(Ion::Events::Event event);
|
||||
float xFocus() override { return interactiveCurveViewRange()->xCenter(); }
|
||||
float yFocus() override { return interactiveCurveViewRange()->yCenter(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
23
apps/shared/zoom_curve_view_controller.cpp
Normal file
23
apps/shared/zoom_curve_view_controller.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "zoom_curve_view_controller.h"
|
||||
#include <cmath>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace Poincare;
|
||||
|
||||
namespace Shared {
|
||||
|
||||
bool ZoomCurveViewController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::Plus || event == Ion::Events::Minus) {
|
||||
return handleZoom(event);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ZoomCurveViewController::handleZoom(Ion::Events::Event event) {
|
||||
float ratio = event == Ion::Events::Plus ? 2.0f/3.0f : 3.0f/2.0f;
|
||||
interactiveCurveViewRange()->zoom(ratio, xFocus(), yFocus());
|
||||
curveView()->reload();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
30
apps/shared/zoom_curve_view_controller.h
Normal file
30
apps/shared/zoom_curve_view_controller.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef SHARED_ZOOM_CURVE_VIEW_CONTROLLER_H
|
||||
#define SHARED_ZOOM_CURVE_VIEW_CONTROLLER_H
|
||||
|
||||
#include <escher/view_controller.h>
|
||||
#include "interactive_curve_view_range.h"
|
||||
#include "curve_view_cursor.h"
|
||||
#include "curve_view.h"
|
||||
|
||||
namespace Shared {
|
||||
|
||||
/* ZoomCurveViewController is a View controller with a cursor that can handles
|
||||
* zoom in/out events. */
|
||||
|
||||
class ZoomCurveViewController : public ViewController {
|
||||
public:
|
||||
ZoomCurveViewController(Responder * parentResponder) : ViewController(parentResponder) {}
|
||||
View * view() override { return curveView(); }
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
protected:
|
||||
virtual bool handleZoom(Ion::Events::Event event);
|
||||
virtual InteractiveCurveViewRange * interactiveCurveViewRange() = 0;
|
||||
virtual CurveView * curveView() = 0;
|
||||
virtual float xFocus() = 0;
|
||||
virtual float yFocus() = 0;
|
||||
CurveViewCursor * m_cursor;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace Shared {
|
||||
|
||||
ZoomParameterController::ZoomParameterController(Responder * parentResponder, InteractiveCurveViewRange * interactiveRange, CurveView * curveView) :
|
||||
ViewController(parentResponder),
|
||||
ZoomAndPanCurveViewController(parentResponder),
|
||||
m_contentView(curveView),
|
||||
m_interactiveRange(interactiveRange)
|
||||
{
|
||||
@@ -15,45 +15,6 @@ const char * ZoomParameterController::title() {
|
||||
return I18n::translate(I18n::Message::Zoom);
|
||||
}
|
||||
|
||||
View * ZoomParameterController::view() {
|
||||
return &m_contentView;
|
||||
}
|
||||
|
||||
bool ZoomParameterController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::Plus) {
|
||||
m_interactiveRange->zoom(2.0f/3.0f, m_interactiveRange->xCenter(), m_interactiveRange->yCenter());
|
||||
m_contentView.curveView()->reload();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Minus) {
|
||||
m_interactiveRange->zoom(3.0f/2.0f, m_interactiveRange->xCenter(), m_interactiveRange->yCenter());
|
||||
m_contentView.curveView()->reload();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Up) {
|
||||
m_interactiveRange->panWithVector(0.0f, m_interactiveRange->yGridUnit());
|
||||
m_contentView.curveView()->reload();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Down) {
|
||||
m_interactiveRange->panWithVector(0.0f, -m_interactiveRange->yGridUnit());
|
||||
m_contentView.curveView()->reload();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Left) {
|
||||
m_interactiveRange->panWithVector(-m_interactiveRange->xGridUnit(), 0.0f);
|
||||
m_contentView.curveView()->reload();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Right) {
|
||||
m_interactiveRange->panWithVector(m_interactiveRange->xGridUnit(), 0.0f);
|
||||
m_contentView.curveView()->reload();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ZoomParameterController::viewWillAppear() {
|
||||
ViewController::viewWillAppear();
|
||||
m_contentView.curveView()->setOkView(nullptr);
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
#ifndef SHARED_ZOOM_PARAMETER_CONTROLLER_H
|
||||
#define SHARED_ZOOM_PARAMETER_CONTROLLER_H
|
||||
|
||||
#include <escher.h>
|
||||
#include "interactive_curve_view_range.h"
|
||||
#include "curve_view.h"
|
||||
#include "zoom_and_pan_curve_view_controller.h"
|
||||
#include <apps/i18n.h>
|
||||
|
||||
namespace Shared {
|
||||
|
||||
class ZoomParameterController : public ViewController {
|
||||
class ZoomParameterController : public ZoomAndPanCurveViewController {
|
||||
public:
|
||||
ZoomParameterController(Responder * parentResponder, InteractiveCurveViewRange * interactiveCurveViewRange, CurveView * curveView);
|
||||
const char * title() override;
|
||||
View * view() override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
View * view() override { return &m_contentView; }
|
||||
void viewWillAppear() override;
|
||||
void viewDidDisappear() override;
|
||||
void didBecomeFirstResponder() override;
|
||||
TELEMETRY_ID("Zoom");
|
||||
private:
|
||||
constexpr static KDCoordinate k_standardViewHeight = 175;
|
||||
|
||||
class ContentView : public View {
|
||||
public:
|
||||
constexpr static KDCoordinate k_legendHeight = 30;
|
||||
@@ -46,7 +44,13 @@ private:
|
||||
CurveView * m_curveView;
|
||||
LegendView m_legendView;
|
||||
};
|
||||
|
||||
void adaptCurveRange(bool viewWillAppear);
|
||||
|
||||
// ZoomAndPanCurveViewController
|
||||
InteractiveCurveViewRange * interactiveCurveViewRange() override { return m_interactiveRange; }
|
||||
CurveView * curveView() override { return m_contentView.curveView(); }
|
||||
|
||||
ContentView m_contentView;
|
||||
InteractiveCurveViewRange * m_interactiveRange;
|
||||
};
|
||||
|
||||
@@ -211,7 +211,16 @@ EquationStore::Error EquationStore::privateExactSolve(Poincare::Context * contex
|
||||
// Step 3. Polynomial & Monovariable?
|
||||
assert(numberOfVariables == 1 && numberOfDefinedModels() == 1);
|
||||
Expression polynomialCoefficients[Expression::k_maxNumberOfPolynomialCoefficients];
|
||||
int degree = modelForRecord(definedRecordAtIndex(0))->standardForm(context, replaceFunctionsButNotSymbols).getPolynomialReducedCoefficients(m_variables[0], polynomialCoefficients, context, updatedComplexFormat(context), preferences->angleUnit(), replaceFunctionsButNotSymbols ? ExpressionNode::SymbolicComputation::ReplaceDefinedFunctionsWithDefinitions : ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition);
|
||||
int degree = modelForRecord(definedRecordAtIndex(0))->standardForm(context, replaceFunctionsButNotSymbols)
|
||||
.getPolynomialReducedCoefficients(
|
||||
m_variables[0],
|
||||
polynomialCoefficients,
|
||||
context,
|
||||
updatedComplexFormat(context),
|
||||
preferences->angleUnit(),
|
||||
replaceFunctionsButNotSymbols ?
|
||||
ExpressionNode::SymbolicComputation::ReplaceDefinedFunctionsWithDefinitions :
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition);
|
||||
if (degree == 2) {
|
||||
// Polynomial degree <= 2
|
||||
m_type = Type::PolynomialMonovariable;
|
||||
@@ -262,7 +271,9 @@ EquationStore::Error EquationStore::resolveLinearSystem(Expression exactSolution
|
||||
Preferences::AngleUnit angleUnit = Preferences::sharedPreferences()->angleUnit();
|
||||
// n unknown variables
|
||||
int n = 0;
|
||||
while (m_variables[n][0] != 0) { n++; }
|
||||
while (n < Expression::k_maxNumberOfVariables && m_variables[n][0] != 0) {
|
||||
n++;
|
||||
}
|
||||
int m = numberOfDefinedModels(); // m equations
|
||||
/* Create the matrix (A | b) for the equation Ax=b */
|
||||
Matrix Ab = Matrix::Builder();
|
||||
|
||||
@@ -12,8 +12,4 @@ void BoxAxisView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
drawLabelsAndGraduations(ctx, rect, Axis::Horizontal, false, false, true, k_axisMargin);
|
||||
}
|
||||
|
||||
char * BoxAxisView::label(Axis axis, int index) const {
|
||||
return axis == Axis::Vertical ? nullptr : (char *)m_labels[index];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,24 +3,21 @@
|
||||
|
||||
#include "box_range.h"
|
||||
#include "store.h"
|
||||
#include "../shared/curve_view.h"
|
||||
#include "../shared/labeled_curve_view.h"
|
||||
#include "../constant.h"
|
||||
#include <poincare/print_float.h>
|
||||
|
||||
namespace Statistics {
|
||||
|
||||
class BoxAxisView : public Shared::CurveView {
|
||||
class BoxAxisView : public Shared::HorizontallyLabeledCurveView {
|
||||
public:
|
||||
BoxAxisView(Store * store) :
|
||||
CurveView(&m_boxRange),
|
||||
m_labels{},
|
||||
HorizontallyLabeledCurveView(&m_boxRange),
|
||||
m_boxRange(BoxRange(store))
|
||||
{}
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
private:
|
||||
constexpr static KDCoordinate k_axisMargin = 3;
|
||||
char * label(Axis axis, int index) const override;
|
||||
char m_labels[k_maxNumberOfXLabels][k_labelBufferMaxSize];
|
||||
BoxRange m_boxRange;
|
||||
};
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ void BoxView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
// Draw the horizontal lines linking the box to the extreme bounds
|
||||
KDColor horizontalColor = isMainViewSelected() ? m_selectedHistogramColor : Palette::SecondaryText;
|
||||
float segmentOrd = (lowBound + upBound)/ 2.0f;
|
||||
drawSegment(ctx, rect, Axis::Horizontal, segmentOrd, minVal, firstQuart, horizontalColor);
|
||||
drawSegment(ctx, rect, Axis::Horizontal, segmentOrd, thirdQuart, maxVal, horizontalColor);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, segmentOrd, minVal, firstQuart, horizontalColor);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, segmentOrd, thirdQuart, maxVal, horizontalColor);
|
||||
|
||||
double calculations[5] = {minVal, firstQuart, m_store->median(m_series), thirdQuart, maxVal};
|
||||
/* We then draw all the vertical lines of the box and then recolor the
|
||||
@@ -83,10 +83,10 @@ void BoxView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
* lines. This solution could hide the highlighted line by coloring the next
|
||||
* quantile if it has the same value. */
|
||||
for (int k = 0; k < 5; k++) {
|
||||
drawSegment(ctx, rect, Axis::Vertical, calculations[k], lowBound, upBound, Palette::StatisticsBoxVerticalLine, k_quantileBarWidth);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, calculations[k], lowBound, upBound, Palette::StatisticsBoxVerticalLine, k_quantileBarWidth);
|
||||
}
|
||||
if (isMainViewSelected()) {
|
||||
drawSegment(ctx, rect, Axis::Vertical, calculations[(int)*m_selectedQuantile], lowBound, upBound, Palette::StatisticsBox, k_quantileBarWidth);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, calculations[(int)*m_selectedQuantile], lowBound, upBound, Palette::StatisticsBox, k_quantileBarWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ private:
|
||||
static constexpr KDCoordinate k_quantileBarWidth = 2;
|
||||
KDCoordinate boxLowerBoundPixel() const;
|
||||
KDCoordinate boxUpperBoundPixel() const;
|
||||
char * label(Axis axis, int index) const override { return nullptr; }
|
||||
Store * m_store;
|
||||
BoxRange m_boxRange;
|
||||
int m_series;
|
||||
|
||||
@@ -8,10 +8,9 @@ using namespace Shared;
|
||||
namespace Statistics {
|
||||
|
||||
HistogramView::HistogramView(HistogramController * controller, Store * store, int series, Shared::BannerView * bannerView, KDColor selectedHistogramColor, KDColor notSelectedHistogramColor, KDColor selectedBarColor) :
|
||||
CurveView(store, nullptr, bannerView, nullptr),
|
||||
HorizontallyLabeledCurveView(store, nullptr, bannerView, nullptr),
|
||||
m_controller(controller),
|
||||
m_store(store),
|
||||
m_labels{},
|
||||
m_highlightedBarStart(NAN),
|
||||
m_highlightedBarEnd(NAN),
|
||||
m_series(series),
|
||||
@@ -63,10 +62,6 @@ void HistogramView::setHighlight(float start, float end) {
|
||||
}
|
||||
}
|
||||
|
||||
char * HistogramView::label(Axis axis, int index) const {
|
||||
return axis == Axis::Vertical ? nullptr : (char *)m_labels[index];
|
||||
}
|
||||
|
||||
float HistogramView::EvaluateHistogramAtAbscissa(float abscissa, void * model, void * context) {
|
||||
Store * store = (Store *)model;
|
||||
float totalSize = ((float *)context)[0];
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#include <poincare/print_float.h>
|
||||
#include "store.h"
|
||||
#include "../constant.h"
|
||||
#include "../shared/curve_view.h"
|
||||
#include "../shared/labeled_curve_view.h"
|
||||
|
||||
namespace Statistics {
|
||||
|
||||
class HistogramController;
|
||||
|
||||
class HistogramView : public Shared::CurveView {
|
||||
class HistogramView : public Shared::HorizontallyLabeledCurveView {
|
||||
public:
|
||||
HistogramView(HistogramController * controller, Store * store, int series, Shared::BannerView * bannerView, KDColor selectedHistogramColor = Palette::StatisticsSelected, KDColor notSelectedHistogramColor = Palette::StatisticsNotSelected, KDColor selectedBarColor = Palette::StatisticsSelected);
|
||||
int series() const { return m_series; }
|
||||
@@ -21,10 +21,8 @@ public:
|
||||
void setHighlight(float start, float end);
|
||||
void setDisplayLabels(bool display) { m_displayLabels = display; }
|
||||
private:
|
||||
char * label(Axis axis, int index) const override;
|
||||
HistogramController * m_controller;
|
||||
Store * m_store;
|
||||
char m_labels[k_maxNumberOfXLabels][k_labelBufferMaxSize];
|
||||
static float EvaluateHistogramAtAbscissa(float abscissa, void * model, void * context);
|
||||
float m_highlightedBarStart;
|
||||
float m_highlightedBarEnd;
|
||||
|
||||
@@ -7,8 +7,8 @@ LEDS_CHOICE ?= 0
|
||||
include build/defaults.mak
|
||||
include build/platform.$(PLATFORM).mak
|
||||
|
||||
EPSILON_VERSION ?= 13.0.0
|
||||
EPSILON_CUSTOM_VERSION ?= 1.19.1
|
||||
EPSILON_VERSION ?= 13.2.0
|
||||
EPSILON_CUSTOM_VERSION ?= 1.19.2
|
||||
# USERNAME ?= N/A
|
||||
EPSILON_APPS ?= calculation rpn graph code statistics probability solver atom sequence regression settings external
|
||||
EPSILON_I18N ?= en fr es de pt hu
|
||||
@@ -21,9 +21,6 @@ OMEGA_THEME ?= omega_light
|
||||
ifndef USE_LIBA
|
||||
$(error platform.mak should define USE_LIBA)
|
||||
endif
|
||||
ifndef EXE
|
||||
$(error platform.mak should define EXE, the extension for executables)
|
||||
endif
|
||||
include build/toolchain.$(TOOLCHAIN).mak
|
||||
|
||||
SFLAGS += -DDEBUG=$(DEBUG)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
TOOLCHAIN = android
|
||||
EXE = so
|
||||
|
||||
EPSILON_TELEMETRY ?= 1
|
||||
|
||||
ifdef NDK_ABI
|
||||
BUILD_DIR := $(BUILD_DIR)/$(NDK_ABI)
|
||||
ARCHS = armeabi-v7a arm64-v8a x86 x86_64
|
||||
|
||||
ifdef ARCH
|
||||
EXE = so
|
||||
BUILD_DIR := $(BUILD_DIR)/$(ARCH)
|
||||
endif
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
# Define standard compilation rules
|
||||
|
||||
.PHONY: official_authorization
|
||||
ifeq ($(ACCEPT_OFFICIAL_TOS),1)
|
||||
official_authorization:
|
||||
@echo "CAUTION: You are about to build an official NumWorks firmware. Distribution of such firmware by a third party is prohibited. Are you sure you want to proceed? Please type "yes" to confirm." && read ans && [ $${ans:-no} = yes ]
|
||||
else
|
||||
official_authorization:
|
||||
@echo "CAUTION: You are trying to build an official NumWorks firmware."
|
||||
@echo "Distribution of such firmware by a third party is prohibited."
|
||||
@echo "Please set the ACCEPT_OFFICIAL_TOS environment variable to proceed."
|
||||
@exit -1
|
||||
endif
|
||||
|
||||
$(eval $(call rule_for, \
|
||||
AS, %.o, %.s, \
|
||||
@@ -31,6 +38,12 @@ $(eval $(call rule_for, \
|
||||
$$(CXX) $$(CXXFLAGS) $$(SFLAGS) -c $$< -o $$@ \
|
||||
))
|
||||
|
||||
$(eval $(call rule_for, \
|
||||
CPP, %, %.inc, \
|
||||
$$(CPP) -P $$< $$@ \
|
||||
))
|
||||
|
||||
ifdef EXE
|
||||
ifeq ($(OS),Windows_NT)
|
||||
# Work around command-line length limit
|
||||
# On Msys2 the max command line is 32 000 characters. Our standard LD command
|
||||
@@ -47,6 +60,7 @@ $(eval $(call rule_for, \
|
||||
$$(LD) $$^ $$(LDFLAGS) -o $$@ \
|
||||
))
|
||||
endif
|
||||
endif
|
||||
|
||||
$(eval $(call rule_for, \
|
||||
WINDRES, %.o, %.rc, \
|
||||
|
||||
@@ -29,32 +29,32 @@ all_official:
|
||||
$(call file_check,$(ANDROID_GRADLE_PROPERTIES))
|
||||
$(call file_check,$(IOS_MOBILE_PROVISION))
|
||||
$(call command_check,$(EMCC))
|
||||
$(Q) rm -rf output/stable_release
|
||||
$(Q) mkdir -p output/stable_release
|
||||
$(Q) rm -rf output/all_official
|
||||
$(Q) mkdir -p output/all_official
|
||||
$(Q) echo "BUILD_FIRMWARE DEVICE N0110"
|
||||
$(Q) $(MAKE) clean
|
||||
$(Q) $(MAKE) epsilon.official.onboarding.dfu
|
||||
$(Q) cp output/release/device/n0110/epsilon.official.onboarding.dfu output/stable_release/epsilon.device.n0110.dfu
|
||||
$(Q) cp output/release/device/n0110/epsilon.official.onboarding.dfu output/all_official/epsilon.device.n0110.dfu
|
||||
$(Q) echo "BUILD_FIRMWARE DEVICE N0100"
|
||||
$(Q) $(MAKE) MODEL=n0100 clean
|
||||
$(Q) $(MAKE) MODEL=n0100 epsilon.official.onboarding.dfu
|
||||
$(Q) cp output/release/device/n0100/epsilon.official.onboarding.dfu output/stable_release/epsilon.device.n0100.dfu
|
||||
$(Q) cp output/release/device/n0100/epsilon.official.onboarding.dfu output/all_official/epsilon.device.n0100.dfu
|
||||
$(Q) echo "BUILD_FIRMWARE SIMULATOR WEB ZIP"
|
||||
$(Q) $(MAKE) DEBUG=0 PLATFORM=simulator TARGET=web clean
|
||||
$(Q) $(call source_emsdk); $(MAKE) DEBUG=0 PLATFORM=simulator TARGET=web output/release/simulator/web/simulator.official.zip
|
||||
$(Q) cp output/release/simulator/web/simulator.official.zip output/stable_release/simulator.web.zip
|
||||
$(Q) $(MAKE) PLATFORM=simulator TARGET=web clean
|
||||
$(Q) $(call source_emsdk); $(MAKE) PLATFORM=simulator TARGET=web epsilon.official.zip
|
||||
$(Q) cp output/release/simulator/web/epsilon.official.zip output/all_official/simulator.web.zip
|
||||
$(Q) echo "BUILD_FIRMWARE SIMULATOR WEB JS"
|
||||
$(Q) $(call source_emsdk); $(MAKE) DEBUG=0 PLATFORM=simulator TARGET=web epsilon.official.js
|
||||
$(Q) cp output/release/simulator/web/epsilon.official.js output/stable_release/epsilon.js
|
||||
$(Q) $(call source_emsdk); $(MAKE) PLATFORM=simulator TARGET=web epsilon.official.js
|
||||
$(Q) cp output/release/simulator/web/epsilon.official.js output/all_official/epsilon.js
|
||||
$(Q) echo "BUILD_FIRMWARE SIMULATOR WEB PYTHON JS"
|
||||
$(Q) $(MAKE) DEBUG=0 PLATFORM=simulator TARGET=web clean
|
||||
$(Q) $(call source_emsdk); $(MAKE) DEBUG=0 PLATFORM=simulator TARGET=web EPSILON_GETOPT=1 EPSILON_APPS=code epsilon.official.js
|
||||
$(Q) cp output/release/simulator/web/epsilon.official.js output/stable_release/epsilon.python.js
|
||||
$(Q) $(MAKE) PLATFORM=simulator TARGET=web clean
|
||||
$(Q) $(call source_emsdk); $(MAKE) PLATFORM=simulator TARGET=web EPSILON_GETOPT=1 EPSILON_APPS=code epsilon.official.js
|
||||
$(Q) cp output/release/simulator/web/epsilon.official.js output/all_official/epsilon.python.js
|
||||
$(Q) echo "BUILD_FIRMWARE SIMULATOR ANDROID"
|
||||
$(Q) $(MAKE) PLATFORM=simulator TARGET=android clean
|
||||
$(Q) $(MAKE) PLATFORM=simulator TARGET=android epsilon.official.apk
|
||||
$(Q) cp output/release/simulator/android/app/outputs/apk/release/android-release-unsigned.apk output/stable_release/epsilon.apk
|
||||
$(Q) $(MAKE) PLATFORM=simulator TARGET=android epsilon.official.signed.apk
|
||||
$(Q) cp output/release/simulator/android/app/outputs/apk/codesigned/android-codesigned.apk output/all_official/epsilon.official.apk
|
||||
$(Q) echo "BUILD_FIRMWARE SIMULATOR IOS"
|
||||
$(Q) $(MAKE) PLATFORM=simulator TARGET=ios clean
|
||||
$(Q) $(MAKE) PLATFORM=simulator TARGET=ios IOS_PROVISIONNING_PROFILE="~/Downloads/NumWorks_Graphing_Calculator_Distribution.mobileprovision" output/release/simulator/ios/app/epsilon.official.ipa
|
||||
$(Q) cp output/release/simulator/ios/app/epsilon.official.ipa output/stable_release/epsilon.ipa
|
||||
$(Q) $(MAKE) PLATFORM=simulator TARGET=ios IOS_PROVISIONNING_PROFILE=$(IOS_MOBILE_PROVISION) output/release/simulator/ios/app/epsilon.official.ipa
|
||||
$(Q) cp output/release/simulator/ios/app/epsilon.official.ipa output/all_official/epsilon.ipa
|
||||
|
||||
@@ -20,28 +20,3 @@ $(BUILD_DIR)/test.external_flash.write.$(EXE): $(BUILD_DIR)/quiz/src/test_ion_ex
|
||||
fi
|
||||
$(Q) $(PYTHON) build/device/dfu.py -u $(word 1,$^)
|
||||
|
||||
.PHONY: %.two_binaries
|
||||
%.two_binaries: %.elf
|
||||
@echo "Building an internal and an external binary for $<"
|
||||
$(Q) $(OBJCOPY) -O binary -j .text.external -j .rodata.external -j .exam_mode_buffer $(BUILD_DIR)/$< $(BUILD_DIR)/$(basename $<).external.bin
|
||||
$(Q) $(OBJCOPY) -O binary -R .text.external -R .rodata.external -R .exam_mode_buffer $(BUILD_DIR)/$< $(BUILD_DIR)/$(basename $<).internal.bin
|
||||
@echo "Padding $(basename $<).external.bin and $(basename $<).internal.bin"
|
||||
$(Q) printf "\xFF\xFF\xFF\xFF" >> $(BUILD_DIR)/$(basename $<).external.bin
|
||||
$(Q) printf "\xFF\xFF\xFF\xFF" >> $(BUILD_DIR)/$(basename $<).internal.bin
|
||||
|
||||
.PHONY: binpack
|
||||
binpack:
|
||||
rm -rf output/binpack
|
||||
mkdir -p output/binpack
|
||||
$(MAKE) clean
|
||||
$(MAKE) $(BUILD_DIR)/flasher.light.bin
|
||||
cp $(BUILD_DIR)/flasher.light.bin output/binpack
|
||||
$(MAKE) $(BUILD_DIR)/bench.flash.bin
|
||||
$(MAKE) $(BUILD_DIR)/bench.ram.bin
|
||||
cp $(BUILD_DIR)/bench.ram.bin $(BUILD_DIR)/bench.flash.bin output/binpack
|
||||
$(MAKE) epsilon.official.onboarding.update.two_binaries
|
||||
cp $(BUILD_DIR)/epsilon.official.onboarding.update.internal.bin $(BUILD_DIR)/epsilon.official.onboarding.update.external.bin output/binpack
|
||||
$(MAKE) clean
|
||||
cd output && for binary in flasher.light.bin bench.flash.bin bench.ram.bin epsilon.official.onboarding.update.internal.bin epsilon.official.onboarding.update.external.bin; do shasum -a 256 -b binpack/$${binary} > binpack/$${binary}.sha256;done
|
||||
cd output && tar cvfz binpack-`git rev-parse HEAD | head -c 7`.tgz binpack
|
||||
rm -rf output/binpack
|
||||
|
||||
3
build/targets.simulator.android.mak
Normal file
3
build/targets.simulator.android.mak
Normal file
@@ -0,0 +1,3 @@
|
||||
ifndef ARCH
|
||||
HANDY_TARGETS_EXTENSIONS += apk
|
||||
endif
|
||||
@@ -1,6 +1,3 @@
|
||||
$(BUILD_DIR)/epsilon%packed.js: EMSCRIPTEN_INIT_FILE = 0
|
||||
HANDY_TARGETS_EXTENSIONS += zip
|
||||
|
||||
$(BUILD_DIR)/test.headless.js: EMSCRIPTEN_MODULARIZE = 0
|
||||
|
||||
$(BUILD_DIR)/epsilon.packed.js: $(call object_for,$(epsilon_src))
|
||||
$(BUILD_DIR)/epsilon.official.packed.js: $(call object_for,$(epsilon_official_src))
|
||||
|
||||
@@ -13,16 +13,16 @@ NDK_TOOLCHAIN_PATH = $(NDK_PATH)/toolchains/llvm/prebuilt/$(NDK_HOST_TAG)/bin
|
||||
# is no toolchain for those archs on those API levels. Let's enforce NDK_VERSION
|
||||
# at 21 for these archs, and 16 for the others.
|
||||
|
||||
ifeq ($(NDK_ABI),armeabi-v7a)
|
||||
ifeq ($(ARCH),armeabi-v7a)
|
||||
NDK_TARGET = armv7a-linux-androideabi
|
||||
NDK_VERSION = 16
|
||||
else ifeq ($(NDK_ABI),arm64-v8a)
|
||||
else ifeq ($(ARCH),arm64-v8a)
|
||||
NDK_TARGET = aarch64-linux-android
|
||||
NDK_VERSION = 21
|
||||
else ifeq ($(NDK_ABI),x86)
|
||||
else ifeq ($(ARCH),x86)
|
||||
NDK_TARGET = i686-linux-android
|
||||
NDK_VERSION = 16
|
||||
else ifeq ($(NDK_ABI),x86_64)
|
||||
else ifeq ($(ARCH),x86_64)
|
||||
NDK_TARGET = x86_64-linux-android
|
||||
NDK_VERSION = 21
|
||||
endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user