lsp: Add option to show/hide preview ui

... and use that option in VSCode configuration.
This commit is contained in:
Tobias Hunger 2023-11-22 19:13:02 +01:00 committed by Tobias Hunger
parent b19cbba7ad
commit 548f10be2b
11 changed files with 177 additions and 66 deletions

View file

@ -94,6 +94,10 @@
}, },
"description": "The command line arguments passed to the Slint LSP server" "description": "The command line arguments passed to the Slint LSP server"
}, },
"slint.preview.show_ui": {
"type": "boolean",
"description": "Show the toolbar of the preview"
},
"slint.preview.style": { "slint.preview.style": {
"type": "string", "type": "string",
"description": "The default style to be used for the preview (eg: 'fluent', 'material', or 'native')" "description": "The default style to be used for the preview (eg: 'fluent', 'material', or 'native')"

View file

@ -19,6 +19,7 @@ pub trait PreviewApi {
fn load_preview(&self, component: PreviewComponent); fn load_preview(&self, component: PreviewComponent);
fn config_changed( fn config_changed(
&self, &self,
show_preview_ui: bool,
style: &str, style: &str,
include_paths: &[PathBuf], include_paths: &[PathBuf],
library_paths: &HashMap<String, PathBuf>, library_paths: &HashMap<String, PathBuf>,
@ -27,6 +28,12 @@ pub trait PreviewApi {
/// What is the current component to preview? /// What is the current component to preview?
fn current_component(&self) -> Option<PreviewComponent>; fn current_component(&self) -> Option<PreviewComponent>;
/// Return the currently configured `show_preview_ui` value.
///
/// This is not ideal, but we can not access the configuration without
/// a round trip into the editor.
fn show_preview_ui(&self) -> bool;
} }
/// The Component to preview /// The Component to preview
@ -57,6 +64,7 @@ pub enum LspToPreviewMessage {
contents: String, contents: String,
}, },
SetConfiguration { SetConfiguration {
show_preview_ui: bool,
style: String, style: String,
include_paths: Vec<String>, include_paths: Vec<String>,
library_paths: Vec<(String, String)>, library_paths: Vec<(String, String)>,

View file

@ -90,6 +90,7 @@ pub fn request_state(ctx: &std::rc::Rc<Context>) {
} }
let style = documents.compiler_config.style.clone().unwrap_or_default(); let style = documents.compiler_config.style.clone().unwrap_or_default();
ctx.preview.config_changed( ctx.preview.config_changed(
ctx.preview.show_preview_ui(),
&style, &style,
&documents.compiler_config.include_paths, &documents.compiler_config.include_paths,
&documents.compiler_config.library_paths, &documents.compiler_config.library_paths,
@ -1221,6 +1222,7 @@ pub async fn load_configuration(ctx: &Context) -> Result<()> {
.await?; .await?;
let document_cache = &mut ctx.document_cache.borrow_mut(); let document_cache = &mut ctx.document_cache.borrow_mut();
let mut show_preview_ui = false;
for v in r { for v in r {
if let Some(o) = v.as_object() { if let Some(o) = v.as_object() {
if let Some(ip) = o.get("includePaths").and_then(|v| v.as_array()) { if let Some(ip) = o.get("includePaths").and_then(|v| v.as_array()) {
@ -1244,6 +1246,10 @@ pub async fn load_configuration(ctx: &Context) -> Result<()> {
document_cache.documents.compiler_config.style = Some(style.into()); document_cache.documents.compiler_config.style = Some(style.into());
} }
} }
show_preview_ui = o
.get("preview")
.and_then(|v| v.as_object()?.get("show_ui")?.as_bool())
.unwrap_or_default();
} }
} }
@ -1254,6 +1260,7 @@ pub async fn load_configuration(ctx: &Context) -> Result<()> {
let cc = &document_cache.documents.compiler_config; let cc = &document_cache.documents.compiler_config;
let empty_string = String::new(); let empty_string = String::new();
ctx.preview.config_changed( ctx.preview.config_changed(
show_preview_ui,
cc.style.as_ref().unwrap_or(&empty_string), cc.style.as_ref().unwrap_or(&empty_string),
&cc.include_paths, &cc.include_paths,
&cc.library_paths, &cc.library_paths,

View file

@ -37,6 +37,7 @@ struct Previewer {
#[allow(unused)] #[allow(unused)]
server_notifier: ServerNotifier, server_notifier: ServerNotifier,
use_external_previewer: RefCell<bool>, use_external_previewer: RefCell<bool>,
show_preview_ui: RefCell<bool>,
to_show: RefCell<Option<common::PreviewComponent>>, to_show: RefCell<Option<common::PreviewComponent>>,
} }
@ -103,15 +104,18 @@ impl PreviewApi for Previewer {
fn config_changed( fn config_changed(
&self, &self,
_show_preview_ui: bool,
_style: &str, _style: &str,
_include_paths: &[PathBuf], _include_paths: &[PathBuf],
_library_paths: &HashMap<String, PathBuf>, _library_paths: &HashMap<String, PathBuf>,
) { ) {
*self.show_preview_ui.borrow_mut() = _show_preview_ui;
if *self.use_external_previewer.borrow() { if *self.use_external_previewer.borrow() {
#[cfg(feature = "preview-external")] #[cfg(feature = "preview-external")]
let _ = self.server_notifier.send_notification( let _ = self.server_notifier.send_notification(
"slint/lsp_to_preview".to_string(), "slint/lsp_to_preview".to_string(),
crate::common::LspToPreviewMessage::SetConfiguration { crate::common::LspToPreviewMessage::SetConfiguration {
show_preview_ui: _show_preview_ui,
style: _style.to_string(), style: _style.to_string(),
include_paths: _include_paths include_paths: _include_paths
.iter() .iter()
@ -125,7 +129,7 @@ impl PreviewApi for Previewer {
); );
} else { } else {
#[cfg(feature = "preview-builtin")] #[cfg(feature = "preview-builtin")]
preview::config_changed(_style, _include_paths, _library_paths); preview::config_changed(_show_preview_ui, _style, _include_paths, _library_paths);
} }
} }
@ -152,6 +156,10 @@ impl PreviewApi for Previewer {
fn current_component(&self) -> Option<crate::common::PreviewComponent> { fn current_component(&self) -> Option<crate::common::PreviewComponent> {
self.to_show.borrow().clone() self.to_show.borrow().clone()
} }
fn show_preview_ui(&self) -> bool {
*self.show_preview_ui.borrow()
}
} }
#[derive(Clone, clap::Parser)] #[derive(Clone, clap::Parser)]
@ -176,6 +184,10 @@ struct Cli {
/// Start the preview in full screen mode /// Start the preview in full screen mode
#[arg(long, action)] #[arg(long, action)]
fullscreen: bool, fullscreen: bool,
/// Show the preview UI
#[arg(long, default_value = "true", action = clap::ArgAction::Set)]
show_preview_ui: bool,
} }
enum OutgoingRequest { enum OutgoingRequest {
@ -265,11 +277,13 @@ fn main() {
std::env::set_var("SLINT_FULLSCREEN", "1"); std::env::set_var("SLINT_FULLSCREEN", "1");
} }
let show_preview_ui = args.show_preview_ui;
#[cfg(feature = "preview-engine")] #[cfg(feature = "preview-engine")]
{ {
let lsp_thread = std::thread::Builder::new() let lsp_thread = std::thread::Builder::new()
.name("LanguageServer".into()) .name("LanguageServer".into())
.spawn(|| { .spawn(move || {
/// Make sure we quit the event loop even if we panic /// Make sure we quit the event loop even if we panic
struct QuitEventLoop; struct QuitEventLoop;
impl Drop for QuitEventLoop { impl Drop for QuitEventLoop {
@ -279,7 +293,7 @@ fn main() {
} }
let quit_ui_loop = QuitEventLoop; let quit_ui_loop = QuitEventLoop;
let threads = match run_lsp_server() { let threads = match run_lsp_server(show_preview_ui) {
Ok(threads) => threads, Ok(threads) => threads,
Err(error) => { Err(error) => {
eprintln!("Error running LSP server: {}", error); eprintln!("Error running LSP server: {}", error);
@ -304,7 +318,7 @@ fn main() {
} }
} }
pub fn run_lsp_server() -> Result<IoThreads> { pub fn run_lsp_server(show_preview_ui: bool) -> Result<IoThreads> {
let (connection, io_threads) = Connection::stdio(); let (connection, io_threads) = Connection::stdio();
let (id, params) = connection.initialize_start()?; let (id, params) = connection.initialize_start()?;
@ -313,12 +327,16 @@ pub fn run_lsp_server() -> Result<IoThreads> {
serde_json::to_value(language::server_initialize_result(&init_param.capabilities))?; serde_json::to_value(language::server_initialize_result(&init_param.capabilities))?;
connection.initialize_finish(id, initialize_result)?; connection.initialize_finish(id, initialize_result)?;
main_loop(connection, init_param)?; main_loop(connection, init_param, show_preview_ui)?;
Ok(io_threads) Ok(io_threads)
} }
fn main_loop(connection: Connection, init_param: InitializeParams) -> Result<()> { fn main_loop(
connection: Connection,
init_param: InitializeParams,
show_preview_ui: bool,
) -> Result<()> {
let mut rh = RequestHandler::default(); let mut rh = RequestHandler::default();
register_request_handlers(&mut rh); register_request_handlers(&mut rh);
@ -336,6 +354,7 @@ fn main_loop(connection: Connection, init_param: InitializeParams) -> Result<()>
#[cfg(all(feature = "preview-builtin", feature = "preview-external"))] #[cfg(all(feature = "preview-builtin", feature = "preview-external"))]
use_external_previewer: RefCell::new(false), // prefer internal use_external_previewer: RefCell::new(false), // prefer internal
to_show: RefCell::new(None), to_show: RefCell::new(None),
show_preview_ui: RefCell::new(show_preview_ui),
}); });
let mut compiler_config = let mut compiler_config =
CompilerConfiguration::new(i_slint_compiler::generator::OutputFormat::Interpreter); CompilerConfiguration::new(i_slint_compiler::generator::OutputFormat::Interpreter);

View file

@ -49,6 +49,8 @@ struct ContentCache {
ui_is_visible: bool, ui_is_visible: bool,
design_mode: bool, design_mode: bool,
default_style: String, default_style: String,
// Duplicate this information in case the UI is not up yet.
show_preview_ui: bool,
} }
static CONTENT_CACHE: std::sync::OnceLock<Mutex<ContentCache>> = std::sync::OnceLock::new(); static CONTENT_CACHE: std::sync::OnceLock<Mutex<ContentCache>> = std::sync::OnceLock::new();
@ -106,6 +108,7 @@ pub fn finish_parsing(ok: bool) {
} }
pub fn config_changed( pub fn config_changed(
show_preview_ui: bool,
style: &str, style: &str,
include_paths: &[PathBuf], include_paths: &[PathBuf],
library_paths: &HashMap<String, PathBuf>, library_paths: &HashMap<String, PathBuf>,
@ -116,15 +119,20 @@ pub fn config_changed(
if cache.current.style != style if cache.current.style != style
|| cache.current.include_paths != include_paths || cache.current.include_paths != include_paths
|| cache.current.library_paths != *library_paths || cache.current.library_paths != *library_paths
|| cache.show_preview_ui != show_preview_ui
{ {
cache.current.include_paths = include_paths.to_vec(); cache.current.include_paths = include_paths.to_vec();
cache.current.library_paths = library_paths.clone(); cache.current.library_paths = library_paths.clone();
cache.default_style = style; cache.default_style = style;
cache.show_preview_ui = show_preview_ui;
let current = cache.current.clone(); let current = cache.current.clone();
let ui_is_visible = cache.ui_is_visible; let ui_is_visible = cache.ui_is_visible;
let show_preview_ui = cache.show_preview_ui;
drop(cache); drop(cache);
if ui_is_visible && !current.path.as_os_str().is_empty() { if ui_is_visible && !current.path.as_os_str().is_empty() {
set_show_preview_ui(show_preview_ui);
load_preview(current); load_preview(current);
} }
} }

View file

@ -122,7 +122,7 @@ pub fn open_ui(sender: &ServerNotifier) {
} }
} }
let default_style = { let (default_style, show_preview_ui) = {
let mut cache = super::CONTENT_CACHE.get_or_init(Default::default).lock().unwrap(); let mut cache = super::CONTENT_CACHE.get_or_init(Default::default).lock().unwrap();
if cache.ui_is_visible { if cache.ui_is_visible {
return; // UI is already up! return; // UI is already up!
@ -132,21 +132,23 @@ pub fn open_ui(sender: &ServerNotifier) {
let mut s = SERVER_NOTIFIER.get_or_init(Default::default).lock().unwrap(); let mut s = SERVER_NOTIFIER.get_or_init(Default::default).lock().unwrap();
*s = Some(sender.clone()); *s = Some(sender.clone());
cache.default_style.clone() (cache.default_style.clone(), cache.show_preview_ui)
}; };
i_slint_core::api::invoke_from_event_loop(move || { i_slint_core::api::invoke_from_event_loop(move || {
PREVIEW_STATE.with(|preview_state| { PREVIEW_STATE.with(|preview_state| {
let mut preview_state = preview_state.borrow_mut(); let mut preview_state = preview_state.borrow_mut();
open_ui_impl(&mut preview_state, default_style); open_ui_impl(&mut preview_state, default_style, show_preview_ui);
}); });
}) })
.unwrap(); .unwrap();
} }
fn open_ui_impl(preview_state: &mut PreviewState, default_style: String) { fn open_ui_impl(preview_state: &mut PreviewState, default_style: String, show_preview_ui: bool) {
// TODO: Handle Error! // TODO: Handle Error!
let ui = preview_state.ui.get_or_insert_with(|| super::ui::create_ui(default_style).unwrap()); let ui = preview_state
.ui
.get_or_insert_with(|| super::ui::create_ui(default_style, show_preview_ui).unwrap());
ui.on_show_document(|url, line, column| { ui.on_show_document(|url, line, column| {
ask_editor_to_show_document( ask_editor_to_show_document(
url.as_str().to_string(), url.as_str().to_string(),
@ -218,6 +220,17 @@ pub fn notify_diagnostics(diagnostics: &[slint_interpreter::Diagnostic]) -> Opti
Some(()) Some(())
} }
pub fn set_show_preview_ui(show_preview_ui: bool) {
run_in_ui_thread(move || async move {
PREVIEW_STATE.with(|preview_state| {
let preview_state = preview_state.borrow();
if let Some(ui) = &preview_state.ui {
ui.set_show_preview_ui(show_preview_ui)
}
})
});
}
pub fn set_current_style(style: String) { pub fn set_current_style(style: String) {
PREVIEW_STATE.with(move |preview_state| { PREVIEW_STATE.with(move |preview_state| {
let preview_state = preview_state.borrow_mut(); let preview_state = preview_state.borrow_mut();
@ -312,15 +325,15 @@ pub fn configure_design_mode(enabled: bool) {
/// This runs `set_preview_factory` in the UI thread /// This runs `set_preview_factory` in the UI thread
pub fn update_preview_area(compiled: slint_interpreter::ComponentDefinition, design_mode: bool) { pub fn update_preview_area(compiled: slint_interpreter::ComponentDefinition, design_mode: bool) {
let default_style = { let (default_style, show_preview_ui) = {
let cache = super::CONTENT_CACHE.get_or_init(Default::default).lock().unwrap(); let cache = super::CONTENT_CACHE.get_or_init(Default::default).lock().unwrap();
cache.default_style.clone() (cache.default_style.clone(), cache.show_preview_ui)
}; };
PREVIEW_STATE.with(|preview_state| { PREVIEW_STATE.with(|preview_state| {
let mut preview_state = preview_state.borrow_mut(); let mut preview_state = preview_state.borrow_mut();
open_ui_impl(&mut preview_state, default_style); open_ui_impl(&mut preview_state, default_style, show_preview_ui);
let shared_handle = preview_state.handle.clone(); let shared_handle = preview_state.handle.clone();

View file

@ -11,12 +11,10 @@ use slint_interpreter::{DiagnosticLevel, PlatformError};
slint::include_modules!(); slint::include_modules!();
pub fn create_ui(style: String) -> Result<PreviewUi, PlatformError> { pub fn create_ui(style: String, show_preview_ui: bool) -> Result<PreviewUi, PlatformError> {
let ui = PreviewUi::new()?; let ui = PreviewUi::new()?;
if std::env::var("SLINT_FULLSCREEN").is_ok() { ui.set_show_preview_ui(show_preview_ui);
ui.set_hide_toolbar(true);
}
// design mode: // design mode:
ui.on_design_mode_changed(super::set_design_mode); ui.on_design_mode_changed(super::set_design_mode);

View file

@ -75,7 +75,7 @@ impl PreviewConnector {
reject_c.take().call1(&JsValue::UNDEFINED, reject_c.take().call1(&JsValue::UNDEFINED,
&JsValue::from("PreviewConnector already set up.")).unwrap_throw(); &JsValue::from("PreviewConnector already set up.")).unwrap_throw();
} else { } else {
match super::ui::create_ui(style) { match super::ui::create_ui(style, true) {
Ok(ui) => { Ok(ui) => {
ui.on_show_document(|url, line, column| ask_editor_to_show_document(url.as_str().to_string(), line as u32, column as u32, line as u32, column as u32)); ui.on_show_document(|url, line, column| ask_editor_to_show_document(url.as_str().to_string(), line as u32, column as u32, line as u32, column as u32));
preview_state.borrow_mut().ui = Some(ui); preview_state.borrow_mut().ui = Some(ui);
@ -125,11 +125,11 @@ impl PreviewConnector {
super::set_contents(&PathBuf::from(&path), contents); super::set_contents(&PathBuf::from(&path), contents);
Ok(()) Ok(())
} }
M::SetConfiguration { style, include_paths, library_paths } => { M::SetConfiguration { show_preview_ui, style, include_paths, library_paths } => {
let ip: Vec<PathBuf> = include_paths.iter().map(PathBuf::from).collect(); let ip: Vec<PathBuf> = include_paths.iter().map(PathBuf::from).collect();
let lp: HashMap<String, PathBuf> = let lp: HashMap<String, PathBuf> =
library_paths.iter().map(|(n, p)| (n.clone(), PathBuf::from(p))).collect(); library_paths.iter().map(|(n, p)| (n.clone(), PathBuf::from(p))).collect();
super::config_changed(&style, &ip, &lp); super::config_changed(show_preview_ui, &style, &ip, &lp);
Ok(()) Ok(())
} }
M::ShowPreview { path, component, style, include_paths, library_paths } => { M::ShowPreview { path, component, style, include_paths, library_paths } => {
@ -259,6 +259,15 @@ pub fn send_message_to_lsp(message: crate::common::PreviewToLspMessage) {
}) })
} }
pub fn set_show_preview_ui(show_preview_ui: bool) {
PREVIEW_STATE.with(move |preview_state| {
let preview_state = preview_state.borrow_mut();
if let Some(ui) = &preview_state.ui {
ui.set_show_preview_ui(show_preview_ui)
}
});
}
pub fn set_current_style(style: String) { pub fn set_current_style(style: String) {
PREVIEW_STATE.with(move |preview_state| { PREVIEW_STATE.with(move |preview_state| {
let preview_state = preview_state.borrow_mut(); let preview_state = preview_state.borrow_mut();

View file

@ -0,0 +1,51 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
// cSpell: ignore Heade
import { ListView, VerticalBox } from "std-widgets.slint";
export struct Diagnostics {
level: string,
message: string,
url: string,
line: int,
column: int,
}
export component DiagnosticsOverlay {
in property<[Diagnostics]> diagnostics;
callback show-document(/* url */ string, /* line */ int, /* column */ int);
if (root.diagnostics.length != 0): Rectangle {
background: #fff;
VerticalBox {
Text {
color: #000;
text: "Compilation failed:";
}
ListView {
width: parent.width - 10px;
height: parent.height - 10px;
padding: 5px;
for diag in root.diagnostics: Rectangle {
TouchArea {
mouse-cursor: pointer;
clicked => { root.show_document(diag.url, diag.line, diag.column); }
Text {
width: 100%;
wrap: word-wrap;
color: #000;
text: diag.level + ": " + diag.message;
}
}
}
}
}
}
}

View file

@ -5,22 +5,17 @@
import { Button, ComboBox, HorizontalBox, ListView, ScrollView, VerticalBox } from "std-widgets.slint"; import { Button, ComboBox, HorizontalBox, ListView, ScrollView, VerticalBox } from "std-widgets.slint";
import { HeaderBar } from "header-bar.slint"; import { HeaderBar } from "header-bar.slint";
import { Diagnostics, DiagnosticsOverlay } from "diagnostics-overlay.slint";
export struct Diagnostics { export { Diagnostics }
level: string,
message: string,
url: string,
line: int,
column: int,
}
export component PreviewUi inherits Window { export component PreviewUi inherits Window {
in property<[string]> known-styles; in property<[string]> known-styles;
in property<[Diagnostics]> diagnostics; in property<[Diagnostics]> diagnostics;
in property<string> status-text; in property<string> status-text;
in property<component-factory> preview-area <=> i-preview-area-container.component-factory; in property<component-factory> preview-area;
in-out property<string> current-style; in-out property<string> current-style;
in property<bool> hide-toolbar; in property<bool> show-preview-ui;
callback design-mode-changed(/* enabled */ bool); callback design-mode-changed(/* enabled */ bool);
callback style-changed(); callback style-changed();
@ -29,8 +24,24 @@ export component PreviewUi inherits Window {
title: "Slint Live-Preview"; title: "Slint Live-Preview";
icon: @image-url("assets/slint-logo-small-light.png"); icon: @image-url("assets/slint-logo-small-light.png");
VerticalLayout { if (!show-preview-ui): VerticalLayout {
if !hide_toolbar: HeaderBar { no-ui-drawing-rect := Rectangle {
/* background: checkerboard pattern; */
ComponentContainer {
component-factory <=> root.preview-area;
width: clamp(no-ui-drawing-rect.width, self.min-width, self.max-width);
height: clamp(no-ui-drawing-rect.height, self.min-height, self.max-height);
}
// Diagnostics overlay:
DiagnosticsOverlay {
diagnostics <=> root.diagnostics;
show-document(url, line, column) => { root.show-document(url, line, column); }
}
}
}
if (show-preview-ui): VerticalLayout {
HeaderBar {
vertical-stretch: 0.0; vertical-stretch: 0.0;
height: self.preferred-height; height: self.preferred-height;
@ -64,43 +75,16 @@ export component PreviewUi inherits Window {
drawing-rect := Rectangle { drawing-rect := Rectangle {
/* background: checkerboard pattern; */ /* background: checkerboard pattern; */
i-preview-area-container := ComponentContainer { ComponentContainer {
width: max(self.min-width, min(self.max-width, drawing-rect.width)); component-factory <=> root.preview-area;
height: max(self.min-height, min(self.max-height, drawing-rect.height)); width: clamp(drawing-rect.width, self.min-width, self.max-width);
height: clamp(drawing-rect.height, self.min-height, self.max-height);
} }
// Diagnostics overlay: // Diagnostics overlay:
if (root.diagnostics.length != 0): Rectangle { DiagnosticsOverlay {
background: #fff; diagnostics <=> root.diagnostics;
show-document(url, line, column) => { root.show-document(url, line, column); }
VerticalBox {
Text {
color: #000;
text: "Compilation failed:";
}
ListView {
width: parent.width - 10px;
height: parent.height - 10px;
padding: 5px;
for diag in root.diagnostics: Rectangle {
TouchArea {
mouse-cursor: pointer;
clicked => { root.show_document(diag.url, diag.line, diag.column); }
Text {
width: 100%;
wrap: word-wrap;
color: #000;
text: diag.level + ": " + diag.message;
}
}
}
}
}
} }
} }
} }

View file

@ -46,6 +46,7 @@ pub mod wasm_prelude {
struct Previewer { struct Previewer {
server_notifier: ServerNotifier, server_notifier: ServerNotifier,
to_show: RefCell<Option<common::PreviewComponent>>, to_show: RefCell<Option<common::PreviewComponent>>,
show_preview_ui: RefCell<bool>,
} }
impl PreviewApi for Previewer { impl PreviewApi for Previewer {
@ -94,14 +95,18 @@ impl PreviewApi for Previewer {
fn config_changed( fn config_changed(
&self, &self,
show_preview_ui: bool,
style: &str, style: &str,
include_paths: &[PathBuf], include_paths: &[PathBuf],
library_paths: &HashMap<String, PathBuf>, library_paths: &HashMap<String, PathBuf>,
) { ) {
*self.show_preview_ui.borrow_mut() = show_preview_ui;
#[cfg(feature = "preview-external")] #[cfg(feature = "preview-external")]
let _ = self.server_notifier.send_notification( let _ = self.server_notifier.send_notification(
"slint/lsp_to_preview".to_string(), "slint/lsp_to_preview".to_string(),
crate::common::LspToPreviewMessage::SetConfiguration { crate::common::LspToPreviewMessage::SetConfiguration {
show_preview_ui,
style: style.to_string(), style: style.to_string(),
include_paths: include_paths include_paths: include_paths
.iter() .iter()
@ -129,6 +134,10 @@ impl PreviewApi for Previewer {
fn current_component(&self) -> Option<crate::common::PreviewComponent> { fn current_component(&self) -> Option<crate::common::PreviewComponent> {
self.to_show.borrow().clone() self.to_show.borrow().clone()
} }
fn show_preview_ui(&self) -> bool {
*self.show_preview_ui.borrow()
}
} }
#[derive(Clone)] #[derive(Clone)]
@ -269,6 +278,7 @@ pub fn create(
let preview = Rc::new(Previewer { let preview = Rc::new(Previewer {
server_notifier: server_notifier.clone(), server_notifier: server_notifier.clone(),
to_show: Default::default(), to_show: Default::default(),
show_preview_ui: RefCell::new(true),
}); });
let init_param = serde_wasm_bindgen::from_value(init_param)?; let init_param = serde_wasm_bindgen::from_value(init_param)?;