feat(FileSelectionDialogModule): prompt dialog for new folder name, gate move button on recursive
This commit is contained in:
@@ -11,6 +11,7 @@ import de.extio.game_engine.i18n.LocalizationService;
|
|||||||
import de.extio.game_engine.renderer.work.RenderingBoPool;
|
import de.extio.game_engine.renderer.work.RenderingBoPool;
|
||||||
import de.extio.game_engine.storage.dialog.FileSelectionDialogModule;
|
import de.extio.game_engine.storage.dialog.FileSelectionDialogModule;
|
||||||
import de.extio.game_engine.storage.dialog.FileSelectionMoveDialogModule;
|
import de.extio.game_engine.storage.dialog.FileSelectionMoveDialogModule;
|
||||||
|
import de.extio.game_engine.storage.dialog.FileSelectionNewFolderDialogModule;
|
||||||
|
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@ConditionalOnProperty(name = "game-engine.storage.enabled", havingValue = "true", matchIfMissing = true)
|
@ConditionalOnProperty(name = "game-engine.storage.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
@@ -34,7 +35,15 @@ public class StorageServiceAutoConfiguration {
|
|||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@ConditionalOnProperty(name = "game-engine.storage.dialog.enabled", havingValue = "true", matchIfMissing = true)
|
@ConditionalOnProperty(name = "game-engine.storage.dialog.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
@ConditionalOnProperty(name = "game-engine.renderer.enabled", havingValue = "true", matchIfMissing = true)
|
@ConditionalOnProperty(name = "game-engine.renderer.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
FileSelectionDialogModule fileSelectionDialog(final ApplicationContext applicationContext, final EventService eventService, final LocalizationService localizationService, final RenderingBoPool renderingBoPool, final StorageService storageService, final FileSelectionMoveDialogModule fileSelectionMoveDialog) {
|
FileSelectionNewFolderDialogModule fileSelectionNewFolderDialog(final ApplicationContext applicationContext, final EventService eventService, final LocalizationService localizationService, final RenderingBoPool renderingBoPool) {
|
||||||
return new FileSelectionDialogModule(applicationContext, eventService, localizationService, renderingBoPool, storageService, fileSelectionMoveDialog);
|
return new FileSelectionNewFolderDialogModule(applicationContext, eventService, localizationService, renderingBoPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConditionalOnProperty(name = "game-engine.storage.dialog.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
@ConditionalOnProperty(name = "game-engine.renderer.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
FileSelectionDialogModule fileSelectionDialog(final ApplicationContext applicationContext, final EventService eventService, final LocalizationService localizationService, final RenderingBoPool renderingBoPool, final StorageService storageService, final FileSelectionMoveDialogModule fileSelectionMoveDialog, final FileSelectionNewFolderDialogModule fileSelectionNewFolderDialog) {
|
||||||
|
return new FileSelectionDialogModule(applicationContext, eventService, localizationService, renderingBoPool, storageService, fileSelectionMoveDialog, fileSelectionNewFolderDialog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import de.extio.game_engine.storage.StorageItemDescriptor;
|
|||||||
import de.extio.game_engine.storage.StorageResource;
|
import de.extio.game_engine.storage.StorageResource;
|
||||||
import de.extio.game_engine.storage.StorageService;
|
import de.extio.game_engine.storage.StorageService;
|
||||||
import de.extio.game_engine.storage.dialog.FileSelectionMoveDialogModule.FileSelectionMoveDialogResponse;
|
import de.extio.game_engine.storage.dialog.FileSelectionMoveDialogModule.FileSelectionMoveDialogResponse;
|
||||||
|
import de.extio.game_engine.storage.dialog.FileSelectionNewFolderDialogModule.FileSelectionNewFolderDialogResponse;
|
||||||
|
|
||||||
public class FileSelectionDialogModule extends AbstractClientModule {
|
public class FileSelectionDialogModule extends AbstractClientModule {
|
||||||
|
|
||||||
@@ -82,8 +83,6 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
|
|
||||||
private static final String NAME_FIELD_ID = "FileSelectionDialog_NameField";
|
private static final String NAME_FIELD_ID = "FileSelectionDialog_NameField";
|
||||||
|
|
||||||
private static final String NEW_FOLDER_FIELD_ID = "FileSelectionDialog_NewFolderField";
|
|
||||||
|
|
||||||
private static final String BUTTON_NEW_FOLDER = "FileSelectionDialog_Button_NewFolder";
|
private static final String BUTTON_NEW_FOLDER = "FileSelectionDialog_Button_NewFolder";
|
||||||
|
|
||||||
private static final String BUTTON_NEW_ITEM = "FileSelectionDialog_Button_NewItem";
|
private static final String BUTTON_NEW_ITEM = "FileSelectionDialog_Button_NewItem";
|
||||||
@@ -110,13 +109,16 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
|
|
||||||
private final FileSelectionMoveDialogModule moveDialogModule;
|
private final FileSelectionMoveDialogModule moveDialogModule;
|
||||||
|
|
||||||
public FileSelectionDialogModule(final ApplicationContext applicationContext, final EventService eventService, final LocalizationService localizationService, final RenderingBoPool renderingBoPool, final StorageService storageService, final FileSelectionMoveDialogModule moveDialogModule) {
|
private final FileSelectionNewFolderDialogModule newFolderDialogModule;
|
||||||
|
|
||||||
|
public FileSelectionDialogModule(final ApplicationContext applicationContext, final EventService eventService, final LocalizationService localizationService, final RenderingBoPool renderingBoPool, final StorageService storageService, final FileSelectionMoveDialogModule moveDialogModule, final FileSelectionNewFolderDialogModule newFolderDialogModule) {
|
||||||
this.applicationContext = applicationContext;
|
this.applicationContext = applicationContext;
|
||||||
this.eventService = eventService;
|
this.eventService = eventService;
|
||||||
this.localizationService = localizationService;
|
this.localizationService = localizationService;
|
||||||
this.renderingBoPool = renderingBoPool;
|
this.renderingBoPool = renderingBoPool;
|
||||||
this.storageService = storageService;
|
this.storageService = storageService;
|
||||||
this.moveDialogModule = moveDialogModule;
|
this.moveDialogModule = moveDialogModule;
|
||||||
|
this.newFolderDialogModule = newFolderDialogModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Window dialogWindow;
|
private Window dialogWindow;
|
||||||
@@ -143,8 +145,6 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
|
|
||||||
private String nameFieldValue;
|
private String nameFieldValue;
|
||||||
|
|
||||||
private String newFolderValue;
|
|
||||||
|
|
||||||
private final Map<String, List<String>> folderPathByControlId = new HashMap<>();
|
private final Map<String, List<String>> folderPathByControlId = new HashMap<>();
|
||||||
|
|
||||||
private final Map<String, StorageItemDescriptor> itemByControlId = new HashMap<>();
|
private final Map<String, StorageItemDescriptor> itemByControlId = new HashMap<>();
|
||||||
@@ -189,6 +189,7 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
public void onShow() {
|
public void onShow() {
|
||||||
this.eventService.register(UiControlEvent.class, this.getId(), this::onUiControlEvent);
|
this.eventService.register(UiControlEvent.class, this.getId(), this::onUiControlEvent);
|
||||||
this.eventService.register(FileSelectionMoveDialogResponse.class, this.getId(), this::onMoveResponse);
|
this.eventService.register(FileSelectionMoveDialogResponse.class, this.getId(), this::onMoveResponse);
|
||||||
|
this.eventService.register(FileSelectionNewFolderDialogResponse.class, this.getId(), this::onNewFolderResponse);
|
||||||
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), true);
|
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), true);
|
||||||
if (this.modal) {
|
if (this.modal) {
|
||||||
this.getModuleService().hideExcept(this.getId(), this.dialogWindow.getId());
|
this.getModuleService().hideExcept(this.getId(), this.dialogWindow.getId());
|
||||||
@@ -199,6 +200,7 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
public void onHide() {
|
public void onHide() {
|
||||||
this.eventService.unregister(UiControlEvent.class, this.getId());
|
this.eventService.unregister(UiControlEvent.class, this.getId());
|
||||||
this.eventService.unregister(FileSelectionMoveDialogResponse.class, this.getId());
|
this.eventService.unregister(FileSelectionMoveDialogResponse.class, this.getId());
|
||||||
|
this.eventService.unregister(FileSelectionNewFolderDialogResponse.class, this.getId());
|
||||||
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), false);
|
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), false);
|
||||||
if (this.modal) {
|
if (this.modal) {
|
||||||
this.getModuleService().restoreVisibility();
|
this.getModuleService().restoreVisibility();
|
||||||
@@ -217,7 +219,6 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
this.selectedDescriptor = null;
|
this.selectedDescriptor = null;
|
||||||
this.selectionIsNew = this.mode == FileSelectionMode.SAVE;
|
this.selectionIsNew = this.mode == FileSelectionMode.SAVE;
|
||||||
this.nameFieldValue = initialName != null && !initialName.isBlank() ? initialName.trim() : "";
|
this.nameFieldValue = initialName != null && !initialName.isBlank() ? initialName.trim() : "";
|
||||||
this.newFolderValue = "";
|
|
||||||
this.virtualFolders.clear();
|
this.virtualFolders.clear();
|
||||||
this.dialogWindow.setParent(parentWindow);
|
this.dialogWindow.setParent(parentWindow);
|
||||||
this.applyInitialSelection();
|
this.applyInitialSelection();
|
||||||
@@ -256,12 +257,7 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
this.handleNameChanged(text);
|
this.handleNameChanged(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case NEW_FOLDER_FIELD_ID -> {
|
case BUTTON_NEW_FOLDER -> this.openNewFolderDialog();
|
||||||
if (event.getPayload() instanceof final String text) {
|
|
||||||
this.newFolderValue = text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case BUTTON_NEW_FOLDER -> this.createFolder();
|
|
||||||
case BUTTON_NEW_ITEM -> this.selectNewItem();
|
case BUTTON_NEW_ITEM -> this.selectNewItem();
|
||||||
case BUTTON_RENAME -> this.renameSelection();
|
case BUTTON_RENAME -> this.renameSelection();
|
||||||
case BUTTON_DELETE -> this.deleteSelection();
|
case BUTTON_DELETE -> this.deleteSelection();
|
||||||
@@ -355,33 +351,6 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
}
|
}
|
||||||
yOffset += FIELD_HEIGHT + SPACING;
|
yOffset += FIELD_HEIGHT + SPACING;
|
||||||
|
|
||||||
final boolean showFolderField = this.recursive;
|
|
||||||
if (showFolderField) {
|
|
||||||
final var folderLabel = this.renderingBoPool.acquire("FileSelectionDialog_Label_NewFolder", ControlRenderingBo.class)
|
|
||||||
.setType(LabelControl.class)
|
|
||||||
.setCaption(this.localizationService.translate("ecyoa-190") + ":")
|
|
||||||
.setFontSize(18)
|
|
||||||
.setVisible(true)
|
|
||||||
.setEnabled(false)
|
|
||||||
.withDimensionAbsolute(contentWidth, LABEL_HEIGHT)
|
|
||||||
.withPositionRelative(Window.MARGIN_LEFT, yOffset)
|
|
||||||
.setLayer(RenderingBoLayer.UI0);
|
|
||||||
this.dialogWindow.putRenderingBo(folderLabel);
|
|
||||||
yOffset += LABEL_HEIGHT + SPACING / 2;
|
|
||||||
|
|
||||||
final var folderField = this.renderingBoPool.acquire(NEW_FOLDER_FIELD_ID, ControlRenderingBo.class)
|
|
||||||
.setType(TextfieldControl.class)
|
|
||||||
.setCaption(this.newFolderValue != null ? this.newFolderValue : "")
|
|
||||||
.setControlData(new TextfieldData(false, null))
|
|
||||||
.setVisible(true)
|
|
||||||
.setEnabled(true)
|
|
||||||
.withDimensionAbsolute(contentWidth, FIELD_HEIGHT)
|
|
||||||
.withPositionRelative(Window.MARGIN_LEFT, yOffset)
|
|
||||||
.setLayer(RenderingBoLayer.UI1);
|
|
||||||
this.dialogWindow.putRenderingBo(folderField);
|
|
||||||
yOffset += FIELD_HEIGHT + SPACING;
|
|
||||||
}
|
|
||||||
|
|
||||||
final var bottomRowY = WINDOW_HEIGHT - Window.MARGIN_BOTTOM - BUTTON_HEIGHT;
|
final var bottomRowY = WINDOW_HEIGHT - Window.MARGIN_BOTTOM - BUTTON_HEIGHT;
|
||||||
final var scrollHeight = Math.max(120, bottomRowY - yOffset - SPACING);
|
final var scrollHeight = Math.max(120, bottomRowY - yOffset - SPACING);
|
||||||
this.itemsScrollArea.setRelativeArea(new Area2(ImmutableCoordI2.create(Window.MARGIN_LEFT, yOffset), ImmutableCoordI2.create(contentWidth, scrollHeight)));
|
this.itemsScrollArea.setRelativeArea(new Area2(ImmutableCoordI2.create(Window.MARGIN_LEFT, yOffset), ImmutableCoordI2.create(contentWidth, scrollHeight)));
|
||||||
@@ -422,16 +391,18 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
this.dialogWindow.putRenderingBo(deleteButton);
|
this.dialogWindow.putRenderingBo(deleteButton);
|
||||||
buttonX += BUTTON_WIDTH + SPACING;
|
buttonX += BUTTON_WIDTH + SPACING;
|
||||||
|
|
||||||
final var moveButton = this.renderingBoPool.acquire(BUTTON_MOVE, ControlRenderingBo.class)
|
if (this.recursive) {
|
||||||
.setType(ButtonControl.class)
|
final var moveButton = this.renderingBoPool.acquire(BUTTON_MOVE, ControlRenderingBo.class)
|
||||||
.setCaption(this.localizationService.translate("ecyoa-644"))
|
.setType(ButtonControl.class)
|
||||||
.setVisible(true)
|
.setCaption(this.localizationService.translate("ecyoa-644"))
|
||||||
.setEnabled(this.selectedDescriptor != null)
|
.setVisible(true)
|
||||||
.withDimensionAbsolute(BUTTON_WIDTH, BUTTON_HEIGHT)
|
.setEnabled(this.selectedDescriptor != null)
|
||||||
.withPositionRelative(buttonX, bottomRowY)
|
.withDimensionAbsolute(BUTTON_WIDTH, BUTTON_HEIGHT)
|
||||||
.setLayer(RenderingBoLayer.UI1);
|
.withPositionRelative(buttonX, bottomRowY)
|
||||||
this.dialogWindow.putRenderingBo(moveButton);
|
.setLayer(RenderingBoLayer.UI1);
|
||||||
buttonX += BUTTON_WIDTH + SPACING;
|
this.dialogWindow.putRenderingBo(moveButton);
|
||||||
|
buttonX += BUTTON_WIDTH + SPACING;
|
||||||
|
}
|
||||||
|
|
||||||
final var okButton = this.renderingBoPool.acquire(BUTTON_OK, ControlRenderingBo.class)
|
final var okButton = this.renderingBoPool.acquire(BUTTON_OK, ControlRenderingBo.class)
|
||||||
.setType(ButtonControl.class)
|
.setType(ButtonControl.class)
|
||||||
@@ -585,20 +556,49 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createFolder() {
|
private void openNewFolderDialog() {
|
||||||
if (!this.canCreateFolder()) {
|
if (!this.recursive) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final var newPath = this.appendPath(this.currentPath, this.newFolderValue.trim());
|
this.newFolderDialogModule.open(this.childFolderNames(), this.dialogWindow);
|
||||||
this.virtualFolders.add(newPath);
|
}
|
||||||
this.currentPath = newPath;
|
|
||||||
this.newFolderValue = "";
|
private void onNewFolderResponse(final FileSelectionNewFolderDialogResponse event) {
|
||||||
|
if (event == null || !event.confirmed() || event.name() == null || event.name().isBlank()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final var name = event.name().trim();
|
||||||
|
final var targetPath = this.appendPath(this.currentPath, name);
|
||||||
|
if (this.virtualFolders.contains(targetPath) || this.folderExistsInStorage(name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.virtualFolders.add(targetPath);
|
||||||
|
this.currentPath = targetPath;
|
||||||
this.selectedDescriptor = null;
|
this.selectedDescriptor = null;
|
||||||
this.selectionIsNew = false;
|
this.selectionIsNew = false;
|
||||||
this.nameFieldValue = "";
|
this.nameFieldValue = "";
|
||||||
this.buildDialog();
|
this.buildDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<String> childFolderNames() {
|
||||||
|
final var names = new HashSet<String>();
|
||||||
|
for (final var descriptor : this.loadDescriptors()) {
|
||||||
|
if (descriptor == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final var path = this.safePath(descriptor.path());
|
||||||
|
if (this.isPathPrefix(this.currentPath, path) && path.size() > this.currentPath.size()) {
|
||||||
|
names.add(path.get(this.currentPath.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (final var virtualPath : this.virtualFolders) {
|
||||||
|
if (this.isPathPrefix(this.currentPath, virtualPath) && virtualPath.size() > this.currentPath.size()) {
|
||||||
|
names.add(virtualPath.get(this.currentPath.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
private void selectNewItem() {
|
private void selectNewItem() {
|
||||||
if (!this.canSelectNewItem()) {
|
if (!this.canSelectNewItem()) {
|
||||||
return;
|
return;
|
||||||
@@ -685,7 +685,6 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
this.selectedDescriptor = null;
|
this.selectedDescriptor = null;
|
||||||
this.selectionIsNew = false;
|
this.selectionIsNew = false;
|
||||||
this.nameFieldValue = "";
|
this.nameFieldValue = "";
|
||||||
this.newFolderValue = "";
|
|
||||||
this.virtualFolders.clear();
|
this.virtualFolders.clear();
|
||||||
this.folderPathByControlId.clear();
|
this.folderPathByControlId.clear();
|
||||||
this.itemByControlId.clear();
|
this.itemByControlId.clear();
|
||||||
@@ -699,15 +698,7 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean canCreateFolder() {
|
private boolean canCreateFolder() {
|
||||||
if (!this.recursive) {
|
return this.recursive;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.newFolderValue == null || this.newFolderValue.isBlank()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final var name = this.newFolderValue.trim();
|
|
||||||
final var targetPath = this.appendPath(this.currentPath, name);
|
|
||||||
return !this.virtualFolders.contains(targetPath) && !this.folderExistsInStorage(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean folderExistsInStorage(final String name) {
|
private boolean folderExistsInStorage(final String name) {
|
||||||
|
|||||||
@@ -0,0 +1,250 @@
|
|||||||
|
package de.extio.game_engine.storage.dialog;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
import de.extio.game_engine.event.Event;
|
||||||
|
import de.extio.game_engine.event.EventService;
|
||||||
|
import de.extio.game_engine.i18n.LocalizationService;
|
||||||
|
import de.extio.game_engine.module.AbstractClientModule;
|
||||||
|
import de.extio.game_engine.renderer.RendererControl;
|
||||||
|
import de.extio.game_engine.renderer.container.Window;
|
||||||
|
import de.extio.game_engine.renderer.model.RenderingBoLayer;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.ButtonControl;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.LabelControl;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.TextfieldControl;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.TextfieldData;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.DrawFontRenderingBo;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.HorizontalAlignment;
|
||||||
|
import de.extio.game_engine.renderer.model.event.UiControlEvent;
|
||||||
|
import de.extio.game_engine.renderer.work.RenderingBoPool;
|
||||||
|
import de.extio.game_engine.spatial2.model.CoordI2;
|
||||||
|
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
||||||
|
|
||||||
|
public class FileSelectionNewFolderDialogModule extends AbstractClientModule {
|
||||||
|
|
||||||
|
public record FileSelectionNewFolderDialogResponse(
|
||||||
|
boolean confirmed,
|
||||||
|
String name) implements Event {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int WINDOW_WIDTH = 500;
|
||||||
|
|
||||||
|
private static final int WINDOW_HEIGHT = 230;
|
||||||
|
|
||||||
|
private static final int TITLE_HEIGHT = 46;
|
||||||
|
|
||||||
|
private static final int LABEL_HEIGHT = 26;
|
||||||
|
|
||||||
|
private static final int FIELD_HEIGHT = 36;
|
||||||
|
|
||||||
|
private static final int BUTTON_HEIGHT = 42;
|
||||||
|
|
||||||
|
private static final int BUTTON_WIDTH = 150;
|
||||||
|
|
||||||
|
private static final int SPACING = 12;
|
||||||
|
|
||||||
|
private static final String NAME_FIELD_ID = "FileSelectionNewFolderDialog_NameField";
|
||||||
|
|
||||||
|
private static final String BUTTON_OK = "FileSelectionNewFolderDialog_Button_Ok";
|
||||||
|
|
||||||
|
private static final String BUTTON_CANCEL = "FileSelectionNewFolderDialog_Button_Cancel";
|
||||||
|
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final EventService eventService;
|
||||||
|
|
||||||
|
private final LocalizationService localizationService;
|
||||||
|
|
||||||
|
private final RenderingBoPool renderingBoPool;
|
||||||
|
|
||||||
|
public FileSelectionNewFolderDialogModule(final ApplicationContext applicationContext, final EventService eventService, final LocalizationService localizationService, final RenderingBoPool renderingBoPool) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
this.eventService = eventService;
|
||||||
|
this.localizationService = localizationService;
|
||||||
|
this.renderingBoPool = renderingBoPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Window dialogWindow;
|
||||||
|
|
||||||
|
private boolean opened;
|
||||||
|
|
||||||
|
private String nameFieldValue = "";
|
||||||
|
|
||||||
|
private Set<String> existingFolderNames = Set.of();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isProtected() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
this.dialogWindow = this.applicationContext.getBean(Window.class);
|
||||||
|
this.dialogWindow.setNormalizedDimension(ImmutableCoordI2.create(WINDOW_WIDTH, WINDOW_HEIGHT));
|
||||||
|
this.dialogWindow.setNormalizedPosition(this.centeredPosition(this.dialogWindow.getNormalizedDimension()));
|
||||||
|
this.dialogWindow.setDraggable(true);
|
||||||
|
this.dialogWindow.setCloseButton(true);
|
||||||
|
this.dialogWindow.setOnCloseAction(this::onCancel);
|
||||||
|
|
||||||
|
this.getModuleService().changeActiveState(this.getId(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnload() {
|
||||||
|
this.getModuleService().unloadModule(this.dialogWindow.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShow() {
|
||||||
|
this.eventService.register(UiControlEvent.class, this.getId(), this::onUiControlEvent);
|
||||||
|
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHide() {
|
||||||
|
this.eventService.unregister(UiControlEvent.class, this.getId());
|
||||||
|
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), false);
|
||||||
|
this.resetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(final Set<String> existingFolderNames, final Window parentWindow) {
|
||||||
|
this.existingFolderNames = existingFolderNames != null ? Set.copyOf(existingFolderNames) : Set.of();
|
||||||
|
this.nameFieldValue = "";
|
||||||
|
this.opened = true;
|
||||||
|
this.dialogWindow.setParent(parentWindow);
|
||||||
|
this.buildDialog();
|
||||||
|
this.getModuleService().changeDisplayState(this.getId(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onUiControlEvent(final UiControlEvent event) {
|
||||||
|
if (event.getId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (event.getId()) {
|
||||||
|
case NAME_FIELD_ID -> {
|
||||||
|
if (event.getPayload() instanceof final String text) {
|
||||||
|
final var value = text != null ? text : "";
|
||||||
|
if (!Objects.equals(this.nameFieldValue, value)) {
|
||||||
|
this.nameFieldValue = value;
|
||||||
|
this.buildDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case BUTTON_OK -> this.onOk();
|
||||||
|
case BUTTON_CANCEL -> this.onCancel();
|
||||||
|
default -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildDialog() {
|
||||||
|
this.dialogWindow.clearRenderingBos();
|
||||||
|
|
||||||
|
final var contentWidth = WINDOW_WIDTH - Window.MARGIN_LEFT - Window.MARGIN_RIGHT;
|
||||||
|
final var buttonRowY = WINDOW_HEIGHT - Window.MARGIN_BOTTOM - BUTTON_HEIGHT;
|
||||||
|
final var nameFieldY = buttonRowY - SPACING - FIELD_HEIGHT;
|
||||||
|
final var nameLabelY = nameFieldY - SPACING / 2 - LABEL_HEIGHT;
|
||||||
|
|
||||||
|
final var titleBo = this.renderingBoPool.acquire("FileSelectionNewFolderDialog_Title", DrawFontRenderingBo.class)
|
||||||
|
.setText(this.localizationService.translate("ecyoa-190"))
|
||||||
|
.setSize(28)
|
||||||
|
.setAlignment(HorizontalAlignment.CENTER)
|
||||||
|
.withDimensionAbsolute(contentWidth, TITLE_HEIGHT)
|
||||||
|
.withPositionRelative(Window.MARGIN_LEFT, Window.MARGIN_TOP);
|
||||||
|
this.dialogWindow.putRenderingBo(titleBo);
|
||||||
|
|
||||||
|
final var nameLabel = this.renderingBoPool.acquire("FileSelectionNewFolderDialog_Label_Name", ControlRenderingBo.class)
|
||||||
|
.setType(LabelControl.class)
|
||||||
|
.setCaption(this.localizationService.translate("ecyoa-646") + ":")
|
||||||
|
.setFontSize(18)
|
||||||
|
.setVisible(true)
|
||||||
|
.setEnabled(false)
|
||||||
|
.withDimensionAbsolute(contentWidth, LABEL_HEIGHT)
|
||||||
|
.withPositionRelative(Window.MARGIN_LEFT, nameLabelY)
|
||||||
|
.setLayer(RenderingBoLayer.UI0);
|
||||||
|
this.dialogWindow.putRenderingBo(nameLabel);
|
||||||
|
|
||||||
|
final var nameField = this.renderingBoPool.acquire(NAME_FIELD_ID, ControlRenderingBo.class)
|
||||||
|
.setType(TextfieldControl.class)
|
||||||
|
.setCaption(this.nameFieldValue != null ? this.nameFieldValue : "")
|
||||||
|
.setControlData(new TextfieldData(false, null))
|
||||||
|
.setVisible(true)
|
||||||
|
.setEnabled(true)
|
||||||
|
.withDimensionAbsolute(contentWidth, FIELD_HEIGHT)
|
||||||
|
.withPositionRelative(Window.MARGIN_LEFT, nameFieldY)
|
||||||
|
.setLayer(RenderingBoLayer.UI1);
|
||||||
|
this.dialogWindow.putRenderingBo(nameField);
|
||||||
|
|
||||||
|
final var okButton = this.renderingBoPool.acquire(BUTTON_OK, ControlRenderingBo.class)
|
||||||
|
.setType(ButtonControl.class)
|
||||||
|
.setCaption(this.localizationService.translate("ecyoa-3"))
|
||||||
|
.setVisible(true)
|
||||||
|
.setEnabled(this.canConfirm())
|
||||||
|
.withDimensionAbsolute(BUTTON_WIDTH, BUTTON_HEIGHT)
|
||||||
|
.withPositionRelative(Window.MARGIN_LEFT, buttonRowY)
|
||||||
|
.setLayer(RenderingBoLayer.UI1);
|
||||||
|
this.dialogWindow.putRenderingBo(okButton);
|
||||||
|
|
||||||
|
final var cancelButton = this.renderingBoPool.acquire(BUTTON_CANCEL, ControlRenderingBo.class)
|
||||||
|
.setType(ButtonControl.class)
|
||||||
|
.setCaption(this.localizationService.translate("ecyoa-89"))
|
||||||
|
.setVisible(true)
|
||||||
|
.setEnabled(true)
|
||||||
|
.withDimensionAbsolute(BUTTON_WIDTH, BUTTON_HEIGHT)
|
||||||
|
.withPositionRelative(WINDOW_WIDTH - Window.MARGIN_RIGHT - BUTTON_WIDTH, buttonRowY)
|
||||||
|
.setLayer(RenderingBoLayer.UI1);
|
||||||
|
this.dialogWindow.putRenderingBo(cancelButton);
|
||||||
|
|
||||||
|
this.dialogWindow.draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onOk() {
|
||||||
|
if (!this.canConfirm()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.eventService.fire(new FileSelectionNewFolderDialogResponse(true, this.nameFieldValue.trim()));
|
||||||
|
this.onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onCancel() {
|
||||||
|
if (this.opened) {
|
||||||
|
this.eventService.fire(new FileSelectionNewFolderDialogResponse(false, null));
|
||||||
|
this.onClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClose() {
|
||||||
|
this.getModuleService().changeDisplayState(this.getId(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetState() {
|
||||||
|
this.opened = false;
|
||||||
|
this.nameFieldValue = "";
|
||||||
|
this.existingFolderNames = Set.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canConfirm() {
|
||||||
|
final var name = this.nameFieldValue != null ? this.nameFieldValue.trim() : "";
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (final var existing : this.existingFolderNames) {
|
||||||
|
if (existing.equalsIgnoreCase(name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImmutableCoordI2 centeredPosition(final CoordI2 dimension) {
|
||||||
|
final var referenceResolution = RendererControl.REFERENCE_RESOLUTION;
|
||||||
|
final var x = (referenceResolution.getX() - dimension.getX()) / 2;
|
||||||
|
final var y = (referenceResolution.getY() - dimension.getY()) / 2;
|
||||||
|
return ImmutableCoordI2.create(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user