mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-22 00:02:40 +00:00
live-preview: Handle known components using our local DocumentCache
This commit is contained in:
parent
6c034372a1
commit
d657ee65af
9 changed files with 124 additions and 117 deletions
|
@ -68,7 +68,7 @@ preview-lense = []
|
||||||
## to provide an implementation of the external preview API when building for WASM)
|
## to provide an implementation of the external preview API when building for WASM)
|
||||||
preview-api = ["preview-external"]
|
preview-api = ["preview-external"]
|
||||||
## Build in the actual code to act as a preview for slint files.
|
## Build in the actual code to act as a preview for slint files.
|
||||||
preview-engine = ["dep:slint", "dep:slint-interpreter", "dep:i-slint-core", "dep:i-slint-backend-selector", "dep:image", "dep:slint-build", "dep:spin_on", "dep:i-slint-common"]
|
preview-engine = ["dep:slint", "dep:slint-interpreter", "dep:i-slint-core", "dep:i-slint-backend-selector", "dep:image", "dep:slint-build", "dep:i-slint-common"]
|
||||||
## Build in the actual code to act as a preview for slint files. Does nothing in WASM!
|
## Build in the actual code to act as a preview for slint files. Does nothing in WASM!
|
||||||
preview-builtin = ["preview-engine"]
|
preview-builtin = ["preview-engine"]
|
||||||
## Support the external preview optionally used by e.g. the VSCode plugin
|
## Support the external preview optionally used by e.g. the VSCode plugin
|
||||||
|
@ -93,7 +93,6 @@ i-slint-common = { workspace = true, optional = true }
|
||||||
i-slint-core = { workspace = true, features = ["std"], optional = true }
|
i-slint-core = { workspace = true, features = ["std"], optional = true }
|
||||||
slint = { workspace = true, features = ["compat-1-2"], optional = true }
|
slint = { workspace = true, features = ["compat-1-2"], optional = true }
|
||||||
slint-interpreter = { workspace = true, features = ["compat-1-2", "highlight", "internal"], optional = true }
|
slint-interpreter = { workspace = true, features = ["compat-1-2", "highlight", "internal"], optional = true }
|
||||||
spin_on = { workspace = true, optional = true }
|
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
|
@ -114,6 +113,7 @@ wasm-bindgen-futures = "0.4.30"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
i-slint-backend-testing = { path = "../../internal/backends/testing" }
|
i-slint-backend-testing = { path = "../../internal/backends/testing" }
|
||||||
|
spin_on = { workspace = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
slint-build = { workspace = true, features = ["default"], optional = true }
|
slint-build = { workspace = true, features = ["default"], optional = true }
|
||||||
|
|
|
@ -30,8 +30,7 @@ use crate::wasm_prelude::*;
|
||||||
|
|
||||||
pub fn uri_to_file(uri: &Url) -> Option<PathBuf> {
|
pub fn uri_to_file(uri: &Url) -> Option<PathBuf> {
|
||||||
if uri.scheme() == "builtin" {
|
if uri.scheme() == "builtin" {
|
||||||
let path = String::from("builtin:") + uri.path();
|
Some(PathBuf::from(uri.to_string()))
|
||||||
Some(PathBuf::from(path))
|
|
||||||
} else {
|
} else {
|
||||||
let path = uri.to_file_path().ok()?;
|
let path = uri.to_file_path().ok()?;
|
||||||
let cleaned_path = i_slint_compiler::pathutils::clean_path(&path);
|
let cleaned_path = i_slint_compiler::pathutils::clean_path(&path);
|
||||||
|
@ -41,15 +40,7 @@ pub fn uri_to_file(uri: &Url) -> Option<PathBuf> {
|
||||||
|
|
||||||
pub fn file_to_uri(path: &Path) -> Option<Url> {
|
pub fn file_to_uri(path: &Path) -> Option<Url> {
|
||||||
if path.starts_with("builtin:/") {
|
if path.starts_with("builtin:/") {
|
||||||
let p_str = path.to_string_lossy();
|
Url::parse(path.to_str()?).ok()
|
||||||
let p_str = if &p_str[9..11] == "///" {
|
|
||||||
p_str.to_string()
|
|
||||||
} else {
|
|
||||||
let mut r = p_str.to_string();
|
|
||||||
r.insert_str(8, "//");
|
|
||||||
r
|
|
||||||
};
|
|
||||||
Url::parse(&p_str).ok()
|
|
||||||
} else {
|
} else {
|
||||||
Url::from_file_path(path).ok()
|
Url::from_file_path(path).ok()
|
||||||
}
|
}
|
||||||
|
@ -155,8 +146,7 @@ impl DocumentCache {
|
||||||
content: String,
|
content: String,
|
||||||
diag: &mut BuildDiagnostics,
|
diag: &mut BuildDiagnostics,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let path =
|
let path = uri_to_file(url).ok_or("Failed to convert path")?;
|
||||||
uri_to_file(url).ok_or::<Error>(String::from("Failed to convert path").into())?;
|
|
||||||
self.0.load_file(&path, version, &path, content, false, diag).await;
|
self.0.load_file(&path, version, &path, content, false, diag).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -531,7 +521,6 @@ pub enum LspToPreviewMessage {
|
||||||
SetConfiguration { config: PreviewConfig },
|
SetConfiguration { config: PreviewConfig },
|
||||||
ShowPreview(PreviewComponent),
|
ShowPreview(PreviewComponent),
|
||||||
HighlightFromEditor { url: Option<Url>, offset: u32 },
|
HighlightFromEditor { url: Option<Url>, offset: u32 },
|
||||||
KnownComponents { url: Option<VersionedUrl>, components: Vec<ComponentInformation> },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -704,4 +693,20 @@ mod tests {
|
||||||
|
|
||||||
assert!(Url::from_file_path(&builtin_path).is_err());
|
assert!(Url::from_file_path(&builtin_path).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_uri_conversion_of_slashed_builtins() {
|
||||||
|
let builtin_path1 = PathBuf::from("builtin:/fluent/button.slint");
|
||||||
|
let builtin_path3 = PathBuf::from("builtin:///fluent/button.slint");
|
||||||
|
|
||||||
|
let url1 = file_to_uri(&builtin_path1).unwrap();
|
||||||
|
let url3 = file_to_uri(&builtin_path3).unwrap();
|
||||||
|
assert_ne!(url1, url3);
|
||||||
|
|
||||||
|
let back_conversion1 = uri_to_file(&url1).unwrap();
|
||||||
|
let back_conversion3 = uri_to_file(&url3).unwrap();
|
||||||
|
assert_eq!(back_conversion1, back_conversion3);
|
||||||
|
|
||||||
|
assert_eq!(back_conversion1, builtin_path1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
// cSpell: ignore descr rfind unindented
|
// cSpell: ignore descr rfind unindented
|
||||||
|
|
||||||
use crate::common::{ComponentInformation, DocumentCache, Position, PropertyChange};
|
use crate::common::{ComponentInformation, DocumentCache, Position, PropertyChange};
|
||||||
|
#[cfg(feature = "preview-engine")]
|
||||||
use i_slint_compiler::langtype::{DefaultSizeBinding, ElementType};
|
use i_slint_compiler::langtype::{DefaultSizeBinding, ElementType};
|
||||||
|
#[cfg(feature = "preview-engine")]
|
||||||
use lsp_types::Url;
|
use lsp_types::Url;
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(feature = "preview-engine")]
|
||||||
use crate::wasm_prelude::UrlWasm;
|
|
||||||
|
|
||||||
fn builtin_component_info(name: &str, fills_parent: bool) -> ComponentInformation {
|
fn builtin_component_info(name: &str, fills_parent: bool) -> ComponentInformation {
|
||||||
let (category, is_layout) = match name {
|
let (category, is_layout) = match name {
|
||||||
"GridLayout" | "HorizontalLayout" | "VerticalLayout" => ("Layout", true),
|
"GridLayout" | "HorizontalLayout" | "VerticalLayout" => ("Layout", true),
|
||||||
|
@ -98,6 +98,7 @@ fn exported_project_component_info(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "preview-engine")]
|
||||||
fn file_local_component_info(name: &str, position: Position) -> ComponentInformation {
|
fn file_local_component_info(name: &str, position: Position) -> ComponentInformation {
|
||||||
ComponentInformation {
|
ComponentInformation {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
@ -113,6 +114,7 @@ fn file_local_component_info(name: &str, position: Position) -> ComponentInforma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "preview-engine")]
|
||||||
pub fn builtin_components(document_cache: &DocumentCache, result: &mut Vec<ComponentInformation>) {
|
pub fn builtin_components(document_cache: &DocumentCache, result: &mut Vec<ComponentInformation>) {
|
||||||
let registry = document_cache.global_type_registry();
|
let registry = document_cache.global_type_registry();
|
||||||
result.extend(registry.all_elements().iter().filter_map(|(name, ty)| match ty {
|
result.extend(registry.all_elements().iter().filter_map(|(name, ty)| match ty {
|
||||||
|
@ -171,6 +173,7 @@ pub fn all_exported_components(
|
||||||
result.dedup_by(|a, b| a.name == b.name);
|
result.dedup_by(|a, b| a.name == b.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "preview-engine")]
|
||||||
pub fn file_local_components(
|
pub fn file_local_components(
|
||||||
document_cache: &DocumentCache,
|
document_cache: &DocumentCache,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
use crate::wasm_prelude::*;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::common;
|
use crate::common;
|
||||||
|
|
|
@ -11,7 +11,7 @@ mod semantic_tokens;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
|
||||||
use crate::common::{self, component_catalog, DocumentCache, Result};
|
use crate::common::{self, DocumentCache, Result};
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
@ -93,6 +93,7 @@ pub struct Context {
|
||||||
pub server_notifier: crate::ServerNotifier,
|
pub server_notifier: crate::ServerNotifier,
|
||||||
pub init_param: InitializeParams,
|
pub init_param: InitializeParams,
|
||||||
/// The last component for which the user clicked "show preview"
|
/// The last component for which the user clicked "show preview"
|
||||||
|
#[cfg(any(feature = "preview-external", feature = "preview-engine"))]
|
||||||
pub to_show: RefCell<Option<common::PreviewComponent>>,
|
pub to_show: RefCell<Option<common::PreviewComponent>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,9 +424,6 @@ pub fn show_preview_command(params: &[serde_json::Value], ctx: &Rc<Context>) ->
|
||||||
ctx.to_show.replace(Some(c.clone()));
|
ctx.to_show.replace(Some(c.clone()));
|
||||||
ctx.server_notifier.send_message_to_preview(common::LspToPreviewMessage::ShowPreview(c));
|
ctx.server_notifier.send_message_to_preview(common::LspToPreviewMessage::ShowPreview(c));
|
||||||
|
|
||||||
// Update known Components
|
|
||||||
report_known_components(document_cache, ctx);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,28 +679,6 @@ pub(crate) async fn reload_document_impl(
|
||||||
lsp_diags
|
lsp_diags
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_known_components(document_cache: &mut DocumentCache, ctx: &Rc<Context>) {
|
|
||||||
let mut components = Vec::new();
|
|
||||||
component_catalog::builtin_components(document_cache, &mut components);
|
|
||||||
component_catalog::all_exported_components(
|
|
||||||
&document_cache,
|
|
||||||
&mut |ci| !ci.is_global,
|
|
||||||
&mut components,
|
|
||||||
);
|
|
||||||
|
|
||||||
components.sort_by(|a, b| a.name.cmp(&b.name));
|
|
||||||
|
|
||||||
let url = ctx.to_show.borrow().as_ref().map(|pc| {
|
|
||||||
let url = pc.url.clone();
|
|
||||||
let version = document_cache.document_version(&url);
|
|
||||||
component_catalog::file_local_components(document_cache, &url, &mut components);
|
|
||||||
common::VersionedUrl::new(url, version)
|
|
||||||
});
|
|
||||||
|
|
||||||
ctx.server_notifier
|
|
||||||
.send_message_to_preview(common::LspToPreviewMessage::KnownComponents { url, components });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn reload_document(
|
pub async fn reload_document(
|
||||||
ctx: &Rc<Context>,
|
ctx: &Rc<Context>,
|
||||||
content: String,
|
content: String,
|
||||||
|
@ -720,9 +696,6 @@ pub async fn reload_document(
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell Preview about the Components:
|
|
||||||
report_known_components(document_cache, ctx);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
// cSpell: ignore rfind
|
// cSpell: ignore rfind
|
||||||
|
|
||||||
use super::component_catalog::all_exported_components;
|
use crate::common::component_catalog::all_exported_components;
|
||||||
use crate::common::{self, DocumentCache};
|
use crate::common::{self, DocumentCache};
|
||||||
use crate::util::{lookup_current_element_type, map_position, with_lookup_ctx};
|
use crate::util::{lookup_current_element_type, map_position, with_lookup_ctx};
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,6 @@ use i_slint_compiler::parser::{syntax_nodes, Language, SyntaxKind};
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
use crate::wasm_prelude::*;
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, PartialEq)]
|
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, PartialEq)]
|
||||||
pub(crate) struct DefinitionInformation {
|
pub(crate) struct DefinitionInformation {
|
||||||
property_definition_range: lsp_types::Range,
|
property_definition_range: lsp_types::Range,
|
||||||
|
|
|
@ -310,6 +310,7 @@ fn main_loop(connection: Connection, init_param: InitializeParams, cli_args: Cli
|
||||||
preview_config: RefCell::new(Default::default()),
|
preview_config: RefCell::new(Default::default()),
|
||||||
server_notifier,
|
server_notifier,
|
||||||
init_param,
|
init_param,
|
||||||
|
#[cfg(any(feature = "preview-external", feature = "preview-engine"))]
|
||||||
to_show: Default::default(),
|
to_show: Default::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
||||||
|
|
||||||
use crate::common::{self, ComponentInformation, ElementRcNode, PreviewComponent, PreviewConfig};
|
use crate::common::{
|
||||||
|
self, component_catalog, ComponentInformation, ElementRcNode, PreviewComponent, PreviewConfig,
|
||||||
|
};
|
||||||
use crate::lsp_ext::Health;
|
use crate::lsp_ext::Health;
|
||||||
use crate::preview::element_selection::ElementSelection;
|
use crate::preview::element_selection::ElementSelection;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
@ -74,34 +76,77 @@ struct PreviewState {
|
||||||
}
|
}
|
||||||
thread_local! {static PREVIEW_STATE: std::cell::RefCell<PreviewState> = Default::default();}
|
thread_local! {static PREVIEW_STATE: std::cell::RefCell<PreviewState> = Default::default();}
|
||||||
|
|
||||||
|
struct DummyWaker();
|
||||||
|
|
||||||
|
impl std::task::Wake for DummyWaker {
|
||||||
|
fn wake(self: std::sync::Arc<Self>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll_once<F: std::future::Future>(future: F) -> Option<F::Output> {
|
||||||
|
let waker = std::sync::Arc::new(DummyWaker()).into();
|
||||||
|
let mut ctx = std::task::Context::from_waker(&waker);
|
||||||
|
|
||||||
|
let future = std::pin::pin!(future);
|
||||||
|
|
||||||
|
match future.poll(&mut ctx) {
|
||||||
|
std::task::Poll::Ready(result) => Some(result),
|
||||||
|
std::task::Poll::Pending => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PreviewState {
|
impl PreviewState {
|
||||||
fn refresh_document_cache(
|
fn refresh_document_cache(
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &lsp_types::Url,
|
url: &Url,
|
||||||
version: SourceFileVersion,
|
version: SourceFileVersion,
|
||||||
source_code: String,
|
source_code: String,
|
||||||
) {
|
) {
|
||||||
let Some(dc) = self.document_cache.as_mut() else {
|
let Some(document_cache) = self.document_cache.as_mut() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut diag = BuildDiagnostics::default();
|
let mut diag = BuildDiagnostics::default();
|
||||||
let _ = spin_on::spin_on(dc.load_url(url, version, source_code, &mut diag)); // ignore url conversion errors
|
let _ = poll_once(document_cache.load_url(url, version, source_code, &mut diag)); // ignore url conversion errors
|
||||||
|
|
||||||
eprintln!("Updated Document Cache in Live Preview: has_error: {}", diag.has_error());
|
let mut components = Vec::new();
|
||||||
|
component_catalog::builtin_components(document_cache, &mut components);
|
||||||
|
component_catalog::all_exported_components(
|
||||||
|
&document_cache,
|
||||||
|
&mut |ci| !ci.is_global,
|
||||||
|
&mut components,
|
||||||
|
);
|
||||||
|
|
||||||
|
components.sort_by(|a, b| a.name.cmp(&b.name));
|
||||||
|
|
||||||
|
self.known_components = components;
|
||||||
|
|
||||||
|
if let Some(ui) = &self.ui {
|
||||||
|
ui::ui_set_known_components(ui, &self.known_components)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recreate_document_cache(&mut self, config: &PreviewConfig, style: String) {
|
fn recreate_document_cache(
|
||||||
|
&mut self,
|
||||||
|
config: &PreviewConfig,
|
||||||
|
style: String,
|
||||||
|
preview_url: &Url,
|
||||||
|
) {
|
||||||
|
let style = if style.is_empty() { None } else { Some(style) };
|
||||||
|
|
||||||
|
if let Some(dc) = &self.document_cache {
|
||||||
|
let cc = dc.compiler_configuration();
|
||||||
|
if cc.style == style
|
||||||
|
&& cc.include_paths == config.include_paths
|
||||||
|
&& cc.library_paths == config.library_paths
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
let mut compiler_config = i_slint_compiler::CompilerConfiguration::new(
|
let mut compiler_config = i_slint_compiler::CompilerConfiguration::new(
|
||||||
i_slint_compiler::generator::OutputFormat::Interpreter,
|
i_slint_compiler::generator::OutputFormat::Interpreter,
|
||||||
);
|
);
|
||||||
|
|
||||||
if style.is_empty() {
|
compiler_config.style = style;
|
||||||
compiler_config.style = None;
|
|
||||||
} else {
|
|
||||||
compiler_config.style = Some(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
compiler_config.include_paths = config.include_paths.clone();
|
compiler_config.include_paths = config.include_paths.clone();
|
||||||
compiler_config.library_paths = config.library_paths.clone();
|
compiler_config.library_paths = config.library_paths.clone();
|
||||||
compiler_config.open_import_fallback = Some(Rc::new(|path| {
|
compiler_config.open_import_fallback = Some(Rc::new(|path| {
|
||||||
|
@ -110,31 +155,43 @@ impl PreviewState {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
self.document_cache = Some(common::DocumentCache::new(compiler_config));
|
self.document_cache = Some(common::DocumentCache::new(compiler_config));
|
||||||
|
|
||||||
|
if let Some((version, contents)) = CONTENT_CACHE
|
||||||
|
.get_or_init(Default::default)
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.source_code
|
||||||
|
.get(&preview_url)
|
||||||
|
.cloned()
|
||||||
|
{
|
||||||
|
self.refresh_document_cache(preview_url, version, contents);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_contents(url: &common::VersionedUrl, content: String) {
|
pub fn set_contents(url: &common::VersionedUrl, content: String) {
|
||||||
let mut cache = CONTENT_CACHE.get_or_init(Default::default).lock().unwrap();
|
let mut cache = CONTENT_CACHE.get_or_init(Default::default).lock().unwrap();
|
||||||
let old = cache.source_code.insert(url.url().clone(), (*url.version(), content.clone()));
|
let old = cache.source_code.insert(url.url().clone(), (*url.version(), content.clone()));
|
||||||
if cache.dependency.contains(url.url()) {
|
|
||||||
if let Some((old_version, old)) = old {
|
if let Some((old_version, old)) = old {
|
||||||
if content == old && old_version == *url.version() {
|
if content == old && old_version == *url.version() {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let fu = url.clone();
|
let fu = url.clone();
|
||||||
let fc = content.clone();
|
let fc = content.clone();
|
||||||
|
|
||||||
let _ = i_slint_core::api::invoke_from_event_loop(move || {
|
let _ = i_slint_core::api::invoke_from_event_loop(move || {
|
||||||
let url = fu;
|
let url = fu;
|
||||||
let content = fc;
|
let content = fc;
|
||||||
|
|
||||||
PREVIEW_STATE.with(move |ps| {
|
PREVIEW_STATE.with(move |ps| {
|
||||||
ps.borrow_mut().refresh_document_cache(url.url(), url.version().clone(), content)
|
ps.borrow_mut().refresh_document_cache(url.url(), url.version().clone(), content)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if cache.dependency.contains(url.url()) {
|
||||||
let ui_is_visible = cache.ui_is_visible;
|
let ui_is_visible = cache.ui_is_visible;
|
||||||
let Some(current) = cache.current.clone() else {
|
let Some(current) = cache.current.clone() else {
|
||||||
return;
|
return;
|
||||||
|
@ -400,12 +457,6 @@ fn change_style() {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let config = cache.config.clone();
|
|
||||||
let style = get_current_style();
|
|
||||||
let _ = i_slint_core::api::invoke_from_event_loop(move || {
|
|
||||||
PREVIEW_STATE.with(|ps| ps.borrow_mut().recreate_document_cache(&config, style))
|
|
||||||
});
|
|
||||||
|
|
||||||
drop(cache);
|
drop(cache);
|
||||||
|
|
||||||
if ui_is_visible {
|
if ui_is_visible {
|
||||||
|
@ -440,11 +491,6 @@ pub fn config_changed(config: PreviewConfig) {
|
||||||
|
|
||||||
drop(cache);
|
drop(cache);
|
||||||
|
|
||||||
let style = get_current_style();
|
|
||||||
let _ = i_slint_core::api::invoke_from_event_loop(move || {
|
|
||||||
PREVIEW_STATE.with(|ps| ps.borrow_mut().recreate_document_cache(&config, style))
|
|
||||||
});
|
|
||||||
|
|
||||||
if ui_is_visible {
|
if ui_is_visible {
|
||||||
if let Some(hide_ui) = hide_ui {
|
if let Some(hide_ui) = hide_ui {
|
||||||
set_show_preview_ui(!hide_ui);
|
set_show_preview_ui(!hide_ui);
|
||||||
|
@ -612,10 +658,16 @@ async fn reload_preview_impl(
|
||||||
style: String,
|
style: String,
|
||||||
config: PreviewConfig,
|
config: PreviewConfig,
|
||||||
) {
|
) {
|
||||||
|
let preview_url = preview_component.url.clone();
|
||||||
|
|
||||||
let component = PreviewComponent { style: String::new(), ..preview_component };
|
let component = PreviewComponent { style: String::new(), ..preview_component };
|
||||||
|
|
||||||
start_parsing();
|
start_parsing();
|
||||||
|
|
||||||
|
PREVIEW_STATE.with(|preview_state| {
|
||||||
|
preview_state.borrow_mut().recreate_document_cache(&config, style.clone(), &preview_url);
|
||||||
|
});
|
||||||
|
|
||||||
let path = component.url.to_file_path().unwrap_or(PathBuf::from(&component.url.to_string()));
|
let path = component.url.to_file_path().unwrap_or(PathBuf::from(&component.url.to_string()));
|
||||||
let source = {
|
let source = {
|
||||||
let (_, from_cache) = get_url_from_cache(&component.url).unwrap_or_default();
|
let (_, from_cache) = get_url_from_cache(&component.url).unwrap_or_default();
|
||||||
|
@ -699,24 +751,6 @@ pub fn highlight(url: Option<Url>, offset: u32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn known_components(
|
|
||||||
_url: &Option<common::VersionedUrl>,
|
|
||||||
mut components: Vec<ComponentInformation>,
|
|
||||||
) {
|
|
||||||
components.sort_unstable_by_key(|ci| ci.name.clone());
|
|
||||||
|
|
||||||
run_in_ui_thread(move || async move {
|
|
||||||
PREVIEW_STATE.with(|preview_state| {
|
|
||||||
let mut preview_state = preview_state.borrow_mut();
|
|
||||||
preview_state.known_components = components;
|
|
||||||
|
|
||||||
if let Some(ui) = &preview_state.ui {
|
|
||||||
ui::ui_set_known_components(ui, &preview_state.known_components)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_component_info(component_type: &str) -> Option<ComponentInformation> {
|
pub fn get_component_info(component_type: &str) -> Option<ComponentInformation> {
|
||||||
PREVIEW_STATE.with(|preview_state| {
|
PREVIEW_STATE.with(|preview_state| {
|
||||||
let preview_state = preview_state.borrow();
|
let preview_state = preview_state.borrow();
|
||||||
|
@ -730,15 +764,15 @@ pub fn get_component_info(component_type: &str) -> Option<ComponentInformation>
|
||||||
|
|
||||||
fn convert_diagnostics(
|
fn convert_diagnostics(
|
||||||
diagnostics: &[slint_interpreter::Diagnostic],
|
diagnostics: &[slint_interpreter::Diagnostic],
|
||||||
) -> HashMap<lsp_types::Url, Vec<lsp_types::Diagnostic>> {
|
) -> HashMap<Url, Vec<lsp_types::Diagnostic>> {
|
||||||
let mut result: HashMap<lsp_types::Url, Vec<lsp_types::Diagnostic>> = Default::default();
|
let mut result: HashMap<Url, Vec<lsp_types::Diagnostic>> = Default::default();
|
||||||
for d in diagnostics {
|
for d in diagnostics {
|
||||||
if d.source_file().map_or(true, |f| !i_slint_compiler::pathutils::is_absolute(f)) {
|
if d.source_file().map_or(true, |f| !i_slint_compiler::pathutils::is_absolute(f)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let uri = lsp_types::Url::from_file_path(d.source_file().unwrap())
|
let uri = Url::from_file_path(d.source_file().unwrap())
|
||||||
.ok()
|
.ok()
|
||||||
.unwrap_or_else(|| lsp_types::Url::parse("file:/unknown").unwrap());
|
.unwrap_or_else(|| Url::parse("file:/unknown").unwrap());
|
||||||
result.entry(uri).or_default().push(crate::util::to_lsp_diag(d));
|
result.entry(uri).or_default().push(crate::util::to_lsp_diag(d));
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
|
@ -954,9 +988,6 @@ pub fn lsp_to_preview_message(
|
||||||
M::HighlightFromEditor { url, offset } => {
|
M::HighlightFromEditor { url, offset } => {
|
||||||
highlight(url, offset);
|
highlight(url, offset);
|
||||||
}
|
}
|
||||||
M::KnownComponents { url, components } => {
|
|
||||||
known_components(&url, components);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue