diff --git a/app/gui/view/component-browser/component-group/src/lib.rs b/app/gui/view/component-browser/component-group/src/lib.rs index 563fcfcbbe9fd..72010c87eaa03 100644 --- a/app/gui/view/component-browser/component-group/src/lib.rs +++ b/app/gui/view/component-browser/component-group/src/lib.rs @@ -123,14 +123,10 @@ pub mod selection_box { ensogl::define_shape_system! { pointer_events = false; - (style:Style) { + (style:Style,corners_radius:f32) { let width: Var = "input_size.x".into(); let height: Var = "input_size.y".into(); - let corners_radius = style.get_number(theme::selection::corners_radius); - let padding_y = style.get_number(theme::selection::vertical_padding); - let padding_x = style.get_number(theme::selection::horizontal_padding); - let shape = Rect((width - padding_x.px(), height - padding_y.px())); - shape.corners_radius(corners_radius.px()).into() + Rect((width, height)).corners_radius(corners_radius.px()).into() } } } @@ -219,6 +215,42 @@ pub mod header_overlay { +// ====================== +// === SelectionStyle === +// ====================== + +#[derive(Debug, Copy, Clone, Default)] +struct SelectionStyle { + padding_x: f32, + height: f32, + header_height: f32, + corners_radius: f32, + header_corners_radius: f32, +} + +impl SelectionStyle { + fn from_style(style: &StyleWatchFrp, network: &frp::Network) -> frp::Sampler { + let padding_x = style.get_number(theme::selection::horizontal_padding); + let height = style.get_number(theme::selection::height); + let header_height = style.get_number(theme::selection::header_height); + let corners_radius = style.get_number(theme::selection::corners_radius); + let header_corners_radius = style.get_number(theme::selection::header_corners_radius); + frp::extend! { network + init <- source_(); + theme <- all_with6(&init,&height,&header_height,&corners_radius,&header_corners_radius, + &padding_x, |_,&height,&header_height,&corners_radius,&header_corners_radius, + &padding_x| + Self {height,header_height,corners_radius,header_corners_radius, + padding_x} ); + theme_sampler <- theme.sampler(); + } + init.emit(()); + theme_sampler + } +} + + + // ======================= // === Header Geometry === // ======================= @@ -379,6 +411,7 @@ ensogl::define_endpoints_2! { header_accepted(), selection_size(Vector2), selection_position_target(Vector2), + selection_corners_radius(f32), size(Vector2) } } @@ -487,11 +520,12 @@ impl component::Frp for Frp { out.is_header_selected <+ bool(&deselect_header, &select_header).on_change(); model.entries.select_entry <+ select_header.constant(None); + let selection_style = SelectionStyle::from_style(style, network); out.selection_size <+ all_with3( - &header_geometry, + &selection_style, &out.is_header_selected, &out.focused, - f!((geom, h_sel, _) model.selection_size(geom.height, *h_sel)) + f!((style, h_sel, _) model.selection_size(*h_sel, *style)) ); out.selection_position_target <+ all_with5( &out.is_header_selected, @@ -503,6 +537,12 @@ impl component::Frp for Frp { model.selection_position(*h_sel, *h_geom, *size, *esp, *h_pos) ) ); + out.selection_corners_radius <+ all_with3( + &out.is_header_selected, + &selection_style, + &out.focused, + f!((h_sel, style,_) model.selection_corners_radius(*h_sel, *style)) + ); } @@ -776,9 +816,18 @@ impl Model { } } - fn selection_size(&self, header_height: f32, is_header_selected: bool) -> Vector2 { - let height = if is_header_selected { header_height } else { list_view::entry::HEIGHT }; - Vector2(self.entries.size.value().x, height) + fn selection_size(&self, is_header_selected: bool, style: SelectionStyle) -> Vector2 { + let width = self.entries.size.value().x - style.padding_x * 2.0; + let height = if is_header_selected { style.header_height } else { style.height }; + Vector2(width, height) + } + + fn selection_corners_radius(&self, is_header_selected: bool, style: SelectionStyle) -> f32 { + if is_header_selected { + style.header_corners_radius + } else { + style.corners_radius + } } } diff --git a/app/gui/view/component-browser/component-group/src/set.rs b/app/gui/view/component-browser/component-group/src/set.rs index 24e2f79972a3d..82c6aa4d71ed3 100644 --- a/app/gui/view/component-browser/component-group/src/set.rs +++ b/app/gui/view/component-browser/component-group/src/set.rs @@ -143,6 +143,7 @@ propagated_events! { header_accepted: GroupId, selection_position_target: (GroupId, Vector2), selection_size: (GroupId, Vector2), + selection_corners_radius: (GroupId, f32), focused: (GroupId, bool), } } @@ -273,6 +274,7 @@ impl Wrapper { (expression_accepted, move |e| (id, *e)), (selection_position_target, move |p| (id, *p)), (selection_size, move |p| (id, *p)), + (selection_corners_radius, move |r| (id, *r)), (is_header_selected, move |h| (id, *h)), (header_accepted, move |_| id) } @@ -286,7 +288,8 @@ impl Wrapper { (suggestion_accepted, move |e| (id, *e)), (expression_accepted, move |e| (id, *e)), (selection_position_target, move |p| (id, *p)), - (selection_size, move |p| (id, *p)) + (selection_size, move |p| (id, *p)), + (selection_corners_radius, move |r| (id, *r)) } } } diff --git a/app/gui/view/component-browser/component-group/src/wide.rs b/app/gui/view/component-browser/component-group/src/wide.rs index 4089e8f9f90e7..04020f16009b7 100644 --- a/app/gui/view/component-browser/component-group/src/wide.rs +++ b/app/gui/view/component-browser/component-group/src/wide.rs @@ -17,6 +17,7 @@ use crate::background; use crate::entry; use crate::theme; use crate::Colors; +use crate::SelectionStyle; use enso_frp as frp; use ensogl::application::shortcut::Shortcut; @@ -123,6 +124,7 @@ ensogl::define_endpoints_2! { /// the next non-empty column to the left. selection_position_target(Vector2), selection_size(Vector2), + selection_corners_radius(f32), entry_count(usize), size(Vector2), } @@ -140,6 +142,7 @@ impl component::Frp> for Frp { let out = &api.output; let colors = Colors::from_main_color(network, style, &input.set_color, &input.set_dimmed); let padding = style.get_number(theme::entry_list::padding); + let column_padding = style.get_number(theme::selection::wide_group_column_padding); frp::extend! { network init <- source_(); entry_count <- input.set_entries.map(|p| p.entry_count()); @@ -171,9 +174,19 @@ impl component::Frp> for Frp { eval size((size) model.background.size.set(*size)); eval size((size) model.selection_background.size.set(*size)); out.size <+ size; - out.selection_size <+ background_width.all_with( + let selection_style = SelectionStyle::from_style(style, network); + out.selection_size <+ background_width.all_with4( + &selection_style, + &column_padding, &out.focused, - |&width, _| Vector2 (width / 3.0,list_view::entry::HEIGHT) + |&width,&style,&column_padding,_| { + let width = (width - 2.0 * column_padding) / COLUMNS as f32; + let height = style.height; + Vector2(width, height) + } + ); + out.selection_corners_radius <+ all_with(&selection_style, &out.focused, + |style,_| style.corners_radius ); // === "No items" label === diff --git a/app/gui/view/component-browser/searcher-list-panel/src/lib.rs b/app/gui/view/component-browser/searcher-list-panel/src/lib.rs index c8ff8ba3bba32..ecbf0b86d050b 100644 --- a/app/gui/view/component-browser/searcher-list-panel/src/lib.rs +++ b/app/gui/view/component-browser/searcher-list-panel/src/lib.rs @@ -94,11 +94,12 @@ const SELECTION_ANIMATION_SPRING_FORCE_MULTIPLIER: f32 = 1.5; #[derive(Debug, Clone, CloneRef)] struct Layers { - groups: GroupLayers, - base: Layer, - selection: Layer, - selection_mask: Layer, - scroll_layer: Layer, + groups: GroupLayers, + base: Layer, + selection: Layer, + selection_mask: Layer, + scroll_layer: Layer, + scrollbar_layer: Layer, } impl Layers { @@ -106,14 +107,16 @@ impl Layers { let main_camera = app.display.default_scene.layers.main.camera(); let base = Layer::new_with_cam(app.logger.sub("component_groups"), &main_camera); let selection = Layer::new_with_cam(app.logger.sub("selection"), &main_camera); + let scrollbar_layer = Layer::new_with_cam(app.logger.sub("scroll_bar"), &main_camera); let selection_mask = Layer::new_with_cam(app.logger.sub("selection_mask"), &main_camera); selection.set_mask(&selection_mask); app.display.default_scene.layers.node_searcher.add_sublayer(&base); app.display.default_scene.layers.node_searcher.add_sublayer(&selection); + app.display.default_scene.layers.node_searcher.add_sublayer(&scrollbar_layer); let content = &scroll_area.content_layer(); let groups = GroupLayers::new(&app.logger, content, &selection); let scroll_layer = scroll_area.content_layer().clone_ref(); - Self { base, selection, groups, selection_mask, scroll_layer } + Self { base, selection, groups, selection_mask, scroll_layer, scrollbar_layer } } } @@ -319,6 +322,9 @@ impl Model { display_object.add_child(&selection); layers.selection_mask.add_exclusive(&selection); + scroll_area.set_scrollbars_layer(&layers.scrollbar_layer); + layers.scrollbar_layer.set_mask(scroll_area.mask_layer()); + favourites_section.set_parent(scroll_area.content()); local_scope_section.set_parent(scroll_area.content()); sub_modules_section.set_parent(scroll_area.content()); @@ -694,6 +700,7 @@ impl component::Frp for Frp { let selection_animation = Animation::::new(&network); let selection_size_animation = Animation::::new(&network); + let selection_corners_animation = Animation::::new(&network); let spring = inertia::Spring::default() * SELECTION_ANIMATION_SPRING_FORCE_MULTIPLIER; selection_animation.set_spring.emit(spring); fn selection_position(model: &Model, id: GroupId, group_local_pos: Vector2) -> Vector2 { @@ -743,8 +750,10 @@ impl component::Frp for Frp { &model.scroll_area.scroll_position_y, f!([model]((id, pos), _) selection_position(&model,*id, *pos)) ); + selection_corners_animation.target <+ groups.selection_corners_radius._1(); eval selection_animation.value ((pos) selection.set_position_xy(*pos)); eval selection_size_animation.value ((pos) selection.size.set(*pos)); + eval selection_corners_animation.value ((r) selection.corners_radius.set(*r)); eval_ model.scroll_area.scroll_position_y(selection_animation.skip.emit(())); } layout_frp.init.emit(()); diff --git a/lib/rust/ensogl/app/theme/hardcoded/src/lib.rs b/lib/rust/ensogl/app/theme/hardcoded/src/lib.rs index f44ea324c0901..3bf0e4d638aa4 100644 --- a/lib/rust/ensogl/app/theme/hardcoded/src/lib.rs +++ b/lib/rust/ensogl/app/theme/hardcoded/src/lib.rs @@ -244,8 +244,11 @@ define_themes! { [light:0, dark:1] } selection { corners_radius = 10.0, 10.0; - horizontal_padding = 10.0, 10.0; - vertical_padding = 3.0, 3.0; + header_corners_radius = 5.0, 5.0; + horizontal_padding = 3.0, 3.0; + height = 30.0, 30.0; + wide_group_column_padding = 18.0, 18.0; + header_height = 21.0, 21.0; } background_color_intensity = 0.2, 0.2; selection_color_intensity = 1.0, 1.0; diff --git a/lib/rust/ensogl/component/scroll-area/src/lib.rs b/lib/rust/ensogl/component/scroll-area/src/lib.rs index 11b899dfcd788..75b025b282443 100644 --- a/lib/rust/ensogl/component/scroll-area/src/lib.rs +++ b/lib/rust/ensogl/component/scroll-area/src/lib.rs @@ -337,6 +337,16 @@ impl ScrollArea { &self.model.content_layer } + /// Set a scene layer for scrollbars. + pub fn set_scrollbars_layer(&self, layer: &layer::Layer) { + layer.add_exclusive(&self.model.scrollbars); + } + + /// A scene layer used as a mask for the content. + pub fn mask_layer(&self) -> &layer::Layer { + &self.model.display_object.layer.mask_layer + } + /// Return whether some object with the given position and size is visible in the scoll area. pub fn is_visible(&self, pos: Vector2, size: Vector2) -> bool {