From dcc84e4e7e15dd60616668ab253dd11b0b5bffce Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Thu, 11 Aug 2022 16:56:49 -0400 Subject: [PATCH] v1.4.0: implemented a copy and paste button for text input --- .../java/com/watabou/input/InputHandler.java | 1 - .../java/com/watabou/input/PointerEvent.java | 8 ++ .../java/com/watabou/noosa/TextInput.java | 25 +++++ core/src/main/assets/interfaces/icons.png | Bin 14808 -> 14926 bytes .../assets/messages/scenes/scenes.properties | 2 +- .../shatteredpixeldungeon/ui/Icons.java | 22 +++-- .../ui/StyledButton.java | 1 + .../windows/WndTextInput.java | 87 ++++++++++++++++-- 8 files changed, 127 insertions(+), 19 deletions(-) diff --git a/SPD-classes/src/main/java/com/watabou/input/InputHandler.java b/SPD-classes/src/main/java/com/watabou/input/InputHandler.java index bb30580a3..88020a246 100644 --- a/SPD-classes/src/main/java/com/watabou/input/InputHandler.java +++ b/SPD-classes/src/main/java/com/watabou/input/InputHandler.java @@ -93,7 +93,6 @@ public class InputHandler extends InputAdapter { public synchronized boolean touchDown(int screenX, int screenY, int pointer, int button) { ControllerHandler.setControllerPointer(false); ControllerHandler.controllerActive = false; - Gdx.input.setOnscreenKeyboardVisible(false); //in-game events never need keyboard, so hide it if (button >= 3 && KeyBindings.isKeyBound( button + 1000 )) { KeyEvent.addKeyEvent( new KeyEvent( button + 1000, true ) ); diff --git a/SPD-classes/src/main/java/com/watabou/input/PointerEvent.java b/SPD-classes/src/main/java/com/watabou/input/PointerEvent.java index 43f47af63..4e9352cd2 100644 --- a/SPD-classes/src/main/java/com/watabou/input/PointerEvent.java +++ b/SPD-classes/src/main/java/com/watabou/input/PointerEvent.java @@ -21,6 +21,7 @@ package com.watabou.input; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.watabou.noosa.Game; import com.watabou.noosa.ui.Cursor; @@ -138,6 +139,8 @@ public class PointerEvent { pointerEvents.add(event); } } + + public static boolean clearKeyboardThisPress = true; public static synchronized void processPointerEvents(){ //handle any hover events separately first as we may need to add drag events @@ -164,6 +167,7 @@ public class PointerEvent { if (p.type == Type.HOVER){ continue; } + clearKeyboardThisPress = true; if (activePointers.containsKey(p.id)){ PointerEvent existing = activePointers.get(p.id); existing.current = p.current; @@ -181,6 +185,10 @@ public class PointerEvent { } pointerSignal.dispatch(p); } + if (clearKeyboardThisPress){ + //most press events should clear the keyboard + Gdx.input.setOnscreenKeyboardVisible(false); + } } pointerEvents.clear(); } diff --git a/SPD-classes/src/main/java/com/watabou/noosa/TextInput.java b/SPD-classes/src/main/java/com/watabou/noosa/TextInput.java index 84869de7c..b997c6a71 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/TextInput.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/TextInput.java @@ -126,6 +126,31 @@ public class TextInput extends Component { 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 protected void layout() { super.layout(); diff --git a/core/src/main/assets/interfaces/icons.png b/core/src/main/assets/interfaces/icons.png index 2ffc63cf96db973d0c8a1ce327561e87f414da26..3c96d8f9c09944389d7793b3cd9d2e43db2d6811 100644 GIT binary patch literal 14926 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 G5&sA9JmfV1 literal 14808 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 W%ttx1i}}COG)+}ql^P}6i2ny7N~zxf diff --git a/core/src/main/assets/messages/scenes/scenes.properties b/core/src/main/assets/messages/scenes/scenes.properties index c2ba3399b..04ce74eea 100644 --- a/core/src/main/assets/messages/scenes/scenes.properties +++ b/core/src/main/assets/messages/scenes/scenes.properties @@ -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_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_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_set=Set scenes.heroselectscene.custom_seed_clear=Clear diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java index 48eb5ca03..58e86d566 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java @@ -80,6 +80,8 @@ public enum Icons { MAGNIFY, BUFFS, ENERGY, + COPY, + PASTE, COIN_SML, ENERGY_SML, BACKPACK, @@ -259,26 +261,32 @@ public enum Icons { case ENERGY: icon.frame( icon.texture.uvRectBySize( 176, 48, 16, 16 ) ); 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: - icon.frame( icon.texture.uvRectBySize( 192, 48, 7, 7 ) ); + icon.frame( icon.texture.uvRectBySize( 192, 64, 7, 7 ) ); break; case ENERGY_SML: - icon.frame( icon.texture.uvRectBySize( 192, 56, 8, 7 ) ); + icon.frame( icon.texture.uvRectBySize( 192, 72, 8, 7 ) ); break; case BACKPACK: - icon.frame( icon.texture.uvRectBySize( 201, 48, 10, 10 ) ); + icon.frame( icon.texture.uvRectBySize( 201, 64, 10, 10 ) ); break; case SCROLL_HOLDER: - icon.frame( icon.texture.uvRectBySize( 211, 48, 10, 10 ) ); + icon.frame( icon.texture.uvRectBySize( 211, 64, 10, 10 ) ); break; case SEED_POUCH: - icon.frame( icon.texture.uvRectBySize( 221, 48, 10, 10 ) ); + icon.frame( icon.texture.uvRectBySize( 221, 64, 10, 10 ) ); break; case WAND_HOLSTER: - icon.frame( icon.texture.uvRectBySize( 231, 48, 10, 10 ) ); + icon.frame( icon.texture.uvRectBySize( 231, 64, 10, 10 ) ); break; case POTION_BANDOLIER: - icon.frame( icon.texture.uvRectBySize( 241, 48, 10, 10 ) ); + icon.frame( icon.texture.uvRectBySize( 241, 64, 10, 10 ) ); break; case TARGET: diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/StyledButton.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/StyledButton.java index eb9e6d41d..3f3eaecc2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/StyledButton.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/StyledButton.java @@ -113,6 +113,7 @@ public class StyledButton extends Button { public void enable( boolean value ) { active = value; text.alpha( value ? 1.0f : 0.3f ); + if (icon != null) icon.alpha( value ? 1.0f : 0.3f ); } public void text( String value ) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndTextInput.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndTextInput.java index 1fadeaa48..aaabd32d7 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndTextInput.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndTextInput.java @@ -21,23 +21,29 @@ package com.shatteredpixel.shatteredpixeldungeon.windows; +import com.badlogic.gdx.Gdx; import com.shatteredpixel.shatteredpixeldungeon.Chrome; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; +import com.shatteredpixel.shatteredpixeldungeon.ui.Icons; import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton; import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock; import com.shatteredpixel.shatteredpixeldungeon.ui.Window; +import com.watabou.input.PointerEvent; import com.watabou.noosa.TextInput; import com.watabou.utils.DeviceCompat; public class WndTextInput extends Window { - private static final int WIDTH = 130; - private static final int W_LAND_EXTRA = 200; //extra width is sometimes used in landscape - private static final int MARGIN = 2; + private static final int WIDTH = 135; + private static final int W_LAND_EXTRA = 220; //extra width is sometimes used in landscape + private static final int MARGIN = 1; private static final int BUTTON_HEIGHT = 16; protected TextInput textBox; + protected RedButton btnCopy; + protected RedButton btnPaste; + public WndTextInput(final String title, final String body, final String initialValue, final int maxLength, final boolean multiLine, final String posTxt, final String negTxt) { super(); @@ -67,7 +73,7 @@ public class WndTextInput extends Window { txtTitle.setPos((width - txtTitle.width()) / 2, 2); add(txtTitle); - pos = txtTitle.bottom() + 2 * MARGIN; + pos = txtTitle.bottom() + 4 * MARGIN; } if (body != null) { @@ -98,8 +104,59 @@ public class WndTextInput extends Window { } else { inputHeight = 16; } + + float textBoxWidth = width-3*MARGIN-BUTTON_HEIGHT; + 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; @@ -124,23 +181,33 @@ public class WndTextInput extends Window { negativeBtn = null; } + float btnWidth = multiLine ? width-2*MARGIN : textBoxWidth; if (negTxt != null) { - positiveBtn.setRect(MARGIN, pos, (width - MARGIN * 3) / 2, BUTTON_HEIGHT); + positiveBtn.setRect(MARGIN, pos, (btnWidth - MARGIN) / 2, BUTTON_HEIGHT); 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); } else { - positiveBtn.setRect(MARGIN, pos, width - MARGIN * 2, BUTTON_HEIGHT); + positiveBtn.setRect(MARGIN, pos, btnWidth, BUTTON_HEIGHT); 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 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