use of com.codename1.ui.TextField in project CodenameOne by codenameone.
the class ResetableTextWatcher method edit.
/**
* Entry point for using this class
* @param impl The current running activity
* @param component Any subclass of com.codename1.ui.TextArea
* @param inputType One of the TextArea's input-type constants
*/
public static void edit(final AndroidImplementation impl, final Component component, final int inputType) {
if (impl.getActivity() == null) {
throw new IllegalArgumentException("activity is null");
}
if (component == null) {
throw new IllegalArgumentException("component is null");
}
if (!(component instanceof TextArea)) {
throw new IllegalArgumentException("component must be instance of TextArea");
}
final TextArea textArea = (TextArea) component;
final String initialText = textArea.getText();
textArea.putClientProperty("InPlaceEditView.initialText", initialText);
// The very first time we try to edit a string, let's determine if the
// system default is to do async editing. If the system default
// is not yet set, we set it here, and it will be used as the default from now on
// We do this because the nativeInstance.isAsyncEditMode() value changes
// to reflect the currently edited field so it isn't a good way to keep a
// system default.
String defaultAsyncEditingSetting = Display.getInstance().getProperty("android.VKBAlwaysOpen", null);
if (defaultAsyncEditingSetting == null) {
defaultAsyncEditingSetting = impl.isAsyncEditMode() ? "true" : "false";
Display.getInstance().setProperty("android.VKBAlwaysOpen", defaultAsyncEditingSetting);
}
boolean asyncEdit = "true".equals(defaultAsyncEditingSetting) ? true : false;
// Check if the form has any setting for asyncEditing that should override
// the application defaults.
final Form parentForm = component.getComponentForm();
if (parentForm == null) {
com.codename1.io.Log.p("Attempt to edit text area that is not on a form. This is not supported");
return;
}
if (parentForm.getClientProperty("asyncEditing") != null) {
Object async = parentForm.getClientProperty("asyncEditing");
if (async instanceof Boolean) {
asyncEdit = ((Boolean) async).booleanValue();
// Log.p("Form overriding asyncEdit due to asyncEditing client property: "+asyncEdit);
}
}
if (parentForm.getClientProperty("android.asyncEditing") != null) {
Object async = parentForm.getClientProperty("android.asyncEditing");
if (async instanceof Boolean) {
asyncEdit = ((Boolean) async).booleanValue();
// Log.p("Form overriding asyncEdit due to ios.asyncEditing client property: "+asyncEdit);
}
}
if (parentForm.isFormBottomPaddingEditingMode()) {
asyncEdit = true;
}
// then this will override all other settings.
if (component.getClientProperty("asyncEditing") != null) {
Object async = component.getClientProperty("asyncEditing");
if (async instanceof Boolean) {
asyncEdit = ((Boolean) async).booleanValue();
// Log.p("Overriding asyncEdit due to field asyncEditing client property: "+asyncEdit);
}
}
if (component.getClientProperty("android.asyncEditing") != null) {
Object async = component.getClientProperty("android.asyncEditing");
if (async instanceof Boolean) {
asyncEdit = ((Boolean) async).booleanValue();
// Log.p("Overriding asyncEdit due to field ios.asyncEditing client property: "+asyncEdit);
}
}
// if true, then in async mode we are currently editing and are switching to another field
final boolean isEditedFieldSwitch;
// If we are already editing, we need to finish that up before we proceed to edit the next field.
synchronized (editingLock) {
if (mIsEditing) {
if (impl.isAsyncEditMode()) {
// Using isEditedFieldSwitch was causing issues with cursors not showing up.
// https://github.com/codenameone/CodenameOne/issues/2353
// https://stackoverflow.com/questions/49004370/focus-behaviour-in-textarea-in-cn1
// Disabling this feature by default now, but can be re-enabled by setting
// Display.getInstance().setProperty("android.reuseTextEditorOnSwitch", "true");
// This editedFieldSwitch feature was added a while back to improve experience on older
// Android devices where the field switching was going too slow.
// https://github.com/codenameone/CodenameOne/issues/2012
// This issue was resolved in this commit (https://github.com/jaanushansen/CodenameOne/commit/f3e53a80704149e4d7cde276d01c1368bcdcfe2c)
// which was submitted as part of a pull request. This fix has been the source of several
// regressions, mostly related to properties not being propagated properly when a text field is changed
// However, this issue (with the cursor not showing up), doesn't appear to have a simple solution
// so, I'm disabling this feature for now.
isEditedFieldSwitch = "true".equals(Display.getInstance().getProperty("android.reuseTextEditorOnSwitch", "false"));
final String[] out = new String[1];
TextArea prevTextArea = null;
if (sInstance != null && sInstance.mLastEditText != null) {
prevTextArea = sInstance.mLastEditText.getTextArea();
}
if (prevTextArea != null) {
final TextArea fPrevTextArea = prevTextArea;
final String retVal = sInstance.mLastEditText.getText().toString();
Display.getInstance().callSerially(new Runnable() {
public void run() {
Display.getInstance().onEditingComplete(fPrevTextArea, retVal);
}
});
}
InPlaceEditView.setEditedTextField(textArea);
nextTextArea = null;
} else {
isEditedFieldSwitch = false;
final InPlaceEditView instance = sInstance;
if (instance != null && instance.mEditText != null && instance.mEditText.mTextArea == textArea) {
instance.showTextEditorAgain();
return;
}
if (!isClosing && sInstance != null && sInstance.mEditText != null) {
isClosing = true;
impl.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
instance.endEditing(REASON_UNDEFINED, true, 0);
}
});
}
afterClose = new Runnable() {
@Override
public void run() {
impl.callHideTextEditor();
Display.getInstance().editString(component, textArea.getMaxSize(), inputType, textArea.getText());
}
};
return;
}
} else {
isEditedFieldSwitch = false;
}
mIsEditing = true;
isClosing = false;
afterClose = null;
}
impl.setAsyncEditMode(asyncEdit);
// textArea.setPreferredSize(prefSize);
if (!impl.isAsyncEditMode() && textArea instanceof TextField) {
((TextField) textArea).setEditable(false);
}
final boolean scrollableParent = isScrollableParent(textArea);
// We wrap the text area so that we can safely pass data across to the
// android UI thread.
final TextAreaData textAreaData = new TextAreaData(textArea);
impl.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (!isEditedFieldSwitch) {
releaseEdit();
if (sInstance == null) {
sInstance = new InPlaceEditView(impl);
impl.relativeLayout.addView(sInstance);
}
// Let's try something new here
// We'll ALWAYS try resize edit mode (since it just works better)
// But we'll detect whether the field is still covered by the keyboard
// and switch to pan mode if necessary.
}
if (scrollableParent || parentForm.isFormBottomPaddingEditingMode()) {
setEditMode(true);
} else {
trySetEditMode(true);
}
sInstance.startEditing(impl.getActivity(), textAreaData, initialText, inputType, isEditedFieldSwitch);
}
});
final String[] out = new String[1];
// In order to reuse the code the runs after edit completion, we will wrap it in a runnable
// For sync edit mode, we will just run onComplete.run() at the end of this method. For
// Async mode we add the Runnable to the textarea as a client property, then run it
// when editing eventually completes.
Runnable onComplete = new Runnable() {
public void run() {
if (!impl.isAsyncEditMode() && textArea instanceof TextField) {
((TextField) textArea).setEditable(true);
}
textArea.setPreferredSize(null);
if (sInstance != null && sInstance.mLastEditText != null && sInstance.mLastEditText.mTextArea == textArea) {
String retVal = sInstance.mLastEditText.getText().toString();
if (!impl.isAsyncEditMode()) {
sInstance.mLastEditText = null;
impl.getActivity().runOnUiThread(new Runnable() {
public void run() {
releaseEdit();
}
});
}
out[0] = retVal;
} else {
out[0] = initialText;
}
Display.getInstance().onEditingComplete(component, out[0]);
if (impl.isAsyncEditMode()) {
impl.callHideTextEditor();
} else {
// lock.
if (sInstance != null) {
Display.getInstance().invokeAndBlock(new Runnable() {
public void run() {
while (sInstance != null) {
com.codename1.io.Util.sleep(5);
}
}
});
}
}
// Release the editing flag
synchronized (editingLock) {
mIsEditing = false;
}
// as a runnable ... this should take priority over the "nextTextArea" setting
if (afterClose != null) {
Display.getInstance().callSerially(afterClose);
} else if (nextTextArea != null) {
final TextArea next = nextTextArea;
nextTextArea = null;
next.requestFocus();
Display.getInstance().callSerially(new Runnable() {
public void run() {
Display.getInstance().editString(next, next.getMaxSize(), next.getConstraint(), next.getText());
}
});
}
}
};
textArea.requestFocus();
textArea.repaint();
if (impl.isAsyncEditMode()) {
component.putClientProperty("android.onAsyncEditingComplete", onComplete);
return;
}
// Make this call synchronous
// We set this flag so that waitForEditCompletion can block on it.
// The flag will be released inside the endEditing method which will
// allow the method to proceed.
waitingForSynchronousEditingCompletion = true;
waitForEditCompletion();
onComplete.run();
}
use of com.codename1.ui.TextField in project CodenameOne by codenameone.
the class ResetableTextWatcher method hideTextEditor.
/**
* Hides the native text editor while keeping the active async edit session going.
* This will effectively hide the native text editor, and show the light-weight text area
* with cursor still in the correct position.
*/
private void hideTextEditor() {
if (!mIsEditing || textEditorHidden || mEditText == null) {
return;
}
textEditorHidden = true;
final TextArea ta = mEditText.mTextArea;
// Since this may be called off the UI thread, we need to issue async request on UI thread
// to hide the text area.
impl.getActivity().runOnUiThread(new Runnable() {
public void run() {
if (mEditText != null && mEditText.mTextArea == ta) {
// Note: Setting visibility to GONE doesn't work here because the TextWatcher
// will stop receiving input from the keyboard, so we don't have a way to
// reactivate the text editor when the user starts typing again. Using the margin
// to move it off screen keeps the text editor active.
mEditLayoutParams.setMargins(-Display.getInstance().getDisplayWidth(), 0, 0, 0);
InPlaceEditView.this.requestLayout();
final int cursorPos = mEditText.getSelectionStart();
// Since we are going to be displaying the CN1 text area now, we need to update
// the cursor. That needs to happen on the EDT.
Display.getInstance().callSerially(new Runnable() {
public void run() {
if (mEditText != null && mEditText.mTextArea == ta && mIsEditing && textEditorHidden) {
if (ta instanceof TextField) {
((TextField) ta).setCursorPosition(cursorPos);
}
}
}
});
}
}
});
// Repaint the CN1 text area on the EDT. This is necessary because while the native editor
// was shown, the cn1 text area paints only its background. Now that the editor is hidden
// it should paint its foreground also.
Display.getInstance().callSerially(new Runnable() {
public void run() {
if (mEditText != null && mEditText.mTextArea != null) {
mEditText.mTextArea.repaint();
}
}
});
// repaintTextEditor(true);
}
use of com.codename1.ui.TextField in project CodenameOne by codenameone.
the class BooleanContainer method editNextTextArea.
/**
* Opens onscreenkeyboard for the next textfield. The method works in EDT if
* needed.
*/
public static void editNextTextArea() {
Runnable task = new Runnable() {
public void run() {
Component next = getNextEditComponent();
if (next != null) {
if (next instanceof TextArea) {
TextArea text = (TextArea) next;
text.requestFocus();
Display.getInstance().editString(next, text.getMaxSize(), text.getConstraint(), text.getText(), 0);
}
} else {
IOSImplementation.foldKeyboard();
}
}
};
Display.getInstance().callSerially(task);
}
use of com.codename1.ui.TextField in project CodenameOne by codenameone.
the class SignIn method start.
public void start() {
// new SignInFormGB(theme).show();
// if (true) return;
loginForm = new Form("Sign in Demo");
loginForm.setLayout(new BorderLayout());
Container center = new Container(new BoxLayout(BoxLayout.Y_AXIS));
center.setUIID("ContainerWithPadding");
Image logo = theme.getImage("CodenameOne.png");
Label l = new Label(logo);
Container flow = new Container(new FlowLayout(Component.CENTER));
flow.addComponent(l);
center.addComponent(flow);
final TextField username = new TextField();
username.setHint("Username");
final TextField pass = new TextField();
pass.setHint("Password");
pass.setConstraint(TextField.PASSWORD);
center.addComponent(username);
center.addComponent(pass);
Button signIn = new Button("Sign In");
signIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (username.getText().length() == 0 || pass.getText().length() == 0) {
return;
}
UserForm userForm = new UserForm(username.getText(), (EncodedImage) theme.getImage("user.png"), null);
userForm.show();
}
});
center.addComponent(signIn);
loginForm.addComponent(BorderLayout.CENTER, center);
Container bottom = new Container(new BoxLayout(BoxLayout.Y_AXIS));
Button loginWFace = new Button(theme.getImage("signin_facebook.png"));
loginWFace.setUIID("LoginButton");
loginWFace.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// create your own app identity on facebook follow the guide here:
// facebook-login.html
String clientId = "1171134366245722";
String redirectURI = "http://www.codenameone.com/";
String clientSecret = "";
if (clientSecret.length() == 0) {
System.err.println("create your own facebook app follow the guide here:");
System.err.println("http://www.codenameone.com/facebook-login.html");
return;
}
Login fb = FacebookConnect.getInstance();
fb.setClientId(clientId);
fb.setRedirectURI(redirectURI);
fb.setClientSecret(clientSecret);
login = fb;
fb.setCallback(new LoginListener(LoginListener.FACEBOOK));
if (!fb.isUserLoggedIn()) {
fb.doLogin();
} else {
showFacebookUser(fb.getAccessToken().getToken());
}
}
});
Button loginWG = new Button(theme.getImage("signin_google.png"));
loginWG.setUIID("LoginButton");
loginWG.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
SignIn.this.doFirebase();
// create your own google project follow the guide here:
// http://www.codenameone.com/google-login.html
String clientId = "555462747934-iujpd5saj4pjpibo7c6r9tbjfef22rh1.apps.googleusercontent.com";
String redirectURI = "https://www.codenameone.com/oauth2callback";
String clientSecret = "650YqplrnAI0KXb9LMUnVNnx";
if (clientSecret.length() == 0) {
System.err.println("create your own google project follow the guide here:");
System.err.println("http://www.codenameone.com/google-login.html");
return;
}
Login gc = GoogleConnect.getInstance();
gc.setClientId(clientId);
gc.setRedirectURI(redirectURI);
gc.setClientSecret(clientSecret);
gc.setScope("https://www.googleapis.com/auth/plus.profile.emails.read https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file");
login = gc;
gc.setCallback(new LoginListener(LoginListener.GOOGLE));
if (!gc.isUserLoggedIn()) {
gc.doLogin();
} else {
showGoogleUser(gc.getAccessToken().getToken());
}
}
});
bottom.addComponent(loginWFace);
bottom.addComponent(loginWG);
loginForm.addComponent(BorderLayout.SOUTH, bottom);
loginForm.show();
}
use of com.codename1.ui.TextField in project CodenameOne by codenameone.
the class HTMLComponent method handleInput.
/**
* Handles the INPUT tag
*
* @param element The input element
* @param align The current aligment
*/
private void handleInput(HTMLElement element, int align) {
String type = element.getAttributeById(HTMLElement.ATTR_TYPE);
if (type == null) {
return;
}
int typeID = INPUT_TYPES.indexOf(type.toLowerCase());
if (typeID == -1) {
if (htmlCallback != null) {
if (!htmlCallback.parsingError(HTMLCallback.ERROR_ATTIBUTE_VALUE_INVALID, element.getTagName(), element.getAttributeName(new Integer(HTMLElement.ATTR_TYPE)), type, "Unsupported input type '" + type + "'. Supported types: text, password, checkbox, radio, submit, reset, hidden, image")) {
cancel();
}
}
return;
}
String name = element.getAttributeById(HTMLElement.ATTR_NAME);
String id = element.getAttributeById(HTMLElement.ATTR_ID);
String value = element.getAttributeById(HTMLElement.ATTR_VALUE);
if (value == null) {
value = "";
}
Component cmp = null;
switch(typeID) {
case INPUT_CHECKBOX:
CheckBox cb = new CheckBox();
if (element.getAttributeById(HTMLElement.ATTR_CHECKED) != null) {
cb.setSelected(true);
}
cmp = cb;
if (curForm != null) {
curForm.addCheckBox(name, cb, value);
}
break;
case INPUT_HIDDEN:
if (curForm != null) {
curForm.addInput(name, value, null);
}
break;
case INPUT_EMAIL:
case INPUT_TEXT:
case INPUT_PASSWORD:
TextField tf = new TextField(value);
tf.setLeftAndRightEditingTrigger(false);
if (typeID == INPUT_PASSWORD) {
tf.setConstraint(TextField.PASSWORD);
}
if (typeID == INPUT_EMAIL) {
tf.setConstraint(TextField.EMAILADDR);
}
if (SUPPORT_INPUT_FORMAT) {
HTMLInputFormat inputFormat = HTMLInputFormat.getInputFormat(element.getAttributeById(HTMLElement.ATTR_FORMAT));
if (inputFormat != null) {
tf = (TextField) inputFormat.applyConstraints(tf);
if (curForm != null) {
curForm.setInputFormat(tf, inputFormat);
}
}
String emptyOk = element.getAttributeById(HTMLElement.ATTR_EMPTYOK);
if ((emptyOk != null) && (curForm != null)) {
if (emptyOk.equalsIgnoreCase("true")) {
curForm.setEmptyOK(tf, true);
} else if (emptyOk.equalsIgnoreCase("false")) {
curForm.setEmptyOK(tf, false);
}
}
}
int size = getInt(element.getAttributeById(HTMLElement.ATTR_SIZE));
int maxlen = getInt(element.getAttributeById(HTMLElement.ATTR_MAXLENGTH));
if (size == 0) {
size = DEFAULT_TEXTFIELD_SIZE;
}
if (maxlen != 0) {
tf.setMaxSize(maxlen);
if (size > maxlen) {
size = maxlen;
}
}
tf.setPreferredW(tf.getStyle().getFont().stringWidth("W") * size);
tf.getSelectedStyle().setFont(font.getFont());
tf.getUnselectedStyle().setFont(font.getFont());
if ((!PROCESS_HTML_MP1_ONLY) && (element.getAttributeById(HTMLElement.ATTR_READONLY) != null)) {
tf.setEditable(false);
}
cmp = tf;
if (curForm != null) {
curForm.addInput(name, cmp, value);
textfieldsToForms.put(tf, curForm);
}
break;
case INPUT_RADIO:
RadioButton rb = new RadioButton(" ");
if (element.getAttributeById(HTMLElement.ATTR_CHECKED) != null) {
rb.setSelected(true);
}
cmp = rb;
if (curForm != null) {
curForm.addRadioButton(name, rb, value);
}
break;
case INPUT_RESET:
Command resetCmd = null;
if (curForm != null) {
resetCmd = curForm.createResetCommand(value);
}
if (resetCmd == null) {
// dummy command - no form so it won't do anything
resetCmd = new Command(getUIManager().localize("html.reset", HTMLForm.DEFAULT_RESET_TEXT));
}
Button resetButton = new Button(resetCmd);
cmp = resetButton;
break;
case INPUT_BUTTON:
case INPUT_SUBMIT:
Command submitCmd = null;
if (curForm != null) {
submitCmd = curForm.createSubmitCommand(name, value);
}
if (submitCmd == null) {
// dummy command - no form so it won't do anything
submitCmd = new Command(value.equals("") ? value = getUIManager().localize("html.submit", HTMLForm.DEFAULT_SUBMIT_TEXT) : value);
}
Button submitButton = new Button(submitCmd);
cmp = submitButton;
break;
case // Image submit is not officially supported in XHTML-MP 1.0 but was added anyway, but pixel data submission is not supported (i.e. name.x=xx&name.y=yy)
INPUT_IMAGE:
submitCmd = null;
if (curForm != null) {
submitCmd = curForm.createSubmitCommand(name, value);
}
handleImage(element, align, submitCmd);
break;
}
if (cmp != null) {
if ((!PROCESS_HTML_MP1_ONLY) && (element.getAttributeById(HTMLElement.ATTR_DISABLED) != null)) {
cmp.setEnabled(false);
}
String aKey = element.getAttributeById(HTMLElement.ATTR_ACCESSKEY);
if ((aKey != null) && (aKey.length() == 1)) {
// accessKeys.put(new Integer(aKey.charAt(0)), cmp);
addAccessKey(aKey.charAt(0), cmp, false);
}
if (eventsListener != null) {
eventsListener.registerComponent(cmp, element);
}
// Even if CSS is off, we need to associate it for HTMLElement.getCurentValue
element.setAssociatedComponents(cmp);
if ((curForm != null) && (curForm.action == null)) {
// Form that submits to a forbidden link
cmp.setEnabled(false);
} else if (firstFocusable == null) {
firstFocusable = cmp;
}
if (id != null) {
inputFields.put(id, cmp);
}
}
addCmp(cmp, align);
}
Aggregations