Android Open Source - libgdx-chat-example Chat Text Field






From Project

Back to project page libgdx-chat-example.

License

The source code is released under:

Apache License

If you think the Android project libgdx-chat-example listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package org.stofkat.chat.core;
//from ww  w  . jav  a2 s.c  om
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.BitmapFont.TextBounds;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Widget;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.Disableable;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Clipboard;
import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.TimeUtils;
import com.badlogic.gdx.utils.Timer;
import com.badlogic.gdx.utils.Timer.Task;

/**
 * In the TextFieldListener implementation of libgdx there's currently (libgdx
 * version 0.9.8 & 0.9.9) a bug that makes the "ENTER" key impossible to detect when
 * it's pressed in a TextField in GWT.
 * 
 * So with this class we're going to override some methods to make sure we do
 * pass the enter key correctly.
 * 
 * @author Leejjon
 */
public class ChatTextField extends Widget implements Disableable {
  static private final char BACKSPACE = 8;
  static private final char ENTER_DESKTOP = '\r';
  static private final char ENTER_ANDROID = '\n';
  static private final char TAB = '\t';
  static private final char DELETE = 127;
  static private final char BULLET = 149;

  static private final Vector2 tmp1 = new Vector2();
  static private final Vector2 tmp2 = new Vector2();
  static private final Vector2 tmp3 = new Vector2();

  static boolean isMac = System.getProperty("os.name").contains("Mac");

  TextFieldStyle style;
  String text, messageText;
  private CharSequence displayText;
  int cursor;
  private Clipboard clipboard;
  TextFieldListener listener;
  TextFieldFilter filter;
  OnscreenKeyboard keyboard = new DefaultOnscreenKeyboard();
  boolean focusTraversal = true;
  boolean disabled;
  boolean onlyFontChars = true;

  private boolean passwordMode;
  private StringBuilder passwordBuffer;

  private final Rectangle fieldBounds = new Rectangle();
  private final TextBounds textBounds = new TextBounds();
  private final Rectangle scissor = new Rectangle();
  float renderOffset, textOffset;
  private int visibleTextStart, visibleTextEnd;
  private final FloatArray glyphAdvances = new FloatArray();
  final FloatArray glyphPositions = new FloatArray();

  boolean cursorOn = true;
  private float blinkTime = 0.32f;
  long lastBlink;

  boolean hasSelection;
  int selectionStart;
  private float selectionX, selectionWidth;

  private char passwordCharacter = BULLET;

  InputListener inputListener;
  KeyRepeatTask keyRepeatTask = new KeyRepeatTask();
  float keyRepeatInitialTime = 0.4f;
  float keyRepeatTime = 0.1f;
  boolean rightAligned;

  int maxLength = 0;

  public ChatTextField (String text, Skin skin) {
    this(text, skin.get(TextFieldStyle.class));
  }

  public ChatTextField (String text, Skin skin, String styleName) {
    this(text, skin.get(styleName, TextFieldStyle.class));
  }

  public ChatTextField (String text, TextFieldStyle style) {
    setStyle(style);
    this.clipboard = Gdx.app.getClipboard();
    setText(text);
    setWidth(getPrefWidth());
    setHeight(getPrefHeight());
    initialize();
  }

  private void initialize () {
    addListener(inputListener = new ClickListener() {
      public void clicked (InputEvent event, float x, float y) {
        if (getTapCount() > 1) setSelection(0, text.length());
      }

      public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
        if (!super.touchDown(event, x, y, pointer, button)) return false;
        if (pointer == 0 && button != 0) return false;
        if (disabled) return true;
        clearSelection();
        setCursorPosition(x);
        selectionStart = cursor;
        Stage stage = getStage();
        if (stage != null) stage.setKeyboardFocus(ChatTextField.this);
        keyboard.show(true);
        return true;
      }

      public void touchDragged (InputEvent event, float x, float y, int pointer) {
        super.touchDragged(event, x, y, pointer);
        lastBlink = 0;
        cursorOn = false;
        setCursorPosition(x);
        hasSelection = true;
      }

      private void setCursorPosition (float x) {
        lastBlink = 0;
        cursorOn = false;
        x -= renderOffset + textOffset;
        for (int i = 0; i < glyphPositions.size; i++) {
          if (glyphPositions.items[i] > x) {
            cursor = Math.max(0, i - 1);
            return;
          }
        }
        cursor = Math.max(0, glyphPositions.size - 1);
      }

      public boolean keyDown (InputEvent event, int keycode) {
        if (disabled) return false;

        lastBlink = 0;
        cursorOn = false;

        Stage stage = getStage();
        if (stage != null && stage.getKeyboardFocus() == ChatTextField.this) {
          boolean repeat = false;
          boolean ctrl;
          if (isMac)
            ctrl = Gdx.input.isKeyPressed(Keys.SYM);
          else
            ctrl = Gdx.input.isKeyPressed(Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(Keys.CONTROL_RIGHT);
          if (ctrl) {
            // paste
            if (keycode == Keys.V) {
              paste();
              return true;
            }
            // copy
            if (keycode == Keys.C || keycode == Keys.INSERT) {
              copy();
              return true;
            }
            // cut
            if (keycode == Keys.X || keycode == Keys.DEL) {
              cut();
              return true;
            }
            // select all
            if (keycode == Keys.A) {
              selectAll();
              return true;
            }
          }
          if (Gdx.input.isKeyPressed(Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Keys.SHIFT_RIGHT)) {
            // paste
            if (keycode == Keys.INSERT) paste();
            // cut
            if (keycode == Keys.FORWARD_DEL) {
              if (hasSelection) {
                copy();
                delete();
              }
            }
            // selection
            if (keycode == Keys.LEFT) {
              if (!hasSelection) {
                selectionStart = cursor;
                hasSelection = true;
              }
              while (--cursor > 0 && ctrl) {
                char c = text.charAt(cursor);
                if (c >= 'A' && c <= 'Z') continue;
                if (c >= 'a' && c <= 'z') continue;
                if (c >= '0' && c <= '9') continue;
                break;
              }
              repeat = true;
            }
            if (keycode == Keys.RIGHT) {
              if (!hasSelection) {
                selectionStart = cursor;
                hasSelection = true;
              }
              int length = text.length();
              while (++cursor < length && ctrl) {
                char c = text.charAt(cursor - 1);
                if (c >= 'A' && c <= 'Z') continue;
                if (c >= 'a' && c <= 'z') continue;
                if (c >= '0' && c <= '9') continue;
                break;
              }
              repeat = true;
            }
            if (keycode == Keys.HOME) {
              if (!hasSelection) {
                selectionStart = cursor;
                hasSelection = true;
              }
              cursor = 0;
            }
            if (keycode == Keys.END) {
              if (!hasSelection) {
                selectionStart = cursor;
                hasSelection = true;
              }
              cursor = text.length();
            }

            cursor = Math.max(0, cursor);
            cursor = Math.min(text.length(), cursor);
          } else {
            // cursor movement or other keys (kill selection)
            if (keycode == Keys.LEFT) {
              while (cursor-- > 1 && ctrl) {
                char c = text.charAt(cursor - 1);
                if (c >= 'A' && c <= 'Z') continue;
                if (c >= 'a' && c <= 'z') continue;
                if (c >= '0' && c <= '9') continue;
                break;
              }
              clearSelection();
              repeat = true;
            }
            if (keycode == Keys.RIGHT) {
              int length = text.length();
              while (++cursor < length && ctrl) {
                char c = text.charAt(cursor - 1);
                if (c >= 'A' && c <= 'Z') continue;
                if (c >= 'a' && c <= 'z') continue;
                if (c >= '0' && c <= '9') continue;
                break;
              }
              clearSelection();
              repeat = true;
            }
            if (keycode == Keys.HOME) {
              cursor = 0;
              clearSelection();
            }
            if (keycode == Keys.END) {
              cursor = text.length();
              clearSelection();
            }

            cursor = Math.max(0, cursor);
            cursor = Math.min(text.length(), cursor);
          }
          if (repeat && (!keyRepeatTask.isScheduled() || keyRepeatTask.keycode != keycode)) {
            keyRepeatTask.keycode = keycode;
            keyRepeatTask.cancel();
            Timer.schedule(keyRepeatTask, keyRepeatInitialTime, keyRepeatTime);
          }
          return true;
        }
        return false;
      }

      public boolean keyUp (InputEvent event, int keycode) {
        if (disabled) return false;
        keyRepeatTask.cancel();
        return true;
      }

      public boolean keyTyped (InputEvent event, char character) {
        if (disabled) return false;

        final BitmapFont font = style.font;

        Stage stage = getStage();
        if (stage != null && stage.getKeyboardFocus() == ChatTextField.this) {
          if (character == BACKSPACE) {
            if (cursor > 0 || hasSelection) {
              if (!hasSelection) {
                text = text.substring(0, cursor - 1) + text.substring(cursor);
                updateDisplayText();
                cursor--;
                renderOffset = 0;
              } else {
                delete();
              }
            }
          } else if (character == DELETE) {
            if (cursor < text.length() || hasSelection) {
              if (!hasSelection) {
                text = text.substring(0, cursor) + text.substring(cursor + 1);
                updateDisplayText();
              } else {
                delete();
              }
            }
          } else if ((character == TAB /*|| character == ENTER_ANDROID*/) && focusTraversal) {
//            next(Gdx.input.isKeyPressed(Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Keys.SHIFT_RIGHT));
          } else if (font.containsCharacter(character)) {
            // Character may be added to the text.
            if (character != ENTER_DESKTOP && character != ENTER_ANDROID) {
              if (filter != null && !filter.acceptChar(ChatTextField.this, character)) return true;
            }
            if (maxLength > 0 && text.length() + 1 > maxLength) return true;
            if (!hasSelection) {
              text = text.substring(0, cursor) + character + text.substring(cursor, text.length());
              updateDisplayText();
              cursor++;
            } else {
              int minIndex = Math.min(cursor, selectionStart);
              int maxIndex = Math.max(cursor, selectionStart);

              text = (minIndex > 0 ? text.substring(0, minIndex) : "")
                + (maxIndex < text.length() ? text.substring(maxIndex, text.length()) : "");
              cursor = minIndex;
              text = text.substring(0, cursor) + character + text.substring(cursor, text.length());
              updateDisplayText();
              cursor++;
              clearSelection();
            }
          }
          if (listener != null) {
            // CODE I ADDED TO MAKE ENTER WORK - Leejjon
            if ((int)character == 0 && event.getKeyCode() == 66) {
              character = '\r';
            }
            // END OF CODE I ADDED TO MAKE ENTER WORK - Leejjon
            listener.keyTyped(ChatTextField.this, character);
          }
        
          return true;
        } else
          return false;
      }
    });
  }

  public void setMaxLength (int maxLength) {
    this.maxLength = maxLength;
  }

  public int getMaxLength () {
    return this.maxLength;
  }

  /** When false, text set by {@link #setText(String)} may contain characters not in the font, a space will be displayed instead.
   * When true (the default), characters not in the font are stripped by setText. Characters not in the font are always stripped
   * when typed or pasted. */
  public void setOnlyFontChars (boolean onlyFontChars) {
    this.onlyFontChars = onlyFontChars;
  }

  public void setStyle (TextFieldStyle style) {
    if (style == null) throw new IllegalArgumentException("style cannot be null.");
    this.style = style;
    invalidateHierarchy();
  }

  /** Sets the password character for the text field. The character must be present in the {@link BitmapFont} */
  public void setPasswordCharacter (char passwordCharacter) {
    this.passwordCharacter = passwordCharacter;
    if (passwordMode) updateDisplayText();
  }

  /** Returns the text field's style. Modifying the returned style may not have an effect until {@link #setStyle(TextFieldStyle)}
   * is called. */
  public TextFieldStyle getStyle () {
    return style;
  }

  private void calculateOffsets () {
    float visibleWidth = getWidth();
    if (style.background != null) visibleWidth -= style.background.getLeftWidth() + style.background.getRightWidth();

    // Check if the cursor has gone out the left or right side of the visible area and adjust renderoffset.
    float position = glyphPositions.get(cursor);
    float distance = position - Math.abs(renderOffset);
    if (distance <= 0) {
      if (cursor > 0)
        renderOffset = -glyphPositions.get(cursor - 1);
      else
        renderOffset = 0;
    } else if (distance > visibleWidth) {
      renderOffset -= distance - visibleWidth;
    }

    // calculate first visible char based on render offset
    visibleTextStart = 0;
    textOffset = 0;
    float start = Math.abs(renderOffset);
    int len = glyphPositions.size;
    float startPos = 0;
    for (int i = 0; i < len; i++) {
      if (glyphPositions.items[i] >= start) {
        visibleTextStart = i;
        startPos = glyphPositions.items[i];
        textOffset = startPos - start;
        break;
      }
    }

    // calculate last visible char based on visible width and render offset
    visibleTextEnd = Math.min(displayText.length(), cursor + 1);
    for (; visibleTextEnd <= displayText.length(); visibleTextEnd++) {
      if (glyphPositions.items[visibleTextEnd] - startPos > visibleWidth) break;
    }
    visibleTextEnd = Math.max(0, visibleTextEnd - 1);

    // calculate selection x position and width
    if (hasSelection) {
      int minIndex = Math.min(cursor, selectionStart);
      int maxIndex = Math.max(cursor, selectionStart);
      float minX = Math.max(glyphPositions.get(minIndex), startPos);
      float maxX = Math.min(glyphPositions.get(maxIndex), glyphPositions.get(visibleTextEnd));
      selectionX = minX;
      selectionWidth = maxX - minX;
    }

    if (rightAligned) {
      textOffset = visibleWidth - (glyphPositions.items[visibleTextEnd] - startPos);
      if (hasSelection) selectionX += textOffset;
    }
  }

  @Override
  public void draw (SpriteBatch batch, float parentAlpha) {

    Stage stage = getStage();
    boolean focused = stage != null && stage.getKeyboardFocus() == this;

    final BitmapFont font = style.font;
    final Color fontColor = (disabled && style.disabledFontColor != null) ? style.disabledFontColor
      : ((focused && style.focusedFontColor != null) ? style.focusedFontColor : style.fontColor);
    final Drawable selection = style.selection;
    final Drawable cursorPatch = style.cursor;
    final Drawable background = (disabled && style.disabledBackground != null) ? style.disabledBackground
      : ((focused && style.focusedBackground != null) ? style.focusedBackground : style.background);

    Color color = getColor();
    float x = getX();
    float y = getY();
    float width = getWidth();
    float height = getHeight();
    float textY = textBounds.height / 2 + font.getDescent();

    batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
    float bgLeftWidth = 0;
    if (background != null) {
      background.draw(batch, x, y, width, height);
      bgLeftWidth = background.getLeftWidth();
      float bottom = background.getBottomHeight();
      textY = (int)(textY + (height - background.getTopHeight() - bottom) / 2 + bottom);
    } else
      textY = (int)(textY + height / 2);

    calculateOffsets();

    if (focused && hasSelection && selection != null) {
      selection.draw(batch, x + selectionX + bgLeftWidth + renderOffset, y + textY - textBounds.height - font.getDescent(),
        selectionWidth, textBounds.height + font.getDescent() / 2);
    }

    float yOffset = font.isFlipped() ? -textBounds.height : 0;
    if (displayText.length() == 0) {
      if (!focused && messageText != null) {
        if (style.messageFontColor != null) {
          font.setColor(style.messageFontColor.r, style.messageFontColor.g, style.messageFontColor.b,
            style.messageFontColor.a * parentAlpha);
        } else
          font.setColor(0.7f, 0.7f, 0.7f, parentAlpha);
        BitmapFont messageFont = style.messageFont != null ? style.messageFont : font;
        messageFont.draw(batch, messageText, x + bgLeftWidth, y + textY + yOffset);
      }
    } else {
      font.setColor(fontColor.r, fontColor.g, fontColor.b, fontColor.a * parentAlpha);
      font.draw(batch, displayText, x + bgLeftWidth + textOffset, y + textY + yOffset, visibleTextStart, visibleTextEnd);
    }
    if (focused && !disabled) {
      blink();
      if (cursorOn && cursorPatch != null) {
        cursorPatch.draw(batch, x + bgLeftWidth + textOffset + glyphPositions.get(cursor)
          - glyphPositions.items[visibleTextStart] - 1, y + textY - textBounds.height - font.getDescent(),
          cursorPatch.getMinWidth(), textBounds.height + font.getDescent() / 2);
      }
    }
  }

  void updateDisplayText () {
    StringBuilder buffer = new StringBuilder();
    for (int i = 0; i < text.length(); i++) {
      char c = text.charAt(i);
      buffer.append(style.font.containsCharacter(c) ? c : ' ');
    }
    String text = buffer.toString();

    if (passwordMode && style.font.containsCharacter(passwordCharacter)) {
      if (passwordBuffer == null) passwordBuffer = new StringBuilder(text.length());
      if (passwordBuffer.length() > text.length()) //
        passwordBuffer.setLength(text.length());
      else {
        for (int i = passwordBuffer.length(), n = text.length(); i < n; i++)
          passwordBuffer.append(passwordCharacter);
      }
      displayText = passwordBuffer;
    } else
      displayText = text;
    style.font.computeGlyphAdvancesAndPositions(displayText, glyphAdvances, glyphPositions);
    if (selectionStart > text.length()) selectionStart = text.length();
  }

  private void blink () {
    long time = TimeUtils.nanoTime();
    if ((time - lastBlink) / 1000000000.0f > blinkTime) {
      cursorOn = !cursorOn;
      lastBlink = time;
    }
  }

  /** Copies the contents of this TextField to the {@link Clipboard} implementation set on this TextField. */
  public void copy () {
    if (hasSelection && !passwordMode) {
      int minIndex = Math.min(cursor, selectionStart);
      int maxIndex = Math.max(cursor, selectionStart);
      clipboard.setContents(text.substring(minIndex, maxIndex));
    }
  }

  /** Copies the selected contents of this TextField to the {@link Clipboard} implementation set on this TextField, then removes
   * it. */
  public void cut () {
    if (hasSelection && !passwordMode) {
      copy();
      delete();
    }
  }

  /** Pastes the content of the {@link Clipboard} implementation set on this Textfield to this TextField. */
  void paste () {
    String content = clipboard.getContents();
    if (content != null) {
      StringBuilder buffer = new StringBuilder();
      for (int i = 0; i < content.length(); i++) {
        if (maxLength > 0 && text.length() + buffer.length() + 1 > maxLength) break;
        char c = content.charAt(i);
        if (!style.font.containsCharacter(c)) continue;
        if (filter != null && !filter.acceptChar(this, c)) continue;
        buffer.append(c);
      }
      content = buffer.toString();

      if (!hasSelection) {
        text = text.substring(0, cursor) + content + text.substring(cursor, text.length());
        updateDisplayText();
        cursor += content.length();
      } else {
        int minIndex = Math.min(cursor, selectionStart);
        int maxIndex = Math.max(cursor, selectionStart);

        text = (minIndex > 0 ? text.substring(0, minIndex) : "")
          + (maxIndex < text.length() ? text.substring(maxIndex, text.length()) : "");
        cursor = minIndex;
        text = text.substring(0, cursor) + content + text.substring(cursor, text.length());
        updateDisplayText();
        cursor = minIndex + content.length();
        clearSelection();
      }

    }
  }

  void delete () {
    int minIndex = Math.min(cursor, selectionStart);
    int maxIndex = Math.max(cursor, selectionStart);
    text = (minIndex > 0 ? text.substring(0, minIndex) : "")
      + (maxIndex < text.length() ? text.substring(maxIndex, text.length()) : "");
    updateDisplayText();
    cursor = minIndex;
    clearSelection();
  }

  /** Focuses the next TextField. If none is found, the keyboard is hidden. Does nothing if the text field is not in a stage.
   * @param up If true, the TextField with the same or next smallest y coordinate is found, else the next highest. */
  public void next (boolean up) {
    Stage stage = getStage();
    if (stage == null) return;
    getParent().localToStageCoordinates(tmp1.set(getX(), getY()));
    TextField textField = findNextTextField(stage.getActors(), null, tmp2, tmp1, up);
    if (textField == null) { // Try to wrap around.
      if (up)
        tmp1.set(Float.MIN_VALUE, Float.MIN_VALUE);
      else
        tmp1.set(Float.MAX_VALUE, Float.MAX_VALUE);
      textField = findNextTextField(getStage().getActors(), null, tmp2, tmp1, up);
    }
    if (textField != null)
      stage.setKeyboardFocus(textField);
    else
      Gdx.input.setOnscreenKeyboardVisible(false);
  }

  private TextField findNextTextField (Array<Actor> actors, TextField best, Vector2 bestCoords, Vector2 currentCoords, boolean up) {
    for (int i = 0, n = actors.size; i < n; i++) {
      Actor actor = actors.get(i);
      if (actor == this) continue;
      if (actor instanceof TextField) {
        ChatTextField textField = (ChatTextField)actor;
        if (textField.isDisabled() || !textField.focusTraversal) continue;
        Vector2 actorCoords = actor.getParent().localToStageCoordinates(tmp3.set(actor.getX(), actor.getY()));
        if ((actorCoords.y < currentCoords.y || (actorCoords.y == currentCoords.y && actorCoords.x > currentCoords.x)) ^ up) {
          if (best == null
            || (actorCoords.y > bestCoords.y || (actorCoords.y == bestCoords.y && actorCoords.x < bestCoords.x)) ^ up) {
            best = (TextField)actor;
            bestCoords.set(actorCoords);
          }
        }
      } else if (actor instanceof Group)
        best = findNextTextField(((Group)actor).getChildren(), best, bestCoords, currentCoords, up);
    }
    return best;
  }

  /** @param listener May be null. */
  public void setTextFieldListener (TextFieldListener listener) {
    this.listener = listener;
  }

  /** @param filter May be null. */
  public void setTextFieldFilter (TextFieldFilter filter) {
    this.filter = filter;
  }

  /** If true (the default), tab/shift+tab will move to the next text field. */
  public void setFocusTraversal (boolean focusTraversal) {
    this.focusTraversal = focusTraversal;
  }

  /** @return May be null. */
  public String getMessageText () {
    return messageText;
  }

  /** Sets the text that will be drawn in the text field if no text has been entered.
   * @param messageText may be null. */
  public void setMessageText (String messageText) {
    this.messageText = messageText;
  }

  public void setText (String text) {
    if (text == null) throw new IllegalArgumentException("text cannot be null.");

    BitmapFont font = style.font;

    StringBuilder buffer = new StringBuilder();
    for (int i = 0; i < text.length(); i++) {
      if (maxLength > 0 && buffer.length() + 1 > maxLength) break;
      char c = text.charAt(i);
      if (onlyFontChars && !style.font.containsCharacter(c)) continue;
      if (filter != null && !filter.acceptChar(this, c)) continue;
      buffer.append(c);
    }

    this.text = buffer.toString();
    updateDisplayText();
    cursor = 0;
    clearSelection();

    textBounds.set(font.getBounds(displayText));
    textBounds.height -= font.getDescent() * 2;
    font.computeGlyphAdvancesAndPositions(displayText, glyphAdvances, glyphPositions);
  }

  /** @return Never null, might be an empty string. */
  public String getText () {
    return text;
  }

  /** Sets the selected text. */
  public void setSelection (int selectionStart, int selectionEnd) {
    if (selectionStart < 0) throw new IllegalArgumentException("selectionStart must be >= 0");
    if (selectionEnd < 0) throw new IllegalArgumentException("selectionEnd must be >= 0");
    selectionStart = Math.min(text.length(), selectionStart);
    selectionEnd = Math.min(text.length(), selectionEnd);
    if (selectionEnd == selectionStart) {
      clearSelection();
      return;
    }
    if (selectionEnd < selectionStart) {
      int temp = selectionEnd;
      selectionEnd = selectionStart;
      selectionStart = temp;
    }

    hasSelection = true;
    this.selectionStart = selectionStart;
    cursor = selectionEnd;
  }

  public void selectAll () {
    setSelection(0, text.length());
  }

  public void clearSelection () {
    hasSelection = false;
  }

  /** Sets the cursor position and clears any selection. */
  public void setCursorPosition (int cursorPosition) {
    if (cursorPosition < 0) throw new IllegalArgumentException("cursorPosition must be >= 0");
    clearSelection();
    cursor = Math.min(cursorPosition, text.length());
  }

  public int getCursorPosition () {
    return cursor;
  }

  /** Default is an instance of {@link DefaultOnscreenKeyboard}. */
  public OnscreenKeyboard getOnscreenKeyboard () {
    return keyboard;
  }

  public void setOnscreenKeyboard (OnscreenKeyboard keyboard) {
    this.keyboard = keyboard;
  }

  public void setClipboard (Clipboard clipboard) {
    this.clipboard = clipboard;
  }

  public float getPrefWidth () {
    return 150;
  }

  public float getPrefHeight () {
    float prefHeight = textBounds.height;
    if (style.background != null) {
      prefHeight = Math.max(prefHeight + style.background.getBottomHeight() + style.background.getTopHeight(),
        style.background.getMinHeight());
    }
    return prefHeight;
  }

  public void setRightAligned (boolean rightAligned) {
    this.rightAligned = rightAligned;
  }

  /** If true, the text in this text field will be shown as bullet characters. The font must have character 149 or this will have
   * no affect. */
  public void setPasswordMode (boolean passwordMode) {
    this.passwordMode = passwordMode;
    updateDisplayText();
  }

  public void setBlinkTime (float blinkTime) {
    this.blinkTime = blinkTime;
  }

  public void setDisabled (boolean disabled) {
    this.disabled = disabled;
  }

  public boolean isDisabled () {
    return disabled;
  }

  public boolean isPasswordMode () {
    return passwordMode;
  }

  public TextFieldFilter getTextFieldFilter () {
    return filter;
  }

  class KeyRepeatTask extends Task {
    int keycode;

    public void run () {
      inputListener.keyDown(null, keycode);
    }
  }

  /** Interface for listening to typed characters.
   * @author mzechner */
  static public interface TextFieldListener {
    public void keyTyped (ChatTextField textField, char key);
  }

  /** Interface for filtering characters entered into the text field.
   * @author mzechner */
  static public interface TextFieldFilter {
    /** @param textField
     * @param key
     * @return whether to accept the character */
    public boolean acceptChar (ChatTextField textField, char key);

    static public class DigitsOnlyFilter implements TextFieldFilter {
      @Override
      public boolean acceptChar (ChatTextField textField, char key) {
        return Character.isDigit(key);
      }

    }
  }

  /** An interface for onscreen keyboards. Can invoke the default keyboard or render your own keyboard!
   * @author mzechner */
  static public interface OnscreenKeyboard {
    public void show (boolean visible);
  }

  /** The default {@link OnscreenKeyboard} used by all {@link TextField} instances. Just uses
   * {@link Input#setOnscreenKeyboardVisible(boolean)} as appropriate. Might overlap your actual rendering, so use with care!
   * @author mzechner */
  static public class DefaultOnscreenKeyboard implements OnscreenKeyboard {
    @Override
    public void show (boolean visible) {
      Gdx.input.setOnscreenKeyboardVisible(visible);
    }
  }
}




Java Source Code List

org.stofkat.chat.android.AndroidChat.java
org.stofkat.chat.android.AndroidDispatchServiceAsync.java
org.stofkat.chat.android.ChatActivity.java
org.stofkat.chat.common.ChatMessage.java
org.stofkat.chat.common.ClientInterface.java
org.stofkat.chat.common.actions.Action.java
org.stofkat.chat.common.actions.ChatAction.java
org.stofkat.chat.common.actions.UpdateAction.java
org.stofkat.chat.common.exceptions.ActionException.java
org.stofkat.chat.common.exceptions.DispatchException.java
org.stofkat.chat.common.exceptions.ServiceException.java
org.stofkat.chat.common.exceptions.UnsupportedActionException.java
org.stofkat.chat.common.results.ChatResult.java
org.stofkat.chat.common.results.Result.java
org.stofkat.chat.common.util.HashMapToOrderedArray.java
org.stofkat.chat.common.util.LowestIdFinder.java
org.stofkat.chat.core.ChatTextField.java
org.stofkat.chat.core.Chat.java
org.stofkat.chat.core.PickNameStage.java
org.stofkat.chat.core.ServerInterface.java
org.stofkat.chat.core.UpdateTask.java
org.stofkat.chat.html.ChatHtml.java
org.stofkat.chat.html.HtmlChat.java
org.stofkat.chat.html.dispatch.GwtAsyncCallbackHandler.java
org.stofkat.chat.html.dispatch.GwtDispatchServiceAsync.java
org.stofkat.chat.html.dispatch.GwtDispatchService.java
org.stofkat.chat.http.dispatch.AsyncCallbackHandler.java
org.stofkat.chat.http.dispatch.AsyncCallback.java
org.stofkat.chat.http.dispatch.CustomCookieStore.java
org.stofkat.chat.http.dispatch.HttpDispatchServiceAsync.java
org.stofkat.chat.http.dispatch.HttpUtils.java
org.stofkat.chat.java.ChatDesktop.java
org.stofkat.chat.java.DesktopChat.java
org.stofkat.chat.java.DesktopDispatchServiceAsync.java
org.stofkat.chat.server.AbstractDispatch.java
org.stofkat.chat.server.ActionHandlerRegistry.java
org.stofkat.chat.server.ActionHandler.java
org.stofkat.chat.server.ActionResult.java
org.stofkat.chat.server.ChatMessagesDatabase.java
org.stofkat.chat.server.DefaultActionHandlerRegistry.java
org.stofkat.chat.server.Dispatch.java
org.stofkat.chat.server.InstanceActionHandlerRegistry.java
org.stofkat.chat.server.SimpleDispatch.java
org.stofkat.chat.server.actionhandlers.ChatActionHandler.java
org.stofkat.chat.server.actionhandlers.UpdateActionHandler.java
org.stofkat.chat.server.gwt.dispatch.GwtDispatchServlet.java
org.stofkat.chat.server.http.dispatch.HttpDispatchServlet.java