slint/tools/lsp/ui/api.slint
Tobias Hunger 9d5b9fb46a live-preview: Implement a selection stack
... that provides a model containing all the elements
at a position sorted from "front" to "back" with extra
information so that we can present the data in a nice UI
in the next step.

The selection code now filters out builtins and ignore nodes
when collecting nodes. So the following filter step does not
need to take those into account anymore.

Whether a selection candidate is actually a part of the root
component or not is now handled by looking at whether the
elements text range is inside the root component's text
range. This is closer to what users expect to happen I think.
2024-11-19 20:20:14 +01:00

440 lines
13 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
/// Basic information on a known component
export struct ComponentItem {
name: string,
index: int,
defined-at: string,
pretty-location: string,
is-user-defined: bool,
is-currently-shown: bool,
is-exported: bool,
}
/// A `category` with a lost of `ComponentItem`s that belong into it.
///
/// Fiel url is either an empty string or a URL to some document
export struct ComponentListItem {
category: string,
file_url: string,
components: [ComponentItem]
}
/// Some `Diagnostics` as raised by the compiler
export struct Diagnostics {
level: string,
message: string,
url: string,
line: int,
column: int,
}
/// What kind of layout we are working with
export enum LayoutKind {
None,
Horizontal,
Vertical,
Grid,
}
/// A rectangular region that is selected
struct SelectionRectangle {
x: length,
y: length,
width: length,
height: length,
}
/// A `Selection`
export struct Selection {
geometry: SelectionRectangle,
layout-data: LayoutKind,
is-interactive: bool,
is-primary: bool,
is-moveable: bool,
is-resizable: bool,
}
/// A mark showing where an element will show up when dropped into the current location
export struct DropMark {
x1: length,
y1: length,
x2: length,
y2: length,
}
export struct SelectionStackFrame {
width: percent,
height: percent,
x: percent,
y: percent,
is-in-root-component: bool,
is-layout: bool,
is-interactive: bool,
is-selected: bool,
type-name: string,
file-name: string,
element-path: string,
element-offset: int,
id: string,
}
/// A Range in a source
export struct Range {
start: int,
end: int,
}
export struct ColorData {
r: int,
g: int,
b: int,
a: int,
text: string,
}
export enum PropertyValueKind {
boolean,
brush,
code,
color,
enum,
float,
integer,
string,
}
/// Data about the property value for use in "simple" mode
export struct PropertyValue {
value-bool: bool, // boolean
is-translatable: bool, // string
kind: PropertyValueKind,
value-brush: brush, // brush, color
value-float: float, // float
value-int: int, // integer, enum/float (current index into visual_items)
default-selection: int, // enum/float (default index into visual_items)
value-string: string, // enum (name), string, brush (color value)
visual-items: [string], // enum (enum members), float (units)
tr-context: string, // string
tr-plural: string, // string
tr-plural-expression: string, // string
code: string, // ALWAYS, empty if property is not explicitly defined
}
/// Important Ranges in the property definition
///
/// The URL and version is the same as in the Element it belongs to
export struct PropertyDefinition {
definition-range: Range,
selection-range: Range,
expression-range: Range,
expression-value: string,
}
/// The Property Declaration
export struct PropertyDeclaration {
defined-at: PropertyDefinition,
source-path: string,
source-version: int,
range: Range,
}
/// Information on one Property
export struct PropertyInformation {
name: string,
type-name: string,
value: PropertyValue,
display-priority: int,
}
/// Information on one Property
export struct PropertyGroup {
group-name: string,
properties: [PropertyInformation],
}
/// Information on an Element a Property belongs to
export struct ElementInformation {
id: string,
type-name: string,
source-uri: string,
source-version: int,
range: Range,
}
export global Api {
// # Properties
// ## General preview state:
// experimental features are available
in property <bool> experimental: false;
// enable editing mode
in property <bool> show-preview-ui: true;
// std-widgets are used (=> show style dropdown)
in-out property <bool> uses-widgets;
// ## Component Data for ComponentList:
// All the components
in property <[ComponentListItem]> known-components;
// The component currently viewed
out property <ComponentItem> visible-component;
// ## Diagnostics and other Status messages
// Compiler diagnostics
in property <[Diagnostics]> diagnostics;
// status message text
in property <string> status-text;
// ## Style:
// All the known styles
in property <[string]> known-styles;
// The current style
in-out property <string> current-style;
// control, but command on macOS
in-out property <string> control-key-name: "control";
// ## Drawing Area
// Borders around things
in property <[Selection]> selections;
in-out property <DropMark> drop-mark;
// The actual preview
in property <component-factory> preview-area;
// set to true to resize
in property <bool> resize-to-preferred-size: false;
// ## Property Editor
in-out property <ElementInformation> current-element;
in-out property <[PropertyGroup]> properties: [
{
group-name: "Geometry",
properties: [
{
name: "width",
type-name: "length",
value: {
kind: PropertyValueKind.float,
value-float: 100,
visual-items: ["px", "cm", "mm", "in", "pt", "phx"],
}
},
{
name: "height",
type-name: "length",
value: {
kind: PropertyValueKind.float,
value-float: 200,
visual-items: ["px", "cm", "mm", "in", "pt", "phx"],
}
},
{
name: "z",
type-name: "float",
value: {
kind: PropertyValueKind.float,
value-float: 10,
}
},
{
name: "combobox",
type-name: "string",
value: {
kind: PropertyValueKind.enum,
value-int: 1,
default-selection: 0,
visual-items: ["one", "twenty two", "one hundred", "infinite"],
}
},
]
},
{
group-name: "Button",
properties: [
{
name: "text",
type-name: "string",
value: {
is-translatable: true,
kind: PropertyValueKind.string,
}
},
{
name: "checkable",
type-name: "bool",
value: {
kind: PropertyValueKind.boolean,
}
},
{
name: "icon",
type-name: "image",
value: {
kind: PropertyValueKind.code,
}
},
{
name: "color",
type-name: "brush",
value: {
kind: PropertyValueKind.brush,
value-brush: Colors.green,
value-string: "#00ff00"
},
},
{
name: "a-really-long-named-attribute",
type-name: "float",
value: {
kind: PropertyValueKind.float,
value-float: 10,
}
},
{
name: "bar",
type-name: "float",
value: {
kind: PropertyValueKind.code,
value-float: 10.5,
code: 10/2,
}
},
{
name: "baz",
type-name: "float",
value: {
kind: PropertyValueKind.code,
value-float: 10.5,
code: "",
}
}
]
}, {
group-name: "Other",
properties: [
{
name: "text",
type-name: "string",
value: {
is-translatable: true,
kind: PropertyValueKind.string,
}
},
{
name: "checkable",
type-name: "bool",
value: {
kind: PropertyValueKind.boolean,
}
},
{
name: "icon",
type-name: "image",
value: {
kind: PropertyValueKind.code,
}
},
{
name: "color",
type-name: "brush",
value: {
kind: PropertyValueKind.brush,
value-brush: Colors.magenta,
value-string: "#ff00ff"
},
},
{
name: "a-really-long-named-attribute",
type-name: "float",
value: {
kind: PropertyValueKind.float,
value-float: 10,
}
},
{
name: "bar",
type-name: "float",
value: {
kind: PropertyValueKind.code,
value-float: 10.5,
code: 10/2,
}
},
{
name: "baz",
type-name: "float",
value: {
kind: PropertyValueKind.code,
value-float: 10.5,
code: "",
}
}
]
}
];
// # Callbacks
// ## Custom conversion functions:
pure callback string-is-color(string) -> bool;
pure callback string-to-color(string) -> color;
pure callback color-to-data(color) -> ColorData;
pure callback rgba_to_color(r: int, g: int, b: int, a: int) -> color;
// ## Style:
callback style-changed();
// ## Component life-cycle:
// Create a new componnet
callback add-new-component();
// Add an existing component
pure callback can-drop(component-index: int, x: length, y: length, on-drop-area: bool) -> bool;
callback drop(component-index: int, x: length, y: length);
callback rename-component(old-name: string, defined-at: string, new-name: string);
callback selected-element-can-move-to(x: length, y: length, mouse-x: length, mouse-y: length) -> bool;
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);
callback selected-element-delete();
// ## Element selection:
callback selection-stack-at(x: length, y: length) -> [SelectionStackFrame];
callback select-element(file: string, offset: int, x: length, y: length);
callback select-at(x: length, y: length, enter-component: bool);
callback select-behind(x: length, y: length, enter-component: bool, reverse: bool);
callback reselect();
callback unselect();
// ## Change Editor:
// Show a conponent in the editor
callback show-component(name: string, url: string);
// Show a position consisting of `line` and `column` in a `file` in the editor
callback show-document(file: string, line: int, column: int);
// Show a position consisting of `line` and `column` in a `file` in the editor
callback show-document-offset-range(url: string, start_offset: int, end_offset: int, take-focus: bool);
// ## Drawing Area
// Preview some other component
callback show-preview-for(name: string, url: string);
callback reload-preview();
// ## Property Editor
pure callback test-code-binding(element-url: string, element-version: int, element-offset: int, property-name: string, property-value: string) -> bool;
pure callback test-string-binding(element-url: string, element-version: int, element-offset: int, property-name: string, value: string, is_translatable: bool, tr_context: string, tr_plural: string, tr_plural_expression: string) -> bool;
callback set-code-binding(element-url: string, element-version: int, element-offset: int, property-name: string, property-value: string);
callback set-color-binding(element-url: string, element-version: int, element-offset: int, property-name: string, property-value: color);
callback set-string-binding(element-url: string, element-version: int, element-offset: int, property-name: string, value: string, is_translatable: bool, tr_context: string, tr_plural: string, tr_plural_exprression: string);
// Get the property declaration/definition ranges
callback property-declaration-ranges(property-name: string) -> PropertyDeclaration;
}