mirror of
https://github.com/processing/processing4.git
synced 2026-05-09 12:22:43 +02:00
Merge branch 'main' into gradle-plugin
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
name: Pre-releases with Gradle
|
name: Branch Builds
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
@@ -6,31 +6,58 @@ on:
|
|||||||
- '.all-contributorsrc'
|
- '.all-contributorsrc'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Test Processing
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Install Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew test
|
||||||
build:
|
build:
|
||||||
name: Create Pre-release for ${{ matrix.os_prefix }} (${{ matrix.arch }})
|
name: (${{ matrix.os_prefix }}/${{ matrix.arch }}) Create Processing Build
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
permissions:
|
needs: test
|
||||||
contents: write
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: [self-hosted, linux, ARM64]
|
- os: ubuntu-24.04-arm
|
||||||
os_prefix: linux
|
os_prefix: linux
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
|
binary: processing*.snap
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
os_prefix: linux
|
os_prefix: linux
|
||||||
arch: x64
|
arch: x64
|
||||||
|
binary: processing*.snap
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
os_prefix: windows
|
os_prefix: windows
|
||||||
arch: x64
|
arch: x64
|
||||||
|
binary: msi/Processing-*.msi
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
os_prefix: macos
|
os_prefix: macos
|
||||||
arch: x64
|
arch: x64
|
||||||
|
binary: dmg/Processing-*.dmg
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
os_prefix: macos
|
os_prefix: macos
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
|
binary: dmg/Processing-*.dmg
|
||||||
steps:
|
steps:
|
||||||
|
- name: Install Snapcraft
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
uses: samuelmeuli/action-snapcraft@v3
|
||||||
|
- name: Install LXD
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
uses: canonical/setup-lxd@main
|
||||||
|
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Java
|
- name: Install Java
|
||||||
@@ -41,19 +68,13 @@ jobs:
|
|||||||
architecture: ${{ matrix.arch }}
|
architecture: ${{ matrix.arch }}
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew packageDistributionForCurrentOS
|
run: ./gradlew packageDistributionForCurrentOS
|
||||||
- name: Add instructions
|
|
||||||
if: ${{ matrix.os_prefix == 'macos' }}
|
|
||||||
run: |
|
|
||||||
echo "run 'xattr -d com.apple.quarantine Processing-${version}.dmg' to remove the quarantine flag" > ./app/build/compose/binaries/main/dmg/INSTRUCTIONS_FOR_TESTING.txt
|
|
||||||
- name: Add artifact
|
- name: Add artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: processing-${{ github.ref_name }}-${{github.sha}}-${{ matrix.os_prefix }}-${{ matrix.arch }}-gradle
|
name: processing-${{ matrix.os_prefix }}-${{ matrix.arch }}-br_${{ github.ref_name }}
|
||||||
path: |
|
|
||||||
./app/build/compose/binaries/main/dmg/Processing-*.dmg
|
|
||||||
./app/build/compose/binaries/main/dmg/INSTRUCTIONS_FOR_TESTING.txt
|
|
||||||
./app/build/compose/binaries/main/msi/Processing-*.msi
|
|
||||||
./app/build/compose/binaries/main/deb/processing*.deb
|
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
path: app/build/compose/binaries/main/${{ matrix.binary }}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
name: Maven Release
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: 'Version to release'
|
|
||||||
required: true
|
|
||||||
default: '1.0.0'
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
name: Create Processing Core Release on Maven Central
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: 17
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v4
|
|
||||||
- name: Build with Gradle
|
|
||||||
run: ./gradlew publish
|
|
||||||
env:
|
|
||||||
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
|
|
||||||
MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
|
|
||||||
|
|
||||||
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
|
|
||||||
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
|
|
||||||
|
|
||||||
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_IN_MEMORY_KEY }}
|
|
||||||
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_IN_MEMORY_KEY_PASSWORD }}
|
|
||||||
|
|
||||||
ORG_GRADLE_PROJECT_version: ${{ github.event.inputs.version }}
|
|
||||||
@@ -7,12 +7,26 @@ on:
|
|||||||
- main
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
test:
|
||||||
name: Create Pull Request Build for ${{ matrix.os_prefix }} (${{ matrix.arch }})
|
runs-on: ubuntu-latest
|
||||||
|
name: Test Processing
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Install Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew test
|
||||||
|
build:
|
||||||
|
name: (${{ matrix.os_prefix }}/${{ matrix.arch }}) Create Processing Build
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
permissions:
|
needs: test
|
||||||
pull-requests: write
|
|
||||||
contents: read
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -20,19 +34,31 @@ jobs:
|
|||||||
- os: ubuntu-24.04-arm
|
- os: ubuntu-24.04-arm
|
||||||
os_prefix: linux
|
os_prefix: linux
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
|
binary: processing*.snap
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
os_prefix: linux
|
os_prefix: linux
|
||||||
arch: x64
|
arch: x64
|
||||||
|
binary: processing*.snap
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
os_prefix: windows
|
os_prefix: windows
|
||||||
arch: x64
|
arch: x64
|
||||||
|
binary: msi/Processing-*.msi
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
os_prefix: macos
|
os_prefix: macos
|
||||||
arch: x64
|
arch: x64
|
||||||
|
binary: dmg/Processing-*.dmg
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
os_prefix: macos
|
os_prefix: macos
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
|
binary: dmg/Processing-*.dmg
|
||||||
steps:
|
steps:
|
||||||
|
- name: Install Snapcraft
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
uses: samuelmeuli/action-snapcraft@v3
|
||||||
|
- name: Install LXD
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
uses: canonical/setup-lxd@main
|
||||||
|
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Java
|
- name: Install Java
|
||||||
@@ -43,19 +69,13 @@ jobs:
|
|||||||
architecture: ${{ matrix.arch }}
|
architecture: ${{ matrix.arch }}
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew packageDistributionForCurrentOS
|
run: ./gradlew packageDistributionForCurrentOS
|
||||||
- name: Add instructions
|
|
||||||
if: ${{ matrix.os_prefix == 'macos' }}
|
|
||||||
run: |
|
|
||||||
echo "run 'xattr -d com.apple.quarantine Processing-${version}.dmg' to remove the quarantine flag" > ./app/build/compose/binaries/main/dmg/INSTRUCTIONS_FOR_TESTING.txt
|
|
||||||
- name: Add artifact
|
- name: Add artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: processing-pr${{ github.event.pull_request.number }}-${{github.sha}}-${{ matrix.os_prefix }}-${{ matrix.arch }}-gradle
|
name: processing-${{ matrix.os_prefix }}-${{ matrix.arch }}-pr_${{ github.event.pull_request.number }}
|
||||||
path: |
|
|
||||||
./app/build/compose/binaries/main/dmg/Processing-*.dmg
|
|
||||||
./app/build/compose/binaries/main/dmg/INSTRUCTIONS_FOR_TESTING.txt
|
|
||||||
./app/build/compose/binaries/main/msi/Processing-*.msi
|
|
||||||
./app/build/compose/binaries/main/deb/processing*.deb
|
|
||||||
retention-days: 5
|
retention-days: 5
|
||||||
|
path: app/build/compose/binaries/main/${{ matrix.binary }}
|
||||||
@@ -7,22 +7,50 @@ jobs:
|
|||||||
version:
|
version:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
build_number: ${{ steps.tag_info.outputs.build_number }}
|
revision: ${{ steps.tag_info.outputs.revision }}
|
||||||
version: ${{ steps.tag_info.outputs.version }}
|
version: ${{ steps.tag_info.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Extract version and build number
|
- name: Extract version and revision
|
||||||
id: tag_info
|
id: tag_info
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
TAG_NAME="${GITHUB_REF#refs/tags/}"
|
TAG_NAME="${GITHUB_REF#refs/tags/}"
|
||||||
BUILD_NUMBER=$(echo "$TAG_NAME" | cut -d'-' -f2)
|
REVISION=$(echo "$TAG_NAME" | cut -d'-' -f2)
|
||||||
VERSION=$(echo "$TAG_NAME" | cut -d'-' -f3)
|
VERSION=$(echo "$TAG_NAME" | cut -d'-' -f3)
|
||||||
|
|
||||||
# Set outputs for use in later jobs or steps
|
# Set outputs for use in later jobs or steps
|
||||||
echo "build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT
|
echo "revision=$REVISION" >> $GITHUB_OUTPUT
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
reference:
|
||||||
|
name: Publish Processing Reference to release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
needs: version
|
||||||
|
steps:
|
||||||
|
- name: Checkout Website Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: processing/processing-website
|
||||||
|
- name: Use Node.js 16
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
- name: Make reference.zip
|
||||||
|
run: npm run zip
|
||||||
|
- name: Upload reference to release
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
asset_name: processing-${{ needs.version.outputs.version }}-reference.zip
|
||||||
|
file: reference.zip
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
name: Publish Processing Core to Maven Central
|
name: Publish Processing Libraries to Maven Central
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: version
|
needs: version
|
||||||
steps:
|
steps:
|
||||||
@@ -35,6 +63,7 @@ jobs:
|
|||||||
java-version: 17
|
java-version: 17
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew publish
|
run: ./gradlew publish
|
||||||
env:
|
env:
|
||||||
@@ -48,9 +77,9 @@ jobs:
|
|||||||
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_IN_MEMORY_KEY_PASSWORD }}
|
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_IN_MEMORY_KEY_PASSWORD }}
|
||||||
|
|
||||||
ORG_GRADLE_PROJECT_version: ${{ needs.version.outputs.version }}
|
ORG_GRADLE_PROJECT_version: ${{ needs.version.outputs.version }}
|
||||||
ORG_GRADLE_PROJECT_group: ${{ vars.PROCESSING_GROUP }}
|
ORG_GRADLE_PROJECT_group: ${{ vars.GRADLE_GROUP }}
|
||||||
build:
|
build:
|
||||||
name: Publish Release for ${{ matrix.os_prefix }} (${{ matrix.arch }})
|
name: (${{ matrix.os_prefix }}/${{ matrix.arch }}) Create Processing Release
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
needs: version
|
needs: version
|
||||||
permissions:
|
permissions:
|
||||||
@@ -59,26 +88,47 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
# compiling for arm32 needs a self-hosted runner on Raspi OS (32-bit)
|
- os: ubuntu-24.04-arm
|
||||||
- os: [self-hosted, linux, ARM]
|
|
||||||
os_prefix: linux
|
os_prefix: linux
|
||||||
arch: arm
|
arch: aarch64
|
||||||
|
binary: ${{ vars.SNAP_NAME }}_${{ needs.version.outputs.version }}_arm64
|
||||||
|
extension: snap
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
os_prefix: linux
|
os_prefix: linux
|
||||||
arch: x64
|
arch: x64
|
||||||
|
binary: ${{ vars.SNAP_NAME }}_${{ needs.version.outputs.version }}_amd64
|
||||||
|
extension: snap
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
os_prefix: windows
|
os_prefix: windows
|
||||||
arch: x64
|
arch: x64
|
||||||
|
binary: msi/Processing-${{ needs.version.outputs.version }}
|
||||||
|
extension: msi
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
os_prefix: macos
|
os_prefix: macos
|
||||||
arch: x64
|
arch: x64
|
||||||
|
binary: dmg/Processing-${{ needs.version.outputs.version }}
|
||||||
|
extension: dmg
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
os_prefix: macos
|
os_prefix: macos
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
- os: macos-latest
|
binary: dmg/Processing-${{ needs.version.outputs.version }}
|
||||||
os_prefix: linux
|
extension: dmg
|
||||||
arch: aarch64
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Install Certificates for Code Signing
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
continue-on-error: true
|
||||||
|
uses: apple-actions/import-codesign-certs@v3
|
||||||
|
with:
|
||||||
|
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
|
||||||
|
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Install Snapcraft
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
uses: samuelmeuli/action-snapcraft@v3
|
||||||
|
- name: Install LXD
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
uses: canonical/setup-lxd@main
|
||||||
|
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Java
|
- name: Install Java
|
||||||
@@ -89,25 +139,53 @@ jobs:
|
|||||||
architecture: ${{ matrix.arch }}
|
architecture: ${{ matrix.arch }}
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
# - name: Install Certificates for Code Signing
|
|
||||||
# if: ${{ matrix.os_prefix == 'macos' }}
|
|
||||||
# uses: apple-actions/import-codesign-certs@v3
|
|
||||||
# with:
|
|
||||||
# p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
|
|
||||||
# p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew packageDistributionForCurrentOS
|
run: ./gradlew packageDistributionForCurrentOS
|
||||||
env:
|
env:
|
||||||
ORG_GRADLE_PROJECT_version: ${{ needs.version.outputs.version }}
|
ORG_GRADLE_PROJECT_version: ${{ needs.version.outputs.version }}
|
||||||
ORG_GRADLE_PROJECT_group: ${{ vars.PROCESSING_GROUP }}
|
ORG_GRADLE_PROJECT_group: ${{ vars.GRADLE_GROUP }}
|
||||||
|
ORG_GRADLE_PROJECT_revision: ${{ needs.version.outputs.revision }}
|
||||||
|
ORG_GRADLE_PROJECT_compose.desktop.verbose: true
|
||||||
|
ORG_GRADLE_PROJECT_compose.desktop.mac.sign: ${{ secrets.PROCESSING_SIGNING }}
|
||||||
|
ORG_GRADLE_PROJECT_compose.desktop.mac.signing.identity: ${{ secrets.PROCESSING_SIGNING_IDENTITY }}
|
||||||
|
ORG_GRADLE_PROJECT_compose.desktop.mac.notarization.appleID: ${{ secrets.PROCESSING_APPLE_ID }}
|
||||||
|
ORG_GRADLE_PROJECT_compose.desktop.mac.notarization.password: ${{ secrets.PROCESSING_APP_PASSWORD }}
|
||||||
|
ORG_GRADLE_PROJECT_compose.desktop.mac.notarization.teamID: ${{ secrets.PROCESSING_TEAM_ID }}
|
||||||
|
ORG_GRADLE_PROJECT_snapname: ${{ vars.SNAP_NAME }}
|
||||||
|
|
||||||
- name: Upload binaries to release
|
- name: Upload portables to release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: |
|
asset_name: processing-${{ needs.version.outputs.version }}-${{ matrix.os_prefix }}-${{ matrix.arch }}-portable.zip
|
||||||
./app/build/compose/binaries/main/dmg/Processing-*.dmg
|
file: app/build/compose/binaries/main/Processing-${{ needs.version.outputs.version }}.zip
|
||||||
./app/build/compose/binaries/main/dmg/INSTRUCTIONS_FOR_TESTING.txt
|
|
||||||
./app/build/compose/binaries/main/msi/Processing-*.msi
|
- name: Upload installers to release
|
||||||
./app/build/compose/binaries/main/deb/processing*.deb
|
uses: svenstaro/upload-release-action@v2
|
||||||
file_glob: true
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
asset_name: processing-${{ needs.version.outputs.version }}-${{ matrix.os_prefix }}-${{ matrix.arch }}.${{ matrix.extension }}
|
||||||
|
file: app/build/compose/binaries/main/${{ matrix.binary }}.${{ matrix.extension }}
|
||||||
|
|
||||||
|
- name: Upload snap to Snap Store
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: snapcraft upload --release=beta app/build/compose/binaries/main/${{ matrix.binary }}.${{ matrix.extension }}
|
||||||
|
env:
|
||||||
|
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.PROCESSING_SNAPCRAFT_TOKEN }}
|
||||||
|
|
||||||
|
- name: Sign files with Trusted Signing
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
uses: azure/trusted-signing-action@v0
|
||||||
|
with:
|
||||||
|
azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||||
|
azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||||
|
azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||||
|
endpoint: https://eus.codesigning.azure.net/
|
||||||
|
trusted-signing-account-name: vscx-codesigning
|
||||||
|
certificate-profile-name: vscx-certificate-profile
|
||||||
|
files-folder: app/build/compose/binaries/main/msi
|
||||||
|
files-folder-filter: msi
|
||||||
|
file-digest: SHA256
|
||||||
|
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||||
|
timestamp-digest: SHA256
|
||||||
@@ -113,3 +113,6 @@ java/build/
|
|||||||
/core/examples/build
|
/core/examples/build
|
||||||
/java/gradle/build
|
/java/gradle/build
|
||||||
/java/gradle/example/.processing
|
/java/gradle/example/.processing
|
||||||
|
|
||||||
|
.build/
|
||||||
|
/app/windows/obj
|
||||||
|
|||||||
Generated
+5
@@ -0,0 +1,5 @@
|
|||||||
|
<svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M400 500C700 500 700 100 400 100" stroke="#0468FF" stroke-width="150"/>
|
||||||
|
<path d="M400 200L100 600" stroke="#1F34AB" stroke-width="150"/>
|
||||||
|
<path d="M100 300L200 500" stroke="#85AEFF" stroke-width="150"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 324 B |
Generated
-1
@@ -4,7 +4,6 @@
|
|||||||
<option name="env">
|
<option name="env">
|
||||||
<map>
|
<map>
|
||||||
<entry key="DEBUG" value="true" />
|
<entry key="DEBUG" value="true" />
|
||||||
<entry key="ORG_GRADLE_PROJECT_version" value="Development Build" />
|
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
<option name="executionName" />
|
<option name="executionName" />
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package processing.app.ui;
|
||||||
|
|
||||||
|
|
||||||
|
// Stub class for backwards compatibility with the ant-build system
|
||||||
|
// This class is not used in the Gradle build system
|
||||||
|
// The actual implementation is in src/.../Schema.kt
|
||||||
|
public class WelcomeToBeta {
|
||||||
|
public static void showWelcomeToBeta(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+303
-16
@@ -1,6 +1,14 @@
|
|||||||
|
import org.gradle.kotlin.dsl.support.zipTo
|
||||||
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
|
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
|
||||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||||
|
import org.jetbrains.compose.desktop.application.tasks.AbstractJPackageTask
|
||||||
import org.jetbrains.compose.internal.de.undercouch.gradle.tasks.download.Download
|
import org.jetbrains.compose.internal.de.undercouch.gradle.tasks.download.Download
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.overrides
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipOutputStream
|
||||||
|
|
||||||
|
// TODO: Update to 2.10.20 and add hot-reloading: https://github.com/JetBrains/compose-hot-reload
|
||||||
|
|
||||||
plugins{
|
plugins{
|
||||||
id("java")
|
id("java")
|
||||||
@@ -12,9 +20,6 @@ plugins{
|
|||||||
alias(libs.plugins.download)
|
alias(libs.plugins.download)
|
||||||
}
|
}
|
||||||
|
|
||||||
group = rootProject.group
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
repositories{
|
repositories{
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
@@ -29,6 +34,14 @@ sourceSets{
|
|||||||
kotlin{
|
kotlin{
|
||||||
srcDirs("src")
|
srcDirs("src")
|
||||||
}
|
}
|
||||||
|
resources{
|
||||||
|
srcDirs("resources", listOf("languages", "fonts", "theme").map { "../build/shared/lib/$it" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test{
|
||||||
|
kotlin{
|
||||||
|
srcDirs("test")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,37 +50,38 @@ compose.desktop {
|
|||||||
mainClass = "processing.app.ui.Start"
|
mainClass = "processing.app.ui.Start"
|
||||||
|
|
||||||
jvmArgs(*listOf(
|
jvmArgs(*listOf(
|
||||||
Pair("processing.version", version),
|
Pair("processing.version", rootProject.version),
|
||||||
Pair("processing.revision", "1300"),
|
Pair("processing.revision", findProperty("revision") ?: Int.MAX_VALUE),
|
||||||
Pair("processing.contributions.source", "https://contributions-preview.processing.org/contribs.txt"),
|
Pair("processing.contributions.source", "https://download.processing.org/contribs.txt"),
|
||||||
Pair("processing.download.page", "https://processing.org/download/"),
|
Pair("processing.download.page", "https://processing.org/download/"),
|
||||||
Pair("processing.download.latest", "https://processing.org/download/latest.txt"),
|
Pair("processing.download.latest", "https://processing.org/download/latest.txt"),
|
||||||
Pair("processing.tutorials", "https://processing.org/tutorials/"),
|
Pair("processing.tutorials", "https://processing.org/tutorials/"),
|
||||||
).map { "-D${it.first}=${it.second}" }.toTypedArray())
|
).map { "-D${it.first}=${it.second}" }.toTypedArray())
|
||||||
|
|
||||||
nativeDistributions{
|
nativeDistributions{
|
||||||
modules("jdk.jdi", "java.compiler", "jdk.accessibility")
|
modules("jdk.jdi", "java.compiler", "jdk.accessibility", "java.management.rmi")
|
||||||
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
||||||
packageName = "Processing"
|
packageName = "Processing"
|
||||||
|
|
||||||
macOS{
|
macOS{
|
||||||
bundleID = "org.processing.app"
|
bundleID = "${rootProject.group}.app"
|
||||||
iconFile = project.file("../build/macos/processing.icns")
|
iconFile = rootProject.file("build/macos/processing.icns")
|
||||||
infoPlist{
|
infoPlist{
|
||||||
extraKeysRawXml = layout.projectDirectory.file("info.plist").asFile.readText()
|
extraKeysRawXml = file("macos/info.plist").readText()
|
||||||
}
|
}
|
||||||
entitlementsFile.set(project.file("entitlements.plist"))
|
entitlementsFile.set(file("macos/entitlements.plist"))
|
||||||
runtimeEntitlementsFile.set(project.file("entitlements.plist"))
|
runtimeEntitlementsFile.set(file("macos/entitlements.plist"))
|
||||||
|
appStore = true
|
||||||
}
|
}
|
||||||
windows{
|
windows{
|
||||||
iconFile = project.file("../build/windows/processing.ico")
|
iconFile = rootProject.file("build/windows/processing.ico")
|
||||||
menuGroup = "Processing"
|
menuGroup = "Processing"
|
||||||
upgradeUuid = "89d8d7fe-5602-4b12-ba10-0fe78efbd602"
|
upgradeUuid = "89d8d7fe-5602-4b12-ba10-0fe78efbd602"
|
||||||
}
|
}
|
||||||
linux {
|
linux {
|
||||||
appCategory = "Programming"
|
appCategory = "Programming"
|
||||||
menuGroup = "Processing"
|
menuGroup = "Development;Programming;"
|
||||||
iconFile = project.file("../build/linux/processing.png")
|
iconFile = rootProject.file("build/linux/processing.png")
|
||||||
// Fix fonts on some Linux distributions
|
// Fix fonts on some Linux distributions
|
||||||
jvmArgs("-Dawt.useSystemAAFontSettings=on")
|
jvmArgs("-Dawt.useSystemAAFontSettings=on")
|
||||||
|
|
||||||
@@ -99,12 +113,191 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.compottie)
|
implementation(libs.compottie)
|
||||||
implementation(libs.kaml)
|
implementation(libs.kaml)
|
||||||
|
implementation(libs.markdown)
|
||||||
|
implementation(libs.markdownJVM)
|
||||||
|
|
||||||
|
testImplementation(kotlin("test"))
|
||||||
|
testImplementation(libs.mockitoKotlin)
|
||||||
|
testImplementation(libs.junitJupiter)
|
||||||
|
testImplementation(libs.junitJupiterParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
workingDir = file("build/test")
|
||||||
|
workingDir.mkdirs()
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.compileJava{
|
tasks.compileJava{
|
||||||
options.encoding = "UTF-8"
|
options.encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val version = if(project.version == "unspecified") "1.0.0" else project.version
|
||||||
|
|
||||||
|
tasks.register<Exec>("installCreateDmg") {
|
||||||
|
onlyIf { org.gradle.internal.os.OperatingSystem.current().isMacOsX }
|
||||||
|
commandLine("arch", "-arm64", "brew", "install", "--quiet", "create-dmg")
|
||||||
|
}
|
||||||
|
tasks.register<Exec>("packageCustomDmg"){
|
||||||
|
onlyIf { org.gradle.internal.os.OperatingSystem.current().isMacOsX }
|
||||||
|
group = "compose desktop"
|
||||||
|
|
||||||
|
val distributable = tasks.named<AbstractJPackageTask>("createDistributable").get()
|
||||||
|
dependsOn(distributable, "installCreateDmg")
|
||||||
|
|
||||||
|
val packageName = distributable.packageName.get()
|
||||||
|
val dir = distributable.destinationDir.get()
|
||||||
|
val dmg = dir.file("../dmg/$packageName-$version.dmg").asFile
|
||||||
|
val app = dir.file("$packageName.app").asFile
|
||||||
|
|
||||||
|
dmg.parentFile.deleteRecursively()
|
||||||
|
dmg.parentFile.mkdirs()
|
||||||
|
|
||||||
|
val extra = mutableListOf<String>()
|
||||||
|
val isSigned = compose.desktop.application.nativeDistributions.macOS.signing.sign.get()
|
||||||
|
|
||||||
|
if(!isSigned) {
|
||||||
|
val content = """
|
||||||
|
run 'xattr -d com.apple.quarantine Processing-${version}.dmg' to remove the quarantine flag
|
||||||
|
""".trimIndent()
|
||||||
|
val instructions = dmg.parentFile.resolve("INSTRUCTIONS.txt")
|
||||||
|
instructions.writeText(content)
|
||||||
|
extra.add("--add-file")
|
||||||
|
extra.add("INSTRUCTIONS.txt")
|
||||||
|
extra.add(instructions.path)
|
||||||
|
extra.add("200")
|
||||||
|
extra.add("25")
|
||||||
|
}
|
||||||
|
|
||||||
|
commandLine("brew", "install", "--quiet", "create-dmg")
|
||||||
|
|
||||||
|
commandLine("create-dmg",
|
||||||
|
"--volname", packageName,
|
||||||
|
"--volicon", file("macos/volume.icns"),
|
||||||
|
"--background", file("macos/background.png"),
|
||||||
|
"--icon", "$packageName.app", "190", "185",
|
||||||
|
"--window-pos", "200", "200",
|
||||||
|
"--window-size", "658", "422",
|
||||||
|
"--app-drop-link", "466", "185",
|
||||||
|
"--hide-extension", "$packageName.app",
|
||||||
|
*extra.toTypedArray(),
|
||||||
|
dmg,
|
||||||
|
app
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<Exec>("packageCustomMsi"){
|
||||||
|
onlyIf { org.gradle.internal.os.OperatingSystem.current().isWindows }
|
||||||
|
dependsOn("createDistributable")
|
||||||
|
workingDir = file("windows")
|
||||||
|
group = "compose desktop"
|
||||||
|
|
||||||
|
val version = if(version == "unspecified") "1.0.0" else version
|
||||||
|
|
||||||
|
commandLine(
|
||||||
|
"dotnet",
|
||||||
|
"build",
|
||||||
|
"/p:Platform=x64",
|
||||||
|
"/p:Version=$version",
|
||||||
|
"/p:DefineConstants=\"Version=$version;\""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val snapname = findProperty("snapname") ?: rootProject.name
|
||||||
|
val snaparch = when (System.getProperty("os.arch")) {
|
||||||
|
"amd64", "x86_64" -> "amd64"
|
||||||
|
"aarch64" -> "arm64"
|
||||||
|
else -> System.getProperty("os.arch")
|
||||||
|
}
|
||||||
|
tasks.register("generateSnapConfiguration"){
|
||||||
|
onlyIf { org.gradle.internal.os.OperatingSystem.current().isLinux }
|
||||||
|
val distributable = tasks.named<AbstractJPackageTask>("createDistributable").get()
|
||||||
|
dependsOn(distributable)
|
||||||
|
|
||||||
|
val dir = distributable.destinationDir.get()
|
||||||
|
val content = """
|
||||||
|
name: $snapname
|
||||||
|
version: $version
|
||||||
|
base: core22
|
||||||
|
summary: A creative coding editor
|
||||||
|
description: |
|
||||||
|
Processing is a flexible software sketchbook and a programming language designed for learning how to code.
|
||||||
|
confinement: strict
|
||||||
|
|
||||||
|
apps:
|
||||||
|
processing:
|
||||||
|
command: opt/processing/bin/Processing
|
||||||
|
desktop: opt/processing/lib/processing-Processing.desktop
|
||||||
|
environment:
|
||||||
|
LD_LIBRARY_PATH: ${'$'}SNAP/opt/processing/lib/runtime/lib:${'$'}LD_LIBRARY_PATH
|
||||||
|
LIBGL_DRIVERS_PATH: ${'$'}SNAP/usr/lib/${'$'}SNAPCRAFT_ARCH_TRIPLET/dri
|
||||||
|
plugs:
|
||||||
|
- desktop
|
||||||
|
- desktop-legacy
|
||||||
|
- wayland
|
||||||
|
- x11
|
||||||
|
- network
|
||||||
|
- opengl
|
||||||
|
|
||||||
|
parts:
|
||||||
|
processing:
|
||||||
|
plugin: dump
|
||||||
|
source: deb/processing_$version-1_$snaparch.deb
|
||||||
|
source-type: deb
|
||||||
|
stage-packages:
|
||||||
|
- openjdk-17-jre
|
||||||
|
override-prime: |
|
||||||
|
snapcraftctl prime
|
||||||
|
chmod -R +x opt/processing/lib/app/resources/jdk-*
|
||||||
|
rm -vf usr/lib/jvm/java-17-openjdk-*/lib/security/cacerts
|
||||||
|
""".trimIndent()
|
||||||
|
dir.file("../snapcraft.yaml").asFile.writeText(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<Exec>("packageSnap"){
|
||||||
|
onlyIf { org.gradle.internal.os.OperatingSystem.current().isLinux }
|
||||||
|
dependsOn("packageDeb", "generateSnapConfiguration")
|
||||||
|
group = "compose desktop"
|
||||||
|
|
||||||
|
val distributable = tasks.named<AbstractJPackageTask>("createDistributable").get()
|
||||||
|
workingDir = distributable.destinationDir.dir("../").get().asFile
|
||||||
|
commandLine("snapcraft")
|
||||||
|
}
|
||||||
|
tasks.register<Zip>("zipDistributable"){
|
||||||
|
dependsOn("createDistributable", "setExecutablePermissions")
|
||||||
|
group = "compose desktop"
|
||||||
|
|
||||||
|
val distributable = tasks.named<AbstractJPackageTask>("createDistributable").get()
|
||||||
|
val dir = distributable.destinationDir.get()
|
||||||
|
val packageName = distributable.packageName.get()
|
||||||
|
|
||||||
|
from(dir){ eachFile{ permissions{ unix("755") } } }
|
||||||
|
archiveBaseName.set(packageName)
|
||||||
|
destinationDirectory.set(dir.file("../").asFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate{
|
||||||
|
tasks.named("packageDmg").configure{
|
||||||
|
dependsOn("packageCustomDmg")
|
||||||
|
group = "compose desktop"
|
||||||
|
actions = emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named("packageMsi").configure{
|
||||||
|
dependsOn("packageCustomMsi")
|
||||||
|
group = "compose desktop"
|
||||||
|
actions = emptyList()
|
||||||
|
}
|
||||||
|
tasks.named("packageDistributionForCurrentOS").configure {
|
||||||
|
if(org.gradle.internal.os.OperatingSystem.current().isMacOsX
|
||||||
|
&& compose.desktop.application.nativeDistributions.macOS.notarization.appleID.isPresent
|
||||||
|
){
|
||||||
|
dependsOn("notarizeDmg")
|
||||||
|
}
|
||||||
|
dependsOn("packageSnap", "zipDistributable")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// LEGACY TASKS
|
// LEGACY TASKS
|
||||||
// Most of these are shims to be compatible with the old build system
|
// Most of these are shims to be compatible with the old build system
|
||||||
@@ -220,6 +413,97 @@ tasks.register<Copy>("renameWindres") {
|
|||||||
}
|
}
|
||||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||||
into(dir)
|
into(dir)
|
||||||
|
}
|
||||||
|
tasks.register("signResources"){
|
||||||
|
onlyIf {
|
||||||
|
org.gradle.internal.os.OperatingSystem.current().isMacOsX
|
||||||
|
&&
|
||||||
|
compose.desktop.application.nativeDistributions.macOS.signing.sign.get()
|
||||||
|
}
|
||||||
|
group = "compose desktop"
|
||||||
|
dependsOn(
|
||||||
|
"includeCore",
|
||||||
|
"includeJavaMode",
|
||||||
|
"includeJdk",
|
||||||
|
"includeSharedAssets",
|
||||||
|
"includeProcessingExamples",
|
||||||
|
"includeProcessingWebsiteExamples",
|
||||||
|
"includeJavaModeResources",
|
||||||
|
"renameWindres"
|
||||||
|
)
|
||||||
|
finalizedBy("prepareAppResources")
|
||||||
|
|
||||||
|
val resourcesPath = composeResources("")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// find jars in the resources directory
|
||||||
|
val jars = mutableListOf<File>()
|
||||||
|
doFirst{
|
||||||
|
fileTree(resourcesPath)
|
||||||
|
.matching { include("**/Info.plist") }
|
||||||
|
.singleOrNull()
|
||||||
|
?.let { file ->
|
||||||
|
copy {
|
||||||
|
from(file)
|
||||||
|
into(resourcesPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileTree(resourcesPath) {
|
||||||
|
include("**/*.jar")
|
||||||
|
exclude("**/*.jar.tmp/**")
|
||||||
|
}.forEach { file ->
|
||||||
|
val tempDir = file.parentFile.resolve("${file.name}.tmp")
|
||||||
|
copy {
|
||||||
|
from(zipTree(file))
|
||||||
|
into(tempDir)
|
||||||
|
}
|
||||||
|
file.delete()
|
||||||
|
jars.add(tempDir)
|
||||||
|
}
|
||||||
|
fileTree(resourcesPath){
|
||||||
|
include("**/bin/**")
|
||||||
|
include("**/*.jnilib")
|
||||||
|
include("**/*.dylib")
|
||||||
|
include("**/*aarch64*")
|
||||||
|
include("**/*x86_64*")
|
||||||
|
include("**/*ffmpeg*")
|
||||||
|
include("**/ffmpeg*/**")
|
||||||
|
exclude("jdk-*/**")
|
||||||
|
exclude("*.jar")
|
||||||
|
exclude("*.so")
|
||||||
|
exclude("*.dll")
|
||||||
|
}.forEach{ file ->
|
||||||
|
exec {
|
||||||
|
commandLine("codesign", "--timestamp", "--force", "--deep","--options=runtime", "--sign", "Developer ID Application", file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jars.forEach { file ->
|
||||||
|
FileOutputStream(File(file.parentFile, file.nameWithoutExtension)).use { fos ->
|
||||||
|
ZipOutputStream(fos).use { zos ->
|
||||||
|
file.walkTopDown().forEach { fileEntry ->
|
||||||
|
if (fileEntry.isFile) {
|
||||||
|
// Calculate the relative path for the zip entry
|
||||||
|
val zipEntryPath = fileEntry.relativeTo(file).path
|
||||||
|
val entry = ZipEntry(zipEntryPath)
|
||||||
|
zos.putNextEntry(entry)
|
||||||
|
|
||||||
|
// Copy file contents to the zip
|
||||||
|
fileEntry.inputStream().use { input ->
|
||||||
|
input.copyTo(zos)
|
||||||
|
}
|
||||||
|
zos.closeEntry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.deleteRecursively()
|
||||||
|
}
|
||||||
|
file(composeResources("Info.plist")).delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
tasks.named("prepareAppResources").configure {
|
tasks.named("prepareAppResources").configure {
|
||||||
@@ -253,5 +537,8 @@ afterEvaluate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tasks.findByName("createDistributable")?.finalizedBy("setExecutablePermissions")
|
tasks.named("createDistributable").configure {
|
||||||
|
dependsOn("signResources")
|
||||||
|
finalizedBy("setExecutablePermissions")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 497 KiB |
Binary file not shown.
@@ -0,0 +1,5 @@
|
|||||||
|
<svg width="900" height="900" viewBox="0 0 900 900" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M456.735 552.393L155.9 151.279" stroke="#A44D28" stroke-width="150.418"/>
|
||||||
|
<path d="M757.575 452.113C456.738 552.391 456.738 752.948 155.903 652.67" stroke="#FF7D45" stroke-width="150.418"/>
|
||||||
|
<path d="M556.832 552.392L456.555 51" stroke="#FFBEA2" stroke-width="150.418"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 386 B |
@@ -0,0 +1,309 @@
|
|||||||
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
|
||||||
|
# DO NOT MAKE CHANGES TO THIS FILE!!!
|
||||||
|
|
||||||
|
# These are the default preferences. If you want to modify
|
||||||
|
# them directly, use the per-user local version of the file:
|
||||||
|
|
||||||
|
# Users -> [username] -> AppData -> Roaming ->
|
||||||
|
# Processing -> preferences.txt (on Windows 10)
|
||||||
|
|
||||||
|
# ~/Library -> Processing -> preferences.txt (on macOS)
|
||||||
|
|
||||||
|
# ~/.config/processing -> preferences.txt (on Linux)
|
||||||
|
|
||||||
|
# The exact location of your preferences file can be found at
|
||||||
|
# the bottom of the Preferences window inside Processing.
|
||||||
|
|
||||||
|
# Because AppData and Application Data may be considered
|
||||||
|
# hidden or system folders on Windows, you'll have to ensure
|
||||||
|
# that they're visible in order to get at preferences.txt
|
||||||
|
|
||||||
|
# You'll have problems running Processing if you incorrectly
|
||||||
|
# modify lines in this file. It will probably not start at all.
|
||||||
|
|
||||||
|
# AGAIN, DO NOT ALTER THIS FILE! I'M ONLY YELLING BECAUSE I LOVE YOU!
|
||||||
|
|
||||||
|
|
||||||
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
|
||||||
|
# If you don't want users to have their sketchbook default to
|
||||||
|
# "My Documents/Processing" on Windows and "Documents/Processing" on OS X,
|
||||||
|
# set this to another path that will be used by default.
|
||||||
|
# Note that this path must exist already otherwise it won't see
|
||||||
|
# the sketchbook folder, and will instead assume the sketchbook
|
||||||
|
# has gone missing, and that it should instead use the default.
|
||||||
|
# In 4.0, the location has changed.
|
||||||
|
#sketchbook.path.four=
|
||||||
|
|
||||||
|
# Whether or not to show the Welcome screen for 4.0
|
||||||
|
# (It's always available under Help → Welcome)
|
||||||
|
welcome.four.show = true
|
||||||
|
welcome.four.seen = false
|
||||||
|
|
||||||
|
# Set 'true' for the default behavior before 4.0, where the
|
||||||
|
# main tab must have the same name as the sketch folder
|
||||||
|
editor.sync_folder_and_filename = true
|
||||||
|
|
||||||
|
# By default, contributions are moved to backup folders when
|
||||||
|
# they are removed or replaced. The backups can be found at
|
||||||
|
# sketchbook/libraries/old, sketchbook/tools/old, and sketchbook/modes/old
|
||||||
|
|
||||||
|
# true to backup contributions when "Remove" button is pressed
|
||||||
|
contribution.backup.on_remove = true
|
||||||
|
# true to backup contributions when installing a newer version
|
||||||
|
contribution.backup.on_install = true
|
||||||
|
|
||||||
|
recent.count = 10
|
||||||
|
|
||||||
|
# Default to the native (AWT) file selector where possible
|
||||||
|
chooser.files.native = true
|
||||||
|
# We were shutting this off on macOS because it broke Copy/Paste:
|
||||||
|
# https://github.com/processing/processing/issues/1035
|
||||||
|
# But removing again for 4.0 alpha 5, because the JFileChooser is awful,
|
||||||
|
# and worse on Big Sur, so a bigger problem than the Copy/Paste issue.
|
||||||
|
# https://github.com/processing/processing4/issues/77
|
||||||
|
#chooser.files.native.macos = false
|
||||||
|
|
||||||
|
# set to 'lab' to interpolate theme gradients using L*a*b* color space
|
||||||
|
theme.gradient.method = rgb
|
||||||
|
|
||||||
|
|
||||||
|
# by default, check the processing server for any updates
|
||||||
|
# (please avoid disabling, this also helps us know basic numbers
|
||||||
|
# on how many people are using Processing)
|
||||||
|
update.check = true
|
||||||
|
|
||||||
|
# on windows, automatically associate .pde files with processing.exe
|
||||||
|
platform.auto_file_type_associations = true
|
||||||
|
|
||||||
|
|
||||||
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
|
||||||
|
# default size for the main window
|
||||||
|
editor.window.width.default = 700
|
||||||
|
editor.window.height.default = 600
|
||||||
|
|
||||||
|
editor.window.width.min = 400
|
||||||
|
editor.window.height.min = 500
|
||||||
|
# tested as approx 440 on OS X
|
||||||
|
editor.window.height.min.macos = 450
|
||||||
|
# tested to be 515 on Windows XP, this leaves some room
|
||||||
|
editor.window.height.min.windows = 530
|
||||||
|
# tested with Raspberry Pi display
|
||||||
|
editor.window.height.min.linux = 480
|
||||||
|
|
||||||
|
# scaling for the interface (to handle Windows and Linux HiDPI displays)
|
||||||
|
editor.zoom = 100%
|
||||||
|
# automatically set based on system dpi (only helps on Windows)
|
||||||
|
editor.zoom.auto = true
|
||||||
|
|
||||||
|
# Use the default monospace font included in lib/fonts.
|
||||||
|
# (As of Processing 4 alpha 5, that's Source Code Pro)
|
||||||
|
editor.font.family = processing.mono
|
||||||
|
editor.font.size = 12
|
||||||
|
|
||||||
|
# To reset everyone's default, replaced editor.antialias with editor.smooth
|
||||||
|
# for 2.1. Fonts are unusably gross on OS X (and Linux) w/o smoothing and
|
||||||
|
# the Oracle JVM, and many longtime users have anti-aliasing turned off.
|
||||||
|
editor.smooth = true
|
||||||
|
|
||||||
|
# blink the caret by default
|
||||||
|
editor.caret.blink = true
|
||||||
|
# change to true to use a block (instead of a bar)
|
||||||
|
editor.caret.block = false
|
||||||
|
|
||||||
|
# enable ctrl-ins, shift-ins, shift-delete for cut/copy/paste
|
||||||
|
# on windows and linux, but disable on the mac
|
||||||
|
editor.keys.alternative_cut_copy_paste = true
|
||||||
|
editor.keys.alternative_cut_copy_paste.macos = false
|
||||||
|
|
||||||
|
# true if shift-backspace sends the delete character,
|
||||||
|
# false if shift-backspace just means backspace
|
||||||
|
editor.keys.shift_backspace_is_delete = false
|
||||||
|
|
||||||
|
# home and end keys should only travel to the start/end of the current line
|
||||||
|
editor.keys.home_and_end_travel_far = false
|
||||||
|
# home and end keys move to the first/last non-whitespace character,
|
||||||
|
# and move to the actual start/end when pressed a second time.
|
||||||
|
# Only works if editor.keys.home_and_end_travel_far is false.
|
||||||
|
editor.keys.home_and_end_travel_smart = true
|
||||||
|
# The OS X HI Guidelines say that home/end are relative to the document,
|
||||||
|
# but that drives some people nuts. This pref enables/disables it.
|
||||||
|
editor.keys.home_and_end_travel_far.macos = true
|
||||||
|
|
||||||
|
# Enable/disable support for complex scripts. Used for Japanese and others,
|
||||||
|
# but disable when not needed, otherwise basic Western European chars break.
|
||||||
|
editor.input_method_support = false
|
||||||
|
|
||||||
|
# convert tabs to spaces? how many spaces?
|
||||||
|
editor.tabs.expand = true
|
||||||
|
editor.tabs.size = 2
|
||||||
|
|
||||||
|
# Set to true to automatically close [ { ( " and '
|
||||||
|
editor.completion.auto_close = false
|
||||||
|
|
||||||
|
# automatically indent each line
|
||||||
|
editor.indent = true
|
||||||
|
|
||||||
|
# Whether to check files to see if they've been modified externally
|
||||||
|
editor.watcher = true
|
||||||
|
# Set true to enable debugging, since this is quirky on others' machines
|
||||||
|
editor.watcher.debug = false
|
||||||
|
# The window of time (in milliseconds) in which a change won't be counted
|
||||||
|
editor.watcher.window = 1500
|
||||||
|
|
||||||
|
# Format and search engine to use for online queries
|
||||||
|
search.format = https://google.com/search?q=%s
|
||||||
|
|
||||||
|
# font choice and size for the console
|
||||||
|
console.font.size = 12
|
||||||
|
|
||||||
|
# number of lines to show by default
|
||||||
|
console.lines = 4
|
||||||
|
|
||||||
|
# Number of blank lines to advance/clear console.
|
||||||
|
# Note that those lines are also printed in the terminal when
|
||||||
|
# Processing is executed there.
|
||||||
|
# Setting to 0 stops this behavior.
|
||||||
|
console.head_padding = 10
|
||||||
|
|
||||||
|
# Set to false to disable automatically clearing the console
|
||||||
|
# each time 'run' is hit
|
||||||
|
# If one sets it to false, one may also want to set 'console.head_padding'
|
||||||
|
# to a positive number to separate outputs from different runs.
|
||||||
|
console.auto_clear = true
|
||||||
|
|
||||||
|
# number of days of history to keep around before cleaning
|
||||||
|
# setting to 0 will never clean files
|
||||||
|
console.temp.days = 7
|
||||||
|
|
||||||
|
# set the maximum number of lines remembered by the console
|
||||||
|
# the default is 500, lengthen at your own peril
|
||||||
|
console.scrollback.lines = 500
|
||||||
|
console.scrollback.chars = 40000
|
||||||
|
|
||||||
|
# Any additional Java options when running.
|
||||||
|
# If you change this and can't run things, it's your own durn fault.
|
||||||
|
run.options =
|
||||||
|
|
||||||
|
# settings for the -XmsNNNm and -XmxNNNm command line option
|
||||||
|
run.options.memory = false
|
||||||
|
run.options.memory.initial = 64
|
||||||
|
run.options.memory.maximum = 512
|
||||||
|
|
||||||
|
# Index of the display to use for running sketches (starts at 1).
|
||||||
|
# Kept this 1-indexed because older vesions of Processing were setting
|
||||||
|
# the preference even before it was being used.
|
||||||
|
# -1 means the default display, 0 means all displays
|
||||||
|
run.display = -1
|
||||||
|
|
||||||
|
# set internally because it comes from the system
|
||||||
|
#run.window.bgcolor=
|
||||||
|
|
||||||
|
# set to false to open a new untitled window when closing the last window
|
||||||
|
# (otherwise, the environment will quit)
|
||||||
|
# default to the relative norm for the different platforms,
|
||||||
|
# but the setting can be changed in the prefs dialog anyway
|
||||||
|
#sketchbook.closing_last_window_quits = true
|
||||||
|
#sketchbook.closing_last_window_quits.macos = false
|
||||||
|
|
||||||
|
editor.untitled.prefix=sketch_
|
||||||
|
# The old (pre-1.0, back for 2.0) style for default sketch name.
|
||||||
|
# If you change this, be careful that this will work with your language
|
||||||
|
# settings. For instance, MMMdd won't work on Korean-language systems
|
||||||
|
# because it'll insert non-ASCII characters and break the environment.
|
||||||
|
# https://github.com/processing/processing/issues/322
|
||||||
|
editor.untitled.suffix=yyMMdd
|
||||||
|
|
||||||
|
# replace underscores in .pde file names with spaces
|
||||||
|
sketch.name.replace_underscore = true
|
||||||
|
|
||||||
|
# what to use for generating sketch names (change in the prefs window)
|
||||||
|
#sketch.name.approach =
|
||||||
|
|
||||||
|
# number of days of build history and other temp files to keep around
|
||||||
|
# these are kept around for debugging purposes, and in case code is lost
|
||||||
|
temp.days = 7
|
||||||
|
|
||||||
|
|
||||||
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
|
||||||
|
# whether or not to export as full screen (present) mode
|
||||||
|
export.application.fullscreen = false
|
||||||
|
|
||||||
|
# whether to show the stop button when exporting to application
|
||||||
|
export.application.stop = true
|
||||||
|
|
||||||
|
# embed Java by default for lower likelihood of problems
|
||||||
|
export.application.embed_java = true
|
||||||
|
|
||||||
|
# set to false to no longer delete application folders before export
|
||||||
|
# (removed from the Preferences windows in 4.0 beta 9)
|
||||||
|
export.delete_target_folder = true
|
||||||
|
|
||||||
|
# may be useful when attempting to debug the preprocessor
|
||||||
|
preproc.save_build_files=false
|
||||||
|
|
||||||
|
# allows various preprocessor features to be toggled
|
||||||
|
# in case they are causing problems
|
||||||
|
|
||||||
|
# preprocessor: pde.g
|
||||||
|
preproc.color_datatype = true
|
||||||
|
preproc.web_colors = true
|
||||||
|
preproc.enhanced_casting = true
|
||||||
|
|
||||||
|
# preprocessor: PdeEmitter.java
|
||||||
|
preproc.substitute_floats = true
|
||||||
|
|
||||||
|
# PdePreproc.java
|
||||||
|
# writes out the parse tree as parseTree.xml, which can be usefully
|
||||||
|
# viewed in (at least) Mozilla or IE. useful when debugging the preprocessor.
|
||||||
|
preproc.output_parse_tree = false
|
||||||
|
|
||||||
|
# set to the program to be used for opening HTML files, folders, etc.
|
||||||
|
#launcher.linux = xdg-open
|
||||||
|
|
||||||
|
# FULL SCREEN (PRESENT MODE)
|
||||||
|
run.present.bgcolor = #666666
|
||||||
|
run.present.stop.color = #cccccc
|
||||||
|
|
||||||
|
# PROXIES
|
||||||
|
# Set a proxy server for folks that require it. This will allow the update
|
||||||
|
# checker and the contrib manager to run properly in those environments.
|
||||||
|
# This changed from proxy.host and proxy.port to proxy.http.host and
|
||||||
|
# proxy.http.port in 3.0a8. In addition, https and socks were added.
|
||||||
|
proxy.http.host=
|
||||||
|
proxy.http.port=
|
||||||
|
proxy.https.host=
|
||||||
|
proxy.https.port=
|
||||||
|
proxy.socks.host=
|
||||||
|
proxy.socks.port=
|
||||||
|
# Example of usage (replace 'http' with 'https' or 'socks' as needed)
|
||||||
|
#proxy.http.host=proxy.example.com
|
||||||
|
#proxy.http.port=8080
|
||||||
|
# Whether to use the system proxy by default
|
||||||
|
proxy.system=true
|
||||||
|
|
||||||
|
# PDE X
|
||||||
|
pdex.errorCheckEnabled = true
|
||||||
|
pdex.warningsEnabled = true
|
||||||
|
pdex.writeErrorLogs = false
|
||||||
|
|
||||||
|
pdex.autoSave.autoSaveEnabled = false
|
||||||
|
pdex.autoSaveInterval = 5
|
||||||
|
pdex.autoSave.promptDisplay = true
|
||||||
|
pdex.autoSave.autoSaveByDefault = true
|
||||||
|
|
||||||
|
# Enable auto-completion when hitting ctrl-space
|
||||||
|
pdex.completion = false
|
||||||
|
# Setting this true will show completions whenever available, not just after ctrl-space
|
||||||
|
pdex.completion.trigger = false
|
||||||
|
# Suggest libraries to import when a class is undefined/unavailable
|
||||||
|
pdex.suggest.imports = true
|
||||||
|
# Set to false to disable ctrl/cmd-click jump to definition
|
||||||
|
pdex.inspectMode.hotkey = true
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M400 500C700 500 700 100 400 100" stroke="#0468FF" stroke-width="150"/>
|
||||||
|
<path d="M400 200L100 600" stroke="#1F34AB" stroke-width="150"/>
|
||||||
|
<path d="M100 300L200 500" stroke="#85AEFF" stroke-width="150"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 329 B |
@@ -124,6 +124,7 @@ public class Base {
|
|||||||
|
|
||||||
|
|
||||||
static public void main(final String[] args) {
|
static public void main(final String[] args) {
|
||||||
|
Messages.log("Starting Processing version" + VERSION_NAME + " revision "+ REVISION);
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
try {
|
try {
|
||||||
createAndShowGUI(args);
|
createAndShowGUI(args);
|
||||||
@@ -563,14 +564,12 @@ public class Base {
|
|||||||
cl.downloadAvailableList(this, new ContribProgress(null));
|
cl.downloadAvailableList(this, new ContribProgress(null));
|
||||||
long t9 = System.currentTimeMillis();
|
long t9 = System.currentTimeMillis();
|
||||||
|
|
||||||
if (DEBUG) {
|
Messages.log("core modes: " + (t2b-t2) +
|
||||||
System.out.println("core modes: " + (t2b-t2) +
|
", contrib modes: " + (t2c-t2b) +
|
||||||
", contrib modes: " + (t2c-t2b) +
|
", contrib ex: " + (t2c-t2b));
|
||||||
", contrib ex: " + (t2c-t2b));
|
Messages.log("base took " + (t2-t1) + " " + (t3-t2) + " " + (t4-t3) +
|
||||||
System.out.println("base took " + (t2-t1) + " " + (t3-t2) + " " + (t4-t3) +
|
|
||||||
" " + (t5-t4) + " t6-t5=" + (t6-t5) + " " + (t7-t6) +
|
" " + (t5-t4) + " t6-t5=" + (t6-t5) + " " + (t7-t6) +
|
||||||
" handleNew=" + (t8-t7) + " " + (t9-t8) + " ms");
|
" handleNew=" + (t8-t7) + " " + (t9-t8) + " ms");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1366,10 +1365,10 @@ public class Base {
|
|||||||
* @param schemeUri the full URI, including pde://
|
* @param schemeUri the full URI, including pde://
|
||||||
*/
|
*/
|
||||||
public Editor handleScheme(String schemeUri) {
|
public Editor handleScheme(String schemeUri) {
|
||||||
// var result = Schema.handleSchema(schemeUri, this);
|
var result = Schema.handleSchema(schemeUri, this);
|
||||||
// if (result != null) {
|
if (result != null) {
|
||||||
// return result;
|
return result;
|
||||||
// }
|
}
|
||||||
|
|
||||||
String location = schemeUri.substring(6);
|
String location = schemeUri.substring(6);
|
||||||
if (location.length() > 0) {
|
if (location.length() > 0) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package processing.app;
|
package processing.app;
|
||||||
|
|
||||||
import java.awt.EventQueue;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
@@ -330,6 +329,7 @@ public class Library extends LocalContribution {
|
|||||||
* imports to specific libraries.
|
* imports to specific libraries.
|
||||||
* @param importToLibraryTable mapping from package names to Library objects
|
* @param importToLibraryTable mapping from package names to Library objects
|
||||||
*/
|
*/
|
||||||
|
static boolean instructed = false;
|
||||||
// public void addPackageList(HashMap<String,Library> importToLibraryTable) {
|
// public void addPackageList(HashMap<String,Library> importToLibraryTable) {
|
||||||
public void addPackageList(Map<String, List<Library>> importToLibraryTable) {
|
public void addPackageList(Map<String, List<Library>> importToLibraryTable) {
|
||||||
// PApplet.println(packages);
|
// PApplet.println(packages);
|
||||||
@@ -342,18 +342,20 @@ public class Library extends LocalContribution {
|
|||||||
libraries = new ArrayList<>();
|
libraries = new ArrayList<>();
|
||||||
importToLibraryTable.put(pkg, libraries);
|
importToLibraryTable.put(pkg, libraries);
|
||||||
} else {
|
} else {
|
||||||
if (Base.DEBUG) {
|
if(!instructed) {
|
||||||
System.err.println("The library found in");
|
instructed = true;
|
||||||
System.err.println(getPath());
|
Messages.err("The library found in");
|
||||||
System.err.println("conflicts with");
|
Messages.err(getPath());
|
||||||
|
Messages.err("conflicts with");
|
||||||
for (Library library : libraries) {
|
for (Library library : libraries) {
|
||||||
System.err.println(library.getPath());
|
Messages.err(library.getPath());
|
||||||
}
|
}
|
||||||
System.err.println("which already define(s) the package " + pkg);
|
Messages.err("which already define(s) the package " + pkg);
|
||||||
System.err.println("If you have a line in your sketch that reads");
|
Messages.err("If you have a line in your sketch that reads");
|
||||||
System.err.println("import " + pkg + ".*;");
|
Messages.err("import " + pkg + ".*;");
|
||||||
System.err.println("Then you'll need to first remove one of those libraries.");
|
Messages.err("Then you'll need to first remove one of those libraries.");
|
||||||
System.err.println();
|
}else{
|
||||||
|
Messages.err("\tPackage ("+pkg+")\t conflict found in [" + name + "] with libraries: " + libraries.stream().map(Library::getName).reduce((a, b) -> a + ", " + b).orElse(""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
libraries.add(this);
|
libraries.add(this);
|
||||||
|
|||||||
@@ -0,0 +1,282 @@
|
|||||||
|
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /*
|
||||||
|
Part of the Processing project - http://processing.org
|
||||||
|
|
||||||
|
Copyright (c) 2015 The Processing Foundation
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
version 2, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
package processing.app
|
||||||
|
|
||||||
|
import processing.app.ui.Toolkit
|
||||||
|
import java.awt.EventQueue
|
||||||
|
import java.awt.Frame
|
||||||
|
import java.io.PrintWriter
|
||||||
|
import java.io.StringWriter
|
||||||
|
import javax.swing.JFrame
|
||||||
|
import javax.swing.JOptionPane
|
||||||
|
|
||||||
|
class Messages {
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* "No cookie for you" type messages. Nothing fatal or all that
|
||||||
|
* much of a bummer, but something to notify the user about.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun showMessage(title: String = "Message", message: String) {
|
||||||
|
if (Base.isCommandLine()) {
|
||||||
|
println("$title: $message")
|
||||||
|
} else {
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
Frame(), message, title,
|
||||||
|
JOptionPane.INFORMATION_MESSAGE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-fatal error message with optional stack trace side dish.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Non-fatal error message.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
|
fun showWarning(title: String = "Warning", message: String, e: Throwable? = null) {
|
||||||
|
if (Base.isCommandLine()) {
|
||||||
|
println("$title: $message")
|
||||||
|
} else {
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
Frame(), message, title,
|
||||||
|
JOptionPane.WARNING_MESSAGE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
e?.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-fatal error message with two levels of formatting.
|
||||||
|
* Unlike the others, this is non-blocking and will run later on the EDT.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun showWarningTiered(
|
||||||
|
title: String,
|
||||||
|
primary: String, secondary: String,
|
||||||
|
e: Throwable?
|
||||||
|
) {
|
||||||
|
if (Base.isCommandLine()) {
|
||||||
|
// TODO All these messages need to be handled differently for
|
||||||
|
// proper parsing on the command line. Many have \n in them.
|
||||||
|
println("$title: $primary\n$secondary")
|
||||||
|
} else {
|
||||||
|
EventQueue.invokeLater {
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
JFrame(),
|
||||||
|
Toolkit.formatMessage(primary, secondary),
|
||||||
|
title, JOptionPane.WARNING_MESSAGE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e?.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show an error message that's actually fatal to the program.
|
||||||
|
* This is an error that can't be recovered. Use showWarning()
|
||||||
|
* for errors that allow P5 to continue running.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun showError(title: String = "Error", message: String, e: Throwable?) {
|
||||||
|
if (Base.isCommandLine()) {
|
||||||
|
System.err.println("$title: $message")
|
||||||
|
} else {
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
Frame(), message, title,
|
||||||
|
JOptionPane.ERROR_MESSAGE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
e?.printStackTrace()
|
||||||
|
System.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning window that includes the stack trace.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun showTrace(
|
||||||
|
title: String?,
|
||||||
|
message: String,
|
||||||
|
t: Throwable?,
|
||||||
|
fatal: Boolean
|
||||||
|
) {
|
||||||
|
val title = title ?: if (fatal) "Error" else "Warning"
|
||||||
|
|
||||||
|
if (Base.isCommandLine()) {
|
||||||
|
System.err.println("$title: $message")
|
||||||
|
t?.printStackTrace()
|
||||||
|
} else {
|
||||||
|
val sw = StringWriter()
|
||||||
|
t!!.printStackTrace(PrintWriter(sw))
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
Frame(), // first <br/> clears to the next line
|
||||||
|
// second <br/> is a shorter height blank space before the trace
|
||||||
|
Toolkit.formatMessage("$message<br/><tt><br/>$sw</tt>"),
|
||||||
|
title,
|
||||||
|
if (fatal) JOptionPane.ERROR_MESSAGE else JOptionPane.WARNING_MESSAGE
|
||||||
|
)
|
||||||
|
|
||||||
|
if (fatal) {
|
||||||
|
System.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun showYesNoQuestion(
|
||||||
|
editor: Frame?, title: String?,
|
||||||
|
primary: String?, secondary: String?
|
||||||
|
): Int {
|
||||||
|
if (!Platform.isMacOS()) {
|
||||||
|
return JOptionPane.showConfirmDialog(
|
||||||
|
editor,
|
||||||
|
Toolkit.formatMessage(primary, secondary), //"<html><body>" +
|
||||||
|
//"<b>" + primary + "</b>" +
|
||||||
|
//"<br>" + secondary,
|
||||||
|
title,
|
||||||
|
JOptionPane.YES_NO_OPTION,
|
||||||
|
JOptionPane.QUESTION_MESSAGE
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
val result = showCustomQuestion(
|
||||||
|
editor, title, primary, secondary,
|
||||||
|
0, "Yes", "No"
|
||||||
|
)
|
||||||
|
return if (result == 0) {
|
||||||
|
JOptionPane.YES_OPTION
|
||||||
|
} else if (result == 1) {
|
||||||
|
JOptionPane.NO_OPTION
|
||||||
|
} else {
|
||||||
|
JOptionPane.CLOSED_OPTION
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param highlight A valid array index for options[] that specifies the
|
||||||
|
* default (i.e. safe) choice.
|
||||||
|
* @return The (zero-based) index of the selected value, -1 otherwise.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun showCustomQuestion(
|
||||||
|
editor: Frame?, title: String?,
|
||||||
|
primary: String?, secondary: String?,
|
||||||
|
highlight: Int, vararg options: String
|
||||||
|
): Int {
|
||||||
|
val result: Any
|
||||||
|
if (!Platform.isMacOS()) {
|
||||||
|
return JOptionPane.showOptionDialog(
|
||||||
|
editor,
|
||||||
|
Toolkit.formatMessage(primary, secondary), title,
|
||||||
|
JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null,
|
||||||
|
options, options[highlight]
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
val pane =
|
||||||
|
JOptionPane(
|
||||||
|
Toolkit.formatMessage(primary, secondary),
|
||||||
|
JOptionPane.QUESTION_MESSAGE
|
||||||
|
)
|
||||||
|
|
||||||
|
pane.options = options
|
||||||
|
|
||||||
|
// highlight the safest option ala apple hig
|
||||||
|
pane.initialValue = options[highlight]
|
||||||
|
|
||||||
|
val dialog = pane.createDialog(editor, null)
|
||||||
|
dialog.isVisible = true
|
||||||
|
|
||||||
|
result = pane.value
|
||||||
|
}
|
||||||
|
for (i in options.indices) {
|
||||||
|
if (result != null && result == options[i]) return i
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
@JvmStatic
|
||||||
|
@Deprecated("Use log() instead")
|
||||||
|
fun log(from: Any, message: String) {
|
||||||
|
if (Base.DEBUG) {
|
||||||
|
val callingClass = Throwable()
|
||||||
|
.stackTrace[2]
|
||||||
|
.className
|
||||||
|
.formatClassName()
|
||||||
|
println("$callingClass: $message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun log(message: String?) {
|
||||||
|
if (Base.DEBUG) {
|
||||||
|
val callingClass = Throwable()
|
||||||
|
.stackTrace[2]
|
||||||
|
.className
|
||||||
|
.formatClassName()
|
||||||
|
println("$callingClass$message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun logf(message: String?, vararg args: Any?) {
|
||||||
|
if (Base.DEBUG) {
|
||||||
|
val callingClass = Throwable()
|
||||||
|
.stackTrace[2]
|
||||||
|
.className
|
||||||
|
.formatClassName()
|
||||||
|
System.out.printf("$callingClass$message", *args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
|
fun err(message: String?, e: Throwable? = null) {
|
||||||
|
if (Base.DEBUG) {
|
||||||
|
if (message != null) {
|
||||||
|
val callingClass = Throwable()
|
||||||
|
.stackTrace[4]
|
||||||
|
.className
|
||||||
|
.formatClassName()
|
||||||
|
System.err.println("$callingClass$message")
|
||||||
|
}
|
||||||
|
e?.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions to give the base classes a color
|
||||||
|
fun String.formatClassName() = this
|
||||||
|
.replace("processing.", "")
|
||||||
|
.replace(".", "/")
|
||||||
|
.padEnd(40)
|
||||||
|
.colorizePathParts()
|
||||||
|
fun String.colorizePathParts() = split("/").joinToString("/") { part ->
|
||||||
|
"\u001B[${31 + (part.hashCode() and 0x7).rem(6)}m$part\u001B[0m"
|
||||||
|
}
|
||||||
@@ -577,18 +577,25 @@ public class Platform {
|
|||||||
|
|
||||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These methods were refactored to use the Preferences system instead of
|
||||||
|
* actual environment variables, since modifying environment variables at runtime
|
||||||
|
* proved problematic. This approach provides similar functionality
|
||||||
|
* while being compatible with various platforms and execution environments.
|
||||||
|
*
|
||||||
|
* This abstraction maintains a consistent API for environment-like variable storage
|
||||||
|
* while implementing it differently under the hood to work around runtime limitations.
|
||||||
|
*/
|
||||||
|
|
||||||
static public void setenv(String variable, String value) {
|
static public void setenv(String variable, String value) {
|
||||||
inst.setenv(variable, value);
|
Preferences.set(variable, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static public String getenv(String variable) {
|
static public String getenv(String variable) {
|
||||||
return inst.getenv(variable);
|
return Preferences.get(variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static public int unsetenv(String variable) {
|
static public int unsetenv(String variable) {
|
||||||
return inst.unsetenv(variable);
|
throw new RuntimeException("unsetenv() not yet implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-16
@@ -1,11 +1,10 @@
|
|||||||
package processing.app.contrib.ui
|
package processing.app
|
||||||
|
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import processing.app.Base
|
|
||||||
import processing.app.Platform
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
import java.nio.file.*
|
import java.nio.file.*
|
||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
|
|
||||||
@@ -13,10 +12,13 @@ import java.util.Properties
|
|||||||
const val PREFERENCES_FILE_NAME = "preferences.txt"
|
const val PREFERENCES_FILE_NAME = "preferences.txt"
|
||||||
const val DEFAULTS_FILE_NAME = "defaults.txt"
|
const val DEFAULTS_FILE_NAME = "defaults.txt"
|
||||||
|
|
||||||
|
fun PlatformStart(){
|
||||||
|
Platform.inst ?: Platform.init()
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun loadPreferences(): Properties{
|
fun loadPreferences(): Properties{
|
||||||
Platform.init()
|
PlatformStart()
|
||||||
|
|
||||||
val settingsFolder = Platform.getSettingsFolder()
|
val settingsFolder = Platform.getSettingsFolder()
|
||||||
val preferencesFile = settingsFolder.resolve(PREFERENCES_FILE_NAME)
|
val preferencesFile = settingsFolder.resolve(PREFERENCES_FILE_NAME)
|
||||||
@@ -24,20 +26,12 @@ fun loadPreferences(): Properties{
|
|||||||
if(!preferencesFile.exists()){
|
if(!preferencesFile.exists()){
|
||||||
preferencesFile.createNewFile()
|
preferencesFile.createNewFile()
|
||||||
}
|
}
|
||||||
val watched = watchFile(preferencesFile)
|
watchFile(preferencesFile)
|
||||||
|
|
||||||
val preferences by remember {
|
return Properties().apply {
|
||||||
mutableStateOf(Properties())
|
load(ClassLoader.getSystemResourceAsStream(DEFAULTS_FILE_NAME) ?: InputStream.nullInputStream())
|
||||||
|
load(preferencesFile.inputStream())
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(watched){
|
|
||||||
val defaults = Base::class.java.getResourceAsStream("/lib/${DEFAULTS_FILE_NAME}") ?: return@LaunchedEffect
|
|
||||||
|
|
||||||
preferences.load(defaults)
|
|
||||||
preferences.load(preferencesFile.inputStream())
|
|
||||||
}
|
|
||||||
|
|
||||||
return preferences
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -68,4 +62,12 @@ fun watchFile(file: File): Any? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return event
|
return event
|
||||||
|
}
|
||||||
|
val LocalPreferences = compositionLocalOf<Properties> { error("No preferences provided") }
|
||||||
|
@Composable
|
||||||
|
fun PreferencesProvider(content: @Composable () -> Unit){
|
||||||
|
val preferences = loadPreferences()
|
||||||
|
CompositionLocalProvider(LocalPreferences provides preferences){
|
||||||
|
content()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,11 @@ class Schema {
|
|||||||
private fun handleSketchUrl(uri: URI): Editor?{
|
private fun handleSketchUrl(uri: URI): Editor?{
|
||||||
val url = File(uri.path.replace("/url/", ""))
|
val url = File(uri.path.replace("/url/", ""))
|
||||||
|
|
||||||
val tempSketchFolder = File(Base.untitledFolder, url.nameWithoutExtension)
|
val rand = (1..6)
|
||||||
|
.map { (('a'..'z') + ('A'..'Z')).random() }
|
||||||
|
.joinToString("")
|
||||||
|
|
||||||
|
val tempSketchFolder = File(File(Base.untitledFolder, rand), url.nameWithoutExtension)
|
||||||
tempSketchFolder.mkdirs()
|
tempSketchFolder.mkdirs()
|
||||||
val tempSketchFile = File(tempSketchFolder, "${tempSketchFolder.name}.pde")
|
val tempSketchFile = File(tempSketchFolder, "${tempSketchFolder.name}.pde")
|
||||||
|
|
||||||
@@ -71,7 +75,7 @@ class Schema {
|
|||||||
?.map { it.split("=") }
|
?.map { it.split("=") }
|
||||||
?.associate {
|
?.associate {
|
||||||
URLDecoder.decode(it[0], StandardCharsets.UTF_8) to
|
URLDecoder.decode(it[0], StandardCharsets.UTF_8) to
|
||||||
URLDecoder.decode(it[1], StandardCharsets.UTF_8)
|
URLDecoder.decode(it[1], StandardCharsets.UTF_8)
|
||||||
}
|
}
|
||||||
?: emptyMap()
|
?: emptyMap()
|
||||||
options["data"]?.let{ data ->
|
options["data"]?.let{ data ->
|
||||||
@@ -81,7 +85,7 @@ class Schema {
|
|||||||
downloadFiles(uri, code, File(sketchFolder, "code"))
|
downloadFiles(uri, code, File(sketchFolder, "code"))
|
||||||
}
|
}
|
||||||
options["pde"]?.let{ pde ->
|
options["pde"]?.let{ pde ->
|
||||||
downloadFiles(uri, pde, sketchFolder)
|
downloadFiles(uri, pde, sketchFolder, "pde")
|
||||||
}
|
}
|
||||||
options["mode"]?.let{ mode ->
|
options["mode"]?.let{ mode ->
|
||||||
val modeFile = File(sketchFolder, "sketch.properties")
|
val modeFile = File(sketchFolder, "sketch.properties")
|
||||||
@@ -89,7 +93,7 @@ class Schema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
private fun downloadFiles(uri: URI, urlList: String, targetFolder: File){
|
private fun downloadFiles(uri: URI, urlList: String, targetFolder: File, extension: String = ""){
|
||||||
Thread{
|
Thread{
|
||||||
targetFolder.mkdirs()
|
targetFolder.mkdirs()
|
||||||
|
|
||||||
@@ -101,37 +105,31 @@ class Schema {
|
|||||||
val files = urlList.split(",")
|
val files = urlList.split(",")
|
||||||
|
|
||||||
files.filter { it.isNotBlank() }
|
files.filter { it.isNotBlank() }
|
||||||
.map{ it.split(":", limit = 2) }
|
.map {
|
||||||
.map{ segments ->
|
if (it.contains(":")) it
|
||||||
if(segments.size == 2){
|
else "$it:$it"
|
||||||
if(segments[0].isBlank()){
|
|
||||||
return@map listOf(null, segments[1])
|
|
||||||
}
|
|
||||||
return@map segments
|
|
||||||
}
|
|
||||||
return@map listOf(null, segments[0])
|
|
||||||
}
|
}
|
||||||
|
.map{ it.split(":", limit = 2) }
|
||||||
.forEach { (name, content) ->
|
.forEach { (name, content) ->
|
||||||
|
var target = File(targetFolder, name)
|
||||||
|
if(extension.isNotBlank() && target.extension != extension){
|
||||||
|
target = File(targetFolder, "$name.$extension")
|
||||||
|
}
|
||||||
try{
|
try{
|
||||||
// Try to decode the content as base64
|
|
||||||
val file = Base64.getDecoder().decode(content)
|
val file = Base64.getDecoder().decode(content)
|
||||||
if(name == null){
|
if(name.isBlank()){
|
||||||
Messages.err("Base64 files needs to start with a file name followed by a colon")
|
Messages.err("Base64 files needs to start with a file name followed by a colon")
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
File(targetFolder, name).writeBytes(file)
|
target.writeBytes(file)
|
||||||
}catch(_: IllegalArgumentException){
|
}catch(_: IllegalArgumentException){
|
||||||
// Assume it's a URL and download it
|
val url = URL(when{
|
||||||
var url = URI.create(content)
|
content.startsWith("https://") -> content
|
||||||
if(url.host == null){
|
content.startsWith("http://") -> content.replace("http://", "https://")
|
||||||
url = URI.create("https://$base/$content")
|
URL("https://$content").path.isNotBlank() -> "https://$content"
|
||||||
}
|
else -> "https://$base/$content"
|
||||||
if(url.scheme == null){
|
})
|
||||||
url = URI.create("https://$content")
|
url.openStream().use { input ->
|
||||||
}
|
|
||||||
|
|
||||||
val target = File(targetFolder, name ?: url.path.split("/").last())
|
|
||||||
url.toURL().openStream().use { input ->
|
|
||||||
target.outputStream().use { output ->
|
target.outputStream().use { output ->
|
||||||
input.copyTo(output)
|
input.copyTo(output)
|
||||||
}
|
}
|
||||||
@@ -148,7 +146,7 @@ class Schema {
|
|||||||
?.map { it.split("=") }
|
?.map { it.split("=") }
|
||||||
?.associate {
|
?.associate {
|
||||||
URLDecoder.decode(it[0], StandardCharsets.UTF_8) to
|
URLDecoder.decode(it[0], StandardCharsets.UTF_8) to
|
||||||
URLDecoder.decode(it[1], StandardCharsets.UTF_8)
|
URLDecoder.decode(it[1], StandardCharsets.UTF_8)
|
||||||
}
|
}
|
||||||
?: emptyMap()
|
?: emptyMap()
|
||||||
for ((key, value) in options){
|
for ((key, value) in options){
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import java.util.Random;
|
|||||||
|
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
|
import processing.app.ui.WelcomeToBeta;
|
||||||
import processing.core.PApplet;
|
import processing.core.PApplet;
|
||||||
|
|
||||||
|
|
||||||
@@ -116,7 +117,7 @@ public class UpdateCheck {
|
|||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if (lastString != null) {
|
if (lastString != null) {
|
||||||
long when = Long.parseLong(lastString);
|
long when = Long.parseLong(lastString);
|
||||||
if (now - when < ONE_DAY) {
|
if (now - when < ONE_DAY && !Base.DEBUG) {
|
||||||
// don't annoy the shit outta people
|
// don't annoy the shit outta people
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -134,6 +135,9 @@ public class UpdateCheck {
|
|||||||
// offerToUpdateContributions = !promptToVisitDownloadPage();
|
// offerToUpdateContributions = !promptToVisitDownloadPage();
|
||||||
promptToVisitDownloadPage();
|
promptToVisitDownloadPage();
|
||||||
}
|
}
|
||||||
|
if(latest < Base.getRevision()){
|
||||||
|
WelcomeToBeta.showWelcomeToBeta();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (offerToUpdateContributions) {
|
if (offerToUpdateContributions) {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import processing.app.Base;
|
import processing.app.Base;
|
||||||
|
import processing.app.Messages;
|
||||||
import processing.app.UpdateCheck;
|
import processing.app.UpdateCheck;
|
||||||
import processing.app.Util;
|
import processing.app.Util;
|
||||||
import processing.core.PApplet;
|
import processing.core.PApplet;
|
||||||
@@ -228,6 +229,7 @@ public class ContributionListing {
|
|||||||
public void downloadAvailableList(final Base base,
|
public void downloadAvailableList(final Base base,
|
||||||
final ContribProgress progress) {
|
final ContribProgress progress) {
|
||||||
// TODO: replace with SwingWorker [jv]
|
// TODO: replace with SwingWorker [jv]
|
||||||
|
Messages.log("Downloading contributions list from " + LISTING_URL);
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
downloadingLock.lock();
|
downloadingLock.lock();
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.awt.ComposePanel
|
import androidx.compose.ui.awt.ComposePanel
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.key.Key
|
|
||||||
import androidx.compose.ui.input.key.key
|
|
||||||
import androidx.compose.ui.input.pointer.PointerIcon
|
import androidx.compose.ui.input.pointer.PointerIcon
|
||||||
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@@ -25,6 +23,7 @@ import com.charleskorn.kaml.Yaml
|
|||||||
import com.charleskorn.kaml.YamlConfiguration
|
import com.charleskorn.kaml.YamlConfiguration
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import processing.app.Platform
|
import processing.app.Platform
|
||||||
|
import processing.app.loadPreferences
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.swing.JFrame
|
import javax.swing.JFrame
|
||||||
@@ -33,16 +32,7 @@ import kotlin.io.path.*
|
|||||||
|
|
||||||
|
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
val active = remember { mutableStateOf(true) }
|
Window(onCloseRequest = ::exitApplication) {
|
||||||
if(!active.value){
|
|
||||||
Window(onCloseRequest = ::exitApplication) {
|
|
||||||
|
|
||||||
}
|
|
||||||
return@application
|
|
||||||
}
|
|
||||||
Window(
|
|
||||||
onCloseRequest = { active.value = false },
|
|
||||||
) {
|
|
||||||
contributionsManager()
|
contributionsManager()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import processing.app.Base;
|
import processing.app.Base;
|
||||||
|
import processing.app.Messages;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,8 +80,7 @@ public class StreamPump implements Runnable {
|
|||||||
}
|
}
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
if (Base.DEBUG) {
|
if (Base.DEBUG) {
|
||||||
System.err.println("StreamPump: " + name);
|
Messages.err("StreamPump: " + name, e);
|
||||||
e.printStackTrace(System.err);
|
|
||||||
// removing for 0190, but need a better way to handle these
|
// removing for 0190, but need a better way to handle these
|
||||||
throw new RuntimeException("Inside " + this + " for " + name, e);
|
throw new RuntimeException("Inside " + this + " for " + name, e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,31 +257,31 @@ public class DefaultPlatform {
|
|||||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|
||||||
|
|
||||||
public interface CLibrary extends Library {
|
// public interface CLibrary extends Library {
|
||||||
CLibrary INSTANCE = Native.load("c", CLibrary.class);
|
// CLibrary INSTANCE = Native.load("c", CLibrary.class);
|
||||||
int setenv(String name, String value, int overwrite);
|
// int setenv(String name, String value, int overwrite);
|
||||||
String getenv(String name);
|
// String getenv(String name);
|
||||||
int unsetenv(String name);
|
// int unsetenv(String name);
|
||||||
int putenv(String string);
|
// int putenv(String string);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
public void setenv(String variable, String value) {
|
// public void setenv(String variable, String value) {
|
||||||
CLibrary clib = CLibrary.INSTANCE;
|
// CLibrary clib = CLibrary.INSTANCE;
|
||||||
clib.setenv(variable, value, 1);
|
// clib.setenv(variable, value, 1);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
public String getenv(String variable) {
|
// public String getenv(String variable) {
|
||||||
CLibrary clib = CLibrary.INSTANCE;
|
// CLibrary clib = CLibrary.INSTANCE;
|
||||||
return clib.getenv(variable);
|
// return clib.getenv(variable);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
public int unsetenv(String variable) {
|
// public int unsetenv(String variable) {
|
||||||
CLibrary clib = CLibrary.INSTANCE;
|
// CLibrary clib = CLibrary.INSTANCE;
|
||||||
return clib.unsetenv(variable);
|
// return clib.unsetenv(variable);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ import processing.core.PApplet;
|
|||||||
|
|
||||||
|
|
||||||
public class LinuxPlatform extends DefaultPlatform {
|
public class LinuxPlatform extends DefaultPlatform {
|
||||||
String homeDir;
|
// Switched to use ~ as the home directory for compatibility with snap
|
||||||
|
String homeDir = "~";
|
||||||
|
|
||||||
|
|
||||||
public void initBase(Base base) {
|
public void initBase(Base base) {
|
||||||
@@ -98,7 +99,7 @@ public class LinuxPlatform extends DefaultPlatform {
|
|||||||
File configHome = null;
|
File configHome = null;
|
||||||
|
|
||||||
// Check to see if the user has set a different location for their config
|
// Check to see if the user has set a different location for their config
|
||||||
String configHomeEnv = getenv("XDG_CONFIG_HOME");
|
String configHomeEnv = System.getenv("XDG_CONFIG_HOME");
|
||||||
if (configHomeEnv != null && !configHomeEnv.isBlank()) {
|
if (configHomeEnv != null && !configHomeEnv.isBlank()) {
|
||||||
configHome = new File(configHomeEnv);
|
configHome = new File(configHomeEnv);
|
||||||
if (!configHome.exists()) {
|
if (!configHome.exists()) {
|
||||||
|
|||||||
@@ -79,9 +79,7 @@ public class InputMethodSupport implements InputMethodRequests, InputMethodListe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Rectangle getTextLocation(TextHitInfo offset) {
|
public Rectangle getTextLocation(TextHitInfo offset) {
|
||||||
if (Base.DEBUG) {
|
Messages.log("#Called getTextLocation:" + offset);
|
||||||
Messages.log("#Called getTextLocation:" + offset);
|
|
||||||
}
|
|
||||||
int line = textArea.getCaretLine();
|
int line = textArea.getCaretLine();
|
||||||
int offsetX = textArea.getCaretPosition() - textArea.getLineStartOffset(line);
|
int offsetX = textArea.getCaretPosition() - textArea.getLineStartOffset(line);
|
||||||
// '+1' mean textArea.lineToY(line) + textArea.getPainter().getFontMetrics().getHeight().
|
// '+1' mean textArea.lineToY(line) + textArea.getPainter().getFontMetrics().getHeight().
|
||||||
@@ -238,9 +236,7 @@ public class InputMethodSupport implements InputMethodRequests, InputMethodListe
|
|||||||
RenderingHints.VALUE_TEXT_ANTIALIAS_ON :
|
RenderingHints.VALUE_TEXT_ANTIALIAS_ON :
|
||||||
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
|
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
|
||||||
FontRenderContext frc = g2d.getFontRenderContext();
|
FontRenderContext frc = g2d.getFontRenderContext();
|
||||||
if (Base.DEBUG) {
|
Messages.log("debug: FontRenderContext is Antialiased = " + frc.getAntiAliasingHint());
|
||||||
Messages.log("debug: FontRenderContext is Antialiased = " + frc.getAntiAliasingHint());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TextLayout(composedTextString.getIterator(), frc);
|
return new TextLayout(composedTextString.getIterator(), frc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,7 +276,9 @@ public class EditorConsole extends JScrollPane {
|
|||||||
// components, causing deadlock. Updates are buffered to the console and
|
// components, causing deadlock. Updates are buffered to the console and
|
||||||
// displayed at regular intervals on Swing's event-dispatching thread.
|
// displayed at regular intervals on Swing's event-dispatching thread.
|
||||||
// (patch by David Mellis)
|
// (patch by David Mellis)
|
||||||
consoleDoc.appendString(what, err ? errStyle : stdStyle);
|
// Remove ANSI escape codes from the text before adding it to the console
|
||||||
|
String clean = what.replaceAll("\u001B\\[[0-9;]*m", "");
|
||||||
|
consoleDoc.appendString(clean, err ? errStyle : stdStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
package processing.app.ui
|
||||||
|
|
||||||
|
import androidx.compose.animation.animateColorAsState
|
||||||
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.MaterialTheme.colors
|
||||||
|
import androidx.compose.material.MaterialTheme.typography
|
||||||
|
import androidx.compose.material.Surface
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.awt.ComposePanel
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.input.pointer.PointerEventType
|
||||||
|
import androidx.compose.ui.input.pointer.PointerIcon
|
||||||
|
import androidx.compose.ui.input.pointer.onPointerEvent
|
||||||
|
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.DpSize
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.window.Window
|
||||||
|
import androidx.compose.ui.window.WindowPosition
|
||||||
|
import androidx.compose.ui.window.application
|
||||||
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo
|
||||||
|
import com.mikepenz.markdown.compose.Markdown
|
||||||
|
import com.mikepenz.markdown.m2.markdownColor
|
||||||
|
import com.mikepenz.markdown.m2.markdownTypography
|
||||||
|
import com.mikepenz.markdown.model.MarkdownColors
|
||||||
|
import com.mikepenz.markdown.model.MarkdownTypography
|
||||||
|
import processing.app.Base.getRevision
|
||||||
|
import processing.app.Base.getVersionName
|
||||||
|
import processing.app.ui.theme.LocalLocale
|
||||||
|
import processing.app.ui.theme.LocalTheme
|
||||||
|
import processing.app.ui.theme.Locale
|
||||||
|
import processing.app.ui.theme.ProcessingTheme
|
||||||
|
import java.awt.Cursor
|
||||||
|
import java.awt.Dimension
|
||||||
|
import java.awt.event.KeyAdapter
|
||||||
|
import java.awt.event.KeyEvent
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.Properties
|
||||||
|
import javax.swing.JFrame
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
|
|
||||||
|
class WelcomeToBeta {
|
||||||
|
companion object{
|
||||||
|
val windowSize = Dimension(400, 200)
|
||||||
|
val windowTitle = Locale()["beta.window.title"]
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun showWelcomeToBeta() {
|
||||||
|
val mac = SystemInfo.isMacFullWindowContentSupported
|
||||||
|
SwingUtilities.invokeLater {
|
||||||
|
JFrame(windowTitle).apply {
|
||||||
|
val close = { dispose() }
|
||||||
|
rootPane.putClientProperty("apple.awt.transparentTitleBar", mac)
|
||||||
|
rootPane.putClientProperty("apple.awt.fullWindowContent", mac)
|
||||||
|
defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE
|
||||||
|
contentPane.add(ComposePanel().apply {
|
||||||
|
size = windowSize
|
||||||
|
setContent {
|
||||||
|
ProcessingTheme {
|
||||||
|
Box(modifier = Modifier.padding(top = if (mac) 22.dp else 0.dp)) {
|
||||||
|
welcomeToBeta(close)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
pack()
|
||||||
|
background = java.awt.Color.white
|
||||||
|
setLocationRelativeTo(null)
|
||||||
|
addKeyListener(object : KeyAdapter() {
|
||||||
|
override fun keyPressed(e: KeyEvent) {
|
||||||
|
if (e.keyCode == KeyEvent.VK_ESCAPE) close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
isResizable = false
|
||||||
|
isVisible = true
|
||||||
|
requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun welcomeToBeta(close: () -> Unit = {}) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(20.dp, 10.dp)
|
||||||
|
.size(windowSize.width.dp, windowSize.height.dp),
|
||||||
|
horizontalArrangement = Arrangement
|
||||||
|
.spacedBy(20.dp)
|
||||||
|
){
|
||||||
|
val locale = LocalLocale.current
|
||||||
|
Image(
|
||||||
|
painter = painterResource("bird.svg"),
|
||||||
|
contentDescription = locale["beta.logo"],
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterVertically)
|
||||||
|
.size(100.dp, 100.dp)
|
||||||
|
.offset(0.dp, (-25).dp)
|
||||||
|
)
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight(),
|
||||||
|
verticalArrangement = Arrangement
|
||||||
|
.spacedBy(
|
||||||
|
10.dp,
|
||||||
|
alignment = Alignment.CenterVertically
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = locale["beta.title"],
|
||||||
|
style = typography.subtitle1,
|
||||||
|
)
|
||||||
|
val text = locale["beta.message"]
|
||||||
|
.replace('$' + "version", getVersionName())
|
||||||
|
.replace('$' + "revision", getRevision().toString())
|
||||||
|
Markdown(
|
||||||
|
text,
|
||||||
|
colors = markdownColor(),
|
||||||
|
typography = markdownTypography(text = typography.body1, link = typography.body1.copy(color = colors.primary)),
|
||||||
|
modifier = Modifier.background(Color.Transparent).padding(bottom = 10.dp)
|
||||||
|
)
|
||||||
|
Row {
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
PDEButton(onClick = {
|
||||||
|
close()
|
||||||
|
}) {
|
||||||
|
Text(
|
||||||
|
text = locale["beta.button"],
|
||||||
|
color = colors.onPrimary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
|
@Composable
|
||||||
|
fun PDEButton(onClick: () -> Unit, content: @Composable BoxScope.() -> Unit) {
|
||||||
|
val theme = LocalTheme.current
|
||||||
|
|
||||||
|
var hover by remember { mutableStateOf(false) }
|
||||||
|
var clicked by remember { mutableStateOf(false) }
|
||||||
|
val offset by animateFloatAsState(if (hover) -5f else 5f)
|
||||||
|
val color by animateColorAsState(if(clicked) colors.primaryVariant else colors.primary)
|
||||||
|
|
||||||
|
Box(modifier = Modifier.padding(end = 5.dp, top = 5.dp)) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.offset((-offset).dp, (offset).dp)
|
||||||
|
.background(theme.getColor("toolbar.button.pressed.field"))
|
||||||
|
.matchParentSize()
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.onPointerEvent(PointerEventType.Press) {
|
||||||
|
clicked = true
|
||||||
|
}
|
||||||
|
.onPointerEvent(PointerEventType.Release) {
|
||||||
|
clicked = false
|
||||||
|
onClick()
|
||||||
|
}
|
||||||
|
.onPointerEvent(PointerEventType.Enter) {
|
||||||
|
hover = true
|
||||||
|
}
|
||||||
|
.onPointerEvent(PointerEventType.Exit) {
|
||||||
|
hover = false
|
||||||
|
}
|
||||||
|
.pointerHoverIcon(PointerIcon(Cursor(Cursor.HAND_CURSOR)))
|
||||||
|
.background(color)
|
||||||
|
.padding(10.dp)
|
||||||
|
.sizeIn(minWidth = 100.dp),
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
application {
|
||||||
|
val windowState = rememberWindowState(
|
||||||
|
size = DpSize.Unspecified,
|
||||||
|
position = WindowPosition(Alignment.Center)
|
||||||
|
)
|
||||||
|
|
||||||
|
Window(onCloseRequest = ::exitApplication, state = windowState, title = windowTitle) {
|
||||||
|
ProcessingTheme {
|
||||||
|
Surface(color = colors.background) {
|
||||||
|
welcomeToBeta {
|
||||||
|
exitApplication()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package processing.app.ui.theme
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.compositionLocalOf
|
||||||
|
import processing.app.LocalPreferences
|
||||||
|
import processing.app.Messages
|
||||||
|
import processing.app.Platform
|
||||||
|
import processing.app.PlatformStart
|
||||||
|
import processing.app.watchFile
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class Locale(language: String = "") : Properties() {
|
||||||
|
init {
|
||||||
|
val locale = java.util.Locale.getDefault()
|
||||||
|
load(ClassLoader.getSystemResourceAsStream("PDE.properties"))
|
||||||
|
load(ClassLoader.getSystemResourceAsStream("PDE_${locale.language}.properties") ?: InputStream.nullInputStream())
|
||||||
|
load(ClassLoader.getSystemResourceAsStream("PDE_${locale.toLanguageTag()}.properties") ?: InputStream.nullInputStream())
|
||||||
|
load(ClassLoader.getSystemResourceAsStream("PDE_${language}.properties") ?: InputStream.nullInputStream())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use get instead", ReplaceWith("get(key)"))
|
||||||
|
override fun getProperty(key: String?, default: String): String {
|
||||||
|
val value = super.getProperty(key, default)
|
||||||
|
if(value == default) Messages.log("Missing translation for $key")
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
operator fun get(key: String): String = getProperty(key, key)
|
||||||
|
}
|
||||||
|
val LocalLocale = compositionLocalOf { Locale() }
|
||||||
|
@Composable
|
||||||
|
fun LocaleProvider(content: @Composable () -> Unit) {
|
||||||
|
PlatformStart()
|
||||||
|
|
||||||
|
val settingsFolder = Platform.getSettingsFolder()
|
||||||
|
val languageFile = File(settingsFolder, "language.txt")
|
||||||
|
watchFile(languageFile)
|
||||||
|
|
||||||
|
val locale = Locale(languageFile.readText().substring(0, 2))
|
||||||
|
CompositionLocalProvider(LocalLocale provides locale) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package processing.app.ui.theme
|
||||||
|
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.material.Colors
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.compositionLocalOf
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import processing.app.LocalPreferences
|
||||||
|
import processing.app.PreferencesProvider
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.util.Properties
|
||||||
|
|
||||||
|
|
||||||
|
class Theme(themeFile: String? = "") : Properties() {
|
||||||
|
init {
|
||||||
|
load(ClassLoader.getSystemResourceAsStream("theme.txt"))
|
||||||
|
load(ClassLoader.getSystemResourceAsStream(themeFile) ?: InputStream.nullInputStream())
|
||||||
|
}
|
||||||
|
fun getColor(key: String): Color {
|
||||||
|
return Color(getProperty(key).toColorInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val LocalTheme = compositionLocalOf<Theme> { error("No theme provided") }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ProcessingTheme(
|
||||||
|
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||||
|
content: @Composable() () -> Unit
|
||||||
|
) {
|
||||||
|
PreferencesProvider {
|
||||||
|
val preferences = LocalPreferences.current
|
||||||
|
val theme = Theme(preferences.getProperty("theme"))
|
||||||
|
val colors = Colors(
|
||||||
|
primary = theme.getColor("editor.gradient.top"),
|
||||||
|
primaryVariant = theme.getColor("toolbar.button.pressed.field"),
|
||||||
|
secondary = theme.getColor("editor.gradient.bottom"),
|
||||||
|
secondaryVariant = theme.getColor("editor.scrollbar.thumb.pressed.color"),
|
||||||
|
background = theme.getColor("editor.bgcolor"),
|
||||||
|
surface = theme.getColor("editor.bgcolor"),
|
||||||
|
error = theme.getColor("status.error.bgcolor"),
|
||||||
|
onPrimary = theme.getColor("toolbar.button.enabled.field"),
|
||||||
|
onSecondary = theme.getColor("toolbar.button.enabled.field"),
|
||||||
|
onBackground = theme.getColor("editor.fgcolor"),
|
||||||
|
onSurface = theme.getColor("editor.fgcolor"),
|
||||||
|
onError = theme.getColor("status.error.fgcolor"),
|
||||||
|
isLight = theme.getProperty("laf.mode").equals("light")
|
||||||
|
)
|
||||||
|
|
||||||
|
CompositionLocalProvider(LocalTheme provides theme) {
|
||||||
|
LocaleProvider {
|
||||||
|
MaterialTheme(
|
||||||
|
colors = colors,
|
||||||
|
typography = Typography,
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.toColorInt(): Int {
|
||||||
|
if (this[0] == '#') {
|
||||||
|
var color = substring(1).toLong(16)
|
||||||
|
if (length == 7) {
|
||||||
|
color = color or 0x00000000ff000000L
|
||||||
|
} else if (length != 9) {
|
||||||
|
throw IllegalArgumentException("Unknown color")
|
||||||
|
}
|
||||||
|
return color.toInt()
|
||||||
|
}
|
||||||
|
throw IllegalArgumentException("Unknown color")
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package processing.app.ui.theme
|
||||||
|
|
||||||
|
import androidx.compose.material.MaterialTheme.typography
|
||||||
|
import androidx.compose.material.Typography
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.platform.Font
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
val processingFont = FontFamily(
|
||||||
|
Font(
|
||||||
|
resource = "ProcessingSans-Regular.ttf",
|
||||||
|
weight = FontWeight.Normal,
|
||||||
|
style = FontStyle.Normal
|
||||||
|
),
|
||||||
|
Font(
|
||||||
|
resource = "ProcessingSans-Bold.ttf",
|
||||||
|
weight = FontWeight.Bold,
|
||||||
|
style = FontStyle.Normal
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val Typography = Typography(
|
||||||
|
body1 = TextStyle(
|
||||||
|
fontFamily = processingFont,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
fontSize = 13.sp,
|
||||||
|
lineHeight = 16.sp
|
||||||
|
),
|
||||||
|
subtitle1 = TextStyle(
|
||||||
|
fontFamily = processingFont,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
lineHeight = 20.sp
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package processing.app
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource
|
||||||
|
import org.mockito.ArgumentCaptor
|
||||||
|
import org.mockito.MockedStatic
|
||||||
|
import org.mockito.Mockito.mockStatic
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.verify
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.io.encoding.Base64
|
||||||
|
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
|
||||||
|
class SchemaTest {
|
||||||
|
private val base: Base = mock<Base>{
|
||||||
|
|
||||||
|
}
|
||||||
|
companion object {
|
||||||
|
val preferences: MockedStatic<Preferences> = mockStatic(Preferences::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testLocalFiles() {
|
||||||
|
val file = "/this/is/a/local/file"
|
||||||
|
Schema.handleSchema("pde://$file", base)
|
||||||
|
verify(base).handleOpen(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNewSketch() {
|
||||||
|
Schema.handleSchema("pde://sketch/new", base)
|
||||||
|
verify(base).handleNew()
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalEncodingApi::class)
|
||||||
|
@Test
|
||||||
|
fun testBase64SketchAndExtraFiles() {
|
||||||
|
val sketch = """
|
||||||
|
void setup(){
|
||||||
|
|
||||||
|
}
|
||||||
|
void draw(){
|
||||||
|
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val base64 = Base64.encode(sketch.toByteArray())
|
||||||
|
Schema.handleSchema("pde://sketch/base64/$base64?pde=AnotherFile:$base64", base)
|
||||||
|
val captor = ArgumentCaptor.forClass(String::class.java)
|
||||||
|
|
||||||
|
verify(base).handleOpenUntitled(captor.capture())
|
||||||
|
|
||||||
|
val file = File(captor.value)
|
||||||
|
assert(file.exists())
|
||||||
|
assert(file.readText() == sketch)
|
||||||
|
|
||||||
|
val extra = file.parentFile.resolve("AnotherFile.pde")
|
||||||
|
assert(extra.exists())
|
||||||
|
assert(extra.readText() == sketch)
|
||||||
|
file.parentFile.deleteRecursively()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testURLSketch() {
|
||||||
|
Schema.handleSchema("pde://sketch/url/github.com/processing/processing-examples/raw/refs/heads/main/Basics/Arrays/Array/Array.pde", base)
|
||||||
|
|
||||||
|
val captor = ArgumentCaptor.forClass(String::class.java)
|
||||||
|
verify(base).handleOpenUntitled(captor.capture())
|
||||||
|
val output = File(captor.value)
|
||||||
|
assert(output.exists())
|
||||||
|
assert(output.name == "Array.pde")
|
||||||
|
assert(output.extension == "pde")
|
||||||
|
assert(output.parentFile.name == "Array")
|
||||||
|
|
||||||
|
output.parentFile.parentFile.deleteRecursively()
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = [
|
||||||
|
"Module.pde:https://github.com/processing/processing-examples/raw/refs/heads/main/Basics/Arrays/ArrayObjects/Module.pde",
|
||||||
|
"Module.pde",
|
||||||
|
"Module:Module.pde",
|
||||||
|
"Module:https://github.com/processing/processing-examples/raw/refs/heads/main/Basics/Arrays/ArrayObjects/Module.pde",
|
||||||
|
"Module.pde:github.com/processing/processing-examples/raw/refs/heads/main/Basics/Arrays/ArrayObjects/Module.pde"
|
||||||
|
])
|
||||||
|
fun testURLSketchWithFile(file: String){
|
||||||
|
Schema.handleSchema("pde://sketch/url/github.com/processing/processing-examples/raw/refs/heads/main/Basics/Arrays/ArrayObjects/ArrayObjects.pde?pde=$file", base)
|
||||||
|
|
||||||
|
val captor = ArgumentCaptor.forClass(String::class.java)
|
||||||
|
verify(base).handleOpenUntitled(captor.capture())
|
||||||
|
|
||||||
|
// wait for threads to resolve
|
||||||
|
Thread.sleep(1000)
|
||||||
|
|
||||||
|
val output = File(captor.value)
|
||||||
|
assert(output.parentFile.name == "ArrayObjects")
|
||||||
|
assert(output.exists())
|
||||||
|
assert(output.parentFile.resolve("Module.pde").exists())
|
||||||
|
output.parentFile.parentFile.deleteRecursively()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPreferences() {
|
||||||
|
Schema.handleSchema("pde://preferences?test=value", base)
|
||||||
|
preferences.verify {
|
||||||
|
Preferences.set("test", "value")
|
||||||
|
Preferences.save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="WixToolset.Sdk/5.0.1">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputPath>..\build\compose\binaries\main\msi</OutputPath>
|
||||||
|
<OutputName>Processing-$(Version)</OutputName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="WixToolset.UI.wixext" Version="5.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
|
||||||
|
<Package Name="Processing" Manufacturer="Processing Foundation" Version="$(Version)" UpgradeCode="89d8d7fe-5602-4b12-ba10-0fe78efbd602">
|
||||||
|
<Icon Id="icon.ico" SourceFile="..\..\build\windows\processing.ico" />
|
||||||
|
<Property Id="ARPPRODUCTICON" Value="icon.ico" />
|
||||||
|
|
||||||
|
<MediaTemplate EmbedCab="yes" />
|
||||||
|
|
||||||
|
<ui:WixUI Id="WixUI_Mondo" InstallDirectory="INSTALLFOLDER" />
|
||||||
|
|
||||||
|
<WixVariable Id="WixUILicenseRtf" Value="LICENSE.rtf" />
|
||||||
|
<WixVariable Id="WixUIDialogBmp" Value="background.png" />
|
||||||
|
<WixVariable Id="WixUIBannerBmp" Value="banner.png" />
|
||||||
|
<Feature Id="MainApplication" Title="Processing" Level="1">
|
||||||
|
<Files Include="..\build\compose\binaries\main\app\Processing\**" />
|
||||||
|
<ComponentRef Id="ApplicationShortcut" />
|
||||||
|
</Feature>
|
||||||
|
<Directory Id="ProgramMenuFolder">
|
||||||
|
<Directory Id="ApplicationProgramsFolder" Name="Processing"/>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="ProgramFiles64Folder">
|
||||||
|
<Directory Id="INSTALLFOLDER" Name="Processing">
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
<Component Id="ApplicationShortcut" Guid="b15e6d69-f054-4ec2-aade-8e3756b537d6">
|
||||||
|
<Shortcut Id="ApplicationStartMenuShortcut"
|
||||||
|
Name="Processing"
|
||||||
|
Description="My Application Description"
|
||||||
|
Directory="ApplicationProgramsFolder"
|
||||||
|
Target="[INSTALLFOLDER]\Processing.exe"
|
||||||
|
WorkingDirectory="INSTALLFOLDER"/>
|
||||||
|
<RemoveFolder Id="CleanUpShortCut" Directory="ApplicationProgramsFolder" On="uninstall"/>
|
||||||
|
<RegistryValue Root="HKCU" Key="Software\Processing Foundation\Processing" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
|
||||||
|
</Component>
|
||||||
|
</Package>
|
||||||
|
</Wix>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
@@ -1,6 +1,3 @@
|
|||||||
group = "org.processing"
|
|
||||||
version = "4.4.0"
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version libs.versions.kotlin apply false
|
kotlin("jvm") version libs.versions.kotlin apply false
|
||||||
alias(libs.plugins.kotlinMultiplatform) apply false
|
alias(libs.plugins.kotlinMultiplatform) apply false
|
||||||
|
|||||||
@@ -613,7 +613,6 @@ update_check = Update
|
|||||||
update_check.updates_available.core = A new version of Processing is available,\nwould you like to visit the Processing download page?
|
update_check.updates_available.core = A new version of Processing is available,\nwould you like to visit the Processing download page?
|
||||||
update_check.updates_available.contributions = There are updates available for some of the installed contributions,\nwould you like to open the the Contribution Manager now?
|
update_check.updates_available.contributions = There are updates available for some of the installed contributions,\nwould you like to open the the Contribution Manager now?
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
# Color Chooser
|
# Color Chooser
|
||||||
|
|
||||||
|
|||||||
@@ -315,6 +315,13 @@ update_check = Update
|
|||||||
update_check.updates_available.core = Een nieuwe versie van Processing is beschikbaar,\nwilt u de Processing download pagina bezoeken?
|
update_check.updates_available.core = Een nieuwe versie van Processing is beschikbaar,\nwilt u de Processing download pagina bezoeken?
|
||||||
update_check.updates_available.contributions = Er zijn updates beschikbaar voor sommige van de door u geïnstalleerde bijdragen,\nwilt u nu de Bijdragen Manager openen?
|
update_check.updates_available.contributions = Er zijn updates beschikbaar voor sommige van de door u geïnstalleerde bijdragen,\nwilt u nu de Bijdragen Manager openen?
|
||||||
|
|
||||||
|
# ---------------------------------------
|
||||||
|
# Beta
|
||||||
|
beta.window.title = Welkom bij Beta
|
||||||
|
beta.title = Welkom bij de Processing Beta
|
||||||
|
beta.message = Bedankt dat je de nieuwe versie van Processing uitprobeert. We zijn je zeer dankbaar!\n\nMeld eventuele bugs alsjeblieft op de forums.
|
||||||
|
beta.button = Okee!
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
# Color Chooser
|
# Color Chooser
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ dependencies {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Developing for Core
|
## Developing for Core
|
||||||
The easiest way to develop for core, without the need to build the whole project, is to use the `examples/src` sketches. In
|
The easiest way to develop for core, without the need to build the whole project, is to use the `examples/src` sketches.
|
||||||
|
|
||||||
## PGraphics Modes
|
## PGraphics Modes
|
||||||
Documentation on how to develop graphics modes as a library should go here.
|
Documentation on how to develop graphics modes as a library should go here.
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ plugins {
|
|||||||
alias(libs.plugins.mavenPublish)
|
alias(libs.plugins.mavenPublish)
|
||||||
}
|
}
|
||||||
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url = uri("https://jogamp.org/deployment/maven") }
|
maven { url = uri("https://jogamp.org/deployment/maven") }
|
||||||
@@ -23,6 +21,11 @@ sourceSets{
|
|||||||
exclude("**/*.java")
|
exclude("**/*.java")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
test{
|
||||||
|
java{
|
||||||
|
srcDirs("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -70,4 +73,7 @@ tasks.test {
|
|||||||
}
|
}
|
||||||
tasks.withType<Jar> {
|
tasks.withType<Jar> {
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
}
|
}
|
||||||
|
tasks.compileJava{
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,17 +3,21 @@ kotlin = "2.0.20"
|
|||||||
compose-plugin = "1.7.1"
|
compose-plugin = "1.7.1"
|
||||||
jogl = "2.5.0"
|
jogl = "2.5.0"
|
||||||
antlr = "4.13.2"
|
antlr = "4.13.2"
|
||||||
|
jupiter = "5.12.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
jogl = { module = "org.jogamp.jogl:jogl-all-main", version.ref = "jogl" }
|
jogl = { module = "org.jogamp.jogl:jogl-all-main", version.ref = "jogl" }
|
||||||
gluegen = { module = "org.jogamp.gluegen:gluegen-rt-main", version.ref = "jogl" }
|
gluegen = { module = "org.jogamp.gluegen:gluegen-rt-main", version.ref = "jogl" }
|
||||||
flatlaf = { module = "com.formdev:flatlaf", version = "3.4.1" }
|
flatlaf = { module = "com.formdev:flatlaf", version = "2.4" }
|
||||||
jna = { module = "net.java.dev.jna:jna", version = "5.12.1" }
|
jna = { module = "net.java.dev.jna:jna", version = "5.12.1" }
|
||||||
jnaplatform = { module = "net.java.dev.jna:jna-platform", version = "5.12.1" }
|
jnaplatform = { module = "net.java.dev.jna:jna-platform", version = "5.12.1" }
|
||||||
compottie = { module = "io.github.alexzhirkevich:compottie", version = "2.0.0-rc02" }
|
compottie = { module = "io.github.alexzhirkevich:compottie", version = "2.0.0-rc02" }
|
||||||
kaml = { module = "com.charleskorn.kaml:kaml", version = "0.65.0" }
|
kaml = { module = "com.charleskorn.kaml:kaml", version = "0.65.0" }
|
||||||
junit = { module = "junit:junit", version = "4.13.2" }
|
junit = { module = "junit:junit", version = "4.13.2" }
|
||||||
|
junitJupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "jupiter" }
|
||||||
|
junitJupiterParams = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "jupiter" }
|
||||||
mockito = { module = "org.mockito:mockito-core", version = "4.11.0" }
|
mockito = { module = "org.mockito:mockito-core", version = "4.11.0" }
|
||||||
|
mockitoKotlin = { module = "org.mockito.kotlin:mockito-kotlin", version = "5.4.0" }
|
||||||
antlr = { module = "org.antlr:antlr4", version = "4.7.2" }
|
antlr = { module = "org.antlr:antlr4", version = "4.7.2" }
|
||||||
eclipseJDT = { module = "org.eclipse.jdt:org.eclipse.jdt.core", version = "3.16.0" }
|
eclipseJDT = { module = "org.eclipse.jdt:org.eclipse.jdt.core", version = "3.16.0" }
|
||||||
eclipseJDTCompiler = { module = "org.eclipse.jdt:org.eclipse.jdt.compiler.apt", version = "1.3.400" }
|
eclipseJDTCompiler = { module = "org.eclipse.jdt:org.eclipse.jdt.compiler.apt", version = "1.3.400" }
|
||||||
@@ -27,6 +31,8 @@ antlr4Runtime = { module = "org.antlr:antlr4-runtime", version.ref = "antlr" }
|
|||||||
composeGradlePlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "compose-plugin" }
|
composeGradlePlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "compose-plugin" }
|
||||||
kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||||
kotlinComposePlugin = { module = "org.jetbrains.kotlin.plugin.compose:org.jetbrains.kotlin.plugin.compose.gradle.plugin", version.ref = "kotlin" }
|
kotlinComposePlugin = { module = "org.jetbrains.kotlin.plugin.compose:org.jetbrains.kotlin.plugin.compose.gradle.plugin", version.ref = "kotlin" }
|
||||||
|
markdown = { module = "com.mikepenz:multiplatform-markdown-renderer-m2", version = "0.31.0" }
|
||||||
|
markdownJVM = { module = "com.mikepenz:multiplatform-markdown-renderer-jvm", version = "0.31.0" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" }
|
jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" }
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ plugins{
|
|||||||
id("com.vanniktech.maven.publish") version "0.30.0"
|
id("com.vanniktech.maven.publish") version "0.30.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "org.processing"
|
|
||||||
|
|
||||||
repositories{
|
repositories{
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ plugins{
|
|||||||
alias(libs.plugins.mavenPublish)
|
alias(libs.plugins.mavenPublish)
|
||||||
}
|
}
|
||||||
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
repositories{
|
repositories{
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ public class CompletionPanel {
|
|||||||
int x = ta.getCaretPosition() - ta.getLineStartOffset(line) - 1, x1 = x - 1;
|
int x = ta.getCaretPosition() - ta.getLineStartOffset(line) - 1, x1 = x - 1;
|
||||||
if (x >= s.length() || x < 0)
|
if (x >= s.length() || x < 0)
|
||||||
return null; //TODO: Does this check cause problems? Verify.
|
return null; //TODO: Does this check cause problems? Verify.
|
||||||
if (Base.DEBUG) System.out.print(" x char: " + s.charAt(x));
|
Messages.log(" x char: " + s.charAt(x));
|
||||||
|
|
||||||
String word = String.valueOf(s.charAt(x));
|
String word = String.valueOf(s.charAt(x));
|
||||||
if (s.trim().length() == 1) {
|
if (s.trim().length() == 1) {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public class PreprocService {
|
|||||||
running = true;
|
running = true;
|
||||||
PreprocSketch prevResult = null;
|
PreprocSketch prevResult = null;
|
||||||
CompletableFuture<?> runningCallbacks = null;
|
CompletableFuture<?> runningCallbacks = null;
|
||||||
Messages.log("PPS: Hi!");
|
Messages.log("Hi!");
|
||||||
while (running) {
|
while (running) {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
@@ -127,7 +127,7 @@ public class PreprocService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Messages.log("PPS: Starting");
|
Messages.log("Starting");
|
||||||
|
|
||||||
prevResult = preprocessSketch(prevResult);
|
prevResult = preprocessSketch(prevResult);
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ public class PreprocService {
|
|||||||
synchronized (requestLock) {
|
synchronized (requestLock) {
|
||||||
if (requestQueue.isEmpty()) {
|
if (requestQueue.isEmpty()) {
|
||||||
runningCallbacks = lastCallback;
|
runningCallbacks = lastCallback;
|
||||||
Messages.log("PPS: Done");
|
Messages.log("Done");
|
||||||
preprocessingTask.complete(prevResult);
|
preprocessingTask.complete(prevResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ public class PreprocService {
|
|||||||
Messages.err("problem in preprocessor service loop", e);
|
Messages.err("problem in preprocessor service loop", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Messages.log("PPS: Bye!");
|
Messages.log("Bye!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -188,7 +188,7 @@ public class PreprocService {
|
|||||||
* Indicate to this service that the sketch libraries have changed.
|
* Indicate to this service that the sketch libraries have changed.
|
||||||
*/
|
*/
|
||||||
public void notifyLibrariesChanged() {
|
public void notifyLibrariesChanged() {
|
||||||
Messages.log("PPS: notified libraries changed");
|
Messages.log("notified libraries changed");
|
||||||
librariesChanged.set(true);
|
librariesChanged.set(true);
|
||||||
notifySketchChanged();
|
notifySketchChanged();
|
||||||
}
|
}
|
||||||
@@ -197,7 +197,7 @@ public class PreprocService {
|
|||||||
* Indicate to this service that the folder housing sketch code has changed.
|
* Indicate to this service that the folder housing sketch code has changed.
|
||||||
*/
|
*/
|
||||||
public void notifyCodeFolderChanged() {
|
public void notifyCodeFolderChanged() {
|
||||||
Messages.log("PPS: notified code folder changed");
|
Messages.log("notified code folder changed");
|
||||||
codeFolderChanged.set(true);
|
codeFolderChanged.set(true);
|
||||||
notifySketchChanged();
|
notifySketchChanged();
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ public class PreprocService {
|
|||||||
.thenAcceptBothAsync(lastCallback, (ps, a) -> callback.accept(ps))
|
.thenAcceptBothAsync(lastCallback, (ps, a) -> callback.accept(ps))
|
||||||
// Make sure exception in callback won't cancel whole callback chain
|
// Make sure exception in callback won't cancel whole callback chain
|
||||||
.handleAsync((res, e) -> {
|
.handleAsync((res, e) -> {
|
||||||
if (e != null) Messages.err("PPS: exception in callback", e);
|
if (e != null) Messages.err("exception in callback", e);
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
return lastCallback;
|
return lastCallback;
|
||||||
|
|||||||
@@ -253,19 +253,19 @@ public class Runner implements MessageConsumer {
|
|||||||
// while (!available) {
|
// while (!available) {
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
Messages.log(getClass().getName() + " attempting to attach to VM");
|
Messages.log("attempting to attach to VM");
|
||||||
synchronized (cancelLock) {
|
synchronized (cancelLock) {
|
||||||
vm = connector.attach(arguments);
|
vm = connector.attach(arguments);
|
||||||
if (cancelled && vm != null) {
|
if (cancelled && vm != null) {
|
||||||
// cancelled and connected to the VM, handle closing now
|
// cancelled and connected to the VM, handle closing now
|
||||||
Messages.log(getClass().getName() + " aborting, launch cancelled");
|
Messages.log("aborting, launch cancelled");
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// vm = connector.attach(arguments);
|
// vm = connector.attach(arguments);
|
||||||
if (vm != null) {
|
if (vm != null) {
|
||||||
Messages.log(getClass().getName() + " attached to the VM");
|
Messages.log("attached to the VM");
|
||||||
// generateTrace();
|
// generateTrace();
|
||||||
// available = true;
|
// available = true;
|
||||||
return true;
|
return true;
|
||||||
@@ -273,17 +273,17 @@ public class Runner implements MessageConsumer {
|
|||||||
} catch (ConnectException ce) {
|
} catch (ConnectException ce) {
|
||||||
// This will fire ConnectException (socket not available) until
|
// This will fire ConnectException (socket not available) until
|
||||||
// the VM finishes starting up and opens its socket for us.
|
// the VM finishes starting up and opens its socket for us.
|
||||||
Messages.log(getClass().getName() + " socket for VM not ready");
|
Messages.log("socket for VM not ready");
|
||||||
// System.out.println("waiting");
|
// System.out.println("waiting");
|
||||||
// e.printStackTrace();
|
// e.printStackTrace();
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
Messages.err(getClass().getName() + " interrupted", ie);
|
Messages.err("interrupted", ie);
|
||||||
// ie.printStackTrace(sketchErr);
|
// ie.printStackTrace(sketchErr);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Messages.err(getClass().getName() + " while attaching to VM", e);
|
Messages.err("while attaching to VM", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// } catch (IOException exc) {
|
// } catch (IOException exc) {
|
||||||
|
|||||||
Reference in New Issue
Block a user