Closes#6261
- Adds support for copy-pasting nodes with `cmd + C` and `cmd + V` shortcuts.
- Only a single, currently selected node will be copied. Adding support for multiple node copies seems easy, though (but was out of the scope of the task).
- We use a custom data format for clipboard content. Node's metadata is also copied, so opened visualizations are preserved. However, the visualization's size is not preserved, as we do not store this info in metadata.
- For custom format to work, we use a pretty new feature called [Clipboard pickling](https://github.com/w3c/editing/blob/gh-pages/docs/clipboard-pickling/explainer.md), but it is available in Electron and in most browsers already.
- Pasting plain text from other applications (or from Enso, if the code is copied in edit mode) is supported and is currently enabled. There are some security concerns related to this, though. I will create a separate issue/discussion for that.
- Undo/redo works as you expect.
- New node is pasted at the cursor position.
https://github.com/enso-org/enso/assets/6566674/7a04d941-19f7-4a39-9bce-0e554af50ba3
Introduce new APIs for managing focus and using focus to inform delivery of keyboard events.
Use new APIs to implement the following behavior:
Focus:
- If the component browser is opened, its initial state is *focused*.
- If the node input area's text component is clicked, the component browser's state becomes *blurred*.
- If a click occurs anywhere in the component browser, the component browser's state becomes *focused*.
Event dispatch:
- When the component browser is in the *focused* state, it handles certain keyboard events (chiefly, arrow keys).
- If the component browser handles an event, the event is not received by other components.
- If an event occurs that the component browser doesn't handle, the node input area's text component receives the event.
[vokoscreenNG-2023-06-29_10-55-00.webm](https://github.com/enso-org/enso/assets/1047859/f1d9d07c-8c32-4482-ba32-15b6e4e20ae7)
# Important Notes
Changes to display object interface:
- **`display::Object` can now be derived.**
- Introduce display object *focus receiver* concept. Many components, when receiving focus, should actually be focused indirectly by focusing a descendant.
- For example, when the CB Panel receives focus, its descendant at `self.model().grid.model().grid` should be focused, because that's the underlying Grid View, which has its own event handlers. By allowing each level of the hierarchy to define a `focus_receiver`, focus can reach the right object without the CB panel having to know structural details of its descendants.
- When delegating to a field's `display::Object` implementation, the derived implementation uses the child's `focus_receiver`, which will normally be the correct behavior.
**Changes to `shortcut` API**:
- New `View::focused_shortcuts()` is a focus-aware alternative to `View::default_shortcuts()` (which should now only be used for global shortcuts, i.e. shortcuts that don't depend on whether the component is focused). It's based on the *Keyboard Event* API (see below), so events propagate up the focus hierarchy until a shortcut is executed and `stop_propagation()` is called; this allows sensible resolution of event targets when more than one component is capable of handling the same keypress.
Keypress dataflow overview:
DOM -> KeyboardManager -> FrpKeyboard -> KeyboardEvents -> Shortcut.
Low-level keyboard changes to support Focus:
- New `KeyboardManager`: Attaches DOM event handlers the same way as `MouseManager`.
- New *Keyboard Event* API: `on_event::<KeyDown>()`. Events propagate up the focus hierarchy. This API is used for low-level keyboard listeners such a `Text`, which may need complex logic to determine whether a key is handled (rather than having a closed set of bindings, which can be handled by `shortcut`).
- FRP keyboard: Now attaches to the `KeyboardManager` API. It now serves primarily to produce Keyboard Events (it still performs the role of making `KeyUp` events saner in a couple different ways). The FRP keyboard can also be used directly as a global keyboard, for such things as reacting to modifier state.
Misc:
- Updated the workspace `syn` to version 2. Crates still depending on legacy `syn` now do so through the workspace-level `syn_1` alias.
1. Fixed leaks of Scene. We were making several cycles of Rc references.
2. Fix removing event listeners: the remove listener option should take same options as those passed in addEventListener.
This should finally fix#6505
Implements #5640 and #5650
It made sense for me to implement those two together, as I wanted to make sure that the necessary widget API changes will support custom entry values for both dynamic and static data.
- Added support for custom dropdown labels defined on the method annotations
- Added shortening of static dropdown values, which resolves
| dynamic dropdown - custom labels | static dropdown - automatic shortening |
|-|-|
|![image](https://user-images.githubusercontent.com/919491/220117241-8682736e-d750-4eeb-b9bb-cd6cfce42356.png)|![image](https://user-images.githubusercontent.com/919491/220117412-05ad7f4a-3ccf-468b-a976-c52395a497e2.png)|
# Important Notes
During implementation I had multiple data update order issues caused by FRP network forming a diamond shape. Two inputs that are often updated together were combined with `all` combinator, and that was further fed into the dropdown. This caused two updates to propagate through the whole network, and one of them was immediately outdated. To fix this and similar future scenarios, I've added an `next_tick` FRP node. It buffers the incoming events until the next browser microtask, preserving only the last received event. Currently if it is called inside a `requestAnimationFrame` callback, the effects of that processing will only be rendered in the next frame. Later this can be mitigated by delaying the rendering logic until the microtask queue is empty.
Visualizations closing right after opening was caused by the GUI being unresponsive during loading of some visualizations. This caused the timer for measuring the time between space bar press and space bar release to be inflated. The delayed events triggered the "visualization preview mode”, thus closing the visualization has it seemed that the space bar was held down, even though the events just arrived with some delay.
The problem is mitigated by considering the number of frames that have passed between the space and down and the space bar up event, instead of just the wall clock time. If the number of frames is too low, this indicates that frames were dropped to the time is inflated.
Fixes https://github.com/enso-org/enso/issues/5223
This PR implements HTML generation from documentation IR for all suggestion database entries and replaces the old documentation panel with a newer one.
Additional adjustments to the looks of the documentation would be applied separately in a future PR. This PR focuses on the fastest possible delivery of a usable documentation panel. We want to test it in real-world use cases and gather feedback for future improvements.
Documentation demo scene with mocked data:
https://user-images.githubusercontent.com/6566674/213436313-88753ed8-346f-423e-956e-7db39f5dc266.mp4
Component browser with actual engine-provided data:
https://user-images.githubusercontent.com/6566674/213436375-d0ec074b-f7a6-4deb-a7de-3adee999cc86.mp4
# Important Notes
- Fixed language protocol data structures.
- Scrolling to the selected method is also implemented here.
- Also, the selected item is highlighted with yellow.
- Only some pieces of information we have are displayed. For example, we don't display return types for methods or types of arguments.
- A bunch of code related to previous implementation is removed, but probably not all of it.
Logging: Replace tracing with an efficient logging implementation, with 0-runtime cost for disabled log levels. (https://www.pivotaltracker.com/story/show/183755412)
Profiling: Support submitting `profiler` events to the User Timing Web API, so that measurements can be viewed directly in the browser. (https://www.pivotaltracker.com/story/show/184003550)
# Important Notes
Logging interface:
- The macros (`warn!`, etc.) now take standard `format_args!` arguments (the tracing implementations accepted a broader syntax).
- Compile-time log levels can now be set through the CLI, like so:
`./run ide start --log-level=trace --uncollapsed-log-level=info`
Profiling:
- The hotkey Ctrl+Alt+Shift+P submits all `profiler` events logged since the application was loaded to the Web API, so that they can then be viewed with the browser's developer tools. Note that standard tools are not able to represent async task lifetimes or metadata; this is a convenient interface to a subset of `profiler` data.
- As an alternative interface, a runtime flag enables continuous measurement submission. In the browser it can be set through a URL parameter, like http://localhost:8080/?emit_user_timing_measurements=true. Note that this mode significantly impacts performance.
Implement a command that launches the application, runs a series of steps (a "workflow"), writes a profile to a file, and exits.
See: [#181775808](https://www.pivotaltracker.com/story/show/181775808)
# Important Notes
- The command to capture run and profile is used like: `./run profile --workflow=new_project --save-profile=out.json`. Defining some more workflows (collapse nodes, create node and edit value) comes next; they are implemented with the same infrastructure as the integration-tests.
- The `--save-profile` option can also be used when profiling interactively; when the option is provided, capturing a profile with the hotkey will write a file instead of dumping the data to the devtools console.
- If the IDE panics, the error message is now printed to the console that invoked the process, as well as the devtools console. (If a batch workflow fails, this allows us to see why.)
- New functionality (writing profile files, quitting on command, logging to console) relies on Electron APIs. These APIs are implemented in `index.js`, bridged to the render process in `preload.js`, and wrapped for use in Rust in a `debug_api` crate.
* The List View component was refactored: it allows for hiding the internal selection widget, and exposes information where the widget should be placed. This allows us to create selection widget in component list panel, so it can be animated between component groups and sections.
* Fixed some warnings when checking WASM code.
* Adjusted the style of Component Group View a little, so it better reflects the design doc. Still not ideal, because the list_view has some weird design regarding padding, but I don't want to stuck in some bigger refactoring.
I will add a video in a few minutes.
# Important Notes
https://user-images.githubusercontent.com/3919101/165507826-60329f9e-7de3-4eb2-9271-292e45568cb2.mov
See: [#181837344](https://www.pivotaltracker.com/story/show/181837344).
I've separated this PR from some deeper changes I'm making to the profile format, because the changeset was getting too complex. The new APIs and tools in this PR are fully-implemented, except the profile format is too simplistic--it doesn't currently support headers that are needed to determine the relative timings of events from different processes.
- Adds basic support for profile files containing data collected by multiple processes.
- Implements `api_events_to_profile`, a tool for converting backend message logs (#3392) to the `profiler` format so they can be merged with frontend profiles (currently they can be merged with `cat`, but the next PR will introduce a merge tool).
- Introduces `message_beanpoles`, a simple tool that diagrams timing relationships between frontend and backend messages.
### Important Notes
- All TODOs introduced here will be addressed in the next PR that defines the new format.
- Introduced a new crate, `enso_profiler_enso_data`, to be used by profile consumers that need to refer to Enso application datatypes to interpret metadata.
- Introduced a `ProfileBuilder` abstraction for writing the JSON profile format; partially decouples the runtime event log structures from the format definition.
- Introducing the conversion performed for `ProfilerBuilder` uncovered that the `.._with_same_start!` low-level `profiler` APIs don't currently work; they return `Started<_>` profilers, but that is inconsistent with the stricter data model that I introduced when I implemented `profiler_data`; they need to return profilers in a created, unstarted state. Low-level async profilers have not been a priority, but once #3382 merges we'll have a way to render their data, which will be really useful because async profilers capture *why* we're doing things. I'll bring up scheduling this in the next performance meeting.
This change makes EnsoGL runtime stats be always collected, even when EnsoGL `Monitor` panel is not visible. Those stats are intended to be used in the future by a profiling framework.
**Performance impact:** Continuous collection of stats introduces an overhead of two Web Performance API `now()` calls in each frame of the main rendering loop, plus a small number of simple arithmetic calculations. This is assumed to be a negligible and acceptable overhead.
#### Visuals
A screenshot of the Monitor panel in full `ide` after applying the PR, taken in IDE built with `./run dist`:
<img width="991" alt="Screenshot 2022-02-14 at 16 11 42" src="https://user-images.githubusercontent.com/273837/153891378-8a2fb333-34ce-46ce-99df-7d796817310c.png">
A recording, also in IDE built with `./run dist`; note that FPS is impacted by the act of recording itself:
https://user-images.githubusercontent.com/273837/154104016-49a12e23-1210-4477-9743-ec1611e5b4ed.movhttps://www.pivotaltracker.com/story/show/181093601
# Important Notes
- Responsibility for controlling how `Stats` gathering and calculation is performed at various points in the main rendering loop was removed from `Monitor` - the `Monitor`'s purpose is only to display existing data, it should not influence how the data is collected.
- Two previously existing distinct `Monitor` structs were merged into one, to avoid confusion; after previous refactorings, the remaining `stats::Monitor` did not have much useful code anyway.
- In `stats` package, refactoring was done, to make `StatsData` a "dumb", data-only type, and to move the logic related to stats collection and frame tracking to other helper types.
[ci no changelog needed]