diff --git a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java index 5e0ed902e7..ea4e8a9460 100644 --- a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java +++ b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java @@ -2,99 +2,93 @@ package org.cocos2dx.lib; import android.content.Context; import android.opengl.GLSurfaceView; -import android.os.Build.VERSION; +import android.os.Handler; +import android.os.Message; +import android.text.Editable; +import android.text.TextWatcher; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.inputmethod.BaseInputConnection; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; -class Cocos2dxInputConnection extends BaseInputConnection { - - private static final boolean mDebug = false; - void LogD(String msg) { - if (mDebug) { - Log.d("Cocos2dxInputConnection", msg); - } +class TextInputWraper implements TextWatcher, OnEditorActionListener { + + private static final Boolean debug = false; + private void LogD(String msg) { + if (debug) Log.d("TextInputFilter", msg); } - private Cocos2dxGLSurfaceView mView; - private String mLastCommit; - - Cocos2dxInputConnection(Cocos2dxGLSurfaceView view) { - super(view, false); - mView = view; - mLastCommit = ""; - LogD("SDK Version(" + VERSION.SDK_INT + "):\n " - + "Release: " + VERSION.RELEASE + "\n " - + "Incremental: " + VERSION.INCREMENTAL + "\n " - + "CodeName: " + VERSION.CODENAME); - } + private Cocos2dxGLSurfaceView mMainView; + private String mText; + private String mOriginText; + + private Boolean isFullScreenEdit() { + InputMethodManager imm = (InputMethodManager)mMainView.getTextField().getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + return imm.isFullscreenMode(); + } + public TextInputWraper(Cocos2dxGLSurfaceView view) { + mMainView = view; + } + + public void setOriginText(String text) { + mOriginText = text; + } + @Override - public boolean commitText(CharSequence text, int newCursorPosition) { - super.commitText(text, newCursorPosition); - if (null != mView) { - final String insertText = text.toString(); - mLastCommit = insertText; - mView.insertText(insertText); - LogD("commitText: " + insertText); + public void afterTextChanged(Editable s) { + if (isFullScreenEdit()) { + return; } - return true; - } - - @Override - public ExtractedText getExtractedText(ExtractedTextRequest request, - int flags) { - LogD("getExtractedText: " + request.toString() + "," + flags); - return new ExtractedText(); - } - - @Override - public boolean performEditorAction(int editorAction) { - LogD("performEditorAction: " + editorAction); - if (null != mView) { - final String insertText = "\n"; - mLastCommit = insertText; - mView.insertText(insertText); + + LogD("afterTextChanged: " + s); + int nModified = s.length() - mText.length(); + if (nModified > 0) { + final String insertText = s.subSequence(mText.length(), s.length()).toString(); + mMainView.insertText(insertText); + LogD("insertText(" + insertText + ")"); } - return true; - } - - @Override - public boolean sendKeyEvent(KeyEvent event) { - LogD("sendKeyEvent: " + event.toString()); - super.sendKeyEvent(event); - if (null != mView) { - switch (event.getKeyCode()) { - - case KeyEvent.KEYCODE_DEL: - if (KeyEvent.ACTION_UP == event.getAction()) { - mView.deleteBackward(); - } - break; + else { + for (; nModified < 0; ++nModified) { + mMainView.deleteBackward(); + LogD("deleteBackward"); } } - return true; + mText = s.toString(); } @Override - public boolean finishComposingText() { - LogD("finishComposingText"); - mLastCommit = ""; - return super.finishComposingText(); + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + LogD("beforeTextChanged(" + s + ")start: " + start + ",count: " + count + ",after: " + after); + mText = s.toString(); } + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } @Override - public CharSequence getTextBeforeCursor(int n, int flags) { - LogD("getTextBeforeCursor"); - return mLastCommit; + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (mMainView.getTextField() == v && isFullScreenEdit()) { + // user press the action button, delete all old text and insert new text + for (int i = mOriginText.length(); i > 0; --i) { + mMainView.deleteBackward(); + LogD("deleteBackward"); + } + String text = v.getText().toString(); + if ('\n' != text.charAt(text.length() - 1)) { + text += '\n'; + } + final String insertText = text; + mMainView.insertText(insertText); + LogD("insertText(" + insertText + ")"); + } + return false; } } @@ -104,8 +98,9 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { private static final String TAG = Cocos2dxGLSurfaceView.class.getCanonicalName(); private Cocos2dxRenderer mRenderer; - private final boolean debug = false; - + + private static final boolean debug = false; + /////////////////////////////////////////////////////////////////////////// // for initialize /////////////////////////////////////////////////////////////////////////// @@ -123,6 +118,38 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { mRenderer = new Cocos2dxRenderer(); setFocusableInTouchMode(true); setRenderer(mRenderer); + + textInputWraper = new TextInputWraper(this); + + handler = new Handler(){ + public void handleMessage(Message msg){ + switch(msg.what){ + case HANDLER_OPEN_IME_KEYBOARD: + if (null != mTextField && mTextField.requestFocus()) { + mTextField.removeTextChangedListener(textInputWraper); + mTextField.setText(""); + String text = (String)msg.obj; + mTextField.append(text); + textInputWraper.setOriginText(text); + mTextField.addTextChangedListener(textInputWraper); + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(mTextField, 0); + Log.d("GLSurfaceView", "showSoftInput"); + } + break; + + case HANDLER_CLOSE_IME_KEYBOARD: + if (null != mTextField) { + mTextField.removeTextChangedListener(textInputWraper); + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mTextField.getWindowToken(), 0); + Log.d("GLSurfaceView", "HideSoftInput"); + } + break; + } + } + }; + mainView = this; } @@ -151,46 +178,44 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { /////////////////////////////////////////////////////////////////////////// // for text input /////////////////////////////////////////////////////////////////////////// - + private final static int HANDLER_OPEN_IME_KEYBOARD = 2; + private final static int HANDLER_CLOSE_IME_KEYBOARD = 3; + private static Handler handler; + private static TextInputWraper textInputWraper; + private TextView mTextField; + + public TextView getTextField() { + return mTextField; + } + + public void setTextField(TextView view) { + mTextField = view; + if (null != mTextField && null != textInputWraper) { + LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) mTextField.getLayoutParams(); + linearParams.height = 0; + mTextField.setLayoutParams(linearParams); + mTextField.setOnEditorActionListener(textInputWraper); + } + } + public static void openIMEKeyboard() { - if (null == mainView) { - return; - } - InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - if (imm == null) { - return; - } - imm.showSoftInput(mainView, 0); - } - - public static void closeIMEKeyboard() { - if (null == mainView) { - return; - } - InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - if (imm == null) { - return; - } - imm.hideSoftInputFromWindow(mainView.getWindowToken(), 0); - } - - private Cocos2dxInputConnection ic; - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT; - outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI; - outAttrs.initialSelStart = -1; - outAttrs.initialSelEnd = -1; - outAttrs.initialCapsMode = 1; - - if (null == ic) - { - ic = new Cocos2dxInputConnection(this); - } + Message msg = new Message(); + msg.what = HANDLER_OPEN_IME_KEYBOARD; + msg.obj = mainView.getContentText(); + handler.sendMessage(msg); - return ic; } + + private String getContentText() { + return mRenderer.getContentText(); + } + public static void closeIMEKeyboard() { + Message msg = new Message(); + msg.what = HANDLER_CLOSE_IME_KEYBOARD; + handler.sendMessage(msg); + } + public void insertText(final String text) { queueEvent(new Runnable() { @Override diff --git a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java index d56651c6f4..95139b4dc6 100644 --- a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java +++ b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java @@ -96,7 +96,12 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer { public void handleDeleteBackward() { nativeDeleteBackward(); } - + + public String getContentText() { + return nativeGetContentText(); + } + private static native void nativeInsertText(String text); private static native void nativeDeleteBackward(); + private static native String nativeGetContentText(); } diff --git a/cocos2dx/base_nodes/CCNode.cpp b/cocos2dx/base_nodes/CCNode.cpp index e9c0d97b28..dae62ef4f5 100644 --- a/cocos2dx/base_nodes/CCNode.cpp +++ b/cocos2dx/base_nodes/CCNode.cpp @@ -110,7 +110,7 @@ void CCNode::arrayMakeObjectsPerformSelector(CCArray* pArray, callbackFunc func) CCARRAY_FOREACH(pArray, child) { CCNode* pNode = (CCNode*) child; - if(pNode && (NULL != func)) + if(pNode && func) { (pNode->*func)(); } @@ -919,7 +919,7 @@ void CCNode::schedule(SEL_SCHEDULE selector) void CCNode::schedule(SEL_SCHEDULE selector, ccTime interval) { - CCAssert( selector != NULL, "Argument must be non-nil"); + CCAssert( selector, "Argument must be non-nil"); CCAssert( interval >=0, "Argument must be positive"); CCScheduler::sharedScheduler()->scheduleSelector(selector, this, interval, !m_bIsRunning); diff --git a/cocos2dx/include/CCIMEDelegate.h b/cocos2dx/include/CCIMEDelegate.h index be9ad903d1..b260afb712 100644 --- a/cocos2dx/include/CCIMEDelegate.h +++ b/cocos2dx/include/CCIMEDelegate.h @@ -81,6 +81,11 @@ protected: */ virtual void deleteBackward() {} + /** + @brief Called by CCIMEDispatcher for get text which delegate already has. + */ + virtual const char * getContentText() { return 0; } + ////////////////////////////////////////////////////////////////////////// // keyboard show/hide notification ////////////////////////////////////////////////////////////////////////// diff --git a/cocos2dx/include/CCIMEDispatcher.h b/cocos2dx/include/CCIMEDispatcher.h index 515c02677a..6560787b60 100644 --- a/cocos2dx/include/CCIMEDispatcher.h +++ b/cocos2dx/include/CCIMEDispatcher.h @@ -57,6 +57,11 @@ public: */ void dispatchDeleteBackward(); + /** + @brief get the content text, which current CCIMEDelegate which attached with IME has. + */ + const char * getContentText(); + ////////////////////////////////////////////////////////////////////////// // dispatch keyboard notification ////////////////////////////////////////////////////////////////////////// diff --git a/cocos2dx/include/CCTextFieldTTF.h b/cocos2dx/include/CCTextFieldTTF.h index 6641a59aae..26ba54ea0d 100644 --- a/cocos2dx/include/CCTextFieldTTF.h +++ b/cocos2dx/include/CCTextFieldTTF.h @@ -141,7 +141,7 @@ protected: virtual bool canDetachWithIME(); virtual void insertText(const char * text, int len); virtual void deleteBackward(); - + virtual const char * getContentText(); private: class LengthStack; LengthStack * m_pLens; diff --git a/cocos2dx/platform/android/Cocos2dJni.cpp b/cocos2dx/platform/android/Cocos2dJni.cpp index 1d776e6580..32c6b60bf6 100644 --- a/cocos2dx/platform/android/Cocos2dJni.cpp +++ b/cocos2dx/platform/android/Cocos2dJni.cpp @@ -376,6 +376,18 @@ extern "C" cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); } + jstring Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeGetContentText() + { + JNIEnv * env = 0; + + if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK || ! env) + { + return 0; + } + const char * pszText = cocos2d::CCIMEDispatcher::sharedDispatcher()->getContentText(); + return env->NewStringUTF(pszText); + } + ////////////////////////////////////////////////////////////////////////// // get package name ////////////////////////////////////////////////////////////////////////// diff --git a/cocos2dx/text_input_node/CCIMEDispatcher.cpp b/cocos2dx/text_input_node/CCIMEDispatcher.cpp index 3fc914f636..9535e59895 100644 --- a/cocos2dx/text_input_node/CCIMEDispatcher.cpp +++ b/cocos2dx/text_input_node/CCIMEDispatcher.cpp @@ -239,6 +239,16 @@ void CCIMEDispatcher::dispatchDeleteBackward() } while (0); } +const char * CCIMEDispatcher::getContentText() +{ + const char * pszContentText = 0; + if (m_pImpl && m_pImpl->m_DelegateWithIme) + { + pszContentText = m_pImpl->m_DelegateWithIme->getContentText(); + } + return (pszContentText) ? pszContentText : ""; +} + ////////////////////////////////////////////////////////////////////////// // dispatch keyboard message ////////////////////////////////////////////////////////////////////////// diff --git a/cocos2dx/text_input_node/CCTextFieldTTF.cpp b/cocos2dx/text_input_node/CCTextFieldTTF.cpp index b6b6236107..b419aa9383 100644 --- a/cocos2dx/text_input_node/CCTextFieldTTF.cpp +++ b/cocos2dx/text_input_node/CCTextFieldTTF.cpp @@ -246,6 +246,11 @@ void CCTextFieldTTF::deleteBackward() setString(sText.c_str()); } +const char * CCTextFieldTTF::getContentText() +{ + return m_pInputText->c_str(); +} + void CCTextFieldTTF::draw() { if (m_pDelegate && m_pDelegate->onDraw(this)) diff --git a/tests/test.android/gen/org/cocos2dx/tests/R.java b/tests/test.android/gen/org/cocos2dx/tests/R.java index ddffad4950..f73cf6f8cd 100644 --- a/tests/test.android/gen/org/cocos2dx/tests/R.java +++ b/tests/test.android/gen/org/cocos2dx/tests/R.java @@ -11,7 +11,8 @@ public final class R { public static final class attr { } public static final class id { - public static final int test_demo_gl_surfaceview=0x7f040000; + public static final int test_demo_gl_surfaceview=0x7f040001; + public static final int textField=0x7f040000; } public static final class layout { public static final int test_demo=0x7f020000; diff --git a/tests/test.android/res/layout/test_demo.xml b/tests/test.android/res/layout/test_demo.xml index 79d33d88fb..5ad6e29b46 100644 --- a/tests/test.android/res/layout/test_demo.xml +++ b/tests/test.android/res/layout/test_demo.xml @@ -2,7 +2,8 @@ + android:orientation="vertical" android:layout_gravity="bottom"> + 0) { + final String insertText = s.subSequence(mText.length(), s.length()).toString(); + mMainView.insertText(insertText); + LogD("insertText(" + insertText + ")"); } - return true; - } - - @Override - public boolean sendKeyEvent(KeyEvent event) { - LogD("sendKeyEvent: " + event.toString()); - super.sendKeyEvent(event); - if (null != mView) { - switch (event.getKeyCode()) { - - case KeyEvent.KEYCODE_DEL: - if (KeyEvent.ACTION_UP == event.getAction()) { - mView.deleteBackward(); - } - break; + else { + for (; nModified < 0; ++nModified) { + mMainView.deleteBackward(); + LogD("deleteBackward"); } } - return true; + mText = s.toString(); } @Override - public boolean finishComposingText() { - LogD("finishComposingText"); - mLastCommit = ""; - return super.finishComposingText(); + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + LogD("beforeTextChanged(" + s + ")start: " + start + ",count: " + count + ",after: " + after); + mText = s.toString(); } + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } @Override - public CharSequence getTextBeforeCursor(int n, int flags) { - LogD("getTextBeforeCursor"); - return mLastCommit; + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (mMainView.getTextField() == v && isFullScreenEdit()) { + // user press the action button, delete all old text and insert new text + for (int i = mOriginText.length(); i > 0; --i) { + mMainView.deleteBackward(); + LogD("deleteBackward"); + } + String text = v.getText().toString(); + if ('\n' != text.charAt(text.length() - 1)) { + text += '\n'; + } + final String insertText = text; + mMainView.insertText(insertText); + LogD("insertText(" + insertText + ")"); + } + return false; } } @@ -104,8 +98,9 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { private static final String TAG = Cocos2dxGLSurfaceView.class.getCanonicalName(); private Cocos2dxRenderer mRenderer; - private final boolean debug = false; - + + private static final boolean debug = false; + /////////////////////////////////////////////////////////////////////////// // for initialize /////////////////////////////////////////////////////////////////////////// @@ -123,6 +118,38 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { mRenderer = new Cocos2dxRenderer(); setFocusableInTouchMode(true); setRenderer(mRenderer); + + textInputWraper = new TextInputWraper(this); + + handler = new Handler(){ + public void handleMessage(Message msg){ + switch(msg.what){ + case HANDLER_OPEN_IME_KEYBOARD: + if (null != mTextField && mTextField.requestFocus()) { + mTextField.removeTextChangedListener(textInputWraper); + mTextField.setText(""); + String text = (String)msg.obj; + mTextField.append(text); + textInputWraper.setOriginText(text); + mTextField.addTextChangedListener(textInputWraper); + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(mTextField, 0); + Log.d("GLSurfaceView", "showSoftInput"); + } + break; + + case HANDLER_CLOSE_IME_KEYBOARD: + if (null != mTextField) { + mTextField.removeTextChangedListener(textInputWraper); + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mTextField.getWindowToken(), 0); + Log.d("GLSurfaceView", "HideSoftInput"); + } + break; + } + } + }; + mainView = this; } @@ -151,46 +178,44 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { /////////////////////////////////////////////////////////////////////////// // for text input /////////////////////////////////////////////////////////////////////////// - + private final static int HANDLER_OPEN_IME_KEYBOARD = 2; + private final static int HANDLER_CLOSE_IME_KEYBOARD = 3; + private static Handler handler; + private static TextInputWraper textInputWraper; + private TextView mTextField; + + public TextView getTextField() { + return mTextField; + } + + public void setTextField(TextView view) { + mTextField = view; + if (null != mTextField && null != textInputWraper) { + LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) mTextField.getLayoutParams(); + linearParams.height = 0; + mTextField.setLayoutParams(linearParams); + mTextField.setOnEditorActionListener(textInputWraper); + } + } + public static void openIMEKeyboard() { - if (null == mainView) { - return; - } - InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - if (imm == null) { - return; - } - imm.showSoftInput(mainView, 0); - } - - public static void closeIMEKeyboard() { - if (null == mainView) { - return; - } - InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - if (imm == null) { - return; - } - imm.hideSoftInputFromWindow(mainView.getWindowToken(), 0); - } - - private Cocos2dxInputConnection ic; - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT; - outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI; - outAttrs.initialSelStart = -1; - outAttrs.initialSelEnd = -1; - outAttrs.initialCapsMode = 1; - - if (null == ic) - { - ic = new Cocos2dxInputConnection(this); - } + Message msg = new Message(); + msg.what = HANDLER_OPEN_IME_KEYBOARD; + msg.obj = mainView.getContentText(); + handler.sendMessage(msg); - return ic; } + + private String getContentText() { + return mRenderer.getContentText(); + } + public static void closeIMEKeyboard() { + Message msg = new Message(); + msg.what = HANDLER_CLOSE_IME_KEYBOARD; + handler.sendMessage(msg); + } + public void insertText(final String text) { queueEvent(new Runnable() { @Override diff --git a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java index d56651c6f4..95139b4dc6 100644 --- a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java +++ b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java @@ -96,7 +96,12 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer { public void handleDeleteBackward() { nativeDeleteBackward(); } - + + public String getContentText() { + return nativeGetContentText(); + } + private static native void nativeInsertText(String text); private static native void nativeDeleteBackward(); + private static native String nativeGetContentText(); } diff --git a/tests/test.android/src/org/cocos2dx/tests/TestsDemo.java b/tests/test.android/src/org/cocos2dx/tests/TestsDemo.java index 3c5095f70a..9adf8f5485 100644 --- a/tests/test.android/src/org/cocos2dx/tests/TestsDemo.java +++ b/tests/test.android/src/org/cocos2dx/tests/TestsDemo.java @@ -4,10 +4,11 @@ import org.cocos2dx.lib.Cocos2dxActivity; import org.cocos2dx.lib.Cocos2dxGLSurfaceView; import android.os.Bundle; +import android.widget.EditText; public class TestsDemo extends Cocos2dxActivity{ private Cocos2dxGLSurfaceView mGLView; - + protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); @@ -17,7 +18,8 @@ public class TestsDemo extends Cocos2dxActivity{ setContentView(R.layout.test_demo); mGLView = (Cocos2dxGLSurfaceView) findViewById(R.id.test_demo_gl_surfaceview); - + mGLView.setTextField((EditText)findViewById(R.id.textField)); + // Get the size of the mGLView after the layout happens mGLView.post(new Runnable() {