minecraft-src/net/minecraft/client/gui/components/ContainerObjectSelectionList.java
2025-07-04 03:45:38 +03:00

224 lines
6.8 KiB
Java

package net.minecraft.client.gui.components;
import java.util.List;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ComponentPath;
import net.minecraft.client.gui.components.events.ContainerEventHandler;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.narration.NarratedElementType;
import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.client.gui.narration.NarratableEntry.NarrationPriority;
import net.minecraft.client.gui.navigation.FocusNavigationEvent;
import net.minecraft.client.gui.navigation.ScreenAxis;
import net.minecraft.client.gui.navigation.ScreenDirection;
import net.minecraft.client.gui.navigation.FocusNavigationEvent.ArrowNavigation;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraft.util.Mth;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public abstract class ContainerObjectSelectionList<E extends ContainerObjectSelectionList.Entry<E>> extends AbstractSelectionList<E> {
public ContainerObjectSelectionList(Minecraft minecraft, int i, int j, int k, int l) {
super(minecraft, i, j, k, l);
}
public ContainerObjectSelectionList(Minecraft minecraft, int i, int j, int k, int l, int m) {
super(minecraft, i, j, k, l, m);
}
@Nullable
@Override
public ComponentPath nextFocusPath(FocusNavigationEvent event) {
if (this.getItemCount() == 0) {
return null;
} else if (!(event instanceof ArrowNavigation arrowNavigation)) {
return super.nextFocusPath(event);
} else {
E entry = this.getFocused();
if (arrowNavigation.direction().getAxis() == ScreenAxis.HORIZONTAL && entry != null) {
return ComponentPath.path(this, entry.nextFocusPath(event));
} else {
int i = -1;
ScreenDirection screenDirection = arrowNavigation.direction();
if (entry != null) {
i = entry.children().indexOf(entry.getFocused());
}
if (i == -1) {
switch (screenDirection) {
case LEFT:
i = Integer.MAX_VALUE;
screenDirection = ScreenDirection.DOWN;
break;
case RIGHT:
i = 0;
screenDirection = ScreenDirection.DOWN;
break;
default:
i = 0;
}
}
E entry2 = entry;
ComponentPath componentPath;
do {
entry2 = this.nextEntry(screenDirection, entryx -> !entryx.children().isEmpty(), entry2);
if (entry2 == null) {
return null;
}
componentPath = entry2.focusPathAtIndex(arrowNavigation, i);
} while (componentPath == null);
return ComponentPath.path(this, componentPath);
}
}
}
@Override
public void setFocused(@Nullable GuiEventListener focused) {
if (this.getFocused() != focused) {
super.setFocused(focused);
if (focused == null) {
this.setSelected(null);
}
}
}
@Override
public NarrationPriority narrationPriority() {
return this.isFocused() ? NarrationPriority.FOCUSED : super.narrationPriority();
}
@Override
protected boolean isSelectedItem(int index) {
return false;
}
@Override
public void updateWidgetNarration(NarrationElementOutput narrationElementOutput) {
E entry = this.getHovered();
if (entry != null) {
entry.updateNarration(narrationElementOutput.nest());
this.narrateListElementPosition(narrationElementOutput, entry);
} else {
E entry2 = this.getFocused();
if (entry2 != null) {
entry2.updateNarration(narrationElementOutput.nest());
this.narrateListElementPosition(narrationElementOutput, entry2);
}
}
narrationElementOutput.add(NarratedElementType.USAGE, Component.translatable("narration.component_list.usage"));
}
@Environment(EnvType.CLIENT)
public abstract static class Entry<E extends ContainerObjectSelectionList.Entry<E>>
extends net.minecraft.client.gui.components.AbstractSelectionList.Entry<E>
implements ContainerEventHandler {
@Nullable
private GuiEventListener focused;
@Nullable
private NarratableEntry lastNarratable;
private boolean dragging;
@Override
public boolean isDragging() {
return this.dragging;
}
@Override
public void setDragging(boolean isDragging) {
this.dragging = isDragging;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
return ContainerEventHandler.super.mouseClicked(mouseX, mouseY, button);
}
@Override
public void setFocused(@Nullable GuiEventListener focused) {
if (this.focused != null) {
this.focused.setFocused(false);
}
if (focused != null) {
focused.setFocused(true);
}
this.focused = focused;
}
@Nullable
@Override
public GuiEventListener getFocused() {
return this.focused;
}
@Nullable
public ComponentPath focusPathAtIndex(FocusNavigationEvent event, int index) {
if (this.children().isEmpty()) {
return null;
} else {
ComponentPath componentPath = ((GuiEventListener)this.children().get(Math.min(index, this.children().size() - 1))).nextFocusPath(event);
return ComponentPath.path(this, componentPath);
}
}
@Nullable
@Override
public ComponentPath nextFocusPath(FocusNavigationEvent event) {
if (event instanceof ArrowNavigation arrowNavigation) {
int i = switch (arrowNavigation.direction()) {
case LEFT -> -1;
case RIGHT -> 1;
case UP, DOWN -> 0;
};
if (i == 0) {
return null;
}
int j = Mth.clamp(i + this.children().indexOf(this.getFocused()), 0, this.children().size() - 1);
for (int k = j; k >= 0 && k < this.children().size(); k += i) {
GuiEventListener guiEventListener = (GuiEventListener)this.children().get(k);
ComponentPath componentPath = guiEventListener.nextFocusPath(event);
if (componentPath != null) {
return ComponentPath.path(this, componentPath);
}
}
}
return ContainerEventHandler.super.nextFocusPath(event);
}
public abstract List<? extends NarratableEntry> narratables();
void updateNarration(NarrationElementOutput narrationElementOutput) {
List<? extends NarratableEntry> list = this.narratables();
Screen.NarratableSearchResult narratableSearchResult = Screen.findNarratableWidget(list, this.lastNarratable);
if (narratableSearchResult != null) {
if (narratableSearchResult.priority.isTerminal()) {
this.lastNarratable = narratableSearchResult.entry;
}
if (list.size() > 1) {
narrationElementOutput.add(
NarratedElementType.POSITION, Component.translatable("narrator.position.object_list", narratableSearchResult.index + 1, list.size())
);
if (narratableSearchResult.priority == NarrationPriority.FOCUSED) {
narrationElementOutput.add(NarratedElementType.USAGE, Component.translatable("narration.component_list.usage"));
}
}
narratableSearchResult.entry.updateNarration(narrationElementOutput.nest());
}
}
}
}