Merge branch 'processing:main' into gradle-welcome-screen

This commit is contained in:
Stef Tervelde
2025-03-30 08:52:37 +02:00
committed by GitHub
67 changed files with 944 additions and 258 deletions
+28
View File
@@ -1465,6 +1465,34 @@
"contributions": [
"code"
]
},
{
"login": "Rishab87",
"name": "Rishab Kumar Jha",
"avatar_url": "https://avatars.githubusercontent.com/u/138858208?v=4",
"profile": "https://github.com/Rishab87",
"contributions": [
"code"
]
},
{
"login": "yehiarasheed",
"name": "Yehia Rasheed",
"avatar_url": "https://avatars.githubusercontent.com/u/157399068?v=4",
"profile": "https://github.com/yehiarasheed",
"contributions": [
"code"
]
},
{
"login": "babaissarkar",
"name": "Subhraman Sarkar",
"avatar_url": "https://avatars.githubusercontent.com/u/8469888?v=4",
"profile": "https://github.com/babaissarkar",
"contributions": [
"code",
"a11y"
]
}
],
"repoType": "github",
+1 -1
View File
@@ -1,4 +1,4 @@
name: Pre-releases
name: Branch Builds (Legacy)
on:
push:
paths-ignore:
+1 -1
View File
@@ -1,4 +1,4 @@
name: Pull Requests
name: Pull Requests (Legacy)
on:
pull_request:
paths-ignore:
+18 -16
View File
@@ -134,7 +134,7 @@ jobs:
- name: Install Java
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '17.0.8'
distribution: 'temurin'
architecture: ${{ matrix.arch }}
- name: Setup Gradle
@@ -153,6 +153,22 @@ jobs:
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: 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: ${{ secrets.AZURE_SIGNING_ACCOUNT_NAME }}
certificate-profile-name: ${{ secrets.AZURE_CERTIFICATE_PROFILE_NAME }}
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
- name: Upload portables to release
uses: svenstaro/upload-release-action@v2
@@ -174,18 +190,4 @@ jobs:
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
+1 -1
View File
@@ -1,4 +1,4 @@
name: Releases
name: Releases (Legacy)
on:
release:
types: [published]
+2
View File
@@ -113,3 +113,5 @@ java/build/
.build/
/app/windows/obj
/java/gradle/build
/java/gradle/example/.processing
+39 -4
View File
@@ -1,5 +1,40 @@
<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 width="824" height="825" viewBox="0 0 824 825" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2066_295)">
<g clip-path="url(#clip1_2066_295)">
<rect y="0.82666" width="824" height="824" rx="412" fill="url(#paint0_linear_2066_295)"/>
<g filter="url(#filter0_dd_2066_295)">
<path d="M442.935 523.359C678.119 523.359 678.119 209.453 442.935 209.453" stroke="white" stroke-width="117.1"/>
<path d="M432.083 318.783L211.328 628.892" stroke="#9FCFFF" stroke-width="117.738"/>
<path d="M205.021 349.27L280.708 535.86" stroke="#1C48B5" stroke-width="117.044"/>
</g>
</g>
</g>
<defs>
<filter id="filter0_dd_2066_295" x="10.7905" y="10.9026" width="815.083" height="800.13" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="4" dy="4"/>
<feGaussianBlur stdDeviation="72"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2066_295"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="11"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_2066_295" result="effect2_dropShadow_2066_295"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_2066_295" result="shape"/>
</filter>
<linearGradient id="paint0_linear_2066_295" x1="178.174" y1="61.0872" x2="636.323" y2="764.108" gradientUnits="userSpaceOnUse">
<stop stop-color="#60B0FF"/>
<stop offset="1" stop-color="#308EFF"/>
</linearGradient>
<clipPath id="clip0_2066_295">
<rect width="824" height="824" fill="white" transform="translate(0 0.82666)"/>
</clipPath>
<clipPath id="clip1_2066_295">
<rect width="824" height="824" fill="white" transform="translate(0 0.82666)"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 2.1 KiB

+13 -12
View File
@@ -25,36 +25,37 @@ Instructions for other editors are welcome and feel free to contribute the docum
## Architecture
Processing is made of three distinct parts, the `Core`, `Java` and the `App`. The `Core` currently stands alone and `Java` and `App` depend on it. `Java` and `App` are currently interdependent but we are working on decoupling those two.
Processing consists of three main components: `Core`, `Java`, and `App`. The `Core` is independent, while `Java` and `App` depend on it. Currently, `Java` and `App` are interdependent, but efforts are underway to decouple them.
`Core`: The part of the code that gets bundled with your sketches, so the functionality like `ellipse(25,25,50,50);` The inner workings of that function can be found here.
- **Core**: The essential code included with your sketches that provides Processings basic functions. When you use functions like `ellipse(25,25,50,50)` or `background(255)`, their underlying code is part of `Core`.
`Java`: This is the pipeline that will take your `.pde` file and compile and run it. The PDE understands different _modes_ with `Java` being the primary one.
- **Java**: The part of Processing that compiles and runs `.pde` files. It supports different *modes* which implement support for different languages or versions of Processing. The default mode is `Java`.
- **App**: This is the Processing Development Environment (PDE), the visual part of the editor that you see and work within when you use Processing.
`App`: This is the PDE, the visual part of the editor that you see and work within when you use Processing.
### Examples
- You want to fix a bug with one of the argument of a function that you use in a sketch. The `Core` is probably where you would find the implementation of the function that you would like to modify.
- A feature/bug of the PDE editor has been driving you nuts, and you can no longer stand it. You would probably find your bug in the `App` section of this project.
- You've written a large sketch and Processing has become slow to compile, a place to improve this code can probably be found in the `Java` section.
- A bug of the PDE editor has been keeping you up at night, you would likely find the relevant code in the `App` section of this project.
- If you've written a large sketch and Processing has become slow to compile and run it, a place to improve this code can most likely be found in the `Java` section.
## User interface
Traditionally Processing has been written in Java swing and Flatlaf (and some html & css). Since 2025 we have switched to include Jetpack Compose, for a variety of reasons but mostly for it's inter-compatibility. There were ideas to switch to a React based editor, but this approach allows us to slowly replace Java swing components to Jetpack Compose, Ship of Theseus style.
Historically, Processing's UI has been written in Java Swing and Flatlaf (and some html & css). Since 2025 we have switched to include Jetpack Compose, mostly for it's backwards-compatibility with Swing. This approach allows us to gradually replace Java Swing components with Jetpack Compose ones, instead of doing a complete overhaul of the editor.
## Build system
We use `Gradle` as the build system for Processing. This used to be `Ant` but we have switched to be more in line with modern standards and to hopefully switch the internal build system in the `Java` mode to `Gradle` as well, unifying both systems for simplicity.
We use `Gradle` as the build system for Processing. Until 2025, Processing used `Ant` but we have switched to `Gradle` to be more in line with modern standards. We plan to migrate the internal build system of the `Java` mode to `Gradle` as well, unifying both systems for simplicity.
## Kotlin vs Java
Since introducing the Gradle build system we also support Kotlin within the repository. Refactors from Java to Kotlin are not really necessary at this stage, but all new functionality should be written in Kotlin.
With the introduction of the Gradle build system we now support Kotlin within the repository. Refactors from Java to Kotlin are not necessary at this stage, but all new functionality should be written in Kotlin.
Any classes that end in `..Kt.Java` are there for backwards compatibility with the `Ant` build system and can be removed when that is no longer necessary.
Any classes that end up being written in Kotlin have their equivalent Java class under `app/ant/` source directory.
### Running Processing
The main task to run or debug the PDE is `app:run` this run the application with `compose desktop`
The main task to run or debug the PDE is `run`. That means you just need to run `./gradlew run` (Linux) or `./gradlew.bat run` (Windows) to build and run Processing.
If your main concern is with the `Core` you don't need to start the whole PDE to test your changes. In IntelliJ IDEA you can select any of the sketches in `core/examples/src/.../` to run by click on the green arrow next to their main functions. This will just compile core and the example sketch. Feel free to also new examples for your newly added functionality.
If your main concern is with the `Core` you don't need to build and start the whole PDE to test your changes. In IntelliJ IDEA you can select any of the sketches in `core/examples/src/.../` to run by click on the green arrow next to their main functions. This will just compile core and the example sketch. Feel free to create additional examples for your new functionality.
## Other editors
+112 -67
View File
@@ -1,6 +1,106 @@
## Welcome to Processing!
# Contributing to Processing on GitHub
Thanks for your interest in contributing to Processing! Processing is a collaborative project with contributions from many volunteers. Our community is always looking for contributors and appreciates involvement in all forms. We acknowledge that not everyone has the capacity, time, or financial means to participate actively or in the same ways. We want to expand the meaning of the word “contributor.” Whether you're an experienced developer or just starting out, we value your involvement. Your unique perspectives, skills, and experiences enrich our community, and we encourage you to get involved in a way that works for you. It includes documentation, teaching, writing code, making art, writing, design, activism, organizing, curating, or anything else you might imagine. The [p5.js contribute page](https://p5js.org/contribute/) gives a great overview of different ways to get involved and contribute.
Welcome to the contributor guidelines!
This document is for new contributors looking to contribute code to Processing, contributors refreshing their memory on some technical steps, or anyone interested in working on Processings codebase. We believe that anyone can be a contributor. You dont need to be an expert. We also know that not everyone has the same time, energy, or resources to spend on Processing. Thats okay. Were glad youre here!
> [!TIP]
> For questions about your own sketches, or broader conversations about coding in Processing, our [online forum](https://discourse.processing.org/) is a fantastic resource (make sure to read the [forum guidelines](https://discourse.processing.org/t/welcome-to-the-processing-foundation-discourse/8) before posting). You can also visit the [Processing Community Discord](https://discord.gg/8pFwMVATh8).
## About GitHub
Processings codebase is hosted on [GitHub](https://github.com/processing). GitHub is a website where people can collaborate on code. Its widely used for open source projects and makes it easier to keep track of changes, report issues with the software, and contribute improvements to the code.
If you're new to GitHub, a good place to start is [this tutorial](https://github.com/firstcontributions/first-contributions/blob/main/docs/gui-tool-tutorials/github-desktop-tutorial.md) guide, which walks you through the basics of contributing to a project using GitHub Desktop. For more information, we recommend [Git and GitHub for Poets](https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZF9C0YMKuns9sLDzK6zoiV), a beginner-friendly video series by Dan Shiffman.
## About issues
Most activity on Processings GitHub happens in _issues_. Issues are GitHub posts which can contain bug reports, feature requests, or broader discussions about the development of Processing. Its a great place to begin contributing.
To file a new issue, visit the [Issues](https://github.com/processing/processing4/issues) tab on the repository and click `New issue` then select the most appropriate template and follow the included instructions. These templates help maintainers understand and respond to issues faster.
## Working on the Processing codebase
### Prerequisites
To contribute to Processing, we recommend using [GitHub Desktop](https://github.com/apps/desktop) and [IntelliJ IDEA (Community Edition)](https://www.jetbrains.com/idea/download/), as thats the toolchain were best able to support. If youre comfortable using Git on the command line or prefer a different editor, thats totally fine too! Use what works best for you. Some familiarity with the [command line](https://developer.mozilla.org/en-US/docs/Learn_web_development/Getting_started/Environment_setup/Command_line) can help, but its not required.
You'll need to set up a local development environment—see our [build instructions](https://github.com/processing/processing4/blob/main/BUILD.md) to get started.
### Making your first contribution
Most issues marked [help wanted](https://github.com/processing/processing4/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) or [good first issue](https://github.com/processing/processing4/issues?q=is%3Aissue%20is%3Aopen%20label%3A%22good%20first%20issue%22%20) are a good place to start.
Before beginning work on a code contribution, please make sure that:
- The issue has been discussed and a proposed solution has been approved.
- You have been **assigned** to the issue.
If an implementation has been agreed upon but no one has volunteered to take it on, feel free to comment and offer to help. A maintainer can then assign the issue to you.
Please do **not** open a pull request for an issue that is already assigned to someone else. We follow a “first assigned, first served” approach to avoid duplicated work. If you open a PR for an issue that someone else is already working on, your PR will be closed.
If an issue has been inactive for a long time, youre welcome to check in politely by commenting to see if the assignee still plans to work on it or would be open to someone else taking over.
Theres no hard deadline for completing contributions. We understand that people often contribute on a volunteer basis and timelines may vary. That said, if you run into trouble or have questions at any point, dont hesitate to ask for help in the issue thread. Maintainers and other community members are here to support you.
### Follow the style guidelines
Keep the [style guidelines](https://github.com/processing/processing/wiki/Style-Guidelines) in mind when making changes to the code. If you dont, someone else will have to reformat your code so that it fits everything else (or well have to reject your changes if itll take us too long to clean things up).
### Test locally
Before you contribute your changes, it's essential that you make sure that Processing still builds, runs, and functions on your machine. Here again, the [build instructions](https://github.com/processing/processing4/blob/main/BUILD.md) are your best friend. Pay special attention to any features that may be affected by your changes. Does everything still work as before? Great!
## Submit a pull request (PR)
Once your changes are ready:
1. Push your branch to your fork
2. Open a pull request from your branch into `main` on the official repository
3. Fill out the pull request information:
- **Title**: clear and descriptive
- **Resolves**: add `Resolves #[issue-number]` if applicable
- **Changes**: explain what you changed and why
- **Tests**: mention if you added tests or validated your changes
- **Checklist**: ensure tests pass and the branch is up-to-date
Maintainers usually review pull requests within one to two weeks. If changes are requested, follow up by pushing additional commits. The PR will automatically update.
If there hasnt been any activity after two weeks, feel free to gently follow up. We kindly ask that you dont request a review or tag maintainers before that time. Thanks for your patience!
Before opening a pull request, please make sure to discuss the related issue and get assigned to it first. This helps us stay aligned and avoid unnecessary work. Thank you!
## New Features
In most cases, the best way to contribute a new feature is to create a library. The [Processing Library Template](https://github.com/processing/processing-library-template) is a great way to get started. For more instructions, see the [library template documenation](https://processing.github.io/processing-library-template/).
Nearly all new features are first introduced as a Library or a Mode, or even as an example. The current [OpenGL renderer](http://glgraphics.sourceforge.net/) and Video library began as separate projects by Andrés Colubri, who needed a more performant, more sophisticated version of what we had in Processing for work that he was creating. The original `loadShape()` implementation came from the “Candy” library by Michael Chang (“mflux“). Similarly, Tweak Mode began as a [separate project](http://galsasson.com/tweakmode/) by Gal Sasson before being incorporated. PDE X was a Google Summer of code [project](https://github.com/processing/processing-experimental) by Manindra Moharana that updated the PDE to include basic refactoring and better error checking.
Developing features separately from the main software has several benefits:
* Its easier for the contributor to develop the software without it needing to work for tens or hundreds of thousands of Processing users.
* It provides a way to get feedback on that code independently of everything else, and the ability to iterate on it rapidly.
* This feedback process also helps gauge the level of interest for the community, and how it should be prioritized for the software.
* We can delay the process of “normalizing” the features so that theyre consistent with the rest of Processing (function naming, structure, etc).
A major consideration for any new feature is the level of maintenance that it might require in the future. If the original maintainer loses interest over time (which is normal) and the feature breaks (which happens more often than we'd like), it sits on the issues list unfixed, which isnt good for anyone.
Processing is a massive project that has existed for more than 20 years. Part of its longevity comes from the effort thats gone into keeping things as simple as we can, and in particular, making a lot of difficult decisions about *what to leave out*. Adding a new feature always has to be weighed against the potential confusion of one more thing—whether its a menu item, a dialog box, a function that needs to be added to the reference, etc. Adding a new graphics function means making it work across all the renderers that we ship (Java2D, OpenGL, JavaFX, PDF, etc) and across platforms (macOS, Windows, Linux). Does the feature help enough people that it's worth making the reference longer? Or the additional burden of maintaining that feature? It's no fun to say “no,” especially to people volunteering their time, but we often have to.
## Editor
The current Editor component is based on the ancient [JEditSyntax](http://syntax.jedit.org/) package and has held up long past its expiration date. [Exhaustive work](https://github.com/processing/processing4/blob/master/app/src/processing/app/syntax/README.md) has been done to look at replacing the component with something more modern, like `RSyntaxArea`, but that approach was considered too risky.
With Processing 4.4.0, weve started transitioning the Processing UI from Swing to Jetpack Compose Multiplatform, allowing us to replace Swing components gradually, without a full rewrite. Any work on updating the PDE and adding new features should focus on this migration. Replacing JEditSyntax will likely be the last step in the process. In the meantime, the editor does what it needs to do, for the intended audience. Features like code-folding, refactoring, or symbol navigation are currently out of scope.
For users who want editor features beyond what the PDE offers, were working to make Processing easier to use in other environments. [Migrating the Processing CLI to Gradle](https://github.com/orgs/processing/projects/32/views/2?filterQuery=CLI&pane=issue&itemId=81026317) and [better Language Server support](https://github.com/orgs/processing/projects/32/views/2?filterQuery=LSP&pane=issue&itemId=90809690) will help make that possible. This should reduce the pressure to add these features to the PDE itself, allowing it to stay focused on being a minimal, beginner-friendly coding sketchbook. If you'd like to help, [let us know](https://github.com/processing/processing4/issues/883)!
## Refactoring
Refactoring is fun! Theres always more cleaning to do. Its also often not very helpful.
Broadly speaking, the code is built the way it is for a reason. There are so many things that can be improved, but those improvements need to come from an understanding of whats been built so far. Changes that include refactoring are typically only accepted from contributors who have an established record of working on the code. With a better understanding of the software, the refactoring decisions come from a better, more useful place.
## Contributor Recognition
The Processing project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification, recognizing all types of contributions, not just code. We use the @all-contributors bot to handle adding people to the README.md file. You can ask the @all-contributors bot to add you in an issue or PR comment like so:
@@ -10,70 +110,15 @@ The Processing project follows the [all-contributors](https://github.com/kentcdo
We usually add contributors automatically after merging a PR, but feel free to request addition yourself by commenting on [this issue](https://github.com/processing/processing4-carbon-aug-19/issues/839).
## Found a Bug?
## Other Ways to Contribute
First, please visit our [troubleshooting](https://github.com/processing/processing/wiki/Troubleshooting) page for common issues—you might find the answer there!
We're always grateful for your help fixing bugs and implementing new features BUT You dont have to write code to contribute to Processing! Here are just a few other ways to get involved:
For coding questions or help getting started, our [online forum](https://discourse.processing.org/) is a fantastic resource. Make sure to read the [forum guidelines](https://discourse.processing.org/t/welcome-to-the-processing-foundation-discourse/8) before posting.
If your issue remains unresolved after exploring these options, we'd appreciate it if you could [file a bug report](https://github.com/processing/processing4/issues). Your feedback is crucial as it helps us address issues we might not be aware of yet.
## Making Your First Contribution
* **Help Wanted** Most [issues marked help wanted](https://github.com/processing/processing4/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) are a good place to start. Issues are marked with this tag when:
* They are isolated enough that someone can jump into it without significant reworking of other code.
* Ben knows that its unlikely that hell have time to work on them.
* **The Old Repository** There are also many “help wanted” [issues in the 3.x repository](https://github.com/processing/processing4/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). Some of these are very old, so if you're interested in one of these, check in about the priority before putting in too much work!
* **JavaFX** There are several [active issues](https://github.com/processing/processing4-javafx/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) for the JavaFX renderer as well.
* **The `todo.txt` File** This is *not* a good place to start. Its Bens rambling to-do list, and dates back to the very start of the project over twenty years ago. It shouldnt be used as a guideline for work to be done, because there are lots of things there that are no longer relevant. Consider it the dusty attic of whats inside his head. If you see something of interest there, open an issue to see if its still a priority, or how it should be approached. But really, there are *so many open issues*, which represent actual problems identified by community members, and they are by far the best place to start.
* **Style Guidelines** Keep the [style guidelines](https://github.com/processing/processing/wiki/Style-Guidelines) in mind when submitting pull requests. If you dont, someone else will have to reformat your code so that it fits everything else (or well have to reject it if itll take us too long to clean it up).
* **Larger Projects** If youre looking for a larger project, check out the [Project List](https://github.com/processing/processing/wiki/Project-List#processing) for other ideas.
## New Features
Nearly all new features are first introduced as a Library or a Mode, or even as an example. The current [OpenGL renderer](http://glgraphics.sourceforge.net/) and Video library began as separate projects by Andrés Colubri, who needed a more performant, more sophisticated version of what we had in Processing for work that he was creating. The original `loadShape()` implementation came from the “Candy” library by Michael Chang (“mflux“).
Similarly, Tweak Mode began as a [separate project](http://galsasson.com/tweakmode/) by Gal Sasson before being incorporated. PDE X was a Google Summer of code [project](https://github.com/processing/processing-experimental) by Manindra Moharana that updated the PDE to include basic refactoring and better error checking.
Developing features separately from the main software has several benefits:
* Its easier for the contributor to develop the software without it needing to work for tens or hundreds of thousands of Processing users.
* It provides a way to get feedback on that code independently of everything else, and the ability to iterate on it rapidly.
* This feedback process also helps gauge the level of interest for the community, and how it should be prioritized for the software.
* We can delay the process of “normalizing” the features so that theyre consistent with the rest of Processing (function naming, structure, etc).
A major consideration for any new feature is the level of maintenance that it might require in the future. If the original maintainer loses interest over time (which is normal), any ongoing work usually falls to Ben, or it sits on the issues list unfixed, which isnt good for the community, or for Ben, who has plenty of issues of his own—whether Processing or otherwise.
Processing is a massive project that has existed for more than 20 years. Part of its longevity comes from the effort thats gone into keeping things as simple as we can, and in particular, making a lot of difficult decisions about *what to leave out*. Adding a new feature always has to be weighed against the potential confusion of one more thing—whether its a menu item, a dialog box, a function that needs to be added to the reference, etc. Adding a new graphics function means making it work across all the renderers that we ship (Java2D, OpenGL, JavaFX, PDF, etc) and across platforms (macOS, Windows, Linux). Does the feature help enough people that it's worth making the reference longer? Or the additional burden of maintaining that feature? It's no fun to say “no,” especially to people volunteering their time, but we often have to.
## Editor
The current Editor, based on the ancient [JEditSyntax](http://syntax.jedit.org/) package has held up long past its expiration date. [Exhaustive work](https://github.com/processing/processing4/blob/master/app/src/processing/app/syntax/README.md) has been done to look at replacing the component with something more modern, like `RSyntaxArea`, but its simply not feasible without breaking a massive amount of code, and likely introducing a lot of regressions in the process. All for… code folding? An incrementally better experience? But with potential for major setbacks in low-level code? Its simply not a path that makes sense.
With that in mind, any work on updating the editor and adding new features should be focused on further [adapting the preprocessor and compiler](https://github.com/processing/processing4/issues/117) to be wrapped using the [Language Server Protocol](https://en.wikipedia.org/wiki/Language_Server_Protocol), so that we can link to other existing editors (Visual Studio Code and many others). It should be possible to create a Java-only, headless implementation that wraps the current source in this repository and can communicate via LSP.
The initial work was completed in Processing 4.1, and now needs more testing and implementation of Language Server clients such as [this one](https://github.com/kgtkr/processing-language-server-vscode).
We can start building a new PDE thats as simple to use as the current application, based on something like [Theia](https://theia-ide.org/), a new editor platform that uses LSP as its basis.
With that in mind, nearly all editor enhancement requests will be redirected to this aim. The current editor does what we want it to, for the intended audience, and improving it requires a better foundation as a starting point.
## Refactoring
Refactoring is fun! Theres always more cleaning to do. Its also often not very helpful.
Broadly speaking, the code is built the way it is for a reason. There are so many things that can be improved, but those improvements need to come from an understanding of whats been built so far. Changes that include refactoring are typically only accepted from contributors who have an established record of working on the code. With a better understanding of the software, the refactoring decisions come from a better, more useful place.
## Other Details
This document was hastily thrown together in an attempt to improve the bug reporting and development/contribution process. It doesnt yet include detail about our intent with the project, the community behind it, our values, and an explanation of how the code itself is designed.
- **Translation** Help localize the software and documentation in your language. Many of us made our first contribution this way.
- **Testing** Try out new releases (especially the betas) and [report bugs](https://github.com/processing/processing4/issues/new/choose).
- **Documentation** Improve tutorials, reference pages, or even this guide!
- **Design** Contribute UI design ideas or help improve user experience.
- **Community Support** Answer questions on the [forum](https://discourse.processing.org/).
- **Education** Create learning resources, curriculums, organize workshops, or share your teaching experiences.
- **Art and Projects** Share what youre making with Processing and use the #BuiltWithProcessing hashtag 💙
- **Outreach and Advocacy** Help others discover and get excited about the project.
+5
View File
@@ -287,6 +287,11 @@ Add yourself to the contributors list [here](https://github.com/processing/proce
<td align="center" valign="top" width="16.66%"><a href="http://benjaminfoxstudios.com"><img src="https://avatars.githubusercontent.com/u/234190?v=4?s=120" width="120px;" alt="Benjamin Fox"/><br /><sub><b>Benjamin Fox</b></sub></a><br /><a href="https://github.com/processing/processing4/commits?author=tracerstar" title="Code">💻</a></td>
<td align="center" valign="top" width="16.66%"><a href="https://github.com/e1dem"><img src="https://avatars.githubusercontent.com/u/32488297?v=4?s=120" width="120px;" alt="e1dem"/><br /><sub><b>e1dem</b></sub></a><br /><a href="https://github.com/processing/processing4/commits?author=e1dem" title="Code">💻</a></td>
<td align="center" valign="top" width="16.66%"><a href="https://github.com/inteqam"><img src="https://avatars.githubusercontent.com/u/104833943?v=4?s=120" width="120px;" alt="Aditya Chaudhary"/><br /><sub><b>Aditya Chaudhary</b></sub></a><br /><a href="https://github.com/processing/processing4/commits?author=inteqam" title="Code">💻</a></td>
<td align="center" valign="top" width="16.66%"><a href="https://github.com/Rishab87"><img src="https://avatars.githubusercontent.com/u/138858208?v=4?s=120" width="120px;" alt="Rishab Kumar Jha"/><br /><sub><b>Rishab Kumar Jha</b></sub></a><br /><a href="https://github.com/processing/processing4/commits?author=Rishab87" title="Code">💻</a></td>
<td align="center" valign="top" width="16.66%"><a href="https://github.com/yehiarasheed"><img src="https://avatars.githubusercontent.com/u/157399068?v=4?s=120" width="120px;" alt="Yehia Rasheed"/><br /><sub><b>Yehia Rasheed</b></sub></a><br /><a href="https://github.com/processing/processing4/commits?author=yehiarasheed" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="16.66%"><a href="https://github.com/babaissarkar"><img src="https://avatars.githubusercontent.com/u/8469888?v=4?s=120" width="120px;" alt="Subhraman Sarkar"/><br /><sub><b>Subhraman Sarkar</b></sub></a><br /><a href="https://github.com/processing/processing4/commits?author=babaissarkar" title="Code">💻</a> <a href="#a11y-babaissarkar" title="Accessibility">️♿️</a></td>
</tr>
</tbody>
</table>
+10 -1
View File
@@ -1,5 +1,14 @@
# Processing URI Schema Definition
The Processing URI schema defines a custom protocol for launching and interacting with the Processing Development Environment (PDE) via specially formatted `pde://` links. These links can be used to open sketches, create new ones, load hosted or base64-encoded files, and set preferences, all through a simple URI-based interface.
This feature is primarily intended for integration with web platforms, tutorials, documentation, or third-party tools that want to streamline the experience of launching sketches in Processing from a web page.
Because these links can be generated dynamically, they support a range of interactive use cases. For example, an online editor could generate a unique link for each sketch, or a forum could create links based on user-submitted code snippets.
>[!WARNING]
> Be cautious when opening `pde://` links from unknown sources. Always review the contents of a sketch before running it, especially if it was shared by someone you dont know. To protect your system, Processing runs downloaded sketches in a temporary folder, but you should still treat untrusted code with care.
## Local File Schema
```
pde:///path/to/sketch.pde
@@ -60,4 +69,4 @@ Sets and saves multiple preferences in a single operation.
- URL-based operations automatically prepend https:// if no scheme is provided
- All URLs and query parameters are decoded using UTF-8
- File downloads occur asynchronously in a separate thread
- Base64 and remote sketches are saved to temporary folders
- Base64 and remote sketches are saved to temporary folders
+6 -4
View File
@@ -53,7 +53,7 @@ compose.desktop {
jvmArgs(*listOf(
Pair("processing.version", rootProject.version),
Pair("processing.revision", findProperty("revision") ?: Int.MAX_VALUE),
Pair("processing.contributions.source", "https://download.processing.org/contribs.txt"),
Pair("processing.contributions.source", "https://contributions.processing.org/contribs"),
Pair("processing.download.page", "https://processing.org/download/"),
Pair("processing.download.latest", "https://processing.org/download/latest.txt"),
Pair("processing.tutorials", "https://processing.org/tutorials/"),
@@ -73,6 +73,7 @@ compose.desktop {
entitlementsFile.set(file("macos/entitlements.plist"))
runtimeEntitlementsFile.set(file("macos/entitlements.plist"))
appStore = true
jvmArgs("-Dsun.java2d.metal=true")
}
windows{
iconFile = rootProject.file("build/windows/processing.ico")
@@ -243,6 +244,7 @@ tasks.register("generateSnapConfiguration"){
- x11
- network
- opengl
- home
parts:
processing:
@@ -358,6 +360,7 @@ tasks.register<Download>("includeJdk") {
into(composeResources(""))
}
}
finalizedBy("prepareAppResources")
}
tasks.register<Copy>("includeSharedAssets"){
from("../build/shared/")
@@ -515,7 +518,6 @@ afterEvaluate {
dependsOn(
"includeCore",
"includeJavaMode",
"includeJdk",
"includeSharedAssets",
"includeProcessingExamples",
"includeProcessingWebsiteExamples",
@@ -543,7 +545,7 @@ afterEvaluate {
}
}
tasks.named("createDistributable").configure {
dependsOn("signResources")
dependsOn("signResources", "includeJdk")
finalizedBy("setExecutablePermissions")
}
}
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 185 KiB

@@ -0,0 +1,23 @@
# The default is 8, which creates tiny nubby scroll bars
ScrollBar.width = 16
TitlePane.inactiveForeground = #000000
# Better matched for macOS dark mode (but using everywhere)
# https://github.com/JFormDesigner/FlatLaf/issues/497
[dark]@background = #1e1e1e
[dark]@foreground = #e0e0e0
[dark]@accentColor = #107aff
[dark]@accentFocusColor = #176896
[dark]Component.arrowType = chevron
[dark]CheckBox.icon.style = filled
[dark]CheckBox.icon[filled].selectedBorderColor = @accentColor
[dark]CheckBox.icon[filled].selectedBackground = @accentColor
[dark]CheckBox.icon[filled].checkmarkColor = @foreground
[dark]RadioButton.icon.style = filled
[dark]RadioButton.icon[filled].centerDiameter = 6
+19 -8
View File
@@ -1,5 +1,9 @@
package processing.app
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import processing.app.ui.Editor
import java.io.File
import java.io.FileOutputStream
@@ -13,6 +17,8 @@ import java.util.*
class Schema {
companion object{
private var base: Base? = null
val jobs = mutableListOf<Job>()
@JvmStatic
fun handleSchema(input: String, base: Base): Editor?{
this.base = base
@@ -72,10 +78,9 @@ class Schema {
}
private fun handleSketchOptions(uri: URI, sketchFolder: File){
val options = uri.query?.split("&")
?.map { it.split("=") }
?.map { it.split("=", limit = 2) }
?.associate {
URLDecoder.decode(it[0], StandardCharsets.UTF_8) to
URLDecoder.decode(it[1], StandardCharsets.UTF_8)
it[0] to it[1]
}
?: emptyMap()
options["data"]?.let{ data ->
@@ -93,8 +98,9 @@ class Schema {
}
}
private val scope = CoroutineScope(Dispatchers.Default)
private fun downloadFiles(uri: URI, urlList: String, targetFolder: File, extension: String = ""){
Thread{
targetFolder.mkdirs()
val base = uri.path.split("/")
@@ -129,15 +135,20 @@ class Schema {
URL("https://$content").path.isNotBlank() -> "https://$content"
else -> "https://$base/$content"
})
url.openStream().use { input ->
target.outputStream().use { output ->
input.copyTo(output)
val download = scope.launch{
url.openStream().use { input ->
target.outputStream().use { output ->
input.copyTo(output)
}
}
}
jobs.add(download)
download.invokeOnCompletion {
jobs.remove(download)
}
}
}
}.start()
}
@@ -31,15 +31,19 @@ import processing.app.Messages;
import processing.app.Preferences;
import processing.core.PApplet;
import javax.swing.*;
public class LinuxPlatform extends DefaultPlatform {
// Switched to use ~ as the home directory for compatibility with snap
String homeDir = "~";
String homeDir;
public void initBase(Base base) {
super.initBase(base);
JFrame.setDefaultLookAndFeelDecorated(true);
System.setProperty("flatlaf.menuBarEmbedded", "true");
// Set X11 WM_CLASS property which is used as the application
// name by Gnome 3 and other window managers.
// https://github.com/processing/processing/issues/2534
@@ -107,6 +111,10 @@ public class LinuxPlatform extends DefaultPlatform {
configHome = null; // don't use non-existent folder
}
}
String snapUserCommon = System.getenv("SNAP_USER_COMMON");
if (snapUserCommon != null && !snapUserCommon.isBlank()) {
configHome = new File(snapUserCommon);
}
// If not set properly, use the default
if (configHome == null) {
configHome = new File(getHomeDir(), ".config");
@@ -399,6 +399,7 @@ public class JEditTextArea extends JComponent
public void updateScrollBars() {
if (vertical != null && visibleLines != 0) {
vertical.setValues(firstLine,visibleLines,0,getLineCount());
vertical.setVisible(visibleLines < getLineCount());
vertical.setUnitIncrement(2);
vertical.setBlockIncrement(visibleLines);
}
@@ -424,6 +425,7 @@ public class JEditTextArea extends JComponent
// https://github.com/processing/processing/issues/319
// https://github.com/processing/processing/issues/355
//setValues(int newValue, int newExtent, int newMin, int newMax)
horizontal.setVisible(painterWidth < width);
if (horizontalOffset < 0) {
horizontal.setValues(-horizontalOffset, painterWidth, -leftHandGutter, width);
} else {
+156 -8
View File
@@ -208,7 +208,7 @@ public abstract class Editor extends JFrame implements RunnerListener {
Box box = Box.createVerticalBox();
Box upper = Box.createVerticalBox();
if(SystemInfo.isMacFullWindowContentSupported) {
if(Platform.isMacOS() && SystemInfo.isMacFullWindowContentSupported) {
getRootPane().putClientProperty( "apple.awt.fullWindowContent", true );
getRootPane().putClientProperty( "apple.awt.transparentTitleBar", true );
@@ -349,6 +349,30 @@ public abstract class Editor extends JFrame implements RunnerListener {
// Enable window resizing (which allows for full screen button)
setResizable(true);
{
// Move Lines Keyboard Shortcut (Alt + Arrow Up/Down)
KeyStroke moveUpKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_DOWN_MASK);
final String MOVE_UP_ACTION_KEY = "moveLinesUp";
textarea.getInputMap(JComponent.WHEN_FOCUSED).put(moveUpKeyStroke, MOVE_UP_ACTION_KEY);
textarea.getActionMap().put(MOVE_UP_ACTION_KEY, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
handleMoveLines(true);
}
});
KeyStroke moveDownKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK);
final String MOVE_DOWN_ACTION_KEY = "moveLinesDown";
textarea.getInputMap(JComponent.WHEN_FOCUSED).put(moveDownKeyStroke, MOVE_DOWN_ACTION_KEY);
textarea.getActionMap().put(MOVE_DOWN_ACTION_KEY, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
handleMoveLines(false);
}
});
}
}
@@ -595,12 +619,10 @@ public abstract class Editor extends JFrame implements RunnerListener {
toolTipWarningColor = Theme.get("errors.selection.warning.bgcolor");
toolTipErrorColor = Theme.get("errors.selection.error.bgcolor");
if(Platform.isWindows()) {
UIManager.put("RootPane.background", color);
UIManager.put("TitlePane.embeddedForeground", Theme.getColor("editor.fgcolor"));
getRootPane().updateUI();
UIManager.put("RootPane.background", null);
}
UIManager.put("RootPane.background", color);
UIManager.put("TitlePane.embeddedForeground", Theme.getColor("editor.fgcolor"));
getRootPane().updateUI();
UIManager.put("RootPane.background", null);
JPopupMenu popup = modePopup.getPopupMenu();
// Cannot use instanceof because com.formdev.flatlaf.ui.FlatPopupMenuBorder
@@ -791,6 +813,18 @@ public abstract class Editor extends JFrame implements RunnerListener {
item.addActionListener(e -> handleIndentOutdent(false));
menu.add(item);
item = Toolkit.newJMenuItemExt("menu.edit.increase_font");
item.addActionListener(e -> {
modifyFontSize(true);
});
menu.add(item);
item = Toolkit.newJMenuItemExt("menu.edit.decrease_font");
item.addActionListener(e -> {
modifyFontSize(false);
});
menu.add(item);
menu.addSeparator();
item = Toolkit.newJMenuItem(Language.text("menu.edit.find"), 'F');
@@ -848,6 +882,16 @@ public abstract class Editor extends JFrame implements RunnerListener {
return menu;
}
protected void modifyFontSize(boolean increase){
var fontSize = Preferences.getInteger("editor.font.size");
fontSize += increase ? 1 : -1;
fontSize = Math.max(5, Math.min(72, fontSize));
Preferences.setInteger("editor.font.size", fontSize);
for (Editor editor : base.getEditors()) {
editor.applyPreferences();
}
Preferences.save();
}
abstract public JMenu buildSketchMenu();
@@ -1919,6 +1963,110 @@ public abstract class Editor extends JFrame implements RunnerListener {
sketch.setModified(true);
}
/**
* Moves the selected lines up or down in the text editor.
*
* <p>If {@code moveUp} is true, the selected lines are moved up. If false, they move down.</p>
* <p>This method ensures proper selection updates and handles edge cases like moving
* the first or last line.</p>
* <p>This operation is undo/redoable, allowing the user to revert the action using
* {@code Ctrl/Cmd + Z} (Undo). Redo functionality is available through the
* keybinding {@code Ctrl/Cmd + Z} on Windows/Linux and {@code Shift + Cmd + Z} on macOS.</p>
*
* @param moveUp {@code true} to move the selection up, {@code false} to move it down.
*/
public void handleMoveLines(boolean moveUp) {
startCompoundEdit();
boolean isSelected = false;
if (textarea.isSelectionActive())
isSelected = true;
int caretPos = textarea.getCaretPosition();
int currentLine = textarea.getCaretLine();
int lineStart = textarea.getLineStartOffset(currentLine);
int column = caretPos - lineStart;
int startLine = textarea.getSelectionStartLine();
int stopLine = textarea.getSelectionStopLine();
// Adjust selection if the last line isn't fully selected
if (startLine != stopLine &&
textarea.getSelectionStop() == textarea.getLineStartOffset(stopLine)) {
stopLine--;
}
int replacedLine = moveUp ? startLine - 1 : stopLine + 1;
if (replacedLine < 0 || replacedLine >= textarea.getLineCount()) {
stopCompoundEdit();
return;
}
final String source = textarea.getText(); // Get full text from textarea
int replaceStart = textarea.getLineStartOffset(replacedLine);
int replaceEnd = textarea.getLineStopOffset(replacedLine);
if (replaceEnd > source.length()) {
replaceEnd = source.length();
}
int selectionStart = textarea.getLineStartOffset(startLine);
int selectionEnd = textarea.getLineStopOffset(stopLine);
if (selectionEnd > source.length()) {
selectionEnd = source.length();
}
String replacedText = source.substring(replaceStart, replaceEnd);
String selectedText = source.substring(selectionStart, selectionEnd);
if (replacedLine == textarea.getLineCount() - 1) {
replacedText += "\n";
selectedText = selectedText.substring(0, Math.max(0, selectedText.length() - 1));
} else if (stopLine == textarea.getLineCount() - 1) {
selectedText += "\n";
replacedText = replacedText.substring(0, Math.max(0, replacedText.length() - 1));
}
int newSelectionStart, newSelectionEnd;
if (moveUp) {
textarea.select(selectionStart, selectionEnd);
textarea.setSelectedText(replacedText); // Use setSelectedText()
textarea.select(replaceStart, replaceEnd);
textarea.setSelectedText(selectedText);
newSelectionStart = textarea.getLineStartOffset(startLine - 1);
newSelectionEnd = textarea.getLineStopOffset(stopLine - 1);
} else {
textarea.select(replaceStart, replaceEnd);
textarea.setSelectedText(selectedText);
textarea.select(selectionStart, selectionEnd);
textarea.setSelectedText(replacedText);
newSelectionStart = textarea.getLineStartOffset(startLine + 1);
newSelectionEnd = stopLine + 1 < textarea.getLineCount()
? Math.min(textarea.getLineStopOffset(stopLine + 1), source.length())
: textarea.getLineStopOffset(stopLine); // Prevent out-of-bounds
}
stopCompoundEdit();
if (isSelected)
SwingUtilities.invokeLater(() -> {
textarea.select(newSelectionStart, newSelectionEnd-1);
});
else if (replacedLine >= 0 && replacedLine < textarea.getLineCount()) {
int replacedLineStart = textarea.getLineStartOffset(replacedLine);
int replacedLineEnd = textarea.getLineStopOffset(replacedLine);
// Ensure caret stays within bounds of the new line
int newCaretPos = Math.min(replacedLineStart + column, replacedLineEnd - 1);
SwingUtilities.invokeLater(() -> textarea.setCaretPosition(newCaretPos));
}
}
static public boolean checkParen(char[] array, int index, int stop) {
while (index < stop) {
@@ -2128,7 +2276,7 @@ public abstract class Editor extends JFrame implements RunnerListener {
* something like "sketch_070752a - Processing 0126"
*/
public void updateTitle() {
setTitle(sketch.getName() + " | Processing " + Base.getVersionName());
setTitle(sketch.getName());
if (!sketch.isUntitled()) {
// Set current file for macOS so that cmd-click in title bar works.
+42 -1
View File
@@ -30,6 +30,8 @@ import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
@@ -39,6 +41,7 @@ import java.util.List;
import javax.swing.*;
import processing.app.Base;
import processing.app.Mode;
import processing.app.Sketch;
import processing.app.contrib.ContributionManager;
@@ -83,10 +86,14 @@ public class EditorFooter extends Box {
Image gradient;
Color bgColor;
Box tabBar;
JPanel cardPanel;
CardLayout cardLayout;
Controller controller;
JLabel version;
int updateCount;
@@ -98,8 +105,33 @@ public class EditorFooter extends Box {
cardPanel = new JPanel(cardLayout);
add(cardPanel);
tabBar = new Box(BoxLayout.X_AXIS);
controller = new Controller();
add(controller);
tabBar.add(controller);
version = new JLabel(Base.getVersionName());
version.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, Editor.RIGHT_GUTTER));
version.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(e.getClickCount() == 5){
Base.DEBUG = !Base.DEBUG;
}
var debugInformation = String.join("\n",
"Version: " + Base.getVersionName(),
"Revision: " + Base.getRevision(),
"OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch"),
"Java: " + System.getProperty("java.version") + " " + System.getProperty("java.vendor")
);
var stringSelection = new StringSelection(debugInformation);
var clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, null);
}
});
tabBar.add(version);
add(tabBar);
updateTheme();
}
@@ -175,6 +207,15 @@ public class EditorFooter extends Box {
// replace colors for the "updates" indicator
controller.updateTheme();
tabBar.setOpaque(true);
tabBar.setBackground(bgColor);
var updatesTextColor = Theme.getColor("footer.updates.text.color");
var withAlpha = new Color(updatesTextColor.getRed(), updatesTextColor.getGreen(), updatesTextColor.getBlue(), 128);
version.setForeground(withAlpha);
version.setFont(font);
}
+8 -3
View File
@@ -33,6 +33,8 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Enumeration;
import javax.swing.Box;
@@ -57,6 +59,7 @@ import processing.app.Mode;
import processing.app.Platform;
import processing.app.Preferences;
import processing.app.SketchReference;
import processing.app.contrib.Contribution;
import processing.app.contrib.ContributionManager;
import processing.app.contrib.ContributionType;
import processing.app.contrib.ExamplesContribution;
@@ -313,9 +316,11 @@ public class ExamplesFrame extends JFrame {
}
// Get examples for third party libraries
DefaultMutableTreeNode contributedLibExamples = new
DefaultMutableTreeNode(Language.text("examples.libraries"));
for (Library lib : mode.contribLibraries) {
DefaultMutableTreeNode contributedLibExamples = new DefaultMutableTreeNode(Language.text("examples.libraries"));
var sortedContribLibs = new ArrayList<>(mode.contribLibraries);
// Sort the libraries by actual name (not the name of the folder)
sortedContribLibs.sort(Comparator.comparing(Contribution::getName));
for (Library lib : sortedContribLibs) {
if (lib.hasExamples()) {
DefaultMutableTreeNode libNode =
new DefaultMutableTreeNode(lib.getName());
+4 -8
View File
@@ -12,15 +12,12 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.toComposeImageBitmap
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import processing.app.Base
import processing.app.Platform
import javax.imageio.ImageIO
/**
* Show a splash screen window. A rewrite of Splash.java
@@ -29,8 +26,6 @@ class Start {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val splash = Platform.getContentFile("lib/about-processing.png")
val image = ImageIO.read(splash).toComposeImageBitmap()
val duration = 200
val timeMargin = 50
@@ -44,7 +39,8 @@ class Start {
resizable = false,
state = rememberWindowState(
position = WindowPosition(Alignment.Center),
size = DpSize(image.width.dp / 2 , image.height.dp / 2)
width = 578.dp,
height = 665.dp
)
) {
var visible by remember { mutableStateOf(false) }
@@ -81,7 +77,7 @@ class Start {
)
) {
Image(
bitmap = image,
painter = painterResource("about-processing.svg"),
contentDescription = "About",
modifier = Modifier
.fillMaxSize()
+27 -1
View File
@@ -1,5 +1,7 @@
package processing.app
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import org.mockito.ArgumentCaptor
@@ -35,6 +37,22 @@ class SchemaTest {
verify(base).handleNew()
}
@Test
fun testCustomBase64Sketch(){
Schema.handleSchema("pde://sketch/base64/LyoqCiAqIEFycmF5IE9iamVjdHMuIAogKiAKICogRGVtb25zdHJhdGVzIHRoZSBzeW50YXggZm9yIGNyZWF0aW5nIGFuIGFycmF5IG9mIGN1c3RvbSBvYmplY3RzLiAKICovCgppbnQgdW5pdCA9IDQwOwppbnQgY291bnQ7Ck1vZHVsZVtdIG1vZHM7Cgp2b2lkIHNldHVwKCkgewogIHNpemUoNjQwLCAzNjApOwogIG5vU3Ryb2tlKCk7CiAgaW50IHdpZGVDb3VudCA9IHdpZHRoIC8gdW5pdDsKICBpbnQgaGlnaENvdW50ID0gaGVpZ2h0IC8gdW5pdDsKICBjb3VudCA9IHdpZGVDb3VudCAqIGhpZ2hDb3VudDsKICBtb2RzID0gbmV3IE1vZHVsZVtjb3VudF07CgogIGludCBpbmRleCA9IDA7CiAgZm9yIChpbnQgeSA9IDA7IHkgPCBoaWdoQ291bnQ7IHkrKykgewogICAgZm9yIChpbnQgeCA9IDA7IHggPCB3aWRlQ291bnQ7IHgrKykgewogICAgICBtb2RzW2luZGV4KytdID0gbmV3IE1vZHVsZSh4KnVuaXQsIHkqdW5pdCwgdW5pdC8yLCB1bml0LzIsIHJhbmRvbSgwLjA1LCAwLjgpLCB1bml0KTsKICAgIH0KICB9Cn0KCnZvaWQgZHJhdygpIHsKICBiYWNrZ3JvdW5kKDApOwogIGZvciAoTW9kdWxlIG1vZCA6IG1vZHMpIHsKICAgIG1vZC51cGRhdGUoKTsKICAgIG1vZC5kaXNwbGF5KCk7CiAgfQp9?pde=Module:Y2xhc3MgTW9kdWxlIHsKICBpbnQgeE9mZnNldDsKICBpbnQgeU9mZnNldDsKICBmbG9hdCB4LCB5OwogIGludCB1bml0OwogIGludCB4RGlyZWN0aW9uID0gMTsKICBpbnQgeURpcmVjdGlvbiA9IDE7CiAgZmxvYXQgc3BlZWQ7IAogIAogIC8vIENvbnRydWN0b3IKICBNb2R1bGUoaW50IHhPZmZzZXRUZW1wLCBpbnQgeU9mZnNldFRlbXAsIGludCB4VGVtcCwgaW50IHlUZW1wLCBmbG9hdCBzcGVlZFRlbXAsIGludCB0ZW1wVW5pdCkgewogICAgeE9mZnNldCA9IHhPZmZzZXRUZW1wOwogICAgeU9mZnNldCA9IHlPZmZzZXRUZW1wOwogICAgeCA9IHhUZW1wOwogICAgeSA9IHlUZW1wOwogICAgc3BlZWQgPSBzcGVlZFRlbXA7CiAgICB1bml0ID0gdGVtcFVuaXQ7CiAgfQogIAogIC8vIEN1c3RvbSBtZXRob2QgZm9yIHVwZGF0aW5nIHRoZSB2YXJpYWJsZXMKICB2b2lkIHVwZGF0ZSgpIHsKICAgIHggPSB4ICsgKHNwZWVkICogeERpcmVjdGlvbik7CiAgICBpZiAoeCA+PSB1bml0IHx8IHggPD0gMCkgewogICAgICB4RGlyZWN0aW9uICo9IC0xOwogICAgICB4ID0geCArICgxICogeERpcmVjdGlvbik7CiAgICAgIHkgPSB5ICsgKDEgKiB5RGlyZWN0aW9uKTsKICAgIH0KICAgIGlmICh5ID49IHVuaXQgfHwgeSA8PSAwKSB7CiAgICAgIHlEaXJlY3Rpb24gKj0gLTE7CiAgICAgIHkgPSB5ICsgKDEgKiB5RGlyZWN0aW9uKTsKICAgIH0KICB9CiAgCiAgLy8gQ3VzdG9tIG1ldGhvZCBmb3IgZHJhd2luZyB0aGUgb2JqZWN0CiAgdm9pZCBkaXNwbGF5KCkgewogICAgZmlsbCgyNTUpOwogICAgZWxsaXBzZSh4T2Zmc2V0ICsgeCwgeU9mZnNldCArIHksIDYsIDYpOwogIH0KfQAA", base)
val captor = ArgumentCaptor.forClass(String::class.java)
verify(base).handleOpenUntitled(captor.capture())
val file = File(captor.value)
assert(file.exists())
val extra = file.parentFile.resolve("Module.pde")
assert(extra.exists())
file.parentFile.deleteRecursively()
}
@OptIn(ExperimentalEncodingApi::class)
@Test
fun testBase64SketchAndExtraFiles() {
@@ -49,8 +67,8 @@ class SchemaTest {
val base64 = Base64.encode(sketch.toByteArray())
Schema.handleSchema("pde://sketch/base64/$base64?pde=AnotherFile:$base64", base)
val captor = ArgumentCaptor.forClass(String::class.java)
val captor = ArgumentCaptor.forClass(String::class.java)
verify(base).handleOpenUntitled(captor.capture())
val file = File(captor.value)
@@ -66,6 +84,7 @@ class SchemaTest {
@Test
fun testURLSketch() {
Schema.handleSchema("pde://sketch/url/github.com/processing/processing-examples/raw/refs/heads/main/Basics/Arrays/Array/Array.pde", base)
waitForSchemeJobsToComplete()
val captor = ArgumentCaptor.forClass(String::class.java)
verify(base).handleOpenUntitled(captor.capture())
@@ -88,6 +107,7 @@ class SchemaTest {
])
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)
waitForSchemeJobsToComplete()
val captor = ArgumentCaptor.forClass(String::class.java)
verify(base).handleOpenUntitled(captor.capture())
@@ -110,4 +130,10 @@ class SchemaTest {
Preferences.save()
}
}
fun waitForSchemeJobsToComplete(){
runBlocking {
joinAll(*Schema.jobs.toTypedArray())
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 22 KiB

+19
View File
@@ -0,0 +1,19 @@
<svg width="825" height="825" viewBox="0 0 825 825" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2067_354)">
<mask id="mask0_2067_354" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="825" height="825">
<rect x="0.5" y="0.82666" width="824" height="824" rx="50" fill="#1369C9"/>
</mask>
<g mask="url(#mask0_2067_354)">
<rect x="0.5" y="0.82666" width="824" height="824" rx="50" fill="#1369C9"/>
<rect x="0.5" y="-19.1733" width="824" height="824" rx="50" fill="#489EFF"/>
<path d="M447.435 527.359C682.619 527.359 682.619 213.453 447.435 213.453" stroke="white" stroke-width="117.1"/>
<path d="M436.583 322.783L215.828 632.892" stroke="#9FCFFF" stroke-width="117.738"/>
<path d="M209.521 353.27L285.208 539.86" stroke="#1C48B5" stroke-width="117.044"/>
</g>
</g>
<defs>
<clipPath id="clip0_2067_354">
<rect width="824" height="824" fill="white" transform="translate(0.5 0.82666)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 710 KiB

+15
View File
@@ -59,6 +59,14 @@ menu.edit.decrease_indent = ← Decrease Indent
menu.edit.decrease_indent.keystroke.macos = meta pressed OPEN_BRACKET
menu.edit.decrease_indent.keystroke.windows = ctrl pressed OPEN_BRACKET
menu.edit.decrease_indent.keystroke.linux = ctrl pressed OPEN_BRACKET
menu.edit.increase_font = Increase Font Size
menu.edit.increase_font.keystroke.macos = meta pressed EQUALS
menu.edit.increase_font.keystroke.windows = ctrl pressed EQUALS
menu.edit.increase_font.keystroke.linux = ctrl pressed EQUALS
menu.edit.decrease_font = Decrease Font Size
menu.edit.decrease_font.keystroke.macos = meta pressed MINUS
menu.edit.decrease_font.keystroke.windows = ctrl pressed MINUS
menu.edit.decrease_font.keystroke.linux = ctrl pressed MINUS
menu.edit.find = Find...
menu.edit.find_next = Find Next
menu.edit.find_previous = Find Previous
@@ -631,6 +639,13 @@ beta.title = Welcome to the Processing Beta
beta.message = Thank you for trying out the new version of Processing. We're very grateful!\n\nPlease report any bugs on the forums.
beta.button = Got it!
# ---------------------------------------
# Beta
beta.window.title = Welcome to Beta
beta.title = Thanks for testing this Processing Beta!
beta.message = This preview release lets us gather feedback and fix issues before the final version. **Some features may not work as expected.** If you encounter problems, [please post on the forum](https://discourse.processing.org) or [open a GitHub issue](https://github.com/processing/processing4/issues).
beta.button = Ok
# ---------------------------------------
# Color Chooser
+3 -4
View File
@@ -318,10 +318,9 @@ update_check.updates_available.contributions = Er zijn updates beschikbaar voor
# ---------------------------------------
# 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!
beta.title = Dankuwel voor het testen van deze Processing Beta!
beta.message = Deze preview release laat ons feedback verzamelen en problemen oplossen. **Sommige functies werken mogelijk niet zoals verwacht.** Als u problemen ondervindt, [post dan op het forum](https://discourse.processing.org) of [open een GitHub issue](https://github.com/processing/processing4/issues).
beta.button = Ok
# ---------------------------------------
# Color Chooser
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #0066C5
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #C0FFFF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #374E81
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #834548
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #FFEBEC
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #0087A9
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #49D0A7
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #1A0300
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #9C9824
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #431D29
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #FFF2FF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #544587
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #47502C
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #FBFFD7
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #3D4B37
+4 -4
View File
@@ -161,16 +161,16 @@ editor.scrollbar.color = #978FAC
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #540000
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 90
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 60
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #CA0022
editor.gutter.highlight.color = #F7637B
# squiggly line underneath errors in the editor
editor.error.underline.color = #000000
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #9D0038
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #FFE8FF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #8F4965
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #F07D44
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #3E0000
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #D9964A
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #E9E9E9
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #00003B
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #809AE3
+4 -4
View File
@@ -161,16 +161,16 @@ editor.scrollbar.color = #FF6E38
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #000049
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #4F4CA9
editor.gutter.highlight.color = #9090ED
# squiggly line underneath errors in the editor
editor.error.underline.color = #000000
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #FF8F2F
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #470000
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 90
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 50
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #CF226A
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #697982
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #EFFFFF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #7C5295
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #4E535A
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #FAFFFF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #535558
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #00593B
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #B7FFEA
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #347A00
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #A55134
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #FFFDFB
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #888280
+4 -4
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #008A50
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.color = #71FFD5
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #CBFFEF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 90
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 60
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #8F9090
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #092D38
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #E1FFFF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #30505D
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #4A4E59
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #FAFEFF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #686C78
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #00926F
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #001E00
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #007757
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #B9BDC4
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #000009
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #92969D
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #BD8A68
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #270000
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #9C6D4C
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #402563
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #FFEFFF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #654788
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #7A896D
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #000700
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #606F54
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #6C7076
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #000009
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #565A60
+4 -4
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #973542
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.color = #FFDFE5
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #FFEFF2
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 90
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #B9545E
+4 -4
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #CC383C
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.color = #460000
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #fbb5b5
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 100
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 70
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #B11928
+4 -4
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #5E93BF
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.color = #00072B
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #000833
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #3E76A0
@@ -161,13 +161,13 @@ editor.scrollbar.color = #313E38
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #F2FFFA
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #515F58
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #869F36
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #000D00
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #678015
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #EFBA4E
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #2D0000
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #C29225
+3 -3
View File
@@ -161,13 +161,13 @@ editor.scrollbar.color = #06545D
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #C9FFFF
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 40
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #32747C
@@ -161,13 +161,13 @@ editor.scrollbar.color = #DE5C25
## PdeTextAreaPainter - extras added to the editor ##
editor.gutter.text.font = processing.mono,plain,12
editor.gutter.text.font = processing.mono,bold,16
editor.gutter.text.color = #440000
# transparency (0..100) for line numbers in gutter
editor.gutter.text.active.alpha = 70
editor.gutter.text.active.alpha = 80
# transparency for lines not currently in use
editor.gutter.text.inactive.alpha = 30
editor.gutter.text.inactive.alpha = 50
# bgcolor for the current (highlighted) line
editor.gutter.highlight.color = #BC4007
Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 KiB

+40
View File
@@ -0,0 +1,40 @@
<svg width="824" height="825" viewBox="0 0 824 825" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2066_295)">
<g clip-path="url(#clip1_2066_295)">
<rect y="0.82666" width="824" height="824" rx="412" fill="url(#paint0_linear_2066_295)"/>
<g filter="url(#filter0_dd_2066_295)">
<path d="M442.935 523.359C678.119 523.359 678.119 209.453 442.935 209.453" stroke="white" stroke-width="117.1"/>
<path d="M432.083 318.783L211.328 628.892" stroke="#9FCFFF" stroke-width="117.738"/>
<path d="M205.021 349.27L280.708 535.86" stroke="#1C48B5" stroke-width="117.044"/>
</g>
</g>
</g>
<defs>
<filter id="filter0_dd_2066_295" x="10.7905" y="10.9026" width="815.083" height="800.13" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="4" dy="4"/>
<feGaussianBlur stdDeviation="72"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2066_295"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="11"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_2066_295" result="effect2_dropShadow_2066_295"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_2066_295" result="shape"/>
</filter>
<linearGradient id="paint0_linear_2066_295" x1="178.174" y1="61.0872" x2="636.323" y2="764.108" gradientUnits="userSpaceOnUse">
<stop stop-color="#60B0FF"/>
<stop offset="1" stop-color="#308EFF"/>
</linearGradient>
<clipPath id="clip0_2066_295">
<rect width="824" height="824" fill="white" transform="translate(0 0.82666)"/>
</clipPath>
<clipPath id="clip1_2066_295">
<rect width="824" height="824" fill="white" transform="translate(0 0.82666)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

+6 -2
View File
@@ -2635,8 +2635,11 @@ public class PApplet implements PConstants {
keyPressed = true;
keyPressed(keyEvent);
}
case KeyEvent.RELEASE -> {
pressedKeys.remove(((long) keyCode << Character.SIZE) | key);
case KeyEvent.RELEASE -> {
pressedKeys.removeIf(hash -> {
int pressedKeyCode = (int)(hash >> Character.SIZE);
return pressedKeyCode == keyCode;
});
keyPressed = !pressedKeys.isEmpty();
keyReleased(keyEvent);
}
@@ -2842,6 +2845,7 @@ public class PApplet implements PConstants {
public void focusLost() {
// TODO: if user overrides this without calling super it's not gonna work
pressedKeys.clear();
keyPressed = false;
}
+17 -11
View File
@@ -1057,6 +1057,9 @@ public class PImage implements PConstants, Cloneable {
* [toxi 050728]
*/
protected void buildBlurKernel(float r) {
float maxRadius = Math.min(width, height) / 2.0f;
float maxR = maxRadius / 3.5f;
r = Math.min(r, maxR);
int radius = (int) (r * 3.5f);
if (radius < 1) radius = 1;
if (radius > 248) radius = 248;
@@ -1083,6 +1086,9 @@ public class PImage implements PConstants, Cloneable {
}
}
private int safeDivide(int numerator, int denominator) {
return denominator == 0 ? numerator : numerator / denominator;
}
protected void blurAlpha(float r) {
int sum, cb;
@@ -1115,7 +1121,7 @@ public class PImage implements PConstants, Cloneable {
read++;
}
ri = yi + x;
b2[ri] = cb / sum;
b2[ri] = safeDivide(cb, sum);
}
yi += pixelWidth;
}
@@ -1146,7 +1152,7 @@ public class PImage implements PConstants, Cloneable {
ri++;
read += pixelWidth;
}
pixels[x+yi] = (cb/sum);
pixels[x+yi] = safeDivide(cb, sum);
}
yi += pixelWidth;
ymi += pixelWidth;
@@ -1191,9 +1197,9 @@ public class PImage implements PConstants, Cloneable {
read++;
}
ri = yi + x;
r2[ri] = cr / sum;
g2[ri] = cg / sum;
b2[ri] = cb / sum;
r2[ri] = safeDivide(cr, sum);
g2[ri] = safeDivide(cg, sum);
b2[ri] = safeDivide(cb, sum);
}
yi += pixelWidth;
}
@@ -1228,7 +1234,7 @@ public class PImage implements PConstants, Cloneable {
ri++;
read += pixelWidth;
}
pixels[x+yi] = 0xff000000 | (cr/sum)<<16 | (cg/sum)<<8 | (cb/sum);
pixels[x+yi] = 0xff000000 | (safeDivide(cr, sum))<<16 | (safeDivide(cg, sum))<<8 | (safeDivide(cb, sum));
}
yi += pixelWidth;
ymi += pixelWidth;
@@ -1276,10 +1282,10 @@ public class PImage implements PConstants, Cloneable {
read++;
}
ri = yi + x;
a2[ri] = ca / sum;
r2[ri] = cr / sum;
g2[ri] = cg / sum;
b2[ri] = cb / sum;
a2[ri] = safeDivide(ca, sum);
r2[ri] = safeDivide(cr, sum);
g2[ri] = safeDivide(cg, sum);
b2[ri] = safeDivide(cb, sum);
}
yi += pixelWidth;
}
@@ -1315,7 +1321,7 @@ public class PImage implements PConstants, Cloneable {
ri++;
read += pixelWidth;
}
pixels[x+yi] = (ca/sum)<<24 | (cr/sum)<<16 | (cg/sum)<<8 | (cb/sum);
pixels[x+yi] = (safeDivide(ca, sum))<<24 | (safeDivide(cr, sum))<<16 | (safeDivide(cg, sum))<<8 | (safeDivide(cb, sum));
}
yi += pixelWidth;
ymi += pixelWidth;
@@ -4481,7 +4481,7 @@ public class PGraphicsOpenGL extends PGraphics {
// The minus sign is needed to invert the Y axis.
projection.set(x, 0, 0, tx,
0, -y, 0, ty,
0, -y, 0, -ty,
0, 0, z, tz,
0, 0, 0, 1);
@@ -0,0 +1,140 @@
package processing.core;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import processing.event.KeyEvent;
public class PAppletKeyEventTest {
private static final int SHIFT_MASK = 1;
private static final int CTRL_MASK = 2;
private static final int ALT_MASK = 4;
private PApplet applet;
@Before
public void setup() {
applet = new PApplet();
}
@Test
public void testSingleKeyPressAndRelease() {
KeyEvent pressEvent = new KeyEvent(null, 0L, KeyEvent.PRESS, 0, 'a', 65, false);
applet.handleKeyEvent(pressEvent);
Assert.assertEquals(1, applet.pressedKeys.size());
KeyEvent releaseEvent = new KeyEvent(null, 0L, KeyEvent.RELEASE, 0, 'a', 65, false);
applet.handleKeyEvent(releaseEvent);
Assert.assertEquals(0, applet.pressedKeys.size());
Assert.assertFalse(applet.keyPressed);
}
@Test
public void testShiftAndLetterSequence() {
KeyEvent pressA = new KeyEvent(null, 0L, KeyEvent.PRESS, 0, 'a', 65, false);
applet.handleKeyEvent(pressA);
KeyEvent pressShift = new KeyEvent(null, 0L, KeyEvent.PRESS, SHIFT_MASK, 'A', 16, false);
applet.handleKeyEvent(pressShift);
KeyEvent releaseA = new KeyEvent(null, 0L, KeyEvent.RELEASE, SHIFT_MASK, 'A', 65, false);
applet.handleKeyEvent(releaseA);
KeyEvent releaseShift = new KeyEvent(null, 0L, KeyEvent.RELEASE, 0, 'A', 16, false);
applet.handleKeyEvent(releaseShift);
Assert.assertFalse("keyPressed should be false after all keys released", applet.keyPressed);
Assert.assertTrue("pressedKeys should be empty", applet.pressedKeys.isEmpty());
}
@Test
public void testControlAndLetterSequence() {
KeyEvent pressCtrl = new KeyEvent(null, 0L, KeyEvent.PRESS, CTRL_MASK, '\0', 17, false);
applet.handleKeyEvent(pressCtrl);
KeyEvent pressC = new KeyEvent(null, 0L, KeyEvent.PRESS, CTRL_MASK, (char)3, 67, false);
applet.handleKeyEvent(pressC);
KeyEvent releaseC = new KeyEvent(null, 0L, KeyEvent.RELEASE, CTRL_MASK, 'c', 67, false);
applet.handleKeyEvent(releaseC);
KeyEvent releaseCtrl = new KeyEvent(null, 0L, KeyEvent.RELEASE, 0, '\0', 17, false);
applet.handleKeyEvent(releaseCtrl);
Assert.assertFalse("keyPressed should be false after all keys released", applet.keyPressed);
Assert.assertTrue("pressedKeys should be empty", applet.pressedKeys.isEmpty());
}
@Test
public void testAltAndLetterSequence() {
KeyEvent pressV = new KeyEvent(null, 0L, KeyEvent.PRESS, 0, 'v', 86, false);
applet.handleKeyEvent(pressV);
KeyEvent pressAlt = new KeyEvent(null, 0L, KeyEvent.PRESS, ALT_MASK, 'v', 18, false);
applet.handleKeyEvent(pressAlt);
KeyEvent releaseV = new KeyEvent(null, 0L, KeyEvent.RELEASE, ALT_MASK, 'v', 86, false);
applet.handleKeyEvent(releaseV);
KeyEvent releaseAlt = new KeyEvent(null, 0L, KeyEvent.RELEASE, 0, 'v', 18, false);
applet.handleKeyEvent(releaseAlt);
Assert.assertFalse("keyPressed should be false after all keys released", applet.keyPressed);
Assert.assertTrue("pressedKeys should be empty", applet.pressedKeys.isEmpty());
}
@Test
public void testKeyRepeat() {
applet.keyRepeatEnabled = false;
KeyEvent pressR = new KeyEvent(null, 0L, KeyEvent.PRESS, 0, 'r', 82, false);
applet.handleKeyEvent(pressR);
KeyEvent repeatR = new KeyEvent(null, 0L, KeyEvent.PRESS, 0, 'r', 82, true);
applet.handleKeyEvent(repeatR);
Assert.assertTrue("keyPressed should be true after key press", applet.keyPressed);
Assert.assertEquals("pressedKeys should have 1 entry", 1, applet.pressedKeys.size());
KeyEvent releaseR = new KeyEvent(null, 0L, KeyEvent.RELEASE, 0, 'r', 82, false);
applet.handleKeyEvent(releaseR);
Assert.assertFalse("keyPressed should be false after key release", applet.keyPressed);
Assert.assertEquals("pressedKeys should be empty", true, applet.pressedKeys.isEmpty());
}
@Test
public void testKeyRepeatEnabled() {
applet.keyRepeatEnabled = true;
KeyEvent pressT = new KeyEvent(null, 0L, KeyEvent.PRESS, 0, 't', 84, false);
applet.handleKeyEvent(pressT);
KeyEvent repeatT = new KeyEvent(null, 0L, KeyEvent.PRESS, 0, 't', 84, true);
applet.handleKeyEvent(repeatT);
Assert.assertTrue("keyPressed should be true with key repeat enabled", applet.keyPressed);
Assert.assertEquals("pressedKeys should have 1 entry", 1, applet.pressedKeys.size());
KeyEvent releaseT = new KeyEvent(null, 0L, KeyEvent.RELEASE, 0, 't', 84, false);
applet.handleKeyEvent(releaseT);
Assert.assertFalse("keyPressed should be false after key release", applet.keyPressed);
Assert.assertEquals("pressedKeys should be empty", true, applet.pressedKeys.isEmpty());
}
@Test
public void testKeyFocusLost() {
KeyEvent pressF = new KeyEvent(null, 0L, KeyEvent.PRESS, 0, 'f', 70, false);
applet.handleKeyEvent(pressF);
Assert.assertTrue("keyPressed should be true after key press", applet.keyPressed);
Assert.assertEquals("pressedKeys should have 1 entry", 1, applet.pressedKeys.size());
applet.focusLost();
Assert.assertFalse("keyPressed should be false after focus lost", applet.keyPressed);
Assert.assertEquals("pressedKeys should be empty after focus lost", true, applet.pressedKeys.isEmpty());
}
}