Path: blob/master/SLICK_HOME/src/org/newdawn/slick/gui/TextField.java
1457 views
package org.newdawn.slick.gui;12import org.lwjgl.Sys;3import org.newdawn.slick.Color;4import org.newdawn.slick.Font;5import org.newdawn.slick.Graphics;6import org.newdawn.slick.Input;7import org.newdawn.slick.geom.Rectangle;89/**10* A single text field supporting text entry11*12* @author kevin13*/14public class TextField extends AbstractComponent {15/** The key repeat interval */16private static final int INITIAL_KEY_REPEAT_INTERVAL = 400;17/** The key repeat interval */18private static final int KEY_REPEAT_INTERVAL = 50;1920/** The width of the field */21private int width;2223/** The height of the field */24private int height;2526/** The location in the X coordinate */27protected int x;2829/** The location in the Y coordinate */30protected int y;3132/** The maximum number of characters allowed to be input */33private int maxCharacter = 10000;3435/** The value stored in the text field */36private String value = "";3738/** The font used to render text in the field */39private Font font;4041/** The border color - null if no border */42private Color border = Color.white;4344/** The text color */45private Color text = Color.white;4647/** The background color - null if no background */48private Color background = new Color(0, 0, 0, 0.5f);4950/** The current cursor position */51private int cursorPos;5253/** True if the cursor should be visible */54private boolean visibleCursor = true;5556/** The last key pressed */57private int lastKey = -1;5859/** The last character pressed */60private char lastChar = 0;6162/** The time since last key repeat */63private long repeatTimer;6465/** The text before the paste in */66private String oldText;6768/** The cursor position before the paste */69private int oldCursorPos;7071/** True if events should be consumed by the field */72private boolean consume = true;7374/**75* Create a new text field76*77* @param container78* The container rendering this field79* @param font80* The font to use in the text field81* @param x82* The x coordinate of the top left corner of the text field83* @param y84* The y coordinate of the top left corner of the text field85* @param width86* The width of the text field87* @param height88* The height of the text field89* @param listener90* The listener to add to the text field91*/92public TextField(GUIContext container, Font font, int x, int y, int width,93int height, ComponentListener listener) {94this(container,font,x,y,width,height);95addListener(listener);96}9798/**99* Create a new text field100*101* @param container102* The container rendering this field103* @param font104* The font to use in the text field105* @param x106* The x coordinate of the top left corner of the text field107* @param y108* The y coordinate of the top left corner of the text field109* @param width110* The width of the text field111* @param height112* The height of the text field113*/114public TextField(GUIContext container, Font font, int x, int y, int width,115int height) {116super(container);117118this.font = font;119120setLocation(x, y);121this.width = width;122this.height = height;123}124125/**126* Indicate if the input events should be consumed by this field127*128* @param consume True if events should be consumed by this field129*/130public void setConsumeEvents(boolean consume) {131this.consume = consume;132}133134/**135* Deactivate the key input handling for this field136*/137public void deactivate() {138setFocus(false);139}140141/**142* Moves the component.143*144* @param x145* X coordinate146* @param y147* Y coordinate148*/149public void setLocation(int x, int y) {150this.x = x;151this.y = y;152}153154/**155* Returns the position in the X coordinate156*157* @return x158*/159public int getX() {160return x;161}162163/**164* Returns the position in the Y coordinate165*166* @return y167*/168public int getY() {169return y;170}171172/**173* Get the width of the component174*175* @return The width of the component176*/177public int getWidth() {178return width;179}180181/**182* Get the height of the component183*184* @return The height of the component185*/186public int getHeight() {187return height;188}189190/**191* Set the background color. Set to null to disable the background192*193* @param color194* The color to use for the background195*/196public void setBackgroundColor(Color color) {197background = color;198}199200/**201* Set the border color. Set to null to disable the border202*203* @param color204* The color to use for the border205*/206public void setBorderColor(Color color) {207border = color;208}209210/**211* Set the text color.212*213* @param color214* The color to use for the text215*/216public void setTextColor(Color color) {217text = color;218}219220/**221* @see org.newdawn.slick.gui.AbstractComponent#render(org.newdawn.slick.gui.GUIContext,222* org.newdawn.slick.Graphics)223*/224public void render(GUIContext container, Graphics g) {225if (lastKey != -1) {226if (input.isKeyDown(lastKey)) {227if (repeatTimer < System.currentTimeMillis()) {228repeatTimer = System.currentTimeMillis() + KEY_REPEAT_INTERVAL;229keyPressed(lastKey, lastChar);230}231} else {232lastKey = -1;233}234}235Rectangle oldClip = g.getClip();236g.setWorldClip(x,y,width, height);237238// Someone could have set a color for me to blend...239Color clr = g.getColor();240241if (background != null) {242g.setColor(background.multiply(clr));243g.fillRect(x, y, width, height);244}245g.setColor(text.multiply(clr));246Font temp = g.getFont();247248int cpos = font.getWidth(value.substring(0, cursorPos));249int tx = 0;250if (cpos > width) {251tx = width - cpos - font.getWidth("_");252}253254g.translate(tx + 2, 0);255g.setFont(font);256g.drawString(value, x + 1, y + 1);257258if (hasFocus() && visibleCursor) {259g.drawString("_", x + 1 + cpos + 2, y + 1);260}261262g.translate(-tx - 2, 0);263264if (border != null) {265g.setColor(border.multiply(clr));266g.drawRect(x, y, width, height);267}268g.setColor(clr);269g.setFont(temp);270g.clearWorldClip();271g.setClip(oldClip);272}273274/**275* Get the value in the text field276*277* @return The value in the text field278*/279public String getText() {280return value;281}282283/**284* Set the value to be displayed in the text field285*286* @param value287* The value to be displayed in the text field288*/289public void setText(String value) {290this.value = value;291if (cursorPos > value.length()) {292cursorPos = value.length();293}294}295296/**297* Set the position of the cursor298*299* @param pos300* The new position of the cursor301*/302public void setCursorPos(int pos) {303cursorPos = pos;304if (cursorPos > value.length()) {305cursorPos = value.length();306}307}308309/**310* Indicate whether the mouse cursor should be visible or not311*312* @param visibleCursor313* True if the mouse cursor should be visible314*/315public void setCursorVisible(boolean visibleCursor) {316this.visibleCursor = visibleCursor;317}318319/**320* Set the length of the allowed input321*322* @param length323* The length of the allowed input324*/325public void setMaxLength(int length) {326maxCharacter = length;327if (value.length() > maxCharacter) {328value = value.substring(0, maxCharacter);329}330}331332/**333* Do the paste into the field, overrideable for custom behaviour334*335* @param text The text to be pasted in336*/337protected void doPaste(String text) {338recordOldPosition();339340for (int i=0;i<text.length();i++) {341keyPressed(-1, text.charAt(i));342}343}344345/**346* Record the old position and content347*/348protected void recordOldPosition() {349oldText = getText();350oldCursorPos = cursorPos;351}352353/**354* Do the undo of the paste, overrideable for custom behaviour355*356* @param oldCursorPos before the paste357* @param oldText The text before the last paste358*/359protected void doUndo(int oldCursorPos, String oldText) {360if (oldText != null) {361setText(oldText);362setCursorPos(oldCursorPos);363}364}365366/**367* @see org.newdawn.slick.gui.AbstractComponent#keyPressed(int, char)368*/369public void keyPressed(int key, char c) {370if (hasFocus()) {371if (key != -1)372{373if ((key == Input.KEY_V) &&374((input.isKeyDown(Input.KEY_LCONTROL)) || (input.isKeyDown(Input.KEY_RCONTROL)))) {375String text = Sys.getClipboard();376if (text != null) {377doPaste(text);378}379return;380}381if ((key == Input.KEY_Z) &&382((input.isKeyDown(Input.KEY_LCONTROL)) || (input.isKeyDown(Input.KEY_RCONTROL)))) {383if (oldText != null) {384doUndo(oldCursorPos, oldText);385}386return;387}388389// alt and control keys don't come through here390if (input.isKeyDown(Input.KEY_LCONTROL) || input.isKeyDown(Input.KEY_RCONTROL)) {391return;392}393if (input.isKeyDown(Input.KEY_LALT) || input.isKeyDown(Input.KEY_RALT)) {394return;395}396}397398if (lastKey != key) {399lastKey = key;400repeatTimer = System.currentTimeMillis() + INITIAL_KEY_REPEAT_INTERVAL;401} else {402repeatTimer = System.currentTimeMillis() + KEY_REPEAT_INTERVAL;403}404lastChar = c;405406if (key == Input.KEY_LEFT) {407if (cursorPos > 0) {408cursorPos--;409}410// Nobody more will be notified411if (consume) {412container.getInput().consumeEvent();413}414} else if (key == Input.KEY_RIGHT) {415if (cursorPos < value.length()) {416cursorPos++;417}418// Nobody more will be notified419if (consume) {420container.getInput().consumeEvent();421}422} else if (key == Input.KEY_BACK) {423if ((cursorPos > 0) && (value.length() > 0)) {424if (cursorPos < value.length()) {425value = value.substring(0, cursorPos - 1)426+ value.substring(cursorPos);427} else {428value = value.substring(0, cursorPos - 1);429}430cursorPos--;431}432// Nobody more will be notified433if (consume) {434container.getInput().consumeEvent();435}436} else if (key == Input.KEY_DELETE) {437if (value.length() > cursorPos) {438value = value.substring(0,cursorPos) + value.substring(cursorPos+1);439}440// Nobody more will be notified441if (consume) {442container.getInput().consumeEvent();443}444} else if ((c < 127) && (c > 31) && (value.length() < maxCharacter)) {445if (cursorPos < value.length()) {446value = value.substring(0, cursorPos) + c447+ value.substring(cursorPos);448} else {449value = value.substring(0, cursorPos) + c;450}451cursorPos++;452// Nobody more will be notified453if (consume) {454container.getInput().consumeEvent();455}456} else if (key == Input.KEY_RETURN) {457notifyListeners();458// Nobody more will be notified459if (consume) {460container.getInput().consumeEvent();461}462}463464}465}466467/**468* @see org.newdawn.slick.gui.AbstractComponent#setFocus(boolean)469*/470public void setFocus(boolean focus) {471lastKey = -1;472473super.setFocus(focus);474}475}476477478