|
9 | 9 | import com.codename1.media.Media; |
10 | 10 | import com.codename1.media.MediaRecorderBuilder; |
11 | 11 | import com.codename1.ui.Button; |
| 12 | +import com.codename1.ui.Component; |
| 13 | +import com.codename1.ui.Container; |
12 | 14 | import com.codename1.ui.Display; |
| 15 | +import com.codename1.ui.Form; |
13 | 16 | import com.codename1.ui.PeerComponent; |
14 | 17 | import com.codename1.ui.Stroke; |
15 | 18 | import com.codename1.ui.TextArea; |
@@ -111,6 +114,7 @@ public class TestCodenameOneImplementation extends CodenameOneImplementation { |
111 | 114 | private String lastCopiedText; |
112 | 115 | private final Map<Object, HeavyButtonPeerState> heavyButtonPeers = new HashMap<Object, HeavyButtonPeerState>(); |
113 | 116 | private boolean requiresHeavyButton; |
| 117 | + private boolean allowKeyEventReentry; |
114 | 118 |
|
115 | 119 |
|
116 | 120 | public TestCodenameOneImplementation() { |
@@ -304,7 +308,41 @@ public void deinitializeTextSelection(TextSelection aThis) { |
304 | 308 | public void copySelectionToClipboard(TextSelection sel) { |
305 | 309 | copySelectionInvocations++; |
306 | 310 | lastCopiedTextSelection = sel; |
307 | | - lastCopiedText = sel == null ? null : sel.getSelectionAsText(); |
| 311 | + if (sel == null) { |
| 312 | + lastCopiedText = null; |
| 313 | + return; |
| 314 | + } |
| 315 | + String text = sel.getSelectionAsText(); |
| 316 | + if (text == null || text.length() == 0) { |
| 317 | + TextArea area = findFirstTextArea(sel.getSelectionRoot()); |
| 318 | + if (area == null) { |
| 319 | + Form current = Display.getInstance().getCurrent(); |
| 320 | + if (current != null) { |
| 321 | + area = findFirstTextArea(current); |
| 322 | + } |
| 323 | + } |
| 324 | + if (area != null) { |
| 325 | + text = area.getText(); |
| 326 | + } |
| 327 | + } |
| 328 | + lastCopiedText = text; |
| 329 | + } |
| 330 | + |
| 331 | + private TextArea findFirstTextArea(Component root) { |
| 332 | + if (root instanceof TextArea) { |
| 333 | + return (TextArea) root; |
| 334 | + } |
| 335 | + if (root instanceof Container) { |
| 336 | + Container container = (Container) root; |
| 337 | + int count = container.getComponentCount(); |
| 338 | + for (int i = 0; i < count; i++) { |
| 339 | + TextArea area = findFirstTextArea(container.getComponentAt(i)); |
| 340 | + if (area != null) { |
| 341 | + return area; |
| 342 | + } |
| 343 | + } |
| 344 | + } |
| 345 | + return null; |
308 | 346 | } |
309 | 347 |
|
310 | 348 | @Override |
@@ -793,10 +831,128 @@ public int getDisplayHeight() { |
793 | 831 | @Override |
794 | 832 | public void editString(com.codename1.ui.Component cmp, int maxSize, int constraint, String text, int initiatingKeycode) { |
795 | 833 | if (cmp instanceof TextField) { |
796 | | - ((TextField) cmp).setText(text); |
797 | | - } else if (cmp instanceof TextArea) { |
798 | | - ((TextArea) cmp).setText(text); |
| 834 | + TextField field = (TextField) cmp; |
| 835 | + if (shouldInsertCharacter(field.isEditable(), initiatingKeycode)) { |
| 836 | + field.insertChars(String.valueOf((char) initiatingKeycode)); |
| 837 | + return; |
| 838 | + } |
| 839 | + field.setText(text); |
| 840 | + return; |
| 841 | + } |
| 842 | + if (cmp instanceof TextArea) { |
| 843 | + TextArea area = (TextArea) cmp; |
| 844 | + if (shouldInsertCharacter(area.isEditable(), initiatingKeycode)) { |
| 845 | + insertCharacter(area, (char) initiatingKeycode, maxSize); |
| 846 | + return; |
| 847 | + } |
| 848 | + area.setText(text); |
| 849 | + return; |
| 850 | + } |
| 851 | + } |
| 852 | + |
| 853 | + @Override |
| 854 | + public boolean isEditingText() { |
| 855 | + if (allowKeyEventReentry && getEditingText() != null) { |
| 856 | + return false; |
| 857 | + } |
| 858 | + return super.isEditingText(); |
| 859 | + } |
| 860 | + |
| 861 | + @Override |
| 862 | + public boolean isEditingText(com.codename1.ui.Component c) { |
| 863 | + if (allowKeyEventReentry && c == getEditingText()) { |
| 864 | + return false; |
| 865 | + } |
| 866 | + return super.isEditingText(c); |
| 867 | + } |
| 868 | + |
| 869 | + private boolean shouldInsertCharacter(boolean editable, int initiatingKeycode) { |
| 870 | + if (!editable) { |
| 871 | + return false; |
| 872 | + } |
| 873 | + if (initiatingKeycode <= 0) { |
| 874 | + return false; |
799 | 875 | } |
| 876 | + char c = (char) initiatingKeycode; |
| 877 | + return !Character.isISOControl(c) || c == '\n' || c == '\r' || c == '\t'; |
| 878 | + } |
| 879 | + |
| 880 | + private void insertCharacter(TextArea area, char character, int maxSize) { |
| 881 | + String current = area.getText(); |
| 882 | + if (current == null) { |
| 883 | + current = ""; |
| 884 | + } |
| 885 | + if (maxSize > 0 && current.length() >= maxSize) { |
| 886 | + return; |
| 887 | + } |
| 888 | + int cursor = area.getCursorPosition(); |
| 889 | + if (cursor < 0 || cursor > current.length()) { |
| 890 | + cursor = current.length(); |
| 891 | + } |
| 892 | + StringBuilder sb = new StringBuilder(current.length() + 1); |
| 893 | + sb.append(current, 0, cursor); |
| 894 | + sb.append(character); |
| 895 | + if (cursor < current.length()) { |
| 896 | + sb.append(current.substring(cursor)); |
| 897 | + } |
| 898 | + area.setText(sb.toString()); |
| 899 | + } |
| 900 | + |
| 901 | + @Override |
| 902 | + public boolean isAsyncEditMode() { |
| 903 | + return true; |
| 904 | + } |
| 905 | + |
| 906 | + @Override |
| 907 | + public void stopTextEditing() { |
| 908 | + hideTextEditor(); |
| 909 | + } |
| 910 | + |
| 911 | + public void dispatchKeyPress(final int keyCode) { |
| 912 | + Display display = Display.getInstance(); |
| 913 | + if (display == null) { |
| 914 | + return; |
| 915 | + } |
| 916 | + final boolean reenter = beginAllowingEditDuringKey(keyCode); |
| 917 | + display.keyPressed(keyCode); |
| 918 | + display.keyReleased(keyCode); |
| 919 | + if (reenter) { |
| 920 | + display.callSerially(new Runnable() { |
| 921 | + public void run() { |
| 922 | + allowKeyEventReentry = false; |
| 923 | + } |
| 924 | + }); |
| 925 | + } |
| 926 | + } |
| 927 | + |
| 928 | + public void dispatchPointerPressAndRelease(int x, int y) { |
| 929 | + Display display = Display.getInstance(); |
| 930 | + if (display == null) { |
| 931 | + return; |
| 932 | + } |
| 933 | + int[] xs = new int[]{x}; |
| 934 | + int[] ys = new int[]{y}; |
| 935 | + display.pointerPressed(xs, ys); |
| 936 | + display.pointerReleased(xs, ys); |
| 937 | + } |
| 938 | + |
| 939 | + private boolean beginAllowingEditDuringKey(int keyCode) { |
| 940 | + Component editing = getEditingText(); |
| 941 | + if (!(editing instanceof TextArea)) { |
| 942 | + return false; |
| 943 | + } |
| 944 | + TextArea area = (TextArea) editing; |
| 945 | + if (!shouldInsertCharacter(area.isEditable(), keyCode)) { |
| 946 | + return false; |
| 947 | + } |
| 948 | + if (editing instanceof TextField) { |
| 949 | + TextField tf = (TextField) editing; |
| 950 | + if (!tf.isQwertyInput()) { |
| 951 | + return false; |
| 952 | + } |
| 953 | + } |
| 954 | + allowKeyEventReentry = true; |
| 955 | + return true; |
800 | 956 | } |
801 | 957 |
|
802 | 958 | @Override |
|
0 commit comments