载入中...
搜索中...
未找到
DefinitionFormRuntime.cpp
浏览该文件的文档.
2
5
6#include <cmath>
7
9namespace {
10
11PropertyType propertyType(const schema::FieldDefinition& field) {
12 if (!field.enumValues.empty()) return PropertyType::Enum;
13 if (!field.ref.empty() || !field.reference.empty()) return PropertyType::ObjectRef;
14 switch (field.type) {
15 case schema::ValueType::Boolean: return PropertyType::Bool;
16 case schema::ValueType::Integer: return PropertyType::Int;
17 case schema::ValueType::Number: return PropertyType::Float;
18 case schema::ValueType::String: return PropertyType::String;
19 case schema::ValueType::Array: return PropertyType::Array;
20 case schema::ValueType::Object: return PropertyType::Struct;
22 case schema::ValueType::Null: return PropertyType::ReadOnlyText;
23 }
24 return PropertyType::ReadOnlyText;
25}
26
27EditorValue defaultValue(const schema::FieldDefinition& field) {
28 if (!field.defaultJson.empty()) {
29 auto parsed = editorValueFromJson(field.defaultJson);
30 if (parsed.ok()) return parsed.value();
31 }
32 switch (field.type) {
33 case schema::ValueType::Boolean: return false;
34 case schema::ValueType::Integer: return int64_t{0};
35 case schema::ValueType::Number: return 0.0;
36 case schema::ValueType::String: return std::string{};
40 case schema::ValueType::Null: return {};
41 }
42 return {};
43}
44
45Result<DomainOperation> formError(EditorStatus status, const char* rule, std::string message) {
46 return eve::editing::failed<DomainOperation>(status, RuleId(rule), std::move(message));
47}
48
49} // namespace
50
52 const schema::SchemaDefinition* schema)
53 : document_(document), schema_(schema) {}
54
55bool DefinitionSchemaFormTarget::matches(const SelectionSnapshot& selection) const {
56 return document_ && selection.items.size() == 1 &&
57 selection.items.front().target == TargetId(document_->targetId());
58}
59
61 const SelectionSnapshot& selection) const {
62 if (!matches(selection))
64 eve::DiagnosticCode::InvalidArgument, "Definition form selection does not match its document",
65 "editor.definition.form-selection"));
67}
68
70 PropertySchema result;
71 if (!schema_) return result;
72 result.typeId = "definition." + schema_->id;
73 result.version = static_cast<std::uint32_t>(schema_->version);
74 for (const schema::FieldDefinition& field : schema_->fields) {
76 descriptor.path = PropertyPath(field.name);
77 descriptor.displayNameKey = field.title.empty() ? field.name : field.title;
78 descriptor.descriptionKey = field.description;
79 descriptor.category = "definition";
80 descriptor.type = propertyType(field);
81 descriptor.defaultValue = defaultValue(field);
82 descriptor.numeric.minimum = field.minimum;
83 descriptor.numeric.maximum = field.maximum;
84 descriptor.enumItems = field.enumValues;
85 descriptor.presenterHint = !field.ref.empty() || !field.reference.empty()
86 ? "definition-reference-picker" : "schema-field";
87 if (descriptor.type == PropertyType::ReadOnlyText) descriptor.flags = PropertyFlag::ReadOnly;
88 if (field.required) descriptor.validators.push_back(RuleId("editor.definition.required"));
89 result.properties.push_back(std::move(descriptor));
90 }
91 return result;
92}
93
95 const PropertyPath& path) const {
96 const auto descriptor = schema(selection).find(path);
97 if (!matches(selection) || !descriptor) return {};
98 auto parsed = editorValueFromJson(document_->json());
99 const auto* object = parsed.ok() ? parsed.value().getIf<EditorValue::Object>() : nullptr;
100 if (!object) return {PropertyReadState::Error, {}, parsed.diagnostics()};
101 const auto found = object->find(path.value());
102 if (found == object->end()) return {PropertyReadState::Missing, {}, {}};
103 if (descriptor->type == PropertyType::Float) {
104 if (const auto* integer = found->second.getIf<int64_t>())
105 return {PropertyReadState::Value, static_cast<double>(*integer), {}};
106 }
107 return {PropertyReadState::Value, found->second, {}};
108}
109
111 const SelectionSnapshot& selection, const PropertyPath& path, const EditorValue& value,
112 PropertySetMode mode) const {
113 if (mode == PropertySetMode::Reset) return makeReset(selection, path);
114 if (!matches(selection) || !schema_)
115 return formError(EditorStatus::Rejected, "editor.definition.form-selection",
116 "Definition form selection does not match its document");
117 auto descriptor = schema(selection).find(path);
118 if (!descriptor)
119 return formError(EditorStatus::Unsupported, "editor.definition.form-field",
120 "Definition schema does not contain field: " + path.value());
121 if (hasPropertyFlag(descriptor->flags, PropertyFlag::ReadOnly))
122 return formError(EditorStatus::Rejected, "editor.definition.form-read-only",
123 "Definition field is not directly editable");
125 if (!valid.ok()) return Result<DomainOperation>::failure(valid.status());
126 return document_->makeSetField(path.value(), value);
127}
128
130 const SelectionSnapshot& selection, const PropertyPath& path) const {
131 auto descriptor = schema(selection).find(path);
132 if (!matches(selection) || !descriptor)
133 return formError(EditorStatus::Unsupported, "editor.definition.form-field",
134 "Definition schema field is unavailable");
135 return makeSet(selection, path, descriptor->defaultValue, PropertySetMode::Absolute);
136}
137
138std::vector<EditorDiagnostic> DefinitionSchemaFormTarget::validate() const {
139 std::vector<EditorDiagnostic> diagnostics;
140 if (!document_ || !schema_ || document_->type() != schema_->id || document_->version() != schema_->version) {
141 diagnostics.push_back(eve::editing::ruleDiagnostic(
143 RuleId("editor.definition.form-schema-mismatch"), DiagnosticSeverity::Error,
144 "Definition document and exact schema identity do not match"));
145 return diagnostics;
146 }
147 auto parsed = editorValueFromJson(document_->json());
148 const auto* object = parsed.ok() ? parsed.value().getIf<EditorValue::Object>() : nullptr;
149 if (!object) {
150 diagnostics.push_back(eve::editing::ruleDiagnostic(
152 RuleId("editor.definition.form-object-required"), DiagnosticSeverity::Error,
153 "Schema-driven definition forms require an object payload"));
154 return diagnostics;
155 }
156 const PropertySchema formSchema = schema({});
157 for (const schema::FieldDefinition& field : schema_->fields) {
158 const auto found = object->find(field.name);
159 if (found == object->end()) {
160 if (field.required)
161 diagnostics.push_back(eve::editing::ruleDiagnostic(
163 RuleId("editor.definition.required-field-missing"), DiagnosticSeverity::Error,
164 "Required definition field is missing: " + field.name));
165 continue;
166 }
167 auto descriptor = formSchema.find(PropertyPath(field.name));
169 diagnostics.insert(diagnostics.end(), valid.diagnostics().begin(), valid.diagnostics().end());
170 }
171 return diagnostics;
172}
173
174} // namespace eve::definitions_editing
double value
std::string descriptor
std::string message
wgpu::PopErrorScopeStatus status
bool valid
std::string path
Definition PlayHost.cpp:110
bool found
Json object
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
UI-neutral versioned definition asset and cross-reference model.
const std::string & json() const
Return JSON payload text.
int version() const
Return schema version.
const std::string & type() const
Return definition type/schema id.
TargetId targetId() const override
Target id.
Result< DomainOperation > makeSetField(const std::string &field, const EditorValue &value) const
Plan a reversible top-level field assignment from a schema form.
Result< DomainOperation > makeReset(const SelectionSnapshot &selection, const PropertyPath &path) const override
Make reset.
std::vector< EditorDiagnostic > validate() const
Diagnose schema/document identity, missing required fields and current value constraints.
PropertyReadResult read(const SelectionSnapshot &selection, const PropertyPath &path) const override
Reads .
Result< DomainOperation > makeSet(const SelectionSnapshot &selection, const PropertyPath &path, const EditorValue &value, PropertySetMode mode) const override
Make set.
PropertySchema schema(const SelectionSnapshot &selection) const override
Schema.
eve::Result< eve::Revision > currentRevision(const SelectionSnapshot &selection) const override
Current revision.
DefinitionSchemaFormTarget(DefinitionDocument *document, const schema::SchemaDefinition *schema)
Bind a document and exact immutable schema; both must outlive this adapter.
std::uint64_t revision() const override
Return the current revision.
Dotted property path (layout.size) compared and persisted as text.
Definition EditingIds.h:78
Deterministic owning value tree shared by authoring hosts.
std::vector< Value > Array
std::map< std::string, Value > Object
Type type() const
Return the active value type.
const char * defaultValue
eve::editing::Status EditorStatus
eve::editing::Value EditorValue
StrongId< TargetIdTag > TargetId
Definition EditingIds.h:57
Result< EditorValue > editorValueFromJson(const std::string &json)
Parse JSON into the pointer-free EditorValue protocol tree.
PropertyType
PropertyType public API.
StrongId< RuleIdTag > RuleId
Definition EditingIds.h:60
PropertySetMode
PropertySetMode public API.
Result< void > validatePropertyValue(const PropertyDescriptor &descriptor, const Value &value)
Validate property value.
constexpr bool hasPropertyFlag(PropertyFlag value, PropertyFlag flag)
True when property flag.
Diagnostic ruleDiagnostic(eve::DiagnosticCode code, RuleId rule, DiagnosticSeverity severity, std::string message)
Build a common diagnostic carrying an open editing rule identity.
const EditorValue * field(const EditorValue &value, const char *name)
PropertyDescriptor public API.
PropertyReadResult public API.
EVENGINE_API_PLATFORM public API.
std::vector< PropertyDescriptor > properties
PropertyDescriptorLookup find(const PropertyPath &path) const
Finds find.
SelectionSnapshot public API.
std::vector< SelectionItem > items
Metadata and validation constraints for one object member.
Definition SchemaTypes.h:77
Versioned runtime schema for a JSON object.
Definition SchemaTypes.h:93
std::vector< FieldDefinition > fields
Definition SchemaTypes.h:99