ContainerEventHandler.java

net.minecraft.client.gui.components.events.ContainerEventHandler

信息

  • 全限定名:net.minecraft.client.gui.components.events.ContainerEventHandler
  • 类型:public interface
  • 包:net.minecraft.client.gui.components.events
  • 源码路径:src/main/java/net/minecraft/client/gui/components/events/ContainerEventHandler.java
  • 起始行号:L28
  • 继承:GuiEventListener
  • 职责:

    TODO

字段/常量

内部类/嵌套类型

构造器

方法

下面的方法块按源码顺序生成。

List<?extends GuiEventListener> children() @ L29

  • 方法名:children
  • 源码定位:L29
  • 返回类型:List<?extends GuiEventListener>
  • 修饰符:package-private

参数:

说明:

TODO

default Optional<GuiEventListener> getChildAt(double x, double y) @ L31

  • 方法名:getChildAt
  • 源码定位:L31
  • 返回类型:Optional
  • 修饰符:default

参数:

  • x: double
  • y: double

说明:

TODO

default boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) @ L41

  • 方法名:mouseClicked
  • 源码定位:L41
  • 返回类型:boolean
  • 修饰符:default

参数:

  • event: MouseButtonEvent
  • doubleClick: boolean

说明:

TODO

default boolean mouseReleased(MouseButtonEvent event) @ L59

  • 方法名:mouseReleased
  • 源码定位:L59
  • 返回类型:boolean
  • 修饰符:default

参数:

  • event: MouseButtonEvent

说明:

TODO

default boolean mouseDragged(MouseButtonEvent event, double dx, double dy) @ L71

  • 方法名:mouseDragged
  • 源码定位:L71
  • 返回类型:boolean
  • 修饰符:default

参数:

  • event: MouseButtonEvent
  • dx: double
  • dy: double

说明:

TODO

boolean isDragging() @ L76

  • 方法名:isDragging
  • 源码定位:L76
  • 返回类型:boolean
  • 修饰符:package-private

参数:

说明:

TODO

void setDragging(boolean dragging) @ L78

  • 方法名:setDragging
  • 源码定位:L78
  • 返回类型:void
  • 修饰符:package-private

参数:

  • dragging: boolean

说明:

TODO

default boolean mouseScrolled(double x, double y, double scrollX, double scrollY) @ L80

  • 方法名:mouseScrolled
  • 源码定位:L80
  • 返回类型:boolean
  • 修饰符:default

参数:

  • x: double
  • y: double
  • scrollX: double
  • scrollY: double

说明:

TODO

default boolean keyPressed(KeyEvent event) @ L85

  • 方法名:keyPressed
  • 源码定位:L85
  • 返回类型:boolean
  • 修饰符:default

参数:

  • event: KeyEvent

说明:

TODO

default boolean keyReleased(KeyEvent event) @ L90

  • 方法名:keyReleased
  • 源码定位:L90
  • 返回类型:boolean
  • 修饰符:default

参数:

  • event: KeyEvent

说明:

TODO

default boolean charTyped(CharacterEvent event) @ L95

  • 方法名:charTyped
  • 源码定位:L95
  • 返回类型:boolean
  • 修饰符:default

参数:

  • event: CharacterEvent

说明:

TODO

default boolean preeditUpdated(PreeditEvent event) @ L100

  • 方法名:preeditUpdated
  • 源码定位:L100
  • 返回类型:boolean
  • 修饰符:default

参数:

  • event: PreeditEvent

说明:

TODO

default ScreenRectangle getBorderForArrowNavigation(ScreenDirection opposite) @ L105

  • 方法名:getBorderForArrowNavigation
  • 源码定位:L105
  • 返回类型:ScreenRectangle
  • 修饰符:default

参数:

  • opposite: ScreenDirection

说明:

TODO

GuiEventListener getFocused() @ L111

  • 方法名:getFocused
  • 源码定位:L111
  • 返回类型:GuiEventListener
  • 修饰符:package-private

参数:

说明:

TODO

void setFocused(GuiEventListener focused) @ L113

  • 方法名:setFocused
  • 源码定位:L113
  • 返回类型:void
  • 修饰符:package-private

参数:

  • focused: GuiEventListener

说明:

TODO

default void setFocused(boolean focused) @ L115

  • 方法名:setFocused
  • 源码定位:L115
  • 返回类型:void
  • 修饰符:default

参数:

  • focused: boolean

说明:

TODO

default boolean isFocused() @ L122

  • 方法名:isFocused
  • 源码定位:L122
  • 返回类型:boolean
  • 修饰符:default

参数:

说明:

TODO

default ComponentPath getCurrentFocusPath() @ L127

  • 方法名:getCurrentFocusPath
  • 源码定位:L127
  • 返回类型:ComponentPath
  • 修饰符:default

参数:

说明:

TODO

default ComponentPath nextFocusPath(FocusNavigationEvent navigationEvent) @ L133

  • 方法名:nextFocusPath
  • 源码定位:L133
  • 返回类型:ComponentPath
  • 修饰符:default

参数:

  • navigationEvent: FocusNavigationEvent

说明:

TODO

private ComponentPath handleTabNavigation(FocusNavigationEvent.TabNavigation tabNavigation) @ L150

  • 方法名:handleTabNavigation
  • 源码定位:L150
  • 返回类型:ComponentPath
  • 修饰符:private

参数:

  • tabNavigation: FocusNavigationEvent.TabNavigation

说明:

TODO

private ComponentPath handleArrowNavigation(FocusNavigationEvent.ArrowNavigation arrowNavigation) @ L180

  • 方法名:handleArrowNavigation
  • 源码定位:L180
  • 返回类型:ComponentPath
  • 修饰符:private

参数:

  • arrowNavigation: FocusNavigationEvent.ArrowNavigation

说明:

TODO

private ComponentPath nextFocusPathInDirection(ScreenRectangle focusedRectangle, ScreenDirection direction, GuiEventListener excluded, FocusNavigationEvent.ArrowNavigation navigationEvent) @ L199

  • 方法名:nextFocusPathInDirection
  • 源码定位:L199
  • 返回类型:ComponentPath
  • 修饰符:private

参数:

  • focusedRectangle: ScreenRectangle
  • direction: ScreenDirection
  • excluded: GuiEventListener
  • navigationEvent: FocusNavigationEvent.ArrowNavigation

说明:

TODO

private ComponentPath nextFocusPathVaguelyInDirection(ScreenRectangle focusedRectangle, ScreenDirection direction, GuiEventListener excluded, FocusNavigationEvent navigationEvent) @ L242

  • 方法名:nextFocusPathVaguelyInDirection
  • 源码定位:L242
  • 返回类型:ComponentPath
  • 修饰符:private

参数:

  • focusedRectangle: ScreenRectangle
  • direction: ScreenDirection
  • excluded: GuiEventListener
  • navigationEvent: FocusNavigationEvent

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public interface ContainerEventHandler extends GuiEventListener {
    List<? extends GuiEventListener> children();
 
    default Optional<GuiEventListener> getChildAt(double x, double y) {
        for (GuiEventListener child : this.children()) {
            if (child.isMouseOver(x, y)) {
                return Optional.of(child);
            }
        }
 
        return Optional.empty();
    }
 
    @Override
    default boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) {
        Optional<GuiEventListener> child = this.getChildAt(event.x(), event.y());
        if (child.isEmpty()) {
            return false;
        } else {
            GuiEventListener widget = child.get();
            if (widget.mouseClicked(event, doubleClick) && widget.shouldTakeFocusAfterInteraction()) {
                this.setFocused(widget);
                if (event.button() == 0) {
                    this.setDragging(true);
                }
            }
 
            return true;
        }
    }
 
    @Override
    default boolean mouseReleased(MouseButtonEvent event) {
        if (event.button() == 0 && this.isDragging()) {
            this.setDragging(false);
            if (this.getFocused() != null) {
                return this.getFocused().mouseReleased(event);
            }
        }
 
        return false;
    }
 
    @Override
    default boolean mouseDragged(MouseButtonEvent event, double dx, double dy) {
        return this.getFocused() != null && this.isDragging() && event.button() == 0 ? this.getFocused().mouseDragged(event, dx, dy) : false;
    }
 
    boolean isDragging();
 
    void setDragging(boolean dragging);
 
    @Override
    default boolean mouseScrolled(double x, double y, double scrollX, double scrollY) {
        return this.getChildAt(x, y).filter(child -> child.mouseScrolled(x, y, scrollX, scrollY)).isPresent();
    }
 
    @Override
    default boolean keyPressed(KeyEvent event) {
        return this.getFocused() != null && this.getFocused().keyPressed(event);
    }
 
    @Override
    default boolean keyReleased(KeyEvent event) {
        return this.getFocused() != null && this.getFocused().keyReleased(event);
    }
 
    @Override
    default boolean charTyped(CharacterEvent event) {
        return this.getFocused() != null && this.getFocused().charTyped(event);
    }
 
    @Override
    default boolean preeditUpdated(@Nullable PreeditEvent event) {
        return this.getFocused() != null && this.getFocused().preeditUpdated(event);
    }
 
    @Override
    default ScreenRectangle getBorderForArrowNavigation(ScreenDirection opposite) {
        GuiEventListener focused = this.getFocused();
        return focused != null ? focused.getBorderForArrowNavigation(opposite) : GuiEventListener.super.getBorderForArrowNavigation(opposite);
    }
 
    @Nullable GuiEventListener getFocused();
 
    void setFocused(final @Nullable GuiEventListener focused);
 
    @Override
    default void setFocused(boolean focused) {
        if (!focused) {
            this.setFocused(null);
        }
    }
 
    @Override
    default boolean isFocused() {
        return this.getFocused() != null;
    }
 
    @Override
    default @Nullable ComponentPath getCurrentFocusPath() {
        GuiEventListener focused = this.getFocused();
        return focused != null ? ComponentPath.path(this, focused.getCurrentFocusPath()) : null;
    }
 
    @Override
    default @Nullable ComponentPath nextFocusPath(FocusNavigationEvent navigationEvent) {
        GuiEventListener focus = this.getFocused();
        if (focus != null) {
            ComponentPath focusPath = focus.nextFocusPath(navigationEvent);
            if (focusPath != null) {
                return ComponentPath.path(this, focusPath);
            }
        }
 
        if (navigationEvent instanceof FocusNavigationEvent.TabNavigation tabNavigation) {
            return this.handleTabNavigation(tabNavigation);
        } else {
            return navigationEvent instanceof FocusNavigationEvent.ArrowNavigation arrowNavigation ? this.handleArrowNavigation(arrowNavigation) : null;
        }
    }
 
    private @Nullable ComponentPath handleTabNavigation(FocusNavigationEvent.TabNavigation tabNavigation) {
        boolean forward = tabNavigation.forward();
        GuiEventListener focus = this.getFocused();
        List<? extends GuiEventListener> sortedChildren = new ArrayList<>(this.children());
        Collections.sort(sortedChildren, Comparator.comparingInt(childx -> childx.getTabOrderGroup()));
        int index = sortedChildren.indexOf(focus);
        int newIndex;
        if (focus != null && index >= 0) {
            newIndex = index + (forward ? 1 : 0);
        } else if (forward) {
            newIndex = 0;
        } else {
            newIndex = sortedChildren.size();
        }
 
        ListIterator<? extends GuiEventListener> iterator = sortedChildren.listIterator(newIndex);
        BooleanSupplier test = forward ? iterator::hasNext : iterator::hasPrevious;
        Supplier<? extends GuiEventListener> getter = forward ? iterator::next : iterator::previous;
 
        while (test.getAsBoolean()) {
            GuiEventListener child = getter.get();
            ComponentPath focusPath = child.nextFocusPath(tabNavigation);
            if (focusPath != null) {
                return ComponentPath.path(this, focusPath);
            }
        }
 
        return null;
    }
 
    private @Nullable ComponentPath handleArrowNavigation(FocusNavigationEvent.ArrowNavigation arrowNavigation) {
        GuiEventListener focus = this.getFocused();
        ScreenDirection direction = arrowNavigation.direction();
        if (focus == null) {
            ScreenRectangle var5 = arrowNavigation.previousFocus();
            if (var5 instanceof ScreenRectangle) {
                return ComponentPath.path(this, this.nextFocusPathInDirection(var5, arrowNavigation.direction(), null, arrowNavigation));
            } else {
                ScreenRectangle borderRectangle = this.getBorderForArrowNavigation(direction.getOpposite());
                return ComponentPath.path(this, this.nextFocusPathInDirection(borderRectangle, direction, null, arrowNavigation));
            }
        } else {
            ScreenRectangle focusedRectangle = focus.getBorderForArrowNavigation(direction);
            return ComponentPath.path(
                this, this.nextFocusPathInDirection(focusedRectangle, arrowNavigation.direction(), focus, arrowNavigation.with(focusedRectangle))
            );
        }
    }
 
    private @Nullable ComponentPath nextFocusPathInDirection(
        ScreenRectangle focusedRectangle, ScreenDirection direction, @Nullable GuiEventListener excluded, FocusNavigationEvent.ArrowNavigation navigationEvent
    ) {
        ScreenAxis axis = direction.getAxis();
        ScreenAxis otherAxis = axis.orthogonal();
        ScreenDirection positiveDirectionOtherAxis = otherAxis.getPositive();
        int focusedFirstBound = focusedRectangle.getBoundInDirection(direction.getOpposite());
        List<GuiEventListener> potentialChildren = new ArrayList<>();
 
        for (GuiEventListener child : this.children()) {
            if (child != excluded) {
                ScreenRectangle childRectangle = child.getRectangle();
                if (childRectangle.overlapsInAxis(focusedRectangle, otherAxis)) {
                    int childFirstBound = childRectangle.getBoundInDirection(direction.getOpposite());
                    if (direction.isAfter(childFirstBound, focusedFirstBound)) {
                        potentialChildren.add(child);
                    } else if (childFirstBound == focusedFirstBound
                        && direction.isAfter(childRectangle.getBoundInDirection(direction), focusedRectangle.getBoundInDirection(direction))) {
                        potentialChildren.add(child);
                    }
                }
            }
        }
 
        Comparator<GuiEventListener> primaryComparator = Comparator.comparing(
            childx -> childx.getRectangle().getBoundInDirection(direction.getOpposite()), direction.coordinateValueComparator()
        );
        Comparator<GuiEventListener> secondaryComparator = Comparator.comparing(
            childx -> childx.getRectangle().getBoundInDirection(positiveDirectionOtherAxis.getOpposite()),
            positiveDirectionOtherAxis.coordinateValueComparator()
        );
        potentialChildren.sort(primaryComparator.thenComparing(secondaryComparator));
 
        for (GuiEventListener childx : potentialChildren) {
            ComponentPath componentPath = childx.nextFocusPath(navigationEvent);
            if (componentPath != null) {
                return componentPath;
            }
        }
 
        return this.nextFocusPathVaguelyInDirection(focusedRectangle, direction, excluded, navigationEvent);
    }
 
    private @Nullable ComponentPath nextFocusPathVaguelyInDirection(
        ScreenRectangle focusedRectangle, ScreenDirection direction, @Nullable GuiEventListener excluded, FocusNavigationEvent navigationEvent
    ) {
        ScreenAxis axis = direction.getAxis();
        ScreenAxis otherAxis = axis.orthogonal();
        List<Pair<GuiEventListener, Long>> potentialChildren = new ArrayList<>();
        ScreenPosition focusedSideCenter = ScreenPosition.of(axis, focusedRectangle.getBoundInDirection(direction), focusedRectangle.getCenterInAxis(otherAxis));
 
        for (GuiEventListener child : this.children()) {
            if (child != excluded) {
                ScreenRectangle childRectangle = child.getRectangle();
                ScreenPosition childOpposingSideCenter = ScreenPosition.of(
                    axis, childRectangle.getBoundInDirection(direction.getOpposite()), childRectangle.getCenterInAxis(otherAxis)
                );
                if (direction.isAfter(childOpposingSideCenter.getCoordinate(axis), focusedSideCenter.getCoordinate(axis))) {
                    long distanceSquared = Vector2i.distanceSquared(
                        focusedSideCenter.x(), focusedSideCenter.y(), childOpposingSideCenter.x(), childOpposingSideCenter.y()
                    );
                    potentialChildren.add(Pair.of(child, distanceSquared));
                }
            }
        }
 
        potentialChildren.sort(Comparator.comparingDouble(Pair::getSecond));
 
        for (Pair<GuiEventListener, Long> childx : potentialChildren) {
            ComponentPath componentPath = childx.getFirst().nextFocusPath(navigationEvent);
            if (componentPath != null) {
                return componentPath;
            }
        }
 
        return null;
    }
}

引用的其他类