implements PR-10c bank composition section shell and form session integration
This commit is contained in:
parent
bd753a8f1e
commit
de8720abc3
@ -22,6 +22,8 @@ public abstract class StudioDualListView<T> extends HBox {
|
||||
private final ObservableList<T> rightItems = FXCollections.observableArrayList();
|
||||
private final ListView<T> leftListView = new ListView<>(leftItems);
|
||||
private final ListView<T> rightListView = new ListView<>(rightItems);
|
||||
private final Label leftTitleLabel = new Label("Available");
|
||||
private final Label rightTitleLabel = new Label("Selected");
|
||||
private final Button moveToRightButton = new Button(">");
|
||||
private final Button moveToLeftButton = new Button("<");
|
||||
private final Button moveUpButton = new Button("Up");
|
||||
@ -41,8 +43,8 @@ public abstract class StudioDualListView<T> extends HBox {
|
||||
leftListView.setCellFactory(ignored -> createCell(false));
|
||||
rightListView.setCellFactory(ignored -> createCell(true));
|
||||
|
||||
final VBox leftColumn = createColumn("Available", leftListView);
|
||||
final VBox rightColumn = createColumn("Selected", rightListView);
|
||||
final VBox leftColumn = createColumn(leftTitleLabel, leftListView);
|
||||
final VBox rightColumn = createColumn(rightTitleLabel, rightListView);
|
||||
final VBox centerActions = new VBox(8, moveToRightButton, moveToLeftButton, moveUpButton, moveDownButton);
|
||||
centerActions.setAlignment(Pos.CENTER);
|
||||
centerActions.getStyleClass().add("studio-dual-list-actions");
|
||||
@ -114,14 +116,21 @@ public abstract class StudioDualListView<T> extends HBox {
|
||||
this.onMoveDown = Objects.requireNonNull(onMoveDown, "onMoveDown");
|
||||
}
|
||||
|
||||
public void setLeftTitle(String title) {
|
||||
leftTitleLabel.setText(Objects.requireNonNull(title, "title"));
|
||||
}
|
||||
|
||||
public void setRightTitle(String title) {
|
||||
rightTitleLabel.setText(Objects.requireNonNull(title, "title"));
|
||||
}
|
||||
|
||||
protected abstract String itemText(T item);
|
||||
|
||||
protected Node itemGraphic(T item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private VBox createColumn(String title, ListView<T> listView) {
|
||||
final Label titleLabel = new Label(title);
|
||||
private VBox createColumn(Label titleLabel, ListView<T> listView) {
|
||||
titleLabel.getStyleClass().add("studio-dual-list-title");
|
||||
final VBox column = new VBox(8, titleLabel, listView);
|
||||
column.getStyleClass().add("studio-dual-list-column");
|
||||
|
||||
@ -96,6 +96,7 @@ public enum I18n {
|
||||
ASSETS_BADGE_DIAGNOSTICS("assets.badge.diagnostics"),
|
||||
ASSETS_SECTION_SUMMARY("assets.section.summary"),
|
||||
ASSETS_SECTION_RUNTIME_CONTRACT("assets.section.runtimeContract"),
|
||||
ASSETS_SECTION_BANK_COMPOSITION("assets.section.bankComposition"),
|
||||
ASSETS_SUBSECTION_CODEC_CONFIGURATION("assets.subsection.codecConfiguration"),
|
||||
ASSETS_SUBSECTION_METADATA("assets.subsection.metadata"),
|
||||
ASSETS_SECTION_INPUTS_PREVIEW("assets.section.inputsPreview"),
|
||||
@ -177,6 +178,10 @@ public enum I18n {
|
||||
ASSETS_DETAILS_EMPTY("assets.details.empty"),
|
||||
ASSETS_DETAILS_READY("assets.details.ready"),
|
||||
ASSETS_DETAILS_NO_SELECTION("assets.details.noSelection"),
|
||||
ASSETS_DETAILS_BANK_COMPOSITION_AVAILABLE("assets.details.bankComposition.available"),
|
||||
ASSETS_DETAILS_BANK_COMPOSITION_SELECTED("assets.details.bankComposition.selected"),
|
||||
ASSETS_DETAILS_BANK_COMPOSITION_READONLY_HINT("assets.details.bankComposition.readonlyHint"),
|
||||
ASSETS_DETAILS_BANK_COMPOSITION_EDITING_HINT("assets.details.bankComposition.editingHint"),
|
||||
ASSETS_DETAILS_CODEC_CONFIGURATION_EMPTY("assets.details.codecConfiguration.empty"),
|
||||
ASSETS_DETAILS_METADATA_EMPTY("assets.details.metadata.empty"),
|
||||
ASSETS_ADD_WIZARD_TITLE("assets.addWizard.title"),
|
||||
|
||||
@ -15,6 +15,7 @@ import p.studio.Container;
|
||||
import p.studio.events.StudioWorkspaceEventBus;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
import p.studio.workspaces.assets.details.bank.AssetDetailsBankCompositionControl;
|
||||
import p.studio.workspaces.assets.details.contract.AssetDetailsContractControl;
|
||||
import p.studio.workspaces.assets.details.summary.AssetDetailsSummaryControl;
|
||||
import p.studio.workspaces.assets.messages.AssetWorkspaceAssetAction;
|
||||
@ -45,6 +46,7 @@ public final class AssetDetailsControl extends VBox implements StudioEventAware
|
||||
private final ScrollPane detailsScroll = new ScrollPane();
|
||||
private final AssetDetailsSummaryControl summaryControl;
|
||||
private final AssetDetailsContractControl contractControl;
|
||||
private final AssetDetailsBankCompositionControl bankCompositionControl;
|
||||
private final VBox actionsContent = new VBox(10);
|
||||
private final ScrollPane actionsScroll = new ScrollPane();
|
||||
private final VBox actionsSection;
|
||||
@ -63,6 +65,7 @@ public final class AssetDetailsControl extends VBox implements StudioEventAware
|
||||
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
||||
this.summaryControl = new AssetDetailsSummaryControl(projectReference, workspaceBus);
|
||||
this.contractControl = new AssetDetailsContractControl(projectReference, workspaceBus);
|
||||
this.bankCompositionControl = new AssetDetailsBankCompositionControl(projectReference, workspaceBus);
|
||||
this.actionsSection = createActionsSection();
|
||||
|
||||
getStyleClass().add("assets-workspace-pane");
|
||||
@ -224,7 +227,7 @@ public final class AssetDetailsControl extends VBox implements StudioEventAware
|
||||
renderActions();
|
||||
if (!readyMounted) {
|
||||
readyMounted = true;
|
||||
detailsContent.getChildren().setAll(primarySectionsRow, contractControl);
|
||||
detailsContent.getChildren().setAll(primarySectionsRow, contractControl, bankCompositionControl);
|
||||
}
|
||||
syncActionsSectionHeight(summaryControl.getHeight());
|
||||
}
|
||||
|
||||
@ -0,0 +1,149 @@
|
||||
package p.studio.workspaces.assets.details.bank;
|
||||
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import p.studio.Container;
|
||||
import p.studio.controls.banks.StudioAssetCapacityMeter;
|
||||
import p.studio.controls.banks.StudioAssetCapacitySeverity;
|
||||
import p.studio.controls.forms.StudioFormActionBar;
|
||||
import p.studio.controls.forms.StudioFormMode;
|
||||
import p.studio.controls.forms.StudioFormSession;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycle;
|
||||
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
|
||||
import p.studio.events.StudioWorkspaceEventBus;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
import p.studio.workspaces.assets.details.AssetDetailsUiSupport;
|
||||
import p.studio.workspaces.assets.messages.AssetWorkspaceBankCompositionDetails;
|
||||
import p.studio.workspaces.assets.messages.AssetWorkspaceDetailsViewState;
|
||||
import p.studio.workspaces.assets.messages.events.StudioAssetsDetailsViewStateChangedEvent;
|
||||
import p.studio.workspaces.framework.StudioSubscriptionBag;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class AssetDetailsBankCompositionControl extends VBox implements StudioControlLifecycle {
|
||||
private final StudioWorkspaceEventBus workspaceBus;
|
||||
private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag();
|
||||
private final StudioFormActionBar actionBar = new StudioFormActionBar(
|
||||
this::beginEdit,
|
||||
this::applyDraft,
|
||||
this::resetDraft,
|
||||
this::cancelEdit);
|
||||
private final AssetDetailsBankCompositionDualListView dualListView = new AssetDetailsBankCompositionDualListView();
|
||||
private final StudioAssetCapacityMeter capacityMeter = new StudioAssetCapacityMeter();
|
||||
|
||||
private AssetWorkspaceDetailsViewState viewState;
|
||||
private StudioFormSession<AssetWorkspaceBankCompositionDetails> formSession;
|
||||
|
||||
public AssetDetailsBankCompositionControl(ProjectReference projectReference, StudioWorkspaceEventBus workspaceBus) {
|
||||
StudioControlLifecycleSupport.install(this, this);
|
||||
Objects.requireNonNull(projectReference, "projectReference");
|
||||
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe() {
|
||||
subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> {
|
||||
viewState = event.viewState();
|
||||
syncFormSession();
|
||||
render();
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe() {
|
||||
subscriptions.clear();
|
||||
}
|
||||
|
||||
private void syncFormSession() {
|
||||
if (viewState == null || viewState.selectedAssetDetails() == null) {
|
||||
formSession = null;
|
||||
return;
|
||||
}
|
||||
|
||||
final AssetWorkspaceBankCompositionDetails source = viewState.selectedAssetDetails().bankComposition();
|
||||
if (formSession == null) {
|
||||
formSession = new StudioFormSession<>(source);
|
||||
return;
|
||||
}
|
||||
if (!Objects.equals(formSession.source(), source)) {
|
||||
formSession.replaceSource(source);
|
||||
}
|
||||
}
|
||||
|
||||
private void render() {
|
||||
if (viewState == null || viewState.selectedAssetDetails() == null) {
|
||||
getChildren().clear();
|
||||
return;
|
||||
}
|
||||
if (formSession == null) {
|
||||
syncFormSession();
|
||||
}
|
||||
if (formSession == null) {
|
||||
getChildren().clear();
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean editing = formSession.mode() == StudioFormMode.EDITING;
|
||||
final AssetWorkspaceBankCompositionDetails draft = formSession.draft();
|
||||
|
||||
dualListView.setLeftItems(draft.availableFiles());
|
||||
dualListView.setRightItems(draft.selectedFiles());
|
||||
dualListView.setInteractionEnabled(false);
|
||||
|
||||
capacityMeter.setProgress(0.0d);
|
||||
capacityMeter.setSeverity(StudioAssetCapacitySeverity.GREEN);
|
||||
capacityMeter.setLabelText(draft.measuredBankSizeBytes() + " bytes");
|
||||
capacityMeter.setHintText(editing
|
||||
? Container.i18n().text(I18n.ASSETS_DETAILS_BANK_COMPOSITION_EDITING_HINT)
|
||||
: Container.i18n().text(I18n.ASSETS_DETAILS_BANK_COMPOSITION_READONLY_HINT));
|
||||
|
||||
final HBox body = new HBox(16, dualListView, capacityMeter);
|
||||
body.getStyleClass().add("assets-details-bank-composition-body");
|
||||
HBox.setHgrow(dualListView, Priority.ALWAYS);
|
||||
dualListView.setMaxWidth(Double.MAX_VALUE);
|
||||
|
||||
final VBox content = new VBox(12, body);
|
||||
actionBar.updateState(formSession.mode(), formSession.isDirty());
|
||||
content.getChildren().add(actionBar);
|
||||
|
||||
final VBox section = AssetDetailsUiSupport.createSection(
|
||||
Container.i18n().text(I18n.ASSETS_SECTION_BANK_COMPOSITION),
|
||||
content);
|
||||
section.getStyleClass().add("assets-details-bank-composition-section");
|
||||
getChildren().setAll(section);
|
||||
}
|
||||
|
||||
private void beginEdit() {
|
||||
if (formSession == null) {
|
||||
return;
|
||||
}
|
||||
formSession.beginEdit();
|
||||
render();
|
||||
}
|
||||
|
||||
private void applyDraft() {
|
||||
if (formSession == null) {
|
||||
return;
|
||||
}
|
||||
formSession.apply();
|
||||
render();
|
||||
}
|
||||
|
||||
private void resetDraft() {
|
||||
if (formSession == null) {
|
||||
return;
|
||||
}
|
||||
formSession.resetDraft();
|
||||
render();
|
||||
}
|
||||
|
||||
private void cancelEdit() {
|
||||
if (formSession == null) {
|
||||
return;
|
||||
}
|
||||
formSession.cancelEdit();
|
||||
render();
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,16 @@
|
||||
package p.studio.workspaces.assets.details.bank;
|
||||
|
||||
import p.studio.controls.banks.StudioDualListView;
|
||||
import p.studio.Container;
|
||||
import p.studio.utilities.i18n.I18n;
|
||||
import p.studio.workspaces.assets.messages.AssetWorkspaceBankCompositionFile;
|
||||
|
||||
public final class AssetDetailsBankCompositionDualListView extends StudioDualListView<AssetWorkspaceBankCompositionFile> {
|
||||
public AssetDetailsBankCompositionDualListView() {
|
||||
setLeftTitle(Container.i18n().text(I18n.ASSETS_DETAILS_BANK_COMPOSITION_AVAILABLE));
|
||||
setRightTitle(Container.i18n().text(I18n.ASSETS_DETAILS_BANK_COMPOSITION_SELECTED));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String itemText(AssetWorkspaceBankCompositionFile item) {
|
||||
if (item.displayName().equals(item.path())) {
|
||||
|
||||
@ -86,6 +86,7 @@ assets.badge.preload=Preload
|
||||
assets.badge.diagnostics=Diagnostics
|
||||
assets.section.summary=Summary
|
||||
assets.section.runtimeContract=Runtime Contract
|
||||
assets.section.bankComposition=Bank Composition
|
||||
assets.subsection.codecConfiguration=Codec Configuration
|
||||
assets.subsection.metadata=Metadata
|
||||
assets.section.inputsPreview=Inputs / Preview
|
||||
@ -168,6 +169,10 @@ assets.details.loading=Waiting for asset data...
|
||||
assets.details.empty=Create or add assets to this project to start using the Assets workspace.
|
||||
assets.details.ready=Selected asset: {0}\nState: {1}\nRoot: {2}
|
||||
assets.details.noSelection=Select an asset from the navigator once assets are available.
|
||||
assets.details.bankComposition.available=Available
|
||||
assets.details.bankComposition.selected=Selected
|
||||
assets.details.bankComposition.readonlyHint=Current bank composition state is shown read-only until editing begins.
|
||||
assets.details.bankComposition.editingHint=Bank composition editing shell is active. Behavior wiring lands in the next slice.
|
||||
assets.details.codecConfiguration.empty=This codec does not expose configuration fields yet.
|
||||
assets.details.metadata.empty=This asset does not expose metadata fields yet.
|
||||
assets.addWizard.title=Add Asset
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user