implements PR-07b asset navigator and row subscriptions
This commit is contained in:
parent
c351814b6f
commit
3e0592e75c
@ -1,16 +1,13 @@
|
||||
package p.studio.workspaces.assets;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
import javafx.scene.layout.FlowPane;
|
||||
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;
|
||||
@ -41,6 +38,7 @@ final class AssetWorkspaceNavigatorControl extends VBox implements StudioControl
|
||||
|
||||
private AssetWorkspaceNavigatorViewState viewState;
|
||||
private EnumSet<AssetNavigatorFilter> activeFilters = EnumSet.noneOf(AssetNavigatorFilter.class);
|
||||
private String projectionSignature = "";
|
||||
|
||||
AssetWorkspaceNavigatorControl(
|
||||
ProjectReference projectReference,
|
||||
@ -136,10 +134,16 @@ final class AssetWorkspaceNavigatorControl extends VBox implements StudioControl
|
||||
|
||||
navigatorStateLabel.setText(viewState.message());
|
||||
if (!viewState.hasProjection()) {
|
||||
projectionSignature = "";
|
||||
navigatorContent.getChildren().setAll(createMessage(viewState.message()));
|
||||
return;
|
||||
}
|
||||
|
||||
final String nextSignature = projectionSignature(viewState.projection());
|
||||
if (Objects.equals(projectionSignature, nextSignature)) {
|
||||
return;
|
||||
}
|
||||
projectionSignature = nextSignature;
|
||||
navigatorContent.getChildren().clear();
|
||||
for (AssetNavigatorGroup group : viewState.projection().groups()) {
|
||||
final VBox groupBox = new VBox(6);
|
||||
@ -150,61 +154,18 @@ final class AssetWorkspaceNavigatorControl extends VBox implements StudioControl
|
||||
groupBox.getChildren().add(groupLabel);
|
||||
|
||||
for (AssetWorkspaceAssetSummary asset : group.assets()) {
|
||||
groupBox.getChildren().add(createAssetRow(asset, asset.selectionKey().equals(viewState.workspaceState().selectedKey())));
|
||||
groupBox.getChildren().add(new AssetWorkspaceNavigatorRowControl(
|
||||
projectReference,
|
||||
workspaceBus,
|
||||
interactions,
|
||||
asset,
|
||||
asset.selectionKey().equals(viewState.workspaceState().selectedKey())));
|
||||
}
|
||||
|
||||
navigatorContent.getChildren().add(groupBox);
|
||||
}
|
||||
}
|
||||
|
||||
private Node createAssetRow(AssetWorkspaceAssetSummary asset, boolean selected) {
|
||||
final VBox row = new VBox(4);
|
||||
row.getStyleClass().add("assets-workspace-asset-row");
|
||||
row.getStyleClass().add(assetRowToneClass(asset.assetFamily()));
|
||||
updateAssetRowSelection(row, selected);
|
||||
|
||||
final HBox topLine = new HBox(8);
|
||||
topLine.setAlignment(Pos.CENTER_LEFT);
|
||||
final Label name = new Label(asset.assetName());
|
||||
name.getStyleClass().add("assets-workspace-asset-name");
|
||||
name.getStyleClass().add(assetNameToneClass(asset.assetFamily()));
|
||||
final Region spacer = new Region();
|
||||
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||
final HBox badges = new HBox(6);
|
||||
badges.setAlignment(Pos.CENTER_RIGHT);
|
||||
badges.getStyleClass().add("assets-workspace-asset-badges");
|
||||
if (asset.state() == AssetWorkspaceAssetState.UNREGISTERED) {
|
||||
badges.getChildren().add(createBadge(Container.i18n().text(I18n.ASSETS_BADGE_UNREGISTERED), "assets-workspace-badge-orphan"));
|
||||
} else if (asset.buildParticipation() == AssetWorkspaceBuildParticipation.INCLUDED) {
|
||||
badges.getChildren().add(createBadge(buildParticipationLabel(asset.buildParticipation()), "assets-workspace-badge-preload"));
|
||||
if (asset.preload()) {
|
||||
badges.getChildren().add(createBadge(Container.i18n().text(I18n.ASSETS_BADGE_PRELOAD), "assets-workspace-badge-preload"));
|
||||
}
|
||||
} else {
|
||||
badges.getChildren().add(createBadge(buildParticipationLabel(asset.buildParticipation()), "assets-workspace-badge-diagnostics"));
|
||||
}
|
||||
if (asset.hasDiagnostics()) {
|
||||
badges.getChildren().add(createBadge(Container.i18n().text(I18n.ASSETS_BADGE_DIAGNOSTICS), "assets-workspace-badge-diagnostics"));
|
||||
}
|
||||
topLine.getChildren().addAll(name, spacer, badges);
|
||||
|
||||
final Label path = new Label(AssetNavigatorProjectionBuilder.relativeRoot(asset, projectRoot));
|
||||
path.getStyleClass().add("assets-workspace-asset-path");
|
||||
row.getChildren().addAll(topLine, path);
|
||||
row.setOnMouseClicked(event -> interactions.selectAsset(asset.selectionKey()));
|
||||
return row;
|
||||
}
|
||||
|
||||
private void updateAssetRowSelection(VBox row, boolean selected) {
|
||||
if (selected) {
|
||||
if (!row.getStyleClass().contains("assets-workspace-asset-row-selected")) {
|
||||
row.getStyleClass().add("assets-workspace-asset-row-selected");
|
||||
}
|
||||
return;
|
||||
}
|
||||
row.getStyleClass().remove("assets-workspace-asset-row-selected");
|
||||
}
|
||||
|
||||
private Node createMessage(String text) {
|
||||
final Label label = new Label(text);
|
||||
label.getStyleClass().add("assets-workspace-empty-state");
|
||||
@ -212,35 +173,15 @@ final class AssetWorkspaceNavigatorControl extends VBox implements StudioControl
|
||||
return label;
|
||||
}
|
||||
|
||||
private Node createBadge(String text, String styleClass) {
|
||||
final Label badge = new Label(text);
|
||||
badge.getStyleClass().add("assets-workspace-badge");
|
||||
badge.getStyleClass().add(styleClass);
|
||||
return badge;
|
||||
private String projectionSignature(AssetNavigatorProjection projection) {
|
||||
final StringBuilder signature = new StringBuilder();
|
||||
for (AssetNavigatorGroup group : projection.groups()) {
|
||||
signature.append(group.label()).append('|');
|
||||
for (AssetWorkspaceAssetSummary asset : group.assets()) {
|
||||
signature.append(asset.selectionKey().stableKey()).append(',');
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
signature.append(';');
|
||||
}
|
||||
|
||||
private String assetRowToneClass(String assetFamily) {
|
||||
return switch (assetFamily == null ? "" : assetFamily.toLowerCase()) {
|
||||
case "image_bank" -> "assets-workspace-asset-row-image";
|
||||
case "palette_bank" -> "assets-workspace-asset-row-palette";
|
||||
case "sound_bank" -> "assets-workspace-asset-row-sound";
|
||||
default -> "assets-workspace-asset-row-generic";
|
||||
};
|
||||
}
|
||||
|
||||
private String assetNameToneClass(String assetFamily) {
|
||||
return switch (assetFamily == null ? "" : assetFamily.toLowerCase()) {
|
||||
case "image_bank" -> "assets-workspace-asset-name-image";
|
||||
case "palette_bank" -> "assets-workspace-asset-name-palette";
|
||||
case "sound_bank" -> "assets-workspace-asset-name-sound";
|
||||
default -> "assets-workspace-asset-name-generic";
|
||||
};
|
||||
return signature.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,153 @@
|
||||
package p.studio.workspaces.assets;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Label;
|
||||
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;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
|
||||
import p.studio.events.StudioAssetsAssetSummaryPatchedEvent;
|
||||
import p.studio.events.StudioAssetsWorkspaceSelectionChangedEvent;
|
||||
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.Objects;
|
||||
|
||||
final class AssetWorkspaceNavigatorRowControl extends VBox implements StudioControlLifecycle {
|
||||
private final ProjectReference projectReference;
|
||||
private final Path projectRoot;
|
||||
private final StudioWorkspaceEventBus workspaceBus;
|
||||
private final AssetWorkspaceInteractionPort interactions;
|
||||
private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag();
|
||||
|
||||
private AssetWorkspaceAssetSummary summary;
|
||||
private boolean selected;
|
||||
|
||||
AssetWorkspaceNavigatorRowControl(
|
||||
ProjectReference projectReference,
|
||||
StudioWorkspaceEventBus workspaceBus,
|
||||
AssetWorkspaceInteractionPort interactions,
|
||||
AssetWorkspaceAssetSummary summary,
|
||||
boolean selected) {
|
||||
StudioControlLifecycleSupport.install(this, this);
|
||||
this.projectReference = Objects.requireNonNull(projectReference, "projectReference");
|
||||
this.projectRoot = this.projectReference.rootPath();
|
||||
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
||||
this.interactions = Objects.requireNonNull(interactions, "interactions");
|
||||
this.summary = Objects.requireNonNull(summary, "summary");
|
||||
this.selected = selected;
|
||||
render();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe() {
|
||||
subscriptions.add(workspaceBus.subscribe(StudioAssetsWorkspaceSelectionChangedEvent.class, event -> {
|
||||
if (projectReference.equals(event.project())) {
|
||||
updateSelection(event.selectionKey().equals(summary.selectionKey()));
|
||||
}
|
||||
}));
|
||||
subscriptions.add(workspaceBus.subscribe(StudioAssetsAssetSummaryPatchedEvent.class, event -> {
|
||||
if (projectReference.equals(event.project())
|
||||
&& summary.selectionKey().equals(event.summary().selectionKey())) {
|
||||
summary = event.summary();
|
||||
render();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe() {
|
||||
subscriptions.clear();
|
||||
}
|
||||
|
||||
private void updateSelection(boolean selected) {
|
||||
if (this.selected == selected) {
|
||||
return;
|
||||
}
|
||||
this.selected = selected;
|
||||
renderSelection();
|
||||
}
|
||||
|
||||
private void render() {
|
||||
getChildren().clear();
|
||||
getStyleClass().setAll("assets-workspace-asset-row", assetRowToneClass(summary.assetFamily()));
|
||||
renderSelection();
|
||||
|
||||
final HBox topLine = new HBox(8);
|
||||
topLine.setAlignment(Pos.CENTER_LEFT);
|
||||
final Label name = new Label(summary.assetName());
|
||||
name.getStyleClass().addAll("assets-workspace-asset-name", assetNameToneClass(summary.assetFamily()));
|
||||
final Region spacer = new Region();
|
||||
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||
final HBox badges = new HBox(6);
|
||||
badges.setAlignment(Pos.CENTER_RIGHT);
|
||||
badges.getStyleClass().add("assets-workspace-asset-badges");
|
||||
populateBadges(badges);
|
||||
topLine.getChildren().addAll(name, spacer, badges);
|
||||
|
||||
final Label path = new Label(AssetNavigatorProjectionBuilder.relativeRoot(summary, projectRoot));
|
||||
path.getStyleClass().add("assets-workspace-asset-path");
|
||||
getChildren().setAll(topLine, path);
|
||||
setOnMouseClicked(event -> interactions.selectAsset(summary.selectionKey()));
|
||||
}
|
||||
|
||||
private void renderSelection() {
|
||||
getStyleClass().remove("assets-workspace-asset-row-selected");
|
||||
if (selected) {
|
||||
getStyleClass().add("assets-workspace-asset-row-selected");
|
||||
}
|
||||
}
|
||||
|
||||
private void populateBadges(HBox badges) {
|
||||
if (summary.state() == AssetWorkspaceAssetState.UNREGISTERED) {
|
||||
badges.getChildren().add(createBadge(Container.i18n().text(I18n.ASSETS_BADGE_UNREGISTERED), "assets-workspace-badge-orphan"));
|
||||
} else if (summary.buildParticipation() == AssetWorkspaceBuildParticipation.INCLUDED) {
|
||||
badges.getChildren().add(createBadge(buildParticipationLabel(summary.buildParticipation()), "assets-workspace-badge-preload"));
|
||||
if (summary.preload()) {
|
||||
badges.getChildren().add(createBadge(Container.i18n().text(I18n.ASSETS_BADGE_PRELOAD), "assets-workspace-badge-preload"));
|
||||
}
|
||||
} else {
|
||||
badges.getChildren().add(createBadge(buildParticipationLabel(summary.buildParticipation()), "assets-workspace-badge-diagnostics"));
|
||||
}
|
||||
if (summary.hasDiagnostics()) {
|
||||
badges.getChildren().add(createBadge(Container.i18n().text(I18n.ASSETS_BADGE_DIAGNOSTICS), "assets-workspace-badge-diagnostics"));
|
||||
}
|
||||
}
|
||||
|
||||
private Label createBadge(String text, String styleClass) {
|
||||
final Label badge = new Label(text);
|
||||
badge.getStyleClass().addAll("assets-workspace-badge", styleClass);
|
||||
return badge;
|
||||
}
|
||||
|
||||
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 assetRowToneClass(String assetFamily) {
|
||||
return switch (assetFamily == null ? "" : assetFamily.toLowerCase()) {
|
||||
case "image_bank" -> "assets-workspace-asset-row-image";
|
||||
case "palette_bank" -> "assets-workspace-asset-row-palette";
|
||||
case "sound_bank" -> "assets-workspace-asset-row-sound";
|
||||
default -> "assets-workspace-asset-row-generic";
|
||||
};
|
||||
}
|
||||
|
||||
private String assetNameToneClass(String assetFamily) {
|
||||
return switch (assetFamily == null ? "" : assetFamily.toLowerCase()) {
|
||||
case "image_bank" -> "assets-workspace-asset-name-image";
|
||||
case "palette_bank" -> "assets-workspace-asset-name-palette";
|
||||
case "sound_bank" -> "assets-workspace-asset-name-sound";
|
||||
default -> "assets-workspace-asset-name-generic";
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user