feat(FileSelectionDialogModule, G2DButtonControlImpl): add optional lazy per-file tooltip data on hover
This commit is contained in:
@@ -9,8 +9,11 @@ import de.extio.game_engine.renderer.g2d.theme.G2DThemeManager;
|
|||||||
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.ButtonControl;
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.ButtonControl;
|
||||||
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.ButtonData;
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.ButtonData;
|
||||||
import de.extio.game_engine.renderer.model.color.RgbaColor;
|
import de.extio.game_engine.renderer.model.color.RgbaColor;
|
||||||
|
import de.extio.game_engine.renderer.model.event.MouseEnterEvent;
|
||||||
|
import de.extio.game_engine.renderer.model.event.MouseExitEvent;
|
||||||
import de.extio.game_engine.renderer.model.event.UiControlEvent;
|
import de.extio.game_engine.renderer.model.event.UiControlEvent;
|
||||||
import de.extio.game_engine.resource.StaticResource;
|
import de.extio.game_engine.resource.StaticResource;
|
||||||
|
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
|
||||||
|
|
||||||
public class G2DButtonControlImpl extends G2DBaseControlImpl implements ButtonControl {
|
public class G2DButtonControlImpl extends G2DBaseControlImpl implements ButtonControl {
|
||||||
|
|
||||||
@@ -23,6 +26,8 @@ public class G2DButtonControlImpl extends G2DBaseControlImpl implements ButtonCo
|
|||||||
protected long lastControlDataUpdateTime;
|
protected long lastControlDataUpdateTime;
|
||||||
|
|
||||||
protected long lastControlDataUpdateTimeInternal;
|
protected long lastControlDataUpdateTimeInternal;
|
||||||
|
|
||||||
|
protected boolean hovered;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCustomData(final ButtonData data) {
|
public void setCustomData(final ButtonData data) {
|
||||||
@@ -68,7 +73,21 @@ public class G2DButtonControlImpl extends G2DBaseControlImpl implements ButtonCo
|
|||||||
this.control.setLocation(this.x, this.y);
|
this.control.setLocation(this.x, this.y);
|
||||||
this.positionModified = false;
|
this.positionModified = false;
|
||||||
}
|
}
|
||||||
this.tooltipMousePosition = this.control.getLastMousePosition();
|
final var mousePosition = this.control.getLastMousePosition();
|
||||||
|
final var hoveredNow = mousePosition != null && this.visible && this.enabled;
|
||||||
|
if (hoveredNow != this.hovered) {
|
||||||
|
this.hovered = hoveredNow;
|
||||||
|
final var coord = mousePosition != null
|
||||||
|
? ImmutableCoordI2.create(this.x + mousePosition.getX(), this.y + mousePosition.getY())
|
||||||
|
: ImmutableCoordI2.create(this.x + this.width / 2, this.y + this.height / 2);
|
||||||
|
if (hoveredNow) {
|
||||||
|
this.rendererData.getEventService().fire(new MouseEnterEvent(this.id, 0, coord, coord));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.rendererData.getEventService().fire(new MouseExitEvent(this.id, 0, coord, coord));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.tooltipMousePosition = mousePosition;
|
||||||
|
|
||||||
super.render();
|
super.render();
|
||||||
}
|
}
|
||||||
@@ -82,6 +101,7 @@ public class G2DButtonControlImpl extends G2DBaseControlImpl implements ButtonCo
|
|||||||
this.control.invalidate();
|
this.control.invalidate();
|
||||||
this.control.close();
|
this.control.close();
|
||||||
((G2DRenderer) this.rendererData.getRenderer()).getMainFrame().remove(this.control);
|
((G2DRenderer) this.rendererData.getRenderer()).getMainFrame().remove(this.control);
|
||||||
|
this.hovered = false;
|
||||||
|
|
||||||
super.close();
|
super.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,22 @@ import de.extio.game_engine.spatial2.model.CoordI2;
|
|||||||
*/
|
*/
|
||||||
public final class MouseEnterEvent extends MouseEvent {
|
public final class MouseEnterEvent extends MouseEvent {
|
||||||
|
|
||||||
|
private final String controlId;
|
||||||
|
|
||||||
public MouseEnterEvent(final int modifiers, final CoordI2 rawCoord, final CoordI2 scaledCoord) {
|
public MouseEnterEvent(final int modifiers, final CoordI2 rawCoord, final CoordI2 scaledCoord) {
|
||||||
|
this(null, modifiers, rawCoord, scaledCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MouseEnterEvent(final String controlId, final int modifiers, final CoordI2 rawCoord, final CoordI2 scaledCoord) {
|
||||||
super(rawCoord, scaledCoord, modifiers);
|
super(rawCoord, scaledCoord, modifiers);
|
||||||
|
this.controlId = controlId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control ID the mouse entered, null if the mouse entered the viewport
|
||||||
|
*/
|
||||||
|
public String getControlId() {
|
||||||
|
return this.controlId;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,22 @@ import de.extio.game_engine.spatial2.model.CoordI2;
|
|||||||
*/
|
*/
|
||||||
public final class MouseExitEvent extends MouseEvent {
|
public final class MouseExitEvent extends MouseEvent {
|
||||||
|
|
||||||
|
private final String controlId;
|
||||||
|
|
||||||
public MouseExitEvent(final int modifiers, final CoordI2 rawCoord, final CoordI2 scaledCoord) {
|
public MouseExitEvent(final int modifiers, final CoordI2 rawCoord, final CoordI2 scaledCoord) {
|
||||||
|
this(null, modifiers, rawCoord, scaledCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MouseExitEvent(final String controlId, final int modifiers, final CoordI2 rawCoord, final CoordI2 scaledCoord) {
|
||||||
super(rawCoord, scaledCoord, modifiers);
|
super(rawCoord, scaledCoord, modifiers);
|
||||||
|
this.controlId = controlId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control ID the mouse exited, null if the mouse exited the viewport
|
||||||
|
*/
|
||||||
|
public String getControlId() {
|
||||||
|
return this.controlId;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
@@ -30,6 +31,8 @@ import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.ToggleButtonCon
|
|||||||
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.ToggleButtonData;
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.ToggleButtonData;
|
||||||
import de.extio.game_engine.renderer.model.bo.DrawFontRenderingBo;
|
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.bo.HorizontalAlignment;
|
||||||
|
import de.extio.game_engine.renderer.model.event.MouseEnterEvent;
|
||||||
|
import de.extio.game_engine.renderer.model.event.MouseExitEvent;
|
||||||
import de.extio.game_engine.renderer.model.event.UiControlEvent;
|
import de.extio.game_engine.renderer.model.event.UiControlEvent;
|
||||||
import de.extio.game_engine.renderer.work.RenderingBoPool;
|
import de.extio.game_engine.renderer.work.RenderingBoPool;
|
||||||
import de.extio.game_engine.spatial2.model.Area2;
|
import de.extio.game_engine.spatial2.model.Area2;
|
||||||
@@ -145,8 +148,12 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
|
|
||||||
private String nameFieldValue;
|
private String nameFieldValue;
|
||||||
|
|
||||||
|
private Function<StorageItemDescriptor, String> tooltipDataProvider;
|
||||||
|
|
||||||
private final Map<String, List<String>> folderPathByControlId = new HashMap<>();
|
private final Map<String, List<String>> folderPathByControlId = new HashMap<>();
|
||||||
|
|
||||||
|
private final Map<UUID, String> tooltipCache = new HashMap<>();
|
||||||
|
|
||||||
private final Map<String, StorageItemDescriptor> itemByControlId = new HashMap<>();
|
private final Map<String, StorageItemDescriptor> itemByControlId = new HashMap<>();
|
||||||
|
|
||||||
private final Set<List<String>> virtualFolders = new HashSet<>();
|
private final Set<List<String>> virtualFolders = new HashSet<>();
|
||||||
@@ -188,6 +195,8 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
@Override
|
@Override
|
||||||
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(MouseEnterEvent.class, this.getId(), this::onItemMouseEnter);
|
||||||
|
this.eventService.register(MouseExitEvent.class, this.getId(), this::onItemMouseExit);
|
||||||
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.eventService.register(FileSelectionNewFolderDialogResponse.class, this.getId(), this::onNewFolderResponse);
|
||||||
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), true);
|
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), true);
|
||||||
@@ -199,6 +208,8 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
@Override
|
@Override
|
||||||
public void onHide() {
|
public void onHide() {
|
||||||
this.eventService.unregister(UiControlEvent.class, this.getId());
|
this.eventService.unregister(UiControlEvent.class, this.getId());
|
||||||
|
this.eventService.unregister(MouseEnterEvent.class, this.getId());
|
||||||
|
this.eventService.unregister(MouseExitEvent.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.eventService.unregister(FileSelectionNewFolderDialogResponse.class, this.getId());
|
||||||
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), false);
|
this.getModuleService().changeDisplayState(this.dialogWindow.getId(), false);
|
||||||
@@ -209,6 +220,10 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void open(final String requestId, final FileSelectionMode mode, final List<String> basePath, final String filterPattern, final boolean recursive, final boolean modal, final String initialName, final Window parentWindow) {
|
public void open(final String requestId, final FileSelectionMode mode, final List<String> basePath, final String filterPattern, final boolean recursive, final boolean modal, final String initialName, final Window parentWindow) {
|
||||||
|
this.open(requestId, mode, basePath, filterPattern, recursive, modal, initialName, parentWindow, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(final String requestId, final FileSelectionMode mode, final List<String> basePath, final String filterPattern, final boolean recursive, final boolean modal, final String initialName, final Window parentWindow, final Function<StorageItemDescriptor, String> tooltipDataProvider) {
|
||||||
this.requestId = requestId;
|
this.requestId = requestId;
|
||||||
this.mode = mode != null ? mode : FileSelectionMode.LOAD;
|
this.mode = mode != null ? mode : FileSelectionMode.LOAD;
|
||||||
this.basePath = basePath != null ? List.copyOf(basePath) : List.of();
|
this.basePath = basePath != null ? List.copyOf(basePath) : List.of();
|
||||||
@@ -216,6 +231,8 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
this.filterPattern = filterPattern;
|
this.filterPattern = filterPattern;
|
||||||
this.recursive = recursive;
|
this.recursive = recursive;
|
||||||
this.modal = modal;
|
this.modal = modal;
|
||||||
|
this.tooltipDataProvider = tooltipDataProvider;
|
||||||
|
this.tooltipCache.clear();
|
||||||
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() : "";
|
||||||
@@ -269,6 +286,52 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onItemMouseEnter(final MouseEnterEvent event) {
|
||||||
|
if (this.tooltipDataProvider == null || event == null || event.getControlId() == null || !event.getControlId().startsWith(ITEM_PREFIX)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final var descriptor = this.itemByControlId.get(event.getControlId());
|
||||||
|
if (descriptor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final var data = this.resolveTooltipData(descriptor);
|
||||||
|
if (data == null || data.isBlank()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.updateItemTooltip(event.getControlId(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onItemMouseExit(final MouseExitEvent event) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveTooltipData(final StorageItemDescriptor descriptor) {
|
||||||
|
final var cached = this.tooltipCache.get(descriptor.id());
|
||||||
|
if (cached != null) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
String data;
|
||||||
|
try {
|
||||||
|
data = this.tooltipDataProvider.apply(descriptor);
|
||||||
|
}
|
||||||
|
catch (final Exception ex) {
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
if (data == null) {
|
||||||
|
data = "";
|
||||||
|
}
|
||||||
|
this.tooltipCache.put(descriptor.id(), data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateItemTooltip(final String controlId, final String data) {
|
||||||
|
final var bo = this.itemsScrollArea.getRenderingBo(controlId, ControlRenderingBo.class);
|
||||||
|
if (bo != null) {
|
||||||
|
bo.setTooltip(data);
|
||||||
|
this.itemsScrollArea.putRenderingBo(bo);
|
||||||
|
this.dialogWindow.draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void buildDialog() {
|
private void buildDialog() {
|
||||||
this.dialogWindow.clearRenderingBos();
|
this.dialogWindow.clearRenderingBos();
|
||||||
this.clearScrollArea();
|
this.clearScrollArea();
|
||||||
@@ -685,6 +748,8 @@ public class FileSelectionDialogModule extends AbstractClientModule {
|
|||||||
this.selectedDescriptor = null;
|
this.selectedDescriptor = null;
|
||||||
this.selectionIsNew = false;
|
this.selectionIsNew = false;
|
||||||
this.nameFieldValue = "";
|
this.nameFieldValue = "";
|
||||||
|
this.tooltipDataProvider = null;
|
||||||
|
this.tooltipCache.clear();
|
||||||
this.virtualFolders.clear();
|
this.virtualFolders.clear();
|
||||||
this.folderPathByControlId.clear();
|
this.folderPathByControlId.clear();
|
||||||
this.itemByControlId.clear();
|
this.itemByControlId.clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user