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.path,
drop_data.selection_offset, drop_data.selection_offset,
None, None,
true, SelectionNotification::AfterUpdate,
); );
{ {
@ -668,7 +668,7 @@ fn drop_component(component_index: i32, x: f32, y: f32) {
drop_data.path, drop_data.path,
drop_data.selection_offset, drop_data.selection_offset,
None, None,
true, SelectionNotification::AfterUpdate,
); );
send_workspace_edit(format!("Add element {}", component_name), edit, false); 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.path,
drop_data.selection_offset, drop_data.selection_offset,
None, None,
true, SelectionNotification::AfterUpdate,
); );
send_workspace_edit("Move element".to_string(), edit, false); send_workspace_edit("Move element".to_string(), edit, false);
@ -1167,7 +1167,7 @@ async fn reload_timer_function() {
se.path.clone(), se.path.clone(),
se.offset, se.offset,
None, None,
false, SelectionNotification::Never,
); );
if notify_editor { if notify_editor {
@ -1411,7 +1411,12 @@ pub fn highlight(url: Option<Url>, offset: TextSize) {
// Already selected! // Already selected!
return; 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( fn set_selected_element(
selection: Option<element_selection::ElementSelection>, selection: Option<element_selection::ElementSelection>,
positions: &[i_slint_core::lengths::LogicalRect], 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 (layout_kind, parent_layout_kind, type_name) = {
let selection_node = selection.as_ref().and_then(|s| s.as_element_node()); 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); 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| { PREVIEW_STATE.with(move |preview_state| {
let mut preview_state = preview_state.borrow_mut(); let mut preview_state = preview_state.borrow_mut();
@ -1633,7 +1648,24 @@ fn set_selected_element(
preview_state.selected = selection; preview_state.selected = selection;
preview_state.notify_editor_about_selection_after_update = preview_state.notify_editor_about_selection_after_update =
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> { fn selected_element() -> Option<ElementSelection> {

View file

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

View file

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