v1.4.0: implemented a copy and paste button for text input
This commit is contained in:
@@ -93,7 +93,6 @@ public class InputHandler extends InputAdapter {
|
|||||||
public synchronized boolean touchDown(int screenX, int screenY, int pointer, int button) {
|
public synchronized boolean touchDown(int screenX, int screenY, int pointer, int button) {
|
||||||
ControllerHandler.setControllerPointer(false);
|
ControllerHandler.setControllerPointer(false);
|
||||||
ControllerHandler.controllerActive = false;
|
ControllerHandler.controllerActive = false;
|
||||||
Gdx.input.setOnscreenKeyboardVisible(false); //in-game events never need keyboard, so hide it
|
|
||||||
|
|
||||||
if (button >= 3 && KeyBindings.isKeyBound( button + 1000 )) {
|
if (button >= 3 && KeyBindings.isKeyBound( button + 1000 )) {
|
||||||
KeyEvent.addKeyEvent( new KeyEvent( button + 1000, true ) );
|
KeyEvent.addKeyEvent( new KeyEvent( button + 1000, true ) );
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
package com.watabou.input;
|
package com.watabou.input;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.Input;
|
import com.badlogic.gdx.Input;
|
||||||
import com.watabou.noosa.Game;
|
import com.watabou.noosa.Game;
|
||||||
import com.watabou.noosa.ui.Cursor;
|
import com.watabou.noosa.ui.Cursor;
|
||||||
@@ -139,6 +140,8 @@ public class PointerEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean clearKeyboardThisPress = true;
|
||||||
|
|
||||||
public static synchronized void processPointerEvents(){
|
public static synchronized void processPointerEvents(){
|
||||||
//handle any hover events separately first as we may need to add drag events
|
//handle any hover events separately first as we may need to add drag events
|
||||||
boolean hovered = false;
|
boolean hovered = false;
|
||||||
@@ -164,6 +167,7 @@ public class PointerEvent {
|
|||||||
if (p.type == Type.HOVER){
|
if (p.type == Type.HOVER){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
clearKeyboardThisPress = true;
|
||||||
if (activePointers.containsKey(p.id)){
|
if (activePointers.containsKey(p.id)){
|
||||||
PointerEvent existing = activePointers.get(p.id);
|
PointerEvent existing = activePointers.get(p.id);
|
||||||
existing.current = p.current;
|
existing.current = p.current;
|
||||||
@@ -181,6 +185,10 @@ public class PointerEvent {
|
|||||||
}
|
}
|
||||||
pointerSignal.dispatch(p);
|
pointerSignal.dispatch(p);
|
||||||
}
|
}
|
||||||
|
if (clearKeyboardThisPress){
|
||||||
|
//most press events should clear the keyboard
|
||||||
|
Gdx.input.setOnscreenKeyboardVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pointerEvents.clear();
|
pointerEvents.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,31 @@ public class TextInput extends Component {
|
|||||||
return textField.getText();
|
return textField.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void copyToClipboard(){
|
||||||
|
if (textField.getSelection().isEmpty()) {
|
||||||
|
textField.selectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
textField.copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pasteFromClipboard(){
|
||||||
|
if (!Gdx.app.getClipboard().hasContents()) return;
|
||||||
|
|
||||||
|
if (!textField.getSelection().isEmpty()){
|
||||||
|
//just use cut, but override clipboard
|
||||||
|
String existingClip = Gdx.app.getClipboard().getContents();
|
||||||
|
textField.cut();
|
||||||
|
Gdx.app.getClipboard().setContents(existingClip);
|
||||||
|
}
|
||||||
|
|
||||||
|
String existing = textField.getText();
|
||||||
|
int cursorIdx = textField.getCursorPosition();
|
||||||
|
|
||||||
|
textField.setText(existing.substring(0, cursorIdx) + Gdx.app.getClipboard().getContents() + existing.substring(cursorIdx));
|
||||||
|
textField.setCursorPosition(cursorIdx + Gdx.app.getClipboard().getContents().length());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void layout() {
|
protected void layout() {
|
||||||
super.layout();
|
super.layout();
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
@@ -60,7 +60,7 @@ scenes.heroselectscene.daily_unavailable=A new daily run is available every day
|
|||||||
scenes.heroselectscene.daily_unavailable_long=It seems you've started a daily that's in the future! This can happen if you recently changed timezones, or if you changed your system clock. _Your next daily will be available in %d days._
|
scenes.heroselectscene.daily_unavailable_long=It seems you've started a daily that's in the future! This can happen if you recently changed timezones, or if you changed your system clock. _Your next daily will be available in %d days._
|
||||||
scenes.heroselectscene.daily_existing=You already have a daily run in progress. You must end that run before starting another daily.
|
scenes.heroselectscene.daily_existing=You already have a daily run in progress. You must end that run before starting another daily.
|
||||||
scenes.heroselectscene.custom_seed_title=Enter a Custom Seed
|
scenes.heroselectscene.custom_seed_title=Enter a Custom Seed
|
||||||
scenes.heroselectscene.custom_seed_desc=The same seed and game version always generate the same dungeon! Seeds are nine uppercase letters (e.g. ABC-DEF-GHI), but you can enter anything you want and the game will convert it. _Games with a custom seed cannot earn badges, contribute to games played, and appear at the bottom of the rankings page._
|
scenes.heroselectscene.custom_seed_desc=The same seed and game version always generate the same dungeon! _Custom seed games cannot earn badges or contribute to games played, and appear at the bottom of the rankings page._
|
||||||
scenes.heroselectscene.custom_seed_duplicate=You already have a regular game in progress with that seed. You must end that game before using that custom seed.
|
scenes.heroselectscene.custom_seed_duplicate=You already have a regular game in progress with that seed. You must end that game before using that custom seed.
|
||||||
scenes.heroselectscene.custom_seed_set=Set
|
scenes.heroselectscene.custom_seed_set=Set
|
||||||
scenes.heroselectscene.custom_seed_clear=Clear
|
scenes.heroselectscene.custom_seed_clear=Clear
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ public enum Icons {
|
|||||||
MAGNIFY,
|
MAGNIFY,
|
||||||
BUFFS,
|
BUFFS,
|
||||||
ENERGY,
|
ENERGY,
|
||||||
|
COPY,
|
||||||
|
PASTE,
|
||||||
COIN_SML,
|
COIN_SML,
|
||||||
ENERGY_SML,
|
ENERGY_SML,
|
||||||
BACKPACK,
|
BACKPACK,
|
||||||
@@ -259,26 +261,32 @@ public enum Icons {
|
|||||||
case ENERGY:
|
case ENERGY:
|
||||||
icon.frame( icon.texture.uvRectBySize( 176, 48, 16, 16 ) );
|
icon.frame( icon.texture.uvRectBySize( 176, 48, 16, 16 ) );
|
||||||
break;
|
break;
|
||||||
|
case COPY:
|
||||||
|
icon.frame( icon.texture.uvRectBySize( 192, 48, 13, 13 ) );
|
||||||
|
break;
|
||||||
|
case PASTE:
|
||||||
|
icon.frame( icon.texture.uvRectBySize( 208, 48, 13, 13 ) );
|
||||||
|
break;
|
||||||
case COIN_SML:
|
case COIN_SML:
|
||||||
icon.frame( icon.texture.uvRectBySize( 192, 48, 7, 7 ) );
|
icon.frame( icon.texture.uvRectBySize( 192, 64, 7, 7 ) );
|
||||||
break;
|
break;
|
||||||
case ENERGY_SML:
|
case ENERGY_SML:
|
||||||
icon.frame( icon.texture.uvRectBySize( 192, 56, 8, 7 ) );
|
icon.frame( icon.texture.uvRectBySize( 192, 72, 8, 7 ) );
|
||||||
break;
|
break;
|
||||||
case BACKPACK:
|
case BACKPACK:
|
||||||
icon.frame( icon.texture.uvRectBySize( 201, 48, 10, 10 ) );
|
icon.frame( icon.texture.uvRectBySize( 201, 64, 10, 10 ) );
|
||||||
break;
|
break;
|
||||||
case SCROLL_HOLDER:
|
case SCROLL_HOLDER:
|
||||||
icon.frame( icon.texture.uvRectBySize( 211, 48, 10, 10 ) );
|
icon.frame( icon.texture.uvRectBySize( 211, 64, 10, 10 ) );
|
||||||
break;
|
break;
|
||||||
case SEED_POUCH:
|
case SEED_POUCH:
|
||||||
icon.frame( icon.texture.uvRectBySize( 221, 48, 10, 10 ) );
|
icon.frame( icon.texture.uvRectBySize( 221, 64, 10, 10 ) );
|
||||||
break;
|
break;
|
||||||
case WAND_HOLSTER:
|
case WAND_HOLSTER:
|
||||||
icon.frame( icon.texture.uvRectBySize( 231, 48, 10, 10 ) );
|
icon.frame( icon.texture.uvRectBySize( 231, 64, 10, 10 ) );
|
||||||
break;
|
break;
|
||||||
case POTION_BANDOLIER:
|
case POTION_BANDOLIER:
|
||||||
icon.frame( icon.texture.uvRectBySize( 241, 48, 10, 10 ) );
|
icon.frame( icon.texture.uvRectBySize( 241, 64, 10, 10 ) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TARGET:
|
case TARGET:
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ public class StyledButton extends Button {
|
|||||||
public void enable( boolean value ) {
|
public void enable( boolean value ) {
|
||||||
active = value;
|
active = value;
|
||||||
text.alpha( value ? 1.0f : 0.3f );
|
text.alpha( value ? 1.0f : 0.3f );
|
||||||
|
if (icon != null) icon.alpha( value ? 1.0f : 0.3f );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void text( String value ) {
|
public void text( String value ) {
|
||||||
|
|||||||
@@ -21,23 +21,29 @@
|
|||||||
|
|
||||||
package com.shatteredpixel.shatteredpixeldungeon.windows;
|
package com.shatteredpixel.shatteredpixeldungeon.windows;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Chrome;
|
import com.shatteredpixel.shatteredpixeldungeon.Chrome;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
|
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
|
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
|
||||||
|
import com.watabou.input.PointerEvent;
|
||||||
import com.watabou.noosa.TextInput;
|
import com.watabou.noosa.TextInput;
|
||||||
import com.watabou.utils.DeviceCompat;
|
import com.watabou.utils.DeviceCompat;
|
||||||
|
|
||||||
public class WndTextInput extends Window {
|
public class WndTextInput extends Window {
|
||||||
|
|
||||||
private static final int WIDTH = 130;
|
private static final int WIDTH = 135;
|
||||||
private static final int W_LAND_EXTRA = 200; //extra width is sometimes used in landscape
|
private static final int W_LAND_EXTRA = 220; //extra width is sometimes used in landscape
|
||||||
private static final int MARGIN = 2;
|
private static final int MARGIN = 1;
|
||||||
private static final int BUTTON_HEIGHT = 16;
|
private static final int BUTTON_HEIGHT = 16;
|
||||||
|
|
||||||
protected TextInput textBox;
|
protected TextInput textBox;
|
||||||
|
|
||||||
|
protected RedButton btnCopy;
|
||||||
|
protected RedButton btnPaste;
|
||||||
|
|
||||||
public WndTextInput(final String title, final String body, final String initialValue, final int maxLength,
|
public WndTextInput(final String title, final String body, final String initialValue, final int maxLength,
|
||||||
final boolean multiLine, final String posTxt, final String negTxt) {
|
final boolean multiLine, final String posTxt, final String negTxt) {
|
||||||
super();
|
super();
|
||||||
@@ -67,7 +73,7 @@ public class WndTextInput extends Window {
|
|||||||
txtTitle.setPos((width - txtTitle.width()) / 2, 2);
|
txtTitle.setPos((width - txtTitle.width()) / 2, 2);
|
||||||
add(txtTitle);
|
add(txtTitle);
|
||||||
|
|
||||||
pos = txtTitle.bottom() + 2 * MARGIN;
|
pos = txtTitle.bottom() + 4 * MARGIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
@@ -98,8 +104,59 @@ public class WndTextInput extends Window {
|
|||||||
} else {
|
} else {
|
||||||
inputHeight = 16;
|
inputHeight = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float textBoxWidth = width-3*MARGIN-BUTTON_HEIGHT;
|
||||||
|
|
||||||
add(textBox);
|
add(textBox);
|
||||||
textBox.setRect(MARGIN, pos, width-2*MARGIN, inputHeight);
|
textBox.setRect(MARGIN, pos, textBoxWidth, inputHeight);
|
||||||
|
|
||||||
|
btnCopy = new RedButton(""){
|
||||||
|
@Override
|
||||||
|
protected void onPointerDown() {
|
||||||
|
super.onPointerDown();
|
||||||
|
PointerEvent.clearKeyboardThisPress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPointerUp() {
|
||||||
|
super.onPointerUp();
|
||||||
|
PointerEvent.clearKeyboardThisPress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onClick() {
|
||||||
|
super.onClick();
|
||||||
|
textBox.copyToClipboard();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
btnCopy.icon(Icons.COPY.get());
|
||||||
|
add(btnCopy);
|
||||||
|
|
||||||
|
btnPaste = new RedButton(""){
|
||||||
|
@Override
|
||||||
|
protected void onPointerDown() {
|
||||||
|
super.onPointerDown();
|
||||||
|
PointerEvent.clearKeyboardThisPress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPointerUp() {
|
||||||
|
super.onPointerUp();
|
||||||
|
PointerEvent.clearKeyboardThisPress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onClick() {
|
||||||
|
super.onClick();
|
||||||
|
textBox.pasteFromClipboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
btnPaste.icon(Icons.PASTE.get());
|
||||||
|
add(btnPaste);
|
||||||
|
|
||||||
|
btnCopy.setRect(textBoxWidth + 2*MARGIN, pos, BUTTON_HEIGHT, BUTTON_HEIGHT);
|
||||||
|
btnPaste.setRect(textBoxWidth + 2*MARGIN, btnCopy.bottom()+MARGIN, BUTTON_HEIGHT, BUTTON_HEIGHT);
|
||||||
|
|
||||||
pos += inputHeight + MARGIN;
|
pos += inputHeight + MARGIN;
|
||||||
|
|
||||||
@@ -124,23 +181,33 @@ public class WndTextInput extends Window {
|
|||||||
negativeBtn = null;
|
negativeBtn = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float btnWidth = multiLine ? width-2*MARGIN : textBoxWidth;
|
||||||
if (negTxt != null) {
|
if (negTxt != null) {
|
||||||
positiveBtn.setRect(MARGIN, pos, (width - MARGIN * 3) / 2, BUTTON_HEIGHT);
|
positiveBtn.setRect(MARGIN, pos, (btnWidth - MARGIN) / 2, BUTTON_HEIGHT);
|
||||||
add(positiveBtn);
|
add(positiveBtn);
|
||||||
negativeBtn.setRect(positiveBtn.right() + MARGIN, pos, (width - MARGIN * 3) / 2, BUTTON_HEIGHT);
|
negativeBtn.setRect(positiveBtn.right() + MARGIN, pos, (btnWidth - MARGIN) / 2, BUTTON_HEIGHT);
|
||||||
add(negativeBtn);
|
add(negativeBtn);
|
||||||
} else {
|
} else {
|
||||||
positiveBtn.setRect(MARGIN, pos, width - MARGIN * 2, BUTTON_HEIGHT);
|
positiveBtn.setRect(MARGIN, pos, btnWidth, BUTTON_HEIGHT);
|
||||||
add(positiveBtn);
|
add(positiveBtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += BUTTON_HEIGHT + MARGIN;
|
pos += BUTTON_HEIGHT;
|
||||||
|
|
||||||
//need to resize first before laying out the text box, as it depends on the window's camera
|
//need to resize first before laying out the text box, as it depends on the window's camera
|
||||||
resize(width, (int) pos);
|
resize(width, (int) pos);
|
||||||
|
|
||||||
textBox.setRect(MARGIN, textBox.top(), width-2*MARGIN, inputHeight);
|
textBox.setRect(MARGIN, textBox.top(), textBoxWidth, inputHeight);
|
||||||
|
|
||||||
|
PointerEvent.clearKeyboardThisPress = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void update() {
|
||||||
|
super.update();
|
||||||
|
btnCopy.enable(!textBox.getText().isEmpty());
|
||||||
|
btnPaste.enable(Gdx.app.getClipboard().hasContents());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user