implements PR-07c asset details and form lifecycle
This commit is contained in:
parent
3e0592e75c
commit
03ca81cd1e
@ -1,22 +1,8 @@
|
||||
package p.studio.workspaces.assets;
|
||||
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ProgressBar;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.control.SplitPane;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
import p.studio.Container;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycle;
|
||||
@ -27,21 +13,22 @@ import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
import p.studio.workspaces.framework.StudioSubscriptionBag;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
final class AssetWorkspaceDetailsControl extends VBox implements StudioControlLifecycle {
|
||||
private final ProjectReference projectReference;
|
||||
private final StudioWorkspaceEventBus workspaceBus;
|
||||
private final AssetWorkspaceInteractionPort interactions;
|
||||
private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag();
|
||||
private final Label workspaceSummaryLabel = new Label();
|
||||
private final VBox detailsContent = new VBox(12);
|
||||
private final ScrollPane detailsScroll = new ScrollPane();
|
||||
private final AssetWorkspaceSummaryActionsControl summaryActionsControl;
|
||||
private final AssetWorkspaceRuntimeContractControl runtimeContractControl;
|
||||
private final AssetWorkspaceInputsPreviewControl inputsPreviewControl;
|
||||
private final AssetWorkspaceDiagnosticsControl diagnosticsControl;
|
||||
|
||||
private AssetWorkspaceDetailsViewState viewState;
|
||||
private boolean readyMounted;
|
||||
|
||||
AssetWorkspaceDetailsControl(
|
||||
ProjectReference projectReference,
|
||||
@ -50,7 +37,10 @@ final class AssetWorkspaceDetailsControl extends VBox implements StudioControlLi
|
||||
StudioControlLifecycleSupport.install(this, this);
|
||||
this.projectReference = Objects.requireNonNull(projectReference, "projectReference");
|
||||
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
||||
this.interactions = Objects.requireNonNull(interactions, "interactions");
|
||||
this.summaryActionsControl = new AssetWorkspaceSummaryActionsControl(projectReference, workspaceBus, interactions);
|
||||
this.runtimeContractControl = new AssetWorkspaceRuntimeContractControl(projectReference, workspaceBus, interactions);
|
||||
this.inputsPreviewControl = new AssetWorkspaceInputsPreviewControl(projectReference, workspaceBus, interactions);
|
||||
this.diagnosticsControl = new AssetWorkspaceDiagnosticsControl(projectReference, workspaceBus);
|
||||
|
||||
getStyleClass().add("assets-workspace-pane");
|
||||
setSpacing(10);
|
||||
@ -74,7 +64,8 @@ final class AssetWorkspaceDetailsControl extends VBox implements StudioControlLi
|
||||
public void subscribe() {
|
||||
subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> {
|
||||
if (projectReference.equals(event.project())) {
|
||||
applyViewState(event.viewState());
|
||||
viewState = event.viewState();
|
||||
render();
|
||||
}
|
||||
}));
|
||||
}
|
||||
@ -88,483 +79,47 @@ final class AssetWorkspaceDetailsControl extends VBox implements StudioControlLi
|
||||
detailsScroll.setVvalue(0.0d);
|
||||
}
|
||||
|
||||
private void applyViewState(AssetWorkspaceDetailsViewState viewState) {
|
||||
this.viewState = viewState;
|
||||
render();
|
||||
}
|
||||
|
||||
private void render() {
|
||||
detailsContent.getChildren().clear();
|
||||
if (viewState == null) {
|
||||
readyMounted = false;
|
||||
workspaceSummaryLabel.setText(Container.i18n().text(I18n.ASSETS_SUMMARY_LOADING));
|
||||
detailsContent.getChildren().add(createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING)));
|
||||
detailsContent.getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING)));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (viewState.workspaceState().status()) {
|
||||
case LOADING -> {
|
||||
readyMounted = false;
|
||||
workspaceSummaryLabel.setText(Container.i18n().text(I18n.ASSETS_SUMMARY_LOADING));
|
||||
detailsContent.getChildren().add(createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING)));
|
||||
detailsContent.getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING)));
|
||||
}
|
||||
case EMPTY -> {
|
||||
readyMounted = false;
|
||||
workspaceSummaryLabel.setText(Container.i18n().text(I18n.ASSETS_SUMMARY_EMPTY));
|
||||
detailsContent.getChildren().add(createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_EMPTY)));
|
||||
detailsContent.getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_EMPTY)));
|
||||
}
|
||||
case ERROR -> {
|
||||
readyMounted = false;
|
||||
workspaceSummaryLabel.setText(Container.i18n().text(I18n.ASSETS_SUMMARY_ERROR));
|
||||
detailsContent.getChildren().add(createSectionMessage(viewState.workspaceState().errorMessage()));
|
||||
detailsContent.getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSectionMessage(viewState.workspaceState().errorMessage()));
|
||||
}
|
||||
case READY -> {
|
||||
workspaceSummaryLabel.setText(Container.i18n().format(I18n.ASSETS_SUMMARY_READY, viewState.workspaceState().assets().size()));
|
||||
viewState.workspaceState().selectedAsset()
|
||||
.ifPresentOrElse(this::renderSelectedAssetDetails, () ->
|
||||
detailsContent.getChildren().add(createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_NO_SELECTION))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderSelectedAssetDetails(AssetWorkspaceAssetSummary summary) {
|
||||
detailsContent.getChildren().add(createSummaryActionsRow(summary));
|
||||
if (viewState.detailsStatus() == AssetWorkspaceDetailsStatus.LOADING) {
|
||||
detailsContent.getChildren().add(createLoadingSections());
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewState.detailsStatus() == AssetWorkspaceDetailsStatus.ERROR || viewState.selectedAssetDetails() == null) {
|
||||
final String message = Objects.requireNonNullElse(viewState.detailsErrorMessage(), Container.i18n().text(I18n.ASSETS_DETAILS_EMPTY));
|
||||
detailsContent.getChildren().add(createDetailsErrorSections(message));
|
||||
return;
|
||||
}
|
||||
|
||||
detailsContent.getChildren().add(createRuntimeContractSection(viewState.selectedAssetDetails()));
|
||||
detailsContent.getChildren().add(createInputsPreviewSection(viewState.selectedAssetDetails()));
|
||||
detailsContent.getChildren().add(createDiagnosticsSection(viewState.selectedAssetDetails()));
|
||||
}
|
||||
|
||||
private Node createLoadingSections() {
|
||||
final VBox box = new VBox(10);
|
||||
box.getChildren().add(createSection(Container.i18n().text(I18n.ASSETS_SECTION_RUNTIME_CONTRACT), createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING))));
|
||||
box.getChildren().add(createSection(Container.i18n().text(I18n.ASSETS_SECTION_INPUTS_PREVIEW), createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING))));
|
||||
box.getChildren().add(createSection(Container.i18n().text(I18n.ASSETS_SECTION_DIAGNOSTICS), createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING))));
|
||||
return box;
|
||||
}
|
||||
|
||||
private Node createDetailsErrorSections(String message) {
|
||||
final VBox box = new VBox(10);
|
||||
box.getChildren().add(createSection(Container.i18n().text(I18n.ASSETS_SECTION_RUNTIME_CONTRACT), createSectionMessage(message)));
|
||||
box.getChildren().add(createSection(Container.i18n().text(I18n.ASSETS_SECTION_INPUTS_PREVIEW), createSectionMessage(message)));
|
||||
box.getChildren().add(createSection(Container.i18n().text(I18n.ASSETS_SECTION_DIAGNOSTICS), createSectionMessage(message)));
|
||||
return box;
|
||||
}
|
||||
|
||||
private Node createSummaryActionsRow(AssetWorkspaceAssetSummary summary) {
|
||||
final HBox row = new HBox(12);
|
||||
row.getStyleClass().add("assets-details-summary-actions-row");
|
||||
|
||||
final VBox summarySection = createSummarySection(summary);
|
||||
final VBox actionsSection = createActionsSection(summary);
|
||||
HBox.setHgrow(summarySection, Priority.ALWAYS);
|
||||
HBox.setHgrow(actionsSection, Priority.NEVER);
|
||||
summarySection.setMaxWidth(Double.MAX_VALUE);
|
||||
summarySection.setMinWidth(0);
|
||||
actionsSection.setPrefWidth(280);
|
||||
actionsSection.setMinWidth(240);
|
||||
actionsSection.setMaxWidth(320);
|
||||
|
||||
row.getChildren().addAll(summarySection, actionsSection);
|
||||
return row;
|
||||
}
|
||||
|
||||
private VBox createSummarySection(AssetWorkspaceAssetSummary summary) {
|
||||
final VBox content = new VBox(8);
|
||||
content.getChildren().addAll(
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_NAME), summary.assetName()),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_REGISTRATION), registrationLabel(summary.state())),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_BUILD_PARTICIPATION), buildParticipationLabel(summary.buildParticipation())),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_ASSET_ID), summary.assetId() == null ? "—" : String.valueOf(summary.assetId())),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_TYPE), summary.assetFamily()),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), projectRelativePath(summary.assetRoot())));
|
||||
return createSection(Container.i18n().text(I18n.ASSETS_SECTION_SUMMARY), content);
|
||||
}
|
||||
|
||||
private VBox createActionsSection(AssetWorkspaceAssetSummary summary) {
|
||||
final AssetWorkspaceActionSet actionSet = AssetWorkspaceActionSetBuilder.forAsset(summary);
|
||||
final VBox content = new VBox(12);
|
||||
for (AssetWorkspaceAction action : actionSet.primaryActions()) {
|
||||
content.getChildren().add(createActionButton(action, false));
|
||||
}
|
||||
for (AssetWorkspaceAction action : actionSet.sensitiveActions()) {
|
||||
content.getChildren().add(createActionButton(action, true));
|
||||
}
|
||||
|
||||
if (viewState.stagedMutationPreview() != null
|
||||
&& viewState.stagedMutationPreview().asset().selectionKey().equals(summary.selectionKey())) {
|
||||
content.getChildren().add(createStagedMutationPanel(viewState.stagedMutationPreview()));
|
||||
}
|
||||
return createSection(Container.i18n().text(I18n.ASSETS_SECTION_ACTIONS), content);
|
||||
}
|
||||
|
||||
private Button createActionButton(AssetWorkspaceAction action, boolean sensitive) {
|
||||
final Button button = new Button(actionLabel(action));
|
||||
button.getStyleClass().addAll("studio-button", actionButtonVariant(action, sensitive));
|
||||
button.setMaxWidth(Double.MAX_VALUE);
|
||||
button.setOnAction(event -> interactions.requestMutationPreview(action));
|
||||
return button;
|
||||
}
|
||||
|
||||
private Node createRuntimeContractSection(AssetWorkspaceAssetDetails details) {
|
||||
final VBox content = new VBox(8);
|
||||
content.getChildren().addAll(
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_PRELOAD), createPreloadToggle(details)),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_FORMAT), details.outputFormat()),
|
||||
createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_CODEC), details.outputCodec()));
|
||||
return createSection(Container.i18n().text(I18n.ASSETS_SECTION_RUNTIME_CONTRACT), content);
|
||||
}
|
||||
|
||||
private Node createInputsPreviewSection(AssetWorkspaceAssetDetails details) {
|
||||
if (details.inputsByRole().isEmpty()) {
|
||||
return createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_INPUTS_PREVIEW),
|
||||
createSectionMessage(Container.i18n().text(I18n.ASSETS_INPUTS_EMPTY)));
|
||||
}
|
||||
|
||||
final Path selectedPreviewInput = resolveSelectedPreviewInput(details);
|
||||
final VBox inputsList = new VBox(8);
|
||||
for (Map.Entry<String, List<Path>> entry : details.inputsByRole().entrySet()) {
|
||||
final VBox roleBox = new VBox(6);
|
||||
final Label roleLabel = new Label(entry.getKey());
|
||||
roleLabel.getStyleClass().add("assets-details-role-label");
|
||||
roleBox.getChildren().add(roleLabel);
|
||||
for (Path input : entry.getValue()) {
|
||||
final Button inputButton = new Button(input.getFileName().toString());
|
||||
inputButton.getStyleClass().addAll("assets-details-input-button", "studio-button", "studio-button-secondary");
|
||||
if (input.equals(selectedPreviewInput)) {
|
||||
inputButton.getStyleClass().add("studio-button-active");
|
||||
if (viewState.workspaceState().selectedAsset().isEmpty()) {
|
||||
readyMounted = false;
|
||||
detailsContent.getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_NO_SELECTION)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!readyMounted) {
|
||||
readyMounted = true;
|
||||
detailsContent.getChildren().setAll(
|
||||
summaryActionsControl,
|
||||
runtimeContractControl,
|
||||
inputsPreviewControl,
|
||||
diagnosticsControl);
|
||||
}
|
||||
inputButton.setMaxWidth(Double.MAX_VALUE);
|
||||
inputButton.setOnAction(event -> interactions.updatePreviewInput(input));
|
||||
roleBox.getChildren().add(inputButton);
|
||||
}
|
||||
inputsList.getChildren().add(roleBox);
|
||||
}
|
||||
|
||||
final Node previewPane = createPreviewPane(selectedPreviewInput);
|
||||
final SplitPane splitPane = new SplitPane(inputsList, previewPane);
|
||||
splitPane.setOrientation(Orientation.HORIZONTAL);
|
||||
splitPane.setDividerPositions(0.34);
|
||||
splitPane.getStyleClass().add("assets-details-input-preview-split");
|
||||
return createSection(Container.i18n().text(I18n.ASSETS_SECTION_INPUTS_PREVIEW), splitPane);
|
||||
}
|
||||
|
||||
private Path resolveSelectedPreviewInput(AssetWorkspaceAssetDetails details) {
|
||||
final Path selectedPreviewInput = viewState.selectedPreviewInput();
|
||||
if (selectedPreviewInput == null || !containsInput(details, selectedPreviewInput)) {
|
||||
return details.inputsByRole().values().stream().flatMap(List::stream).findFirst().orElse(null);
|
||||
}
|
||||
return selectedPreviewInput;
|
||||
}
|
||||
|
||||
private Node createDiagnosticsSection(AssetWorkspaceAssetDetails details) {
|
||||
if (details.diagnostics().isEmpty()) {
|
||||
return createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_DIAGNOSTICS),
|
||||
createSectionMessage(Container.i18n().text(I18n.ASSETS_DIAGNOSTICS_EMPTY)));
|
||||
}
|
||||
|
||||
final VBox diagnosticsBox = new VBox(8);
|
||||
for (AssetWorkspaceDiagnostic diagnostic : details.diagnostics()) {
|
||||
final VBox card = new VBox(4);
|
||||
card.getStyleClass().add("assets-details-diagnostic-card");
|
||||
card.getStyleClass().add("assets-details-diagnostic-" + diagnostic.severity().name().toLowerCase());
|
||||
final Label severity = new Label(diagnostic.severity().name());
|
||||
severity.getStyleClass().add("assets-details-diagnostic-severity");
|
||||
final Label message = new Label(diagnostic.message());
|
||||
message.getStyleClass().add("assets-details-diagnostic-message");
|
||||
message.setWrapText(true);
|
||||
card.getChildren().addAll(severity, message);
|
||||
diagnosticsBox.getChildren().add(card);
|
||||
}
|
||||
return createSection(Container.i18n().text(I18n.ASSETS_SECTION_DIAGNOSTICS), diagnosticsBox);
|
||||
}
|
||||
|
||||
private Node createPreloadToggle(AssetWorkspaceAssetDetails details) {
|
||||
final boolean currentValue = details.summary().preload();
|
||||
final CheckBox checkBox = new CheckBox(yesNo(currentValue));
|
||||
checkBox.setSelected(currentValue);
|
||||
checkBox.setFocusTraversable(false);
|
||||
checkBox.getStyleClass().add("assets-details-readonly-check");
|
||||
checkBox.selectedProperty().addListener((ignored, previous, selected) -> checkBox.setText(yesNo(selected)));
|
||||
checkBox.setOnAction(event -> interactions.updatePreload(details, checkBox.isSelected(), checkBox));
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
private Node createPreviewPane(Path input) {
|
||||
final VBox previewBox = new VBox(10);
|
||||
previewBox.getStyleClass().add("assets-details-preview-pane");
|
||||
if (input == null) {
|
||||
previewBox.getChildren().add(createSectionMessage(Container.i18n().text(I18n.ASSETS_PREVIEW_EMPTY)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
final Label title = new Label(input.getFileName().toString());
|
||||
title.getStyleClass().add("assets-details-preview-title");
|
||||
previewBox.getChildren().add(title);
|
||||
|
||||
final String extension = extensionOf(input);
|
||||
if (isImage(extension)) {
|
||||
try {
|
||||
final Image image = new Image(input.toUri().toString(), false);
|
||||
final ImageView imageView = new ImageView(image);
|
||||
imageView.setPreserveRatio(true);
|
||||
imageView.setSmooth(false);
|
||||
imageView.getStyleClass().add("assets-details-preview-image");
|
||||
previewBox.getChildren().add(createPreviewZoomBar(image));
|
||||
AssetWorkspace.applyPreviewScale(image, imageView, viewState.selectedPreviewZoom());
|
||||
previewBox.getChildren().add(imageView);
|
||||
} catch (RuntimeException runtimeException) {
|
||||
previewBox.getChildren().add(createSectionMessage(Container.i18n().text(I18n.ASSETS_PREVIEW_IMAGE_ERROR)));
|
||||
}
|
||||
previewBox.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), projectRelativePath(input)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
if (isText(extension)) {
|
||||
final TextArea textArea = new TextArea(AssetWorkspace.readPreviewText(input));
|
||||
textArea.setWrapText(true);
|
||||
textArea.setEditable(false);
|
||||
textArea.getStyleClass().add("assets-details-preview-text");
|
||||
previewBox.getChildren().add(textArea);
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
if (isAudio(extension)) {
|
||||
previewBox.getChildren().add(createSectionMessage(Container.i18n().format(I18n.ASSETS_PREVIEW_AUDIO_PLACEHOLDER, input.getFileName().toString())));
|
||||
previewBox.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), projectRelativePath(input)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
previewBox.getChildren().add(createSectionMessage(Container.i18n().format(I18n.ASSETS_PREVIEW_GENERIC_PLACEHOLDER, input.getFileName().toString())));
|
||||
previewBox.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), projectRelativePath(input)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
private Node createPreviewZoomBar(Image image) {
|
||||
final HBox zoomBar = new HBox(8);
|
||||
zoomBar.setAlignment(Pos.CENTER_LEFT);
|
||||
zoomBar.getStyleClass().add("assets-details-preview-zoom-bar");
|
||||
|
||||
final Label zoomLabel = new Label(Container.i18n().text(I18n.ASSETS_PREVIEW_ZOOM));
|
||||
zoomLabel.getStyleClass().add("assets-details-preview-zoom-label");
|
||||
zoomBar.getChildren().add(zoomLabel);
|
||||
|
||||
final ToggleGroup zoomGroup = new ToggleGroup();
|
||||
final int maxZoom = AssetWorkspace.maxPreviewZoom(image);
|
||||
for (int zoom : List.of(1, 2, 4, 8)) {
|
||||
final ToggleButton button = new ToggleButton("x" + zoom);
|
||||
button.getStyleClass().addAll(
|
||||
"assets-details-preview-zoom-button",
|
||||
"studio-button",
|
||||
"studio-button-secondary",
|
||||
"studio-button-pill",
|
||||
"studio-button-toggle");
|
||||
button.setToggleGroup(zoomGroup);
|
||||
button.setSelected(viewState.selectedPreviewZoom() == zoom);
|
||||
button.setDisable(zoom > maxZoom);
|
||||
button.setOnAction(event -> interactions.updatePreviewZoom(zoom));
|
||||
zoomBar.getChildren().add(button);
|
||||
}
|
||||
return zoomBar;
|
||||
}
|
||||
|
||||
private Node createStagedMutationPanel(AssetWorkspaceMutationPreview preview) {
|
||||
final VBox panel = new VBox(10);
|
||||
panel.getStyleClass().add("assets-mutation-panel");
|
||||
|
||||
final Label title = new Label(Container.i18n().format(I18n.ASSETS_MUTATION_PREVIEW_TITLE, actionLabel(preview.action())));
|
||||
title.getStyleClass().add("assets-mutation-panel-title");
|
||||
panel.getChildren().add(title);
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_AFFECTED_ASSET),
|
||||
createAffectedAssetContent(preview)));
|
||||
|
||||
final AssetWorkspaceMutationImpactViewModel impacts = AssetWorkspaceMutationImpactViewModel.from(preview);
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_REGISTRY_IMPACT),
|
||||
createMutationChangesContent(impacts.registryChanges(), Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_REGISTRY_IMPACT))));
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_WORKSPACE_IMPACT),
|
||||
createMutationChangesContent(impacts.workspaceChanges(), Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_WORKSPACE_IMPACT))));
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_BLOCKERS),
|
||||
createMutationMessages(preview.blockers(), "assets-mutation-message-blocker", Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_BLOCKERS))));
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_WARNINGS),
|
||||
createMutationMessages(preview.warnings(), "assets-mutation-message-warning", Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_WARNINGS))));
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_SAFE_FIXES),
|
||||
createMutationMessages(preview.safeFixes(), "assets-mutation-message-safe-fix", Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_SAFE_FIXES))));
|
||||
|
||||
final HBox actions = new HBox(8);
|
||||
final Button cancel = new Button(Container.i18n().text(I18n.ASSETS_MUTATION_CANCEL));
|
||||
cancel.getStyleClass().addAll("studio-button", "studio-button-cancel");
|
||||
cancel.setOnAction(event -> interactions.cancelStagedMutationPreview());
|
||||
final Button apply = new Button(Container.i18n().text(I18n.ASSETS_MUTATION_APPLY));
|
||||
apply.getStyleClass().addAll("studio-button", "studio-button-primary");
|
||||
apply.setDisable(!preview.canApply());
|
||||
apply.setOnAction(event -> interactions.applyStagedMutation(preview));
|
||||
actions.getChildren().addAll(cancel, apply);
|
||||
panel.getChildren().add(actions);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private Node createMutationSection(String title, Node content) {
|
||||
final VBox section = new VBox(6);
|
||||
final Label label = new Label(title);
|
||||
label.getStyleClass().add("assets-mutation-section-title");
|
||||
section.getChildren().addAll(label, content);
|
||||
return section;
|
||||
}
|
||||
|
||||
private Node createAffectedAssetContent(AssetWorkspaceMutationPreview preview) {
|
||||
final VBox box = new VBox(6);
|
||||
box.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_NAME), preview.asset().assetName()));
|
||||
box.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), projectRelativePath(preview.asset().assetRoot())));
|
||||
if (preview.targetAssetRoot() != null) {
|
||||
box.getChildren().add(createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_TARGET_LOCATION), projectRelativePath(preview.targetAssetRoot())));
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
private Node createMutationChangesContent(List<AssetWorkspaceMutationChange> changes, String emptyText) {
|
||||
if (changes.isEmpty()) {
|
||||
return createSectionMessage(emptyText);
|
||||
}
|
||||
final VBox box = new VBox(6);
|
||||
for (AssetWorkspaceMutationChange change : changes) {
|
||||
final Label label = new Label(change.verb() + " · " + change.target());
|
||||
label.getStyleClass().add("assets-mutation-change");
|
||||
box.getChildren().add(label);
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
private Node createMutationMessages(List<String> messages, String styleClass, String emptyText) {
|
||||
if (messages.isEmpty()) {
|
||||
return createSectionMessage(emptyText);
|
||||
}
|
||||
final VBox box = new VBox(6);
|
||||
for (String message : messages) {
|
||||
final Label label = new Label(message);
|
||||
label.setWrapText(true);
|
||||
label.getStyleClass().add(styleClass);
|
||||
box.getChildren().add(label);
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
private VBox createSection(String title, Node content) {
|
||||
final VBox section = new VBox(10);
|
||||
section.getStyleClass().add("assets-details-section");
|
||||
final Label titleLabel = new Label(title);
|
||||
titleLabel.getStyleClass().add("assets-details-section-title");
|
||||
section.getChildren().addAll(titleLabel, content);
|
||||
return section;
|
||||
}
|
||||
|
||||
private Node createSectionMessage(String text) {
|
||||
final Label label = new Label(text);
|
||||
label.setWrapText(true);
|
||||
label.getStyleClass().add("assets-details-section-message");
|
||||
return label;
|
||||
}
|
||||
|
||||
private Node createKeyValueRow(String key, String value) {
|
||||
final Label valueLabel = new Label(value);
|
||||
valueLabel.getStyleClass().add("assets-details-value");
|
||||
valueLabel.setWrapText(true);
|
||||
return createKeyValueRow(key, valueLabel);
|
||||
}
|
||||
|
||||
private Node createKeyValueRow(String key, Node valueNode) {
|
||||
final HBox row = new HBox(12);
|
||||
row.setAlignment(Pos.TOP_LEFT);
|
||||
final Label keyLabel = new Label(key);
|
||||
keyLabel.getStyleClass().add("assets-details-key");
|
||||
HBox.setHgrow(valueNode, Priority.ALWAYS);
|
||||
row.getChildren().addAll(keyLabel, valueNode);
|
||||
return row;
|
||||
}
|
||||
|
||||
private String registrationLabel(AssetWorkspaceAssetState state) {
|
||||
return switch (state) {
|
||||
case REGISTERED -> Container.i18n().text(I18n.ASSETS_VALUE_REGISTERED);
|
||||
case UNREGISTERED -> Container.i18n().text(I18n.ASSETS_VALUE_UNREGISTERED);
|
||||
};
|
||||
}
|
||||
|
||||
private String buildParticipationLabel(AssetWorkspaceBuildParticipation buildParticipation) {
|
||||
return switch (buildParticipation) {
|
||||
case INCLUDED -> Container.i18n().text(I18n.ASSETS_VALUE_INCLUDED);
|
||||
case EXCLUDED -> Container.i18n().text(I18n.ASSETS_VALUE_EXCLUDED);
|
||||
};
|
||||
}
|
||||
|
||||
private String yesNo(boolean value) {
|
||||
return value ? Container.i18n().text(I18n.ASSETS_VALUE_YES) : Container.i18n().text(I18n.ASSETS_VALUE_NO);
|
||||
}
|
||||
|
||||
private String projectRelativePath(Path path) {
|
||||
try {
|
||||
return projectReference.rootPath().relativize(path.toAbsolutePath().normalize()).toString();
|
||||
} catch (RuntimeException runtimeException) {
|
||||
return path.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String actionLabel(AssetWorkspaceAction action) {
|
||||
return switch (action) {
|
||||
case REGISTER -> Container.i18n().text(I18n.ASSETS_ACTION_REGISTER);
|
||||
case INCLUDE_IN_BUILD -> Container.i18n().text(I18n.ASSETS_ACTION_INCLUDE_IN_BUILD);
|
||||
case EXCLUDE_FROM_BUILD -> Container.i18n().text(I18n.ASSETS_ACTION_EXCLUDE_FROM_BUILD);
|
||||
case RELOCATE -> Container.i18n().text(I18n.ASSETS_ACTION_RELOCATE);
|
||||
case REMOVE -> Container.i18n().text(I18n.ASSETS_ACTION_REMOVE);
|
||||
};
|
||||
}
|
||||
|
||||
private String actionButtonVariant(AssetWorkspaceAction action, boolean sensitive) {
|
||||
if (!sensitive) {
|
||||
return "studio-button-primary";
|
||||
}
|
||||
return switch (action) {
|
||||
case RELOCATE -> "studio-button-warning";
|
||||
case EXCLUDE_FROM_BUILD, REMOVE -> "studio-button-danger";
|
||||
default -> "studio-button-secondary";
|
||||
};
|
||||
}
|
||||
|
||||
private boolean containsInput(AssetWorkspaceAssetDetails details, Path input) {
|
||||
return details.inputsByRole().values().stream().flatMap(List::stream).anyMatch(input::equals);
|
||||
}
|
||||
|
||||
private String extensionOf(Path input) {
|
||||
final String fileName = input.getFileName().toString();
|
||||
final int dot = fileName.lastIndexOf('.');
|
||||
if (dot < 0 || dot == fileName.length() - 1) {
|
||||
return "";
|
||||
}
|
||||
return fileName.substring(dot + 1).toLowerCase();
|
||||
}
|
||||
|
||||
private boolean isImage(String extension) {
|
||||
return extension.equals("png") || extension.equals("jpg") || extension.equals("jpeg") || extension.equals("gif");
|
||||
}
|
||||
|
||||
private boolean isText(String extension) {
|
||||
return extension.equals("txt") || extension.equals("json") || extension.equals("md") || extension.equals("xml") || extension.equals("csv");
|
||||
}
|
||||
|
||||
private boolean isAudio(String extension) {
|
||||
return extension.equals("wav") || extension.equals("mp3") || extension.equals("ogg");
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,125 @@
|
||||
package p.studio.workspaces.assets;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import p.studio.Container;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
final class AssetWorkspaceDetailsUiSupport {
|
||||
private AssetWorkspaceDetailsUiSupport() {
|
||||
}
|
||||
|
||||
static VBox createSection(String title, Node content) {
|
||||
final VBox section = new VBox(10);
|
||||
section.getStyleClass().add("assets-details-section");
|
||||
final Label titleLabel = new Label(title);
|
||||
titleLabel.getStyleClass().add("assets-details-section-title");
|
||||
section.getChildren().addAll(titleLabel, content);
|
||||
return section;
|
||||
}
|
||||
|
||||
static Node createSectionMessage(String text) {
|
||||
final Label label = new Label(text);
|
||||
label.setWrapText(true);
|
||||
label.getStyleClass().add("assets-details-section-message");
|
||||
return label;
|
||||
}
|
||||
|
||||
static Node createKeyValueRow(String key, String value) {
|
||||
final Label valueLabel = new Label(value);
|
||||
valueLabel.getStyleClass().add("assets-details-value");
|
||||
valueLabel.setWrapText(true);
|
||||
return createKeyValueRow(key, valueLabel);
|
||||
}
|
||||
|
||||
static Node createKeyValueRow(String key, Node valueNode) {
|
||||
final HBox row = new HBox(12);
|
||||
row.setAlignment(Pos.TOP_LEFT);
|
||||
final Label keyLabel = new Label(key);
|
||||
keyLabel.getStyleClass().add("assets-details-key");
|
||||
HBox.setHgrow(valueNode, Priority.ALWAYS);
|
||||
row.getChildren().addAll(keyLabel, valueNode);
|
||||
return row;
|
||||
}
|
||||
|
||||
static String registrationLabel(AssetWorkspaceAssetState state) {
|
||||
return switch (state) {
|
||||
case REGISTERED -> Container.i18n().text(I18n.ASSETS_VALUE_REGISTERED);
|
||||
case UNREGISTERED -> Container.i18n().text(I18n.ASSETS_VALUE_UNREGISTERED);
|
||||
};
|
||||
}
|
||||
|
||||
static String buildParticipationLabel(AssetWorkspaceBuildParticipation buildParticipation) {
|
||||
return switch (buildParticipation) {
|
||||
case INCLUDED -> Container.i18n().text(I18n.ASSETS_VALUE_INCLUDED);
|
||||
case EXCLUDED -> Container.i18n().text(I18n.ASSETS_VALUE_EXCLUDED);
|
||||
};
|
||||
}
|
||||
|
||||
static String yesNo(boolean value) {
|
||||
return value ? Container.i18n().text(I18n.ASSETS_VALUE_YES) : Container.i18n().text(I18n.ASSETS_VALUE_NO);
|
||||
}
|
||||
|
||||
static String projectRelativePath(ProjectReference projectReference, Path path) {
|
||||
try {
|
||||
return projectReference.rootPath().relativize(path.toAbsolutePath().normalize()).toString();
|
||||
} catch (RuntimeException runtimeException) {
|
||||
return path.toString();
|
||||
}
|
||||
}
|
||||
|
||||
static String actionLabel(AssetWorkspaceAction action) {
|
||||
return switch (action) {
|
||||
case REGISTER -> Container.i18n().text(I18n.ASSETS_ACTION_REGISTER);
|
||||
case INCLUDE_IN_BUILD -> Container.i18n().text(I18n.ASSETS_ACTION_INCLUDE_IN_BUILD);
|
||||
case EXCLUDE_FROM_BUILD -> Container.i18n().text(I18n.ASSETS_ACTION_EXCLUDE_FROM_BUILD);
|
||||
case RELOCATE -> Container.i18n().text(I18n.ASSETS_ACTION_RELOCATE);
|
||||
case REMOVE -> Container.i18n().text(I18n.ASSETS_ACTION_REMOVE);
|
||||
};
|
||||
}
|
||||
|
||||
static String actionButtonVariant(AssetWorkspaceAction action, boolean sensitive) {
|
||||
if (!sensitive) {
|
||||
return "studio-button-primary";
|
||||
}
|
||||
return switch (action) {
|
||||
case RELOCATE -> "studio-button-warning";
|
||||
case EXCLUDE_FROM_BUILD, REMOVE -> "studio-button-danger";
|
||||
default -> "studio-button-secondary";
|
||||
};
|
||||
}
|
||||
|
||||
static boolean containsInput(AssetWorkspaceAssetDetails details, Path input) {
|
||||
return details.inputsByRole().values().stream().flatMap(List::stream).anyMatch(input::equals);
|
||||
}
|
||||
|
||||
static String extensionOf(Path input) {
|
||||
final String fileName = input.getFileName().toString();
|
||||
final int dot = fileName.lastIndexOf('.');
|
||||
if (dot < 0 || dot == fileName.length() - 1) {
|
||||
return "";
|
||||
}
|
||||
return fileName.substring(dot + 1).toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
static boolean isImage(String extension) {
|
||||
return extension.equals("png") || extension.equals("jpg") || extension.equals("jpeg") || extension.equals("gif");
|
||||
}
|
||||
|
||||
static boolean isText(String extension) {
|
||||
return extension.equals("txt") || extension.equals("json") || extension.equals("md") || extension.equals("xml") || extension.equals("csv");
|
||||
}
|
||||
|
||||
static boolean isAudio(String extension) {
|
||||
return extension.equals("wav") || extension.equals("mp3") || extension.equals("ogg");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
package p.studio.workspaces.assets;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import p.studio.Container;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycle;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
|
||||
import p.studio.events.StudioAssetsDetailsViewStateChangedEvent;
|
||||
import p.studio.events.StudioWorkspaceEventBus;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
import p.studio.workspaces.framework.StudioSubscriptionBag;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
final class AssetWorkspaceDiagnosticsControl extends VBox implements StudioControlLifecycle {
|
||||
private final ProjectReference projectReference;
|
||||
private final StudioWorkspaceEventBus workspaceBus;
|
||||
private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag();
|
||||
private AssetWorkspaceDetailsViewState viewState;
|
||||
|
||||
AssetWorkspaceDiagnosticsControl(ProjectReference projectReference, StudioWorkspaceEventBus workspaceBus) {
|
||||
StudioControlLifecycleSupport.install(this, this);
|
||||
this.projectReference = Objects.requireNonNull(projectReference, "projectReference");
|
||||
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe() {
|
||||
subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> {
|
||||
if (projectReference.equals(event.project())) {
|
||||
viewState = event.viewState();
|
||||
render();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe() {
|
||||
subscriptions.clear();
|
||||
}
|
||||
|
||||
private void render() {
|
||||
if (viewState == null || viewState.workspaceState().selectedAsset().isEmpty()) {
|
||||
getChildren().clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewState.detailsStatus() == AssetWorkspaceDetailsStatus.LOADING) {
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_DIAGNOSTICS),
|
||||
AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING))));
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewState.detailsStatus() == AssetWorkspaceDetailsStatus.ERROR || viewState.selectedAssetDetails() == null) {
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_DIAGNOSTICS),
|
||||
AssetWorkspaceDetailsUiSupport.createSectionMessage(Objects.requireNonNullElse(viewState.detailsErrorMessage(), Container.i18n().text(I18n.ASSETS_DETAILS_EMPTY)))));
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewState.selectedAssetDetails().diagnostics().isEmpty()) {
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_DIAGNOSTICS),
|
||||
AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_DIAGNOSTICS_EMPTY))));
|
||||
return;
|
||||
}
|
||||
|
||||
final VBox diagnosticsBox = new VBox(8);
|
||||
for (AssetWorkspaceDiagnostic diagnostic : viewState.selectedAssetDetails().diagnostics()) {
|
||||
final VBox card = new VBox(4);
|
||||
card.getStyleClass().add("assets-details-diagnostic-card");
|
||||
card.getStyleClass().add("assets-details-diagnostic-" + diagnostic.severity().name().toLowerCase());
|
||||
final Label severity = new Label(diagnostic.severity().name());
|
||||
severity.getStyleClass().add("assets-details-diagnostic-severity");
|
||||
final Label message = new Label(diagnostic.message());
|
||||
message.getStyleClass().add("assets-details-diagnostic-message");
|
||||
message.setWrapText(true);
|
||||
card.getChildren().addAll(severity, message);
|
||||
diagnosticsBox.getChildren().add(card);
|
||||
}
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(Container.i18n().text(I18n.ASSETS_SECTION_DIAGNOSTICS), diagnosticsBox));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,202 @@
|
||||
package p.studio.workspaces.assets;
|
||||
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.SplitPane;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import p.studio.Container;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycle;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
|
||||
import p.studio.events.StudioAssetsDetailsViewStateChangedEvent;
|
||||
import p.studio.events.StudioWorkspaceEventBus;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
import p.studio.workspaces.framework.StudioSubscriptionBag;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
final class AssetWorkspaceInputsPreviewControl extends VBox implements StudioControlLifecycle {
|
||||
private final ProjectReference projectReference;
|
||||
private final StudioWorkspaceEventBus workspaceBus;
|
||||
private final AssetWorkspaceInteractionPort interactions;
|
||||
private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag();
|
||||
private AssetWorkspaceDetailsViewState viewState;
|
||||
|
||||
AssetWorkspaceInputsPreviewControl(
|
||||
ProjectReference projectReference,
|
||||
StudioWorkspaceEventBus workspaceBus,
|
||||
AssetWorkspaceInteractionPort interactions) {
|
||||
StudioControlLifecycleSupport.install(this, this);
|
||||
this.projectReference = Objects.requireNonNull(projectReference, "projectReference");
|
||||
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
||||
this.interactions = Objects.requireNonNull(interactions, "interactions");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe() {
|
||||
subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> {
|
||||
if (projectReference.equals(event.project())) {
|
||||
viewState = event.viewState();
|
||||
render();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe() {
|
||||
subscriptions.clear();
|
||||
}
|
||||
|
||||
private void render() {
|
||||
if (viewState == null || viewState.workspaceState().selectedAsset().isEmpty()) {
|
||||
getChildren().clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewState.detailsStatus() == AssetWorkspaceDetailsStatus.LOADING) {
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_INPUTS_PREVIEW),
|
||||
AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING))));
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewState.detailsStatus() == AssetWorkspaceDetailsStatus.ERROR || viewState.selectedAssetDetails() == null) {
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_INPUTS_PREVIEW),
|
||||
AssetWorkspaceDetailsUiSupport.createSectionMessage(Objects.requireNonNullElse(viewState.detailsErrorMessage(), Container.i18n().text(I18n.ASSETS_DETAILS_EMPTY)))));
|
||||
return;
|
||||
}
|
||||
|
||||
final AssetWorkspaceAssetDetails details = viewState.selectedAssetDetails();
|
||||
if (details.inputsByRole().isEmpty()) {
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_INPUTS_PREVIEW),
|
||||
AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_INPUTS_EMPTY))));
|
||||
return;
|
||||
}
|
||||
|
||||
final Path selectedPreviewInput = resolveSelectedPreviewInput(details);
|
||||
final VBox inputsList = new VBox(8);
|
||||
for (Map.Entry<String, List<Path>> entry : details.inputsByRole().entrySet()) {
|
||||
final VBox roleBox = new VBox(6);
|
||||
final Label roleLabel = new Label(entry.getKey());
|
||||
roleLabel.getStyleClass().add("assets-details-role-label");
|
||||
roleBox.getChildren().add(roleLabel);
|
||||
for (Path input : entry.getValue()) {
|
||||
final Button inputButton = new Button(input.getFileName().toString());
|
||||
inputButton.getStyleClass().addAll("assets-details-input-button", "studio-button", "studio-button-secondary");
|
||||
if (input.equals(selectedPreviewInput)) {
|
||||
inputButton.getStyleClass().add("studio-button-active");
|
||||
}
|
||||
inputButton.setMaxWidth(Double.MAX_VALUE);
|
||||
inputButton.setOnAction(event -> interactions.updatePreviewInput(input));
|
||||
roleBox.getChildren().add(inputButton);
|
||||
}
|
||||
inputsList.getChildren().add(roleBox);
|
||||
}
|
||||
|
||||
final SplitPane splitPane = new SplitPane(inputsList, createPreviewPane(selectedPreviewInput));
|
||||
splitPane.setOrientation(Orientation.HORIZONTAL);
|
||||
splitPane.setDividerPositions(0.34);
|
||||
splitPane.getStyleClass().add("assets-details-input-preview-split");
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(Container.i18n().text(I18n.ASSETS_SECTION_INPUTS_PREVIEW), splitPane));
|
||||
}
|
||||
|
||||
private Path resolveSelectedPreviewInput(AssetWorkspaceAssetDetails details) {
|
||||
final Path selectedPreviewInput = viewState.selectedPreviewInput();
|
||||
if (selectedPreviewInput == null || !AssetWorkspaceDetailsUiSupport.containsInput(details, selectedPreviewInput)) {
|
||||
return details.inputsByRole().values().stream().flatMap(List::stream).findFirst().orElse(null);
|
||||
}
|
||||
return selectedPreviewInput;
|
||||
}
|
||||
|
||||
private Node createPreviewPane(Path input) {
|
||||
final VBox previewBox = new VBox(10);
|
||||
previewBox.getStyleClass().add("assets-details-preview-pane");
|
||||
if (input == null) {
|
||||
previewBox.getChildren().add(AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_PREVIEW_EMPTY)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
final Label title = new Label(input.getFileName().toString());
|
||||
title.getStyleClass().add("assets-details-preview-title");
|
||||
previewBox.getChildren().add(title);
|
||||
|
||||
final String extension = AssetWorkspaceDetailsUiSupport.extensionOf(input);
|
||||
if (AssetWorkspaceDetailsUiSupport.isImage(extension)) {
|
||||
try {
|
||||
final Image image = new Image(input.toUri().toString(), false);
|
||||
final ImageView imageView = new ImageView(image);
|
||||
imageView.setPreserveRatio(true);
|
||||
imageView.setSmooth(false);
|
||||
imageView.getStyleClass().add("assets-details-preview-image");
|
||||
previewBox.getChildren().add(createPreviewZoomBar(image));
|
||||
AssetWorkspace.applyPreviewScale(image, imageView, viewState.selectedPreviewZoom());
|
||||
previewBox.getChildren().add(imageView);
|
||||
} catch (RuntimeException runtimeException) {
|
||||
previewBox.getChildren().add(AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_PREVIEW_IMAGE_ERROR)));
|
||||
}
|
||||
previewBox.getChildren().add(AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), AssetWorkspaceDetailsUiSupport.projectRelativePath(projectReference, input)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
if (AssetWorkspaceDetailsUiSupport.isText(extension)) {
|
||||
final TextArea textArea = new TextArea(AssetWorkspace.readPreviewText(input));
|
||||
textArea.setWrapText(true);
|
||||
textArea.setEditable(false);
|
||||
textArea.getStyleClass().add("assets-details-preview-text");
|
||||
previewBox.getChildren().add(textArea);
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
if (AssetWorkspaceDetailsUiSupport.isAudio(extension)) {
|
||||
previewBox.getChildren().add(AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().format(I18n.ASSETS_PREVIEW_AUDIO_PLACEHOLDER, input.getFileName().toString())));
|
||||
previewBox.getChildren().add(AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), AssetWorkspaceDetailsUiSupport.projectRelativePath(projectReference, input)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
previewBox.getChildren().add(AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().format(I18n.ASSETS_PREVIEW_GENERIC_PLACEHOLDER, input.getFileName().toString())));
|
||||
previewBox.getChildren().add(AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), AssetWorkspaceDetailsUiSupport.projectRelativePath(projectReference, input)));
|
||||
return previewBox;
|
||||
}
|
||||
|
||||
private Node createPreviewZoomBar(Image image) {
|
||||
final HBox zoomBar = new HBox(8);
|
||||
zoomBar.setAlignment(Pos.CENTER_LEFT);
|
||||
zoomBar.getStyleClass().add("assets-details-preview-zoom-bar");
|
||||
|
||||
final Label zoomLabel = new Label(Container.i18n().text(I18n.ASSETS_PREVIEW_ZOOM));
|
||||
zoomLabel.getStyleClass().add("assets-details-preview-zoom-label");
|
||||
zoomBar.getChildren().add(zoomLabel);
|
||||
|
||||
final ToggleGroup zoomGroup = new ToggleGroup();
|
||||
final int maxZoom = AssetWorkspace.maxPreviewZoom(image);
|
||||
for (int zoom : List.of(1, 2, 4, 8)) {
|
||||
final ToggleButton button = new ToggleButton("x" + zoom);
|
||||
button.getStyleClass().addAll(
|
||||
"assets-details-preview-zoom-button",
|
||||
"studio-button",
|
||||
"studio-button-secondary",
|
||||
"studio-button-pill",
|
||||
"studio-button-toggle");
|
||||
button.setToggleGroup(zoomGroup);
|
||||
button.setSelected(viewState.selectedPreviewZoom() == zoom);
|
||||
button.setDisable(zoom > maxZoom);
|
||||
button.setOnAction(event -> interactions.updatePreviewZoom(zoom));
|
||||
zoomBar.getChildren().add(button);
|
||||
}
|
||||
return zoomBar;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package p.studio.workspaces.assets;
|
||||
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import p.studio.Container;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycle;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
|
||||
import p.studio.events.StudioAssetsDetailsViewStateChangedEvent;
|
||||
import p.studio.events.StudioWorkspaceEventBus;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
import p.studio.workspaces.framework.StudioSubscriptionBag;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
final class AssetWorkspaceRuntimeContractControl extends VBox implements StudioControlLifecycle {
|
||||
private final ProjectReference projectReference;
|
||||
private final StudioWorkspaceEventBus workspaceBus;
|
||||
private final AssetWorkspaceInteractionPort interactions;
|
||||
private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag();
|
||||
private AssetWorkspaceDetailsViewState viewState;
|
||||
|
||||
AssetWorkspaceRuntimeContractControl(
|
||||
ProjectReference projectReference,
|
||||
StudioWorkspaceEventBus workspaceBus,
|
||||
AssetWorkspaceInteractionPort interactions) {
|
||||
StudioControlLifecycleSupport.install(this, this);
|
||||
this.projectReference = Objects.requireNonNull(projectReference, "projectReference");
|
||||
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
||||
this.interactions = Objects.requireNonNull(interactions, "interactions");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe() {
|
||||
subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> {
|
||||
if (projectReference.equals(event.project())) {
|
||||
viewState = event.viewState();
|
||||
render();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe() {
|
||||
subscriptions.clear();
|
||||
}
|
||||
|
||||
private void render() {
|
||||
if (viewState == null || viewState.workspaceState().selectedAsset().isEmpty()) {
|
||||
getChildren().clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewState.detailsStatus() == AssetWorkspaceDetailsStatus.LOADING) {
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_RUNTIME_CONTRACT),
|
||||
AssetWorkspaceDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_DETAILS_LOADING))));
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewState.detailsStatus() == AssetWorkspaceDetailsStatus.ERROR || viewState.selectedAssetDetails() == null) {
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_RUNTIME_CONTRACT),
|
||||
AssetWorkspaceDetailsUiSupport.createSectionMessage(Objects.requireNonNullElse(viewState.detailsErrorMessage(), Container.i18n().text(I18n.ASSETS_DETAILS_EMPTY)))));
|
||||
return;
|
||||
}
|
||||
|
||||
final AssetWorkspaceAssetDetails details = viewState.selectedAssetDetails();
|
||||
final VBox content = new VBox(8);
|
||||
content.getChildren().addAll(
|
||||
AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_PRELOAD), createPreloadToggle(details)),
|
||||
AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_FORMAT), details.outputFormat()),
|
||||
AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_CODEC), details.outputCodec()));
|
||||
getChildren().setAll(AssetWorkspaceDetailsUiSupport.createSection(Container.i18n().text(I18n.ASSETS_SECTION_RUNTIME_CONTRACT), content));
|
||||
}
|
||||
|
||||
private CheckBox createPreloadToggle(AssetWorkspaceAssetDetails details) {
|
||||
final boolean currentValue = details.summary().preload();
|
||||
final CheckBox checkBox = new CheckBox(AssetWorkspaceDetailsUiSupport.yesNo(currentValue));
|
||||
checkBox.setSelected(currentValue);
|
||||
checkBox.setFocusTraversable(false);
|
||||
checkBox.getStyleClass().add("assets-details-readonly-check");
|
||||
checkBox.selectedProperty().addListener((ignored, previous, selected) -> checkBox.setText(AssetWorkspaceDetailsUiSupport.yesNo(selected)));
|
||||
checkBox.setOnAction(event -> interactions.updatePreload(details, checkBox.isSelected(), checkBox));
|
||||
return checkBox;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,203 @@
|
||||
package p.studio.workspaces.assets;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import p.studio.Container;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycle;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
|
||||
import p.studio.events.StudioAssetsDetailsViewStateChangedEvent;
|
||||
import p.studio.events.StudioWorkspaceEventBus;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
import p.studio.workspaces.framework.StudioSubscriptionBag;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
final class AssetWorkspaceSummaryActionsControl extends HBox implements StudioControlLifecycle {
|
||||
private final ProjectReference projectReference;
|
||||
private final StudioWorkspaceEventBus workspaceBus;
|
||||
private final AssetWorkspaceInteractionPort interactions;
|
||||
private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag();
|
||||
private AssetWorkspaceDetailsViewState viewState;
|
||||
|
||||
AssetWorkspaceSummaryActionsControl(
|
||||
ProjectReference projectReference,
|
||||
StudioWorkspaceEventBus workspaceBus,
|
||||
AssetWorkspaceInteractionPort interactions) {
|
||||
StudioControlLifecycleSupport.install(this, this);
|
||||
this.projectReference = Objects.requireNonNull(projectReference, "projectReference");
|
||||
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
||||
this.interactions = Objects.requireNonNull(interactions, "interactions");
|
||||
setSpacing(12);
|
||||
getStyleClass().add("assets-details-summary-actions-row");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe() {
|
||||
subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> {
|
||||
if (projectReference.equals(event.project())) {
|
||||
viewState = event.viewState();
|
||||
render();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe() {
|
||||
subscriptions.clear();
|
||||
}
|
||||
|
||||
private void render() {
|
||||
getChildren().clear();
|
||||
if (viewState == null) {
|
||||
return;
|
||||
}
|
||||
final AssetWorkspaceAssetSummary summary = viewState.workspaceState().selectedAsset().orElse(null);
|
||||
if (summary == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final VBox summarySection = createSummarySection(summary);
|
||||
final VBox actionsSection = createActionsSection(summary);
|
||||
HBox.setHgrow(summarySection, Priority.ALWAYS);
|
||||
HBox.setHgrow(actionsSection, Priority.NEVER);
|
||||
summarySection.setMaxWidth(Double.MAX_VALUE);
|
||||
summarySection.setMinWidth(0);
|
||||
actionsSection.setPrefWidth(280);
|
||||
actionsSection.setMinWidth(240);
|
||||
actionsSection.setMaxWidth(320);
|
||||
getChildren().setAll(summarySection, actionsSection);
|
||||
}
|
||||
|
||||
private VBox createSummarySection(AssetWorkspaceAssetSummary summary) {
|
||||
final VBox content = new VBox(8);
|
||||
content.getChildren().addAll(
|
||||
AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_NAME), summary.assetName()),
|
||||
AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_REGISTRATION), AssetWorkspaceDetailsUiSupport.registrationLabel(summary.state())),
|
||||
AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_BUILD_PARTICIPATION), AssetWorkspaceDetailsUiSupport.buildParticipationLabel(summary.buildParticipation())),
|
||||
AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_ASSET_ID), summary.assetId() == null ? "—" : String.valueOf(summary.assetId())),
|
||||
AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_TYPE), summary.assetFamily()),
|
||||
AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_LOCATION), AssetWorkspaceDetailsUiSupport.projectRelativePath(projectReference, summary.assetRoot())));
|
||||
return AssetWorkspaceDetailsUiSupport.createSection(Container.i18n().text(I18n.ASSETS_SECTION_SUMMARY), content);
|
||||
}
|
||||
|
||||
private VBox createActionsSection(AssetWorkspaceAssetSummary summary) {
|
||||
final AssetWorkspaceActionSet actionSet = AssetWorkspaceActionSetBuilder.forAsset(summary);
|
||||
final VBox content = new VBox(12);
|
||||
for (AssetWorkspaceAction action : actionSet.primaryActions()) {
|
||||
content.getChildren().add(createActionButton(action, false));
|
||||
}
|
||||
for (AssetWorkspaceAction action : actionSet.sensitiveActions()) {
|
||||
content.getChildren().add(createActionButton(action, true));
|
||||
}
|
||||
if (viewState.stagedMutationPreview() != null
|
||||
&& viewState.stagedMutationPreview().asset().selectionKey().equals(summary.selectionKey())) {
|
||||
content.getChildren().add(createStagedMutationPanel(viewState.stagedMutationPreview()));
|
||||
}
|
||||
return AssetWorkspaceDetailsUiSupport.createSection(Container.i18n().text(I18n.ASSETS_SECTION_ACTIONS), content);
|
||||
}
|
||||
|
||||
private Button createActionButton(AssetWorkspaceAction action, boolean sensitive) {
|
||||
final Button button = new Button(AssetWorkspaceDetailsUiSupport.actionLabel(action));
|
||||
button.getStyleClass().addAll("studio-button", AssetWorkspaceDetailsUiSupport.actionButtonVariant(action, sensitive));
|
||||
button.setMaxWidth(Double.MAX_VALUE);
|
||||
button.setOnAction(event -> interactions.requestMutationPreview(action));
|
||||
return button;
|
||||
}
|
||||
|
||||
private Node createStagedMutationPanel(AssetWorkspaceMutationPreview preview) {
|
||||
final VBox panel = new VBox(10);
|
||||
panel.getStyleClass().add("assets-mutation-panel");
|
||||
|
||||
final Label title = new Label(Container.i18n().format(I18n.ASSETS_MUTATION_PREVIEW_TITLE, AssetWorkspaceDetailsUiSupport.actionLabel(preview.action())));
|
||||
title.getStyleClass().add("assets-mutation-panel-title");
|
||||
panel.getChildren().add(title);
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_AFFECTED_ASSET),
|
||||
createAffectedAssetContent(preview)));
|
||||
|
||||
final AssetWorkspaceMutationImpactViewModel impacts = AssetWorkspaceMutationImpactViewModel.from(preview);
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_REGISTRY_IMPACT),
|
||||
createMutationChangesContent(impacts.registryChanges(), Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_REGISTRY_IMPACT))));
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_WORKSPACE_IMPACT),
|
||||
createMutationChangesContent(impacts.workspaceChanges(), Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_WORKSPACE_IMPACT))));
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_BLOCKERS),
|
||||
createMutationMessages(preview.blockers(), "assets-mutation-message-blocker", Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_BLOCKERS))));
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_WARNINGS),
|
||||
createMutationMessages(preview.warnings(), "assets-mutation-message-warning", Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_WARNINGS))));
|
||||
panel.getChildren().add(createMutationSection(
|
||||
Container.i18n().text(I18n.ASSETS_MUTATION_SECTION_SAFE_FIXES),
|
||||
createMutationMessages(preview.safeFixes(), "assets-mutation-message-safe-fix", Container.i18n().text(I18n.ASSETS_MUTATION_EMPTY_SAFE_FIXES))));
|
||||
|
||||
final HBox actions = new HBox(8);
|
||||
final Button cancel = new Button(Container.i18n().text(I18n.ASSETS_MUTATION_CANCEL));
|
||||
cancel.getStyleClass().addAll("studio-button", "studio-button-cancel");
|
||||
cancel.setOnAction(event -> interactions.cancelStagedMutationPreview());
|
||||
final Button apply = new Button(Container.i18n().text(I18n.ASSETS_MUTATION_APPLY));
|
||||
apply.getStyleClass().addAll("studio-button", "studio-button-primary");
|
||||
apply.setDisable(!preview.canApply());
|
||||
apply.setOnAction(event -> interactions.applyStagedMutation(preview));
|
||||
actions.getChildren().addAll(cancel, apply);
|
||||
panel.getChildren().add(actions);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private Node createMutationSection(String title, Node content) {
|
||||
final VBox section = new VBox(6);
|
||||
final Label label = new Label(title);
|
||||
label.getStyleClass().add("assets-mutation-section-title");
|
||||
section.getChildren().addAll(label, content);
|
||||
return section;
|
||||
}
|
||||
|
||||
private Node createAffectedAssetContent(AssetWorkspaceMutationPreview preview) {
|
||||
final VBox box = new VBox(6);
|
||||
box.getChildren().add(AssetWorkspaceDetailsUiSupport.createKeyValueRow(Container.i18n().text(I18n.ASSETS_LABEL_NAME), preview.asset().assetName()));
|
||||
box.getChildren().add(AssetWorkspaceDetailsUiSupport.createKeyValueRow(
|
||||
Container.i18n().text(I18n.ASSETS_LABEL_LOCATION),
|
||||
AssetWorkspaceDetailsUiSupport.projectRelativePath(projectReference, preview.asset().assetRoot())));
|
||||
if (preview.targetAssetRoot() != null) {
|
||||
box.getChildren().add(AssetWorkspaceDetailsUiSupport.createKeyValueRow(
|
||||
Container.i18n().text(I18n.ASSETS_LABEL_TARGET_LOCATION),
|
||||
AssetWorkspaceDetailsUiSupport.projectRelativePath(projectReference, preview.targetAssetRoot())));
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
private Node createMutationChangesContent(List<AssetWorkspaceMutationChange> changes, String emptyText) {
|
||||
if (changes.isEmpty()) {
|
||||
return AssetWorkspaceDetailsUiSupport.createSectionMessage(emptyText);
|
||||
}
|
||||
final VBox box = new VBox(6);
|
||||
for (AssetWorkspaceMutationChange change : changes) {
|
||||
final Label label = new Label(change.verb() + " · " + change.target());
|
||||
label.getStyleClass().add("assets-mutation-change");
|
||||
box.getChildren().add(label);
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
private Node createMutationMessages(List<String> messages, String styleClass, String emptyText) {
|
||||
if (messages.isEmpty()) {
|
||||
return AssetWorkspaceDetailsUiSupport.createSectionMessage(emptyText);
|
||||
}
|
||||
final VBox box = new VBox(6);
|
||||
for (String message : messages) {
|
||||
final Label label = new Label(message);
|
||||
label.setWrapText(true);
|
||||
label.getStyleClass().add(styleClass);
|
||||
box.getChildren().add(label);
|
||||
}
|
||||
return box;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user