live-preview: Have the selection popup highlight locations

Have the selection popup actually highlight the hovered
object in the editor.

We did not have this use case before: We used to either
highlight after an update or never at all. Neither semantic
matches what we are doing in the selection popup, so I added
a highlight-now flag.
This commit is contained in:
Tobias Hunger 2024-11-26 17:50:54 +01:00 committed by Tobias Hunger
parent 9ca916e547
commit 03e02b5094
3 changed files with 50 additions and 18 deletions

View file

@ -252,7 +252,7 @@ fn add_new_component() {
drop_data.path,
drop_data.selection_offset,
None,
true,
SelectionNotification::AfterUpdate,
);
{
@ -668,7 +668,7 @@ fn drop_component(component_index: i32, x: f32, y: f32) {
drop_data.path,
drop_data.selection_offset,
None,
true,
SelectionNotification::AfterUpdate,
);
send_workspace_edit(format!("Add element {}", component_name), edit, false);
@ -860,7 +860,7 @@ fn move_selected_element(x: f32, y: f32, mouse_x: f32, mouse_y: f32) {
drop_data.path,
drop_data.selection_offset,
None,
true,
SelectionNotification::AfterUpdate,
);
send_workspace_edit("Move element".to_string(), edit, false);
@ -1167,7 +1167,7 @@ async fn reload_timer_function() {
se.path.clone(),
se.offset,
None,
false,
SelectionNotification::Never,
);
if notify_editor {
@ -1411,7 +1411,12 @@ pub fn highlight(url: Option<Url>, offset: TextSize) {
// Already selected!
return;
}
element_selection::select_element_at_source_code_position(path, offset, None, false);
element_selection::select_element_at_source_code_position(
path,
offset,
None,
SelectionNotification::Never,
);
});
}
}
@ -1528,10 +1533,17 @@ fn set_drop_mark(mark: &Option<drop_location::DropMark>) {
})
}
#[derive(Debug, PartialEq)]
pub enum SelectionNotification {
Never,
Now,
AfterUpdate,
}
fn set_selected_element(
selection: Option<element_selection::ElementSelection>,
positions: &[i_slint_core::lengths::LogicalRect],
notify_editor_about_selection_after_update: bool,
editor_notification: SelectionNotification,
) {
let (layout_kind, parent_layout_kind, type_name) = {
let selection_node = selection.as_ref().and_then(|s| s.as_element_node());
@ -1553,6 +1565,9 @@ fn set_selected_element(
set_drop_mark(&None);
let element_node = selection.as_ref().and_then(|s| s.as_element_node());
let notify_editor_about_selection_after_update =
editor_notification == SelectionNotification::AfterUpdate;
PREVIEW_STATE.with(move |preview_state| {
let mut preview_state = preview_state.borrow_mut();
@ -1633,7 +1648,24 @@ fn set_selected_element(
preview_state.selected = selection;
preview_state.notify_editor_about_selection_after_update =
notify_editor_about_selection_after_update;
})
});
if editor_notification == SelectionNotification::Now {
if let Some(element_node) = element_node {
let (path, pos) = element_node.with_element_node(|node| {
let sf = &node.source_file;
(
sf.path().to_owned(),
util::text_size_to_lsp_position(sf, node.text_range().start()),
)
});
ask_editor_to_show_document(
&path.to_string_lossy(),
lsp_types::Range::new(pos, pos),
false,
);
}
}
}
fn selected_element() -> Option<ElementSelection> {

View file

@ -12,7 +12,7 @@ use slint_interpreter::ComponentInstance;
use crate::common;
use super::{ext::ElementRcNodeExt, ui};
use crate::preview::{ext::ElementRcNodeExt, ui, SelectionNotification};
#[derive(Clone, Debug)]
pub struct ElementSelection {
@ -89,14 +89,14 @@ fn element_covers_point(
}
pub fn unselect_element() {
super::set_selected_element(None, &[], false);
super::set_selected_element(None, &[], SelectionNotification::Never);
}
pub fn select_element_at_source_code_position(
path: PathBuf,
offset: TextSize,
position: Option<LogicalPoint>,
notify_editor_about_selection_after_update: bool,
editor_notification: crate::preview::SelectionNotification,
) {
let Some(component_instance) = super::component_instance() else {
return;
@ -106,7 +106,7 @@ pub fn select_element_at_source_code_position(
path,
offset,
position,
notify_editor_about_selection_after_update,
editor_notification,
)
}
@ -115,7 +115,7 @@ fn select_element_at_source_code_position_impl(
path: PathBuf,
offset: TextSize,
position: Option<LogicalPoint>,
notify_editor_about_selection_after_update: bool,
editor_notification: SelectionNotification,
) {
let positions = component_instance.component_positions(&path, offset.into());
@ -126,7 +126,7 @@ fn select_element_at_source_code_position_impl(
super::set_selected_element(
Some(ElementSelection { path, offset, instance_index }),
&positions,
notify_editor_about_selection_after_update,
editor_notification,
);
}
@ -142,7 +142,7 @@ fn select_element_node(
path,
offset,
position,
false, // We update directly;-)
SelectionNotification::Never, // We update directly;-)
);
if let Some(document_position) = lsp_element_node_position(selected_element) {
@ -525,7 +525,7 @@ pub fn select_element_behind(x: f32, y: f32, enter_component: bool, reverse: boo
// Called from UI thread!
pub fn reselect_element() {
let Some(selected) = super::selected_element() else {
super::set_selected_element(None, &[], false);
super::set_selected_element(None, &[], SelectionNotification::Never);
return;
};
let Some(component_instance) = super::component_instance() else {
@ -533,7 +533,7 @@ pub fn reselect_element() {
};
let positions = component_instance.component_positions(&selected.path, selected.offset.into());
super::set_selected_element(Some(selected), &positions, false);
super::set_selected_element(Some(selected), &positions, SelectionNotification::Never);
}
#[cfg(test)]

View file

@ -13,7 +13,7 @@ use slint_interpreter::{DiagnosticLevel, PlatformError};
use smol_str::SmolStr;
use crate::common::{self, ComponentInformation};
use crate::preview::properties;
use crate::preview::{properties, SelectionNotification};
#[cfg(target_arch = "wasm32")]
use crate::wasm_prelude::*;
@ -80,7 +80,7 @@ pub fn create_ui(style: String, experimental: bool) -> Result<PreviewUi, Platfor
PathBuf::from(path.to_string()),
crate::preview::TextSize::from(offset as u32),
Some(i_slint_core::lengths::LogicalPoint::new(x, y)),
true,
SelectionNotification::Now,
);
});
api.on_select_behind(super::element_selection::select_element_behind);