EditBox.java

net.minecraft.client.gui.components.EditBox

信息

  • 全限定名:net.minecraft.client.gui.components.EditBox
  • 类型:public class
  • 包:net.minecraft.client.gui.components
  • 源码路径:src/main/java/net/minecraft/client/gui/components/EditBox.java
  • 起始行号:L32
  • 继承:AbstractWidget
  • 职责:

    TODO

字段/常量

  • SPRITES

    • 类型: WidgetSprites
    • 修饰符: private static final
    • 源码定位: L33
    • 说明:

      TODO

  • BACKWARDS

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L36
    • 说明:

      TODO

  • FORWARDS

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L37
    • 说明:

      TODO

  • DEFAULT_TEXT_COLOR

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L38
    • 说明:

      TODO

  • DEFAULT_HINT_STYLE

    • 类型: Style
    • 修饰符: public static final
    • 源码定位: L39
    • 说明:

      TODO

  • SEARCH_HINT_STYLE

    • 类型: Style
    • 修饰符: public static final
    • 源码定位: L40
    • 说明:

      TODO

  • font

    • 类型: Font
    • 修饰符: private final
    • 源码定位: L41
    • 说明:

      TODO

  • value

    • 类型: String
    • 修饰符: private
    • 源码定位: L42
    • 说明:

      TODO

  • maxLength

    • 类型: int
    • 修饰符: private
    • 源码定位: L43
    • 说明:

      TODO

  • bordered

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L44
    • 说明:

      TODO

  • canLoseFocus

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L45
    • 说明:

      TODO

  • isEditable

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L46
    • 说明:

      TODO

  • centered

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L47
    • 说明:

      TODO

  • textShadow

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L48
    • 说明:

      TODO

  • invertHighlightedTextColor

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L49
    • 说明:

      TODO

  • displayPos

    • 类型: int
    • 修饰符: private
    • 源码定位: L50
    • 说明:

      TODO

  • cursorPos

    • 类型: int
    • 修饰符: private
    • 源码定位: L51
    • 说明:

      TODO

  • highlightPos

    • 类型: int
    • 修饰符: private
    • 源码定位: L52
    • 说明:

      TODO

  • textColor

    • 类型: int
    • 修饰符: private
    • 源码定位: L53
    • 说明:

      TODO

  • textColorUneditable

    • 类型: int
    • 修饰符: private
    • 源码定位: L54
    • 说明:

      TODO

  • suggestion

    • 类型: String
    • 修饰符: private
    • 源码定位: L55
    • 说明:

      TODO

  • responder

    • 类型: Consumer<String>
    • 修饰符: private
    • 源码定位: L56
    • 说明:

      TODO

  • formatters

    • 类型: List<EditBox.TextFormatter>
    • 修饰符: private final
    • 源码定位: L57
    • 说明:

      TODO

  • hint

    • 类型: Component
    • 修饰符: private
    • 源码定位: L58
    • 说明:

      TODO

  • preeditOverlay

    • 类型: IMEPreeditOverlay
    • 修饰符: private
    • 源码定位: L59
    • 说明:

      TODO

  • focusedTime

    • 类型: long
    • 修饰符: private
    • 源码定位: L60
    • 说明:

      TODO

  • textX

    • 类型: int
    • 修饰符: private
    • 源码定位: L61
    • 说明:

      TODO

  • textY

    • 类型: int
    • 修饰符: private
    • 源码定位: L62
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.client.gui.components.EditBox.TextFormatter
    • 类型: interface
    • 修饰符: public
    • 源码定位: L629
    • 说明:

      TODO

构造器

public EditBox(Font font, int width, int height, Component narration) @ L64

  • 构造器名:EditBox
  • 源码定位:L64
  • 修饰符:public

参数:

  • font: Font
  • width: int
  • height: int
  • narration: Component

说明:

TODO

public EditBox(Font font, int x, int y, int width, int height, Component narration) @ L68

  • 构造器名:EditBox
  • 源码定位:L68
  • 修饰符:public

参数:

  • font: Font
  • x: int
  • y: int
  • width: int
  • height: int
  • narration: Component

说明:

TODO

public EditBox(Font font, int x, int y, int width, int height, EditBox oldBox, Component narration) @ L72

  • 构造器名:EditBox
  • 源码定位:L72
  • 修饰符:public

参数:

  • font: Font
  • x: int
  • y: int
  • width: int
  • height: int
  • oldBox: EditBox
  • narration: Component

说明:

TODO

方法

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

public void setResponder(Consumer<String> responder) @ L82

  • 方法名:setResponder
  • 源码定位:L82
  • 返回类型:void
  • 修饰符:public

参数:

  • responder: Consumer

说明:

TODO

public void addFormatter(EditBox.TextFormatter formatter) @ L86

  • 方法名:addFormatter
  • 源码定位:L86
  • 返回类型:void
  • 修饰符:public

参数:

  • formatter: EditBox.TextFormatter

说明:

TODO

protected MutableComponent createNarrationMessage() @ L90

  • 方法名:createNarrationMessage
  • 源码定位:L90
  • 返回类型:MutableComponent
  • 修饰符:protected

参数:

说明:

TODO

public void setValue(String value) @ L96

  • 方法名:setValue
  • 源码定位:L96
  • 返回类型:void
  • 修饰符:public

参数:

  • value: String

说明:

TODO

public String getValue() @ L108

  • 方法名:getValue
  • 源码定位:L108
  • 返回类型:String
  • 修饰符:public

参数:

说明:

TODO

public String getHighlighted() @ L112

  • 方法名:getHighlighted
  • 源码定位:L112
  • 返回类型:String
  • 修饰符:public

参数:

说明:

TODO

public void setX(int x) @ L118

  • 方法名:setX
  • 源码定位:L118
  • 返回类型:void
  • 修饰符:public

参数:

  • x: int

说明:

TODO

public void setY(int y) @ L124

  • 方法名:setY
  • 源码定位:L124
  • 返回类型:void
  • 修饰符:public

参数:

  • y: int

说明:

TODO

public void insertText(String input) @ L130

  • 方法名:insertText
  • 源码定位:L130
  • 返回类型:void
  • 修饰符:public

参数:

  • input: String

说明:

TODO

private void onValueChange(String value) @ L153

  • 方法名:onValueChange
  • 源码定位:L153
  • 返回类型:void
  • 修饰符:private

参数:

  • value: String

说明:

TODO

private void deleteText(int dir, boolean wholeWord) @ L161

  • 方法名:deleteText
  • 源码定位:L161
  • 返回类型:void
  • 修饰符:private

参数:

  • dir: int
  • wholeWord: boolean

说明:

TODO

public void deleteWords(int dir) @ L169

  • 方法名:deleteWords
  • 源码定位:L169
  • 返回类型:void
  • 修饰符:public

参数:

  • dir: int

说明:

TODO

public void deleteChars(int dir) @ L179

  • 方法名:deleteChars
  • 源码定位:L179
  • 返回类型:void
  • 修饰符:public

参数:

  • dir: int

说明:

TODO

public void deleteCharsToPos(int pos) @ L183

  • 方法名:deleteCharsToPos
  • 源码定位:L183
  • 返回类型:void
  • 修饰符:public

参数:

  • pos: int

说明:

TODO

public int getWordPosition(int dir) @ L200

  • 方法名:getWordPosition
  • 源码定位:L200
  • 返回类型:int
  • 修饰符:public

参数:

  • dir: int

说明:

TODO

private int getWordPosition(int dir, int from) @ L204

  • 方法名:getWordPosition
  • 源码定位:L204
  • 返回类型:int
  • 修饰符:private

参数:

  • dir: int
  • from: int

说明:

TODO

private int getWordPosition(int dir, int from, boolean stripSpaces) @ L208

  • 方法名:getWordPosition
  • 源码定位:L208
  • 返回类型:int
  • 修饰符:private

参数:

  • dir: int
  • from: int
  • stripSpaces: boolean

说明:

TODO

public void moveCursor(int dir, boolean hasShiftDown) @ L238

  • 方法名:moveCursor
  • 源码定位:L238
  • 返回类型:void
  • 修饰符:public

参数:

  • dir: int
  • hasShiftDown: boolean

说明:

TODO

private int getCursorPos(int dir) @ L242

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

参数:

  • dir: int

说明:

TODO

public void moveCursorTo(int dir, boolean extendSelection) @ L246

  • 方法名:moveCursorTo
  • 源码定位:L246
  • 返回类型:void
  • 修饰符:public

参数:

  • dir: int
  • extendSelection: boolean

说明:

TODO

public void setCursorPosition(int pos) @ L255

  • 方法名:setCursorPosition
  • 源码定位:L255
  • 返回类型:void
  • 修饰符:public

参数:

  • pos: int

说明:

TODO

public void moveCursorToStart(boolean hasShiftDown) @ L260

  • 方法名:moveCursorToStart
  • 源码定位:L260
  • 返回类型:void
  • 修饰符:public

参数:

  • hasShiftDown: boolean

说明:

TODO

public void moveCursorToEnd(boolean hasShiftDown) @ L264

  • 方法名:moveCursorToEnd
  • 源码定位:L264
  • 返回类型:void
  • 修饰符:public

参数:

  • hasShiftDown: boolean

说明:

TODO

public boolean keyPressed(KeyEvent event) @ L268

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

参数:

  • event: KeyEvent

说明:

TODO

public boolean canConsumeInput() @ L343

  • 方法名:canConsumeInput
  • 源码定位:L343
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public boolean charTyped(CharacterEvent event) @ L347

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

参数:

  • event: CharacterEvent

说明:

TODO

public boolean preeditUpdated(PreeditEvent event) @ L362

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

参数:

  • event: PreeditEvent

说明:

TODO

private int findClickedPositionInText(MouseButtonEvent event) @ L368

  • 方法名:findClickedPositionInText
  • 源码定位:L368
  • 返回类型:int
  • 修饰符:private

参数:

  • event: MouseButtonEvent

说明:

TODO

private void selectWord(MouseButtonEvent event) @ L374

  • 方法名:selectWord
  • 源码定位:L374
  • 返回类型:void
  • 修饰符:private

参数:

  • event: MouseButtonEvent

说明:

TODO

public void onClick(MouseButtonEvent event, boolean doubleClick) @ L382

  • 方法名:onClick
  • 源码定位:L382
  • 返回类型:void
  • 修饰符:public

参数:

  • event: MouseButtonEvent
  • doubleClick: boolean

说明:

TODO

protected void onDrag(MouseButtonEvent event, double dx, double dy) @ L391

  • 方法名:onDrag
  • 源码定位:L391
  • 返回类型:void
  • 修饰符:protected

参数:

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

说明:

TODO

public void playDownSound(SoundManager soundManager) @ L396

  • 方法名:playDownSound
  • 源码定位:L396
  • 返回类型:void
  • 修饰符:public

参数:

  • soundManager: SoundManager

说明:

TODO

public void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) @ L400

  • 方法名:extractWidgetRenderState
  • 源码定位:L400
  • 返回类型:void
  • 修饰符:public

参数:

  • graphics: GuiGraphicsExtractor
  • mouseX: int
  • mouseY: int
  • a: float

说明:

TODO

private FormattedCharSequence applyFormat(String text, int offset) @ L473

  • 方法名:applyFormat
  • 源码定位:L473
  • 返回类型:FormattedCharSequence
  • 修饰符:private

参数:

  • text: String
  • offset: int

说明:

TODO

private void updateTextPosition() @ L484

  • 方法名:updateTextPosition
  • 源码定位:L484
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

public void setMaxLength(int maxLength) @ L492

  • 方法名:setMaxLength
  • 源码定位:L492
  • 返回类型:void
  • 修饰符:public

参数:

  • maxLength: int

说明:

TODO

private int getMaxLength() @ L500

  • 方法名:getMaxLength
  • 源码定位:L500
  • 返回类型:int
  • 修饰符:private

参数:

说明:

TODO

public int getCursorPosition() @ L504

  • 方法名:getCursorPosition
  • 源码定位:L504
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

public boolean isBordered() @ L508

  • 方法名:isBordered
  • 源码定位:L508
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public void setBordered(boolean bordered) @ L512

  • 方法名:setBordered
  • 源码定位:L512
  • 返回类型:void
  • 修饰符:public

参数:

  • bordered: boolean

说明:

TODO

public void setTextColor(int textColor) @ L517

  • 方法名:setTextColor
  • 源码定位:L517
  • 返回类型:void
  • 修饰符:public

参数:

  • textColor: int

说明:

TODO

public void setTextColorUneditable(int textColorUneditable) @ L521

  • 方法名:setTextColorUneditable
  • 源码定位:L521
  • 返回类型:void
  • 修饰符:public

参数:

  • textColorUneditable: int

说明:

TODO

public void setFocused(boolean focused) @ L525

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

参数:

  • focused: boolean

说明:

TODO

private boolean isEditable() @ L539

  • 方法名:isEditable
  • 源码定位:L539
  • 返回类型:boolean
  • 修饰符:private

参数:

说明:

TODO

public void setEditable(boolean isEditable) @ L543

  • 方法名:setEditable
  • 源码定位:L543
  • 返回类型:void
  • 修饰符:public

参数:

  • isEditable: boolean

说明:

TODO

private boolean isCentered() @ L551

  • 方法名:isCentered
  • 源码定位:L551
  • 返回类型:boolean
  • 修饰符:private

参数:

说明:

TODO

public void setCentered(boolean centered) @ L555

  • 方法名:setCentered
  • 源码定位:L555
  • 返回类型:void
  • 修饰符:public

参数:

  • centered: boolean

说明:

TODO

public void setTextShadow(boolean textShadow) @ L560

  • 方法名:setTextShadow
  • 源码定位:L560
  • 返回类型:void
  • 修饰符:public

参数:

  • textShadow: boolean

说明:

TODO

public void setInvertHighlightedTextColor(boolean invertHighlightedTextColor) @ L564

  • 方法名:setInvertHighlightedTextColor
  • 源码定位:L564
  • 返回类型:void
  • 修饰符:public

参数:

  • invertHighlightedTextColor: boolean

说明:

TODO

public int getInnerWidth() @ L568

  • 方法名:getInnerWidth
  • 源码定位:L568
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

public void setHighlightPos(int pos) @ L572

  • 方法名:setHighlightPos
  • 源码定位:L572
  • 返回类型:void
  • 修饰符:public

参数:

  • pos: int

说明:

TODO

private void scrollTo(int pos) @ L577

  • 方法名:scrollTo
  • 源码定位:L577
  • 返回类型:void
  • 修饰符:private

参数:

  • pos: int

说明:

TODO

public void setCanLoseFocus(boolean canLoseFocus) @ L597

  • 方法名:setCanLoseFocus
  • 源码定位:L597
  • 返回类型:void
  • 修饰符:public

参数:

  • canLoseFocus: boolean

说明:

TODO

public boolean isVisible() @ L601

  • 方法名:isVisible
  • 源码定位:L601
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public void setVisible(boolean visible) @ L605

  • 方法名:setVisible
  • 源码定位:L605
  • 返回类型:void
  • 修饰符:public

参数:

  • visible: boolean

说明:

TODO

public void setSuggestion(String suggestion) @ L609

  • 方法名:setSuggestion
  • 源码定位:L609
  • 返回类型:void
  • 修饰符:public

参数:

  • suggestion: String

说明:

TODO

public int getScreenX(int charIndex) @ L613

  • 方法名:getScreenX
  • 源码定位:L613
  • 返回类型:int
  • 修饰符:public

参数:

  • charIndex: int

说明:

TODO

public void updateWidgetNarration(NarrationElementOutput output) @ L617

  • 方法名:updateWidgetNarration
  • 源码定位:L617
  • 返回类型:void
  • 修饰符:public

参数:

  • output: NarrationElementOutput

说明:

TODO

public void setHint(Component hint) @ L622

  • 方法名:setHint
  • 源码定位:L622
  • 返回类型:void
  • 修饰符:public

参数:

  • hint: Component

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class EditBox extends AbstractWidget {
    private static final WidgetSprites SPRITES = new WidgetSprites(
        Identifier.withDefaultNamespace("widget/text_field"), Identifier.withDefaultNamespace("widget/text_field_highlighted")
    );
    public static final int BACKWARDS = -1;
    public static final int FORWARDS = 1;
    public static final int DEFAULT_TEXT_COLOR = -2039584;
    public static final Style DEFAULT_HINT_STYLE = Style.EMPTY.withColor(ChatFormatting.DARK_GRAY);
    public static final Style SEARCH_HINT_STYLE = Style.EMPTY.applyFormats(ChatFormatting.GRAY, ChatFormatting.ITALIC);
    private final Font font;
    private String value = "";
    private int maxLength = 32;
    private boolean bordered = true;
    private boolean canLoseFocus = true;
    private boolean isEditable = true;
    private boolean centered = false;
    private boolean textShadow = true;
    private boolean invertHighlightedTextColor = true;
    private int displayPos;
    private int cursorPos;
    private int highlightPos;
    private int textColor = -2039584;
    private int textColorUneditable = -9408400;
    private @Nullable String suggestion;
    private @Nullable Consumer<String> responder;
    private final List<EditBox.TextFormatter> formatters = new ArrayList<>();
    private @Nullable Component hint;
    private @Nullable IMEPreeditOverlay preeditOverlay;
    private long focusedTime = Util.getMillis();
    private int textX;
    private int textY;
 
    public EditBox(Font font, int width, int height, Component narration) {
        this(font, 0, 0, width, height, narration);
    }
 
    public EditBox(Font font, int x, int y, int width, int height, Component narration) {
        this(font, x, y, width, height, null, narration);
    }
 
    public EditBox(Font font, int x, int y, int width, int height, @Nullable EditBox oldBox, Component narration) {
        super(x, y, width, height, narration);
        this.font = font;
        if (oldBox != null) {
            this.setValue(oldBox.getValue());
        }
 
        this.updateTextPosition();
    }
 
    public void setResponder(Consumer<String> responder) {
        this.responder = responder;
    }
 
    public void addFormatter(EditBox.TextFormatter formatter) {
        this.formatters.add(formatter);
    }
 
    @Override
    protected MutableComponent createNarrationMessage() {
        Component message = this.getMessage();
        return Component.translatable("gui.narrate.editBox", message, this.value);
    }
 
    public void setValue(String value) {
        if (value.length() > this.maxLength) {
            this.value = value.substring(0, this.maxLength);
        } else {
            this.value = value;
        }
 
        this.moveCursorToEnd(false);
        this.setHighlightPos(this.cursorPos);
        this.onValueChange(value);
    }
 
    public String getValue() {
        return this.value;
    }
 
    public String getHighlighted() {
        int start = Math.min(this.cursorPos, this.highlightPos);
        int end = Math.max(this.cursorPos, this.highlightPos);
        return this.value.substring(start, end);
    }
 
    @Override
    public void setX(int x) {
        super.setX(x);
        this.updateTextPosition();
    }
 
    @Override
    public void setY(int y) {
        super.setY(y);
        this.updateTextPosition();
    }
 
    public void insertText(String input) {
        int start = Math.min(this.cursorPos, this.highlightPos);
        int end = Math.max(this.cursorPos, this.highlightPos);
        int maxInsertionLength = this.maxLength - this.value.length() - (start - end);
        if (maxInsertionLength > 0) {
            String text = StringUtil.filterText(input);
            int insertionLength = text.length();
            if (maxInsertionLength < insertionLength) {
                if (Character.isHighSurrogate(text.charAt(maxInsertionLength - 1))) {
                    maxInsertionLength--;
                }
 
                text = text.substring(0, maxInsertionLength);
                insertionLength = maxInsertionLength;
            }
 
            this.value = new StringBuilder(this.value).replace(start, end, text).toString();
            this.setCursorPosition(start + insertionLength);
            this.setHighlightPos(this.cursorPos);
            this.onValueChange(this.value);
        }
    }
 
    private void onValueChange(String value) {
        if (this.responder != null) {
            this.responder.accept(value);
        }
 
        this.updateTextPosition();
    }
 
    private void deleteText(int dir, boolean wholeWord) {
        if (wholeWord) {
            this.deleteWords(dir);
        } else {
            this.deleteChars(dir);
        }
    }
 
    public void deleteWords(int dir) {
        if (!this.value.isEmpty()) {
            if (this.highlightPos != this.cursorPos) {
                this.insertText("");
            } else {
                this.deleteCharsToPos(this.getWordPosition(dir));
            }
        }
    }
 
    public void deleteChars(int dir) {
        this.deleteCharsToPos(this.getCursorPos(dir));
    }
 
    public void deleteCharsToPos(int pos) {
        if (!this.value.isEmpty()) {
            if (this.highlightPos != this.cursorPos) {
                this.insertText("");
            } else {
                int start = Math.min(pos, this.cursorPos);
                int end = Math.max(pos, this.cursorPos);
                if (start != end) {
                    this.value = new StringBuilder(this.value).delete(start, end).toString();
                    this.setCursorPosition(start);
                    this.onValueChange(this.value);
                    this.moveCursorTo(start, false);
                }
            }
        }
    }
 
    public int getWordPosition(int dir) {
        return this.getWordPosition(dir, this.getCursorPosition());
    }
 
    private int getWordPosition(int dir, int from) {
        return this.getWordPosition(dir, from, true);
    }
 
    private int getWordPosition(int dir, int from, boolean stripSpaces) {
        int result = from;
        boolean reverse = dir < 0;
        int abs = Math.abs(dir);
 
        for (int i = 0; i < abs; i++) {
            if (!reverse) {
                int length = this.value.length();
                result = this.value.indexOf(32, result);
                if (result == -1) {
                    result = length;
                } else {
                    while (stripSpaces && result < length && this.value.charAt(result) == ' ') {
                        result++;
                    }
                }
            } else {
                while (stripSpaces && result > 0 && this.value.charAt(result - 1) == ' ') {
                    result--;
                }
 
                while (result > 0 && this.value.charAt(result - 1) != ' ') {
                    result--;
                }
            }
        }
 
        return result;
    }
 
    public void moveCursor(int dir, boolean hasShiftDown) {
        this.moveCursorTo(this.getCursorPos(dir), hasShiftDown);
    }
 
    private int getCursorPos(int dir) {
        return Util.offsetByCodepoints(this.value, this.cursorPos, dir);
    }
 
    public void moveCursorTo(int dir, boolean extendSelection) {
        this.setCursorPosition(dir);
        if (!extendSelection) {
            this.setHighlightPos(this.cursorPos);
        }
 
        this.updateTextPosition();
    }
 
    public void setCursorPosition(int pos) {
        this.cursorPos = Mth.clamp(pos, 0, this.value.length());
        this.scrollTo(this.cursorPos);
    }
 
    public void moveCursorToStart(boolean hasShiftDown) {
        this.moveCursorTo(0, hasShiftDown);
    }
 
    public void moveCursorToEnd(boolean hasShiftDown) {
        this.moveCursorTo(this.value.length(), hasShiftDown);
    }
 
    @Override
    public boolean keyPressed(KeyEvent event) {
        if (this.isActive() && this.isFocused()) {
            switch (event.key()) {
                case 259:
                    if (this.isEditable) {
                        this.deleteText(-1, event.hasControlDownWithQuirk());
                    }
 
                    return true;
                case 260:
                case 264:
                case 265:
                case 266:
                case 267:
                default:
                    if (event.isSelectAll()) {
                        this.moveCursorToEnd(false);
                        this.setHighlightPos(0);
                        return true;
                    } else if (event.isCopy()) {
                        Minecraft.getInstance().keyboardHandler.setClipboard(this.getHighlighted());
                        return true;
                    } else if (event.isPaste()) {
                        if (this.isEditable()) {
                            this.insertText(Minecraft.getInstance().keyboardHandler.getClipboard());
                        }
 
                        return true;
                    } else {
                        if (event.isCut()) {
                            Minecraft.getInstance().keyboardHandler.setClipboard(this.getHighlighted());
                            if (this.isEditable()) {
                                this.insertText("");
                            }
 
                            return true;
                        }
 
                        return false;
                    }
                case 261:
                    if (this.isEditable) {
                        this.deleteText(1, event.hasControlDownWithQuirk());
                    }
 
                    return true;
                case 262:
                    if (event.hasControlDownWithQuirk()) {
                        this.moveCursorTo(this.getWordPosition(1), event.hasShiftDown());
                    } else {
                        this.moveCursor(1, event.hasShiftDown());
                    }
 
                    return true;
                case 263:
                    if (event.hasControlDownWithQuirk()) {
                        this.moveCursorTo(this.getWordPosition(-1), event.hasShiftDown());
                    } else {
                        this.moveCursor(-1, event.hasShiftDown());
                    }
 
                    return true;
                case 268:
                    this.moveCursorToStart(event.hasShiftDown());
                    return true;
                case 269:
                    this.moveCursorToEnd(event.hasShiftDown());
                    return true;
            }
        } else {
            return false;
        }
    }
 
    public boolean canConsumeInput() {
        return this.isActive() && this.isFocused() && this.isEditable();
    }
 
    @Override
    public boolean charTyped(CharacterEvent event) {
        if (!this.canConsumeInput()) {
            return false;
        } else if (event.isAllowedChatCharacter()) {
            if (this.isEditable) {
                this.insertText(event.codepointAsString());
            }
 
            return true;
        } else {
            return false;
        }
    }
 
    @Override
    public boolean preeditUpdated(@Nullable PreeditEvent event) {
        this.preeditOverlay = event != null ? new IMEPreeditOverlay(event, this.font, 9 + 1) : null;
        return true;
    }
 
    private int findClickedPositionInText(MouseButtonEvent event) {
        int positionInText = Math.min(Mth.floor(event.x()) - this.textX, this.getInnerWidth());
        String displayed = this.value.substring(this.displayPos);
        return this.displayPos + this.font.plainSubstrByWidth(displayed, positionInText).length();
    }
 
    private void selectWord(MouseButtonEvent event) {
        int clickedPosition = this.findClickedPositionInText(event);
        int wordStart = this.getWordPosition(-1, clickedPosition);
        int wordEnd = this.getWordPosition(1, clickedPosition);
        this.moveCursorTo(wordStart, false);
        this.moveCursorTo(wordEnd, true);
    }
 
    @Override
    public void onClick(MouseButtonEvent event, boolean doubleClick) {
        if (doubleClick) {
            this.selectWord(event);
        } else {
            this.moveCursorTo(this.findClickedPositionInText(event), event.hasShiftDown());
        }
    }
 
    @Override
    protected void onDrag(MouseButtonEvent event, double dx, double dy) {
        this.moveCursorTo(this.findClickedPositionInText(event), true);
    }
 
    @Override
    public void playDownSound(SoundManager soundManager) {
    }
 
    @Override
    public void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
        if (this.isVisible()) {
            if (this.isBordered()) {
                Identifier sprite = SPRITES.get(this.isActive(), this.isFocused());
                graphics.blitSprite(RenderPipelines.GUI_TEXTURED, sprite, this.getX(), this.getY(), this.getWidth(), this.getHeight());
            }
 
            int color = this.isEditable ? this.textColor : this.textColorUneditable;
            int relCursorPos = this.cursorPos - this.displayPos;
            String displayed = this.font.plainSubstrByWidth(this.value.substring(this.displayPos), this.getInnerWidth());
            boolean cursorOnScreen = relCursorPos >= 0 && relCursorPos <= displayed.length();
            boolean showCursor = this.isFocused() && TextCursorUtils.isCursorVisible(Util.getMillis() - this.focusedTime) && cursorOnScreen;
            int drawX = this.textX;
            int relHighlightPos = Mth.clamp(this.highlightPos - this.displayPos, 0, displayed.length());
            if (!displayed.isEmpty()) {
                String half = cursorOnScreen ? displayed.substring(0, relCursorPos) : displayed;
                FormattedCharSequence charSequence = this.applyFormat(half, this.displayPos);
                graphics.text(this.font, charSequence, drawX, this.textY, color, this.textShadow);
                drawX += this.font.width(charSequence) + 1;
            }
 
            boolean insert = this.cursorPos < this.value.length() || this.value.length() >= this.getMaxLength();
            int cursorX = drawX;
            if (!cursorOnScreen) {
                cursorX = relCursorPos > 0 ? this.textX + this.width : this.textX;
            } else if (insert) {
                cursorX = drawX - 1;
                drawX--;
            }
 
            if (!displayed.isEmpty() && cursorOnScreen && relCursorPos < displayed.length()) {
                graphics.text(this.font, this.applyFormat(displayed.substring(relCursorPos), this.cursorPos), drawX, this.textY, color, this.textShadow);
            }
 
            if (this.hint != null && displayed.isEmpty() && !this.isFocused()) {
                graphics.text(this.font, this.hint, drawX, this.textY, color);
            }
 
            if (!insert && this.suggestion != null) {
                graphics.text(this.font, this.suggestion, cursorX - 1, this.textY, -8355712, this.textShadow);
            }
 
            if (relHighlightPos != relCursorPos) {
                int highlightX = this.textX + this.font.width(displayed.substring(0, relHighlightPos));
                graphics.textHighlight(
                    Math.min(cursorX, this.getX() + this.width),
                    this.textY - 1,
                    Math.min(highlightX - 1, this.getX() + this.width),
                    this.textY + 1 + 9,
                    this.invertHighlightedTextColor
                );
            }
 
            if (showCursor) {
                if (insert) {
                    TextCursorUtils.extractInsertCursor(graphics, cursorX, this.textY, color, 9 + 1);
                } else {
                    TextCursorUtils.extractAppendCursor(graphics, this.font, cursorX, this.textY, color, this.textShadow);
                }
            }
 
            if (this.isHovered()) {
                graphics.requestCursor(this.isEditable() ? CursorTypes.IBEAM : CursorTypes.NOT_ALLOWED);
            }
 
            if (this.preeditOverlay != null) {
                this.preeditOverlay.updateInputPosition(cursorX, this.textY);
                graphics.setPreeditOverlay(this.preeditOverlay);
            }
        }
    }
 
    private FormattedCharSequence applyFormat(String text, int offset) {
        for (EditBox.TextFormatter formatter : this.formatters) {
            FormattedCharSequence formattedCharSequence = formatter.format(text, offset);
            if (formattedCharSequence != null) {
                return formattedCharSequence;
            }
        }
 
        return FormattedCharSequence.forward(text, Style.EMPTY);
    }
 
    private void updateTextPosition() {
        if (this.font != null) {
            String displayed = this.font.plainSubstrByWidth(this.value.substring(this.displayPos), this.getInnerWidth());
            this.textX = this.getX() + (this.isCentered() ? (this.getWidth() - this.font.width(displayed)) / 2 : (this.bordered ? 4 : 0));
            this.textY = this.bordered ? this.getY() + (this.height - 8) / 2 : this.getY();
        }
    }
 
    public void setMaxLength(int maxLength) {
        this.maxLength = maxLength;
        if (this.value.length() > maxLength) {
            this.value = this.value.substring(0, maxLength);
            this.onValueChange(this.value);
        }
    }
 
    private int getMaxLength() {
        return this.maxLength;
    }
 
    public int getCursorPosition() {
        return this.cursorPos;
    }
 
    public boolean isBordered() {
        return this.bordered;
    }
 
    public void setBordered(boolean bordered) {
        this.bordered = bordered;
        this.updateTextPosition();
    }
 
    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }
 
    public void setTextColorUneditable(int textColorUneditable) {
        this.textColorUneditable = textColorUneditable;
    }
 
    @Override
    public void setFocused(boolean focused) {
        if (this.canLoseFocus || focused) {
            super.setFocused(focused);
            if (focused) {
                this.focusedTime = Util.getMillis();
            }
 
            if (this.isEditable()) {
                Minecraft.getInstance().onTextInputFocusChange(this, focused);
            }
        }
    }
 
    private boolean isEditable() {
        return this.isEditable;
    }
 
    public void setEditable(boolean isEditable) {
        if (this.isFocused()) {
            Minecraft.getInstance().onTextInputFocusChange(this, isEditable);
        }
 
        this.isEditable = isEditable;
    }
 
    private boolean isCentered() {
        return this.centered;
    }
 
    public void setCentered(boolean centered) {
        this.centered = centered;
        this.updateTextPosition();
    }
 
    public void setTextShadow(boolean textShadow) {
        this.textShadow = textShadow;
    }
 
    public void setInvertHighlightedTextColor(boolean invertHighlightedTextColor) {
        this.invertHighlightedTextColor = invertHighlightedTextColor;
    }
 
    public int getInnerWidth() {
        return this.isBordered() ? this.width - 8 : this.width;
    }
 
    public void setHighlightPos(int pos) {
        this.highlightPos = Mth.clamp(pos, 0, this.value.length());
        this.scrollTo(this.highlightPos);
    }
 
    private void scrollTo(int pos) {
        if (this.font != null) {
            this.displayPos = Math.min(this.displayPos, this.value.length());
            int innerWidth = this.getInnerWidth();
            String displayed = this.font.plainSubstrByWidth(this.value.substring(this.displayPos), innerWidth);
            int lastPos = displayed.length() + this.displayPos;
            if (pos == this.displayPos) {
                this.displayPos = this.displayPos - this.font.plainSubstrByWidth(this.value, innerWidth, true).length();
            }
 
            if (pos > lastPos) {
                this.displayPos += pos - lastPos;
            } else if (pos <= this.displayPos) {
                this.displayPos = this.displayPos - (this.displayPos - pos);
            }
 
            this.displayPos = Mth.clamp(this.displayPos, 0, this.value.length());
        }
    }
 
    public void setCanLoseFocus(boolean canLoseFocus) {
        this.canLoseFocus = canLoseFocus;
    }
 
    public boolean isVisible() {
        return this.visible;
    }
 
    public void setVisible(boolean visible) {
        this.visible = visible;
    }
 
    public void setSuggestion(@Nullable String suggestion) {
        this.suggestion = suggestion;
    }
 
    public int getScreenX(int charIndex) {
        return charIndex > this.value.length() ? this.getX() : this.getX() + this.font.width(this.value.substring(0, charIndex));
    }
 
    @Override
    public void updateWidgetNarration(NarrationElementOutput output) {
        output.add(NarratedElementType.TITLE, this.createNarrationMessage());
    }
 
    public void setHint(Component hint) {
        boolean hasNoStyle = hint.getStyle().equals(Style.EMPTY);
        this.hint = (Component)(hasNoStyle ? hint.copy().withStyle(DEFAULT_HINT_STYLE) : hint);
    }
 
    @FunctionalInterface
    @OnlyIn(Dist.CLIENT)
    public interface TextFormatter {
        @Nullable FormattedCharSequence format(final String text, final int offset);
    }
}

引用的其他类

  • Minecraft

    • 引用位置: 方法调用
    • 关联成员: Minecraft.getInstance()
  • Font

    • 引用位置: 参数/字段
  • GuiGraphicsExtractor

    • 引用位置: 参数
  • AbstractWidget

    • 引用位置: 继承
  • IMEPreeditOverlay

    • 引用位置: 字段/构造调用
    • 关联成员: IMEPreeditOverlay()
  • TextCursorUtils

    • 引用位置: 方法调用
    • 关联成员: TextCursorUtils.extractAppendCursor(), TextCursorUtils.extractInsertCursor(), TextCursorUtils.isCursorVisible()
  • WidgetSprites

    • 引用位置: 字段/构造调用
    • 关联成员: WidgetSprites()
  • NarrationElementOutput

    • 引用位置: 参数
  • CharacterEvent

    • 引用位置: 参数
  • KeyEvent

    • 引用位置: 参数
  • MouseButtonEvent

    • 引用位置: 参数
  • PreeditEvent

    • 引用位置: 参数
  • SoundManager

    • 引用位置: 参数
  • Component

    • 引用位置: 参数/字段/方法调用
    • 关联成员: Component.translatable()
  • MutableComponent

    • 引用位置: 返回值
  • Style

    • 引用位置: 字段
  • Identifier

    • 引用位置: 方法调用
    • 关联成员: Identifier.withDefaultNamespace()
  • FormattedCharSequence

    • 引用位置: 方法调用/返回值
    • 关联成员: FormattedCharSequence.forward()
  • Mth

    • 引用位置: 方法调用
    • 关联成员: Mth.clamp(), Mth.floor()
  • StringUtil

    • 引用位置: 方法调用
    • 关联成员: StringUtil.filterText()
  • Util

    • 引用位置: 方法调用
    • 关联成员: Util.getMillis(), Util.offsetByCodepoints()