Discover Table compatibility and declared Row alignment
This commit is contained in:
@@ -213,7 +213,9 @@ public final class DesignerPane extends BorderPane implements AutoCloseable {
|
||||
if (target != null) kit.editor().getSelection().select(target);
|
||||
},
|
||||
values -> validateBindings(values, false));
|
||||
tableEditor = new TableEditor(this::editTable, this::navigateComponent);
|
||||
tableEditor =
|
||||
new TableEditor(
|
||||
this::editTable, this::navigateComponent, values -> validateBindings(values, false));
|
||||
bindingBrowser =
|
||||
new BindingBrowser(
|
||||
this::discoverBindings,
|
||||
@@ -691,6 +693,7 @@ public final class DesignerPane extends BorderPane implements AutoCloseable {
|
||||
bindingWorkflow.cancel();
|
||||
bindingBrowser.invalidate(message);
|
||||
repeatEditor.invalidateDiscovery();
|
||||
tableEditor.invalidateDiscovery();
|
||||
}
|
||||
|
||||
private void editTable(TableEditor.Intent intent) {
|
||||
@@ -817,6 +820,14 @@ public final class DesignerPane extends BorderPane implements AutoCloseable {
|
||||
: "Current successful build")
|
||||
+ " · draft revision "
|
||||
+ captured.revision());
|
||||
tableEditor.metadata(
|
||||
metadata,
|
||||
values,
|
||||
(last
|
||||
? "Explicit retained build (outdated)"
|
||||
: "Current successful build")
|
||||
+ " · draft revision "
|
||||
+ captured.revision());
|
||||
status.setText(
|
||||
"Binding validation complete: "
|
||||
+ metadata.problems().size()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.neitzel.fxdesigner.kit;
|
||||
|
||||
import de.neitzel.fxdesigner.contracts.EditBatch.Replacement;
|
||||
import de.neitzel.fxdesigner.protocol.BindingMetadata;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import javafx.scene.control.*;
|
||||
@@ -21,12 +22,47 @@ final class TableEditor extends VBox {
|
||||
private final Consumer<Intent> edit;
|
||||
private String source = "";
|
||||
private TableDocument document;
|
||||
private boolean loading;
|
||||
private boolean loading, updatingChoices;
|
||||
private final ComboBox<BindingMetadata.RepeatOption> collectionChoices = new ComboBox<>(),
|
||||
rowChoices = new ComboBox<>(),
|
||||
columnChoices = new ComboBox<>();
|
||||
private final Consumer<BindingDocument.Values> discover;
|
||||
|
||||
private BindingDocument.Values values() {
|
||||
return BindingDocument.Values.repeat("@table:" + table, row.getText(), collection.getText());
|
||||
}
|
||||
|
||||
private Integer table, column;
|
||||
|
||||
TableEditor(Consumer<Intent> edit, Consumer<String> navigate) {
|
||||
TableEditor(
|
||||
Consumer<Intent> edit, Consumer<String> navigate, Consumer<BindingDocument.Values> discover) {
|
||||
super(5);
|
||||
this.edit = edit;
|
||||
this.discover = discover;
|
||||
collectionChoices.setId("table-collections");
|
||||
rowChoices.setId("table-rows");
|
||||
columnChoices.setId("table-attributes");
|
||||
for (var c : List.of(collectionChoices, rowChoices, columnChoices)) c.setPrefWidth(360);
|
||||
collectionChoices.setOnAction(
|
||||
e -> {
|
||||
var v = collectionChoices.getValue();
|
||||
if (v != null && !updatingChoices) {
|
||||
collection.setText(v.name());
|
||||
discover.accept(values());
|
||||
}
|
||||
});
|
||||
rowChoices.setOnAction(
|
||||
e -> {
|
||||
var v = rowChoices.getValue();
|
||||
if (v != null && !updatingChoices) row.setText(v.name());
|
||||
});
|
||||
columnChoices.setOnAction(
|
||||
e -> {
|
||||
var v = columnChoices.getValue();
|
||||
if (v != null && !updatingChoices) attribute.setText(v.name());
|
||||
});
|
||||
collection.textProperty().addListener((o, a, b) -> invalidateDiscovery());
|
||||
|
||||
setId("table-editor");
|
||||
tables.setId("table-bindings");
|
||||
columns.setId("table-columns");
|
||||
@@ -68,6 +104,11 @@ final class TableEditor extends VBox {
|
||||
.addAll(
|
||||
tables,
|
||||
tableFields,
|
||||
new HBox(
|
||||
6,
|
||||
button("Discover / Validate Table", () -> discover.accept(values())),
|
||||
collectionChoices,
|
||||
rowChoices),
|
||||
new HBox(
|
||||
6,
|
||||
button(
|
||||
@@ -100,6 +141,7 @@ final class TableEditor extends VBox {
|
||||
})),
|
||||
columns,
|
||||
columnFields,
|
||||
columnChoices,
|
||||
new HBox(
|
||||
6,
|
||||
button(
|
||||
@@ -203,6 +245,7 @@ final class TableEditor extends VBox {
|
||||
setDisable(!writable);
|
||||
if (source.equals(text)) return;
|
||||
source = text;
|
||||
invalidateDiscovery();
|
||||
loading = true;
|
||||
try {
|
||||
document = new TableDocument(text);
|
||||
@@ -243,6 +286,49 @@ final class TableEditor extends VBox {
|
||||
}
|
||||
}
|
||||
|
||||
void invalidateDiscovery() {
|
||||
updatingChoices = true;
|
||||
try {
|
||||
collectionChoices.getItems().clear();
|
||||
rowChoices.getItems().clear();
|
||||
columnChoices.getItems().clear();
|
||||
} finally {
|
||||
updatingChoices = false;
|
||||
}
|
||||
status.setText(
|
||||
"Document/build or collection changed; Discover / Validate Table again. Row alignment"
|
||||
+ " unverified.");
|
||||
}
|
||||
|
||||
void metadata(BindingMetadata metadata, BindingDocument.Values requested, String provenance) {
|
||||
var messages = new java.util.ArrayList<String>();
|
||||
if (document != null) messages.addAll(document.errors());
|
||||
for (var p : metadata.problems())
|
||||
if (java.util.Set.of("collection", "row", "columns", "alignment", "Table")
|
||||
.contains(p.property()))
|
||||
messages.add(p.severity() + " " + p.control() + ": " + p.message());
|
||||
status.setText(
|
||||
provenance
|
||||
+ "\n"
|
||||
+ (messages.isEmpty()
|
||||
? "No Table compatibility errors found."
|
||||
: String.join("\n", messages))
|
||||
+ "\n"
|
||||
+ "Diagnostics describe the current document. Choices compare the requested collection."
|
||||
+ " Open Row Component to resolve alignment warnings; its layout is never changed"
|
||||
+ " automatically.");
|
||||
if (requested != null && requested.equals(values())) {
|
||||
updatingChoices = true;
|
||||
try {
|
||||
collectionChoices.getItems().setAll(metadata.tableCollections());
|
||||
rowChoices.getItems().setAll(metadata.tableRows());
|
||||
columnChoices.getItems().setAll(metadata.tableColumns());
|
||||
} finally {
|
||||
updatingChoices = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void error(String message) {
|
||||
status.setText(message);
|
||||
}
|
||||
|
||||
@@ -691,6 +691,118 @@ public final class ProjectionHostChecks {
|
||||
});
|
||||
}
|
||||
|
||||
private static void tableDiscovery(DesignerPane pane, DocumentSession document, String full)
|
||||
throws Exception {
|
||||
bindingTab(pane, "Table / Columns");
|
||||
tableSelect(pane, "bindings", 0);
|
||||
click(pane, "Discover / Validate Table");
|
||||
await(() -> fx(() -> !((ComboBox<?>) pane.lookup("#table-attributes")).getItems().isEmpty()));
|
||||
check(
|
||||
fx(
|
||||
() ->
|
||||
((Label) pane.lookup("#table-status"))
|
||||
.getText()
|
||||
.contains("matches direct bindings")),
|
||||
"Declared Row alignment missing");
|
||||
fx(
|
||||
() -> {
|
||||
var rows =
|
||||
(ComboBox<de.neitzel.fxdesigner.protocol.BindingMetadata.RepeatOption>)
|
||||
pane.lookup("#table-rows");
|
||||
check(
|
||||
rows.getItems().stream()
|
||||
.anyMatch(
|
||||
c ->
|
||||
c.name().equals("fixture.components.VisitRow")
|
||||
&& c.status().equals("COMPATIBLE")),
|
||||
"Compatible Row absent");
|
||||
check(
|
||||
rows.getItems().stream()
|
||||
.anyMatch(
|
||||
c ->
|
||||
c.name().equals("fixture.components.WrongRepeatCard")
|
||||
&& c.status().equals("INCOMPATIBLE")),
|
||||
"Wrong Model Row accepted");
|
||||
check(
|
||||
((TextField) pane.lookup("#table-row"))
|
||||
.getText()
|
||||
.equals("fixture.components.VisitRow"),
|
||||
"Discovery replaced explicit Row");
|
||||
var attrs =
|
||||
(ComboBox<de.neitzel.fxdesigner.protocol.BindingMetadata.RepeatOption>)
|
||||
pane.lookup("#table-attributes");
|
||||
attrs
|
||||
.getSelectionModel()
|
||||
.select(
|
||||
attrs.getItems().stream()
|
||||
.filter(c -> c.name().equals("street"))
|
||||
.findFirst()
|
||||
.orElseThrow());
|
||||
return null;
|
||||
});
|
||||
check(documentText(document).equals(full), "Table discovery changed source");
|
||||
// The Row draft must participate in discovery even though the parent source is unchanged.
|
||||
var rowFile =
|
||||
java.nio.file.Path.of(document.snapshot().toCompletableFuture().get().document())
|
||||
.resolveSibling("VisitRow.fxml");
|
||||
String disk = java.nio.file.Files.readString(rowFile);
|
||||
try (var row =
|
||||
pane.kit().host().documents().open(rowFile.toUri()).toCompletableFuture().get()) {
|
||||
String original = documentText(row);
|
||||
set(row, original.replace("path=\"street\"", "path=\"different\""));
|
||||
await(() -> fx(() -> ((ComboBox<?>) pane.lookup("#table-rows")).getItems().isEmpty()));
|
||||
click(pane, "Discover / Validate Table");
|
||||
await(
|
||||
() ->
|
||||
fx(
|
||||
() ->
|
||||
((Label) pane.lookup("#table-status"))
|
||||
.getText()
|
||||
.contains("mismatch at Column")));
|
||||
check(
|
||||
java.nio.file.Files.readString(rowFile).equals(disk),
|
||||
"Row discovery saved or rewrote Row source");
|
||||
set(row, original);
|
||||
click(pane, "Discover / Validate Table");
|
||||
await(
|
||||
() ->
|
||||
fx(
|
||||
() ->
|
||||
((Label) pane.lookup("#table-status"))
|
||||
.getText()
|
||||
.contains("matches direct bindings")));
|
||||
}
|
||||
tableSelect(pane, "columns", 0);
|
||||
tableField(pane, "attribute", "missing");
|
||||
click(pane, "Apply Column");
|
||||
await(() -> !documentText(document).equals(full));
|
||||
String invalid = documentText(document);
|
||||
await(() -> fx(() -> source(pane).getText().equals(invalid)));
|
||||
document
|
||||
.save(document.snapshot().toCompletableFuture().get().revision())
|
||||
.toCompletableFuture()
|
||||
.get();
|
||||
click(pane, "Render drafts");
|
||||
await(
|
||||
() ->
|
||||
fx(
|
||||
() ->
|
||||
pane.lookupAll(".label").stream()
|
||||
.anyMatch(
|
||||
n ->
|
||||
n instanceof Label l
|
||||
&& l.getText() != null
|
||||
&& l.getText().startsWith("Preview blocked:")
|
||||
&& l.getText().contains("simple read/write Attribute"))));
|
||||
repeatHistory(pane, document, full, invalid);
|
||||
click(pane, "Undo");
|
||||
await(() -> documentText(document).equals(full));
|
||||
await(() -> fx(() -> source(pane).getText().equals(full)));
|
||||
System.out.println(
|
||||
"PASS Table discovery: choices, explicit selection, Row draft overlays/alignment, type"
|
||||
+ " errors, preview gating and undo/redo");
|
||||
}
|
||||
|
||||
private static void tableEdits(DesignerPane pane, DocumentSession document, String full)
|
||||
throws Exception {
|
||||
set(document, full);
|
||||
@@ -1413,6 +1525,7 @@ public final class ProjectionHostChecks {
|
||||
directBindingEdits(pane, document, full);
|
||||
computedBindingEdits(pane, document, full);
|
||||
repeatBindingEdits(pane, document, full);
|
||||
tableDiscovery(pane, document, full);
|
||||
tableEdits(pane, document, full);
|
||||
document
|
||||
.save(document.snapshot().toCompletableFuture().get().revision())
|
||||
|
||||
Reference in New Issue
Block a user