mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-19 23:07:21 +00:00
517 lines
18 KiB
Text
517 lines
18 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
|
|
|
|
import { Palette } from "std-widgets.slint";
|
|
import { Api, BrushKind, ElementInformation, GradientStop, PreviewData, PreviewDataKind, PropertyContainer, PropertyInformation, PropertyValue, PropertyValueKind } from "../api.slint";
|
|
import { StatusLineApi } from "../components/status-line.slint";
|
|
import { EditorSpaceSettings } from "../components/styling.slint";
|
|
|
|
import { BooleanWidget } from "./widgets/boolean-widget.slint";
|
|
import { ConsoleStyles } from "./styling.slint";
|
|
import { CodeWidget } from "./widgets/code-widget.slint";
|
|
import { EnumWidget } from "./widgets/enum-widget.slint";
|
|
import { FloatWidget } from "./widgets/float-widget.slint";
|
|
import { IntegerWidget } from "./widgets/integer-widget.slint";
|
|
import { JsonWidget } from "./widgets/json-widget.slint";
|
|
import { MultiValueWidget } from "./widgets/multi-value-widget.slint";
|
|
import { StringWidget } from "./widgets/string-widget.slint";
|
|
import { BrushPropertyType, WindowGlobal, WindowManager } from "../windowglobal.slint";
|
|
import { InlineBrushWidget } from "widgets/inline-brush-widget.slint";
|
|
import { NameLabel, ResettingLineEdit } from "widgets/basics.slint";
|
|
|
|
export component PropertyValueWidget inherits VerticalLayout {
|
|
in-out property <PropertyValue> property-value;
|
|
in property <PreviewData> preview-data;
|
|
in property <string> property-name;
|
|
in property <bool> enabled;
|
|
in property <bool> has-code-action: true;
|
|
in property <bool> has-reset-action: true;
|
|
in property <bool> strings-are-translatable: true;
|
|
in property <string> property-container-id;
|
|
|
|
callback update-display-string(value: string);
|
|
|
|
callback set-bool-binding(value: bool);
|
|
callback set-color-binding(text: string);
|
|
callback test-color-binding(text: string) -> bool;
|
|
callback set-brush-binding(kind: BrushKind, angle: float, color: color, stops: [GradientStop]);
|
|
callback test-brush-binding(kind: BrushKind, angle: float, color: color, stops: [GradientStop]) -> bool;
|
|
callback set-float-binding(text: string, unit: string);
|
|
callback test-float-binding(text: string, unit: string) -> bool;
|
|
callback set-code-binding(text: string);
|
|
callback test-code-binding(text: string) -> bool;
|
|
callback set-string-binding(text: string, is_translated: bool);
|
|
callback test-string-binding(text: string, is_translated: bool) -> bool;
|
|
callback set-enum-binding(text: string);
|
|
callback set-current-item();
|
|
|
|
callback reset-action();
|
|
callback code-action();
|
|
|
|
function update-display-string-impl(value: string) {
|
|
self.property-value.display-string = value;
|
|
self.update-display-string(value);
|
|
}
|
|
|
|
if root.property-value.kind == PropertyValueKind.boolean: BooleanWidget {
|
|
enabled <=> root.enabled;
|
|
property-value <=> root.property-value;
|
|
|
|
set-bool-binding(value) => {
|
|
root.set-bool-binding(value);
|
|
}
|
|
|
|
update-display-string(value) => {
|
|
root.update-display-string-impl(value);
|
|
}
|
|
}
|
|
|
|
if root.property-value.kind == PropertyValueKind.color || root.property-value.kind == PropertyValueKind.brush: InlineBrushWidget {
|
|
enabled <=> root.enabled;
|
|
property-name <=> root.property-name;
|
|
property-value <=> root.property-value;
|
|
brush-property-type: root.property-value.kind == PropertyValueKind.color ? BrushPropertyType.color : BrushPropertyType.brush;
|
|
preview-data <=> root.preview-data;
|
|
|
|
update-floating-editor() => {
|
|
return root.set-current-item();
|
|
}
|
|
|
|
test-color-binding(text) => {
|
|
return (root.test-color-binding(text));
|
|
}
|
|
set-color-binding(text) => {
|
|
root.set-color-binding(text);
|
|
}
|
|
|
|
test-brush-binding(kind, angle, color, stops) => {
|
|
return root.test-brush-binding(kind, angle, color, stops);
|
|
}
|
|
set-brush-binding(kind, angle, color, stops) => {
|
|
root.set-brush-binding(kind, angle, color, stops);
|
|
}
|
|
|
|
update-display-string(value) => {
|
|
root.update-display-string-impl(value);
|
|
}
|
|
|
|
init => {
|
|
// Floating editors need to know the current property details. Call the update if something changes.
|
|
if WindowManager.showing-color-picker && WindowManager.current-property-information.name == root.property-name {
|
|
self.update-floating-editor();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if root.property-value.kind == PropertyValueKind.code: CodeWidget {
|
|
enabled <=> root.enabled;
|
|
property-value <=> root.property-value;
|
|
|
|
update-display-string(value) => {
|
|
root.update-display-string-impl(value);
|
|
}
|
|
|
|
reset-action() => {
|
|
root.reset-action();
|
|
}
|
|
code-action() => {
|
|
root.code-action();
|
|
}
|
|
}
|
|
|
|
if root.property-value.kind == PropertyValueKind.enum: EnumWidget {
|
|
enabled <=> root.enabled;
|
|
property-value <=> root.property-value;
|
|
|
|
set-enum-binding(text) => {
|
|
root.set-enum-binding(text);
|
|
}
|
|
|
|
update-display-string(value) => {
|
|
root.update-display-string-impl(value);
|
|
}
|
|
}
|
|
|
|
if root.property-value.kind == PropertyValueKind.float: FloatWidget {
|
|
enabled <=> root.enabled;
|
|
property-value <=> root.property-value;
|
|
|
|
test-float-binding(text, unit) => {
|
|
return (root.test-float-binding(text, unit));
|
|
}
|
|
set-float-binding(text, unit) => {
|
|
root.set-float-binding(text, unit);
|
|
}
|
|
|
|
update-display-string(value) => {
|
|
root.update-display-string-impl(value);
|
|
}
|
|
}
|
|
|
|
if root.property-value.kind == PropertyValueKind.integer: IntegerWidget {
|
|
enabled <=> root.enabled;
|
|
property-value <=> root.property-value;
|
|
|
|
test-integer-binding(text) => {
|
|
return (root.test-code-binding(text));
|
|
}
|
|
set-integer-binding(text) => {
|
|
root.set-code-binding(text);
|
|
}
|
|
|
|
update-display-string(value) => {
|
|
root.update-display-string-impl(value);
|
|
}
|
|
}
|
|
|
|
if root.property-value.kind == PropertyValueKind.string: StringWidget {
|
|
enabled <=> root.enabled;
|
|
property-value: root.property-value;
|
|
|
|
has-code-action: root.has-code-action;
|
|
has-reset-action: root.has-reset-action;
|
|
is-translatable <=> root.strings-are-translatable;
|
|
|
|
test-string-binding(text, is_translated) => {
|
|
return root.test-string-binding(text, is_translated);
|
|
}
|
|
set-string-binding(text, is_translated) => {
|
|
root.set-string-binding(text, is_translated);
|
|
}
|
|
|
|
update-display-string(value) => {
|
|
root.update-display-string-impl(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
component IconButton inherits Rectangle {
|
|
in property <image> icon;
|
|
in property <bool> checked: false;
|
|
in property <bool> enabled: true;
|
|
ta := TouchArea {
|
|
clicked => root.clicked();
|
|
mouse-cursor: pointer;
|
|
enabled: root.enabled;
|
|
}
|
|
|
|
callback clicked();
|
|
Image {
|
|
height: 1rem;
|
|
colorize: !enabled ? Palette.foreground.transparentize(0.8) :
|
|
checked ? Palette.accent-background :
|
|
ta.has-hover ? Palette.accent-background.transparentize(0.2) :
|
|
Palette.foreground.transparentize(0.5);
|
|
source: root.icon;
|
|
}
|
|
}
|
|
|
|
|
|
enum PropertyWidgetMode { value, expression, bind }
|
|
|
|
|
|
export component PropertyInformationWidget inherits TouchArea {
|
|
in property <PropertyInformation> property-information;
|
|
in property <ElementInformation> element-information;
|
|
|
|
private property <PropertyValueKind> kind: property-information.value.kind;
|
|
changed kind => {
|
|
if kind == PropertyValueKind.code {
|
|
mode = PropertyWidgetMode.expression;
|
|
} else {
|
|
mode = PropertyWidgetMode.value;
|
|
}
|
|
}
|
|
private property <PropertyWidgetMode> mode: kind == PropertyValueKind.code ? PropertyWidgetMode.expression : PropertyWidgetMode.value;
|
|
|
|
function code-action() {
|
|
Api.show-document-offset-range(
|
|
element-information.source-uri,
|
|
Api.property-declaration-ranges(property-information.name).defined-at.expression-range.start,
|
|
Api.property-declaration-ranges(property-information.name).defined-at.expression-range.start,
|
|
true,
|
|
);
|
|
}
|
|
function reset-action() {
|
|
Api.set-code-binding(
|
|
element-information.source-uri,
|
|
element-information.source-version,
|
|
element-information.offset,
|
|
property-information.name,
|
|
"",
|
|
);
|
|
}
|
|
|
|
VerticalLayout {
|
|
padding-bottom: EditorSpaceSettings.default-padding;
|
|
padding-right: EditorSpaceSettings.default-padding * 2;
|
|
spacing: EditorSpaceSettings.default-spacing / 2;
|
|
|
|
HorizontalLayout {
|
|
alignment: LayoutAlignment.space-between;
|
|
NameLabel {
|
|
property-name: property-information.name;
|
|
property-value: property-information.value;
|
|
TouchArea {
|
|
double-clicked => { root.code-action(); }
|
|
}
|
|
}
|
|
|
|
HorizontalLayout {
|
|
opacity: root.has-hover ? 1 : 0;
|
|
animate opacity {
|
|
duration: 200ms;
|
|
easing: ease-in-out-quad;
|
|
}
|
|
alignment: end;
|
|
spacing: 4px;
|
|
IconButton {
|
|
icon: @image-url("../assets/constant.svg");
|
|
checked: mode == PropertyWidgetMode.value;
|
|
enabled: kind != PropertyValueKind.code;
|
|
clicked => {
|
|
mode = PropertyWidgetMode.value;
|
|
}
|
|
}
|
|
|
|
IconButton {
|
|
checked: mode == PropertyWidgetMode.expression;
|
|
icon: @image-url("../assets/code.svg");
|
|
clicked => {
|
|
mode = PropertyWidgetMode.expression;
|
|
}
|
|
}
|
|
|
|
IconButton {
|
|
icon: @image-url("../assets/revert.svg");
|
|
enabled: property-information.value.code != "";
|
|
clicked => {
|
|
root.reset-action();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if mode == PropertyWidgetMode.expression : HorizontalLayout {
|
|
alignment: LayoutAlignment.stretch;
|
|
spacing: 5px;
|
|
IconButton {
|
|
icon: @image-url("../assets/code.svg");
|
|
clicked => { root.code-action(); }
|
|
}
|
|
ResettingLineEdit {
|
|
enabled: root.enabled;
|
|
|
|
default-text: property-information.value.code;
|
|
|
|
edited(text) => {
|
|
self.can-compile = Api.test-code-binding(
|
|
root.element-information.source-uri,
|
|
root.element-information.source-version,
|
|
root.element-information.offset,
|
|
root.property-information.name,
|
|
text,
|
|
);
|
|
}
|
|
accepted(text) => {
|
|
Api.set-code-binding(
|
|
root.element-information.source-uri,
|
|
root.element-information.source-version,
|
|
root.element-information.offset,
|
|
root.property-information.name,
|
|
text,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if mode == PropertyWidgetMode.value : PropertyValueWidget {
|
|
property-value: root.property-information.value;
|
|
property-name: root.property-information.name;
|
|
enabled: root.enabled;
|
|
|
|
set-current-item() => {
|
|
WindowManager.show-floating-widget(property-information, element-information);
|
|
}
|
|
|
|
set-bool-binding(value) => {
|
|
self.set-code-binding(value ? "true" : "false");
|
|
}
|
|
set-brush-binding(kind, angle, color, stops) => {
|
|
self.set-code-binding(Api.as-slint-brush(kind, angle, color, stops));
|
|
}
|
|
test-brush-binding(kind, angle, color, stops) => {
|
|
return self.test-code-binding(Api.as-slint-brush(kind, angle, color, stops));
|
|
}
|
|
set-color-binding(text) => {
|
|
self.set-code-binding(text);
|
|
}
|
|
test-color-binding(text) => {
|
|
return (Api.string-is-color(text));
|
|
}
|
|
set-enum-binding(text) => {
|
|
self.set-code-binding(text);
|
|
}
|
|
test-float-binding(text, unit) => {
|
|
return (self.test-code-binding(text + unit));
|
|
}
|
|
set-float-binding(text, unit) => {
|
|
self.set-code-binding(text + unit);
|
|
}
|
|
|
|
set-code-binding(text) => {
|
|
Api.set-code-binding(
|
|
element-information.source-uri,
|
|
element-information.source-version,
|
|
element-information.offset,
|
|
property-information.name,
|
|
text,
|
|
);
|
|
}
|
|
test-code-binding(text) => {
|
|
return (Api.test-code-binding(
|
|
root.element-information.source-uri,
|
|
root.element-information.source-version,
|
|
root.element-information.offset,
|
|
root.property-information.name,
|
|
text,
|
|
));
|
|
}
|
|
set-string-binding(text, is-translated) => {
|
|
Api.set-code-binding(
|
|
element-information.source-uri,
|
|
element-information.source-version,
|
|
element-information.offset,
|
|
property-information.name,
|
|
text);
|
|
}
|
|
test-string-binding(text, is-translated) => {
|
|
return (Api.test-code-binding(
|
|
root.element-information.source-uri,
|
|
root.element-information.source-version,
|
|
root.element-information.offset,
|
|
root.property-information.name,
|
|
text));
|
|
}
|
|
|
|
reset-action() => {
|
|
root.reset-action();
|
|
}
|
|
|
|
code-action() => {
|
|
root.code-action();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export component PreviewDataPropertyValueWidget inherits VerticalLayout {
|
|
in property <PreviewData> preview-data;
|
|
in property <string> property-container-id;
|
|
|
|
private property <PropertyValue> value: Api.get-property-value(root.property-container-id, root.preview-data.name);
|
|
private property <string> possible-error;
|
|
|
|
callback edit-in-table-editor(property-group-id: string, data: PreviewData);
|
|
|
|
function reset-action() {
|
|
self.set-code-binding(self.value.code);
|
|
}
|
|
|
|
function set-code-binding(text: string) -> bool {
|
|
self.possible_error = Api.set-json-preview-data(root.property-container-id, root.preview-data.name, text, check-new-value(root.property-container-id + root.preview-data.name));
|
|
|
|
StatusLineApi.help-text = self.possible-error;
|
|
|
|
return (self.possible-error == "");
|
|
}
|
|
|
|
property <string> container-property-name;
|
|
function check-new-value(value: string) -> bool {
|
|
if container-property-name == value {
|
|
return false;
|
|
} else {
|
|
container-property-name = value;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
padding-bottom: EditorSpaceSettings.default-padding;
|
|
padding-right: EditorSpaceSettings.default-padding * 2;
|
|
spacing: EditorSpaceSettings.default-spacing / 2;
|
|
|
|
NameLabel {
|
|
property-name: root.preview-data.name;
|
|
property-value: root.value;
|
|
}
|
|
|
|
if root.preview-data.kind == PreviewDataKind.Value: PropertyValueWidget {
|
|
property-value <=> root.value;
|
|
property-name: root.preview-data.name;
|
|
enabled: root.preview-data.has-setter;
|
|
property-container-id <=> root.property-container-id;
|
|
preview-data <=> root.preview-data;
|
|
|
|
strings-are-translatable: false;
|
|
has-code-action: false;
|
|
has-reset-action: false;
|
|
|
|
set-current-item() => {
|
|
WindowManager.show-floating-preview-widget(property-container-id, preview-data, root.value);
|
|
}
|
|
set-bool-binding(value) => {
|
|
self.set-code-binding(value ? "true" : "false");
|
|
}
|
|
set-brush-binding(kind, angle, color, stops) => {
|
|
self.set-code-binding(Api.as-json-brush(kind, angle, color, stops));
|
|
}
|
|
test-brush-binding(kind, angle, color, stops) => {
|
|
return self.test-code-binding(Api.as-json-brush(kind, angle, color, stops));
|
|
}
|
|
set-color-binding(text) => {
|
|
self.set-code-binding("\"\{text}\"");
|
|
}
|
|
test-color-binding(text) => {
|
|
return (root.set-code-binding("\"\{text}\""));
|
|
}
|
|
set-float-binding(text, _unit) => {
|
|
self.set-code-binding("\{text}");
|
|
}
|
|
test-float-binding(text, _unit) => {
|
|
return (root.set-code-binding("\{text}"));
|
|
}
|
|
set-enum-binding(text) => {
|
|
self.set-code-binding("\"\{text}\"");
|
|
}
|
|
set-code-binding(text) => {
|
|
root.set-code-binding(text);
|
|
}
|
|
test-code-binding(text) => {
|
|
return (root.set-code-binding(text));
|
|
}
|
|
set-string-binding(text, is_translated) => {
|
|
self.test-string-binding(text, is_translated);
|
|
}
|
|
test-string-binding(text, is_translated) => {
|
|
return (root.set-code-binding(is_translated ? "\"\{text}\"" : text));
|
|
}
|
|
}
|
|
if root.preview-data.kind == PreviewDataKind.Table: MultiValueWidget {
|
|
property-value <=> root.value;
|
|
preview-data: root.preview-data;
|
|
property-group-id: root.property-container-id;
|
|
|
|
edit-in-table-editor(property-group-id, data) => {
|
|
root.edit-in-table-editor(property-group-id, data);
|
|
}
|
|
}
|
|
if root.preview-data.kind == PreviewDataKind.Json: JsonWidget {
|
|
enabled: root.preview-data.has-setter;
|
|
property-value <=> root.value;
|
|
|
|
set-code-binding(text) => {
|
|
return (root.set-code-binding(text));
|
|
}
|
|
}
|
|
}
|