slint/tools/lsp/ui/components/property-widgets.slint
Nigel Breslaw 22143a04ff
Tidy the brush pickers (#8277)
This refactor is to help make future maintenance easier.

Items are now consistently named as brush instead of color.
Instead of one huge brush picker file, various elements such as gradients live in their own file.
The brush picker is also made a bit less 'smart' and doesn't have to fully understand how the current color or brush needs to be updated or if the data tab live preview needs to be updated. In turn the PickerData has been made smarter and looks after these updates.

This has fixed a few bug regarding gradient stops.
2025-04-28 12:29:43 +03:00

396 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
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 { 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";
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-name <=> root.property-name;
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);
}
reset-action() => {
root.reset-action();
}
code-action() => {
root.code-action();
}
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-name <=> root.property-name;
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-name <=> root.property-name;
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-name <=> root.property-name;
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-name <=> root.property-name;
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-name <=> root.property-name;
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);
}
reset-action() => {
root.reset-action();
}
code-action() => {
root.code-action();
}
}
}
export component PropertyInformationWidget inherits VerticalLayout {
in property <PropertyInformation> property-information;
in property <ElementInformation> element-information;
in property <bool> enabled;
padding-bottom: EditorSpaceSettings.default-padding;
padding-right: EditorSpaceSettings.default-padding * 2;
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.range.start,
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.range.start,
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.range.start,
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.range.start,
root.property-information.name,
text));
}
reset-action() => {
Api.set-code-binding(
element-information.source-uri,
element-information.source-version,
element-information.range.start,
property-information.name,
"",
);
}
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,
);
}
}
}
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);
StatusLineApi.help-text = self.possible-error;
return (self.possible-error == "");
}
padding-bottom: EditorSpaceSettings.default-padding;
padding-right: EditorSpaceSettings.default-padding * 2;
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-name: root.preview-data.name;
property-value <=> root.value;
set-code-binding(text) => {
return (root.set-code-binding(text));
}
}
}