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 ObservableList<T> rightItems = FXCollections.observableArrayList();
|
||||||
private final ListView<T> leftListView = new ListView<>(leftItems);
|
private final ListView<T> leftListView = new ListView<>(leftItems);
|
||||||
private final ListView<T> rightListView = new ListView<>(rightItems);
|
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 moveToRightButton = new Button(">");
|
||||||
private final Button moveToLeftButton = new Button("<");
|
private final Button moveToLeftButton = new Button("<");
|
||||||
private final Button moveUpButton = new Button("Up");
|
private final Button moveUpButton = new Button("Up");
|
||||||
@ -41,8 +43,8 @@ public abstract class StudioDualListView<T> extends HBox {
|
|||||||
leftListView.setCellFactory(ignored -> createCell(false));
|
leftListView.setCellFactory(ignored -> createCell(false));
|
||||||
rightListView.setCellFactory(ignored -> createCell(true));
|
rightListView.setCellFactory(ignored -> createCell(true));
|
||||||
|
|
||||||
final VBox leftColumn = createColumn("Available", leftListView);
|
final VBox leftColumn = createColumn(leftTitleLabel, leftListView);
|
||||||
final VBox rightColumn = createColumn("Selected", rightListView);
|
final VBox rightColumn = createColumn(rightTitleLabel, rightListView);
|
||||||
final VBox centerActions = new VBox(8, moveToRightButton, moveToLeftButton, moveUpButton, moveDownButton);
|
final VBox centerActions = new VBox(8, moveToRightButton, moveToLeftButton, moveUpButton, moveDownButton);
|
||||||
centerActions.setAlignment(Pos.CENTER);
|
centerActions.setAlignment(Pos.CENTER);
|
||||||
centerActions.getStyleClass().add("studio-dual-list-actions");
|
centerActions.getStyleClass().add("studio-dual-list-actions");
|
||||||
@ -114,14 +116,21 @@ public abstract class StudioDualListView<T> extends HBox {
|
|||||||
this.onMoveDown = Objects.requireNonNull(onMoveDown, "onMoveDown");
|
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 abstract String itemText(T item);
|
||||||
|
|
||||||
protected Node itemGraphic(T item) {
|
protected Node itemGraphic(T item) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private VBox createColumn(String title, ListView<T> listView) {
|
private VBox createColumn(Label titleLabel, ListView<T> listView) {
|
||||||
final Label titleLabel = new Label(title);
|
|
||||||
titleLabel.getStyleClass().add("studio-dual-list-title");
|
titleLabel.getStyleClass().add("studio-dual-list-title");
|
||||||
final VBox column = new VBox(8, titleLabel, listView);
|
final VBox column = new VBox(8, titleLabel, listView);
|
||||||
column.getStyleClass().add("studio-dual-list-column");
|
column.getStyleClass().add("studio-dual-list-column");
|
||||||
|
|||||||
@ -96,6 +96,7 @@ public enum I18n {
|
|||||||
ASSETS_BADGE_DIAGNOSTICS("assets.badge.diagnostics"),
|
ASSETS_BADGE_DIAGNOSTICS("assets.badge.diagnostics"),
|
||||||
ASSETS_SECTION_SUMMARY("assets.section.summary"),
|
ASSETS_SECTION_SUMMARY("assets.section.summary"),
|
||||||
ASSETS_SECTION_RUNTIME_CONTRACT("assets.section.runtimeContract"),
|
ASSETS_SECTION_RUNTIME_CONTRACT("assets.section.runtimeContract"),
|
||||||
|
ASSETS_SECTION_BANK_COMPOSITION("assets.section.bankComposition"),
|
||||||
ASSETS_SUBSECTION_CODEC_CONFIGURATION("assets.subsection.codecConfiguration"),
|
ASSETS_SUBSECTION_CODEC_CONFIGURATION("assets.subsection.codecConfiguration"),
|
||||||
ASSETS_SUBSECTION_METADATA("assets.subsection.metadata"),
|
ASSETS_SUBSECTION_METADATA("assets.subsection.metadata"),
|
||||||
ASSETS_SECTION_INPUTS_PREVIEW("assets.section.inputsPreview"),
|
ASSETS_SECTION_INPUTS_PREVIEW("assets.section.inputsPreview"),
|
||||||
@ -177,6 +178,10 @@ public enum I18n {
|
|||||||
ASSETS_DETAILS_EMPTY("assets.details.empty"),
|
ASSETS_DETAILS_EMPTY("assets.details.empty"),
|
||||||
ASSETS_DETAILS_READY("assets.details.ready"),
|
ASSETS_DETAILS_READY("assets.details.ready"),
|
||||||
ASSETS_DETAILS_NO_SELECTION("assets.details.noSelection"),
|
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_CODEC_CONFIGURATION_EMPTY("assets.details.codecConfiguration.empty"),
|
||||||
ASSETS_DETAILS_METADATA_EMPTY("assets.details.metadata.empty"),
|
ASSETS_DETAILS_METADATA_EMPTY("assets.details.metadata.empty"),
|
||||||
ASSETS_ADD_WIZARD_TITLE("assets.addWizard.title"),
|
ASSETS_ADD_WIZARD_TITLE("assets.addWizard.title"),
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import p.studio.Container;
|
|||||||
import p.studio.events.StudioWorkspaceEventBus;
|
import p.studio.events.StudioWorkspaceEventBus;
|
||||||
import p.studio.projects.ProjectReference;
|
import p.studio.projects.ProjectReference;
|
||||||
import p.studio.utilities.i18n.I18n;
|
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.contract.AssetDetailsContractControl;
|
||||||
import p.studio.workspaces.assets.details.summary.AssetDetailsSummaryControl;
|
import p.studio.workspaces.assets.details.summary.AssetDetailsSummaryControl;
|
||||||
import p.studio.workspaces.assets.messages.AssetWorkspaceAssetAction;
|
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 ScrollPane detailsScroll = new ScrollPane();
|
||||||
private final AssetDetailsSummaryControl summaryControl;
|
private final AssetDetailsSummaryControl summaryControl;
|
||||||
private final AssetDetailsContractControl contractControl;
|
private final AssetDetailsContractControl contractControl;
|
||||||
|
private final AssetDetailsBankCompositionControl bankCompositionControl;
|
||||||
private final VBox actionsContent = new VBox(10);
|
private final VBox actionsContent = new VBox(10);
|
||||||
private final ScrollPane actionsScroll = new ScrollPane();
|
private final ScrollPane actionsScroll = new ScrollPane();
|
||||||
private final VBox actionsSection;
|
private final VBox actionsSection;
|
||||||
@ -63,6 +65,7 @@ public final class AssetDetailsControl extends VBox implements StudioEventAware
|
|||||||
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
|
||||||
this.summaryControl = new AssetDetailsSummaryControl(projectReference, workspaceBus);
|
this.summaryControl = new AssetDetailsSummaryControl(projectReference, workspaceBus);
|
||||||
this.contractControl = new AssetDetailsContractControl(projectReference, workspaceBus);
|
this.contractControl = new AssetDetailsContractControl(projectReference, workspaceBus);
|
||||||
|
this.bankCompositionControl = new AssetDetailsBankCompositionControl(projectReference, workspaceBus);
|
||||||
this.actionsSection = createActionsSection();
|
this.actionsSection = createActionsSection();
|
||||||
|
|
||||||
getStyleClass().add("assets-workspace-pane");
|
getStyleClass().add("assets-workspace-pane");
|
||||||
@ -224,7 +227,7 @@ public final class AssetDetailsControl extends VBox implements StudioEventAware
|
|||||||
renderActions();
|
renderActions();
|
||||||
if (!readyMounted) {
|
if (!readyMounted) {
|
||||||
readyMounted = true;
|
readyMounted = true;
|
||||||
detailsContent.getChildren().setAll(primarySectionsRow, contractControl);
|
detailsContent.getChildren().setAll(primarySectionsRow, contractControl, bankCompositionControl);
|
||||||
}
|
}
|
||||||
syncActionsSectionHeight(summaryControl.getHeight());
|
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;
|
package p.studio.workspaces.assets.details.bank;
|
||||||
|
|
||||||
import p.studio.controls.banks.StudioDualListView;
|
import p.studio.controls.banks.StudioDualListView;
|
||||||
|
import p.studio.Container;
|
||||||
|
import p.studio.utilities.i18n.I18n;
|
||||||
import p.studio.workspaces.assets.messages.AssetWorkspaceBankCompositionFile;
|
import p.studio.workspaces.assets.messages.AssetWorkspaceBankCompositionFile;
|
||||||
|
|
||||||
public final class AssetDetailsBankCompositionDualListView extends StudioDualListView<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
|
@Override
|
||||||
protected String itemText(AssetWorkspaceBankCompositionFile item) {
|
protected String itemText(AssetWorkspaceBankCompositionFile item) {
|
||||||
if (item.displayName().equals(item.path())) {
|
if (item.displayName().equals(item.path())) {
|
||||||
|
|||||||
@ -86,6 +86,7 @@ assets.badge.preload=Preload
|
|||||||
assets.badge.diagnostics=Diagnostics
|
assets.badge.diagnostics=Diagnostics
|
||||||
assets.section.summary=Summary
|
assets.section.summary=Summary
|
||||||
assets.section.runtimeContract=Runtime Contract
|
assets.section.runtimeContract=Runtime Contract
|
||||||
|
assets.section.bankComposition=Bank Composition
|
||||||
assets.subsection.codecConfiguration=Codec Configuration
|
assets.subsection.codecConfiguration=Codec Configuration
|
||||||
assets.subsection.metadata=Metadata
|
assets.subsection.metadata=Metadata
|
||||||
assets.section.inputsPreview=Inputs / Preview
|
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.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.ready=Selected asset: {0}\nState: {1}\nRoot: {2}
|
||||||
assets.details.noSelection=Select an asset from the navigator once assets are available.
|
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.codecConfiguration.empty=This codec does not expose configuration fields yet.
|
||||||
assets.details.metadata.empty=This asset does not expose metadata fields yet.
|
assets.details.metadata.empty=This asset does not expose metadata fields yet.
|
||||||
assets.addWizard.title=Add Asset
|
assets.addWizard.title=Add Asset
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user