enso/app/gui/src/ide.rs
Ilya Bogdanov 0d74ab6124
Breadcrumbs integration (#3720)
[ci no changelog needed]
[Task link](https://www.pivotaltracker.com/story/show/182675703)

This PR implements the actual integration of the breadcrumbs panel with the component list panel. A special breadcrumbs controller (`controller::searcher::breadcrumbs`) is tracking the currently opened module with a list of its parents. The searcher presenter uses the API of the controller to sync the displayed list of breadcrumbs with the controller state.


https://user-images.githubusercontent.com/6566674/193064122-7d3fc4d6-9148-4ded-a73e-767ac9ac83f8.mp4

# Important Notes
- There is an `All` breadcrumb displayed at all times at the beginning of the list. It will be replaced with a section name as part of [Section Title on Component Browser's Breadcrumbs Panel](https://www.pivotaltracker.com/story/show/182610561) task.
- I changed the implementation of `project::main_module_id`, `project::QualifiedName::main_module`, and `API::main_module` so that they are logically connected which each other.
- I adjusted the Breadcrumbs View to avoid "appearance" animation glitches when opening new modules. `set_entries` was replaced with the `set_entries_from` endpoint.
2022-10-03 10:54:09 +00:00

109 lines
3.2 KiB
Rust

//! This module contains the IDE object implementation.
use crate::prelude::*;
use crate::presenter::Presenter;
use analytics::AnonymousData;
use enso_frp as frp;
use ensogl::system::web::sleep;
use std::time::Duration;
// ==============
// === Export ===
// ==============
pub mod initializer;
pub use initializer::Initializer;
// =================
// === Constants ===
// =================
/// Text that shows up in the statusbar when any of the backend connections is lost.
pub const BACKEND_DISCONNECTED_MESSAGE: &str =
"Connection to the backend has been lost. Please try restarting IDE.";
const ALIVE_LOG_INTERVAL_SEC: u64 = 60;
// ===========
// === Ide ===
// ===========
/// The main Ide structure.
///
/// This structure is a root of all objects in our application. It includes both layers:
/// Controllers and Views, and an integration between them.
#[allow(missing_docs)]
#[derive(Debug)]
pub struct Ide {
pub ensogl_app: ensogl::application::Application,
pub presenter: Presenter,
network: frp::Network,
}
impl Ide {
/// Constructor.
pub fn new(
ensogl_app: ensogl::application::Application,
view: ide_view::root::View,
controller: controller::Ide,
) -> Self {
let presenter = Presenter::new(controller, view);
let network = frp::Network::new("Ide");
Ide { ensogl_app, presenter, network }.init()
}
fn init(self) -> Self {
executor::global::spawn(self.alive_log_sending_loop());
self
}
fn alive_log_sending_loop(&self) -> impl Future<Output = ()> + 'static {
let network = &self.network;
let scene = &self.ensogl_app.display.default_scene;
let mouse = &scene.mouse.frp;
let keyboard = &scene.keyboard.frp;
enso_frp::extend! { network
on_log_sent <- source::<()>();
mouse_moved <- mouse.position.constant(()).profile();
any_mouse_press <- any(mouse.up,mouse.down).constant(()).profile();
any_mouse_event <- any(any_mouse_press,mouse_moved,mouse.wheel).profile();
any_keyboard_event <- any(keyboard.down,keyboard.up).constant(()).profile();
any_input_event <- any(any_mouse_event,any_keyboard_event).profile();
// True if any input event was captured since the last "alive" log sending.
input_event_received <- bool(&on_log_sent,&any_input_event).profile().sampler();
}
async move {
loop {
let value = AnonymousData(input_event_received.value());
analytics::remote_log_value("alive", "input_event_received", value);
on_log_sent.emit(());
sleep(Duration::from_secs(ALIVE_LOG_INTERVAL_SEC)).await;
}
}
}
}
/// A reduced version of [`Ide`] structure, representing an application which failed to initialize.
///
/// It contains only the view displaying the error. No connection to the backend is maintained.
#[allow(missing_docs)]
#[derive(Debug)]
pub struct FailedIde {
pub view: ide_view::root::View,
}
/// The Path of the module initially opened after opening project in IDE.
pub fn initial_module_path(project: &model::Project) -> model::module::Path {
project.main_module_path()
}