mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-17 02:43:04 +00:00
live preview: Prefer LogicalPoint over providing x and y
This commit is contained in:
parent
69b8e8d57c
commit
9b2a7fc694
3 changed files with 276 additions and 367 deletions
|
|
@ -2,7 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.2 OR LicenseRef-Slint-commercial
|
||||
|
||||
use i_slint_compiler::parser::{SyntaxKind, SyntaxNode};
|
||||
use i_slint_core::lengths::{LogicalPoint, LogicalRect};
|
||||
use i_slint_core::lengths::{LogicalPoint, LogicalRect, LogicalSize};
|
||||
use slint_interpreter::ComponentInstance;
|
||||
|
||||
use crate::common;
|
||||
|
|
@ -75,16 +75,15 @@ impl DropMarkDirection {
|
|||
}
|
||||
|
||||
fn border_size(dimension: f32) -> f32 {
|
||||
match dimension {
|
||||
d if d >= 16.0 => 4.0,
|
||||
d if d >= 14.0 => 3.0,
|
||||
d if d >= 12.0 => 2.0,
|
||||
d if d >= 6.0 => 1.0,
|
||||
_ => 0.0,
|
||||
let bs = (dimension / 4.0).floor();
|
||||
if bs > 8.0 {
|
||||
8.0
|
||||
} else {
|
||||
bs
|
||||
}
|
||||
}
|
||||
|
||||
// Does this hit the center of an element that accepty drops?
|
||||
// Does this hit the center area of an element that accept drops?
|
||||
fn element_accepts(
|
||||
element_geometry: &LogicalRect,
|
||||
position: LogicalPoint,
|
||||
|
|
@ -171,7 +170,6 @@ impl DropMarkDirection {
|
|||
|
||||
let ne_half = y <= ascend * x;
|
||||
let nw_half = y <= (x * -ascend) + element_geometry.size.height;
|
||||
eprintln!("GRID: {position:?} in {element_geometry:?}: x: {x}, y: {y}, ascend: {ascend} => NE-half: {} => {ne_half}, NW-half: {} => {nw_half}", -ascend * x, (x * ascend) - element_geometry.size.height);
|
||||
|
||||
match (ne_half, nw_half) {
|
||||
(false, false) => DropMarkDirection::S,
|
||||
|
|
@ -260,14 +258,13 @@ fn insert_position_at_end(
|
|||
|
||||
fn drop_target_element_node(
|
||||
component_instance: &ComponentInstance,
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
component_type: &str,
|
||||
) -> (Option<common::ElementRcNode>, Option<common::ElementRcNode>) {
|
||||
let mut self_node = None;
|
||||
let mut surrounding_node = None;
|
||||
let tl = component_instance.definition().type_loader();
|
||||
for sc in &element_selection::collect_all_element_nodes_covering(x, y, component_instance) {
|
||||
for sc in &element_selection::collect_all_element_nodes_covering(position, component_instance) {
|
||||
let Some(en) = sc.as_element_node() else {
|
||||
continue;
|
||||
};
|
||||
|
|
@ -318,34 +315,15 @@ fn extract_element(node: SyntaxNode) -> Option<i_slint_compiler::parser::syntax_
|
|||
fn examine_target_element_node(
|
||||
context: &str,
|
||||
component_instance: &ComponentInstance,
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
target_element_node: &common::ElementRcNode,
|
||||
) {
|
||||
let geometry = target_element_node.geometry_at(component_instance, x, y);
|
||||
eprintln!(
|
||||
"{context} :: {target_element_node:?}<{:?}> [{:?}] @ {x}, {y}",
|
||||
target_element_node.with_element_node(|n| n.kind()),
|
||||
target_element_node.layout_kind()
|
||||
);
|
||||
let geometry = target_element_node.geometry_at(component_instance, position);
|
||||
// let mut result = Vec::new();
|
||||
if let Some(geometry) = geometry {
|
||||
eprintln!(
|
||||
" Element : children count: {}, Geometry: {geometry:?}",
|
||||
target_element_node.element.borrow().children.len()
|
||||
);
|
||||
for (i, c) in target_element_node.element.borrow().children.iter().enumerate() {
|
||||
let c = common::ElementRcNode::new(c.clone(), 0).unwrap();
|
||||
eprintln!(
|
||||
" {i}: {c:?}<{:?}>, Geometry: {:?}",
|
||||
c.with_element_node(|n| n.kind()),
|
||||
c.geometry_in(component_instance, &geometry)
|
||||
);
|
||||
}
|
||||
eprintln!(
|
||||
" Node : children count: {}",
|
||||
target_element_node.with_element_node(|node| node.children().count())
|
||||
);
|
||||
target_element_node.with_element_node(|node| {
|
||||
for (i, c) in node.children().enumerate() {
|
||||
let element_data = if let Some(c_element) = extract_element(c.clone()) {
|
||||
|
|
@ -357,46 +335,90 @@ fn examine_target_element_node(
|
|||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
eprintln!(" {i}: {:?}<{:?}>{element_data}", c.text_range(), c.kind());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn drop_into_layout(
|
||||
component_instance: &ComponentInstance,
|
||||
element_node: common::ElementRcNode,
|
||||
insert_position: Option<(DropMarkDirection, common::ElementRcNode)>,
|
||||
position: LogicalPoint,
|
||||
) -> Option<DropInformation> {
|
||||
let geometry = element_node.geometry_at(component_instance, position)?;
|
||||
let insert_info = insert_position_at_end(&element_node)?;
|
||||
|
||||
Some(DropInformation {
|
||||
target_element_node: element_node,
|
||||
insert_info,
|
||||
drop_mark: Some(DropMark {
|
||||
start: geometry.origin + LogicalSize::new(0.0, geometry.size.height - 1.0),
|
||||
end: geometry.origin + geometry.size,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
fn drop_into_element(
|
||||
component_instance: &ComponentInstance,
|
||||
element_node: common::ElementRcNode,
|
||||
surround_node: Option<common::ElementRcNode>,
|
||||
position: LogicalPoint,
|
||||
) -> Option<DropInformation> {
|
||||
let geometry = element_node.geometry_at(component_instance, position)?;
|
||||
let drop_mark_direction = DropMarkDirection::for_element(
|
||||
&geometry,
|
||||
position,
|
||||
surround_node.as_ref().map(|n| n.layout_kind()).unwrap_or(ui::LayoutKind::None),
|
||||
);
|
||||
|
||||
if drop_mark_direction == DropMarkDirection::None {
|
||||
let insert_info = insert_position_at_end(&element_node)?;
|
||||
|
||||
Some(DropInformation { target_element_node: element_node, insert_info, drop_mark: None })
|
||||
} else {
|
||||
drop_into_layout(
|
||||
component_instance,
|
||||
surround_node.unwrap(),
|
||||
Some((drop_mark_direction, element_node)),
|
||||
position,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn find_drop_location(
|
||||
component_instance: &ComponentInstance,
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
component_type: &str,
|
||||
) -> Option<DropInformation> {
|
||||
let (drop_element_node, drop_surrounding_element_node) =
|
||||
drop_target_element_node(component_instance, x, y, component_type);
|
||||
drop_target_element_node(component_instance, position, component_type);
|
||||
|
||||
let drop_element_node = drop_element_node?;
|
||||
|
||||
examine_target_element_node("Drop target", component_instance, x, y, &drop_element_node);
|
||||
examine_target_element_node("Drop target", component_instance, position, &drop_element_node);
|
||||
if let Some(sn) = &drop_surrounding_element_node {
|
||||
examine_target_element_node("Surrounding", component_instance, x, y, sn);
|
||||
examine_target_element_node("Surrounding", component_instance, position, sn);
|
||||
}
|
||||
|
||||
let insert_info = insert_position_at_end(&drop_element_node)?;
|
||||
|
||||
Some(DropInformation {
|
||||
target_element_node: drop_element_node,
|
||||
insert_info,
|
||||
drop_mark: Some(DropMark {
|
||||
start: LogicalPoint::new(x - 10.0, y - 10.0),
|
||||
end: LogicalPoint::new(x + 10.0, y + 10.0),
|
||||
}),
|
||||
})
|
||||
if drop_element_node.layout_kind() != ui::LayoutKind::None {
|
||||
drop_into_layout(component_instance, drop_element_node, None, position)
|
||||
} else {
|
||||
drop_into_element(
|
||||
component_instance,
|
||||
drop_element_node,
|
||||
drop_surrounding_element_node,
|
||||
position,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the Element to insert into. None means we can not insert at this point.
|
||||
pub fn can_drop_at(x: f32, y: f32, component: &common::ComponentInformation) -> bool {
|
||||
let component_type = component.name.to_string();
|
||||
if let Some(dm) =
|
||||
&super::component_instance().and_then(|ci| find_drop_location(&ci, x, y, &component_type))
|
||||
let position = LogicalPoint::new(x, y);
|
||||
if let Some(dm) = &super::component_instance()
|
||||
.and_then(|ci| find_drop_location(&ci, position, &component_type))
|
||||
{
|
||||
super::set_drop_mark(&dm.drop_mark);
|
||||
true
|
||||
|
|
@ -424,10 +446,11 @@ pub fn drop_at(
|
|||
y: f32,
|
||||
component: &common::ComponentInformation,
|
||||
) -> Option<(lsp_types::WorkspaceEdit, DropData)> {
|
||||
let position = LogicalPoint::new(x, y);
|
||||
let component_type = &component.name;
|
||||
let component_instance = preview::component_instance()?;
|
||||
let tl = component_instance.definition().type_loader();
|
||||
let drop_info = find_drop_location(&component_instance, x, y, component_type)?;
|
||||
let drop_info = find_drop_location(&component_instance, position, component_type)?;
|
||||
|
||||
let properties = {
|
||||
let mut props = component.default_properties.clone();
|
||||
|
|
@ -435,7 +458,8 @@ pub fn drop_at(
|
|||
if drop_info.target_element_node.layout_kind() == ui::LayoutKind::None
|
||||
&& !component.fills_parent
|
||||
{
|
||||
if let Some(area) = drop_info.target_element_node.geometry_at(&component_instance, x, y)
|
||||
if let Some(area) =
|
||||
drop_info.target_element_node.geometry_at(&component_instance, position)
|
||||
{
|
||||
props.push(common::PropertyChange::new("x", format!("{}px", x - area.origin.x)));
|
||||
props.push(common::PropertyChange::new("y", format!("{}px", y - area.origin.y)));
|
||||
|
|
@ -508,13 +532,15 @@ mod tests {
|
|||
for i in 0_u16..100 {
|
||||
let dimension = f32::from(i) / 10.0;
|
||||
let bs = DropMarkDirection::border_size(dimension);
|
||||
assert!(bs >= (expected - 0.05));
|
||||
assert!(bs <= (expected + 1.05));
|
||||
assert!((bs * 2.0) <= dimension); // this makes sure the first bs is 0.0
|
||||
expected = bs;
|
||||
assert!(
|
||||
bs >= (expected - 0.05) && bs < (expected + 0.05)
|
||||
|| (bs >= (expected + 0.95) && bs < (expected + 1.05))
|
||||
);
|
||||
assert!((bs * 3.0) <= dimension); // this makes sure the first bs is 0.0
|
||||
expected = bs.round();
|
||||
}
|
||||
// The maximum border size is 4px:
|
||||
assert!(expected <= 4.05);
|
||||
assert!(expected <= 8.05);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -666,342 +692,218 @@ mod tests {
|
|||
);
|
||||
let bs_h = DropMarkDirection::border_size(rect.size.width);
|
||||
let bs_v = DropMarkDirection::border_size(rect.size.height);
|
||||
eprintln!("width: {width}, height: {height} => border-h: {bs_h}, border-v: {bs_v}");
|
||||
|
||||
// Center: Drop into self, no drop mark ever:
|
||||
let pos =
|
||||
LogicalPoint::new(50.0 + (width / 2.0), 50.0 + (height / 2.0));
|
||||
eprintln!(" Testing: {pos:?}");
|
||||
let pos = LogicalPoint::new(50.0 + (width / 2.0), 50.0 + (height / 2.0));
|
||||
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::None
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::None),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Horizontal
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Horizontal),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Vertical
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Vertical),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Grid
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Grid),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
|
||||
// N-side (in border):
|
||||
let pos = LogicalPoint::new(50.0 + (width / 2.0), 49.0 + bs_v);
|
||||
eprintln!(" Testing: {pos:?}");
|
||||
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::None
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::None),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Horizontal
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Horizontal),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Vertical
|
||||
),
|
||||
if bs_h > 0.9 && bs_v > 0.9 { DropMarkDirection::N } else { DropMarkDirection::None }
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Vertical),
|
||||
if bs_h > 0.9 && bs_v > 0.9 {
|
||||
DropMarkDirection::N
|
||||
} else {
|
||||
DropMarkDirection::None
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Grid
|
||||
),
|
||||
if bs_h > 0.9 && bs_v > 0.9 { DropMarkDirection::N } else { DropMarkDirection::None }
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Grid),
|
||||
if bs_h > 0.9 && bs_v > 0.9 {
|
||||
DropMarkDirection::N
|
||||
} else {
|
||||
DropMarkDirection::None
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// N-side (outside border):
|
||||
let pos = LogicalPoint::new(50.0 + (width / 2.0), 50.0 + bs_v);
|
||||
eprintln!(" Testing: {pos:?}");
|
||||
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::None
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::None),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Horizontal
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Horizontal),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Vertical
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Vertical),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Grid
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Grid),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
|
||||
// E-side (inside border):
|
||||
let pos = LogicalPoint::new(50.0 + width - bs_h, 50.0 + (height / 2.0));
|
||||
eprintln!(" Testing: {pos:?}");
|
||||
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::None
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::None),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Horizontal
|
||||
),
|
||||
if bs_h > 0.9 && bs_v > 0.9 { DropMarkDirection::E } else { DropMarkDirection::None }
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Horizontal),
|
||||
if bs_h > 0.9 && bs_v > 0.9 {
|
||||
DropMarkDirection::E
|
||||
} else {
|
||||
DropMarkDirection::None
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Vertical
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Vertical),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Grid
|
||||
),
|
||||
if bs_h > 0.9 && bs_v > 0.9 { DropMarkDirection::E } else { DropMarkDirection::None }
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Grid),
|
||||
if bs_h > 0.9 && bs_v > 0.9 {
|
||||
DropMarkDirection::E
|
||||
} else {
|
||||
DropMarkDirection::None
|
||||
}
|
||||
);
|
||||
|
||||
// E-side (outside border):
|
||||
let pos = LogicalPoint::new(49.0 + width - bs_h, 50.0 + (height / 2.0));
|
||||
eprintln!(" Testing: {pos:?}");
|
||||
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::None
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::None),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Horizontal
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Horizontal),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Vertical
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Vertical),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Grid
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Grid),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
|
||||
// S-side (in border):
|
||||
let pos = LogicalPoint::new(50.0 + (width / 2.0), 50.0 + height - bs_v);
|
||||
eprintln!(" Testing: {pos:?}");
|
||||
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::None
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::None),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Horizontal
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Horizontal),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Vertical
|
||||
),
|
||||
if bs_h > 0.9 && bs_v > 0.9 { DropMarkDirection::S } else { DropMarkDirection::None }
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Vertical),
|
||||
if bs_h > 0.9 && bs_v > 0.9 {
|
||||
DropMarkDirection::S
|
||||
} else {
|
||||
DropMarkDirection::None
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Grid
|
||||
),
|
||||
if bs_h > 0.9 && bs_v > 0.9 { DropMarkDirection::S } else { DropMarkDirection::None }
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Grid),
|
||||
if bs_h > 0.9 && bs_v > 0.9 {
|
||||
DropMarkDirection::S
|
||||
} else {
|
||||
DropMarkDirection::None
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// S-side (outside border):
|
||||
let pos = LogicalPoint::new(50.0 + (width / 2.0), 49.0 + height - bs_v);
|
||||
eprintln!(" Testing: {pos:?}");
|
||||
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::None
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::None),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Horizontal
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Horizontal),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Vertical
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Vertical),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Grid
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Grid),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
|
||||
// W-side (inside border):
|
||||
let pos = LogicalPoint::new(49.0 + bs_h, 50.0 + (height / 2.0));
|
||||
eprintln!(" Testing: {pos:?}");
|
||||
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::None
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::None),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Horizontal
|
||||
),
|
||||
if bs_h > 0.9 && bs_v > 0.9 { DropMarkDirection::W } else { DropMarkDirection::None }
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Horizontal),
|
||||
if bs_h > 0.9 && bs_v > 0.9 {
|
||||
DropMarkDirection::W
|
||||
} else {
|
||||
DropMarkDirection::None
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Vertical
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Vertical),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Grid
|
||||
),
|
||||
if bs_h > 0.9 && bs_v > 0.9 { DropMarkDirection::W } else { DropMarkDirection::None }
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Grid),
|
||||
if bs_h > 0.9 && bs_v > 0.9 {
|
||||
DropMarkDirection::W
|
||||
} else {
|
||||
DropMarkDirection::None
|
||||
}
|
||||
);
|
||||
|
||||
// W-side (outside border):
|
||||
let pos = LogicalPoint::new(50.0 + bs_h, 50.0 + (height / 2.0));
|
||||
eprintln!(" Testing: {pos:?}");
|
||||
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::None
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::None),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Horizontal
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Horizontal),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Vertical
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Vertical),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
assert_eq!(
|
||||
DropMarkDirection::for_element(
|
||||
&rect,
|
||||
pos,
|
||||
ui::LayoutKind::Grid
|
||||
),
|
||||
DropMarkDirection::for_element(&rect, pos, ui::LayoutKind::Grid),
|
||||
DropMarkDirection::None
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::{path::PathBuf, rc::Rc};
|
|||
|
||||
use i_slint_compiler::diagnostics::SourceFile;
|
||||
use i_slint_compiler::object_tree::{Component, ElementRc};
|
||||
use i_slint_core::lengths::{LogicalLength, LogicalPoint};
|
||||
use i_slint_core::lengths::LogicalPoint;
|
||||
use rowan::TextRange;
|
||||
use slint_interpreter::ComponentInstance;
|
||||
|
||||
|
|
@ -73,17 +73,11 @@ fn lsp_element_node_position(element: &ElementRcNode) -> Option<(String, lsp_typ
|
|||
}
|
||||
|
||||
fn element_covers_point(
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
component_instance: &ComponentInstance,
|
||||
selected_element: &ElementRc,
|
||||
) -> bool {
|
||||
let click_position = LogicalPoint::from_lengths(LogicalLength::new(x), LogicalLength::new(y));
|
||||
|
||||
component_instance
|
||||
.element_positions(selected_element)
|
||||
.iter()
|
||||
.any(|p| p.contains(click_position))
|
||||
component_instance.element_positions(selected_element).iter().any(|p| p.contains(position))
|
||||
}
|
||||
|
||||
pub fn unselect_element() {
|
||||
|
|
@ -197,8 +191,7 @@ impl std::fmt::Debug for SelectionCandidate {
|
|||
// Traverse the element tree in reverse render order and collect information on
|
||||
// all elements that "render" at the given x and y coordinates
|
||||
fn collect_all_element_nodes_covering_impl(
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
component_instance: &ComponentInstance,
|
||||
current_element: &ElementRc,
|
||||
component_stack: &Vec<Rc<Component>>,
|
||||
|
|
@ -223,8 +216,7 @@ fn collect_all_element_nodes_covering_impl(
|
|||
|
||||
for c in ce.borrow().children.iter().rev() {
|
||||
collect_all_element_nodes_covering_impl(
|
||||
x,
|
||||
y,
|
||||
position,
|
||||
component_instance,
|
||||
c,
|
||||
children_component_stack,
|
||||
|
|
@ -232,7 +224,7 @@ fn collect_all_element_nodes_covering_impl(
|
|||
);
|
||||
}
|
||||
|
||||
if element_covers_point(x, y, component_instance, &ce) {
|
||||
if element_covers_point(position, component_instance, &ce) {
|
||||
for (i, _) in ce.borrow().debug.iter().enumerate().rev() {
|
||||
// All nodes have the same geometry
|
||||
let text_range = element_node_source_range(&ce, i);
|
||||
|
|
@ -247,15 +239,13 @@ fn collect_all_element_nodes_covering_impl(
|
|||
}
|
||||
|
||||
pub fn collect_all_element_nodes_covering(
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
component_instance: &ComponentInstance,
|
||||
) -> Vec<SelectionCandidate> {
|
||||
let root_element = root_element(component_instance);
|
||||
let mut elements = Vec::new();
|
||||
collect_all_element_nodes_covering_impl(
|
||||
x,
|
||||
y,
|
||||
position,
|
||||
component_instance,
|
||||
&root_element,
|
||||
&vec![],
|
||||
|
|
@ -300,11 +290,10 @@ pub fn is_same_file_as_root_node(
|
|||
|
||||
fn select_element_at_impl(
|
||||
component_instance: &ComponentInstance,
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
enter_component: bool,
|
||||
) -> Option<ElementRcNode> {
|
||||
for sc in &collect_all_element_nodes_covering(x, y, component_instance) {
|
||||
for sc in &collect_all_element_nodes_covering(position, component_instance) {
|
||||
if let Some(en) = filter_nodes_for_selection(component_instance, sc, enter_component) {
|
||||
return Some(en);
|
||||
}
|
||||
|
|
@ -317,20 +306,22 @@ pub fn select_element_at(x: f32, y: f32, enter_component: bool) {
|
|||
return;
|
||||
};
|
||||
|
||||
let position = LogicalPoint::new(x, y);
|
||||
|
||||
if let Some(se) = super::selected_element() {
|
||||
if let Some(element) = se.as_element() {
|
||||
if element_covers_point(x, y, &component_instance, &element) {
|
||||
if element_covers_point(position, &component_instance, &element) {
|
||||
// We clicked on the already selected element: Do nothing!
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let Some(en) = select_element_at_impl(&component_instance, x, y, enter_component) else {
|
||||
let Some(en) = select_element_at_impl(&component_instance, position, enter_component) else {
|
||||
return;
|
||||
};
|
||||
|
||||
select_element_node(&component_instance, &en, Some(LogicalPoint::new(x, y)));
|
||||
select_element_node(&component_instance, &en, Some(position));
|
||||
}
|
||||
|
||||
pub fn is_element_node_in_layout(element: &ElementRcNode) -> bool {
|
||||
|
|
@ -381,12 +372,11 @@ fn filter_nodes_for_selection(
|
|||
pub fn select_element_behind_impl(
|
||||
component_instance: &ComponentInstance,
|
||||
selected_element_node: &ElementRcNode,
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
enter_component: bool,
|
||||
reverse: bool,
|
||||
) -> Option<ElementRcNode> {
|
||||
let elements = collect_all_element_nodes_covering(x, y, component_instance);
|
||||
let elements = collect_all_element_nodes_covering(position, component_instance);
|
||||
let current_selection_position =
|
||||
elements.iter().position(|sc| sc.is_selected_element_node(selected_element_node))?;
|
||||
|
||||
|
|
@ -422,6 +412,7 @@ pub fn select_element_behind(x: f32, y: f32, enter_component: bool, reverse: boo
|
|||
let Some(component_instance) = super::component_instance() else {
|
||||
return;
|
||||
};
|
||||
let position = LogicalPoint::new(x, y);
|
||||
let Some(selected_element_node) =
|
||||
super::selected_element().and_then(|sel| sel.as_element_node())
|
||||
else {
|
||||
|
|
@ -431,15 +422,14 @@ pub fn select_element_behind(x: f32, y: f32, enter_component: bool, reverse: boo
|
|||
let Some(en) = select_element_behind_impl(
|
||||
&component_instance,
|
||||
&selected_element_node,
|
||||
x,
|
||||
y,
|
||||
position,
|
||||
enter_component,
|
||||
reverse,
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
select_element_node(&component_instance, &en, Some(LogicalPoint::new(x, y)));
|
||||
select_element_node(&component_instance, &en, Some(position));
|
||||
}
|
||||
|
||||
// Called from UI thread!
|
||||
|
|
@ -459,6 +449,7 @@ pub fn reselect_element() {
|
|||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use i_slint_core::lengths::LogicalPoint;
|
||||
use slint_interpreter::ComponentInstance;
|
||||
|
||||
fn demo_app() -> ComponentInstance {
|
||||
|
|
@ -494,8 +485,10 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
fn test_find_covering_elements() {
|
||||
let component_instance = demo_app();
|
||||
|
||||
let mut covers_center =
|
||||
super::collect_all_element_nodes_covering(100.0, 100.0, &component_instance);
|
||||
let mut covers_center = super::collect_all_element_nodes_covering(
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
&component_instance,
|
||||
);
|
||||
|
||||
// Remove the "button" implenmentation details. They must be at the start:
|
||||
let button_path = PathBuf::from("builtin:/fluent-base/button.slint");
|
||||
|
|
@ -518,8 +511,10 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
assert_eq!(offset, *expected_offset);
|
||||
}
|
||||
|
||||
let covers_below =
|
||||
super::collect_all_element_nodes_covering(100.0, 180.0, &component_instance);
|
||||
let covers_below = super::collect_all_element_nodes_covering(
|
||||
LogicalPoint::new(100.0, 180.0),
|
||||
&component_instance,
|
||||
);
|
||||
|
||||
// All but the button itself as well as the SomeComponent (impl and use)
|
||||
assert_eq!(covers_below.len(), covers_center.len() - 3);
|
||||
|
|
@ -537,26 +532,31 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let component_instance = demo_app();
|
||||
|
||||
let button_path = PathBuf::from("builtin:/fluent-base/button.slint");
|
||||
let mut covers_center =
|
||||
super::collect_all_element_nodes_covering(100.0, 100.0, &component_instance)
|
||||
.iter()
|
||||
.flat_map(|sc| sc.as_element_node())
|
||||
.map(|en| en.path_and_offset())
|
||||
.collect::<Vec<_>>();
|
||||
let mut covers_center = super::collect_all_element_nodes_covering(
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
&component_instance,
|
||||
)
|
||||
.iter()
|
||||
.flat_map(|sc| sc.as_element_node())
|
||||
.map(|en| en.path_and_offset())
|
||||
.collect::<Vec<_>>();
|
||||
let first_non_button = covers_center.iter().position(|(p, _)| p != &button_path).unwrap();
|
||||
covers_center.drain(1..(first_non_button - 1)); // strip all but first/last of button
|
||||
|
||||
// Select without crossing file boundries
|
||||
let select =
|
||||
super::select_element_at_impl(&component_instance, 100.0, 100.0, false).unwrap();
|
||||
let select = super::select_element_at_impl(
|
||||
&component_instance,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(&select.path_and_offset(), covers_center.get(2).unwrap());
|
||||
|
||||
// Move deeper into the image:
|
||||
let next = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&select,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
|
|
@ -565,8 +565,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let next = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
|
|
@ -575,8 +574,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let next = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
|
|
@ -585,8 +583,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let next = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
|
|
@ -595,8 +592,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
assert!(super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
false
|
||||
)
|
||||
|
|
@ -606,8 +602,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let prev = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
|
|
@ -616,8 +611,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let prev = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&prev,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
|
|
@ -626,8 +620,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let prev = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&prev,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
|
|
@ -636,8 +629,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let prev = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&prev,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
|
|
@ -646,8 +638,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
assert!(super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&prev,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
true
|
||||
)
|
||||
|
|
@ -657,8 +648,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&select,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
true
|
||||
),
|
||||
|
|
@ -666,8 +656,12 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
);
|
||||
|
||||
// Select with crossing file boundries
|
||||
let select =
|
||||
super::select_element_at_impl(&component_instance, 100.0, 100.0, true).unwrap();
|
||||
let select = super::select_element_at_impl(
|
||||
&component_instance,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(&select.path_and_offset(), covers_center.get(0).unwrap());
|
||||
|
||||
// move to the last in the button definition:
|
||||
|
|
@ -676,8 +670,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
button = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&button,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
|
|
@ -691,8 +684,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let next = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&button,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
|
|
@ -701,8 +693,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let next = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
|
|
@ -711,8 +702,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let next = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
|
|
@ -721,8 +711,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let next = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
|
|
@ -731,8 +720,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
let next = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
|
|
@ -741,33 +729,57 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
assert!(super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
false,
|
||||
false
|
||||
)
|
||||
.is_none());
|
||||
|
||||
// Move towards the viewer:
|
||||
let prev =
|
||||
super::select_element_behind_impl(&component_instance, &next, 100.0, 100.0, true, true)
|
||||
.unwrap();
|
||||
let prev = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&next,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(&prev.path_and_offset(), covers_center.get(5).unwrap());
|
||||
let prev =
|
||||
super::select_element_behind_impl(&component_instance, &prev, 100.0, 100.0, true, true)
|
||||
.unwrap();
|
||||
let prev = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&prev,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(&prev.path_and_offset(), covers_center.get(4).unwrap());
|
||||
let prev =
|
||||
super::select_element_behind_impl(&component_instance, &prev, 100.0, 100.0, true, true)
|
||||
.unwrap();
|
||||
let prev = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&prev,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(&prev.path_and_offset(), covers_center.get(3).unwrap());
|
||||
let prev =
|
||||
super::select_element_behind_impl(&component_instance, &prev, 100.0, 100.0, true, true)
|
||||
.unwrap();
|
||||
let prev = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&prev,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(&prev.path_and_offset(), covers_center.get(2).unwrap());
|
||||
let prev =
|
||||
super::select_element_behind_impl(&component_instance, &prev, 100.0, 100.0, true, true)
|
||||
.unwrap();
|
||||
let prev = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&prev,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(&prev.path_and_offset(), covers_center.get(1).unwrap());
|
||||
|
||||
button = prev;
|
||||
|
|
@ -775,8 +787,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
button = super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&button,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
true,
|
||||
)
|
||||
|
|
@ -789,8 +800,7 @@ export component Entry inherits Main { /* @lsp:ignore-node */ } // 401
|
|||
assert!(super::select_element_behind_impl(
|
||||
&component_instance,
|
||||
&button,
|
||||
100.0,
|
||||
100.0,
|
||||
LogicalPoint::new(100.0, 100.0),
|
||||
true,
|
||||
true
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@ pub trait ElementRcNodeExt {
|
|||
fn geometry_at(
|
||||
&self,
|
||||
component_instance: &ComponentInstance,
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
) -> Option<i_slint_core::lengths::LogicalRect>;
|
||||
|
||||
/// Find the first geometry of ElementRcNode in `rect`
|
||||
|
|
@ -60,11 +59,9 @@ impl ElementRcNodeExt for common::ElementRcNode {
|
|||
fn geometry_at(
|
||||
&self,
|
||||
component_instance: &ComponentInstance,
|
||||
x: f32,
|
||||
y: f32,
|
||||
position: LogicalPoint,
|
||||
) -> Option<i_slint_core::lengths::LogicalRect> {
|
||||
let click_position = LogicalPoint::new(x, y);
|
||||
self.geometries(component_instance).iter().find(|g| g.contains(click_position)).cloned()
|
||||
self.geometries(component_instance).iter().find(|g| g.contains(position)).cloned()
|
||||
}
|
||||
|
||||
fn geometry_in(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue