live-preview: Only pass information on the component previewed once

This commit is contained in:
Tobias Hunger 2024-06-21 11:22:03 +02:00 committed by Tobias Hunger
parent 229fdb73ec
commit d0d0327049
5 changed files with 69 additions and 47 deletions

View file

@ -345,14 +345,20 @@ fn navigate(nav_direction: i32) {
}
// triggered from the UI, running in UI thread
fn show_component(name: slint::SharedString, file: slint::SharedString) {
fn show_component(name: slint::SharedString, url: slint::SharedString) {
let name = name.to_string();
let file = PathBuf::from(file.to_string());
let Ok(url) = Url::parse(&url.to_string()) else {
return;
};
let Ok(file) = url.to_file_path() else {
return;
};
let Some(document_cache) = document_cache() else {
return;
};
let Some(document) = document_cache.get_document_by_path(&file) else {
let Some(document) = document_cache.get_document(&url) else {
return;
};
let Some(document) = document.node.as_ref() else {
@ -955,26 +961,8 @@ fn set_preview_factory(
Some(instance)
});
let (name, file, pretty_location) = {
let cache = CONTENT_CACHE.get_or_init(Default::default).lock().unwrap();
if let Some(current) = cache.current_component() {
let file = current.url.to_file_path().unwrap_or_default();
(
current.component.as_ref().cloned().unwrap_or_else(|| "Default".to_string()),
file.to_string_lossy().to_string(),
file.file_name().unwrap_or_default().to_string_lossy().to_string(),
)
} else {
(String::new(), String::new(), String::new())
}
};
ui.set_preview_area(ui::Preview {
factory,
name: name.into(),
pretty_location: pretty_location.into(),
file: file.into(),
});
ui.set_preview_area(factory);
}
/// Highlight the element pointed at the offset in the path.

View file

@ -6,6 +6,11 @@ use std::{collections::HashMap, iter::once, rc::Rc};
use slint::{Model, SharedString, VecModel};
use slint_interpreter::{DiagnosticLevel, PlatformError};
use crate::common::ComponentInformation;
#[cfg(target_arch = "wasm32")]
use crate::wasm_prelude::*;
slint::include_modules!();
pub fn create_ui(style: String, experimental: bool) -> Result<PreviewUi, PlatformError> {
@ -81,6 +86,19 @@ pub fn convert_diagnostics(diagnostics: &[slint_interpreter::Diagnostic]) -> Vec
.collect::<Vec<_>>()
}
fn extract_definition_location(
ci: &ComponentInformation,
) -> (slint::SharedString, slint::SharedString) {
let Some(url) = ci.defined_at.as_ref().map(|da| &da.url) else {
return (Default::default(), Default::default());
};
let path = url.to_file_path().unwrap_or_default();
let file_name = path.file_name().unwrap_or_default().to_string_lossy().to_string();
(url.to_string().into(), file_name.into())
}
pub fn ui_set_known_components(
ui: &PreviewUi,
known_components: &[crate::common::ComponentInformation],
@ -91,14 +109,11 @@ pub fn ui_set_known_components(
if ci.is_global {
continue;
}
let (url, pretty_location) = extract_definition_location(ci);
map.entry(ci.category.clone()).or_default().push(ComponentItem {
name: ci.name.clone().into(),
defined_at: ci
.defined_at
.as_ref()
.map(|da| da.url.to_string())
.unwrap_or_default()
.into(),
defined_at: url,
pretty_location,
is_user_defined: !(ci.is_builtin || ci.is_std_widget),
is_currently_shown: idx == current_component_index,
});

View file

@ -6,6 +6,7 @@ import { Button, Palette, ScrollView, VerticalBox, GroupBox, LineEdit } from "st
export struct ComponentItem {
name: string,
defined_at: string,
pretty_location: string,
is_user_defined: bool,
is_currently_shown: bool,
}
@ -23,6 +24,15 @@ export component ComponentList {
in property <length> preview-area-width;
in property <length> preview-area-height;
in-out property <ComponentItem> visible-component: empty-component-item;
private property <ComponentItem> empty-component-item: {
name: "",
defined_at: "",
is_user_defined: false,
is_currently_shown: false,
};
private property <length> list-spacing: 6px;
out property <bool> over-target;
@ -77,13 +87,22 @@ export component ComponentList {
drop-x >= 0 && drop-x <= root.preview-area-width && drop-y >= 0 && drop-y <= root.preview-area-height;
private property <bool> can-drop-here: !self.data.is-currently-shown && root.can-drop(self.data.name, drop-x, drop-y, on-drop-area);
private property <ComponentItem> data: ci;
private property <int> my-index: index;
private property <int> my-index: index;
enabled: root.preview-visible;
width: 100%;
private property <bool> edit-me: self.data.is-user-defined && root.editing-in-category == category.my-category-index && category.editing-component-index == self.my-index;
// Hack to initialize currently visible component:
if ci.is_currently_shown: Rectangle {
visible: false;
init() => {
root.visible-component = ci;
}
}
VerticalLayout {
if component.edit-me: LineEdit {
horizontal-alignment: center;

View file

@ -3,8 +3,9 @@
// cSpell: ignore resizer
import { Button, ComboBox, HorizontalBox, ListView, ScrollView, Palette, VerticalBox } from "std-widgets.slint";
import { Button, ComboBox, HorizontalBox, LineEdit, ListView, ScrollView, Palette, VerticalBox } from "std-widgets.slint";
import { Diagnostics, DiagnosticsOverlay } from "diagnostics-overlay.slint";
import { ComponentItem } from "component-list.slint";
import { Resizer } from "resizer.slint";
export enum LayoutKind {
@ -42,13 +43,6 @@ export struct DropMark {
y2: length,
}
export struct Preview {
factory: component-factory,
name: string,
pretty-location: string,
file: string,
}
component SelectionFrame {
in property <Selection> selection;
in property <bool> interactive: true;
@ -177,8 +171,9 @@ export enum DrawAreaMode {
export component DrawArea {
in property <[Diagnostics]> diagnostics;
in property <[Selection]> selections;
in property <ComponentItem> visible-component;
in property <DropMark> drop-mark;
in property <Preview> preview-area;
in property <component-factory> preview-area;
in property <bool> design-mode;
out property <bool> preview-visible: preview-area-container.has-component && !diagnostics.diagnostics-open;
@ -253,7 +248,7 @@ export component DrawArea {
// is called every time the condition is dirty, to make sure that the size
// is within the bounds.
// Query the preview-area to make sure this is evaluated when it changes
if preview-area-container.has-component && root.preview-area.factory == preview-area-container.component-factory: Rectangle {
if preview-area-container.has-component && root.preview-area == preview-area-container.component-factory: Rectangle {
init => {
preview-area-container.width = clamp(preview-area-container.width, max(preview-area-container.min-width, 16px), max(preview-area-container.max-width, 16px));
preview-area-container.height = clamp(preview-area-container.height, max(preview-area-container.min-height, 16px), max(preview-area-container.max-height, 16px));
@ -263,7 +258,7 @@ export component DrawArea {
preview-area-container := ComponentContainer {
property <bool> is-resizable: (self.min-width != self.max-width && self.min-height != self.max-height) && self.has-component;
component-factory: root.preview-area.factory;
component-factory: root.preview-area;
// The width and the height can't depend on the layout info of the inner item otherwise this would
// cause a recursion if this happens (#3989)
@ -335,6 +330,8 @@ export component DrawArea {
}
component-label := Rectangle {
visible: root.visible-component.is_currently_shown;
property <length> offset: 10px;
width: self.min-width;
height: self.min-height;
@ -352,7 +349,7 @@ export component DrawArea {
font-size: 1.2rem;
font-weight: 700;
horizontal-alignment: left;
text: root.preview-area.name;
text: root.visible-component.name;
width: 100%;
}
HorizontalLayout {
@ -362,10 +359,10 @@ export component DrawArea {
Text {
font-size: 0.8rem;
horizontal-alignment: left;
text: root.preview-area.pretty-location;
text: root.visible-component.defined_at;
}
clicked() => {
root.show-component(root.preview-area.name, root.preview-area.file);
root.show-component(root.visible-component.name, root.visible-component.defined-at);
}
}
}

View file

@ -4,8 +4,8 @@
// cSpell: ignore Heade
import { Button, ComboBox, ListView, ScrollView, VerticalBox } from "std-widgets.slint";
import { ComponentList, ComponentListItem } from "component-list.slint";
import { DrawArea, DrawAreaMode, DropMark, LayoutKind, Preview, Selection } from "draw-area.slint";
import { ComponentItem, ComponentList, ComponentListItem } from "component-list.slint";
import { DrawArea, DrawAreaMode, DropMark, LayoutKind, Selection } from "draw-area.slint";
import { HeaderBar } from "header-bar.slint";
import { Diagnostics, DiagnosticsOverlay } from "diagnostics-overlay.slint";
@ -13,13 +13,14 @@ export { Diagnostics, DropMark, LayoutKind }
export component PreviewUi inherits Window {
in property <[ComponentListItem]> known-components;
in-out property <ComponentItem> visible-component;
in property <[Diagnostics]> diagnostics;
in property <[Selection]> selections;
in-out property <DropMark> drop-mark;
in property <[string]> known-styles;
in property <bool> experimental: false;
in property <bool> show-preview-ui: true;
in property <Preview> preview-area;
in property <component-factory> preview-area;
in property <string> status-text;
in-out property <string> current-style;
in property <bool> can-navigate-back: false;
@ -57,7 +58,7 @@ export component PreviewUi inherits Window {
if (!show-preview-ui): no-ui-drawing-rect := Rectangle {
VerticalLayout {
ComponentContainer {
component-factory: root.preview-area.factory;
component-factory: root.preview-area;
}
}
@ -126,6 +127,7 @@ export component PreviewUi inherits Window {
VerticalBox {
ComponentList {
known-components <=> root.known-components;
visible-component <=> root.visible-component;
preview-area-position-x: draw-area.preview-area-position-x;
preview-area-position-y: draw-area.preview-area-position-y;
preview-area-width: draw-area.preview-area-width;
@ -165,6 +167,7 @@ export component PreviewUi inherits Window {
preview-area <=> root.preview-area;
selections <=> root.selections;
drop-mark <=> root.drop-mark;
visible-component <=> root.visible-component;
select-at(x, y, enter_component) => {
root.select-at(x, y, enter_component);