Compare commits

...

451 Commits

Author SHA1 Message Date
Yaya-Cout
b9b49e0c17 [simulator/web] Fix window definition check 2025-12-14 12:59:08 +01:00
Yaya-Cout
bcef91bb59 [simulator/web] Better window definition check 2025-12-14 12:34:23 +01:00
Yaya-Cout
ff068ca797 [simulator/web] Add createContext to exported methods (emcc change) 2025-12-14 12:32:34 +01:00
Yaya-Cout
9d8e78ca1e [simulator/web] Avoid broadcasting storage if navigator isn't defined (on Node CI) 2025-12-14 12:20:49 +01:00
Yaya-Cout
90efabb404 [simulator/web] Broadcast storage after script execution 2025-12-14 12:09:05 +01:00
Yaya-Cout
26ee665d50 [simulator/web] Fix keyHandler not defined (backported from Upsilon Workshop) 2025-12-14 12:02:58 +01:00
Yaya-Cout
2233ca341b Merge pull request #389 from Random-Penguin/patch-1
Update toolbox.en.i18n molar masses
2025-12-06 17:45:57 +00:00
Random Penguin
677528dfb6 Update toolbox.en.i18n molar masses
Finally got around to fixing the molar masses of the atomic elements in the toolbox for the English language.
2025-12-04 15:19:33 +01:00
Yaya-Cout
bd78483d82 Merge pull request #388 from mickbot-92/ci
[CI] Update workflows
2025-11-30 10:46:29 +00:00
Yaya-Cout
2b5d6e9d7f [bootloader] Mark Epsilon 24.10.0 as safe 2025-11-26 22:11:08 +01:00
mickbot-92
9bf61ded07 [CI] Update workflows 2025-11-23 13:43:11 +01:00
Yaya-Cout
e3938e355b Merge pull request #387 from mickbot-92/bump-android
[Simulator/Android] Bump Gradle and Java & Add Android on README
2025-11-23 10:11:03 +00:00
Yaya-Cout
076fa3ab81 [apps/home] Fix trailing comma in apps_layout.csv 2025-11-10 19:07:34 +01:00
mickbot-92
be0edc48b6 [Simulator/Android] Bump Gradle and Java & Add Android on README 2025-11-08 23:25:11 +01:00
Yaya-Cout
d1b8cefcf9 Merge pull request #254 from RedGl0w/additional_result_trigo
Changes to the trigonometry additional result
2025-11-05 17:17:44 +00:00
Yaya-Cout
81ced8662c Merge pull request #308 from joecrop/logic-toolbox
Logic Toolbox
2025-11-05 15:08:30 +00:00
Yaya-Cout
c1f5b4afac Merge branch 'upsilon-dev' into logic-toolbox 2025-11-05 15:01:45 +00:00
Yaya-Cout
18f979dffe Merge pull request #294 from fmOOmf/upsilon-dev
Correction CIRCLE avec angle négatif (correct circle with negative angle)
2025-11-05 14:58:05 +00:00
Yaya-Cout
3c1bf54f0b Merge pull request #341 from AngeDieu/apps-layout
[build] update apps_layout.csv from EPSILON_APPS flag in make command
2025-11-05 14:49:27 +00:00
Yaya-Cout
5eb8054cde Merge pull request #361 from Ozero4/upsilon-dev
-- devient ans-
2025-11-05 14:40:59 +00:00
Yaya-Cout
f0f67b2766 Merge pull request #351 from AngeDieu/upsilon-dev
Update README.md
2025-11-05 14:40:28 +00:00
Yaya-Cout
c403aeaa04 Merge branch 'upsilon-dev' into upsilon-dev 2025-11-05 14:39:44 +00:00
Yaya-Cout
0a119fbad1 Merge pull request #383 from mickbot-92/build-on-arm
[CI] Build using Ubuntu ARM
2025-11-05 14:35:14 +00:00
Yaya-Cout
be688a487d Merge branch 'upsilon-dev' into build-on-arm 2025-11-05 14:29:20 +00:00
Lukas MAUFFRÉ
84fe92e3d7 Fix highlight background in console line view
Replaces Palette::BackgroundApps with Palette::CodeBackground for highlighted console lines to ensure consistent background color.
2025-11-02 10:43:17 +00:00
Yaya-Cout
96077fcfb6 [build] Version 1.1.2 2025-10-12 11:21:24 +02:00
Yaya-Cout
3566d44df2 [ion/usb] Fix USB descriptor 2025-10-12 10:58:59 +02:00
Yaya-Cout
13902cae72 [ion/platformInfo] Fix recovery boot address computation 2025-10-08 15:07:40 +02:00
Martin
59db12e78e [simulator/macos] Add universal binary support for x86_64 and ARM64
Build universal macOS simulator binaries that work on both Intel and Apple Silicon Macs by default. The build system now:
- Defaults to building for both x86_64 and ARM64 architectures
- Uses lipo to create universal binaries
- Allows single-architecture builds via ARCHS=arm64 or ARCHS=x86_64
- Conditionally includes the appropriate assembly files for each architecture
2025-10-08 11:15:37 +00:00
Yaya-Cout
696747a9a0 [build] Version 1.1.1 2025-10-02 18:34:05 +02:00
Yaya-Cout
7093f706ff [CI] Push to binfiles repo for N0110/N0110/Bootloader configs 2025-09-22 21:04:44 +02:00
Yaya-Cout
cc4b008048 [ion/usb] Fake alt interface to fix NumWorks website 2025-09-22 20:38:39 +02:00
Yaya-Cout
1b9b53a201 [build] Version 1.1.0 2025-09-22 20:34:33 +02:00
Yaya-Cout
a1f598194c [bootloader] Skip animation on keyboard event 2025-09-07 17:43:45 +02:00
Yaya-Cout
768bd52d46 [bootloader] Mark Epsilon 24.4.0 as safe 2025-09-07 16:52:21 +02:00
Yaya-Cout
818e4d281f [apps/external] Fix SCANCODE_OnOff being triggered by the left arrow 2025-08-25 17:00:00 +02:00
mickbot-92
f380c927f7 [CI] Build using Ubuntu ARM 2025-05-11 17:30:27 +02:00
Yaya-Cout
0fc06fafaf [README] Update usbipd instructions for WSL 2025-04-07 18:29:07 +02:00
Yaya-Cout
7a9a8ba371 [CI/Android] Run APT update to fix 404 2025-03-31 20:53:33 +02:00
Yaya-Cout
e6f14741d6 [CI] Install Linux toolchain for Web build to avoid dependancies issues (mainly libpng) 2025-03-31 20:46:25 +02:00
Yaya-Cout
6a83882826 [CI] Run APT update to fix 404 2025-03-31 20:40:23 +02:00
cartoone222
34506d334c Add an option to disable shift + clear (#368)
* add bgcolor to turtul module

* add bgcolor to toolbox and a minor fix

* ok is ok now i hope however

* Submodule Omega-Kawaii-Theme remove

* this featurs https://github.com/UpsilonNumworks/Upsilon/issues/285

* Update escher/src/text_area.cpp casse coresction

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* change name of function beacause code to late in night is bad idee

* invation of capital letter

* Update apps/settings/sub_menu/code_options_controller.cpp

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* Update escher/src/text_area.cpp

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* im not shure all is done

* the last hiden locke

* fix https://github.com/UpsilonNumworks/Upsilon/issues/271

* Update apps/global_preferences.h

Co-authored-by: Quentin <github@arra.red>

* Update apps/settings/sub_menu/code_options_controller.cpp

Co-authored-by: Quentin <git@quentinguidee.dev>

* Update apps/global_preferences.h

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* Update apps/global_preferences.h

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* reformatting the code to meet the expected quality

* Update apps/settings/base.pt.i18n

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* Update apps/settings/base.de.i18n

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* Update apps/settings/base.es.i18n

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* Update apps/settings/base.hu.i18n

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* Update apps/settings/base.it.i18n

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* Update apps/settings/base.nl.i18n

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>

* fix nameing

* Update apps/settings/base.en.i18n

---------

Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
Co-authored-by: Quentin <github@arra.red>
Co-authored-by: Quentin <git@quentinguidee.dev>
2025-03-31 18:17:30 +00:00
mickbot-92
ee8d456f1e [CI] [Simulator] Fix CI building (#381)
* [CI] Install more dependencies

* [Simulator] Some upgrades

* [CI] Fix Metrics

* Re-add newlines
2025-02-26 13:05:40 +00:00
Yaya-Cout
e971681dfd [Ion/bldata] Fix crash when going back to home screen after suspending 2025-01-25 19:21:56 +01:00
Yaya-Cout
276e8a603a [apps/settings] Unify prompt controller 2025-01-25 18:09:46 +01:00
Yaya-Cout
c1cc19d47c Avoid initializing storage to flash, reduce storage size by 8B and restore GCC 11 in CI 2025-01-25 18:00:29 +01:00
Yaya-Cout
7f560f8a5b [platformInfo] Add attribute weak to static storage declaration for simulators to fix windaube build (declaration is always weak for non-N0110 bootloader config) 2025-01-03 23:09:25 +01:00
Yaya-Cout
f7cd1693c9 [CI/Linux] Install libxtst-dev to fix build 2025-01-03 19:44:34 +01:00
Yaya-Cout
e6a308891b [CI/bootloader] Take toolchain from Ubuntu repos 2025-01-03 19:05:42 +01:00
Yaya-Cout
0c3506d85d Fix build for N0100 and legacy N0110 2025-01-03 18:32:20 +01:00
Yaya-Cout
d6831e46bf [bootloader] Change to version 1.1.0 - RECOVER 2024-12-29 12:01:21 +01:00
Yaya-Cout
b6d5bda120 [platformInfo] Hardcode recovery boot address to fix build on GCC 13+ 2024-12-29 11:57:44 +01:00
Yaya-Cout
4c26e846d3 Fix some spammy warnings 2024-12-29 11:48:18 +01:00
Yaya-Cout
219c6c4046 [bootloader] Don't shutdown he screen when booting to keep compatibility 2024-12-29 11:45:13 +01:00
Yaya-Cout
ea1e0c8140 Merge remote-tracking branch 'devdl11/upsilon-dev-1.0.1.01fix' into upsilon-dev 2024-12-27 19:01:17 +01:00
Yaya-Cout
7f5fc1269d [bootloader] Mark Epsilon 24.0.1 as safe 2024-12-27 18:38:56 +01:00
Yaya-Cout
deda7483e3 [bootloader] Fix slotInfo on Epsilon 2024-12-27 18:30:36 +01:00
Yaya-Cout
520b88e364 [Liba] Fix build on new GCC versions 2024-12-08 22:10:50 +01:00
mickbot-92
172f168bb2 [Simulator/Android] Bump to latest dependencies + other improvements (#376)
Co-authored-by: mickbot-92 <e3rck4b4[at]duck[dot]com>

* Bumping to latest stable dependencies and Gradle.
  * [CI] Building with JDK 21 instead of with JDK 11 (JDK 17 works fine too if you remove the latest line of build.gradle).
  * Using `mavenCentral()` instead of [deprecated](https://docs.gradle.org/current/userguide/upgrading_version_6.html#jcenter_deprecation) `jcenter()`
* Removing useless Google plugins.
* Setting `compileSdk` to 33 : Upsilon no longer requires the Notification permission.
* versionCode : compiling with the current Unix/Epoch timestamp.
* versionName : using the `UPSILON_VERSION` variable instead of the Omega one + adding the date of compiling.
* Some improvements about icons.
* [CI] Using the latests `uses: ` to make the warning about NodeJS deprecation disappear.

Many thanks to @Yaya-Cout (and to @pi-dev500 too :) 🫡
2024-10-20 08:39:17 +00:00
Yaya-Cout
89def884f7 [bootloader] Mark Epsilon 23.2.6 as safe and change the warning a bit the error message 2024-10-19 18:29:01 +02:00
Raphael Le Goaller
d3513a0763 [apps/math_toolbox] Remove duplicate entries in French i18n (#369) 2024-06-17 18:53:04 +00:00
cartoone222
ff54918502 [python] add bgcolor to turtule module (#367)
* add bgcolor to turtul module

* add bgcolor to toolbox and a minor fix

* ok is ok now i hope however

* Submodule Omega-Kawaii-Theme remove
2024-06-09 07:01:17 +00:00
Yaya-Cout
3b22656d4f Merge branch 'upsilon-dev' of github.com:UpsilonNumworks/Upsilon into upsilon-dev 2024-06-06 11:18:06 +02:00
Yaya-Cout
16d1946934 [Simulator/Android] Rename to Upsilon and other improvements 2024-06-06 11:18:02 +02:00
Leviathan3DPrinting
ac71576acc [Ion] Prevent crash if locale is null (#365)
* fix a compilation issue

* revert file

---------

Co-authored-by: Leviathan3DPrinting <leviathan3dprinting@gmail.com>
2024-05-12 11:35:12 +00:00
Yaya-Cout
891693abe2 [CI] Update Fxcg git url 2024-05-11 11:19:11 +02:00
Yaya-Cout
cf3cec7442 [Simulator] Fix Web simulator build on latest emscripten 2024-05-11 10:48:53 +02:00
Yaya-Cout
e20b1dee07 [bootloader] Update version code (1.0.11) 2024-05-08 20:18:33 +02:00
Yaya-Cout
8ff2e021ec Merge branch 'upsilon-dev' of github.com:UpsilonNumworks/Upsilon into upsilon-dev 2024-05-08 19:09:17 +02:00
Yaya-Cout
43a96629a4 [bootloader] Fix Epsilon 22+ exam mode detection on first flash 2024-05-08 19:09:12 +02:00
mickbot-92
6748f12239 Typos in README (#363)
* Update README.md

* Update README.fr.md
2024-04-17 16:12:14 +00:00
Yaya-Cout
5e83c03f8d [bootloader] Fix booting on newer toolchain versions 2024-04-04 19:22:56 +02:00
Yaya-Cout
510143678f [ion/simulator] Reduce rumble from 40 ms to 1 ms
Waaaay better on Android, simulator is usable (Look like RetroArch, even if I didn't copy the parameters)
2024-04-02 21:08:28 +02:00
Ozero4
35799f9a0d Update expression_field.h 2024-03-18 18:18:15 +01:00
Ozero4
46f7eb5afe Update expression_field.h 2024-03-18 18:14:01 +01:00
Ozero4
2671b6e0e1 Update expression_field.cpp 2024-03-18 18:13:25 +01:00
Ozero4
64b4012f90 Update expression_field.cpp 2024-03-18 18:11:43 +01:00
Yaya-Cout
2374fe4cf8 [bootloader] Fix exam mode with Epsilon 16-19 2024-02-29 12:49:58 +01:00
Yaya-Cout
1953371266 [apps/math_toolbox] Add centimeter and square meter 2024-02-18 20:28:54 +01:00
Yaya-Cout
b667509ab4 [themes/script.sh] Make script executable by default 2024-02-10 14:32:33 +01:00
Yaya-Cout
cb6fd76141 [bootloader] Fix exam mode with Epsilon 22 2024-01-17 19:35:43 +01:00
Yaya-Cout
f7a298aa0b [build] Fix DFU on recent Python versions and drop Python 2 2024-01-14 12:13:24 +01:00
Rathmox
5b87721f6e Fix Numworks not recognizing calculator (#352)
* Fix Numworks not recognizing calculator

* Fix issue also for scripts recovery
2023-12-20 06:38:39 +00:00
AngeDieu
d51c55fc6c Update README.md
precise to use linux terminal with wsl installation
2023-12-07 22:29:44 +01:00
Yaya-Cout
52bc616cd2 Merge branch 'upsilon-dev' of https://github.com/UpsilonNumworks/Upsilon into upsilon-dev 2023-11-23 19:21:13 +01:00
Yaya-Cout
458c9316f1 [Ion][DFU] Restore compatibility with NumWorks website
Revert product string descriptor change
2023-11-23 19:21:10 +01:00
AngeDieu
9ac62c0496 add factorial to toolbox -> combinatorics (#348)
* add factorial to toolbox -> combinatorics

* Update math_toolbox.cpp

removed newline for format purpose
2023-11-11 18:27:58 +01:00
Rathmox
7f2ba08761 Mark 21.3.0 as safe (#347)
* Mark 21.3.0 as safe

* set to FREEDOM 21.3
2023-10-20 19:03:52 +02:00
Yaya-Cout
a5354f589a Merge branch 'upsilon-dev' of https://github.com/UpsilonNumworks/Upsilon into upsilon-dev 2023-10-16 19:35:51 +02:00
Yaya-Cout
2bf46f59ce [apps_container] Avoid crashing on ×10^ on N0100 2023-10-16 19:35:31 +02:00
Rathmox
0f2ce293d1 Mark 21.2.0 as safe (#342)
* Mark 21.2.0 as safe

* Update messages.h
2023-10-02 21:12:43 +02:00
Yaya-Cout
764ff6fd86 Merge branch 'upsilon-dev' of https://github.com/UpsilonNumworks/Upsilon into upsilon-dev 2023-09-28 20:39:04 +02:00
Yaya-Cout
a0583aa2a9 [python] Prevent waiting for 2^32 ms if user entered a negative delay
This is due to a missing check in the interruptible sleep function which was not
checking if the delay was negative, then was passed to the
Ion::Timing::usleep function, who only takes signed values
2023-09-28 20:38:40 +02:00
Luminoso-256
0cabec542d [NSpire Simulator] Fix framebuffer in nspire port (#340)
* Fix the nspire port (ergo: framebuffer functions, shift/ctrl don't corrupt things due to weird draw calls)

* cleanup the k_csdk changes
2023-09-15 16:12:05 +00:00
AngeDieu
ab854e16ab Merge branch 'UpsilonNumworks:upsilon-dev' into upsilon-dev 2023-08-30 21:12:45 +02:00
Yaya-Cout
fd159fe489 [bootloader] Update version number 2023-08-29 12:26:38 +02:00
Yaya-Cout
f89ffc9b00 [bootloader] Mark Epsilon 21.1.1 as safe 2023-08-29 11:54:31 +02:00
AngeDieu
51d5ed04d0 [build] update apps_layout.csv from EPSILON_APPS flag in make command
python approach
2023-07-13 18:28:27 +02:00
Yaya-Cout
a945fc1025 [python/kandinsky] Fix big font selection 2023-07-01 20:14:20 +02:00
Yaya-Cout
6976e524ad [python/kandinsky] Allow selecting italic font for draw_string using 7th argument 2023-06-27 20:04:24 +02:00
Yaya-Cout
4630052630 [i18n/code] Fix random description in italian 2023-06-26 18:18:28 +02:00
andrigamerita
3c6641c808 [it.i18n] Add missing italian translations, fix typos / excessive length in the existing ones (#331)
* [it.i18n] [apps/code] Add missing translations

* [it.i18n] [apps/reader] Fix typo

* [it.i18n] [apps/external, apps/setting] Add missing translations + fixes
2023-06-26 17:01:54 +02:00
Yaya-Cout
45a9dda989 [apps/host_filemanager] Fix N0100 build 2023-06-07 08:54:38 +02:00
Yaya-Cout
73450419bb [Ports] Merge Nspire port and Fxcg improvements
Close #327
2023-06-06 21:28:54 +02:00
Yaya-Cout
a124ed72b5 [Ion] Quick-and-dirty fix for the Web simulator 2023-05-21 11:53:08 +02:00
circuit10
b44a95a9b3 Casio fx-CG series port (#324)
* Initial test - working on Linux

* Try to make it work with liba

* Stop using liba and the filesystem

* IT WORKS

* Key input, full res, fix some of the crashes

* Fix the hang when doing calculations

* Add some more key mappings

* Fix the square root issue

* Icons

* Better key mappings, brightness control, better gamma correction, more effficient framebuffer

* Cleanup stage 1

* Cleanup stage 2

* Make the build system build a g3a

* Make it not exit when you press the menu button

* Add Casio port to README

* Use omega-master instead of omega-dev

* Fix mistake with cherry-picking in the README

* Fix internal storage crash

* Fix compile error on Numworks calculators

* Upsilon branding

* Sharper icon

* Make the CI work

* Add power off and improve menu

* Map Alpha + up/down to the brightness shortcut

* Add missing file

* Fix web CI build

* Revert "Fix web CI build"

This reverts commit f19657d9fc.

* Change "prizm" to "fxcg"

* Add FASTLOAD option for Add-in Push

* Add some charatcers to the catalog on Casio and improve key mappings

* Build with -Os -flto

* Disable LTO for now as it's causing crashes

* Put back the fonts I accidently changed

I'd like to add an option for this though as I prefer the ones from Epsilon
2023-05-10 18:28:18 +02:00
Yaya-Cout
aadcd37f31 Fix 3DS simulator (#243)
* [CI] Fix 3DS try 1

* [CI] Fix 3DS try 2

* [CI] Fix 3DS try 3

* [CI] Fix 3DS try 4

* [CI] Fix 3DS try 5

* [CI] Fix 3DS try 6

* [CI] Fix 3DS try 7

* [CI] Fix 3DS try 8

* [CI] Fix 3DS try 9

* [CI] Fix 3DS try 10

* [CI] Fix 3DS try 11

* [CI] Fix 3DS try 12

* [CI] Fix 3DS try 13

* [CI] Fix 3DS try 14

* [CI] Fix 3DS try 15

* [CI] Fix 3DS try 16

* [CI] Fix 3DS try 17

* [CI] Fix 3DS try 18

* [CI] Fix 3DS try 19

* [CI] Make other simulators than 3DS working

* [CI] Fix 3DS without breaking others simulators try 1

* Apply suggestions from code review

* Improve SDL assert

* Fix SDL assert

* Fix SDL assert 2

* [CI] Enable iOS, macOS and 3DS tests by default

* [CI] Change epsilon-sdk tap url

* Revert "[CI] Change epsilon-sdk tap url"

This reverts commit 9516607aba.
2023-04-13 16:24:38 +02:00
Lisra-git
0916996121 [Bootloader] Enhance Global Stability 2023-04-08 14:25:31 +02:00
Wiwok
b4820d52e4 [README] Fix a bad string in French README (#317) 2023-03-19 10:31:27 +01:00
Yaya-Cout
a87a99af7a [bootloader] Mark Epsilon 20.4 as safe 2023-03-17 17:20:23 +01:00
Yaya-Cout
83d6d33edf [apps/math_toolbox] Move Matrix and Vectors to a submenu 2023-03-12 11:19:14 +01:00
Yaya-Cout
1067216d4f [bootloader] Mark Epsilon 20.3 as safe 2023-02-17 21:39:51 +01:00
Yaya-Cout
c0d998017d [apps/main] Add open app option 2023-02-17 19:32:50 +01:00
Yaya-Cout
a729ef2a4c [apps] Move Dimensions i18n out of calculation
This allow Escher to build successfully without calculation app
2023-02-17 19:32:16 +01:00
Yaya-Cout
b43d773051 [calculation/UnitList] Fix crash when pressing OK 2023-02-08 17:09:48 +01:00
Yaya-Cout
4acc79f1c7 [apps/on_boarding] Fix logo view crash when interrupted 2023-02-03 08:25:54 +01:00
Yaya-Cout
58a373e683 [apps/reader] Fix reader crash when opening bookmark
I just disabled color restoration, but I am still not understanding why it isn't working

Fix #307
2023-01-29 19:36:13 +01:00
Joe Crop
8041c7a9d0 Updated french translations after feedback 2023-01-21 21:12:46 -08:00
Yaya-Cout
c5960430a3 Merge pull request #313 from lolocomotive/simulator-fix
[Simulator] Fix keys not working and reduce log spam
2023-01-21 15:01:00 +01:00
lolocomotive
12d8eeeb2c [Simulator] Fix keys not working and reduce log spam 2023-01-21 14:39:57 +01:00
Yaya-Cout
224cec5efc [apps/settings] Remove rests of USB protection 2023-01-16 18:49:52 +01:00
Yaya-Cout
7af7b895f5 [i18n] Clean translations 2023-01-16 18:39:31 +01:00
Yaya-Cout
0e65c97774 [Simulator] Fix MicroPython in Web simulator and update to Emscripten 3.1.30 2023-01-14 19:52:30 +00:00
Loïc
72d10f8396 [Simulator] Don't resize canvas to 0x0 (#310)
* [Simulator] Don't resize canvas to 0x0

* [storage] Fix broken script saving/loading

* [Simulator] Don't resize canvas to 0x0

Co-authored-by: Yaya-Cout <yaya.cout@free.fr>
2023-01-05 17:33:53 +01:00
Yaya-Cout
7030c58c51 [storage] Fix broken script saving/loading 2023-01-05 17:18:11 +01:00
Loïc
1a681c7c75 Fix android simulator (#277)
* Fix android CI

* Set NDK path

* Reduced log spam

* Fixed NDK path

* Fixed NDK path

* Android NDK v21e

* Use debug signin config
if SIGNING_STORE_FILE is not defined
This allows the apk to be installed

* Fix OmegaActivity class name

* Fix formatting

Co-authored-by: Yaya-Cout <yaya.cout@free.fr>

Co-authored-by: Yaya-Cout <yaya.cout@free.fr>
2023-01-01 14:16:12 +01:00
Yaya-Cout
ed002ed14b [apps/atomic] Fix last commit (std::max error) 2023-01-01 11:59:36 +01:00
Yaya-Cout
2312147957 [apps/atomic] Use latest commit (redesign) 2022-12-29 12:38:44 +01:00
Joe Crop
d7f54ad644 removed shift functions with explicit number of bits 2022-12-26 22:01:11 -08:00
Yaya-Cout
1de090cea4 [apps/home] Quick select for apps using numbers (#306)
* [apps/home] Quick select for apps using numbers

* [apps/home] Fix build error
2022-12-09 17:42:44 +01:00
Joe Crop
81dc1bd806 moved logic toolbox to the bottom of the list 2022-12-06 11:16:04 -08:00
Joe Crop
fc95028b57 - Added clog2 function
- negative numbers can now be displayed in 2's compliment binary
2022-12-06 11:10:01 -08:00
Yaya-Cout
c9c868c32c [CI] Use latest version of ARM toolchain for bootloader 2022-12-06 17:14:27 +01:00
Yaya-Cout
8d6c7d1bff [CI] Build all bin checksums 2022-12-06 16:37:41 +01:00
Joe Crop
42d8fea8c6 logic toolbox with logic functions 2022-12-05 20:07:45 -08:00
Yaya-Cout
2a89c23e07 [CI] Rebuild checksums before uploading bootloader 2022-12-05 20:57:51 +01:00
Yaya-Cout
62d4d59d6b [CI] Fix bootloader upload 2022-12-05 20:44:54 +01:00
Yaya-Cout
1bf164e1e3 [CI] Add bootloader in bootloader binpack (#304)
* [CI] Add bootloader in bootloader binpack

* [CI] Second try to add bootloader in bootloader binpack
2022-12-03 18:53:22 +01:00
Yaya-Cout
851ec2ab69 [bootloader] Fix exam mode with Epsilon 19 and add support for Epsilon 20 (#302)
* [bootloader] Fix exam mode on Epsilon 19

* [bootloader] Fix comment indentation

* [bootloader] Restore comment indentation (even if GitHub tell that it isn't indented properly)

* [bootloader] Turn tabulations into spaces

* [bootloader] Mark Epsilon 19 as "safe to boot"

* [bootloader] Fix Epsilon 20 boot

* [bootloader] Chang version to 1.0.2
2022-12-03 18:14:43 +01:00
Yaya-Cout
08eb1aec99 [CI] Fix Web CI (#303) 2022-12-03 17:21:26 +01:00
devdl11
78b606e825 [bootloader] Fix e19 boot (#263) 2022-11-19 11:13:17 +01:00
fmOOmf
ea89bc9aa5 code comment
Co-authored-by: Yaya-Cout <yaya.cout@ik.me>
2022-10-27 11:26:01 +02:00
fmOOmf
56ce3b0f42 Review changes (indentation, spaces) 2022-10-26 22:10:15 +02:00
fmOOmf
57e4cbe402 Final Heading correction 2022-10-26 21:22:56 +02:00
fmOOmf
dfb5b90e55 Modif pour le circle avec angle négatif (modif for circle with negative angle) 2022-10-26 19:43:33 +02:00
Rathmox
1d00d7d9d3 Fix README powershell commands (#278) 2022-10-08 19:25:28 +02:00
Hug0
3a220c0507 Upsilon readme nix (#287) 2022-10-08 19:25:03 +02:00
Laury
1fbd5281a9 [escher] Fixed bugs in previous commit (XNT) 2022-07-07 12:37:55 +02:00
Laury
51a5f699c3 [escher] XNT button is now cyclic 2022-07-06 22:52:49 +02:00
Laury
77167d1706 [statistics] Added 3 new measurements 2022-07-04 11:12:19 +02:00
Yaya-Cout
a1e213ac91 [apps] Add Shift + Ans shortcut to go to the last application (#196) 2022-07-04 11:09:58 +02:00
Laury
d87c67d35b [kandinsky | code] Coding style improvement in the new font (part 1) 2022-07-01 21:11:45 +02:00
Oreig403
99b070a30d New font and italic in python keywords (#232) 2022-07-01 11:39:23 +02:00
Laury
2a234305f3 [reader] FIxed "syntax error" with colors when going backward 2022-06-27 13:00:30 +02:00
Laury
992fb5dc85 [escher] Fixed icon view 2022-06-27 11:44:53 +02:00
Laury
891afff4bb [code] Added ulab.utils in toolbox 2022-06-26 14:30:50 +02:00
Yaya-Cout
92c653f2f2 [python] Upgrade MicroPython to version 1.19.1, Ulab and add unit tests for Ulab (#259) 2022-06-26 13:03:22 +02:00
Laury
25d4793441 [poincare] Fixed tests 2022-06-25 23:35:38 +02:00
Laury
4893b73917 [test] Fixed tests compilation 2022-06-25 19:46:00 +02:00
Laury
0b2a581177 [escher] Rework of timers and bigger text in toolboxes 2022-06-25 19:46:00 +02:00
Laury
391fd5e243 [python/ion] Error if brightness isn't between 0 and 240 in set_brightness 2022-06-25 19:45:59 +02:00
fmOOmf
ba43135fcb [kandinsky/font] Fix replacement character 2022-06-25 12:32:06 +02:00
LeMoustachu
4d5b37fab1 Improvements to README.md and README.fr.md (#256)
* [README] clean fedora dependencies installation instruction

* [README] n0110 instructions clearification

* [README] add instruction for native simulator build

* Fix translation

Changed "native simulator" into "simulateur natif"

Co-authored-by: Yaya-Cout <yaya.cout@free.fr>

* [README] add automatic platform detection command to native simulator instructions

* [README.fr] fix translations

* Update README.fr.md

change "apps external" into "appllications externes"

Co-authored-by: Yaya-Cout <yaya.cout@free.fr>

* Update README.fr.md

Co-authored-by: Yaya-Cout <yaya.cout@free.fr>

Co-authored-by: Yaya-Cout <yaya.cout@free.fr>
2022-06-21 18:09:41 +02:00
Laury
e8ea693e5c [calculation] Dimension in additional output for values with units 2022-06-18 22:36:55 +02:00
Laury
125e1a8a82 [settings] Remove option to save cursor 2022-06-17 18:01:15 +02:00
Joachim LF
7dff05287d [calculation/additional_result] draw in trigonometric graph the tangent 2022-06-17 13:23:51 +02:00
Joachim LF
25cd0d44f3 [calculation/additional_outputs] Use input rather than output if possible, and open on tan 2022-06-17 13:09:45 +02:00
Mino1289
0751c88a2d [TexParser] Adding Sum, Product and Integral (#252) 2022-06-17 12:25:38 +02:00
Laury
d983797ac8 Revert "[storage] New attempt to save cursor position"
This reverts commit c826e556a1.
2022-06-17 12:12:39 +02:00
Yaya-Cout
1319ad2f42 [Make] Add shasum for bootloader binpack 2022-06-14 19:58:50 +02:00
Yaya-Cout
741a71554d [CI] Add bootloader upload to dev version on Firebase 2022-06-14 19:46:06 +02:00
fmOOmf
9588052d68 Correction de la gestion de la couleur marron Liseuse / Brown color processing in Reader (#251)
* Ajout de \binom pour afficher les coefficients binomiaux

* Correction in reader Brown color  processing
2022-06-12 18:24:55 +02:00
Lisra-git
35017ec167 Lock Hardware Test while Exam Mode enabled (#227) 2022-06-12 11:38:52 +02:00
Mino1289
3b12f29815 [apps/reader] Adding new symbols and functions in the TexParser (#237) 2022-06-12 11:37:17 +02:00
Rathmox
1f91a5f900 Fixing README Files (#241) 2022-06-12 11:36:03 +02:00
Laury
c826e556a1 [storage] New attempt to save cursor position 2022-06-10 16:16:16 +02:00
fmOOmf
1db74c78ab Ajout de \binom pour afficher les coefficients binomiaux (#250) 2022-06-09 17:10:07 +02:00
Yaya-Cout
71a8c20ee7 [bootloader] Fix minimum brightness when booting 2022-05-31 18:23:51 +02:00
Joachim Le Fournis
d8423fb4f1 [LD] Fixed warning about different array declaration (#242)
The size declared in toolbox_ion_keys.cpp for the modion_module_globals_table array was different that the defined array in micropython
2022-05-29 10:26:59 +02:00
Yaya-Cout
5444bdae99 [build] Disable telemetry on IOS 2022-05-27 16:56:27 +02:00
devdl11
952a83400a ld fix possibility 2022-05-27 10:02:59 +02:00
devdl11
8996f960dc Add specific header and extra version 2022-05-25 09:53:00 +02:00
Yaya-Cout
e4718fcb95 [apps/external] Add simulator support (#238) 2022-05-21 17:38:26 +02:00
Yaya-Cout
19de87f9b5 [CI] Fix metric workflow 2022-05-21 10:54:24 +02:00
Yaya-Cout
5f51ed0628 [README/CI] Fix README and CI (#235)
* [README] Fix readme

* [CI] Fix CI

* [CI] Fix bootloader
2022-05-20 19:31:21 +02:00
Yaya-Cout
e4f0762db3 [README/build] Add bootloader in README 2022-05-20 19:07:50 +02:00
devdl11
cbec2e5883 Update bootloader/interface/menus/upsilon_recovery.h
Co-authored-by: Yaya-Cout <yaya.cout@free.fr>
2022-05-20 18:00:00 +02:00
devdl11
1e0fa89efe Update bootloader/interface/menus/upsilon_recovery.cpp
Co-authored-by: Yaya-Cout <yaya.cout@free.fr>
2022-05-20 17:59:53 +02:00
devdl11
363ffbcaf8 Removing debug led 2022-05-20 11:43:40 +02:00
devdl11
48587c15d7 Review 2022-05-19 20:51:18 +02:00
devdl11
3eaa116ec6 Merge branch 'upsilon-dev' of https://github.com/UpsilonNumworks/Upsilon into upsilon-dev-v1.0.1.01fix_bis 2022-05-19 19:54:08 +02:00
Yaya-Cout
ab8b353c9c Change Upsilon version from 1.0.0 to 1.0.1-dev 2022-05-19 19:52:46 +02:00
devdl11
8e543f30c9 Magical Backup 2022-05-19 19:52:46 +02:00
Andrej
833bc4a120 [bootloader/menu] Fix typo (#231) 2022-05-19 19:52:46 +02:00
emanuel
a01f4bcf1a Update config.mak (#230)
[build/config.mak] Set OMEGA_VERSION to 2.0.2
2022-05-19 19:52:46 +02:00
Laury
3e42d4847a Revert "[storage] Possibility to store metadata with records (cursor in scripts)" 2022-05-19 19:52:45 +02:00
Yaya-Cout
2a6d110f2f Change Upsilon version from 1.0.0 to 1.0.1-dev 2022-05-18 13:02:41 +02:00
Andrej
2ee7b67af1 [bootloader/menu] Fix typo (#231) 2022-05-11 20:27:12 +02:00
emanuel
be3c8fce9c Update config.mak (#230)
[build/config.mak] Set OMEGA_VERSION to 2.0.2
2022-05-10 18:06:46 +02:00
Laury
ec36325799 Merge branch 'upsilon-dev' of https://github.com/UpsilonNumworks/Upsilon into upsilon-dev 2022-05-09 18:40:45 +02:00
Laury
36fa4a4152 Revert "[storage] Possibility to store metadata with records (cursor in scripts)" 2022-05-09 18:39:10 +02:00
iamlambda
6758a95292 misleading comment (#216) 2022-05-07 20:40:23 +02:00
LeMoustachu
5be8d6a1f5 [minor changes] Just Update issues badge to work with new repo URL (#222) 2022-05-07 20:39:53 +02:00
Laury
5220dda095 Merge remote-tracking branch 'origin/upsilon-dev' into upsilon-master 2022-05-05 18:02:51 +02:00
Yaya-Cout
7c51b1e55d [apps/code] Fix fr" typing in editor
Fix #217
2022-05-05 17:55:19 +02:00
Laury
7a2ee2bc56 [config] Set upsilon version to 1.0.0 2022-05-04 15:49:24 +02:00
Laury
9f6d52d9d5 [usb] Removing residues from the USB protection 2022-05-04 15:49:11 +02:00
Laury
efb32c9612 [bootloader] Fix "make binpack" in the CI 2022-05-03 18:41:39 +02:00
Laury
caf23dcbab [bootloader] Fix compilation to dfu file 2022-05-03 17:48:16 +02:00
Laury
6a894997fc [flasher] Fixed compilation 2022-05-03 16:34:22 +02:00
Laury
f348d9eb5d [bootloader] Fixed compilation 2022-05-03 16:34:07 +02:00
Laury
0e0dc4a9c2 Revert "[apps] Add Shift + Ans shortcut to go to the last application" 2022-05-02 18:55:46 +02:00
Laury
2be1a6e5a9 [usb] Changed link in descriptor 2022-05-02 17:01:20 +02:00
Laury
adab2c223b [reader] Improved previous position algorithm and fixed symbols 2022-05-01 21:02:07 +02:00
Laury
745099842a [poincare] Fixed two serious bugs in sequences simplification 2022-04-30 19:12:54 +02:00
Yaya-Cout
39f33347f9 Merge remote-tracking branch 'upsilon-yayacout/upsilon-dev-ci-bootloader-fix' into upsilon-master 2022-04-29 22:04:52 +02:00
Yaya-Cout
03ae762b4a [external] Updated for compatibility with KhiCAS 2022-04-29 22:00:12 +02:00
Laury
5b7bdc1ec1 Revert "[external] First attempt to merge Khi external API"
This reverts commit 38796253cb.
2022-04-28 21:33:01 +02:00
Laury
7d61e236df [bootloader] Small fixes 2022-04-28 21:32:42 +02:00
devdl11
7f8e6a6b87 Merged new bootloader
Co-authored-by: Yaya-Cout <yaya.cout@free.fr>
2022-04-27 21:02:04 +02:00
devdl11
9c69379096 fix 2022-04-27 20:37:39 +02:00
Yaya-Cout
aff5803ef3 [CI] Fix bootloader CI 2022-04-27 20:07:08 +02:00
devdl11
fd7bdc7345 Dumb error fix 2022-04-27 19:56:37 +02:00
Yaya-Cout
807945ad0f [CI] Fix bench.flash 2022-04-27 19:45:55 +02:00
devdl11
35f09ed389 Merge branch 'upsilon-new-bootloader' of https://github.com/devdl11/Upsilon into upsilon-new-bootloader 2022-04-27 19:25:03 +02:00
devdl11
c73b13bd41 Some code 2022-04-27 19:24:59 +02:00
devdl11
47558446c4 Update bootloader/interface/menus/dfu.h
Co-authored-by: Yaya-Cout <yaya.cout@free.fr>
2022-04-27 18:56:06 +02:00
devdl11
45b4dd337c Update bootloader/interface/static/messages.h
Co-authored-by: Yaya-Cout <yaya.cout@free.fr>
2022-04-27 15:46:31 +02:00
devdl11
0332f43c5c Reviews 2022-04-27 15:44:42 +02:00
Yaya-Cout
667bac136b Merge remote-tracking branch 'upsilon-yayacout/upsilon-dev-autocompletion-fix' into upsilon-master 2022-04-27 15:26:58 +02:00
Yaya-Cout
b15d49511d [apps/python] Use super implementation in the select sub menu function of the toolbox 2022-04-27 14:06:02 +02:00
devdl11
04ae526a39 Removing useless file 2022-04-26 18:10:34 +02:00
devdl11
0e49d23faa Apply suggestions from code review
Co-authored-by: Yaya-Cout <yaya.cout@free.fr>
2022-04-26 15:26:34 +02:00
Laury
595c69bfcf Merged upsilon-dev 2022-04-26 12:48:52 +02:00
devdl11
18ff283580 Boot fix 2022-04-25 19:52:58 +02:00
devdl11
42368ecd6e second patch 2022-04-25 18:40:55 +02:00
devdl11
27cf6a0615 Fix CLI bootloader 2022-04-25 18:35:16 +02:00
devdl11
5ed8aef907 Bootloader pre-release 2022-04-25 18:22:19 +02:00
Laury
3c53421ffa [poincare] Added simplification of nested radicals 2022-04-23 23:10:58 +02:00
Laury
d10d1cd65d [rpn] Updated submodule to fix dirty line 2022-04-17 21:57:47 +02:00
Laury
cec75bfaed [rpn] Updated submodules 2022-04-17 18:05:58 +02:00
Laury
77352e34b5 [storage] Possibility to store metadata with records (cursor in scripts) 2022-04-15 22:30:53 +02:00
Laury
38796253cb [external] First attempt to merge Khi external API 2022-04-15 22:30:35 +02:00
Yaya.Cout
4b7631e78a [apps/apps_container_storage.cpp] Add an assert 2022-04-15 22:19:32 +02:00
Yaya.Cout
c54a97a03d [apps/apps_container_storage.cpp] Add newline 2022-04-15 22:19:32 +02:00
Yaya.Cout
d42e4269a9 [apps] Add Shift + Ans shortcut to go to the last application 2022-04-15 22:19:32 +02:00
Laury
2bf6de5044 [reader] Fixed bug when a word is too big 2022-04-15 22:19:31 +02:00
Laury
22ba190542 [calculation] Fix bug in calculation store 2022-04-15 22:19:31 +02:00
Nithin
0e24823511 Fix Readme Links (#210) 2022-04-15 18:50:17 +02:00
Yaya.Cout
f174fbc3f5 [apps/code] Fix Key selector in auto completion
Scenario: Go in the Python editor and type "from ion import *",
          then type "K" and see what happens.
This fix UpsilonNumworks#198
2022-04-15 17:05:19 +02:00
Lauryy06
4ca7d9208c [escher] Changed PopUpTopMargin in metrics (#201) 2022-04-10 22:17:52 +02:00
LeMoustachu
2bfc243e5a update atomic submodule (#208) 2022-04-09 19:08:04 +02:00
devdl11
add333b920 [bootloade] Fix freezing 2022-04-09 11:08:02 +02:00
devdl11
eeff886cc1 [bootloader > menus] Improvement 2022-04-09 11:02:34 +02:00
devdl11
ff307b8df8 [bootloader > interfaces] Interface improvement 2022-04-08 23:44:24 +02:00
devdl11
21f08a2d06 [bootloader/interface] Yaya-cout commit 2022-04-08 18:53:26 +02:00
devdl11
c837709801 [flasher] Fix old dfu code 2022-04-08 18:40:08 +02:00
devdl11
a0caf67d7c [review] revert flasher code 2022-04-08 18:33:27 +02:00
devdl11
f4e84bc208 Update ion/src/device/n0110/internal_flash.ld
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:07:28 +02:00
devdl11
225b942989 Update ion/src/device/shared/usb/dfu.ld
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:07:11 +02:00
devdl11
3b955c2eb6 Update ion/src/device/n0110/drivers/board.cpp
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:06:59 +02:00
devdl11
0e46954f80 Update ion/src/device/shared/usb/dfu_interface.h
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:06:22 +02:00
devdl11
bf1d570623 Update ion/src/device/shared/usb/dfu_relocated.cpp
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:06:15 +02:00
devdl11
5f50f3fc9c Update ion/src/device/shared/usb/stack/device.cpp
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:06:07 +02:00
devdl11
4a830a0f30 Update ion/src/device/n0100/flash.ld
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:05:57 +02:00
devdl11
01c3f767e4 Update ion/src/device/bootloader/usb/Makefile
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:03:32 +02:00
devdl11
3c098b684b Update bootloader/usb_data.h
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:03:19 +02:00
devdl11
e886863230 Update bootloader/messages.h
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:03:11 +02:00
devdl11
7ce3aac2f6 Update bootloader/messages.h
Co-authored-by: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com>
2022-04-08 18:02:56 +02:00
devdl11
3c26035feb [Review] Class to namespace 2022-04-08 14:01:55 +02:00
devdl11
ff40b8b862 Merge branch 'upsilon-new-bootloader' of https://github.com/devdl11/Upsilon into upsilon-new-bootloader 2022-04-08 13:50:39 +02:00
devdl11
62e98107f7 [Reviews] Code correction and improvement 2022-04-08 13:49:44 +02:00
devdl11
7a6c211001 Update bootloader/itoa.cpp
Co-authored-by: Lauryy06 <80424145+Lauryy06@users.noreply.github.com>
2022-04-08 13:20:56 +02:00
devdl11
80f099c274 Update bootloader/usb_data.cpp
Co-authored-by: Lauryy06 <80424145+Lauryy06@users.noreply.github.com>
2022-04-08 13:17:43 +02:00
devdl11
d3754a931a Update bootloader/itoa.h
Co-authored-by: Lauryy06 <80424145+Lauryy06@users.noreply.github.com>
2022-04-08 13:17:27 +02:00
devdl11
3af3d70055 Update bootloader/itoa.cpp
Co-authored-by: Lauryy06 <80424145+Lauryy06@users.noreply.github.com>
2022-04-08 13:17:11 +02:00
devdl11
8db051474c Update bootloader/itoa.cpp
Co-authored-by: Lauryy06 <80424145+Lauryy06@users.noreply.github.com>
2022-04-08 13:17:04 +02:00
devdl11
3328bc28b9 Update bootloader/itoa.cpp
Co-authored-by: Lauryy06 <80424145+Lauryy06@users.noreply.github.com>
2022-04-08 13:16:52 +02:00
devdl11
c65b1c6d3c [Review] Review Update 2022-04-07 22:18:05 +02:00
devdl11
15801ae9e4 [DFU] Fix simulators 2022-04-07 20:07:03 +02:00
devdl11
3dfc8d749c [bootloader/storage] new bootloader and fix python issue 2022-04-07 19:56:53 +02:00
lolocomotive
9f7aba4593 Run upload to firebase only when on UpsilonNumworks/Upsilon on upsilon-dev (#197) 2022-04-06 21:43:46 +02:00
Yaya.Cout
5365718761 [bootloader] Fix building with no computer and cable icons 2022-04-05 18:23:02 +02:00
Yaya.Cout
c0c1615f14 [apps] Swap graph and rpn apps
Close #195
2022-04-03 09:56:07 +02:00
Laury
a770ee919b [code] End of revert #113 2022-03-31 22:23:21 +02:00
Laury
7e64124ddc Revert #113 because of incompatibility with the workshop 2022-03-31 22:19:54 +02:00
Andrej
e2598031c8 [escher] Changed font in Toolbox expressions to LargeFont for better readability and aesthetics (#190) 2022-03-31 16:10:05 +02:00
Yaya.Cout
2ebc1bc22f [apps] Add Shift + EE to go to the settings
Before, EE go to the settings, because ShiftEE event wasn't correctly bound :
It was bound to a simple press of the key, and not to a Shift press.
This commit keep this behavior, but add the correct binding (Shift + EE).

This fix #194.
2022-03-30 19:25:43 +02:00
Yaya.Cout
202c273c67 [apps/graph] Separate Cyan from Blue (fix #192)
This separate the Cyan colour's name from the blue, before this commit, it was the same text
2022-03-30 08:18:18 +02:00
Mino1289
45229b80cd [python] Support more operators overload (classes) (#188) 2022-03-28 20:59:21 +02:00
Laury
b675a78a87 [ion] Part of the fix for CI 2022-03-28 19:25:29 +02:00
Laury
15f0833f3b [ion] Fix compilation 2022-03-28 18:23:22 +02:00
Laury
e40d63a6ff Merge Upsilon-dev 2022-03-23 22:02:27 +01:00
Laury
323eba63e1 Merge with Omega-dev 2022-03-23 21:51:06 +01:00
Yaya-Cout
3b293c822a [apps/graph] Added a color menu in graph and list (#189)
* Revert "[github/workflows] Update Metrics to remove NumWorksBot"

This reverts commit 110f333122.

* Added a color menu in graph and list

* Fixed color select display issue and build issue

* Changed color_cell to a circle

* Revert "Changed color_cell to a circle"

This reverts commit 28dddb42af.

* Color_cell with mask

* Fixed build issue

* Color selection : Added right handle and color name display in menu

* Fixed constexpr static colorMask

* Changed font in color_parameter_controller

* Fix building without debug

* Re-Fix building without debug

* Update colors

Co-authored-by: Hugo Saint-Vignes <hugo.saint-vignes@numworks.com>
Co-authored-by: Joachim LF <joachimlf@pm.me>
2022-03-23 08:36:23 +01:00
Yaya-Cout
8ac969d772 [Feature] Backlight settings (#137)
* Added backlight settings

* Changed location of the brightness setting

* Fix row size of brightness settings

* [apps/settings/brightness] Update translations

* Fix dimmer

* Update translations

* [apps/settings] Add dimmer duration setting

* [apps/settings] Ensure of the brightness level is greater than the dimmed brightness level

* Make transition smooth

* Removed transition time setting
I personally think that this setting is completely useless except if you absolutely want a transition that is not smooth, which is weird.

* Moved everything related to brightness in one submenu

* Some refactoring

* Update defaults

* Removed unnecessary translation

* [apps/settings] Fix Shift + Minus/Plus in settings

* Apply suggestions from code review

* [apps/shared] Remove a think that I don't know what it is

* Apply review suggestions

Co-authored-by: Joachim LF <joachimlf@pm.me>
Co-authored-by: lolocomotive <lolocomotive181@gmail.com>
2022-03-22 17:59:52 +01:00
Yaya-Cout
865bacf89a [build/utilities] Add translations clean script (#179) 2022-03-20 16:10:54 +01:00
Assim ZEMOUCHI
841ac7d5f4 [ion] Fix win11 build for n0110 (#182) (#183) 2022-03-20 16:09:02 +01:00
Yaya-Cout
c92c4d8383 [apps/reader] Add slanted arrows, \in, \cdot, \cdots and \ldots (#184) 2022-03-20 16:08:39 +01:00
Laury
97a168052b [code] Improved code quality in gutter view resize 2022-03-19 23:39:44 +01:00
devdl11
42343d562c [ code ] Gutter improvement (#71) (#168) 2022-03-19 19:01:50 +01:00
Laury
3740a93a9f [ion] Fixed CI 2022-03-19 17:59:07 +01:00
Laury
6dc31401fe [bootloader] Compatibility with Omega 2.0 2022-03-17 20:05:20 +01:00
Maxime FRIESS
8c3378a723 [ion/bootloader] Fixed wrong trampoline call. 2022-03-16 00:06:24 +01:00
Maxime FRIESS
126bdd68bb Merge pull request #2 from quentinguidee/fix-assert-external-flash
[ion/external_flash] Fix SectorAtAddress assert()
2022-03-15 23:59:42 +01:00
Quentin Guidée
f1c24db90a [ion/external_flash] Fix SectorAtAddress assert() 2022-03-15 22:41:51 +01:00
Maxime FRIESS
fd4a2205f3 Merge pull request #1 from quentinguidee/fix-macos-simulator
[Simulator] Fix macOS compilation
2022-03-15 22:36:08 +01:00
Quentin Guidée
fc252672cc [Simulator] Fix macOS compilation 2022-03-15 22:14:08 +01:00
Laury
1c918f549c [ion] Try a fix to make compilation work 2022-03-13 21:43:14 +01:00
Laury
72a25ec26d [ion] Rework of storage trash 2022-03-13 21:32:35 +01:00
M4x1m3
bdfae184e9 [config.mak] Omega 2.0.0 2022-03-10 19:34:49 +01:00
M4x1m3
23936a0c63 [themes] Fixed building bootloader 2022-03-10 19:34:49 +01:00
M4x1m3
209428ca9d [bootloader] Made bootloader Upsilon-aware 2022-03-10 19:34:49 +01:00
M4x1m3
370eb14a04 [build] Fixed wrong model comparaison 2022-03-10 19:34:48 +01:00
lolocomotive
bf8f8bcb27 Fix web simulator 2022-03-10 19:34:48 +01:00
M4x1m3
fc3941511f [build] Fixed bootloader build system 2022-03-10 19:34:48 +01:00
M4x1m3
9fda743de9 [build/bootloader] Rewrote binpack 2022-03-10 19:34:48 +01:00
M4x1m3
74ef528845 [build] Added "bootloader" target 2022-03-10 19:34:48 +01:00
M4x1m3
7a2721c979 [bootloader] Allow quitting the DFU stack 2022-03-10 19:34:48 +01:00
M4x1m3
227ca616ca [bootloader] Boot other slot if a slot is invalid 2022-03-10 19:34:48 +01:00
M4x1m3
1c04949336 [bootloader] Added custom trampolines 2022-03-10 19:34:48 +01:00
M4x1m3
93099ad808 [bootloader] Expose ExternalFlash instead of Flash 2022-03-10 19:34:47 +01:00
M4x1m3
88b4e904c0 [ion/external_flash] Take absolute address for WriteMemory 2022-03-10 19:34:47 +01:00
M4x1m3
dee783065b [bootloader] Use custom USB descriptor 2022-03-10 19:34:47 +01:00
M4x1m3
5a7b076ebe [bootloader] Added dual boot 2022-03-10 19:34:47 +01:00
M4x1m3
85ef57f7ed [bootloader] Added userland header, rewrote lernel header 2022-03-10 19:34:47 +01:00
M4x1m3
63c2b99260 [ion/simulator] Fixed simulator 2022-03-10 19:34:47 +01:00
M4x1m3
377f4eee0c [ci] Build bootloader 2022-03-10 19:34:47 +01:00
M4x1m3
a63cbcf0c2 [bootloader] Make work with Numworks workshop 2022-03-10 19:34:47 +01:00
M4x1m3
f2c17121d2 [bootloader] Added trampolines 2022-03-10 19:34:46 +01:00
M4x1m3
d16808183b [bootloader] MPU config 2022-03-10 19:34:46 +01:00
M4x1m3
6eabe9acae [ion/n0110] Fixed invalid assert in external flash driver 2022-03-10 19:34:46 +01:00
M4x1m3
e1dcbad18a [bootloader] Run usb stack on Reset+4 2022-03-10 19:34:46 +01:00
M4x1m3
4fe84a4959 [bootloader] Added slot definition 2022-03-10 19:34:46 +01:00
M4x1m3
272797f31f [bootloader] Added bootloader 2022-03-10 19:34:46 +01:00
M4x1m3
c635f4e2b9 [ci] Add building Omega for bootloader 2022-03-10 19:34:46 +01:00
M4x1m3
c8ba2fd268 [build/bootloader] Allow building slot A and B 2022-03-10 19:34:46 +01:00
M4x1m3
3a391261c7 [ion/bootloader/usb] Removed internal flash from descriptior 2022-03-10 19:34:45 +01:00
M4x1m3
2da1610b27 [build/bootloader] Include extrnal 2022-03-10 19:34:45 +01:00
M4x1m3
5e130cc4f2 [ion/bootloader] Made suspend work 2022-03-10 19:34:45 +01:00
M4x1m3
2b5a773993 [ion/bootloader] Made exam mode work 2022-03-10 19:34:39 +01:00
BAALBAKYA
19e5562228 2 corrections of bugs about the battery level in the settings (#148)
* added battery level handler for simulator

* added battery level > 100% when charging

* corrected version

* laury version but with float type

* Update apps/settings/sub_menu/about_controller.cpp

* Update apps/settings/sub_menu/about_controller.cpp

Co-authored-by: = <=>
Co-authored-by: Lauryy06 <80424145+Lauryy06@users.noreply.github.com>
2022-03-03 17:16:24 +01:00
Yaya.Cout
9edf026110 [python] Fix brackets in get_keys() 2022-03-01 18:59:22 +01:00
M4x1m3
ffb4c39e04 [ion] Added bootloader device 2022-02-27 00:32:24 +01:00
M4x1m3
61673cd1b5 [apps] Reduced heap to make room for SVC table 2022-02-25 15:07:47 +01:00
Laury
f95f9ebb2d [poincare] Better simplification of sequences 2022-02-24 18:48:10 +01:00
Laury
23af100ed5 [poincare] Allow replacement of sequences by their definition if rank is an integer 2022-02-24 18:05:30 +01:00
Laury
c7516f1464 [settings] Fixed name of contributors 2022-02-22 20:44:16 +01:00
Laury
23a94b7f50 [calculation] Simplify angles in additional outputs and fix an assert in calculation store 2022-02-21 17:30:27 +01:00
Laury
af5f9ea578 [ion/storage] Added the "ctrl-z" system everywhere 2022-02-19 12:09:02 +01:00
Laury
f3d632c462 [apps/calculation] Add a "ctrl-z" system 2022-02-15 22:24:50 +01:00
Laury
893a2a550d [reader] Fixed a bug in list of books 2022-02-14 20:52:33 +01:00
Laury
2443fa7d57 Merge branch 'upsilon-dev' of https://github.com/UpsilonNumworks/Upsilon into upsilon-dev 2022-02-11 19:52:34 +01:00
Yaya-Cout
4f0f41be56 [python] Add FStrings support (#155) 2022-02-09 22:21:07 +01:00
Yaya-Cout
5eb0598107 [apps/code] Add documentation on math.factorial (#146) 2022-02-06 19:06:48 +01:00
LeMoustachu
43b56f3a89 Update doc titlebar to match upsilon color. (#145) 2022-02-05 19:01:47 +01:00
Laury
034fc65bc2 [settings] Updated contributors ! 2022-02-05 19:00:33 +01:00
LeMoustachu
9ab3e6c715 remove white reader icon background in omega_dark (#144) 2022-02-05 13:49:47 +01:00
Jules
d8f93709b8 Update README.fr.md (#142) 2022-02-04 13:14:32 +01:00
Laury
708070c284 [calculation] Fix (again) a bug in second degree additional output 2022-02-02 23:16:52 +01:00
Laury
9632b59b67 [reader] Separated .urt and .txt files 2022-02-02 23:16:52 +01:00
LeMoustachu
a0afbe9916 Update building docs and french readme (#136) 2022-02-02 22:19:36 +01:00
Yaya-Cout
100917f29f [build] Add auto translate script (#140) 2022-02-02 22:18:45 +01:00
Yaya-Cout
814e2dee06 [python] Enable math.factorial (#141) 2022-02-02 22:18:04 +01:00
lolocomotive
1a546e011b Upload artifacts to google cloud (#138) 2022-02-01 19:43:46 +01:00
Yaya-Cout
1faac23ee8 [apps/settings] Fix assert in about submenu when username enabled (#134) 2022-01-25 20:17:07 +01:00
Yaya-Cout
38614a849f [apps/python] Add set_brightness and get_brightness in Ion module (#132) 2022-01-25 18:58:25 +01:00
Yaya-Cout
24205a7e03 Fix CI and replacement character (#133) 2022-01-24 18:22:07 +01:00
Yaya-Cout
f4ce415e32 [apps/code] Fix multiplication in Python app on simulator (#126) 2022-01-21 16:51:58 +01:00
Yaya-Cout
169fb7404e Fix spelling (#128)
* Fix spelling in .cpp files

* Fix spelling in all files
2022-01-20 17:21:35 +01:00
Laury
e575ffc7ce [apps/code] Shift + OK don't quit toolbox 2022-01-15 21:33:32 +01:00
Laury
f591816122 [apps/functions] Save if user want display derivative even when quitting the app 2022-01-15 12:40:06 +01:00
Laury
cbbe7ef6ac [poincare] Fix bug in equal simplifcation 2022-01-15 11:07:06 +01:00
Yaya-Cout
f862cb023a [apps/code] Add a setting for cursor saving (#125) 2022-01-14 13:42:30 +01:00
Laury
f296778014 [python] Moved get_keys to ion module 2022-01-14 13:36:11 +01:00
Laury
16eaab3b52 [apps/calculation] Make the second_degree_controller works 2022-01-13 18:57:34 +01:00
Laury
77707cd930 [kandinsky] Fix bugs in fill_polygon and removed the limit of 32 points 2022-01-13 17:23:25 +01:00
apoleon33
a3e2c9732f fix link to the discord (#122) 2022-01-12 22:25:26 +01:00
Overengined
98c919db88 added mention of the installer in the readme (#119) 2022-01-10 22:20:30 +01:00
Yaya-Cout
8126e0da7e Fix cursor storage (#120) 2022-01-10 20:53:38 +01:00
Laury
685e73c52d [reader] Make reader works ! 2022-01-09 21:47:53 +01:00
Laury
64a90422c4 [settings] Removed auto usb reactivation 2022-01-09 21:47:53 +01:00
Laury
fea588bd9d [escher/timer] Little code quality improvement 2022-01-09 21:47:53 +01:00
Laury
9595ed1570 [calculation] Fix a bug in second degree controller 2022-01-09 21:47:53 +01:00
Laury
4f63100195 [theme] Added reader icons 2022-01-09 21:47:52 +01:00
Laury
ed06b4e48b [python/ulab] Updated ulab 2022-01-09 21:47:52 +01:00
Laury
d5dbb8df6f [reader] Make fonts better 2022-01-09 21:47:51 +01:00
Mino1289
fdef2b5d6e Merge branch 'upsilon-dev-latex' 2022-01-09 21:47:51 +01:00
Laury
7fc28f8b72 [reader] Added detection of rich text files (.urt) TODO: parse differently this files 2022-01-09 21:47:51 +01:00
lolocomotive
2248e415c4 Separate Upsilon and Omega versions (#112) 2022-01-04 20:37:46 +01:00
lolocomotive
1da537479f Fix CI (#115) 2021-12-28 21:51:52 +01:00
devdl11
0860e48cb6 For those who likes to code ❤ (#113) 2021-12-28 15:13:01 +01:00
Yaya-Cout
70b162e63b Fix web simulator and binpack build (#114) 2021-12-28 15:12:13 +01:00
Joachim Le Fournis
398e974ccd Fix ODR warnings (#107) 2021-12-22 17:40:28 +01:00
Yaya-Cout
d57e19ae70 Add natural dimer (#106) 2021-12-18 14:34:35 +01:00
Mino1289
87a5dc354d [apps/calculation/additional_output] Adding parenthesis. (#97) 2021-12-17 22:17:21 +01:00
Yaya-Cout
cd3f5225bb Various fixes (#102) 2021-12-17 19:12:24 +01:00
Lauryy06
139ef4a052 Merge pull request #104 from lemoustachu/upsilon-dev 2021-12-17 18:58:47 +01:00
Lauryy06
66afb977db Merge pull request #103 from lolocomotive/patch-2 2021-12-17 18:57:22 +01:00
Lauryy06
cb9dc38fa9 Merge pull request #101 from Yaya-Cout/mpy-update 2021-12-17 18:43:53 +01:00
LeMoustachu
67e42aaac3 Readme update for wsl usb support 2021-12-17 17:54:44 +01:00
lolocomotive
f1be48bdb1 Use a fallback theme
This allows themes to be incomplete (with missing values), which leads to following benefits:
- Older themes that have not been updated to have the latest colors will not result in compilation errors
- If you only want to change one single color you don't have to copy the whole json file which makes it much more readable
2021-12-15 23:38:54 +01:00
Yaya.Cout
ed5cff15c6 Fix sys in Python toolbox 2021-12-15 18:35:41 +01:00
Lauryy06
963647d59f Merge pull request #100 from Yaya-Cout/mpy-update
MicroPython update
2021-12-15 14:36:46 +01:00
Yaya.Cout
a14f2015cf Remove sys module 2021-12-15 14:31:07 +01:00
Yaya.Cout
dbbf27e59b Fix sys module 2021-12-15 13:40:13 +01:00
ArtichautCosmique
65b3a2857f [ion/simulator/assets] New background.jpg (#99) 2021-12-15 13:39:51 +01:00
devdl11
dd48235721 USB Protection correction (#90) 2021-12-14 21:51:53 +01:00
Yaya.Cout
46041e8e9a Fix Matplotlib 2021-12-14 19:06:50 +01:00
Yaya.Cout
38faecda29 Update MicroPython from 1.12 to 1.17 2021-12-14 18:18:45 +01:00
ArtichautCosmique
0bd30ed2e6 [ion/simulator/assets] New icons Upsilon flavored (#98) 2021-12-13 19:37:12 +01:00
Laury
5cbce3c116 [calculation] Fix a bug in second degree controller 2021-12-09 19:05:42 +01:00
ArtichautCosmique
665de51bae [toolbar] Fix battery icon width when "half full battery" (#93) 2021-12-08 22:12:52 +01:00
apoleon33
47e3036afd [readme] changed link to the discord server (#88)
in the LISEZ_MOI.md
2021-11-29 20:27:29 +01:00
Yaya-Cout
1df3ef87e6 [apps/settings] Fix voltage in settings (#86)
* [apps/settings] Fix voltage in settings

* [apps/settings] Fix batteryLevel size
2021-11-28 19:07:48 +01:00
Laury
4222137549 [apps/code] Improve code style in syntax highlighting setting 2021-11-27 13:42:47 +01:00
Yaya-Cout
806b11b589 [apps/code] Add a setting for syntax highlighting (#85) 2021-11-27 12:34:09 +01:00
Laury
fb4b2ffdfa [usb | recovery] Make the code works 2021-11-26 23:41:53 +01:00
Laury
d2ec87d9fd Merge branch 'upsilon-dev-usb-protection' into upsilon-dev 2021-11-21 21:53:53 +01:00
Laury
6b12d1aebf [settings] Translations and bug fixed 2021-11-21 21:53:33 +01:00
Laury
9afb42716d [usb | recovery] Improve code quality 2021-11-21 21:48:51 +01:00
Thibaut
2d4c0f18d0 Update of a name in the list of contributors (#83) 2021-11-18 19:24:51 +01:00
lolocomotive
918c9249db Partly fix #66 (#82)
Removed the double V appearing sometimes
2021-11-17 12:19:44 +01:00
Quentin Guidée
cf33f84106 [config.mak] Omega 1.23.0 2021-11-11 22:13:07 +01:00
ArtichautCosmique
df7b97bb87 [toolbar] Pimp my battery (#80) 2021-11-11 18:48:01 +01:00
devdl11
e8a1bc6149 Creation of a protection system against unintentional updates to Epsilon 16 (foundation) + Recovery Improvement (#37) 2021-11-11 18:20:16 +01:00
Lauryy06
b304a2ff7d [github] Update bug_report.md 2021-11-11 17:47:12 +01:00
Mino1289
50ee8021f3 [apps/settings] Fixing newline with Flag checking (#77) 2021-11-09 19:28:45 +01:00
lolocomotive
ed7e0bd915 Show battery percentage in about menu (#69) 2021-11-05 13:46:42 +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
1170 changed files with 49384 additions and 12780 deletions

View File

@@ -1,6 +1,6 @@
--- ---
name: Bug report 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: '' title: ''
labels: 'Status: Triage, Type: Bug' labels: 'Status: Triage, Type: Bug'
assignees: '' assignees: ''
@@ -23,5 +23,7 @@ A clear and concise description of what you expected to happen.
**Screenshots** **Screenshots**
If applicable, add screenshots to help explain your problem. If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):** **Device (please complete the following information):**
- Omega Version: [go to settings > about > Omega Version and type the version here] - The device on which you're running Upsilon (computer, n0110, n0100, etc...)
- Upsilon Version: [go to settings > about > Upsilon Version and type the version here]
- Upsilon commit: [settings > about > click one time on epsilon version]

View File

@@ -1,6 +1,6 @@
--- ---
name: Feature request name: Feature request
about: Suggest an idea for Omega about: Suggest an idea for Upsilon
title: '' title: ''
labels: 'Status: Triage, Type: Feature' labels: 'Status: Triage, Type: Feature'
assignees: '' 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 name: Problems during installation
about: Need help to install Omega? about: Need help to install Upsilon?
title: '' title: ''
labels: 'Status: Triage, Type: Installation issue' labels: 'Status: Triage, Type: Installation issue'
assignees: '' assignees: ''
@@ -16,4 +16,4 @@ Copy/paste the logs here (If you have some)
``` ```
**Environment** **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

@@ -1,12 +0,0 @@
name: Docker Image CI
on: [pull_request, push]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Build the Docker image
run: docker build . --file docker/Dockerfile --tag omega:$(date +%s)

View File

@@ -8,115 +8,359 @@ on:
triggerIos: triggerIos:
description: 'Run iOS tests' description: 'Run iOS tests'
required: true required: true
default: 'no' default: 'yes'
triggerMacos: triggerMacos:
description: 'Run macOS tests' description: 'Run macOS tests'
required: true required: true
default: 'no' default: 'yes'
trigger3DS: trigger3DS:
description: 'Run 3DS tests' description: 'Run 3DS tests'
required: true required: true
default: 'yes'
triggerFxcg:
description: 'Run fxcg tests'
required: true
default: 'no' default: 'no'
jobs: jobs:
nintendo_3ds: fxcg: # fxcg build is broken for now, disabling it for now to avoid noise
if: github.event.inputs.trigger3DS == 'yes' if: github.event.inputs.triggerFxcg == 'yes'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- run: wget https://github.com/devkitPro/pacman/releases/download/v1.0.2/devkitpro-pacman.amd64.deb -O /tmp/devkitpro-pacman.deb - uses: actions/checkout@v5
- run: yes | sudo dpkg -i /tmp/devkitpro-pacman.deb with:
- run: yes | sudo dkp-pacman -Syu --needed devkitARM 3dstools libctru submodules: 'recursive'
- run: echo ::set-env name=DEVKITPRO::/opt/devkitpro - name: Install dependencies
- run: echo ::set-env name=DEVKITARM::/opt/devkitpro/devkitARM run: |
- run: echo ::set-env name=PATH::$DEVKITPRO/tools/bin:$DEVKITARM/bin:$PATH sudo apt-get update
sudo apt-get install build-essential cmake libfreetype-dev -y
- uses: actions/checkout@v1 - name: Get latest gint commit hash
run: |
LATEST_COMMIT_HASH=$(curl --silent https://git.planet-casio.com/api/v1/repos/Lephenixnoir/gint/branches/master | jq -r .commit.id)
echo "Latest commit hash is: $LATEST_COMMIT_HASH"
echo "LATEST_COMMIT_HASH=$LATEST_COMMIT_HASH" >> $GITHUB_OUTPUT
id: get-latest-commit-hash
- name: Cache gint/fxsdk installation
id: cache-gint
uses: actions/cache@v4
with:
path: |
~/.local/*/*
!~/.local/share/containers
key: ${{ runner.os }}-gint-${{ steps.get-latest-commit-hash.outputs.LATEST_COMMIT_HASH }}
- name: Install gint/fxsdk
if: steps.cache-gint.outputs.cache-hit != 'true'
env:
URL: "https://git.planet-casio.com/Lephenixnoir/GiteaPC/archive/master.tar.gz"
run: |
export PATH="~/.local/bin:$PATH"
cd "$(mktemp -d)"
curl "$URL" -o giteapc-master.tar.gz
tar -xzf giteapc-master.tar.gz
cd giteapc
python3 giteapc.py install Lephenixnoir/GiteaPC -y
sudo apt-get install python3-pil libusb-1.0-0-dev libudev-dev libsdl2-dev libpng-dev libudisks2-dev libglib2.0-dev libmpfr-dev libmpc-dev libppl-dev -y
giteapc install Lephenixnoir/fxsdk:noudisks2 Lephenixnoir/sh-elf-binutils Lephenixnoir/sh-elf-gcc -y
giteapc install Lephenixnoir/OpenLibm Vhex-Kernel-Core/fxlibc Lephenixnoir/sh-elf-gcc -y
giteapc install Lephenixnoir/gint -y
- name: Add fxsdk to PATH
run: echo "~/.local/bin" >> $GITHUB_PATH
- run: make -j2 PLATFORM=simulator TARGET=fxcg
- id: 'auth'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/auth@v0'
with:
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- id: 'upload-directory'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/upload-cloud-storage@v0'
with:
path: 'output/release/simulator/fxcg/epsilon.g3a'
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
parent: false
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/simulator/fxcg/epsilon.g3a binfiles/binaries/dev/simulator
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
- uses: actions/upload-artifact@v4
with:
name: epsilon.g3a
path: output/release/simulator/fxcg/epsilon.g3a
nintendo_3ds:
if: github.event.inputs.trigger3DS == 'yes' || github.event.inputs.trigger3DS == ''
runs-on: ubuntu-latest
container: devkitpro/devkitarm:latest
steps:
- uses: actions/checkout@v5
with: with:
submodules: true submodules: true
- run: sudo apt-get update
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config -y
- run: yes | sudo dkp-pacman -S --needed devkitARM 3dstools libctru
- run: wget https://github.com/3DSGuy/Project_CTR/releases/download/makerom-v0.18.3/makerom-v0.18.3-ubuntu_x86_64.zip
- run: unzip makerom-v0.18.3-ubuntu_x86_64.zip
- run: rm makerom-v0.18.3-ubuntu_x86_64.zip
- run: chmod +x ./makerom
- run: echo "PATH=.:$PATH" >> $GITHUB_ENV
- run: make -j2 PLATFORM=simulator TARGET=3ds - run: make -j2 PLATFORM=simulator TARGET=3ds
- run: make -j2 PLATFORM=simulator TARGET=3ds epsilon.cia - run: make -j2 PLATFORM=simulator TARGET=3ds epsilon.cia
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@v4
with: with:
name: epsilon-3ds.3dsx name: epsilon-3ds.3dsx
path: output/release/simulator/3ds/epsilon.3dsx path: output/release/simulator/3ds/epsilon.3dsx
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@v4
with: with:
name: epsilon-3ds.cia name: epsilon-3ds.cia
path: output/release/simulator/3ds/epsilon.cia path: output/release/simulator/3ds/epsilon.cia
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/simulator/3ds/epsilon.3dsx output/release/simulator/3ds/epsilon.cia binfiles/binaries/dev/simulator
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
android: android:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v5
with: with:
submodules: 'recursive' submodules: 'recursive'
- run: make -j2 PLATFORM=simulator TARGET=android - run: |
- uses: actions/upload-artifact@master sudo apt-get update
sudo apt-get install imagemagick libfreetype-dev libpng-dev
- name: Set up JDK 25
uses: actions/setup-java@v5
with:
java-version: '25'
distribution: 'temurin'
- run: wget -nv https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip
- run: unzip -q android-ndk-r21e-linux-x86_64.zip
- run: make -j2 PLATFORM=simulator TARGET=android NDK_PATH=./android-ndk-r21e
- id: 'auth'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/auth@v0'
with:
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- id: 'upload-file'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/upload-cloud-storage@v0'
with:
path: 'output/release/simulator/android/epsilon.apk'
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
parent: false
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/simulator/android/epsilon.apk binfiles/binaries/dev/simulator
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
- uses: actions/upload-artifact@v4
with: with:
name: epsilon-android.apk name: epsilon-android.apk
path: output/release/simulator/android/epsilon.apk path: output/release/simulator/android/epsilon.apk
n0100: n0100:
runs-on: ubuntu-latest runs-on: ubuntu-24.04-arm
steps: steps:
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config - run: |
- uses: numworks/setup-arm-toolchain@2020-q2 sudo apt-get update
- uses: actions/checkout@v2 sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
- uses: actions/checkout@v5
with: with:
submodules: 'recursive' submodules: 'recursive'
- run: mkdir final-output - run: mkdir final-output
- run: make -j2 MODEL=n0100 EPSILON_I18N=en output/release/device/n0100/epsilon.onboarding.two_binaries - run: make -j2 MODEL=n0100 EPSILON_I18N=en output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.en.bin - run: make -j2 MODEL=n0100 EPSILON_I18N=en output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.en.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp - run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
# We need to duplicate make to work around i18n generator race condition in Makefile leading to inconsistent incremental rebuilds
- run: make -j2 MODEL=n0100 EPSILON_I18N=fr output/release/device/n0100/epsilon.onboarding.two_binaries - run: make -j2 MODEL=n0100 EPSILON_I18N=fr output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.fr.bin - run: make -j2 MODEL=n0100 EPSILON_I18N=fr output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.fr.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp - run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=nl output/release/device/n0100/epsilon.onboarding.two_binaries - run: make -j2 MODEL=n0100 EPSILON_I18N=nl output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.nl.bin - run: make -j2 MODEL=n0100 EPSILON_I18N=nl output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.nl.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp - run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=pt output/release/device/n0100/epsilon.onboarding.two_binaries - run: make -j2 MODEL=n0100 EPSILON_I18N=pt output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.pt.bin - run: make -j2 MODEL=n0100 EPSILON_I18N=pt output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.pt.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp - run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=it output/release/device/n0100/epsilon.onboarding.two_binaries - run: make -j2 MODEL=n0100 EPSILON_I18N=it output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.it.bin - run: make -j2 MODEL=n0100 EPSILON_I18N=it output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.it.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp - run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=de output/release/device/n0100/epsilon.onboarding.two_binaries - run: make -j2 MODEL=n0100 EPSILON_I18N=de output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.de.bin - run: make -j2 MODEL=n0100 EPSILON_I18N=de output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.de.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp - run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=es output/release/device/n0100/epsilon.onboarding.two_binaries - run: make -j2 MODEL=n0100 EPSILON_I18N=es output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.es.bin - run: make -j2 MODEL=n0100 EPSILON_I18N=es output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.es.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp - run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=hu output/release/device/n0100/epsilon.onboarding.two_binaries - run: make -j2 MODEL=n0100 EPSILON_I18N=hu output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.hu.bin - run: make -j2 MODEL=n0100 EPSILON_I18N=hu output/release/device/n0100/epsilon.onboarding.two_binaries
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.hu.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp - run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 output/release/device/n0100/flasher.light.bin - run: make -j2 MODEL=n0100 output/release/device/n0100/flasher.light.bin
- run: mv output/release/device/n0100/flasher.light.bin final-output/flasher.light.bin - run: mv output/release/device/n0100/flasher.light.bin final-output/flasher.light.bin
- run: make -j2 MODEL=n0100 output/release/device/n0100/flasher.verbose.bin
- run: mv output/release/device/n0100/flasher.verbose.bin final-output/flasher.verbose.bin
- run: find final-output/ -type f -exec bash -c "shasum -a 256 -b {} > {}.sha256" \; - run: find final-output/ -type f -exec bash -c "shasum -a 256 -b {} > {}.sha256" \;
- run: tar cvfz binpack-n0100.tgz final-output/* - run: tar cvfz binpack-n0100.tgz final-output/*
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@v4
with: with:
name: epsilon-binpack-n0100.tgz name: epsilon-binpack-n0100.tgz
path: binpack-n0100.tgz path: binpack-n0100.tgz
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r final-output/* binfiles/binaries/dev/n100
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
n0110: n0110:
runs-on: ubuntu-latest runs-on: ubuntu-24.04-arm
steps: steps:
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config - run: |
- uses: numworks/setup-arm-toolchain@2020-q2 sudo apt-get update
- uses: actions/checkout@v2 sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
- uses: actions/checkout@v5
with: with:
submodules: 'recursive' submodules: 'recursive'
- run: make -j2 epsilon.dfu - run: make -j2 MODEL=n0110 epsilon.dfu
- run: make -j2 epsilon.onboarding.dfu - run: make -j2 MODEL=n0110 epsilon.onboarding.dfu
- run: make -j2 epsilon.onboarding.update.dfu - run: make -j2 MODEL=n0110 epsilon.onboarding.update.dfu
- run: make -j2 epsilon.onboarding.beta.dfu - run: make -j2 MODEL=n0110 epsilon.onboarding.beta.dfu
- run: make -j2 flasher.light.dfu - run: make -j2 MODEL=n0110 flasher.light.dfu
- run: make -j2 flasher.verbose.dfu - run: make -j2 MODEL=n0110 flasher.verbose.dfu
- run: make -j2 bench.ram.dfu - run: make -j2 MODEL=n0110 flasher.verbose.bin
- run: make -j2 bench.flash.dfu - run: make -j2 MODEL=n0110 bench.ram.dfu
- run: make -j2 binpack # - run: make -j2 MODEL=n0110 bench.flash.dfu
- run: make -j2 MODEL=n0110 binpack
- run: cp output/release/device/n0110/binpack-n0110-`git rev-parse HEAD | head -c 7`.tgz output/release/device/n0110/binpack-n0110.tgz - run: cp output/release/device/n0110/binpack-n0110-`git rev-parse HEAD | head -c 7`.tgz output/release/device/n0110/binpack-n0110.tgz
- uses: actions/upload-artifact@master - run: cp output/release/device/n0110/flasher.verbose.bin output/release/device/n0110/binpack/
- run: cd output/release/device/n0110 && for binary in *.bin; do shasum -a 256 -b binpack/${binary} > binpack/${binary}.sha256;done
- run: cp output/release/device/n0110/binpack-n0110-`git rev-parse HEAD | head -c 7`.tgz output/release/device/n0110/binpack/binpack.tgz
- uses: actions/upload-artifact@v4
with: with:
name: epsilon-binpack-n0110.tgz name: epsilon-binpack-n0110.tgz
path: output/release/device/n0110/binpack-n0110.tgz path: output/release/device/n0110/binpack-n0110.tgz
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/device/n0110/binpack/* binfiles/binaries/dev/n110
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
bootloader:
runs-on: ubuntu-24.04-arm
steps:
- run: |
sudo apt-get update
sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
- uses: actions/checkout@v5
with:
submodules: 'recursive'
- run: make -j2 MODEL=n0110 bootloader
- run: make -j2 epsilon.A.dfu epsilon.B.dfu
- run: make -j2 epsilon.onboarding.A.dfu
- run: make -j2 epsilon.onboarding.B.dfu
- run: make -j2 epsilon.onboarding.update.A.dfu
- run: make -j2 epsilon.onboarding.update.B.dfu
- run: make -j2 epsilon.onboarding.beta.A.dfu
- run: make -j2 epsilon.onboarding.beta.B.dfu
- run: make -j2 binpack
- run: cp output/release/device/bootloader/binpack-bootloader-`git rev-parse HEAD | head -c 7`.tgz output/release/device/bootloader/binpack-bootloader.tgz
- run: cp output/release/device/n0110/bootloader.bin output/release/device/bootloader/binpack/
- run: cp output/release/device/n0110/bootloader.bin output/release/device/bootloader/
- run: cd output/release/device/bootloader && for binary in *.bin; do shasum -a 256 -b binpack/${binary} > binpack/${binary}.sha256;done
- run: cd output/release/device/bootloader && tar cvfz binpack-bootloader.tgz binpack/*
- uses: actions/upload-artifact@v4
with:
name: epsilon-binpack-bootloader.tgz
path: output/release/device/bootloader/binpack-bootloader.tgz
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/device/bootloader/binpack/* binfiles/binaries/dev/n110
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
windows: windows:
runs-on: windows-latest runs-on: windows-latest
defaults: defaults:
@@ -124,76 +368,215 @@ jobs:
shell: msys2 {0} shell: msys2 {0}
steps: steps:
- uses: msys2/setup-msys2@v2 - uses: msys2/setup-msys2@v2
- uses: actions/checkout@v2 - uses: actions/checkout@v5
with: with:
submodules: 'recursive' submodules: 'recursive'
- run: pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config make mingw-w64-x86_64-python3 mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-libpng - run: pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config make mingw-w64-x86_64-python3 mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-libpng git
- run: make -j2 PLATFORM=simulator - run: make -j2 PLATFORM=simulator
- run: make -j2 PLATFORM=simulator test.exe - run: make -j2 PLATFORM=simulator test.exe
- run: cmd /c output\release\simulator\windows\test.exe --headless - run: cmd /c output\release\simulator\windows\test.exe --headless
- uses: actions/upload-artifact@master - id: 'auth'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/auth@v0'
with:
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- id: 'upload-file'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/upload-cloud-storage@v0'
with:
path: 'output/release/simulator/windows/epsilon.exe'
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
parent: false
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/simulator/windows/epsilon.exe binfiles/binaries/dev/simulator
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
- uses: actions/upload-artifact@v4
with: with:
name: epsilon-windows.exe name: epsilon-windows.exe
path: output/release/simulator/windows/epsilon.exe path: output/release/simulator/windows/epsilon.exe
web: web:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: numworks/setup-emscripten@v1 - uses: numworks/setup-emscripten@master
with: with:
sdk: latest-upstream sdk: latest
- uses: actions/checkout@v2 - uses: actions/checkout@v4
with: with:
submodules: 'recursive' submodules: 'recursive'
# Install the Linux toolchin to avoid dependancies issues, but maybe only libpng is needed
- run: |
sudo apt-get update
sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config libxtst-dev
- run: make -j2 PLATFORM=simulator TARGET=web - run: make -j2 PLATFORM=simulator TARGET=web
- run: make -j2 PLATFORM=simulator TARGET=web test.js - run: make -j2 PLATFORM=simulator TARGET=web test.js
- run: node output/release/simulator/web/test.js --headless - run: node output/release/simulator/web/test.js --headless
- uses: actions/upload-artifact@master - id: 'auth'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/auth@v0'
with:
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- id: 'upload-file'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/upload-cloud-storage@v0'
with:
path: 'output/release/simulator/web/epsilon.js'
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
parent: false
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/simulator/web/epsilon.zip binfiles/binaries/dev/simulator
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
- uses: actions/upload-artifact@v4
with: with:
name: epsilon-web.zip name: epsilon-web.zip
path: output/release/simulator/web/epsilon.zip path: output/release/simulator/web/epsilon.zip
linux: linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config - run: |
- uses: actions/checkout@v2 sudo apt-get update
sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config libxtst-dev
- uses: actions/checkout@v5
with: with:
submodules: 'recursive' submodules: 'recursive'
- run: make -j2 PLATFORM=simulator - run: make -j2 PLATFORM=simulator
- run: make -j2 PLATFORM=simulator test.bin - run: make -j2 PLATFORM=simulator test.bin
- run: output/release/simulator/linux/test.bin --headless - run: output/release/simulator/linux/test.bin --headless
- uses: actions/upload-artifact@master - id: 'auth'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/auth@v0'
with:
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- id: 'upload-file'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/upload-cloud-storage@v0'
with:
path: 'output/release/simulator/linux/epsilon.bin'
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
parent: false
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/simulator/linux/epsilon.bin binfiles/binaries/dev/simulator
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
- uses: actions/upload-artifact@v4
with: with:
name: epsilon-linux.bin name: epsilon-linux.bin
path: output/release/simulator/linux/epsilon.bin path: output/release/simulator/linux/epsilon.bin
macos: macos:
if: github.event.inputs.triggerMacos == 'yes' if: github.event.inputs.triggerMacos == 'yes' || github.event.inputs.triggerMacos == ''
runs-on: macOS-latest runs-on: macOS-latest
steps: steps:
- run: brew install python-setuptools
- run: brew install numworks/tap/epsilon-sdk - run: brew install numworks/tap/epsilon-sdk
- uses: actions/checkout@v2 - uses: actions/checkout@v5
with: with:
submodules: 'recursive' submodules: 'recursive'
- run: make -j2 PLATFORM=simulator - run: make -j2 PLATFORM=simulator
- run: make -j2 PLATFORM=simulator ARCH=x86_64 test.bin - run: make -j2 PLATFORM=simulator ARCH=x86_64 test.bin
- run: output/release/simulator/macos/x86_64/test.bin --headless - run: output/release/simulator/macos/x86_64/test.bin --headless
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@v4
with: with:
name: epsilon-macos.zip name: epsilon-macos.zip
path: output/release/simulator/macos/epsilon.app path: output/release/simulator/macos/epsilon.app
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/simulator/macos/epsilon.app binfiles/binaries/dev/simulator
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
ios: ios:
if: github.event.inputs.triggerIos == 'yes' if: github.event.inputs.triggerIos == 'yes' || github.event.inputs.triggerIos == ''
runs-on: macOS-latest runs-on: macos-14
steps: steps:
- run: brew install python-setuptools
- run: brew install numworks/tap/epsilon-sdk - run: brew install numworks/tap/epsilon-sdk
- uses: actions/checkout@v2 - uses: actions/checkout@v5
with: with:
submodules: 'recursive' submodules: 'recursive'
- run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0 - run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0
- run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0 APPLE_PLATFORM=ios-simulator - run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0 APPLE_PLATFORM=ios-simulator
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@v4
with: with:
name: epsilon-ios.ipa name: epsilon-ios.ipa
path: output/release/simulator/ios/epsilon.ipa path: output/release/simulator/ios/epsilon.ipa
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: actions/checkout@v5
with:
repository: Yaya-Cout/Upsilon-binfiles
ref: 'main'
token: ${{ secrets.PAT_UPSILON_BINFILES }}
path: 'binfiles'
# TODO: Handle git conflicts using rebase
- name: Upload binary files to website
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
run: |
cp -r output/release/simulator/ios/epsilon.ipa binfiles/binaries/dev/simulator
cd binfiles
git add -A
git config --global user.email "ci@github.com"
git config --global user.name "GitHub Upsilon CI"
git pull
git commit -m "Update from CI"
git push
env: env:
ACCEPT_OFFICIAL_TOS: 1 ACCEPT_OFFICIAL_TOS: 1

View File

@@ -3,38 +3,43 @@ on: [pull_request_target]
jobs: jobs:
binary-size: binary-size:
runs-on: ubuntu-latest runs-on: ubuntu-24.04-arm
steps: steps:
- name: Install dependencies - name: Install dependencies
run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
- name: Install ARM toolchain - name: Install ARM toolchain
uses: numworks/setup-arm-toolchain@2020-q2 run: sudo apt-get install gcc-arm-none-eabi binutils-arm-none-eabi
- name: Checkout PR base - name: Checkout PR base
uses: actions/checkout@v2 uses: actions/checkout@v5
with: with:
submodules: recursive submodules: recursive
ref: ${{ github.event.pull_request.base.sha }} ref: ${{ github.event.pull_request.base.sha }}
path: base path: base
- name: Build base - name: Build base
run: make -j2 -C base epsilon.elf run: make -j2 -C base MODEL=n0110 epsilon.elf
- name: Checkout PR head - name: Checkout PR head
uses: actions/checkout@v2 uses: actions/checkout@v5
with: with:
submodules: recursive submodules: recursive
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
path: head path: head
- name: Build head - name: Build head
run: make -j2 -C head epsilon.elf run: make -j2 -C head MODEL=n0110 epsilon.elf
- name: Retrieve binary size analysis - name: Retrieve binary size analysis
id: binary_size run: |
run: echo "::set-output name=table::$(python3 head/build/metrics/binary_size.py base/output/release/device/n0110/epsilon.elf head/output/release/device/n0110/epsilon.elf --labels Base Head --sections .text .rodata .bss .data --custom 'Total (RAM)' .data .bss --custom 'Total (ROM)' .text .rodata .data --escape)" table="$(python3 head/build/metrics/binary_size.py base/output/release/device/n0110/epsilon.elf head/output/release/device/n0110/epsilon.elf --labels Base Head --sections .text .rodata .bss .data --custom 'Total (RAM)' .data .bss --custom 'Total (ROM)' .text .rodata .data --escape)"
{
echo 'table<<EOF'
echo "${table//%0A/$'\n'}"
echo EOF
} >> "$GITHUB_ENV"
- name: Add comment - name: Add comment
uses: actions/github-script@v3.0.0 uses: actions/github-script@v8
with: with:
script: | script: |
await github.issues.createComment({ await github.rest.issues.createComment({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
issue_number: context.payload.pull_request.number, issue_number: context.payload.pull_request.number,
body: `${{ steps.binary_size.outputs.table }}`, body: `${{ env.table }}`,
}); });

2
.gitignore vendored
View File

@@ -8,3 +8,5 @@ epsilon.map
.gradle .gradle
.idea/ .idea/
.vs .vs
.cache/
compile_commands.json

4
.gitmodules vendored
View File

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

View File

@@ -27,10 +27,15 @@ ifeq (${MODEL}, n0100)
endif endif
endif endif
ifeq (${MODEL}, n0110) ifeq ($(filter reader,$(apps_list)),)
apps_list = ${EPSILON_APPS} HAS_READER := 1
endif
# Remove the external apps for the n0100
ifeq (${MODEL}, n0100)
apps_list = $(foreach i, ${EPSILON_APPS}, $(if $(filter external, $(i)),,$(i)))
else else
apps_list = $(foreach i, ${EPSILON_APPS}, $(if $(filter external, $(i)),,$(i))) apps_list = ${EPSILON_APPS}
endif endif
ifdef FORCE_EXTERNAL ifdef FORCE_EXTERNAL
@@ -88,6 +93,7 @@ help:
@echo " make PLATFORM=simulator TARGET=web" @echo " make PLATFORM=simulator TARGET=web"
@echo " make PLATFORM=simulator TARGET=windows" @echo " make PLATFORM=simulator TARGET=windows"
@echo " make PLATFORM=simulator TARGET=3ds" @echo " make PLATFORM=simulator TARGET=3ds"
@echo " make PLATFORM=simulator TARGET=fxcg"
.PHONY: doc .PHONY: doc
doc: doc:
@@ -101,7 +107,7 @@ print-%:
@echo $*\'s origin is $(origin $*) @echo $*\'s origin is $(origin $*)
# Since we're building out-of-tree, we need to make sure the output directories # Since we're building out-of-tree, we need to make sure the output directories
# are created, otherwise the receipes will fail (e.g. gcc will fail to create # are created, otherwise the recipes will fail (e.g. gcc will fail to create
# "output/foo/bar.o" because the directory "output/foo" doesn't exist). # "output/foo/bar.o" because the directory "output/foo" doesn't exist).
# We need to mark those directories as precious, otherwise Make will try to get # We need to mark those directories as precious, otherwise Make will try to get
# rid of them upon completion (and fail, since those folders won't be empty). # rid of them upon completion (and fail, since those folders won't be empty).
@@ -122,6 +128,7 @@ ifndef USE_LIBA
endif endif
ifeq ($(USE_LIBA),0) ifeq ($(USE_LIBA),0)
include liba/Makefile.bridge include liba/Makefile.bridge
include libaxx/Makefile.bridge
else else
SFLAGS += -ffreestanding -nostdinc -nostdlib SFLAGS += -ffreestanding -nostdinc -nostdlib
include liba/Makefile include liba/Makefile
@@ -133,6 +140,7 @@ include poincare/Makefile
include python/Makefile include python/Makefile
include escher/Makefile include escher/Makefile
# Executable Makefiles # Executable Makefiles
include bootloader/Makefile
include apps/Makefile include apps/Makefile
include build/struct_layout/Makefile include build/struct_layout/Makefile
include build/scenario/Makefile include build/scenario/Makefile
@@ -205,3 +213,13 @@ clean_run: cleanandcompile
.PHONY: run .PHONY: run
run: compile run: compile
${MAKE} start ${MAKE} start
.PHONY: translations
translations:
@echo "TRANSLATIONS"
$(Q) ${PYTHON} build/utilities/translate.py
.PHONY: translations_clean
translations_clean:
@echo "TRANSLATIONS CLEAN"
$(Q) ${PYTHON} build/utilities/translations_clean.py

View File

@@ -2,150 +2,474 @@
<p align="center"> <p align="center">
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="cc by-nc-sa 4.0" src="https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-525252.svg?labelColor=292929&logo=creative%20commons&style=for-the-badge" /></a> <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="cc by-nc-sa 4.0" src="https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-525252.svg?labelColor=292929&logo=creative%20commons&style=for-the-badge" /></a>
<a href="https://github.com/Lauryy06/Upsilon/issues"><img alt="Issues" src="https://img.shields.io/github/issues/Lauryy06/Upsilon.svg?labelColor=292929&logo=git&style=for-the-badge" /></a> <a href="https://github.com/UpsilonNumworks/Upsilon/issues"><img alt="Issues" src="https://img.shields.io/github/issues/Lauryy06/Upsilon.svg?labelColor=292929&logo=git&style=for-the-badge" /></a>
<br/> <br/>
<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> <a href="https://discord.gg/sbGvhWETAd"><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> </p>
> Don't understand french ? speak english ? here's the [english README](./README.md) ! > Don't understand French ? Speak English ? here's the [english README](./README.md) !
## À propos ## À propos
Upsilon est un fork d'Omega, un fork d'Epsilon, l'OS de Numworks tournant sur les calculatrices du même nom, qui apporte beaucoup de fonctionnalités en plus, mais qui fut archivé et fermé pour des raisons légales après un changement de politique de Numworks. Upsilon est fait pour ceux qui aimeraient voir un futur pour les OS créées par les utilisateurs pour Numworks, même après l'arrèt du projet initial. Upsilon est un fork d'Omega, un fork d'Epsilon, l'OS de NumWorks tournant sur les calculatrices du même nom, qui apporte beaucoup de fonctionnalités en plus, mais qui fut archivé et fermé pour des raisons légales après un changement de politique de NumWorks. Upsilon est fait pour ceux qui aimeraient voir un futur pour les OS créés par les utilisateurs pour NumWorks, même après l'arrêt du projet initial.
### Quelques fonctionnalités supplémentaires ### Quelques fonctionnalités supplémentaires
- Un module python kandinsky amélioré
- Un module Python Kandinsky amélioré
- Un support pour fonds d'écrans personnalisés - Un support pour fonds d'écrans personnalisés
- Des applications externes - Des applications externes
- Un thème Upsilon - Un thème Upsilon
- La surcharge des opérateurs en python - La surcharge des opérateurs en Python
- Un tableau périodique légèrement amélioré - Un tableau périodique légèrement amélioré
- L'utilisation possible du signe "=" dans les calculs - L'utilisation possible du signe "=" dans les calculs
- *Ainsi que tout ce qui a été ajouté sur Omega, et bien plus...* [Changelogs complets d'Omega](https://github.com/Omega-Numworks/Omega/wiki/Changelog) | [Fonctionnalités principales d'Omega & captures d'écran](https://github.com/Omega-Numworks/Omega/wiki/Main-features). - *Ainsi que tout ce qui a été ajouté sur Omega, et bien plus...* [Changelogs complets d'Omega](https://github.com/Omega-Numworks/Omega/wiki/Changelog) | [Fonctionnalités principales d'Omega & captures d'écran](https://github.com/Omega-Numworks/Omega/wiki/Main-features).
## Installation ## Installation
### Site web
Rendez-vous sur le [site d'Upsilon](https://getupsilon.web.app/) à la section "Installer".
Si votre calculatrice est reconnue, qu'elle contient une version d'Epsilon inférieure à 16 et que votre navigateur accepte WebUSB, la page vous proposera d'installer Upsilon.
Ne débranchez votre calculatrice qu'une fois l'installation terminée.
### Manuelle ### Manuelle
*A l'heure actuelle, seule l'installation manuelle est possible.* *Vous pouvez vous référer à ce [site internet](https://www.numworks.com/resources/engineering/software/build/) pour la première étape si vous avez des erreurs*
Tout d'abord, suivez **la première étape** [ici](https://www.numworks.com/resources/engineering/software/build/), puis : ### 1. Installation du SDK
<br>
<details> <details>
<summary><b>Modèle n0100</b></summary>
(note : vous pouvez changer `EPSILON_I18N=fr` en `en`, `nl`, `pt`, `it`, `de`, `es` ou `hu`). <summary><b>1.1 Linux</b></summary>
<br>
<details>
<summary>Debian ou Ubuntu</summary>
<br>
Il suffit juste d'installer les dépendances en tapant ces commandes dans un terminal en mode super-utilisateur.
```bash ```bash
git clone --recursive https://github.com/Lauryy06/Upsilon.git apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
```
C'est fait ! Vous pouvez aller à l'étape 2.
<br>
</details>
<details>
<summary>Fedora</summary>
<br>
Installez toutes les dépendances grâce à cette commande :
```bash
dnf install make automake gcc gcc-c++ kernel-devel git ImageMagick libX11-devel libXext-devel freetype-devel libpng-devel libjpeg-devel pkg-config arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++
```
<br>
</details>
<details>
<summary>Nix/Nixos</summary>
<br>
Installez toutes les dépendances grâce à cette commande :
```bash
nix-env -p gcc libpng libjpeg xorg.libX11 pkg-config freetype xorg.libXext python3 imagemagick python310Packages.lz4 python310Packages.pypng python310Packages.pypng gcc-arm-embedded
```
<br>
</details>
</details>
<details>
<summary><b>1.2 Mac</b></summary>
<br>
Il est recommandé d'utiliser [Homebrew](https://brew.sh/). Une fois installé, utilisez :
```bash
brew install numworks/tap/epsilon-sdk
```
Et toutes les dépendances seront installées.
<br>
Vous pouvez aller à l'étape 2.
<br>
</details>
<details>
<summary><b>1.3 Windows</b></summary>
[Git](http://git-scm.com) doit être installé.
<br>
<details>
<summary>Avec Msys2/Mingw (Supportés par NumWorks bien qu'il y ait beaucoup de bugs)</summary>
L'environnement de compilation [Msys2](https://www.msys2.org/) est recommandé par NumWorks pour obtenir la plupart des outils requis facilement. C'est ici que vous allez copier-coller toutes les commandes de ce tutoriel. Une fois installé, copiez-collez ces deux commandes dans le terminal:
```bash
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config mingw-w64-x86_64-libusb git make python
echo "export PATH=/mingw64/bin:$PATH" >> .bashrc
```
Ensuite, vous devrez installer [GCC toolchain for ARM](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). Quand il vous est demandé de choisir un dossier d'installation, choisissez `C:\msys64\home\User\gcc-arm\`. Il vous faudra ensuite ajouter ce dossier à votre $PATH. Tapez juste:
```bash
echo "export PATH=$PATH:$HOME/gcc-arm/bin" >> .bashrc
```
Redémarrez votre terminal et vous pouvez aller à l'étape 2!
</details>
<details>
<summary>Avec WSL 2</summary>
WSL est un système qui virtualise un environnement GNU/Linux dans Windows.
Votre version de Windows doit être >= 1903.
#### Installation de WSL
1. Apuyez simultanément sur les touches "Windows" et "X" puis cliquez sur "PowerShell Administrateur". Entrez ensuite ceci dans la nouvelle fenêtre:
```powershell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
```
Cette commande active WSL
```powershell
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```
Cette commande permet d'autoriser le démarrage des machines signées par Microsoft.
2. Redémarrez votre ordinateur.
3. Téléchargez [ce fichier](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi) et suivez les instructions d'installation.
4. Ouvrez votre fenêtre PowerShell comme avant et tapez:
```powershell
wsl --set-default-version 2
```
5. Téléchargez [Ubuntu](https://www.microsoft.com/store/apps/9n6svws3rx71) depuis le Microsoft store. Vous pouvez aussi installer [Debian](https://www.microsoft.com/store/productI9MSVKQC78PK6) à la place.
WSL est maintenant installé.
6. Installez maintenant la version pour ARM de GCC.
```bash
sudo apt-get update
sudo apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
```
### Installation d'usbipd pour connecter la calculatrice à WSL (facultatif)
Pour connecter la calculatrice, il faut installer cet [outil](hthttps://github.com/dorssel/usbipd-win/releases/download/v5.0.0/usbipd-win_5.0.0_x64.msi). Il permet de connecter des périphériques par Internet. Suivez les instructions pour l'installer.
#### Ubuntu
1. Dans un terminal WSL Ubuntu, tapez :
```bash
sudo apt install linux-tools-generic hwdata
```
<!-- 2. Editez /etc/sudoers pour que l'on puisse utiliser la commande usbip. Sur Ubuntu, cela est fait de cette manière :
```bash
sudo visudo
```
3. Ajoutez `/usr/lib/linux-tools/5.4.0-77-generic` au début du secure_path. Après édition, la ligne devrait ressembler à:
`Defaults secure_path="/usr/lib/linux-tools/5.4.0-77-generic:/usr/local/sbin:..."` -->
#### Debian
1.Si vous utilisez Debian, lancez cette commande:
```bash
sudo apt install usbip hwdata usbutils
```
### Pour connecter la calculatrice à WSL
1. Ouvrez à nouveau un PowerShell en mode administrateur et tapez :
```powershell
usbipd list
```
Ceci va lister les périphériques USB connectés à l'ordinateur. Regardez le BUSID de votre "Numworks Calculator".
2. Maintenant, lancez cette commande en remplaçant <BUSID> par celui de votre calculatrice :
```powershell
usbipd bind --busid <BUSID>
usbipd attach --wsl --busid <BUSID>
```
Le mot de passe de votre machine WSL vous sera demandé.
Vous pouvez aller à l'étape 2.
</details>
</details>
<br>
### 2. Récupérer le code source
Le code source est disponible dans une repository git. Récupérez-le de cette manière :
```bash
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
cd Upsilon cd Upsilon
git checkout omega-master git checkout upsilon-dev
```
<br>
### 3. Choisissez le système à compiler
<details>
<summary><b>Model n0100</b></summary>
(note: vous pouvez changer l'argument `EPSILON_I18N=en` avec `fr`, `nl`, `pt`, `it`, `de`, `es` or `hu`).
```bash
make MODEL=n0100 clean make MODEL=n0100 clean
make MODEL=n0100 EPSILON_I18N=fr OMEGA_USERNAME="{Votre nom ici, 15 caractères max}" -j4 make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Votre nom, maximum 15 caractères}" -j4
```
Maintenant, lancez soit:
```bash
make MODEL=n0100 epsilon_flash make MODEL=n0100 epsilon_flash
``` ```
Important : N'oubliez pas l'argument `--recursive`, Upsilon a besoin de sous-modules. pour directement flasher la calculatrice après avoir appuyé simultanément sur `reset` et `6` et avoir branché la calculatrice à l'ordinateur.
Vous pouvez aussi changer le nombre de processus parallèles pendant la compilation en changeant la valeur suivant `-j`.
</details> <br>
<details> soit:
<summary><b>Modèle n0110</b></summary>
```bash ```bash
git clone --recursive https://github.com/Lauryy06/Upsilon.git make MODEL=n0100 OMEGA_USERNAME="" binpack -j4
cd Upsilon
git checkout omega-master
make clean
make OMEGA_USERNAME="{Votre nom ici, 15 caractères max}" -j4
make epsilon_flash
``` ```
Important : N'oubliez pas l'argument `--recursive`, Upsilon a besoin de sous-modules. pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [WebDFU de TI-Planet](https://ti-planet.github.io/webdfu_numworks/n0100/).
Vous pouvez aussi changer le nombre de processus parallèles pendant la compilation en changeant la valeur suivant `-j`.
</details> </details>
<details> <details>
<summary><b>Fichiers binaires</b></summary>
<summary><b>Model n0110</b></summary>
Ces fichiers peuvent être utilisés pour distribuer Upsilon (pour que tout le monde puisse le flasher via [Webdfu_Numworks](https://ti-planet.github.io/webdfu_numworks/)).
Le bootloader vous permet d'installer 2 firmwares dans des "slots" séparés. Dans ce cas les applications externes ne pourront pas utiliser toute la mémoire mais la moitié. Si un seul slot est utilisé, le bootloader permettra d'utiliser toute la mémoire. Sans bootloader, les apps externes peuvent utiliser toute la mémoire.
<details>
<summary>Bootloader</summary>
Votre calculatrice doit être flashé avec le bootloader d'[Upsilon](https://getupsilon.web.app) ou d'[Omega](https://getomega.dev).
Compilez avec:
```bash ```bash
git clone --recursive https://github.com/Lauryy06/Upsilon.git
cd Upsilon
git checkout omega-master
make clean make clean
make MODEL=n0100 OMEGA_USERNAME="" -j8 make OMEGA_USERNAME="{Votre nom, max 15 caractères}" -j4
make MODEL=n0100 OMEGA_USERNAME="" binpack -j8
make OMEGA_USERNAME="" -j8
make OMEGA_USERNAME="" binpack -j8
``` ```
Important : N'oubliez pas l'argument `--recursive`, Upsilon a besoin de sous-modules. Ensuite lancez soit:
Vous pouvez aussi changer le nombre de processus parallèles pendant la compilation en changeant la valeur suivant `-j`.
```bash
make epsilon.A_flash
```
pour flasher le slot actuel ou pour flasher par le flasher du booloader avec RESET, puis 4 (flash) et 1 (flash slots) pour flasher n'importe quel slot.
<br>
soit:
```bash
make OMEGA_USERNAME="{Votre nom, max 15 caractères}" binpack -j4
```
pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [WebDFU de TI-Planet](https://ti-planet.github.io/webdfu_numworks/n0100/). Vous les trouverez dans `output/release/device/bootloader/`.
</details> </details>
<details> <details>
<summary><b>Simulateur web</b></summary>
<summary>Model n0110 sans bootloader (obsolète, utilisez le bootloader à la place pour la protection contre Epsilon)</summary>
Compilez avec:
```bash
make MODEL=n0110 clean
make MODEL=n0110 OMEGA_USERNAME="{Votre nom, max 15 caractères}" -j4
```
Ensuite lancez soit:
```bash
make MODEL=n0110 epsilon_flash
```
pour directement flasher la calculatrice après avoir appuyé simultanément sur `RESET` et `6` et avoir branché la calculatrice à l'ordinateur.
<br>
soit:
```bash
make MODEL=n0110 OMEGA_USERNAME="{Votre nom, max 15 caractères}" binpack -j4
```
pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [WebDFU de TI-Planet](https://ti-planet.github.io/webdfu_numworks/n0100/). Vous les trouverez dans `output/release/device/n0110/`.
</details>
</details>
<details>
<summary><b>Simulateur Natif</b></summary>
Lancez cette commande:
```bash
make clean
```
Vous pouvez soit choisir d'utiliser la commmande qui détectera automatiquement votre plateforme:
```bash
make PLATFORM=simulator
```
Ou choisir une commande qui correspond à votre plateforme:
```bash
make PLATFORM=simulator TARGET=android
make PLATFORM=simulator TARGET=ios
make PLATFORM=simulator TARGET=macos
make PLATFORM=simulator TARGET=web
make PLATFORM=simulator TARGET=windows
make PLATFORM=simulator TARGET=3ds
```
Vous trouverez les fichiers du simulateur dans `output/release/simulator/`.
</details>
<details>
<summary><b>Simulateur web</b></summary>
D'abord, installez emsdk : D'abord, installez emsdk :
```bash ```bash
git clone https://github.com/emscripten-core/emsdk.git git clone https://github.com/emscripten-core/emsdk.git
cd emsdk cd emsdk
./emsdk install latest-fastcomp ./emsdk install 1.40.1
./emsdk activate latest-fastcomp ./emsdk activate 1.40.1
source emsdk_env.sh source emsdk_env.sh
``` ```
Puis, compilez Upsilon : Puis, compilez Upsilon :
```bash ```bash
git clone --recursive https://github.com/Lauryy06/Upsilon.git
cd Upsilon
git checkout omega-master
make clean make clean
make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Votre nom ici, 15 caractères max}" -j4 make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Votre nom, maximum 15 caractères}" -j4
``` ```
Le simulateur se trouve dans `output/release/simulator/web/simulator.zip` Le simulateur se trouve dans `output/release/simulator/web/simulator.zip`
Important : N'oubliez pas l'argument `--recursive`, Upsilon a besoin de sous-modules. </details>
Vous pouvez aussi changer le nombre de processus parallèles pendant la compilation en changeant la valeur suivant `-j`.
<details>
<summary><b>Simulateur Android</b></summary>
Assurez-vous d'avoir JDK 25 d'installé.
Ensuite, téléchargez la toolchain Android version r21e comme suit :
```
export ANDROID_HOME=$PWD/android-sdk
wget -nv https://gitlab.com/fdroid/sdkmanager/-/raw/master/sdkmanager.py
python3 sdkmanager.py --licenses
python3 sdkmanager.py --install "ndk-bundle;r21e"
```
Il ne vous reste plus qu'à lancer cette commande pour compiler Upsilon.
```
make -j$(nproc) PLATFORM=simulator TARGET=android
```
Le fichier compilé nommé `epsilon.apk` sera celui à installer sur le téléphone depuis votre gestionnaire de fichier. Fonctionne normalement à partir de Android 4.
</details> </details>
<details> <details>
<summary><b>Simulateur 3DS</b></summary>
<summary><b>Simulateur pour 3DS</b></summary>
Vous aurez besoin de devkitPro et de devkitARM disponible dans votre `$PATH` (instructions [ici](https://devkitpro.org/wiki/Getting_Started) (en anglais))
Il vous faut devkitPro et devkitARM installés et dans votre path (les instructions sont [ici](https://devkitpro.org/wiki/Getting_Started))
```bash ```bash
git clone --recursive https://github.com/Lauryy06/Upsilon.git git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
cd Upsilon cd Upsilon
git checkout --recursive omega-dev git checkout --recursive upsilon-dev
make PLATFORM=simulator TARGET=3ds -j make PLATFORM=simulator TARGET=3ds -j
``` ```
Vous pouvez ensuite copier epsilon.3dsx sur une carte SD pour l'exécuter depuis le HBC ou utiliser 3dslink pour le lancer via le réseau : Vous pouvez ensuite mettre epsilon.3dsx sur une carte SD pour le lancer depuis le HBC ou utilisez 3dslink pour le lancer via le réseau:
```bash ```bash
3dslink output/release/simulator/3ds/epsilon.3dsx -a <ADRESSE IP 3DS> 3dslink output/release/simulator/3ds/epsilon.3dsx -a <3DS' IP ADDRESS>
``` ```
</details> </details>
Si vous avez besoin d'aide, n'hésitez pas à rejoindre notre serveur discord : https://discord.gg/Q9buEMduXG <br>
Important: n'oubliez pas l'argument `--recursive` parce qu'Upsilon dépend de submodules.
Aussi, vous pouvez changer le nombre de processus de compilation en parallèles en changeant le nombre après l'argument `-j`.
N'oubliez pas de mettre votre nom à la place `{Votre nom, maximum 15 caractères}`. Si vous n'en voulez pas, enlevez l'argument `OMEGA_USERNAME`.
Si vous avez besoin d'aide, n'hésitez pas à rejoindre notre serveur Discord : <https://discord.gg/Q9buEMduXG>
<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/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 ## 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/) - [Upsilon-External (pour installer des applications supplémentaires et des fonds d'écran)](https://upsilonnumworks.github.io/Upsilon-External/)
- [Documentation d'Ulab](https://micropython-ulab.readthedocs.io/en/latest/)
## Contribution ## Contribution
@@ -155,29 +479,29 @@ Pour contribuer, merci de lire le [Wiki d'Omega](https://github.com/Omega-Numwor
Les anciens projets d'Omega, avant sa fermeture, qui ont été utilisés pour ce projet Les anciens projets d'Omega, avant sa fermeture, qui ont été utilisés pour ce projet
* [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes) - [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes)
* [Omega Website](https://github.com/Omega-Numworks/Omega-Website) - [Omega Website](https://github.com/Omega-Numworks/Omega-Website)
* [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN) - [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN)
* [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic) - [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic)
* [Omega Design](https://github.com/Omega-Numworks/Omega-Design) - [Omega Design](https://github.com/Omega-Numworks/Omega-Design)
* [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot) - [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot)
* [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template) - [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template)
* [External Apps](https://github.com/Omega-Numworks/External-Apps) - [External Apps](https://github.com/Omega-Numworks/External-Apps)
## À propos d'Epsilon ## À propos d'Epsilon
Upsilon est un fork d'Omega, visant a continuer le projet des OS utilisateurs pour Numworks Upsilon est un fork d'Omega, visant a continuer le projet des OS utilisateurs pour NumWorks.
Omega est un fork d'Epsilon, un système d'exploitation performant pour calculatrices graphiques. Il inclut huit applications pour les mathématiques de lycée et d'études supérieurs Omega est un fork d'Epsilon, un système d'exploitation performant pour calculatrices graphiques. Il inclut huit applications pour les mathématiques de lycée et d'études supérieures.
Vous pouvez essayer Epsilon depuis votre navigateur sur le [simulateur en ligne](https://www.numworks.com/simulator/). Vous pouvez essayer Epsilon depuis votre navigateur sur le [simulateur en ligne](https://www.numworks.com/simulator/).
## Licence ## Licence
NumWorks est une marque déposée de NumWorks SAS, 24 Rue Godot de Mauroy, 75009 Paris, France. NumWorks est une marque déposée de NumWorks SAS, 24 Rue Godot de Mauroy, 75009 Paris, France.
Nintendo est Nintendo 3DS sont des marques déposées de Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, Etats-Unis. Nintendo et Nintendo 3DS sont des marques déposées de Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, Etats-Unis.
NumWorks SAS et Nintendo of America Inc ne sont en aucun cas associés avec ce projet. NumWorks SAS et Nintendo of America Inc ne sont en aucun cas associés avec ce projet.
* NumWorks Epsilon est disponible sous [Lisense CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode). - NumWorks Epsilon est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
* Omega est disponible sous [Lisense CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode). - Omega est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
* Upsilon est disponible sous [Lisense CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode). - Upsilon est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).

369
README.md
View File

@@ -2,24 +2,22 @@
<p align="center"> <p align="center">
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="cc by-nc-sa 4.0" src="https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-525252.svg?labelColor=292929&logo=creative%20commons&style=for-the-badge" /></a> <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="cc by-nc-sa 4.0" src="https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-525252.svg?labelColor=292929&logo=creative%20commons&style=for-the-badge" /></a>
<a href="https://github.com/Lauryy06/Upsilon/issues"><img alt="Issues" src="https://img.shields.io/github/issues/Lauryy06/Upsilon.svg?labelColor=292929&logo=git&style=for-the-badge" /></a> <a href="https://github.com/UpsilonNumworks/Upsilon/issues"><img alt="Issues" src="https://img.shields.io/github/issues/UpsilonNumworks/Upsilon.svg?labelColor=292929&logo=git&style=for-the-badge" /></a>
<br/> <br/>
<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> <a href="https://discord.gg/hnEqPzAJzn"><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> </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 ## About
Upsilon is a fork of Omega, an user-made OS that runs on the Numworks calculator, which brings many features to it, but was discontinued because of a policy change from Numworks. Upsilon is for the people who want to see a future for user-made OSes for Numworks, even after the closure and archiving of Omega. Upsilon is a fork of Omega, an user-made OS that runs on the NumWorks calculator, which brings many features to it, but was discontinued because of a policy change from NumWorks. Upsilon is for the people who want to see a future for user-made OSes for NumWorks, even after the closure and archiving of Omega.
### Some new features ### Some new features
- Enhancements for the Kandinsky python module - Enhancements for the Kandinsky python module
- Support for wallpapers - Support for wallpapers
- Exernal apps - External apps
- A custom theme - A custom theme
- Operator overload for python - Operator overload for python
- Improvements for the Periodic table application - Improvements for the Periodic table application
@@ -29,23 +27,28 @@ Upsilon is a fork of Omega, an user-made OS that runs on the Numworks calculator
## Installation ## Installation
### Installer
Go to the [Upsilon website](https://getupsilon.web.app/) to the "Install" section.
If your calculator is recognized, contains a version of Epsilon lower than 16 and your browser accepts WebUSB, the page will suggest you to install Upsilon.
Do not disconnect your calculator until the installation is complete.
### Manual ### Manual
*As of today, only the manual installation is available. You can refer to this [website](https://www.numworks.com/resources/engineering/software/build/) for the first step if you get errors.* *You can refer to this [website](https://www.numworks.com/resources/engineering/software/build/) for the first step if you get errors.*
### 1. Install SDK ### 1. Install SDK
<br> <br>
<details> <details>
<summary><b>1.1 Linux</b></summary> <summary><b>1.1 Linux</b></summary>
<br> <br>
<details> <details>
<summary>Debian or Ubuntu</summary> <summary>Debian or Ubuntu</summary>
<br> <br>
@@ -63,26 +66,31 @@ And there you can go to step 2!
</details> </details>
<details> <details>
<summary>Fedora</summary> <summary>Fedora</summary>
<br> <br>
First install basics dev tools. To install all dependencies:
```bash ```bash
dnf install make automake gcc gcc-c++ kernel-devel dnf install make automake gcc gcc-c++ kernel-devel git ImageMagick libX11-devel libXext-devel freetype-devel libpng-devel libjpeg-devel pkg-config arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++
``` ```
Then install required packages. <br>
</details>
<details>
<summary>Nix or Nixos</summary>
<br>
To install all dependencies:
```bash ```bash
dnf install git ImageMagick libX11-devel libXext-devel freetype-devel libpng-devel libjpeg-devel pkg-config nix-shell -p gcc libpng libjpeg xorg.libX11 pkg-config freetype xorg.libXext python3 imagemagick python310Packages.lz4 python310Packages.pypng python310Packages.pypng gcc-arm-embedded
```
Then, install GCC cross compiler for ARM.
```bash
dnf install arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++
``` ```
<br> <br>
@@ -94,14 +102,17 @@ dnf install arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++
</details> </details>
<details> <details>
<summary><b>1.2 Mac</b></summary> <summary><b>1.2 Mac</b></summary>
<br> <br>
It's recommended to use [Homebrew](https://brew.sh/). Once it's installed, just run: It's recommended to use [Homebrew](https://brew.sh/). Once it's installed, just run:
```bash ```bash
brew install numworks/tap/epsilon-sdk brew install numworks/tap/epsilon-sdk
``` ```
and it will install all dependencies. and it will install all dependencies.
<br> <br>
@@ -110,16 +121,19 @@ And there you can go to step 2!
<br> <br>
</details> </details>
<details> <details>
<summary><b>1.3 Windows</b></summary> <summary><b>1.3 Windows</b></summary>
<br> <br>
[Msys2](https://www.msys2.org/) environment is recommended to get most of the required tools on Windows easily. It's where you'll paste all the commands of this tutorial. Once it's installed, paste these commands into the Msys2 terminal. <details>
<summary>With Msys2/Mingw (officialized by NumWorks but with a lot of bugs)</summary>
[Msys2](https://www.msys2.org/) environment is recommended by NumWorks to get most of the required tools on Windows easily. It's where you'll paste all the commands of this tutorial. Once it's installed, paste these commands into the Msys2 terminal.
```bash ```bash
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config mingw-w64-x86_64-libusb git make python pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config mingw-w64-x86_64-libusb git make python
@@ -131,35 +145,140 @@ Next, you'll need to install the [GCC toolchain for ARM](https://developer.arm.c
```bash ```bash
echo "export PATH=$PATH:$HOME/gcc-arm/bin" >> .bashrc echo "export PATH=$PATH:$HOME/gcc-arm/bin" >> .bashrc
``` ```
Just restart and you can go to step 2!
Just restart terminal and you can go to step 2!
</details>
<details>
<summary>With WSL 2</summary>
You need a Windows version >= 1903.
#### WSL Installation
1. Use simultaneously Win + X keys and then click on "admin powershell".
```powershell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
```
This command activate WSL functionalities.
```powershell
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```
This one allows virtual machines developed by Microsoft.
2. Restart your computer.
3. Download [this file](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi) and follow instructions.
4. Now open powershell admin like before and type:
```powershell
wsl --set-default-version 2
```
5. Download [Ubuntu](https://www.microsoft.com/store/apps/9n6svws3rx71) from Microsoft store.
WSL is now installed.
6. Then Install GCC cross compiler for ARM. In your Ubuntu teminal, run:
<!-- TODO: Test if `wsl --install` works better, and if WSL2 has not became the
default -->
```bash
sudo apt-get update
sudo apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
```
### Usbipd installation to connect your calculator
If you want to connect to the calculator, you have to connect to install this
[tool](https://github.com/dorssel/usbipd-win/releases/download/v5.0.0/usbipd-win_5.0.0_x64.msi).
This will allow you to connect WSL to the calculator through internet. Follow
the on screen information to install.
#### Ubuntu
1. In a WSL Ubuntu command prompt, type:
```bash
sudo apt install linux-tools-generic hwdata
```
<!-- 2. Edit /etc/sudoers so that root can find the usbip command. On Ubuntu, run this command.
```bash
sudo visudo
```
3. Add `/usr/lib/linux-tools/5.4.0-77-generic` to the beginning of secure_path. After editing, the line should look similar to this.
`Defaults secure_path="/usr/lib/linux-tools/5.4.0-77-generic:/usr/local/sbin:..."` -->
#### Debian
1. If you use Debian for your WSL distro, use this command instead:
```bash
sudo apt install usbip hwdata usbutils
```
And that's all for installation and set up.
### To connect your calculator
1. Open an admin PowerShell and type:
```powershell
usbipd list
```
This will list your USB devices connected. Look at the BUSID column and remember the one for your calculator (it should be called "Numworks Calculator").
2. Now run this command replacing `<BUSID>` by your calculator's USB port id:
```powershell
usbipd bind --busid <BUSID>
usbipd attach --wsl --busid <BUSID>
```
It will ask you to type your WSL's password and will connect your calculator to WSL.
You can now go to step 2!
</details>
</details> </details>
<br> <br>
### 2. Set up repo ### 2. Set up repo
Clone repo and use 'upsilon-dev' branch by pasting these two commands: Clone repo and use 'upsilon-dev' branch by pasting these two commands:
```bash ```bash
git clone --recursive https://github.com/Lauryy06/Upsilon.git git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
cd Upsilon cd Upsilon
git checkout upsilon-dev git checkout upsilon-dev
``` ```
<br>
<br>
### 3. Choose the target ### 3. Choose the target
<details> <details>
<summary><b>Model n0100</b></summary>
<summary><b>Model n0100</b></summary>
(note: you can change the `EPSILON_I18N=en` flag to `fr`, `nl`, `pt`, `it`, `de`, `es` or `hu`). (note: you can change the `EPSILON_I18N=en` flag to `fr`, `nl`, `pt`, `it`, `de`, `es` or `hu`).
```bash ```bash
make MODEL=n0100 clean make MODEL=n0100 clean
make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Your name, max 15 characters}" -j4 make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
``` ```
Now, run either: Now, run either:
@@ -167,56 +286,127 @@ Now, run either:
```bash ```bash
make MODEL=n0100 epsilon_flash make MODEL=n0100 epsilon_flash
``` ```
to directly flash the calculator after pressing simultaneously `reset` and `6` buttons and pluging in.
to directly flash the calculator after pressing simultaneously `reset` and `6` buttons and plugging in.
<br> <br>
or: or:
```bash ```bash
make MODEL=n0100 OMEGA_USERNAME="" binpack -j4 make MODEL=n0100 OMEGA_USERNAME="" binpack -j$(nproc)
``` ```
to make binpack wich you can flash to the caculator from [Ti-planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0100/). Binpacks are a great way to share a custom build of Upsilon to friends.
to make binpack which you can flash to the calculator from [TI-Planet's WebDFU](https://ti-planet.github.io/webdfu_numworks/n0100/). Binpacks are a great way to share a custom build of Upsilon to friends.
</details> </details>
<details> <details>
<summary><b>Model n0110</b></summary>
<summary><b>Model n0110</b></summary>
The bootloader allows you to install 2 firmwares in separated "slots". If so, external apps won't have all the space but half. Bootloader will allow use of all of the memory if only one slot is flashed. In legacy mode, external apps use all the space available.
<details>
<summary>Bootloader</summary>
Your calculator must already have been flashed with [Upsilon](https://getupsilon.web.app)'s or [Omega](https://getomega.dev)'s bootloader.
Then, build with:
```bash ```bash
make clean make clean
make OMEGA_USERNAME="{Your name, max 15 characters}" -j4 make OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
``` ```
Now, run either: Now, run either:
```bash ```bash
make epsilon_flash make epsilon.A_flash
``` ```
to directly flash the calculator after pressing simultaneously `reset` and `6` buttons and pluging in.
to directly flash the calculator into the current slot, or thought bootloader's slot flasher with RESET, then 4 (flash), and 1 (flash slots) for other slots.
<br> <br>
or: or:
```bash ```bash
make OMEGA_USERNAME="" binpack -j4 make OMEGA_USERNAME="" binpack -j$(nproc)
``` ```
to make binpack wich you can flash to the caculator from [Ti-planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0110/). Binpacks are a great way to share a custom build of Upsilon to friends.
to make binpack which you can flash to the calculator from [TI-Planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0110/). You'll find them at `output/release/device/bootloader/`. Binpacks are a great way to share a custom build of Upsilon to friends.
</details>
<details>
<summary>Model N0110 legacy (deprecated, use bootloader instead for Epsilon protection)</summary>
```bash
make MODEL=n0110 clean
make MODEL=n0110 OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
```
Now, run either:
```bash
make MODEL=n0110 epsilon_flash
```
to directly flash the calculator after pressing simultaneously `reset` and `6` buttons and plugging in.
<br>
or:
```bash
make MODEL=n0110 OMEGA_USERNAME="" binpack -j$(nproc)
```
to make binpack which you can flash to the calculator from [Ti-Planet's WebDFU](https://ti-planet.github.io/webdfu_numworks/n0110/). You'll find them at `output/release/device/bootloader/`. Binpacks are a great way to share a custom build of Upsilon to friends.
</details>
</details> </details>
<details> <details>
<summary><b>Web simulator</b></summary>
<summary><b>Native simulator</b></summary>
Run this command:
```bash
make clean
```
You can either build using the following command that will automatically detect your platform:
```bash
make PLATFORM=simulator
```
or, choose the command corresponding to your platform:
```bash
make PLATFORM=simulator TARGET=android
make PLATFORM=simulator TARGET=ios
make PLATFORM=simulator TARGET=macos
make PLATFORM=simulator TARGET=web
make PLATFORM=simulator TARGET=windows
make PLATFORM=simulator TARGET=3ds
```
You'll find simulator files in `output/release/simulator/`.
</details>
<details>
<summary><b>Web simulator</b></summary>
First, install emsdk : First, install emsdk :
```bash ```bash
git clone https://github.com/emscripten-core/emsdk.git git clone https://github.com/emscripten-core/emsdk.git
cd emsdk cd emsdk
./emsdk install latest-fastcomp ./emsdk install 1.40.1
./emsdk activate latest-fastcomp ./emsdk activate 1.40.1
source emsdk_env.sh source emsdk_env.sh
``` ```
@@ -224,25 +414,26 @@ Then, compile Upsilon :
```bash ```bash
make clean make clean
make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Your name, max 15 characters}" -j4 make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
``` ```
The simulator is now in `output/release/simulator/web/simulator.zip` The simulator is now in `output/release/simulator/web/simulator.zip`
</details> </details>
<details> <details>
<summary><b>3DS Simulator</b></summary>
<summary><b>3DS Simulator</b></summary>
You need devkitPro and devkitARM installed and in your path (instructions [here](https://devkitpro.org/wiki/Getting_Started)) You need devkitPro and devkitARM installed and in your path (instructions [here](https://devkitpro.org/wiki/Getting_Started))
```bash ```bash
git clone --recursive https://github.com/Lauryy06/Upsilon.git git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
cd Upsilon cd Upsilon
git checkout --recursive omega-dev git checkout upsilon-dev
make PLATFORM=simulator TARGET=3ds -j make PLATFORM=simulator TARGET=3ds -j$(nproc)
``` ```
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: 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:
```bash ```bash
@@ -251,7 +442,41 @@ You can then put epsilon.3dsx on a SD card to run it from the HBC or use 3dslink
</details> </details>
<br> <details>
<summary><b>Android Simulator</b></summary>
Make sure you have JDK 25 installed.
Then, download the Android toolchain r21e as following :
```
export ANDROID_HOME=$PWD/android-sdk
wget -nv https://gitlab.com/fdroid/sdkmanager/-/raw/master/sdkmanager.py
python3 sdkmanager.py --licenses
python3 sdkmanager.py --install "ndk-bundle;r21e"
```
All you have to do is run this command to compile Upsilon.
```
make -j$(nproc) PLATFORM=simulator TARGET=android
```
The compiled file named `epsilon.apk` will be the one to install on the phone from your file manager. Shoudl work on Android 4.1+.
</details>
<details>
<summary><b>Casio fx-CG-series Port</b></summary>
First, install gint and fxsdk along with a cross compiler for the calculator. There are instructions for this (in French, but Google Translate works well enough) [here](https://www.planet-casio.com/Fr/forums/topic16614-last-giteapc-installer-et-mettre-a-jour-automatiquement-des-projets-gitea.html).
Next:
```bash
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
cd Omega
git checkout upsilon-dev
make PLATFORM=simulator TARGET=fxcg -j$(nproc)
```
Then copy the file at `./output/release/simulator/fxcg/epsilon.g3a` to the calculator over USB.
</details>
Important: Don't forget the `--recursive` tag, because Upsilon relies on submodules. Important: Don't forget the `--recursive` tag, because Upsilon relies on submodules.
Also, you can change the number of processes that run in parallel during the build by changing the value of the `-j` flag. Also, you can change the number of processes that run in parallel during the build by changing the value of the `-j` flag.
@@ -259,30 +484,33 @@ Don't forget to put your pseudo instead of `{your pseudo, max 15 char}`. If you
<br> <br>
If you need help, you can join our Discord server here : https://discord.gg/NFvzdCBTQn If you need help, you can join our Discord server here : <https://discord.gg/NFvzdCBTQn>
<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> <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 ## 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/) - [Upsilon external (to install additional apps and wallpapers)](https://upsilonnumworks.github.io/Upsilon-External/)
- [Ulab documentation](https://micropython-ulab.readthedocs.io/en/latest/)
## Contributing ## Contributing
To contribute, please refer to [Omega's Wiki](https://github.com/Omega-Numworks/Omega/wiki/Contributing), the same rules apply here. To contribute, please refer to [Omega's Wiki](https://github.com/Omega-Numworks/Omega/wiki/Contributing), the same rules apply here.
## Related repositories ## Related repositories
Here are the main links toward Omega's different websites and repositories, that have been used for the creation of Upsilon. Here are the main links toward Omega's different websites and repositories, that have been used for the creation of Upsilon.
* [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes) - [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes)
* [Omega Website](https://github.com/Omega-Numworks/Omega-Website) - [Omega Website](https://github.com/Omega-Numworks/Omega-Website)
* [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN) - [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN)
* [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic) - [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic)
* [Omega Design](https://github.com/Omega-Numworks/Omega-Design) - [Omega Design](https://github.com/Omega-Numworks/Omega-Design)
* [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot) - [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot)
* [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template) - [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template)
* [External Apps](https://github.com/Omega-Numworks/External-Apps) - [External Apps](https://github.com/Omega-Numworks/External-Apps)
## About Epsilon ## About Epsilon
@@ -296,8 +524,9 @@ You can try Epsilon straight from your browser in the [online simulator](https:/
NumWorks is a registered trademark of NumWorks SAS, 24 Rue Godot de Mauroy, 75009 Paris, France. NumWorks is a registered trademark of NumWorks SAS, 24 Rue Godot de Mauroy, 75009 Paris, France.
Nintendo and Nintendo 3DS are registered trademarks of Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, USA. Nintendo and Nintendo 3DS are registered trademarks of Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, USA.
NumWorks SAS and Nintendo of America Inc aren't associated in any shape or form with this project. Casio is a registered trademark of Casio Computer Co., Ltd. CORPORATION JAPAN 6-2, Hon-machi 1-chome Shibuya-ku, Tokyo JAPAN 151-8543.
NumWorks SAS, Nintendo of America Inc and Casio aren't associated in any shape or form with this project.
* NumWorks Epsilon is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode). - NumWorks Epsilon is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
* Omega is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode). - Omega is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
* Upsilon is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode). - Upsilon is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).

View File

@@ -23,7 +23,7 @@ ifneq ($(strip $(apps_missing)),)
$(foreach i, $(SUBMODULES_APPS), $(if $(call app_equals, $(filter $(i), $(apps_missing)), $(i)), $(eval miss_modules=1))) $(foreach i, $(SUBMODULES_APPS), $(if $(call app_equals, $(filter $(i), $(apps_missing)), $(i)), $(eval miss_modules=1)))
ifeq ($(miss_modules), 1) ifeq ($(miss_modules), 1)
PLS_IGNORE := $(shell >&2 printf "\nSome submodules apps seem to be missing. To download them, assumming you git clone'd the repo, do\n") PLS_IGNORE := $(shell >&2 printf "\nSome submodules apps seem to be missing. To download them, assuming you git clone'd the repo, do\n")
PLS_IGNORE := $(shell >&2 printf " git submodule init\n") PLS_IGNORE := $(shell >&2 printf " git submodule init\n")
PLS_IGNORE := $(shell >&2 printf " git submodule update\n\n") PLS_IGNORE := $(shell >&2 printf " git submodule update\n\n")
endif endif
@@ -50,6 +50,7 @@ apps_src += $(addprefix apps/,\
exam_mode_configuration_official.cpp:+official \ exam_mode_configuration_official.cpp:+official \
exam_mode_configuration_non_official.cpp:-official \ exam_mode_configuration_non_official.cpp:-official \
global_preferences.cpp \ global_preferences.cpp \
host_filemanager.cpp \
i18n.py \ i18n.py \
lock_view.cpp \ lock_view.cpp \
main.cpp \ main.cpp \
@@ -58,7 +59,9 @@ apps_src += $(addprefix apps/,\
math_variable_box_empty_controller.cpp \ math_variable_box_empty_controller.cpp \
shift_alpha_lock_view.cpp \ shift_alpha_lock_view.cpp \
suspend_timer.cpp \ suspend_timer.cpp \
timer_manager.cpp \
title_bar_view.cpp \ title_bar_view.cpp \
xnt_loop.cpp \
) )
tests_src += $(addprefix apps/,\ tests_src += $(addprefix apps/,\
@@ -81,7 +84,7 @@ $(call object_for,apps/apps_container_storage.cpp apps/apps_container.cpp apps/m
country_preferences = apps/country_preferences.csv country_preferences = apps/country_preferences.csv
language_preferences = apps/language_preferences.csv language_preferences = apps/language_preferences.csv
# The header is refered to as <apps/i18n.h> so make sure it's findable this way # The header is referred to as <apps/i18n.h> so make sure it's findable this way
SFLAGS += -I$(BUILD_DIR) SFLAGS += -I$(BUILD_DIR)
i18n_files += $(addprefix apps/language_,$(addsuffix .universal.i18n, $(EPSILON_I18N))) i18n_files += $(addprefix apps/language_,$(addsuffix .universal.i18n, $(EPSILON_I18N)))
@@ -117,6 +120,7 @@ apps_tests_src = $(app_calculation_test_src) $(app_code_test_src) $(app_graph_te
apps_tests_src += $(addprefix apps/,\ apps_tests_src += $(addprefix apps/,\
alternate_empty_nested_menu_controller.cpp \ alternate_empty_nested_menu_controller.cpp \
global_preferences.cpp \ global_preferences.cpp \
dummy_timer_manager.cpp \
) )
ifeq ($(THEME_REPO),local) ifeq ($(THEME_REPO),local)

View File

@@ -37,7 +37,8 @@ AppsContainer::AppsContainer() :
m_homeSnapshot(), m_homeSnapshot(),
m_onBoardingSnapshot(), m_onBoardingSnapshot(),
m_hardwareTestSnapshot(), m_hardwareTestSnapshot(),
m_usbConnectedSnapshot() m_usbConnectedSnapshot(),
m_startAppSnapshot()
{ {
m_emptyBatteryWindow.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height), false); m_emptyBatteryWindow.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height), false);
// #if __EMSCRIPTEN__ // #if __EMSCRIPTEN__
@@ -47,7 +48,7 @@ AppsContainer::AppsContainer() :
* poincareCircuitBreaker is run. This means either whitelisting all Epsilon * poincareCircuitBreaker is run. This means either whitelisting all Epsilon
* (which makes bigger files to download and slower execution), or * (which makes bigger files to download and slower execution), or
* whitelisting all the symbols (that's a big amount of symbols to find and * whitelisting all the symbols (that's a big amount of symbols to find and
* quite painy to maintain). * quite paint to maintain).
* We just remove the circuit breaker for now. * We just remove the circuit breaker for now.
* TODO: Put the Poincare circuit breaker back on epsilon's web emulator */ * TODO: Put the Poincare circuit breaker back on epsilon's web emulator */
@@ -58,6 +59,11 @@ AppsContainer::AppsContainer() :
Poincare::Expression::SetCircuitBreaker(AppsContainer::poincareCircuitBreaker); Poincare::Expression::SetCircuitBreaker(AppsContainer::poincareCircuitBreaker);
// #endif // #endif
Ion::Storage::sharedStorage()->setDelegate(this); Ion::Storage::sharedStorage()->setDelegate(this);
addTimer(&m_batteryTimer);
addTimer(&m_suspendTimer);
addTimer(&m_backlightDimmingTimer);
addTimer(&m_clockTimer);
} }
bool AppsContainer::poincareCircuitBreaker() { bool AppsContainer::poincareCircuitBreaker() {
@@ -146,8 +152,11 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
* We do it before switching to USB application to redraw the battery * We do it before switching to USB application to redraw the battery
* pictogram. */ * pictogram. */
updateBatteryState(); updateBatteryState();
if (switchTo(usbConnectedAppSnapshot())) { if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
Ion::USB::DFU(); // If we are in exam mode, we don't switch to usb connected app
didProcessEvent = true;
} else if (switchTo(usbConnectedAppSnapshot())) {
Ion::USB::DFU(true);
// Update LED when exiting DFU mode // Update LED when exiting DFU mode
Ion::LED::updateColorWithPlugAndCharge(); Ion::LED::updateColorWithPlugAndCharge();
bool switched = switchTo(activeSnapshot); bool switched = switchTo(activeSnapshot);
@@ -220,6 +229,7 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
return didProcessEvent || alphaLockWantsRedraw; return didProcessEvent || alphaLockWantsRedraw;
} }
// List of keys that are used to switch between apps, in order of app to go (eg. 0 : First App, 1 : Second App, 2 : Third App, ...)
static constexpr Ion::Events::Event switch_events[] = { static constexpr Ion::Events::Event switch_events[] = {
Ion::Events::ShiftSeven, Ion::Events::ShiftEight, Ion::Events::ShiftNine, Ion::Events::ShiftSeven, Ion::Events::ShiftEight, Ion::Events::ShiftNine,
Ion::Events::ShiftFour, Ion::Events::ShiftFive, Ion::Events::ShiftSix, Ion::Events::ShiftFour, Ion::Events::ShiftFive, Ion::Events::ShiftSix,
@@ -231,27 +241,33 @@ bool AppsContainer::processEvent(Ion::Events::Event event) {
// Warning: if the window is dirtied, you need to call window()->redraw() // Warning: if the window is dirtied, you need to call window()->redraw()
if (event == Ion::Events::USBPlug) { if (event == Ion::Events::USBPlug) {
if (Ion::USB::isPlugged()) { if (Ion::USB::isPlugged()) {
// If the exam mode is enabled, we ask to disable it, else, we enable USB
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
displayExamModePopUp(GlobalPreferences::ExamMode::Off); displayExamModePopUp(GlobalPreferences::ExamMode::Off);
window()->redraw(); window()->redraw();
} else { } else {
Ion::USB::enable(); Ion::USB::enable();
} }
// Update brightness when USB is plugged
Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel());
} else { } else {
// If the USB isn't plugged in USBPlug event, we disable USB
Ion::USB::disable(); Ion::USB::disable();
} }
return true; return true;
} }
// If key home or key back is pressed, we switch to the home app.
if (event == Ion::Events::Home || event == Ion::Events::Back) { if (event == Ion::Events::Home || event == Ion::Events::Back) {
switchTo(appSnapshotAtIndex(0)); switchTo(appSnapshotAtIndex(0));
return true; return true;
} }
// If shift + Home are pressed, we switch to the first app.
if (event == Ion::Events::ShiftHome) { if (event == Ion::Events::ShiftHome) {
switchTo(appSnapshotAtIndex(1)); switchTo(appSnapshotAtIndex(1));
return true; return true;
} }
// Iterate through the switch events to find the one that matches the event, if one match, switch to the app at the index of the switch event.
for(int i = 0; i < std::min((int) (sizeof(switch_events) / sizeof(Ion::Events::Event)), APPS_CONTAINER_SNAPSHOT_COUNT); i++) { for(int i = 0; i < std::min((int) (sizeof(switch_events) / sizeof(Ion::Events::Event)), APPS_CONTAINER_SNAPSHOT_COUNT); i++) {
if (event == switch_events[i]) { if (event == switch_events[i]) {
m_window.redraw(true); m_window.redraw(true);
@@ -260,19 +276,44 @@ bool AppsContainer::processEvent(Ion::Events::Event event) {
} }
} }
// Add EE shortcut to go to the settings (app number 12)
if (event == Ion::Events::EE) {
switchTo(appSnapshotAtIndex(12));
return true;
}
// Add Shift + Ans shortcut to go to the previous app
if (event == Ion::Events::ShiftAns) {
switchTo(appSnapshotAtIndex(m_lastAppIndex));
return true;
}
// If the event is the OnOff key, we suspend the calculator.
if (event == Ion::Events::OnOff) { if (event == Ion::Events::OnOff) {
suspend(true); suspend(true);
return true; return true;
} }
// If the event is a brightness event, we update the brightness according to the event.
if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus) { if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus) {
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates; int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
int direction = (event == Ion::Events::BrightnessPlus) ? Ion::Backlight::NumberOfStepsPerShortcut*delta : -delta*Ion::Backlight::NumberOfStepsPerShortcut; int NumberOfStepsPerShortcut = GlobalPreferences::sharedGlobalPreferences()->brightnessShortcut();
int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsPerShortcut*delta : -delta*NumberOfStepsPerShortcut;
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction); GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
} }
// Else, the event was not processed.
return false; return false;
} }
bool AppsContainer::switchTo(App::Snapshot * snapshot) { bool AppsContainer::switchTo(App::Snapshot * snapshot) {
// Get app index of the snapshot
int m_appIndexToSwitch = appIndexFromSnapshot(snapshot);
// If the app is home, skip app index saving
if (m_appIndexToSwitch != 0) {
// Save last app index
m_lastAppIndex = m_currentAppIndex;
// Save current app index
m_currentAppIndex = m_appIndexToSwitch;
}
if (s_activeApp && snapshot != s_activeApp->snapshot()) { if (s_activeApp && snapshot != s_activeApp->snapshot()) {
resetShiftAlphaStatus(); resetShiftAlphaStatus();
} }
@@ -309,7 +350,13 @@ void AppsContainer::run() {
/* Normal execution. The exception checkpoint must be created before /* Normal execution. The exception checkpoint must be created before
* switching to the first app, because the first app might create nodes on * switching to the first app, because the first app might create nodes on
* the pool. */ * the pool. */
bool switched = switchTo(initialAppSnapshot()); bool switched;
if (m_startAppSnapshot != nullptr) {
switched = switchTo(m_startAppSnapshot);
} else {
switched = switchTo(initialAppSnapshot());
}
assert(switched); assert(switched);
(void) switched; // Silence compilation warning about unused variable. (void) switched; // Silence compilation warning about unused variable.
} else { } else {
@@ -319,7 +366,7 @@ void AppsContainer::run() {
* destroyed from the pool. To avoid using them before packing the app * destroyed from the pool. To avoid using them before packing the app
* (in App::willBecomeInactive for instance), we tidy them early on. */ * (in App::willBecomeInactive for instance), we tidy them early on. */
s_activeApp->snapshot()->tidy(); s_activeApp->snapshot()->tidy();
/* When an app encoutered an exception due to a full pool, the next time /* When an app encountered an exception due to a full pool, the next time
* the user enters the app, the same exception could happen again which * the user enters the app, the same exception could happen again which
* would prevent from reopening the app. To avoid being stuck outside the * would prevent from reopening the app. To avoid being stuck outside the
* app causing the issue, we reset its snapshot when leaving it due to * app causing the issue, we reset its snapshot when leaving it due to
@@ -353,6 +400,8 @@ bool AppsContainer::updateBatteryState() {
} }
void AppsContainer::refreshPreferences() { void AppsContainer::refreshPreferences() {
m_suspendTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds()*1000/Timer::TickDuration);
m_backlightDimmingTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration);
m_window.refreshPreferences(); m_window.refreshPreferences();
} }
@@ -446,15 +495,6 @@ Window * AppsContainer::window() {
return &m_window; return &m_window;
} }
int AppsContainer::numberOfContainerTimers() {
return 4;
}
Timer * AppsContainer::containerTimerAtIndex(int i) {
Timer * timers[4] = {&m_batteryTimer, &m_suspendTimer, &m_backlightDimmingTimer, &m_clockTimer};
return timers[i];
}
void AppsContainer::resetShiftAlphaStatus() { void AppsContainer::resetShiftAlphaStatus() {
Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default); Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
updateAlphaLock(); updateAlphaLock();

View File

@@ -18,6 +18,7 @@
#include "shared/global_context.h" #include "shared/global_context.h"
#include "clock_timer.h" #include "clock_timer.h"
#include "on_boarding/prompt_controller.h" #include "on_boarding/prompt_controller.h"
#include "xnt_loop.h"
#include <ion/events.h> #include <ion/events.h>
@@ -28,6 +29,7 @@ public:
static bool poincareCircuitBreaker(); static bool poincareCircuitBreaker();
virtual int numberOfApps() = 0; virtual int numberOfApps() = 0;
virtual App::Snapshot * appSnapshotAtIndex(int index) = 0; virtual App::Snapshot * appSnapshotAtIndex(int index) = 0;
virtual int appIndexFromSnapshot(App::Snapshot * snapshot) = 0;
App::Snapshot * initialAppSnapshot(); App::Snapshot * initialAppSnapshot();
App::Snapshot * hardwareTestAppSnapshot(); App::Snapshot * hardwareTestAppSnapshot();
App::Snapshot * onBoardingAppSnapshot(); App::Snapshot * onBoardingAppSnapshot();
@@ -47,6 +49,8 @@ public:
void displayExamModePopUp(GlobalPreferences::ExamMode mode); void displayExamModePopUp(GlobalPreferences::ExamMode mode);
void shutdownDueToLowBattery(); void shutdownDueToLowBattery();
void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus); void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus);
CodePoint XNT(CodePoint defaultXNT, bool * shouldRemoveLastCharacter) { return m_XNTLoop.XNT(defaultXNT, shouldRemoveLastCharacter); }
void resetXNT() { m_XNTLoop.reset(); }
OnBoarding::PromptController * promptController(); OnBoarding::PromptController * promptController();
void redrawWindow(bool force = false); void redrawWindow(bool force = false);
void activateExamMode(GlobalPreferences::ExamMode examMode); void activateExamMode(GlobalPreferences::ExamMode examMode);
@@ -55,12 +59,13 @@ public:
// Ion::StorageDelegate // Ion::StorageDelegate
void storageDidChangeForRecord(const Ion::Storage::Record record) override; void storageDidChangeForRecord(const Ion::Storage::Record record) override;
void storageIsFull() override; void storageIsFull() override;
#ifdef EPSILON_GETOPT
void setStartApp(App::Snapshot * snapshot) { m_startAppSnapshot = snapshot; }
#endif
protected: protected:
Home::App::Snapshot * homeAppSnapshot() { return &m_homeSnapshot; } Home::App::Snapshot * homeAppSnapshot() { return &m_homeSnapshot; }
private: private:
Window * window() override; Window * window() override;
int numberOfContainerTimers() override;
Timer * containerTimerAtIndex(int i) override;
bool processEvent(Ion::Events::Event event); bool processEvent(Ion::Events::Event event);
void resetShiftAlphaStatus(); void resetShiftAlphaStatus();
bool updateAlphaLock(); bool updateAlphaLock();
@@ -69,6 +74,8 @@ private:
static KDColor k_promptFGColors[]; static KDColor k_promptFGColors[];
static KDColor k_promptBGColors[]; static KDColor k_promptBGColors[];
static int k_promptNumberOfMessages; static int k_promptNumberOfMessages;
int m_currentAppIndex; // Home isn't included after the second app switching
int m_lastAppIndex;
AppsWindow m_window; AppsWindow m_window;
EmptyBatteryWindow m_emptyBatteryWindow; EmptyBatteryWindow m_emptyBatteryWindow;
Shared::GlobalContext m_globalContext; Shared::GlobalContext m_globalContext;
@@ -84,6 +91,10 @@ private:
OnBoarding::App::Snapshot m_onBoardingSnapshot; OnBoarding::App::Snapshot m_onBoardingSnapshot;
HardwareTest::App::Snapshot m_hardwareTestSnapshot; HardwareTest::App::Snapshot m_hardwareTestSnapshot;
USB::App::Snapshot m_usbConnectedSnapshot; USB::App::Snapshot m_usbConnectedSnapshot;
XNTLoop m_XNTLoop;
#ifdef EPSILON_GETOPT
App::Snapshot * m_startAppSnapshot;
#endif
}; };
#endif #endif

View File

@@ -34,5 +34,25 @@ App::Snapshot * AppsContainerStorage::appSnapshotAtIndex(int index) {
}; };
assert(sizeof(snapshots)/sizeof(snapshots[0]) == k_numberOfCommonApps); assert(sizeof(snapshots)/sizeof(snapshots[0]) == k_numberOfCommonApps);
assert(index >= 0 && index < k_numberOfCommonApps); assert(index >= 0 && index < k_numberOfCommonApps);
// To avoid crashes, we return the home app snapshot if the index is out of
// bounds. (no crash in release mode, but an assert in debug mode)
if (index >= k_numberOfCommonApps) {
return snapshots[0];
}
return snapshots[index]; return snapshots[index];
} }
// Get the index of the app from its snapshot
int AppsContainerStorage::appIndexFromSnapshot(App::Snapshot * snapshot) {
App::Snapshot * snapshots[] = {
homeAppSnapshot()
APPS_CONTAINER_SNAPSHOT_LIST
};
assert(sizeof(snapshots)/sizeof(snapshots[0]) == k_numberOfCommonApps);
for (int i = 0; i < k_numberOfCommonApps; i++) {
if (snapshots[i] == snapshot) {
return i;
}
}
return NULL;
}

View File

@@ -12,6 +12,7 @@ public:
AppsContainerStorage(); AppsContainerStorage();
int numberOfApps() override; int numberOfApps() override;
App::Snapshot * appSnapshotAtIndex(int index) override; App::Snapshot * appSnapshotAtIndex(int index) override;
int appIndexFromSnapshot(App::Snapshot * snapshot) override;
void * currentAppBuffer() override { return &m_apps; }; void * currentAppBuffer() override { return &m_apps; };
private: private:
union Apps { union Apps {

View File

@@ -1,11 +1,26 @@
#include "backlight_dimming_timer.h" #include "backlight_dimming_timer.h"
#include "global_preferences.h"
#include <ion/backlight.h>
#include <ion/events.h>
#include <apps/apps_container.h>
BacklightDimmingTimer::BacklightDimmingTimer() : BacklightDimmingTimer::BacklightDimmingTimer() :
Timer(k_idleBeforeDimmingDuration/Timer::TickDuration) Timer(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration)
{ {
} }
bool BacklightDimmingTimer::fire() { bool BacklightDimmingTimer::fire(){
Ion::Backlight::setBrightness(k_dimBacklightBrightness); int i = Ion::Backlight::brightness();
while (i > 0){
int t = 20;
Ion::Events::Event e = Ion::Events::getEvent(&t);
AppsContainer::sharedAppsContainer()->dispatchEvent(e);
if (e.isKeyboardEvent()){
return false;
}
Ion::Backlight::setBrightness(i);
i -= 15;
}
return false; return false;
} }

View File

@@ -7,8 +7,6 @@ class BacklightDimmingTimer : public Timer {
public: public:
BacklightDimmingTimer(); BacklightDimmingTimer();
private: private:
constexpr static int k_idleBeforeDimmingDuration = 30*1000; // In miliseconds
constexpr static int k_dimBacklightBrightness = 0;
bool fire() override; bool fire() override;
}; };

View File

@@ -60,32 +60,36 @@ void BatteryView::drawRect(KDContext * ctx, KDRect rect) const {
*'content' depends on the charge */ *'content' depends on the charge */
// Draw the left part // Draw the left part
ctx->fillRect(KDRect(0, 0, k_elementWidth, k_batteryHeight), Palette::Battery); ctx->fillRect(KDRect(0, 1, k_elementWidth, k_batteryHeight - 2), Palette::Battery);
// Draw top and bottom part
ctx->fillRect(KDRect(1, 0, k_batteryWidth-3, 1), Palette::Battery);
ctx->fillRect(KDRect(1, k_batteryHeight-1, k_batteryWidth-3, 1), Palette::Battery);
// Draw the middle part // Draw the middle part
constexpr KDCoordinate batteryInsideX = k_elementWidth+k_separatorThickness; constexpr KDCoordinate batteryInsideX = k_elementWidth+k_separatorThickness;
constexpr KDCoordinate batteryInsideWidth = k_batteryWidth-3*k_elementWidth-2*k_separatorThickness; constexpr KDCoordinate batteryInsideWidth = k_batteryWidth-3*k_elementWidth-2*k_separatorThickness;
if (m_isCharging) { if (m_isCharging) {
// Charging: Yellow background with flash // Charging: Yellow background with flash
ctx->fillRect(KDRect(batteryInsideX, 0, batteryInsideWidth, k_batteryHeight), Palette::BatteryInCharge); ctx->fillRect(KDRect(batteryInsideX, 2, batteryInsideWidth, k_batteryHeight-4), Palette::BatteryInCharge);
KDRect frame((k_batteryWidth-k_flashWidth)/2, 0, k_flashWidth, k_flashHeight); KDRect frame((k_batteryWidth-k_flashWidth)/2, 0, k_flashWidth, k_flashHeight);
KDColor flashWorkingBuffer[BatteryView::k_flashHeight*BatteryView::k_flashWidth]; KDColor flashWorkingBuffer[BatteryView::k_flashHeight*BatteryView::k_flashWidth];
ctx->blendRectWithMask(frame, Palette::Battery, (const uint8_t *)flashMask, flashWorkingBuffer); ctx->blendRectWithMask(frame, Palette::Battery, (const uint8_t *)flashMask, flashWorkingBuffer);
} else if (m_chargeState == Ion::Battery::Charge::LOW) { } else if (m_chargeState == Ion::Battery::Charge::LOW) {
assert(!m_isPlugged); assert(!m_isPlugged);
// Low: Quite empty battery // Low: Quite empty battery
ctx->fillRect(KDRect(batteryInsideX, 0, 2*k_elementWidth, k_batteryHeight), Palette::BatteryLow); ctx->fillRect(KDRect(batteryInsideX, 2, 2*k_elementWidth, k_batteryHeight-4), 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, 2, k_batteryWidth-5*k_elementWidth-2*k_separatorThickness, k_batteryHeight-4), KDColor::blend(Palette::Toolbar, Palette::Battery, 128));
} else if (m_chargeState == Ion::Battery::Charge::SOMEWHERE_INBETWEEN) { } else if (m_chargeState == Ion::Battery::Charge::SOMEWHERE_INBETWEEN) {
assert(!m_isPlugged); assert(!m_isPlugged);
// Middle: Half full battery // Middle: Half full battery
constexpr KDCoordinate middleChargeWidth = batteryInsideWidth/2; constexpr KDCoordinate middleChargeWidth = batteryInsideWidth/2;
ctx->fillRect(KDRect(batteryInsideX, 0, middleChargeWidth, k_batteryHeight), Palette::Battery); ctx->fillRect(KDRect(batteryInsideX, 2, middleChargeWidth, k_batteryHeight-4), Palette::Battery);
ctx->fillRect(KDRect(batteryInsideX+middleChargeWidth, 0, middleChargeWidth, k_batteryHeight), Palette::BatteryInCharge); ctx->fillRect(KDRect(batteryInsideX+middleChargeWidth, 2, middleChargeWidth+1, k_batteryHeight-4), KDColor::blend(Palette::Toolbar, Palette::Battery, 128));
} else { } else {
assert(m_chargeState == Ion::Battery::Charge::FULL); assert(m_chargeState == Ion::Battery::Charge::FULL);
// Full but not plugged: Full battery // Full but not plugged: Full battery
ctx->fillRect(KDRect(batteryInsideX, 0, batteryInsideWidth, k_batteryHeight), Palette::Battery); ctx->fillRect(KDRect(batteryInsideX, 2, batteryInsideWidth, k_batteryHeight-4), Palette::Battery);
if (m_isPlugged) { if (m_isPlugged) {
// Plugged and full: Full battery with tick // Plugged and full: Full battery with tick
KDRect frame((k_batteryWidth-k_tickWidth)/2, (k_batteryHeight-k_tickHeight)/2, k_tickWidth, k_tickHeight); KDRect frame((k_batteryWidth-k_tickWidth)/2, (k_batteryHeight-k_tickHeight)/2, k_tickWidth, k_tickHeight);
@@ -95,7 +99,7 @@ void BatteryView::drawRect(KDContext * ctx, KDRect rect) const {
} }
// Draw the right part // Draw the right part
ctx->fillRect(KDRect(k_batteryWidth-2*k_elementWidth, 0, k_elementWidth, k_batteryHeight), Palette::Battery); ctx->fillRect(KDRect(k_batteryWidth-2*k_elementWidth, 1, k_elementWidth, k_batteryHeight-2), Palette::Battery);
ctx->fillRect(KDRect(k_batteryWidth-k_elementWidth, (k_batteryHeight-k_capHeight)/2, k_elementWidth, k_capHeight), Palette::Battery); ctx->fillRect(KDRect(k_batteryWidth-k_elementWidth, (k_batteryHeight-k_capHeight)/2, k_elementWidth, k_capHeight), Palette::Battery);
} }

View File

@@ -20,10 +20,10 @@ public:
constexpr static int k_tickHeight = 6; constexpr static int k_tickHeight = 6;
constexpr static int k_tickWidth = 8; constexpr static int k_tickWidth = 8;
private: private:
constexpr static KDCoordinate k_batteryHeight = 8; constexpr static KDCoordinate k_batteryHeight = 9;
constexpr static KDCoordinate k_batteryWidth = 15; constexpr static KDCoordinate k_batteryWidth = 16;
constexpr static KDCoordinate k_elementWidth = 1; constexpr static KDCoordinate k_elementWidth = 1;
constexpr static KDCoordinate k_capHeight = 4; constexpr static KDCoordinate k_capHeight = 3;
constexpr static KDCoordinate k_separatorThickness = Metric::CellSeparatorThickness; constexpr static KDCoordinate k_separatorThickness = Metric::CellSeparatorThickness;
Ion::Battery::Charge m_chargeState; Ion::Battery::Charge m_chargeState;
bool m_isCharging; bool m_isCharging;

View File

@@ -1,6 +1,8 @@
#include "integer_list_controller.h" #include "integer_list_controller.h"
#include <poincare/based_integer.h> #include <poincare/based_integer.h>
#include <poincare/opposite.h>
#include <poincare/integer.h> #include <poincare/integer.h>
#include <poincare/logarithm.h>
#include <poincare/empty_layout.h> #include <poincare/empty_layout.h>
#include <poincare/factor.h> #include <poincare/factor.h>
#include "../app.h" #include "../app.h"
@@ -26,10 +28,30 @@ Integer::Base baseAtIndex(int index) {
void IntegerListController::setExpression(Poincare::Expression e) { void IntegerListController::setExpression(Poincare::Expression e) {
ExpressionsListController::setExpression(e); ExpressionsListController::setExpression(e);
static_assert(k_maxNumberOfRows >= k_indexOfFactorExpression + 1, "k_maxNumberOfRows must be greater than k_indexOfFactorExpression"); static_assert(k_maxNumberOfRows >= k_indexOfFactorExpression + 1, "k_maxNumberOfRows must be greater than k_indexOfFactorExpression");
assert(!m_expression.isUninitialized() && m_expression.type() == ExpressionNode::Type::BasedInteger); assert(!m_expression.isUninitialized() && m_expression.type() == ExpressionNode::Type::BasedInteger || (m_expression.type() == ExpressionNode::Type::Opposite && m_expression.childAtIndex(0).type() == ExpressionNode::Type::BasedInteger));
Integer integer = static_cast<BasedInteger &>(m_expression).integer(); assert(!m_expression.isUninitialized());
for (int index = 0; index < k_indexOfFactorExpression; ++index) {
m_layouts[index] = integer.createLayout(baseAtIndex(index)); if (m_expression.type() == ExpressionNode::Type::BasedInteger) {
Integer integer = static_cast<BasedInteger &>(m_expression).integer();
for (int index = 0; index < k_indexOfFactorExpression; ++index) {
m_layouts[index] = integer.createLayout(baseAtIndex(index));
}
}
else
{
Opposite b = static_cast<Opposite &>(m_expression);
Expression e = b.childAtIndex(0);
Integer childInt = static_cast<BasedInteger &>(e).integer();
childInt.setNegative(true);
Integer num_bits = Integer::CeilingLog2(childInt);
Integer integer = Integer::TwosComplementToBits(childInt, num_bits);
for (int index = 0; index < k_indexOfFactorExpression; ++index) {
if(baseAtIndex(index) == Integer::Base::Decimal) {
m_layouts[index] = childInt.createLayout(baseAtIndex(index));
} else {
m_layouts[index] = integer.createLayout(baseAtIndex(index));
}
}
} }
// Computing factorExpression // Computing factorExpression
Expression factor = Factor::Builder(m_expression.clone()); Expression factor = Factor::Builder(m_expression.clone());

View File

@@ -20,15 +20,21 @@ using namespace Poincare;
using namespace Shared; using namespace Shared;
namespace Calculation { namespace Calculation {
void SecondDegreeListController::setExpression(Poincare::Expression e) { void SecondDegreeListController::setExpression(Poincare::Expression e) {
ExpressionsListController::setExpression(e); ExpressionsListController::setExpression(e);
assert(!m_expression.isUninitialized()); assert(!m_expression.isUninitialized());
Expression polynomialCoefficients[Expression::k_maxNumberOfPolynomialCoefficients]; Expression polynomialCoefficients[Expression::k_maxNumberOfPolynomialCoefficients];
Context * context = App::app()->localContext(); Context * context = App::app()->localContext();
Preferences * preferences = Preferences::sharedPreferences(); 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); PoincareHelpers::Reduce(&m_expression, context, ExpressionNode::ReductionTarget::SystemForAnalysis);
@@ -47,59 +53,105 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
Expression b = polynomialCoefficients[1]; Expression b = polynomialCoefficients[1];
Expression c = polynomialCoefficients[0]; 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())); 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); PoincareHelpers::Simplify(&delta, context, ExpressionNode::ReductionTarget::SystemForApproximation);
Expression alpha = Opposite::Builder(Division::Builder(b.clone(), Multiplication::Builder(Rational::Builder(2), a.clone()))); // Alpha is -b/2a, but because after we use -α, we immediately store -α=-(-b/2a)=b/2a.
PoincareHelpers::Simplify(&alpha, context, ExpressionNode::ReductionTarget::User); 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()))); // Same thing for β
PoincareHelpers::Simplify(&beta, context, ExpressionNode::ReductionTarget::User); Expression minusBeta = Division::Builder(delta.clone(), Multiplication::Builder(Rational::Builder(4), a.clone()));
PoincareHelpers::Reduce(&minusBeta, context, ExpressionNode::ReductionTarget::SystemForApproximation);
/* enum MultiplicationTypeForA {
* Because when can't apply reduce or simplify to keep the canonised Nothing,
* we must beautify the expression manually 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
* canonized form we must beautify the expression manually
*/ */
Expression canonised; Expression xMinusAlphaPowerTwo;
if (alpha.type() == ExpressionNode::Type::Opposite) { Expression alpha = getOppositeIfExists(minusAlpha, &reductionContext);
canonised = Addition::Builder(Symbol::Builder("x", strlen("x")), alpha.childAtIndex(0).clone());
} if (alpha.isUninitialized()) {
else { PoincareHelpers::Simplify(&minusAlpha, context, ExpressionNode::ReductionTarget::User);
canonised = Subtraction::Builder(Symbol::Builder("x", strlen("x")), alpha.clone()); xMinusAlphaPowerTwo = Power::Builder(Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), minusAlpha)), Rational::Builder(2));
} } else {
canonised = Power::Builder(Parenthesis::Builder(canonised.clone()), Rational::Builder(2)); PoincareHelpers::Simplify(&alpha, context, ExpressionNode::ReductionTarget::User);
if (aIsNotOne) { xMinusAlphaPowerTwo = Power::Builder(Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), alpha)), Rational::Builder(2));
canonised = Multiplication::Builder(a.clone(), canonised.clone()); }
}
if (beta.type() == ExpressionNode::Type::Opposite) { Expression xMinusAlphaPowerTwoWithFactor;
canonised = Subtraction::Builder(canonised.clone(), beta.childAtIndex(0).clone());
} switch (multiplicationTypeForA)
else { {
canonised = Addition::Builder(canonised.clone(), beta.clone()); case MultiplicationTypeForA::Nothing:
xMinusAlphaPowerTwoWithFactor = xMinusAlphaPowerTwo;
break;
case MultiplicationTypeForA::Minus:
xMinusAlphaPowerTwoWithFactor = Opposite::Builder(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;
PoincareHelpers::Simplify(&minusBeta, context, ExpressionNode::ReductionTarget::User);
Expression beta = getOppositeIfExists(minusBeta, &reductionContext);
if (beta.isUninitialized()) {
if (minusBeta.type() == ExpressionNode::Type::Addition || minusBeta.type() == ExpressionNode::Type::Subtraction) {
canonized = Subtraction::Builder(xMinusAlphaPowerTwoWithFactor, Parenthesis::Builder(minusBeta));
} else {
canonized = Subtraction::Builder(xMinusAlphaPowerTwoWithFactor, minusBeta);
}
} else {
PoincareHelpers::Simplify(&beta, context, ExpressionNode::ReductionTarget::User);
canonized = Addition::Builder(xMinusAlphaPowerTwoWithFactor, beta);
} }
Expression x0; Expression x0;
Expression x1; Expression x1;
if (delta.nullStatus(context) == ExpressionNode::NullStatus::Null) { if (delta.nullStatus(context) == ExpressionNode::NullStatus::Null) {
// x0 = x1 = -b/(2a) // 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; m_numberOfSolutions = 1;
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User); PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::SystemForApproximation);
} } else {
else {
// x0 = (-b-sqrt(delta))/(2a) // 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())); 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 = (-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; m_numberOfSolutions = 2;
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User); PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::SystemForApproximation);
PoincareHelpers::Simplify(&x1, context, ExpressionNode::ReductionTarget::User); PoincareHelpers::Simplify(&x1, context, ExpressionNode::ReductionTarget::SystemForApproximation);
if (x0.type() == ExpressionNode::Type::Unreal) { if (x0.type() == ExpressionNode::Type::Unreal) {
assert(x1.type() == ExpressionNode::Type::Unreal); assert(x1.type() == ExpressionNode::Type::Unreal);
m_numberOfSolutions = 0; m_numberOfSolutions = 0;
@@ -109,40 +161,99 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
Expression factorized; Expression factorized;
if (m_numberOfSolutions == 2) { if (m_numberOfSolutions == 2) {
if (x0.type() == ExpressionNode::Type::Opposite) { Expression firstFactor;
factorized = Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), x0.childAtIndex(0).clone())); Expression secondFactor;
}
else { Expression x0Opposite = getOppositeIfExists(x0, &reductionContext);
factorized = Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0.clone())); if (x0Opposite.isUninitialized()) {
} PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
if (x0.type() == ExpressionNode::Type::Addition || x0.type() == ExpressionNode::Type::Subtraction) {
if (x1.type() == ExpressionNode::Type::Opposite) { firstFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), Parenthesis::Builder(x0.clone()));
factorized = Multiplication::Builder(factorized.clone(), Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), x1.childAtIndex(0).clone()))); } else {
} firstFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0.clone());
else { }
factorized = Multiplication::Builder(factorized.clone(), Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), x1.clone()))); } else {
if (x0Opposite.type() == ExpressionNode::Type::Addition || x0Opposite.type() == ExpressionNode::Type::Subtraction) {
x0Opposite = Parenthesis::Builder(x0Opposite.clone());
}
firstFactor = Addition::Builder(Symbol::Builder("x", strlen("x")), x0Opposite.clone());
} }
if (aIsNotOne) { Expression x1Opposite = getOppositeIfExists(x1, &reductionContext);
factorized = Multiplication::Builder(a.clone(), factorized.clone()); if (x1Opposite.isUninitialized()) {
} PoincareHelpers::Simplify(&x1, context, ExpressionNode::ReductionTarget::User);
} if (x1.type() == ExpressionNode::Type::Addition || x1.type() == ExpressionNode::Type::Subtraction) {
else if (m_numberOfSolutions == 1) { secondFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), Parenthesis::Builder(x1.clone()));
if (x0.type() == ExpressionNode::Type::Opposite) { } else {
factorized = Power::Builder(Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), x0.childAtIndex(0).clone())), Rational::Builder(2)); secondFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x1.clone());
} }
else { } else {
factorized = Power::Builder(Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0.clone())), Rational::Builder(2)); PoincareHelpers::Simplify(&x1Opposite, context, ExpressionNode::ReductionTarget::User);
if (x1Opposite.type() == ExpressionNode::Type::Addition || x1Opposite.type() == ExpressionNode::Type::Subtraction) {
x1Opposite = Parenthesis::Builder(x1Opposite.clone());
}
secondFactor = Addition::Builder(Symbol::Builder("x", strlen("x")), x1Opposite.clone());
} }
if (aIsNotOne) { Expression solutionProduct = Multiplication::Builder(Parenthesis::Builder(firstFactor), Parenthesis::Builder(secondFactor));
factorized = Multiplication::Builder(a.clone(), factorized.clone()); switch (multiplicationTypeForA)
{
case MultiplicationTypeForA::Nothing:
factorized = solutionProduct;
break;
case MultiplicationTypeForA::Minus:
factorized = Opposite::Builder(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) {
Expression x0Opposite = getOppositeIfExists(x0, &reductionContext);
Expression factor;
if (x0Opposite.isUninitialized()) {
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
if (x0.type() == ExpressionNode::Type::Addition || x0.type() == ExpressionNode::Type::Subtraction) {
factor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), Parenthesis::Builder(x0.clone()));
} else {
factor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0.clone());
}
} else {
PoincareHelpers::Simplify(&x0Opposite, context, ExpressionNode::ReductionTarget::User);
factor = Addition::Builder(Symbol::Builder("x", strlen("x")), x0Opposite.clone());
}
Expression solutionProduct = Power::Builder(Parenthesis::Builder(factor), Rational::Builder(2));
switch (multiplicationTypeForA)
{
case MultiplicationTypeForA::Nothing:
factorized = solutionProduct;
break;
case MultiplicationTypeForA::Minus:
factorized = Opposite::Builder(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); PoincareHelpers::Simplify(&delta, context, ExpressionNode::ReductionTarget::User);
m_layouts[0] = PoincareHelpers::CreateLayout(canonised); m_layouts[0] = PoincareHelpers::CreateLayout(canonized);
if (m_numberOfSolutions > 0) { if (m_numberOfSolutions > 0) {
m_layouts[1] = PoincareHelpers::CreateLayout(factorized); m_layouts[1] = PoincareHelpers::CreateLayout(factorized);
m_layouts[2] = PoincareHelpers::CreateLayout(delta); m_layouts[2] = PoincareHelpers::CreateLayout(delta);
@@ -150,17 +261,38 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
if (m_numberOfSolutions > 1) { if (m_numberOfSolutions > 1) {
m_layouts[4] = PoincareHelpers::CreateLayout(x1); m_layouts[4] = PoincareHelpers::CreateLayout(x1);
} }
} } else {
else {
m_layouts[1] = PoincareHelpers::CreateLayout(delta); m_layouts[1] = PoincareHelpers::CreateLayout(delta);
} }
} }
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::Opposite) {
return std::move(e.childAtIndex(0).clone());
} 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) { I18n::Message SecondDegreeListController::messageAtIndex(int index) {
if (m_numberOfSolutions > 0) { if (m_numberOfSolutions > 0) {
if (index == 0) { if (index == 0) {
return I18n::Message::CanonicalForm; return I18n::Message::CanonicalForm;
} }
if (index == 1) { if (index == 1) {
return I18n::Message::FactorizedForm; return I18n::Message::FactorizedForm;
} }
@@ -170,14 +302,12 @@ I18n::Message SecondDegreeListController::messageAtIndex(int index) {
if (index == 3) { if (index == 3) {
if (m_numberOfSolutions == 1) { if (m_numberOfSolutions == 1) {
return I18n::Message::OnlyRoot; return I18n::Message::OnlyRoot;
} } else {
else {
return I18n::Message::FirstRoot; return I18n::Message::FirstRoot;
} }
} }
return I18n::Message::SecondRoot; return I18n::Message::SecondRoot;
} } else {
else {
switch (index) { switch (index) {
case 0: case 0:
return I18n::Message::CanonicalForm; return I18n::Message::CanonicalForm;

View File

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

View File

@@ -8,7 +8,8 @@ namespace Calculation {
TrigonometryGraphView::TrigonometryGraphView(TrigonometryModel * model) : TrigonometryGraphView::TrigonometryGraphView(TrigonometryModel * model) :
CurveView(model), CurveView(model),
m_model(model) m_model(model),
m_shouldDisplayTan(false)
{ {
} }
@@ -22,17 +23,33 @@ void TrigonometryGraphView::drawRect(KDContext * ctx, KDRect rect) const {
drawCurve(ctx, rect, 0.0f, 2.0f*M_PI, M_PI/180.0f, [](float t, void * model, void * context) { drawCurve(ctx, rect, 0.0f, 2.0f*M_PI, M_PI/180.0f, [](float t, void * model, void * context) {
return Poincare::Coordinate2D<float>(std::cos(t), std::sin(t)); return Poincare::Coordinate2D<float>(std::cos(t), std::sin(t));
}, nullptr, nullptr, true, Palette::SecondaryText, false); }, nullptr, nullptr, true, Palette::SecondaryText, false);
// Draw dashed segment to indicate sine and cosine
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, c, 0.0f, s, Palette::CalculationTrigoAndComplexForeground, 1, 3); if (!m_shouldDisplayTan) {
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, s, 0.0f, c, Palette::CalculationTrigoAndComplexForeground, 1, 3); // Draw dashed segment to indicate sine and cosine
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, c, 0.0f, s, Palette::CalculationTrigoAndComplexForeground, 1, 3);
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, s, 0.0f, c, Palette::CalculationTrigoAndComplexForeground, 1, 3);
}
if (m_shouldDisplayTan) {
float t = std::tan(m_model->angle());
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, 1.0f, m_model->yMin(), m_model->yMax(), Palette::SecondaryText, 2);
drawSegment(ctx, rect, 0.0f, 0.0f, 1.0f, t, Palette::SecondaryText, false);
drawDot(ctx, rect, 1.0f, t, Palette::CalculationTrigoAndComplexForeground, Size::Large);
drawLabel(ctx, rect, 0.0f, t, "tan(θ)", Palette::CalculationTrigoAndComplexForeground, CurveView::RelativePosition::Before, CurveView::RelativePosition::None);
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, t, 0.0f, 1.0f, Palette::CalculationTrigoAndComplexForeground, 1, 3);
}
// Draw angle position on the circle // Draw angle position on the circle
drawDot(ctx, rect, c, s, Palette::CalculationTrigoAndComplexForeground, Size::Large); drawDot(ctx, rect, c, s, m_shouldDisplayTan ? Palette::SecondaryText : Palette::CalculationTrigoAndComplexForeground, m_shouldDisplayTan ? Size::Tiny : Size::Large);
// Draw graduations // Draw graduations
drawLabelsAndGraduations(ctx, rect, Axis::Vertical, false, true); drawLabelsAndGraduations(ctx, rect, Axis::Vertical, false, true);
drawLabelsAndGraduations(ctx, rect, Axis::Horizontal, false, true); drawLabelsAndGraduations(ctx, rect, Axis::Horizontal, false, true);
// Draw labels
drawLabel(ctx, rect, 0.0f, s, "sin(θ)", Palette::CalculationTrigoAndComplexForeground, c >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After, CurveView::RelativePosition::None); if (!m_shouldDisplayTan) {
drawLabel(ctx, rect, c, 0.0f, "cos(θ)", Palette::CalculationTrigoAndComplexForeground, CurveView::RelativePosition::None, s >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After); // Draw labels
drawLabel(ctx, rect, 0.0f, s, "sin(θ)", Palette::CalculationTrigoAndComplexForeground, c >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After, CurveView::RelativePosition::None);
drawLabel(ctx, rect, c, 0.0f, "cos(θ)", Palette::CalculationTrigoAndComplexForeground, CurveView::RelativePosition::None, s >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After);
}
} }
} }

View File

@@ -11,13 +11,16 @@ class TrigonometryGraphView : public Shared::CurveView {
public: public:
TrigonometryGraphView(TrigonometryModel * model); TrigonometryGraphView(TrigonometryModel * model);
void drawRect(KDContext * ctx, KDRect rect) const override; void drawRect(KDContext * ctx, KDRect rect) const override;
void setShouldDisplayTan(bool shouldDisplayTan) { m_shouldDisplayTan = shouldDisplayTan; };
private: private:
TrigonometryModel * m_model; TrigonometryModel * m_model;
bool m_shouldDisplayTan;
}; };
class TrigonometryGraphCell : public IllustrationCell { class TrigonometryGraphCell : public IllustrationCell {
public: public:
TrigonometryGraphCell(TrigonometryModel * model) : m_view(model) {} TrigonometryGraphCell(TrigonometryModel * model) : m_view(model) {}
void setShouldDisplayTan(bool shouldDisplayTan) { m_view.setShouldDisplayTan(shouldDisplayTan); };
private: private:
View * view() override { return &m_view; } View * view() override { return &m_view; }
TrigonometryGraphView m_view; TrigonometryGraphView m_view;

View File

@@ -1,16 +1,67 @@
#include "trigonometry_list_controller.h" #include "trigonometry_list_controller.h"
#include "../app.h" #include "../app.h"
#include <poincare_nodes.h>
#include "../../shared/poincare_helpers.h"
using namespace Poincare; using namespace Poincare;
namespace Calculation { namespace Calculation {
void TrigonometryListController::setExpression(Poincare::Expression e) { static constexpr int s_fullCircle[] = {
assert(e.type() == ExpressionNode::Type::Cosine || e.type() == ExpressionNode::Type::Sine); 360,
IllustratedListController::setExpression(e.childAtIndex(0)); 2,
400
};
Poincare::Constant toConstant(Expression e) {
return static_cast<Poincare::Constant &>(e);
}
void TrigonometryListController::setExpression(Expression e) {
assert(e.type() == ExpressionNode::Type::Cosine || e.type() == ExpressionNode::Type::Sine || e.type() == ExpressionNode::Type::Tangent);
bool shouldDisplayTan = e.type() == ExpressionNode::Type::Tangent;
m_graphCell.setShouldDisplayTan(shouldDisplayTan);
m_model.setShouldDisplayTan(shouldDisplayTan);
Poincare::Context * context = App::app()->localContext();
Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences();
Preferences::AngleUnit angleUnit = preferences->angleUnit();
Expression angleExpression = e.childAtIndex(0);
Shared::PoincareHelpers::Reduce(&angleExpression, context, Poincare::ExpressionNode::ReductionTarget::SystemForAnalysis);
if ((angleUnit == Preferences::AngleUnit::Radian
&& angleExpression.type() == ExpressionNode::Type::Multiplication
&& angleExpression.numberOfChildren() == 2
&& angleExpression.childAtIndex(1).type() == ExpressionNode::Type::Constant
&& toConstant(angleExpression.childAtIndex(1)).isPi()
&& angleExpression.childAtIndex(0).type() == ExpressionNode::Type::Rational)
|| ((angleUnit == Preferences::AngleUnit::Degree || angleUnit == Preferences::AngleUnit::Gradian)
&& angleExpression.type() == ExpressionNode::Type::Rational)) {
Expression extracted = angleUnit == Preferences::AngleUnit::Radian ? angleExpression.childAtIndex(0) : angleExpression;
Rational r = static_cast<Rational &>(extracted);
Integer denominator = Integer::Multiplication(r.integerDenominator(), Integer(s_fullCircle[(int) angleUnit]));
IntegerDivision division = Integer::Division(r.signedIntegerNumerator(), denominator);
Integer remainder = division.remainder;
Expression newAngle;
Integer rDenominator = r.integerDenominator();
Rational newCoefficient = Rational::Builder(remainder, rDenominator);
if (angleUnit == Preferences::AngleUnit::Radian) {
angleExpression = Multiplication::Builder(newCoefficient, angleExpression.childAtIndex(1));
} else {
angleExpression = newCoefficient;
}
}
IllustratedListController::setExpression(angleExpression);
// Fill calculation store // Fill calculation store
Poincare::Context * context = App::app()->localContext(); m_calculationStore.push("tan(θ)", context, CalculationHeight);
m_calculationStore.push("sin(θ)", context, CalculationHeight); m_calculationStore.push("sin(θ)", context, CalculationHeight);
m_calculationStore.push("cos(θ)", context, CalculationHeight); m_calculationStore.push("cos(θ)", context, CalculationHeight);
m_calculationStore.push("θ", context, CalculationHeight); m_calculationStore.push("θ", context, CalculationHeight);

View File

@@ -8,4 +8,22 @@ TrigonometryModel::TrigonometryModel() :
{ {
} }
float TrigonometryModel::yMin() const {
if (m_shouldDisplayTan) {
return -1.1f;
}
return yCenter() - yHalfRange();
}
float TrigonometryModel::yMax() const {
if (m_shouldDisplayTan) {
float t = std::tan(angle());
if (t <= 1.2f) {
return 1.2f;
}
return 1.2f * std::tan(angle());
}
return yCenter() + yHalfRange();
}
} }

View File

@@ -14,11 +14,12 @@ public:
// CurveViewRange // CurveViewRange
float xMin() const override { return -k_xHalfRange; } float xMin() const override { return -k_xHalfRange; }
float xMax() const override { return k_xHalfRange; } float xMax() const override { return k_xHalfRange; }
float yMin() const override { return yCenter() - yHalfRange(); } float yMin() const override;
float yMax() const override { return yCenter() + yHalfRange(); } float yMax() const override;
void setAngle(float f) { m_angle = f; } void setAngle(float f) { m_angle = f; }
float angle() const { return m_angle*(float)M_PI/(float)Poincare::Trigonometry::PiInAngleUnit(Poincare::Preferences::sharedPreferences()->angleUnit()); } float angle() const { return m_angle*(float)M_PI/(float)Poincare::Trigonometry::PiInAngleUnit(Poincare::Preferences::sharedPreferences()->angleUnit()); }
void setShouldDisplayTan(bool shouldDisplayTan) { m_shouldDisplayTan = shouldDisplayTan; }
private: private:
constexpr static float k_xHalfRange = 2.1f; constexpr static float k_xHalfRange = 2.1f;
// We center the yRange around the semi-circle where the angle is // We center the yRange around the semi-circle where the angle is
@@ -33,6 +34,7 @@ private:
float yHalfRange() const { return IllustratedListController::k_illustrationHeight*k_xHalfRange/(Ion::Display::Width - Metric::PopUpRightMargin - Metric::PopUpLeftMargin); } float yHalfRange() const { return IllustratedListController::k_illustrationHeight*k_xHalfRange/(Ion::Display::Width - Metric::PopUpRightMargin - Metric::PopUpLeftMargin); }
float m_angle; float m_angle;
bool m_shouldDisplayTan;
}; };
} }

View File

@@ -12,6 +12,26 @@ using namespace Shared;
namespace Calculation { namespace Calculation {
UnitListController::UnitListController(EditExpressionController * editExpressionController) :
ExpressionsListController(editExpressionController),
m_dimensionMessage(I18n::Message::Default)
{
m_dimensionCell.setMessageFont(KDFont::LargeFont);
}
bool UnitListController::handleEvent(Ion::Events::Event event) {
if (selectedRow() == 0 && (event == Ion::Events::OK || event == Ion::Events::EXE)) {
return true;
}
// HACK: Change the selected row (prevent some bugs when OK is pressed)
selectRow(selectedRow() - 1);
bool value = ListController::handleEvent(event);
selectRow(selectedRow() + 1);
return value;
}
void UnitListController::setExpression(Poincare::Expression e) { void UnitListController::setExpression(Poincare::Expression e) {
ExpressionsListController::setExpression(e); ExpressionsListController::setExpression(e);
assert(!m_expression.isUninitialized()); assert(!m_expression.isUninitialized());
@@ -22,6 +42,7 @@ void UnitListController::setExpression(Poincare::Expression e) {
for (size_t i = 0; i < k_maxNumberOfRows; i++) { for (size_t i = 0; i < k_maxNumberOfRows; i++) {
expressions[i] = Expression(); expressions[i] = Expression();
} }
m_dimensionMessage = I18n::Message::Default;
/* 1. First rows: miscellaneous classic units for some dimensions, in both /* 1. First rows: miscellaneous classic units for some dimensions, in both
* metric and imperial units. */ * metric and imperial units. */
@@ -37,7 +58,7 @@ void UnitListController::setExpression(Poincare::Expression e) {
GlobalPreferences::sharedGlobalPreferences()->unitFormat(), GlobalPreferences::sharedGlobalPreferences()->unitFormat(),
ExpressionNode::ReductionTarget::User, ExpressionNode::ReductionTarget::User,
ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined); ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined);
int numberOfExpressions = Unit::SetAdditionalExpressions(units, value, expressions, k_maxNumberOfRows, reductionContext); int numberOfExpressions = Unit::SetAdditionalExpressionsAndMessage(units, value, expressions, k_maxNumberOfRows, reductionContext, &m_dimensionMessage);
// 2. SI units only // 2. SI units only
assert(numberOfExpressions < k_maxNumberOfRows - 1); assert(numberOfExpressions < k_maxNumberOfRows - 1);
@@ -89,6 +110,44 @@ void UnitListController::setExpression(Poincare::Expression e) {
} }
} }
int UnitListController::numberOfRows() const {
int messageRow = m_dimensionMessage != I18n::Message::Default ? 1 : 0;
return ExpressionsListController::numberOfRows() + messageRow;
}
void UnitListController::willDisplayCellForIndex(HighlightCell * cell, int index) {
if (index == 0) {
MessageTableCell<> * messageTableCell = (MessageTableCell<> *)cell;
messageTableCell->setMessage(m_dimensionMessage);
} else {
ExpressionsListController::willDisplayCellForIndex(cell, index - 1);
}
}
KDCoordinate UnitListController::rowHeight(int index) {
if (index == 0) {
return 35;
} else {
return ExpressionsListController::rowHeight(index - 1);
}
}
HighlightCell * UnitListController::reusableCell(int index, int type) {
if (type == 0) {
return ExpressionsListController::reusableCell(index, type);
} else {
return &m_dimensionCell;
}
}
int UnitListController::typeAtLocation(int i, int j) {
if (j == 0) {
return 1;
} else {
return ExpressionsListController::typeAtLocation(i, j - 1);
}
}
I18n::Message UnitListController::messageAtIndex(int index) { I18n::Message UnitListController::messageAtIndex(int index) {
return (I18n::Message)0; return (I18n::Message)0;
} }

View File

@@ -7,13 +7,23 @@ namespace Calculation {
class UnitListController : public ExpressionsListController { class UnitListController : public ExpressionsListController {
public: public:
UnitListController(EditExpressionController * editExpressionController) : UnitListController(EditExpressionController * editExpressionController);
ExpressionsListController(editExpressionController) {}
/* Responder */
bool handleEvent(Ion::Events::Event event) override;
void setExpression(Poincare::Expression e) override; void setExpression(Poincare::Expression e) override;
int reusableCellCount(int type) override { return type == 0 ? ExpressionsListController::reusableCellCount(type) : 1; }
HighlightCell * reusableCell(int index, int type) override;
KDCoordinate rowHeight(int j) override;
int typeAtLocation(int i, int j) override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
int numberOfRows() const override;
private: private:
I18n::Message messageAtIndex(int index) override; I18n::Message messageAtIndex(int index) override;
I18n::Message m_dimensionMessage;
MessageTableCell<> m_dimensionCell;
}; };
} }

View File

@@ -17,4 +17,4 @@ FactorizedForm = "Factorisierte Form"
Discriminant = "Diskriminante" Discriminant = "Diskriminante"
OnlyRoot = "Wurzel" OnlyRoot = "Wurzel"
FirstRoot = "Erste Wurzel" FirstRoot = "Erste Wurzel"
SecondRoot = "Zweite Wurzel" SecondRoot = "Zweite Wurzel"

View File

@@ -17,4 +17,4 @@ FactorizedForm = "Factorized form"
Discriminant = "Discriminant" Discriminant = "Discriminant"
OnlyRoot = "Root" OnlyRoot = "Root"
FirstRoot = "First root" FirstRoot = "First root"
SecondRoot = "Second root" SecondRoot = "Second root"

View File

@@ -17,4 +17,4 @@ FactorizedForm = "Forma factorizada"
Discriminant = "Discriminante" Discriminant = "Discriminante"
OnlyRoot = "Raíz" OnlyRoot = "Raíz"
FirstRoot = "Primera raíz" FirstRoot = "Primera raíz"
SecondRoot = "Segunda raíz" SecondRoot = "Segunda raíz"

View File

@@ -17,4 +17,4 @@ FactorizedForm = "Forme factorisée"
Discriminant = "Discriminant" Discriminant = "Discriminant"
OnlyRoot = "Racine" OnlyRoot = "Racine"
FirstRoot = "Première racine" FirstRoot = "Première racine"
SecondRoot = "Seconde racine" SecondRoot = "Seconde racine"

View File

@@ -1,20 +1,20 @@
CalculApp = "Számolás" CalculApp = "Számolás"
CalculAppCapital = "SZÁMOLÁS" CalculAppCapital = "SZÁMOLÁS"
AdditionalResults = "További eredmények" AdditionalResults = "További eredmények"
DecimalBase = "Decimális" DecimalBase = "Decimális"
HexadecimalBase = "Hexadecimális" HexadecimalBase = "Hexadecimális"
BinaryBase = "Bináris" BinaryBase = "Bináris"
PrimeFactors = "Alapvetö tényezök" PrimeFactors = "Alapvetö tényezök"
MixedFraction = "Vegyes frakció" MixedFraction = "Vegyes frakció"
EuclideanDivision = "Euklideszi osztás" EuclideanDivision = "Euklideszi osztás"
AdditionalDeterminant = "Meghatározó" AdditionalDeterminant = "Meghatározó"
AdditionalInverse = "inverz" AdditionalInverse = "inverz"
AdditionalRowEchelonForm = "Sor echelon forma" AdditionalRowEchelonForm = "Sor echelon forma"
AdditionalReducedRowEchelonForm = "Csökkentett sorú Echelon forma" AdditionalReducedRowEchelonForm = "Csökkentett sorú Echelon forma"
AdditionalTrace = "Nyomkövetés" AdditionalTrace = "Nyomkövetés"
CanonicalForm = "Kanonikus forma" CanonicalForm = "Kanonikus forma"
FactorizedForm = "Factorizált forma" FactorizedForm = "Factorizált forma"
Discriminant = "Discriminant" Discriminant = "Discriminant"
OnlyRoot = "Gyökér" OnlyRoot = "Gyökér"
FirstRoot = "Első gyökér" FirstRoot = "Első gyökér"
SecondRoot = "Második gyökér" SecondRoot = "Második gyökér"

View File

@@ -17,4 +17,4 @@ FactorizedForm = "Forma fattorizzata"
Discriminant = "Discriminante" Discriminant = "Discriminante"
OnlyRoot = "Radice" OnlyRoot = "Radice"
FirstRoot = "Prima radice" FirstRoot = "Prima radice"
SecondRoot = "Seconda radice" SecondRoot = "Seconda radice"

View File

@@ -17,4 +17,4 @@ FactorizedForm = "Factorized vorm"
Discriminant = "Discriminant" Discriminant = "Discriminant"
OnlyRoot = "Wortel" OnlyRoot = "Wortel"
FirstRoot = "Eerste wortel" FirstRoot = "Eerste wortel"
SecondRoot = "Tweede wortel" SecondRoot = "Tweede wortel"

View File

@@ -17,4 +17,4 @@ FactorizedForm = "Factorized form"
Discriminant = "Discriminante" Discriminant = "Discriminante"
OnlyRoot = "Raiz" OnlyRoot = "Raiz"
FirstRoot = "Primeira raiz" FirstRoot = "Primeira raiz"
SecondRoot = "Segunda raiz" SecondRoot = "Segunda raiz"

View File

@@ -251,14 +251,18 @@ Calculation::AdditionalInformationType Calculation::additionalInformationType(Co
* - > input: 2cos(2) - cos(2) * - > input: 2cos(2) - cos(2)
* > output: cos(2) * > output: cos(2)
*/ */
if (input().isDefinedCosineOrSine(context, complexFormat, preferences->angleUnit()) || o.isDefinedCosineOrSine(context, complexFormat, preferences->angleUnit())) { if (i.isDefinedCosineOrSineOrTangent(context, complexFormat, preferences->angleUnit())) {
return AdditionalInformationType::Trigonometry; return AdditionalInformationType::TrigonometryInput;
}
if (o.isDefinedCosineOrSineOrTangent(context, complexFormat, preferences->angleUnit())) {
return AdditionalInformationType::TrigonometryOutput;
} }
if (o.hasUnit()) { if (o.hasUnit()) {
Expression unit; Expression unit;
PoincareHelpers::ReduceAndRemoveUnit(&o, App::app()->localContext(), ExpressionNode::ReductionTarget::User, &unit, ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined, ExpressionNode::UnitConversion::None); PoincareHelpers::ReduceAndRemoveUnit(&o, App::app()->localContext(), ExpressionNode::ReductionTarget::User, &unit, ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined, ExpressionNode::UnitConversion::None);
double value = PoincareHelpers::ApproximateToScalar<double>(o, App::app()->localContext()); UnitNode::Vector<int> vector = UnitNode::Vector<int>::FromBaseUnits(unit);
return (Unit::ShouldDisplayAdditionalOutputs(value, unit, GlobalPreferences::sharedGlobalPreferences()->unitFormat())) ? AdditionalInformationType::Unit : AdditionalInformationType::None; const Unit::Representative * representative = Unit::Representative::RepresentativeForDimension(vector);
return representative != nullptr ? AdditionalInformationType::Unit : AdditionalInformationType::None;
} }
if (o.isBasedIntegerCappedBy(k_maximalIntegerWithAdditionalInformation)) { if (o.isBasedIntegerCappedBy(k_maximalIntegerWithAdditionalInformation)) {
return AdditionalInformationType::Integer; return AdditionalInformationType::Integer;

View File

@@ -40,7 +40,8 @@ public:
Integer, Integer,
Rational, Rational,
SecondDegree, SecondDegree,
Trigonometry, TrigonometryInput,
TrigonometryOutput,
Unit, Unit,
Matrix, Matrix,
Complex Complex
@@ -97,7 +98,7 @@ public:
AdditionalInformationType additionalInformationType(Poincare::Context * context); AdditionalInformationType additionalInformationType(Poincare::Context * context);
private: private:
static constexpr KDCoordinate k_heightComputationFailureHeight = 50; static constexpr KDCoordinate k_heightComputationFailureHeight = 50;
static constexpr const char * k_maximalIntegerWithAdditionalInformation = "10000000000000000"; static constexpr const char * k_maximalIntegerWithAdditionalInformation = "18446744073709551617"; // 2^64 + 1
void setHeights(KDCoordinate height, KDCoordinate expandedHeight); void setHeights(KDCoordinate height, KDCoordinate expandedHeight);

View File

@@ -7,6 +7,39 @@
#include "../exam_mode_configuration.h" #include "../exam_mode_configuration.h"
#include <assert.h> #include <assert.h>
#if defined _FXCG || defined NSPIRE_NEWLIB
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <apps/shared/global_context.h>
static KDCoordinate dummyHeight(::Calculation::Calculation * c, bool expanded) {
bool b;
Poincare::Layout l = c->createExactOutputLayout(&b);
if (!b) {
l=c->createInputLayout();
}
KDSize s = l.layoutSize();
const int bordersize = 10;
int h = s.height() + bordersize;
const int maxheight = 64;
if (h > maxheight) {
return maxheight;
}
return h;
}
extern void * last_calculation_history;
void * last_calculation_history = 0;
const char * retrieve_calc_history();
#endif
using namespace Poincare; using namespace Poincare;
using namespace Shared; using namespace Shared;
@@ -16,16 +49,55 @@ CalculationStore::CalculationStore(char * buffer, int size) :
m_buffer(buffer), m_buffer(buffer),
m_bufferSize(size), m_bufferSize(size),
m_calculationAreaEnd(m_buffer), m_calculationAreaEnd(m_buffer),
m_numberOfCalculations(0) m_numberOfCalculations(0),
m_trashIndex(-1)
{ {
assert(m_buffer != nullptr); assert(m_buffer != nullptr);
assert(m_bufferSize > 0); assert(m_bufferSize > 0);
#if defined _FXCG || defined NSPIRE_NEWLIB
if (last_calculation_history == 0){
// Restore from scriptstore
const char * buf=retrieve_calc_history();
if (buf) {
Shared::GlobalContext globalContext;
char * ptr=(char *)buf;
for (;*ptr;) {
for (;*ptr;++ptr) {
if (*ptr=='\n') {
break;
}
}
char c = *ptr;
*ptr=0;
if (ptr > buf) {
push(buf,&globalContext, dummyHeight);
}
*ptr = c;
++ptr;
buf = ptr;
}
}
last_calculation_history = (void *) this;
}
#endif
} }
// Returns an expiring pointer to the calculation of index i // Returns an expiring pointer to the calculation of index i, and ignore the trash
ExpiringPointer<Calculation> CalculationStore::calculationAtIndex(int i) { ExpiringPointer<Calculation> CalculationStore::calculationAtIndex(int i) {
#if defined _FXCG || defined NSPIRE_NEWLIB
last_calculation_history = (void *) this;
#endif
if (m_trashIndex == -1 || i < m_trashIndex) {
return realCalculationAtIndex(i);
} else {
return realCalculationAtIndex(i + 1);
}
}
// Returns an expiring pointer to the real calculation of index i
ExpiringPointer<Calculation> CalculationStore::realCalculationAtIndex(int i) {
assert(i >= 0 && i < m_numberOfCalculations); assert(i >= 0 && i < m_numberOfCalculations);
// m_buffer is the adress of the oldest calculation in calculation store // m_buffer is the address of the oldest calculation in calculation store
Calculation * c = (Calculation *) m_buffer; Calculation * c = (Calculation *) m_buffer;
if (i != m_numberOfCalculations-1) { if (i != m_numberOfCalculations-1) {
// The calculation we want is not the oldest one so we get its pointer // The calculation we want is not the oldest one so we get its pointer
@@ -36,12 +108,13 @@ ExpiringPointer<Calculation> CalculationStore::calculationAtIndex(int i) {
// Pushes an expression in the store // Pushes an expression in the store
ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context * context, HeightComputer heightComputer) { ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context * context, HeightComputer heightComputer) {
emptyTrash();
/* Compute ans now, before the buffer is updated and before the calculation /* Compute ans now, before the buffer is updated and before the calculation
* might be deleted */ * might be deleted */
Expression ans = ansExpression(context); Expression ans = ansExpression(context);
/* Prepare the buffer for the new calculation /* Prepare the buffer for the new calculation
*The minimal size to store the new calculation is the minimal size of a calculation plus the pointer to its end */ * The minimal size to store the new calculation is the minimal size of a calculation plus the pointer to its end */
int minSize = Calculation::MinimalSize() + sizeof(Calculation *); int minSize = Calculation::MinimalSize() + sizeof(Calculation *);
assert(m_bufferSize > minSize); assert(m_bufferSize > minSize);
while (remainingBufferSize() < minSize) { while (remainingBufferSize() < minSize) {
@@ -100,9 +173,9 @@ ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context *
numberOfSignificantDigits = Poincare::Preferences::sharedPreferences()->numberOfSignificantDigits(); numberOfSignificantDigits = Poincare::Preferences::sharedPreferences()->numberOfSignificantDigits();
} }
if (!pushSerializeExpression(outputs[i], beginingOfFreeSpace, &endOfFreeSpace, numberOfSignificantDigits)) { if (!pushSerializeExpression(outputs[i], beginingOfFreeSpace, &endOfFreeSpace, numberOfSignificantDigits)) {
/* If the exat/approximate output does not fit in the store (event if the /* If the exact/approximate output does not fit in the store (event if the
* current calculation is the only calculation), replace the output with * current calculation is the only calculation), replace the output with
* undef if it fits, else replace the whole calcualtion with undef. */ * undef if it fits, else replace the whole calculation with undef. */
Expression undef = Undefined::Builder(); Expression undef = Undefined::Builder();
if (!pushSerializeExpression(undef, beginingOfFreeSpace, &endOfFreeSpace)) { if (!pushSerializeExpression(undef, beginingOfFreeSpace, &endOfFreeSpace)) {
return emptyStoreAndPushUndef(context, heightComputer); return emptyStoreAndPushUndef(context, heightComputer);
@@ -132,15 +205,23 @@ ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context *
// Delete the calculation of index i // Delete the calculation of index i
void CalculationStore::deleteCalculationAtIndex(int i) { void CalculationStore::deleteCalculationAtIndex(int i) {
if (m_trashIndex != -1) {
emptyTrash();
}
m_trashIndex = i;
}
// Delete the calculation of index i, internal algorithm
void CalculationStore::realDeleteCalculationAtIndex(int i) {
assert(i >= 0 && i < m_numberOfCalculations); assert(i >= 0 && i < m_numberOfCalculations);
if (i == 0) { if (i == 0) {
ExpiringPointer<Calculation> lastCalculationPointer = calculationAtIndex(0); ExpiringPointer<Calculation> lastCalculationPointer = realCalculationAtIndex(0);
m_calculationAreaEnd = (char *)(lastCalculationPointer.pointer()); m_calculationAreaEnd = (char *)(lastCalculationPointer.pointer());
m_numberOfCalculations--; m_numberOfCalculations--;
return; return;
} }
char * calcI = (char *)calculationAtIndex(i).pointer(); char * calcI = (char *)realCalculationAtIndex(i).pointer();
char * nextCalc = (char *) calculationAtIndex(i-1).pointer(); char * nextCalc = (char *) realCalculationAtIndex(i-1).pointer();
assert(m_calculationAreaEnd >= nextCalc); assert(m_calculationAreaEnd >= nextCalc);
size_t slidingSize = m_calculationAreaEnd - nextCalc; size_t slidingSize = m_calculationAreaEnd - nextCalc;
// Slide the i-1 most recent calculations right after the i+1'th // Slide the i-1 most recent calculations right after the i+1'th
@@ -154,13 +235,14 @@ void CalculationStore::deleteCalculationAtIndex(int i) {
// Delete the oldest calculation in the store and returns the amount of space freed by the operation // Delete the oldest calculation in the store and returns the amount of space freed by the operation
size_t CalculationStore::deleteOldestCalculation() { size_t CalculationStore::deleteOldestCalculation() {
char * oldBufferEnd = (char *) m_calculationAreaEnd; char * oldBufferEnd = (char *) m_calculationAreaEnd;
deleteCalculationAtIndex(numberOfCalculations()-1); realDeleteCalculationAtIndex(numberOfCalculations()-1);
char * newBufferEnd = (char *) m_calculationAreaEnd; char * newBufferEnd = (char *) m_calculationAreaEnd;
return oldBufferEnd - newBufferEnd; return oldBufferEnd - newBufferEnd;
} }
// Delete all calculations // Delete all calculations
void CalculationStore::deleteAll() { void CalculationStore::deleteAll() {
m_trashIndex = -1;
m_calculationAreaEnd = m_buffer; m_calculationAreaEnd = m_buffer;
m_numberOfCalculations = 0; m_numberOfCalculations = 0;
} }
@@ -177,8 +259,8 @@ Expression CalculationStore::ansExpression(Context * context) {
* parsed), ans is replaced by the approximation output when any Store or * parsed), ans is replaced by the approximation output when any Store or
* Equal expression appears. */ * Equal expression appears. */
Expression e = mostRecentCalculation->exactOutput(); Expression e = mostRecentCalculation->exactOutput();
bool exactOuptutInvolvesStoreEqual = e.type() == ExpressionNode::Type::Store || e.type() == ExpressionNode::Type::Equal; bool exactOutputInvolvesStoreEqual = e.type() == ExpressionNode::Type::Store || e.type() == ExpressionNode::Type::Equal;
if (mostRecentCalculation->input().recursivelyMatches(Expression::IsApproximate, context) || exactOuptutInvolvesStoreEqual) { if (mostRecentCalculation->input().recursivelyMatches(Expression::IsApproximate, context) || exactOutputInvolvesStoreEqual) {
return mostRecentCalculation->approximateOutput(context, Calculation::NumberOfSignificantDigits::Maximal); return mostRecentCalculation->approximateOutput(context, Calculation::NumberOfSignificantDigits::Maximal);
} }
return mostRecentCalculation->exactOutput(); return mostRecentCalculation->exactOutput();
@@ -200,6 +282,12 @@ bool CalculationStore::pushSerializeExpression(Expression e, char * location, ch
return expressionIsPushed; return expressionIsPushed;
} }
void CalculationStore::emptyTrash() {
if (m_trashIndex != -1) {
realDeleteCalculationAtIndex(m_trashIndex);
m_trashIndex = -1;
}
}
Shared::ExpiringPointer<Calculation> CalculationStore::emptyStoreAndPushUndef(Context * context, HeightComputer heightComputer) { Shared::ExpiringPointer<Calculation> CalculationStore::emptyStoreAndPushUndef(Context * context, HeightComputer heightComputer) {
@@ -213,7 +301,7 @@ Shared::ExpiringPointer<Calculation> CalculationStore::emptyStoreAndPushUndef(Co
void CalculationStore::recomputeMemoizedPointersAfterCalculationIndex(int index) { void CalculationStore::recomputeMemoizedPointersAfterCalculationIndex(int index) {
assert(index < m_numberOfCalculations); assert(index < m_numberOfCalculations);
// Clear pointer and recompute new ones // Clear pointer and recompute new ones
Calculation * c = calculationAtIndex(index).pointer(); Calculation * c = realCalculationAtIndex(index).pointer();
Calculation * nextCalc; Calculation * nextCalc;
while (index != 0) { while (index != 0) {
nextCalc = c->next(); nextCalc = c->next();

View File

@@ -41,11 +41,15 @@ public:
void deleteCalculationAtIndex(int i); void deleteCalculationAtIndex(int i);
void deleteAll(); void deleteAll();
int remainingBufferSize() const { assert(m_calculationAreaEnd >= m_buffer); return m_bufferSize - (m_calculationAreaEnd - m_buffer) - m_numberOfCalculations*sizeof(Calculation*); } int remainingBufferSize() const { assert(m_calculationAreaEnd >= m_buffer); return m_bufferSize - (m_calculationAreaEnd - m_buffer) - m_numberOfCalculations*sizeof(Calculation*); }
int numberOfCalculations() const { return m_numberOfCalculations; } int numberOfCalculations() const { return m_numberOfCalculations - (m_trashIndex != -1); }
Poincare::Expression ansExpression(Poincare::Context * context); Poincare::Expression ansExpression(Poincare::Context * context);
int bufferSize() { return m_bufferSize; } int bufferSize() { return m_bufferSize; }
void reinsertTrash() { m_trashIndex = -1; }
private: private:
void emptyTrash();
Shared::ExpiringPointer<Calculation> realCalculationAtIndex(int i);
void realDeleteCalculationAtIndex(int i);
class CalculationIterator { class CalculationIterator {
public: public:
@@ -70,6 +74,7 @@ private:
int m_bufferSize; int m_bufferSize;
const char * m_calculationAreaEnd; const char * m_calculationAreaEnd;
int m_numberOfCalculations; int m_numberOfCalculations;
int m_trashIndex;
size_t deleteOldestCalculation(); size_t deleteOldestCalculation();
char * addressOfPointerToCalculationOfIndex(int i) {return m_buffer + m_bufferSize - (m_numberOfCalculations - i)*sizeof(Calculation *);} char * addressOfPointerToCalculationOfIndex(int i) {return m_buffer + m_bufferSize - (m_numberOfCalculations - i)*sizeof(Calculation *);}

View File

@@ -68,6 +68,15 @@ void EditExpressionController::memoizeInput() {
*m_cacheBufferInformation = m_contentView.expressionField()->moveCursorAndDumpContent(m_cacheBuffer, k_cacheBufferSize); *m_cacheBufferInformation = m_contentView.expressionField()->moveCursorAndDumpContent(m_cacheBuffer, k_cacheBufferSize);
} }
bool EditExpressionController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::ShiftBack) {
m_historyController->reinsertTrash();
m_historyController->reload();
return true;
}
return false;
}
void EditExpressionController::viewWillAppear() { void EditExpressionController::viewWillAppear() {
m_historyController->viewWillAppear(); m_historyController->viewWillAppear();
} }

View File

@@ -31,6 +31,7 @@ public:
void insertTextBody(const char * text); void insertTextBody(const char * text);
void restoreInput(); void restoreInput();
void memoizeInput(); void memoizeInput();
bool handleEvent(Ion::Events::Event event) override;
/* TextFieldDelegate */ /* TextFieldDelegate */
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;

View File

@@ -1,6 +1,9 @@
#include "expression_field.h" #include "expression_field.h"
#include <poincare/symbol.h> #include <poincare/symbol.h>
#include <poincare/horizontal_layout.h>
#include <poincare/code_point_layout.h>
using namespace Poincare;
namespace Calculation { namespace Calculation {
bool ExpressionField::handleEvent(Ion::Events::Event event) { bool ExpressionField::handleEvent(Ion::Events::Event event) {
@@ -21,7 +24,30 @@ bool ExpressionField::handleEvent(Ion::Events::Event event) {
event == Ion::Events::EE)) { event == Ion::Events::EE)) {
handleEventWithText(Poincare::Symbol::k_ans); handleEventWithText(Poincare::Symbol::k_ans);
} }
return(::ExpressionField::handleEvent(event)); if (event == Ion::Events::Minus
&& isEditing()
&& fieldHasOnlyAMinus()) {
setText(Poincare::Symbol::k_ans);
}
return (::ExpressionField::handleEvent(event));
}
bool ExpressionField::fieldHasOnlyAMinus() const {
if (editionIsInTextField()) {
const char *inputBuffer = m_textField.draftTextBuffer();
return (inputBuffer[0] == '-' && inputBuffer[1] == '\0');
}
Layout layout = m_layoutField.layout();
if (layout.type() == LayoutNode::Type::HorizontalLayout && layout.numberOfChildren() == 1) {
Layout child = layout.childAtIndex(0);
if (child.type() == LayoutNode::Type::CodePointLayout) {
CodePointLayout &codePointLayout = static_cast<CodePointLayout &>(child);
if (codePointLayout.codePoint() == '-'){
return true;
}
}
}
return false;
} }
} }

View File

@@ -13,6 +13,8 @@ public:
} }
protected: protected:
bool handleEvent(Ion::Events::Event event) override; bool handleEvent(Ion::Events::Event event) override;
private:
bool fieldHasOnlyAMinus() const;
}; };
} }

View File

@@ -103,12 +103,12 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
vc = &m_complexController; vc = &m_complexController;
} else if (additionalInfoType == Calculation::AdditionalInformationType::SecondDegree) { } else if (additionalInfoType == Calculation::AdditionalInformationType::SecondDegree) {
vc = &m_secondDegreeController; vc = &m_secondDegreeController;
} else if (additionalInfoType == Calculation::AdditionalInformationType::Trigonometry) { } else if (additionalInfoType == Calculation::AdditionalInformationType::TrigonometryInput) {
vc = &m_trigonometryController; vc = &m_trigonometryController;
// Find which of the input or output is the cosine/sine e = calculationAtIndex(focusRow)->input();
ExpressionNode::Type t = e.type(); } else if (additionalInfoType == Calculation::AdditionalInformationType::TrigonometryOutput) {
e = t == ExpressionNode::Type::Cosine || t == ExpressionNode::Type::Sine ? e : calculationAtIndex(focusRow)->input(); vc = &m_trigonometryController;
} else if (additionalInfoType == Calculation::AdditionalInformationType::Integer) { } else if (additionalInfoType == Calculation::AdditionalInformationType::Integer) {
vc = &m_integerController; vc = &m_integerController;
} else if (additionalInfoType == Calculation::AdditionalInformationType::Rational) { } else if (additionalInfoType == Calculation::AdditionalInformationType::Rational) {
vc = &m_rationalController; vc = &m_rationalController;

View File

@@ -35,6 +35,7 @@ public:
int typeAtLocation(int i, int j) override; int typeAtLocation(int i, int j) override;
void setSelectedSubviewType(SubviewType subviewType, bool sameCell, int previousSelectedX = -1, int previousSelectedY = -1) override; void setSelectedSubviewType(SubviewType subviewType, bool sameCell, int previousSelectedX = -1, int previousSelectedY = -1) override;
void tableViewDidChangeSelectionAndDidScroll(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) override; void tableViewDidChangeSelectionAndDidScroll(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) override;
void reinsertTrash() { m_calculationStore->reinsertTrash(); }
private: private:
int storeIndex(int i) { return numberOfRows() - i - 1; } int storeIndex(int i) { return numberOfRows() - i - 1; }
Shared::ExpiringPointer<Calculation> calculationAtIndex(int i); Shared::ExpiringPointer<Calculation> calculationAtIndex(int i);

View File

@@ -81,7 +81,7 @@ void HistoryViewCell::reloadSubviewHighlight() {
m_ellipsis.setHighlighted(false); m_ellipsis.setHighlighted(false);
if (isHighlighted()) { if (isHighlighted()) {
if (m_dataSource->selectedSubviewType() == HistoryViewCellDataSource::SubviewType::Input) { 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) { } else if (m_dataSource->selectedSubviewType() == HistoryViewCellDataSource::SubviewType::Output) {
m_scrollableOutputView.evenOddCell()->setHighlighted(true); m_scrollableOutputView.evenOddCell()->setHighlighted(true);
} else { } else {

View File

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

View File

@@ -3,6 +3,13 @@
#include <apps/i18n.h> #include <apps/i18n.h>
#include "helpers.h" #include "helpers.h"
#include <ion/unicode/utf8_helper.h> #include <ion/unicode/utf8_helper.h>
#include <apps/apps_container.h>
#if defined _FXCG || defined NSPIRE_NEWLIB
extern "C" int calculator;
extern "C" const int prizm_heap_size;
extern "C" char prizm_heap[];
#endif
namespace Code { namespace Code {
@@ -129,6 +136,16 @@ VariableBoxController * App::variableBoxForInputEventHandler(InputEventHandler *
} }
bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::Event event) { bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::Event event) {
if (event == Ion::Events::XNT) {
int bufferSize = CodePoint::MaxCodePointCharLength + 1;
char buffer[bufferSize];
bool shouldRemoveLastCharacter = false;
CodePoint codePoint = AppsContainer::sharedAppsContainer()->XNT('x', &shouldRemoveLastCharacter);
UTF8Decoder::CodePointToChars(codePoint, buffer, bufferSize);
buffer[UTF8Decoder::CharSizeOfCodePoint(codePoint)] = 0;
textInput->handleEventWithText(const_cast<char *>(buffer), false, false, shouldRemoveLastCharacter);
return true;
}
const char * pythonText = Helpers::PythonTextForEvent(event); const char * pythonText = Helpers::PythonTextForEvent(event);
if (pythonText != nullptr) { if (pythonText != nullptr) {
textInput->handleEventWithText(pythonText); textInput->handleEventWithText(pythonText);
@@ -139,7 +156,17 @@ bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::E
void App::initPythonWithUser(const void * pythonUser) { void App::initPythonWithUser(const void * pythonUser) {
if (!m_pythonUser) { if (!m_pythonUser) {
MicroPython::init(m_pythonHeap, m_pythonHeap + k_pythonHeapSize); #if defined _FXCG || defined NSPIRE_NEWLIB
if (calculator == 1) { // fxcg50
MicroPython::init( (void *) 0x8c200000, (void *)(0x8c200000+ 0x2e0000));
} else if (calculator >= 1 && calculator <=4 ) {
MicroPython::init( prizm_heap, prizm_heap+prizm_heap_size);
} else {
#endif
MicroPython::init(m_pythonHeap, m_pythonHeap + k_pythonHeapSize);
#if defined _FXCG || defined NSPIRE_NEWLIB
}
#endif
} }
m_pythonUser = pythonUser; m_pythonUser = pythonUser;
} }

View File

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

View File

@@ -1,3 +1,2 @@
CodeAppCapital = "PYTHON" CodeAppCapital = "PYTHON"
ConsolePrompt = ">>> " ConsolePrompt = ">>> "
ScriptParameters = "..."

View File

@@ -1,5 +1,11 @@
PythonPound = "Kommentar" PythonPound = "Kommentar"
PythonPercent = "Modulo" PythonPercent = "Modulo"
PythonColon = "Doppelpunkt"
PythonSemicon = "Semikolon"
PythonExclamationMark = "Ausrufezeichen"
PythonLessThan = "Kleiner als"
PythonGreaterThan = "Größer als"
PythonQuestionMark = "Fragezeichen"
Python1J = "Imaginäres i" Python1J = "Imaginäres i"
PythonLF = "Zeilenvorschub" PythonLF = "Zeilenvorschub"
PythonTab = "Tabulator" PythonTab = "Tabulator"
@@ -53,6 +59,7 @@ PythonErfc = "Komplementäre Fehlerfunktion"
PythonEval = "Rückgabe ausgewerteter Ausdruck" PythonEval = "Rückgabe ausgewerteter Ausdruck"
PythonExp = "Exponentialfunktion" PythonExp = "Exponentialfunktion"
PythonExpm1 = "Berechne exp(x)-1" PythonExpm1 = "Berechne exp(x)-1"
PythonFactorial = "Fakultät von x"
PythonFabs = "Absoluter Wert" PythonFabs = "Absoluter Wert"
PythonFillRect = "Gefülltes Rechteck bei Pixel (x,y)" PythonFillRect = "Gefülltes Rechteck bei Pixel (x,y)"
PythonFillCircle = "Füllt einen Kreis" PythonFillCircle = "Füllt einen Kreis"
@@ -102,10 +109,58 @@ PythonIsFinite = "Prüfen, ob x endlich ist"
PythonIsInfinite = "Prüfen, ob x unendlich ist" PythonIsInfinite = "Prüfen, ob x unendlich ist"
PythonIsNaN = "Prüfen, ob x keine Zahl ist" PythonIsNaN = "Prüfen, ob x keine Zahl ist"
PythonIsKeyDown = "Wahr, wenn die Taste k gedrückt ist" PythonIsKeyDown = "Wahr, wenn die Taste k gedrückt ist"
PythonBattery = "Return battery voltage" PythonBattery = "Rückgabe der Batteriespannung"
PythonBatteryLevel = "Return battery level" PythonBatteryLevel = "Gibt den Batteriestand zurück"
PythonBatteryIscharging = "Return if battery is charging" PythonBatteryIscharging = "Gibt zurück, ob die Batterie geladen wird"
PythonSetBrightness = "Helligkeitsstufe festlegen"
PythonGetBrightness = "Helligkeitsstufe abrufen"
PythonKandinskyFunction = "Kandinsky-Modul Funktionspräfix" PythonKandinskyFunction = "Kandinsky-Modul Funktionspräfix"
PythonKeyLeft = "LEFT ARROW key"
PythonKeyUp = "UP ARROW key"
PythonKeyDown = "DOWN ARROW key"
PythonKeyRight = "RIGHT ARROW key"
PythonKeyOk = "OK key"
PythonKeyBack = "BACK key"
PythonKeyHome = "HOME key"
PythonKeyOnOff = "ON/OFF key"
PythonKeyShift = "SHIFT key"
PythonKeyAlpha = "ALPHA key"
PythonKeyXnt = "X,N,T key"
PythonKeyVar = "VAR key"
PythonKeyToolbox = "TOOLBOX key"
PythonKeyBackspace = "BACKSPACE key"
PythonKeyExp = "EXPONENTIAL key"
PythonKeyLn = "NATURAL LOGARITHM key"
PythonKeyLog = "DECIMAL LOGARITHM key"
PythonKeyImaginary = "IMAGINARY I key"
PythonKeyComma = "COMMA key"
PythonKeyPower = "POWER key"
PythonKeySine = "SINE key"
PythonKeyCosine = "COSINE key"
PythonKeyTangent = "TANGENT key"
PythonKeyPi = "PI key"
PythonKeySqrt = "SQUARE ROOT key"
PythonKeySquare = "SQUARE key"
PythonKeySeven = "7 key"
PythonKeyEight = "8 key"
PythonKeyNine = "9 key"
PythonKeyLeftParenthesis = "LEFT PARENTHESIS key"
PythonKeyRightParenthesis = "RIGHT PARENTHESIS key"
PythonKeyFour = "4 key"
PythonKeyFive = "5 key"
PythonKeySix = "6 key"
PythonKeyMultiplication = "MULTIPLICATION key"
PythonKeyDivision = "DIVISION key"
PythonKeyOne = "1 key"
PythonKeyTwo = "2 key"
PythonKeyThree = "3 key"
PythonKeyPlus = "PLUS key"
PythonKeyMinus = "MINUS key"
PythonKeyZero = "0 key"
PythonKeyDot = "DOT key"
PythonKeyEe = "10 POWER X key"
PythonKeyAns = "ANS key"
PythonKeyExe = "EXE key"
PythonLdexp = "Liefert x*(2**i), Inverse von frexp" PythonLdexp = "Liefert x*(2**i), Inverse von frexp"
PythonLength = "Länge eines Objekts" PythonLength = "Länge eines Objekts"
PythonLgamma = "Log-Gamma-Funktion" PythonLgamma = "Log-Gamma-Funktion"
@@ -183,14 +238,11 @@ PythonTurtlePosition = "Aktuelle (x,y) Position zurückgeben"
PythonTurtleReset = "Die Zeichnung zurücksetzen" PythonTurtleReset = "Die Zeichnung zurücksetzen"
PythonTurtleRight = "Um ein Grad nach rechts drehen" PythonTurtleRight = "Um ein Grad nach rechts drehen"
PythonTurtleSetheading = "Ausrichtung auf einen Grad setzen" PythonTurtleSetheading = "Ausrichtung auf einen Grad setzen"
PythonTurtleSetposition = "Den Igel auf Position setzen"
PythonTurtleShowturtle = "Den Igel anzeigen" PythonTurtleShowturtle = "Den Igel anzeigen"
PythonTurtleSpeed = "Zeichengeschwindigkeit von 0 bis 10" PythonTurtleSpeed = "Zeichengeschwindigkeit von 0 bis 10"
PythonTurtleWrite = "Einen Text anzeigen" PythonTurtleWrite = "Einen Text anzeigen"
PythonUniform = "Fließkommazahl in [a,b]" PythonUniform = "Fließkommazahl in [a,b]"
PythonImportTime = "Time-Modul importieren" PythonImportTime = "Time-Modul importieren"
PythonTimePrefix = "Zeitmodul-Funktionspräfix"
PythonTimeSleep = "Warte für n Sekunden"
PythonMonotonic = "Monotone Zeit zurückgeben" PythonMonotonic = "Monotone Zeit zurückgeben"
PythonFileOpen = "Öffnet eine Datei" PythonFileOpen = "Öffnet eine Datei"
PythonFileSeekable = "Kann Datei durchsucht werden?" PythonFileSeekable = "Kann Datei durchsucht werden?"
@@ -208,3 +260,6 @@ PythonFileName = "Enthält den Namen der Datei"
PythonFileMode = "Enthält den Öffnungsmodus der Datei" PythonFileMode = "Enthält den Öffnungsmodus der Datei"
PythonFileReadable = "Kann Datei gelesen werden?" PythonFileReadable = "Kann Datei gelesen werden?"
PythonFileWritable = "Kann Datei geschrieben werden?" PythonFileWritable = "Kann Datei geschrieben werden?"
PythonImportUtils = "Importieren von ulab.utils"
PythonUtilsFunction = "Funktionspräfix des utils-Moduls"
PythonTurtleBgcolor = "Ändern Sie die Hintergrundfarbe"

View File

@@ -1,5 +1,11 @@
PythonPound = "Comment" PythonPound = "Comment"
PythonPercent = "Modulo" PythonPercent = "Modulo"
PythonColon = "Colon"
PythonSemicon = "Semicolon"
PythonExclamationMark = "Exclamation mark"
PythonLessThan = "Less than"
PythonGreaterThan = "Greater than"
PythonQuestionMark = "Question mark"
Python1J = "Imaginary i" Python1J = "Imaginary i"
PythonLF = "Line feed" PythonLF = "Line feed"
PythonTab = "Tabulation" PythonTab = "Tabulation"
@@ -53,6 +59,7 @@ PythonErfc = "Complementary error function"
PythonEval = "Return the evaluated expression" PythonEval = "Return the evaluated expression"
PythonExp = "Exponential function" PythonExp = "Exponential function"
PythonExpm1 = "Compute exp(x)-1" PythonExpm1 = "Compute exp(x)-1"
PythonFactorial = "Factorial of x"
PythonFabs = "Absolute value" PythonFabs = "Absolute value"
PythonFillCircle = "Fill a circle" PythonFillCircle = "Fill a circle"
PythonFillPolygon = "Fill a polygon" PythonFillPolygon = "Fill a polygon"
@@ -90,8 +97,56 @@ PythonIsKeyDown = "Return True if the k key is down"
PythonBattery = "Return battery voltage" PythonBattery = "Return battery voltage"
PythonBatteryLevel = "Return battery level" PythonBatteryLevel = "Return battery level"
PythonBatteryIscharging = "Return if battery is charging" PythonBatteryIscharging = "Return if battery is charging"
PythonSetBrightness = "Set brightness level"
PythonGetBrightness = "Get brightness level"
PythonIsNaN = "Check if x is a NaN" PythonIsNaN = "Check if x is a NaN"
PythonKandinskyFunction = "kandinsky module function prefix" PythonKandinskyFunction = "kandinsky module function prefix"
PythonKeyLeft = "LEFT ARROW key"
PythonKeyUp = "UP ARROW key"
PythonKeyDown = "DOWN ARROW key"
PythonKeyRight = "RIGHT ARROW key"
PythonKeyOk = "OK key"
PythonKeyBack = "BACK key"
PythonKeyHome = "HOME key"
PythonKeyOnOff = "ON/OFF key"
PythonKeyShift = "SHIFT key"
PythonKeyAlpha = "ALPHA key"
PythonKeyXnt = "X,N,T key"
PythonKeyVar = "VAR key"
PythonKeyToolbox = "TOOLBOX key"
PythonKeyBackspace = "BACKSPACE key"
PythonKeyExp = "EXPONENTIAL key"
PythonKeyLn = "NATURAL LOGARITHM key"
PythonKeyLog = "DECIMAL LOGARITHM key"
PythonKeyImaginary = "IMAGINARY I key"
PythonKeyComma = "COMMA key"
PythonKeyPower = "POWER key"
PythonKeySine = "SINE key"
PythonKeyCosine = "COSINE key"
PythonKeyTangent = "TANGENT key"
PythonKeyPi = "PI key"
PythonKeySqrt = "SQUARE ROOT key"
PythonKeySquare = "SQUARE key"
PythonKeySeven = "7 key"
PythonKeyEight = "8 key"
PythonKeyNine = "9 key"
PythonKeyLeftParenthesis = "LEFT PARENTHESIS key"
PythonKeyRightParenthesis = "RIGHT PARENTHESIS key"
PythonKeyFour = "4 key"
PythonKeyFive = "5 key"
PythonKeySix = "6 key"
PythonKeyMultiplication = "MULTIPLICATION key"
PythonKeyDivision = "DIVISION key"
PythonKeyOne = "1 key"
PythonKeyTwo = "2 key"
PythonKeyThree = "3 key"
PythonKeyPlus = "PLUS key"
PythonKeyMinus = "MINUS key"
PythonKeyZero = "0 key"
PythonKeyDot = "DOT key"
PythonKeyEe = "10 POWER X key"
PythonKeyAns = "ANS key"
PythonKeyExe = "EXE key"
PythonLdexp = "Return x*(2**i), inverse of frexp" PythonLdexp = "Return x*(2**i), inverse of frexp"
PythonLength = "Length of an object" PythonLength = "Length of an object"
PythonLgamma = "Log-gamma function" PythonLgamma = "Log-gamma function"
@@ -169,7 +224,6 @@ PythonTurtlePosition = "Return the current (x,y) location"
PythonTurtleReset = "Reset the drawing" PythonTurtleReset = "Reset the drawing"
PythonTurtleRight = "Turn right by a degrees" PythonTurtleRight = "Turn right by a degrees"
PythonTurtleSetheading = "Set the orientation to a degrees" PythonTurtleSetheading = "Set the orientation to a degrees"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Show the turtle" PythonTurtleShowturtle = "Show the turtle"
PythonTurtleSpeed = "Drawing speed between 0 and 10" PythonTurtleSpeed = "Drawing speed between 0 and 10"
PythonTurtleWrite = "Display a text" PythonTurtleWrite = "Display a text"
@@ -189,8 +243,6 @@ PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules" PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)" PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)" PythonSysVersioninfo = "Python language version (tuple)"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonMonotonic = "Return monotonic time" PythonMonotonic = "Return monotonic time"
PythonFileOpen = "Opens a file" PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file" PythonFileSeekable = "Tells if seek can be used on a file"
@@ -208,3 +260,6 @@ PythonFileName = "Contains file's name"
PythonFileMode = "Contains file's open mode" PythonFileMode = "Contains file's open mode"
PythonFileReadable = "Tells if read can be used on a file" PythonFileReadable = "Tells if read can be used on a file"
PythonFileWritable = "Tells if write can be used on a file" PythonFileWritable = "Tells if write can be used on a file"
PythonImportUtils = "Importing ulab.utils"
PythonUtilsFunction = "utils module function prefix"
PythonTurtleBgcolor = "Change the background color"

View File

@@ -1,5 +1,11 @@
PythonPound = "Comment" PythonPound = "Comment"
PythonPercent = "Modulo" PythonPercent = "Modulo"
PythonColon = "Colon"
PythonSemicon = "Semicolon"
PythonExclamationMark = "Exclamation mark"
PythonLessThan = "Less than"
PythonGreaterThan = "Greater than"
PythonQuestionMark = "Question mark"
Python1J = "Imaginary i" Python1J = "Imaginary i"
PythonLF = "Line feed" PythonLF = "Line feed"
PythonTab = "Tabulation" PythonTab = "Tabulation"
@@ -53,6 +59,7 @@ PythonErfc = "Complementary error function"
PythonEval = "Return the evaluated expression" PythonEval = "Return the evaluated expression"
PythonExp = "Exponential function" PythonExp = "Exponential function"
PythonExpm1 = "Compute exp(x)-1" PythonExpm1 = "Compute exp(x)-1"
PythonFactorial = "factorial de x"
PythonFabs = "Absolute value" PythonFabs = "Absolute value"
PythonFillCircle = "Fill a circle" PythonFillCircle = "Fill a circle"
PythonFillPolygon = "Fill a polygon" PythonFillPolygon = "Fill a polygon"
@@ -87,11 +94,59 @@ PythonIonFunction = "ion module function prefix"
PythonIsFinite = "Check if x is finite" PythonIsFinite = "Check if x is finite"
PythonIsInfinite = "Check if x is infinity" PythonIsInfinite = "Check if x is infinity"
PythonIsKeyDown = "Return True if the k key is down" PythonIsKeyDown = "Return True if the k key is down"
PythonBattery = "Return battery voltage" PythonBattery = "Rückgabe der Batteriespannung"
PythonBatteryLevel = "Return battery level" PythonBatteryLevel = "Gibt den Batteriestand zurück"
PythonBatteryIscharging = "Return if battery is charging" PythonBatteryIscharging = "Gibt zurück, ob die Batterie geladen wird"
PythonSetBrightness = "Establecer nivel de brillo"
PythonGetBrightness = "Obtener nivel de brillo"
PythonIsNaN = "Check if x is a NaN" PythonIsNaN = "Check if x is a NaN"
PythonKandinskyFunction = "kandinsky module function prefix" PythonKandinskyFunction = "kandinsky module function prefix"
PythonKeyLeft = "LEFT ARROW key"
PythonKeyUp = "UP ARROW key"
PythonKeyDown = "DOWN ARROW key"
PythonKeyRight = "RIGHT ARROW key"
PythonKeyOk = "OK key"
PythonKeyBack = "BACK key"
PythonKeyHome = "HOME key"
PythonKeyOnOff = "ON/OFF key"
PythonKeyShift = "SHIFT key"
PythonKeyAlpha = "ALPHA key"
PythonKeyXnt = "X,N,T key"
PythonKeyVar = "VAR key"
PythonKeyToolbox = "TOOLBOX key"
PythonKeyBackspace = "BACKSPACE key"
PythonKeyExp = "EXPONENTIAL key"
PythonKeyLn = "NATURAL LOGARITHM key"
PythonKeyLog = "DECIMAL LOGARITHM key"
PythonKeyImaginary = "IMAGINARY I key"
PythonKeyComma = "COMMA key"
PythonKeyPower = "POWER key"
PythonKeySine = "SINE key"
PythonKeyCosine = "COSINE key"
PythonKeyTangent = "TANGENT key"
PythonKeyPi = "PI key"
PythonKeySqrt = "SQUARE ROOT key"
PythonKeySquare = "SQUARE key"
PythonKeySeven = "7 key"
PythonKeyEight = "8 key"
PythonKeyNine = "9 key"
PythonKeyLeftParenthesis = "LEFT PARENTHESIS key"
PythonKeyRightParenthesis = "RIGHT PARENTHESIS key"
PythonKeyFour = "4 key"
PythonKeyFive = "5 key"
PythonKeySix = "6 key"
PythonKeyMultiplication = "MULTIPLICATION key"
PythonKeyDivision = "DIVISION key"
PythonKeyOne = "1 key"
PythonKeyTwo = "2 key"
PythonKeyThree = "3 key"
PythonKeyPlus = "PLUS key"
PythonKeyMinus = "MINUS key"
PythonKeyZero = "0 key"
PythonKeyDot = "DOT key"
PythonKeyEe = "10 POWER X key"
PythonKeyAns = "ANS key"
PythonKeyExe = "EXE key"
PythonLdexp = "Return x*(2**i), inverse of frexp" PythonLdexp = "Return x*(2**i), inverse of frexp"
PythonLength = "Length of an object" PythonLength = "Length of an object"
PythonLgamma = "Log-gamma function" PythonLgamma = "Log-gamma function"
@@ -169,7 +224,6 @@ PythonTurtlePosition = "Return the current (x,y) location"
PythonTurtleReset = "Reset the drawing" PythonTurtleReset = "Reset the drawing"
PythonTurtleRight = "Turn right by a degrees" PythonTurtleRight = "Turn right by a degrees"
PythonTurtleSetheading = "Set the orientation to a degrees" PythonTurtleSetheading = "Set the orientation to a degrees"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Show the turtle" PythonTurtleShowturtle = "Show the turtle"
PythonTurtleSpeed = "Drawing speed between 0 and 10" PythonTurtleSpeed = "Drawing speed between 0 and 10"
PythonTurtleWrite = "Display a text" PythonTurtleWrite = "Display a text"
@@ -189,8 +243,6 @@ PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules" PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)" PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)" PythonSysVersioninfo = "Python language version (tuple)"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Esperar n segundos"
PythonMonotonic = "Tiempo monótono de retorno" PythonMonotonic = "Tiempo monótono de retorno"
PythonFileOpen = "Opens a file" PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file" PythonFileSeekable = "Tells if seek can be used on a file"
@@ -208,3 +260,6 @@ PythonFileName = "Contains file's name"
PythonFileMode = "Contains file's open mode" PythonFileMode = "Contains file's open mode"
PythonFileReadable = "Tells if read can be used on a file" PythonFileReadable = "Tells if read can be used on a file"
PythonFileWritable = "Tells if write can be used on a file" PythonFileWritable = "Tells if write can be used on a file"
PythonImportUtils = "Importando ulab.utils"
PythonUtilsFunction = "prefijo de función del módulo utils"
PythonTurtleBgcolor = "Cambiar el color de fondo"

View File

@@ -1,5 +1,11 @@
PythonPound = "Commentaire" PythonPound = "Commentaire"
PythonPercent = "Modulo" PythonPercent = "Modulo"
PythonColon = "Deux-points"
PythonSemicon = "Point-virgule"
PythonExclamationMark = "Point d'exclamation"
PythonLessThan = "Inférieur à"
PythonGreaterThan = "Supérieur à"
PythonQuestionMark = "Point d'interrogation"
Python1J = "i complexe" Python1J = "i complexe"
PythonLF = "Saut à la ligne" PythonLF = "Saut à la ligne"
PythonTab = "Tabulation" PythonTab = "Tabulation"
@@ -53,6 +59,7 @@ PythonErfc = "Fonction d'erreur complémentaire"
PythonEval = "Evalue l'expression en argument " PythonEval = "Evalue l'expression en argument "
PythonExp = "Fonction exponentielle" PythonExp = "Fonction exponentielle"
PythonExpm1 = "Calcul de exp(x)-1" PythonExpm1 = "Calcul de exp(x)-1"
PythonFactorial = "Factorielle de x"
PythonFabs = "Valeur absolue" PythonFabs = "Valeur absolue"
PythonFillCircle = "Remplit un cercle" PythonFillCircle = "Remplit un cercle"
PythonFillPolygon = "Remplit un polygone" PythonFillPolygon = "Remplit un polygone"
@@ -77,6 +84,7 @@ PythonImportMath = "Importation du module math"
PythonImportMatplotlibPyplot = "Importation de matplotlib.pyplot" PythonImportMatplotlibPyplot = "Importation de matplotlib.pyplot"
PythonImportNumpy = "Importation de ulab.numpy" PythonImportNumpy = "Importation de ulab.numpy"
PythonImportScipy = "Importation de ulab.scipy" PythonImportScipy = "Importation de ulab.scipy"
PythonImportUtils = "Importation de ulab.utils"
PythonImportTurtle = "Importation du module turtle" PythonImportTurtle = "Importation du module turtle"
PythonImportTime = "Importation du module time" PythonImportTime = "Importation du module time"
PythonIndex = "Indice première occurrence de x" PythonIndex = "Indice première occurrence de x"
@@ -90,8 +98,56 @@ PythonIsKeyDown = "Renvoie True si touche k enfoncée"
PythonBattery = "Renvoie le voltage de la batterie" PythonBattery = "Renvoie le voltage de la batterie"
PythonBatteryLevel = "Renvoie le niveau de la batterie" PythonBatteryLevel = "Renvoie le niveau de la batterie"
PythonBatteryIscharging = "Chargement en cours" PythonBatteryIscharging = "Chargement en cours"
PythonSetBrightness = "Définir le niveau de luminosité"
PythonGetBrightness = "Obtenir le niveau de luminosité"
PythonIsNaN = "Teste si x est NaN" PythonIsNaN = "Teste si x est NaN"
PythonKandinskyFunction = "Préfixe fonction module kandinsky" PythonKandinskyFunction = "Préfixe fonction module kandinsky"
PythonKeyLeft = "Touche FLECHE GAUCHE"
PythonKeyUp = "Touche FLECHE HAUT"
PythonKeyDown = "Touche FLECHE BAS"
PythonKeyRight = "Touche FLECHE DROITE"
PythonKeyOk = "Touche OK"
PythonKeyBack = "Touche RETOUR"
PythonKeyHome = "Touche HOME"
PythonKeyOnOff = "Touche ON/OFF"
PythonKeyShift = "Touche SHIFT"
PythonKeyAlpha = "Touche ALPHA"
PythonKeyXnt = "Touche X,N,T"
PythonKeyVar = "Touche VAR"
PythonKeyToolbox = "Touche BOITE A OUTILS"
PythonKeyBackspace = "Touche EFFACER"
PythonKeyExp = "Touche EXPONENTIELLE"
PythonKeyLn = "Touche LOGARITHME NEPERIEN"
PythonKeyLog = "Touche LOGARITHME DECIMAL"
PythonKeyImaginary = "Touche I IMAGINAIRE"
PythonKeyComma = "Touche VIRGULE"
PythonKeyPower = "Touche PUISSANCE"
PythonKeySine = "Touche SINUS"
PythonKeyCosine = "Touche COSINUS"
PythonKeyTangent = "Touche TANGENTE"
PythonKeyPi = "Touche PI"
PythonKeySqrt = "Touche RACINE CARREE"
PythonKeySquare = "Touche CARRE"
PythonKeySeven = "Touche 7"
PythonKeyEight = "Touche 8"
PythonKeyNine = "Touche 9"
PythonKeyLeftParenthesis = "Touche PARENTHESE GAUCHE"
PythonKeyRightParenthesis = "Touche PARENTHESE DROITE"
PythonKeyFour = "Touche 4"
PythonKeyFive = "Touche 5"
PythonKeySix = "Touche 6"
PythonKeyMultiplication = "Touche MULTIPLICATION"
PythonKeyDivision = "Touche DIVISION"
PythonKeyOne = "Touche 1"
PythonKeyTwo = "Touche 2"
PythonKeyThree = "Touche 3"
PythonKeyPlus = "Touche PLUS"
PythonKeyMinus = "Touche MOINS"
PythonKeyZero = "Touche 0"
PythonKeyDot = "Touche POINT"
PythonKeyEe = "Touche 10 PUISSANCE X"
PythonKeyAns = "Touche ANS"
PythonKeyExe = "Touche EXE"
PythonLdexp = "Inverse de frexp : x*(2**i)" PythonLdexp = "Inverse de frexp : x*(2**i)"
PythonLength = "Longueur d'un objet" PythonLength = "Longueur d'un objet"
PythonLgamma = "Logarithme de la fonction gamma" PythonLgamma = "Logarithme de la fonction gamma"
@@ -112,6 +168,7 @@ PythonScipyLinalgFunction = "Préfixe fonction du module scipy.linalg"
PythonScipyOptimizeFunction = "Préfixe fonction du module scipy.optimize" PythonScipyOptimizeFunction = "Préfixe fonction du module scipy.optimize"
PythonScipySignalFunction = "Préfixe fonction du module scipy.signal" PythonScipySignalFunction = "Préfixe fonction du module scipy.signal"
PythonScipySpecialFunction = "Préfixe fonction du module scipy.special" PythonScipySpecialFunction = "Préfixe fonction du module scipy.special"
PythonUtilsFunction = "Préfixe fonction du module utils"
PythonOct = "Conversion en octal" PythonOct = "Conversion en octal"
PythonPhase = "Argument de z" PythonPhase = "Argument de z"
PythonPlot = "Trace y en fonction de x" PythonPlot = "Trace y en fonction de x"
@@ -127,7 +184,7 @@ PythonRandrange = "Nombre dans range(start,stop)"
PythonRangeStartStop = "Liste de start à stop-1" PythonRangeStartStop = "Liste de start à stop-1"
PythonRangeStop = "Liste de 0 à stop-1" PythonRangeStop = "Liste de 0 à stop-1"
PythonRect = "Conversion en algébrique" PythonRect = "Conversion en algébrique"
PythonRemove = "Supprime le premier x de la liste" PythonRemove = "Supprime le premier x de la liste"
PythonReverse = "Inverse les éléments de la liste" PythonReverse = "Inverse les éléments de la liste"
PythonRound = "Arrondi à n décimales" PythonRound = "Arrondi à n décimales"
PythonScatter = "Nuage des points (x,y)" PythonScatter = "Nuage des points (x,y)"
@@ -155,6 +212,7 @@ PythonTurtleBackward = "Recule de x pixels"
PythonTurtleCircle = "Cercle de rayon r pixels" PythonTurtleCircle = "Cercle de rayon r pixels"
PythonTurtleColor = "Modifie la couleur du tracé" PythonTurtleColor = "Modifie la couleur du tracé"
PythonTurtleColorMode = "Met le mode de couleur à 1.0 ou 255" PythonTurtleColorMode = "Met le mode de couleur à 1.0 ou 255"
PythonTurtleBgcolor = "Modifie la couleur du fond"
PythonTurtleForward = "Avance de x pixels" PythonTurtleForward = "Avance de x pixels"
PythonTurtleFunction = "Préfixe fonction du module turtle" PythonTurtleFunction = "Préfixe fonction du module turtle"
PythonTurtleGoto = "Va au point de coordonnées (x,y)" PythonTurtleGoto = "Va au point de coordonnées (x,y)"
@@ -169,7 +227,6 @@ PythonTurtlePosition = "Renvoie la position (x,y)"
PythonTurtleReset = "Réinitialise le dessin" PythonTurtleReset = "Réinitialise le dessin"
PythonTurtleRight = "Pivote de a degrés vers la droite" PythonTurtleRight = "Pivote de a degrés vers la droite"
PythonTurtleSetheading = "Met un cap de a degrés" PythonTurtleSetheading = "Met un cap de a degrés"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Affiche la tortue" PythonTurtleShowturtle = "Affiche la tortue"
PythonTurtleSpeed = "Vitesse du tracé entre 0 et 10" PythonTurtleSpeed = "Vitesse du tracé entre 0 et 10"
PythonTurtleWrite = "Affiche un texte" PythonTurtleWrite = "Affiche un texte"
@@ -189,8 +246,6 @@ PythonSysImplementation = "Information sur Python"
PythonSysModules = "Dictionnaire des modules chargés" PythonSysModules = "Dictionnaire des modules chargés"
PythonSysVersion = "Version du langage Python (string)" PythonSysVersion = "Version du langage Python (string)"
PythonSysVersioninfo = "Version du langage Python (tuple)" PythonSysVersioninfo = "Version du langage Python (tuple)"
PythonTimePrefix = "Préfixe fonction du module temps"
PythonTimeSleep = "Attendre n secondes"
PythonMonotonic = "Retourne le temps monotone" PythonMonotonic = "Retourne le temps monotone"
PythonFileOpen = "Ouvre un fichier" PythonFileOpen = "Ouvre un fichier"
PythonFileSeekable = "Indique si seek peut être utilisé" PythonFileSeekable = "Indique si seek peut être utilisé"

View File

@@ -1,210 +1,265 @@
PythonPound = "Megjegyzés" PythonPound = "Megjegyzés"
PythonPercent = "Modulo" PythonPercent = "Modulo"
Python1J = "Képzeletbeli i" PythonColon = "Kettőspont"
PythonLF = "Enter" PythonSemicon = "Pontosvessző"
PythonTab = "Táblázat" PythonExclamationMark = "Felkiáltójel"
PythonAmpersand = "Logikus és" PythonLessThan = "Kisebb mint"
PythonSymbolExp = "logikus exkluzív vagy pedig" PythonGreaterThan = "Nagyobb mint"
PythonVerticalBar = "logikus vagy pedig" PythonQuestionMark = "Kérdőjel"
PythonImag = "z képzeletbeli része" Python1J = "Képzeletbeli i"
PythonReal = "z valódi része" PythonLF = "Enter"
PythonSingleQuote = "apostróf" PythonTab = "Táblázat"
PythonAbs = "Abszolút érték/nagyság" PythonAmpersand = "Logikus és"
PythonAcos = "Ív (arc) koszinusz" PythonSymbolExp = "logikus exkluzív vagy pedig"
PythonAcosh = "Hiperbolikus arc koszinusz" PythonVerticalBar = "logikus vagy pedig"
PythonAppend = "Lista végére hozzáadni x-et" PythonImag = "z képzeletbeli része"
PythonArrow = "(x,y) nyíla (x+dx,y+dy) nyílához" PythonReal = "z valódi része"
PythonAsin = "Ív (arc) szinusz" PythonSingleQuote = "apostróf"
PythonAsinh = "Hiperbolikus ív (arc) szinusz" PythonAbs = "Abszolút érték/nagyság"
PythonAtan = "Ív (arc) érintö (tan)" PythonAcos = "Ív (arc) koszinusz"
PythonAtan2 = "atan(y/x) sámolása" PythonAcosh = "Hiperbolikus arc koszinusz"
PythonAtanh = "Hiperbolikus ív (arc) érintö (atan)" PythonAppend = "Lista végére hozzáadni x-et"
PythonAxis = "Tengelyeket (xmin,xmax,ymin,ymax)-ra állitani" PythonArrow = "(x,y) nyíla (x+dx,y+dy) nyílához"
PythonBar = "Az x lista oszlopdiagramja" PythonAsin = "Ív (arc) szinusz"
PythonBin = "Egész szám konvertálása binárisra" PythonAsinh = "Hiperbolikus ív (arc) szinusz"
PythonCeil = "Mennyezet" PythonAtan = "Ív (arc) érintö (tan)"
PythonChoice = "Véletlenszerü szám a listában" PythonAtan2 = "atan(y/x) sámolása"
PythonClear = "A lista ürítése" PythonAtanh = "Hiperbolikus ív (arc) érintö (atan)"
PythonCmathFunction = "cmath modul funkció elötag" PythonAxis = "Tengelyeket (xmin,xmax,ymin,ymax)-ra állitani"
PythonColor = "Rgb (pzk) szín allítása" PythonBar = "Az x lista oszlopdiagramja"
PythonColorBlack = "Fekete szín" PythonBin = "Egész szám konvertálása binárisra"
PythonColorBlue = "Kék szín" PythonCeil = "Mennyezet"
PythonColorBrown = "Barna szín" PythonChoice = "Véletlenszerü szám a listában"
PythonColorGreen = "Zöld szín" PythonClear = "A lista ürítése"
PythonColorGray = "Szürke szín" PythonCmathFunction = "cmath modul funkció elötag"
PythonColorOrange = "Narancssárga szín" PythonColor = "Rgb (pzk) szín allítása"
PythonColorPink = "Rózsaszín szín" PythonColorBlack = "Fekete szín"
PythonColorPurple = "Lila szín" PythonColorBlue = "Kék szín"
PythonColorRed = "Piros szín" PythonColorBrown = "Barna szín"
PythonColorWhite = "Fehér szín" PythonColorGreen = "Zöld szín"
PythonColorYellow = "Sárga szín" PythonColorGray = "Szürke szín"
PythonComplex = "A + ib visszaadása" PythonColorOrange = "Narancssárga szín"
PythonCopySign = "X visszaadása y jelével" PythonColorPink = "Rózsaszín szín"
PythonCos = "Koszinusz" PythonColorPurple = "Lila szín"
PythonCosh = "Hiperbolikus koszinusz" PythonColorRed = "Piros szín"
PythonCount = "Számolja az x elöfordulását" PythonColorWhite = "Fehér szín"
PythonDegrees = "x konvertálása radiánokrol fokokra" PythonColorYellow = "Sárga szín"
PythonDivMod = "Hányados és maradék" PythonComplex = "A + ib visszaadása"
PythonDrawCircle = "Rajzolj egy kört" PythonCopySign = "X visszaadása y jelével"
PythonDrawLine = "Húzzon egy vonalat " PythonCos = "Koszinusz"
PythonDrawString = "Szöveg megjelenítése (x, y)-en" PythonCosh = "Hiperbolikus koszinusz"
PythonErf = "Hiba funkció" PythonCount = "Számolja az x elöfordulását"
PythonErfc = "Kiegészítö hiba funkció" PythonDegrees = "x konvertálása radiánokrol fokokra"
PythonEval = "Visszaadja az értékelt kifejezést" PythonDivMod = "Hányados és maradék"
PythonExp = "Exponenciális függvény" PythonDrawCircle = "Rajzolj egy kört"
PythonExpm1 = "exp(x)-1 sámitása" PythonDrawLine = "Húzzon egy vonalat "
PythonFabs = "Abszolút érték" PythonDrawString = "Szöveg megjelenítése (x, y)-en"
PythonFillRect = "Téglalap töltése" PythonErf = "Hiba funkció"
PythonFillCircle = "Kitölti a kört" PythonErfc = "Kiegészítö hiba funkció"
PythonFillPolygon = "Kitölti a poligont" PythonEval = "Visszaadja az értékelt kifejezést"
PythonFloat = "Konvertálása tizedes számra" PythonExp = "Exponenciális függvény"
PythonFloor = "Egész része" PythonExpm1 = "exp(x)-1 sámitása"
PythonFmod = "a modulo b" PythonFactorial = "x faktorál"
PythonFrExp = "X mantissája és kiállítója" PythonFabs = "Abszolút érték"
PythonGamma = "Gamma funkció" PythonFillRect = "Téglalap töltése"
PythonGetKeys = "Billentyűk lenyomva" PythonFillCircle = "Kitölti a kört"
PythonGetPalette = "Téma paletta beszerzése" PythonFillPolygon = "Kitölti a poligont"
PythonGetPixel = "Visszatéríti (x,y) színét" PythonFloat = "Konvertálása tizedes számra"
PythonGetrandbits = "Váletlenszám visszatérítése k biten" PythonFloor = "Egész része"
PythonGrid = "Rács megjelenítése/elrejtése" PythonFmod = "a modulo b"
PythonHex = "Decimális szám konvertálása hexadecimális számra" PythonFrExp = "X mantissája és kiállítója"
PythonHist = "x hisztográmiája" PythonGamma = "Gamma funkció"
PythonImportCmath = "cmath modul importálása" PythonGetKeys = "Billentyűk lenyomva"
PythonImportIon = "Ion modul importálása" PythonGetPalette = "Téma paletta beszerzése"
PythonImportKandinsky = "Kandinsky modul importálása" PythonGetPixel = "Visszatéríti (x,y) színét"
PythonImportRandom = "Véletlenszerü modul importálása" PythonGetrandbits = "Váletlenszám visszatérítése k biten"
PythonImportMath = "math modul importálása" PythonGrid = "Rács megjelenítése/elrejtése"
PythonImportMatplotlibPyplot = "matplotlib.pyplot modul importálása" PythonHex = "Decimális szám konvertálása hexadecimális számra"
PythonImportNumpy = "ulab.numpy modul importálása" PythonHist = "x hisztográmiája"
PythonImportScipy = "ulab.scipy modul importálása" PythonImportCmath = "cmath modul importálása"
PythonImportTurtle = "turtle modul importálása" PythonImportIon = "Ion modul importálása"
PythonImportTime = "time modul importálása" PythonImportKandinsky = "Kandinsky modul importálása"
PythonIndex = "Az elsö x esemény indexe" PythonImportRandom = "Véletlenszerü modul importálása"
PythonInput = "Irjon egy értéket (számot)" PythonImportMath = "math modul importálása"
PythonInsert = "x-et i. pozícióra helyezze a listában" PythonImportMatplotlibPyplot = "matplotlib.pyplot modul importálása"
PythonInt = "egész számra konvertálás" PythonImportNumpy = "ulab.numpy modul importálása"
PythonIonFunction = "ion modul funkció elötag" PythonImportScipy = "ulab.scipy modul importálása"
PythonIsFinite = "x véges-e" PythonImportTurtle = "turtle modul importálása"
PythonIsInfinite = "x végtelen-e" PythonImportTime = "time modul importálása"
PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva" PythonIndex = "Az elsö x esemény indexe"
PythonBattery = "Return battery voltage" PythonInput = "Irjon egy értéket (számot)"
PythonBatteryLevel = "Return battery level" PythonInsert = "x-et i. pozícióra helyezze a listában"
PythonBatteryIscharging = "Return if battery is charging" PythonInt = "egész számra konvertálás"
PythonIsNaN = "Ellenörizze hogy x nem NaN" PythonIonFunction = "ion modul funkció elötag"
PythonKandinskyFunction = "kandinsky modul funkció elötag" PythonIsFinite = "x véges-e"
PythonLdexp = "frexp ellentéte : x*(2**i)" PythonIsInfinite = "x végtelen-e"
PythonLength = "Egy targy hossza" PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva"
PythonLgamma = "Gamma funkció logaritmusa" PythonBattery = "Az akkumulátor feszültségének visszaadása"
PythonLog = "a alapú logaritmus" PythonBatteryLevel = "Az akkumulátor töltöttségi szintjének visszaadása"
PythonLog10 = "Decimális logaritmus" PythonBatteryIscharging = "Visszaadja, ha az akkumulátor töltődik"
PythonLog2 = "Bináris logaritmus" PythonSetBrightness = "Fényerőszint beállítása"
PythonMathFunction = "math modul funkció elötag" PythonGetBrightness = "Get brightness level"
PythonMatplotlibPyplotFunction = "matplotlib.pyplot elötag" PythonIsNaN = "Ellenörizze hogy x nem NaN"
PythonMax = "Maximum" PythonKandinskyFunction = "kandinsky modul funkció elötag"
PythonMin = "Minimum" PythonLdexp = "frexp ellentéte : x*(2**i)"
PythonModf = "x-nek tört és egész részei" PythonLength = "Egy targy hossza"
PythonMonotonic = "Az óra értékét adja vissza" PythonLgamma = "Gamma funkció logaritmusa"
PythonNumpyFunction = "numpy elötag" PythonLog = "a alapú logaritmus"
PythonNumpyFftFunction = "numpy.fft elötag" PythonLog10 = "Decimális logaritmus"
PythonNumpyLinalgFunction = "numpy.linalg elötag" PythonLog2 = "Bináris logaritmus"
PythonScipyFunction = "scipy elötag" PythonMathFunction = "math modul funkció elötag"
PythonScipyLinalgFunction = "scipy.linalg elötag" PythonMatplotlibPyplotFunction = "matplotlib.pyplot elötag"
PythonScipyOptimizeFunction = "scipy.optimize elötag" PythonMax = "Maximum"
PythonScipySignalFunction = "scipy.signal elötag" PythonMin = "Minimum"
PythonScipySpecialFunction = "scipy.special elötag" PythonModf = "x-nek tört és egész részei"
PythonOct = "Decimális szám konvertálása octális számra" PythonMonotonic = "Az óra értékét adja vissza"
PythonPhase = "z fázisa" PythonNumpyFunction = "numpy elötag"
PythonPlot = "y-t jelöli x függvényében" PythonNumpyFftFunction = "numpy.fft elötag"
PythonPolar = "Verctorizálni" PythonNumpyLinalgFunction = "numpy.linalg elötag"
PythonPop = "Az utolsó elemet el törölni" PythonScipyFunction = "scipy elötag"
PythonPower = "x y. kitevö" PythonScipyLinalgFunction = "scipy.linalg elötag"
PythonPrint = "Ki irni a elemeket" PythonScipyOptimizeFunction = "scipy.optimize elötag"
PythonRadians = "Fokról radiánra konvertálni" PythonScipySignalFunction = "scipy.signal elötag"
PythonRandint = "Véletlen egész szám [a;b] -ban" PythonScipySpecialFunction = "scipy.special elötag"
PythonRandom = "Decimális szám [0;1] -ban" PythonOct = "Decimális szám konvertálása octális számra"
PythonRandomFunction = "random modul funkció elötag" PythonPhase = "z fázisa"
PythonRandrange = "Véletlen szám range(start,stop)-ban" PythonPlot = "y-t jelöli x függvényében"
PythonRangeStartStop = "start-tol stop-ig listája" PythonPolar = "Verctorizálni"
PythonRangeStop = "0 tol stop-ig lista" PythonPop = "Az utolsó elemet el törölni"
PythonRect = "Algebrai számra konvertálni" PythonPower = "x y. kitevö"
PythonRemove = "Elsö x elöfordulását törolni" PythonPrint = "Ki irni a elemeket"
PythonReverse = "A lista elemeit megfordítani (másik irány)" PythonRadians = "Fokról radiánra konvertálni"
PythonRound = "N számjegyre kerekítni" PythonRandint = "Véletlen egész szám [a;b] -ban"
PythonScatter = "(x,y) halmaza" PythonRandom = "Decimális szám [0;1] -ban"
PythonSeed = "Inicializálni a véletlenszám-választót" PythonRandomFunction = "random modul funkció elötag"
PythonSetPixel = "Az (x,y) pixel-t ki szinezni" PythonRandrange = "Véletlen szám range(start,stop)-ban"
PythonShow = "Mutassa az ábrát" PythonRangeStartStop = "start-tol stop-ig listája"
PythonSin = "Szinusz" PythonRangeStop = "0 tol stop-ig lista"
PythonSinh = "Hiperbolikus szinusz" PythonRect = "Algebrai számra konvertálni"
PythonSleep = "t másodpercre meg állitani a programmot" PythonRemove = "Elsö x elöfordulását törolni"
PythonLocalTime = "Idő konvertálása csomóvá" PythonReverse = "A lista elemeit megfordítani (másik irány)"
PythonMktime = "A tuple konvertálása az időben" PythonRound = "N számjegyre kerekítni"
PythonTime = "Az aktuális időbélyeg letöltése" PythonScatter = "(x,y) halmaza"
PythonSetLocaltime = "Idő beállítása egy csomóból" PythonSeed = "Inicializálni a véletlenszám-választót"
PythonRTCmode = "Aktuális RTC mód" PythonSetPixel = "Az (x,y) pixel-t ki szinezni"
PythonSetRTCmode = "RTC mód beállítása" PythonShow = "Mutassa az ábrát"
PythonSort = "A listát rendezni" PythonSin = "Szinusz"
PythonSqrt = "Négyzetgyök" PythonSinh = "Hiperbolikus szinusz"
PythonSum = "Összeadni a lista elemeit" PythonSleep = "t másodpercre meg állitani a programmot"
PythonTan = "Érintö (tan)" PythonLocalTime = "Idő konvertálása csomóvá"
PythonTanh = "Hiperbolikus érintö (tan)" PythonMktime = "A tuple konvertálása az időben"
PythonText = "(x,y) nél egy szöveget irni" PythonTime = "Az aktuális időbélyeg letöltése"
PythonTimeFunction = "time funkció elötag" PythonSetLocaltime = "Idő beállítása egy csomóból"
PythonTrunc = "Egész csonka (?)" PythonRTCmode = "Aktuális RTC mód"
PythonTurtleBackward = "x pixelt hátra" PythonSetRTCmode = "RTC mód beállítása"
PythonTurtleCircle = "r pixel sugarú kört rajzolni" PythonSort = "A listát rendezni"
PythonTurtleColor = "Toll szinét beállitani" PythonSqrt = "Négyzetgyök"
PythonTurtleColorMode = "Szin módot 1.0-ra vagy 255-ra állitani" PythonSum = "Összeadni a lista elemeit"
PythonTurtleForward = "x pixelt elölre" PythonTan = "Érintö (tan)"
PythonTurtleFunction = "turtle modul funkció elötag" PythonTanh = "Hiperbolikus érintö (tan)"
PythonTurtleGoto = "Menjen a (x,y) koordinátákra" PythonText = "(x,y) nél egy szöveget irni"
PythonTurtleHeading = "Visszaadja az aktuális irányt" PythonTimeFunction = "time funkció elötag"
PythonTurtleHideturtle = "A teknös elrejtése" PythonTrunc = "Egész csonka (?)"
PythonTurtleIsdown = "True-t válaszol ha a toll irás pozícióban van" PythonTurtleBackward = "x pixelt hátra"
PythonTurtleLeft = "a fokkot forduljon balra" PythonTurtleCircle = "r pixel sugarú kört rajzolni"
PythonTurtlePendown = "Húzza le a tollat" PythonTurtleColor = "Toll szinét beállitani"
PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre" PythonTurtleColorMode = "Szin módot 1.0-ra vagy 255-ra állitani"
PythonTurtlePenup = "Húzza fel a tollat" PythonTurtleForward = "x pixelt elölre"
PythonTurtlePosition = "Az aktuális (x,y) pozíciót visszaadása" PythonTurtleFunction = "turtle modul funkció elötag"
PythonTurtleReset = "Visszaállitani a rajzot (torléssel)" PythonTurtleGoto = "Menjen a (x,y) koordinátákra"
PythonTurtleRight = "a fokkot forduljon jobbra" PythonTurtleHeading = "Visszaadja az aktuális irányt"
PythonTurtleSetheading = "a fokokra állítja be az irányt" PythonTurtleHideturtle = "A teknös elrejtése"
PythonTurtleSetposition = "A teknös pozicioját allitja" PythonTurtleIsdown = "True-t válaszol ha a toll irás pozícióban van"
PythonTurtleShowturtle = "A teknöst meg mutatni" PythonTurtleLeft = "a fokkot forduljon balra"
PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között" PythonTurtlePendown = "Húzza le a tollat"
PythonTurtleWrite = "Szöveg irás" PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre"
PythonUniform = "Lebegöpontos szám [a,b] -ban" PythonTurtlePenup = "Húzza fel a tollat"
PythonImportTime = "time modul importálása" PythonTurtlePosition = "Az aktuális (x,y) pozíciót visszaadása"
PythonTimePrefix = "time funkció elötag" PythonTurtleReset = "Visszaállitani a rajzot (torléssel)"
PythonTimeSleep = "n másodpercet várni" PythonTurtleRight = "a fokkot forduljon jobbra"
PythonMonotonic = "Meg fordítani a monoton idö" PythonTurtleSetheading = "a fokokra állítja be az irányt"
PythonFileOpen = "Fájl megnyitása" PythonTurtleShowturtle = "A teknöst meg mutatni"
PythonFileSeekable = "Seek-et lehete használni" PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
PythonFileSeek = "A kurzort áthelyezni" PythonTurtleWrite = "Szöveg irás"
PythonFileTell = "Visszaadja a kurzor helye" PythonUniform = "Lebegöpontos szám [a,b] -ban"
PythonFileClose = "Bezárni egy fájlt" PythonImportTime = "time modul importálása"
PythonFileClosed = "True ha a fájl bezárva" PythonMonotonic = "Meg fordítani a monoton idö"
PythonFileRead = "Olvas 16 bájtig" PythonFileOpen = "Fájl megnyitása"
PythonFileWrite = "b-t irjon a fájlba" PythonFileSeekable = "Seek-et lehete használni"
PythonFileReadline = "Olvas egy sort vagy 16 bájtig" PythonFileSeek = "A kurzort áthelyezni"
PythonFileReadlines = "Olvas több sort" PythonFileTell = "Visszaadja a kurzor helye"
PythonFileTruncate = "A fájl átméretezése" PythonFileClose = "Bezárni egy fájlt"
PythonFileWritelines = "Irjon több sort" PythonFileClosed = "True ha a fájl bezárva"
PythonFileName = "A fájl neve" PythonFileRead = "Olvas 16 bájtig"
PythonFileMode = "A fájl nyitott módja" PythonFileWrite = "b-t irjon a fájlba"
PythonFileReadable = "read-et lehete használni" PythonFileReadline = "Olvas egy sort vagy 16 bájtig"
PythonFileWritable = "write-ot lehete használni" PythonFileReadlines = "Olvas több sort"
PythonImportOs = "os modul importálása" PythonFileTruncate = "A fájl átméretezése"
PythonOsUname = "Rendszer informaciók" PythonFileWritelines = "Irjon több sort"
PythonOsGetlogin = "Get username" PythonFileName = "A fájl neve"
PythonOsRemove = "Fájl törlése" PythonFileMode = "A fájl nyitott módja"
PythonOsRename = "Fájl átnevezése" PythonFileReadable = "read-et lehete használni"
PythonOsListdir = "Fájlok listája" PythonFileWritable = "write-ot lehete használni"
PythonImportSys = "sys modul importálása" PythonImportOs = "os modul importálása"
PythonSysExit = "Terminate current program" PythonOsUname = "Rendszer informaciók"
PythonSysPrintexception = "Print exception" PythonOsGetlogin = "Get username"
PythonSysByteorder = "The byte order of the system" PythonOsRemove = "Fájl törlése"
PythonSysImplementation = "Information about Python" PythonOsRename = "Fájl átnevezése"
PythonSysModules = "Dictionary of loaded modules" PythonOsListdir = "Fájlok listája"
PythonSysVersion = "Python language version (string)" PythonImportSys = "sys modul importálása"
PythonSysVersioninfo = "Python language version (tuple)" 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)"
PythonKeyLeft = "BALRA NYÍL billentyű"
PythonKeyUp = "FEL NYÍL billentyű"
PythonKeyDown = "LE NYÍL billentyű"
PythonKeyRight = "JOBBRA NYÍL billentyű"
PythonKeyOk = "OK gomb"
PythonKeyBack = "VISSZA gomb"
PythonKeyHome = "Lakáskulcs"
PythonKeyOnOff = "BE/KI gomb"
PythonKeyShift = "SHIFT billentyű"
PythonKeyAlpha = "ALPHA kulcs"
PythonKeyXnt = "X,N,T gomb"
PythonKeyVar = "VAR gomb"
PythonKeyToolbox = "TOOLBOX gomb"
PythonKeyBackspace = "BACKSPACE billentyű"
PythonKeyExp = "EXPONENTIÁLIS kulcs"
PythonKeyLn = "TERMÉSZETES LOGARITMUS kulcs"
PythonKeyLog = "DECIMÁLIS LOGARITMUS billentyű"
PythonKeyImaginary = "KÉPZELETES I kulcs"
PythonKeyComma = "VESZSŰ gomb"
PythonKeyPower = "POWER gomb"
PythonKeySine = "SINE gomb"
PythonKeyCosine = "KOSINUS kulcs"
PythonKeyTangent = "ÉRINTŐ gomb"
PythonKeyPi = "PI kulcs"
PythonKeySqrt = "NÉGYGYÖK kulcs"
PythonKeySquare = "SZÖGZET billentyű"
PythonKeySeven = "7 kulcs"
PythonKeyEight = "8 kulcs"
PythonKeyNine = "9 kulcs"
PythonKeyLeftParenthesis = "BAL ZÁRÓZELŐ gomb"
PythonKeyRightParenthesis = "JOBB ZÁRÓZELŐ billentyű"
PythonKeyFour = "4 kulcs"
PythonKeyFive = "5 kulcs"
PythonKeySix = "6 kulcs"
PythonKeyMultiplication = "SZORZAT gomb"
PythonKeyDivision = "OSZTÁS kulcs"
PythonKeyOne = "1 kulcs"
PythonKeyTwo = "2 kulcs"
PythonKeyThree = "3 kulcs"
PythonKeyPlus = "PLUSZ kulcs"
PythonKeyMinus = "MÍNUS gomb"
PythonKeyZero = "0 kulcs"
PythonKeyDot = "DOT gomb"
PythonKeyEe = "10 POWER X gomb"
PythonKeyAns = "ANS kulcs"
PythonKeyExe = "EXE kulcs"
PythonImportUtils = "Az ulab.utils importálása"
PythonUtilsFunction = "utils modul függvény előtagja"
PythonTurtleBgcolor = "Módosítsa a háttérszínt"

View File

@@ -1,5 +1,11 @@
PythonPound = "Commento" PythonPound = "Commento"
PythonPercent = "Modulo" PythonPercent = "Modulo"
PythonColon = "Due punti"
PythonSemicon = "Punto e virgola"
PythonExclamationMark = "Punto esclamativo"
PythonLessThan = "Minore di"
PythonGreaterThan = "Maggiore di"
PythonQuestionMark = "Punto interrogativo"
Python1J = "Unità immaginaria" Python1J = "Unità immaginaria"
PythonLF = "Nuova riga" PythonLF = "Nuova riga"
PythonTab = "Tabulazione" PythonTab = "Tabulazione"
@@ -25,7 +31,7 @@ PythonBin = "Converte un intero in binario"
PythonCeil = "Parte intera superiore" PythonCeil = "Parte intera superiore"
PythonChoice = "Numero aleatorio nella lista" PythonChoice = "Numero aleatorio nella lista"
PythonClear = "Svuota la lista" PythonClear = "Svuota la lista"
PythonCmathFunction = "Funz. prefissata modulo cmath" PythonCmathFunction = "Prefisso funzione del modulo cmath"
PythonColor = "Definisci un colore rvb" PythonColor = "Definisci un colore rvb"
PythonColorBlack = "Colore nero" PythonColorBlack = "Colore nero"
PythonColorBlue = "Colore blu" PythonColorBlue = "Colore blu"
@@ -53,6 +59,7 @@ PythonErfc = "Funzione d'errore complementare"
PythonEval = "Valuta l'espressione nell'argomento " PythonEval = "Valuta l'espressione nell'argomento "
PythonExp = "Funzione esponenziale" PythonExp = "Funzione esponenziale"
PythonExpm1 = "Calcola exp(x)-1" PythonExpm1 = "Calcola exp(x)-1"
PythonFactorial = "Fattoriale di x"
PythonFabs = "Valore assoluto" PythonFabs = "Valore assoluto"
PythonFillCircle = "Riempire un cerchio" PythonFillCircle = "Riempire un cerchio"
PythonFillPolygon = "Riempire un poligono" PythonFillPolygon = "Riempire un poligono"
@@ -62,7 +69,7 @@ PythonFloor = "Parte intera"
PythonFmod = "a modulo b" PythonFmod = "a modulo b"
PythonFrExp = "Mantissa ed esponente di x : (m,e)" PythonFrExp = "Mantissa ed esponente di x : (m,e)"
PythonGamma = "Funzione gamma" PythonGamma = "Funzione gamma"
PythonGetKeys = "Premere i tasti" PythonGetKeys = "Ottieni i tasti premuti"
PythonGetPalette = "Ottieni la tavolozza del tema" PythonGetPalette = "Ottieni la tavolozza del tema"
PythonGetPixel = "Restituisce colore del pixel(x,y)" PythonGetPixel = "Restituisce colore del pixel(x,y)"
PythonGetrandbits = "Numero aleatorio con k bit" PythonGetrandbits = "Numero aleatorio con k bit"
@@ -81,31 +88,79 @@ PythonImportTurtle = "Importa del modulo turtle"
PythonImportTime = "Importa del modulo time" PythonImportTime = "Importa del modulo time"
PythonImportOs = "Importa modulo os" PythonImportOs = "Importa modulo os"
PythonOsUname = "Ottieni informazioni sul sistema" PythonOsUname = "Ottieni informazioni sul sistema"
PythonOsGetlogin = "Get username" PythonOsGetlogin = "Ottieni username"
PythonOsRemove = "Rimuovere un file" PythonOsRemove = "Rimuovere un file"
PythonOsRename = "Rinomina file" PythonOsRename = "Rinomina file"
PythonOsListdir = "Elenca file" PythonOsListdir = "Elenca file"
PythonImportSys = "Importa modulo sys" PythonImportSys = "Importa modulo sys"
PythonSysExit = "Terminate current program" PythonSysExit = "Termina programma corrente"
PythonSysPrintexception = "Print exception" PythonSysPrintexception = "Stampa eccezione"
PythonSysByteorder = "The byte order of the system" PythonSysByteorder = "Ordine di byte del sistema"
PythonSysImplementation = "Information about Python" PythonSysImplementation = "Informazioni su Python"
PythonSysModules = "Dictionary of loaded modules" PythonSysModules = "Dizionario dei moduli caricati"
PythonSysVersion = "Python language version (string)" PythonSysVersion = "Versione linguaggio Python (stringa)"
PythonSysVersioninfo = "Python language version (tuple)" PythonSysVersioninfo = "Versione linguaggio Python (tupla)"
PythonIndex = "Indice prima occorrenza di x" PythonIndex = "Indice prima occorrenza di x"
PythonInput = "Inserire un valore" PythonInput = "Inserire un valore"
PythonInsert = "Inserire x in posizione i-esima" PythonInsert = "Inserire x in posizione i-esima"
PythonInt = "Conversione in intero" PythonInt = "Conversione in intero"
PythonIonFunction = "Prefisso di funzione modulo ion" PythonIonFunction = "Prefisso di funzione modulo ion"
PythonIsFinite = "Testa se x è finito" PythonIsFinite = "Testa se x è finito"
PythonIsInfinite = "Testa se x est infinito" PythonIsInfinite = "Testa se x è infinito"
PythonIsKeyDown = "Restituisce True premendo tasto k" PythonIsKeyDown = "Restituisce True premendo tasto k"
PythonBattery = "Return battery voltage" PythonBattery = "Restituisce la tensione della batteria"
PythonBatteryLevel = "Return battery level" PythonBatteryLevel = "Restituisce il livello della batteria"
PythonBatteryIscharging = "Return if battery is charging" PythonBatteryIscharging = "Restituisce se la batteria è in carica"
PythonSetBrightness = "Imposta livello di luminosità"
PythonGetBrightness = "Ottieni livello di luminosità"
PythonIsNaN = "Testa se x è NaN" PythonIsNaN = "Testa se x è NaN"
PythonKandinskyFunction = "Prefisso funzione modulo kandinsky" PythonKandinskyFunction = "Prefisso funzione modulo kandinsky"
PythonKeyLeft = "Tasto FRECCIA SINISTRA"
PythonKeyUp = "Tasto FRECCIA ALTO"
PythonKeyDown = "Tasto FRECCIA BASSO"
PythonKeyRight = "Tasto FRECCIA DESTRA"
PythonKeyOk = "Tasto OK"
PythonKeyBack = "Tasto INDIETRO"
PythonKeyHome = "Tasto CASA"
PythonKeyOnOff = "Tasto ON/OFF"
PythonKeyShift = "Tasto SHIFT"
PythonKeyAlpha = "Tasto ALPHA"
PythonKeyXnt = "Tasto X,N,T"
PythonKeyVar = "Tasto VAR"
PythonKeyToolbox = "Tasto TOOLBOX"
PythonKeyBackspace = "Tasto CANCELLA"
PythonKeyExp = "Tasto ESPONENZIALE"
PythonKeyLn = "Tasto LOGARITMO NEPERIANO"
PythonKeyLog = "Tasto LOGARITMO DECIMALE"
PythonKeyImaginary = "Tasto I IMMAGINE"
PythonKeyComma = "Tasto VIRGOLA"
PythonKeyPower = "Tasto POTENZA"
PythonKeySine = "Tasto SENO"
PythonKeyCosine = "Tasto COSENO"
PythonKeyTangent = "Tasto TANGENTE"
PythonKeyPi = "Tasto PI"
PythonKeySqrt = "Tasto RADICE QUADRATA"
PythonKeySquare = "Tasto QUADRATO"
PythonKeySeven = "Tasto 7"
PythonKeyEight = "Tasto 8"
PythonKeyNine = "Tasto 9"
PythonKeyLeftParenthesis = "Tasto PARENTESI SINISTRA"
PythonKeyRightParenthesis = "Tasto PARENTESI DESTRA"
PythonKeyFour = "Tasto 4"
PythonKeyFive = "Tasto 5"
PythonKeySix = "Tasto 6"
PythonKeyMultiplication = "Tasto MOLTIPLICAZIONE"
PythonKeyDivision = "Tasto DIVISIONE"
PythonKeyOne = "Tasto 1"
PythonKeyTwo = "Tasto 2"
PythonKeyThree = "Tasto 3"
PythonKeyPlus = "Tasto PIÙ"
PythonKeyMinus = "Tasto MENO"
PythonKeyZero = "Tasto 0"
PythonKeyDot = "Tasto PUNTO"
PythonKeyEe = "Tasto 10 POTENZA X"
PythonKeyAns = "Tasto ANS"
PythonKeyExe = "Tasto EXE"
PythonLdexp = "Inversa di frexp : x*(2**i)" PythonLdexp = "Inversa di frexp : x*(2**i)"
PythonLength = "Longhezza di un oggetto" PythonLength = "Longhezza di un oggetto"
PythonLgamma = "Logaritmo della funzione gamma" PythonLgamma = "Logaritmo della funzione gamma"
@@ -141,7 +196,7 @@ PythonRandrange = "Numero dentro il range(start, stop)"
PythonRangeStartStop = "Lista da start a stop-1" PythonRangeStartStop = "Lista da start a stop-1"
PythonRangeStop = "Lista da 0 a stop-1" PythonRangeStop = "Lista da 0 a stop-1"
PythonRect = "Converte in coordinate algebriche" PythonRect = "Converte in coordinate algebriche"
PythonRemove = "Cancella la prima x dalla lista" PythonRemove = "Cancella la prima x dalla lista"
PythonReverse = "Inverte gli elementi della lista" PythonReverse = "Inverte gli elementi della lista"
PythonRound = "Arrotondato a n cifre decimali" PythonRound = "Arrotondato a n cifre decimali"
PythonScatter = "Diagramma dispersione y in f. di x" PythonScatter = "Diagramma dispersione y in f. di x"
@@ -183,28 +238,28 @@ PythonTurtlePosition = "Fornisce posizione corrente (x,y)"
PythonTurtleReset = "Azzera il disegno" PythonTurtleReset = "Azzera il disegno"
PythonTurtleRight = "Ruota di a gradi a destra" PythonTurtleRight = "Ruota di a gradi a destra"
PythonTurtleSetheading = "Imposta l'orientamento per a gradi" PythonTurtleSetheading = "Imposta l'orientamento per a gradi"
PythonTurtleSetposition = "Posiziona la tartaruga"
PythonTurtleShowturtle = "Mostra la tartaruga" PythonTurtleShowturtle = "Mostra la tartaruga"
PythonTurtleSpeed = "Velocità di disegno (x tra 0 e 10)" PythonTurtleSpeed = "Velocità di disegno (x tra 0 e 10)"
PythonTurtleWrite = "Mostra un testo" PythonTurtleWrite = "Mostra un testo"
PythonUniform = "Numero decimale tra [a,b]" PythonUniform = "Numero decimale tra [a,b]"
PythonImportTime = "Import time module" PythonImportTime = "Importa modulo time"
PythonTimePrefix = "time module function prefix" PythonMonotonic = "Restituisce tempo monotonico"
PythonTimeSleep = "Wait for n second" PythonFileOpen = "Apre un file"
PythonMonotonic = "Return monotonic time" PythonFileSeekable = "Dice se si può usare il cursore su un file"
PythonFileOpen = "Opens a file" PythonFileSeek = "Sposta cursore di un file"
PythonFileSeekable = "Tells if seek can be used on a file" PythonFileTell = "Ottieni posizione del cursore del file"
PythonFileSeek = "Move file's cursor" PythonFileClose = "Chiude un file"
PythonFileTell = "Get file's cursor location" PythonFileClosed = "True se un file è stato chiuso"
PythonFileClose = "Closes a file" PythonFileRead = "Legge fino ai byte di un file"
PythonFileClosed = "True if file was closed" PythonFileWrite = "Scrive b in un file"
PythonFileRead = "Read up to size bytes" PythonFileReadline = "Legge una riga o fino ai byte di un file"
PythonFileWrite = "Write b into file" PythonFileReadlines = "Legge una lista di linee di un file"
PythonFileReadline = "Reads a line or up to size bytes" PythonFileTruncate = "Ridimensiona il file"
PythonFileReadlines = "Reads a list of lines" PythonFileWritelines = "Scrive una lista di linee su file"
PythonFileTruncate = "Resize the file to size" PythonFileName = "Contiene il nome del file"
PythonFileWritelines = "Writes a list of lines" PythonFileMode = "Contiene la modalità di apertura del file"
PythonFileName = "Contains file's name" PythonFileReadable = "Dice se si può leggere sul file"
PythonFileMode = "Contains file's open mode" PythonFileWritable = "Dice se si può scrivere sul file"
PythonFileReadable = "Tells if read can be used on a file" PythonImportUtils = "Importazione di ulab.utils"
PythonFileWritable = "Tells if write can be used on a file" PythonUtilsFunction = "Prefisso funzione del modulo utils"
PythonTurtleBgcolor = "Cambia il colore dello sfondo"

View File

@@ -1,5 +1,11 @@
PythonPound = "Opmerkingen" PythonPound = "Opmerkingen"
PythonPercent = "Modulo" PythonPercent = "Modulo"
PythonColon = "Dubbele punt"
PythonSemicon = "Puntkomma"
PythonExclamationMark = "Uitroepteken"
PythonLessThan = "Kleiner dan"
PythonGreaterThan = "Groter dan"
PythonQuestionMark = "Vraagteken"
Python1J = "Imaginaire i" Python1J = "Imaginaire i"
PythonLF = "Nieuwe regel" PythonLF = "Nieuwe regel"
PythonTab = "Tabulatie" PythonTab = "Tabulatie"
@@ -53,6 +59,7 @@ PythonErfc = "Complementaire error functie"
PythonEval = "Geef de geëvalueerde uitdrukking" PythonEval = "Geef de geëvalueerde uitdrukking"
PythonExp = "Exponentiële functie" PythonExp = "Exponentiële functie"
PythonExpm1 = "Bereken exp(x)-1" PythonExpm1 = "Bereken exp(x)-1"
PythonFactorial = "faculteit van x"
PythonFabs = "Absolute waarde" PythonFabs = "Absolute waarde"
PythonFillCircle = "Vul een cirkel" PythonFillCircle = "Vul een cirkel"
PythonFillPolygon = "Vul een veelhoek" PythonFillPolygon = "Vul een veelhoek"
@@ -102,11 +109,59 @@ PythonIonFunction = "ion module voorvoegsel"
PythonIsFinite = "Controleer of x eindig is" PythonIsFinite = "Controleer of x eindig is"
PythonIsInfinite = "Controleer of x oneindig is" PythonIsInfinite = "Controleer of x oneindig is"
PythonIsKeyDown = "Geef True als k toets omlaag is" PythonIsKeyDown = "Geef True als k toets omlaag is"
PythonBattery = "Return battery voltage" PythonBattery = "Return batterijspanning"
PythonBatteryLevel = "Return battery level" PythonBatteryLevel = "Batterijniveau teruggeven"
PythonBatteryIscharging = "Return if battery is charging" PythonBatteryIscharging = "Keer terug als de batterij wordt opgeladen"
PythonSetBrightness = "Set brightness level"
PythonGetBrightness = "Get brightness level"
PythonIsNaN = "Controleer of x geen getal is" PythonIsNaN = "Controleer of x geen getal is"
PythonKandinskyFunction = "kandinsky module voorvoegsel" PythonKandinskyFunction = "kandinsky module voorvoegsel"
PythonKeyLeft = "PIJL NAAR LINKS toets"
PythonKeyUp = "PIJL OMHOOG toets"
PythonKeyDown = "PIJL OMLAAG toets"
PythonKeyRight = "PIJL NAAR RECHTS toets"
PythonKeyOk = "OK toets"
PythonKeyBack = "TERUG toets"
PythonKeyHome = "HOME toets"
PythonKeyOnOff = "AAN/UIT toets"
PythonKeyShift = "SHIFT toets"
PythonKeyAlpha = "ALPHA toets"
PythonKeyXnt = "X,N,T toets"
PythonKeyVar = "VAR toets"
PythonKeyToolbox = "TOOLBOX toets"
PythonKeyBackspace = "BACKSPACE toets"
PythonKeyExp = "EXPONENTIEEL toets"
PythonKeyLn = "NATUURLIJKE LOGARITME toets"
PythonKeyLog = "BRIGGSE LOGARITME toets"
PythonKeyImaginary = "IMAGINAIRE I toets"
PythonKeyComma = "KOMMA toets"
PythonKeyPower = "MACHT toets"
PythonKeySine = "SINUS toets"
PythonKeyCosine = "COSINUS toets"
PythonKeyTangent = "TANGENS toets"
PythonKeyPi = "PI toets"
PythonKeySqrt = "VIERKANTSWORTEL toets"
PythonKeySquare = "KWADRAAT toets"
PythonKeySeven = "7 toets"
PythonKeyEight = "8 toets"
PythonKeyNine = "9 toets"
PythonKeyLeftParenthesis = "HAAKJE OPENEN toets"
PythonKeyRightParenthesis = "HAAKJE SLUITEN toets"
PythonKeyFour = "4 toets"
PythonKeyFive = "5 toets"
PythonKeySix = "6 toets"
PythonKeyMultiplication = "VERMENIGVULDIGEN toets"
PythonKeyDivision = "DELEN toets"
PythonKeyOne = "1 toets"
PythonKeyTwo = "2 toets"
PythonKeyThree = "3 toets"
PythonKeyPlus = "PLUS toets"
PythonKeyMinus = "MIN toets"
PythonKeyZero = "0 toets"
PythonKeyDot = "PUNT toets"
PythonKeyEe = "10 TOT DE MACHT X toets"
PythonKeyAns = "ANS toets"
PythonKeyExe = "EXE toets"
PythonLdexp = "Geeft x*(2**i), inversie van frexp" PythonLdexp = "Geeft x*(2**i), inversie van frexp"
PythonLength = "Lengte van een object" PythonLength = "Lengte van een object"
PythonLgamma = "Log-gammafunctie" PythonLgamma = "Log-gammafunctie"
@@ -149,7 +204,7 @@ PythonScatter = "Teken scatterplot van y versus x"
PythonSeed = "Start willek. getallengenerator" PythonSeed = "Start willek. getallengenerator"
PythonSetPixel = "Kleur pixel (x,y)" PythonSetPixel = "Kleur pixel (x,y)"
PythonShow = "Figuur weergeven" PythonShow = "Figuur weergeven"
PythonSin= "Sinus" PythonSin = "Sinus"
PythonSinh = "Sinus hyperbolicus" PythonSinh = "Sinus hyperbolicus"
PythonSleep = "Stel executie voor t seconden uit" PythonSleep = "Stel executie voor t seconden uit"
PythonLocalTime = "Zet tijd om in tuple" PythonLocalTime = "Zet tijd om in tuple"
@@ -184,14 +239,11 @@ PythonTurtlePosition = "Zet huidige (x,y) locatie terug"
PythonTurtleReset = "Reset de tekening" PythonTurtleReset = "Reset de tekening"
PythonTurtleRight = "Ga rechtsaf met a graden" PythonTurtleRight = "Ga rechtsaf met a graden"
PythonTurtleSetheading = "Zet de oriëntatie op a graden" PythonTurtleSetheading = "Zet de oriëntatie op a graden"
PythonTurtleSetposition = "Plaats de schildpad"
PythonTurtleShowturtle = "Laat de schildpad zien" PythonTurtleShowturtle = "Laat de schildpad zien"
PythonTurtleSpeed = "Tekensnelheid tussen 0 and 10" PythonTurtleSpeed = "Tekensnelheid tussen 0 and 10"
PythonTurtleWrite = "Display a text" PythonTurtleWrite = "Display a text"
PythonUniform = "Decimaal getal in [a,b]" PythonUniform = "Decimaal getal in [a,b]"
PythonImportTime = "Import time module" PythonImportTime = "Import time module"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonMonotonic = "Return monotonic time" PythonMonotonic = "Return monotonic time"
PythonFileOpen = "Opens a file" PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file" PythonFileSeekable = "Tells if seek can be used on a file"
@@ -209,3 +261,6 @@ PythonFileName = "Contains file's name"
PythonFileMode = "Contains file's open mode" PythonFileMode = "Contains file's open mode"
PythonFileReadable = "Tells if read can be used on a file" PythonFileReadable = "Tells if read can be used on a file"
PythonFileWritable = "Tells if write can be used on a file" PythonFileWritable = "Tells if write can be used on a file"
PythonImportUtils = "Ulab.utils importeren"
PythonUtilsFunction = "utils module functie prefix"
PythonTurtleBgcolor = "Verander de achtergrondkleur"

View File

@@ -1,5 +1,11 @@
PythonPound = "Comentário" PythonPound = "Comentário"
PythonPercent = "Módulo" PythonPercent = "Módulo"
PythonColon = "Dois pontos"
PythonSemicon = "Ponto e vírgula"
PythonExclamationMark = "Ponto de exclamação"
PythonLessThan = "Menor que"
PythonGreaterThan = "Maior que"
PythonQuestionMark = "Ponto de interrogação"
Python1J = "i Complexo" Python1J = "i Complexo"
PythonLF = "Nova linha" PythonLF = "Nova linha"
PythonTab = "Tabulação" PythonTab = "Tabulação"
@@ -53,6 +59,7 @@ PythonErfc = "Função erro complementar"
PythonEval = "Devolve a expressão avaliada" PythonEval = "Devolve a expressão avaliada"
PythonExp = "Função exponencial" PythonExp = "Função exponencial"
PythonExpm1 = "Calcular exp(x)-1" PythonExpm1 = "Calcular exp(x)-1"
PythonFactorial = "Fatorial de x"
PythonFabs = "Valor absoluto" PythonFabs = "Valor absoluto"
PythonFillCircle = "Preencher um círculo" PythonFillCircle = "Preencher um círculo"
PythonFillPolygon = "Preencher um polígono" PythonFillPolygon = "Preencher um polígono"
@@ -87,11 +94,59 @@ PythonIonFunction = "Prefixo da função do módulo ion"
PythonIsFinite = "Verificar se x é finito" PythonIsFinite = "Verificar se x é finito"
PythonIsInfinite = "Verificar se x é infinito" PythonIsInfinite = "Verificar se x é infinito"
PythonIsKeyDown = "Devolve True se tecla k pressionada" PythonIsKeyDown = "Devolve True se tecla k pressionada"
PythonBattery = "Return battery voltage" PythonBattery = "Retornar a voltagem da bateria"
PythonBatteryLevel = "Return battery level" PythonBatteryLevel = "Retornar nível de bateria"
PythonBatteryIscharging = "Return if battery is charging" PythonBatteryIscharging = "Retorne se a bateria estiver carregando"
PythonSetBrightness = "Definir nível de brilho"
PythonGetBrightness = "Obter nível de brilho"
PythonIsNaN = "Verificar se x é um NaN" PythonIsNaN = "Verificar se x é um NaN"
PythonKandinskyFunction = "Prefixo da função do módulo kandinsky" PythonKandinskyFunction = "Prefixo da função do módulo kandinsky"
PythonKeyLeft = "tecla SETA ESQUERDA"
PythonKeyUp = "tecla SETA CIMA "
PythonKeyDown = "tecla SETA BAIXO"
PythonKeyRight = "tecla SETA DIREITA"
PythonKeyOk = "tecla OK"
PythonKeyBack = "tecla VOLTAR"
PythonKeyHome = "tecla HOME"
PythonKeyOnOff = "tecla ON/OFF"
PythonKeyShift = "tecla SHIFT"
PythonKeyAlpha = "tecla ALPHA"
PythonKeyXnt = "tecla X,N,T"
PythonKeyVar = "tecla VAR"
PythonKeyToolbox = "tecla CAIXA DE FERRAMENTAS"
PythonKeyBackspace = "tecla APAGAR"
PythonKeyExp = "tecla EXPONENCIAL"
PythonKeyLn = "tecla LOGARITMO NATURAL"
PythonKeyLog = "tecla LOGARITMO DECIMAL"
PythonKeyImaginary = "tecla I IMAGINÁRIO"
PythonKeyComma = "tecla VÍRGULA"
PythonKeyPower = "tecla EXPOENTE"
PythonKeySine = "tecla SENO"
PythonKeyCosine = "tecla COSSENO"
PythonKeyTangent = "tecla TANGENTE"
PythonKeyPi = "tecla PI"
PythonKeySqrt = "tecla RAIZ QUADRADA"
PythonKeySquare = "tecla AO QUADRADO"
PythonKeySeven = "tecla 7"
PythonKeyEight = "tecla 8"
PythonKeyNine = "tecla 9"
PythonKeyLeftParenthesis = "tecla PARÊNTESE ESQUERDO"
PythonKeyRightParenthesis = "tecla PARÊNTESE DIREITO"
PythonKeyFour = "tecla 4"
PythonKeyFive = "tecla 5"
PythonKeySix = "tecla 6"
PythonKeyMultiplication = "tecla MULTIPLICAÇÃO"
PythonKeyDivision = "tecla DIVISÃO"
PythonKeyOne = "tecla 1"
PythonKeyTwo = "tecla 2"
PythonKeyThree = "tecla 3"
PythonKeyPlus = "tecla MAIS"
PythonKeyMinus = "tecla MENOS"
PythonKeyZero = "tecla 0"
PythonKeyDot = "tecla PONTO"
PythonKeyEe = "tecla 10 expoente X"
PythonKeyAns = "tecla ANS"
PythonKeyExe = "tecla EXE"
PythonLdexp = "Devolve x*(2**i), inverso de frexp" PythonLdexp = "Devolve x*(2**i), inverso de frexp"
PythonLength = "Comprimento de um objeto" PythonLength = "Comprimento de um objeto"
PythonLgamma = "Logaritmo da função gama" PythonLgamma = "Logaritmo da função gama"
@@ -169,7 +224,6 @@ PythonTurtlePosition = "Devolve a posição atual (x,y)"
PythonTurtleReset = "Reiniciar o desenho" PythonTurtleReset = "Reiniciar o desenho"
PythonTurtleRight = "Virar à esquerda por a graus" PythonTurtleRight = "Virar à esquerda por a graus"
PythonTurtleSetheading = "Definir a orientação por a graus" PythonTurtleSetheading = "Definir a orientação por a graus"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Mostrar o turtle" PythonTurtleShowturtle = "Mostrar o turtle"
PythonTurtleSpeed = "Velocidade do desenho entre 0 e 10" PythonTurtleSpeed = "Velocidade do desenho entre 0 e 10"
PythonTurtleWrite = "Mostrar um texto" PythonTurtleWrite = "Mostrar um texto"
@@ -189,8 +243,6 @@ PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules" PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)" PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)" PythonSysVersioninfo = "Python language version (tuple)"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonMonotonic = "Return monotonic time" PythonMonotonic = "Return monotonic time"
PythonFileOpen = "Opens a file" PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file" PythonFileSeekable = "Tells if seek can be used on a file"
@@ -208,3 +260,6 @@ PythonFileName = "Contains file's name"
PythonFileMode = "Contains file's open mode" PythonFileMode = "Contains file's open mode"
PythonFileReadable = "Tells if read can be used on a file" PythonFileReadable = "Tells if read can be used on a file"
PythonFileWritable = "Tells if write can be used on a file" PythonFileWritable = "Tells if write can be used on a file"
PythonImportUtils = "Importando ulab.utils"
PythonUtilsFunction = "prefixo de função do módulo utils"
PythonTurtleBgcolor = "Alterar a cor de fundo"

View File

@@ -1,6 +1,12 @@
PythonCommandAmpersand = "&" PythonCommandAmpersand = "&"
PythonCommandLF = "\\n" PythonCommandLF = "\\n"
PythonCommandPercent = "%" PythonCommandPercent = "%"
PythonCommandColon = ":"
PythonCommandSemicon = ";"
PythonCommandExclamationMark = "!"
PythonCommandLessThan = "<"
PythonCommandGreaterThan = ">"
PythonCommandQuestionMark = "?"
PythonCommandPound = "#" PythonCommandPound = "#"
PythonCommandSingleQuote = "'x'" PythonCommandSingleQuote = "'x'"
PythonCommandSymbolExp = "^" PythonCommandSymbolExp = "^"
@@ -60,6 +66,7 @@ PythonCommandEval = "eval(\"expression\")"
PythonCommandExp = "exp(x)" PythonCommandExp = "exp(x)"
PythonCommandExpComplex = "exp(z)" PythonCommandExpComplex = "exp(z)"
PythonCommandExpm1 = "expm1(x)" PythonCommandExpm1 = "expm1(x)"
PythonCommandFactorial = "factorial(x)"
PythonCommandFabs = "fabs(x)" PythonCommandFabs = "fabs(x)"
PythonCommandFillCircle = "fill_circle(x,y,r,color)" PythonCommandFillCircle = "fill_circle(x,y,r,color)"
PythonCommandFillPolygon = "fill_polygon([(x1,y1),...],color)" PythonCommandFillPolygon = "fill_polygon([(x1,y1),...],color)"
@@ -163,6 +170,8 @@ PythonCommandIsKeyDown = "keydown(k)"
PythonCommandBattery = "battery()" PythonCommandBattery = "battery()"
PythonCommandBatteryLevel = "battery_level()" PythonCommandBatteryLevel = "battery_level()"
PythonCommandBatteryIscharging = "battery_ischarging()" PythonCommandBatteryIscharging = "battery_ischarging()"
PythonCommandSetBrightness = "set_brightness()"
PythonCommandGetBrightness = "get_brightness()"
PythonCommandLdexp = "ldexp(x,i)" PythonCommandLdexp = "ldexp(x,i)"
PythonCommandLength = "len(object)" PythonCommandLength = "len(object)"
PythonCommandLgamma = "lgamma(x)" PythonCommandLgamma = "lgamma(x)"
@@ -292,6 +301,14 @@ PythonCommandNumpyFftFunction = "np.fft.function"
PythonCommandNumpyFftFunctionWithoutArg = "np.fft.\x11" PythonCommandNumpyFftFunctionWithoutArg = "np.fft.\x11"
PythonCommandNumpyLinalgFunction = "np.linalg.function" PythonCommandNumpyLinalgFunction = "np.linalg.function"
PythonCommandNumpyLinalgFunctionWithoutArg = "np.linalg.\x11" PythonCommandNumpyLinalgFunctionWithoutArg = "np.linalg.\x11"
PythonCommandImportFromUtils = "from ulab import utils"
PythonCommandUtilsFunction = "utils.function"
PythonCommandUtilsFunctionWithoutArg = "utils.\x11"
PythonCommandUtilsSpectrogram = "spectrogram(a)"
PythonCommandUtilsFromInt16Buffer = "from_int16_buffer(b)"
PythonCommandUtilsFromUint16Buffer = "from_uint16_buffer(b)"
PythonCommandUtilsFromInt32Buffer = "from_int32_buffer(b)"
PythonCommandUtilsFromUint32Buffer = "from_uint32_buffer(b)"
PythonCommandOct = "oct(x)" PythonCommandOct = "oct(x)"
PythonCommandPhase = "phase(z)" PythonCommandPhase = "phase(z)"
PythonCommandPlot = "plot(x,y,color)" PythonCommandPlot = "plot(x,y,color)"
@@ -387,6 +404,7 @@ PythonTurtleCommandBackward = "backward(x)"
PythonTurtleCommandCircle = "circle(r)" PythonTurtleCommandCircle = "circle(r)"
PythonTurtleCommandColor = "color('c')" PythonTurtleCommandColor = "color('c')"
PythonTurtleCommandColorMode = "colormode(x)" PythonTurtleCommandColorMode = "colormode(x)"
PythonTurtleCommandBgcolor = "bgcolor('c')"
PythonTurtleCommandForward = "forward(x)" PythonTurtleCommandForward = "forward(x)"
PythonTurtleCommandGoto = "goto(x,y)" PythonTurtleCommandGoto = "goto(x,y)"
PythonTurtleCommandHeading = "heading()" PythonTurtleCommandHeading = "heading()"
@@ -400,16 +418,8 @@ PythonTurtleCommandPosition = "position()"
PythonTurtleCommandReset = "reset()" PythonTurtleCommandReset = "reset()"
PythonTurtleCommandRight = "right(a)" PythonTurtleCommandRight = "right(a)"
PythonTurtleCommandSetheading = "setheading(a)" PythonTurtleCommandSetheading = "setheading(a)"
PythonTurtleCommandSetposition = "setposition(x,[y])"
PythonTurtleCommandShowturtle = "showturtle()" PythonTurtleCommandShowturtle = "showturtle()"
PythonTurtleCommandSpeed = "speed(x)" PythonTurtleCommandSpeed = "speed(x)"
PythonTurtleCommandWhite = "'white'"
PythonTurtleCommandYellow = "'yellow'"
PythonTimeModule = "time"
PythonTimeCommandImportFrom = "from time import *"
PythonTimeCommandSleep = "sleep()"
PythonTimeCommandSleepDemo = "sleep(n)"
PythonTimeCommandMonotonic = "monotonic()"
PythonCommandFileOpen = "open(name, [mode])" PythonCommandFileOpen = "open(name, [mode])"
PythonCommandFileOpenWithoutArg = "open(\x11)" PythonCommandFileOpenWithoutArg = "open(\x11)"
PythonCommandFileSeek = "file.seek(offset, [whence])" PythonCommandFileSeek = "file.seek(offset, [whence])"

View File

@@ -19,7 +19,7 @@ void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::setLine(Consol
void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::drawRect(KDContext * ctx, KDRect rect) const { void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(bounds(), Palette::CodeBackground); ctx->fillRect(bounds(), Palette::CodeBackground);
ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::BackgroundApps); ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::CodeBackground);
} }
KDSize ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::minimalSizeForOptimalDisplay() const { KDSize ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::minimalSizeForOptimalDisplay() const {

View File

@@ -4,6 +4,8 @@
#include "app.h" #include "app.h"
#include <escher/metric.h> #include <escher/metric.h>
#include <ion.h> #include <ion.h>
#include "../global_preferences.h"
#include <apps/apps_container.h>
using namespace Shared; using namespace Shared;
@@ -71,6 +73,10 @@ void EditorController::viewDidDisappear() {
m_menuController->scriptContentEditionDidFinish(); m_menuController->scriptContentEditionDidFinish();
} }
void EditorController::textAreaDidReceiveNoneXNTEvent() {
AppsContainer::sharedAppsContainer()->resetXNT();
}
bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) { bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) {
if (App::app()->textInputDidReceiveEvent(textArea, event)) { if (App::app()->textInputDidReceiveEvent(textArea, event)) {
return true; return true;
@@ -80,7 +86,6 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
return true; return true;
} }
if (event == Ion::Events::Backspace && textArea->selectionIsEmpty()) { if (event == Ion::Events::Backspace && textArea->selectionIsEmpty()) {
/* If the cursor is on the left of the text of a line, backspace one /* If the cursor is on the left of the text of a line, backspace one
* indentation space at a time. */ * indentation space at a time. */

View File

@@ -30,6 +30,7 @@ public:
TELEMETRY_ID("Editor"); TELEMETRY_ID("Editor");
/* TextAreaDelegate */ /* TextAreaDelegate */
void textAreaDidReceiveNoneXNTEvent() override;
bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) override; bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) override;
/* InputEventHandlerDelegate */ /* InputEventHandlerDelegate */

View File

@@ -26,7 +26,9 @@ void EditorView::resetSelection() {
} }
void EditorView::scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) { void EditorView::scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) {
m_gutterView.setOffset(scrollViewDataSource->offset().y()); if (m_gutterView.setOffsetAndNeedResize(scrollViewDataSource->offset().y())) {
internalLayoutSubviews(true);
}
} }
View * EditorView::subviewAtIndex(int index) { View * EditorView::subviewAtIndex(int index) {
@@ -42,8 +44,12 @@ void EditorView::didBecomeFirstResponder() {
} }
void EditorView::layoutSubviews(bool force) { void EditorView::layoutSubviews(bool force) {
m_gutterView.setOffset(0); m_gutterView.setOffsetAndNeedResize(0); // Whatever the return is, we layout the editor view
KDCoordinate gutterWidth = m_gutterView.minimalSizeForOptimalDisplay().width(); internalLayoutSubviews(force);
}
void EditorView::internalLayoutSubviews(bool force) {
KDCoordinate gutterWidth = m_gutterView.computeWidth();
m_gutterView.setFrame(KDRect(0, 0, gutterWidth, bounds().height()), force); m_gutterView.setFrame(KDRect(0, 0, gutterWidth, bounds().height()), force);
m_textArea.setFrame(KDRect( m_textArea.setFrame(KDRect(
@@ -67,23 +73,23 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
KDCoordinate firstLine = m_offset / glyphSize.height(); KDCoordinate firstLine = m_offset / glyphSize.height();
KDCoordinate firstLinePixelOffset = m_offset - firstLine * glyphSize.height(); KDCoordinate firstLinePixelOffset = m_offset - firstLine * glyphSize.height();
char lineNumber[k_lineNumberCharLength]; char lineNumberBuffer[m_numberOfDigits + 1];
int numberOfLines = bounds().height() / glyphSize.height() + 1; int numberOfLines = bounds().height() / glyphSize.height() + 1;
for (int i=0; i<numberOfLines; i++) { for (int i=0; i<numberOfLines; i++) {
// Only the first two digits are displayed int lineNumberValue = (i + firstLine + 1);
int lineNumberValue = (i + firstLine + 1) % 100;
Poincare::Integer line(lineNumberValue); Poincare::Integer line(lineNumberValue);
if (firstLine < 10 || lineNumberValue >= 10) {
line.serialize(lineNumber, k_lineNumberCharLength); int lineDigits = computeNumberOfDigitsFor(lineNumberValue);
} else {
// Add a leading "0" for (int j=0; j < m_numberOfDigits - lineDigits; j++) {
lineNumber[0] = '0'; lineNumberBuffer[j] = ' ';
line.serialize(lineNumber + 1, k_lineNumberCharLength - 1);
} }
KDCoordinate leftPadding = (2 - strlen(lineNumber)) * glyphSize.width();
line.serialize(lineNumberBuffer + (m_numberOfDigits - lineDigits), m_numberOfDigits + 1);
ctx->drawString( ctx->drawString(
lineNumber, lineNumberBuffer,
KDPoint(k_margin + leftPadding, i*glyphSize.height() - firstLinePixelOffset), KDPoint(k_margin, i*glyphSize.height() - firstLinePixelOffset),
m_font, m_font,
textColor, textColor,
backgroundColor backgroundColor
@@ -91,18 +97,36 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
} }
} }
void EditorView::GutterView::setOffset(KDCoordinate offset) { bool EditorView::GutterView::setOffsetAndNeedResize(KDCoordinate offset) {
if (m_offset == offset) { if (m_offset == offset) {
return; return false;
} }
m_offset = offset; m_offset = offset;
int numberOfDigits = computeMaxNumberOfDigits();
if (numberOfDigits != m_numberOfDigits) {
m_numberOfDigits = numberOfDigits;
return true;
}
markRectAsDirty(bounds()); markRectAsDirty(bounds());
return false;
} }
int EditorView::GutterView::computeWidth() {
return 2 * k_margin + (m_numberOfDigits) * m_font->glyphSize().width();
}
KDSize EditorView::GutterView::minimalSizeForOptimalDisplay() const { int EditorView::GutterView::computeMaxNumberOfDigits() {
int numberOfChars = 2; // TODO: Could be computed return computeNumberOfDigitsFor((bounds().height() / m_font->glyphSize().height() + 1) + (m_offset / m_font->glyphSize().height()));
return KDSize(2 * k_margin + numberOfChars * Poincare::Preferences::sharedPreferences()->KDPythonFont()->glyphSize().width(), 0); }
int EditorView::GutterView::computeNumberOfDigitsFor(int value) {
int digits = 1;
while (value >= pow(10, digits)) {
digits++;
}
return digits;
} }
} }

View File

@@ -29,6 +29,7 @@ public:
void unloadSyntaxHighlighter() { m_textArea.unloadSyntaxHighlighter(); }; void unloadSyntaxHighlighter() { m_textArea.unloadSyntaxHighlighter(); };
void scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) override; void scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) override;
void didBecomeFirstResponder() override; void didBecomeFirstResponder() override;
void internalLayoutSubviews(bool force);
private: private:
int numberOfSubviews() const override { return 2; } int numberOfSubviews() const override { return 2; }
View * subviewAtIndex(int index) override; View * subviewAtIndex(int index) override;
@@ -36,15 +37,21 @@ private:
class GutterView : public View { class GutterView : public View {
public: public:
GutterView(const KDFont * font) : View(), m_font(font), m_offset(0) {} GutterView(const KDFont * font) : View(), m_font(font), m_offset(0), m_numberOfDigits(2) {}
void drawRect(KDContext * ctx, KDRect rect) const override; void drawRect(KDContext * ctx, KDRect rect) const override;
void setOffset(KDCoordinate offset); bool setOffsetAndNeedResize(KDCoordinate offset); // Return true if the gutter view need to be resized
KDSize minimalSizeForOptimalDisplay() const override;
int computeWidth();
int computeMaxNumberOfDigits();
static int computeNumberOfDigitsFor(int value);
private: private:
static constexpr KDCoordinate k_margin = 2; static constexpr KDCoordinate k_margin = 2;
static constexpr int k_lineNumberCharLength = 3;
const KDFont * m_font; const KDFont * m_font;
KDCoordinate m_offset; KDCoordinate m_offset;
int m_numberOfDigits;
}; };
PythonTextArea m_textArea; PythonTextArea m_textArea;

View File

@@ -10,9 +10,6 @@ const char * PythonTextForEvent(Ion::Events::Event event) {
if (event.text() == pair.firstString()) { if (event.text() == pair.firstString()) {
return pair.secondString(); return pair.secondString();
} }
if (event == Ion::Events::XNT) {
return "x";
}
} }
return nullptr; return nullptr;
} }

View File

@@ -90,6 +90,11 @@ bool MenuController::handleEvent(Ion::Events::Event event) {
footer()->setSelectedButton(0); footer()->setSelectedButton(0);
return true; return true;
} }
if (event == Ion::Events::ShiftBack) {
Ion::Storage::sharedStorage()->reinsertTrash("py");
m_selectableTableView.reloadData();
return true;
}
if (event == Ion::Events::Up) { if (event == Ion::Events::Up) {
if (footer()->selectedButton() == 0) { if (footer()->selectedButton() == 0) {
footer()->setSelectedButton(-1); footer()->setSelectedButton(-1);

View File

@@ -24,7 +24,20 @@ constexpr KDColor BackgroundColor = Palette::CodeBackground;
constexpr KDColor HighlightColor = Palette::CodeBackgroundSelected; constexpr KDColor HighlightColor = Palette::CodeBackgroundSelected;
constexpr KDColor AutocompleteColor = KDColor::RGB24(0xC6C6C6); // TODO Palette change constexpr KDColor AutocompleteColor = KDColor::RGB24(0xC6C6C6); // TODO Palette change
bool isItalic(mp_token_kind_t tokenKind) {
if (!GlobalPreferences::sharedGlobalPreferences()->syntaxhighlighting()) {
return false;
}
if (tokenKind == MP_TOKEN_STRING) {
return true;
}
return false;
}
static inline KDColor TokenColor(mp_token_kind_t tokenKind) { static inline KDColor TokenColor(mp_token_kind_t tokenKind) {
if (!GlobalPreferences::sharedGlobalPreferences()->syntaxhighlighting()) {
return Palette::CodeText;
}
if (tokenKind == MP_TOKEN_STRING) { if (tokenKind == MP_TOKEN_STRING) {
return StringColor; return StringColor;
} }
@@ -66,7 +79,8 @@ static inline KDColor TokenColor(mp_token_kind_t tokenKind) {
&& MP_TOKEN_KW_TRY + 1 == MP_TOKEN_KW_WHILE && MP_TOKEN_KW_TRY + 1 == MP_TOKEN_KW_WHILE
&& MP_TOKEN_KW_WHILE + 1 == MP_TOKEN_KW_WITH && MP_TOKEN_KW_WHILE + 1 == MP_TOKEN_KW_WITH
&& MP_TOKEN_KW_WITH + 1 == MP_TOKEN_KW_YIELD && MP_TOKEN_KW_WITH + 1 == MP_TOKEN_KW_YIELD
&& MP_TOKEN_KW_YIELD + 1 == MP_TOKEN_OP_TILDE, && MP_TOKEN_KW_YIELD + 1 == MP_TOKEN_OP_ASSIGN
&& MP_TOKEN_OP_ASSIGN + 1 == MP_TOKEN_OP_TILDE,
"MP_TOKEN order changed, so Code::PythonTextArea::TokenColor might need to change too."); "MP_TOKEN order changed, so Code::PythonTextArea::TokenColor might need to change too.");
if (tokenKind >= MP_TOKEN_KW_FALSE && tokenKind <= MP_TOKEN_KW_YIELD) { if (tokenKind >= MP_TOKEN_KW_FALSE && tokenKind <= MP_TOKEN_KW_YIELD) {
return KeywordColor; return KeywordColor;
@@ -119,7 +133,8 @@ static inline KDColor TokenColor(mp_token_kind_t tokenKind) {
if ((tokenKind >= MP_TOKEN_OP_TILDE && tokenKind <= MP_TOKEN_DEL_DBL_STAR_EQUAL) if ((tokenKind >= MP_TOKEN_OP_TILDE && tokenKind <= MP_TOKEN_DEL_DBL_STAR_EQUAL)
|| tokenKind == MP_TOKEN_DEL_EQUAL || tokenKind == MP_TOKEN_DEL_EQUAL
|| tokenKind == MP_TOKEN_DEL_MINUS_MORE) || tokenKind == MP_TOKEN_DEL_MINUS_MORE
|| tokenKind == MP_TOKEN_OP_ASSIGN)
{ {
return OperatorColor; return OperatorColor;
} }
@@ -157,7 +172,7 @@ PythonTextArea::AutocompletionType PythonTextArea::autocompletionType(const char
const char * tokenEnd; const char * tokenEnd;
_mp_token_kind_t currentTokenKind = lex->tok_kind; _mp_token_kind_t currentTokenKind = lex->tok_kind;
while (currentTokenKind != MP_TOKEN_NEWLINE && currentTokenKind != MP_TOKEN_END) { while (currentTokenKind != MP_TOKEN_NEWLINE && currentTokenKind != MP_TOKEN_END && currentTokenKind != MP_TOKEN_FSTRING_RAW) {
tokenStart = firstNonSpace + lex->tok_column - 1; tokenStart = firstNonSpace + lex->tok_column - 1;
tokenEnd = tokenStart + TokenLength(lex, tokenStart); tokenEnd = tokenStart + TokenLength(lex, tokenStart);
@@ -250,7 +265,8 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
BackgroundColor, BackgroundColor,
selectionStart, selectionStart,
selectionEnd, selectionEnd,
HighlightColor); HighlightColor,
false);
} }
if (UTF8Helper::CodePointIs(firstNonSpace, UCodePointNull)) { if (UTF8Helper::CodePointIs(firstNonSpace, UCodePointNull)) {
return; return;
@@ -266,7 +282,7 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
const char * tokenFrom = firstNonSpace; const char * tokenFrom = firstNonSpace;
size_t tokenLength = 0; size_t tokenLength = 0;
const char * tokenEnd = firstNonSpace; const char * tokenEnd = firstNonSpace;
while (lex->tok_kind != MP_TOKEN_NEWLINE && lex->tok_kind != MP_TOKEN_END) { while (lex->tok_kind != MP_TOKEN_NEWLINE && lex->tok_kind != MP_TOKEN_END && lex->tok_kind != MP_TOKEN_FSTRING_RAW) {
tokenFrom = firstNonSpace + lex->tok_column - 1; tokenFrom = firstNonSpace + lex->tok_column - 1;
if (tokenFrom != tokenEnd) { if (tokenFrom != tokenEnd) {
// We passed over white spaces, we need to color them // We passed over white spaces, we need to color them
@@ -280,13 +296,15 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
BackgroundColor, BackgroundColor,
selectionStart, selectionStart,
selectionEnd, selectionEnd,
HighlightColor); HighlightColor,
false);
} }
tokenLength = TokenLength(lex, tokenFrom); tokenLength = TokenLength(lex, tokenFrom);
tokenEnd = tokenFrom + tokenLength; tokenEnd = tokenFrom + tokenLength;
// If the token is being autocompleted, use DefaultColor // If the token is being autocompleted, use DefaultColor/Font
KDColor color = (tokenFrom <= autocompleteStart && autocompleteStart < tokenEnd) ? Palette::CodeText : TokenColor(lex->tok_kind); KDColor color = (tokenFrom <= autocompleteStart && autocompleteStart < tokenEnd) ? Palette::CodeText : TokenColor(lex->tok_kind);
bool italic = (tokenFrom <= autocompleteStart && autocompleteStart < tokenEnd) ? false : isItalic(lex->tok_kind);
LOG_DRAW("Draw \"%.*s\" for token %d\n", tokenLength, tokenFrom, lex->tok_kind); LOG_DRAW("Draw \"%.*s\" for token %d\n", tokenLength, tokenFrom, lex->tok_kind);
drawStringAt(ctx, line, drawStringAt(ctx, line,
@@ -297,7 +315,9 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
BackgroundColor, BackgroundColor,
selectionStart, selectionStart,
selectionEnd, selectionEnd,
HighlightColor); HighlightColor,
italic
);
mp_lexer_to_next(lex); mp_lexer_to_next(lex);
LOG_DRAW("Pop token %d\n", lex->tok_kind); LOG_DRAW("Pop token %d\n", lex->tok_kind);
@@ -305,6 +325,10 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
tokenFrom += tokenLength; tokenFrom += tokenLength;
KDColor color = CommentColor;
if (!GlobalPreferences::sharedGlobalPreferences()->syntaxhighlighting()) {
color = Palette::CodeText;
}
// Even if the token is being autocompleted, use CommentColor // Even if the token is being autocompleted, use CommentColor
if (tokenFrom < text + byteLength) { if (tokenFrom < text + byteLength) {
LOG_DRAW("Draw comment \"%.*s\" from %d\n", byteLength - (tokenFrom - text), firstNonSpace, tokenFrom); LOG_DRAW("Draw comment \"%.*s\" from %d\n", byteLength - (tokenFrom - text), firstNonSpace, tokenFrom);
@@ -312,11 +336,12 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
UTF8Helper::GlyphOffsetAtCodePoint(text, tokenFrom), UTF8Helper::GlyphOffsetAtCodePoint(text, tokenFrom),
tokenFrom, tokenFrom,
text + byteLength - tokenFrom, text + byteLength - tokenFrom,
CommentColor, color,
BackgroundColor, BackgroundColor,
selectionStart, selectionStart,
selectionEnd, selectionEnd,
HighlightColor); HighlightColor,
true);
} }
mp_lexer_free(lex); mp_lexer_free(lex);
@@ -336,7 +361,8 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
BackgroundColor, BackgroundColor,
nullptr, nullptr,
nullptr, nullptr,
HighlightColor); HighlightColor,
false);
} }
} }
@@ -400,14 +426,14 @@ bool PythonTextArea::handleEvent(Ion::Events::Event event) {
return result; return result;
} }
bool PythonTextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) { bool PythonTextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText, bool shouldRemoveLastCharacter) {
if (*text == 0) { if (*text == 0) {
return false; return false;
} }
if (m_contentView.isAutocompleting()) { if (m_contentView.isAutocompleting()) {
removeAutocompletion(); removeAutocompletion();
} }
bool result = TextArea::handleEventWithText(text, indentation, forceCursorRightOfText); bool result = TextArea::handleEventWithText(text, indentation, forceCursorRightOfText, shouldRemoveLastCharacter);
addAutocompletion(); addAutocompletion();
return result; return result;
} }
@@ -467,9 +493,10 @@ bool PythonTextArea::addAutocompletionTextAtIndex(int nextIndex, int * currentIn
if (textToInsertLength > 0) { if (textToInsertLength > 0) {
// Try to insert the text (this might fail if the buffer is full) // Try to insert the text (this might fail if the buffer is full)
if (!m_contentView.insertTextAtLocation(textToInsert, const_cast<char *>(autocompletionLocation), textToInsertLength)) { if (!m_contentView.isAbleToInsertTextAt(textToInsertLength, autocompletionLocation, false)) {
return false; return false;
} }
m_contentView.insertTextAtLocation(textToInsert, const_cast<char *>(autocompletionLocation), textToInsertLength);
autocompletionLocation += textToInsertLength; autocompletionLocation += textToInsertLength;
m_contentView.setAutocompleting(true); m_contentView.setAutocompleting(true);
m_contentView.setAutocompletionEnd(autocompletionLocation); m_contentView.setAutocompletionEnd(autocompletionLocation);
@@ -481,7 +508,8 @@ bool PythonTextArea::addAutocompletionTextAtIndex(int nextIndex, int * currentIn
assert(strlen(parentheses) == parenthesesLength); assert(strlen(parentheses) == parenthesesLength);
/* If couldInsertText is false, we should not try to add the parentheses as /* If couldInsertText is false, we should not try to add the parentheses as
* there was already not enough space to add the autocompletion. */ * there was already not enough space to add the autocompletion. */
if (addParentheses && m_contentView.insertTextAtLocation(parentheses, const_cast<char *>(autocompletionLocation), parenthesesLength)) { if (addParentheses && m_contentView.isAbleToInsertTextAt(parenthesesLength, autocompletionLocation, false)) {
m_contentView.insertTextAtLocation(parentheses, const_cast<char *>(autocompletionLocation), parenthesesLength);
m_contentView.setAutocompleting(true); m_contentView.setAutocompleting(true);
m_contentView.setAutocompletionEnd(autocompletionLocation + parenthesesLength); m_contentView.setAutocompletionEnd(autocompletionLocation + parenthesesLength);
return true; return true;

View File

@@ -23,14 +23,14 @@ public:
void loadSyntaxHighlighter() { m_contentView.loadSyntaxHighlighter(); } void loadSyntaxHighlighter() { m_contentView.loadSyntaxHighlighter(); }
void unloadSyntaxHighlighter() { m_contentView.unloadSyntaxHighlighter(); } void unloadSyntaxHighlighter() { m_contentView.unloadSyntaxHighlighter(); }
bool handleEvent(Ion::Events::Event event) override; bool handleEvent(Ion::Events::Event event) override;
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override; bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false, bool shouldRemoveLastCharacter = false) override;
/* autocompletionType returns: /* autocompletionType returns:
* - EndOfIdentifier if there is currently autocompletion, or if the cursor is * - EndOfIdentifier if there is currently autocompletion, or if the cursor is
* at the end of an identifier, * at the end of an identifier,
* - MiddleOfIdentifier is the cursor is in the middle of an identifier, * - MiddleOfIdentifier is the cursor is in the middle of an identifier,
* - No identifier otherwise. * - No identifier otherwise.
* The autocompletionLocation can be provided with autocompletionLocation, or * The autocompletionLocation can be provided with autocompletionLocation, or
* retreived with autocompletionLocationBeginning and autocompletionLocationEnd. */ * retrieved with autocompletionLocationBeginning and autocompletionLocationEnd. */
AutocompletionType autocompletionType(const char * autocompletionLocation = nullptr, const char ** autocompletionLocationBeginning = nullptr, const char ** autocompletionLocationEnd = nullptr) const; AutocompletionType autocompletionType(const char * autocompletionLocation = nullptr, const char ** autocompletionLocationBeginning = nullptr, const char ** autocompletionLocationEnd = nullptr) const;
bool isAutocompleting() const { return m_contentView.isAutocompleting(); } bool isAutocompleting() const { return m_contentView.isAutocompleting(); }
protected: protected:

View File

@@ -10,22 +10,22 @@ extern "C" {
namespace Code { namespace Code {
const ToolboxMessageTree forLoopChildren[] = { const ToolboxMessageTree forLoopChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::ForInRange1ArgLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInRange1ArgLoop), ToolboxMessageTree::Leaf(I18n::Message::ForInRange1ArgLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInRange1ArgLoop, true, 2),
ToolboxMessageTree::Leaf(I18n::Message::ForInRange2ArgsLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInRange2ArgsLoop), ToolboxMessageTree::Leaf(I18n::Message::ForInRange2ArgsLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInRange2ArgsLoop, true, 2),
ToolboxMessageTree::Leaf(I18n::Message::ForInRange3ArgsLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInRange3ArgsLoop), ToolboxMessageTree::Leaf(I18n::Message::ForInRange3ArgsLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInRange3ArgsLoop, true, 2),
ToolboxMessageTree::Leaf(I18n::Message::ForInListLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInListLoop) ToolboxMessageTree::Leaf(I18n::Message::ForInListLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInListLoop, true, 2)
}; };
const ToolboxMessageTree ifStatementChildren[] = { const ToolboxMessageTree ifStatementChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::IfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfElseStatement), ToolboxMessageTree::Leaf(I18n::Message::IfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfElseStatement, true, 4),
ToolboxMessageTree::Leaf(I18n::Message::IfThenStatementWithArg, I18n::Message::Default, false, I18n::Message::IfThenStatement), ToolboxMessageTree::Leaf(I18n::Message::IfThenStatementWithArg, I18n::Message::Default, false, I18n::Message::IfThenStatement, true, 2),
ToolboxMessageTree::Leaf(I18n::Message::IfElifElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfElifElseStatement), ToolboxMessageTree::Leaf(I18n::Message::IfElifElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfElifElseStatement, true, 6),
ToolboxMessageTree::Leaf(I18n::Message::IfAndIfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfAndIfElseStatement), ToolboxMessageTree::Leaf(I18n::Message::IfAndIfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfAndIfElseStatement, true, 4),
ToolboxMessageTree::Leaf(I18n::Message::IfOrIfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfOrIfElseStatement) ToolboxMessageTree::Leaf(I18n::Message::IfOrIfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfOrIfElseStatement, true, 4)
}; };
const ToolboxMessageTree whileLoopChildren[] = { const ToolboxMessageTree whileLoopChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::WhileLoopWithArg, I18n::Message::Default, false, I18n::Message::WhileLoop) ToolboxMessageTree::Leaf(I18n::Message::WhileLoopWithArg, I18n::Message::Default, false, I18n::Message::WhileLoop, true, 2)
}; };
const ToolboxMessageTree conditionsChildren[] = { const ToolboxMessageTree conditionsChildren[] = {
@@ -75,6 +75,7 @@ const ToolboxMessageTree MathModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAtan2, I18n::Message::PythonAtan2), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAtan2, I18n::Message::PythonAtan2),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCeil, I18n::Message::PythonCeil), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCeil, I18n::Message::PythonCeil),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCopySign, I18n::Message::PythonCopySign), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCopySign, I18n::Message::PythonCopySign),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFactorial, I18n::Message::PythonFactorial),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFabs, I18n::Message::PythonFabs), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFabs, I18n::Message::PythonFabs),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFloor, I18n::Message::PythonFloor), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFloor, I18n::Message::PythonFloor),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFmod, I18n::Message::PythonFmod), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFmod, I18n::Message::PythonFmod),
@@ -294,9 +295,20 @@ const ToolboxMessageTree ScipyModuleChildren[] = {
ToolboxMessageTree::Node(I18n::Message::ScipySpecialModule, ScipySpecialModuleChildren), ToolboxMessageTree::Node(I18n::Message::ScipySpecialModule, ScipySpecialModuleChildren),
}; };
const ToolboxMessageTree UtilsModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromUtils, I18n::Message::PythonImportUtils, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandUtilsFunction, I18n::Message::PythonUtilsFunction, false, I18n::Message::PythonCommandUtilsFunctionWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandUtilsSpectrogram),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandUtilsFromInt16Buffer),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandUtilsFromUint16Buffer),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandUtilsFromInt32Buffer),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandUtilsFromUint32Buffer),
};
const ToolboxMessageTree UlabModuleChildren[] = { const ToolboxMessageTree UlabModuleChildren[] = {
ToolboxMessageTree::Node(I18n::Message::NumpyModule, NumpyModuleChildren), ToolboxMessageTree::Node(I18n::Message::NumpyModule, NumpyModuleChildren),
ToolboxMessageTree::Node(I18n::Message::ScipyModule, ScipyModuleChildren), ToolboxMessageTree::Node(I18n::Message::ScipyModule, ScipyModuleChildren),
ToolboxMessageTree::Node(I18n::Message::UtilsModule, UtilsModuleChildren),
ToolboxMessageTree::Leaf(I18n::Message::UlabDocumentation, I18n::Message::UlabDocumentationLink) ToolboxMessageTree::Leaf(I18n::Message::UlabDocumentation, I18n::Message::UlabDocumentationLink)
}; };
@@ -326,6 +338,7 @@ const ToolboxMessageTree TurtleModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandHideturtle, I18n::Message::PythonTurtleHideturtle, false), ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandHideturtle, I18n::Message::PythonTurtleHideturtle, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColor, I18n::Message::PythonTurtleColor), ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColor, I18n::Message::PythonTurtleColor),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColorMode, I18n::Message::PythonTurtleColorMode), ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColorMode, I18n::Message::PythonTurtleColorMode),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBgcolor, I18n::Message::PythonTurtleBgcolor),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBlue, I18n::Message::PythonColorBlue, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBlue, I18n::Message::PythonColorBlue, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorRed, I18n::Message::PythonColorRed, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorRed, I18n::Message::PythonColorRed, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGreen, I18n::Message::PythonColorGreen, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGreen, I18n::Message::PythonColorGreen, false),
@@ -365,18 +378,72 @@ const ToolboxMessageTree KandinskyModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillRect, I18n::Message::PythonFillRect), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillRect, I18n::Message::PythonFillRect),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillCircle, I18n::Message::PythonFillCircle), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillCircle, I18n::Message::PythonFillCircle),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillPolygon, I18n::Message::PythonFillPolygon), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillPolygon, I18n::Message::PythonFillPolygon),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetKeys, I18n::Message::PythonGetKeys), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetPalette, I18n::Message::PythonGetPalette)
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetPalette, I18n::Message::PythonGetPalette)}; };
const ToolboxMessageTree IonKeyModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyLeft, I18n::Message::PythonKeyLeft, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyUp, I18n::Message::PythonKeyUp, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyDown, I18n::Message::PythonKeyDown, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyRight, I18n::Message::PythonKeyRight, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyOk, I18n::Message::PythonKeyOk, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyBack, I18n::Message::PythonKeyBack, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyHome, I18n::Message::PythonKeyHome, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyOnOff, I18n::Message::PythonKeyOnOff, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyShift, I18n::Message::PythonKeyShift, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyAlpha, I18n::Message::PythonKeyAlpha, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyXnt, I18n::Message::PythonKeyXnt, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyVar, I18n::Message::PythonKeyVar, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyToolbox, I18n::Message::PythonKeyToolbox, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyBackspace, I18n::Message::PythonKeyBackspace, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyExp, I18n::Message::PythonKeyExp, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyLn, I18n::Message::PythonKeyLn, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyLog, I18n::Message::PythonKeyLog, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyImaginary, I18n::Message::PythonKeyImaginary, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyComma, I18n::Message::PythonKeyComma, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyPower, I18n::Message::PythonKeyPower, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySine, I18n::Message::PythonKeySine, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyCosine, I18n::Message::PythonKeyCosine, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyTangent, I18n::Message::PythonKeyTangent, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyPi, I18n::Message::PythonKeyPi, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySqrt, I18n::Message::PythonKeySqrt, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySquare, I18n::Message::PythonKeySquare, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySeven, I18n::Message::PythonKeySeven, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyEight, I18n::Message::PythonKeyEight, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyNine, I18n::Message::PythonKeyNine, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyLeftParenthesis, I18n::Message::PythonKeyLeftParenthesis, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyRightParenthesis, I18n::Message::PythonKeyRightParenthesis, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyFour, I18n::Message::PythonKeyFour, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyFive, I18n::Message::PythonKeyFive, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySix, I18n::Message::PythonKeySix, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyMultiplication, I18n::Message::PythonKeyMultiplication, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyDivision, I18n::Message::PythonKeyDivision, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyOne, I18n::Message::PythonKeyOne, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyTwo, I18n::Message::PythonKeyTwo, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyThree, I18n::Message::PythonKeyThree, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyPlus, I18n::Message::PythonKeyPlus, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyMinus, I18n::Message::PythonKeyMinus, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyZero, I18n::Message::PythonKeyZero, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyDot, I18n::Message::PythonKeyDot, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyEe, I18n::Message::PythonKeyEe, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyAns, I18n::Message::PythonKeyAns, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyExe, I18n::Message::PythonKeyExe, false)
};
const ToolboxMessageTree IonModuleChildren[] = { const ToolboxMessageTree IonModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportIon, I18n::Message::PythonImportIon, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportIon, I18n::Message::PythonImportIon, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromIon, I18n::Message::PythonImportIon, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromIon, I18n::Message::PythonImportIon, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandIonFunction, I18n::Message::PythonIonFunction, false, I18n::Message::PythonCommandIonFunctionWithoutArg), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandIonFunction, I18n::Message::PythonIonFunction, false, I18n::Message::PythonCommandIonFunctionWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandIsKeyDown, I18n::Message::PythonIsKeyDown), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandIsKeyDown, I18n::Message::PythonIsKeyDown),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetKeys, I18n::Message::PythonGetKeys),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBattery, I18n::Message::PythonBattery), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBattery, I18n::Message::PythonBattery),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBatteryLevel, I18n::Message::PythonBatteryLevel), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBatteryLevel, I18n::Message::PythonBatteryLevel),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBatteryIscharging, I18n::Message::PythonBatteryIscharging), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBatteryIscharging, I18n::Message::PythonBatteryIscharging),
ToolboxMessageTree::Leaf(I18n::Message::IonSelector, I18n::Message::IonSelector) ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSetBrightness, I18n::Message::PythonSetBrightness),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetBrightness, I18n::Message::PythonGetBrightness),
// This is a special case, because it is handled separately, so the sub-tree is unused.
ToolboxMessageTree::Node(I18n::Message::IonSelector, IonKeyModuleChildren),
ToolboxMessageTree::Node(I18n::Message::IonKeyList, IonKeyModuleChildren)
}; };
const ToolboxMessageTree TimeModuleChildren[] = { const ToolboxMessageTree TimeModuleChildren[] = {
@@ -403,6 +470,7 @@ const ToolboxMessageTree OsModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonOsCommandListdir, I18n::Message::PythonOsListdir, false) ToolboxMessageTree::Leaf(I18n::Message::PythonOsCommandListdir, I18n::Message::PythonOsListdir, false)
}; };
#if MICROPY_PY_SYS
const ToolboxMessageTree SysModuleChildren[] = { const ToolboxMessageTree SysModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportSys, I18n::Message::PythonImportSys, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportSys, I18n::Message::PythonImportSys, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromSys, I18n::Message::PythonImportSys, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromSys, I18n::Message::PythonImportSys, false),
@@ -414,6 +482,7 @@ const ToolboxMessageTree SysModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandVersion, I18n::Message::PythonSysVersion, false), ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandVersion, I18n::Message::PythonSysVersion, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandVersioninfo, I18n::Message::PythonSysVersioninfo, false) ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandVersioninfo, I18n::Message::PythonSysVersioninfo, false)
}; };
#endif
const ToolboxMessageTree modulesChildren[] = { const ToolboxMessageTree modulesChildren[] = {
ToolboxMessageTree::Node(I18n::Message::MathModule, MathModuleChildren), ToolboxMessageTree::Node(I18n::Message::MathModule, MathModuleChildren),
@@ -427,12 +496,23 @@ const ToolboxMessageTree modulesChildren[] = {
ToolboxMessageTree::Node(I18n::Message::KandinskyModule, KandinskyModuleChildren), ToolboxMessageTree::Node(I18n::Message::KandinskyModule, KandinskyModuleChildren),
ToolboxMessageTree::Node(I18n::Message::IonModule, IonModuleChildren), ToolboxMessageTree::Node(I18n::Message::IonModule, IonModuleChildren),
ToolboxMessageTree::Node(I18n::Message::OsModule, OsModuleChildren), ToolboxMessageTree::Node(I18n::Message::OsModule, OsModuleChildren),
#if MICROPY_PY_SYS
ToolboxMessageTree::Node(I18n::Message::SysModule, SysModuleChildren), ToolboxMessageTree::Node(I18n::Message::SysModule, SysModuleChildren),
#endif
ToolboxMessageTree::Node(I18n::Message::TimeModule, TimeModuleChildren) ToolboxMessageTree::Node(I18n::Message::TimeModule, TimeModuleChildren)
}; };
const ToolboxMessageTree catalogChildren[] = { const ToolboxMessageTree catalogChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPound, I18n::Message::PythonPound, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPound, I18n::Message::PythonPound, false),
#ifdef _FXCG
// There is no question mark button on the fx-CG calculators
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColon, I18n::Message::PythonColon, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSemicon, I18n::Message::PythonSemicon, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandExclamationMark, I18n::Message::PythonExclamationMark, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandLessThan, I18n::Message::PythonLessThan, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGreaterThan, I18n::Message::PythonGreaterThan, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandQuestionMark, I18n::Message::PythonQuestionMark, false),
#endif
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPercent, I18n::Message::PythonPercent, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPercent, I18n::Message::PythonPercent, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommand1J, I18n::Message::Python1J, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommand1J, I18n::Message::Python1J, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandLF, I18n::Message::PythonLF, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandLF, I18n::Message::PythonLF, false),
@@ -463,6 +543,7 @@ const ToolboxMessageTree catalogChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCmathFunction, I18n::Message::PythonCmathFunction, false, I18n::Message::PythonCommandCmathFunctionWithoutArg), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCmathFunction, I18n::Message::PythonCmathFunction, false, I18n::Message::PythonCommandCmathFunctionWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColor, I18n::Message::PythonColor), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColor, I18n::Message::PythonColor),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColorMode, I18n::Message::PythonTurtleColorMode), ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColorMode, I18n::Message::PythonTurtleColorMode),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBgcolor, I18n::Message::PythonTurtleBgcolor),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandComplex, I18n::Message::PythonComplex), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandComplex, I18n::Message::PythonComplex),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCopySign, I18n::Message::PythonCopySign), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCopySign, I18n::Message::PythonCopySign),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCos, I18n::Message::PythonCos), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCos, I18n::Message::PythonCos),
@@ -624,10 +705,10 @@ const ToolboxMessageTree fileChildren[] {
}; };
const ToolboxMessageTree exceptionsChildren[] = { const ToolboxMessageTree exceptionsChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::TryExcept1ErrorWithArg, I18n::Message::Default, false, I18n::Message::TryExcept1Error), ToolboxMessageTree::Leaf(I18n::Message::TryExcept1ErrorWithArg, I18n::Message::Default, false, I18n::Message::TryExcept1Error, true, 4),
ToolboxMessageTree::Leaf(I18n::Message::TryExcept1ErrorElseWithArg, I18n::Message::Default, false, I18n::Message::TryExcept1ErrorElse), ToolboxMessageTree::Leaf(I18n::Message::TryExcept1ErrorElseWithArg, I18n::Message::Default, false, I18n::Message::TryExcept1ErrorElse, true, 6),
ToolboxMessageTree::Leaf(I18n::Message::TryExcept2ErrorWithArg, I18n::Message::Default, false, I18n::Message::TryExcept2Error), ToolboxMessageTree::Leaf(I18n::Message::TryExcept2ErrorWithArg, I18n::Message::Default, false, I18n::Message::TryExcept2Error, true, 4),
ToolboxMessageTree::Leaf(I18n::Message::WithInstructionWithArg, I18n::Message::Default, false, I18n::Message::WithInstruction), ToolboxMessageTree::Leaf(I18n::Message::WithInstructionWithArg, I18n::Message::Default, false, I18n::Message::WithInstruction, true, 2),
}; };
const ToolboxMessageTree menu[] = { const ToolboxMessageTree menu[] = {
@@ -645,6 +726,10 @@ const ToolboxMessageTree toolboxModel = ToolboxMessageTree::Node(I18n::Message::
PythonToolbox::PythonToolbox() : PythonToolbox::PythonToolbox() :
Toolbox(nullptr, rootModel()->label()) Toolbox(nullptr, rootModel()->label())
{ {
for (int i=0; i < k_maxNumberOfDisplayedRows; i++) {
m_leafCells[i].setMessageFont(KDFont::LargeFont);
m_nodeCells[i].setMessageFont(KDFont::LargeFont);
}
} }
const ToolboxMessageTree * PythonToolbox::moduleChildren(const char * name, int * numberOfNodes) const { const ToolboxMessageTree * PythonToolbox::moduleChildren(const char * name, int * numberOfNodes) const {
@@ -675,36 +760,28 @@ bool PythonToolbox::handleEvent(Ion::Events::Event event) {
return false; return false;
} }
void PythonToolbox::willDisplayCellForIndex(HighlightCell * cell, int index) {
Toolbox::willDisplayCellForIndex(cell, index);
const ToolboxMessageTree * messageTree = static_cast<const ToolboxMessageTree *>(m_messageTreeModel->childAtIndex(index));
MessageTableCell<SlideableMessageTextView> * myCell = static_cast<MessageTableCell<SlideableMessageTextView> *>(cell);
myCell->setMessageFont(messageTree->isMultiLine() ? KDFont::SmallFont : KDFont::LargeFont);
}
KDCoordinate PythonToolbox::rowHeight(int j) { KDCoordinate PythonToolbox::rowHeight(int j) {
if (typeAtLocation(0, j) == Toolbox::LeafCellType && (m_messageTreeModel->label() == I18n::Message::IfStatementMenu || m_messageTreeModel->label() == I18n::Message::Exceptions)) { const ToolboxMessageTree * messageTree = static_cast<const ToolboxMessageTree *>(m_messageTreeModel->childAtIndex(j));
/* To get the exact height needed for each cell, we have to compute its if (messageTree->isMultiLine()) {
* text size, which means scan the text char by char to look for '\n' return k_fontForMultiLine->glyphSize().height() * messageTree->numberOfLines() + 2*Metric::TableCellVerticalMargin + (messageTree->text() == I18n::Message::Default ? 0 : Toolbox::rowHeight(j));
* chars. This is very costly and ruins the speed performance when
* scrolling at the bottom of a long table: to compute a position on the
* kth row, we call cumulatedHeightFromIndex(k), which calls rowHeight k
* times.
* We thus decided to compute the real height only for the ifStatement
* children of the toolbox, which is the only menu that has special height
* rows. */
const ToolboxMessageTree * messageTree = static_cast<const ToolboxMessageTree *>(m_messageTreeModel->childAtIndex(j));
return k_font->stringSize(I18n::translate(messageTree->label())).height() + 2*Metric::TableCellVerticalMargin + (messageTree->text() == I18n::Message::Default ? 0 : Toolbox::rowHeight(j));
} }
return Toolbox::rowHeight(j); return Toolbox::rowHeight(j);
} }
bool PythonToolbox::selectLeaf(int selectedRow) { bool PythonToolbox::selectLeaf(int selectedRow, bool quitToolbox) {
ToolboxMessageTree * node = (ToolboxMessageTree *)m_messageTreeModel->childAtIndex(selectedRow); ToolboxMessageTree * node = (ToolboxMessageTree *)m_messageTreeModel->childAtIndex(selectedRow);
#if defined(INCLUDE_ULAB) #if defined(INCLUDE_ULAB)
if(node->text() == I18n::Message::UlabDocumentationLink){ if(node->text() == I18n::Message::UlabDocumentationLink){
return true; return true;
} }
#endif #endif
m_selectableTableView.deselectTable();
if(node->insertedText() == I18n::Message::IonSelector){
m_ionKeys.setSender(sender());
Container::activeApp()->displayModalViewController(static_cast<ViewController*>(&m_ionKeys), 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin);
return true;
}
const char * editedText = I18n::translate(node->insertedText()); const char * editedText = I18n::translate(node->insertedText());
// strippedEditedText array needs to be in the same scope as editedText // strippedEditedText array needs to be in the same scope as editedText
char strippedEditedText[k_maxMessageSize]; char strippedEditedText[k_maxMessageSize];
@@ -715,20 +792,35 @@ bool PythonToolbox::selectLeaf(int selectedRow) {
editedText = strippedEditedText; editedText = strippedEditedText;
} }
sender()->handleEventWithText(editedText, true); sender()->handleEventWithText(editedText, true);
Container::activeApp()->dismissModalViewController(); if (quitToolbox) {
m_selectableTableView.deselectTable();
Container::activeApp()->dismissModalViewController();
}
return true; return true;
} }
// This is the same function as in the Toolbox class, but we need to override it because we need to handle the Key selector differently.
bool PythonToolbox::selectSubMenu(int selectedRow) {
// If the selected row is a is the Key selector, we display the IonKeySelectorViewController
if (m_messageTreeModel->childAtIndex(selectedRow)->label() == I18n::Message::IonSelector) {
m_ionKeys.setSender(sender());
Container::activeApp()->displayModalViewController(static_cast<ViewController*>(&m_ionKeys), 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin);
return true;
}
return Toolbox::selectSubMenu(selectedRow);
}
const ToolboxMessageTree * PythonToolbox::rootModel() const { const ToolboxMessageTree * PythonToolbox::rootModel() const {
return &toolboxModel; return &toolboxModel;
} }
MessageTableCellWithMessage * PythonToolbox::leafCellAtIndex(int index) { MessageTableCellWithMessage<SlideableMessageTextView> * PythonToolbox::leafCellAtIndex(int index) {
assert(index >= 0 && index < k_maxNumberOfDisplayedRows); assert(index >= 0 && index < k_maxNumberOfDisplayedRows);
return &m_leafCells[index]; return &m_leafCells[index];
} }
MessageTableCellWithChevron* PythonToolbox::nodeCellAtIndex(int index) { MessageTableCellWithChevron<SlideableMessageTextView> * PythonToolbox::nodeCellAtIndex(int index) {
assert(index >= 0 && index < k_maxNumberOfDisplayedRows); assert(index >= 0 && index < k_maxNumberOfDisplayedRows);
return &m_nodeCells[index]; return &m_nodeCells[index];
} }

View File

@@ -18,22 +18,28 @@ public:
// Toolbox // Toolbox
bool handleEvent(Ion::Events::Event event) override; bool handleEvent(Ion::Events::Event event) override;
const ToolboxMessageTree * rootModel() const override; const ToolboxMessageTree * rootModel() const override;
// ListViewDataSource
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
protected: protected:
KDCoordinate rowHeight(int j) override; KDCoordinate rowHeight(int j) override;
bool selectLeaf(int selectedRow) override; bool selectLeaf(int selectedRow, bool quitToolbox) override;
MessageTableCellWithMessage * leafCellAtIndex(int index) override; bool selectSubMenu(int selectedRow) override;
MessageTableCellWithChevron* nodeCellAtIndex(int index) override; MessageTableCellWithMessage<SlideableMessageTextView> * leafCellAtIndex(int index) override;
MessageTableCellWithChevron<SlideableMessageTextView> * nodeCellAtIndex(int index) override;
int maxNumberOfDisplayedRows() override; int maxNumberOfDisplayedRows() override;
bool canStayInMenu() override { return true; }
constexpr static int k_maxNumberOfDisplayedRows = 13; // = 240/(13+2*3) constexpr static int k_maxNumberOfDisplayedRows = 13; // = 240/(13+2*3)
// 13 = minimal string height size // 13 = minimal string height size
// 3 = vertical margins // 3 = vertical margins
private: private:
constexpr static const KDFont * k_font = KDFont::SmallFont; constexpr static const KDFont * k_fontForMultiLine = KDFont::SmallFont;
void scrollToLetter(char letter); void scrollToLetter(char letter);
void scrollToAndSelectChild(int i); void scrollToAndSelectChild(int i);
MessageTableCellWithMessage m_leafCells[k_maxNumberOfDisplayedRows]; MessageTableCellWithMessage<SlideableMessageTextView> m_leafCells[k_maxNumberOfDisplayedRows];
MessageTableCellWithChevron m_nodeCells[k_maxNumberOfDisplayedRows]; MessageTableCellWithChevron<SlideableMessageTextView> m_nodeCells[k_maxNumberOfDisplayedRows];
toolboxIonKeys m_ionKeys; ToolboxIonKeys m_ionKeys;
}; };
} }

View File

@@ -21,10 +21,10 @@ void ScriptNodeCell::ScriptNodeView::drawRect(KDContext * ctx, KDRect rect) cons
const int nodeNameLength = m_scriptNode->nameLength(); const int nodeNameLength = m_scriptNode->nameLength();
KDSize nameSize = k_font->stringSize(nodeName, nodeNameLength); KDSize nameSize = k_font->stringSize(nodeName, nodeNameLength);
const KDCoordinate nodeNameY = k_topMargin; 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 it is needed, draw the parentheses
if (m_scriptNode->type() == ScriptNode::Type::WithParentheses) { 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 /* If it exists, draw the source name. If it did not fit, we would have put

View File

@@ -34,11 +34,11 @@ private:
constexpr static int k_totalNumberOfCell = 6; constexpr static int k_totalNumberOfCell = 6;
StackViewController * stackViewController(); StackViewController * stackViewController();
I18n::Message m_pageTitle; I18n::Message m_pageTitle;
MessageTableCell m_executeScript; MessageTableCell<> m_executeScript;
MessageTableCell m_renameScript; MessageTableCell<> m_renameScript;
MessageTableCellWithSwitch m_autoImportScript; MessageTableCellWithSwitch m_autoImportScript;
MessageTableCell m_deleteScript; MessageTableCell<> m_deleteScript;
MessageTableCell m_duplicateScript; MessageTableCell<> m_duplicateScript;
MessageTableCellWithBuffer m_size; MessageTableCellWithBuffer m_size;
void GetScriptSize(MessageTableCellWithBuffer* myCell); void GetScriptSize(MessageTableCellWithBuffer* myCell);
SelectableTableView m_selectableTableView; SelectableTableView m_selectableTableView;

View File

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

View File

@@ -49,7 +49,7 @@ private:
* k_fullFreeSpaceSizeLimit, we consider the script store as full. * k_fullFreeSpaceSizeLimit, we consider the script store as full.
* To be able to add a new empty record, the available space should at least * To be able to add a new empty record, the available space should at least
* be able to store a Script with default name and its extension, the * be able to store a Script with default name and its extension, the
* importation status (1 char), the default content "from math import *\n" * importation status (1 char), the cursor (2 char), the default content "from math import *\n"
* (20 char) and 10 char of free space. */ * (20 char) and 10 char of free space. */
static constexpr int k_fullFreeSpaceSizeLimit = sizeof(Ion::Storage::record_size_t)+Script::k_defaultScriptNameMaxSize+k_scriptExtensionLength+1+20+10; static constexpr int k_fullFreeSpaceSizeLimit = sizeof(Ion::Storage::record_size_t)+Script::k_defaultScriptNameMaxSize+k_scriptExtensionLength+1+20+10;
}; };

View File

@@ -5,103 +5,9 @@ namespace Code {
constexpr ScriptTemplate emptyScriptTemplate(".py", "\x01" R"(from math import * 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() { const ScriptTemplate * ScriptTemplate::Empty() {
return &emptyScriptTemplate; 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: public:
constexpr ScriptTemplate(const char * name, const char * value) : m_name(name), m_value(value) {} constexpr ScriptTemplate(const char * name, const char * value) : m_name(name), m_value(value) {}
static const ScriptTemplate * Empty(); 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 * name() const { return m_name; }
const char * content() const { return m_value + Script::StatusSize(); } const char * content() const { return m_value + Script::StatusSize(); }
const char * value() const { return m_value; } const char * value() const { return m_value; }

View File

@@ -1,26 +1,26 @@
#include "../toolbox_ion_keys.h" #include "../toolbox_ion_keys.h"
namespace Code { namespace Code {
toolboxIonKeys::toolboxIonKeys() : ToolboxIonKeys::ToolboxIonKeys() :
ViewController(nullptr), ViewController(nullptr),
m_view() m_view()
{ {
} }
bool toolboxIonKeys::handleEvent(Ion::Events::Event e) { bool ToolboxIonKeys::handleEvent(Ion::Events::Event e) {
return false; return false;
} }
toolboxIonKeys::toolboxIonView::toolboxIonView(): ToolboxIonKeys::toolboxIonView::toolboxIonView():
View() View()
{ {
} }
void toolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const { void ToolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const {
return; return;
} }
View * toolboxIonKeys::view(){ View * ToolboxIonKeys::view(){
return &m_view; return &m_view;
} }

View File

@@ -40,7 +40,7 @@ void assert_variables_are(const char * script, const char * nameToComplete, cons
&addParentheses, &addParentheses,
i, i,
&index); &index);
quiz_assert(i == index); // If false, the autompletion has cycled: there are not as many results as expected quiz_assert(i == index); // If false, the autocompletion has cycled: there are not as many results as expected
quiz_assert(strncmp(*(expectedVariables + i), autocompletionI - nameToCompleteLength, textToInsertLength + nameToCompleteLength) == 0); quiz_assert(strncmp(*(expectedVariables + i), autocompletionI - nameToCompleteLength, textToInsertLength + nameToCompleteLength) == 0);
index++; index++;
} }
@@ -63,7 +63,7 @@ QUIZ_CASE(variable_box_controller) {
}; };
// FIXME This test does not load imported variables for now // FIXME This test does not load imported variables for now
assert_variables_are( assert_variables_are(
"\x01 from math import *\nfroo=3", "\x01\x01\x01 from math import *\nfroo=3",
"fr", "fr",
expectedVariables, expectedVariables,
sizeof(expectedVariables) / sizeof(const char *)); sizeof(expectedVariables) / sizeof(const char *));

View File

@@ -5,3 +5,6 @@ LoopsAndTests = "Schleifen und Tests"
Files = "Dateien" Files = "Dateien"
Exceptions = "Ausnahmen" Exceptions = "Ausnahmen"
UlabDocumentation = "Dokumentation" UlabDocumentation = "Dokumentation"
IonSelector = "Schlüsselauswahl"
PressAKey = "drücke eine Taste"
IonKeyList = "Liste der Schlüssel"

View File

@@ -5,3 +5,6 @@ LoopsAndTests = "Loops and tests"
Files = "Files" Files = "Files"
Exceptions = "Exceptions" Exceptions = "Exceptions"
UlabDocumentation = "Documentation" UlabDocumentation = "Documentation"
IonSelector = "Key selector"
PressAKey = "Press a key"
IonKeyList = "List of keys"

View File

@@ -5,3 +5,6 @@ LoopsAndTests = "Loops and tests"
Files = "Files" Files = "Files"
Exceptions = "Exceptions" Exceptions = "Exceptions"
UlabDocumentation = "Documentación" UlabDocumentation = "Documentación"
IonSelector = "Selector de llave"
PressAKey = "presione una tecla"
IonKeyList = "Lista de llaves"

View File

@@ -5,3 +5,6 @@ LoopsAndTests = "Boucles et tests"
Files = "Fichiers" Files = "Fichiers"
Exceptions = "Exceptions" Exceptions = "Exceptions"
UlabDocumentation = "Documentation" UlabDocumentation = "Documentation"
IonSelector = "Sélecteur de touche"
PressAKey = "Appuyez sur une touche"
IonKeyList = "Liste des touches"

View File

@@ -5,3 +5,6 @@ LoopsAndTests = "Hurkok és tesztek"
Files = "Fájlok" Files = "Fájlok"
Exceptions = "Kivételek" Exceptions = "Kivételek"
UlabDocumentation = "Dokumentáció" UlabDocumentation = "Dokumentáció"
IonSelector = "Kulcsválasztó"
PressAKey = "Nyomj meg egy gombot"
IonKeyList = "A kulcsok listája"

View File

@@ -2,6 +2,9 @@ Functions = "Funzioni"
Catalog = "Catalogo" Catalog = "Catalogo"
Modules = "Moduli" Modules = "Moduli"
LoopsAndTests = "Cicli e test" LoopsAndTests = "Cicli e test"
Files = "Files" Files = "File"
Exceptions = "Exceptions" Exceptions = "Eccezioni"
UlabDocumentation = "Documentazione" UlabDocumentation = "Documentazione"
IonSelector = "Selettore tasti"
PressAKey = "Premi un tasto"
IonKeyList = "Elenco dei tasti"

View File

@@ -5,3 +5,6 @@ LoopsAndTests = "Herhalingen en testen"
Files = "Files" Files = "Files"
Exceptions = "Exceptions" Exceptions = "Exceptions"
UlabDocumentation = "Documentatie" UlabDocumentation = "Documentatie"
IonSelector = "Toetsenkiezer"
PressAKey = "druk op een knop"
IonKeyList = "Lijst met sleutels"

View File

@@ -5,3 +5,6 @@ LoopsAndTests = "Laços e testes"
Files = "Files" Files = "Files"
Exceptions = "Exceptions" Exceptions = "Exceptions"
UlabDocumentation = "Documentação" UlabDocumentation = "Documentação"
IonSelector = "Seletor de chave"
PressAKey = "Pressione uma tecla"
IonKeyList = "Lista de chaves"

View File

@@ -12,6 +12,7 @@ ScipyOptimizeModule = "optimize"
ScipySignalModule = "signal" ScipySignalModule = "signal"
ScipySpecialModule = "special" ScipySpecialModule = "special"
NumpyNdarray = "ndarray" NumpyNdarray = "ndarray"
UtilsModule = "utils"
OsModule = "os" OsModule = "os"
SysModule = "sys" SysModule = "sys"
TimeModule = "time" TimeModule = "time"
@@ -68,6 +69,4 @@ PythonCommandDef = "def \x11():\n "
PythonCommandDefWithArg = "def function(x):" PythonCommandDefWithArg = "def function(x):"
PythonCommandReturn = "return " PythonCommandReturn = "return "
RandomModule = "random" RandomModule = "random"
IonSelector = "Key selector"
PressAKey = "Press a key"
UlabDocumentationLink = "micropython-ulab.readthedocs.io" UlabDocumentationLink = "micropython-ulab.readthedocs.io"

View File

@@ -6,45 +6,52 @@ extern "C" {
#include <py/obj.h> #include <py/obj.h>
#include <py/objfun.h> #include <py/objfun.h>
} }
extern const mp_rom_map_elem_t modion_module_globals_table[48]; extern "C" const mp_rom_map_elem_t modion_module_globals_table[55];
namespace Code { namespace Code {
toolboxIonKeys::toolboxIonKeys() : ToolboxIonKeys::ToolboxIonKeys() :
ViewController(nullptr), ViewController(nullptr),
m_view() m_view()
{ {
} }
bool toolboxIonKeys::handleEvent(Ion::Events::Event e) { bool ToolboxIonKeys::handleEvent(Ion::Events::Event e) {
Ion::Keyboard::State state = Ion::Keyboard::scan(); // FIXME: Use event data to get the pressed key and fix the EXE key.
for(uint16_t i = 0; i < sizeof(modion_module_globals_table)/sizeof(_mp_rom_map_elem_t); i++){ Ion::Keyboard::State state = Ion::Keyboard::scan();
_mp_rom_map_elem_t element = modion_module_globals_table[i]; for (uint16_t i = 0; i < sizeof(modion_module_globals_table) / sizeof(_mp_rom_map_elem_t); i++) {
if(mp_obj_is_small_int(element.value)){ _mp_rom_map_elem_t element = modion_module_globals_table[i];
int key = mp_obj_get_int(element.value); if (mp_obj_is_small_int(element.value)) {
if(state.keyDown(static_cast<Ion::Keyboard::Key>(key))){ int key = mp_obj_get_int(element.value);
m_sender->handleEventWithText(qstr_str(MP_OBJ_QSTR_VALUE(element.key)), true); if (state.keyDown(static_cast<Ion::Keyboard::Key>(key))) {
} m_sender->handleEventWithText(qstr_str(MP_OBJ_QSTR_VALUE(element.key)), true);
} }
} }
Container::activeApp()->dismissModalViewController();
AppsContainer::sharedAppsContainer()->redrawWindow();
return true;
} }
Container::activeApp()->dismissModalViewController();
AppsContainer::sharedAppsContainer()->redrawWindow();
return true;
}
toolboxIonKeys::toolboxIonView::toolboxIonView(): ToolboxIonKeys::toolboxIonView::toolboxIonView() :
View() View()
{ {
} }
void toolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const { void ToolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(rect, Palette::GrayBright); ctx->fillRect(rect, Palette::WallScreen);
ctx->strokeRect(rect, Palette::GrayDark); ctx->strokeRect(rect, Palette::ListCellBorder);
ctx->drawString(I18n::translate(I18n::Message::PressAKey),KDPoint(rect.left()+80, rect.top()+20)); KDSize fontSize = KDFont::LargeFont->glyphSize();
const char * message = I18n::translate(I18n::Message::PressAKey);
// Get the starting position of the text to center it.
KDPoint textPosition = KDPoint(rect.size().width() / 2 - strlen(message) * fontSize.width() / 2,
rect.size().height() / 2 - fontSize.height() / 2);
} ctx->drawString(message, textPosition, KDFont::LargeFont, Palette::PrimaryText, Palette::WallScreen);
View * toolboxIonKeys::view(){ }
return &m_view;
} View * ToolboxIonKeys::view() {
return &m_view;
}
} }

View File

@@ -2,9 +2,9 @@
namespace Code { namespace Code {
class toolboxIonKeys : public ViewController { class ToolboxIonKeys : public ViewController {
public : public :
toolboxIonKeys(); ToolboxIonKeys();
View * view() override; View * view() override;
bool handleEvent(Ion::Events::Event e) override; bool handleEvent(Ion::Events::Event e) override;
void setSender(InputEventHandler * sender) { m_sender = sender; } void setSender(InputEventHandler * sender) { m_sender = sender; }

View File

@@ -128,7 +128,7 @@ void VariableBoxController::willDisplayCellForIndex(HighlightCell * cell, int in
I18n::Message::BuiltinsAndKeywords, I18n::Message::BuiltinsAndKeywords,
I18n::Message::ImportedModulesAndScripts I18n::Message::ImportedModulesAndScripts
}; };
static_cast<MessageTableCell *>(cell)->setMessage(subtitleMessages[(int)cellOrigin]); static_cast<MessageTableCell<> *>(cell)->setMessage(subtitleMessages[(int)cellOrigin]);
} }
void VariableBoxController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) { void VariableBoxController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) {
@@ -365,7 +365,7 @@ int VariableBoxController::typeAndOriginAtLocation(int i, NodeOrigin * resultOri
} }
bool VariableBoxController::selectLeaf(int rowIndex) { bool VariableBoxController::selectLeaf(int rowIndex, bool quitToolbox) {
assert(rowIndex >= 0 && rowIndex < numberOfRows()); assert(rowIndex >= 0 && rowIndex < numberOfRows());
m_selectableTableView.deselectTable(); m_selectableTableView.deselectTable();
@@ -516,7 +516,7 @@ void VariableBoxController::loadBuiltinNodes(const char * textToAutocomplete, in
assert(sizeof(builtinNames) / sizeof(builtinNames[0]) == k_totalBuiltinNodesCount); assert(sizeof(builtinNames) / sizeof(builtinNames[0]) == k_totalBuiltinNodesCount);
for (int i = 0; i < k_totalBuiltinNodesCount; i++) { for (int i = 0; i < k_totalBuiltinNodesCount; i++) {
if (addNodeIfMatches(textToAutocomplete, textToAutocompleteLength, builtinNames[i].type, NodeOrigin::Builtins, builtinNames[i].name)) { if (addNodeIfMatches(textToAutocomplete, textToAutocompleteLength, builtinNames[i].type, NodeOrigin::Builtins, builtinNames[i].name)) {
/* We can leverage on the fact that buitin nodes are stored in /* We can leverage on the fact that builtin nodes are stored in
* alphabetical order. */ * alphabetical order. */
return; return;
} }
@@ -575,7 +575,7 @@ void VariableBoxController::loadImportedVariablesInScript(const char * scriptCon
} }
void VariableBoxController::loadCurrentVariablesInScript(const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength) { void VariableBoxController::loadCurrentVariablesInScript(const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength) {
/* To find variable and funtion names: we lex the script and keep all /* To find variable and function names: we lex the script and keep all
* MP_TOKEN_NAME that complete the text to autocomplete and are not already in * MP_TOKEN_NAME that complete the text to autocomplete and are not already in
* the builtins or imported scripts. */ * the builtins or imported scripts. */
@@ -653,7 +653,7 @@ void VariableBoxController::loadGlobalAndImportedVariablesInScriptAsImported(Scr
/* At this point, if the script node is not of type "file_input_2", it /* At this point, if the script node is not of type "file_input_2", it
* will not have main structures of the wanted type. * will not have main structures of the wanted type.
* We look for structures at first level (not inside nested scopes) that * We look for structures at first level (not inside nested scopes) that
* are either dunction definitions, variables statements or imports. */ * are either function definitions, variables statements or imports. */
size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
mp_parse_node_t child = pns->nodes[i]; mp_parse_node_t child = pns->nodes[i];
@@ -823,18 +823,18 @@ bool VariableBoxController::importationSourceIsModule(const char * sourceName, c
return true; return true;
} }
// The sourceName might be a module that is not in the toolbox // The sourceName might be a module that is not in the toolbox
return mp_module_get(qstr_from_str(sourceName)) != MP_OBJ_NULL; return mp_module_get_loaded_or_builtin(qstr_from_str(sourceName)) != MP_OBJ_NULL;
} }
bool VariableBoxController::importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retreivedScript) { bool VariableBoxController::importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retrievedScript) {
// Try fetching the nodes from a script // Try fetching the nodes from a script
Script importedScript = ScriptStore::ScriptBaseNamed(sourceName); Script importedScript = ScriptStore::ScriptBaseNamed(sourceName);
if (importedScript.isNull()) { if (importedScript.isNull()) {
return false; return false;
} }
*scriptFullName = importedScript.fullName(); *scriptFullName = importedScript.fullName();
if (retreivedScript != nullptr) { if (retrievedScript != nullptr) {
*retreivedScript = importedScript; *retrievedScript = importedScript;
} }
return true; return true;
} }

View File

@@ -80,7 +80,7 @@ private:
// NestedMenuController // NestedMenuController
HighlightCell * leafCellAtIndex(int index) override { assert(false); return nullptr; } HighlightCell * leafCellAtIndex(int index) override { assert(false); return nullptr; }
HighlightCell * nodeCellAtIndex(int index) override { assert(false); return nullptr; } HighlightCell * nodeCellAtIndex(int index) override { assert(false); return nullptr; }
bool selectLeaf(int rowIndex) override; bool selectLeaf(int rowIndex, bool quitToolbox) override;
void insertTextInCaller(const char * text, int textLength = -1); void insertTextInCaller(const char * text, int textLength = -1);
// Loading // Loading
@@ -92,7 +92,7 @@ private:
bool addNodesFromImportMaybe(mp_parse_node_struct_t * parseNode, const char * textToAutocomplete, int textToAutocompleteLength, bool importFromModules = true); bool addNodesFromImportMaybe(mp_parse_node_struct_t * parseNode, const char * textToAutocomplete, int textToAutocompleteLength, bool importFromModules = true);
const char * importationSourceNameFromNode(mp_parse_node_t & node); const char * importationSourceNameFromNode(mp_parse_node_t & node);
bool importationSourceIsModule(const char * sourceName, const ToolboxMessageTree * * moduleChildren = nullptr, int * numberOfModuleChildren = nullptr); bool importationSourceIsModule(const char * sourceName, const ToolboxMessageTree * * moduleChildren = nullptr, int * numberOfModuleChildren = nullptr);
bool importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retreivedScript = nullptr); bool importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retrievedScript = nullptr);
bool addImportStructFromScript(mp_parse_node_struct_t * pns, uint structKind, const char * scriptName, const char * textToAutocomplete, int textToAutocompleteLength); bool addImportStructFromScript(mp_parse_node_struct_t * pns, uint structKind, const char * scriptName, const char * textToAutocomplete, int textToAutocompleteLength);
/* Add a node if it completes the text to autocomplete and if it is not /* Add a node if it completes the text to autocomplete and if it is not
* already contained in the variable box. The returned boolean means we * already contained in the variable box. The returned boolean means we
@@ -104,7 +104,7 @@ private:
ScriptNode m_builtinNodes[k_totalBuiltinNodesCount]; ScriptNode m_builtinNodes[k_totalBuiltinNodesCount];
ScriptNode m_importedNodes[k_maxScriptNodesCount]; ScriptNode m_importedNodes[k_maxScriptNodesCount];
ScriptNodeCell m_itemCells[k_maxNumberOfDisplayedItems]; ScriptNodeCell m_itemCells[k_maxNumberOfDisplayedItems];
MessageTableCell m_subtitleCells[k_scriptOriginsCount]; MessageTableCell<> m_subtitleCells[k_scriptOriginsCount];
ScriptStore * m_scriptStore; ScriptStore * m_scriptStore;
size_t m_currentScriptNodesCount; size_t m_currentScriptNodesCount;
size_t m_builtinNodesCount; size_t m_builtinNodesCount;

View File

@@ -0,0 +1,6 @@
#include <escher/timer_manager.h>
// This is the dummy implementation used in tests
void TimerManager::AddTimer(Timer * timer) { }
void TimerManager::RemoveTimer(Timer * timer) { }

2
apps/external/app.h vendored
View File

@@ -29,7 +29,7 @@ private:
MainController m_mainController; MainController m_mainController;
StackViewController m_stackViewController; StackViewController m_stackViewController;
Window * m_window; Window * m_window;
static constexpr int k_externalHeapSize = 100000; static constexpr int k_externalHeapSize = 99000;
char m_externalHeap[k_externalHeapSize]; char m_externalHeap[k_externalHeapSize];
}; };

View File

@@ -1,6 +1,15 @@
#include <extapp_api.h> #include <extapp_api.h>
#if defined _FXCG || defined NSPIRE_NEWLIB
// On the port, we use the Built-in file manager to import files.
void host_filemanager();
void extapp_main() {
host_filemanager();
}
#else
// Elsewhere, just draw a rectangle to test the extapp API.
void extapp_main() { void extapp_main() {
extapp_pushRectUniform(10, 10, LCD_WIDTH-20, LCD_HEIGHT-20, 0); extapp_pushRectUniform(10, 10, LCD_WIDTH-20, LCD_HEIGHT-20, 0);
extapp_msleep(1000); extapp_msleep(1000);
} }
#endif

View File

@@ -40,9 +40,10 @@ bool isExamModeAndFileNotExecutable(const TarHeader* tar) {
} }
bool fileAtIndex(size_t index, File &entry) { bool fileAtIndex(size_t index, File &entry) {
if (index == -1) if (index == -1) {
return false; return false;
}
const TarHeader* tar = reinterpret_cast<const TarHeader*>(0x90200000); const TarHeader* tar = reinterpret_cast<const TarHeader*>(0x90200000);
unsigned size = 0; unsigned size = 0;
@@ -74,6 +75,8 @@ bool fileAtIndex(size_t index, File &entry) {
entry.data = reinterpret_cast<const uint8_t*>(tar) + sizeof(TarHeader); entry.data = reinterpret_cast<const uint8_t*>(tar) + sizeof(TarHeader);
entry.dataLength = size; entry.dataLength = size;
entry.isExecutable = (tar->mode[4] & 0x01) == 1; entry.isExecutable = (tar->mode[4] & 0x01) == 1;
// TODO: Handle the trash
entry.readable = true;
return true; return true;
} else { } else {
@@ -111,18 +114,31 @@ uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize) {
return -1; return -1;
} }
int indexFromName(const char *name) {
File entry;
for (int i = 0; fileAtIndex(i, entry); i++) { #else
if (strcmp(name, entry.name) == 0) {
return i; bool fileAtIndex(size_t index, File &entry) {
} if (index != 0) {
return false;
} }
return -1; entry.name = "Built-in";
entry.data = NULL;
entry.dataLength = 0;
entry.isExecutable = true;
entry.readable = true;
return true;
} }
extern "C" void extapp_main(void);
uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize) {
extapp_main();
return 0;
}
#endif
size_t numberOfFiles() { size_t numberOfFiles() {
File dummy; File dummy;
size_t count; size_t count;
@@ -132,6 +148,18 @@ size_t numberOfFiles() {
return count; return count;
} }
int indexFromName(const char *name) {
File entry;
for (int i = 0; fileAtIndex(i, entry); i++) {
if (entry.readable && strcmp(name, entry.name) == 0) {
return i;
}
}
return -1;
}
bool executableAtIndex(size_t index, File &entry) { bool executableAtIndex(size_t index, File &entry) {
File dummy; File dummy;
size_t count; size_t count;
@@ -144,16 +172,19 @@ bool executableAtIndex(size_t index, File &entry) {
entry.data = dummy.data; entry.data = dummy.data;
entry.dataLength = dummy.dataLength; entry.dataLength = dummy.dataLength;
entry.isExecutable = dummy.isExecutable; entry.isExecutable = dummy.isExecutable;
entry.readable = dummy.readable;
return true; return true;
} }
final_count++; final_count++;
} }
} }
return false; return false;
} }
size_t numberOfExecutables() { size_t numberOfExecutables() {
if (!GlobalPreferences::sharedGlobalPreferences()->externalAppShown()) {
return false;
}
File dummy; File dummy;
size_t count; size_t count;
size_t final_count = 0; size_t final_count = 0;
@@ -165,48 +196,5 @@ size_t numberOfExecutables() {
return final_count; return final_count;
} }
#else
bool fileAtIndex(size_t index, File &entry) {
if (index != 0)
return false;
entry.name = "Built-in";
entry.data = NULL;
entry.dataLength = 0;
entry.isExecutable = true;
return true;
}
bool executableAtIndex(size_t index, File &entry) {
return fileAtIndex(index, entry);
}
size_t numberOfExecutables() {
return 1;
}
extern "C" void extapp_main(void);
uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize) {
extapp_main();
return 0;
}
int indexFromName(const char *name) {
if (strcmp(name, "Built-in") == 0)
return 0;
else
return -1;
}
size_t numberOfFiles() {
return 1;
}
#endif
} }
} }

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