mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 16:57:31 +01:00
Compare commits
9 Commits
upsilon-de
...
upsilon-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51fd990c31 | ||
|
|
7af2b45f1d | ||
|
|
d95785ba42 | ||
|
|
d108b76a32 | ||
|
|
a3d3cbbfa5 | ||
|
|
3a41cbdc85 | ||
|
|
3ccfdf0365 | ||
|
|
6aad7d2279 | ||
|
|
5c1f192228 |
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -23,7 +23,5 @@ A clear and concise description of what you expected to happen.
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Device (please complete the following information):**
|
||||
- The device on which you're running Upsilon (computer, n0110, n0100, etc...)
|
||||
**Desktop (please complete the following information):**
|
||||
- Upsilon Version: [go to settings > about > Upsilon Version and type the version here]
|
||||
- Upsilon commit: [settings > about > click one time on epsilon version]
|
||||
|
||||
12
.github/workflows/ci-docker.yml
vendored
Normal file
12
.github/workflows/ci-docker.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
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)
|
||||
505
.github/workflows/ci-workflow.yml
vendored
505
.github/workflows/ci-workflow.yml
vendored
@@ -8,359 +8,115 @@ on:
|
||||
triggerIos:
|
||||
description: 'Run iOS tests'
|
||||
required: true
|
||||
default: 'yes'
|
||||
default: 'no'
|
||||
triggerMacos:
|
||||
description: 'Run macOS tests'
|
||||
required: true
|
||||
default: 'yes'
|
||||
default: 'no'
|
||||
trigger3DS:
|
||||
description: 'Run 3DS tests'
|
||||
required: true
|
||||
default: 'yes'
|
||||
triggerFxcg:
|
||||
description: 'Run fxcg tests'
|
||||
required: true
|
||||
default: 'no'
|
||||
|
||||
jobs:
|
||||
fxcg: # fxcg build is broken for now, disabling it for now to avoid noise
|
||||
if: github.event.inputs.triggerFxcg == 'yes'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential cmake libfreetype-dev -y
|
||||
- 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 == ''
|
||||
if: github.event.inputs.trigger3DS == 'yes'
|
||||
runs-on: ubuntu-latest
|
||||
container: devkitpro/devkitarm:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- run: wget https://github.com/devkitPro/pacman/releases/download/v1.0.2/devkitpro-pacman.amd64.deb -O /tmp/devkitpro-pacman.deb
|
||||
- run: yes | sudo dpkg -i /tmp/devkitpro-pacman.deb
|
||||
- run: yes | sudo dkp-pacman -Syu --needed devkitARM 3dstools libctru
|
||||
- run: echo ::set-env name=DEVKITPRO::/opt/devkitpro
|
||||
- run: echo ::set-env name=DEVKITARM::/opt/devkitpro/devkitARM
|
||||
- run: echo ::set-env name=PATH::$DEVKITPRO/tools/bin:$DEVKITARM/bin:$PATH
|
||||
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
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 epsilon.cia
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-3ds.3dsx
|
||||
path: output/release/simulator/3ds/epsilon.3dsx
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-3ds.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:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: |
|
||||
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
|
||||
- run: make -j2 PLATFORM=simulator TARGET=android
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-android.apk
|
||||
path: output/release/simulator/android/epsilon.apk
|
||||
n0100:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ubuntu-latest
|
||||
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
|
||||
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
|
||||
- uses: numworks/setup-arm-toolchain@2020-q2
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- 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.en.internal.bin
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.en.bin
|
||||
- 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.fr.internal.bin
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.fr.bin
|
||||
- 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.nl.internal.bin
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.nl.bin
|
||||
- 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.pt.internal.bin
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.pt.bin
|
||||
- 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.it.internal.bin
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.it.bin
|
||||
- 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.de.internal.bin
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.de.bin
|
||||
- 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.es.internal.bin
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.es.bin
|
||||
- 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.hu.internal.bin
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.hu.bin
|
||||
- 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: 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: tar cvfz binpack-n0100.tgz final-output/*
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-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:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ubuntu-latest
|
||||
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
|
||||
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
|
||||
- uses: numworks/setup-arm-toolchain@2020-q2
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 MODEL=n0110 epsilon.dfu
|
||||
- run: make -j2 MODEL=n0110 epsilon.onboarding.dfu
|
||||
- run: make -j2 MODEL=n0110 epsilon.onboarding.update.dfu
|
||||
- run: make -j2 MODEL=n0110 epsilon.onboarding.beta.dfu
|
||||
- run: make -j2 MODEL=n0110 flasher.light.dfu
|
||||
- run: make -j2 MODEL=n0110 flasher.verbose.dfu
|
||||
- run: make -j2 MODEL=n0110 flasher.verbose.bin
|
||||
- run: make -j2 MODEL=n0110 bench.ram.dfu
|
||||
# - run: make -j2 MODEL=n0110 bench.flash.dfu
|
||||
- run: make -j2 MODEL=n0110 binpack
|
||||
- run: make -j2 epsilon.dfu
|
||||
- run: make -j2 epsilon.onboarding.dfu
|
||||
- run: make -j2 epsilon.onboarding.update.dfu
|
||||
- run: make -j2 epsilon.onboarding.beta.dfu
|
||||
- run: make -j2 flasher.light.dfu
|
||||
- run: make -j2 flasher.verbose.dfu
|
||||
- run: make -j2 bench.ram.dfu
|
||||
- run: make -j2 bench.flash.dfu
|
||||
- run: make -j2 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/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
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-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:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
@@ -368,215 +124,76 @@ jobs:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: msys2/setup-msys2@v2
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
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 git
|
||||
- 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: make -j2 PLATFORM=simulator
|
||||
- run: make -j2 PLATFORM=simulator test.exe
|
||||
- run: cmd /c output\release\simulator\windows\test.exe --headless
|
||||
- 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
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-windows.exe
|
||||
path: output/release/simulator/windows/epsilon.exe
|
||||
web:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: numworks/setup-emscripten@master
|
||||
- uses: numworks/setup-emscripten@v1
|
||||
with:
|
||||
sdk: latest
|
||||
- uses: actions/checkout@v4
|
||||
sdk: 1.40.1-fastcomp
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
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 test.js
|
||||
- run: node output/release/simulator/web/test.js --headless
|
||||
- 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
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-web.zip
|
||||
path: output/release/simulator/web/epsilon.zip
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
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
|
||||
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator
|
||||
- run: make -j2 PLATFORM=simulator test.bin
|
||||
- run: output/release/simulator/linux/test.bin --headless
|
||||
- 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
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-linux.bin
|
||||
path: output/release/simulator/linux/epsilon.bin
|
||||
macos:
|
||||
if: github.event.inputs.triggerMacos == 'yes' || github.event.inputs.triggerMacos == ''
|
||||
if: github.event.inputs.triggerMacos == 'yes'
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- run: brew install python-setuptools
|
||||
- run: brew install numworks/tap/epsilon-sdk
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator
|
||||
- run: make -j2 PLATFORM=simulator ARCH=x86_64 test.bin
|
||||
- run: output/release/simulator/macos/x86_64/test.bin --headless
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-macos.zip
|
||||
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:
|
||||
if: github.event.inputs.triggerIos == 'yes' || github.event.inputs.triggerIos == ''
|
||||
runs-on: macos-14
|
||||
if: github.event.inputs.triggerIos == 'yes'
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- run: brew install python-setuptools
|
||||
- run: brew install numworks/tap/epsilon-sdk
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0
|
||||
- run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0 APPLE_PLATFORM=ios-simulator
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-ios.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:
|
||||
ACCEPT_OFFICIAL_TOS: 1
|
||||
|
||||
27
.github/workflows/metric-workflow.yml
vendored
27
.github/workflows/metric-workflow.yml
vendored
@@ -3,43 +3,38 @@ on: [pull_request_target]
|
||||
|
||||
jobs:
|
||||
binary-size:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
|
||||
- name: Install ARM toolchain
|
||||
run: sudo apt-get install gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
uses: numworks/setup-arm-toolchain@2020-q2
|
||||
- name: Checkout PR base
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{ github.event.pull_request.base.sha }}
|
||||
path: base
|
||||
- name: Build base
|
||||
run: make -j2 -C base MODEL=n0110 epsilon.elf
|
||||
run: make -j2 -C base epsilon.elf
|
||||
- name: Checkout PR head
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
path: head
|
||||
- name: Build head
|
||||
run: make -j2 -C head MODEL=n0110 epsilon.elf
|
||||
run: make -j2 -C head epsilon.elf
|
||||
- name: Retrieve binary size analysis
|
||||
run: |
|
||||
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"
|
||||
id: binary_size
|
||||
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)"
|
||||
- name: Add comment
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v3.0.0
|
||||
with:
|
||||
script: |
|
||||
await github.rest.issues.createComment({
|
||||
await github.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
body: `${{ env.table }}`,
|
||||
body: `${{ steps.binary_size.outputs.table }}`,
|
||||
});
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,5 +8,3 @@ epsilon.map
|
||||
.gradle
|
||||
.idea/
|
||||
.vs
|
||||
.cache/
|
||||
compile_commands.json
|
||||
|
||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,6 +1,6 @@
|
||||
[submodule "apps/rpn"]
|
||||
path = apps/rpn
|
||||
url = https://github.com/UpsilonNumworks/Upsilon-RPN.git
|
||||
url = https://github.com/Lauryy06/Upsilon-RPN.git
|
||||
[submodule "apps/atomic"]
|
||||
path = apps/atomic
|
||||
url = https://github.com/UpsilonNumworks/atomic
|
||||
url = https://github.com/Lauryy06/atomic
|
||||
|
||||
26
Makefile
26
Makefile
@@ -27,15 +27,10 @@ ifeq (${MODEL}, n0100)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(filter reader,$(apps_list)),)
|
||||
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)))
|
||||
ifeq (${MODEL}, n0110)
|
||||
apps_list = ${EPSILON_APPS}
|
||||
else
|
||||
apps_list = ${EPSILON_APPS}
|
||||
apps_list = $(foreach i, ${EPSILON_APPS}, $(if $(filter external, $(i)),,$(i)))
|
||||
endif
|
||||
|
||||
ifdef FORCE_EXTERNAL
|
||||
@@ -93,7 +88,6 @@ help:
|
||||
@echo " make PLATFORM=simulator TARGET=web"
|
||||
@echo " make PLATFORM=simulator TARGET=windows"
|
||||
@echo " make PLATFORM=simulator TARGET=3ds"
|
||||
@echo " make PLATFORM=simulator TARGET=fxcg"
|
||||
|
||||
.PHONY: doc
|
||||
doc:
|
||||
@@ -107,7 +101,7 @@ print-%:
|
||||
@echo $*\'s origin is $(origin $*)
|
||||
|
||||
# Since we're building out-of-tree, we need to make sure the output directories
|
||||
# are created, otherwise the recipes will fail (e.g. gcc will fail to create
|
||||
# are created, otherwise the receipes will fail (e.g. gcc will fail to create
|
||||
# "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
|
||||
# rid of them upon completion (and fail, since those folders won't be empty).
|
||||
@@ -128,7 +122,6 @@ ifndef USE_LIBA
|
||||
endif
|
||||
ifeq ($(USE_LIBA),0)
|
||||
include liba/Makefile.bridge
|
||||
include libaxx/Makefile.bridge
|
||||
else
|
||||
SFLAGS += -ffreestanding -nostdinc -nostdlib
|
||||
include liba/Makefile
|
||||
@@ -140,7 +133,6 @@ include poincare/Makefile
|
||||
include python/Makefile
|
||||
include escher/Makefile
|
||||
# Executable Makefiles
|
||||
include bootloader/Makefile
|
||||
include apps/Makefile
|
||||
include build/struct_layout/Makefile
|
||||
include build/scenario/Makefile
|
||||
@@ -213,13 +205,3 @@ clean_run: cleanandcompile
|
||||
.PHONY: run
|
||||
run: compile
|
||||
${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
|
||||
|
||||
462
README.fr.md
462
README.fr.md
@@ -2,474 +2,150 @@
|
||||
|
||||
<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://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>
|
||||
<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>
|
||||
<br/>
|
||||
<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>
|
||||
<a href="https://discord.gg/Q9buEMduXG"><img alt="Discord" src="https://img.shields.io/discord/663420259851567114?color=blue&labelColor=292929&label=chat%20-%20discord&logo=discord&style=for-the-badge" /></a>
|
||||
</p>
|
||||
|
||||
> 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
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
### 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
|
||||
- Des applications externes
|
||||
- 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é
|
||||
- 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).
|
||||
|
||||
## 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
|
||||
|
||||
*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*
|
||||
*A l'heure actuelle, seule l'installation manuelle est possible.*
|
||||
|
||||
### 1. Installation du SDK
|
||||
|
||||
<br>
|
||||
Tout d'abord, suivez **la première étape** [ici](https://www.numworks.com/resources/engineering/software/build/), puis :
|
||||
|
||||
<details>
|
||||
<summary><b>Modèle n0100</b></summary>
|
||||
|
||||
<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.
|
||||
(note : vous pouvez changer `EPSILON_I18N=fr` en `en`, `nl`, `pt`, `it`, `de`, `es` ou `hu`).
|
||||
|
||||
```bash
|
||||
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
|
||||
git clone --recursive https://github.com/Lauryy06/Upsilon.git
|
||||
cd Upsilon
|
||||
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
|
||||
git checkout omega-master
|
||||
make MODEL=n0100 clean
|
||||
make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Votre nom, maximum 15 caractères}" -j4
|
||||
```
|
||||
|
||||
Maintenant, lancez soit:
|
||||
|
||||
```bash
|
||||
make MODEL=n0100 EPSILON_I18N=fr OMEGA_USERNAME="{Votre nom ici, 15 caractères max}" -j4
|
||||
make MODEL=n0100 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=n0100 OMEGA_USERNAME="" 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/).
|
||||
Important : N'oubliez pas l'argument `--recursive`, Upsilon a besoin de sous-modules.
|
||||
Vous pouvez aussi changer le nombre de processus parallèles pendant la compilation en changeant la valeur suivant `-j`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Model n0110</b></summary>
|
||||
|
||||
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:
|
||||
<summary><b>Modèle n0110</b></summary>
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/Lauryy06/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout omega-master
|
||||
make clean
|
||||
make OMEGA_USERNAME="{Votre nom, max 15 caractères}" -j4
|
||||
make OMEGA_USERNAME="{Votre nom ici, 15 caractères max}" -j4
|
||||
make epsilon_flash
|
||||
```
|
||||
|
||||
Ensuite lancez soit:
|
||||
Important : N'oubliez pas l'argument `--recursive`, Upsilon a besoin de sous-modules.
|
||||
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>
|
||||
|
||||
<summary>Model n0110 sans bootloader (obsolète, utilisez le bootloader à la place pour la protection contre Epsilon)</summary>
|
||||
Compilez avec:
|
||||
<summary><b>Fichiers binaires</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/)).
|
||||
|
||||
```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
|
||||
git clone --recursive https://github.com/Lauryy06/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout omega-master
|
||||
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
|
||||
make MODEL=n0100 OMEGA_USERNAME="" -j8
|
||||
make MODEL=n0100 OMEGA_USERNAME="" binpack -j8
|
||||
make OMEGA_USERNAME="" -j8
|
||||
make OMEGA_USERNAME="" binpack -j8
|
||||
```
|
||||
|
||||
Vous trouverez les fichiers du simulateur dans `output/release/simulator/`.
|
||||
|
||||
Important : N'oubliez pas l'argument `--recursive`, Upsilon a besoin de sous-modules.
|
||||
Vous pouvez aussi changer le nombre de processus parallèles pendant la compilation en changeant la valeur suivant `-j`.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Simulateur web</b></summary>
|
||||
|
||||
<summary><b>Simulateur web</b></summary>
|
||||
|
||||
D'abord, installez emsdk :
|
||||
|
||||
```bash
|
||||
git clone https://github.com/emscripten-core/emsdk.git
|
||||
cd emsdk
|
||||
./emsdk install 1.40.1
|
||||
./emsdk activate 1.40.1
|
||||
./emsdk install latest-fastcomp
|
||||
./emsdk activate latest-fastcomp
|
||||
source emsdk_env.sh
|
||||
```
|
||||
|
||||
Puis, compilez Upsilon :
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/Lauryy06/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout omega-master
|
||||
make clean
|
||||
make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Votre nom, maximum 15 caractères}" -j4
|
||||
make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Votre nom ici, 15 caractères max}" -j4
|
||||
```
|
||||
|
||||
Le simulateur se trouve dans `output/release/simulator/web/simulator.zip`
|
||||
|
||||
</details>
|
||||
|
||||
<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.
|
||||
Important : N'oubliez pas l'argument `--recursive`, Upsilon a besoin de sous-modules.
|
||||
Vous pouvez aussi changer le nombre de processus parallèles pendant la compilation en changeant la valeur suivant `-j`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Simulateur pour 3DS</b></summary>
|
||||
|
||||
Il vous faut devkitPro et devkitARM installés et dans votre path (les instructions sont [ici](https://devkitpro.org/wiki/Getting_Started))
|
||||
<summary><b>Simulateur 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))
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
|
||||
git clone --recursive https://github.com/Lauryy06/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout --recursive upsilon-dev
|
||||
make PLATFORM=simulator TARGET=3ds -j
|
||||
```
|
||||
|
||||
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:
|
||||
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 :
|
||||
|
||||
```bash
|
||||
3dslink output/release/simulator/3ds/epsilon.3dsx -a <3DS' IP ADDRESS>
|
||||
3dslink output/release/simulator/3ds/epsilon.3dsx -a <ADRESSE IP 3DS>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<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>
|
||||
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>
|
||||
---
|
||||
|
||||
## Liens utiles
|
||||
|
||||
- [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/)
|
||||
* [Upsilon external (pour installer des applications supplémentaires et des fonds d'écran)](https://lauryy06.github.io/Upsilon-External/)
|
||||
* [Documentation d'ulab](https://micropython-ulab.readthedocs.io/en/latest/)
|
||||
|
||||
## Contribution
|
||||
|
||||
@@ -479,29 +155,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
|
||||
|
||||
- [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes)
|
||||
- [Omega Website](https://github.com/Omega-Numworks/Omega-Website)
|
||||
- [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN)
|
||||
- [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic)
|
||||
- [Omega Design](https://github.com/Omega-Numworks/Omega-Design)
|
||||
- [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot)
|
||||
- [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template)
|
||||
- [External Apps](https://github.com/Omega-Numworks/External-Apps)
|
||||
* [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes)
|
||||
* [Omega Website](https://github.com/Omega-Numworks/Omega-Website)
|
||||
* [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN)
|
||||
* [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic)
|
||||
* [Omega Design](https://github.com/Omega-Numworks/Omega-Design)
|
||||
* [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot)
|
||||
* [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template)
|
||||
* [External Apps](https://github.com/Omega-Numworks/External-Apps)
|
||||
|
||||
## À 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érieures.
|
||||
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
|
||||
|
||||
Vous pouvez essayer Epsilon depuis votre navigateur sur le [simulateur en ligne](https://www.numworks.com/simulator/).
|
||||
|
||||
## Licence
|
||||
|
||||
NumWorks est une marque déposée de NumWorks SAS, 24 Rue Godot de Mauroy, 75009 Paris, France.
|
||||
Nintendo et Nintendo 3DS sont des marques déposées de Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, Etats-Unis.
|
||||
Nintendo est 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 Epsilon est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
|
||||
- Omega est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
|
||||
- Upsilon est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
|
||||
* NumWorks Epsilon est disponible sous [Lisense CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
* Omega est disponible sous [Lisense CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
* Upsilon est disponible sous [Lisense CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
|
||||
369
README.md
369
README.md
@@ -2,22 +2,24 @@
|
||||
|
||||
<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://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>
|
||||
<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>
|
||||
<br/>
|
||||
<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>
|
||||
<a href="https://discord.gg/Q9buEMduXG"><img alt="Discord" src="https://img.shields.io/discord/663420259851567114?color=blue&labelColor=292929&label=chat%20-%20discord&logo=discord&style=for-the-badge" /></a>
|
||||
</p>
|
||||
|
||||
> 🇫🇷 Vous ne comprenez pas l'anglais ? Vous êtes francophone ? Regardez le [*LISEZ-MOI* français](./README.fr.md) ! 🇫🇷
|
||||
> Vous ne comprenez pas l'anglais ? Vous êtes francophone ? Regardez le [*LISEZ-MOI* français](./README.fr.md) !
|
||||
|
||||
## About
|
||||
|
||||
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
|
||||
|
||||
- Enhancements for the Kandinsky python module
|
||||
- Support for wallpapers
|
||||
- External apps
|
||||
- Exernal apps
|
||||
- A custom theme
|
||||
- Operator overload for python
|
||||
- Improvements for the Periodic table application
|
||||
@@ -27,28 +29,23 @@ Upsilon is a fork of Omega, an user-made OS that runs on the NumWorks calculator
|
||||
|
||||
## 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
|
||||
|
||||
*You can refer to this [website](https://www.numworks.com/resources/engineering/software/build/) for the first step if you get errors.*
|
||||
*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.*
|
||||
|
||||
|
||||
|
||||
### 1. Install SDK
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>1.1 Linux</b></summary>
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
|
||||
<details>
|
||||
<summary>Debian or Ubuntu</summary>
|
||||
|
||||
<br>
|
||||
@@ -66,31 +63,26 @@ And there you can go to step 2!
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Fedora</summary>
|
||||
|
||||
<br>
|
||||
|
||||
To install all dependencies:
|
||||
First install basics dev tools.
|
||||
|
||||
```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++
|
||||
dnf install make automake gcc gcc-c++ kernel-devel
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Nix or Nixos</summary>
|
||||
|
||||
<br>
|
||||
|
||||
To install all dependencies:
|
||||
Then install required packages.
|
||||
|
||||
```bash
|
||||
nix-shell -p gcc libpng libjpeg xorg.libX11 pkg-config freetype xorg.libXext python3 imagemagick python310Packages.lz4 python310Packages.pypng python310Packages.pypng gcc-arm-embedded
|
||||
dnf install git ImageMagick libX11-devel libXext-devel freetype-devel libpng-devel libjpeg-devel pkg-config
|
||||
```
|
||||
|
||||
Then, install GCC cross compiler for ARM.
|
||||
|
||||
```bash
|
||||
dnf install arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++
|
||||
```
|
||||
|
||||
<br>
|
||||
@@ -102,17 +94,14 @@ nix-shell -p gcc libpng libjpeg xorg.libX11 pkg-config freetype xorg.libXext pyt
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>1.2 Mac</b></summary>
|
||||
|
||||
<br>
|
||||
|
||||
It's recommended to use [Homebrew](https://brew.sh/). Once it's installed, just run:
|
||||
|
||||
```bash
|
||||
brew install numworks/tap/epsilon-sdk
|
||||
```
|
||||
|
||||
and it will install all dependencies.
|
||||
|
||||
<br>
|
||||
@@ -121,19 +110,16 @@ And there you can go to step 2!
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>1.3 Windows</b></summary>
|
||||
|
||||
<br>
|
||||
|
||||
<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.
|
||||
[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.
|
||||
|
||||
```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
|
||||
@@ -145,140 +131,35 @@ Next, you'll need to install the [GCC toolchain for ARM](https://developer.arm.c
|
||||
```bash
|
||||
echo "export PATH=$PATH:$HOME/gcc-arm/bin" >> .bashrc
|
||||
```
|
||||
|
||||
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>
|
||||
|
||||
Just restart and you can go to step 2!
|
||||
</details>
|
||||
|
||||
<br>
|
||||
|
||||
### 2. Set up repo
|
||||
|
||||
|
||||
Clone repo and use 'upsilon-dev' branch by pasting these two commands:
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
|
||||
git clone --recursive https://github.com/Lauryy06/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout upsilon-dev
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
### 3. Choose the target
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Model n0100</b></summary>
|
||||
<details>
|
||||
<summary><b>Model n0100</b></summary>
|
||||
|
||||
(note: you can change the `EPSILON_I18N=en` flag to `fr`, `nl`, `pt`, `it`, `de`, `es` or `hu`).
|
||||
|
||||
```bash
|
||||
make MODEL=n0100 clean
|
||||
make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
|
||||
make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Your name, max 15 characters}" -j4
|
||||
```
|
||||
|
||||
Now, run either:
|
||||
@@ -286,127 +167,56 @@ Now, run either:
|
||||
```bash
|
||||
make MODEL=n0100 epsilon_flash
|
||||
```
|
||||
|
||||
to directly flash the calculator after pressing simultaneously `reset` and `6` buttons and plugging in.
|
||||
to directly flash the calculator after pressing simultaneously `reset` and `6` buttons and pluging in.
|
||||
|
||||
<br>
|
||||
|
||||
or:
|
||||
|
||||
```bash
|
||||
make MODEL=n0100 OMEGA_USERNAME="" binpack -j$(nproc)
|
||||
make MODEL=n0100 OMEGA_USERNAME="" binpack -j4
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
</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
|
||||
make clean
|
||||
make OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
|
||||
make OMEGA_USERNAME="{Your name, max 15 characters}" -j4
|
||||
```
|
||||
|
||||
Now, run either:
|
||||
|
||||
```bash
|
||||
make epsilon.A_flash
|
||||
make epsilon_flash
|
||||
```
|
||||
|
||||
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.
|
||||
to directly flash the calculator after pressing simultaneously `reset` and `6` buttons and pluging in.
|
||||
|
||||
<br>
|
||||
|
||||
or:
|
||||
|
||||
```bash
|
||||
make OMEGA_USERNAME="" binpack -j$(nproc)
|
||||
make OMEGA_USERNAME="" binpack -j4
|
||||
```
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
<summary><b>Web simulator</b></summary>
|
||||
|
||||
First, install emsdk :
|
||||
|
||||
```bash
|
||||
git clone https://github.com/emscripten-core/emsdk.git
|
||||
cd emsdk
|
||||
./emsdk install 1.40.1
|
||||
./emsdk activate 1.40.1
|
||||
./emsdk install latest-fastcomp
|
||||
./emsdk activate latest-fastcomp
|
||||
source emsdk_env.sh
|
||||
```
|
||||
|
||||
@@ -414,26 +224,25 @@ Then, compile Upsilon :
|
||||
|
||||
```bash
|
||||
make clean
|
||||
make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
|
||||
make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Your name, max 15 characters}" -j4
|
||||
```
|
||||
|
||||
The simulator is now in `output/release/simulator/web/simulator.zip`
|
||||
|
||||
|
||||
</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))
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
|
||||
git clone --recursive https://github.com/Lauryy06/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout upsilon-dev
|
||||
make PLATFORM=simulator TARGET=3ds -j$(nproc)
|
||||
git checkout --recursive upsilon-dev
|
||||
make PLATFORM=simulator TARGET=3ds -j
|
||||
```
|
||||
|
||||
You can then put epsilon.3dsx on a SD card to run it from the HBC or use 3dslink to launch it over the network:
|
||||
|
||||
```bash
|
||||
@@ -442,41 +251,7 @@ You can then put epsilon.3dsx on a SD card to run it from the HBC or use 3dslink
|
||||
|
||||
</details>
|
||||
|
||||
<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>
|
||||
<br>
|
||||
|
||||
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.
|
||||
@@ -484,33 +259,30 @@ Don't forget to put your pseudo instead of `{your pseudo, max 15 char}`. If you
|
||||
|
||||
<br>
|
||||
|
||||
If you need help, you can join our Discord server here : <https://discord.gg/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>
|
||||
|
||||
---
|
||||
|
||||
## Useful links
|
||||
|
||||
- [Upsilon external (to install additional apps and wallpapers)](https://upsilonnumworks.github.io/Upsilon-External/)
|
||||
- [Ulab documentation](https://micropython-ulab.readthedocs.io/en/latest/)
|
||||
* [Upsilon external (to install additional apps and wallpapers)](https://lauryy06.github.io/Upsilon-External/)
|
||||
* [Ulab documentation](https://micropython-ulab.readthedocs.io/en/latest/)
|
||||
|
||||
## Contributing
|
||||
|
||||
To contribute, please refer to [Omega's Wiki](https://github.com/Omega-Numworks/Omega/wiki/Contributing), the same rules apply here.
|
||||
|
||||
|
||||
## Related repositories
|
||||
|
||||
Here are the main links toward Omega's different websites and repositories, that have been used for the creation of Upsilon.
|
||||
|
||||
- [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes)
|
||||
- [Omega Website](https://github.com/Omega-Numworks/Omega-Website)
|
||||
- [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN)
|
||||
- [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic)
|
||||
- [Omega Design](https://github.com/Omega-Numworks/Omega-Design)
|
||||
- [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot)
|
||||
- [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template)
|
||||
- [External Apps](https://github.com/Omega-Numworks/External-Apps)
|
||||
* [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes)
|
||||
* [Omega Website](https://github.com/Omega-Numworks/Omega-Website)
|
||||
* [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN)
|
||||
* [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic)
|
||||
* [Omega Design](https://github.com/Omega-Numworks/Omega-Design)
|
||||
* [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot)
|
||||
* [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template)
|
||||
* [External Apps](https://github.com/Omega-Numworks/External-Apps)
|
||||
|
||||
## About Epsilon
|
||||
|
||||
@@ -524,9 +296,8 @@ 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.
|
||||
Nintendo and Nintendo 3DS are registered trademarks of Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, USA.
|
||||
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 SAS and Nintendo of America Inc 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).
|
||||
- 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).
|
||||
* 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).
|
||||
* Upsilon is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
|
||||
@@ -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)))
|
||||
|
||||
ifeq ($(miss_modules), 1)
|
||||
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 "\nSome submodules apps seem to be missing. To download them, assumming you git clone'd the repo, do\n")
|
||||
PLS_IGNORE := $(shell >&2 printf " git submodule init\n")
|
||||
PLS_IGNORE := $(shell >&2 printf " git submodule update\n\n")
|
||||
endif
|
||||
@@ -50,7 +50,6 @@ apps_src += $(addprefix apps/,\
|
||||
exam_mode_configuration_official.cpp:+official \
|
||||
exam_mode_configuration_non_official.cpp:-official \
|
||||
global_preferences.cpp \
|
||||
host_filemanager.cpp \
|
||||
i18n.py \
|
||||
lock_view.cpp \
|
||||
main.cpp \
|
||||
@@ -59,9 +58,7 @@ apps_src += $(addprefix apps/,\
|
||||
math_variable_box_empty_controller.cpp \
|
||||
shift_alpha_lock_view.cpp \
|
||||
suspend_timer.cpp \
|
||||
timer_manager.cpp \
|
||||
title_bar_view.cpp \
|
||||
xnt_loop.cpp \
|
||||
)
|
||||
|
||||
tests_src += $(addprefix apps/,\
|
||||
@@ -84,7 +81,7 @@ $(call object_for,apps/apps_container_storage.cpp apps/apps_container.cpp apps/m
|
||||
country_preferences = apps/country_preferences.csv
|
||||
language_preferences = apps/language_preferences.csv
|
||||
|
||||
# The header is referred to as <apps/i18n.h> so make sure it's findable this way
|
||||
# The header is refered to as <apps/i18n.h> so make sure it's findable this way
|
||||
SFLAGS += -I$(BUILD_DIR)
|
||||
|
||||
i18n_files += $(addprefix apps/language_,$(addsuffix .universal.i18n, $(EPSILON_I18N)))
|
||||
@@ -120,7 +117,6 @@ apps_tests_src = $(app_calculation_test_src) $(app_code_test_src) $(app_graph_te
|
||||
apps_tests_src += $(addprefix apps/,\
|
||||
alternate_empty_nested_menu_controller.cpp \
|
||||
global_preferences.cpp \
|
||||
dummy_timer_manager.cpp \
|
||||
)
|
||||
|
||||
ifeq ($(THEME_REPO),local)
|
||||
|
||||
@@ -37,8 +37,7 @@ AppsContainer::AppsContainer() :
|
||||
m_homeSnapshot(),
|
||||
m_onBoardingSnapshot(),
|
||||
m_hardwareTestSnapshot(),
|
||||
m_usbConnectedSnapshot(),
|
||||
m_startAppSnapshot()
|
||||
m_usbConnectedSnapshot()
|
||||
{
|
||||
m_emptyBatteryWindow.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height), false);
|
||||
// #if __EMSCRIPTEN__
|
||||
@@ -48,7 +47,7 @@ AppsContainer::AppsContainer() :
|
||||
* poincareCircuitBreaker is run. This means either whitelisting all Epsilon
|
||||
* (which makes bigger files to download and slower execution), or
|
||||
* whitelisting all the symbols (that's a big amount of symbols to find and
|
||||
* quite paint to maintain).
|
||||
* quite painy to maintain).
|
||||
* We just remove the circuit breaker for now.
|
||||
* TODO: Put the Poincare circuit breaker back on epsilon's web emulator */
|
||||
|
||||
@@ -59,11 +58,6 @@ AppsContainer::AppsContainer() :
|
||||
Poincare::Expression::SetCircuitBreaker(AppsContainer::poincareCircuitBreaker);
|
||||
// #endif
|
||||
Ion::Storage::sharedStorage()->setDelegate(this);
|
||||
|
||||
addTimer(&m_batteryTimer);
|
||||
addTimer(&m_suspendTimer);
|
||||
addTimer(&m_backlightDimmingTimer);
|
||||
addTimer(&m_clockTimer);
|
||||
}
|
||||
|
||||
bool AppsContainer::poincareCircuitBreaker() {
|
||||
@@ -152,11 +146,8 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
|
||||
* We do it before switching to USB application to redraw the battery
|
||||
* pictogram. */
|
||||
updateBatteryState();
|
||||
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||
// If we are in exam mode, we don't switch to usb connected app
|
||||
didProcessEvent = true;
|
||||
} else if (switchTo(usbConnectedAppSnapshot())) {
|
||||
Ion::USB::DFU(true);
|
||||
if (switchTo(usbConnectedAppSnapshot())) {
|
||||
Ion::USB::DFU();
|
||||
// Update LED when exiting DFU mode
|
||||
Ion::LED::updateColorWithPlugAndCharge();
|
||||
bool switched = switchTo(activeSnapshot);
|
||||
@@ -229,7 +220,6 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
|
||||
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[] = {
|
||||
Ion::Events::ShiftSeven, Ion::Events::ShiftEight, Ion::Events::ShiftNine,
|
||||
Ion::Events::ShiftFour, Ion::Events::ShiftFive, Ion::Events::ShiftSix,
|
||||
@@ -241,33 +231,27 @@ bool AppsContainer::processEvent(Ion::Events::Event event) {
|
||||
// Warning: if the window is dirtied, you need to call window()->redraw()
|
||||
if (event == Ion::Events::USBPlug) {
|
||||
if (Ion::USB::isPlugged()) {
|
||||
// If the exam mode is enabled, we ask to disable it, else, we enable USB
|
||||
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||
displayExamModePopUp(GlobalPreferences::ExamMode::Off);
|
||||
window()->redraw();
|
||||
} else {
|
||||
Ion::USB::enable();
|
||||
}
|
||||
// Update brightness when USB is plugged
|
||||
Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel());
|
||||
} else {
|
||||
// If the USB isn't plugged in USBPlug event, we disable USB
|
||||
Ion::USB::disable();
|
||||
}
|
||||
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) {
|
||||
switchTo(appSnapshotAtIndex(0));
|
||||
return true;
|
||||
}
|
||||
// If shift + Home are pressed, we switch to the first app.
|
||||
if (event == Ion::Events::ShiftHome) {
|
||||
switchTo(appSnapshotAtIndex(1));
|
||||
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++) {
|
||||
if (event == switch_events[i]) {
|
||||
m_window.redraw(true);
|
||||
@@ -276,44 +260,19 @@ 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) {
|
||||
suspend(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) {
|
||||
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
|
||||
int NumberOfStepsPerShortcut = GlobalPreferences::sharedGlobalPreferences()->brightnessShortcut();
|
||||
int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsPerShortcut*delta : -delta*NumberOfStepsPerShortcut;
|
||||
int direction = (event == Ion::Events::BrightnessPlus) ? Ion::Backlight::NumberOfStepsPerShortcut*delta : -delta*Ion::Backlight::NumberOfStepsPerShortcut;
|
||||
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
|
||||
}
|
||||
// Else, the event was not processed.
|
||||
return false;
|
||||
}
|
||||
|
||||
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()) {
|
||||
resetShiftAlphaStatus();
|
||||
}
|
||||
@@ -350,13 +309,7 @@ void AppsContainer::run() {
|
||||
/* Normal execution. The exception checkpoint must be created before
|
||||
* switching to the first app, because the first app might create nodes on
|
||||
* the pool. */
|
||||
bool switched;
|
||||
if (m_startAppSnapshot != nullptr) {
|
||||
switched = switchTo(m_startAppSnapshot);
|
||||
} else {
|
||||
switched = switchTo(initialAppSnapshot());
|
||||
}
|
||||
|
||||
bool switched = switchTo(initialAppSnapshot());
|
||||
assert(switched);
|
||||
(void) switched; // Silence compilation warning about unused variable.
|
||||
} else {
|
||||
@@ -366,7 +319,7 @@ void AppsContainer::run() {
|
||||
* destroyed from the pool. To avoid using them before packing the app
|
||||
* (in App::willBecomeInactive for instance), we tidy them early on. */
|
||||
s_activeApp->snapshot()->tidy();
|
||||
/* When an app encountered an exception due to a full pool, the next time
|
||||
/* When an app encoutered an exception due to a full pool, the next time
|
||||
* the user enters the app, the same exception could happen again which
|
||||
* 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
|
||||
@@ -400,8 +353,6 @@ bool AppsContainer::updateBatteryState() {
|
||||
}
|
||||
|
||||
void AppsContainer::refreshPreferences() {
|
||||
m_suspendTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds()*1000/Timer::TickDuration);
|
||||
m_backlightDimmingTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration);
|
||||
m_window.refreshPreferences();
|
||||
}
|
||||
|
||||
@@ -495,6 +446,15 @@ Window * AppsContainer::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() {
|
||||
Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
|
||||
updateAlphaLock();
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "shared/global_context.h"
|
||||
#include "clock_timer.h"
|
||||
#include "on_boarding/prompt_controller.h"
|
||||
#include "xnt_loop.h"
|
||||
|
||||
#include <ion/events.h>
|
||||
|
||||
@@ -29,7 +28,6 @@ public:
|
||||
static bool poincareCircuitBreaker();
|
||||
virtual int numberOfApps() = 0;
|
||||
virtual App::Snapshot * appSnapshotAtIndex(int index) = 0;
|
||||
virtual int appIndexFromSnapshot(App::Snapshot * snapshot) = 0;
|
||||
App::Snapshot * initialAppSnapshot();
|
||||
App::Snapshot * hardwareTestAppSnapshot();
|
||||
App::Snapshot * onBoardingAppSnapshot();
|
||||
@@ -49,8 +47,6 @@ public:
|
||||
void displayExamModePopUp(GlobalPreferences::ExamMode mode);
|
||||
void shutdownDueToLowBattery();
|
||||
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();
|
||||
void redrawWindow(bool force = false);
|
||||
void activateExamMode(GlobalPreferences::ExamMode examMode);
|
||||
@@ -59,13 +55,12 @@ public:
|
||||
// Ion::StorageDelegate
|
||||
void storageDidChangeForRecord(const Ion::Storage::Record record) override;
|
||||
void storageIsFull() override;
|
||||
#ifdef EPSILON_GETOPT
|
||||
void setStartApp(App::Snapshot * snapshot) { m_startAppSnapshot = snapshot; }
|
||||
#endif
|
||||
protected:
|
||||
Home::App::Snapshot * homeAppSnapshot() { return &m_homeSnapshot; }
|
||||
private:
|
||||
Window * window() override;
|
||||
int numberOfContainerTimers() override;
|
||||
Timer * containerTimerAtIndex(int i) override;
|
||||
bool processEvent(Ion::Events::Event event);
|
||||
void resetShiftAlphaStatus();
|
||||
bool updateAlphaLock();
|
||||
@@ -74,8 +69,6 @@ private:
|
||||
static KDColor k_promptFGColors[];
|
||||
static KDColor k_promptBGColors[];
|
||||
static int k_promptNumberOfMessages;
|
||||
int m_currentAppIndex; // Home isn't included after the second app switching
|
||||
int m_lastAppIndex;
|
||||
AppsWindow m_window;
|
||||
EmptyBatteryWindow m_emptyBatteryWindow;
|
||||
Shared::GlobalContext m_globalContext;
|
||||
@@ -91,10 +84,6 @@ private:
|
||||
OnBoarding::App::Snapshot m_onBoardingSnapshot;
|
||||
HardwareTest::App::Snapshot m_hardwareTestSnapshot;
|
||||
USB::App::Snapshot m_usbConnectedSnapshot;
|
||||
XNTLoop m_XNTLoop;
|
||||
#ifdef EPSILON_GETOPT
|
||||
App::Snapshot * m_startAppSnapshot;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,25 +34,5 @@ App::Snapshot * AppsContainerStorage::appSnapshotAtIndex(int index) {
|
||||
};
|
||||
assert(sizeof(snapshots)/sizeof(snapshots[0]) == 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];
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ public:
|
||||
AppsContainerStorage();
|
||||
int numberOfApps() override;
|
||||
App::Snapshot * appSnapshotAtIndex(int index) override;
|
||||
int appIndexFromSnapshot(App::Snapshot * snapshot) override;
|
||||
void * currentAppBuffer() override { return &m_apps; };
|
||||
private:
|
||||
union Apps {
|
||||
|
||||
Submodule apps/atomic updated: 5f7063d447...69f7a06ba5
@@ -1,26 +1,11 @@
|
||||
#include "backlight_dimming_timer.h"
|
||||
#include "global_preferences.h"
|
||||
#include <ion/backlight.h>
|
||||
#include <ion/events.h>
|
||||
#include <apps/apps_container.h>
|
||||
|
||||
BacklightDimmingTimer::BacklightDimmingTimer() :
|
||||
Timer(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration)
|
||||
Timer(k_idleBeforeDimmingDuration/Timer::TickDuration)
|
||||
{
|
||||
}
|
||||
|
||||
bool BacklightDimmingTimer::fire(){
|
||||
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;
|
||||
}
|
||||
bool BacklightDimmingTimer::fire() {
|
||||
Ion::Backlight::setBrightness(k_dimBacklightBrightness);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ class BacklightDimmingTimer : public Timer {
|
||||
public:
|
||||
BacklightDimmingTimer();
|
||||
private:
|
||||
constexpr static int k_idleBeforeDimmingDuration = 30*1000; // In miliseconds
|
||||
constexpr static int k_dimBacklightBrightness = 0;
|
||||
bool fire() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -60,36 +60,32 @@ void BatteryView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
*'content' depends on the charge */
|
||||
|
||||
// Draw the left part
|
||||
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);
|
||||
ctx->fillRect(KDRect(0, 0, k_elementWidth, k_batteryHeight), Palette::Battery);
|
||||
|
||||
// Draw the middle part
|
||||
constexpr KDCoordinate batteryInsideX = k_elementWidth+k_separatorThickness;
|
||||
constexpr KDCoordinate batteryInsideWidth = k_batteryWidth-3*k_elementWidth-2*k_separatorThickness;
|
||||
if (m_isCharging) {
|
||||
// Charging: Yellow background with flash
|
||||
ctx->fillRect(KDRect(batteryInsideX, 2, batteryInsideWidth, k_batteryHeight-4), Palette::BatteryInCharge);
|
||||
ctx->fillRect(KDRect(batteryInsideX, 0, batteryInsideWidth, k_batteryHeight), Palette::BatteryInCharge);
|
||||
KDRect frame((k_batteryWidth-k_flashWidth)/2, 0, k_flashWidth, k_flashHeight);
|
||||
KDColor flashWorkingBuffer[BatteryView::k_flashHeight*BatteryView::k_flashWidth];
|
||||
ctx->blendRectWithMask(frame, Palette::Battery, (const uint8_t *)flashMask, flashWorkingBuffer);
|
||||
} else if (m_chargeState == Ion::Battery::Charge::LOW) {
|
||||
assert(!m_isPlugged);
|
||||
// Low: Quite empty battery
|
||||
ctx->fillRect(KDRect(batteryInsideX, 2, 2*k_elementWidth, k_batteryHeight-4), Palette::BatteryLow);
|
||||
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));
|
||||
ctx->fillRect(KDRect(batteryInsideX, 0, 2*k_elementWidth, k_batteryHeight), Palette::BatteryLow);
|
||||
ctx->fillRect(KDRect(3*k_elementWidth+k_separatorThickness, 0, k_batteryWidth-5*k_elementWidth-2*k_separatorThickness, k_batteryHeight), KDColor::blend(Palette::Toolbar, Palette::Battery, 128));
|
||||
} else if (m_chargeState == Ion::Battery::Charge::SOMEWHERE_INBETWEEN) {
|
||||
assert(!m_isPlugged);
|
||||
// Middle: Half full battery
|
||||
constexpr KDCoordinate middleChargeWidth = batteryInsideWidth/2;
|
||||
ctx->fillRect(KDRect(batteryInsideX, 2, middleChargeWidth, k_batteryHeight-4), Palette::Battery);
|
||||
ctx->fillRect(KDRect(batteryInsideX+middleChargeWidth, 2, middleChargeWidth+1, k_batteryHeight-4), KDColor::blend(Palette::Toolbar, Palette::Battery, 128));
|
||||
ctx->fillRect(KDRect(batteryInsideX, 0, middleChargeWidth, k_batteryHeight), Palette::Battery);
|
||||
ctx->fillRect(KDRect(batteryInsideX+middleChargeWidth, 0, middleChargeWidth, k_batteryHeight), KDColor::blend(Palette::Toolbar, Palette::Battery, 128));
|
||||
} else {
|
||||
assert(m_chargeState == Ion::Battery::Charge::FULL);
|
||||
// Full but not plugged: Full battery
|
||||
ctx->fillRect(KDRect(batteryInsideX, 2, batteryInsideWidth, k_batteryHeight-4), Palette::Battery);
|
||||
ctx->fillRect(KDRect(batteryInsideX, 0, batteryInsideWidth, k_batteryHeight), Palette::Battery);
|
||||
if (m_isPlugged) {
|
||||
// Plugged and full: Full battery with tick
|
||||
KDRect frame((k_batteryWidth-k_tickWidth)/2, (k_batteryHeight-k_tickHeight)/2, k_tickWidth, k_tickHeight);
|
||||
@@ -99,7 +95,7 @@ void BatteryView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}
|
||||
|
||||
// Draw the right part
|
||||
ctx->fillRect(KDRect(k_batteryWidth-2*k_elementWidth, 1, k_elementWidth, k_batteryHeight-2), Palette::Battery);
|
||||
ctx->fillRect(KDRect(k_batteryWidth-2*k_elementWidth, 0, k_elementWidth, k_batteryHeight), Palette::Battery);
|
||||
ctx->fillRect(KDRect(k_batteryWidth-k_elementWidth, (k_batteryHeight-k_capHeight)/2, k_elementWidth, k_capHeight), Palette::Battery);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ public:
|
||||
constexpr static int k_tickHeight = 6;
|
||||
constexpr static int k_tickWidth = 8;
|
||||
private:
|
||||
constexpr static KDCoordinate k_batteryHeight = 9;
|
||||
constexpr static KDCoordinate k_batteryWidth = 16;
|
||||
constexpr static KDCoordinate k_batteryHeight = 8;
|
||||
constexpr static KDCoordinate k_batteryWidth = 15;
|
||||
constexpr static KDCoordinate k_elementWidth = 1;
|
||||
constexpr static KDCoordinate k_capHeight = 3;
|
||||
constexpr static KDCoordinate k_capHeight = 4;
|
||||
constexpr static KDCoordinate k_separatorThickness = Metric::CellSeparatorThickness;
|
||||
Ion::Battery::Charge m_chargeState;
|
||||
bool m_isCharging;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "integer_list_controller.h"
|
||||
#include <poincare/based_integer.h>
|
||||
#include <poincare/opposite.h>
|
||||
#include <poincare/integer.h>
|
||||
#include <poincare/logarithm.h>
|
||||
#include <poincare/empty_layout.h>
|
||||
#include <poincare/factor.h>
|
||||
#include "../app.h"
|
||||
@@ -28,30 +26,10 @@ Integer::Base baseAtIndex(int index) {
|
||||
void IntegerListController::setExpression(Poincare::Expression e) {
|
||||
ExpressionsListController::setExpression(e);
|
||||
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 || (m_expression.type() == ExpressionNode::Type::Opposite && m_expression.childAtIndex(0).type() == ExpressionNode::Type::BasedInteger));
|
||||
assert(!m_expression.isUninitialized());
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
assert(!m_expression.isUninitialized() && 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));
|
||||
}
|
||||
// Computing factorExpression
|
||||
Expression factor = Factor::Builder(m_expression.clone());
|
||||
|
||||
@@ -20,20 +20,20 @@ using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
|
||||
void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
ExpressionsListController::setExpression(e);
|
||||
assert(!m_expression.isUninitialized());
|
||||
|
||||
Expression polynomialCoefficients[Expression::k_maxNumberOfPolynomialCoefficients];
|
||||
|
||||
|
||||
Context * context = App::app()->localContext();
|
||||
Preferences * preferences = Preferences::sharedPreferences();
|
||||
Poincare::ExpressionNode::ReductionContext reductionContext = Poincare::ExpressionNode::ReductionContext(context,
|
||||
preferences->complexFormat(), preferences->angleUnit(),
|
||||
GlobalPreferences::sharedGlobalPreferences()->unitFormat(),
|
||||
ExpressionNode::ReductionTarget::SystemForApproximation,
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition,
|
||||
Poincare::ExpressionNode::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);
|
||||
@@ -52,7 +52,7 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
Expression a = polynomialCoefficients[2];
|
||||
Expression b = polynomialCoefficients[1];
|
||||
Expression c = polynomialCoefficients[0];
|
||||
|
||||
|
||||
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);
|
||||
|
||||
@@ -72,22 +72,25 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
};
|
||||
|
||||
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()){
|
||||
}
|
||||
else if(a.type() == ExpressionNode::Type::Rational && static_cast<const Rational &>(a).isMinusOne()){
|
||||
multiplicationTypeForA = MultiplicationTypeForA::Minus;
|
||||
} else if (a.type() == ExpressionNode::Type::Addition) {
|
||||
}
|
||||
else if (a.type() == ExpressionNode::Type::Addition) {
|
||||
multiplicationTypeForA = MultiplicationTypeForA::Parenthesis;
|
||||
} else {
|
||||
}
|
||||
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
|
||||
/*
|
||||
* Because when can't apply reduce or simplify to keep the
|
||||
* canonized form we must beautify the expression manually
|
||||
*/
|
||||
|
||||
Expression xMinusAlphaPowerTwo;
|
||||
@@ -96,11 +99,12 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
if (alpha.isUninitialized()) {
|
||||
PoincareHelpers::Simplify(&minusAlpha, context, ExpressionNode::ReductionTarget::User);
|
||||
xMinusAlphaPowerTwo = Power::Builder(Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), minusAlpha)), Rational::Builder(2));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
PoincareHelpers::Simplify(&alpha, context, ExpressionNode::ReductionTarget::User);
|
||||
xMinusAlphaPowerTwo = Power::Builder(Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), alpha)), Rational::Builder(2));
|
||||
}
|
||||
|
||||
|
||||
Expression xMinusAlphaPowerTwoWithFactor;
|
||||
|
||||
switch (multiplicationTypeForA)
|
||||
@@ -109,7 +113,7 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
xMinusAlphaPowerTwoWithFactor = xMinusAlphaPowerTwo;
|
||||
break;
|
||||
case MultiplicationTypeForA::Minus:
|
||||
xMinusAlphaPowerTwoWithFactor = Opposite::Builder(xMinusAlphaPowerTwo);
|
||||
xMinusAlphaPowerTwoWithFactor = Multiplication::Builder(a.clone(), xMinusAlphaPowerTwo);
|
||||
break;
|
||||
case MultiplicationTypeForA::Parenthesis:
|
||||
xMinusAlphaPowerTwoWithFactor = Multiplication::Builder(Parenthesis::Builder(a.clone()), xMinusAlphaPowerTwo);
|
||||
@@ -121,21 +125,18 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
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(&minusBeta, context, ExpressionNode::ReductionTarget::User);
|
||||
canonized = Subtraction::Builder(xMinusAlphaPowerTwoWithFactor, minusBeta);
|
||||
}
|
||||
else {
|
||||
PoincareHelpers::Simplify(&beta, context, ExpressionNode::ReductionTarget::User);
|
||||
canonized = Addition::Builder(xMinusAlphaPowerTwoWithFactor, beta);
|
||||
}
|
||||
|
||||
|
||||
Expression x0;
|
||||
Expression x1;
|
||||
|
||||
@@ -144,7 +145,8 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
x0 = Division::Builder(Opposite::Builder(b.clone()), Multiplication::Builder(Rational::Builder(2), a.clone()));
|
||||
m_numberOfSolutions = 1;
|
||||
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::SystemForApproximation);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// x0 = (-b-sqrt(delta))/(2a)
|
||||
x0 = Division::Builder(Subtraction::Builder(Opposite::Builder(b.clone()), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational::Builder(2), a.clone()));
|
||||
// x1 = (-b+sqrt(delta))/(2a)
|
||||
@@ -167,32 +169,24 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
Expression x0Opposite = getOppositeIfExists(x0, &reductionContext);
|
||||
if (x0Opposite.isUninitialized()) {
|
||||
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
|
||||
if (x0.type() == ExpressionNode::Type::Addition || x0.type() == ExpressionNode::Type::Subtraction) {
|
||||
firstFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), Parenthesis::Builder(x0.clone()));
|
||||
} else {
|
||||
firstFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0.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());
|
||||
firstFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0);
|
||||
}
|
||||
else {
|
||||
PoincareHelpers::Simplify(&x0Opposite, context, ExpressionNode::ReductionTarget::User);
|
||||
firstFactor = Addition::Builder(Symbol::Builder("x", strlen("x")), x0Opposite);
|
||||
}
|
||||
if (x0.type() == ExpressionNode::Type::Opposite) {
|
||||
factorized = Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), x0.childAtIndex(0).clone()));
|
||||
}
|
||||
|
||||
Expression x1Opposite = getOppositeIfExists(x1, &reductionContext);
|
||||
if (x1Opposite.isUninitialized()) {
|
||||
PoincareHelpers::Simplify(&x1, context, ExpressionNode::ReductionTarget::User);
|
||||
if (x1.type() == ExpressionNode::Type::Addition || x1.type() == ExpressionNode::Type::Subtraction) {
|
||||
secondFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), Parenthesis::Builder(x1.clone()));
|
||||
} else {
|
||||
secondFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x1.clone());
|
||||
}
|
||||
} else {
|
||||
secondFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x1);
|
||||
}
|
||||
else {
|
||||
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());
|
||||
secondFactor = Addition::Builder(Symbol::Builder("x", strlen("x")), x1Opposite);
|
||||
}
|
||||
|
||||
Expression solutionProduct = Multiplication::Builder(Parenthesis::Builder(firstFactor), Parenthesis::Builder(secondFactor));
|
||||
@@ -202,43 +196,8 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
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;
|
||||
@@ -250,7 +209,38 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if (m_numberOfSolutions == 1) {
|
||||
Expression x0Opposite = getOppositeIfExists(x0, &reductionContext);
|
||||
Expression factor;
|
||||
if (x0Opposite.isUninitialized()) {
|
||||
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
|
||||
factor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0);
|
||||
}
|
||||
else {
|
||||
PoincareHelpers::Simplify(&x0Opposite, context, ExpressionNode::ReductionTarget::User);
|
||||
factor = Addition::Builder(Symbol::Builder("x", strlen("x")), x0Opposite);
|
||||
}
|
||||
Expression solutionProduct = Power::Builder(Parenthesis::Builder(factor), Rational::Builder(2));
|
||||
switch (multiplicationTypeForA)
|
||||
{
|
||||
case MultiplicationTypeForA::Nothing:
|
||||
factorized = solutionProduct;
|
||||
break;
|
||||
case MultiplicationTypeForA::Minus:
|
||||
factorized = Multiplication::Builder(a.clone(), solutionProduct);
|
||||
break;
|
||||
case MultiplicationTypeForA::Parenthesis:
|
||||
factorized = Multiplication::Builder(Parenthesis::Builder(a.clone()), solutionProduct);
|
||||
break;
|
||||
case MultiplicationTypeForA::Normal:
|
||||
factorized = Multiplication::Builder(a.clone(), solutionProduct);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PoincareHelpers::Simplify(&delta, context, ExpressionNode::ReductionTarget::User);
|
||||
|
||||
m_layouts[0] = PoincareHelpers::CreateLayout(canonized);
|
||||
@@ -261,7 +251,8 @@ void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
if (m_numberOfSolutions > 1) {
|
||||
m_layouts[4] = PoincareHelpers::CreateLayout(x1);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_layouts[1] = PoincareHelpers::CreateLayout(delta);
|
||||
}
|
||||
}
|
||||
@@ -270,9 +261,8 @@ Expression SecondDegreeListController::getOppositeIfExists(Expression e, Poincar
|
||||
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) {
|
||||
}
|
||||
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
|
||||
@@ -292,7 +282,7 @@ I18n::Message SecondDegreeListController::messageAtIndex(int index) {
|
||||
if (m_numberOfSolutions > 0) {
|
||||
if (index == 0) {
|
||||
return I18n::Message::CanonicalForm;
|
||||
}
|
||||
}
|
||||
if (index == 1) {
|
||||
return I18n::Message::FactorizedForm;
|
||||
}
|
||||
@@ -302,12 +292,14 @@ I18n::Message SecondDegreeListController::messageAtIndex(int index) {
|
||||
if (index == 3) {
|
||||
if (m_numberOfSolutions == 1) {
|
||||
return I18n::Message::OnlyRoot;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return I18n::Message::FirstRoot;
|
||||
}
|
||||
}
|
||||
return I18n::Message::SecondRoot;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return I18n::Message::CanonicalForm;
|
||||
|
||||
@@ -8,8 +8,7 @@ namespace Calculation {
|
||||
|
||||
TrigonometryGraphView::TrigonometryGraphView(TrigonometryModel * model) :
|
||||
CurveView(model),
|
||||
m_model(model),
|
||||
m_shouldDisplayTan(false)
|
||||
m_model(model)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -23,33 +22,17 @@ 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) {
|
||||
return Poincare::Coordinate2D<float>(std::cos(t), std::sin(t));
|
||||
}, nullptr, nullptr, true, Palette::SecondaryText, false);
|
||||
|
||||
if (!m_shouldDisplayTan) {
|
||||
// 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 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);
|
||||
// Draw angle position on the circle
|
||||
drawDot(ctx, rect, c, s, m_shouldDisplayTan ? Palette::SecondaryText : Palette::CalculationTrigoAndComplexForeground, m_shouldDisplayTan ? Size::Tiny : Size::Large);
|
||||
drawDot(ctx, rect, c, s, Palette::CalculationTrigoAndComplexForeground, Size::Large);
|
||||
// Draw graduations
|
||||
drawLabelsAndGraduations(ctx, rect, Axis::Vertical, false, true);
|
||||
drawLabelsAndGraduations(ctx, rect, Axis::Horizontal, false, true);
|
||||
|
||||
if (!m_shouldDisplayTan) {
|
||||
// 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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,16 +11,13 @@ class TrigonometryGraphView : public Shared::CurveView {
|
||||
public:
|
||||
TrigonometryGraphView(TrigonometryModel * model);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setShouldDisplayTan(bool shouldDisplayTan) { m_shouldDisplayTan = shouldDisplayTan; };
|
||||
private:
|
||||
TrigonometryModel * m_model;
|
||||
bool m_shouldDisplayTan;
|
||||
};
|
||||
|
||||
class TrigonometryGraphCell : public IllustrationCell {
|
||||
public:
|
||||
TrigonometryGraphCell(TrigonometryModel * model) : m_view(model) {}
|
||||
void setShouldDisplayTan(bool shouldDisplayTan) { m_view.setShouldDisplayTan(shouldDisplayTan); };
|
||||
private:
|
||||
View * view() override { return &m_view; }
|
||||
TrigonometryGraphView m_view;
|
||||
|
||||
@@ -1,67 +1,16 @@
|
||||
#include "trigonometry_list_controller.h"
|
||||
#include "../app.h"
|
||||
#include <poincare_nodes.h>
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
|
||||
using namespace Poincare;
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
static constexpr int s_fullCircle[] = {
|
||||
360,
|
||||
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);
|
||||
void TrigonometryListController::setExpression(Poincare::Expression e) {
|
||||
assert(e.type() == ExpressionNode::Type::Cosine || e.type() == ExpressionNode::Type::Sine);
|
||||
IllustratedListController::setExpression(e.childAtIndex(0));
|
||||
|
||||
// Fill calculation store
|
||||
m_calculationStore.push("tan(θ)", context, CalculationHeight);
|
||||
Poincare::Context * context = App::app()->localContext();
|
||||
m_calculationStore.push("sin(θ)", context, CalculationHeight);
|
||||
m_calculationStore.push("cos(θ)", context, CalculationHeight);
|
||||
m_calculationStore.push("θ", context, CalculationHeight);
|
||||
|
||||
@@ -8,22 +8,4 @@ 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,12 +14,11 @@ public:
|
||||
// CurveViewRange
|
||||
float xMin() const override { return -k_xHalfRange; }
|
||||
float xMax() const override { return k_xHalfRange; }
|
||||
float yMin() const override;
|
||||
float yMax() const override;
|
||||
float yMin() const override { return yCenter() - yHalfRange(); }
|
||||
float yMax() const override { return yCenter() + yHalfRange(); }
|
||||
|
||||
void setAngle(float f) { m_angle = f; }
|
||||
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:
|
||||
constexpr static float k_xHalfRange = 2.1f;
|
||||
// We center the yRange around the semi-circle where the angle is
|
||||
@@ -34,7 +33,6 @@ private:
|
||||
float yHalfRange() const { return IllustratedListController::k_illustrationHeight*k_xHalfRange/(Ion::Display::Width - Metric::PopUpRightMargin - Metric::PopUpLeftMargin); }
|
||||
|
||||
float m_angle;
|
||||
bool m_shouldDisplayTan;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,26 +12,6 @@ using namespace Shared;
|
||||
|
||||
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) {
|
||||
ExpressionsListController::setExpression(e);
|
||||
assert(!m_expression.isUninitialized());
|
||||
@@ -42,7 +22,6 @@ void UnitListController::setExpression(Poincare::Expression e) {
|
||||
for (size_t i = 0; i < k_maxNumberOfRows; i++) {
|
||||
expressions[i] = Expression();
|
||||
}
|
||||
m_dimensionMessage = I18n::Message::Default;
|
||||
|
||||
/* 1. First rows: miscellaneous classic units for some dimensions, in both
|
||||
* metric and imperial units. */
|
||||
@@ -58,7 +37,7 @@ void UnitListController::setExpression(Poincare::Expression e) {
|
||||
GlobalPreferences::sharedGlobalPreferences()->unitFormat(),
|
||||
ExpressionNode::ReductionTarget::User,
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined);
|
||||
int numberOfExpressions = Unit::SetAdditionalExpressionsAndMessage(units, value, expressions, k_maxNumberOfRows, reductionContext, &m_dimensionMessage);
|
||||
int numberOfExpressions = Unit::SetAdditionalExpressions(units, value, expressions, k_maxNumberOfRows, reductionContext);
|
||||
|
||||
// 2. SI units only
|
||||
assert(numberOfExpressions < k_maxNumberOfRows - 1);
|
||||
@@ -110,44 +89,6 @@ 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) {
|
||||
return (I18n::Message)0;
|
||||
}
|
||||
|
||||
@@ -7,23 +7,13 @@ namespace Calculation {
|
||||
|
||||
class UnitListController : public ExpressionsListController {
|
||||
public:
|
||||
UnitListController(EditExpressionController * editExpressionController);
|
||||
|
||||
/* Responder */
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
UnitListController(EditExpressionController * editExpressionController) :
|
||||
ExpressionsListController(editExpressionController) {}
|
||||
|
||||
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:
|
||||
I18n::Message messageAtIndex(int index) override;
|
||||
I18n::Message m_dimensionMessage;
|
||||
MessageTableCell<> m_dimensionCell;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ FactorizedForm = "Factorisierte Form"
|
||||
Discriminant = "Diskriminante"
|
||||
OnlyRoot = "Wurzel"
|
||||
FirstRoot = "Erste Wurzel"
|
||||
SecondRoot = "Zweite Wurzel"
|
||||
SecondRoot = "Zweite Wurzel"
|
||||
@@ -17,4 +17,4 @@ FactorizedForm = "Factorized form"
|
||||
Discriminant = "Discriminant"
|
||||
OnlyRoot = "Root"
|
||||
FirstRoot = "First root"
|
||||
SecondRoot = "Second root"
|
||||
SecondRoot = "Second root"
|
||||
@@ -17,4 +17,4 @@ FactorizedForm = "Forma factorizada"
|
||||
Discriminant = "Discriminante"
|
||||
OnlyRoot = "Raíz"
|
||||
FirstRoot = "Primera raíz"
|
||||
SecondRoot = "Segunda raíz"
|
||||
SecondRoot = "Segunda raíz"
|
||||
@@ -17,4 +17,4 @@ FactorizedForm = "Forme factorisée"
|
||||
Discriminant = "Discriminant"
|
||||
OnlyRoot = "Racine"
|
||||
FirstRoot = "Première racine"
|
||||
SecondRoot = "Seconde racine"
|
||||
SecondRoot = "Seconde racine"
|
||||
@@ -1,20 +1,20 @@
|
||||
CalculApp = "Számolás"
|
||||
CalculAppCapital = "SZÁMOLÁS"
|
||||
AdditionalResults = "További eredmények"
|
||||
DecimalBase = "Decimális"
|
||||
HexadecimalBase = "Hexadecimális"
|
||||
BinaryBase = "Bináris"
|
||||
PrimeFactors = "Alapvetö tényezök"
|
||||
MixedFraction = "Vegyes frakció"
|
||||
EuclideanDivision = "Euklideszi osztás"
|
||||
AdditionalDeterminant = "Meghatározó"
|
||||
AdditionalInverse = "inverz"
|
||||
AdditionalRowEchelonForm = "Sor echelon forma"
|
||||
AdditionalReducedRowEchelonForm = "Csökkentett sorú Echelon forma"
|
||||
AdditionalTrace = "Nyomkövetés"
|
||||
CanonicalForm = "Kanonikus forma"
|
||||
FactorizedForm = "Factorizált forma"
|
||||
Discriminant = "Discriminant"
|
||||
OnlyRoot = "Gyökér"
|
||||
FirstRoot = "Első gyökér"
|
||||
SecondRoot = "Második gyökér"
|
||||
CalculApp = "Számolás"
|
||||
CalculAppCapital = "SZÁMOLÁS"
|
||||
AdditionalResults = "További eredmények"
|
||||
DecimalBase = "Decimális"
|
||||
HexadecimalBase = "Hexadecimális"
|
||||
BinaryBase = "Bináris"
|
||||
PrimeFactors = "Alapvetö tényezök"
|
||||
MixedFraction = "Vegyes frakció"
|
||||
EuclideanDivision = "Euklideszi osztás"
|
||||
AdditionalDeterminant = "Meghatározó"
|
||||
AdditionalInverse = "inverz"
|
||||
AdditionalRowEchelonForm = "Sor echelon forma"
|
||||
AdditionalReducedRowEchelonForm = "Csökkentett sorú Echelon forma"
|
||||
AdditionalTrace = "Nyomkövetés"
|
||||
CanonicalForm = "Kanonikus forma"
|
||||
FactorizedForm = "Factorizált forma"
|
||||
Discriminant = "Discriminant"
|
||||
OnlyRoot = "Gyökér"
|
||||
FirstRoot = "Első gyökér"
|
||||
SecondRoot = "Második gyökér"
|
||||
@@ -17,4 +17,4 @@ FactorizedForm = "Forma fattorizzata"
|
||||
Discriminant = "Discriminante"
|
||||
OnlyRoot = "Radice"
|
||||
FirstRoot = "Prima radice"
|
||||
SecondRoot = "Seconda radice"
|
||||
SecondRoot = "Seconda radice"
|
||||
@@ -17,4 +17,4 @@ FactorizedForm = "Factorized vorm"
|
||||
Discriminant = "Discriminant"
|
||||
OnlyRoot = "Wortel"
|
||||
FirstRoot = "Eerste wortel"
|
||||
SecondRoot = "Tweede wortel"
|
||||
SecondRoot = "Tweede wortel"
|
||||
@@ -17,4 +17,4 @@ FactorizedForm = "Factorized form"
|
||||
Discriminant = "Discriminante"
|
||||
OnlyRoot = "Raiz"
|
||||
FirstRoot = "Primeira raiz"
|
||||
SecondRoot = "Segunda raiz"
|
||||
SecondRoot = "Segunda raiz"
|
||||
@@ -251,18 +251,14 @@ Calculation::AdditionalInformationType Calculation::additionalInformationType(Co
|
||||
* - > input: 2cos(2) - cos(2)
|
||||
* > output: cos(2)
|
||||
*/
|
||||
if (i.isDefinedCosineOrSineOrTangent(context, complexFormat, preferences->angleUnit())) {
|
||||
return AdditionalInformationType::TrigonometryInput;
|
||||
}
|
||||
if (o.isDefinedCosineOrSineOrTangent(context, complexFormat, preferences->angleUnit())) {
|
||||
return AdditionalInformationType::TrigonometryOutput;
|
||||
if (input().isDefinedCosineOrSine(context, complexFormat, preferences->angleUnit()) || o.isDefinedCosineOrSine(context, complexFormat, preferences->angleUnit())) {
|
||||
return AdditionalInformationType::Trigonometry;
|
||||
}
|
||||
if (o.hasUnit()) {
|
||||
Expression unit;
|
||||
PoincareHelpers::ReduceAndRemoveUnit(&o, App::app()->localContext(), ExpressionNode::ReductionTarget::User, &unit, ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined, ExpressionNode::UnitConversion::None);
|
||||
UnitNode::Vector<int> vector = UnitNode::Vector<int>::FromBaseUnits(unit);
|
||||
const Unit::Representative * representative = Unit::Representative::RepresentativeForDimension(vector);
|
||||
return representative != nullptr ? AdditionalInformationType::Unit : AdditionalInformationType::None;
|
||||
double value = PoincareHelpers::ApproximateToScalar<double>(o, App::app()->localContext());
|
||||
return (Unit::ShouldDisplayAdditionalOutputs(value, unit, GlobalPreferences::sharedGlobalPreferences()->unitFormat())) ? AdditionalInformationType::Unit : AdditionalInformationType::None;
|
||||
}
|
||||
if (o.isBasedIntegerCappedBy(k_maximalIntegerWithAdditionalInformation)) {
|
||||
return AdditionalInformationType::Integer;
|
||||
|
||||
@@ -40,8 +40,7 @@ public:
|
||||
Integer,
|
||||
Rational,
|
||||
SecondDegree,
|
||||
TrigonometryInput,
|
||||
TrigonometryOutput,
|
||||
Trigonometry,
|
||||
Unit,
|
||||
Matrix,
|
||||
Complex
|
||||
@@ -98,7 +97,7 @@ public:
|
||||
AdditionalInformationType additionalInformationType(Poincare::Context * context);
|
||||
private:
|
||||
static constexpr KDCoordinate k_heightComputationFailureHeight = 50;
|
||||
static constexpr const char * k_maximalIntegerWithAdditionalInformation = "18446744073709551617"; // 2^64 + 1
|
||||
static constexpr const char * k_maximalIntegerWithAdditionalInformation = "10000000000000000";
|
||||
|
||||
void setHeights(KDCoordinate height, KDCoordinate expandedHeight);
|
||||
|
||||
|
||||
@@ -7,39 +7,6 @@
|
||||
#include "../exam_mode_configuration.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 Shared;
|
||||
|
||||
@@ -49,55 +16,16 @@ CalculationStore::CalculationStore(char * buffer, int size) :
|
||||
m_buffer(buffer),
|
||||
m_bufferSize(size),
|
||||
m_calculationAreaEnd(m_buffer),
|
||||
m_numberOfCalculations(0),
|
||||
m_trashIndex(-1)
|
||||
m_numberOfCalculations(0)
|
||||
{
|
||||
assert(m_buffer != nullptr);
|
||||
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, and ignore the trash
|
||||
// Returns an expiring pointer to the calculation of index 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);
|
||||
// m_buffer is the address of the oldest calculation in calculation store
|
||||
// m_buffer is the adress of the oldest calculation in calculation store
|
||||
Calculation * c = (Calculation *) m_buffer;
|
||||
if (i != m_numberOfCalculations-1) {
|
||||
// The calculation we want is not the oldest one so we get its pointer
|
||||
@@ -108,13 +36,12 @@ ExpiringPointer<Calculation> CalculationStore::realCalculationAtIndex(int i) {
|
||||
|
||||
// Pushes an expression in the store
|
||||
ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context * context, HeightComputer heightComputer) {
|
||||
emptyTrash();
|
||||
/* Compute ans now, before the buffer is updated and before the calculation
|
||||
* might be deleted */
|
||||
Expression ans = ansExpression(context);
|
||||
|
||||
/* 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 *);
|
||||
assert(m_bufferSize > minSize);
|
||||
while (remainingBufferSize() < minSize) {
|
||||
@@ -173,9 +100,9 @@ ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context *
|
||||
numberOfSignificantDigits = Poincare::Preferences::sharedPreferences()->numberOfSignificantDigits();
|
||||
}
|
||||
if (!pushSerializeExpression(outputs[i], beginingOfFreeSpace, &endOfFreeSpace, numberOfSignificantDigits)) {
|
||||
/* If the exact/approximate output does not fit in the store (event if the
|
||||
/* If the exat/approximate output does not fit in the store (event if the
|
||||
* current calculation is the only calculation), replace the output with
|
||||
* undef if it fits, else replace the whole calculation with undef. */
|
||||
* undef if it fits, else replace the whole calcualtion with undef. */
|
||||
Expression undef = Undefined::Builder();
|
||||
if (!pushSerializeExpression(undef, beginingOfFreeSpace, &endOfFreeSpace)) {
|
||||
return emptyStoreAndPushUndef(context, heightComputer);
|
||||
@@ -205,23 +132,15 @@ ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context *
|
||||
|
||||
// Delete the calculation of index 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);
|
||||
if (i == 0) {
|
||||
ExpiringPointer<Calculation> lastCalculationPointer = realCalculationAtIndex(0);
|
||||
ExpiringPointer<Calculation> lastCalculationPointer = calculationAtIndex(0);
|
||||
m_calculationAreaEnd = (char *)(lastCalculationPointer.pointer());
|
||||
m_numberOfCalculations--;
|
||||
return;
|
||||
}
|
||||
char * calcI = (char *)realCalculationAtIndex(i).pointer();
|
||||
char * nextCalc = (char *) realCalculationAtIndex(i-1).pointer();
|
||||
char * calcI = (char *)calculationAtIndex(i).pointer();
|
||||
char * nextCalc = (char *) calculationAtIndex(i-1).pointer();
|
||||
assert(m_calculationAreaEnd >= nextCalc);
|
||||
size_t slidingSize = m_calculationAreaEnd - nextCalc;
|
||||
// Slide the i-1 most recent calculations right after the i+1'th
|
||||
@@ -235,14 +154,13 @@ void CalculationStore::realDeleteCalculationAtIndex(int i) {
|
||||
// Delete the oldest calculation in the store and returns the amount of space freed by the operation
|
||||
size_t CalculationStore::deleteOldestCalculation() {
|
||||
char * oldBufferEnd = (char *) m_calculationAreaEnd;
|
||||
realDeleteCalculationAtIndex(numberOfCalculations()-1);
|
||||
deleteCalculationAtIndex(numberOfCalculations()-1);
|
||||
char * newBufferEnd = (char *) m_calculationAreaEnd;
|
||||
return oldBufferEnd - newBufferEnd;
|
||||
}
|
||||
|
||||
// Delete all calculations
|
||||
void CalculationStore::deleteAll() {
|
||||
m_trashIndex = -1;
|
||||
m_calculationAreaEnd = m_buffer;
|
||||
m_numberOfCalculations = 0;
|
||||
}
|
||||
@@ -259,8 +177,8 @@ Expression CalculationStore::ansExpression(Context * context) {
|
||||
* parsed), ans is replaced by the approximation output when any Store or
|
||||
* Equal expression appears. */
|
||||
Expression e = mostRecentCalculation->exactOutput();
|
||||
bool exactOutputInvolvesStoreEqual = e.type() == ExpressionNode::Type::Store || e.type() == ExpressionNode::Type::Equal;
|
||||
if (mostRecentCalculation->input().recursivelyMatches(Expression::IsApproximate, context) || exactOutputInvolvesStoreEqual) {
|
||||
bool exactOuptutInvolvesStoreEqual = e.type() == ExpressionNode::Type::Store || e.type() == ExpressionNode::Type::Equal;
|
||||
if (mostRecentCalculation->input().recursivelyMatches(Expression::IsApproximate, context) || exactOuptutInvolvesStoreEqual) {
|
||||
return mostRecentCalculation->approximateOutput(context, Calculation::NumberOfSignificantDigits::Maximal);
|
||||
}
|
||||
return mostRecentCalculation->exactOutput();
|
||||
@@ -282,12 +200,6 @@ bool CalculationStore::pushSerializeExpression(Expression e, char * location, ch
|
||||
return expressionIsPushed;
|
||||
}
|
||||
|
||||
void CalculationStore::emptyTrash() {
|
||||
if (m_trashIndex != -1) {
|
||||
realDeleteCalculationAtIndex(m_trashIndex);
|
||||
m_trashIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Shared::ExpiringPointer<Calculation> CalculationStore::emptyStoreAndPushUndef(Context * context, HeightComputer heightComputer) {
|
||||
@@ -301,7 +213,7 @@ Shared::ExpiringPointer<Calculation> CalculationStore::emptyStoreAndPushUndef(Co
|
||||
void CalculationStore::recomputeMemoizedPointersAfterCalculationIndex(int index) {
|
||||
assert(index < m_numberOfCalculations);
|
||||
// Clear pointer and recompute new ones
|
||||
Calculation * c = realCalculationAtIndex(index).pointer();
|
||||
Calculation * c = calculationAtIndex(index).pointer();
|
||||
Calculation * nextCalc;
|
||||
while (index != 0) {
|
||||
nextCalc = c->next();
|
||||
|
||||
@@ -41,15 +41,11 @@ public:
|
||||
void deleteCalculationAtIndex(int i);
|
||||
void deleteAll();
|
||||
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 - (m_trashIndex != -1); }
|
||||
int numberOfCalculations() const { return m_numberOfCalculations; }
|
||||
Poincare::Expression ansExpression(Poincare::Context * context);
|
||||
int bufferSize() { return m_bufferSize; }
|
||||
void reinsertTrash() { m_trashIndex = -1; }
|
||||
|
||||
private:
|
||||
void emptyTrash();
|
||||
Shared::ExpiringPointer<Calculation> realCalculationAtIndex(int i);
|
||||
void realDeleteCalculationAtIndex(int i);
|
||||
|
||||
class CalculationIterator {
|
||||
public:
|
||||
@@ -74,7 +70,6 @@ private:
|
||||
int m_bufferSize;
|
||||
const char * m_calculationAreaEnd;
|
||||
int m_numberOfCalculations;
|
||||
int m_trashIndex;
|
||||
|
||||
size_t deleteOldestCalculation();
|
||||
char * addressOfPointerToCalculationOfIndex(int i) {return m_buffer + m_bufferSize - (m_numberOfCalculations - i)*sizeof(Calculation *);}
|
||||
|
||||
@@ -68,15 +68,6 @@ void EditExpressionController::memoizeInput() {
|
||||
*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() {
|
||||
m_historyController->viewWillAppear();
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ public:
|
||||
void insertTextBody(const char * text);
|
||||
void restoreInput();
|
||||
void memoizeInput();
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
|
||||
/* TextFieldDelegate */
|
||||
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#include "expression_field.h"
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/horizontal_layout.h>
|
||||
#include <poincare/code_point_layout.h>
|
||||
|
||||
using namespace Poincare;
|
||||
namespace Calculation {
|
||||
|
||||
bool ExpressionField::handleEvent(Ion::Events::Event event) {
|
||||
@@ -24,30 +21,7 @@ bool ExpressionField::handleEvent(Ion::Events::Event event) {
|
||||
event == Ion::Events::EE)) {
|
||||
handleEventWithText(Poincare::Symbol::k_ans);
|
||||
}
|
||||
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;
|
||||
return(::ExpressionField::handleEvent(event));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ public:
|
||||
}
|
||||
protected:
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
private:
|
||||
bool fieldHasOnlyAMinus() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -103,12 +103,12 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
|
||||
vc = &m_complexController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::SecondDegree) {
|
||||
vc = &m_secondDegreeController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::TrigonometryInput) {
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Trigonometry) {
|
||||
vc = &m_trigonometryController;
|
||||
e = calculationAtIndex(focusRow)->input();
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::TrigonometryOutput) {
|
||||
vc = &m_trigonometryController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Integer) {
|
||||
// Find which of the input or output is the cosine/sine
|
||||
ExpressionNode::Type t = e.type();
|
||||
e = t == ExpressionNode::Type::Cosine || t == ExpressionNode::Type::Sine ? e : calculationAtIndex(focusRow)->input();
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Integer) {
|
||||
vc = &m_integerController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Rational) {
|
||||
vc = &m_rationalController;
|
||||
|
||||
@@ -35,7 +35,6 @@ public:
|
||||
int typeAtLocation(int i, int j) 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 reinsertTrash() { m_calculationStore->reinsertTrash(); }
|
||||
private:
|
||||
int storeIndex(int i) { return numberOfRows() - i - 1; }
|
||||
Shared::ExpiringPointer<Calculation> calculationAtIndex(int i);
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
#include <apps/i18n.h>
|
||||
#include "helpers.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 {
|
||||
|
||||
@@ -136,16 +129,6 @@ VariableBoxController * App::variableBoxForInputEventHandler(InputEventHandler *
|
||||
}
|
||||
|
||||
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);
|
||||
if (pythonText != nullptr) {
|
||||
textInput->handleEventWithText(pythonText);
|
||||
@@ -156,17 +139,7 @@ bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::E
|
||||
|
||||
void App::initPythonWithUser(const void * pythonUser) {
|
||||
if (!m_pythonUser) {
|
||||
#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
|
||||
MicroPython::init(m_pythonHeap, m_pythonHeap + k_pythonHeapSize);
|
||||
}
|
||||
m_pythonUser = pythonUser;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
|
||||
VariableBoxController * variableBoxController() { return &m_variableBoxController; }
|
||||
|
||||
static constexpr int k_pythonHeapSize = 69500;
|
||||
static constexpr int k_pythonHeapSize = 67000;
|
||||
|
||||
private:
|
||||
/* Python delegate:
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
CodeAppCapital = "PYTHON"
|
||||
ConsolePrompt = ">>> "
|
||||
ScriptParameters = "..."
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
PythonPound = "Kommentar"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Doppelpunkt"
|
||||
PythonSemicon = "Semikolon"
|
||||
PythonExclamationMark = "Ausrufezeichen"
|
||||
PythonLessThan = "Kleiner als"
|
||||
PythonGreaterThan = "Größer als"
|
||||
PythonQuestionMark = "Fragezeichen"
|
||||
Python1J = "Imaginäres i"
|
||||
PythonLF = "Zeilenvorschub"
|
||||
PythonTab = "Tabulator"
|
||||
@@ -59,7 +53,6 @@ PythonErfc = "Komplementäre Fehlerfunktion"
|
||||
PythonEval = "Rückgabe ausgewerteter Ausdruck"
|
||||
PythonExp = "Exponentialfunktion"
|
||||
PythonExpm1 = "Berechne exp(x)-1"
|
||||
PythonFactorial = "Fakultät von x"
|
||||
PythonFabs = "Absoluter Wert"
|
||||
PythonFillRect = "Gefülltes Rechteck bei Pixel (x,y)"
|
||||
PythonFillCircle = "Füllt einen Kreis"
|
||||
@@ -109,58 +102,10 @@ PythonIsFinite = "Prüfen, ob x endlich ist"
|
||||
PythonIsInfinite = "Prüfen, ob x unendlich ist"
|
||||
PythonIsNaN = "Prüfen, ob x keine Zahl ist"
|
||||
PythonIsKeyDown = "Wahr, wenn die Taste k gedrückt ist"
|
||||
PythonBattery = "Rückgabe der Batteriespannung"
|
||||
PythonBatteryLevel = "Gibt den Batteriestand zurück"
|
||||
PythonBatteryIscharging = "Gibt zurück, ob die Batterie geladen wird"
|
||||
PythonSetBrightness = "Helligkeitsstufe festlegen"
|
||||
PythonGetBrightness = "Helligkeitsstufe abrufen"
|
||||
PythonBattery = "Return battery voltage"
|
||||
PythonBatteryLevel = "Return battery level"
|
||||
PythonBatteryIscharging = "Return if battery is charging"
|
||||
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"
|
||||
PythonLength = "Länge eines Objekts"
|
||||
PythonLgamma = "Log-Gamma-Funktion"
|
||||
@@ -238,11 +183,14 @@ PythonTurtlePosition = "Aktuelle (x,y) Position zurückgeben"
|
||||
PythonTurtleReset = "Die Zeichnung zurücksetzen"
|
||||
PythonTurtleRight = "Um ein Grad nach rechts drehen"
|
||||
PythonTurtleSetheading = "Ausrichtung auf einen Grad setzen"
|
||||
PythonTurtleSetposition = "Den Igel auf Position setzen"
|
||||
PythonTurtleShowturtle = "Den Igel anzeigen"
|
||||
PythonTurtleSpeed = "Zeichengeschwindigkeit von 0 bis 10"
|
||||
PythonTurtleWrite = "Einen Text anzeigen"
|
||||
PythonUniform = "Fließkommazahl in [a,b]"
|
||||
PythonImportTime = "Time-Modul importieren"
|
||||
PythonTimePrefix = "Zeitmodul-Funktionspräfix"
|
||||
PythonTimeSleep = "Warte für n Sekunden"
|
||||
PythonMonotonic = "Monotone Zeit zurückgeben"
|
||||
PythonFileOpen = "Öffnet eine Datei"
|
||||
PythonFileSeekable = "Kann Datei durchsucht werden?"
|
||||
@@ -260,6 +208,3 @@ PythonFileName = "Enthält den Namen der Datei"
|
||||
PythonFileMode = "Enthält den Öffnungsmodus der Datei"
|
||||
PythonFileReadable = "Kann Datei gelesen werden?"
|
||||
PythonFileWritable = "Kann Datei geschrieben werden?"
|
||||
PythonImportUtils = "Importieren von ulab.utils"
|
||||
PythonUtilsFunction = "Funktionspräfix des utils-Moduls"
|
||||
PythonTurtleBgcolor = "Ändern Sie die Hintergrundfarbe"
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
PythonPound = "Comment"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Colon"
|
||||
PythonSemicon = "Semicolon"
|
||||
PythonExclamationMark = "Exclamation mark"
|
||||
PythonLessThan = "Less than"
|
||||
PythonGreaterThan = "Greater than"
|
||||
PythonQuestionMark = "Question mark"
|
||||
Python1J = "Imaginary i"
|
||||
PythonLF = "Line feed"
|
||||
PythonTab = "Tabulation"
|
||||
@@ -59,7 +53,6 @@ PythonErfc = "Complementary error function"
|
||||
PythonEval = "Return the evaluated expression"
|
||||
PythonExp = "Exponential function"
|
||||
PythonExpm1 = "Compute exp(x)-1"
|
||||
PythonFactorial = "Factorial of x"
|
||||
PythonFabs = "Absolute value"
|
||||
PythonFillCircle = "Fill a circle"
|
||||
PythonFillPolygon = "Fill a polygon"
|
||||
@@ -97,56 +90,8 @@ PythonIsKeyDown = "Return True if the k key is down"
|
||||
PythonBattery = "Return battery voltage"
|
||||
PythonBatteryLevel = "Return battery level"
|
||||
PythonBatteryIscharging = "Return if battery is charging"
|
||||
PythonSetBrightness = "Set brightness level"
|
||||
PythonGetBrightness = "Get brightness level"
|
||||
PythonIsNaN = "Check if x is a NaN"
|
||||
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"
|
||||
PythonLength = "Length of an object"
|
||||
PythonLgamma = "Log-gamma function"
|
||||
@@ -224,6 +169,7 @@ PythonTurtlePosition = "Return the current (x,y) location"
|
||||
PythonTurtleReset = "Reset the drawing"
|
||||
PythonTurtleRight = "Turn right by a degrees"
|
||||
PythonTurtleSetheading = "Set the orientation to a degrees"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Show the turtle"
|
||||
PythonTurtleSpeed = "Drawing speed between 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
@@ -243,6 +189,8 @@ PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
@@ -260,6 +208,3 @@ PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read 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"
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
PythonPound = "Comment"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Colon"
|
||||
PythonSemicon = "Semicolon"
|
||||
PythonExclamationMark = "Exclamation mark"
|
||||
PythonLessThan = "Less than"
|
||||
PythonGreaterThan = "Greater than"
|
||||
PythonQuestionMark = "Question mark"
|
||||
Python1J = "Imaginary i"
|
||||
PythonLF = "Line feed"
|
||||
PythonTab = "Tabulation"
|
||||
@@ -59,7 +53,6 @@ PythonErfc = "Complementary error function"
|
||||
PythonEval = "Return the evaluated expression"
|
||||
PythonExp = "Exponential function"
|
||||
PythonExpm1 = "Compute exp(x)-1"
|
||||
PythonFactorial = "factorial de x"
|
||||
PythonFabs = "Absolute value"
|
||||
PythonFillCircle = "Fill a circle"
|
||||
PythonFillPolygon = "Fill a polygon"
|
||||
@@ -94,59 +87,11 @@ PythonIonFunction = "ion module function prefix"
|
||||
PythonIsFinite = "Check if x is finite"
|
||||
PythonIsInfinite = "Check if x is infinity"
|
||||
PythonIsKeyDown = "Return True if the k key is down"
|
||||
PythonBattery = "Rückgabe der Batteriespannung"
|
||||
PythonBatteryLevel = "Gibt den Batteriestand zurück"
|
||||
PythonBatteryIscharging = "Gibt zurück, ob die Batterie geladen wird"
|
||||
PythonSetBrightness = "Establecer nivel de brillo"
|
||||
PythonGetBrightness = "Obtener nivel de brillo"
|
||||
PythonBattery = "Return battery voltage"
|
||||
PythonBatteryLevel = "Return battery level"
|
||||
PythonBatteryIscharging = "Return if battery is charging"
|
||||
PythonIsNaN = "Check if x is a NaN"
|
||||
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"
|
||||
PythonLength = "Length of an object"
|
||||
PythonLgamma = "Log-gamma function"
|
||||
@@ -224,6 +169,7 @@ PythonTurtlePosition = "Return the current (x,y) location"
|
||||
PythonTurtleReset = "Reset the drawing"
|
||||
PythonTurtleRight = "Turn right by a degrees"
|
||||
PythonTurtleSetheading = "Set the orientation to a degrees"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Show the turtle"
|
||||
PythonTurtleSpeed = "Drawing speed between 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
@@ -243,6 +189,8 @@ PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Esperar n segundos"
|
||||
PythonMonotonic = "Tiempo monótono de retorno"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
@@ -260,6 +208,3 @@ PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read 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"
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
PythonPound = "Commentaire"
|
||||
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"
|
||||
PythonLF = "Saut à la ligne"
|
||||
PythonTab = "Tabulation"
|
||||
@@ -59,7 +53,6 @@ PythonErfc = "Fonction d'erreur complémentaire"
|
||||
PythonEval = "Evalue l'expression en argument "
|
||||
PythonExp = "Fonction exponentielle"
|
||||
PythonExpm1 = "Calcul de exp(x)-1"
|
||||
PythonFactorial = "Factorielle de x"
|
||||
PythonFabs = "Valeur absolue"
|
||||
PythonFillCircle = "Remplit un cercle"
|
||||
PythonFillPolygon = "Remplit un polygone"
|
||||
@@ -84,7 +77,6 @@ PythonImportMath = "Importation du module math"
|
||||
PythonImportMatplotlibPyplot = "Importation de matplotlib.pyplot"
|
||||
PythonImportNumpy = "Importation de ulab.numpy"
|
||||
PythonImportScipy = "Importation de ulab.scipy"
|
||||
PythonImportUtils = "Importation de ulab.utils"
|
||||
PythonImportTurtle = "Importation du module turtle"
|
||||
PythonImportTime = "Importation du module time"
|
||||
PythonIndex = "Indice première occurrence de x"
|
||||
@@ -98,56 +90,8 @@ PythonIsKeyDown = "Renvoie True si touche k enfoncée"
|
||||
PythonBattery = "Renvoie le voltage de la batterie"
|
||||
PythonBatteryLevel = "Renvoie le niveau de la batterie"
|
||||
PythonBatteryIscharging = "Chargement en cours"
|
||||
PythonSetBrightness = "Définir le niveau de luminosité"
|
||||
PythonGetBrightness = "Obtenir le niveau de luminosité"
|
||||
PythonIsNaN = "Teste si x est NaN"
|
||||
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)"
|
||||
PythonLength = "Longueur d'un objet"
|
||||
PythonLgamma = "Logarithme de la fonction gamma"
|
||||
@@ -168,7 +112,6 @@ PythonScipyLinalgFunction = "Préfixe fonction du module scipy.linalg"
|
||||
PythonScipyOptimizeFunction = "Préfixe fonction du module scipy.optimize"
|
||||
PythonScipySignalFunction = "Préfixe fonction du module scipy.signal"
|
||||
PythonScipySpecialFunction = "Préfixe fonction du module scipy.special"
|
||||
PythonUtilsFunction = "Préfixe fonction du module utils"
|
||||
PythonOct = "Conversion en octal"
|
||||
PythonPhase = "Argument de z"
|
||||
PythonPlot = "Trace y en fonction de x"
|
||||
@@ -184,7 +127,7 @@ PythonRandrange = "Nombre dans range(start,stop)"
|
||||
PythonRangeStartStop = "Liste de start à stop-1"
|
||||
PythonRangeStop = "Liste de 0 à stop-1"
|
||||
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"
|
||||
PythonRound = "Arrondi à n décimales"
|
||||
PythonScatter = "Nuage des points (x,y)"
|
||||
@@ -212,7 +155,6 @@ PythonTurtleBackward = "Recule de x pixels"
|
||||
PythonTurtleCircle = "Cercle de rayon r pixels"
|
||||
PythonTurtleColor = "Modifie la couleur du tracé"
|
||||
PythonTurtleColorMode = "Met le mode de couleur à 1.0 ou 255"
|
||||
PythonTurtleBgcolor = "Modifie la couleur du fond"
|
||||
PythonTurtleForward = "Avance de x pixels"
|
||||
PythonTurtleFunction = "Préfixe fonction du module turtle"
|
||||
PythonTurtleGoto = "Va au point de coordonnées (x,y)"
|
||||
@@ -227,6 +169,7 @@ PythonTurtlePosition = "Renvoie la position (x,y)"
|
||||
PythonTurtleReset = "Réinitialise le dessin"
|
||||
PythonTurtleRight = "Pivote de a degrés vers la droite"
|
||||
PythonTurtleSetheading = "Met un cap de a degrés"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Affiche la tortue"
|
||||
PythonTurtleSpeed = "Vitesse du tracé entre 0 et 10"
|
||||
PythonTurtleWrite = "Affiche un texte"
|
||||
@@ -246,6 +189,8 @@ PythonSysImplementation = "Information sur Python"
|
||||
PythonSysModules = "Dictionnaire des modules chargés"
|
||||
PythonSysVersion = "Version du langage Python (string)"
|
||||
PythonSysVersioninfo = "Version du langage Python (tuple)"
|
||||
PythonTimePrefix = "Préfixe fonction du module temps"
|
||||
PythonTimeSleep = "Attendre n secondes"
|
||||
PythonMonotonic = "Retourne le temps monotone"
|
||||
PythonFileOpen = "Ouvre un fichier"
|
||||
PythonFileSeekable = "Indique si seek peut être utilisé"
|
||||
|
||||
@@ -1,265 +1,210 @@
|
||||
PythonPound = "Megjegyzés"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Kettőspont"
|
||||
PythonSemicon = "Pontosvessző"
|
||||
PythonExclamationMark = "Felkiáltójel"
|
||||
PythonLessThan = "Kisebb mint"
|
||||
PythonGreaterThan = "Nagyobb mint"
|
||||
PythonQuestionMark = "Kérdőjel"
|
||||
Python1J = "Képzeletbeli i"
|
||||
PythonLF = "Enter"
|
||||
PythonTab = "Táblázat"
|
||||
PythonAmpersand = "Logikus és"
|
||||
PythonSymbolExp = "logikus exkluzív vagy pedig"
|
||||
PythonVerticalBar = "logikus vagy pedig"
|
||||
PythonImag = "z képzeletbeli része"
|
||||
PythonReal = "z valódi része"
|
||||
PythonSingleQuote = "apostróf"
|
||||
PythonAbs = "Abszolút érték/nagyság"
|
||||
PythonAcos = "Ív (arc) koszinusz"
|
||||
PythonAcosh = "Hiperbolikus arc koszinusz"
|
||||
PythonAppend = "Lista végére hozzáadni x-et"
|
||||
PythonArrow = "(x,y) nyíla (x+dx,y+dy) nyílához"
|
||||
PythonAsin = "Ív (arc) szinusz"
|
||||
PythonAsinh = "Hiperbolikus ív (arc) szinusz"
|
||||
PythonAtan = "Ív (arc) érintö (tan)"
|
||||
PythonAtan2 = "atan(y/x) sámolása"
|
||||
PythonAtanh = "Hiperbolikus ív (arc) érintö (atan)"
|
||||
PythonAxis = "Tengelyeket (xmin,xmax,ymin,ymax)-ra állitani"
|
||||
PythonBar = "Az x lista oszlopdiagramja"
|
||||
PythonBin = "Egész szám konvertálása binárisra"
|
||||
PythonCeil = "Mennyezet"
|
||||
PythonChoice = "Véletlenszerü szám a listában"
|
||||
PythonClear = "A lista ürítése"
|
||||
PythonCmathFunction = "cmath modul funkció elötag"
|
||||
PythonColor = "Rgb (pzk) szín allítása"
|
||||
PythonColorBlack = "Fekete szín"
|
||||
PythonColorBlue = "Kék szín"
|
||||
PythonColorBrown = "Barna szín"
|
||||
PythonColorGreen = "Zöld szín"
|
||||
PythonColorGray = "Szürke szín"
|
||||
PythonColorOrange = "Narancssárga szín"
|
||||
PythonColorPink = "Rózsaszín szín"
|
||||
PythonColorPurple = "Lila szín"
|
||||
PythonColorRed = "Piros szín"
|
||||
PythonColorWhite = "Fehér szín"
|
||||
PythonColorYellow = "Sárga szín"
|
||||
PythonComplex = "A + ib visszaadása"
|
||||
PythonCopySign = "X visszaadása y jelével"
|
||||
PythonCos = "Koszinusz"
|
||||
PythonCosh = "Hiperbolikus koszinusz"
|
||||
PythonCount = "Számolja az x elöfordulását"
|
||||
PythonDegrees = "x konvertálása radiánokrol fokokra"
|
||||
PythonDivMod = "Hányados és maradék"
|
||||
PythonDrawCircle = "Rajzolj egy kört"
|
||||
PythonDrawLine = "Húzzon egy vonalat "
|
||||
PythonDrawString = "Szöveg megjelenítése (x, y)-en"
|
||||
PythonErf = "Hiba funkció"
|
||||
PythonErfc = "Kiegészítö hiba funkció"
|
||||
PythonEval = "Visszaadja az értékelt kifejezést"
|
||||
PythonExp = "Exponenciális függvény"
|
||||
PythonExpm1 = "exp(x)-1 sámitása"
|
||||
PythonFactorial = "x faktorál"
|
||||
PythonFabs = "Abszolút érték"
|
||||
PythonFillRect = "Téglalap töltése"
|
||||
PythonFillCircle = "Kitölti a kört"
|
||||
PythonFillPolygon = "Kitölti a poligont"
|
||||
PythonFloat = "Konvertálása tizedes számra"
|
||||
PythonFloor = "Egész része"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "X mantissája és kiállítója"
|
||||
PythonGamma = "Gamma funkció"
|
||||
PythonGetKeys = "Billentyűk lenyomva"
|
||||
PythonGetPalette = "Téma paletta beszerzése"
|
||||
PythonGetPixel = "Visszatéríti (x,y) színét"
|
||||
PythonGetrandbits = "Váletlenszám visszatérítése k biten"
|
||||
PythonGrid = "Rács megjelenítése/elrejtése"
|
||||
PythonHex = "Decimális szám konvertálása hexadecimális számra"
|
||||
PythonHist = "x hisztográmiája"
|
||||
PythonImportCmath = "cmath modul importálása"
|
||||
PythonImportIon = "Ion modul importálása"
|
||||
PythonImportKandinsky = "Kandinsky modul importálása"
|
||||
PythonImportRandom = "Véletlenszerü modul importálása"
|
||||
PythonImportMath = "math modul importálása"
|
||||
PythonImportMatplotlibPyplot = "matplotlib.pyplot modul importálása"
|
||||
PythonImportNumpy = "ulab.numpy modul importálása"
|
||||
PythonImportScipy = "ulab.scipy modul importálása"
|
||||
PythonImportTurtle = "turtle modul importálása"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonIndex = "Az elsö x esemény indexe"
|
||||
PythonInput = "Irjon egy értéket (számot)"
|
||||
PythonInsert = "x-et i. pozícióra helyezze a listában"
|
||||
PythonInt = "egész számra konvertálás"
|
||||
PythonIonFunction = "ion modul funkció elötag"
|
||||
PythonIsFinite = "x véges-e"
|
||||
PythonIsInfinite = "x végtelen-e"
|
||||
PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva"
|
||||
PythonBattery = "Az akkumulátor feszültségének visszaadása"
|
||||
PythonBatteryLevel = "Az akkumulátor töltöttségi szintjének visszaadása"
|
||||
PythonBatteryIscharging = "Visszaadja, ha az akkumulátor töltődik"
|
||||
PythonSetBrightness = "Fényerőszint beállítása"
|
||||
PythonGetBrightness = "Get brightness level"
|
||||
PythonIsNaN = "Ellenörizze hogy x nem NaN"
|
||||
PythonKandinskyFunction = "kandinsky modul funkció elötag"
|
||||
PythonLdexp = "frexp ellentéte : x*(2**i)"
|
||||
PythonLength = "Egy targy hossza"
|
||||
PythonLgamma = "Gamma funkció logaritmusa"
|
||||
PythonLog = "a alapú logaritmus"
|
||||
PythonLog10 = "Decimális logaritmus"
|
||||
PythonLog2 = "Bináris logaritmus"
|
||||
PythonMathFunction = "math modul funkció elötag"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot elötag"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "x-nek tört és egész részei"
|
||||
PythonMonotonic = "Az óra értékét adja vissza"
|
||||
PythonNumpyFunction = "numpy elötag"
|
||||
PythonNumpyFftFunction = "numpy.fft elötag"
|
||||
PythonNumpyLinalgFunction = "numpy.linalg elötag"
|
||||
PythonScipyFunction = "scipy elötag"
|
||||
PythonScipyLinalgFunction = "scipy.linalg elötag"
|
||||
PythonScipyOptimizeFunction = "scipy.optimize elötag"
|
||||
PythonScipySignalFunction = "scipy.signal elötag"
|
||||
PythonScipySpecialFunction = "scipy.special elötag"
|
||||
PythonOct = "Decimális szám konvertálása octális számra"
|
||||
PythonPhase = "z fázisa"
|
||||
PythonPlot = "y-t jelöli x függvényében"
|
||||
PythonPolar = "Verctorizálni"
|
||||
PythonPop = "Az utolsó elemet el törölni"
|
||||
PythonPower = "x y. kitevö"
|
||||
PythonPrint = "Ki irni a elemeket"
|
||||
PythonRadians = "Fokról radiánra konvertálni"
|
||||
PythonRandint = "Véletlen egész szám [a;b] -ban"
|
||||
PythonRandom = "Decimális szám [0;1] -ban"
|
||||
PythonRandomFunction = "random modul funkció elötag"
|
||||
PythonRandrange = "Véletlen szám range(start,stop)-ban"
|
||||
PythonRangeStartStop = "start-tol stop-ig listája"
|
||||
PythonRangeStop = "0 tol stop-ig lista"
|
||||
PythonRect = "Algebrai számra konvertálni"
|
||||
PythonRemove = "Elsö x elöfordulását törolni"
|
||||
PythonReverse = "A lista elemeit megfordítani (másik irány)"
|
||||
PythonRound = "N számjegyre kerekítni"
|
||||
PythonScatter = "(x,y) halmaza"
|
||||
PythonSeed = "Inicializálni a véletlenszám-választót"
|
||||
PythonSetPixel = "Az (x,y) pixel-t ki szinezni"
|
||||
PythonShow = "Mutassa az ábrát"
|
||||
PythonSin = "Szinusz"
|
||||
PythonSinh = "Hiperbolikus szinusz"
|
||||
PythonSleep = "t másodpercre meg állitani a programmot"
|
||||
PythonLocalTime = "Idő konvertálása csomóvá"
|
||||
PythonMktime = "A tuple konvertálása az időben"
|
||||
PythonTime = "Az aktuális időbélyeg letöltése"
|
||||
PythonSetLocaltime = "Idő beállítása egy csomóból"
|
||||
PythonRTCmode = "Aktuális RTC mód"
|
||||
PythonSetRTCmode = "RTC mód beállítása"
|
||||
PythonSort = "A listát rendezni"
|
||||
PythonSqrt = "Négyzetgyök"
|
||||
PythonSum = "Összeadni a lista elemeit"
|
||||
PythonTan = "Érintö (tan)"
|
||||
PythonTanh = "Hiperbolikus érintö (tan)"
|
||||
PythonText = "(x,y) nél egy szöveget irni"
|
||||
PythonTimeFunction = "time funkció elötag"
|
||||
PythonTrunc = "Egész csonka (?)"
|
||||
PythonTurtleBackward = "x pixelt hátra"
|
||||
PythonTurtleCircle = "r pixel sugarú kört rajzolni"
|
||||
PythonTurtleColor = "Toll szinét beállitani"
|
||||
PythonTurtleColorMode = "Szin módot 1.0-ra vagy 255-ra állitani"
|
||||
PythonTurtleForward = "x pixelt elölre"
|
||||
PythonTurtleFunction = "turtle modul funkció elötag"
|
||||
PythonTurtleGoto = "Menjen a (x,y) koordinátákra"
|
||||
PythonTurtleHeading = "Visszaadja az aktuális irányt"
|
||||
PythonTurtleHideturtle = "A teknös elrejtése"
|
||||
PythonTurtleIsdown = "True-t válaszol ha a toll irás pozícióban van"
|
||||
PythonTurtleLeft = "a fokkot forduljon balra"
|
||||
PythonTurtlePendown = "Húzza le a tollat"
|
||||
PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre"
|
||||
PythonTurtlePenup = "Húzza fel a tollat"
|
||||
PythonTurtlePosition = "Az aktuális (x,y) pozíciót visszaadása"
|
||||
PythonTurtleReset = "Visszaállitani a rajzot (torléssel)"
|
||||
PythonTurtleRight = "a fokkot forduljon jobbra"
|
||||
PythonTurtleSetheading = "a fokokra állítja be az irányt"
|
||||
PythonTurtleShowturtle = "A teknöst meg mutatni"
|
||||
PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
|
||||
PythonTurtleWrite = "Szöveg irás"
|
||||
PythonUniform = "Lebegöpontos szám [a,b] -ban"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonMonotonic = "Meg fordítani a monoton idö"
|
||||
PythonFileOpen = "Fájl megnyitása"
|
||||
PythonFileSeekable = "Seek-et lehete használni"
|
||||
PythonFileSeek = "A kurzort áthelyezni"
|
||||
PythonFileTell = "Visszaadja a kurzor helye"
|
||||
PythonFileClose = "Bezárni egy fájlt"
|
||||
PythonFileClosed = "True ha a fájl bezárva"
|
||||
PythonFileRead = "Olvas 16 bájtig"
|
||||
PythonFileWrite = "b-t irjon a fájlba"
|
||||
PythonFileReadline = "Olvas egy sort vagy 16 bájtig"
|
||||
PythonFileReadlines = "Olvas több sort"
|
||||
PythonFileTruncate = "A fájl átméretezése"
|
||||
PythonFileWritelines = "Irjon több sort"
|
||||
PythonFileName = "A fájl neve"
|
||||
PythonFileMode = "A fájl nyitott módja"
|
||||
PythonFileReadable = "read-et lehete használni"
|
||||
PythonFileWritable = "write-ot lehete használni"
|
||||
PythonImportOs = "os modul importálása"
|
||||
PythonOsUname = "Rendszer informaciók"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Fájl törlése"
|
||||
PythonOsRename = "Fájl átnevezése"
|
||||
PythonOsListdir = "Fájlok listája"
|
||||
PythonImportSys = "sys modul importálása"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
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"
|
||||
PythonPound = "Megjegyzés"
|
||||
PythonPercent = "Modulo"
|
||||
Python1J = "Képzeletbeli i"
|
||||
PythonLF = "Enter"
|
||||
PythonTab = "Táblázat"
|
||||
PythonAmpersand = "Logikus és"
|
||||
PythonSymbolExp = "logikus exkluzív vagy pedig"
|
||||
PythonVerticalBar = "logikus vagy pedig"
|
||||
PythonImag = "z képzeletbeli része"
|
||||
PythonReal = "z valódi része"
|
||||
PythonSingleQuote = "apostróf"
|
||||
PythonAbs = "Abszolút érték/nagyság"
|
||||
PythonAcos = "Ív (arc) koszinusz"
|
||||
PythonAcosh = "Hiperbolikus arc koszinusz"
|
||||
PythonAppend = "Lista végére hozzáadni x-et"
|
||||
PythonArrow = "(x,y) nyíla (x+dx,y+dy) nyílához"
|
||||
PythonAsin = "Ív (arc) szinusz"
|
||||
PythonAsinh = "Hiperbolikus ív (arc) szinusz"
|
||||
PythonAtan = "Ív (arc) érintö (tan)"
|
||||
PythonAtan2 = "atan(y/x) sámolása"
|
||||
PythonAtanh = "Hiperbolikus ív (arc) érintö (atan)"
|
||||
PythonAxis = "Tengelyeket (xmin,xmax,ymin,ymax)-ra állitani"
|
||||
PythonBar = "Az x lista oszlopdiagramja"
|
||||
PythonBin = "Egész szám konvertálása binárisra"
|
||||
PythonCeil = "Mennyezet"
|
||||
PythonChoice = "Véletlenszerü szám a listában"
|
||||
PythonClear = "A lista ürítése"
|
||||
PythonCmathFunction = "cmath modul funkció elötag"
|
||||
PythonColor = "Rgb (pzk) szín allítása"
|
||||
PythonColorBlack = "Fekete szín"
|
||||
PythonColorBlue = "Kék szín"
|
||||
PythonColorBrown = "Barna szín"
|
||||
PythonColorGreen = "Zöld szín"
|
||||
PythonColorGray = "Szürke szín"
|
||||
PythonColorOrange = "Narancssárga szín"
|
||||
PythonColorPink = "Rózsaszín szín"
|
||||
PythonColorPurple = "Lila szín"
|
||||
PythonColorRed = "Piros szín"
|
||||
PythonColorWhite = "Fehér szín"
|
||||
PythonColorYellow = "Sárga szín"
|
||||
PythonComplex = "A + ib visszaadása"
|
||||
PythonCopySign = "X visszaadása y jelével"
|
||||
PythonCos = "Koszinusz"
|
||||
PythonCosh = "Hiperbolikus koszinusz"
|
||||
PythonCount = "Számolja az x elöfordulását"
|
||||
PythonDegrees = "x konvertálása radiánokrol fokokra"
|
||||
PythonDivMod = "Hányados és maradék"
|
||||
PythonDrawCircle = "Rajzolj egy kört"
|
||||
PythonDrawLine = "Húzzon egy vonalat "
|
||||
PythonDrawString = "Szöveg megjelenítése (x, y)-en"
|
||||
PythonErf = "Hiba funkció"
|
||||
PythonErfc = "Kiegészítö hiba funkció"
|
||||
PythonEval = "Visszaadja az értékelt kifejezést"
|
||||
PythonExp = "Exponenciális függvény"
|
||||
PythonExpm1 = "exp(x)-1 sámitása"
|
||||
PythonFabs = "Abszolút érték"
|
||||
PythonFillRect = "Téglalap töltése"
|
||||
PythonFillCircle = "Kitölti a kört"
|
||||
PythonFillPolygon = "Kitölti a poligont"
|
||||
PythonFloat = "Konvertálása tizedes számra"
|
||||
PythonFloor = "Egész része"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "X mantissája és kiállítója"
|
||||
PythonGamma = "Gamma funkció"
|
||||
PythonGetKeys = "Billentyűk lenyomva"
|
||||
PythonGetPalette = "Téma paletta beszerzése"
|
||||
PythonGetPixel = "Visszatéríti (x,y) színét"
|
||||
PythonGetrandbits = "Váletlenszám visszatérítése k biten"
|
||||
PythonGrid = "Rács megjelenítése/elrejtése"
|
||||
PythonHex = "Decimális szám konvertálása hexadecimális számra"
|
||||
PythonHist = "x hisztográmiája"
|
||||
PythonImportCmath = "cmath modul importálása"
|
||||
PythonImportIon = "Ion modul importálása"
|
||||
PythonImportKandinsky = "Kandinsky modul importálása"
|
||||
PythonImportRandom = "Véletlenszerü modul importálása"
|
||||
PythonImportMath = "math modul importálása"
|
||||
PythonImportMatplotlibPyplot = "matplotlib.pyplot modul importálása"
|
||||
PythonImportNumpy = "ulab.numpy modul importálása"
|
||||
PythonImportScipy = "ulab.scipy modul importálása"
|
||||
PythonImportTurtle = "turtle modul importálása"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonIndex = "Az elsö x esemény indexe"
|
||||
PythonInput = "Irjon egy értéket (számot)"
|
||||
PythonInsert = "x-et i. pozícióra helyezze a listában"
|
||||
PythonInt = "egész számra konvertálás"
|
||||
PythonIonFunction = "ion modul funkció elötag"
|
||||
PythonIsFinite = "x véges-e"
|
||||
PythonIsInfinite = "x végtelen-e"
|
||||
PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva"
|
||||
PythonBattery = "Return battery voltage"
|
||||
PythonBatteryLevel = "Return battery level"
|
||||
PythonBatteryIscharging = "Return if battery is charging"
|
||||
PythonIsNaN = "Ellenörizze hogy x nem NaN"
|
||||
PythonKandinskyFunction = "kandinsky modul funkció elötag"
|
||||
PythonLdexp = "frexp ellentéte : x*(2**i)"
|
||||
PythonLength = "Egy targy hossza"
|
||||
PythonLgamma = "Gamma funkció logaritmusa"
|
||||
PythonLog = "a alapú logaritmus"
|
||||
PythonLog10 = "Decimális logaritmus"
|
||||
PythonLog2 = "Bináris logaritmus"
|
||||
PythonMathFunction = "math modul funkció elötag"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot elötag"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "x-nek tört és egész részei"
|
||||
PythonMonotonic = "Az óra értékét adja vissza"
|
||||
PythonNumpyFunction = "numpy elötag"
|
||||
PythonNumpyFftFunction = "numpy.fft elötag"
|
||||
PythonNumpyLinalgFunction = "numpy.linalg elötag"
|
||||
PythonScipyFunction = "scipy elötag"
|
||||
PythonScipyLinalgFunction = "scipy.linalg elötag"
|
||||
PythonScipyOptimizeFunction = "scipy.optimize elötag"
|
||||
PythonScipySignalFunction = "scipy.signal elötag"
|
||||
PythonScipySpecialFunction = "scipy.special elötag"
|
||||
PythonOct = "Decimális szám konvertálása octális számra"
|
||||
PythonPhase = "z fázisa"
|
||||
PythonPlot = "y-t jelöli x függvényében"
|
||||
PythonPolar = "Verctorizálni"
|
||||
PythonPop = "Az utolsó elemet el törölni"
|
||||
PythonPower = "x y. kitevö"
|
||||
PythonPrint = "Ki irni a elemeket"
|
||||
PythonRadians = "Fokról radiánra konvertálni"
|
||||
PythonRandint = "Véletlen egész szám [a;b] -ban"
|
||||
PythonRandom = "Decimális szám [0;1] -ban"
|
||||
PythonRandomFunction = "random modul funkció elötag"
|
||||
PythonRandrange = "Véletlen szám range(start,stop)-ban"
|
||||
PythonRangeStartStop = "start-tol stop-ig listája"
|
||||
PythonRangeStop = "0 tol stop-ig lista"
|
||||
PythonRect = "Algebrai számra konvertálni"
|
||||
PythonRemove = "Elsö x elöfordulását törolni"
|
||||
PythonReverse = "A lista elemeit megfordítani (másik irány)"
|
||||
PythonRound = "N számjegyre kerekítni"
|
||||
PythonScatter = "(x,y) halmaza"
|
||||
PythonSeed = "Inicializálni a véletlenszám-választót"
|
||||
PythonSetPixel = "Az (x,y) pixel-t ki szinezni"
|
||||
PythonShow = "Mutassa az ábrát"
|
||||
PythonSin = "Szinusz"
|
||||
PythonSinh = "Hiperbolikus szinusz"
|
||||
PythonSleep = "t másodpercre meg állitani a programmot"
|
||||
PythonLocalTime = "Idő konvertálása csomóvá"
|
||||
PythonMktime = "A tuple konvertálása az időben"
|
||||
PythonTime = "Az aktuális időbélyeg letöltése"
|
||||
PythonSetLocaltime = "Idő beállítása egy csomóból"
|
||||
PythonRTCmode = "Aktuális RTC mód"
|
||||
PythonSetRTCmode = "RTC mód beállítása"
|
||||
PythonSort = "A listát rendezni"
|
||||
PythonSqrt = "Négyzetgyök"
|
||||
PythonSum = "Összeadni a lista elemeit"
|
||||
PythonTan = "Érintö (tan)"
|
||||
PythonTanh = "Hiperbolikus érintö (tan)"
|
||||
PythonText = "(x,y) nél egy szöveget irni"
|
||||
PythonTimeFunction = "time funkció elötag"
|
||||
PythonTrunc = "Egész csonka (?)"
|
||||
PythonTurtleBackward = "x pixelt hátra"
|
||||
PythonTurtleCircle = "r pixel sugarú kört rajzolni"
|
||||
PythonTurtleColor = "Toll szinét beállitani"
|
||||
PythonTurtleColorMode = "Szin módot 1.0-ra vagy 255-ra állitani"
|
||||
PythonTurtleForward = "x pixelt elölre"
|
||||
PythonTurtleFunction = "turtle modul funkció elötag"
|
||||
PythonTurtleGoto = "Menjen a (x,y) koordinátákra"
|
||||
PythonTurtleHeading = "Visszaadja az aktuális irányt"
|
||||
PythonTurtleHideturtle = "A teknös elrejtése"
|
||||
PythonTurtleIsdown = "True-t válaszol ha a toll irás pozícióban van"
|
||||
PythonTurtleLeft = "a fokkot forduljon balra"
|
||||
PythonTurtlePendown = "Húzza le a tollat"
|
||||
PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre"
|
||||
PythonTurtlePenup = "Húzza fel a tollat"
|
||||
PythonTurtlePosition = "Az aktuális (x,y) pozíciót visszaadása"
|
||||
PythonTurtleReset = "Visszaállitani a rajzot (torléssel)"
|
||||
PythonTurtleRight = "a fokkot forduljon jobbra"
|
||||
PythonTurtleSetheading = "a fokokra állítja be az irányt"
|
||||
PythonTurtleSetposition = "A teknös pozicioját allitja"
|
||||
PythonTurtleShowturtle = "A teknöst meg mutatni"
|
||||
PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
|
||||
PythonTurtleWrite = "Szöveg irás"
|
||||
PythonUniform = "Lebegöpontos szám [a,b] -ban"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonTimePrefix = "time funkció elötag"
|
||||
PythonTimeSleep = "n másodpercet várni"
|
||||
PythonMonotonic = "Meg fordítani a monoton idö"
|
||||
PythonFileOpen = "Fájl megnyitása"
|
||||
PythonFileSeekable = "Seek-et lehete használni"
|
||||
PythonFileSeek = "A kurzort áthelyezni"
|
||||
PythonFileTell = "Visszaadja a kurzor helye"
|
||||
PythonFileClose = "Bezárni egy fájlt"
|
||||
PythonFileClosed = "True ha a fájl bezárva"
|
||||
PythonFileRead = "Olvas 16 bájtig"
|
||||
PythonFileWrite = "b-t irjon a fájlba"
|
||||
PythonFileReadline = "Olvas egy sort vagy 16 bájtig"
|
||||
PythonFileReadlines = "Olvas több sort"
|
||||
PythonFileTruncate = "A fájl átméretezése"
|
||||
PythonFileWritelines = "Irjon több sort"
|
||||
PythonFileName = "A fájl neve"
|
||||
PythonFileMode = "A fájl nyitott módja"
|
||||
PythonFileReadable = "read-et lehete használni"
|
||||
PythonFileWritable = "write-ot lehete használni"
|
||||
PythonImportOs = "os modul importálása"
|
||||
PythonOsUname = "Rendszer informaciók"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Fájl törlése"
|
||||
PythonOsRename = "Fájl átnevezése"
|
||||
PythonOsListdir = "Fájlok listája"
|
||||
PythonImportSys = "sys modul importálása"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
PythonPound = "Commento"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Due punti"
|
||||
PythonSemicon = "Punto e virgola"
|
||||
PythonExclamationMark = "Punto esclamativo"
|
||||
PythonLessThan = "Minore di"
|
||||
PythonGreaterThan = "Maggiore di"
|
||||
PythonQuestionMark = "Punto interrogativo"
|
||||
Python1J = "Unità immaginaria"
|
||||
PythonLF = "Nuova riga"
|
||||
PythonTab = "Tabulazione"
|
||||
@@ -31,7 +25,7 @@ PythonBin = "Converte un intero in binario"
|
||||
PythonCeil = "Parte intera superiore"
|
||||
PythonChoice = "Numero aleatorio nella lista"
|
||||
PythonClear = "Svuota la lista"
|
||||
PythonCmathFunction = "Prefisso funzione del modulo cmath"
|
||||
PythonCmathFunction = "Funz. prefissata modulo cmath"
|
||||
PythonColor = "Definisci un colore rvb"
|
||||
PythonColorBlack = "Colore nero"
|
||||
PythonColorBlue = "Colore blu"
|
||||
@@ -59,7 +53,6 @@ PythonErfc = "Funzione d'errore complementare"
|
||||
PythonEval = "Valuta l'espressione nell'argomento "
|
||||
PythonExp = "Funzione esponenziale"
|
||||
PythonExpm1 = "Calcola exp(x)-1"
|
||||
PythonFactorial = "Fattoriale di x"
|
||||
PythonFabs = "Valore assoluto"
|
||||
PythonFillCircle = "Riempire un cerchio"
|
||||
PythonFillPolygon = "Riempire un poligono"
|
||||
@@ -69,7 +62,7 @@ PythonFloor = "Parte intera"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "Mantissa ed esponente di x : (m,e)"
|
||||
PythonGamma = "Funzione gamma"
|
||||
PythonGetKeys = "Ottieni i tasti premuti"
|
||||
PythonGetKeys = "Premere i tasti"
|
||||
PythonGetPalette = "Ottieni la tavolozza del tema"
|
||||
PythonGetPixel = "Restituisce colore del pixel(x,y)"
|
||||
PythonGetrandbits = "Numero aleatorio con k bit"
|
||||
@@ -88,79 +81,31 @@ PythonImportTurtle = "Importa del modulo turtle"
|
||||
PythonImportTime = "Importa del modulo time"
|
||||
PythonImportOs = "Importa modulo os"
|
||||
PythonOsUname = "Ottieni informazioni sul sistema"
|
||||
PythonOsGetlogin = "Ottieni username"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Rimuovere un file"
|
||||
PythonOsRename = "Rinomina file"
|
||||
PythonOsListdir = "Elenca file"
|
||||
PythonImportSys = "Importa modulo sys"
|
||||
PythonSysExit = "Termina programma corrente"
|
||||
PythonSysPrintexception = "Stampa eccezione"
|
||||
PythonSysByteorder = "Ordine di byte del sistema"
|
||||
PythonSysImplementation = "Informazioni su Python"
|
||||
PythonSysModules = "Dizionario dei moduli caricati"
|
||||
PythonSysVersion = "Versione linguaggio Python (stringa)"
|
||||
PythonSysVersioninfo = "Versione linguaggio Python (tupla)"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonIndex = "Indice prima occorrenza di x"
|
||||
PythonInput = "Inserire un valore"
|
||||
PythonInsert = "Inserire x in posizione i-esima"
|
||||
PythonInt = "Conversione in intero"
|
||||
PythonIonFunction = "Prefisso di funzione modulo ion"
|
||||
PythonIsFinite = "Testa se x è finito"
|
||||
PythonIsInfinite = "Testa se x è infinito"
|
||||
PythonIsInfinite = "Testa se x est infinito"
|
||||
PythonIsKeyDown = "Restituisce True premendo tasto k"
|
||||
PythonBattery = "Restituisce la tensione della batteria"
|
||||
PythonBatteryLevel = "Restituisce il livello della batteria"
|
||||
PythonBatteryIscharging = "Restituisce se la batteria è in carica"
|
||||
PythonSetBrightness = "Imposta livello di luminosità"
|
||||
PythonGetBrightness = "Ottieni livello di luminosità"
|
||||
PythonBattery = "Return battery voltage"
|
||||
PythonBatteryLevel = "Return battery level"
|
||||
PythonBatteryIscharging = "Return if battery is charging"
|
||||
PythonIsNaN = "Testa se x è NaN"
|
||||
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)"
|
||||
PythonLength = "Longhezza di un oggetto"
|
||||
PythonLgamma = "Logaritmo della funzione gamma"
|
||||
@@ -196,7 +141,7 @@ PythonRandrange = "Numero dentro il range(start, stop)"
|
||||
PythonRangeStartStop = "Lista da start a stop-1"
|
||||
PythonRangeStop = "Lista da 0 a stop-1"
|
||||
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"
|
||||
PythonRound = "Arrotondato a n cifre decimali"
|
||||
PythonScatter = "Diagramma dispersione y in f. di x"
|
||||
@@ -238,28 +183,28 @@ PythonTurtlePosition = "Fornisce posizione corrente (x,y)"
|
||||
PythonTurtleReset = "Azzera il disegno"
|
||||
PythonTurtleRight = "Ruota di a gradi a destra"
|
||||
PythonTurtleSetheading = "Imposta l'orientamento per a gradi"
|
||||
PythonTurtleSetposition = "Posiziona la tartaruga"
|
||||
PythonTurtleShowturtle = "Mostra la tartaruga"
|
||||
PythonTurtleSpeed = "Velocità di disegno (x tra 0 e 10)"
|
||||
PythonTurtleWrite = "Mostra un testo"
|
||||
PythonUniform = "Numero decimale tra [a,b]"
|
||||
PythonImportTime = "Importa modulo time"
|
||||
PythonMonotonic = "Restituisce tempo monotonico"
|
||||
PythonFileOpen = "Apre un file"
|
||||
PythonFileSeekable = "Dice se si può usare il cursore su un file"
|
||||
PythonFileSeek = "Sposta cursore di un file"
|
||||
PythonFileTell = "Ottieni posizione del cursore del file"
|
||||
PythonFileClose = "Chiude un file"
|
||||
PythonFileClosed = "True se un file è stato chiuso"
|
||||
PythonFileRead = "Legge fino ai byte di un file"
|
||||
PythonFileWrite = "Scrive b in un file"
|
||||
PythonFileReadline = "Legge una riga o fino ai byte di un file"
|
||||
PythonFileReadlines = "Legge una lista di linee di un file"
|
||||
PythonFileTruncate = "Ridimensiona il file"
|
||||
PythonFileWritelines = "Scrive una lista di linee su file"
|
||||
PythonFileName = "Contiene il nome del file"
|
||||
PythonFileMode = "Contiene la modalità di apertura del file"
|
||||
PythonFileReadable = "Dice se si può leggere sul file"
|
||||
PythonFileWritable = "Dice se si può scrivere sul file"
|
||||
PythonImportUtils = "Importazione di ulab.utils"
|
||||
PythonUtilsFunction = "Prefisso funzione del modulo utils"
|
||||
PythonTurtleBgcolor = "Cambia il colore dello sfondo"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
PythonFileSeek = "Move file's cursor"
|
||||
PythonFileTell = "Get file's cursor location"
|
||||
PythonFileClose = "Closes a file"
|
||||
PythonFileClosed = "True if file was closed"
|
||||
PythonFileRead = "Read up to size bytes"
|
||||
PythonFileWrite = "Write b into file"
|
||||
PythonFileReadline = "Reads a line or up to size bytes"
|
||||
PythonFileReadlines = "Reads a list of lines"
|
||||
PythonFileTruncate = "Resize the file to size"
|
||||
PythonFileWritelines = "Writes a list of lines"
|
||||
PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read can be used on a file"
|
||||
PythonFileWritable = "Tells if write can be used on a file"
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
PythonPound = "Opmerkingen"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Dubbele punt"
|
||||
PythonSemicon = "Puntkomma"
|
||||
PythonExclamationMark = "Uitroepteken"
|
||||
PythonLessThan = "Kleiner dan"
|
||||
PythonGreaterThan = "Groter dan"
|
||||
PythonQuestionMark = "Vraagteken"
|
||||
Python1J = "Imaginaire i"
|
||||
PythonLF = "Nieuwe regel"
|
||||
PythonTab = "Tabulatie"
|
||||
@@ -59,7 +53,6 @@ PythonErfc = "Complementaire error functie"
|
||||
PythonEval = "Geef de geëvalueerde uitdrukking"
|
||||
PythonExp = "Exponentiële functie"
|
||||
PythonExpm1 = "Bereken exp(x)-1"
|
||||
PythonFactorial = "faculteit van x"
|
||||
PythonFabs = "Absolute waarde"
|
||||
PythonFillCircle = "Vul een cirkel"
|
||||
PythonFillPolygon = "Vul een veelhoek"
|
||||
@@ -109,59 +102,11 @@ PythonIonFunction = "ion module voorvoegsel"
|
||||
PythonIsFinite = "Controleer of x eindig is"
|
||||
PythonIsInfinite = "Controleer of x oneindig is"
|
||||
PythonIsKeyDown = "Geef True als k toets omlaag is"
|
||||
PythonBattery = "Return batterijspanning"
|
||||
PythonBatteryLevel = "Batterijniveau teruggeven"
|
||||
PythonBatteryIscharging = "Keer terug als de batterij wordt opgeladen"
|
||||
PythonSetBrightness = "Set brightness level"
|
||||
PythonGetBrightness = "Get brightness level"
|
||||
PythonBattery = "Return battery voltage"
|
||||
PythonBatteryLevel = "Return battery level"
|
||||
PythonBatteryIscharging = "Return if battery is charging"
|
||||
PythonIsNaN = "Controleer of x geen getal is"
|
||||
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"
|
||||
PythonLength = "Lengte van een object"
|
||||
PythonLgamma = "Log-gammafunctie"
|
||||
@@ -204,7 +149,7 @@ PythonScatter = "Teken scatterplot van y versus x"
|
||||
PythonSeed = "Start willek. getallengenerator"
|
||||
PythonSetPixel = "Kleur pixel (x,y)"
|
||||
PythonShow = "Figuur weergeven"
|
||||
PythonSin = "Sinus"
|
||||
PythonSin= "Sinus"
|
||||
PythonSinh = "Sinus hyperbolicus"
|
||||
PythonSleep = "Stel executie voor t seconden uit"
|
||||
PythonLocalTime = "Zet tijd om in tuple"
|
||||
@@ -239,11 +184,14 @@ PythonTurtlePosition = "Zet huidige (x,y) locatie terug"
|
||||
PythonTurtleReset = "Reset de tekening"
|
||||
PythonTurtleRight = "Ga rechtsaf met a graden"
|
||||
PythonTurtleSetheading = "Zet de oriëntatie op a graden"
|
||||
PythonTurtleSetposition = "Plaats de schildpad"
|
||||
PythonTurtleShowturtle = "Laat de schildpad zien"
|
||||
PythonTurtleSpeed = "Tekensnelheid tussen 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
PythonUniform = "Decimaal getal in [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
@@ -261,6 +209,3 @@ PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read 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"
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
PythonPound = "Comentário"
|
||||
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"
|
||||
PythonLF = "Nova linha"
|
||||
PythonTab = "Tabulação"
|
||||
@@ -59,7 +53,6 @@ PythonErfc = "Função erro complementar"
|
||||
PythonEval = "Devolve a expressão avaliada"
|
||||
PythonExp = "Função exponencial"
|
||||
PythonExpm1 = "Calcular exp(x)-1"
|
||||
PythonFactorial = "Fatorial de x"
|
||||
PythonFabs = "Valor absoluto"
|
||||
PythonFillCircle = "Preencher um círculo"
|
||||
PythonFillPolygon = "Preencher um polígono"
|
||||
@@ -94,59 +87,11 @@ PythonIonFunction = "Prefixo da função do módulo ion"
|
||||
PythonIsFinite = "Verificar se x é finito"
|
||||
PythonIsInfinite = "Verificar se x é infinito"
|
||||
PythonIsKeyDown = "Devolve True se tecla k pressionada"
|
||||
PythonBattery = "Retornar a voltagem da bateria"
|
||||
PythonBatteryLevel = "Retornar nível de bateria"
|
||||
PythonBatteryIscharging = "Retorne se a bateria estiver carregando"
|
||||
PythonSetBrightness = "Definir nível de brilho"
|
||||
PythonGetBrightness = "Obter nível de brilho"
|
||||
PythonBattery = "Return battery voltage"
|
||||
PythonBatteryLevel = "Return battery level"
|
||||
PythonBatteryIscharging = "Return if battery is charging"
|
||||
PythonIsNaN = "Verificar se x é um NaN"
|
||||
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"
|
||||
PythonLength = "Comprimento de um objeto"
|
||||
PythonLgamma = "Logaritmo da função gama"
|
||||
@@ -224,6 +169,7 @@ PythonTurtlePosition = "Devolve a posição atual (x,y)"
|
||||
PythonTurtleReset = "Reiniciar o desenho"
|
||||
PythonTurtleRight = "Virar à esquerda por a graus"
|
||||
PythonTurtleSetheading = "Definir a orientação por a graus"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Mostrar o turtle"
|
||||
PythonTurtleSpeed = "Velocidade do desenho entre 0 e 10"
|
||||
PythonTurtleWrite = "Mostrar um texto"
|
||||
@@ -243,6 +189,8 @@ PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
@@ -260,6 +208,3 @@ PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read 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"
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
PythonCommandAmpersand = "&"
|
||||
PythonCommandLF = "\\n"
|
||||
PythonCommandPercent = "%"
|
||||
PythonCommandColon = ":"
|
||||
PythonCommandSemicon = ";"
|
||||
PythonCommandExclamationMark = "!"
|
||||
PythonCommandLessThan = "<"
|
||||
PythonCommandGreaterThan = ">"
|
||||
PythonCommandQuestionMark = "?"
|
||||
PythonCommandPound = "#"
|
||||
PythonCommandSingleQuote = "'x'"
|
||||
PythonCommandSymbolExp = "^"
|
||||
@@ -66,7 +60,6 @@ PythonCommandEval = "eval(\"expression\")"
|
||||
PythonCommandExp = "exp(x)"
|
||||
PythonCommandExpComplex = "exp(z)"
|
||||
PythonCommandExpm1 = "expm1(x)"
|
||||
PythonCommandFactorial = "factorial(x)"
|
||||
PythonCommandFabs = "fabs(x)"
|
||||
PythonCommandFillCircle = "fill_circle(x,y,r,color)"
|
||||
PythonCommandFillPolygon = "fill_polygon([(x1,y1),...],color)"
|
||||
@@ -170,8 +163,6 @@ PythonCommandIsKeyDown = "keydown(k)"
|
||||
PythonCommandBattery = "battery()"
|
||||
PythonCommandBatteryLevel = "battery_level()"
|
||||
PythonCommandBatteryIscharging = "battery_ischarging()"
|
||||
PythonCommandSetBrightness = "set_brightness()"
|
||||
PythonCommandGetBrightness = "get_brightness()"
|
||||
PythonCommandLdexp = "ldexp(x,i)"
|
||||
PythonCommandLength = "len(object)"
|
||||
PythonCommandLgamma = "lgamma(x)"
|
||||
@@ -301,14 +292,6 @@ PythonCommandNumpyFftFunction = "np.fft.function"
|
||||
PythonCommandNumpyFftFunctionWithoutArg = "np.fft.\x11"
|
||||
PythonCommandNumpyLinalgFunction = "np.linalg.function"
|
||||
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)"
|
||||
PythonCommandPhase = "phase(z)"
|
||||
PythonCommandPlot = "plot(x,y,color)"
|
||||
@@ -404,7 +387,6 @@ PythonTurtleCommandBackward = "backward(x)"
|
||||
PythonTurtleCommandCircle = "circle(r)"
|
||||
PythonTurtleCommandColor = "color('c')"
|
||||
PythonTurtleCommandColorMode = "colormode(x)"
|
||||
PythonTurtleCommandBgcolor = "bgcolor('c')"
|
||||
PythonTurtleCommandForward = "forward(x)"
|
||||
PythonTurtleCommandGoto = "goto(x,y)"
|
||||
PythonTurtleCommandHeading = "heading()"
|
||||
@@ -418,8 +400,16 @@ PythonTurtleCommandPosition = "position()"
|
||||
PythonTurtleCommandReset = "reset()"
|
||||
PythonTurtleCommandRight = "right(a)"
|
||||
PythonTurtleCommandSetheading = "setheading(a)"
|
||||
PythonTurtleCommandSetposition = "setposition(x,[y])"
|
||||
PythonTurtleCommandShowturtle = "showturtle()"
|
||||
PythonTurtleCommandSpeed = "speed(x)"
|
||||
PythonTurtleCommandWhite = "'white'"
|
||||
PythonTurtleCommandYellow = "'yellow'"
|
||||
PythonTimeModule = "time"
|
||||
PythonTimeCommandImportFrom = "from time import *"
|
||||
PythonTimeCommandSleep = "sleep()"
|
||||
PythonTimeCommandSleepDemo = "sleep(n)"
|
||||
PythonTimeCommandMonotonic = "monotonic()"
|
||||
PythonCommandFileOpen = "open(name, [mode])"
|
||||
PythonCommandFileOpenWithoutArg = "open(\x11)"
|
||||
PythonCommandFileSeek = "file.seek(offset, [whence])"
|
||||
|
||||
@@ -19,7 +19,7 @@ void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::setLine(Consol
|
||||
|
||||
void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
ctx->fillRect(bounds(), Palette::CodeBackground);
|
||||
ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::CodeBackground);
|
||||
ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::BackgroundApps);
|
||||
}
|
||||
|
||||
KDSize ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::minimalSizeForOptimalDisplay() const {
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#include "app.h"
|
||||
#include <escher/metric.h>
|
||||
#include <ion.h>
|
||||
#include "../global_preferences.h"
|
||||
#include <apps/apps_container.h>
|
||||
|
||||
using namespace Shared;
|
||||
|
||||
@@ -73,10 +71,6 @@ void EditorController::viewDidDisappear() {
|
||||
m_menuController->scriptContentEditionDidFinish();
|
||||
}
|
||||
|
||||
void EditorController::textAreaDidReceiveNoneXNTEvent() {
|
||||
AppsContainer::sharedAppsContainer()->resetXNT();
|
||||
}
|
||||
|
||||
bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) {
|
||||
if (App::app()->textInputDidReceiveEvent(textArea, event)) {
|
||||
return true;
|
||||
@@ -86,6 +80,7 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (event == Ion::Events::Backspace && textArea->selectionIsEmpty()) {
|
||||
/* If the cursor is on the left of the text of a line, backspace one
|
||||
* indentation space at a time. */
|
||||
|
||||
@@ -30,7 +30,6 @@ public:
|
||||
TELEMETRY_ID("Editor");
|
||||
|
||||
/* TextAreaDelegate */
|
||||
void textAreaDidReceiveNoneXNTEvent() override;
|
||||
bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) override;
|
||||
|
||||
/* InputEventHandlerDelegate */
|
||||
|
||||
@@ -26,9 +26,7 @@ void EditorView::resetSelection() {
|
||||
}
|
||||
|
||||
void EditorView::scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) {
|
||||
if (m_gutterView.setOffsetAndNeedResize(scrollViewDataSource->offset().y())) {
|
||||
internalLayoutSubviews(true);
|
||||
}
|
||||
m_gutterView.setOffset(scrollViewDataSource->offset().y());
|
||||
}
|
||||
|
||||
View * EditorView::subviewAtIndex(int index) {
|
||||
@@ -44,12 +42,8 @@ void EditorView::didBecomeFirstResponder() {
|
||||
}
|
||||
|
||||
void EditorView::layoutSubviews(bool force) {
|
||||
m_gutterView.setOffsetAndNeedResize(0); // Whatever the return is, we layout the editor view
|
||||
internalLayoutSubviews(force);
|
||||
}
|
||||
|
||||
void EditorView::internalLayoutSubviews(bool force) {
|
||||
KDCoordinate gutterWidth = m_gutterView.computeWidth();
|
||||
m_gutterView.setOffset(0);
|
||||
KDCoordinate gutterWidth = m_gutterView.minimalSizeForOptimalDisplay().width();
|
||||
m_gutterView.setFrame(KDRect(0, 0, gutterWidth, bounds().height()), force);
|
||||
|
||||
m_textArea.setFrame(KDRect(
|
||||
@@ -73,23 +67,23 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
KDCoordinate firstLine = m_offset / glyphSize.height();
|
||||
KDCoordinate firstLinePixelOffset = m_offset - firstLine * glyphSize.height();
|
||||
|
||||
char lineNumberBuffer[m_numberOfDigits + 1];
|
||||
char lineNumber[k_lineNumberCharLength];
|
||||
int numberOfLines = bounds().height() / glyphSize.height() + 1;
|
||||
for (int i=0; i<numberOfLines; i++) {
|
||||
int lineNumberValue = (i + firstLine + 1);
|
||||
// Only the first two digits are displayed
|
||||
int lineNumberValue = (i + firstLine + 1) % 100;
|
||||
Poincare::Integer line(lineNumberValue);
|
||||
|
||||
int lineDigits = computeNumberOfDigitsFor(lineNumberValue);
|
||||
|
||||
for (int j=0; j < m_numberOfDigits - lineDigits; j++) {
|
||||
lineNumberBuffer[j] = ' ';
|
||||
if (firstLine < 10 || lineNumberValue >= 10) {
|
||||
line.serialize(lineNumber, k_lineNumberCharLength);
|
||||
} else {
|
||||
// Add a leading "0"
|
||||
lineNumber[0] = '0';
|
||||
line.serialize(lineNumber + 1, k_lineNumberCharLength - 1);
|
||||
}
|
||||
|
||||
line.serialize(lineNumberBuffer + (m_numberOfDigits - lineDigits), m_numberOfDigits + 1);
|
||||
|
||||
KDCoordinate leftPadding = (2 - strlen(lineNumber)) * glyphSize.width();
|
||||
ctx->drawString(
|
||||
lineNumberBuffer,
|
||||
KDPoint(k_margin, i*glyphSize.height() - firstLinePixelOffset),
|
||||
lineNumber,
|
||||
KDPoint(k_margin + leftPadding, i*glyphSize.height() - firstLinePixelOffset),
|
||||
m_font,
|
||||
textColor,
|
||||
backgroundColor
|
||||
@@ -97,36 +91,18 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool EditorView::GutterView::setOffsetAndNeedResize(KDCoordinate offset) {
|
||||
void EditorView::GutterView::setOffset(KDCoordinate offset) {
|
||||
if (m_offset == offset) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
m_offset = offset;
|
||||
|
||||
int numberOfDigits = computeMaxNumberOfDigits();
|
||||
if (numberOfDigits != m_numberOfDigits) {
|
||||
m_numberOfDigits = numberOfDigits;
|
||||
return true;
|
||||
}
|
||||
|
||||
markRectAsDirty(bounds());
|
||||
return false;
|
||||
}
|
||||
|
||||
int EditorView::GutterView::computeWidth() {
|
||||
return 2 * k_margin + (m_numberOfDigits) * m_font->glyphSize().width();
|
||||
}
|
||||
|
||||
int EditorView::GutterView::computeMaxNumberOfDigits() {
|
||||
return computeNumberOfDigitsFor((bounds().height() / m_font->glyphSize().height() + 1) + (m_offset / m_font->glyphSize().height()));
|
||||
}
|
||||
|
||||
int EditorView::GutterView::computeNumberOfDigitsFor(int value) {
|
||||
int digits = 1;
|
||||
while (value >= pow(10, digits)) {
|
||||
digits++;
|
||||
}
|
||||
return digits;
|
||||
KDSize EditorView::GutterView::minimalSizeForOptimalDisplay() const {
|
||||
int numberOfChars = 2; // TODO: Could be computed
|
||||
return KDSize(2 * k_margin + numberOfChars * m_font->glyphSize().width(), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ public:
|
||||
void unloadSyntaxHighlighter() { m_textArea.unloadSyntaxHighlighter(); };
|
||||
void scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
void internalLayoutSubviews(bool force);
|
||||
private:
|
||||
int numberOfSubviews() const override { return 2; }
|
||||
View * subviewAtIndex(int index) override;
|
||||
@@ -37,21 +36,15 @@ private:
|
||||
|
||||
class GutterView : public View {
|
||||
public:
|
||||
GutterView(const KDFont * font) : View(), m_font(font), m_offset(0), m_numberOfDigits(2) {}
|
||||
|
||||
GutterView(const KDFont * font) : View(), m_font(font), m_offset(0) {}
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
bool setOffsetAndNeedResize(KDCoordinate offset); // Return true if the gutter view need to be resized
|
||||
|
||||
int computeWidth();
|
||||
int computeMaxNumberOfDigits();
|
||||
static int computeNumberOfDigitsFor(int value);
|
||||
|
||||
void setOffset(KDCoordinate offset);
|
||||
KDSize minimalSizeForOptimalDisplay() const override;
|
||||
private:
|
||||
static constexpr KDCoordinate k_margin = 2;
|
||||
|
||||
static constexpr int k_lineNumberCharLength = 3;
|
||||
const KDFont * m_font;
|
||||
KDCoordinate m_offset;
|
||||
int m_numberOfDigits;
|
||||
};
|
||||
|
||||
PythonTextArea m_textArea;
|
||||
|
||||
@@ -10,6 +10,9 @@ const char * PythonTextForEvent(Ion::Events::Event event) {
|
||||
if (event.text() == pair.firstString()) {
|
||||
return pair.secondString();
|
||||
}
|
||||
if (event == Ion::Events::XNT) {
|
||||
return "x";
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -90,11 +90,6 @@ bool MenuController::handleEvent(Ion::Events::Event event) {
|
||||
footer()->setSelectedButton(0);
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::ShiftBack) {
|
||||
Ion::Storage::sharedStorage()->reinsertTrash("py");
|
||||
m_selectableTableView.reloadData();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Up) {
|
||||
if (footer()->selectedButton() == 0) {
|
||||
footer()->setSelectedButton(-1);
|
||||
|
||||
@@ -24,20 +24,7 @@ constexpr KDColor BackgroundColor = Palette::CodeBackground;
|
||||
constexpr KDColor HighlightColor = Palette::CodeBackgroundSelected;
|
||||
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) {
|
||||
if (!GlobalPreferences::sharedGlobalPreferences()->syntaxhighlighting()) {
|
||||
return Palette::CodeText;
|
||||
}
|
||||
if (tokenKind == MP_TOKEN_STRING) {
|
||||
return StringColor;
|
||||
}
|
||||
@@ -79,8 +66,7 @@ static inline KDColor TokenColor(mp_token_kind_t tokenKind) {
|
||||
&& MP_TOKEN_KW_TRY + 1 == MP_TOKEN_KW_WHILE
|
||||
&& MP_TOKEN_KW_WHILE + 1 == MP_TOKEN_KW_WITH
|
||||
&& MP_TOKEN_KW_WITH + 1 == MP_TOKEN_KW_YIELD
|
||||
&& MP_TOKEN_KW_YIELD + 1 == MP_TOKEN_OP_ASSIGN
|
||||
&& MP_TOKEN_OP_ASSIGN + 1 == MP_TOKEN_OP_TILDE,
|
||||
&& MP_TOKEN_KW_YIELD + 1 == MP_TOKEN_OP_TILDE,
|
||||
"MP_TOKEN order changed, so Code::PythonTextArea::TokenColor might need to change too.");
|
||||
if (tokenKind >= MP_TOKEN_KW_FALSE && tokenKind <= MP_TOKEN_KW_YIELD) {
|
||||
return KeywordColor;
|
||||
@@ -133,8 +119,7 @@ static inline KDColor TokenColor(mp_token_kind_t tokenKind) {
|
||||
|
||||
if ((tokenKind >= MP_TOKEN_OP_TILDE && tokenKind <= MP_TOKEN_DEL_DBL_STAR_EQUAL)
|
||||
|| tokenKind == MP_TOKEN_DEL_EQUAL
|
||||
|| tokenKind == MP_TOKEN_DEL_MINUS_MORE
|
||||
|| tokenKind == MP_TOKEN_OP_ASSIGN)
|
||||
|| tokenKind == MP_TOKEN_DEL_MINUS_MORE)
|
||||
{
|
||||
return OperatorColor;
|
||||
}
|
||||
@@ -172,7 +157,7 @@ PythonTextArea::AutocompletionType PythonTextArea::autocompletionType(const char
|
||||
const char * tokenEnd;
|
||||
_mp_token_kind_t currentTokenKind = lex->tok_kind;
|
||||
|
||||
while (currentTokenKind != MP_TOKEN_NEWLINE && currentTokenKind != MP_TOKEN_END && currentTokenKind != MP_TOKEN_FSTRING_RAW) {
|
||||
while (currentTokenKind != MP_TOKEN_NEWLINE && currentTokenKind != MP_TOKEN_END) {
|
||||
tokenStart = firstNonSpace + lex->tok_column - 1;
|
||||
tokenEnd = tokenStart + TokenLength(lex, tokenStart);
|
||||
|
||||
@@ -265,8 +250,7 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
|
||||
BackgroundColor,
|
||||
selectionStart,
|
||||
selectionEnd,
|
||||
HighlightColor,
|
||||
false);
|
||||
HighlightColor);
|
||||
}
|
||||
if (UTF8Helper::CodePointIs(firstNonSpace, UCodePointNull)) {
|
||||
return;
|
||||
@@ -282,7 +266,7 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
|
||||
const char * tokenFrom = firstNonSpace;
|
||||
size_t tokenLength = 0;
|
||||
const char * tokenEnd = firstNonSpace;
|
||||
while (lex->tok_kind != MP_TOKEN_NEWLINE && lex->tok_kind != MP_TOKEN_END && lex->tok_kind != MP_TOKEN_FSTRING_RAW) {
|
||||
while (lex->tok_kind != MP_TOKEN_NEWLINE && lex->tok_kind != MP_TOKEN_END) {
|
||||
tokenFrom = firstNonSpace + lex->tok_column - 1;
|
||||
if (tokenFrom != tokenEnd) {
|
||||
// We passed over white spaces, we need to color them
|
||||
@@ -296,15 +280,13 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
|
||||
BackgroundColor,
|
||||
selectionStart,
|
||||
selectionEnd,
|
||||
HighlightColor,
|
||||
false);
|
||||
HighlightColor);
|
||||
}
|
||||
tokenLength = TokenLength(lex, tokenFrom);
|
||||
tokenEnd = tokenFrom + tokenLength;
|
||||
|
||||
// If the token is being autocompleted, use DefaultColor/Font
|
||||
// If the token is being autocompleted, use DefaultColor
|
||||
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);
|
||||
drawStringAt(ctx, line,
|
||||
@@ -315,9 +297,7 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
|
||||
BackgroundColor,
|
||||
selectionStart,
|
||||
selectionEnd,
|
||||
HighlightColor,
|
||||
italic
|
||||
);
|
||||
HighlightColor);
|
||||
|
||||
mp_lexer_to_next(lex);
|
||||
LOG_DRAW("Pop token %d\n", lex->tok_kind);
|
||||
@@ -325,10 +305,6 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
|
||||
|
||||
tokenFrom += tokenLength;
|
||||
|
||||
KDColor color = CommentColor;
|
||||
if (!GlobalPreferences::sharedGlobalPreferences()->syntaxhighlighting()) {
|
||||
color = Palette::CodeText;
|
||||
}
|
||||
// Even if the token is being autocompleted, use CommentColor
|
||||
if (tokenFrom < text + byteLength) {
|
||||
LOG_DRAW("Draw comment \"%.*s\" from %d\n", byteLength - (tokenFrom - text), firstNonSpace, tokenFrom);
|
||||
@@ -336,12 +312,11 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
|
||||
UTF8Helper::GlyphOffsetAtCodePoint(text, tokenFrom),
|
||||
tokenFrom,
|
||||
text + byteLength - tokenFrom,
|
||||
color,
|
||||
CommentColor,
|
||||
BackgroundColor,
|
||||
selectionStart,
|
||||
selectionEnd,
|
||||
HighlightColor,
|
||||
true);
|
||||
HighlightColor);
|
||||
}
|
||||
|
||||
mp_lexer_free(lex);
|
||||
@@ -361,8 +336,7 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
|
||||
BackgroundColor,
|
||||
nullptr,
|
||||
nullptr,
|
||||
HighlightColor,
|
||||
false);
|
||||
HighlightColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,14 +400,14 @@ bool PythonTextArea::handleEvent(Ion::Events::Event event) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PythonTextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText, bool shouldRemoveLastCharacter) {
|
||||
bool PythonTextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) {
|
||||
if (*text == 0) {
|
||||
return false;
|
||||
}
|
||||
if (m_contentView.isAutocompleting()) {
|
||||
removeAutocompletion();
|
||||
}
|
||||
bool result = TextArea::handleEventWithText(text, indentation, forceCursorRightOfText, shouldRemoveLastCharacter);
|
||||
bool result = TextArea::handleEventWithText(text, indentation, forceCursorRightOfText);
|
||||
addAutocompletion();
|
||||
return result;
|
||||
}
|
||||
@@ -493,10 +467,9 @@ bool PythonTextArea::addAutocompletionTextAtIndex(int nextIndex, int * currentIn
|
||||
|
||||
if (textToInsertLength > 0) {
|
||||
// Try to insert the text (this might fail if the buffer is full)
|
||||
if (!m_contentView.isAbleToInsertTextAt(textToInsertLength, autocompletionLocation, false)) {
|
||||
if (!m_contentView.insertTextAtLocation(textToInsert, const_cast<char *>(autocompletionLocation), textToInsertLength)) {
|
||||
return false;
|
||||
}
|
||||
m_contentView.insertTextAtLocation(textToInsert, const_cast<char *>(autocompletionLocation), textToInsertLength);
|
||||
autocompletionLocation += textToInsertLength;
|
||||
m_contentView.setAutocompleting(true);
|
||||
m_contentView.setAutocompletionEnd(autocompletionLocation);
|
||||
@@ -508,8 +481,7 @@ bool PythonTextArea::addAutocompletionTextAtIndex(int nextIndex, int * currentIn
|
||||
assert(strlen(parentheses) == parenthesesLength);
|
||||
/* If couldInsertText is false, we should not try to add the parentheses as
|
||||
* there was already not enough space to add the autocompletion. */
|
||||
if (addParentheses && m_contentView.isAbleToInsertTextAt(parenthesesLength, autocompletionLocation, false)) {
|
||||
m_contentView.insertTextAtLocation(parentheses, const_cast<char *>(autocompletionLocation), parenthesesLength);
|
||||
if (addParentheses && m_contentView.insertTextAtLocation(parentheses, const_cast<char *>(autocompletionLocation), parenthesesLength)) {
|
||||
m_contentView.setAutocompleting(true);
|
||||
m_contentView.setAutocompletionEnd(autocompletionLocation + parenthesesLength);
|
||||
return true;
|
||||
|
||||
@@ -23,14 +23,14 @@ public:
|
||||
void loadSyntaxHighlighter() { m_contentView.loadSyntaxHighlighter(); }
|
||||
void unloadSyntaxHighlighter() { m_contentView.unloadSyntaxHighlighter(); }
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false, bool shouldRemoveLastCharacter = false) override;
|
||||
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override;
|
||||
/* autocompletionType returns:
|
||||
* - EndOfIdentifier if there is currently autocompletion, or if the cursor is
|
||||
* at the end of an identifier,
|
||||
* - MiddleOfIdentifier is the cursor is in the middle of an identifier,
|
||||
* - No identifier otherwise.
|
||||
* The autocompletionLocation can be provided with autocompletionLocation, or
|
||||
* retrieved with autocompletionLocationBeginning and autocompletionLocationEnd. */
|
||||
* retreived with autocompletionLocationBeginning and autocompletionLocationEnd. */
|
||||
AutocompletionType autocompletionType(const char * autocompletionLocation = nullptr, const char ** autocompletionLocationBeginning = nullptr, const char ** autocompletionLocationEnd = nullptr) const;
|
||||
bool isAutocompleting() const { return m_contentView.isAutocompleting(); }
|
||||
protected:
|
||||
|
||||
@@ -10,22 +10,22 @@ extern "C" {
|
||||
namespace Code {
|
||||
|
||||
const ToolboxMessageTree forLoopChildren[] = {
|
||||
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, true, 2),
|
||||
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, true, 2)
|
||||
ToolboxMessageTree::Leaf(I18n::Message::ForInRange1ArgLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInRange1ArgLoop),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::ForInRange2ArgsLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInRange2ArgsLoop),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::ForInRange3ArgsLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInRange3ArgsLoop),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::ForInListLoopWithArg, I18n::Message::Default, false, I18n::Message::ForInListLoop)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree ifStatementChildren[] = {
|
||||
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, true, 2),
|
||||
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, true, 4),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::IfOrIfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfOrIfElseStatement, true, 4)
|
||||
ToolboxMessageTree::Leaf(I18n::Message::IfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfElseStatement),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::IfThenStatementWithArg, I18n::Message::Default, false, I18n::Message::IfThenStatement),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::IfElifElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfElifElseStatement),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::IfAndIfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfAndIfElseStatement),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::IfOrIfElseStatementWithArg, I18n::Message::Default, false, I18n::Message::IfOrIfElseStatement)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree whileLoopChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::WhileLoopWithArg, I18n::Message::Default, false, I18n::Message::WhileLoop, true, 2)
|
||||
ToolboxMessageTree::Leaf(I18n::Message::WhileLoopWithArg, I18n::Message::Default, false, I18n::Message::WhileLoop)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree conditionsChildren[] = {
|
||||
@@ -75,7 +75,6 @@ const ToolboxMessageTree MathModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandAtan2, I18n::Message::PythonAtan2),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCeil, I18n::Message::PythonCeil),
|
||||
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::PythonCommandFloor, I18n::Message::PythonFloor),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFmod, I18n::Message::PythonFmod),
|
||||
@@ -295,20 +294,9 @@ const ToolboxMessageTree ScipyModuleChildren[] = {
|
||||
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[] = {
|
||||
ToolboxMessageTree::Node(I18n::Message::NumpyModule, NumpyModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::ScipyModule, ScipyModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::UtilsModule, UtilsModuleChildren),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::UlabDocumentation, I18n::Message::UlabDocumentationLink)
|
||||
};
|
||||
|
||||
@@ -338,7 +326,6 @@ const ToolboxMessageTree TurtleModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandHideturtle, I18n::Message::PythonTurtleHideturtle, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColor, I18n::Message::PythonTurtleColor),
|
||||
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::PythonCommandColorRed, I18n::Message::PythonColorRed, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGreen, I18n::Message::PythonColorGreen, false),
|
||||
@@ -378,72 +365,18 @@ const ToolboxMessageTree KandinskyModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillRect, I18n::Message::PythonFillRect),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillCircle, I18n::Message::PythonFillCircle),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillPolygon, I18n::Message::PythonFillPolygon),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetPalette, I18n::Message::PythonGetPalette)
|
||||
};
|
||||
|
||||
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)
|
||||
};
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetKeys, I18n::Message::PythonGetKeys),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetPalette, I18n::Message::PythonGetPalette)};
|
||||
|
||||
const ToolboxMessageTree IonModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportIon, I18n::Message::PythonImportIon, false),
|
||||
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::PythonCommandIsKeyDown, I18n::Message::PythonIsKeyDown),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGetKeys, I18n::Message::PythonGetKeys),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBattery, I18n::Message::PythonBattery),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBatteryLevel, I18n::Message::PythonBatteryLevel),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandBatteryIscharging, I18n::Message::PythonBatteryIscharging),
|
||||
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)
|
||||
ToolboxMessageTree::Leaf(I18n::Message::IonSelector, I18n::Message::IonSelector)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree TimeModuleChildren[] = {
|
||||
@@ -470,7 +403,6 @@ const ToolboxMessageTree OsModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonOsCommandListdir, I18n::Message::PythonOsListdir, false)
|
||||
};
|
||||
|
||||
#if MICROPY_PY_SYS
|
||||
const ToolboxMessageTree SysModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportSys, I18n::Message::PythonImportSys, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromSys, I18n::Message::PythonImportSys, false),
|
||||
@@ -482,7 +414,6 @@ const ToolboxMessageTree SysModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandVersion, I18n::Message::PythonSysVersion, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonSysCommandVersioninfo, I18n::Message::PythonSysVersioninfo, false)
|
||||
};
|
||||
#endif
|
||||
|
||||
const ToolboxMessageTree modulesChildren[] = {
|
||||
ToolboxMessageTree::Node(I18n::Message::MathModule, MathModuleChildren),
|
||||
@@ -496,23 +427,12 @@ const ToolboxMessageTree modulesChildren[] = {
|
||||
ToolboxMessageTree::Node(I18n::Message::KandinskyModule, KandinskyModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::IonModule, IonModuleChildren),
|
||||
ToolboxMessageTree::Node(I18n::Message::OsModule, OsModuleChildren),
|
||||
#if MICROPY_PY_SYS
|
||||
ToolboxMessageTree::Node(I18n::Message::SysModule, SysModuleChildren),
|
||||
#endif
|
||||
ToolboxMessageTree::Node(I18n::Message::TimeModule, TimeModuleChildren)
|
||||
};
|
||||
|
||||
const ToolboxMessageTree catalogChildren[] = {
|
||||
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::PythonCommand1J, I18n::Message::Python1J, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandLF, I18n::Message::PythonLF, false),
|
||||
@@ -543,7 +463,6 @@ const ToolboxMessageTree catalogChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCmathFunction, I18n::Message::PythonCmathFunction, false, I18n::Message::PythonCommandCmathFunctionWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColor, I18n::Message::PythonColor),
|
||||
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::PythonCommandCopySign, I18n::Message::PythonCopySign),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCos, I18n::Message::PythonCos),
|
||||
@@ -705,10 +624,10 @@ const ToolboxMessageTree fileChildren[] {
|
||||
};
|
||||
|
||||
const ToolboxMessageTree exceptionsChildren[] = {
|
||||
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, true, 6),
|
||||
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, true, 2),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::TryExcept1ErrorWithArg, I18n::Message::Default, false, I18n::Message::TryExcept1Error),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::TryExcept1ErrorElseWithArg, I18n::Message::Default, false, I18n::Message::TryExcept1ErrorElse),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::TryExcept2ErrorWithArg, I18n::Message::Default, false, I18n::Message::TryExcept2Error),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::WithInstructionWithArg, I18n::Message::Default, false, I18n::Message::WithInstruction),
|
||||
};
|
||||
|
||||
const ToolboxMessageTree menu[] = {
|
||||
@@ -726,10 +645,6 @@ const ToolboxMessageTree toolboxModel = ToolboxMessageTree::Node(I18n::Message::
|
||||
PythonToolbox::PythonToolbox() :
|
||||
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 {
|
||||
@@ -760,28 +675,36 @@ bool PythonToolbox::handleEvent(Ion::Events::Event event) {
|
||||
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) {
|
||||
const ToolboxMessageTree * messageTree = static_cast<const ToolboxMessageTree *>(m_messageTreeModel->childAtIndex(j));
|
||||
if (messageTree->isMultiLine()) {
|
||||
return k_fontForMultiLine->glyphSize().height() * messageTree->numberOfLines() + 2*Metric::TableCellVerticalMargin + (messageTree->text() == I18n::Message::Default ? 0 : Toolbox::rowHeight(j));
|
||||
if (typeAtLocation(0, j) == Toolbox::LeafCellType && (m_messageTreeModel->label() == I18n::Message::IfStatementMenu || m_messageTreeModel->label() == I18n::Message::Exceptions)) {
|
||||
/* To get the exact height needed for each cell, we have to compute its
|
||||
* text size, which means scan the text char by char to look for '\n'
|
||||
* 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);
|
||||
}
|
||||
|
||||
bool PythonToolbox::selectLeaf(int selectedRow, bool quitToolbox) {
|
||||
bool PythonToolbox::selectLeaf(int selectedRow) {
|
||||
ToolboxMessageTree * node = (ToolboxMessageTree *)m_messageTreeModel->childAtIndex(selectedRow);
|
||||
#if defined(INCLUDE_ULAB)
|
||||
if(node->text() == I18n::Message::UlabDocumentationLink){
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
m_selectableTableView.deselectTable();
|
||||
if(node->insertedText() == I18n::Message::IonSelector){
|
||||
m_ionKeys.setSender(sender());
|
||||
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());
|
||||
// strippedEditedText array needs to be in the same scope as editedText
|
||||
char strippedEditedText[k_maxMessageSize];
|
||||
@@ -792,35 +715,20 @@ bool PythonToolbox::selectLeaf(int selectedRow, bool quitToolbox) {
|
||||
editedText = strippedEditedText;
|
||||
}
|
||||
sender()->handleEventWithText(editedText, true);
|
||||
if (quitToolbox) {
|
||||
m_selectableTableView.deselectTable();
|
||||
Container::activeApp()->dismissModalViewController();
|
||||
}
|
||||
Container::activeApp()->dismissModalViewController();
|
||||
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 {
|
||||
return &toolboxModel;
|
||||
}
|
||||
|
||||
MessageTableCellWithMessage<SlideableMessageTextView> * PythonToolbox::leafCellAtIndex(int index) {
|
||||
MessageTableCellWithMessage * PythonToolbox::leafCellAtIndex(int index) {
|
||||
assert(index >= 0 && index < k_maxNumberOfDisplayedRows);
|
||||
return &m_leafCells[index];
|
||||
}
|
||||
|
||||
MessageTableCellWithChevron<SlideableMessageTextView> * PythonToolbox::nodeCellAtIndex(int index) {
|
||||
MessageTableCellWithChevron* PythonToolbox::nodeCellAtIndex(int index) {
|
||||
assert(index >= 0 && index < k_maxNumberOfDisplayedRows);
|
||||
return &m_nodeCells[index];
|
||||
}
|
||||
|
||||
@@ -18,28 +18,22 @@ public:
|
||||
// Toolbox
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
const ToolboxMessageTree * rootModel() const override;
|
||||
|
||||
// ListViewDataSource
|
||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||
|
||||
protected:
|
||||
KDCoordinate rowHeight(int j) override;
|
||||
bool selectLeaf(int selectedRow, bool quitToolbox) override;
|
||||
bool selectSubMenu(int selectedRow) override;
|
||||
MessageTableCellWithMessage<SlideableMessageTextView> * leafCellAtIndex(int index) override;
|
||||
MessageTableCellWithChevron<SlideableMessageTextView> * nodeCellAtIndex(int index) override;
|
||||
bool selectLeaf(int selectedRow) override;
|
||||
MessageTableCellWithMessage * leafCellAtIndex(int index) override;
|
||||
MessageTableCellWithChevron* nodeCellAtIndex(int index) override;
|
||||
int maxNumberOfDisplayedRows() override;
|
||||
bool canStayInMenu() override { return true; }
|
||||
constexpr static int k_maxNumberOfDisplayedRows = 13; // = 240/(13+2*3)
|
||||
// 13 = minimal string height size
|
||||
// 3 = vertical margins
|
||||
private:
|
||||
constexpr static const KDFont * k_fontForMultiLine = KDFont::SmallFont;
|
||||
constexpr static const KDFont * k_font = KDFont::SmallFont;
|
||||
void scrollToLetter(char letter);
|
||||
void scrollToAndSelectChild(int i);
|
||||
MessageTableCellWithMessage<SlideableMessageTextView> m_leafCells[k_maxNumberOfDisplayedRows];
|
||||
MessageTableCellWithChevron<SlideableMessageTextView> m_nodeCells[k_maxNumberOfDisplayedRows];
|
||||
ToolboxIonKeys m_ionKeys;
|
||||
MessageTableCellWithMessage m_leafCells[k_maxNumberOfDisplayedRows];
|
||||
MessageTableCellWithChevron m_nodeCells[k_maxNumberOfDisplayedRows];
|
||||
toolboxIonKeys m_ionKeys;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -34,11 +34,11 @@ private:
|
||||
constexpr static int k_totalNumberOfCell = 6;
|
||||
StackViewController * stackViewController();
|
||||
I18n::Message m_pageTitle;
|
||||
MessageTableCell<> m_executeScript;
|
||||
MessageTableCell<> m_renameScript;
|
||||
MessageTableCell m_executeScript;
|
||||
MessageTableCell m_renameScript;
|
||||
MessageTableCellWithSwitch m_autoImportScript;
|
||||
MessageTableCell<> m_deleteScript;
|
||||
MessageTableCell<> m_duplicateScript;
|
||||
MessageTableCell m_deleteScript;
|
||||
MessageTableCell m_duplicateScript;
|
||||
MessageTableCellWithBuffer m_size;
|
||||
void GetScriptSize(MessageTableCellWithBuffer* myCell);
|
||||
SelectableTableView m_selectableTableView;
|
||||
|
||||
@@ -49,7 +49,7 @@ private:
|
||||
* k_fullFreeSpaceSizeLimit, we consider the script store as full.
|
||||
* 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
|
||||
* importation status (1 char), the cursor (2 char), the default content "from math import *\n"
|
||||
* importation status (1 char), the default content "from math import *\n"
|
||||
* (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;
|
||||
};
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
#include "../toolbox_ion_keys.h"
|
||||
|
||||
namespace Code {
|
||||
ToolboxIonKeys::ToolboxIonKeys() :
|
||||
toolboxIonKeys::toolboxIonKeys() :
|
||||
ViewController(nullptr),
|
||||
m_view()
|
||||
{
|
||||
}
|
||||
|
||||
bool ToolboxIonKeys::handleEvent(Ion::Events::Event e) {
|
||||
bool toolboxIonKeys::handleEvent(Ion::Events::Event e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ToolboxIonKeys::toolboxIonView::toolboxIonView():
|
||||
toolboxIonKeys::toolboxIonView::toolboxIonView():
|
||||
View()
|
||||
{
|
||||
}
|
||||
|
||||
void ToolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
void toolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
return;
|
||||
}
|
||||
|
||||
View * ToolboxIonKeys::view(){
|
||||
View * toolboxIonKeys::view(){
|
||||
return &m_view;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ void assert_variables_are(const char * script, const char * nameToComplete, cons
|
||||
&addParentheses,
|
||||
i,
|
||||
&index);
|
||||
quiz_assert(i == index); // If false, the autocompletion has cycled: there are not as many results as expected
|
||||
quiz_assert(i == index); // If false, the autompletion has cycled: there are not as many results as expected
|
||||
quiz_assert(strncmp(*(expectedVariables + i), autocompletionI - nameToCompleteLength, textToInsertLength + nameToCompleteLength) == 0);
|
||||
index++;
|
||||
}
|
||||
@@ -63,7 +63,7 @@ QUIZ_CASE(variable_box_controller) {
|
||||
};
|
||||
// FIXME This test does not load imported variables for now
|
||||
assert_variables_are(
|
||||
"\x01\x01\x01 from math import *\nfroo=3",
|
||||
"\x01 from math import *\nfroo=3",
|
||||
"fr",
|
||||
expectedVariables,
|
||||
sizeof(expectedVariables) / sizeof(const char *));
|
||||
|
||||
@@ -5,6 +5,3 @@ LoopsAndTests = "Schleifen und Tests"
|
||||
Files = "Dateien"
|
||||
Exceptions = "Ausnahmen"
|
||||
UlabDocumentation = "Dokumentation"
|
||||
IonSelector = "Schlüsselauswahl"
|
||||
PressAKey = "drücke eine Taste"
|
||||
IonKeyList = "Liste der Schlüssel"
|
||||
|
||||
@@ -5,6 +5,3 @@ LoopsAndTests = "Loops and tests"
|
||||
Files = "Files"
|
||||
Exceptions = "Exceptions"
|
||||
UlabDocumentation = "Documentation"
|
||||
IonSelector = "Key selector"
|
||||
PressAKey = "Press a key"
|
||||
IonKeyList = "List of keys"
|
||||
|
||||
@@ -5,6 +5,3 @@ LoopsAndTests = "Loops and tests"
|
||||
Files = "Files"
|
||||
Exceptions = "Exceptions"
|
||||
UlabDocumentation = "Documentación"
|
||||
IonSelector = "Selector de llave"
|
||||
PressAKey = "presione una tecla"
|
||||
IonKeyList = "Lista de llaves"
|
||||
|
||||
@@ -5,6 +5,3 @@ LoopsAndTests = "Boucles et tests"
|
||||
Files = "Fichiers"
|
||||
Exceptions = "Exceptions"
|
||||
UlabDocumentation = "Documentation"
|
||||
IonSelector = "Sélecteur de touche"
|
||||
PressAKey = "Appuyez sur une touche"
|
||||
IonKeyList = "Liste des touches"
|
||||
|
||||
@@ -5,6 +5,3 @@ LoopsAndTests = "Hurkok és tesztek"
|
||||
Files = "Fájlok"
|
||||
Exceptions = "Kivételek"
|
||||
UlabDocumentation = "Dokumentáció"
|
||||
IonSelector = "Kulcsválasztó"
|
||||
PressAKey = "Nyomj meg egy gombot"
|
||||
IonKeyList = "A kulcsok listája"
|
||||
|
||||
@@ -2,9 +2,6 @@ Functions = "Funzioni"
|
||||
Catalog = "Catalogo"
|
||||
Modules = "Moduli"
|
||||
LoopsAndTests = "Cicli e test"
|
||||
Files = "File"
|
||||
Exceptions = "Eccezioni"
|
||||
Files = "Files"
|
||||
Exceptions = "Exceptions"
|
||||
UlabDocumentation = "Documentazione"
|
||||
IonSelector = "Selettore tasti"
|
||||
PressAKey = "Premi un tasto"
|
||||
IonKeyList = "Elenco dei tasti"
|
||||
|
||||
@@ -5,6 +5,3 @@ LoopsAndTests = "Herhalingen en testen"
|
||||
Files = "Files"
|
||||
Exceptions = "Exceptions"
|
||||
UlabDocumentation = "Documentatie"
|
||||
IonSelector = "Toetsenkiezer"
|
||||
PressAKey = "druk op een knop"
|
||||
IonKeyList = "Lijst met sleutels"
|
||||
|
||||
@@ -5,6 +5,3 @@ LoopsAndTests = "Laços e testes"
|
||||
Files = "Files"
|
||||
Exceptions = "Exceptions"
|
||||
UlabDocumentation = "Documentação"
|
||||
IonSelector = "Seletor de chave"
|
||||
PressAKey = "Pressione uma tecla"
|
||||
IonKeyList = "Lista de chaves"
|
||||
|
||||
@@ -12,7 +12,6 @@ ScipyOptimizeModule = "optimize"
|
||||
ScipySignalModule = "signal"
|
||||
ScipySpecialModule = "special"
|
||||
NumpyNdarray = "ndarray"
|
||||
UtilsModule = "utils"
|
||||
OsModule = "os"
|
||||
SysModule = "sys"
|
||||
TimeModule = "time"
|
||||
@@ -69,4 +68,6 @@ PythonCommandDef = "def \x11():\n "
|
||||
PythonCommandDefWithArg = "def function(x):"
|
||||
PythonCommandReturn = "return "
|
||||
RandomModule = "random"
|
||||
IonSelector = "Key selector"
|
||||
PressAKey = "Press a key"
|
||||
UlabDocumentationLink = "micropython-ulab.readthedocs.io"
|
||||
|
||||
@@ -6,52 +6,45 @@ extern "C" {
|
||||
#include <py/obj.h>
|
||||
#include <py/objfun.h>
|
||||
}
|
||||
extern "C" const mp_rom_map_elem_t modion_module_globals_table[55];
|
||||
extern const mp_rom_map_elem_t modion_module_globals_table[48];
|
||||
|
||||
namespace Code {
|
||||
ToolboxIonKeys::ToolboxIonKeys() :
|
||||
toolboxIonKeys::toolboxIonKeys() :
|
||||
ViewController(nullptr),
|
||||
m_view()
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
bool ToolboxIonKeys::handleEvent(Ion::Events::Event e) {
|
||||
// FIXME: Use event data to get the pressed key and fix the EXE key.
|
||||
Ion::Keyboard::State state = Ion::Keyboard::scan();
|
||||
for (uint16_t i = 0; i < sizeof(modion_module_globals_table) / sizeof(_mp_rom_map_elem_t); i++) {
|
||||
_mp_rom_map_elem_t element = modion_module_globals_table[i];
|
||||
if (mp_obj_is_small_int(element.value)) {
|
||||
int key = mp_obj_get_int(element.value);
|
||||
if (state.keyDown(static_cast<Ion::Keyboard::Key>(key))) {
|
||||
m_sender->handleEventWithText(qstr_str(MP_OBJ_QSTR_VALUE(element.key)), true);
|
||||
bool toolboxIonKeys::handleEvent(Ion::Events::Event e) {
|
||||
Ion::Keyboard::State state = Ion::Keyboard::scan();
|
||||
for(uint16_t i = 0; i < sizeof(modion_module_globals_table)/sizeof(_mp_rom_map_elem_t); i++){
|
||||
_mp_rom_map_elem_t element = modion_module_globals_table[i];
|
||||
if(mp_obj_is_small_int(element.value)){
|
||||
int key = mp_obj_get_int(element.value);
|
||||
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() :
|
||||
View()
|
||||
{
|
||||
}
|
||||
toolboxIonKeys::toolboxIonView::toolboxIonView():
|
||||
View()
|
||||
{
|
||||
}
|
||||
|
||||
void ToolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
ctx->fillRect(rect, Palette::WallScreen);
|
||||
ctx->strokeRect(rect, Palette::ListCellBorder);
|
||||
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);
|
||||
void toolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
ctx->fillRect(rect, Palette::WallScreen);
|
||||
ctx->strokeRect(rect, Palette::ListCellBorder);
|
||||
ctx->drawString(I18n::translate(I18n::Message::PressAKey),KDPoint(rect.left()+80, rect.top()+20),KDFont::LargeFont,Palette::PrimaryText,Palette::WallScreen);
|
||||
|
||||
}
|
||||
|
||||
ctx->drawString(message, textPosition, KDFont::LargeFont, Palette::PrimaryText, Palette::WallScreen);
|
||||
|
||||
}
|
||||
|
||||
View * ToolboxIonKeys::view() {
|
||||
return &m_view;
|
||||
}
|
||||
View * toolboxIonKeys::view(){
|
||||
return &m_view;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace Code {
|
||||
|
||||
class ToolboxIonKeys : public ViewController {
|
||||
class toolboxIonKeys : public ViewController {
|
||||
public :
|
||||
ToolboxIonKeys();
|
||||
toolboxIonKeys();
|
||||
View * view() override;
|
||||
bool handleEvent(Ion::Events::Event e) override;
|
||||
void setSender(InputEventHandler * sender) { m_sender = sender; }
|
||||
|
||||
@@ -128,7 +128,7 @@ void VariableBoxController::willDisplayCellForIndex(HighlightCell * cell, int in
|
||||
I18n::Message::BuiltinsAndKeywords,
|
||||
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) {
|
||||
@@ -365,7 +365,7 @@ int VariableBoxController::typeAndOriginAtLocation(int i, NodeOrigin * resultOri
|
||||
|
||||
}
|
||||
|
||||
bool VariableBoxController::selectLeaf(int rowIndex, bool quitToolbox) {
|
||||
bool VariableBoxController::selectLeaf(int rowIndex) {
|
||||
assert(rowIndex >= 0 && rowIndex < numberOfRows());
|
||||
m_selectableTableView.deselectTable();
|
||||
|
||||
@@ -516,7 +516,7 @@ void VariableBoxController::loadBuiltinNodes(const char * textToAutocomplete, in
|
||||
assert(sizeof(builtinNames) / sizeof(builtinNames[0]) == k_totalBuiltinNodesCount);
|
||||
for (int i = 0; i < k_totalBuiltinNodesCount; i++) {
|
||||
if (addNodeIfMatches(textToAutocomplete, textToAutocompleteLength, builtinNames[i].type, NodeOrigin::Builtins, builtinNames[i].name)) {
|
||||
/* We can leverage on the fact that builtin nodes are stored in
|
||||
/* We can leverage on the fact that buitin nodes are stored in
|
||||
* alphabetical order. */
|
||||
return;
|
||||
}
|
||||
@@ -575,7 +575,7 @@ void VariableBoxController::loadImportedVariablesInScript(const char * scriptCon
|
||||
}
|
||||
|
||||
void VariableBoxController::loadCurrentVariablesInScript(const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength) {
|
||||
/* To find variable and function names: we lex the script and keep all
|
||||
/* To find variable and funtion names: we lex the script and keep all
|
||||
* MP_TOKEN_NAME that complete the text to autocomplete and are not already in
|
||||
* 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
|
||||
* will not have main structures of the wanted type.
|
||||
* We look for structures at first level (not inside nested scopes) that
|
||||
* are either function definitions, variables statements or imports. */
|
||||
* are either dunction definitions, variables statements or imports. */
|
||||
size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
mp_parse_node_t child = pns->nodes[i];
|
||||
@@ -823,18 +823,18 @@ bool VariableBoxController::importationSourceIsModule(const char * sourceName, c
|
||||
return true;
|
||||
}
|
||||
// The sourceName might be a module that is not in the toolbox
|
||||
return mp_module_get_loaded_or_builtin(qstr_from_str(sourceName)) != MP_OBJ_NULL;
|
||||
return mp_module_get(qstr_from_str(sourceName)) != MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
bool VariableBoxController::importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retrievedScript) {
|
||||
bool VariableBoxController::importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retreivedScript) {
|
||||
// Try fetching the nodes from a script
|
||||
Script importedScript = ScriptStore::ScriptBaseNamed(sourceName);
|
||||
if (importedScript.isNull()) {
|
||||
return false;
|
||||
}
|
||||
*scriptFullName = importedScript.fullName();
|
||||
if (retrievedScript != nullptr) {
|
||||
*retrievedScript = importedScript;
|
||||
if (retreivedScript != nullptr) {
|
||||
*retreivedScript = importedScript;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ private:
|
||||
// NestedMenuController
|
||||
HighlightCell * leafCellAtIndex(int index) override { assert(false); return nullptr; }
|
||||
HighlightCell * nodeCellAtIndex(int index) override { assert(false); return nullptr; }
|
||||
bool selectLeaf(int rowIndex, bool quitToolbox) override;
|
||||
bool selectLeaf(int rowIndex) override;
|
||||
void insertTextInCaller(const char * text, int textLength = -1);
|
||||
|
||||
// Loading
|
||||
@@ -92,7 +92,7 @@ private:
|
||||
bool addNodesFromImportMaybe(mp_parse_node_struct_t * parseNode, const char * textToAutocomplete, int textToAutocompleteLength, bool importFromModules = true);
|
||||
const char * importationSourceNameFromNode(mp_parse_node_t & node);
|
||||
bool importationSourceIsModule(const char * sourceName, const ToolboxMessageTree * * moduleChildren = nullptr, int * numberOfModuleChildren = nullptr);
|
||||
bool importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retrievedScript = nullptr);
|
||||
bool importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retreivedScript = nullptr);
|
||||
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
|
||||
* already contained in the variable box. The returned boolean means we
|
||||
@@ -104,7 +104,7 @@ private:
|
||||
ScriptNode m_builtinNodes[k_totalBuiltinNodesCount];
|
||||
ScriptNode m_importedNodes[k_maxScriptNodesCount];
|
||||
ScriptNodeCell m_itemCells[k_maxNumberOfDisplayedItems];
|
||||
MessageTableCell<> m_subtitleCells[k_scriptOriginsCount];
|
||||
MessageTableCell m_subtitleCells[k_scriptOriginsCount];
|
||||
ScriptStore * m_scriptStore;
|
||||
size_t m_currentScriptNodesCount;
|
||||
size_t m_builtinNodesCount;
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#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
2
apps/external/app.h
vendored
@@ -29,7 +29,7 @@ private:
|
||||
MainController m_mainController;
|
||||
StackViewController m_stackViewController;
|
||||
Window * m_window;
|
||||
static constexpr int k_externalHeapSize = 99000;
|
||||
static constexpr int k_externalHeapSize = 100000;
|
||||
char m_externalHeap[k_externalHeapSize];
|
||||
};
|
||||
|
||||
|
||||
9
apps/external/app/sample.c
vendored
9
apps/external/app/sample.c
vendored
@@ -1,15 +1,6 @@
|
||||
#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() {
|
||||
extapp_pushRectUniform(10, 10, LCD_WIDTH-20, LCD_HEIGHT-20, 0);
|
||||
extapp_msleep(1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
94
apps/external/archive.cpp
vendored
94
apps/external/archive.cpp
vendored
@@ -40,10 +40,9 @@ bool isExamModeAndFileNotExecutable(const TarHeader* tar) {
|
||||
}
|
||||
|
||||
bool fileAtIndex(size_t index, File &entry) {
|
||||
if (index == -1) {
|
||||
if (index == -1)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const TarHeader* tar = reinterpret_cast<const TarHeader*>(0x90200000);
|
||||
unsigned size = 0;
|
||||
|
||||
@@ -75,8 +74,6 @@ bool fileAtIndex(size_t index, File &entry) {
|
||||
entry.data = reinterpret_cast<const uint8_t*>(tar) + sizeof(TarHeader);
|
||||
entry.dataLength = size;
|
||||
entry.isExecutable = (tar->mode[4] & 0x01) == 1;
|
||||
// TODO: Handle the trash
|
||||
entry.readable = true;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
@@ -114,31 +111,18 @@ uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int indexFromName(const char *name) {
|
||||
File entry;
|
||||
|
||||
#else
|
||||
|
||||
bool fileAtIndex(size_t index, File &entry) {
|
||||
if (index != 0) {
|
||||
return false;
|
||||
for (int i = 0; fileAtIndex(i, entry); i++) {
|
||||
if (strcmp(name, entry.name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
entry.name = "Built-in";
|
||||
entry.data = NULL;
|
||||
entry.dataLength = 0;
|
||||
entry.isExecutable = true;
|
||||
entry.readable = true;
|
||||
return true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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() {
|
||||
File dummy;
|
||||
size_t count;
|
||||
@@ -148,18 +132,6 @@ size_t numberOfFiles() {
|
||||
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) {
|
||||
File dummy;
|
||||
size_t count;
|
||||
@@ -172,19 +144,16 @@ bool executableAtIndex(size_t index, File &entry) {
|
||||
entry.data = dummy.data;
|
||||
entry.dataLength = dummy.dataLength;
|
||||
entry.isExecutable = dummy.isExecutable;
|
||||
entry.readable = dummy.readable;
|
||||
return true;
|
||||
}
|
||||
final_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t numberOfExecutables() {
|
||||
if (!GlobalPreferences::sharedGlobalPreferences()->externalAppShown()) {
|
||||
return false;
|
||||
}
|
||||
File dummy;
|
||||
size_t count;
|
||||
size_t final_count = 0;
|
||||
@@ -196,5 +165,48 @@ size_t numberOfExecutables() {
|
||||
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
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
1
apps/external/archive.h
vendored
1
apps/external/archive.h
vendored
@@ -14,7 +14,6 @@ struct File {
|
||||
const uint8_t *data;
|
||||
size_t dataLength;
|
||||
bool isExecutable;
|
||||
bool readable;
|
||||
};
|
||||
|
||||
bool fileAtIndex(size_t index, File &entry);
|
||||
|
||||
18
apps/external/base.it.i18n
vendored
18
apps/external/base.it.i18n
vendored
@@ -1,9 +1,9 @@
|
||||
ExternalApp = "Esterna"
|
||||
ExternalAppCapital = "ESTERNA"
|
||||
ExternalAppApiMismatch = "Discordanza di API"
|
||||
ExternalAppExecError = "Impossibile eseguire file"
|
||||
ExternalNotCompatible = "Esterna non compatibile"
|
||||
WithSimulator = "con il simulatore"
|
||||
WithN0100 = "con n0100"
|
||||
GetMoreAppsAt = "Ottieni altre app a"
|
||||
NoAppsInstalled = "Nessuna app installata"
|
||||
ExternalApp = "External"
|
||||
ExternalAppCapital = "EXTERNAL"
|
||||
ExternalAppApiMismatch = "API mismatch"
|
||||
ExternalAppExecError = "Cannot execute file"
|
||||
ExternalNotCompatible = "External is not compatible"
|
||||
WithSimulator = "with the simulator"
|
||||
WithN0100 = "with n0100"
|
||||
GetMoreAppsAt = "Get more apps at"
|
||||
NoAppsInstalled = "No apps installed"
|
||||
|
||||
221
apps/external/extapp_api.cpp
vendored
221
apps/external/extapp_api.cpp
vendored
@@ -9,16 +9,10 @@
|
||||
#include "../apps_container.h"
|
||||
#include "../global_preferences.h"
|
||||
|
||||
#ifdef DEVICE
|
||||
#include <ion/src/device/shared/drivers/reset.h>
|
||||
#include <ion/src/device/shared/drivers/board.h>
|
||||
#include <ion/src/device/shared/drivers/flash.h>
|
||||
#endif
|
||||
|
||||
#include <python/port/port.h>
|
||||
|
||||
extern "C" {
|
||||
#include <python/port/mphalport.h>
|
||||
#include <python/port/mphalport.h>
|
||||
}
|
||||
|
||||
uint64_t extapp_millis() {
|
||||
@@ -36,34 +30,22 @@ uint64_t extapp_scanKeyboard() {
|
||||
void extapp_pushRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t * pixels) {
|
||||
KDRect rect(x, y, w, h);
|
||||
|
||||
Ion::Display::pushRect(rect, reinterpret_cast<const KDColor *>(pixels));
|
||||
#ifndef DEVICE
|
||||
// Refresh the display.
|
||||
Ion::Keyboard::scan();
|
||||
#endif
|
||||
Ion::Display::pushRect(rect, reinterpret_cast<const KDColor*>(pixels));
|
||||
}
|
||||
|
||||
void extapp_pushRectUniform(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color) {
|
||||
KDRect rect(x, y, w, h);
|
||||
|
||||
Ion::Display::pushRectUniform(rect, KDColor::RGB16(color));
|
||||
#ifndef DEVICE
|
||||
// Refresh the display.
|
||||
Ion::Keyboard::scan();
|
||||
#endif
|
||||
}
|
||||
|
||||
void extapp_pullRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t * pixels) {
|
||||
KDRect rect(x, y, w, h);
|
||||
|
||||
Ion::Display::pullRect(rect, (KDColor *)pixels);
|
||||
#ifndef DEVICE
|
||||
// Refresh the display.
|
||||
Ion::Keyboard::scan();
|
||||
#endif
|
||||
Ion::Display::pullRect(rect, (KDColor *) pixels);
|
||||
}
|
||||
|
||||
int16_t extapp_drawTextLarge(const char * text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake) {
|
||||
int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake) {
|
||||
KDPoint point(x, y);
|
||||
|
||||
auto ctx = KDIonContext::sharedContext();
|
||||
@@ -71,15 +53,10 @@ int16_t extapp_drawTextLarge(const char * text, int16_t x, int16_t y, uint16_t f
|
||||
ctx->setOrigin(KDPoint(0, 0));
|
||||
point = ctx->drawString(text, point, KDFont::LargeFont, KDColor::RGB16(fg), KDColor::RGB16(bg));
|
||||
|
||||
#ifndef DEVICE
|
||||
// Refresh the display.
|
||||
Ion::Keyboard::scan();
|
||||
#endif
|
||||
|
||||
return point.x();
|
||||
}
|
||||
|
||||
int16_t extapp_drawTextSmall(const char * text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake) {
|
||||
int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake) {
|
||||
KDPoint point(x, y);
|
||||
|
||||
auto ctx = KDIonContext::sharedContext();
|
||||
@@ -87,11 +64,6 @@ int16_t extapp_drawTextSmall(const char * text, int16_t x, int16_t y, uint16_t f
|
||||
ctx->setOrigin(KDPoint(0, 0));
|
||||
point = ctx->drawString(text, point, KDFont::SmallFont, KDColor::RGB16(fg), KDColor::RGB16(bg));
|
||||
|
||||
#ifndef DEVICE
|
||||
// Refresh the display.
|
||||
Ion::Keyboard::scan();
|
||||
#endif
|
||||
|
||||
return point.x();
|
||||
}
|
||||
|
||||
@@ -99,7 +71,7 @@ bool extapp_waitForVBlank() {
|
||||
return Ion::Display::waitForVBlank();
|
||||
}
|
||||
|
||||
void extapp_clipboardStore(const char * text) {
|
||||
void extapp_clipboardStore(const char *text) {
|
||||
Clipboard::sharedClipboard()->store(text);
|
||||
}
|
||||
|
||||
@@ -107,103 +79,101 @@ const char * extapp_clipboardText() {
|
||||
return Clipboard::sharedClipboard()->storedText();
|
||||
}
|
||||
|
||||
bool match(const char * filename, const char * extension) {
|
||||
return strcmp(filename + strlen(filename) - strlen(extension), extension) == 0;
|
||||
}
|
||||
|
||||
int extapp_fileListWithExtension(const char ** filenames, int maxrecords, const char * extension, int storage) {
|
||||
int j = 0;
|
||||
if (storage == EXTAPP_RAM_FILE_SYSTEM || storage == EXTAPP_BOTH_FILE_SYSTEM) {
|
||||
if(storage == EXTAPP_RAM_FILE_SYSTEM) {
|
||||
int n = Ion::Storage::sharedStorage()->numberOfRecordsWithExtension(extension);
|
||||
if (n > maxrecords) {
|
||||
n = maxrecords;
|
||||
}
|
||||
for (; j < n; j++) {
|
||||
filenames[j] = Ion::Storage::sharedStorage()->recordWithExtensionAtIndex(extension, j).fullName();
|
||||
for(int i = 0; i < n; i++) {
|
||||
filenames[i] = Ion::Storage::sharedStorage()->recordWithExtensionAtIndex(extension, i).fullName();
|
||||
}
|
||||
if (j == maxrecords) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
// Don't read external files the exam mode is enabled
|
||||
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) return j;
|
||||
if (storage == EXTAPP_FLASH_FILE_SYSTEM || storage == EXTAPP_BOTH_FILE_SYSTEM) {
|
||||
return n;
|
||||
} else if(storage == EXTAPP_FLASH_FILE_SYSTEM) {
|
||||
// TODO: filter by extension
|
||||
int n = External::Archive::numberOfFiles();
|
||||
for (int i = 0; i < n && j < maxrecords; i++) {
|
||||
External::Archive::File entry;
|
||||
// Filter extension
|
||||
if (External::Archive::fileAtIndex(i, entry) && match(entry.name, extension)) {
|
||||
filenames[j] = entry.name;
|
||||
++j;
|
||||
}
|
||||
if (n > maxrecords) {
|
||||
n = maxrecords;
|
||||
}
|
||||
for(int i = 0; i < n; i++) {
|
||||
External::Archive::File entry;
|
||||
External::Archive::fileAtIndex(i, entry);
|
||||
filenames[i] = entry.name;
|
||||
}
|
||||
return n;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
bool extapp_fileExists(const char * filename, int storage) {
|
||||
if (storage == EXTAPP_RAM_FILE_SYSTEM || storage == EXTAPP_BOTH_FILE_SYSTEM) {
|
||||
if (!Ion::Storage::sharedStorage()->recordNamed(filename).isNull())
|
||||
return true;
|
||||
}
|
||||
if (storage == EXTAPP_FLASH_FILE_SYSTEM || storage == EXTAPP_BOTH_FILE_SYSTEM) {
|
||||
if(storage == EXTAPP_RAM_FILE_SYSTEM) {
|
||||
return !Ion::Storage::sharedStorage()->recordNamed(filename).isNull();
|
||||
} else if(storage == EXTAPP_FLASH_FILE_SYSTEM) {
|
||||
return External::Archive::indexFromName(filename) >= 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool extapp_fileErase(const char * filename, int storage) {
|
||||
if (storage == EXTAPP_RAM_FILE_SYSTEM) {
|
||||
if(storage == EXTAPP_RAM_FILE_SYSTEM) {
|
||||
Ion::Storage::Record record = Ion::Storage::sharedStorage()->recordNamed(filename);
|
||||
if (record.isNull()) {
|
||||
if(record.isNull()) {
|
||||
return false;
|
||||
} else {
|
||||
record.destroy();
|
||||
return true;
|
||||
}
|
||||
record.destroy();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char * extapp_fileRead(const char * filename, size_t * len, int storage) {
|
||||
if (storage == EXTAPP_RAM_FILE_SYSTEM || storage == EXTAPP_BOTH_FILE_SYSTEM) {
|
||||
const char * extapp_fileRead(const char * filename, size_t *len, int storage) {
|
||||
if(storage == EXTAPP_RAM_FILE_SYSTEM) {
|
||||
const Ion::Storage::Record record = Ion::Storage::sharedStorage()->recordNamed(filename);
|
||||
if (!record.isNull()){
|
||||
int delta = 0;
|
||||
if (match(filename, ".py") || match(filename, ".xw"))
|
||||
delta++;
|
||||
// skip record type
|
||||
if (len)
|
||||
*len = record.value().size - delta;
|
||||
return (const char *)record.value().buffer + delta;
|
||||
if (record.isNull()) {
|
||||
return NULL;
|
||||
} else {
|
||||
if(len) {
|
||||
*len = record.value().size;
|
||||
}
|
||||
return (const char *) record.value().buffer;
|
||||
}
|
||||
}
|
||||
if (storage == EXTAPP_FLASH_FILE_SYSTEM || storage == EXTAPP_BOTH_FILE_SYSTEM) {
|
||||
} else if(storage == EXTAPP_FLASH_FILE_SYSTEM) {
|
||||
int index = External::Archive::indexFromName(filename);
|
||||
if (index >= 0) {
|
||||
External::Archive::File entry;
|
||||
External::Archive::fileAtIndex(index, entry);
|
||||
if (len) {
|
||||
if(len) {
|
||||
*len = entry.dataLength;
|
||||
}
|
||||
return (const char *)entry.data;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool extapp_fileWrite(const char * filename, const char * content, size_t len, int storage) {
|
||||
if (storage == EXTAPP_RAM_FILE_SYSTEM) {
|
||||
if(storage == EXTAPP_RAM_FILE_SYSTEM) {
|
||||
Ion::Storage::Record::ErrorStatus status = Ion::Storage::sharedStorage()->createRecordWithFullName(filename, content, len);
|
||||
if (status == Ion::Storage::Record::ErrorStatus::NameTaken) {
|
||||
Ion::Storage::Record::Data data;
|
||||
data.buffer = content;
|
||||
data.size = len;
|
||||
return Ion::Storage::sharedStorage()->recordNamed(filename).setValue(data) == Ion::Storage::Record::ErrorStatus::None;
|
||||
}
|
||||
if (status == Ion::Storage::Record::ErrorStatus::None)
|
||||
} else if (status == Ion::Storage::Record::ErrorStatus::None) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void reloadTitleBar() {
|
||||
@@ -274,42 +244,19 @@ const int16_t translated_keys[] =
|
||||
#define TICKS_PER_MINUTE 11862
|
||||
#endif
|
||||
|
||||
|
||||
int extapp_restoreBackup(int mode) {
|
||||
// Restoring the backup is allowed even if the write protection is enabled, because it may have been writted by Khi.x
|
||||
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode())
|
||||
return 0;
|
||||
size_t length = 32 * 1024;
|
||||
if (mode == -1) { // restore backup saved when exam mode was set
|
||||
uint8_t * src = (uint8_t *)(0x90800000 - 2 * length);
|
||||
if (src[0] == 0xba && src[1] == 0xdd && src[2] == 0x0b && src[3] == 0xee) {
|
||||
memcpy((uint8_t *)Ion::storageAddress(), src, length);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (mode >= 0 && mode < 16) {
|
||||
uint8_t * src = (uint8_t *)(0x90180000 + mode * length);
|
||||
if (src[0] == 0xba && src[1] == 0xdd && src[2] == 0x0b && src[3] == 0xee) {
|
||||
memcpy((uint8_t *)Ion::storageAddress(), src, length);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int extapp_getKey(int allowSuspend, bool * alphaWasActive) {
|
||||
int extapp_getKey(bool allowSuspend, bool *alphaWasActive) {
|
||||
int key = -1;
|
||||
size_t t1 = Ion::Timing::millis();
|
||||
for (;;) {
|
||||
int timeout = 10000;
|
||||
if (alphaWasActive) {
|
||||
if(alphaWasActive) {
|
||||
*alphaWasActive = Ion::Events::isAlphaActive();
|
||||
}
|
||||
Ion::Events::Event event = Ion::Events::getEvent(&timeout);
|
||||
reloadTitleBar();
|
||||
if (event == Ion::Events::None) {
|
||||
size_t t2 = Ion::Timing::millis();
|
||||
if (t2 - t1 > 3 * TICKS_PER_MINUTE) {
|
||||
if (t2 - t1 > 2 * TICKS_PER_MINUTE) {
|
||||
event = Ion::Events::OnOff;
|
||||
}
|
||||
} else {
|
||||
@@ -323,10 +270,10 @@ int extapp_getKey(int allowSuspend, bool * alphaWasActive) {
|
||||
}
|
||||
if (event.isKeyboardEvent()) {
|
||||
key = static_cast<uint8_t>(event);
|
||||
if (key == (int)Ion::Keyboard::Key::Backspace || key == (int)Ion::Keyboard::Key::OK || key == (int)Ion::Keyboard::Key::Back || key == (int)Ion::Keyboard::Key::EXE) {
|
||||
if (key == 17 || key == 4 || key == 5 || key == 52) {
|
||||
extapp_resetKeyboard();
|
||||
}
|
||||
if (allowSuspend && key == (int)Ion::Keyboard::Key::OnOff) {
|
||||
if (allowSuspend && (key == 7 || key == 8)) { // power
|
||||
Ion::Power::suspend(true);
|
||||
extapp_pushRectUniform(0, 0, 320, 240, 65535);
|
||||
Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel());
|
||||
@@ -338,45 +285,6 @@ int extapp_getKey(int allowSuspend, bool * alphaWasActive) {
|
||||
return translated_keys[key];
|
||||
}
|
||||
|
||||
bool extapp_isKeydown(int key) {
|
||||
Ion::Keyboard::State scan = Ion::Keyboard::scan();
|
||||
return scan.keyDown(Ion::Keyboard::Key(key));
|
||||
}
|
||||
|
||||
bool extapp_eraseSector(void * ptr) {
|
||||
#ifdef DEVICE
|
||||
if (ptr == 0)
|
||||
Ion::Device::Reset::core();
|
||||
// Disable flash writting
|
||||
if (GlobalPreferences::sharedGlobalPreferences()->externalAppWritePermission()) {
|
||||
int i = Ion::Device::Flash::SectorAtAddress((size_t)ptr);
|
||||
if (i < 0)
|
||||
return false;
|
||||
Ion::Device::Flash::EraseSector(i);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool extapp_writeMemory(unsigned char * dest, const unsigned char * data, size_t length) {
|
||||
#ifdef DEVICE
|
||||
// Disable flash writting
|
||||
if (GlobalPreferences::sharedGlobalPreferences()->externalAppWritePermission()) {
|
||||
int n = Ion::Device::Flash::SectorAtAddress((uint32_t)dest);
|
||||
if (n < 0)
|
||||
return false;
|
||||
Ion::Device::Flash::WriteMemory(dest, (unsigned char *)data, length);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool extapp_inExamMode() {
|
||||
return GlobalPreferences::sharedGlobalPreferences()->isInExamMode();
|
||||
}
|
||||
|
||||
extern "C" void (* const apiPointers[])(void) = {
|
||||
(void (*)(void)) extapp_millis,
|
||||
(void (*)(void)) extapp_msleep,
|
||||
@@ -397,10 +305,5 @@ extern "C" void (* const apiPointers[])(void) = {
|
||||
(void (*)(void)) extapp_lockAlpha,
|
||||
(void (*)(void)) extapp_resetKeyboard,
|
||||
(void (*)(void)) extapp_getKey,
|
||||
(void (*)(void)) extapp_isKeydown,
|
||||
(void (*)(void)) extapp_restoreBackup,
|
||||
(void (*)(void)) extapp_eraseSector,
|
||||
(void (*)(void)) extapp_writeMemory,
|
||||
(void (*)(void)) extapp_inExamMode,
|
||||
(void (*)(void)) nullptr,
|
||||
};
|
||||
};
|
||||
|
||||
9
apps/external/extapp_api.h
vendored
9
apps/external/extapp_api.h
vendored
@@ -18,7 +18,6 @@
|
||||
|
||||
#define EXTAPP_RAM_FILE_SYSTEM 0
|
||||
#define EXTAPP_FLASH_FILE_SYSTEM 1
|
||||
#define EXTAPP_BOTH_FILE_SYSTEM 2
|
||||
|
||||
#define SCANCODE_Left ((uint64_t)1 << 0)
|
||||
#define SCANCODE_Up ((uint64_t)1 << 1)
|
||||
@@ -27,7 +26,7 @@
|
||||
#define SCANCODE_OK ((uint64_t)1 << 4)
|
||||
#define SCANCODE_Back ((uint64_t)1 << 5)
|
||||
#define SCANCODE_Home ((uint64_t)1 << 6)
|
||||
#define SCANCODE_OnOff (((uint64_t)1 << 7) | ((uint64_t)1 << 8))
|
||||
#define SCANCODE_OnOff (((uint64_t)1 << 7) || ((uint64_t)1 << 8))
|
||||
#define SCANCODE_Shift ((uint64_t)1 << 12)
|
||||
#define SCANCODE_Alpha ((uint64_t)1 << 13)
|
||||
#define SCANCODE_XNT ((uint64_t)1 << 14)
|
||||
@@ -252,10 +251,6 @@ EXTERNC const char * extapp_fileRead(const char * filename, size_t *len, int sto
|
||||
EXTERNC bool extapp_fileWrite(const char * filename, const char * content, size_t len, int storage);
|
||||
EXTERNC void extapp_lockAlpha();
|
||||
EXTERNC void extapp_resetKeyboard();
|
||||
EXTERNC int extapp_getKey(int allowSuspend, bool *alphaWasActive);
|
||||
EXTERNC bool extapp_isKeydown(int key);
|
||||
EXTERNC int extapp_restoreBackup(int mode); // Keep for compatibility with KhiCAS on Khi
|
||||
EXTERNC bool extapp_eraseSector(void * ptr);
|
||||
EXTERNC bool extapp_writeMemory(unsigned char * dest,const unsigned char * data,size_t length);
|
||||
EXTERNC int extapp_getKey(bool allowSuspend, bool *alphaWasActive);
|
||||
|
||||
#endif
|
||||
|
||||
23
apps/geometry/Makefile
Normal file
23
apps/geometry/Makefile
Normal file
@@ -0,0 +1,23 @@
|
||||
apps += Geometry::App
|
||||
app_headers += apps/geometry/app.h
|
||||
|
||||
app_geometry_src = $(addprefix apps/geometry/,\
|
||||
app.cpp \
|
||||
list/figures_controller.cpp \
|
||||
list/definition_type_controller.cpp \
|
||||
list/figure_type_controller.cpp \
|
||||
list/figure_parameters_controller.cpp \
|
||||
list/objects_controller.cpp \
|
||||
list/message_table_cell_with_selector.cpp \
|
||||
figure_store.cpp \
|
||||
graph/graph_controller.cpp \
|
||||
graph/banner_view.cpp \
|
||||
)
|
||||
|
||||
apps_src += $(app_geometry_src)
|
||||
|
||||
app_images += apps/geometry/geometry_icon.png
|
||||
|
||||
i18n_files += $(call i18n_with_universal_for,geometry/base)
|
||||
|
||||
$(eval $(call depends_on_image,apps/geometry/app.cpp,apps/geometry/geometry_icon.png))
|
||||
48
apps/geometry/app.cpp
Normal file
48
apps/geometry/app.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "app.h"
|
||||
#include "geometry_icon.h"
|
||||
#include "apps/apps_container.h"
|
||||
#include "apps/i18n.h"
|
||||
|
||||
namespace Geometry
|
||||
{
|
||||
|
||||
I18n::Message App::Descriptor::name()
|
||||
{
|
||||
return I18n::Message::GeometryApp;
|
||||
}
|
||||
|
||||
I18n::Message App::Descriptor::upperName()
|
||||
{
|
||||
return I18n::Message::GeometryAppCapital;
|
||||
}
|
||||
|
||||
const Image * App::Descriptor::icon()
|
||||
{
|
||||
return ImageStore::GeometryIcon;
|
||||
}
|
||||
|
||||
App * App::Snapshot::unpack(Container * container)
|
||||
{
|
||||
return new (container->currentAppBuffer()) App(this);
|
||||
}
|
||||
|
||||
App::Descriptor * App::Snapshot::descriptor()
|
||||
{
|
||||
static Descriptor descriptor;
|
||||
return &descriptor;
|
||||
}
|
||||
|
||||
App::App(Snapshot * snapshot) :
|
||||
TextFieldDelegateApp(snapshot, &m_tabViewController),
|
||||
m_figuresController(&m_stackViewController),
|
||||
m_stackViewController(&m_tabViewController, &m_figuresController),
|
||||
m_graphController(&m_graphAlternateEmptyViewController, this, &m_graphHeader, nullptr, nullptr, nullptr),
|
||||
m_graphAlternateEmptyViewController(&m_graphHeader, &m_graphController, &m_graphController),
|
||||
m_graphHeader(&m_graphStackViewController, &m_graphAlternateEmptyViewController, &m_graphController),
|
||||
m_graphStackViewController(&m_tabViewController, &m_graphHeader),
|
||||
m_otherViewController(&m_tabViewController),
|
||||
m_tabViewController(&m_modalViewController, snapshot, &m_stackViewController, &m_graphAlternateEmptyViewController, &m_otherViewController)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
40
apps/geometry/app.h
Normal file
40
apps/geometry/app.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef GEOMETRY_H
|
||||
#define GEOMETRY_H
|
||||
|
||||
#include <escher.h>
|
||||
#include "list/figures_controller.h"
|
||||
#include "graph/graph_controller.h"
|
||||
#include "other/other_view_controller.h"
|
||||
#include "../shared/text_field_delegate_app.h"
|
||||
|
||||
namespace Geometry {
|
||||
|
||||
class App : public Shared::TextFieldDelegateApp {
|
||||
public:
|
||||
class Descriptor : public ::App::Descriptor {
|
||||
public:
|
||||
I18n::Message name() override;
|
||||
I18n::Message upperName() override;
|
||||
const Image * icon() override;
|
||||
};
|
||||
class Snapshot : public ::App::Snapshot, public TabViewDataSource {
|
||||
public:
|
||||
App * unpack(Container * container) override;
|
||||
Descriptor * descriptor() override;
|
||||
};
|
||||
private:
|
||||
App(Snapshot * snapshot);
|
||||
|
||||
FiguresController m_figuresController;
|
||||
StackViewController m_stackViewController;
|
||||
GraphController m_graphController;
|
||||
AlternateEmptyViewController m_graphAlternateEmptyViewController;
|
||||
StackViewController m_graphStackViewController;
|
||||
ButtonRowController m_graphHeader;
|
||||
OtherViewController m_otherViewController;
|
||||
TabViewController m_tabViewController;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
6
apps/geometry/base.de.i18n
Normal file
6
apps/geometry/base.de.i18n
Normal file
@@ -0,0 +1,6 @@
|
||||
GeometryApp = "Geometry"
|
||||
GeometryAppCapital = "GEOMETRY"
|
||||
AddFigure = "Ajouter une figure"
|
||||
FigureType = "Type de figure"
|
||||
DefinitionType = "Définition de la figure"
|
||||
ParametersChoice = "Choix des paramètres"
|
||||
6
apps/geometry/base.en.i18n
Normal file
6
apps/geometry/base.en.i18n
Normal file
@@ -0,0 +1,6 @@
|
||||
GeometryApp = "Geometry"
|
||||
GeometryAppCapital = "GEOMETRY"
|
||||
AddFigure = "Ajouter une figure"
|
||||
FigureType = "Type de figure"
|
||||
DefinitionType = "Définition de la figure"
|
||||
ParametersChoice = "Choix des paramètres"
|
||||
6
apps/geometry/base.es.i18n
Normal file
6
apps/geometry/base.es.i18n
Normal file
@@ -0,0 +1,6 @@
|
||||
GeometryApp = "Geometry"
|
||||
GeometryAppCapital = "GEOMETRY"
|
||||
AddFigure = "Ajouter une figure"
|
||||
FigureType = "Type de figure"
|
||||
DefinitionType = "Définition de la figure"
|
||||
ParametersChoice = "Choix des paramètres"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user