asset details (WIP)

This commit is contained in:
bQUARKz 2026-03-19 08:13:22 +00:00
parent c26257163c
commit 7569e93234
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
12 changed files with 1089 additions and 860 deletions

View File

@ -0,0 +1,112 @@
package p.studio.controls.forms;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
public abstract class StudioFormSection extends StudioSection {
private final StudioFormActionBar actionBar = new StudioFormActionBar(
this::handleBeginEdit,
this::handleApply,
this::handleReset,
this::handleCancel);
protected StudioFormSection() {
super();
actionBar.getStyleClass().add("studio-form-section-actions");
}
public static VBox createReadOnlySection(String title, Node content) {
return StudioSection.createSection(title, content);
}
public static VBox createEditableSection(String title, Node headerActions, Node content, StudioFormMode mode) {
return StudioSection.createSection(title, headerActions, content, true, mode == StudioFormMode.EDITING, true);
}
protected final void renderFormSection(Node content) {
updateActionBarState();
final VBox section = createEditableSection(sectionTitle(), actionBar, content, formMode());
final String sectionStyleClass = sectionStyleClass();
if (sectionStyleClass != null && !sectionStyleClass.isBlank()) {
section.getStyleClass().add(sectionStyleClass);
}
getChildren().setAll(section);
}
protected final void updateActionBarState() {
actionBar.updateState(formMode(), isDirty());
}
protected final void rerenderPreservingScrollPosition() {
final ScrollPane scrollPane = findAncestorScrollPane();
final double previousVvalue = scrollPane == null ? 0.0d : scrollPane.getVvalue();
renderSection();
if (scrollPane != null) {
restoreScrollPosition(scrollPane, previousVvalue, 2);
}
}
protected abstract void renderSection();
protected abstract String sectionTitle();
protected abstract StudioFormMode formMode();
protected abstract boolean isDirty();
protected abstract void beginEdit();
protected abstract void apply();
protected abstract void reset();
protected abstract void cancel();
protected String sectionStyleClass() {
return null;
}
private void handleBeginEdit() {
beginEdit();
rerenderPreservingScrollPosition();
}
private void handleApply() {
apply();
}
private void handleReset() {
reset();
rerenderPreservingScrollPosition();
}
private void handleCancel() {
cancel();
rerenderPreservingScrollPosition();
}
private void restoreScrollPosition(ScrollPane scrollPane, double vvalue, int remainingPasses) {
Platform.runLater(() -> {
scrollPane.applyCss();
scrollPane.layout();
scrollPane.setVvalue(vvalue);
if (remainingPasses > 0) {
restoreScrollPosition(scrollPane, vvalue, remainingPasses - 1);
}
});
}
private ScrollPane findAncestorScrollPane() {
Parent current = getParent();
while (current != null) {
if (current instanceof ScrollPane scrollPane) {
return scrollPane;
}
current = current.getParent();
}
return null;
}
}

View File

@ -0,0 +1,59 @@
package p.studio.controls.forms;
import javafx.scene.Node;
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.controls.lifecycle.StudioControlLifecycle;
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
public abstract class StudioSection extends VBox implements StudioControlLifecycle {
protected StudioSection() {
StudioControlLifecycleSupport.install(this, this);
}
public static VBox createSection(String title, Node content) {
return createSection(title, null, content, false, false, true);
}
public static VBox createSectionWithoutHeader(Node content) {
return createSection(null, null, content, false, false, false);
}
protected static VBox createSection(
String title,
Node headerActions,
Node content,
boolean editable,
boolean editing,
boolean showHeader) {
final VBox section = new VBox(10);
section.getStyleClass().add("studio-form-section");
if (editable) {
section.getStyleClass().add("studio-form-section-editable");
}
if (editing) {
section.getStyleClass().add("studio-form-section-editing");
}
if (showHeader) {
final Label titleLabel = new Label(title == null ? "" : title);
titleLabel.getStyleClass().add("studio-form-section-title");
final Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
final HBox header = new HBox(12, titleLabel, spacer);
header.getStyleClass().add("studio-form-section-header");
if (headerActions != null) {
header.getChildren().add(headerActions);
}
section.getChildren().add(header);
}
section.getChildren().add(content);
return section;
}
}

View File

@ -12,6 +12,7 @@ import p.packer.dtos.PackerAssetActionAvailabilityDTO;
import p.packer.dtos.PackerAssetDetailsDTO; import p.packer.dtos.PackerAssetDetailsDTO;
import p.packer.messages.*; import p.packer.messages.*;
import p.studio.Container; import p.studio.Container;
import p.studio.controls.forms.StudioSection;
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;
@ -248,9 +249,9 @@ public final class AssetDetailsControl extends VBox implements StudioEventAware
actionsScroll.setFitToWidth(true); actionsScroll.setFitToWidth(true);
actionsScroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); actionsScroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
actionsScroll.getStyleClass().add("assets-details-actions-scroll"); actionsScroll.getStyleClass().add("assets-details-actions-scroll");
return AssetDetailsUiSupport.createSection( final VBox section = StudioSection.createSectionWithoutHeader(actionsScroll);
Container.i18n().text(I18n.ASSETS_SECTION_ACTIONS), section.getStyleClass().add("assets-details-actions-section");
actionsScroll); return section;
} }
private void syncActionsSectionHeight(double summaryHeight) { private void syncActionsSectionHeight(double summaryHeight) {

View File

@ -11,6 +11,9 @@ import p.packer.messages.assets.AssetAction;
import p.packer.messages.assets.AssetFamilyCatalog; import p.packer.messages.assets.AssetFamilyCatalog;
import p.packer.messages.assets.OutputFormatCatalog; import p.packer.messages.assets.OutputFormatCatalog;
import p.studio.Container; import p.studio.Container;
import p.studio.controls.forms.StudioFormMode;
import p.studio.controls.forms.StudioFormSection;
import p.studio.controls.forms.StudioSection;
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.messages.AssetWorkspaceAssetState; import p.studio.workspaces.assets.messages.AssetWorkspaceAssetState;
@ -23,12 +26,15 @@ public final class AssetDetailsUiSupport {
} }
public static VBox createSection(String title, Node content) { public static VBox createSection(String title, Node content) {
final VBox section = new VBox(10); return StudioSection.createSection(title, content);
section.getStyleClass().add("assets-details-section"); }
final Label titleLabel = new Label(title);
titleLabel.getStyleClass().add("assets-details-section-title"); public static VBox createSection(String title, Node headerActions, Node content) {
section.getChildren().addAll(titleLabel, content); return StudioFormSection.createEditableSection(title, headerActions, content, StudioFormMode.READ_ONLY);
return section; }
public static VBox createEditableSection(String title, Node headerActions, Node content, StudioFormMode mode) {
return StudioFormSection.createEditableSection(title, headerActions, content, mode);
} }
public static Node createSectionMessage(String text) { public static Node createSectionMessage(String text) {

View File

@ -7,9 +7,8 @@ import javafx.scene.layout.VBox;
import p.packer.messages.ApplyBankCompositionRequest; import p.packer.messages.ApplyBankCompositionRequest;
import p.studio.Container; import p.studio.Container;
import p.studio.controls.banks.StudioAssetCapacityMeter; import p.studio.controls.banks.StudioAssetCapacityMeter;
import p.studio.controls.forms.StudioFormActionBar; import p.studio.controls.forms.StudioFormMode;
import p.studio.controls.lifecycle.StudioControlLifecycle; import p.studio.controls.forms.StudioFormSection;
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
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;
@ -26,15 +25,12 @@ import p.studio.workspaces.framework.StudioSubscriptionBag;
import java.util.Objects; import java.util.Objects;
public final class AssetDetailsBankCompositionControl extends VBox implements StudioControlLifecycle { public final class AssetDetailsBankCompositionControl extends StudioFormSection {
private static final double CAPACITY_METER_WIDTH = 180.0d;
private final ProjectReference projectReference; private final ProjectReference projectReference;
private final StudioWorkspaceEventBus workspaceBus; private final StudioWorkspaceEventBus workspaceBus;
private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag(); 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 AssetDetailsBankCompositionDualListView dualListView = new AssetDetailsBankCompositionDualListView();
private final StudioAssetCapacityMeter capacityMeter = new StudioAssetCapacityMeter(); private final StudioAssetCapacityMeter capacityMeter = new StudioAssetCapacityMeter();
private final AssetDetailsBankCompositionCoordinator coordinator = new AssetDetailsBankCompositionCoordinator(); private final AssetDetailsBankCompositionCoordinator coordinator = new AssetDetailsBankCompositionCoordinator();
@ -42,9 +38,11 @@ public final class AssetDetailsBankCompositionControl extends VBox implements St
private AssetWorkspaceDetailsViewState viewState; private AssetWorkspaceDetailsViewState viewState;
public AssetDetailsBankCompositionControl(ProjectReference projectReference, StudioWorkspaceEventBus workspaceBus) { public AssetDetailsBankCompositionControl(ProjectReference projectReference, StudioWorkspaceEventBus workspaceBus) {
StudioControlLifecycleSupport.install(this, this);
this.projectReference = Objects.requireNonNull(projectReference, "projectReference"); this.projectReference = Objects.requireNonNull(projectReference, "projectReference");
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus"); this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
capacityMeter.setMinWidth(CAPACITY_METER_WIDTH);
capacityMeter.setPrefWidth(CAPACITY_METER_WIDTH);
capacityMeter.setMaxWidth(CAPACITY_METER_WIDTH);
} }
@Override @Override
@ -52,7 +50,7 @@ public final class AssetDetailsBankCompositionControl extends VBox implements St
subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> { subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> {
viewState = event.viewState(); viewState = event.viewState();
coordinator.replaceDetails(viewState == null ? null : viewState.selectedAssetDetails()); coordinator.replaceDetails(viewState == null ? null : viewState.selectedAssetDetails());
render(); renderSection();
publishStateNotifications(); publishStateNotifications();
})); }));
} }
@ -62,7 +60,8 @@ public final class AssetDetailsBankCompositionControl extends VBox implements St
subscriptions.clear(); subscriptions.clear();
} }
private void render() { @Override
protected void renderSection() {
if (viewState == null || viewState.selectedAssetDetails() == null) { if (viewState == null || viewState.selectedAssetDetails() == null) {
getChildren().clear(); getChildren().clear();
return; return;
@ -79,22 +78,22 @@ public final class AssetDetailsBankCompositionControl extends VBox implements St
dualListView.setInteractionEnabled(viewModel.editing()); dualListView.setInteractionEnabled(viewModel.editing());
dualListView.setOnMoveToRight(items -> { dualListView.setOnMoveToRight(items -> {
coordinator.moveToSelected(items); coordinator.moveToSelected(items);
render(); renderSection();
publishStateNotifications(); publishStateNotifications();
}); });
dualListView.setOnMoveToLeft(items -> { dualListView.setOnMoveToLeft(items -> {
coordinator.moveToAvailable(items); coordinator.moveToAvailable(items);
render(); renderSection();
publishStateNotifications(); publishStateNotifications();
}); });
dualListView.setOnMoveUp(index -> { dualListView.setOnMoveUp(index -> {
coordinator.moveUp(index); coordinator.moveUp(index);
render(); renderSection();
publishStateNotifications(); publishStateNotifications();
}); });
dualListView.setOnMoveDown(index -> { dualListView.setOnMoveDown(index -> {
coordinator.moveDown(index); coordinator.moveDown(index);
render(); renderSection();
publishStateNotifications(); publishStateNotifications();
}); });
@ -102,9 +101,7 @@ public final class AssetDetailsBankCompositionControl extends VBox implements St
capacityMeter.setSeverity(viewModel.capacityState().severity()); capacityMeter.setSeverity(viewModel.capacityState().severity());
capacityMeter.setLabelText(viewModel.capacityState().labelText()); capacityMeter.setLabelText(viewModel.capacityState().labelText());
capacityMeter.setHintText(viewModel.capacityState().hintText().isBlank() capacityMeter.setHintText(viewModel.capacityState().hintText().isBlank()
? (viewModel.editing() ? Container.i18n().text(I18n.ASSETS_DETAILS_BANK_COMPOSITION_READONLY_HINT)
? Container.i18n().text(I18n.ASSETS_DETAILS_BANK_COMPOSITION_EDITING_HINT)
: Container.i18n().text(I18n.ASSETS_DETAILS_BANK_COMPOSITION_READONLY_HINT))
: viewModel.capacityState().hintText()); : viewModel.capacityState().hintText());
final HBox body = new HBox(16, dualListView, capacityMeter); final HBox body = new HBox(16, dualListView, capacityMeter);
@ -113,23 +110,37 @@ public final class AssetDetailsBankCompositionControl extends VBox implements St
dualListView.setMaxWidth(Double.MAX_VALUE); dualListView.setMaxWidth(Double.MAX_VALUE);
final VBox content = new VBox(12, body); final VBox content = new VBox(12, body);
actionBar.updateState(viewModel.editing() ? p.studio.controls.forms.StudioFormMode.EDITING : p.studio.controls.forms.StudioFormMode.READ_ONLY, viewModel.dirty()); renderFormSection(content);
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() { @Override
protected String sectionTitle() {
return Container.i18n().text(I18n.ASSETS_SECTION_BANK_COMPOSITION);
}
@Override
protected StudioFormMode formMode() {
return coordinator.ready() && coordinator.viewModel().editing() ? StudioFormMode.EDITING : StudioFormMode.READ_ONLY;
}
@Override
protected boolean isDirty() {
return coordinator.ready() && coordinator.viewModel().dirty();
}
@Override
protected String sectionStyleClass() {
return "assets-details-bank-composition-section";
}
@Override
protected void beginEdit() {
coordinator.beginEdit(); coordinator.beginEdit();
render();
publishStateNotifications(); publishStateNotifications();
} }
private void applyDraft() { @Override
protected void apply() {
if (viewState == null || viewState.selectedAssetReference() == null || !coordinator.ready()) { if (viewState == null || viewState.selectedAssetReference() == null || !coordinator.ready()) {
return; return;
} }
@ -148,7 +159,7 @@ public final class AssetDetailsBankCompositionControl extends VBox implements St
Platform.runLater(() -> { Platform.runLater(() -> {
if (response.success()) { if (response.success()) {
coordinator.apply(); coordinator.apply();
render(); renderSection();
publishStateNotifications(); publishStateNotifications();
workspaceBus.publish(new StudioAssetBankCompositionAppliedEvent(assetReference)); workspaceBus.publish(new StudioAssetBankCompositionAppliedEvent(assetReference));
workspaceBus.publish(new StudioAssetsRefreshRequestedEvent(assetReference)); workspaceBus.publish(new StudioAssetsRefreshRequestedEvent(assetReference));
@ -166,15 +177,15 @@ public final class AssetDetailsBankCompositionControl extends VBox implements St
}); });
} }
private void resetDraft() { @Override
protected void reset() {
coordinator.reset(); coordinator.reset();
render();
publishStateNotifications(); publishStateNotifications();
} }
private void cancelEdit() { @Override
protected void cancel() {
coordinator.cancel(); coordinator.cancel();
render();
publishStateNotifications(); publishStateNotifications();
} }

View File

@ -11,11 +11,9 @@ import p.packer.dtos.PackerCodecConfigurationFieldDTO;
import p.packer.messages.UpdateAssetContractRequest; import p.packer.messages.UpdateAssetContractRequest;
import p.packer.messages.assets.OutputCodecCatalog; import p.packer.messages.assets.OutputCodecCatalog;
import p.studio.Container; import p.studio.Container;
import p.studio.controls.forms.StudioFormActionBar;
import p.studio.controls.forms.StudioFormMode; import p.studio.controls.forms.StudioFormMode;
import p.studio.controls.forms.StudioFormSession; import p.studio.controls.forms.StudioFormSession;
import p.studio.controls.lifecycle.StudioControlLifecycle; import p.studio.controls.forms.StudioFormSection;
import p.studio.controls.lifecycle.StudioControlLifecycleSupport;
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;
@ -29,21 +27,15 @@ import p.studio.workspaces.framework.StudioSubscriptionBag;
import java.util.Objects; import java.util.Objects;
public final class AssetDetailsContractControl extends VBox implements StudioControlLifecycle { public final class AssetDetailsContractControl extends StudioFormSection {
private final ProjectReference projectReference; private final ProjectReference projectReference;
private final StudioWorkspaceEventBus workspaceBus; private final StudioWorkspaceEventBus workspaceBus;
private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag(); private final StudioSubscriptionBag subscriptions = new StudioSubscriptionBag();
private final StudioFormActionBar actionBar = new StudioFormActionBar(
this::beginEdit,
this::applyDraft,
this::resetDraft,
this::cancelEdit);
private AssetWorkspaceDetailsViewState viewState; private AssetWorkspaceDetailsViewState viewState;
private StudioFormSession<AssetContractDraft> formSession; private StudioFormSession<AssetContractDraft> formSession;
public AssetDetailsContractControl(ProjectReference projectReference, StudioWorkspaceEventBus workspaceBus) { public AssetDetailsContractControl(ProjectReference projectReference, StudioWorkspaceEventBus workspaceBus) {
StudioControlLifecycleSupport.install(this, this);
this.projectReference = Objects.requireNonNull(projectReference, "projectReference"); this.projectReference = Objects.requireNonNull(projectReference, "projectReference");
this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus"); this.workspaceBus = Objects.requireNonNull(workspaceBus, "workspaceBus");
} }
@ -53,7 +45,7 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> { subscriptions.add(workspaceBus.subscribe(StudioAssetsDetailsViewStateChangedEvent.class, event -> {
viewState = event.viewState(); viewState = event.viewState();
syncFormSession(); syncFormSession();
render(); renderSection();
})); }));
} }
@ -79,7 +71,8 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
} }
} }
private void render() { @Override
protected void renderSection() {
if (viewState == null || viewState.selectedAssetDetails() == null) { if (viewState == null || viewState.selectedAssetDetails() == null) {
getChildren().clear(); getChildren().clear();
return; return;
@ -129,14 +122,27 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
final VBox content = new VBox(12); final VBox content = new VBox(12);
content.getChildren().setAll(contractBody); content.getChildren().setAll(contractBody);
actionBar.updateState(formSession.mode(), formSession.isDirty()); renderFormSection(content);
content.getChildren().add(actionBar); }
final VBox section = AssetDetailsUiSupport.createSection( @Override
Container.i18n().text(I18n.ASSETS_SECTION_RUNTIME_CONTRACT), protected String sectionTitle() {
content); return Container.i18n().text(I18n.ASSETS_SECTION_RUNTIME_CONTRACT);
section.getStyleClass().add("assets-details-contract-section"); }
getChildren().setAll(section);
@Override
protected StudioFormMode formMode() {
return formSession == null ? StudioFormMode.READ_ONLY : formSession.mode();
}
@Override
protected boolean isDirty() {
return formSession != null && formSession.isDirty();
}
@Override
protected String sectionStyleClass() {
return "assets-details-contract-section";
} }
private Node createPreloadEditor(AssetContractDraft draft, boolean editing) { private Node createPreloadEditor(AssetContractDraft draft, boolean editing) {
@ -147,7 +153,7 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
checkBox.selectedProperty().addListener((ignored, oldValue, newValue) -> { checkBox.selectedProperty().addListener((ignored, oldValue, newValue) -> {
if (!Objects.equals(oldValue, newValue)) { if (!Objects.equals(oldValue, newValue)) {
formSession.updateDraft(current -> current.withPreload(newValue)); formSession.updateDraft(current -> current.withPreload(newValue));
actionBar.updateState(formSession.mode(), formSession.isDirty()); updateActionBarState();
} }
}); });
} else { } else {
@ -182,7 +188,7 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
codecCombo.valueProperty().addListener((ignored, oldValue, newValue) -> { codecCombo.valueProperty().addListener((ignored, oldValue, newValue) -> {
if (newValue != null && !Objects.equals(oldValue, newValue)) { if (newValue != null && !Objects.equals(oldValue, newValue)) {
formSession.updateDraft(current -> current.withSelectedCodec(newValue)); formSession.updateDraft(current -> current.withSelectedCodec(newValue));
render(); renderSection();
} }
}); });
} else { } else {
@ -269,7 +275,7 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
formSession.updateDraft(current -> current.withMetadataFieldValue( formSession.updateDraft(current -> current.withMetadataFieldValue(
field.key(), field.key(),
Boolean.toString(newValue))); Boolean.toString(newValue)));
actionBar.updateState(formSession.mode(), formSession.isDirty()); updateActionBarState();
} }
}); });
} else { } else {
@ -292,7 +298,7 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
formSession.updateDraft(current -> current.withMetadataFieldValue( formSession.updateDraft(current -> current.withMetadataFieldValue(
field.key(), field.key(),
newValue)); newValue));
actionBar.updateState(formSession.mode(), formSession.isDirty()); updateActionBarState();
} }
}); });
} else { } else {
@ -315,7 +321,7 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
formSession.updateDraft(current -> current.withMetadataFieldValue( formSession.updateDraft(current -> current.withMetadataFieldValue(
field.key(), field.key(),
Objects.requireNonNullElse(newValue, ""))); Objects.requireNonNullElse(newValue, "")));
actionBar.updateState(formSession.mode(), formSession.isDirty()); updateActionBarState();
} }
}); });
} else { } else {
@ -363,7 +369,7 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
current.selectedCodec(), current.selectedCodec(),
field.key(), field.key(),
Boolean.toString(newValue))); Boolean.toString(newValue)));
actionBar.updateState(formSession.mode(), formSession.isDirty()); updateActionBarState();
} }
}); });
} else { } else {
@ -387,7 +393,7 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
current.selectedCodec(), current.selectedCodec(),
field.key(), field.key(),
newValue)); newValue));
actionBar.updateState(formSession.mode(), formSession.isDirty()); updateActionBarState();
} }
}); });
} else { } else {
@ -411,7 +417,7 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
current.selectedCodec(), current.selectedCodec(),
field.key(), field.key(),
Objects.requireNonNullElse(newValue, ""))); Objects.requireNonNullElse(newValue, "")));
actionBar.updateState(formSession.mode(), formSession.isDirty()); updateActionBarState();
} }
}); });
} else { } else {
@ -434,15 +440,16 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
control.setFocusTraversable(false); control.setFocusTraversable(false);
} }
private void beginEdit() { @Override
protected void beginEdit() {
if (formSession == null) { if (formSession == null) {
return; return;
} }
formSession.beginEdit(); formSession.beginEdit();
render();
} }
private void applyDraft() { @Override
protected void apply() {
if (formSession == null) { if (formSession == null) {
return; return;
} }
@ -462,34 +469,38 @@ public final class AssetDetailsContractControl extends VBox implements StudioCon
final var r = formSession.apply(); final var r = formSession.apply();
workspaceBus.publish(new StudioAssetLogEvent("ASSET DETAILS CONTRACT", "Asset contract updated")); workspaceBus.publish(new StudioAssetLogEvent("ASSET DETAILS CONTRACT", "Asset contract updated"));
workspaceBus.publish(new StudioAssetsRefreshRequestedEvent(r.assetReference())); workspaceBus.publish(new StudioAssetsRefreshRequestedEvent(r.assetReference()));
render(); renderSection();
}); });
} else { } else {
Platform.runLater(() -> { Platform.runLater(() -> {
workspaceBus.publish(new StudioAssetLogEvent("ASSET DETAILS CONTRACT", response.errorMessage())); workspaceBus.publish(new StudioAssetLogEvent("ASSET DETAILS CONTRACT", response.errorMessage()));
cancelEdit(); cancel();
renderSection();
}); });
} }
} catch (Exception e) { } catch (Exception e) {
workspaceBus.publish(new StudioAssetLogEvent("ASSET DETAILS CONTRACT", e.getMessage())); workspaceBus.publish(new StudioAssetLogEvent("ASSET DETAILS CONTRACT", e.getMessage()));
cancelEdit(); Platform.runLater(() -> {
cancel();
renderSection();
});
} }
}); });
} }
private void resetDraft() { @Override
protected void reset() {
if (formSession == null) { if (formSession == null) {
return; return;
} }
formSession.resetDraft(); formSession.resetDraft();
render();
} }
private void cancelEdit() { @Override
protected void cancel() {
if (formSession == null) { if (formSession == null) {
return; return;
} }
formSession.cancelEdit(); formSession.cancelEdit();
render();
} }
} }

View File

@ -71,6 +71,8 @@ public final class AssetDetailsSummaryControl extends VBox implements StudioCont
AssetDetailsUiSupport.createChip( AssetDetailsUiSupport.createChip(
AssetDetailsUiSupport.buildChipTone(summary.buildParticipation()), AssetDetailsUiSupport.buildChipTone(summary.buildParticipation()),
AssetDetailsUiSupport.buildParticipationLabel(summary.buildParticipation())))); AssetDetailsUiSupport.buildParticipationLabel(summary.buildParticipation()))));
getChildren().setAll(AssetDetailsUiSupport.createSection(Container.i18n().text(I18n.ASSETS_SECTION_SUMMARY), content)); getChildren().setAll(AssetDetailsUiSupport.createSection(
Container.i18n().text(I18n.ASSETS_SECTION_SUMMARY),
content));
} }
} }

View File

@ -213,6 +213,44 @@
-fx-padding: 8 0 0 0; -fx-padding: 8 0 0 0;
} }
.studio-form-section {
-fx-background-color: #11151b;
-fx-background-radius: 12;
-fx-border-radius: 12;
-fx-border-color: #26313d;
-fx-padding: 12;
}
.studio-form-section-editing {
-fx-background-color: #24181d;
-fx-border-color: #6f4754;
}
.studio-form-section-header {
-fx-alignment: center-left;
-fx-background-color: #172331;
-fx-border-color: #35516c;
-fx-border-radius: 10;
-fx-background-radius: 10;
-fx-padding: 8 10 8 10;
-fx-min-height: 42;
-fx-pref-height: 42;
}
.studio-form-section-title {
-fx-text-fill: #f5f9ff;
-fx-font-size: 14px;
-fx-font-weight: bold;
}
.studio-form-section-actions {
-fx-padding: 0;
-fx-alignment: center-right;
-fx-min-width: 340;
-fx-pref-width: 340;
-fx-max-width: 340;
}
.studio-workspace-rail-button { .studio-workspace-rail-button {
-fx-font-size: 16px; -fx-font-size: 16px;
} }
@ -509,15 +547,15 @@
-fx-alignment: top-left; -fx-alignment: top-left;
} }
.assets-details-summary-actions-row > .assets-details-section:first-child { .assets-details-summary-actions-row > .studio-form-section:first-child {
-fx-min-width: 0; -fx-min-width: 0;
} }
.assets-details-summary-actions-row > .assets-details-section:last-child { .assets-details-summary-actions-row > .studio-form-section:last-child {
-fx-min-width: 0; -fx-min-width: 0;
} }
.assets-details-summary-actions-row > .assets-details-section { .assets-details-summary-actions-row > .studio-form-section {
-fx-alignment: top-left; -fx-alignment: top-left;
} }
@ -542,20 +580,6 @@
-fx-font-size: 12px; -fx-font-size: 12px;
} }
.assets-details-section {
-fx-background-color: #11151b;
-fx-background-radius: 12;
-fx-border-radius: 12;
-fx-border-color: #26313d;
-fx-padding: 12;
}
.assets-details-section-title {
-fx-text-fill: #f5f9ff;
-fx-font-size: 14px;
-fx-font-weight: bold;
}
.assets-details-subsection-title { .assets-details-subsection-title {
-fx-text-fill: #b8d7f6; -fx-text-fill: #b8d7f6;
-fx-font-size: 12px; -fx-font-size: 12px;

File diff suppressed because it is too large Load Diff

View File

@ -10,14 +10,14 @@
"last_modified" : 1773571367191, "last_modified" : 1773571367191,
"fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094",
"metadata" : { "metadata" : {
"palette" : {
"originalArgb8888" : [ -265674 ],
"convertedRgb565" : [ -122 ]
},
"tile" : { "tile" : {
"width" : 16, "width" : 16,
"height" : 16, "height" : 16,
"paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ=="
},
"palette" : {
"originalArgb8888" : [ -265674 ],
"convertedRgb565" : [ -122 ]
} }
} }
} ] } ]
@ -43,14 +43,14 @@
"last_modified" : 1773253076764, "last_modified" : 1773253076764,
"fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094",
"metadata" : { "metadata" : {
"palette" : {
"originalArgb8888" : [ -265674 ],
"convertedRgb565" : [ -122 ]
},
"tile" : { "tile" : {
"width" : 16, "width" : 16,
"height" : 16, "height" : 16,
"paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ=="
},
"palette" : {
"originalArgb8888" : [ -265674 ],
"convertedRgb565" : [ -122 ]
} }
} }
} ] } ]

View File

@ -15,5 +15,8 @@
"preload" : { "preload" : {
"enabled" : true "enabled" : true
}, },
"artifacts" : [ ] "artifacts" : [ {
"file" : "confirm.png",
"index" : 0
} ]
} }

View File

@ -1,5 +1,5 @@
{ {
"paletteIndices" : [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 ],
"width" : 16, "width" : 16,
"height" : 16 "height" : 16,
"paletteIndices" : [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 ]
} }