Plots in an editor
Address #2270
This adds an action to display a plot from the Plots pane in an editor. It works on static and dynamic plots. It is an editor just for plots and hosts a React container to reuse the components from the Plots pane. So, it could easily display web plots.
A new editor and editor input has been created. The plot id is used for the editor title. It's not very descriptive and perhaps should be replaced with something that makes sense for a user. The plots service now tracks another list of plots for editors. The original plot client is cloned as a new object. It uses the same plot id as the original plot. The service now has an openEditor() method that opens the current plot in an editor.
The entire feature is hidden behind an experimental flag. It is in the Application > Experimental category in the preferences. It is off by default until the rest of the editor actions are implemented. See the issue for linked follow-up work.
QA Notes
It's likely buggy with how the plot behaves with being moved into a new window and splitting the editor. It shares the sizing policy with the Plots pane so changing it there will re-render the editor in the new size.
Makes sense to address the plot clients and the comm. I think it's good to use one comm so that any messages can update multiple plot clients. I did notice that the Runtimes view shows new runtime clients when opening a plot in an editor. But all those plot runtime clients are closed once the plot is closed.
Pushing a rebase on main and moving the PR into draft.
It looks like it's best to create a new comm backed by the same plot in the backend. It will require updating Ark as well but this should simplify the frontend. It turns out sharing a comm on the frontend makes it far more complicated with render queues, throttling, and managing the render events.
If we move this complexity to the backend we will also need to implement for Python and all future language packs. I'd rather have the front end handle all of the complexity around events/throttling since it will keep the logic in one place and make things simpler at the API level.
I'd imagine this could work by adding a service that can manage the plot comms, adding and removing UI instances of the plot (e.g. for the editor placement, the Plots pane, the Save dialog, etc.) and maintaining a single render queue but only delivering events/RPC results to the UI instance that owned the request. When the UI instance refcount drops to zero, we can dispose the comm.
Willing to be convinced otherwise, lmk if you want to discuss realtime!
This is now at a point where the PlotClientInstance has been refactored with the calls to the comm pulled out into PositronPlotCommProxy. This allows sharing the comm while the plot clients can request renders with their own parameters.
The plots service tracks how many clients are still using the comm and will dispose the comm when no more clients are using it. It still uses a new plot client list for editors. I do think it's worth following up with another change to go back to one list by updating IPositronPlotMetadata with a location. This should make it easy to save the plot state for editors and restore it when the UI reloads.
I noticed the progress misplacement as well. I opened https://github.com/posit-dev/positron/issues/4562 to address it later.
I expect https://github.com/posit-dev/positron/issues/4358 to address the sizing policy. It should allow different sizing polices for the editors. Now that the plot client has the comm messages separated, it will be easier for each client to have its own render parameters.
I noticed that the comm events weren't hooked up in the comm proxy. It was preventing the plot client from disposing when the comm closed.
The editor won't close when the comm closes. I think a follow up can address this. It can do the same thing as the data explorer and show a message that the plot is gone.