mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-19 14:57:22 +00:00

Some checks are pending
autofix.ci / format_fix (push) Waiting to run
autofix.ci / lint_typecheck (push) Waiting to run
CI / files-changed (push) Waiting to run
CI / build_and_test (--exclude bevy-example, ubuntu-22.04, 1.85) (push) Blocked by required conditions
CI / cpp_cmake (ubuntu-22.04, stable) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, macos-14, stable) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, windows-2022, beta) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, windows-2022, stable) (push) Blocked by required conditions
CI / cpp_test_driver (windows-2022) (push) Blocked by required conditions
CI / cpp_cmake (macos-14, 1.85) (push) Blocked by required conditions
CI / cpp_cmake (windows-2022, nightly) (push) Blocked by required conditions
CI / mcu (stm32h735g, thumbv7em-none-eabihf) (push) Blocked by required conditions
CI / mcu-embassy (push) Blocked by required conditions
CI / ffi_32bit_build (push) Blocked by required conditions
CI / python_test (windows-2022) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, --exclude bevy-example, windows-2022, 1.85) (push) Blocked by required conditions
CI / build_and_test (ubuntu-22.04, nightly-2025-08-15) (push) Blocked by required conditions
CI / node_test (macos-14) (push) Blocked by required conditions
CI / node_test (ubuntu-22.04) (push) Blocked by required conditions
CI / node_test (windows-2022) (push) Blocked by required conditions
CI / python_test (macos-14) (push) Blocked by required conditions
CI / python_test (ubuntu-22.04) (push) Blocked by required conditions
CI / cpp_test_driver (macos-13) (push) Blocked by required conditions
CI / cpp_test_driver (ubuntu-22.04) (push) Blocked by required conditions
CI / cpp_package_test (push) Blocked by required conditions
CI / vsce_build_test (push) Blocked by required conditions
CI / mcu (pico-st7789, thumbv6m-none-eabi) (push) Blocked by required conditions
CI / mcu (pico2-st7789, thumbv8m.main-none-eabihf) (push) Blocked by required conditions
CI / docs (push) Blocked by required conditions
CI / wasm (push) Blocked by required conditions
CI / tree-sitter (push) Blocked by required conditions
CI / updater_test (0.3.0) (push) Blocked by required conditions
CI / fmt_test (push) Blocked by required conditions
CI / esp-idf-quick (push) Blocked by required conditions
CI / android (push) Blocked by required conditions
CI / miri (push) Blocked by required conditions
CI / test-figma-inspector (push) Blocked by required conditions
CI / wasm_demo (push) Blocked by required conditions
384 lines
14 KiB
Text
384 lines
14 KiB
Text
// 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
|
|
|
|
// cSpell: ignore Heade
|
|
|
|
import { Button, TabWidget, Palette, Switch, ScrollView} from "std-widgets.slint";
|
|
import { Api, ComponentItem, DiagnosticSummary } from "api.slint";
|
|
|
|
import { EditorSizeSettings, EditorSpaceSettings, Icons, PickerStyles, ConsoleStyles } from "./components/styling.slint";
|
|
import { StatusLine } from "./components/status-line.slint";
|
|
import { HeaderView } from "./views/header-view.slint";
|
|
import { LibraryView } from "./views/library-view.slint";
|
|
import { DrawAreaMode, PreviewView } from "./views/preview-view.slint";
|
|
import { OutOfDateBox } from "./components/out-of-date-box.slint";
|
|
import { PropertyView } from "./views/property-view.slint";
|
|
import { OutlineView } from "./views/outline-view.slint";
|
|
import { PreviewDataView } from "./views/preview-data-view.slint";
|
|
import { WindowGlobal, WindowManager } from "windowglobal.slint";
|
|
import { ColorPickerView } from "components/widgets/floating-brush-picker-widget.slint";
|
|
import { TableEditorView } from "components/spreadsheet-dialog.slint";
|
|
import "./assets/Inter-VariableFont.ttf";
|
|
import "./assets/SourceCodePro-Medium.ttf";
|
|
import { ConsolePanel } from "components/console-panel.slint";
|
|
|
|
export { Api }
|
|
|
|
export component PreviewUi inherits Window {
|
|
property <length> border: 20px;
|
|
property <ComponentItem> visible-component: {
|
|
name: "",
|
|
defined-at: "",
|
|
pretty-location: "",
|
|
is-user-defined: false,
|
|
is-currently-shown: false,
|
|
};
|
|
property <bool> show-left-sidebar;
|
|
property <bool> show-right-sidebar;
|
|
property <bool> show-floating-widget <=> WindowManager.showing-color-picker;
|
|
property <bool> show-floating-table-editor <=> WindowManager.showing-table-editor;
|
|
property <bool> show-color-stop-picker <=> WindowManager.showing-color-stop-picker;
|
|
property <length> initial-floating-x;
|
|
property <bool> console-panel-expanded: false;
|
|
property <bool> properties-widget: false;
|
|
property <bool> data-widget: false;
|
|
property <bool> outline-widget: false;
|
|
property <bool> library-widget: false;
|
|
in-out property <bool> select-mode: false;
|
|
|
|
title: @tr("Slint Live-Preview");
|
|
icon: @image-url("assets/slint-logo-small-light.png");
|
|
always-on-top <=> Api.always-on-top;
|
|
init => {
|
|
WindowGlobal.window-width = self.width;
|
|
WindowGlobal.window-height = self.height;
|
|
initial-floating-x = (self.width - PickerStyles.picker-width - 350px).max(0);
|
|
}
|
|
changed width => {
|
|
WindowGlobal.window-width = self.width;
|
|
initial-floating-x = (self.width - PickerStyles.picker-width - 350px).max(0);
|
|
}
|
|
changed height => {
|
|
WindowGlobal.window-height = self.height;
|
|
}
|
|
|
|
if Api.show-preview-ui : MenuBar {
|
|
Menu {
|
|
title: @tr("File");
|
|
|
|
if Api.runs-in-slintpad: Menu {
|
|
title: @tr("Open Demo");
|
|
for demo in Api.demos: MenuItem {
|
|
title: demo.title;
|
|
activated => {
|
|
Api.load-demo(demo.url);
|
|
}
|
|
}
|
|
}
|
|
|
|
MenuSeparator { }
|
|
|
|
MenuItem {
|
|
title: @tr("Reload");
|
|
activated => {
|
|
Api.reload-preview();
|
|
}
|
|
}
|
|
|
|
if Api.runs-in-slintpad: Menu {
|
|
title: @tr("Share");
|
|
|
|
MenuItem {
|
|
title: @tr("Copy Permalink to Clipboard");
|
|
activated => {
|
|
Api.share-permalink-to-clipboard();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Menu {
|
|
title: @tr("Edit");
|
|
MenuItem {
|
|
title: @tr("Undo");
|
|
enabled: Api.undo-enabled;
|
|
activated => {
|
|
Api.undo();
|
|
}
|
|
}
|
|
|
|
MenuItem {
|
|
title: @tr("Redo");
|
|
enabled: Api.redo-enabled;
|
|
activated => {
|
|
Api.redo();
|
|
}
|
|
}
|
|
}
|
|
|
|
Menu {
|
|
title: @tr("View");
|
|
|
|
MenuItem {
|
|
title: @tr("Library");
|
|
checkable: true;
|
|
checked <=> root.library-widget;
|
|
}
|
|
|
|
MenuItem {
|
|
title: @tr("Properties");
|
|
checkable: true;
|
|
checked <=> root.properties-widget;
|
|
}
|
|
|
|
MenuItem {
|
|
title: @tr("Outline");
|
|
checkable: true;
|
|
checked <=> root.outline-widget;
|
|
}
|
|
|
|
MenuItem {
|
|
title: @tr("Simulation Data");
|
|
checkable: true;
|
|
checked <=> root.data-widget;
|
|
}
|
|
|
|
MenuItem {
|
|
title: @tr("Console");
|
|
checkable: true;
|
|
checked <=> root.console-panel-expanded;
|
|
}
|
|
}
|
|
if !Api.runs-in-slintpad: Menu {
|
|
title: @tr("Window");
|
|
MenuItem {
|
|
title: @tr("Keep on Top");
|
|
checkable: true;
|
|
checked <=> Api.always-on-top;
|
|
}
|
|
}
|
|
|
|
if Api.runs-in-slintpad: Menu {
|
|
title: @tr("Help");
|
|
MenuItem {
|
|
title: @tr("About");
|
|
activated => {
|
|
Api.show-about-slint();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ap := VerticalLayout {
|
|
if !Api.show-preview-ui: no-ui-drawing-rect := Rectangle {
|
|
VerticalLayout {
|
|
ComponentContainer {
|
|
component-factory: Api.preview-area;
|
|
}
|
|
}
|
|
}
|
|
if Api.show-preview-ui: FocusScope {
|
|
key-pressed(event) => {
|
|
if Api.undo-enabled && event.modifiers.control && event.text == "z" {
|
|
Api.undo();
|
|
return accept;
|
|
} else if Api.redo-enabled && event.modifiers.control &&
|
|
((Platform.os != OperatingSystemType.windows && event.text == "Z") || (Platform.os == OperatingSystemType.windows && event.text == "y")) {
|
|
Api.redo();
|
|
return accept;
|
|
}
|
|
reject
|
|
}
|
|
|
|
VerticalLayout {
|
|
header-view := HeaderView {
|
|
vertical-stretch: 0;
|
|
height: self.preferred-height;
|
|
|
|
current-style <=> Api.current-style;
|
|
known-styles <=> Api.known-styles;
|
|
library-widget <=> root.library-widget;
|
|
properties-widget <=> root.properties-widget;
|
|
outline-widget <=> root.outline-widget;
|
|
data-widget <=> root.data-widget;
|
|
|
|
style-selected => {
|
|
Api.style-changed();
|
|
}
|
|
library-toggled(val) => {
|
|
root.library-widget = val;
|
|
}
|
|
outline-toggled(val) => {
|
|
root.outline-widget = val;
|
|
}
|
|
properties-toggled(val) => {
|
|
root.properties-widget = val;
|
|
}
|
|
simulator-toggled(val) => {
|
|
root.data-widget = val;
|
|
}
|
|
edit := Button {
|
|
icon: Icons.inspect;
|
|
colorize-icon: preview.select-mode ? false : true;
|
|
checkable: true;
|
|
checked <=> preview.select-mode;
|
|
primary: preview.select-mode;
|
|
enabled: preview.preview-is-current;
|
|
}
|
|
}
|
|
|
|
HorizontalLayout {
|
|
spacing: 0px;
|
|
|
|
if root.library-widget: LibraryView {
|
|
known-components: Api.known-components;
|
|
library-visible <=> root.library-widget;
|
|
|
|
preview-area-is-current: preview.preview-is-current;
|
|
visible-component: root.visible-component;
|
|
|
|
show-preview-for(name, defined-at) => {
|
|
Api.show-preview-for(name, defined-at);
|
|
}
|
|
}
|
|
|
|
preview := PreviewView {
|
|
visible-component <=> root.visible-component;
|
|
}
|
|
|
|
if properties-widget || outline-widget || data-widget : right-panel := Rectangle {
|
|
width: EditorSizeSettings.property-bar-width + right-panel-border.width;
|
|
|
|
right-panel-border := Rectangle {
|
|
x: 0px;
|
|
width: 2px;
|
|
background: Palette.border;
|
|
}
|
|
|
|
property <float> ratio1: 0.5;
|
|
property <float> ratio2: 0.5;
|
|
|
|
property <int> widget-count: (properties-widget ? 1 : 0) + (outline-widget ? 1 : 0) + (data-widget ? 1 : 0);
|
|
property <length> splitter-height: 3px;
|
|
property <length> usable-height: self.height - (widget-count - 1) * splitter-height;
|
|
property <float> min-ratio: 3 * ConsoleStyles.header-height / usable-height;
|
|
property <float> effective-ratio1: ratio1.max(min-ratio).min(1 - (widget-count - 1) * min-ratio).max(0);
|
|
property <float> effective-ratio2: ratio2.max(min-ratio).min(1 - (properties-widget ? effective-ratio1 : 0) - min-ratio).max(0);
|
|
|
|
if properties-widget: PropertyView {
|
|
y: 0;
|
|
height: widget-count > 1 ? usable-height * effective-ratio1 : parent.height;
|
|
x: right-panel-border.width;
|
|
width: EditorSizeSettings.property-bar-width;
|
|
opacity: preview.preview-is-current ? 1.0 : 0.3;
|
|
enabled: preview.preview-is-current;
|
|
properties-visible <=> root.properties-widget;
|
|
}
|
|
|
|
if properties-widget && widget-count > 1: TouchArea {
|
|
y: usable-height * effective-ratio1;
|
|
height: splitter-height;
|
|
x: right-panel-border.width;
|
|
width: EditorSizeSettings.property-bar-width;
|
|
|
|
moved => {
|
|
ratio1 = Math.clamp((self.y + self.mouse-y - self.pressed-y) / usable-height, 0, 1);
|
|
}
|
|
mouse-cursor: ns-resize;
|
|
Rectangle {
|
|
background: Palette.border;
|
|
}
|
|
}
|
|
|
|
if outline-widget: OutlineView {
|
|
y: properties-widget ? usable-height * effective-ratio1 + splitter-height : 0;
|
|
height: usable-height * (1 - (properties-widget ? effective-ratio1 : 0) - (data-widget ? effective-ratio2 : 0));
|
|
x: right-panel-border.width;
|
|
width: EditorSizeSettings.property-bar-width;
|
|
opacity: preview.preview-is-current ? 1.0 : 0.3;
|
|
enabled: preview.preview-is-current;
|
|
outline <=> root.outline-widget;
|
|
}
|
|
|
|
if data-widget && outline-widget: TouchArea {
|
|
y: parent.height - self.height - usable-height * effective-ratio2;
|
|
height: splitter-height;
|
|
x: right-panel-border.width;
|
|
width: EditorSizeSettings.property-bar-width;
|
|
moved => {
|
|
ratio2 = 1 - Math.clamp((self.y + self.mouse-y - self.pressed-y) / usable-height, 0, 1);
|
|
}
|
|
mouse-cursor: ns-resize;
|
|
Rectangle {
|
|
background: Palette.border;
|
|
}
|
|
}
|
|
|
|
if data-widget: PreviewDataView {
|
|
y: parent.height - self.height;
|
|
height: usable-height * (outline-widget ? effective-ratio2 : properties-widget ? (1 - effective-ratio1) : 1);
|
|
x: right-panel-border.width;
|
|
width: EditorSizeSettings.property-bar-width;
|
|
|
|
data-visible <=> root.data-widget;
|
|
opacity: preview.preview-is-current ? 1.0 : 0.3;
|
|
enabled: preview.preview-is-current;
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
height: cp.height;
|
|
}
|
|
|
|
// StatusLine { }
|
|
}
|
|
cp := ConsolePanel {
|
|
y: parent.height - self.height - 1px;
|
|
width: parent.width;
|
|
panel-expanded <=> root.console-panel-expanded;
|
|
}
|
|
}
|
|
}
|
|
|
|
if Api.diagnostic-summary == DiagnosticSummary.Errors: OutOfDateBox {
|
|
x: (parent.width - self.width) / 2;
|
|
y: (parent.height / 10);
|
|
}
|
|
|
|
if show-floating-table-editor || show-color-stop-picker || show-floating-widget: TouchArea {
|
|
changed pressed => {
|
|
WindowManager.hide-floating-widget();
|
|
}
|
|
}
|
|
|
|
if show-floating-table-editor: TableEditorView {
|
|
init => {
|
|
self.initial-x = root.initial-floating-x;
|
|
self.initial-y = 50px;
|
|
}
|
|
}
|
|
|
|
if show-floating-widget: ColorPickerView {
|
|
init => {
|
|
self.initial-x = root.initial-floating-x;
|
|
self.initial-y = 50px;
|
|
}
|
|
close => {
|
|
WindowManager.hide-floating-color-widget();
|
|
}
|
|
}
|
|
|
|
if show-color-stop-picker: ColorPickerView {
|
|
|
|
color-stop-mode: true;
|
|
|
|
init => {
|
|
self.initial-x = root.initial-floating-x - 240px;
|
|
self.initial-y = 50px;
|
|
}
|
|
close => {
|
|
WindowManager.hide-color-stop-picker();
|
|
}
|
|
}
|
|
}
|