mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 22:10:15 +03:00
No rendering after drop (#6911)
This commit is contained in:
parent
67821bf8df
commit
e9e90fe152
@ -81,7 +81,7 @@ impl Initializer {
|
||||
match self.initialize_ide_controller_with_retries().await {
|
||||
Ok(controller) => {
|
||||
let can_manage_projects = controller.can_manage_projects();
|
||||
let ide = Ide::new(ensogl_app, view.clone_ref(), controller);
|
||||
let ide = Ide::new(ensogl_app, view, controller);
|
||||
if can_manage_projects {
|
||||
if let Some(project) = &self.config.project_to_open {
|
||||
ide.open_or_create_project(project.clone());
|
||||
|
@ -203,12 +203,20 @@ pub fn main() {
|
||||
#[wasm_bindgen]
|
||||
pub fn drop() {
|
||||
let ide = IDE.with(RefCell::take);
|
||||
if let Some(Ok(ide)) = &ide {
|
||||
if let Some(Ok(ide)) = ide {
|
||||
//TODO[ao] #6420 We should not do this, but somehow the `dom` field in the scene is
|
||||
// leaking.
|
||||
ide.ensogl_app.display.default_scene.dom.root.remove();
|
||||
}
|
||||
mem::drop(ide);
|
||||
// The presenter need to be dropped first, so all visible components should hide themselves
|
||||
// and be pushed to the garbage collector before we clear it.
|
||||
mem::drop(ide.presenter);
|
||||
//TODO[ao] As widgets which are garbage-collected may (and ofter do) keep references to
|
||||
// [`Application`] or [`World`], we need to force dropping them. This is not an ideal
|
||||
// solution, but the garbage collector will be removed soon anyway - see
|
||||
// https://github.com/enso-org/enso/issues/6850#issuecomment-1576754037
|
||||
ide.ensogl_app.display.force_garbage_drop();
|
||||
mem::drop(ide.ensogl_app)
|
||||
};
|
||||
EXECUTOR.with(RefCell::take);
|
||||
leak_detector::TRACKED_OBJECTS.with(|objects| {
|
||||
let objects = objects.borrow();
|
||||
|
@ -12,7 +12,6 @@ use crate::presenter::graph::AstNodeId;
|
||||
use crate::presenter::graph::ViewNodeId;
|
||||
|
||||
use enso_frp as frp;
|
||||
use ensogl::application::View;
|
||||
use ide_view as view;
|
||||
use ide_view::graph_editor::component::node as node_view;
|
||||
use ide_view::graph_editor::component::visualization as visualization_view;
|
||||
@ -181,7 +180,6 @@ impl Visualization {
|
||||
state,
|
||||
});
|
||||
|
||||
let app = &view.app().frp;
|
||||
frp::extend! { network
|
||||
eval view.visualization_shown (((node, metadata)) model.visualization_shown(*node, metadata.clone()));
|
||||
eval view.visualization_hidden ((node) model.visualization_hidden(*node));
|
||||
@ -196,8 +194,7 @@ impl Visualization {
|
||||
|
||||
view.set_visualization_data <+ set_data;
|
||||
view.set_error_visualization_data <+ error_update;
|
||||
view.disable_visualization <+ visualization_failure._0();
|
||||
app.show_notification <+ visualization_failure._1();
|
||||
view.visualization_update_failed <+ visualization_failure;
|
||||
|
||||
eval_ view.visualization_registry_reload_requested (model.load_visualizations());
|
||||
}
|
||||
|
@ -492,10 +492,6 @@ impl ensogl_core::application::View for Breadcrumbs {
|
||||
Self::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
self.widget.app()
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<Shortcut> {
|
||||
use ensogl_core::application::shortcut::ActionType::*;
|
||||
[(Press, "shift enter", "move_up"), (Press, "ctrl shift enter", "move_down")]
|
||||
|
@ -246,7 +246,6 @@ pub struct Model {
|
||||
|
||||
impl Model {
|
||||
fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let scene = &app.display.default_scene;
|
||||
let display_object = display::object::Instance::new();
|
||||
|
||||
@ -256,7 +255,7 @@ impl Model {
|
||||
let grid = app.new_view::<grid::View>();
|
||||
display_object.add_child(&grid);
|
||||
|
||||
let section_navigator = SectionNavigator::new(&app);
|
||||
let section_navigator = SectionNavigator::new(app);
|
||||
display_object.add_child(§ion_navigator);
|
||||
|
||||
let breadcrumbs = app.new_view::<breadcrumbs::Breadcrumbs>();
|
||||
|
@ -132,6 +132,7 @@ pub struct BreadcrumbsModel {
|
||||
/// A container for all the breadcrumbs after project name. This contained and all its
|
||||
/// breadcrumbs are moved when project name component is resized.
|
||||
breadcrumbs_container: display::object::Instance,
|
||||
// Required for creating new breadcrumbs
|
||||
app: Application,
|
||||
breadcrumbs: Rc<RefCell<Vec<Breadcrumb>>>,
|
||||
frp_inputs: FrpInputs,
|
||||
|
@ -127,7 +127,6 @@ impl Animations {
|
||||
#[derive(Debug, Clone, CloneRef)]
|
||||
#[allow(missing_docs)]
|
||||
struct ProjectNameModel {
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
view: background::View,
|
||||
style: StyleWatch,
|
||||
@ -138,7 +137,6 @@ struct ProjectNameModel {
|
||||
impl ProjectNameModel {
|
||||
/// Constructor.
|
||||
fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let scene = &app.display.default_scene;
|
||||
let display_object = display::object::Instance::new();
|
||||
// FIXME : StyleWatch is unsuitable here, as it was designed as an internal tool for shape
|
||||
@ -160,7 +158,7 @@ impl ProjectNameModel {
|
||||
scene.layers.panel.add(&view);
|
||||
|
||||
let project_name = default();
|
||||
Self { app, display_object, view, style, text_field, project_name }.init()
|
||||
Self { display_object, view, style, text_field, project_name }.init()
|
||||
}
|
||||
|
||||
/// Compute the width of the ProjectName view.
|
||||
@ -423,12 +421,10 @@ impl View for ProjectName {
|
||||
fn label() -> &'static str {
|
||||
"ProjectName"
|
||||
}
|
||||
|
||||
fn new(app: &Application) -> Self {
|
||||
ProjectName::new(app)
|
||||
}
|
||||
fn app(&self) -> &Application {
|
||||
&self.model.app
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<shortcut::Shortcut> {
|
||||
use shortcut::ActionType::*;
|
||||
|
@ -402,6 +402,7 @@ impl Deref for Node {
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct NodeModel {
|
||||
// Required for switching the node to a different layer
|
||||
pub app: Application,
|
||||
pub display_object: display::object::Instance,
|
||||
pub background: Background,
|
||||
|
@ -133,7 +133,6 @@ impl From<node::Expression> for Expression {
|
||||
/// Internal model of the port area.
|
||||
#[derive(Debug)]
|
||||
pub struct Model {
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
edit_mode_label: text::Text,
|
||||
expression: RefCell<Expression>,
|
||||
@ -152,17 +151,16 @@ impl Model {
|
||||
/// Constructor.
|
||||
#[profile(Debug)]
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let display_object = display::object::Instance::new_named("input");
|
||||
|
||||
let edit_mode_label = app.new_view::<text::Text>();
|
||||
let expression = default();
|
||||
let styles = StyleWatch::new(&app.display.default_scene.style_sheet);
|
||||
let styles_frp = StyleWatchFrp::new(&app.display.default_scene.style_sheet);
|
||||
let widget_tree = widget::Tree::new(&app);
|
||||
let widget_tree = widget::Tree::new(app);
|
||||
with_context(|ctx| ctx.layers.widget.add(&widget_tree));
|
||||
Self { app, display_object, edit_mode_label, expression, styles, styles_frp, widget_tree }
|
||||
.init()
|
||||
Self { display_object, edit_mode_label, expression, styles, styles_frp, widget_tree }
|
||||
.init(app)
|
||||
}
|
||||
|
||||
/// React to edit mode change. Shows and hides appropriate child views according to current
|
||||
@ -183,19 +181,24 @@ impl Model {
|
||||
}
|
||||
|
||||
#[profile(Debug)]
|
||||
fn init(self) -> Self {
|
||||
fn init(self, app: &Application) -> Self {
|
||||
// TODO: Depth sorting of labels to in front of the mouse pointer. Temporary solution.
|
||||
// It needs to be more flexible once we have proper depth management.
|
||||
// See https://www.pivotaltracker.com/story/show/183567632.
|
||||
let scene = &self.app.display.default_scene;
|
||||
let scene = &app.display.default_scene;
|
||||
self.set_label_layer(&scene.layers.label);
|
||||
|
||||
let text_color = self.styles.get_color(theme::graph_editor::node::text);
|
||||
|
||||
self.edit_mode_label.set_single_line_mode(true);
|
||||
self.edit_mode_label.disable_command("cursor_move_up");
|
||||
self.edit_mode_label.disable_command("cursor_move_down");
|
||||
self.edit_mode_label.disable_command("add_cursor_at_mouse_position");
|
||||
|
||||
app.commands.set_command_enabled(&self.edit_mode_label, "cursor_move_up", false);
|
||||
app.commands.set_command_enabled(&self.edit_mode_label, "cursor_move_down", false);
|
||||
app.commands.set_command_enabled(
|
||||
&self.edit_mode_label,
|
||||
"add_cursor_at_mouse_position",
|
||||
false,
|
||||
);
|
||||
self.edit_mode_label.set_property_default(text_color);
|
||||
self.edit_mode_label.set_property_default(text::Size(TEXT_SIZE));
|
||||
self.edit_mode_label.remove_all_cursors();
|
||||
|
@ -400,6 +400,7 @@ fn entry_for_current_value(
|
||||
/// is minimal, as the actual dropdown view is not created.
|
||||
#[derive(Debug)]
|
||||
struct LazyDropdown {
|
||||
// Required for lazy initialization
|
||||
app: ensogl::application::Application,
|
||||
set_all_entries: frp::Any<Vec<Choice>>,
|
||||
set_selected_entries: frp::Any<HashSet<Choice>>,
|
||||
|
@ -156,7 +156,6 @@ impl Model {
|
||||
/// Constructor.
|
||||
#[profile(Debug)]
|
||||
pub fn new(app: &Application, frp: &Frp) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let display_object = display::object::Instance::new_named("output");
|
||||
let ports = display::object::Instance::new();
|
||||
let port_models = default();
|
||||
@ -169,7 +168,7 @@ impl Model {
|
||||
display_object.add_child(&label);
|
||||
display_object.add_child(&ports);
|
||||
Self {
|
||||
app,
|
||||
app: app.clone_ref(),
|
||||
display_object,
|
||||
ports,
|
||||
port_models,
|
||||
@ -180,21 +179,21 @@ impl Model {
|
||||
styles_frp,
|
||||
frp,
|
||||
}
|
||||
.init()
|
||||
.init(app)
|
||||
}
|
||||
|
||||
#[profile(Debug)]
|
||||
fn init(self) -> Self {
|
||||
fn init(self, app: &Application) -> Self {
|
||||
// FIXME[WD]: Depth sorting of labels to in front of the mouse pointer. Temporary solution.
|
||||
// It needs to be more flexible once we have proper depth management.
|
||||
let scene = &self.app.display.default_scene;
|
||||
let scene = &app.display.default_scene;
|
||||
scene.layers.main.remove(&self.label);
|
||||
self.label.add_to_scene_layer(&scene.layers.label);
|
||||
|
||||
let text_color = self.styles.get_color(theme::graph_editor::node::text);
|
||||
self.label.set_single_line_mode(true);
|
||||
self.label.disable_command("cursor_move_up");
|
||||
self.label.disable_command("cursor_move_down");
|
||||
app.commands.set_command_enabled(&self.label, "cursor_move_up", false);
|
||||
app.commands.set_command_enabled(&self.label, "cursor_move_up", false);
|
||||
self.label.set_property_default(text_color);
|
||||
self.label.set_property_default(text::Size(input::area::TEXT_SIZE));
|
||||
self.label.remove_all_cursors();
|
||||
|
@ -658,6 +658,8 @@ ensogl::define_endpoints_2! {
|
||||
set_error_visualization_data ((NodeId, visualization::Data)),
|
||||
enable_visualization (NodeId),
|
||||
disable_visualization (NodeId),
|
||||
/// Inform Graph Editor that attaching or updating visualization has resulted in error.
|
||||
visualization_update_failed ((NodeId, String)),
|
||||
|
||||
/// Remove from visualization registry all non-default visualizations.
|
||||
reset_visualization_registry (),
|
||||
@ -760,6 +762,7 @@ ensogl::define_endpoints_2! {
|
||||
is_fs_visualization_displayed (bool),
|
||||
visualization_preprocessor_changed ((NodeId,PreprocessorConfiguration)),
|
||||
visualization_registry_reload_requested (),
|
||||
visualization_update_error ((NodeId, String)),
|
||||
|
||||
widgets_requested (NodeId, ast::Id, ast::Id),
|
||||
request_import (ImString),
|
||||
@ -1802,6 +1805,7 @@ impl GraphEditorModelWithNetwork {
|
||||
#[allow(missing_docs)] // FIXME[everyone] Public-facing API should be documented.
|
||||
pub struct GraphEditorModel {
|
||||
pub display_object: display::object::Instance,
|
||||
// Required for dynamically creating nodes and edges.
|
||||
pub app: Application,
|
||||
pub breadcrumbs: component::Breadcrumbs,
|
||||
pub cursor: cursor::Cursor,
|
||||
@ -2713,10 +2717,6 @@ impl application::View for GraphEditor {
|
||||
new_graph_editor(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
&self.model.app
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<application::shortcut::Shortcut> {
|
||||
use crate::shortcuts::SHORTCUTS;
|
||||
SHORTCUTS.iter().map(|(a, b, c, d)| Self::self_shortcut_when(*a, *c, *d, *b)).collect()
|
||||
@ -3520,7 +3520,8 @@ fn new_graph_editor(app: &Application) -> GraphEditor {
|
||||
viz_enable_by_press <= viz_tgt_nodes.gate_not(&viz_tgt_nodes_all_on);
|
||||
viz_enable <- any(viz_enable_by_press,inputs.enable_visualization);
|
||||
viz_disable_by_press <= viz_tgt_nodes.gate(&viz_tgt_nodes_all_on);
|
||||
viz_disable <- any(viz_disable_by_press,inputs.disable_visualization);
|
||||
viz_update_failed <- inputs.visualization_update_failed._0();
|
||||
viz_disable <- any(viz_disable_by_press, inputs.disable_visualization, viz_update_failed);
|
||||
viz_preview_disable <= viz_tgt_nodes_off.sample(&viz_preview_mode_end);
|
||||
viz_fullscreen_on <= viz_open_fs_ev.map(f_!(model.nodes.last_selected()));
|
||||
|
||||
@ -3544,6 +3545,8 @@ fn new_graph_editor(app: &Application) -> GraphEditor {
|
||||
|
||||
out.is_fs_visualization_displayed <+ out.visualization_fullscreen.map(Option::is_some);
|
||||
|
||||
out.visualization_update_error <+ inputs.visualization_update_failed;
|
||||
|
||||
|
||||
// === Register Visualization ===
|
||||
|
||||
|
@ -155,10 +155,6 @@ impl application::View for View {
|
||||
Self::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
self.model.app()
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<shortcut::Shortcut> {
|
||||
use shortcut::ActionType::*;
|
||||
[(Press, "ctrl `", "toggle"), (Press, "escape", "hide")]
|
||||
|
@ -143,7 +143,6 @@ ensogl::define_endpoints! {
|
||||
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
struct Model {
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
project_view_top_bar: ProjectViewTopBar,
|
||||
graph_editor: Rc<GraphEditor>,
|
||||
@ -175,10 +174,8 @@ impl Model {
|
||||
display_object.add_child(&project_view_top_bar);
|
||||
display_object.remove_child(&searcher);
|
||||
|
||||
let app = app.clone_ref();
|
||||
let graph_editor = Rc::new(graph_editor);
|
||||
Self {
|
||||
app,
|
||||
display_object,
|
||||
project_view_top_bar,
|
||||
graph_editor,
|
||||
@ -411,6 +408,7 @@ impl View {
|
||||
graph.set_navigator_disabled <+ disable_navigation;
|
||||
|
||||
model.popup.set_label <+ graph.model.breadcrumbs.project_name_error;
|
||||
model.popup.set_label <+ graph.visualization_update_error._1();
|
||||
graph.set_read_only <+ frp.set_read_only;
|
||||
graph.set_debug_mode <+ frp.source.debug_mode;
|
||||
|
||||
@ -722,10 +720,6 @@ impl application::View for View {
|
||||
View::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
&self.model.app
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<application::shortcut::Shortcut> {
|
||||
use shortcut::ActionType::*;
|
||||
[
|
||||
|
@ -44,7 +44,6 @@ mod shape {
|
||||
/// An internal model of Status Bar component
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
pub struct Model {
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
shape: shape::View,
|
||||
close: close::View,
|
||||
@ -54,7 +53,6 @@ pub struct Model {
|
||||
impl Model {
|
||||
/// Constructor.
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let display_object = display::object::Instance::new_named("WindowControlButtons");
|
||||
|
||||
ensogl::shapes_order_dependencies! {
|
||||
@ -63,10 +61,10 @@ impl Model {
|
||||
shape -> fullscreen::shape;
|
||||
}
|
||||
};
|
||||
let close = close::View::new(&app);
|
||||
let close = close::View::new(app);
|
||||
display_object.add_child(&close);
|
||||
|
||||
let fullscreen = fullscreen::View::new(&app);
|
||||
let fullscreen = fullscreen::View::new(app);
|
||||
display_object.add_child(&fullscreen);
|
||||
|
||||
let shape = shape::View::new();
|
||||
@ -74,7 +72,7 @@ impl Model {
|
||||
|
||||
app.display.default_scene.layers.panel.add(&display_object);
|
||||
|
||||
Self { app, display_object, shape, close, fullscreen }
|
||||
Self { display_object, shape, close, fullscreen }
|
||||
}
|
||||
|
||||
/// Updates positions of the buttons and sizes of the mouse area.
|
||||
@ -190,10 +188,8 @@ impl application::View for View {
|
||||
fn label() -> &'static str {
|
||||
"TopButtons"
|
||||
}
|
||||
|
||||
fn new(app: &Application) -> Self {
|
||||
View::new(app)
|
||||
}
|
||||
fn app(&self) -> &Application {
|
||||
&self.model.app
|
||||
}
|
||||
}
|
||||
|
@ -33,13 +33,14 @@ enum State {
|
||||
/// visibility.
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
pub struct Model {
|
||||
// Required for creating project view dynamically
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
state: Rc<CloneCell<State>>,
|
||||
status_bar: crate::status_bar::View,
|
||||
welcome_view: crate::welcome_screen::View,
|
||||
project_view: Rc<CloneCell<Option<crate::project::View>>>,
|
||||
frp: Frp,
|
||||
frp_outputs: FrpOutputsSource,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
@ -53,9 +54,9 @@ impl Model {
|
||||
let welcome_view = app.new_view::<crate::welcome_screen::View>();
|
||||
let project_view = Rc::new(CloneCell::new(None));
|
||||
display_object.add_child(&welcome_view);
|
||||
let frp = frp.clone_ref();
|
||||
let frp_outputs = frp.output.source.clone_ref();
|
||||
|
||||
Self { app, display_object, state, status_bar, welcome_view, project_view, frp }
|
||||
Self { app, display_object, state, status_bar, welcome_view, project_view, frp_outputs }
|
||||
}
|
||||
|
||||
/// Switch displayed view from Project View to Welcome Screen. Project View will not be
|
||||
@ -84,18 +85,18 @@ impl Model {
|
||||
|
||||
fn init_project_view(&self) {
|
||||
if self.project_view.get().is_none() {
|
||||
let network = &self.frp.network;
|
||||
let view = self.app.new_view::<crate::project::View>();
|
||||
let network = &view.network;
|
||||
let project_list_frp = &view.project_list().frp;
|
||||
let status_bar = &self.status_bar;
|
||||
let display_object = &self.display_object;
|
||||
frp::new_bridge_network! { [network, view.network] project_bridge
|
||||
frp::extend! { network
|
||||
fs_vis_shown <- view.fullscreen_visualization_shown.on_true();
|
||||
fs_vis_hidden <- view.fullscreen_visualization_shown.on_false();
|
||||
eval fs_vis_shown ((_) status_bar.unset_parent());
|
||||
eval fs_vis_hidden ([display_object, status_bar](_) display_object.add_child(&status_bar));
|
||||
|
||||
self.frp.source.selected_project <+ project_list_frp.selected_project;
|
||||
self.frp_outputs.selected_project <+ project_list_frp.selected_project;
|
||||
}
|
||||
self.project_view.set(Some(view));
|
||||
}
|
||||
@ -203,8 +204,4 @@ impl application::View for View {
|
||||
fn new(app: &Application) -> Self {
|
||||
Self::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
&self.model.app
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,6 @@ pub type Entry = list_view::entry::GlyphHighlightedLabel;
|
||||
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
struct Model {
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
list: ListView<Entry>,
|
||||
documentation: documentation::View,
|
||||
@ -117,11 +116,10 @@ struct Model {
|
||||
impl Model {
|
||||
fn new(app: &Application) -> Self {
|
||||
let scene = &app.display.default_scene;
|
||||
let app = app.clone_ref();
|
||||
let display_object = display::object::Instance::new();
|
||||
let list = app.new_view::<ListView<Entry>>();
|
||||
list.deprecated_focus();
|
||||
let documentation = documentation::View::new(&app);
|
||||
let documentation = documentation::View::new(app);
|
||||
let doc_provider = default();
|
||||
scene.layers.node_searcher.add(&list);
|
||||
display_object.add_child(&documentation);
|
||||
@ -137,7 +135,7 @@ impl Model {
|
||||
list.set_x(ACTION_LIST_X);
|
||||
documentation.set_x(DOCUMENTATION_X);
|
||||
documentation.set_y(-action_list_gap);
|
||||
Self { app, display_object, list, documentation, doc_provider }
|
||||
Self { display_object, list, documentation, doc_provider }
|
||||
}
|
||||
|
||||
fn set_height(&self, h: f32) {
|
||||
@ -287,12 +285,11 @@ impl application::View for View {
|
||||
fn label() -> &'static str {
|
||||
"Searcher"
|
||||
}
|
||||
|
||||
fn new(app: &Application) -> Self {
|
||||
Self::new(app)
|
||||
}
|
||||
fn app(&self) -> &Application {
|
||||
&self.model.app
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<shortcut::Shortcut> {
|
||||
use shortcut::ActionType::*;
|
||||
[(Press, "tab", "use_as_suggestion")]
|
||||
|
@ -116,7 +116,6 @@ static STYLESHEET: &str = include_str!("../style.css");
|
||||
/// Model of Welcome Screen that generates HTML DOM elements.
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
pub struct Model {
|
||||
application: Application,
|
||||
dom: DomSymbol,
|
||||
display_object: display::object::Instance,
|
||||
side_menu: SideMenu,
|
||||
@ -126,7 +125,6 @@ pub struct Model {
|
||||
impl Model {
|
||||
/// Constructor. `frp` is used to set up event handlers on buttons.
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let application = app.clone_ref();
|
||||
let display_object = display::object::Instance::new();
|
||||
|
||||
let side_menu = SideMenu::new();
|
||||
@ -141,7 +139,7 @@ impl Model {
|
||||
style.set_inner_html(STYLESHEET);
|
||||
dom.append_or_warn(&style);
|
||||
|
||||
Self { application, dom, display_object, side_menu, template_cards }
|
||||
Self { dom, display_object, side_menu, template_cards }
|
||||
}
|
||||
|
||||
fn create_dom(side_menu: &SideMenu, template_cards: &TemplateCards) -> DomSymbol {
|
||||
@ -258,8 +256,4 @@ impl application::View for View {
|
||||
fn new(app: &Application) -> Self {
|
||||
Self::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
&self.model.application
|
||||
}
|
||||
}
|
||||
|
@ -203,19 +203,17 @@ pub mod shape {
|
||||
#[derivative(Clone(bound = ""))]
|
||||
#[allow(missing_docs)]
|
||||
pub struct Model<S: Shape> {
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
shape: ShapeView<S>,
|
||||
}
|
||||
|
||||
impl<Shape: ButtonShape> Model<Shape> {
|
||||
/// Construct a button's model.
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
pub fn new(_app: &Application) -> Self {
|
||||
let display_object = display::object::Instance::new();
|
||||
let shape = ShapeView::new();
|
||||
display_object.add_child(&shape);
|
||||
Self { app, display_object, shape }
|
||||
Self { display_object, shape }
|
||||
}
|
||||
|
||||
/// Set the background (i.e. the circle) color.
|
||||
|
@ -95,7 +95,6 @@ impl component::Frp<Model> for Frp {
|
||||
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
pub struct Model {
|
||||
app: Application,
|
||||
background: background::View,
|
||||
label: Rc<RefCell<Option<text::Text>>>,
|
||||
display_object: display::object::Instance,
|
||||
@ -115,8 +114,7 @@ impl component::Model for Model {
|
||||
display_object.add_child(&background);
|
||||
scene.layers.tooltip.add(&background);
|
||||
|
||||
let app = app.clone_ref();
|
||||
Model { app, background, label, display_object }
|
||||
Model { background, label, display_object }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,7 @@ pub struct FlameGraph {
|
||||
blocks: Vec<Block>,
|
||||
marks: Vec<Mark>,
|
||||
origin_x: f64,
|
||||
// Required for dynamically adding blocks.
|
||||
app: Application,
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,6 @@ impl component::Frp<Model> for Frp {
|
||||
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
pub struct Model {
|
||||
app: Application,
|
||||
background: background::View,
|
||||
label: Rc<RefCell<Option<text::Text>>>,
|
||||
display_object: display::object::Instance,
|
||||
@ -118,8 +117,7 @@ impl component::Model for Model {
|
||||
display_object.add_child(&background);
|
||||
scene.layers.tooltip.add(&background);
|
||||
|
||||
let app = app.clone_ref();
|
||||
Model { app, background, label, display_object }
|
||||
Model { background, label, display_object }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,7 @@ impl<E: display::Object> display::Object for VisibleEntry<E> {
|
||||
#[derive(CloneRef, Debug, Derivative)]
|
||||
#[derivative(Clone(bound = ""))]
|
||||
pub struct CreationCtx<EntryParams> {
|
||||
// Required for dynamically creating entries.
|
||||
pub app: Application,
|
||||
pub network: frp::WeakNetwork,
|
||||
pub set_entry_size: frp::Stream<Vector2>,
|
||||
|
@ -688,10 +688,6 @@ impl<E: Entry> application::View for GridView<E> {
|
||||
GridView::<E>::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
self.widget.app()
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<application::shortcut::Shortcut> {
|
||||
use application::shortcut::ActionType::*;
|
||||
[
|
||||
|
@ -144,10 +144,6 @@ where
|
||||
ComponentView::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
self.widget.app()
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<shortcut::Shortcut> {
|
||||
F::default_shortcuts()
|
||||
}
|
||||
|
@ -59,8 +59,7 @@ struct Model {
|
||||
}
|
||||
|
||||
impl Model {
|
||||
fn new(app: Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
fn new(app: &Application) -> Self {
|
||||
let scene = &app.display.default_scene;
|
||||
let display_object = display::object::Instance::new();
|
||||
let label = app.new_view::<text::Text>();
|
||||
@ -144,7 +143,7 @@ impl Label {
|
||||
/// Constructor.
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let frp = Rc::new(Frp::new());
|
||||
let model = Rc::new(Model::new(app.clone_ref()));
|
||||
let model = Rc::new(Model::new(app));
|
||||
Label { model, frp }.init()
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,7 @@ pub type List<E> = ListData<E, <E as Entry>::Params>;
|
||||
#[derivative(Clone(bound = ""))]
|
||||
#[clone_ref(bound = "E:CloneRef")]
|
||||
pub struct ListData<E, P> {
|
||||
// Required for dynamically creating new entries.
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
entries: Rc<RefCell<Vec<DisplayedEntry<E>>>>,
|
||||
|
@ -124,7 +124,6 @@ impl Default for JumpTarget {
|
||||
/// The Model of Select Component.
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
struct Model<E: Entry> {
|
||||
app: Application,
|
||||
entries: entry::List<E>,
|
||||
selection: Selection,
|
||||
background: Rectangle,
|
||||
@ -134,10 +133,9 @@ struct Model<E: Entry> {
|
||||
|
||||
impl<E: Entry> Model<E> {
|
||||
fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let display_object = display::object::Instance::new();
|
||||
let scrolled_area = display::object::Instance::new();
|
||||
let entries = entry::List::new(&app);
|
||||
let entries = entry::List::new(app);
|
||||
let background = Rectangle();
|
||||
background.set_border_color(color::Rgba::transparent());
|
||||
let selection = Selection::default();
|
||||
@ -146,7 +144,7 @@ impl<E: Entry> Model<E> {
|
||||
display_object.add_child(&scrolled_area);
|
||||
scrolled_area.add_child(&entries);
|
||||
scrolled_area.add_child(&selection);
|
||||
Model { app, entries, selection, background, scrolled_area, display_object }
|
||||
Model { entries, selection, background, scrolled_area, display_object }
|
||||
}
|
||||
|
||||
/// Update the displayed entries list when _view_ has changed - the list was scrolled or
|
||||
@ -438,7 +436,7 @@ where E::Model: Default
|
||||
|
||||
// === Selected Entry ===
|
||||
|
||||
eval frp.source.focused([frp](f) if !f { frp.deselect_entries.emit(()) } );
|
||||
frp.deselect_entries <+ frp.focused.on_false();
|
||||
|
||||
frp.source.selected_entry <+ frp.select_entry;
|
||||
frp.source.selected_entry <+ frp.output.chosen_entry;
|
||||
@ -636,12 +634,11 @@ impl<E: Entry> application::View for ListView<E> {
|
||||
fn label() -> &'static str {
|
||||
"ListView"
|
||||
}
|
||||
|
||||
fn new(app: &Application) -> Self {
|
||||
ListView::new(app)
|
||||
}
|
||||
fn app(&self) -> &Application {
|
||||
&self.model.app
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<shortcut::Shortcut> {
|
||||
use shortcut::ActionType::*;
|
||||
[
|
||||
|
@ -367,18 +367,14 @@ impl ScrollArea {
|
||||
(0.0..=size.x).contains(&local_pos.x) && (-size.y..=0.0).contains(&local_pos.y)
|
||||
}));
|
||||
hovering <- hovering.sampler();
|
||||
let on_scroll = model.display_object.on_event::<mouse::Wheel>();
|
||||
on_scroll_when_hovering <- on_scroll.gate(&hovering);
|
||||
model.h_scrollbar.scroll_by <+ on_scroll_when_hovering
|
||||
.map(|event| event.delta_x() as f32);
|
||||
model.v_scrollbar.scroll_by <+ on_scroll_when_hovering
|
||||
.map(|event| event.delta_y() as f32);
|
||||
}
|
||||
|
||||
let mouse_manager = &mouse.mouse_manager;
|
||||
let scroll_handler = f!([model](event: &mouse::Wheel)
|
||||
if hovering.value() {
|
||||
model.h_scrollbar.scroll_by(event.delta_x() as f32);
|
||||
model.v_scrollbar.scroll_by(event.delta_y() as f32);
|
||||
}
|
||||
);
|
||||
let scroll_handler_handle = mouse_manager.on_wheel.add(scroll_handler);
|
||||
network.store(&scroll_handler_handle);
|
||||
|
||||
|
||||
ScrollArea { model, frp }
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ impl Frp {
|
||||
resize <- frp.set_length.map(|&length| Vector2::new(length,WIDTH));
|
||||
}
|
||||
|
||||
let base_frp = selector::Frp::new(model, style, network, resize.clone(), mouse);
|
||||
let base_frp = selector::Frp::new(app, model, style, network, resize.clone(), mouse);
|
||||
|
||||
model.use_track_handles(false);
|
||||
model.set_track_corner_round(true);
|
||||
@ -358,22 +358,17 @@ pub struct Scrollbar {
|
||||
/// Public FRP api of the Component.
|
||||
pub frp: Rc<Frp>,
|
||||
model: Rc<Model>,
|
||||
/// Reference to the application the Component belongs to. Generally required for implementing
|
||||
/// `application::View` and initialising the `Model` and `Frp` and thus provided by the
|
||||
/// `Component`.
|
||||
pub app: Application,
|
||||
}
|
||||
|
||||
impl Scrollbar {
|
||||
/// Constructor.
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let model = Rc::new(Model::new(&app));
|
||||
let model = Rc::new(Model::new(app));
|
||||
let frp = Frp::default();
|
||||
let style = StyleWatchFrp::new(&app.display.default_scene.style_sheet);
|
||||
frp.init(&app, &model, &style);
|
||||
frp.init(app, &model, &style);
|
||||
let frp = Rc::new(frp);
|
||||
Self { frp, model, app }
|
||||
Self { frp, model }
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,10 +395,8 @@ impl application::View for Scrollbar {
|
||||
fn label() -> &'static str {
|
||||
"Scrollbar"
|
||||
}
|
||||
|
||||
fn new(app: &Application) -> Self {
|
||||
Scrollbar::new(app)
|
||||
}
|
||||
fn app(&self) -> &Application {
|
||||
&self.app
|
||||
}
|
||||
}
|
||||
|
@ -100,18 +100,16 @@ impl display::Object for Model {
|
||||
pub struct FloatLabel {
|
||||
pub frp: Rc<Frp>,
|
||||
model: Rc<Model>,
|
||||
app: Application,
|
||||
}
|
||||
|
||||
impl FloatLabel {
|
||||
/// Constructor.
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let model = Rc::new(Model::new(&app));
|
||||
let model = Rc::new(Model::new(app));
|
||||
let frp = Frp::default();
|
||||
frp.init(&model);
|
||||
let frp = Rc::new(frp);
|
||||
Self { frp, model, app }
|
||||
Self { frp, model }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ use crate::shape::shape_is_dragged;
|
||||
use enso_frp as frp;
|
||||
use enso_frp::io::Mouse_DEPRECATED;
|
||||
use enso_frp::Network;
|
||||
use ensogl_core::application::Application;
|
||||
use ensogl_core::display::object::ObjectOps;
|
||||
use ensogl_core::display::shape::StyleWatchFrp;
|
||||
use ensogl_hardcoded_theme as theme;
|
||||
@ -69,6 +70,7 @@ pub struct Frp {
|
||||
impl Frp {
|
||||
/// Create and initialize the FRP.
|
||||
pub fn new(
|
||||
app: &Application,
|
||||
model: &Model,
|
||||
style: &StyleWatchFrp,
|
||||
network: &Network,
|
||||
@ -76,7 +78,7 @@ impl Frp {
|
||||
mouse: &Mouse_DEPRECATED,
|
||||
) -> Frp {
|
||||
let net = &network;
|
||||
let scene = &model.app.display.default_scene;
|
||||
let scene = &app.display.default_scene;
|
||||
let shadow = shadow::frp_from_style(style, theme::shadow);
|
||||
let text_size = style.get_number(theme::text::size);
|
||||
|
||||
|
@ -77,22 +77,17 @@ pub struct NumberPicker {
|
||||
/// Public FRP api of the Component.
|
||||
pub frp: Rc<number::Frp>,
|
||||
model: Rc<Model>,
|
||||
/// Reference to the application the Component belongs to. Generally required for implementing
|
||||
/// `application::View` and initialising the `Model` and `Frp` and thus provided by the
|
||||
/// `Component`.
|
||||
pub app: Application,
|
||||
}
|
||||
|
||||
impl NumberPicker {
|
||||
/// Constructor.
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let model = Rc::new(Model::new(&app));
|
||||
let model = Rc::new(Model::new(app));
|
||||
let frp = number::Frp::default();
|
||||
let style = StyleWatchFrp::new(&app.display.default_scene.style_sheet);
|
||||
frp.init(&app, &model, &style);
|
||||
frp.init(app, &model, &style);
|
||||
let frp = Rc::new(frp);
|
||||
Self { frp, model, app }
|
||||
Self { frp, model }
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,12 +114,10 @@ impl application::View for NumberPicker {
|
||||
fn label() -> &'static str {
|
||||
"NumberPicker"
|
||||
}
|
||||
|
||||
fn new(app: &Application) -> Self {
|
||||
NumberPicker::new(app)
|
||||
}
|
||||
fn app(&self) -> &Application {
|
||||
&self.app
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -147,22 +140,17 @@ pub struct NumberRangePicker {
|
||||
/// Public FRP api of the Component.
|
||||
pub frp: Rc<range::Frp>,
|
||||
model: Rc<Model>,
|
||||
/// Reference to the application the Component belongs to. Generally required for implementing
|
||||
/// `application::View` and initialising the `Model` and `Frp` and thus provided by the
|
||||
/// `Component`.
|
||||
pub app: Application,
|
||||
}
|
||||
|
||||
impl NumberRangePicker {
|
||||
/// Constructor.
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
let model = Rc::new(Model::new(&app));
|
||||
let model = Rc::new(Model::new(app));
|
||||
let frp = range::Frp::default();
|
||||
let style = StyleWatchFrp::new(&app.display.default_scene.style_sheet);
|
||||
frp.init(&app, &model, &style);
|
||||
frp.init(app, &model, &style);
|
||||
let frp = Rc::new(frp);
|
||||
Self { frp, model, app }
|
||||
Self { frp, model }
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,10 +177,8 @@ impl application::View for NumberRangePicker {
|
||||
fn label() -> &'static str {
|
||||
"RangePicker"
|
||||
}
|
||||
|
||||
fn new(app: &Application) -> Self {
|
||||
NumberRangePicker::new(app)
|
||||
}
|
||||
fn app(&self) -> &Application {
|
||||
&self.app
|
||||
}
|
||||
}
|
||||
|
@ -70,8 +70,6 @@ pub struct Model {
|
||||
background_left_corner_roundness: Rc<Cell<bool>>,
|
||||
background_right_corner_roundness: Rc<Cell<bool>>,
|
||||
padding: Rc<Cell<f32>>,
|
||||
|
||||
pub app: Application,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
@ -95,7 +93,6 @@ impl Model {
|
||||
let background_right_corner_roundness = default();
|
||||
let padding = default();
|
||||
|
||||
let app = app.clone_ref();
|
||||
let scene = &app.display.default_scene;
|
||||
|
||||
root.add_child(&label);
|
||||
@ -134,7 +131,6 @@ impl Model {
|
||||
background_left_corner_roundness,
|
||||
background_right_corner_roundness,
|
||||
padding,
|
||||
app,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,8 @@ impl Frp {
|
||||
|
||||
model.show_background(true);
|
||||
|
||||
let base_frp = super::Frp::new(model, style, network, frp.resize.clone().into(), mouse);
|
||||
let base_frp =
|
||||
super::Frp::new(app, model, style, network, frp.resize.clone().into(), mouse);
|
||||
|
||||
let background_click = relative_shape_down_position(network, scene, &model.background);
|
||||
let track_click = relative_shape_down_position(network, scene, &model.track);
|
||||
|
@ -44,7 +44,8 @@ impl Frp {
|
||||
let scene = &app.display.default_scene;
|
||||
let mouse = &scene.mouse.frp_deprecated;
|
||||
|
||||
let base_frp = super::Frp::new(model, style, network, frp.resize.clone().into(), mouse);
|
||||
let base_frp =
|
||||
super::Frp::new(app, model, style, network, frp.resize.clone().into(), mouse);
|
||||
|
||||
model.use_track_handles(true);
|
||||
model.show_background(true);
|
||||
|
@ -89,6 +89,7 @@ impl component::Frp<Model> for Frp {
|
||||
/// Internal model of the SequenceDiagram.
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
pub struct Model {
|
||||
// Required for dynamically creating new lines.
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
actor_lines: Rc<RefCell<Vec<LabeledLine>>>,
|
||||
|
@ -337,10 +337,6 @@ pub struct Slider {
|
||||
#[deref]
|
||||
pub frp: Frp,
|
||||
model: Rc<Model>,
|
||||
/// Reference to the application the component belongs to. Generally required for implementing
|
||||
/// `application::View` and initialising the `Model` and `Frp` and thus provided by the
|
||||
/// component.
|
||||
pub app: Application,
|
||||
}
|
||||
|
||||
impl Slider {
|
||||
@ -348,12 +344,11 @@ impl Slider {
|
||||
pub fn new(app: &Application) -> Self {
|
||||
let frp = Frp::new();
|
||||
let model = Rc::new(Model::new(app, frp.network()));
|
||||
let app = app.clone_ref();
|
||||
Self { frp, model, app }.init()
|
||||
Self { frp, model }.init(app)
|
||||
}
|
||||
|
||||
fn init(self) -> Self {
|
||||
self.init_value_update();
|
||||
fn init(self, app: &Application) -> Self {
|
||||
self.init_value_update(app);
|
||||
self.init_limit_handling();
|
||||
self.init_value_display();
|
||||
|
||||
@ -367,13 +362,13 @@ impl Slider {
|
||||
}
|
||||
|
||||
/// Initialize the slider value update FRP network.
|
||||
fn init_value_update(&self) {
|
||||
fn init_value_update(&self, app: &Application) {
|
||||
let network = self.frp.network();
|
||||
let frp = &self.frp;
|
||||
let input = &self.frp.input;
|
||||
let output = &self.frp.private.output;
|
||||
let model = &self.model;
|
||||
let scene = &self.app.display.default_scene;
|
||||
let scene = &app.display.default_scene;
|
||||
let mouse = &scene.mouse.frp_deprecated;
|
||||
let keyboard = &scene.keyboard.frp;
|
||||
|
||||
@ -845,10 +840,6 @@ impl application::View for Slider {
|
||||
Self::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
&self.app
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<shortcut::Shortcut> {
|
||||
use shortcut::ActionType::DoublePress;
|
||||
use shortcut::ActionType::Press;
|
||||
|
@ -1978,10 +1978,6 @@ impl application::View for Text {
|
||||
Text::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
&self.data.app
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<shortcut::Shortcut> {
|
||||
use shortcut::ActionType::*;
|
||||
([
|
||||
|
@ -76,15 +76,6 @@ pub struct ApplicationData {
|
||||
pub frp: Frp,
|
||||
}
|
||||
|
||||
impl ApplicationData {
|
||||
/// Show or hide the system mouse cursor by setting the `cursor` CSS property of the `body`
|
||||
/// element.
|
||||
fn show_system_cursor(&self, show: bool) {
|
||||
let style = if show { "auto" } else { "none" };
|
||||
web::document.body_or_panic().set_style_or_warn("cursor", style);
|
||||
}
|
||||
}
|
||||
|
||||
impl Application {
|
||||
/// Constructor.
|
||||
pub fn new(dom: impl DomPath) -> Self {
|
||||
@ -94,7 +85,7 @@ impl Application {
|
||||
let commands = command::Registry::create();
|
||||
let shortcuts =
|
||||
shortcut::Registry::new(&scene.mouse.frp_deprecated, &scene.keyboard.frp, &commands);
|
||||
let views = view::Registry::create(&display, &commands, &shortcuts);
|
||||
let views = view::Registry::create(&commands, &shortcuts);
|
||||
let cursor = Cursor::new(&display.default_scene);
|
||||
display.add_child(&cursor);
|
||||
let frp = Frp::new();
|
||||
@ -106,20 +97,27 @@ impl Application {
|
||||
|
||||
fn init(self) -> Self {
|
||||
let frp = &self.frp;
|
||||
let data = &self.inner;
|
||||
let network = self.frp.network();
|
||||
enso_frp::extend! { network
|
||||
app_focused <- self.display.default_scene.frp.focused.on_change();
|
||||
eval app_focused((t) data.show_system_cursor(!t));
|
||||
eval app_focused([](t) Self::show_system_cursor(!t));
|
||||
eval_ frp.private.input.show_system_cursor([] Self::show_system_cursor(true));
|
||||
eval_ frp.private.input.hide_system_cursor([] Self::show_system_cursor(false));
|
||||
|
||||
frp.private.output.tooltip <+ frp.private.input.set_tooltip;
|
||||
eval_ frp.private.input.show_system_cursor(data.show_system_cursor(true));
|
||||
eval_ frp.private.input.hide_system_cursor(data.show_system_cursor(false));
|
||||
}
|
||||
// We hide the system cursor to replace it with the EnsoGL-provided one.
|
||||
self.frp.hide_system_cursor();
|
||||
self
|
||||
}
|
||||
|
||||
/// Show or hide the system mouse cursor by setting the `cursor` CSS property of the `body`
|
||||
/// element.
|
||||
fn show_system_cursor(show: bool) {
|
||||
let style = if show { "auto" } else { "none" };
|
||||
web::document.body_or_panic().set_style_or_warn("cursor", style);
|
||||
}
|
||||
|
||||
/// Create a new instance of a view.
|
||||
pub fn new_view<T: View>(&self) -> T {
|
||||
self.views.new_view(self)
|
||||
|
@ -27,9 +27,6 @@ pub trait View: FrpNetworkProvider + DerefToCommandApi {
|
||||
/// Constructor.
|
||||
fn new(app: &Application) -> Self;
|
||||
|
||||
/// Application reference.
|
||||
fn app(&self) -> &Application;
|
||||
|
||||
/// Set of default shortcuts.
|
||||
fn default_shortcuts() -> Vec<Shortcut> {
|
||||
default()
|
||||
@ -58,24 +55,6 @@ pub trait View: FrpNetworkProvider + DerefToCommandApi {
|
||||
condition,
|
||||
)
|
||||
}
|
||||
|
||||
/// Disable the command in this component instance.
|
||||
fn disable_command(&self, name: impl AsRef<str>)
|
||||
where Self: Sized {
|
||||
self.set_command_enabled(name, false)
|
||||
}
|
||||
|
||||
/// Enable the command in this component instance.
|
||||
fn enable_command(&self, name: impl AsRef<str>)
|
||||
where Self: Sized {
|
||||
self.set_command_enabled(name, true)
|
||||
}
|
||||
|
||||
/// Set the command enable status in this component instance.
|
||||
fn set_command_enabled(&self, name: impl AsRef<str>, enabled: bool)
|
||||
where Self: Sized {
|
||||
self.app().commands.set_command_enabled(self, name, enabled)
|
||||
}
|
||||
}
|
||||
|
||||
/// FRP Network provider. Used to check whether FRP bindings are still alive.
|
||||
@ -232,7 +211,7 @@ impl Registry {
|
||||
}
|
||||
|
||||
/// Sets the command enable status for the provided component instance.
|
||||
fn set_command_enabled<T: View>(&self, instance: &T, name: impl AsRef<str>, enabled: bool) {
|
||||
pub fn set_command_enabled<T: View>(&self, instance: &T, name: impl AsRef<str>, enabled: bool) {
|
||||
self.with_command_mut(instance, name, |command| command.enabled = enabled)
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::display::world::World;
|
||||
|
||||
use super::command;
|
||||
use super::shortcut;
|
||||
use super::Application;
|
||||
@ -26,7 +24,6 @@ pub use command::View;
|
||||
#[derive(Debug, Clone, CloneRef)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct Registry {
|
||||
pub display: World,
|
||||
pub command_registry: command::Registry,
|
||||
pub shortcut_registry: shortcut::Registry,
|
||||
pub definitions: Rc<RefCell<HashSet<String>>>,
|
||||
@ -35,15 +32,13 @@ pub struct Registry {
|
||||
impl Registry {
|
||||
/// Constructor.
|
||||
pub fn create(
|
||||
display: &World,
|
||||
command_registry: &command::Registry,
|
||||
shortcut_registry: &shortcut::Registry,
|
||||
) -> Self {
|
||||
let display = display.clone_ref();
|
||||
let command_registry = command_registry.clone_ref();
|
||||
let shortcut_registry = shortcut_registry.clone_ref();
|
||||
let definitions = default();
|
||||
Self { display, command_registry, shortcut_registry, definitions }
|
||||
Self { command_registry, shortcut_registry, definitions }
|
||||
}
|
||||
|
||||
/// View registration.
|
||||
|
@ -18,6 +18,14 @@ struct Garbage {
|
||||
before_mouse_events: Vec<Box<dyn Any>>,
|
||||
}
|
||||
|
||||
impl Garbage {
|
||||
fn collected_items_count(&self) -> usize {
|
||||
self.before_pixel_sync.len()
|
||||
+ self.before_pixel_update.len()
|
||||
+ self.before_mouse_events.len()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// The Garbage Collector
|
||||
///
|
||||
@ -90,6 +98,14 @@ impl Collector {
|
||||
};
|
||||
drop(before_mouse_events);
|
||||
}
|
||||
|
||||
/// Immediately drop all collected garbage.
|
||||
pub fn force_garbage_drop(&self) {
|
||||
// Elements may add new objects on drop, thus we need to clear garbage in loop.
|
||||
while self.garbage.borrow().collected_items_count() > 0 {
|
||||
self.garbage.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -670,6 +670,13 @@ impl WorldData {
|
||||
self.garbage_collector.collect(object);
|
||||
}
|
||||
|
||||
/// Immediately drop the garbage.
|
||||
///
|
||||
/// May be used to resolve dependence cycles if garbage keeps reference to [`World`].
|
||||
pub fn force_garbage_drop(&self) {
|
||||
self.garbage_collector.force_garbage_drop()
|
||||
}
|
||||
|
||||
/// Set the maximum frequency at which the pointer location will be checked, in terms of number
|
||||
/// of frames per check.
|
||||
pub fn set_pixel_read_period(&self, period: usize) {
|
||||
|
@ -367,13 +367,6 @@ impl<Model: 'static, Frp: 'static> Widget<Model, Frp> {
|
||||
pub fn model(&self) -> &Model {
|
||||
&self.data.model
|
||||
}
|
||||
|
||||
/// Reference to the application the Widget belongs to. It's required for handling model and
|
||||
/// FRP garbage collection, but also may be helpful when, for example, implementing
|
||||
/// `application::View`.
|
||||
pub fn app(&self) -> &Application {
|
||||
&self.data.app
|
||||
}
|
||||
}
|
||||
|
||||
impl<Model: 'static, Frp: 'static> display::Object for Widget<Model, Frp> {
|
||||
|
@ -44,15 +44,13 @@ use ensogl_text_msdf::run_once_initialized;
|
||||
|
||||
#[derive(Clone, CloneRef, Debug)]
|
||||
struct Model {
|
||||
app: Application,
|
||||
display_object: display::object::Instance,
|
||||
shape: Rectangle,
|
||||
cover: Rectangle,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
fn new(app: &Application) -> Self {
|
||||
let app = app.clone_ref();
|
||||
fn new() -> Self {
|
||||
let display_object = display::object::Instance::new();
|
||||
let shape: Rectangle = default();
|
||||
shape.set_size(Vector2(300.0, 300.0));
|
||||
@ -68,7 +66,7 @@ impl Model {
|
||||
cover.set_corner_radius_max();
|
||||
cover.set_pointer_events(false);
|
||||
display_object.add_child(&cover);
|
||||
Self { app, display_object, shape, cover }
|
||||
Self { display_object, shape, cover }
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,9 +97,9 @@ struct View {
|
||||
|
||||
impl View {
|
||||
/// Constructor.
|
||||
pub fn new(app: &Application) -> Self {
|
||||
pub fn new() -> Self {
|
||||
let frp = Frp::new();
|
||||
let model = Model::new(app);
|
||||
let model = Model::new();
|
||||
let network = &frp.network;
|
||||
frp::extend! { network
|
||||
trace model.shape.events_deprecated.mouse_up;
|
||||
@ -139,11 +137,9 @@ impl application::View for View {
|
||||
fn label() -> &'static str {
|
||||
"Circul"
|
||||
}
|
||||
fn new(app: &Application) -> Self {
|
||||
View::new(app)
|
||||
}
|
||||
fn app(&self) -> &Application {
|
||||
&self.model.app
|
||||
|
||||
fn new(_app: &Application) -> Self {
|
||||
View::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,16 +232,14 @@ impl FrpNetworkProvider for SliderCollection {
|
||||
struct SliderCollection {
|
||||
#[deref]
|
||||
frp: Frp,
|
||||
app: Application,
|
||||
model: Model,
|
||||
}
|
||||
|
||||
impl SliderCollection {
|
||||
fn new(app: &Application) -> Self {
|
||||
let frp = Frp::new();
|
||||
let app = app.clone_ref();
|
||||
let model = Model::new(&app);
|
||||
Self { frp, app, model }.init()
|
||||
let model = Model::new(app);
|
||||
Self { frp, model }.init()
|
||||
}
|
||||
|
||||
fn init(self) -> Self {
|
||||
@ -272,10 +270,6 @@ impl View for SliderCollection {
|
||||
Self::new(app)
|
||||
}
|
||||
|
||||
fn app(&self) -> &Application {
|
||||
&self.app
|
||||
}
|
||||
|
||||
fn default_shortcuts() -> Vec<shortcut::Shortcut> {
|
||||
use shortcut::ActionType::Press;
|
||||
vec![
|
||||
|
@ -146,9 +146,9 @@ impl Drop for TraceCopies {
|
||||
/// A module containing an utility for detecting leaks.
|
||||
///
|
||||
/// If you suspect a particular struct is leaking, i.e. its instances are still present when we
|
||||
/// expect them to be removed, you may add a [`Trace`] field to it. Then, at the point where we
|
||||
/// expect all instances to be dropped, we may check the [`TRACKED_OBJECTS`] global variable, what
|
||||
/// instances are still alive and their creation backtraces.
|
||||
/// expect them to be removed, you may add a [`Trace`] field to it and call [`enable`]. Then, at
|
||||
/// the point where we expect all instances to be dropped, we may check the [`TRACKED_OBJECTS`]
|
||||
/// global variable, what instances are still alive and their creation backtraces.
|
||||
pub mod leak_detector {
|
||||
use crate::*;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user