diff --git a/packages/project-editor/lvgl/identifiers.ts b/packages/project-editor/lvgl/identifiers.ts
index 7af31ed6..86106a3e 100644
--- a/packages/project-editor/lvgl/identifiers.ts
+++ b/packages/project-editor/lvgl/identifiers.ts
@@ -165,6 +165,12 @@ export class LVGLIdentifiers {
flow: Flow,
displayName: string
): LVGLIdentifier | undefined {
+ const identifierName = getName(
+ "",
+ displayName,
+ NamingConvention.UnderscoreLowerCase
+ );
+
let identifiers = this.getIdentifiersVisibleFromFlow(flow);
if (!identifiers) {
@@ -180,7 +186,7 @@ export class LVGLIdentifiers {
}
return identifiers.find(
- lvglIdentifier => lvglIdentifier.identifier == displayName
+ lvglIdentifier => lvglIdentifier.identifier == identifierName
);
}
diff --git a/packages/project-editor/ui-components/PropertyGrid/Property.tsx b/packages/project-editor/ui-components/PropertyGrid/Property.tsx
index dce091c1..b84587f0 100644
--- a/packages/project-editor/ui-components/PropertyGrid/Property.tsx
+++ b/packages/project-editor/ui-components/PropertyGrid/Property.tsx
@@ -6,24 +6,20 @@ import { dialog } from "@electron/remote";
import { guid } from "eez-studio-shared/guid";
import { humanize } from "eez-studio-shared/string";
-import { validators, filterNumber } from "eez-studio-shared/validation";
-import { validators as validatorsRenderer } from "eez-studio-shared/validation-renderer";
+import { filterNumber } from "eez-studio-shared/validation";
import { confirm } from "eez-studio-ui/dialog-electron";
-import { showGenericDialog } from "eez-studio-ui/generic-dialog";
import { Icon } from "eez-studio-ui/icon";
import {
PropertyType,
PropertyProps,
- getParent,
getObjectPropertyDisplayName,
isPropertyOptional,
EnumItem
} from "project-editor/core/object";
import { info } from "project-editor/core/util";
-import { replaceObjectReference } from "project-editor/core/search";
import { ConfigurationReferencesPropertyValue } from "project-editor/ui-components/ConfigurationReferencesPropertyValue";
@@ -52,6 +48,7 @@ import { Checkbox } from "./Checkbox";
import { ImageProperty } from "./ImageProperty";
import { General } from "project-editor/project/project";
+import { UniqueValueInput } from "./UniqueValueInput";
////////////////////////////////////////////////////////////////////////////////
@@ -393,82 +390,6 @@ export const Property = observer(
);
};
- onEditUnique = () => {
- const propertyInfoUnique = (this.props.propertyInfo.unique ||
- this.props.propertyInfo.uniqueIdentifier)!;
-
- showGenericDialog({
- dialogDefinition: {
- fields: [
- {
- name: this.props.propertyInfo.name,
- displayName: getObjectPropertyDisplayName(
- this.props.objects[0],
- this.props.propertyInfo
- ),
- type: "string",
- validators: [
- typeof propertyInfoUnique === "boolean"
- ? validators.unique(
- this.props.objects[0],
- getParent(this.props.objects[0])
- )
- : propertyInfoUnique(
- this.props.objects[0],
- getParent(this.props.objects[0]),
- this.props.propertyInfo
- )
- ]
- .concat(
- isPropertyOptional(
- this.props.objects[0],
- this.props.propertyInfo
- )
- ? []
- : [validators.required]
- )
- .concat(
- this.props.propertyInfo.uniqueIdentifier
- ? [
- validatorsRenderer.identifierValidator
- ]
- : []
- )
- }
- ]
- },
- values: this.props.objects[0]
- })
- .then(result => {
- let oldValue = this._value;
- let newValue =
- result.values[this.props.propertyInfo.name].trim();
- if (newValue.length === 0) {
- newValue = undefined;
- }
- if (newValue != oldValue) {
- this.context.undoManager.setCombineCommands(true);
-
- console.log("Change unique value", oldValue, newValue);
-
- runInAction(() => {
- replaceObjectReference(
- this.props.objects[0],
- newValue
- );
- this.changeValue(newValue);
- });
-
- this.context.undoManager.setCombineCommands(false);
- }
- })
- .catch(error => {
- if (error !== undefined) {
- console.error(error);
- }
- });
- };
-
onGenerateGuid = () => {
this.changeValue(guid());
};
@@ -572,22 +493,11 @@ export const Property = observer(
(propertyInfo.unique || propertyInfo.uniqueIdentifier)
) {
return (
-
- (this.input = ref)}
- type="text"
- className="form-control"
- value={this._value || ""}
- readOnly
- />
-
-
+
);
} else if (propertyInfo.type === PropertyType.MultilineText) {
if (!readOnly && isOnSelectAvailable) {
diff --git a/packages/project-editor/ui-components/PropertyGrid/UniqueValueInput.tsx b/packages/project-editor/ui-components/PropertyGrid/UniqueValueInput.tsx
new file mode 100644
index 00000000..542d2879
--- /dev/null
+++ b/packages/project-editor/ui-components/PropertyGrid/UniqueValueInput.tsx
@@ -0,0 +1,225 @@
+import React from "react";
+import { observable, action, runInAction, makeObservable } from "mobx";
+import { observer } from "mobx-react";
+
+import { getParent, PropertyProps } from "project-editor/core/object";
+
+import { ProjectContext } from "project-editor/project/context";
+
+import { validators } from "eez-studio-shared/validation";
+import { validators as validatorsRenderer } from "eez-studio-shared/validation-renderer";
+
+import { isPropertyOptional } from "project-editor/core/object";
+import { replaceObjectReference } from "project-editor/core/search";
+import { Icon } from "eez-studio-ui/icon";
+
+////////////////////////////////////////////////////////////////////////////////
+
+export const UniqueValueInput = observer(
+ class UniqueValueInput extends React.Component<
+ PropertyProps & { value: any; changeValue: (newValue: any) => void }
+ > {
+ static contextType = ProjectContext;
+ declare context: React.ContextType;
+
+ oldValue: any;
+ _value: string | undefined;
+ error: string | undefined = undefined;
+
+ constructor(props: any) {
+ super(props);
+
+ makeObservable(this, {
+ _value: observable,
+ error: observable
+ });
+ }
+
+ componentDidUpdate(prevProps: PropertyProps) {
+ if (
+ !arrayCompareShallow(prevProps.objects, this.props.objects) ||
+ prevProps.propertyInfo != this.props.propertyInfo ||
+ this.oldValue != this.props.value
+ ) {
+ this.resetChange();
+ }
+ }
+
+ onChange = action((event: React.ChangeEvent) => {
+ this.oldValue = this.props.value;
+ this._value = event.target.value.toString();
+ this.error = undefined;
+ });
+
+ onKeyDown = (event: React.KeyboardEvent) => {
+ if (event.key === "Enter") {
+ this.commitChange();
+ } else if (event.key == "Escape") {
+ this.discardChange();
+ }
+ };
+
+ onOK = () => {
+ this.commitChange();
+ };
+
+ onCancel = () => {
+ this.discardChange();
+ };
+
+ onBlur = (event: React.FocusEvent) => {};
+
+ resetChange() {
+ runInAction(() => {
+ this._value = undefined;
+ this.error = undefined;
+ });
+ }
+
+ discardChange() {
+ this.resetChange();
+ }
+
+ commitChange = async () => {
+ if (this._value == undefined) {
+ return;
+ }
+
+ let newValue = this._value.trim();
+
+ const valueValidators = [];
+
+ const propertyInfoUnique = (this.props.propertyInfo.unique ||
+ this.props.propertyInfo.uniqueIdentifier)!;
+ if (typeof propertyInfoUnique === "boolean") {
+ valueValidators.push(
+ validators.unique(
+ this.props.objects[0],
+ getParent(this.props.objects[0])
+ )
+ );
+ } else {
+ valueValidators.push(
+ propertyInfoUnique(
+ this.props.objects[0],
+ getParent(this.props.objects[0]),
+ this.props.propertyInfo
+ )
+ );
+ }
+
+ if (
+ !isPropertyOptional(
+ this.props.objects[0],
+ this.props.propertyInfo
+ )
+ ) {
+ valueValidators.push(validators.required);
+ }
+
+ if (this.props.propertyInfo.uniqueIdentifier) {
+ valueValidators.push(validatorsRenderer.identifierValidator);
+ }
+
+ for (const valueValidator of valueValidators) {
+ const error = await valueValidator(
+ {
+ [this.props.propertyInfo.name]: newValue
+ },
+ this.props.propertyInfo.name
+ );
+
+ if (error) {
+ runInAction(() => {
+ this.error = error;
+ });
+ return;
+ }
+ }
+
+ let oldValue = this.props.value;
+
+ if (newValue != oldValue) {
+ if (newValue.length == 0) {
+ runInAction(() => {
+ this.props.changeValue(undefined);
+ });
+ } else {
+ this.context.undoManager.setCombineCommands(true);
+
+ runInAction(() => {
+ replaceObjectReference(this.props.objects[0], newValue);
+ this.props.changeValue(newValue);
+ });
+
+ this.context.undoManager.setCombineCommands(false);
+ }
+ }
+
+ this.resetChange();
+ };
+
+ render() {
+ return (
+ <>
+
+ 1}
+ />
+ {this._value != undefined && (
+ <>
+
+
+ >
+ )}
+
+ {this.error && (
+ {this.error}
+ )}
+ >
+ );
+ }
+ }
+);
+
+function arrayCompareShallow(arr1: any, arr2: any) {
+ if (!arr1 && !arr2) {
+ return true;
+ }
+
+ if ((!arr1 && arr2) || (arr1 && !arr2) || arr1.length != arr2.length) {
+ return false;
+ }
+
+ for (let i = 0; i < arr1.length; i++) {
+ if (arr1[i] != arr2[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}