// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 // 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 { HeaderBar } from "header-bar.slint"; import { Diagnostics, DiagnosticsOverlay } from "diagnostics-overlay.slint"; export { Diagnostics, DropMark, LayoutKind } export component PreviewUi inherits Window { in property <[ComponentListItem]> known-components; in property <[Diagnostics]> diagnostics; in property <[Selection]> selections; in-out property drop-mark; in property <[string]> known-styles; in property experimental: false; in property show-preview-ui: true; in property preview-area; in property status-text; in-out property current-style; out property design-mode; callback add_new_component(); pure callback can-drop(/* component_type */ string, /* x */ length, /* y */ length, /* on-drop-area */ bool) -> bool; callback drop(/* component_type */ string, /* x */ length, /* y */ length); callback rename_component(string/* old_name */, string/* defined_at */, string/* new_name */); callback reselect(); callback select-at(/* x */ length, /* y */ length, /* enter_component? */ bool); callback select-behind(/* x */ length, /* y */ length, /* enter_component* */ bool, /* reverse */ bool); callback selected-element-can-move-to(/* x */ length, /* y */ length, /* mouse-x */ length, /* mouse-y */ length) -> bool; callback selected-element-delete(); callback selected-element-move(/* x */ length, /* y */ length, /* mouse-x */ length, /* mouse-y */ length); callback selected-element-resize(/* x */ length, /* y */ length, /* width */ length, /* height */ length); // Show the component `name` found in `file` in the editor callback show-component(/* name */ string, /* file */ string); // Show a position consisiting of `line` and `column` in a `file` in the editor callback show-document(/* file */ string, /* line */ int, /* column */ int); callback show_preview_for(string/* name */, string/*url*/); callback style-changed(); callback unselect(); property border: 20px; property side-bar-width: 200px; title: "Slint Live-Preview"; icon: @image-url("assets/slint-logo-small-light.png"); VerticalLayout { if (!show-preview-ui): no-ui-drawing-rect := Rectangle { VerticalLayout { ComponentContainer { component-factory: root.preview-area.factory; } } // Diagnostics overlay: DiagnosticsOverlay { width: 100%; height: 100%; diagnostics <=> root.diagnostics; show-document(url, line, column) => { root.show-document(url, line, column); } } } if (show-preview-ui): Rectangle { VerticalLayout { HeaderBar { vertical-stretch: 0.0; height: self.preferred-height; pick-button := Button { text: @tr("Design Mode"); checkable: true; checked <=> root.design-mode; clicked() => { key-handler.focus(); } } Text { text: @tr("Style:"); vertical-alignment: center; } style-select := ComboBox { model: root.known-styles; current-value <=> current-style; selected(value) => { root.style-changed(); } } Text { text: root.status-text; vertical-alignment: center; } } HorizontalLayout { left-sidebar := Rectangle { VerticalBox { ComponentList { known-components <=> root.known-components; 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; preview-area-height: draw-area.preview-area-height; can-drop(c, x, y, oda) => { return root.can-drop(c, x, y, oda); } drop(c, x, y) => { root.drop(c, x, y); } add_new_component => { return root.add_new_component(); } rename_component(on, op, nn) => { return root.rename_component(on, op, nn); } show_preview_for(cn, cp) => { return root.show_preview_for(cn, cp); } } } states [ visible when !pick-button.checked: { width: 0px; } hidden when pick-button.checked: { width: root.side-bar-width; } ] } draw-area := DrawArea { design-mode <=> root.design-mode; diagnostics <=> root.diagnostics; preview-area <=> root.preview-area; selections <=> root.selections; drop-mark <=> root.drop-mark; select-at(x, y, enter_component) => { root.select-at(x, y, enter_component); } selected-element-resize(x, y, w, h) => { root.selected-element-resize(x, y, w, h); } selected-element-can-move-to(x, y, mx, my) => { root.selected-element-can-move-to(x, y, mx, my); } selected-element-move(x, y, mx, my) => { root.selected-element-move(x, y, mx, my); } selected-element-delete() => { root.selected-element-delete(); } select-behind(x, y, stay_in_file, reverse) => { root.select-behind(x, y, stay_in_file, reverse); } show-component(name, file) => { root.show-component(name, file); } show-document(url, line, column) => { root.show-document(url, line, column); } unselect() => { root.unselect(); } reselect() => { root.reselect(); } } preferred-width: draw-area.preferred-width + root.side-bar-width/* for left-side-bar */; } } key-handler := FocusScope { enabled: draw-area.mode == DrawAreaMode.designing; key-released(event) => { if event.text == Key.Delete { // This `if` should not be necessary, but without it // we do trigger deletion of Elements while errors // are on screen. if draw-area.mode == DrawAreaMode.designing { root.selected-element-delete(); } return accept; } reject } } } } }