Compare commits

...

56 Commits

Author SHA1 Message Date
Laury
51fd990c31 [geometry] Start of graph 2022-01-25 21:15:57 +01:00
Laury
7af2b45f1d [geometry] Make the app multi-tabs 2022-01-23 21:11:02 +01:00
Laury
d95785ba42 [geometry] Finished V1 of the first menu 2022-01-22 12:44:40 +01:00
Laury
d108b76a32 [geometry] Added text field in FigureParametersController 2021-12-19 14:54:54 +01:00
Laury
a3d3cbbfa5 [geometry] WIP 2021-12-13 20:39:57 +01:00
Laury
3a41cbdc85 [geometry] Some progress but don't compile 2021-12-11 21:21:18 +01:00
Laury
3ccfdf0365 [geometry] Also not working 2021-12-06 20:43:13 +01:00
Laury
6aad7d2279 [geometry] Not working third menu 2021-11-11 17:46:45 +01:00
Laury
5c1f192228 [geometry] Base app and firsts two menu (WIP) 2021-11-05 13:49:01 +01:00
Laury
84d88a3e8d [Apps] Updated submodules 2021-10-31 21:58:49 +01:00
lolocomotive
00b5d4b9fe Make gutter view background the right width (#70) 2021-10-31 21:43:29 +01:00
Lauryy06
2aee07ae55 [github] Updated issue templates 2021-10-31 21:40:52 +01:00
Yaya-Cout
41b2b64d80 Fix somes Upsilon name in somes files (#61) 2021-10-28 22:23:10 +02:00
Mino1289
473b0bbfcb [apps/settings|code] Add a Flag to remove Code option in settings if code app is not compiled (#67) 2021-10-28 22:20:00 +02:00
Mino1289
58ef8cb95d [apps/code] Remove import of mathsup (residue of #50) (#63) 2021-10-28 19:15:53 +02:00
Mino1289
5dce215165 [build/config.mak] Update of base theme (#64) 2021-10-28 19:15:26 +02:00
lolocomotive
f2f44f0f6f Make use theme colors instead of hard-coded ones (#65) 2021-10-28 19:13:21 +02:00
Laury
fbe542e5bf [python] Fix bug in draw_string 2021-10-28 14:41:33 +02:00
Laury
0a1b3bcaee [theme] Added upsilon light theme 2021-10-28 14:38:32 +02:00
Laury
f6e937a927 [settings] Bug fix in code options controller 2021-10-27 19:35:19 +02:00
Laporte
c4ed8f84d3 Custom themes script (#46) 2021-10-27 19:30:35 +02:00
Yaya-Cout
8e1b311be0 [apps/settings] Fix gamma selector (#60) 2021-10-27 19:29:53 +02:00
lolocomotive
89e51166e7 Make battery background use appropriate colors (#59) 2021-10-27 10:10:14 +02:00
Mino1289
e4961563e9 [apps/code] Remove base python script and add mathsup.py (#50) 2021-10-25 16:27:21 +02:00
Laury
e72b0f633e [calculation] Fix bug in second degree list controller 2021-10-24 19:31:14 +02:00
Hector
0550b66c03 Dark Theme changes (#42)
* Dark Theme changes

* added reader icon for dark mode

* epsilon Dark Theme changes
2021-10-20 23:11:30 +02:00
Lauryy06
e41910e2f8 [workflow] Re-update SDK version of emscripten 2021-10-20 22:38:49 +02:00
Lauryy06
d91ae29607 [workflow] Change sdk of emscripten for tests 2021-10-20 22:36:18 +02:00
ArtichautCosmique
3b90969b42 [mpy] Enabled property/etc decorators (#52) 2021-10-20 22:26:01 +02:00
lolocomotive
bd207cb845 Replace hard-coded color values with Palette colors and use the correct palette colors (#51) 2021-10-20 22:25:27 +02:00
lolocomotive
917ba7ce83 Allow themes to override default colors (#49) 2021-10-20 22:20:19 +02:00
Laury
9c9758fcb6 [reader] update README 2021-10-15 14:50:03 +02:00
Laury
83ce9d5e86 [reader] Rich text support (look at README.md) 2021-10-15 14:47:00 +02:00
ArtichOwO
d4f0c7d3e8 Added sys to the code toolbox 2021-10-15 14:47:00 +02:00
ArtichOwO
2837b240e9 [mpy] Added sys module
Removed useless "path" and "argv"
2021-10-15 14:46:39 +02:00
ArtichautCosmique
0906dc919b [mpy/kandinsky] Fix draw_string() on new line + good colors (#47)
* [mpy/kandinsky] Use good colors

* [kandinsky/context_text] Avoid returning to pos x=0 on new line, use arg's x coordinate instead
2021-10-11 20:25:03 +02:00
Faustin
9cda9d9e59 [apps/code] Add a settings for autocomplete (#36) 2021-10-07 21:48:19 +02:00
Yaya-Cout
553f3fc682 [apps/settings] Use right key to enable setting (#35) 2021-10-07 20:36:03 +02:00
Mino1289
9fdedecbff [apps/toolbox] Order of submenus & New electricity constants (#34) 2021-10-06 18:26:17 +02:00
Lauryy06
83c63a7011 [readme] Update readme 2021-10-01 21:37:44 +02:00
Yolwoocle
9636964cb9 Better English translation (#32) 2021-09-29 18:31:10 +02:00
Yaya-Cout
69d6ad5205 Add get_keys in toolbox and fix setlocaltime description (#33) 2021-09-29 18:30:30 +02:00
Laury
f9a123cc08 [mpy/ulab] Added support of from and to bytes array methods 2021-09-28 20:50:34 +02:00
Lauryy06
56f735e302 [github] update metric-workflow.yml 2021-09-26 20:50:53 +02:00
ArtichautCosmique
0a5e9e0889 [apps/code][mpy][makefile] Fix size error on n0100 (#30) 2021-09-26 20:37:56 +02:00
apoleon33
8c949d7048 [build]changed color of upsilon logo in pimp.mak (#31) 2021-09-26 20:36:13 +02:00
Laporte
2f7edc5024 Update pimp.mak (#29)
* Update pimp.mak

Mise a jour du pimp.mak pour le nouveau slogan et le logo ascii.

* Update pimp.mak
2021-09-26 14:25:00 +02:00
Lauryy06
cd40938b26 [readme] Add a capital line 10 2021-09-25 19:52:14 +02:00
ArtichautCosmique
0b54bf13f4 [storage][apps/code] Change sizes (#28) 2021-09-25 19:49:26 +02:00
Laury
f5f11c6478 [poincare] Added simplification of equals 2021-09-25 19:32:23 +02:00
ArtichautCosmique
efda561425 [ion/device/flasher] Pimp my flasher (light & verbose) (#27) 2021-09-25 18:55:43 +02:00
Lauryy06
15c96cefa6 [readme] Update french readme 2021-09-25 10:29:29 +02:00
Lauryy06
400d03ebdb [readme] Addition of a "useful links" section 2021-09-25 10:25:57 +02:00
Lauryy06
6f48adde7d Merge pull request #25 from Mino1289/upsilon-dev-dev 2021-09-25 10:17:21 +02:00
Mino1289
3a573b1204 [apps/code] fix typo 2021-09-24 11:15:56 +02:00
Mino1289
48598296cf [apps/code] Increase of number of variables loaded in the variable box 2021-09-24 11:09:23 +02:00
186 changed files with 3194 additions and 427 deletions

View File

@@ -1,6 +1,6 @@
---
name: Bug report
about: Omega is not working like it should? Let us know!
about: Upsilon is not working like it should? Let us know!
title: ''
labels: 'Status: Triage, Type: Bug'
assignees: ''
@@ -24,4 +24,4 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- Omega Version: [go to settings > about > Omega Version and type the version here]
- Upsilon Version: [go to settings > about > Upsilon Version and type the version here]

View File

@@ -1,6 +1,6 @@
---
name: Feature request
about: Suggest an idea for Omega
about: Suggest an idea for Upsilon
title: ''
labels: 'Status: Triage, Type: Feature'
assignees: ''

View File

@@ -1,28 +0,0 @@
---
name: OMEGA BETA ONLY - Bug report
about: Omega 1.21 is not working like it should? Let us know!
title: "[BETA-1.21] …"
labels: 'Status: Triage, Type: Bug'
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- Omega Version: [go to settings > about > Omega Version and type the version here]
- Discord username: ..........#....

View File

@@ -1,6 +1,6 @@
---
name: Problems during installation
about: Need help to install Omega?
about: Need help to install Upsilon?
title: ''
labels: 'Status: Triage, Type: Installation issue'
assignees: ''
@@ -16,4 +16,4 @@ Copy/paste the logs here (If you have some)
```
**Environment**
- Omega Version: {go to settings > about > Omega Version and type the version here}
- Upsilon Version: {go to settings > about > Upsilon Version and type the version here}

View File

@@ -140,7 +140,7 @@ jobs:
steps:
- uses: numworks/setup-emscripten@v1
with:
sdk: latest-upstream
sdk: 1.40.1-fastcomp
- uses: actions/checkout@v2
with:
submodules: 'recursive'

View File

@@ -31,7 +31,6 @@ jobs:
- name: Add comment
uses: actions/github-script@v3.0.0
with:
github-token: ${{ secrets.OMEGA_ROBOT_TOKEN }}
script: |
await github.issues.createComment({
owner: context.repo.owner,

2
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "apps/rpn"]
path = apps/rpn
url = https://github.com/Omega-Numworks/Omega-RPN.git
url = https://github.com/Lauryy06/Upsilon-RPN.git
[submodule "apps/atomic"]
path = apps/atomic
url = https://github.com/Lauryy06/atomic

View File

@@ -13,7 +13,18 @@ include build/variants.mak
include build/helpers.mk
ifeq (${MODEL}, n0100)
EPSILON_APPS := $(filter-out reader,$(EPSILON_APPS))
ifeq ($(filter reader,$(apps_list)),)
$(warning reader app included, removing it on n0100. )
EPSILON_APPS := $(filter-out reader,$(EPSILON_APPS))
endif
ifneq ($(words $(EPSILON_I18N)), 1)
$(warning Only use 1 language on n0100, defaulting to en. )
EPSILON_I18N := en
endif
ifeq ($(INCLUDE_ULAB), 1)
$(warning Removing uLab on n0100. )
INCLUDE_ULAB := 0
endif
endif
ifeq (${MODEL}, n0110)
@@ -26,6 +37,10 @@ ifdef FORCE_EXTERNAL
apps_list = ${EPSILON_APPS}
endif
ifeq ($(INCLUDE_ULAB), 1)
SFLAGS += -DINCLUDE_ULAB
endif
ifdef HOME_DISPLAY_EXTERNALS
ifneq ($(filter external,$(apps_list)),)
SFLAGS += -DHOME_DISPLAY_EXTERNALS

View File

@@ -126,7 +126,7 @@ Vous aurez besoin de devkitPro et de devkitARM disponible dans votre `$PATH` (in
```bash
git clone --recursive https://github.com/Lauryy06/Upsilon.git
cd Upsilon
git checkout --recursive omega-dev
git checkout --recursive upsilon-dev
make PLATFORM=simulator TARGET=3ds -j
```
@@ -143,6 +143,10 @@ Si vous avez besoin d'aide, n'hésitez pas à rejoindre notre serveur discord :
<a href="https://discord.gg/Q9buEMduXG"><p align="center"><img alt="Omega Banner Discord" src="https://user-images.githubusercontent.com/12123721/86287349-54ef5800-bbe8-11ea-80c1-34eb1f93eebd.png" /></p></a>
---
## Liens utiles
* [Upsilon external (pour installer des applications supplémentaires et des fonds d'écran)](https://lauryy06.github.io/Upsilon-External/)
* [Documentation d'ulab](https://micropython-ulab.readthedocs.io/en/latest/)
## Contribution
Pour contribuer, merci de lire le [Wiki d'Omega](https://github.com/Omega-Numworks/Omega/wiki/Contributing), les mêmes règles s'appliquent ici.

View File

@@ -7,7 +7,7 @@
<a href="https://discord.gg/Q9buEMduXG"><img alt="Discord" src="https://img.shields.io/discord/663420259851567114?color=blue&labelColor=292929&label=chat%20-%20discord&logo=discord&style=for-the-badge" /></a>
</p>
> Vous ne comprenez pas l'anglais ? vous êtes francophone ? Regardez le [*LISEZ-MOI* français](./README.fr.md) !
> Vous ne comprenez pas l'anglais ? Vous êtes francophone ? Regardez le [*LISEZ-MOI* français](./README.fr.md) !
## About
@@ -18,7 +18,7 @@ Upsilon is a fork of Omega, an user-made OS that runs on the Numworks calculator
### Some new features
- Enhancements for the Kandinsky python module
- A support for wallpapers
- Support for wallpapers
- Exernal apps
- A custom theme
- Operator overload for python
@@ -240,7 +240,7 @@ You need devkitPro and devkitARM installed and in your path (instructions [here]
```bash
git clone --recursive https://github.com/Lauryy06/Upsilon.git
cd Upsilon
git checkout --recursive omega-dev
git checkout --recursive upsilon-dev
make PLATFORM=simulator TARGET=3ds -j
```
You can then put epsilon.3dsx on a SD card to run it from the HBC or use 3dslink to launch it over the network:
@@ -259,15 +259,18 @@ Don't forget to put your pseudo instead of `{your pseudo, max 15 char}`. If you
<br>
If you need help, you can join our Discord server here : https://discord.gg/Q9buEMduXG
If you need help, you can join our Discord server here : https://discord.gg/NFvzdCBTQn
<a href="https://discord.gg/Q9buEMduXG"><p align="center"><img alt="Omega Banner Discord" src="https://user-images.githubusercontent.com/12123721/86287349-54ef5800-bbe8-11ea-80c1-34eb1f93eebd.png" /></p></a>
<a href="https://discord.gg/NFvzdCBTQn"><p align="center"><img alt="Omega Banner Discord" src="https://user-images.githubusercontent.com/12123721/86287349-54ef5800-bbe8-11ea-80c1-34eb1f93eebd.png" /></p></a>
---
## Useful links
* [Upsilon external (to install additional apps and wallpapers)](https://lauryy06.github.io/Upsilon-External/)
* [Ulab documentation](https://micropython-ulab.readthedocs.io/en/latest/)
## Contributing
To contribute, please refer to [Omega's Wiki](https://github.com/Omega-Numworks/Omega/wiki/Contributing), the same rules apply here.
## Related repositories
Here are the main links toward Omega's different websites and repositories, that have been used for the creation of Upsilon.

View File

@@ -75,13 +75,13 @@ void BatteryView::drawRect(KDContext * ctx, KDRect rect) const {
assert(!m_isPlugged);
// Low: Quite empty battery
ctx->fillRect(KDRect(batteryInsideX, 0, 2*k_elementWidth, k_batteryHeight), Palette::BatteryLow);
ctx->fillRect(KDRect(3*k_elementWidth+k_separatorThickness, 0, k_batteryWidth-5*k_elementWidth-2*k_separatorThickness, k_batteryHeight), Palette::BatteryInCharge);
ctx->fillRect(KDRect(3*k_elementWidth+k_separatorThickness, 0, k_batteryWidth-5*k_elementWidth-2*k_separatorThickness, k_batteryHeight), KDColor::blend(Palette::Toolbar, Palette::Battery, 128));
} else if (m_chargeState == Ion::Battery::Charge::SOMEWHERE_INBETWEEN) {
assert(!m_isPlugged);
// Middle: Half full battery
constexpr KDCoordinate middleChargeWidth = batteryInsideWidth/2;
ctx->fillRect(KDRect(batteryInsideX, 0, middleChargeWidth, k_batteryHeight), Palette::Battery);
ctx->fillRect(KDRect(batteryInsideX+middleChargeWidth, 0, middleChargeWidth, k_batteryHeight), Palette::BatteryInCharge);
ctx->fillRect(KDRect(batteryInsideX+middleChargeWidth, 0, middleChargeWidth, k_batteryHeight), KDColor::blend(Palette::Toolbar, Palette::Battery, 128));
} else {
assert(m_chargeState == Ion::Battery::Charge::FULL);
// Full but not plugged: Full battery

View File

@@ -29,6 +29,12 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
Context * context = App::app()->localContext();
Preferences * preferences = Preferences::sharedPreferences();
Poincare::ExpressionNode::ReductionContext reductionContext = Poincare::ExpressionNode::ReductionContext(context,
preferences->complexFormat(), preferences->angleUnit(),
GlobalPreferences::sharedGlobalPreferences()->unitFormat(),
ExpressionNode::ReductionTarget::SystemForApproximation,
ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition,
Poincare::ExpressionNode::UnitConversion::Default);
PoincareHelpers::Reduce(&m_expression, context, ExpressionNode::ReductionTarget::SystemForAnalysis);
@@ -46,60 +52,108 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
Expression a = polynomialCoefficients[2];
Expression b = polynomialCoefficients[1];
Expression c = polynomialCoefficients[0];
bool aIsNotOne = !(a.type() == ExpressionNode::Type::Rational && static_cast<const Rational &>(a).isOne());
Expression delta = Subtraction::Builder(Power::Builder(b.clone(), Rational::Builder(2)), Multiplication::Builder(Rational::Builder(4), a.clone(), c.clone()));
PoincareHelpers::Simplify(&delta, context, ExpressionNode::ReductionTarget::SystemForApproximation);
Expression alpha = Opposite::Builder(Division::Builder(b.clone(), Multiplication::Builder(Rational::Builder(2), a.clone())));
PoincareHelpers::Simplify(&alpha, context, ExpressionNode::ReductionTarget::User);
// Alpha is -b/2a, but because after we use -α, we immediately store -α=-(-b/2a)=b/2a.
Expression minusAlpha = Division::Builder(b.clone(), Multiplication::Builder(Rational::Builder(2), a.clone()));
PoincareHelpers::Reduce(&minusAlpha, context, ExpressionNode::ReductionTarget::SystemForApproximation);
Expression beta = Opposite::Builder(Division::Builder(delta.clone(), Multiplication::Builder(Rational::Builder(4), a.clone())));
PoincareHelpers::Simplify(&beta, context, ExpressionNode::ReductionTarget::User);
// Same thing for β
Expression minusBeta = Division::Builder(delta.clone(), Multiplication::Builder(Rational::Builder(4), a.clone()));
PoincareHelpers::Reduce(&minusBeta, context, ExpressionNode::ReductionTarget::SystemForApproximation);
enum MultiplicationTypeForA {
Nothing,
Minus,
Parenthesis,
Normal
};
MultiplicationTypeForA multiplicationTypeForA;
if (a.type() == ExpressionNode::Type::Rational && static_cast<const Rational &>(a).isOne()) {
multiplicationTypeForA = MultiplicationTypeForA::Nothing;
}
else if(a.type() == ExpressionNode::Type::Rational && static_cast<const Rational &>(a).isMinusOne()){
multiplicationTypeForA = MultiplicationTypeForA::Minus;
}
else if (a.type() == ExpressionNode::Type::Addition) {
multiplicationTypeForA = MultiplicationTypeForA::Parenthesis;
}
else {
multiplicationTypeForA = MultiplicationTypeForA::Normal;
}
PoincareHelpers::Simplify(&a, context, ExpressionNode::ReductionTarget::User);
/*
* Because when can't apply reduce or simplify to keep the canonised
* we must beautify the expression manually
* Because when can't apply reduce or simplify to keep the
* canonized form we must beautify the expression manually
*/
Expression canonised;
if (alpha.type() == ExpressionNode::Type::Opposite) {
canonised = Addition::Builder(Symbol::Builder("x", strlen("x")), alpha.childAtIndex(0).clone());
}
else {
canonised = Subtraction::Builder(Symbol::Builder("x", strlen("x")), alpha.clone());
}
canonised = Power::Builder(Parenthesis::Builder(canonised.clone()), Rational::Builder(2));
if (aIsNotOne) {
canonised = Multiplication::Builder(a.clone(), canonised.clone());
}
if (beta.type() == ExpressionNode::Type::Opposite) {
canonised = Subtraction::Builder(canonised.clone(), beta.childAtIndex(0).clone());
}
else {
canonised = Addition::Builder(canonised.clone(), beta.clone());
}
Expression xMinusAlphaPowerTwo;
Expression alpha = getOppositeIfExists(minusAlpha, &reductionContext);
if (alpha.isUninitialized()) {
PoincareHelpers::Simplify(&minusAlpha, context, ExpressionNode::ReductionTarget::User);
xMinusAlphaPowerTwo = Power::Builder(Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), minusAlpha)), Rational::Builder(2));
}
else {
PoincareHelpers::Simplify(&alpha, context, ExpressionNode::ReductionTarget::User);
xMinusAlphaPowerTwo = Power::Builder(Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), alpha)), Rational::Builder(2));
}
Expression xMinusAlphaPowerTwoWithFactor;
switch (multiplicationTypeForA)
{
case MultiplicationTypeForA::Nothing:
xMinusAlphaPowerTwoWithFactor = xMinusAlphaPowerTwo;
break;
case MultiplicationTypeForA::Minus:
xMinusAlphaPowerTwoWithFactor = Multiplication::Builder(a.clone(), xMinusAlphaPowerTwo);
break;
case MultiplicationTypeForA::Parenthesis:
xMinusAlphaPowerTwoWithFactor = Multiplication::Builder(Parenthesis::Builder(a.clone()), xMinusAlphaPowerTwo);
break;
case MultiplicationTypeForA::Normal:
xMinusAlphaPowerTwoWithFactor = Multiplication::Builder(a.clone(), xMinusAlphaPowerTwo);
break;
default:
assert(false);
break;
}
Expression canonized;
Expression beta = getOppositeIfExists(minusBeta, &reductionContext);
if (beta.isUninitialized()) {
PoincareHelpers::Simplify(&minusBeta, context, ExpressionNode::ReductionTarget::User);
canonized = Subtraction::Builder(xMinusAlphaPowerTwoWithFactor, minusBeta);
}
else {
PoincareHelpers::Simplify(&beta, context, ExpressionNode::ReductionTarget::User);
canonized = Addition::Builder(xMinusAlphaPowerTwoWithFactor, beta);
}
Expression x0;
Expression x1;
if (delta.nullStatus(context) == ExpressionNode::NullStatus::Null) {
// x0 = x1 = -b/(2a)
x0 = Division::Builder(Opposite::Builder(b), Multiplication::Builder(Rational::Builder(2), a));
x0 = Division::Builder(Opposite::Builder(b.clone()), Multiplication::Builder(Rational::Builder(2), a.clone()));
m_numberOfSolutions = 1;
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::SystemForApproximation);
}
else {
// x0 = (-b-sqrt(delta))/(2a)
x0 = Division::Builder(Subtraction::Builder(Opposite::Builder(b.clone()), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational::Builder(2), a.clone()));
// x1 = (-b+sqrt(delta))/(2a)
x1 = Division::Builder(Addition::Builder(Opposite::Builder(b), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational::Builder(2), a));
x1 = Division::Builder(Addition::Builder(Opposite::Builder(b.clone()), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational::Builder(2), a.clone()));
m_numberOfSolutions = 2;
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
PoincareHelpers::Simplify(&x1, context, ExpressionNode::ReductionTarget::User);
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::SystemForApproximation);
PoincareHelpers::Simplify(&x1, context, ExpressionNode::ReductionTarget::SystemForApproximation);
if (x0.type() == ExpressionNode::Type::Unreal) {
assert(x1.type() == ExpressionNode::Type::Unreal);
m_numberOfSolutions = 0;
@@ -109,40 +163,87 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
Expression factorized;
if (m_numberOfSolutions == 2) {
Expression firstFactor;
Expression secondFactor;
Expression x0Opposite = getOppositeIfExists(x0, &reductionContext);
if (x0Opposite.isUninitialized()) {
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
firstFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0);
}
else {
PoincareHelpers::Simplify(&x0Opposite, context, ExpressionNode::ReductionTarget::User);
firstFactor = Addition::Builder(Symbol::Builder("x", strlen("x")), x0Opposite);
}
if (x0.type() == ExpressionNode::Type::Opposite) {
factorized = Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), x0.childAtIndex(0).clone()));
}
else {
factorized = Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0.clone()));
}
if (x1.type() == ExpressionNode::Type::Opposite) {
factorized = Multiplication::Builder(factorized.clone(), Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), x1.childAtIndex(0).clone())));
Expression x1Opposite = getOppositeIfExists(x1, &reductionContext);
if (x1Opposite.isUninitialized()) {
PoincareHelpers::Simplify(&x1, context, ExpressionNode::ReductionTarget::User);
secondFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x1);
}
else {
factorized = Multiplication::Builder(factorized.clone(), Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), x1.clone())));
PoincareHelpers::Simplify(&x1Opposite, context, ExpressionNode::ReductionTarget::User);
secondFactor = Addition::Builder(Symbol::Builder("x", strlen("x")), x1Opposite);
}
if (aIsNotOne) {
factorized = Multiplication::Builder(a.clone(), factorized.clone());
Expression solutionProduct = Multiplication::Builder(Parenthesis::Builder(firstFactor), Parenthesis::Builder(secondFactor));
switch (multiplicationTypeForA)
{
case MultiplicationTypeForA::Nothing:
factorized = solutionProduct;
break;
case MultiplicationTypeForA::Minus:
factorized = Multiplication::Builder(a.clone(), solutionProduct);
break;
case MultiplicationTypeForA::Parenthesis:
factorized = Multiplication::Builder(Parenthesis::Builder(a.clone()), solutionProduct);
break;
case MultiplicationTypeForA::Normal:
factorized = Multiplication::Builder(a.clone(), solutionProduct);
break;
default:
assert(false);
break;
}
}
else if (m_numberOfSolutions == 1) {
if (x0.type() == ExpressionNode::Type::Opposite) {
factorized = Power::Builder(Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), x0.childAtIndex(0).clone())), Rational::Builder(2));
Expression x0Opposite = getOppositeIfExists(x0, &reductionContext);
Expression factor;
if (x0Opposite.isUninitialized()) {
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
factor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0);
}
else {
factorized = Power::Builder(Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0.clone())), Rational::Builder(2));
PoincareHelpers::Simplify(&x0Opposite, context, ExpressionNode::ReductionTarget::User);
factor = Addition::Builder(Symbol::Builder("x", strlen("x")), x0Opposite);
}
if (aIsNotOne) {
factorized = Multiplication::Builder(a.clone(), factorized.clone());
Expression solutionProduct = Power::Builder(Parenthesis::Builder(factor), Rational::Builder(2));
switch (multiplicationTypeForA)
{
case MultiplicationTypeForA::Nothing:
factorized = solutionProduct;
break;
case MultiplicationTypeForA::Minus:
factorized = Multiplication::Builder(a.clone(), solutionProduct);
break;
case MultiplicationTypeForA::Parenthesis:
factorized = Multiplication::Builder(Parenthesis::Builder(a.clone()), solutionProduct);
break;
case MultiplicationTypeForA::Normal:
factorized = Multiplication::Builder(a.clone(), solutionProduct);
break;
default:
assert(false);
break;
}
}
PoincareHelpers::Simplify(&delta, context, ExpressionNode::ReductionTarget::User);
m_layouts[0] = PoincareHelpers::CreateLayout(canonised);
m_layouts[0] = PoincareHelpers::CreateLayout(canonized);
if (m_numberOfSolutions > 0) {
m_layouts[1] = PoincareHelpers::CreateLayout(factorized);
m_layouts[2] = PoincareHelpers::CreateLayout(delta);
@@ -156,6 +257,27 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
}
}
Expression SecondDegreeListController::getOppositeIfExists(Expression e, Poincare::ExpressionNode::ReductionContext * reductionContext) {
if (e.isNumber() && e.sign(reductionContext->context()) == ExpressionNode::Sign::Negative) {
Number n = static_cast<Number&>(e);
return std::move(n.setSign(ExpressionNode::Sign::Positive));
}
else if (e.type() == ExpressionNode::Type::Multiplication && e.numberOfChildren() > 0 && e.childAtIndex(0).isNumber() && e.childAtIndex(0).sign(reductionContext->context()) == ExpressionNode::Sign::Negative) {
Multiplication m = static_cast<Multiplication&>(e);
if (m.childAtIndex(0).type() == ExpressionNode::Type::Rational && static_cast<Rational&>(e).isMinusOne()) {
// The negative numeral factor is -1, we just remove it
m.removeChildAtIndexInPlace(0);
} else {
Expression firstChild = m.childAtIndex(0);
Number n = static_cast<Number&>(firstChild);
m.childAtIndex(0).setChildrenInPlace(n.setSign(ExpressionNode::Sign::Positive));
}
PoincareHelpers::Simplify(&m, reductionContext->context(), ExpressionNode::ReductionTarget::User);
return std::move(m);
}
return Expression();
}
I18n::Message SecondDegreeListController::messageAtIndex(int index) {
if (m_numberOfSolutions > 0) {
if (index == 0) {

View File

@@ -14,6 +14,7 @@ public:
void setExpression(Poincare::Expression e) override;
private:
Poincare::Expression getOppositeIfExists(Poincare::Expression e, Poincare::ExpressionNode::ReductionContext * reductionContext);
I18n::Message messageAtIndex(int index) override;
int m_numberOfSolutions;
};

View File

@@ -81,7 +81,7 @@ void HistoryViewCell::reloadSubviewHighlight() {
m_ellipsis.setHighlighted(false);
if (isHighlighted()) {
if (m_dataSource->selectedSubviewType() == HistoryViewCellDataSource::SubviewType::Input) {
m_inputView.setExpressionBackgroundColor(Palette::ListCellBackgroundSelected);
m_inputView.setExpressionBackgroundColor(Palette::Select);
} else if (m_dataSource->selectedSubviewType() == HistoryViewCellDataSource::SubviewType::Output) {
m_scrollableOutputView.evenOddCell()->setHighlighted(true);
} else {

View File

@@ -1,6 +1,8 @@
apps += Code::App
app_headers += apps/code/app.h
SFLAGS += -DHAS_CODE
app_code_src = $(addprefix apps/code/,\
app.cpp \
console_controller.cpp \

View File

@@ -75,7 +75,7 @@ public:
VariableBoxController * variableBoxController() { return &m_variableBoxController; }
static constexpr int k_pythonHeapSize = 100000;
static constexpr int k_pythonHeapSize = 67000;
private:
/* Python delegate:

View File

@@ -62,6 +62,7 @@ PythonFloor = "Abrunden"
PythonFmod = "a modulo b"
PythonFrExp = "Mantisse und Exponent von x: (m,e)"
PythonGamma = "Gamma-Funktion"
PythonGetKeys = "Gedrückte Tasten erhalten"
PythonGetPalette = "Themenpalette erhalten"
PythonGetPixel = "Farbe von Pixel (x,y) zurückgeben"
PythonGetrandbits = "Ganzzahl mit k Zufallsbits"
@@ -77,11 +78,19 @@ PythonImportMatplotlibPyplot = "Matplotlib.pyplot-Modul importieren"
PythonImportNumpy = "Ulab.numpy-Modul importieren"
PythonImportScipy = "Ulab.scipy-Modul importieren"
PythonImportOs = "OS-Modul importieren"
PythonImportSys = "SYS-Modul importieren"
PythonOsUname = "Informationen über das System holen"
PythonOsGetlogin = "Benutzernamen holen"
PythonOsRemove = "Datei namens Dateiname entfernen"
PythonOsRename = "Datei umbenennen von Alt nach Neu"
PythonOsListdir = "Dateien im Speicher auflisten"
PythonSysExit = "Terminate current program"
PythonSysPrintexception = "Print exception"
PythonSysByteorder = "The byte order of the system"
PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonImportTime = "Time-Modul importieren"
PythonImportTurtle = "Turtle-Modul importieren"
PythonIndex = "Index des ersten x-Vorkommens"
@@ -145,7 +154,7 @@ PythonSleep = "Ausführung aussetzen für t Sekunden"
PythonLocalTime = "Zeit in Tupel umwandeln"
PythonMktime = "Tupel in Zeit umwandeln"
PythonTime = "Abrufen des aktuellen Zeitstempels"
PythonSetLocaltime = "Zeit aus einem Tupel von localtime()"
PythonSetLocaltime = "Zeit aus einem Tupel einstellen"
PythonRTCmode = "Aktuellen RTC-Modus abrufen"
PythonSetRTCmode = "RTC-Modus festlegen"
PythonSort = "Die Liste sortieren"

View File

@@ -62,6 +62,7 @@ PythonFloor = "Floor"
PythonFmod = "a modulo b"
PythonFrExp = "Mantissa and exponent of x: (m,e)"
PythonGamma = "Gamma function"
PythonGetKeys = "Get keys pressed"
PythonGetPalette = "Get theme palette"
PythonGetPixel = "Return pixel (x,y) color"
PythonGetrandbits = "Integer with k random bits"
@@ -139,7 +140,7 @@ PythonSleep = "Suspend the execution for t seconds"
PythonLocalTime = "Convert time into tuple"
PythonMktime = "Convert tuple into time"
PythonTime = "Get the current timestamp"
PythonSetLocaltime = "Set time from a tuple of localtime()"
PythonSetLocaltime = "Set time from a tuple"
PythonRTCmode = "Get current RTC mode"
PythonSetRTCmode = "Set RTC mode"
PythonSort = "Sort the list"
@@ -175,11 +176,19 @@ PythonTurtleWrite = "Display a text"
PythonUniform = "Floating point number in [a,b]"
PythonImportTime = "Import time module"
PythonImportOs = "Import os module"
PythonImportSys = "Import sys module"
PythonOsUname = "Get infos about the system"
PythonOsGetlogin = "Get username"
PythonOsRemove = "Remove file named filename"
PythonOsRename = "Rename file oldname to newname"
PythonOsListdir = "List files in memory"
PythonSysExit = "Terminate current program"
PythonSysPrintexception = "Print exception"
PythonSysByteorder = "The byte order of the system"
PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonMonotonic = "Return monotonic time"

View File

@@ -62,6 +62,7 @@ PythonFloor = "Floor"
PythonFmod = "a modulo b"
PythonFrExp = "Mantissa and exponent of x: (m,e)"
PythonGamma = "Gamma function"
PythonGetKeys = "Obtener teclas presionadas"
PythonGetPalette = "Get theme palette"
PythonGetPixel = "Return pixel (x,y) color"
PythonGetrandbits = "Integer with k random bits"
@@ -139,7 +140,7 @@ PythonSleep = "Suspend the execution for t seconds"
PythonLocalTime = "Convertir el tiempo en tupla"
PythonMktime = "Convertir tupla en tiempo"
PythonTime = "Obtener la marca de tiempo actual"
PythonSetLocaltime = "Establecer tiempo desde una tupla de localtime()"
PythonSetLocaltime = "Establecer tiempo desde una tupla"
PythonRTCmode = "Obtener el modo RTC actual"
PythonSetRTCmode = "Establecer modo RTC"
PythonSort = "Sort the list"
@@ -175,11 +176,19 @@ PythonTurtleWrite = "Display a text"
PythonUniform = "Floating point number in [a,b]"
PythonImportTime = "Import time module"
PythonImportOs = "Import os module"
PythonImportSys = "Import sys module"
PythonOsUname = " Información del sistema "
PythonOsGetlogin = "Get username"
PythonOsRemove = "Eliminar un archivo"
PythonOsRename = "Renombrar archivo"
PythonOsListdir = "Archivos de la lista"
PythonSysExit = "Terminate current program"
PythonSysPrintexception = "Print exception"
PythonSysByteorder = "The byte order of the system"
PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Esperar n segundos"
PythonMonotonic = "Tiempo monótono de retorno"

View File

@@ -62,6 +62,7 @@ PythonFloor = "Partie entière"
PythonFmod = "a modulo b"
PythonFrExp = "Mantisse et exposant de x : (m,e)"
PythonGamma = "Fonction gamma"
PythonGetKeys = "Obtenir les touches pressées"
PythonGetPalette = "Obtient la palette du thème"
PythonGetPixel = "Renvoie la couleur du pixel (x,y)"
PythonGetrandbits = "Nombre aléatoire sur k bits"
@@ -139,7 +140,7 @@ PythonSleep = "Suspend l'exécution t secondes"
PythonLocalTime = "Convertir le temps en tuple"
PythonMktime = "Convertir le tuple en temps"
PythonTime = "Obtenir l'horodatage actuel"
PythonSetLocaltime = "Définir l'heure à partir d'un tuple de localtime()"
PythonSetLocaltime = "Définir l'heure à partir d'un tuple"
PythonRTCmode = "Obtenir le mode RTC actuel"
PythonSetRTCmode = "Définir le mode RTC"
PythonSort = "Trie la liste"
@@ -175,11 +176,19 @@ PythonTurtleWrite = "Affiche un texte"
PythonUniform = "Nombre décimal dans [a,b]"
PythonImportTime = "Importation du module temps"
PythonImportOs = "Importation du module os"
PythonImportSys = "Importation du module sys"
PythonOsUname = "Donne des infos sur le système"
PythonOsGetlogin = "Donne le nom d'utilisateur"
PythonOsRemove = "Supprime le fichier nommé filename"
PythonOsRename = "Renomme oldname en newname"
PythonOsListdir = "Liste les fichiers"
PythonSysExit = "Termine le programme"
PythonSysPrintexception = "Imprime une exception"
PythonSysByteorder = "L'ordre des octets du système"
PythonSysImplementation = "Information sur Python"
PythonSysModules = "Dictionnaire des modules chargés"
PythonSysVersion = "Version du langage Python (string)"
PythonSysVersioninfo = "Version du langage Python (tuple)"
PythonTimePrefix = "Préfixe fonction du module temps"
PythonTimeSleep = "Attendre n secondes"
PythonMonotonic = "Retourne le temps monotone"

View File

@@ -62,6 +62,7 @@ PythonFloor = "Egész része"
PythonFmod = "a modulo b"
PythonFrExp = "X mantissája és kiállítója"
PythonGamma = "Gamma funkció"
PythonGetKeys = "Billentyűk lenyomva"
PythonGetPalette = "Téma paletta beszerzése"
PythonGetPixel = "Visszatéríti (x,y) színét"
PythonGetrandbits = "Váletlenszám visszatérítése k biten"
@@ -139,7 +140,7 @@ PythonSleep = "t másodpercre meg állitani a programmot"
PythonLocalTime = "Idő konvertálása csomóvá"
PythonMktime = "A tuple konvertálása az időben"
PythonTime = "Az aktuális időbélyeg letöltése"
PythonSetLocaltime = "Állítsd be az időt egy tufából a localtime()"
PythonSetLocaltime = "Idő beállítása egy csomóból"
PythonRTCmode = "Aktuális RTC mód"
PythonSetRTCmode = "RTC mód beállítása"
PythonSort = "A listát rendezni"
@@ -199,3 +200,11 @@ PythonOsGetlogin = "Get username"
PythonOsRemove = "Fájl törlése"
PythonOsRename = "Fájl átnevezése"
PythonOsListdir = "Fájlok listája"
PythonImportSys = "sys modul importálása"
PythonSysExit = "Terminate current program"
PythonSysPrintexception = "Print exception"
PythonSysByteorder = "The byte order of the system"
PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"

View File

@@ -62,6 +62,7 @@ PythonFloor = "Parte intera"
PythonFmod = "a modulo b"
PythonFrExp = "Mantissa ed esponente di x : (m,e)"
PythonGamma = "Funzione gamma"
PythonGetKeys = "Premere i tasti"
PythonGetPalette = "Ottieni la tavolozza del tema"
PythonGetPixel = "Restituisce colore del pixel(x,y)"
PythonGetrandbits = "Numero aleatorio con k bit"
@@ -84,6 +85,14 @@ PythonOsGetlogin = "Get username"
PythonOsRemove = "Rimuovere un file"
PythonOsRename = "Rinomina file"
PythonOsListdir = "Elenca file"
PythonImportSys = "Importa modulo sys"
PythonSysExit = "Terminate current program"
PythonSysPrintexception = "Print exception"
PythonSysByteorder = "The byte order of the system"
PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonIndex = "Indice prima occorrenza di x"
PythonInput = "Inserire un valore"
PythonInsert = "Inserire x in posizione i-esima"
@@ -145,7 +154,7 @@ PythonSleep = "Sospende l'esecuzione t secondi"
PythonLocalTime = "Converti il tempo in tuple"
PythonMktime = "Converti tuple in tempo"
PythonTime = "Ottieni il timestamp corrente"
PythonSetLocaltime = "Imposta il tempo da una tupla di localtime()"
PythonSetLocaltime = "Imposta il tempo da una tupla"
PythonRTCmode = "Ottieni la modalità RTC corrente"
PythonSetRTCmode = "Imposta modalità RTC"
PythonSort = "Ordina l'elenco"

View File

@@ -62,6 +62,7 @@ PythonFloor = "Vloer"
PythonFmod = "a modulo b"
PythonFrExp = "Mantisse en exponent van x: (m,e)"
PythonGamma = "Gammafunctie"
PythonGetKeys = "Get toetsen ingedrukt"
PythonGetPalette = "Thema palet krijgen"
PythonGetPixel = "Geef pixel (x,y) kleur (rgb)"
PythonGetrandbits = "Integer met k willekeurige bits"
@@ -83,6 +84,15 @@ PythonOsGetlogin = "Get username"
PythonOsRemove = "Een bestand verwijderen"
PythonOsRename = "Hernoem bestand"
PythonOsListdir = "Lijstbestanden"
PythonImportSys = "Importeer sys module"
PythonImportSys = "Importeer sys module"
PythonSysExit = "Terminate current program"
PythonSysPrintexception = "Print exception"
PythonSysByteorder = "The byte order of the system"
PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonImportTurtle = "Importeer turtle module"
PythonIndex = "Index van de eerste x aanwezigheden"
PythonInput = "Wijs een waarde toe"
@@ -145,7 +155,7 @@ PythonSleep = "Stel executie voor t seconden uit"
PythonLocalTime = "Zet tijd om in tuple"
PythonMktime = "Tuple omzetten in tijd"
PythonTime = "Haal de huidige tijdstempel"
PythonSetLocaltime = "Stel de tijd in vanaf een tuple van localtime()"
PythonSetLocaltime = "Stel de tijd in vanaf een tuple"
PythonRTCmode = "Huidige RTC-modus kregen"
PythonSetRTCmode = "RTC-modus instellen"
PythonSort = "Sorteer de lijst"

View File

@@ -62,6 +62,7 @@ PythonFloor = "Parte inteira"
PythonFmod = "a módulo b"
PythonFrExp = "Coeficiente e expoente de x: (m, e)"
PythonGamma = "Função gama"
PythonGetKeys = "Obter teclas pressionadas"
PythonGetPalette = "Obter paleta temática"
PythonGetPixel = "Devolve a cor do pixel (x,y)"
PythonGetrandbits = "Número inteiro aleatório com k bits"
@@ -139,7 +140,7 @@ PythonSleep = "Suspender a execução por t segundos"
PythonLocalTime = "Convert o tempo em tupla"
PythonMktime = "Convert tuple em tempo"
PythonTime = "Obter o estamp de tempo atual"
PythonSetLocaltime = "Definir tempo a partir de uma tupla de localtime()"
PythonSetLocaltime = "Definir tempo a partir de uma tupla"
PythonRTCmode = "Obter o modo RTC atual"
PythonSetRTCmode = "Definir o modo RTC"
PythonSort = "Ordenar a lista"
@@ -180,6 +181,14 @@ PythonOsGetlogin = "Get username"
PythonOsRemove = "Remover um ficheiro"
PythonOsRename = "Renomear ficheiro"
PythonOsListdir = "Listar ficheiros"
PythonImportSys = "Import sys module"
PythonSysExit = "Terminate current program"
PythonSysPrintexception = "Print exception"
PythonSysByteorder = "The byte order of the system"
PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonMonotonic = "Return monotonic time"

View File

@@ -69,6 +69,7 @@ PythonCommandFloor = "floor(x)"
PythonCommandFmod = "fmod(a,b)"
PythonCommandFrExp = "frexp(x)"
PythonCommandGamma = "gamma(x)"
PythonCommandGetKeys = "get_keys()"
PythonCommandGetPalette = "get_palette()"
PythonCommandGetPixel = "get_pixel(x,y)"
PythonCommandGetrandbits = "getrandbits(k)"
@@ -95,6 +96,8 @@ PythonCommandImportFromScipy = "from ulab import scipy as spy"
PythonCommandImportRandom = "import random"
PythonCommandImportOs = "import os"
PythonCommandImportFromOs = "from os import *"
PythonCommandImportSys = "import sys"
PythonCommandImportFromSys = "from sys import *"
PythonCommandImportTime = "import time"
PythonCommandImportTurtle = "import turtle"
PythonCommandIndex = "list.index(x)"
@@ -204,6 +207,9 @@ PythonCommandNumpyTranspose = "ndarray.transpose()"
PythonCommandNumpyTransposeWithoutArg = ".transpose()"
PythonCommandNumpySort = "ndarray.sort()"
PythonCommandNumpySortWithoutArg = ".sort()"
PythonCommandNumpyFromBuffer = "ndarray.frombuffer(b)"
PythonCommandNumpyToBytes = "ndarray.tobytes()"
PythonCommandNumpyToBytesWithoutArg = ".tobytes()"
PythonCommandNumpySetPrintOptions = "np.set_printoptions()"
PythonCommandNumpyGetPrintOptions = "np.get_printoptions()"
PythonCommandNumpyNdinfo = "np.ndinfo(a)"
@@ -369,6 +375,14 @@ PythonOsCommandRename = "rename(oldname, newname)"
PythonOsCommandRemoveWithoutArg = "remove(\x11)"
PythonOsCommandRenameWithoutArg = "rename(\x11,)"
PythonOsCommandListdir = "listdir()"
PythonSysCommandExit = "exit()"
PythonSysCommandPrintexception = "print_exception(exc)"
PythonSysCommandPrintexceptionWithoutArg = "print_exception(\x11)"
PythonSysCommandByteorder = "byteorder"
PythonSysCommandImplementation = "implementation"
PythonSysCommandModules = "modules"
PythonSysCommandVersion = "version"
PythonSysCommandVersioninfo = "version_info"
PythonTurtleCommandBackward = "backward(x)"
PythonTurtleCommandCircle = "circle(r)"
PythonTurtleCommandColor = "color('c')"

View File

@@ -102,7 +102,7 @@ void EditorView::GutterView::setOffset(KDCoordinate offset) {
KDSize EditorView::GutterView::minimalSizeForOptimalDisplay() const {
int numberOfChars = 2; // TODO: Could be computed
return KDSize(2 * k_margin + numberOfChars * Poincare::Preferences::sharedPreferences()->KDPythonFont()->glyphSize().width(), 0);
return KDSize(2 * k_margin + numberOfChars * m_font->glyphSize().width(), 0);
}
}

View File

@@ -3,6 +3,7 @@
#include <escher/palette.h>
#include <ion/unicode/utf8_helper.h>
#include <python/port/port.h>
#include "../global_preferences.h"
extern "C" {
#include "py/nlr.h"
@@ -444,6 +445,11 @@ void PythonTextArea::addAutocompletion() {
}
bool PythonTextArea::addAutocompletionTextAtIndex(int nextIndex, int * currentIndexToUpdate) {
// If Autocomplete disable, skip this step
if(!GlobalPreferences::sharedGlobalPreferences()->autocomplete()) {
return false;
}
// The variable box should be loaded at this point
const char * autocompletionTokenBeginning = nullptr;
const char * autocompletionLocation = const_cast<char *>(cursorLocation());

View File

@@ -135,7 +135,9 @@ const ToolboxMessageTree MatplotlibPyplotModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGray, I18n::Message::PythonColorGray, false)
};
const ToolboxMessageTree NumpyNdarrayModuleChildren[] = {
#if defined(INCLUDE_ULAB)
const ToolboxMessageTree NumpyNdarrayModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyArray),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyArange),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyConcatenate),
@@ -147,15 +149,17 @@ const ToolboxMessageTree MatplotlibPyplotModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyFull),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyLinspace),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyLogspace),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyCopy),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyDtype),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyFlat),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyFlatten),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyShape),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyReshape),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpySize),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyTranspose),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpySort),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyFromBuffer),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyCopy, I18n::Message::Default, false, I18n::Message::PythonCommandNumpyCopyWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyDtype, I18n::Message::Default, false, I18n::Message::PythonCommandNumpyDtypeWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyFlat, I18n::Message::Default, false, I18n::Message::PythonCommandNumpyFlatWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyFlatten, I18n::Message::Default, false, I18n::Message::PythonCommandNumpyFlattenWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyShape, I18n::Message::Default, false, I18n::Message::PythonCommandNumpyShapeWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyReshape, I18n::Message::Default, false, I18n::Message::PythonCommandNumpyReshapeWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpySize, I18n::Message::Default, false, I18n::Message::PythonCommandNumpySizeWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyTranspose, I18n::Message::Default, false, I18n::Message::PythonCommandNumpyTransposeWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpySort, I18n::Message::Default, false, I18n::Message::PythonCommandNumpySortWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandNumpyToBytes, I18n::Message::Default, false, I18n::Message::PythonCommandNumpyToBytesWithoutArg)
};
const ToolboxMessageTree NumpyFunctionsModuleChildren[] = {
@@ -254,7 +258,6 @@ const ToolboxMessageTree NumpyModuleChildren[] = {
ToolboxMessageTree::Node(I18n::Message::NumpyLinalgModule, NumpyLinalgModuleChildren)
};
#if !defined(DEVICE_N0100)
const ToolboxMessageTree ScipyLinalgModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandScipyLinalgFunction, I18n::Message::PythonScipyLinalgFunction, false, I18n::Message::PythonCommandScipyLinalgFunctionWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandScipyLinalgChoSolve),
@@ -291,16 +294,14 @@ const ToolboxMessageTree ScipyModuleChildren[] = {
ToolboxMessageTree::Node(I18n::Message::ScipySpecialModule, ScipySpecialModuleChildren),
};
#endif
const ToolboxMessageTree UlabModuleChildren[] = {
ToolboxMessageTree::Node(I18n::Message::NumpyModule, NumpyModuleChildren),
#if !defined(DEVICE_N0100)
ToolboxMessageTree::Node(I18n::Message::ScipyModule, ScipyModuleChildren),
#endif
ToolboxMessageTree::Leaf(I18n::Message::UlabDocumentation, I18n::Message::UlabDocumentationLink)
};
#endif
const ToolboxMessageTree TurtleModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportTurtle, I18n::Message::PythonImportTurtle, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromTurtle, I18n::Message::PythonImportTurtle, false),
@@ -364,8 +365,8 @@ const ToolboxMessageTree KandinskyModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillRect, I18n::Message::PythonFillRect),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillCircle, I18n::Message::PythonFillCircle),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillPolygon, I18n::Message::PythonFillPolygon),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetPalette, I18n::Message::PythonGetPalette)
};
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetKeys, I18n::Message::PythonGetKeys),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetPalette, I18n::Message::PythonGetPalette)};
const ToolboxMessageTree IonModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportIon, I18n::Message::PythonImportIon, false),
@@ -402,16 +403,31 @@ const ToolboxMessageTree OsModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonOsCommandListdir, I18n::Message::PythonOsListdir, false)
};
const ToolboxMessageTree SysModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportSys, I18n::Message::PythonImportSys, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromSys, I18n::Message::PythonImportSys, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandExit, I18n::Message::PythonSysExit, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandPrintexception, I18n::Message::PythonSysPrintexception, false, I18n::Message::PythonSysCommandPrintexceptionWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandByteorder, I18n::Message::PythonSysByteorder, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandImplementation, I18n::Message::PythonSysImplementation, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandModules, I18n::Message::PythonSysModules, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandVersion, I18n::Message::PythonSysVersion, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandVersioninfo, I18n::Message::PythonSysVersioninfo, false)
};
const ToolboxMessageTree modulesChildren[] = {
ToolboxMessageTree::Node(I18n::Message::MathModule, MathModuleChildren),
ToolboxMessageTree::Node(I18n::Message::CmathModule, CMathModuleChildren),
ToolboxMessageTree::Node(I18n::Message::MatplotlibPyplotModule, MatplotlibPyplotModuleChildren),
#if defined(INCLUDE_ULAB)
ToolboxMessageTree::Node(I18n::Message::UlabModule, UlabModuleChildren),
#endif
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::OsModule, OsModuleChildren),
ToolboxMessageTree::Node(I18n::Message::SysModule, SysModuleChildren),
ToolboxMessageTree::Node(I18n::Message::TimeModule, TimeModuleChildren)
};
@@ -678,9 +694,11 @@ KDCoordinate PythonToolbox::rowHeight(int j) {
bool PythonToolbox::selectLeaf(int selectedRow) {
ToolboxMessageTree * node = (ToolboxMessageTree *)m_messageTreeModel->childAtIndex(selectedRow);
#if defined(INCLUDE_ULAB)
if(node->text() == I18n::Message::UlabDocumentationLink){
return true;
}
#endif
m_selectableTableView.deselectTable();
if(node->insertedText() == I18n::Message::IonSelector){
m_ionKeys.setSender(sender());

View File

@@ -21,10 +21,10 @@ void ScriptNodeCell::ScriptNodeView::drawRect(KDContext * ctx, KDRect rect) cons
const int nodeNameLength = m_scriptNode->nameLength();
KDSize nameSize = k_font->stringSize(nodeName, nodeNameLength);
const KDCoordinate nodeNameY = k_topMargin;
ctx->drawString(nodeName, KDPoint(0, nodeNameY), k_font, KDColorBlack, backgroundColor, nodeNameLength);
ctx->drawString(nodeName, KDPoint(0, nodeNameY), k_font, Palette::PrimaryText, backgroundColor, nodeNameLength);
// If it is needed, draw the parentheses
if (m_scriptNode->type() == ScriptNode::Type::WithParentheses) {
ctx->drawString(ScriptNodeCell::k_parentheses, KDPoint(nameSize.width(), nodeNameY), k_font, KDColorBlack, backgroundColor);
ctx->drawString(ScriptNodeCell::k_parentheses, KDPoint(nameSize.width(), nodeNameY), k_font, Palette::PrimaryText, backgroundColor);
}
/* If it exists, draw the source name. If it did not fit, we would have put

View File

@@ -8,11 +8,9 @@ bool ScriptStore::ScriptNameIsFree(const char * baseName) {
return ScriptBaseNamed(baseName).isNull();
}
// Here we add "base" script
ScriptStore::ScriptStore() {
addScriptFromTemplate(ScriptTemplate::Squares());
addScriptFromTemplate(ScriptTemplate::Parabola());
addScriptFromTemplate(ScriptTemplate::Mandelbrot());
addScriptFromTemplate(ScriptTemplate::Polynomial());
}
void ScriptStore::deleteAllScripts() {

View File

@@ -5,103 +5,9 @@ namespace Code {
constexpr ScriptTemplate emptyScriptTemplate(".py", "\x01" R"(from math import *
)");
constexpr ScriptTemplate squaresScriptTemplate("squares.py", "\x01" R"(from math import *
from turtle import *
def squares(angle=0.5):
reset()
L=330
speed(10)
penup()
goto(-L/2,-L/2)
pendown()
for i in range(660):
forward(L)
left(90+angle)
L=L-L*sin(angle*pi/180)
hideturtle())");
constexpr ScriptTemplate mandelbrotScriptTemplate("mandelbrot.py", "\x01" R"(# This script draws a Mandelbrot fractal set
# N_iteration: degree of precision
import kandinsky
def mandelbrot(N_iteration):
for x in range(320):
for y in range(222):
# Compute the mandelbrot sequence for the point c = (c_r, c_i) with start value z = (z_r, z_i)
z = complex(0,0)
# Rescale to fit the drawing screen 320x222
c = complex(3.5*x/319-2.5, -2.5*y/221+1.25)
i = 0
while (i < N_iteration) and abs(z) < 2:
i = i + 1
z = z*z+c
# Choose the color of the dot from the Mandelbrot sequence
rgb = int(255*i/N_iteration)
col = kandinsky.color(int(rgb*0.82),int(rgb*0.13),int(rgb*0.18))
# Draw a pixel colored in 'col' at position (x,y)
kandinsky.set_pixel(x,y,col))");
constexpr ScriptTemplate polynomialScriptTemplate("polynomial.py", "\x01" R"(from math import *
# roots(a,b,c) computes the solutions of the equation a*x**2+b*x+c=0
def roots(a,b,c):
delta = b*b-4*a*c
if delta == 0:
return -b/(2*a)
elif delta > 0:
x_1 = (-b-sqrt(delta))/(2*a)
x_2 = (-b+sqrt(delta))/(2*a)
return x_1, x_2
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;
}
const ScriptTemplate * ScriptTemplate::Squares() {
return &squaresScriptTemplate;
}
const ScriptTemplate * ScriptTemplate::Mandelbrot() {
return &mandelbrotScriptTemplate;
}
const ScriptTemplate * ScriptTemplate::Polynomial() {
return &polynomialScriptTemplate;
}
const ScriptTemplate * ScriptTemplate::Parabola() {
return &parabolaScriptTemplate;
}
}

View File

@@ -9,10 +9,6 @@ class ScriptTemplate {
public:
constexpr ScriptTemplate(const char * name, const char * value) : m_name(name), m_value(value) {}
static const ScriptTemplate * Empty();
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 + Script::StatusSize(); }
const char * value() const { return m_value; }

View File

@@ -13,6 +13,7 @@ ScipySignalModule = "signal"
ScipySpecialModule = "special"
NumpyNdarray = "ndarray"
OsModule = "os"
SysModule = "sys"
TimeModule = "time"
TurtleModule = "turtle"
UlabModule = "ulab"

View File

@@ -37,10 +37,10 @@ namespace Code {
}
void toolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(rect, Palette::GrayBright);
ctx->strokeRect(rect, Palette::GrayDark);
ctx->drawString(I18n::translate(I18n::Message::PressAKey),KDPoint(rect.left()+80, rect.top()+20));
ctx->fillRect(rect, Palette::WallScreen);
ctx->strokeRect(rect, Palette::ListCellBorder);
ctx->drawString(I18n::translate(I18n::Message::PressAKey),KDPoint(rect.left()+80, rect.top()+20),KDFont::LargeFont,Palette::PrimaryText,Palette::WallScreen);
}
View * toolboxIonKeys::view(){

View File

@@ -43,9 +43,9 @@ public:
private:
constexpr static size_t k_maxNumberOfDisplayedItems = (Ion::Display::Height - Metric::TitleBarHeight - Metric::PopUpTopMargin) / ScriptNodeCell::k_simpleItemHeight + 2; // +2 if the cells are cropped on top and at the bottom
constexpr static size_t k_maxScriptNodesCount = 32; // Chosen without particular reasons
constexpr static size_t k_maxScriptNodesCount = 64; // Chosen without particular reasons (Number of functions in the variables box)
constexpr static int k_totalBuiltinNodesCount = 107;
constexpr static uint8_t k_scriptOriginsCount = 3;
constexpr static uint8_t k_scriptOriginsCount = 8; // Number of scripts loaded in the variable box
constexpr static uint8_t k_subtitleCellType = NodeCellType; // We don't care as it is not selectable
constexpr static uint8_t k_itemCellType = LeafCellType; // So that upper class NestedMenuController knows it's a leaf
constexpr static KDCoordinate k_subtitleRowHeight = 23;

23
apps/geometry/Makefile Normal file
View File

@@ -0,0 +1,23 @@
apps += Geometry::App
app_headers += apps/geometry/app.h
app_geometry_src = $(addprefix apps/geometry/,\
app.cpp \
list/figures_controller.cpp \
list/definition_type_controller.cpp \
list/figure_type_controller.cpp \
list/figure_parameters_controller.cpp \
list/objects_controller.cpp \
list/message_table_cell_with_selector.cpp \
figure_store.cpp \
graph/graph_controller.cpp \
graph/banner_view.cpp \
)
apps_src += $(app_geometry_src)
app_images += apps/geometry/geometry_icon.png
i18n_files += $(call i18n_with_universal_for,geometry/base)
$(eval $(call depends_on_image,apps/geometry/app.cpp,apps/geometry/geometry_icon.png))

48
apps/geometry/app.cpp Normal file
View File

@@ -0,0 +1,48 @@
#include "app.h"
#include "geometry_icon.h"
#include "apps/apps_container.h"
#include "apps/i18n.h"
namespace Geometry
{
I18n::Message App::Descriptor::name()
{
return I18n::Message::GeometryApp;
}
I18n::Message App::Descriptor::upperName()
{
return I18n::Message::GeometryAppCapital;
}
const Image * App::Descriptor::icon()
{
return ImageStore::GeometryIcon;
}
App * App::Snapshot::unpack(Container * container)
{
return new (container->currentAppBuffer()) App(this);
}
App::Descriptor * App::Snapshot::descriptor()
{
static Descriptor descriptor;
return &descriptor;
}
App::App(Snapshot * snapshot) :
TextFieldDelegateApp(snapshot, &m_tabViewController),
m_figuresController(&m_stackViewController),
m_stackViewController(&m_tabViewController, &m_figuresController),
m_graphController(&m_graphAlternateEmptyViewController, this, &m_graphHeader, nullptr, nullptr, nullptr),
m_graphAlternateEmptyViewController(&m_graphHeader, &m_graphController, &m_graphController),
m_graphHeader(&m_graphStackViewController, &m_graphAlternateEmptyViewController, &m_graphController),
m_graphStackViewController(&m_tabViewController, &m_graphHeader),
m_otherViewController(&m_tabViewController),
m_tabViewController(&m_modalViewController, snapshot, &m_stackViewController, &m_graphAlternateEmptyViewController, &m_otherViewController)
{
}
}

40
apps/geometry/app.h Normal file
View File

@@ -0,0 +1,40 @@
#ifndef GEOMETRY_H
#define GEOMETRY_H
#include <escher.h>
#include "list/figures_controller.h"
#include "graph/graph_controller.h"
#include "other/other_view_controller.h"
#include "../shared/text_field_delegate_app.h"
namespace Geometry {
class App : public Shared::TextFieldDelegateApp {
public:
class Descriptor : public ::App::Descriptor {
public:
I18n::Message name() override;
I18n::Message upperName() override;
const Image * icon() override;
};
class Snapshot : public ::App::Snapshot, public TabViewDataSource {
public:
App * unpack(Container * container) override;
Descriptor * descriptor() override;
};
private:
App(Snapshot * snapshot);
FiguresController m_figuresController;
StackViewController m_stackViewController;
GraphController m_graphController;
AlternateEmptyViewController m_graphAlternateEmptyViewController;
StackViewController m_graphStackViewController;
ButtonRowController m_graphHeader;
OtherViewController m_otherViewController;
TabViewController m_tabViewController;
};
}
#endif

View File

@@ -0,0 +1,6 @@
GeometryApp = "Geometry"
GeometryAppCapital = "GEOMETRY"
AddFigure = "Ajouter une figure"
FigureType = "Type de figure"
DefinitionType = "Définition de la figure"
ParametersChoice = "Choix des paramètres"

View File

@@ -0,0 +1,6 @@
GeometryApp = "Geometry"
GeometryAppCapital = "GEOMETRY"
AddFigure = "Ajouter une figure"
FigureType = "Type de figure"
DefinitionType = "Définition de la figure"
ParametersChoice = "Choix des paramètres"

View File

@@ -0,0 +1,6 @@
GeometryApp = "Geometry"
GeometryAppCapital = "GEOMETRY"
AddFigure = "Ajouter une figure"
FigureType = "Type de figure"
DefinitionType = "Définition de la figure"
ParametersChoice = "Choix des paramètres"

View File

@@ -0,0 +1,6 @@
GeometryApp = "Geometry"
GeometryAppCapital = "GEOMETRY"
AddFigure = "Ajouter une figure"
FigureType = "Type de figure"
DefinitionType = "Définition de la figure"
ParametersChoice = "Choix des paramètres"

View File

@@ -0,0 +1,6 @@
GeometryApp = "Geometry"
GeometryAppCapital = "GEOMETRY"
AddFigure = "Ajouter une figure"
FigureType = "Type de figure"
DefinitionType = "Définition de la figure"
ParametersChoice = "Choix des paramètres"

View File

@@ -0,0 +1,6 @@
GeometryApp = "Geometry"
GeometryAppCapital = "GEOMETRY"
AddFigure = "Ajouter une figure"
FigureType = "Type de figure"
DefinitionType = "Définition de la figure"
ParametersChoice = "Choix des paramètres"

View File

@@ -0,0 +1,6 @@
GeometryApp = "Geometry"
GeometryAppCapital = "GEOMETRY"
AddFigure = "Ajouter une figure"
FigureType = "Type de figure"
DefinitionType = "Définition de la figure"
ParametersChoice = "Choix des paramètres"

View File

@@ -0,0 +1,6 @@
GeometryApp = "Geometry"
GeometryAppCapital = "GEOMETRY"
AddFigure = "Ajouter une figure"
FigureType = "Type de figure"
DefinitionType = "Définition de la figure"
ParametersChoice = "Choix des paramètres"

View File

@@ -0,0 +1,24 @@
FiguresTab = "Figures"
NoFigures = "Aucune figure à afficher"
OtherTab = "TODO"
Coordinates = "Coordonnées"
Middle = "Milieu"
VectorProject = "Projeté vectoriel"
OrthogonalProject = "Projeté orthogonal"
CartesianEquation = "Equation cartésienne"
LinearEquation = "Equation linéaire"
Points = "Points"
PointAndVector = "Point et vecteur"
Parallele = "Parallèle"
Perpendicular = "Perpendiculaire"
PointAndRadius = "Point et rayon"
Diameter = "Diamètre"
TwoPoints = "Deux points"
Segment = "Segment"
Angle = "Angle"
Area = "Surface"
Point = "Point"
Line = "Droite"
Circle = "Cercle"
Vector = "Vecteur"
Indicator = "Indicateur"

View File

@@ -0,0 +1 @@
#include "figure_store.h"

View File

@@ -0,0 +1,14 @@
#ifndef FIGURE__STORE__H
#define FIGURE__STORE__H
#include "../shared/expression_model_store.h"
namespace Geometry {
class FigureStore: Shared::ExpressionModelStore {
};
}
#endif

View File

@@ -0,0 +1,27 @@
#ifndef POINCARE_FIGURE_H
#define POINCARE_FIGURE_H
#include "figure_type.h"
using namespace Poincare;
namespace Geometry {
class FigureNode : public TreeNode {
public:
virtual size_t size() const override = 0;
virtual int numberOfChildren() const override { return 0; }
virtual FigureType type() const = 0;
virtual FigureDefinitionType definitionType() const = 0;
};
class Figure : public TreeHandle {
public:
Figure(const FigureNode * node) : TreeHandle(node) {}
};
}
#endif

View File

@@ -0,0 +1,24 @@
#ifndef GEOMETRY_FIGURE_TYPE_H
#define GEOMETRY_FIGURE_TYPE_H
namespace Geometry {
enum class FigureType {
None = 0, // Used to trigger assert in debug mode
Expression, // It's not a real figure type but we use it to build figures like points
Point,
Line,
Circle,
Vector,
Indicator
};
enum class FigureDefinitionType {
PointByCoordinates
};
}
#endif

View File

@@ -0,0 +1,6 @@
#ifndef FIGURES_H
#define FIGURES_H
#include "point_by_coordinates.h"
#endif

View File

@@ -0,0 +1 @@
#include "point.h"

View File

@@ -0,0 +1,18 @@
#ifndef GEOMETRY_POINT_H
#define GEOMETRY_POINT_H
#include "figure.h"
namespace Geometry {
class PointNode : public FigureNode {
virtual FigureType type() const override { return FigureType::Point; }
};
class Point : public Figure {
public:
Point(const PointNode * n) : Figure(n) {}
};
}
#endif

View File

@@ -0,0 +1,31 @@
#ifndef POINT_BY_COORDINATES_H
#define POINT_BY_COORDINATES_H
#include <poincare/expression.h>
#include "point.h"
namespace Geometry {
class PointByCoordinatesNode : public PointNode {
public:
virtual size_t size() const override { return sizeof(PointByCoordinatesNode); }
virtual int numberOfChildren() const override { return 2; }
virtual FigureDefinitionType definitionType() const override { return FigureDefinitionType::PointByCoordinates; }
#if POINCARE_TREE_LOG
void logNodeName(std::ostream & stream) const override {
stream << "PointByCoordinates";
}
#endif
};
class PointByCoordinates : public Figure {
public:
PointByCoordinates(const PointByCoordinatesNode * n) : Figure(n) {}
static PointByCoordinates Builder(Expression x, Expression y) { return TreeHandle::FixedArityBuilder<PointByCoordinates, PointByCoordinatesNode>({x, x}); }
static int numberOfParameters() { return 2; }
static FigureType parameterTypeAtIndex(int i) { return FigureType::Expression; }
};
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,15 @@
#include "banner_view.h"
namespace Geometry {
BannerView::BannerView(
Responder * parentResponder,
InputEventHandlerDelegate * inputEventHandlerDelegate,
TextFieldDelegate * textFieldDelegate
) :
Shared::XYBannerView(parentResponder, inputEventHandlerDelegate, textFieldDelegate)
{
}
}

View File

@@ -0,0 +1,15 @@
#ifndef GEOMETRY_BANNER_VIEW_H
#define GEOMETRY_BANNER_VIEW_H
#include "../../shared/xy_banner_view.h"
namespace Geometry {
class BannerView : public Shared::XYBannerView {
public:
BannerView(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, TextFieldDelegate * textFieldDelegate);
};
}
#endif

View File

@@ -0,0 +1,11 @@
#include "graph_controller.h"
namespace Geometry {
GraphController::GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, Shared::InteractiveCurveViewRange/*TODO -> Store*/ * store, Shared::CurveViewCursor * cursor, uint32_t * rangeVersion) :
InteractiveCurveViewController(parentResponder, inputEventHandlerDelegate, header, store, nullptr, cursor, rangeVersion)
{
/* WHEREIWAS: Now i must make the app launch again without crash, by replacing the multiples nullptr that I used... */
}
}

View File

@@ -0,0 +1,33 @@
#ifndef GRAPH_VIEW_CONTROLLER_H
#define GRAPH_VIEW_CONTROLLER_H
#include "../shared/interactive_curve_view_controller.h"
namespace Geometry {
class GraphController : public Shared::InteractiveCurveViewController {
public:
GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, Shared::InteractiveCurveViewRange * store, Shared::CurveViewCursor * cursor, uint32_t * rangeVersion);
virtual Shared::InteractiveCurveViewRange * interactiveCurveViewRange() override { return nullptr; } //TOIMPLEMENT
virtual Shared::CurveView * curveView() override { return nullptr; } //TOIMPLEMENT
virtual void reloadBannerView() override { } //TOIMPLEMENT
virtual bool handleEnter() override { return false; } //TOIMPLEMENT
virtual void initCursorParameters() override { } //TOIMPLEMENT
virtual bool moveCursorVertically(int direction) override { return false; } //TOIMPLEMENT
virtual uint32_t rangeVersion() override { return 0; } //TOIMPLEMENT
virtual bool cursorMatchesModel() override { return false; } //TOIMPLEMENT
virtual Poincare::Coordinate2D<double> xyValues(int curveIndex, double t, Poincare::Context * context) const override { return Poincare::Coordinate2D<double>(0, 0); } //TOIMPLEMENT
virtual bool closestCurveIndexIsSuitable(int newIndex, int currentIndex) const override { return false; }
virtual int selectedCurveIndex() const override { return 0; }
virtual int numberOfCurves() const override { return 0; }
/* AlternateEmptyViewDefaultDelegate */
virtual bool isEmpty() const override { return false; }
virtual I18n::Message emptyMessage() override { return I18n::Message::NoFigures; }
private:
};
}
#endif

View File

@@ -0,0 +1,147 @@
#include "figure_type_controller.h"
#include "../figures/figures.h"
namespace Geometry {
static constexpr I18n::Message sPointDefinitionsMessages[] = {
I18n::Message::Coordinates,
I18n::Message::Middle,
I18n::Message::VectorProject,
I18n::Message::OrthogonalProject
};
static const uint8_t sPointDefinitionsMessagesCount = sizeof(sPointDefinitionsMessages) / sizeof(I18n::Message);
static constexpr I18n::Message sLineDefinitionMessages[] = {
I18n::Message::CartesianEquation,
I18n::Message::LinearEquation,
I18n::Message::Points,
I18n::Message::PointAndVector,
I18n::Message::Parallele,
I18n::Message::Perpendicular
};
static const uint8_t sLineDefinitionsMessagesCount = sizeof(sLineDefinitionMessages) / sizeof(I18n::Message);
static constexpr I18n::Message sCircleDefinitionsMessages[] = {
I18n::Message::PointAndRadius,
I18n::Message::Diameter,
I18n::Message::CartesianEquation,
};
static const uint8_t sCircleDefinitionsMessagesCount = sizeof(sCircleDefinitionsMessages) / sizeof(I18n::Message);
static constexpr I18n::Message sVectorDefinitionsMessages[] = {
I18n::Message::Coordinates,
I18n::Message::TwoPoints
};
static const uint8_t sVectorDefinitionsMessagesCount = sizeof(sVectorDefinitionsMessages) / sizeof(I18n::Message);
static constexpr I18n::Message sIndicatorDefinitionsMessages[] = {
I18n::Message::Segment,
I18n::Message::Angle,
I18n::Message::Area,
};
static const uint8_t sIndicatorDefinitionsMessagesCount = sizeof(sIndicatorDefinitionsMessages) / sizeof(I18n::Message);
DefinitionTypeController::DefinitionTypeController(Responder * parentResponder, FigureParametersController * parametersController):
ViewController(parentResponder),
m_lastSelectedRow(0),
m_selectableTableView(this),
m_messages(nullptr),
m_figureType(FigureType::None),
m_parametersController(parametersController)
{
for (int i = 0; i < k_numberOfCells; i ++) {
m_cells[i].setMessageFont(KDFont::LargeFont);
}
}
void DefinitionTypeController::viewWillAppear() {
assert(m_figureType != FigureType::None && m_messages != nullptr);
selectRow(m_lastSelectedRow);
m_selectableTableView.reloadData(); // We reload the cell of the table view to update their message
}
void DefinitionTypeController::didBecomeFirstResponder() {
//App::app()->snapshot()->setActivePage(App::Snapshot::Page::Distribution);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool DefinitionTypeController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
m_lastSelectedRow = selectedRow();
StackViewController * stack = static_cast<StackViewController *>(parentResponder());
m_parametersController->setParametersInfoFunctions(PointByCoordinates::numberOfParameters, PointByCoordinates::parameterTypeAtIndex);
stack->push(m_parametersController);
return true;
}
if (event == Ion::Events::Back) {
StackViewController * stack = static_cast<StackViewController *>(parentResponder());
stack->pop();
return true;
}
return false;
}
HighlightCell * DefinitionTypeController::reusableCell(int index) {
assert(index >= 0);
assert(index < k_numberOfCells);
return &m_cells[index];
}
void DefinitionTypeController::willDisplayCellForIndex(HighlightCell * cell, int index) {
MessageTableCellWithChevron * myCell = (MessageTableCellWithChevron *)cell;
myCell->setMessage(m_messages[index]);
}
int DefinitionTypeController::numberOfRows() const {
switch (m_figureType) {
case FigureType::Point:
return sPointDefinitionsMessagesCount;
break;
case FigureType::Line:
return sLineDefinitionsMessagesCount;
break;
case FigureType::Circle:
return sCircleDefinitionsMessagesCount;
break;
case FigureType::Vector:
return sVectorDefinitionsMessagesCount;
break;
case FigureType::Indicator:
return sIndicatorDefinitionsMessagesCount;
break;
default:
assert(false);
return 0;
}
}
void DefinitionTypeController::setFigureType(FigureType figureType) {
m_figureType = figureType;
switch (m_figureType) {
case FigureType::Point:
m_messages = sPointDefinitionsMessages;
break;
case FigureType::Line:
m_messages = sLineDefinitionMessages;
break;
case FigureType::Circle:
m_messages = sCircleDefinitionsMessages;
break;
case FigureType::Vector:
m_messages = sVectorDefinitionsMessages;
break;
case FigureType::Indicator:
m_messages = sIndicatorDefinitionsMessages;
break;
default:
assert(false);
break;
}
}
}

View File

@@ -0,0 +1,53 @@
#ifndef GEOMETRY_DEFINITION_TYPE_CONTROLLER_H
#define GEOMETRY_DEFINITION_TYPE_CONTROLLER_H
#include <escher.h>
#include "apps/i18n.h"
#include "../figures/figure_type.h"
#include "figure_parameters_controller.h"
namespace Geometry {
/**
* \brief DefinitionTypeController is a controller to choose how the figure is defined
*/
class DefinitionTypeController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource {
public:
DefinitionTypeController(Responder * parentResponder, FigureParametersController * parametersController);
/* ViewController */
View * view() override { return &m_selectableTableView; }
// We want to avoid using half of the screen just for titles
virtual DisplayParameter displayParameter() override { return DisplayParameter::DoNotShowOwnTitle; }
const char * title() override { return I18n::translate(I18n::Message::DefinitionType); }
/* Responder */
bool handleEvent(Ion::Events::Event event) override;
/* ViewController */
void didBecomeFirstResponder() override;
void viewWillAppear() override;
TELEMETRY_ID("FigureType");
/* SelectableTableViewDataSource */
int numberOfRows() const override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
KDCoordinate cellHeight() override { return k_cellHeight; }
HighlightCell * reusableCell(int index) override;
int reusableCellCount() const override { return k_numberOfCells; }
/* Customs methods */
void setFigureType(FigureType type);
private:
constexpr static KDCoordinate k_cellHeight = Metric::ParameterCellHeight;
constexpr static int k_numberOfCells = 6;
int m_lastSelectedRow;
MessageTableCellWithChevron m_cells[k_numberOfCells];
SelectableTableView m_selectableTableView;
const I18n::Message * m_messages;
FigureType m_figureType;
FigureParametersController * m_parametersController;
};
}
#endif

View File

@@ -0,0 +1,114 @@
#include "figure_parameters_controller.h"
#include "../app.h"
namespace Geometry {
FigureParametersController::FigureParametersController(Responder * parentResponder):
ViewController(parentResponder),
m_lastSelectedRow(0),
m_selectableTableView(this),
m_okButton(&m_selectableTableView, I18n::Message::Ok, Invocation([](void * context, void * sender) {
FigureParametersController * parameterController = (FigureParametersController *) context;
parameterController->returnToMenu();
return true;
}, this))
{
for (int i = 0; i < k_choiceCells; i++) {
m_choicesCells[i].setParentResponder(&m_selectableTableView);
}
for (int i = 0; i < k_textCells; i++) {
m_textCells[i].setParentResponder(&m_selectableTableView);
m_textCells[i].textField()->setDelegates(this, this);
}
}
void FigureParametersController::setParametersInfoFunctions(NumberOfParametersFunction numberOfParametersFunction, TypeOfParametersAtIndexFunction typeOfParametersAtIndexFunction) {
m_numberOfParametersFunction = numberOfParametersFunction;
m_typeOfParametersAtIndexFunction = typeOfParametersAtIndexFunction;
}
void FigureParametersController::didBecomeFirstResponder() {
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
void FigureParametersController::viewWillAppear() {
selectRow(m_lastSelectedRow);
}
void FigureParametersController::returnToMenu() {
StackViewController * stack = static_cast<StackViewController *>(parentResponder());
stack->pop();
stack->pop();
stack->pop();
}
/* ListViewDataSource */
int FigureParametersController::typeAtLocation(int i, int j) {
if (j == m_numberOfParametersFunction()) {
return 0; // It's equivalent to "None", so we can use it for button cell
}
return (int) m_typeOfParametersAtIndexFunction(j);
}
int FigureParametersController::reusableCellCount(int type) {
if (type == 0) {
return 1;
}
return type == (int) FigureType::Expression ? k_textCells: k_choiceCells;
}
HighlightCell * FigureParametersController::reusableCell(int index, int type) {
if (type == 0) {
return &m_okButton;
}
if (type == (int) FigureType::Expression) {
return &m_textCells[index];
}
return &m_choicesCells[index];
}
int FigureParametersController::numberOfRows() const {
return m_numberOfParametersFunction() + 1;
}
KDCoordinate FigureParametersController::rowHeight(int j) {
if (j == numberOfRows()-1) {
return Metric::ParameterCellHeight+k_buttonMargin;
}
return Metric::ParameterCellHeight;
}
KDCoordinate FigureParametersController::cumulatedHeightFromIndex(int j) {
if (j == numberOfRows()) {
return j*Metric::ParameterCellHeight+k_buttonMargin;
}
return Metric::ParameterCellHeight*j;
}
int FigureParametersController::indexFromCumulatedHeight(KDCoordinate offsetY) {
return (offsetY - 1) / Metric::ParameterCellHeight;
}
void FigureParametersController::willDisplayCellForIndex(HighlightCell * cell, int index) {
}
bool FigureParametersController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) {
return (event == Ion::Events::Down && selectedRow() < numberOfRows()-1)
|| (event == Ion::Events::Up && selectedRow() > 0)
|| TextFieldDelegate::textFieldShouldFinishEditing(textField, event);
}
bool FigureParametersController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
m_selectableTableView.reloadCellAtLocation(0, selectedRow());
m_selectableTableView.reloadData();
textField->setText(text);
if (event == Ion::Events::EXE || event == Ion::Events::OK) {
m_selectableTableView.selectCellAtLocation(selectedColumn(), selectedRow() + 1);
} else {
m_selectableTableView.handleEvent(event);
}
return true;
}
}

View File

@@ -0,0 +1,64 @@
#ifndef GEOMETRY_FIGURE_PARAMETERS_CONTROLLER_H
#define GEOMETRY_FIGURE_PARAMETERS_CONTROLLER_H
#include <escher.h>
#include "apps/i18n.h"
#include "message_table_cell_with_selector.h"
#include "../figures/figure.h"
#include "../../shared/parameter_text_field_delegate.h"
#include "../../shared/input_event_handler_delegate.h"
#include "../../shared/button_with_separator.h"
namespace Geometry {
typedef int (*NumberOfParametersFunction)();
typedef FigureType (*TypeOfParametersAtIndexFunction)(int);
/**
* \brief Controller returning the parameter choosen by the user to define the figure
*/
class FigureParametersController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource, public Shared::ParameterTextFieldDelegate, public Shared::InputEventHandlerDelegate {
public:
FigureParametersController(Responder * parentResponder);
void setParametersInfoFunctions(NumberOfParametersFunction numberOfParametersFunction, TypeOfParametersAtIndexFunction typeOfParametersAtIndexFunction);
void returnToMenu();
/* ViewController */
const char * title() override { return I18n::translate(I18n::Message::ParametersChoice); }
// We want to avoid using half of the screen just for titles
virtual DisplayParameter displayParameter() override { return DisplayParameter::DoNotShowOwnTitle; }
View * view() override { return &m_selectableTableView; };
/* Responder */
void didBecomeFirstResponder() override;
void viewWillAppear() override;
/* ListViewDataSource */
int typeAtLocation(int i, int j) override;
int reusableCellCount(int type) override; // TO IMPLEMENT
HighlightCell * reusableCell(int index, int type) override;
int numberOfRows() const override;
KDCoordinate rowHeight(int j) override;
KDCoordinate cumulatedHeightFromIndex(int j) override;
int indexFromCumulatedHeight(KDCoordinate offsetY) override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
/* InputEventHandlerDelegate */
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
private:
SelectableTableView m_selectableTableView;
constexpr static int k_textCells = 2;
constexpr static int k_choiceCells = 3;
constexpr static int k_buttonMargin = 6;
int m_lastSelectedRow;
MessageTableCellWithEditableText m_textCells[k_textCells];
MessageTableCellWithSelector m_choicesCells[k_choiceCells];
ButtonWithSeparator m_okButton;
NumberOfParametersFunction m_numberOfParametersFunction;
TypeOfParametersAtIndexFunction m_typeOfParametersAtIndexFunction;
};
}
#endif

View File

@@ -0,0 +1,70 @@
#include "figure_type_controller.h"
#include "apps/i18n.h"
namespace Geometry {
static FigureType sTypes[] = {
FigureType::Point,
FigureType::Line,
FigureType::Circle,
FigureType::Vector,
FigureType::Indicator
};
static I18n::Message sMessages[] = {
I18n::Message::Point,
I18n::Message::Line,
I18n::Message::Circle,
I18n::Message::Vector,
I18n::Message::Indicator
};
FigureTypeController::FigureTypeController(Responder * parentResponder, DefinitionTypeController * definitionTypeController) :
ViewController(parentResponder),
m_lastSelectedRow(0),
m_selectableTableView(this),
m_definitionTypeController(definitionTypeController),
m_messages(sMessages)
{
for (int i = 0; i < k_numberOfCells; i ++) {
m_cells[i].setMessageFont(KDFont::LargeFont);
}
}
void FigureTypeController::viewWillAppear() {
selectRow(m_lastSelectedRow);
}
void FigureTypeController::didBecomeFirstResponder() {
//App::app()->snapshot()->setActivePage(App::Snapshot::Page::Distribution);
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool FigureTypeController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
m_lastSelectedRow = selectedRow();
StackViewController * stack = static_cast<StackViewController *>(parentResponder());
m_definitionTypeController->setFigureType(sTypes[selectedRow()]);
stack->push(m_definitionTypeController);
return true;
}
if (event == Ion::Events::Back ) {
StackViewController * stack = static_cast<StackViewController *>(parentResponder());
stack->pop();
return true;
}
return false;
}
HighlightCell * FigureTypeController::reusableCell(int index) {
assert(index >= 0);
assert(index < k_numberOfCells);
return &m_cells[index];
}
void FigureTypeController::willDisplayCellForIndex(HighlightCell * cell, int index) {
MessageTableCellWithChevron * myCell = (MessageTableCellWithChevron *)cell;
myCell->setMessage(m_messages[index]);
}
}

View File

@@ -0,0 +1,49 @@
#ifndef GEOMETRY_FIGURE_TYPE_CONTROLLER_H
#define GEOMETRY_FIGURE_TYPE_CONTROLLER_H
#include <escher.h>
#include "definition_type_controller.h"
namespace Geometry {
/**
* \brief FigureTypeController is a controller that is used to select the type of
* figure to be created.
*/
class FigureTypeController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource {
public:
FigureTypeController(Responder * parentResponder, DefinitionTypeController * definitionController);
/* ViewController */
View * view() override { return &m_selectableTableView; }
// We want to avoid using half of the screen just for titles
virtual DisplayParameter displayParameter() override { return DisplayParameter::DoNotShowOwnTitle; }
const char * title() override { return I18n::translate(I18n::Message::FigureType); }
/* Responder */
bool handleEvent(Ion::Events::Event event) override;
void didBecomeFirstResponder() override;
/* ViewController */
void viewWillAppear() override;
TELEMETRY_ID("FigureType");
/* TableViewDataSource */
int numberOfRows() const override { return k_numberOfRows; }
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
KDCoordinate cellHeight() override { return k_cellHeight; }
HighlightCell * reusableCell(int index) override;
int reusableCellCount() const override { return k_numberOfCells; }
private:
constexpr static KDCoordinate k_cellHeight = Metric::ParameterCellHeight;
constexpr static int k_numberOfCells = 5;
constexpr static int k_numberOfRows = 5;
int m_lastSelectedRow;
MessageTableCellWithChevron m_cells[k_numberOfCells];
SelectableTableView m_selectableTableView;
DefinitionTypeController * m_definitionTypeController;
I18n::Message * m_messages;
};
}
#endif

View File

@@ -0,0 +1,77 @@
#include "figures_controller.h"
#include "definition_type_controller.h"
#include <apps/i18n.h>
namespace Geometry {
FiguresController::FiguresController(Responder * parentResponder):
ViewController(parentResponder),
m_selectableTableView(this, this, this, this),
m_addFigureCell(),
m_emptyCell(),
m_figureTypeController(this, &m_definitionTypeController),
m_definitionTypeController(&m_figureTypeController, &m_parametersController),
m_parametersController(&m_definitionTypeController)
{
m_addFigureCell.setMessage(I18n::Message::AddFigure);
}
bool FiguresController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
if (isAddFigureRow(selectedRow())) {
StackViewController * stack = static_cast<StackViewController *>(parentResponder());
stack->push(&m_figureTypeController);
return true;
}
}
if (event == Ion::Events::Up && selectedRow() == 0) {
m_selectableTableView.deselectTable();
assert(selectedRow() == -1);
Container::activeApp()->setFirstResponder(parentResponder()->parentResponder());
return true;
}
return false;
}
void FiguresController::didBecomeFirstResponder() {
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
HighlightCell * FiguresController::reusableCell(int index, int type) {
assert(index >= 0);
if (type == 2) {
return &m_emptyCell;
}
return &m_addFigureCell;
}
void FiguresController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) {
if (i == 0) {
return;
}
EvenOddCell * myCell = (EvenOddCell *)cell;
myCell->setEven(j%2 == 0);
myCell->setHighlighted(i == selectedColumn() && j == selectedRow());
myCell->reloadCell();
}
bool FiguresController::isAddFigureRow(int j) {
return j == 0;
}
int FiguresController::reusableCellCount(int type) {
if (type > 1) {
return 1;
}
return 0;
}
int FiguresController::typeAtLocation(int i, int j) {
if (isAddFigureRow(j)) {
return i + 2;
}
return i;
}
}

View File

@@ -0,0 +1,47 @@
#ifndef FIGURES_CONTROLLER_H
#define FIGURES_CONTROLLER_H
#include <escher.h>
#include "figure_type_controller.h"
namespace Geometry
{
/**
* \brief FiguresController is a controller to show the list of the figures
*/
class FiguresController : public ViewController, public SelectableTableViewDataSource, public SelectableTableViewDelegate, public TableViewDataSource {
public:
FiguresController(Responder * parentResponder);
/* ViewController */
View * view() override { return &m_selectableTableView; }
const char * title() override { return I18n::translate(I18n::Message::FiguresTab); }
virtual DisplayParameter displayParameter() override { return DisplayParameter::DoNotShowOwnTitle; }
/* Responder */
bool handleEvent(Ion::Events::Event event) override; // TO IMPLEMENT
void didBecomeFirstResponder() override;
/* TableView */
int numberOfRows() const override { return 1; } // TO IMPLEMENT
int numberOfColumns() const override { return 2; } // TO IMPLEMENT
KDCoordinate columnWidth(int i) { return i == 0 ? 50 : 150; } // TO IMPLEMENT
KDCoordinate rowHeight(int j) { return 50; } // TO IMPLEMENT
HighlightCell * reusableCell(int index, int type); // TO IMPLEMENT
void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; // TO IMPLEMENT
int reusableCellCount(int type);
int typeAtLocation(int i, int j); // TO IMPLEMENT
private:
/* Customs methods */
bool isAddFigureRow(int j); // TO IMPLEMENT
SelectableTableView m_selectableTableView;
EvenOddMessageTextCell m_addFigureCell;
EvenOddCell m_emptyCell;
FigureTypeController m_figureTypeController;
DefinitionTypeController m_definitionTypeController;
FigureParametersController m_parametersController;
};
}
#endif

View File

@@ -0,0 +1,24 @@
#include "message_table_cell_with_selector.h"
#include <escher/container.h>
namespace Geometry {
MessageTableCellWithSelector::MessageTableCellWithSelector(ToolboxMessageTree * root, const KDFont * font) :
Responder(nullptr),
MessageTableCell((I18n::Message)0, font),
m_objectsRoot(root),
m_selectedMessage(nullptr),
m_toolbox(this)
{
}
bool MessageTableCellWithSelector::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
Container::activeApp()->displayModalViewController(&m_toolbox, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin);
return true;
}
return false;
}
}

View File

@@ -0,0 +1,26 @@
#ifndef ESHER_MESSAGE_TABLE_CELL_WITH_OBJECT_SELECTOR_H_
#define ESHER_MESSAGE_TABLE_CELL_WITH_OBJECT_SELECTOR_H_
#include <escher/message_table_cell_with_buffer.h>
#include <escher/toolbox_message_tree.h>
#include "objects_controller.h"
namespace Geometry {
class MessageTableCellWithSelector : public Responder, public MessageTableCell {
public:
MessageTableCellWithSelector(ToolboxMessageTree * root = nullptr, const KDFont * font = KDFont::SmallFont);
ToolboxMessageTree * getSelectedMessage() const { return m_selectedMessage; };
bool handleEvent(Ion::Events::Event event);
Responder * responder() override {
return this;
}
private:
ToolboxMessageTree * m_objectsRoot;
ToolboxMessageTree * m_selectedMessage;
ObjectsController m_toolbox;
};
}
#endif

View File

@@ -0,0 +1,35 @@
#include "objects_controller.h"
namespace Geometry {
ObjectsController::ObjectsController(Responder * responder) :
NestedMenuController(this)
{
}
int ObjectsController::numberOfRows() const {
return 0;
}
int ObjectsController::reusableCellCount(int type) {
return 0;
}
int ObjectsController::typeAtLocation(int i, int j) {
return 0;
}
bool ObjectsController::selectLeaf(int type) {
return false;
}
HighlightCell * ObjectsController::leafCellAtIndex(int index) {
return nullptr;
}
HighlightCell * ObjectsController::nodeCellAtIndex(int index) {
return nullptr;
}
}

View File

@@ -0,0 +1,21 @@
#ifndef GEOMETRY_OBJECTS_CONTROLLER_H
#define GEOMETRY_OBJECTS_CONTROLLER_H
#include <escher/nested_menu_controller.h>
namespace Geometry {
class ObjectsController : public NestedMenuController {
public:
ObjectsController(Responder * parentResponder);
virtual int numberOfRows() const override;
virtual int reusableCellCount(int type) override;
virtual int typeAtLocation(int i, int j) override;
virtual bool selectLeaf(int selectedRow) override;
virtual HighlightCell * leafCellAtIndex(int index) override;
virtual HighlightCell * nodeCellAtIndex(int index) override;
};
}
#endif

View File

@@ -0,0 +1,16 @@
#ifndef OTHER_VIEW_CONTROLLER_H
#define OTHER_VIEW_CONTROLLER_H
namespace Geometry {
class OtherViewController : public ViewController {
public:
OtherViewController(Responder * parentResponder):
ViewController(parentResponder) {}
View * view() override { return nullptr; }
const char * title() override { return I18n::translate(I18n::Message::OtherTab); }
};
}
#endif

View File

@@ -30,6 +30,8 @@ public:
void setTempExamMode(ExamMode examMode);
bool showPopUp() const { return m_showPopUp; }
void setShowPopUp(bool showPopUp) { m_showPopUp = showPopUp; }
bool autocomplete() const { return m_autoComplete; }
void setAutocomplete(bool autocomple) { m_autoComplete = autocomple; }
int brightnessLevel() const { return m_brightnessLevel; }
void setBrightnessLevel(int brightnessLevel);
const KDFont * font() const { return m_font; }
@@ -44,6 +46,7 @@ private:
m_examMode(ExamMode::Unknown),
m_tempExamMode(ExamMode::Standard),
m_showPopUp(true),
m_autoComplete(true),
m_brightnessLevel(Ion::Backlight::MaxBrightness),
m_font(KDFont::LargeFont) {}
I18n::Language m_language;
@@ -53,6 +56,7 @@ private:
mutable ExamMode m_examMode;
mutable ExamMode m_tempExamMode;
bool m_showPopUp;
bool m_autoComplete;
int m_brightnessLevel;
const KDFont * m_font;
};

View File

@@ -1,2 +1,2 @@
Default,calculation,rpn,graph,code,statistics,probability,solver,atomic,sequence,regression,reader,settings
HidePython,calculation,rpn,graph,code,statistics,probability,solver,atomic,sequence,regression,reader,settings
Default,geometry,calculation,rpn,graph,code,statistics,probability,solver,atomic,sequence,regression,reader,settings
HidePython,geometry,calculation,rpn,graph,code,statistics,probability,solver,atomic,sequence,regression,reader,settings
1 Default geometry calculation rpn graph code statistics probability solver atomic sequence regression reader settings
2 HidePython geometry calculation rpn graph code statistics probability solver atomic sequence regression reader settings

View File

@@ -711,6 +711,54 @@ const ToolboxMessageTree Electromagnetism[] = {
};
const ToolboxMessageTree Resistivity[] = {
ToolboxMessageTree::Leaf(I18n::Message::Silver, I18n::Message::Rstvt_Silver, false, I18n::Message::Rstvt_Silver),
ToolboxMessageTree::Leaf(I18n::Message::Copper, I18n::Message::Rstvt_Copper, false, I18n::Message::Rstvt_Copper),
ToolboxMessageTree::Leaf(I18n::Message::Gold, I18n::Message::Rstvt_Gold, false, I18n::Message::Rstvt_Gold),
ToolboxMessageTree::Leaf(I18n::Message::Aluminium, I18n::Message::Rstvt_Aluminium, false, I18n::Message::Rstvt_Aluminium),
ToolboxMessageTree::Leaf(I18n::Message::Calcium, I18n::Message::Rstvt_Calcium, false, I18n::Message::Rstvt_Calcium),
ToolboxMessageTree::Leaf(I18n::Message::Tungsten, I18n::Message::Rstvt_Tungsten, false, I18n::Message::Rstvt_Tungsten),
ToolboxMessageTree::Leaf(I18n::Message::Zinc, I18n::Message::Rstvt_Zinc, false, I18n::Message::Rstvt_Zinc),
ToolboxMessageTree::Leaf(I18n::Message::Cobalt, I18n::Message::Rstvt_Cobalt, false, I18n::Message::Rstvt_Cobalt),
ToolboxMessageTree::Leaf(I18n::Message::Nickel, I18n::Message::Rstvt_Nickel, false, I18n::Message::Rstvt_Nickel),
ToolboxMessageTree::Leaf(I18n::Message::Lithium, I18n::Message::Rstvt_Lithium, false, I18n::Message::Rstvt_Lithium),
ToolboxMessageTree::Leaf(I18n::Message::Iron, I18n::Message::Rstvt_Iron, false, I18n::Message::Rstvt_Iron),
ToolboxMessageTree::Leaf(I18n::Message::Platinum, I18n::Message::Rstvt_Platinum, false, I18n::Message::Rstvt_Platinum),
ToolboxMessageTree::Leaf(I18n::Message::Tin, I18n::Message::Rstvt_Tin, false, I18n::Message::Rstvt_Tin),
ToolboxMessageTree::Leaf(I18n::Message::Sea_water, I18n::Message::Rstvt_Sea_water, false, I18n::Message::Rstvt_Sea_water),
ToolboxMessageTree::Leaf(I18n::Message::Water, I18n::Message::Rstvt_Water, false, I18n::Message::Rstvt_Water),
ToolboxMessageTree::Leaf(I18n::Message::Air, I18n::Message::Rstvt_Air, false, I18n::Message::Rstvt_Air),
ToolboxMessageTree::Leaf(I18n::Message::Wood, I18n::Message::Rstvt_Wood, false, I18n::Message::Rstvt_Wood),
ToolboxMessageTree::Leaf(I18n::Message::Glass, I18n::Message::Rstvt_Glass, false, I18n::Message::Rstvt_Glass)
};
const ToolboxMessageTree Conductivity[] = {
ToolboxMessageTree::Leaf(I18n::Message::Silver, I18n::Message::Cndcvt_Silver, false, I18n::Message::Cndcvt_Silver),
ToolboxMessageTree::Leaf(I18n::Message::Copper, I18n::Message::Cndcvt_Copper, false, I18n::Message::Cndcvt_Copper),
ToolboxMessageTree::Leaf(I18n::Message::Gold, I18n::Message::Cndcvt_Gold, false, I18n::Message::Cndcvt_Gold),
ToolboxMessageTree::Leaf(I18n::Message::Aluminium, I18n::Message::Cndcvt_Aluminium, false, I18n::Message::Cndcvt_Aluminium),
ToolboxMessageTree::Leaf(I18n::Message::Calcium, I18n::Message::Cndcvt_Calcium, false, I18n::Message::Cndcvt_Calcium),
ToolboxMessageTree::Leaf(I18n::Message::Tungsten, I18n::Message::Cndcvt_Tungsten, false, I18n::Message::Cndcvt_Tungsten),
ToolboxMessageTree::Leaf(I18n::Message::Zinc, I18n::Message::Cndcvt_Zinc, false, I18n::Message::Cndcvt_Zinc),
ToolboxMessageTree::Leaf(I18n::Message::Cobalt, I18n::Message::Cndcvt_Cobalt, false, I18n::Message::Cndcvt_Cobalt),
ToolboxMessageTree::Leaf(I18n::Message::Nickel, I18n::Message::Cndcvt_Nickel, false, I18n::Message::Cndcvt_Nickel),
ToolboxMessageTree::Leaf(I18n::Message::Lithium, I18n::Message::Cndcvt_Lithium, false, I18n::Message::Cndcvt_Lithium),
ToolboxMessageTree::Leaf(I18n::Message::Iron, I18n::Message::Cndcvt_Iron, false, I18n::Message::Cndcvt_Iron),
ToolboxMessageTree::Leaf(I18n::Message::Platinum, I18n::Message::Cndcvt_Platinum, false, I18n::Message::Cndcvt_Platinum),
ToolboxMessageTree::Leaf(I18n::Message::Tin, I18n::Message::Cndcvt_Tin, false, I18n::Message::Cndcvt_Tin),
ToolboxMessageTree::Leaf(I18n::Message::Sea_water, I18n::Message::Cndcvt_Sea_water, false, I18n::Message::Cndcvt_Sea_water),
ToolboxMessageTree::Leaf(I18n::Message::Water, I18n::Message::Cndcvt_Water, false, I18n::Message::Cndcvt_Water),
ToolboxMessageTree::Leaf(I18n::Message::Air, I18n::Message::Cndcvt_Air, false, I18n::Message::Cndcvt_Air),
ToolboxMessageTree::Leaf(I18n::Message::Wood, I18n::Message::Cndcvt_Wood, false, I18n::Message::Cndcvt_Wood),
ToolboxMessageTree::Leaf(I18n::Message::Glass, I18n::Message::Cndcvt_Glass, false, I18n::Message::Cndcvt_Glass)
};
const ToolboxMessageTree Electricity[] = {
ToolboxMessageTree::Leaf(I18n::Message::ElementalChargeTag, I18n::Message::ElementalCharge, false, I18n::Message::ElementalCharge),
ToolboxMessageTree::Node(I18n::Message::ResistivityConstants, Resistivity),
ToolboxMessageTree::Node(I18n::Message::ConductivityConstants, Conductivity)
};
const ToolboxMessageTree ParticleMass[] = {
ToolboxMessageTree::Leaf(I18n::Message::ElectronMassTag, I18n::Message::ElectronMass, false, I18n::Message::ElectronMass),
ToolboxMessageTree::Leaf(I18n::Message::MuonMassTag, I18n::Message::MuonMass, false, I18n::Message::MuonMass),
@@ -788,6 +836,7 @@ const ToolboxMessageTree PlanckUnits[] = {
const ToolboxMessageTree Physics[] = {
ToolboxMessageTree::Node(I18n::Message::FundamentalConstants, FundamentalConstants),
ToolboxMessageTree::Node(I18n::Message::Electromagnetism, Electromagnetism),
ToolboxMessageTree::Node(I18n::Message::Electricity, Electricity),
ToolboxMessageTree::Node(I18n::Message::NuclearConstants, Nuclear),
ToolboxMessageTree::Node(I18n::Message::Thermodynamics, Thermodynamics),
ToolboxMessageTree::Node(I18n::Message::Gravitation, Gravitation),
@@ -805,15 +854,15 @@ const ToolboxMessageTree menu[] = {
ToolboxMessageTree::Leaf(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm),
ToolboxMessageTree::Node(I18n::Message::Calculation, calculChildren),
ToolboxMessageTree::Node(I18n::Message::ComplexNumber, complexChildren),
ToolboxMessageTree::Node(I18n::Message::Combinatorics, combinatoricsChildren),
ToolboxMessageTree::Node(I18n::Message::Probability, probabilityChildren),
ToolboxMessageTree::Node(I18n::Message::Unit, unitChildren),
ToolboxMessageTree::Node(I18n::Message::Arithmetic, arithmeticChildren),
ToolboxMessageTree::Node(I18n::Message::Matrices, matricesChildren),
ToolboxMessageTree::Node(I18n::Message::Probability, probabilityChildren),
ToolboxMessageTree::Node(I18n::Message::Vectors, vectorsChildren),
#if LIST_ARE_DEFINED
ToolboxMessageTree::Node(I18n::Message::Lists,listsChildren),
#endif
ToolboxMessageTree::Node(I18n::Message::Unit, unitChildren),
ToolboxMessageTree::Node(I18n::Message::Combinatorics, combinatoricsChildren),
ToolboxMessageTree::Node(I18n::Message::RandomAndApproximation, randomAndApproximationChildren),
ToolboxMessageTree::Node(I18n::Message::HyperbolicTrigonometry, trigonometryChildren),
ToolboxMessageTree::Node(I18n::Message::Fluctuation, predictionChildren),

View File

@@ -5,7 +5,7 @@
MathVariableBoxEmptyController::MathVariableBoxEmptyView::MathVariableBoxEmptyView() :
ModalViewEmptyView(),
m_layoutExample(0.5f, 0.5f, KDColorBlack, Palette::WallScreen)
m_layoutExample(0.5f, 0.5f, Palette::PrimaryText, Palette::WallScreen)
{
initMessageViews();
}

27
apps/reader/README.md Normal file
View File

@@ -0,0 +1,27 @@
# Thanks
Thanks to [Gabriel79](https://github.com/Gabriel79) for the original reader app, his source code available [here](https://github.com/Gabriel79/OmegaWithReaderTutorial) and the [tutorial](https://www.codingame.com/playgrounds/55846/reader-faire-une-application-pour-omega-sur-numworks/introduction) to code it !
---
# Rich text format
Reader app supports now a rich text format :
* `$` around a mathematical expression **without spaces** to render it
* `%` around a color-code (see below) to change the color of the text
### Color codes :
|code|color|
| --:| ---:|
|`%\last_color%`|Stop using last color|
|`%r%`|Red|
|`%rl%`|Light red|
|`%m%`|Magenta|
|`%t%`|Turquoise|
|`%pk%`|Pink|
|`%pp%`|Purple|
|`%b%`|Blue|
|`%bl%`|Light blue|
|`%br%`|Brown|
|`%o%`|Orange|
|`%g%`|Green|
|`%gl%`|Light green|
|`%c%`|Cyan|

View File

@@ -27,19 +27,21 @@ bool ReadBookController::handleEvent(Ion::Events::Event event) {
m_readerView.previousPage();
return true;
}
if(event == Ion::Events::Back || event == Ion::Events::Home) {
savePosition();
}
return false;
}
void ReadBookController::viewDidDisappear() {
savePosition();
}
void ReadBookController::savePosition() const {
int pageOffset = m_readerView.getPageOffset();
Ion::Storage::Record::ErrorStatus status = Ion::Storage::sharedStorage()->createRecordWithFullName(m_file->name, &pageOffset, sizeof(pageOffset));
BookSave save = m_readerView.getBookSave();
Ion::Storage::Record::ErrorStatus status = Ion::Storage::sharedStorage()->createRecordWithFullName(m_file->name, &save, sizeof(save));
if(Ion::Storage::Record::ErrorStatus::NameTaken == status) {
Ion::Storage::Record::Data data;
data.buffer = &pageOffset;
data.size = sizeof(pageOffset);
data.buffer = &save;
data.size = sizeof(save);
status = Ion::Storage::sharedStorage()->recordNamed(m_file->name).setValue(data);
}
}
@@ -47,11 +49,14 @@ void ReadBookController::savePosition() const {
void ReadBookController::loadPosition() {
Ion::Storage::Record r = Ion::Storage::sharedStorage()->recordNamed(m_file->name);
if(Ion::Storage::sharedStorage()->hasRecord(r)) {
int pageOffset = *(static_cast<const int*>(r.value().buffer));
m_readerView.setPageOffset(pageOffset);
BookSave save = *(static_cast<const BookSave*>(r.value().buffer));
m_readerView.setBookSave(save);
}
else {
m_readerView.setPageOffset(0);
m_readerView.setBookSave({
0,
Palette::PrimaryText
});
}
}

View File

@@ -11,10 +11,9 @@ class ReadBookController : public ViewController {
public:
ReadBookController(Responder * parentResponder);
View * view() override;
void setBook(const External::Archive::File& file);
bool handleEvent(Ion::Events::Event event) override;
void viewDidDisappear() override;
void savePosition() const;
void loadPosition();
private:

View File

@@ -110,4 +110,21 @@ int filesWithExtension(const char* extension, External::Archive::File* files, in
}
#endif
const char * EndOfPrintableWord(const char * word, const char * end) {
if (word == end) {
return word;
}
UTF8Decoder decoder(word);
CodePoint codePoint = decoder.nextCodePoint();
const char * result = word;
while (codePoint != '\n' && codePoint != ' ' && codePoint != '%') {
result = decoder.stringPosition();
if (result >= end) {
break;
}
codePoint = decoder.nextCodePoint();
}
return result;
}
}

View File

@@ -2,6 +2,8 @@
#define __UTILITY_H__
#include <apps/external/archive.h>
#include <ion/unicode/code_point.h>
#include <ion/unicode/utf8_decoder.h>
namespace Reader
{
@@ -9,6 +11,7 @@ namespace Reader
bool stringEndsWith(const char* str, const char* end);
int filesWithExtension(const char* extension, External::Archive::File* files, int filesSize);
void stringNCopy(char* dest, int max, const char* src, int len);
const char * EndOfPrintableWord(const char * word, const char * end);
}
#endif

View File

@@ -1,10 +1,22 @@
#include "word_wrap_view.h"
#include "utility.h"
#include <poincare/expression.h>
#include "../shared/poincare_helpers.h"
#include <poincare/undefined.h>
namespace Reader
{
WordWrapTextView::WordWrapTextView() :
PointerTextView(GlobalPreferences::sharedGlobalPreferences()->font()),
m_pageOffset(0),
m_nextPageOffset(0),
m_length(0)
{
}
void WordWrapTextView::nextPage() {
if(m_nextPageOffset >= m_length) {
return;
@@ -29,12 +41,35 @@ void WordWrapTextView::previousPage() {
const char * endOfWord = text() + m_pageOffset - 1;
const char * startOfWord = UTF8Helper::BeginningOfWord(text(), endOfWord);
KDSize textSize = KDSizeZero;
KDPoint textEndPosition(m_frame.width() - k_margin, m_frame.height() - k_margin);
while(startOfWord>=text()) {
startOfWord = UTF8Helper::BeginningOfWord(text(), endOfWord);
endOfWord = UTF8Helper::EndOfWord(startOfWord);
KDSize textSize = m_font->stringSizeUntil(startOfWord, endOfWord);
endOfWord = UTF8Helper::EndOfWord(startOfWord);
if (*startOfWord == '%') {
if (updateTextColorBackward(startOfWord)) {
endOfWord = startOfWord - 1;
continue;
}
}
if (*startOfWord == '$' && *(endOfWord-1) == '$') {
const int wordMaxLength = 128;
char word[wordMaxLength];
stringNCopy(word, wordMaxLength, startOfWord + 1, endOfWord-startOfWord-2);
Poincare::Expression expr = Poincare::Expression::Parse(word, nullptr);
if (expr.isUninitialized()) {
expr = Poincare::Undefined::Builder();
}
Poincare::Layout layout = Shared::PoincareHelpers::CreateLayout(expr);
textSize = layout.layoutSize();
}
else {
textSize = m_font->stringSizeUntil(startOfWord, endOfWord);
}
KDPoint textStartPosition = KDPoint(textEndPosition.x()-textSize.width(), textEndPosition.y());
if(textStartPosition.x() < k_margin) {
@@ -84,37 +119,85 @@ void WordWrapTextView::drawRect(KDContext * ctx, KDRect rect) const {
const char * endOfFile = text() + m_length;
const char * startOfWord = text() + m_pageOffset;
const char * endOfWord = UTF8Helper::EndOfWord(startOfWord);
const char * endOfWord = EndOfPrintableWord(startOfWord, endOfFile);
KDPoint textPosition(k_margin, k_margin);
const int wordMaxLength = 128;
char word[wordMaxLength];
Poincare::Layout layout;
enum class ToDraw {
Text,
Expression,
Nothing
};
ToDraw toDraw = ToDraw::Text;
const int charWidth = m_font->glyphSize().width();
const int charHeight = m_font->glyphSize().height();
int nextLineOffset = charHeight;
KDSize textSize = KDSizeZero;
while(startOfWord < endOfFile) {
KDSize textSize = m_font->stringSizeUntil(startOfWord, endOfWord);
if (*startOfWord == '%') { // Look for color keyword (ex '%bl%')
if (updateTextColorForward(startOfWord)) {
startOfWord = endOfWord + 1;
endOfWord = EndOfPrintableWord(startOfWord, endOfFile);
continue;
}
}
if (*startOfWord == '$' && *(endOfWord-1) == '$') { // Look for expression
stringNCopy(word, wordMaxLength, startOfWord + 1, endOfWord-startOfWord-2);
Poincare::Expression expr = Poincare::Expression::Parse(word, nullptr);
if (expr.isUninitialized()) {
expr = Poincare::Undefined::Builder();
}
layout = Shared::PoincareHelpers::CreateLayout(expr);
textSize = layout.layoutSize();
toDraw = ToDraw::Expression;
}
else {
textSize = m_font->stringSizeUntil(startOfWord, endOfWord);
stringNCopy(word, wordMaxLength, startOfWord, endOfWord-startOfWord);
toDraw = ToDraw::Text;
}
KDPoint nextTextPosition = KDPoint(textPosition.x()+textSize.width(), textPosition.y());
if(nextTextPosition.x() > m_frame.width() - k_margin) { // Right overflow
textPosition = KDPoint(k_margin, textPosition.y() + textSize.height());
textPosition = KDPoint(k_margin, textPosition.y() + nextLineOffset);
nextTextPosition = KDPoint(k_margin + textSize.width(), textPosition.y());
nextLineOffset = charHeight;
}
if (nextLineOffset < textSize.height()) {
nextLineOffset = textSize.height();
}
if(textPosition.y() + textSize.height() > m_frame.height() - k_margin) { // Bottom overflow
break;
}
stringNCopy(word, wordMaxLength, startOfWord, endOfWord-startOfWord);
ctx->drawString(word, textPosition, m_font, m_textColor, m_backgroundColor);
if (toDraw == ToDraw::Expression) {
layout.draw(ctx, textPosition, m_textColor);
}
else if (toDraw == ToDraw::Text) {
ctx->drawString(word, textPosition, m_font, m_textColor, m_backgroundColor);
}
while(*endOfWord == ' ' || *endOfWord == '\n') {
if(*endOfWord == ' ') {
nextTextPosition = KDPoint(nextTextPosition.x() + charWidth, nextTextPosition.y());
}
else {
nextTextPosition = KDPoint(k_margin, nextTextPosition.y() + charHeight);
nextTextPosition = KDPoint(k_margin, nextTextPosition.y() + nextLineOffset);
nextLineOffset = charHeight;
}
++endOfWord;
}
@@ -123,6 +206,10 @@ void WordWrapTextView::drawRect(KDContext * ctx, KDRect rect) const {
//two times the same word if the break below is used
startOfWord = endOfWord;
if (endOfWord >= endOfFile) {
break;
}
if(nextTextPosition.y() + textSize.height() > m_frame.height() - k_margin) { // If out of page, quit
break;
}
@@ -130,22 +217,181 @@ void WordWrapTextView::drawRect(KDContext * ctx, KDRect rect) const {
nextTextPosition = KDPoint(k_margin, nextTextPosition.y());
}
if(nextTextPosition.x() > m_frame.width() - k_margin) { // Go to line if right overflow
nextTextPosition = KDPoint(k_margin, nextTextPosition.y() + textSize.height());
nextTextPosition = KDPoint(k_margin, nextTextPosition.y() + nextLineOffset);
nextLineOffset = charHeight;
}
textPosition = nextTextPosition;
endOfWord = UTF8Helper::EndOfWord(startOfWord);
endOfWord = EndOfPrintableWord(startOfWord+1, endOfFile);
}
m_nextPageOffset = startOfWord - text();
};
int WordWrapTextView::getPageOffset() const {
return m_pageOffset;
BookSave WordWrapTextView::getBookSave() const {
return {
m_pageOffset,
m_textColor
};
}
void WordWrapTextView::setPageOffset(int o) {
m_pageOffset = o;
void WordWrapTextView::setBookSave(BookSave save) {
m_pageOffset = save.offset;
m_textColor = save.color;
}
}
bool WordWrapTextView::updateTextColorForward(const char * colorStart) const {
if (*(colorStart + 1) == '\\') {
m_textColor = Palette::PrimaryText;
return (*(colorStart + 3) == '%' || *(colorStart + 4) == '%');
}
int keySize = 1;
KDColor lastColor = m_textColor;
switch (*(colorStart+1))
{
case 'r':
if (*(colorStart+2) == 'l') {
m_textColor = Palette::RedLight;
keySize = 2;
}
else {
m_textColor = Palette::Red;
}
break;
case 'm':
m_textColor = Palette::Magenta;
break;
case 't':
m_textColor = Palette::Turquoise;
break;
case 'p':
if (*(colorStart+2) == 'k') {
m_textColor = Palette::Pink;
keySize = 2;
}
else if (*(colorStart+2) == 'p') {
m_textColor = Palette::Purple;
keySize = 2;
}
break;
case 'b':
if (*(colorStart+2) == 'r') {
m_textColor = Palette::Brown;
keySize = 2;
}
if (*(colorStart+2) == 'l') {
m_textColor = Palette::BlueLight;
keySize = 2;
}
else {
m_textColor = Palette::Blue;
}
break;
case 'o':
m_textColor = Palette::Orange;
break;
case 'g':
if (*(colorStart+2) == 'l') {
m_textColor = Palette::GreenLight;
keySize = 2;
}
else {
m_textColor = Palette::Green;
}
break;
case 'c':
m_textColor = Palette::Cyan;
break;
default:
return false;
}
if (*(colorStart + keySize + 1) != '%') {
m_textColor = lastColor;
return false;
}
return true;
}
bool WordWrapTextView::updateTextColorBackward(const char * colorStart) const {
if (*(colorStart++) != '\\') {
return false;
}
int keySize = 1;
KDColor lastColor = m_textColor;
switch (*(colorStart+1))
{
case 'r':
if (*(colorStart+2) == 'l') {
m_textColor = Palette::RedLight;
keySize = 2;
}
else {
m_textColor = Palette::Red;
}
break;
case 'm':
m_textColor = Palette::Magenta;
break;
case 't':
m_textColor = Palette::Turquoise;
break;
case 'p':
if (*(colorStart+2) == 'k') {
m_textColor = Palette::Pink;
keySize = 2;
}
else if (*(colorStart+2) == 'p') {
m_textColor = Palette::Purple;
keySize = 2;
}
break;
case 'b':
if (*(colorStart+2) == 'r') {
m_textColor = Palette::Brown;
keySize = 2;
}
if (*(colorStart+2) == 'l') {
m_textColor = Palette::BlueLight;
keySize = 2;
}
else {
m_textColor = Palette::Blue;
}
break;
case 'o':
m_textColor = Palette::Orange;
break;
case 'g':
if (*(colorStart+2) == 'l') {
m_textColor = Palette::GreenLight;
keySize = 2;
}
else {
m_textColor = Palette::Green;
}
break;
case 'c':
m_textColor = Palette::Cyan;
break;
default:
return false;
}
if (*(colorStart + keySize + 1) != '%') {
m_textColor = lastColor;
return false;
}
return true;
}
}

View File

@@ -7,20 +7,28 @@
namespace Reader
{
struct BookSave {
int offset;
KDColor color;
};
class WordWrapTextView : public PointerTextView {
public:
WordWrapTextView() : PointerTextView(GlobalPreferences::sharedGlobalPreferences()->font()) {};
WordWrapTextView();
void drawRect(KDContext * ctx, KDRect rect) const override;
void setText(const char*, int length);
void nextPage();
void previousPage();
int getPageOffset() const;
void setPageOffset(int o);
protected:
int m_pageOffset = 0;
mutable int m_nextPageOffset = 0;
int m_length = 0;
BookSave getBookSave() const;
void setBookSave(BookSave save);
private:
bool updateTextColorForward(const char * colorStart) const;
bool updateTextColorBackward(const char * colorStart) const;
static const int k_margin = 10;
int m_pageOffset;
mutable int m_nextPageOffset;
int m_length;
mutable KDColor m_textColor;
};
}

View File

@@ -11,6 +11,7 @@ app_settings_src = $(addprefix apps/settings/,\
main_controller_prompt_update.cpp:+update \
sub_menu/about_controller.cpp \
sub_menu/accessibility_controller.cpp \
sub_menu/code_options_controller.cpp \
sub_menu/about_controller_official.cpp:+official \
sub_menu/about_controller_non_official.cpp:-official \
sub_menu/exam_mode_controller_official.cpp:+official \

View File

@@ -17,9 +17,16 @@ constexpr SettingsMessageTree s_modelDateTimeChildren[3] = {SettingsMessageTree(
constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::Message::SymbolMultiplicationCross),SettingsMessageTree(I18n::Message::SymbolMultiplicationMiddleDot),SettingsMessageTree(I18n::Message::SymbolMultiplicationStar),SettingsMessageTree(I18n::Message::SymbolMultiplicationAutoSymbol)};
constexpr SettingsMessageTree s_symbolFunctionChildren[3] = {SettingsMessageTree(I18n::Message::SymbolDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgFunction)};
constexpr SettingsMessageTree s_modelMathOptionsChildren[6] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren), SettingsMessageTree(I18n::Message::SymbolFunction, s_symbolFunctionChildren), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren)};
constexpr SettingsMessageTree s_modelFontChildren[2] = {SettingsMessageTree(I18n::Message::LargeFont), SettingsMessageTree(I18n::Message::SmallFont)};
constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)};
constexpr SettingsMessageTree s_contributorsChildren[23] = {SettingsMessageTree(I18n::Message::Developers), SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::MaximeFriess), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::SandraSimmons), SettingsMessageTree(I18n::Message::David), SettingsMessageTree(I18n::Message::DamienNicolet), SettingsMessageTree(I18n::Message::EvannDreumont), SettingsMessageTree(I18n::Message::SzaboLevente), SettingsMessageTree(I18n::Message::VenceslasDuet), SettingsMessageTree(I18n::Message::CharlotteThomas), SettingsMessageTree(I18n::Message::AntoninLoubiere), SettingsMessageTree(I18n::Message::CyprienMejat), SettingsMessageTree(I18n::Message::BetaTesters), SettingsMessageTree(I18n::Message::TimeoArnouts), SettingsMessageTree(I18n::Message::JulieC), SettingsMessageTree(I18n::Message::LelahelHideux), SettingsMessageTree(I18n::Message::Madil), SettingsMessageTree(I18n::Message::HilaireLeRoux), SettingsMessageTree(I18n::Message::HectorNussbaumer), SettingsMessageTree(I18n::Message::RaphaelDyda), SettingsMessageTree(I18n::Message::ThibautC)};
// Code Settings
#ifdef HAS_CODE
constexpr SettingsMessageTree s_codeChildren[2] = {SettingsMessageTree(I18n::Message::FontSizes, s_modelFontChildren), SettingsMessageTree(I18n::Message::Autocomplete)};
#endif
constexpr SettingsMessageTree s_modelFontChildren[2] = {SettingsMessageTree(I18n::Message::LargeFont), SettingsMessageTree(I18n::Message::SmallFont)};
constexpr SettingsMessageTree s_modelAboutChildren[9] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::UpsilonVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::Battery), SettingsMessageTree(I18n::Message::MemUse), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren)};
MainController::MainController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate) :
@@ -31,6 +38,7 @@ MainController::MainController(Responder * parentResponder, InputEventHandlerDel
m_localizationController(this, Metric::CommonTopMargin, LocalizationController::Mode::Language),
m_accessibilityController(this),
m_dateTimeController(this),
m_codeOptionsController(this),
m_examModeController(this),
m_aboutController(this),
m_preferencesController(this)
@@ -62,7 +70,7 @@ bool MainController::handleEvent(Ion::Events::Event event) {
}
if (model()->childAtIndex(selectedRow())->numberOfChildren() == 0) {
if (model()->childAtIndex(selectedRow())->label() == promptMessage()) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
globalPreferences->setShowPopUp(!globalPreferences->showPopUp());
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
return true;
@@ -103,6 +111,8 @@ bool MainController::handleEvent(Ion::Events::Event event) {
subController = &m_dateTimeController;
} else if (title == I18n::Message::MathOptions) {
subController = &m_mathOptionsController;
} else if (title == I18n::Message::CodeApp) {
subController = &m_codeOptionsController;
} else {
subController = &m_preferencesController;
}
@@ -202,9 +212,6 @@ void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) {
MessageTableCellWithChevronAndMessage * myTextCell = (MessageTableCellWithChevronAndMessage *)cell;
int childIndex = -1;
switch (model()->childAtIndex(index)->label()) {
case I18n::Message::FontSizes:
childIndex = GlobalPreferences::sharedGlobalPreferences()->font() == KDFont::LargeFont ? 0 : 1;
break;
default:
break;
}

View File

@@ -8,6 +8,7 @@
#include "sub_menu/accessibility_controller.h"
#include "sub_menu/datetime_controller.h"
#include "sub_menu/exam_mode_controller.h"
#include "sub_menu/code_options_controller.h"
#include "sub_menu/localization_controller.h"
#include "sub_menu/math_options_controller.h"
#include "sub_menu/preferences_controller.h"
@@ -22,6 +23,7 @@ extern const Shared::SettingsMessageTree s_symbolChildren[4];
extern const Shared::SettingsMessageTree s_symbolFunctionChildren[3];
extern const Shared::SettingsMessageTree s_modelMathOptionsChildren[6];
extern const Shared::SettingsMessageTree s_modelFontChildren[2];
extern const Shared::SettingsMessageTree s_codeChildren[2];
extern const Shared::SettingsMessageTree s_modelDateTimeChildren[3];
extern const Shared::SettingsMessageTree s_accessibilityChildren[6];
extern const Shared::SettingsMessageTree s_contributorsChildren[23];
@@ -70,6 +72,7 @@ private:
LocalizationController m_localizationController;
AccessibilityController m_accessibilityController;
DateTimeController m_dateTimeController;
CodeOptionsController m_codeOptionsController;
ExamModeController m_examModeController;
AboutController m_aboutController;
PreferencesController m_preferencesController;

View File

@@ -10,10 +10,12 @@ constexpr SettingsMessageTree s_modelMenu[] =
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren),
SettingsMessageTree(I18n::Message::Brightness),
SettingsMessageTree(I18n::Message::DateTime, s_modelDateTimeChildren),
SettingsMessageTree(I18n::Message::FontSizes, s_modelFontChildren),
SettingsMessageTree(I18n::Message::Language),
SettingsMessageTree(I18n::Message::Country),
SettingsMessageTree(I18n::Message::ExamMode, ExamModeConfiguration::s_modelExamChildren),
#ifdef HAS_CODE
SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren),
#endif
SettingsMessageTree(I18n::Message::BetaPopUp),
SettingsMessageTree(I18n::Message::About, s_modelAboutChildren),
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren)};

View File

@@ -13,7 +13,9 @@ constexpr SettingsMessageTree s_modelMenu[] =
SettingsMessageTree(I18n::Message::Language),
SettingsMessageTree(I18n::Message::Country),
SettingsMessageTree(I18n::Message::ExamMode, ExamModeConfiguration::s_modelExamChildren),
SettingsMessageTree(I18n::Message::FontSizes, s_modelFontChildren),
#ifdef HAS_CODE
SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren),
#endif
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren),
SettingsMessageTree(I18n::Message::About, s_modelAboutChildren)};

View File

@@ -10,11 +10,12 @@ constexpr SettingsMessageTree s_modelMenu[] =
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren),
SettingsMessageTree(I18n::Message::Brightness),
SettingsMessageTree(I18n::Message::DateTime, s_modelDateTimeChildren),
SettingsMessageTree(I18n::Message::FontSizes, s_modelFontChildren),
SettingsMessageTree(I18n::Message::Language),
SettingsMessageTree(I18n::Message::Country),
SettingsMessageTree(I18n::Message::ExamMode, ExamModeConfiguration::s_modelExamChildren),
SettingsMessageTree(I18n::Message::UpdatePopUp),
#ifdef HAS_CODE
SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren),
#endif SettingsMessageTree(I18n::Message::UpdatePopUp),
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren),
SettingsMessageTree(I18n::Message::About, s_modelAboutChildren)};

View File

@@ -25,7 +25,7 @@ bool AccessibilityController::handleEvent(Ion::Events::Event event) {
int redGamma, greenGamma, blueGamma;
KDIonContext::sharedContext()->gamma.gamma(redGamma, greenGamma, blueGamma);
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
if ((event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) && (selectedRow() <= 2)) {
if (selectedRow() == 0) {
invertEnabled = !invertEnabled;
}

View File

@@ -0,0 +1,74 @@
#include "code_options_controller.h"
#include <assert.h>
#include "../../global_preferences.h"
using namespace Shared;
namespace Settings {
CodeOptionsController::CodeOptionsController(Responder * parentResponder) :
GenericSubController(parentResponder),
m_preferencesController(this)
{
m_chevronCell.setMessageFont(KDFont::LargeFont);
m_switchCell.setMessageFont(KDFont::LargeFont);
}
bool CodeOptionsController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
switch (selectedRow()){
case 1:
GlobalPreferences::sharedGlobalPreferences()->setAutocomplete(!GlobalPreferences::sharedGlobalPreferences()->autocomplete());
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
break;
default:
GenericSubController * subController = nullptr;
subController = &m_preferencesController;
subController->setMessageTreeModel(m_messageTreeModel->childAtIndex(selectedRow()));
StackViewController * stack = stackController();
m_lastSelect = selectedRow();
stack->push(subController);
break;
}
return true;
}
return GenericSubController::handleEvent(event);
}
HighlightCell * CodeOptionsController::reusableCell(int index, int type) {
assert(type == 0);
assert(index >= 0 && index < k_totalNumberOfCell);
if (index == 0) {
return &m_chevronCell;
}
return &m_switchCell;
}
int CodeOptionsController::reusableCellCount(int type) {
assert(type == 0);
return k_totalNumberOfCell;
}
void CodeOptionsController::willDisplayCellForIndex(HighlightCell * cell, int index) {
GenericSubController::willDisplayCellForIndex(cell, index);
I18n::Message thisLabel = m_messageTreeModel->childAtIndex(index)->label();
if (thisLabel == I18n::Message::FontSizes){
MessageTableCellWithChevronAndMessage * myTextCell = (MessageTableCellWithChevronAndMessage *)cell;
myTextCell->setMessage(thisLabel);
GlobalPreferences::sharedGlobalPreferences()->font() == KDFont::LargeFont
? myTextCell->setSubtitle(I18n::Message::LargeFont)
: myTextCell->setSubtitle(I18n::Message::SmallFont);
}
#ifdef HAS_CODE
else if (thisLabel == I18n::Message::Autocomplete) {
MessageTableCellWithSwitch * mySwitchCell = (MessageTableCellWithSwitch *)cell;
SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView();
mySwitch->setState(GlobalPreferences::sharedGlobalPreferences()->autocomplete());
}
#endif
}
}

View File

@@ -0,0 +1,25 @@
#ifndef SETTINGS_CODE_OPTIONS_CONTROLLER_H
#define SETTINGS_CODE_OPTIONS_CONTROLLER_H
#include "generic_sub_controller.h"
#include "preferences_controller.h"
namespace Settings {
class CodeOptionsController : public GenericSubController {
public:
CodeOptionsController(Responder * parentResponder);
bool handleEvent(Ion::Events::Event event) override;
HighlightCell * reusableCell(int index, int type) override;
int reusableCellCount(int type) override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
private:
constexpr static int k_totalNumberOfCell = 2;
PreferencesController m_preferencesController;
MessageTableCellWithChevronAndMessage m_chevronCell;
MessageTableCellWithSwitch m_switchCell;
};
}
#endif

View File

@@ -26,7 +26,7 @@ DateTimeController::DateTimeController(Responder * parentResponder) :
bool DateTimeController::handleEvent(Ion::Events::Event event) {
bool clockEnabled = Ion::RTC::mode() != Ion::RTC::Mode::Disabled;
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
if (selectedRow() == 0) {
clockEnabled = !clockEnabled;
if (clockEnabled) {

View File

@@ -27,7 +27,7 @@ void PreferencesController::didBecomeFirstResponder() {
}
bool PreferencesController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
/* Generic behaviour of preference menu*/
assert(m_messageTreeModel->label() != I18n::Message::DisplayMode || selectedRow() != numberOfRows()-1); // In that case, events OK and EXE are handled by the cell
setPreferenceWithValueIndex(m_messageTreeModel->label(), selectedRow());

View File

@@ -458,3 +458,39 @@ HartreeConstant = "4.3597447222071·10^-18_J"
MagneticFluxQuantum = "2.067833848·10^-15_Wb"
ConductanceQuantum = "7.748091729·10^-5_S"
CirculationQuantum = "3.6369475516·10^-4_m^2_s^-1"
Cndcvt_Silver = "6.30·10^7_S_m^-1"
Cndcvt_Copper = "5.96·10^7_S_m^-1"
Cndcvt_Gold = "4.11·10^7_S_m^-1"
Cndcvt_Aluminium = "3.77·10^7_S_m^-1"
Cndcvt_Calcium = "2.98·10^7_S_m^-1"
Cndcvt_Tungsten = "1.79·10^7_S_m^-1"
Cndcvt_Zinc = "1.69·10^7_S_m^-1"
Cndcvt_Cobalt = "1.60·10^7_S_m^-1"
Cndcvt_Nickel = "1.43·10^7_S_m^-1"
Cndcvt_Lithium = "1.08·10^7_S_m^-1"
Cndcvt_Iron = "1.00·10^7_S_m^-1"
Cndcvt_Platinum = "9.43·10^6_S_m^-1"
Cndcvt_Tin = "9.17·10^6_S_m^-1"
Cndcvt_Sea_water = "4.80_S_m^-1"
Cndcvt_Water = "5.00·10^-3_S_m^-1"
Cndcvt_Air = "1.00·10^-13_S_m^-1"
Cndcvt_Glass = "1.00·10^-13_S_m^-1"
Cndcvt_Wood = "1.00·10^-3_S_m^-1"
Rstvt_Silver = "1.59·10^-8_Ω_m"
Rstvt_Copper = "1.68·10^-8_Ω_m"
Rstvt_Gold = "2.44·10^-8_Ω_m"
Rstvt_Aluminium = "2.65·10^-8_Ω_m"
Rstvt_Calcium = "3.36·10^-8_Ω_m"
Rstvt_Tungsten = "5.60·10^-8_Ω_m"
Rstvt_Zinc = "5.90·10^-8_Ω_m"
Rstvt_Cobalt = "6.24·10^-8_Ω_m"
Rstvt_Nickel = "6.99·10^-8_Ω_m"
Rstvt_Lithium = "9.28·10^-8_Ω_m"
Rstvt_Iron = "9.70·10^-8_Ω_m"
Rstvt_Platinum = "1.06·10^-7_Ω_m"
Rstvt_Tin = "1.09·10^-7_Ω_m"
Rstvt_Sea_water = "2.1·10^-1_Ω_m"
Rstvt_Water = "1.01·10^3_Ω_m"
Rstvt_Air = "1.00·10^9_Ω_m"
Rstvt_Glass = "5.00·10^14_Ω_m"
Rstvt_Wood = "1.00·10^3_Ω_m"

View File

@@ -24,13 +24,13 @@ void AbstractScrollableMultipleExpressionsView::ContentCell::setHighlighted(bool
// Do not call HighlightCell::setHighlighted to avoid marking all cell as dirty
m_highlighted = highlight;
KDColor defaultColor = backgroundColor();
KDColor color = highlight && m_selectedSubviewPosition == SubviewPosition::Center ? Palette::ExpressionInputBackground : defaultColor;
KDColor color = highlight && m_selectedSubviewPosition == SubviewPosition::Center ? Palette::Select : defaultColor;
m_centeredExpressionView.setBackgroundColor(color);
color = highlight && m_selectedSubviewPosition == SubviewPosition::Right ? Palette::ExpressionInputBackground : defaultColor;
color = highlight && m_selectedSubviewPosition == SubviewPosition::Right ? Palette::Select : defaultColor;
m_rightExpressionView.setBackgroundColor(color);
m_approximateSign.setBackgroundColor(defaultColor);
if (leftExpressionView()) {
color = highlight && m_selectedSubviewPosition == SubviewPosition::Left ? Palette::ExpressionInputBackground : defaultColor;
color = highlight && m_selectedSubviewPosition == SubviewPosition::Left ? Palette::Select : defaultColor;
leftExpressionView()->setBackgroundColor(color);
}
}

View File

@@ -430,6 +430,27 @@ AvogadroTag = "Avogadro-Konstante"
GasTag = "Gaskonstante"
Electromagnetism = "Elektromagnetismus"
CoulombTag = "Coulomb-Konstante"
ConductivityConstants = "Leitfähigkeitskonstanten"
Electricity = "Elektrizität"
ResistivityConstants = "Konstanten der Widerstandsfähigkeit"
Silver = "Silber"
Copper = "Kupfer"
Gold = "Gold"
Aluminium = "Aluminium"
Calcium = "Kalzium"
Tungsten = "Wolfram"
Zinc = "Zink"
Cobalt = "Kobalt"
Nickel = "Nickel"
Lithium = "Lithium"
Iron = "eisen"
Platinum = "Platin"
Tin = "Zinn"
Sea_water = "Meerwasser"
Water = "Wasser"
Air = "Luft"
Glass = "Glas"
Wood = "Holz"
Vacuum_permittivityTag = "Vakuum-Durchlässigkeit"
Vacuum_permeabilityTag = "Vakuumdurchlässigkeit"
PlanckTag = "Planck - Konstante"

Some files were not shown because too many files have changed in this diff Show More