From d11bd85d0068bf90e132057f51bc7d709294b261 Mon Sep 17 00:00:00 2001 From: yangws Date: Tue, 19 Apr 2011 09:32:33 +0800 Subject: [PATCH 1/5] CCTextFieldTTF works on win32. --- cocos2dx/include/CCIMEDelegate.h | 78 ++++++ cocos2dx/include/CCIMEDispatcher.h | 91 +++++++ cocos2dx/include/CCTextFieldTTF.h | 98 ++++++++ cocos2dx/include/CCTouchDelegateProtocol.h | 2 +- cocos2dx/label_nodes/CCLabelTTF.cpp | 4 +- cocos2dx/platform/win32/CCEGLView_win32.cpp | 31 +++ cocos2dx/platform/win32/CCEGLView_win32.h | 2 + cocos2dx/proj.win32/cocos2d-win32.vcproj | 24 ++ cocos2dx/text_input_node/CCIMEDispatcher.cpp | 222 ++++++++++++++++ cocos2dx/text_input_node/CCTextFieldTTF.cpp | 251 +++++++++++++++++++ 10 files changed, 800 insertions(+), 3 deletions(-) create mode 100644 cocos2dx/include/CCIMEDelegate.h create mode 100644 cocos2dx/include/CCIMEDispatcher.h create mode 100644 cocos2dx/include/CCTextFieldTTF.h create mode 100644 cocos2dx/text_input_node/CCIMEDispatcher.cpp create mode 100644 cocos2dx/text_input_node/CCTextFieldTTF.cpp diff --git a/cocos2dx/include/CCIMEDelegate.h b/cocos2dx/include/CCIMEDelegate.h new file mode 100644 index 0000000000..fe40c4f887 --- /dev/null +++ b/cocos2dx/include/CCIMEDelegate.h @@ -0,0 +1,78 @@ +/**************************************************************************** +Copyright (c) 2010 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#ifndef __CC_IME_DELEGATE_H__ +#define __CC_IME_DELEGATE_H__ + +#include "CCCommon.h" + +NS_CC_BEGIN; + +/** +@brief Input method editor protocol. +*/ +class CC_DLL CCIMEDelegate +{ +public: + virtual ~CCIMEDelegate(); + + bool attachWithIME(); + +protected: + friend class CCIMEDispatcher; + + /** + @brief Decide the delegate instance is ready for receive ime message or not. + + Called by CCIMEDispatcher. + */ + virtual bool canAttachWithIME() = 0; + + /** + @brief Decide the delegate instance can stop receive ime message or not. + */ + virtual bool canDetatchWithIME() = 0; + + /** + @brief Input end and release keyboard. + */ + virtual void detatchWithIME() = 0; + + /** + @brief Called by CCIMEDispatcher when some text input from IME. + */ + virtual void insertText(const char * text, int len) = 0; + + /** + @brief Called by CCIMEDispatcher when user clicked the backward key. + */ + virtual void deleteBackward() = 0; + +protected: + CCIMEDelegate(); +}; + +NS_CC_END; + +#endif // __CC_IME_DELEGATE_H__ diff --git a/cocos2dx/include/CCIMEDispatcher.h b/cocos2dx/include/CCIMEDispatcher.h new file mode 100644 index 0000000000..5e71d0239a --- /dev/null +++ b/cocos2dx/include/CCIMEDispatcher.h @@ -0,0 +1,91 @@ +/**************************************************************************** +Copyright (c) 2010 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#ifndef __CC_IME_DISPATCHER_H__ +#define __CC_IME_DISPATCHER_H__ + +#include "CCCommon.h" + +NS_CC_BEGIN; + +class CCIMEDelegate; + +/** +@brief Input Method Edit Message Dispatcher. +*/ +class CC_DLL CCIMEDispatcher +{ +public: + ~CCIMEDispatcher(); + + /** + @brief Returns the shared CCIMEDispatcher object for the system. + */ + static CCIMEDispatcher* sharedDispatcher(); + +// /** +// @brief Release all CCIMEDelegates from shared dispatcher. +// */ +// static void purgeSharedDispatcher(); + + /** + @brief dispatch the input text from ime + */ + void dispatchInsertText(const char * pText, int nLen); + + /** + @brief dispatch the delete backward operation + */ + void dispatchDeleteBackward(); + +protected: + friend class CCIMEDelegate; + + /** + @brief add delegate to concern ime msg + */ + void addDelegate(CCIMEDelegate * pDelegate); + + /** + @brief attach the pDeleate with ime. + @return If the old delegate can detattach with ime and the new delegate + can attach with ime, return true, otherwise return false. + */ + bool attachDelegateWithIME(CCIMEDelegate * pDelegate); + + /** + @brief remove the delegate from the delegates who concern ime msg + */ + void removeDelegate(CCIMEDelegate * pDelegate); + +private: + CCIMEDispatcher(); + + class Impl; + Impl * m_pImpl; +}; + +NS_CC_END; + +#endif // __CC_IME_DISPATCHER_H__ diff --git a/cocos2dx/include/CCTextFieldTTF.h b/cocos2dx/include/CCTextFieldTTF.h new file mode 100644 index 0000000000..d7a6e34ba2 --- /dev/null +++ b/cocos2dx/include/CCTextFieldTTF.h @@ -0,0 +1,98 @@ +/**************************************************************************** +Copyright (c) 2010 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#ifndef __CC_TEXT_FIELD_H__ +#define __CC_TEXT_FIELD_H__ + +#include "CCLabelTTF.h" +#include "CCIMEDelegate.h" +#include "CCTouchDelegateProtocol.h" + +NS_CC_BEGIN; + +/** +@brief A simple text input field with system TTF font. +*/ + +class CC_DLL CCTextFieldTTF : public CCLabelTTF, public CCIMEDelegate//, public CCTargetedTouchDelegate +{ +public: + CCTextFieldTTF(); + virtual ~CCTextFieldTTF(); + + //char * description(); + + /** creates a CCTextFieldTTF from a fontname, alignment, dimension and font size */ + static CCTextFieldTTF * textFieldWithPlaceHolder(const char *placeholder, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize); + /** creates a CCLabelTTF from a fontname and font size */ + static CCTextFieldTTF * textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize); + /** initializes the CCTextFieldTTF with a font name, alignment, dimension and font size */ + bool initWithPlaceHolder(const char *placeholder, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize); + /** initializes the CCTextFieldTTF with a font name and font size */ + bool initWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize); + + /** + @brief Get keyboard ready and waiting for input. + */ + bool attachWithIME(); + + ////////////////////////////////////////////////////////////////////////// + // properties + ////////////////////////////////////////////////////////////////////////// + + // input text property +public: + virtual void setString(const char *text); + virtual const char* getString(void); +protected: + std::string * m_pInputText; + + // place holder text property + // place holder text displayed when there is no text in the text field. +public: + virtual void setPlaceHolder(const char * text); + virtual const char * getPlaceHolder(void); +protected: + std::string * m_pPlaceHolder; + bool m_bLock; // when insertText or deleteBackward called, m_bLock is true +protected: + + ////////////////////////////////////////////////////////////////////////// + // CCIMEDelegate interface + ////////////////////////////////////////////////////////////////////////// + + virtual bool canAttachWithIME(); + virtual bool canDetatchWithIME(); + virtual void detatchWithIME(); + virtual void insertText(const char * text, int len); + virtual void deleteBackward(); + +private: + class LengthStack; + LengthStack * m_pLens; +}; + +NS_CC_END; + +#endif // __CC_TEXT_FIELD_H__ \ No newline at end of file diff --git a/cocos2dx/include/CCTouchDelegateProtocol.h b/cocos2dx/include/CCTouchDelegateProtocol.h index d2cd187d0c..119a7413fe 100644 --- a/cocos2dx/include/CCTouchDelegateProtocol.h +++ b/cocos2dx/include/CCTouchDelegateProtocol.h @@ -53,8 +53,8 @@ public: virtual void keep(void) {} virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { return false;}; - // optional + virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {} virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {} virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent) {} diff --git a/cocos2dx/label_nodes/CCLabelTTF.cpp b/cocos2dx/label_nodes/CCLabelTTF.cpp index ca25edf7b1..6b9abef6a3 100644 --- a/cocos2dx/label_nodes/CCLabelTTF.cpp +++ b/cocos2dx/label_nodes/CCLabelTTF.cpp @@ -50,7 +50,7 @@ namespace cocos2d{ pRet->autorelease(); return pRet; } - CC_SAFE_DELETE(pRet) + CC_SAFE_DELETE(pRet); return NULL; } CCLabelTTF * CCLabelTTF::labelWithString(const char *label, const char *fontName, float fontSize) @@ -61,7 +61,7 @@ namespace cocos2d{ pRet->autorelease(); return pRet; } - CC_SAFE_DELETE(pRet) + CC_SAFE_DELETE(pRet); return NULL; } diff --git a/cocos2dx/platform/win32/CCEGLView_win32.cpp b/cocos2dx/platform/win32/CCEGLView_win32.cpp index 0a9cea49de..22c340388f 100644 --- a/cocos2dx/platform/win32/CCEGLView_win32.cpp +++ b/cocos2dx/platform/win32/CCEGLView_win32.cpp @@ -32,6 +32,7 @@ THE SOFTWARE. #include "CCDirector.h" #include "CCTouch.h" #include "CCTouchDispatcher.h" +#include "CCIMEDispatcher.h" NS_CC_BEGIN; @@ -310,6 +311,32 @@ LRESULT CCEGLView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) } break; + case WM_CHAR: + { + if (wParam < 0x20) + { + if (VK_BACK == wParam) + { + CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); + } + else if (VK_TAB == wParam) + { + // tab input + } + else if (VK_ESCAPE == wParam) + { + // ESC input + } + + break; + } + char szUtf8[8] = {0}; + int nLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)&wParam, 1, szUtf8, sizeof(szUtf8), NULL, NULL); + + CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(szUtf8, nLen); + } + break; + case WM_PAINT: BeginPaint(m_hWnd, &ps); EndPaint(m_hWnd, &ps); @@ -407,6 +434,10 @@ void CCEGLView::setViewPortInPoints(float x, float y, float w, float h) } } +void CCEGLView::setIMEKeyboardState(bool /*bOpen*/) +{ +} + HWND CCEGLView::getHWnd() { return m_hWnd; diff --git a/cocos2dx/platform/win32/CCEGLView_win32.h b/cocos2dx/platform/win32/CCEGLView_win32.h index b50fcf2504..37914b1b93 100644 --- a/cocos2dx/platform/win32/CCEGLView_win32.h +++ b/cocos2dx/platform/win32/CCEGLView_win32.h @@ -59,6 +59,8 @@ public: int setDeviceOrientation(int eOritation); void setViewPortInPoints(float x, float y, float w, float h); + void setIMEKeyboardState(bool bOpen); + // win32 platform function HWND getHWnd(); void resize(int width, int height); diff --git a/cocos2dx/proj.win32/cocos2d-win32.vcproj b/cocos2dx/proj.win32/cocos2d-win32.vcproj index 611fd6c093..9d1d8e2047 100644 --- a/cocos2dx/proj.win32/cocos2d-win32.vcproj +++ b/cocos2dx/proj.win32/cocos2d-win32.vcproj @@ -415,6 +415,14 @@ RelativePath="..\include\CCGL.h" > + + + + @@ -551,6 +559,10 @@ RelativePath="..\include\CCString.h" > + + @@ -1040,6 +1052,18 @@ > + + + + + + diff --git a/cocos2dx/text_input_node/CCIMEDispatcher.cpp b/cocos2dx/text_input_node/CCIMEDispatcher.cpp new file mode 100644 index 0000000000..4032cd6910 --- /dev/null +++ b/cocos2dx/text_input_node/CCIMEDispatcher.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +Copyright (c) 2010 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#include "CCIMEDispatcher.h" + +#include + +#include "CCIMEDelegate.h" + +NS_CC_BEGIN; + +////////////////////////////////////////////////////////////////////////// +// add/remove delegate in CCIMEDelegate Cons/Destructor +////////////////////////////////////////////////////////////////////////// + +CCIMEDelegate::CCIMEDelegate() +{ + CCIMEDispatcher::sharedDispatcher()->addDelegate(this); +} + +CCIMEDelegate::~CCIMEDelegate() +{ + CCIMEDispatcher::sharedDispatcher()->removeDelegate(this); +} + +bool CCIMEDelegate::attachWithIME() +{ + return CCIMEDispatcher::sharedDispatcher()->attachDelegateWithIME(this); +} + +////////////////////////////////////////////////////////////////////////// + +typedef std::list< CCIMEDelegate * > DelegateList; +typedef std::list< CCIMEDelegate * >::iterator DelegateIter; + +////////////////////////////////////////////////////////////////////////// +// Delegate List manage class +////////////////////////////////////////////////////////////////////////// + +class CCIMEDispatcher::Impl +{ +public: + Impl() + { + } + + ~Impl() + { + + } + + void init() + { + m_DelegateWithIme = m_DelegateList.end(); + } + + DelegateIter findDelegate(CCIMEDelegate* pDelegate) + { + DelegateIter end = m_DelegateList.end(); + for (DelegateIter iter = m_DelegateList.begin(); iter != end; ++iter) + { + if (pDelegate == *iter) + { + return iter; + } + } + return end; + } + + DelegateList m_DelegateList; + DelegateIter m_DelegateWithIme; +}; + +////////////////////////////////////////////////////////////////////////// +// Cons/Destructor +////////////////////////////////////////////////////////////////////////// + +CCIMEDispatcher::CCIMEDispatcher() +: m_pImpl(new CCIMEDispatcher::Impl) +{ + m_pImpl->init(); +} + +CCIMEDispatcher::~CCIMEDispatcher() +{ + CC_SAFE_DELETE(m_pImpl); +} + +////////////////////////////////////////////////////////////////////////// +// Add/Attach/Remove CCIMEDelegate +////////////////////////////////////////////////////////////////////////// + +void CCIMEDispatcher::addDelegate(CCIMEDelegate* pDelegate) +{ + if (! pDelegate || ! m_pImpl) + { + return; + } + if (m_pImpl->m_DelegateList.end() != m_pImpl->findDelegate(pDelegate)) + { + // pDelegate already in list + return; + } + m_pImpl->m_DelegateList.push_front(pDelegate); +} + +bool CCIMEDispatcher::attachDelegateWithIME(CCIMEDelegate * pDelegate) +{ + bool bRet = false; + do + { + CC_BREAK_IF(! m_pImpl || ! pDelegate); + + DelegateIter end = m_pImpl->m_DelegateList.end(); + DelegateIter iter = m_pImpl->findDelegate(pDelegate); + + // if pDelegate is not in delegate list, return + CC_BREAK_IF(end == iter); + + if (m_pImpl->m_DelegateWithIme != end) + { + // if old delegate canDetatchWithIME return false + // or pDelegate canAttachWithIME return false, + // do nothing. + CC_BREAK_IF(! (*(m_pImpl->m_DelegateWithIme))->canDetatchWithIME() + || ! pDelegate->canAttachWithIME()); + + // detach first + CCIMEDelegate * pOldDelegate = *(m_pImpl->m_DelegateWithIme); + m_pImpl->m_DelegateWithIme = end; + pOldDelegate->detatchWithIME(); + } + m_pImpl->m_DelegateWithIme = iter; + bRet = true; + } while (0); + return bRet; +} + +void CCIMEDispatcher::removeDelegate(CCIMEDelegate* pDelegate) +{ + do + { + CC_BREAK_IF(! pDelegate || ! m_pImpl); + + DelegateIter iter = m_pImpl->findDelegate(pDelegate); + DelegateIter end = m_pImpl->m_DelegateList.end(); + CC_BREAK_IF(end == iter); + + if (m_pImpl->m_DelegateWithIme != end + &&*iter == *(m_pImpl->m_DelegateWithIme)) + { + m_pImpl->m_DelegateWithIme == end; + } + m_pImpl->m_DelegateList.erase(iter); + } while (0); +} + +void CCIMEDispatcher::dispatchInsertText(const char * pText, int nLen) +{ + do + { + CC_BREAK_IF(! m_pImpl || ! pText || nLen <= 0); + + // there is no delegate attach with ime + CC_BREAK_IF(m_pImpl->m_DelegateWithIme == m_pImpl->m_DelegateList.end()); + + CCIMEDelegate * pDelegate = *(m_pImpl->m_DelegateWithIme); + pDelegate->insertText(pText, nLen); + } while (0); +} + +void CCIMEDispatcher::dispatchDeleteBackward() +{ + do + { + CC_BREAK_IF(! m_pImpl); + + // there is no delegate attach with ime + CC_BREAK_IF(m_pImpl->m_DelegateWithIme == m_pImpl->m_DelegateList.end()); + + CCIMEDelegate * pDelegate = *(m_pImpl->m_DelegateWithIme); + pDelegate->deleteBackward(); + } while (0); +} + +////////////////////////////////////////////////////////////////////////// +// protected member function +////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////// +// static member function +////////////////////////////////////////////////////////////////////////// + +CCIMEDispatcher* CCIMEDispatcher::sharedDispatcher() +{ + static CCIMEDispatcher s_instance; + return &s_instance; +} + +NS_CC_END; diff --git a/cocos2dx/text_input_node/CCTextFieldTTF.cpp b/cocos2dx/text_input_node/CCTextFieldTTF.cpp new file mode 100644 index 0000000000..65a935b839 --- /dev/null +++ b/cocos2dx/text_input_node/CCTextFieldTTF.cpp @@ -0,0 +1,251 @@ +/**************************************************************************** +Copyright (c) 2010 cocos2d-x.org + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#include "CCTextFieldTTF.h" + +#include + +#include "CCDirector.h" +#include "CCEGLView.h" + +NS_CC_BEGIN; + +/** +@brief Use std::vector store every input text length. +*/ +class CCTextFieldTTF::LengthStack : public std::vector< unsigned short > +{ +}; + +////////////////////////////////////////////////////////////////////////// +// constructor and destructor +////////////////////////////////////////////////////////////////////////// + +CCTextFieldTTF::CCTextFieldTTF() +: m_pInputText(new std::string) +, m_pPlaceHolder(new std::string) // prevent CCLabelTTF initWithString assertion +, m_pLens(new LengthStack) +, m_bLock(false) +{ +} + +CCTextFieldTTF::~CCTextFieldTTF() +{ + CC_SAFE_DELETE(m_pInputText); + CC_SAFE_DELETE(m_pPlaceHolder); +} + +////////////////////////////////////////////////////////////////////////// +// static constructor +////////////////////////////////////////////////////////////////////////// + +CCTextFieldTTF * CCTextFieldTTF::textFieldWithPlaceHolder(const char *placeholder, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize) +{ + CCTextFieldTTF *pRet = new CCTextFieldTTF(); + if(pRet && pRet->initWithPlaceHolder("", dimensions, alignment, fontName, fontSize)) + { + pRet->autorelease(); + if (placeholder) + { + pRet->setPlaceHolder(placeholder); + } + return pRet; + } + CC_SAFE_DELETE(pRet); + return NULL; +} + +CCTextFieldTTF * CCTextFieldTTF::textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize) +{ + CCTextFieldTTF *pRet = new CCTextFieldTTF(); + if(pRet && pRet->initWithString("", fontName, fontSize)) + { + pRet->autorelease(); + if (placeholder) + { + pRet->setPlaceHolder(placeholder); + } + return pRet; + } + CC_SAFE_DELETE(pRet); + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +// initialize +////////////////////////////////////////////////////////////////////////// + +bool CCTextFieldTTF::initWithPlaceHolder(const char *placeholder, CCSize dimensions, CCTextAlignment alignment, const char *fontName, float fontSize) +{ + if (placeholder) + { + CC_SAFE_DELETE(m_pPlaceHolder); + m_pPlaceHolder = new std::string(placeholder); + } + return CCLabelTTF::initWithString(m_pPlaceHolder->c_str(), dimensions, alignment, fontName, fontSize); +} +bool CCTextFieldTTF::initWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize) +{ + if (placeholder) + { + CC_SAFE_DELETE(m_pPlaceHolder); + m_pPlaceHolder = new std::string(placeholder); + } + return CCLabelTTF::initWithString(m_pPlaceHolder->c_str(), fontName, fontSize); +} + +////////////////////////////////////////////////////////////////////////// +// CCIMEDelegate +////////////////////////////////////////////////////////////////////////// + +bool CCTextFieldTTF::attachWithIME() +{ + bool bRet = CCIMEDelegate::attachWithIME(); + if (bRet) + { + // open keyboard + CCEGLView * pGlView = CCDirector::sharedDirector()->getOpenGLView(); + if (pGlView) + { + pGlView->setIMEKeyboardState(true); + } + } + return bRet; +} + +bool CCTextFieldTTF::canAttachWithIME() +{ + return true; +} + +bool CCTextFieldTTF::canDetatchWithIME() +{ + return true; +} + +void CCTextFieldTTF::detatchWithIME() +{ + CCEGLView * pGlView = CCDirector::sharedDirector()->getOpenGLView(); + if (pGlView) + { + pGlView->setIMEKeyboardState(false); + } +} + +void CCTextFieldTTF::insertText(const char * text, int len) +{ + m_bLock = true; + std::string sText(*m_pInputText); + sText.append(text, len); + m_pLens->push_back((unsigned short)len); + setString(sText.c_str()); + m_bLock = false; +} + +void CCTextFieldTTF::deleteBackward() +{ + int nStrLen = m_pInputText->length(); + if (! nStrLen) + { + // there is no string + return; + } + + m_bLock = true; + + // get the delete byte number + int nStackSize = m_pLens->size(); + unsigned short uDeleteLen = 1; // default, erase 1 byte + if (nStackSize) + { + // get the last input text size + uDeleteLen = m_pLens->at(nStackSize - 1); + m_pLens->pop_back(); + } + + // if delete all text, show space holder string + if (nStrLen <= uDeleteLen) + { + CC_SAFE_DELETE(m_pInputText); + m_pInputText = new std::string; + CCLabelTTF::setString(m_pPlaceHolder->c_str()); + return; + } + + // set new input text + std::string sText(m_pInputText->c_str(), nStrLen - uDeleteLen); + setString(sText.c_str()); + m_bLock = false; +} + +////////////////////////////////////////////////////////////////////////// +// properties +////////////////////////////////////////////////////////////////////////// + +// input text property +void CCTextFieldTTF::setString(const char *text) +{ + CC_SAFE_DELETE(m_pInputText); + if (false == m_bLock) + { + // user use this function to set string value, clear lenStack + m_pLens->clear(); + } + if (text) + { + m_pInputText = new std::string(text); + } + else + { + m_pInputText = new std::string; + } + + // if there is no input text, display placeholder instead if (! m_pInputText->length()) { CCLabelTTF::setString(m_pPlaceHolder->c_str()); } else + { + CCLabelTTF::setString(m_pInputText->c_str()); + } +} + +const char* CCTextFieldTTF::getString(void) +{ + return m_pInputText->c_str(); +} + +// place holder text property +void CCTextFieldTTF::setPlaceHolder(const char * text) +{ + CC_SAFE_DELETE(m_pPlaceHolder); + m_pPlaceHolder = (text) ? new std::string(text) : new std::string; + if (! m_pInputText->length()) + { + CCLabelTTF::setString(m_pPlaceHolder->c_str()); + } +} + +const char * CCTextFieldTTF::getPlaceHolder(void) +{ + return m_pPlaceHolder->c_str(); +} + +NS_CC_END; From 85027c40ca092102a3b07c656961a23c38e56f2c Mon Sep 17 00:00:00 2001 From: yangws Date: Tue, 19 Apr 2011 18:11:57 +0800 Subject: [PATCH 2/5] CCIMEDispatcher works on ios. --- .../project.pbxproj.REMOVED.git-id | 2 +- cocos2dx/include/CCIMEDelegate.h | 8 + cocos2dx/include/CCIMEDispatcher.h | 10 +- cocos2dx/platform/ios/CCEGLView_ios.h | 2 + cocos2dx/platform/ios/CCEGLView_ios.mm | 18 +- cocos2dx/platform/ios/EAGLView.h | 18 +- cocos2dx/platform/ios/EAGLView.mm | 200 ++++++++++++++++++ cocos2dx/text_input_node/CCIMEDispatcher.cpp | 76 +++++++ 8 files changed, 325 insertions(+), 9 deletions(-) diff --git a/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj.REMOVED.git-id b/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj.REMOVED.git-id index 651d71b20b..e9ae813670 100644 --- a/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/HelloWorld/ios/HelloWorld.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -564b1b0ff02bf8c6185be8446b8ea8e156db7f6a \ No newline at end of file +75af303921a155bf8589306700acea56aa270738 \ No newline at end of file diff --git a/cocos2dx/include/CCIMEDelegate.h b/cocos2dx/include/CCIMEDelegate.h index fe40c4f887..f2044b8f5d 100644 --- a/cocos2dx/include/CCIMEDelegate.h +++ b/cocos2dx/include/CCIMEDelegate.h @@ -69,6 +69,14 @@ protected: */ virtual void deleteBackward() = 0; + ////////////////////////////////////////////////////////////////////////// + // keyboard show/hide notification + ////////////////////////////////////////////////////////////////////////// + virtual void keyboardWillShow(CCRect& begin, CCRect& end) {} + virtual void keyboardDidShow(CCRect& begin, CCRect& end) {} + virtual void keyboardWillHide(CCRect& begin, CCRect& end) {} + virtual void keyboardDidHide(CCRect& begin, CCRect& end) {} + protected: CCIMEDelegate(); }; diff --git a/cocos2dx/include/CCIMEDispatcher.h b/cocos2dx/include/CCIMEDispatcher.h index 5e71d0239a..a1c28c0ebc 100644 --- a/cocos2dx/include/CCIMEDispatcher.h +++ b/cocos2dx/include/CCIMEDispatcher.h @@ -25,7 +25,7 @@ THE SOFTWARE. #ifndef __CC_IME_DISPATCHER_H__ #define __CC_IME_DISPATCHER_H__ -#include "CCCommon.h" +#include "CCGeometry.h" NS_CC_BEGIN; @@ -59,6 +59,14 @@ public: */ void dispatchDeleteBackward(); + ////////////////////////////////////////////////////////////////////////// + // dispatch keyboard notification + ////////////////////////////////////////////////////////////////////////// + void dispatchKeyboardWillShow(CCRect& begin, CCRect& end); + void dispatchKeyboardDidShow(CCRect& begin, CCRect& end); + void dispatchKeyboardWillHide(CCRect& begin, CCRect& end); + void dispatchKeyboardDidHide(CCRect& begin, CCRect& end); + protected: friend class CCIMEDelegate; diff --git a/cocos2dx/platform/ios/CCEGLView_ios.h b/cocos2dx/platform/ios/CCEGLView_ios.h index 5c6d0decf6..0115a5f745 100644 --- a/cocos2dx/platform/ios/CCEGLView_ios.h +++ b/cocos2dx/platform/ios/CCEGLView_ios.h @@ -55,6 +55,8 @@ public: void touchesEnded(CCSet *set); void touchesCancelled(CCSet *set); + void setIMEKeyboardState(bool bOpen); + static CCEGLView& sharedOpenGLView(); private: diff --git a/cocos2dx/platform/ios/CCEGLView_ios.mm b/cocos2dx/platform/ios/CCEGLView_ios.mm index 587b5e5149..e6b62f4b12 100644 --- a/cocos2dx/platform/ios/CCEGLView_ios.mm +++ b/cocos2dx/platform/ios/CCEGLView_ios.mm @@ -111,13 +111,25 @@ void CCEGLView::touchesCancelled(CCSet *set) void CCEGLView::setViewPortInPoints(float x, float y, float w, float h) { - glViewport((GLint)x, (GLint)y, (GLint)w, (GLint)h); + glViewport((GLint)x, (GLint)y, (GLint)w, (GLint)h); +} + +void CCEGLView::setIMEKeyboardState(bool bOpen) +{ + if (bOpen) + { + [[EAGLView sharedEGLView] becomeFirstResponder]; + } + else + { + [[EAGLView sharedEGLView] resignFirstResponder]; + } } CCEGLView& CCEGLView::sharedOpenGLView() { - static CCEGLView instance; - return instance; + static CCEGLView instance; + return instance; } } // end of namespace cocos2d; diff --git a/cocos2dx/platform/ios/EAGLView.h b/cocos2dx/platform/ios/EAGLView.h index ab2019ae76..fe36d9eaf5 100755 --- a/cocos2dx/platform/ios/EAGLView.h +++ b/cocos2dx/platform/ios/EAGLView.h @@ -77,7 +77,7 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. * The view content is basically an EAGL surface you render your OpenGL scene into. * Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel. */ -@interface EAGLView : UIView +@interface EAGLView : UIView { id renderer_; EAGLContext *context_; // weak ref @@ -91,12 +91,21 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. //fsaa addition BOOL multisampling_; - unsigned int requestedSamples_; + unsigned int requestedSamples_; @private - CFMutableDictionaryRef touchesIntergerDict; - unsigned int indexBitsUsed; + CFMutableDictionaryRef touchesIntergerDict; + unsigned int indexBitsUsed; + NSString * markedText_; } +@property(nonatomic, readonly) UITextPosition *beginningOfDocument; +@property(nonatomic, readonly) UITextPosition *endOfDocument; +@property(nonatomic, assign) id inputDelegate; +@property(nonatomic, readonly) UITextRange *markedTextRange; +@property (nonatomic, copy) NSDictionary *markedTextStyle; +@property(readwrite, copy) UITextRange *selectedTextRange; +@property(nonatomic, readonly) id tokenizer; + /** creates an initializes an EAGLView with a frame and 0-bit depth buffer, and a RGB565 color buffer */ + (id) viewWithFrame:(CGRect)frame; /** creates an initializes an EAGLView with a frame, a color buffer format, and 0-bit depth buffer */ @@ -142,4 +151,5 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. -(int) getHeight; -(int) getUnUsedIndex; -(void) removeUsedIndexBit:(int) index; + @end diff --git a/cocos2dx/platform/ios/EAGLView.mm b/cocos2dx/platform/ios/EAGLView.mm index 4f9213ad79..83b14653f0 100755 --- a/cocos2dx/platform/ios/EAGLView.mm +++ b/cocos2dx/platform/ios/EAGLView.mm @@ -68,6 +68,7 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. #import "CCDirector.h" #import "CCSet.h" #import "CCTouch.h" +#import "CCIMEDispatcher.h" #import "OpenGL_Internal.h" //CLASS IMPLEMENTATIONS: @@ -491,4 +492,203 @@ static cocos2d::CCTouch *s_pTouches[MAX_TOUCHES]; cocos2d::CCDirector::sharedDirector()->getOpenGLView()->touchesCancelled(&set); } +#pragma mark - +#pragma mark UIView - Responder + +- (BOOL)canBecomeFirstResponder +{ + markedText_ = nil; + return YES; +} + +#pragma mark - +#pragma mark EAGLView - UIKeyInput + +- (BOOL)hasText +{ + return NO; +} + +- (void)insertText:(NSString *)text +{ + const char * pszText = [text cStringUsingEncoding:NSUTF8StringEncoding]; + cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText)); +} + +- (void)deleteBackward +{ + cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); +} + +#pragma mark - +#pragma mark UITextInput protocol + +#pragma mark UITextInput - properties + +@synthesize beginningOfDocument; +@synthesize endOfDocument; +@synthesize inputDelegate; +@synthesize markedTextRange; +@synthesize markedTextStyle; +// @synthesize selectedTextRange; // must implement +@synthesize tokenizer; + +/* Text may have a selection, either zero-length (a caret) or ranged. Editing operations are + * always performed on the text from this selection. nil corresponds to no selection. */ +- (void)setSelectedTextRange:(UITextRange *)aSelectedTextRange; +{ + CCLOG("UITextRange:setSelectedTextRange"); +} +- (UITextRange *)selectedTextRange; +{ + return [[[UITextRange alloc] init] autorelease]; +} + +#pragma mark UITextInput - Replacing and Returning Text + +- (NSString *)textInRange:(UITextRange *)range; +{ + CCLOG("textInRange"); + return nil; +} +- (void)replaceRange:(UITextRange *)range withText:(NSString *)theText; +{ + CCLOG("replaceRange"); +} + +#pragma mark UITextInput - Working with Marked and Selected Text + + + +/* If text can be selected, it can be marked. Marked text represents provisionally + * inserted text that has yet to be confirmed by the user. It requires unique visual + * treatment in its display. If there is any marked text, the selection, whether a + * caret or an extended range, always resides witihin. + * + * Setting marked text either replaces the existing marked text or, if none is present, + * inserts it from the current selection. */ + +- (void)setMarkedTextRange:(UITextRange *)markedTextRange; +{ + CCLOG("setMarkedTextRange"); +} + +- (UITextRange *)markedTextRange; +{ + CCLOG("markedTextRange"); + return nil; // Nil if no marked text. +} +- (void)setMarkedTextStyle:(NSDictionary *)markedTextStyle; +{ + CCLOG("setMarkedTextStyle"); + +} +- (NSDictionary *)markedTextStyle; +{ + CCLOG("markedTextStyle"); + return nil; +} +- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange; +{ + CCLOG("setMarkedText"); + markedText_ = markedText; +} +- (void)unmarkText; +{ + CCLOG("unmarkText"); + if (nil == markedText_) + { + return; + } + const char * pszText = [markedText_ cStringUsingEncoding:NSUTF8StringEncoding]; + cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText)); + markedText_ = nil; +} + +#pragma mark Methods for creating ranges and positions. + +- (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition; +{ + CCLOG("textRangeFromPosition"); + return nil; +} +- (UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset; +{ + CCLOG("positionFromPosition"); + return nil; +} +- (UITextPosition *)positionFromPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset; +{ + CCLOG("positionFromPosition"); + return nil; +} + +/* Simple evaluation of positions */ +- (NSComparisonResult)comparePosition:(UITextPosition *)position toPosition:(UITextPosition *)other; +{ + CCLOG("comparePosition"); + return 0; +} +- (NSInteger)offsetFromPosition:(UITextPosition *)from toPosition:(UITextPosition *)toPosition; +{ + CCLOG("offsetFromPosition"); + return 0; +} + +- (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction; +{ + CCLOG("positionWithinRange"); + return nil; +} +- (UITextRange *)characterRangeByExtendingPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction; +{ + CCLOG("characterRangeByExtendingPosition"); + return nil; +} + +#pragma mark Writing direction + +- (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction; +{ + CCLOG("baseWritingDirectionForPosition"); + return UITextWritingDirectionNatural; +} +- (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range; +{ + CCLOG("setBaseWritingDirection"); +} + +#pragma mark Geometry + +/* Geometry used to provide, for example, a correction rect. */ +- (CGRect)firstRectForRange:(UITextRange *)range; +{ + CCLOG("firstRectForRange"); + return CGRectNull; +} +- (CGRect)caretRectForPosition:(UITextPosition *)position; +{ + CCLOG("caretRectForPosition"); + return CGRectMake(0, 0, 0, 0); +} + +#pragma mark Hit testing + +/* JS - Find the closest position to a given point */ +- (UITextPosition *)closestPositionToPoint:(CGPoint)point; +{ + CCLOG(@"closestPositionToPoint"); + return nil; +} +- (UITextPosition *)closestPositionToPoint:(CGPoint)point withinRange:(UITextRange *)range; +{ + CCLOG("closestPositionToPoint"); + return nil; +} +- (UITextRange *)characterRangeAtPoint:(CGPoint)point; +{ + CCLOG("characterRangeAtPoint"); + return nil; +} + @end diff --git a/cocos2dx/text_input_node/CCIMEDispatcher.cpp b/cocos2dx/text_input_node/CCIMEDispatcher.cpp index 4032cd6910..46981ecd2d 100644 --- a/cocos2dx/text_input_node/CCIMEDispatcher.cpp +++ b/cocos2dx/text_input_node/CCIMEDispatcher.cpp @@ -176,6 +176,10 @@ void CCIMEDispatcher::removeDelegate(CCIMEDelegate* pDelegate) } while (0); } +////////////////////////////////////////////////////////////////////////// +// dispatch text message +////////////////////////////////////////////////////////////////////////// + void CCIMEDispatcher::dispatchInsertText(const char * pText, int nLen) { do @@ -204,6 +208,78 @@ void CCIMEDispatcher::dispatchDeleteBackward() } while (0); } +////////////////////////////////////////////////////////////////////////// +// dispatch keyboard message +////////////////////////////////////////////////////////////////////////// + +void CCIMEDispatcher::dispatchKeyboardWillShow(CCRect& begin, CCRect& end) +{ + if (m_pImpl) + { + CCIMEDelegate * pDelegate = 0; + DelegateIter last = m_pImpl->m_DelegateList.end(); + for (DelegateIter first = m_pImpl->m_DelegateList.begin(); first != last; ++first) + { + pDelegate = *(first); + if (pDelegate) + { + pDelegate->keyboardWillShow(begin, end); + } + } + } +} + +void CCIMEDispatcher::dispatchKeyboardDidShow(CCRect& begin, CCRect& end) +{ + if (m_pImpl) + { + CCIMEDelegate * pDelegate = 0; + DelegateIter last = m_pImpl->m_DelegateList.end(); + for (DelegateIter first = m_pImpl->m_DelegateList.begin(); first != last; ++first) + { + pDelegate = *(first); + if (pDelegate) + { + pDelegate->keyboardDidShow(begin, end); + } + } + } +} + +void CCIMEDispatcher::dispatchKeyboardWillHide(CCRect& begin, CCRect& end) +{ + if (m_pImpl) + { + CCIMEDelegate * pDelegate = 0; + DelegateIter last = m_pImpl->m_DelegateList.end(); + for (DelegateIter first = m_pImpl->m_DelegateList.begin(); first != last; ++first) + { + pDelegate = *(first); + if (pDelegate) + { + pDelegate->keyboardWillHide(begin, end); + } + } + } +} + +void CCIMEDispatcher::dispatchKeyboardDidHide(CCRect& begin, CCRect& end) +{ + if (m_pImpl) + { + CCIMEDelegate * pDelegate = 0; + DelegateIter last = m_pImpl->m_DelegateList.end(); + for (DelegateIter first = m_pImpl->m_DelegateList.begin(); first != last; ++first) + { + pDelegate = *(first); + if (pDelegate) + { + pDelegate->keyboardDidHide(begin, end); + } + } + } +} + ////////////////////////////////////////////////////////////////////////// // protected member function ////////////////////////////////////////////////////////////////////////// From 252f3efe1aa1349d44335a028e1dab9b8c5c389d Mon Sep 17 00:00:00 2001 From: yangws Date: Fri, 22 Apr 2011 16:33:41 +0800 Subject: [PATCH 3/5] CCIMEDispatcher works on android. --- .../cocos2dx/lib/Cocos2dxGLSurfaceView.java | 210 ++++++++++++++++- .../org/cocos2dx/lib/Cocos2dxRenderer.java | 18 +- cocos2dx/Android.mk | 4 +- .../platform/android/CCEGLView_android.cpp | 55 +++-- cocos2dx/platform/android/CCEGLView_android.h | 1 + cocos2dx/platform/android/Cocos2dJni.cpp | 212 +++++++++++------- cocos2dx/platform/android/Cocos2dJni.h | 1 + cocos2dx/platform/win32/CCEGLView_win32.cpp | 20 +- cocos2dx/text_input_node/CCTextFieldTTF.cpp | 22 +- .../cocos2dx/lib/Cocos2dxGLSurfaceView.java | 210 ++++++++++++++++- .../org/cocos2dx/lib/Cocos2dxRenderer.java | 18 +- 11 files changed, 651 insertions(+), 120 deletions(-) diff --git a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java index f7b64beb08..1a975de2d6 100644 --- a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java +++ b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java @@ -2,17 +2,145 @@ package org.cocos2dx.lib; import android.content.Context; import android.opengl.GLSurfaceView; +import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.inputmethod.CompletionInfo; +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; + +class Cocos2dxInputConnection implements InputConnection { + + @Override + public boolean beginBatchEdit() { + return false; + } + + @Override + public boolean clearMetaKeyStates(int states) { + return false; + } + + @Override + public boolean commitCompletion(CompletionInfo text) { + return false; + } + + @Override + public boolean commitText(CharSequence text, int newCursorPosition) { + if (null != mView) { + final String insertText = text.toString(); + mView.insertText(insertText); + } + return false; + } + + @Override + public boolean deleteSurroundingText(int leftLength, int rightLength) { + return false; + } + + @Override + public boolean endBatchEdit() { + return false; + } + + @Override + public boolean finishComposingText() { + return false; + } + + @Override + public int getCursorCapsMode(int reqModes) { + return 0; + } + + @Override + public ExtractedText getExtractedText(ExtractedTextRequest request, + int flags) { + return null; + } + + @Override + public CharSequence getTextAfterCursor(int n, int flags) { + return null; + } + + @Override + public CharSequence getTextBeforeCursor(int n, int flags) { + return null; + } + + @Override + public boolean performContextMenuAction(int id) { + return false; + } + + @Override + public boolean performEditorAction(int editorAction) { + if (null != mView) { + final String insertText = "\n"; + mView.insertText(insertText); + } + return false; + } + + @Override + public boolean performPrivateCommand(String action, Bundle data) { + return false; + } + + @Override + public boolean reportFullscreenMode(boolean enabled) { + return false; + } + + @Override + public boolean sendKeyEvent(KeyEvent event) { + if (null != mView) { + switch (event.getKeyCode()) { + + case KeyEvent.KEYCODE_DEL: + mView.deleteBackward(); + break; + } + } + return false; + } + + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition) { + return false; + } + + @Override + public boolean setSelection(int start, int end) { + return false; + } + + public void setGLSurfaceView(Cocos2dxGLSurfaceView view) { + mView = view; + } + + private Cocos2dxGLSurfaceView mView; +} public class Cocos2dxGLSurfaceView extends GLSurfaceView { - private static final String TAG = Cocos2dxGLSurfaceView.class - .getCanonicalName(); + + static private Cocos2dxGLSurfaceView mainView; + + private static final String TAG = Cocos2dxGLSurfaceView.class.getCanonicalName(); private Cocos2dxRenderer mRenderer; private final boolean debug = false; + /////////////////////////////////////////////////////////////////////////// + // for initialize + /////////////////////////////////////////////////////////////////////////// public Cocos2dxGLSurfaceView(Context context) { super(context); initView(); @@ -27,8 +155,86 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { mRenderer = new Cocos2dxRenderer(); setFocusableInTouchMode(true); setRenderer(mRenderer); + mainView = this; } + /////////////////////////////////////////////////////////////////////////// + // for text input + /////////////////////////////////////////////////////////////////////////// + + 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, InputMethodManager.SHOW_IMPLICIT); + } + + public static void closeIMEKeyboard() { + if (null != mainView) { + Log.d("Cocos2dxGLSurfaceView", "closeIMEKeyboard"); + } + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) { + return; + } + imm.hideSoftInputFromWindow(mainView.getWindowToken(), 0); + } + + @Override + public boolean onCheckIsTextEditor() { + if (null == mainView) + { + return false; + } + return true; + } + + private Cocos2dxInputConnection ic; + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + if (onCheckIsTextEditor()) { + + outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT; + outAttrs.imeOptions = EditorInfo.IME_NULL; + outAttrs.initialSelStart = -1; + outAttrs.initialSelEnd = -1; + outAttrs.initialCapsMode = 0; + + if (null == ic) + { + ic = new Cocos2dxInputConnection(); + ic.setGLSurfaceView(this); + } + return ic; + } + return null; + } + + public void insertText(final String text) { + queueEvent(new Runnable() { + @Override + public void run() { + mRenderer.handleInsertText(text); + } + }); + } + + public void deleteBackward() { + queueEvent(new Runnable() { + @Override + public void run() { + mRenderer.handleDeleteBackward(); + } + }); + } + /////////////////////////////////////////////////////////////////////////// + // for touch event + /////////////////////////////////////////////////////////////////////////// + public boolean onTouchEvent(final MotionEvent event) { // these data are used in ACTION_MOVE and ACTION_CANCEL final int pointerNumber = event.getPointerCount(); diff --git a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java index 4a80d59ac6..90f280614b 100644 --- a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java +++ b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxRenderer.java @@ -67,12 +67,26 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer { public static void setAnimationInterval(double interval){ animationInterval = (long)(interval * NANOSECONDSPERSECOND); } - private static native void nativeTouchesBegin(int id, float x, float y); private static native void nativeTouchesEnd(int id, float x, float y); private static native void nativeTouchesMove(int[] id, float[] x, float[] y); private static native void nativeTouchesCancel(int[] id, float[] x, float[] y); -private static native boolean nativeKeyDown(int keyCode); + private static native boolean nativeKeyDown(int keyCode); private static native void nativeRender(); private static native void nativeInit(int w, int h); + + ///////////////////////////////////////////////////////////////////////////////// + // handle input method edit message + ///////////////////////////////////////////////////////////////////////////////// + + public void handleInsertText(final String text) { + nativeInsertText(text); + } + + public void handleDeleteBackward() { + nativeDeleteBackward(); + } + + private static native void nativeInsertText(String text); + private static native void nativeDeleteBackward(); } diff --git a/cocos2dx/Android.mk b/cocos2dx/Android.mk index af06f10e43..9364f11f8d 100644 --- a/cocos2dx/Android.mk +++ b/cocos2dx/Android.mk @@ -82,6 +82,8 @@ support/image_support/TGAlib.cpp \ support/zip_support/ZipUtils.cpp \ support/zip_support/ioapi.cpp \ support/zip_support/unzip.cpp \ +text_input_node/CCIMEDispatcher.cpp \ +text_input_node/CCTextFieldTTF.cpp \ textures/CCTexture2D.cpp \ textures/CCTextureAtlas.cpp \ textures/CCTextureCache.cpp \ @@ -135,4 +137,4 @@ LOCAL_LDLIBS := -L$(LOCAL_PATH)/platform/third_party/android/libraries \ # define the macro to compile through support/zip_support/ioapi.c LOCAL_CFLAGS := -DUSE_FILE32API -include $(BUILD_SHARED_LIBRARY) \ No newline at end of file +include $(BUILD_SHARED_LIBRARY) diff --git a/cocos2dx/platform/android/CCEGLView_android.cpp b/cocos2dx/platform/android/CCEGLView_android.cpp index b64aa585b0..321b344334 100644 --- a/cocos2dx/platform/android/CCEGLView_android.cpp +++ b/cocos2dx/platform/android/CCEGLView_android.cpp @@ -28,6 +28,7 @@ THE SOFTWARE. #include "CCDirector.h" #include "ccMacros.h" #include "CCTouchDispatcher.h" +#include "Cocos2dJni.h" #include @@ -127,21 +128,21 @@ void CCEGLView::setContentScaleFactor(float contentScaleFactor) void CCEGLView::setViewPortInPoints(float x, float y, float w, float h) { - if (m_bNotHVGA) - { - float factor = m_fScreenScaleFactor / CC_CONTENT_SCALE_FACTOR(); - glViewport((GLint)(x * factor) + m_rcViewPort.origin.x, - (GLint)(y * factor) + m_rcViewPort.origin.y, - (GLint)(w * factor), - (GLint)(h * factor)); - } - else - { - glViewport((GLint)x, - (GLint)y, - (GLint)w, - (GLint)h); - } + if (m_bNotHVGA) + { + float factor = m_fScreenScaleFactor / CC_CONTENT_SCALE_FACTOR(); + glViewport((GLint)(x * factor) + m_rcViewPort.origin.x, + (GLint)(y * factor) + m_rcViewPort.origin.y, + (GLint)(w * factor), + (GLint)(h * factor)); + } + else + { + glViewport((GLint)x, + (GLint)y, + (GLint)w, + (GLint)h); + } } CCEGLView& CCEGLView::sharedOpenGLView() @@ -157,15 +158,21 @@ float CCEGLView::getScreenScaleFactor() CCRect CCEGLView::getViewPort() { - if (m_bNotHVGA) - { - return m_rcViewPort; - } - else - { - CCRect rect(0, 0, 0, 0); - return rect; - } + if (m_bNotHVGA) + { + return m_rcViewPort; + } + else + { + CCRect rect(0, 0, 0, 0); + return rect; + } +} + +void CCEGLView::setIMEKeyboardState(bool bOpen) +{ + + setKeyboardStateJNI((int)bOpen); } } // end of namespace cocos2d diff --git a/cocos2dx/platform/android/CCEGLView_android.h b/cocos2dx/platform/android/CCEGLView_android.h index af10c8dfa7..9830cd6611 100644 --- a/cocos2dx/platform/android/CCEGLView_android.h +++ b/cocos2dx/platform/android/CCEGLView_android.h @@ -60,6 +60,7 @@ public: void setViewPortInPoints(float x, float y, float w, float h); CCRect getViewPort(); float getScreenScaleFactor(); + void setIMEKeyboardState(bool bOpen); // static function /** diff --git a/cocos2dx/platform/android/Cocos2dJni.cpp b/cocos2dx/platform/android/Cocos2dJni.cpp index 3beb0f21b5..b0375c7056 100644 --- a/cocos2dx/platform/android/Cocos2dJni.cpp +++ b/cocos2dx/platform/android/Cocos2dJni.cpp @@ -29,6 +29,7 @@ THE SOFTWARE. #include "CCTouchDispatcher.h" #include "CCFileUtils.h" #include "CCGeometry.h" +#include "CCIMEDispatcher.h" #include "platform/android/CCAccelerometer_android.h" #include @@ -43,24 +44,73 @@ using namespace cocos2d; extern "C" { + ////////////////////////////////////////////////////////////////////////// + // java vm helper function + ////////////////////////////////////////////////////////////////////////// - #define MAX_TOUCHES 5 - static CCTouch *s_pTouches[MAX_TOUCHES] = { NULL }; + JavaVM *gJavaVM = NULL; - // handle accelerometer changes + jint JNI_OnLoad(JavaVM *vm, void *reserved) + { + gJavaVM = vm; + return JNI_VERSION_1_4; + } - void Java_org_cocos2dx_lib_Cocos2dxAccelerometer_onSensorChanged(JNIEnv* env, jobject thiz, jfloat x, jfloat y, jfloat z, jlong timeStamp) - { - // We need to invert to make it compatible with iOS. - CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort(); - float fScreenScaleFactor = CCEGLView::sharedOpenGLView().getScreenScaleFactor(); - cocos2d::CCAccelerometer::sharedAccelerometer()->update((x - rcRect.origin.x) / fScreenScaleFactor, - (y - rcRect.origin.y) / fScreenScaleFactor, - z, - timeStamp); - } + struct TMethodJNI + { + JNIEnv * env; + jclass classID; + jmethodID methodID; + }; + static bool getMethodID(struct TMethodJNI& t, const char *className, const char *methodName, const char *paramCode) + { + bool ret = 0; + do + { + if (gJavaVM->GetEnv((void**)&t.env, JNI_VERSION_1_4) != JNI_OK) + { + LOGD("Failed to get the environment using GetEnv()"); + break; + } - // handle touch event + if (gJavaVM->AttachCurrentThread(&t.env, 0) < 0) + { + LOGD("Failed to get the environment using AttachCurrentThread()"); + break; + } + + t.classID = t.env->FindClass(className); + if (! t.classID) + { + LOGD("Failed to find class of %s", className); + break; + } + + t.methodID = t.env->GetStaticMethodID(t.classID, methodName, paramCode); + if (! t.methodID) + { + LOGD("Failed to find method id of %s", methodName); + break; + } + ret = true; + } while (0); + + return ret; + } + + ////////////////////////////////////////////////////////////////////////// + // native renderer + ////////////////////////////////////////////////////////////////////////// + + #define MAX_TOUCHES 5 + static CCTouch *s_pTouches[MAX_TOUCHES] = { NULL }; + + void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) + { + cocos2d::CCDirector::sharedDirector()->mainLoop(); + } + + // handle touch event void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin(JNIEnv* env, jobject thiz, jint id, jfloat x, jfloat y) { CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort(); @@ -196,6 +246,21 @@ extern "C" return JNI_FALSE; } + ////////////////////////////////////////////////////////////////////////// + // handle accelerometer changes + ////////////////////////////////////////////////////////////////////////// + + void Java_org_cocos2dx_lib_Cocos2dxAccelerometer_onSensorChanged(JNIEnv* env, jobject thiz, jfloat x, jfloat y, jfloat z, jlong timeStamp) + { + // We need to invert to make it compatible with iOS. + CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort(); + float fScreenScaleFactor = CCEGLView::sharedOpenGLView().getScreenScaleFactor(); + cocos2d::CCAccelerometer::sharedAccelerometer()->update((x - rcRect.origin.x) / fScreenScaleFactor, + (y - rcRect.origin.y) / fScreenScaleFactor, + z, + timeStamp); + } + void Java_org_cocos2dx_lib_Cocos2dxActivity_nativeSetPaths(JNIEnv* env, jobject thiz, jstring apkPath) { const char* str; @@ -207,72 +272,29 @@ extern "C" } } - // record the java vm - - JavaVM *gJavaVM = NULL; - jclass classOfCocos2dxActivity = 0; - JNIEnv *env = 0; - - jint JNI_OnLoad(JavaVM *vm, void *reserved) - { - gJavaVM = vm; - return JNI_VERSION_1_4; - } - - static jmethodID getMethodID(const char *methodName, const char *paramCode) - { - jmethodID ret = 0; - - // get jni environment and java class for Cocos2dxActivity - if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) - { - LOGD("Failed to get the environment using GetEnv()"); - return 0; - } - - if (gJavaVM->AttachCurrentThread(&env, 0) < 0) - { - LOGD("Failed to get the environment using AttachCurrentThread()"); - return 0; - } - - classOfCocos2dxActivity = env->FindClass("org/cocos2dx/lib/Cocos2dxActivity"); - if (! classOfCocos2dxActivity) - { - LOGD("Failed to find class of org/cocos2dx/lib/Cocos2dxActivity"); - return 0; - } - - if (env != 0 && classOfCocos2dxActivity != 0) - { - ret = env->GetStaticMethodID(classOfCocos2dxActivity, methodName, paramCode); - } - - if (! ret) - { - LOGD("get method id of %s error", methodName); - } - - return ret; - } void enableAccelerometerJNI() { - jmethodID methodID = getMethodID("enableAccelerometer", "()V"); - - if (methodID) + TMethodJNI t; + if (getMethodID(t + , "org/cocos2dx/lib/Cocos2dxActivity" + , "enableAccelerometer" + , "()V")) { - env->CallStaticVoidMethod(classOfCocos2dxActivity, methodID); + t.env->CallStaticVoidMethod(t.classID, t.methodID); } } void disableAccelerometerJNI() { - jmethodID methodID = getMethodID("disableAccelerometer", "()V"); + TMethodJNI t; - if (methodID) + if (getMethodID(t + , "org/cocos2dx/lib/Cocos2dxActivity" + , "disableAccelerometer" + , "()V")) { - env->CallStaticVoidMethod(classOfCocos2dxActivity, methodID); + t.env->CallStaticVoidMethod(t.classID, t.methodID); } } @@ -283,30 +305,58 @@ extern "C" return; } - jmethodID methodID = getMethodID("showMessageBox", "(Ljava/lang/String;Ljava/lang/String;)V"); - - if (methodID) + TMethodJNI t; + if (getMethodID(t + , "org/cocos2dx/lib/Cocos2dxActivity" + , "showMessageBox" + , "(Ljava/lang/String;Ljava/lang/String;)V")) { jstring StringArg1; if (! pszTitle) { - StringArg1 = env->NewStringUTF(""); + StringArg1 = t.env->NewStringUTF(""); } else { - StringArg1 = env->NewStringUTF(pszTitle); + StringArg1 = t.env->NewStringUTF(pszTitle); } - jstring StringArg2 = env->NewStringUTF(pszMsg); - env->CallStaticVoidMethod(classOfCocos2dxActivity, methodID, StringArg1, StringArg2); + jstring StringArg2 = t.env->NewStringUTF(pszMsg); + t.env->CallStaticVoidMethod(t.classID, t.methodID, StringArg1, StringArg2); } } - // native renderer + ////////////////////////////////////////////////////////////////////////// + // handle IME message + ////////////////////////////////////////////////////////////////////////// - void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) - { - cocos2d::CCDirector::sharedDirector()->mainLoop(); - } + void setKeyboardStateJNI(int bOpen) + { + TMethodJNI t; + jint open = bOpen; + if (getMethodID(t + , "org/cocos2dx/lib/Cocos2dxGLSurfaceView" + , (bOpen) ? "openIMEKeyboard" : "closeIMEKeyboard" + , "()V")) + { + t.env->CallStaticVoidMethod(t.classID, t.methodID); + } + } + + void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInsertText(JNIEnv* env, jobject thiz, jstring text) + { + jboolean isCopy = 0; + const char* pszText = env->GetStringUTFChars(text, &isCopy); + if (isCopy) + { + cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText)); + env->ReleaseStringUTFChars(text, pszText); + } + } + + void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeDeleteBackward(JNIEnv* env, jobject thiz) + { + cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); + } } diff --git a/cocos2dx/platform/android/Cocos2dJni.h b/cocos2dx/platform/android/Cocos2dJni.h index d83aa73a0e..7cf0d83c98 100644 --- a/cocos2dx/platform/android/Cocos2dJni.h +++ b/cocos2dx/platform/android/Cocos2dJni.h @@ -33,6 +33,7 @@ extern "C" void enableAccelerometerJNI(); void disableAccelerometerJNI(); void showMessageBoxJNI(const char * pszMsg, const char * pszTitle); + void setKeyboardStateJNI(int bOpen); } #endif // __ANDROID_COCOS2D_JNI_H__ diff --git a/cocos2dx/platform/win32/CCEGLView_win32.cpp b/cocos2dx/platform/win32/CCEGLView_win32.cpp index 22c340388f..63af858d3f 100644 --- a/cocos2dx/platform/win32/CCEGLView_win32.cpp +++ b/cocos2dx/platform/win32/CCEGLView_win32.cpp @@ -319,6 +319,10 @@ LRESULT CCEGLView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); } + else if (VK_RETURN == wParam) + { + CCIMEDispatcher::sharedDispatcher()->dispatchInsertText("\n", 1); + } else if (VK_TAB == wParam) { // tab input @@ -327,13 +331,19 @@ LRESULT CCEGLView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // ESC input } - - break; } - char szUtf8[8] = {0}; - int nLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)&wParam, 1, szUtf8, sizeof(szUtf8), NULL, NULL); + else if (wParam < 128) + { + // ascii char + CCIMEDispatcher::sharedDispatcher()->dispatchInsertText((const char *)&wParam, 1); + } + else + { + char szUtf8[8] = {0}; + int nLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)&wParam, 1, szUtf8, sizeof(szUtf8), NULL, NULL); - CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(szUtf8, nLen); + CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(szUtf8, nLen); + } } break; diff --git a/cocos2dx/text_input_node/CCTextFieldTTF.cpp b/cocos2dx/text_input_node/CCTextFieldTTF.cpp index 65a935b839..5b170b4edd 100644 --- a/cocos2dx/text_input_node/CCTextFieldTTF.cpp +++ b/cocos2dx/text_input_node/CCTextFieldTTF.cpp @@ -155,9 +155,29 @@ void CCTextFieldTTF::detatchWithIME() void CCTextFieldTTF::insertText(const char * text, int len) { + std::string sInsert(text, len); + + // insert \n means input end + int nPos = sInsert.find('\n'); + if (sInsert.npos != nPos) + { + len = nPos; + sInsert.erase(nPos); + } + if (len <= 0) + { + // close keyboard + CCEGLView * pGlView = CCDirector::sharedDirector()->getOpenGLView(); + if (pGlView) + { + pGlView->setIMEKeyboardState(false); + } + return; + } + m_bLock = true; std::string sText(*m_pInputText); - sText.append(text, len); + sText.append(sInsert); m_pLens->push_back((unsigned short)len); setString(sText.c_str()); m_bLock = false; diff --git a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java index f7b64beb08..1a975de2d6 100644 --- a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java +++ b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java @@ -2,17 +2,145 @@ package org.cocos2dx.lib; import android.content.Context; import android.opengl.GLSurfaceView; +import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.inputmethod.CompletionInfo; +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; + +class Cocos2dxInputConnection implements InputConnection { + + @Override + public boolean beginBatchEdit() { + return false; + } + + @Override + public boolean clearMetaKeyStates(int states) { + return false; + } + + @Override + public boolean commitCompletion(CompletionInfo text) { + return false; + } + + @Override + public boolean commitText(CharSequence text, int newCursorPosition) { + if (null != mView) { + final String insertText = text.toString(); + mView.insertText(insertText); + } + return false; + } + + @Override + public boolean deleteSurroundingText(int leftLength, int rightLength) { + return false; + } + + @Override + public boolean endBatchEdit() { + return false; + } + + @Override + public boolean finishComposingText() { + return false; + } + + @Override + public int getCursorCapsMode(int reqModes) { + return 0; + } + + @Override + public ExtractedText getExtractedText(ExtractedTextRequest request, + int flags) { + return null; + } + + @Override + public CharSequence getTextAfterCursor(int n, int flags) { + return null; + } + + @Override + public CharSequence getTextBeforeCursor(int n, int flags) { + return null; + } + + @Override + public boolean performContextMenuAction(int id) { + return false; + } + + @Override + public boolean performEditorAction(int editorAction) { + if (null != mView) { + final String insertText = "\n"; + mView.insertText(insertText); + } + return false; + } + + @Override + public boolean performPrivateCommand(String action, Bundle data) { + return false; + } + + @Override + public boolean reportFullscreenMode(boolean enabled) { + return false; + } + + @Override + public boolean sendKeyEvent(KeyEvent event) { + if (null != mView) { + switch (event.getKeyCode()) { + + case KeyEvent.KEYCODE_DEL: + mView.deleteBackward(); + break; + } + } + return false; + } + + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition) { + return false; + } + + @Override + public boolean setSelection(int start, int end) { + return false; + } + + public void setGLSurfaceView(Cocos2dxGLSurfaceView view) { + mView = view; + } + + private Cocos2dxGLSurfaceView mView; +} public class Cocos2dxGLSurfaceView extends GLSurfaceView { - private static final String TAG = Cocos2dxGLSurfaceView.class - .getCanonicalName(); + + static private Cocos2dxGLSurfaceView mainView; + + private static final String TAG = Cocos2dxGLSurfaceView.class.getCanonicalName(); private Cocos2dxRenderer mRenderer; private final boolean debug = false; + /////////////////////////////////////////////////////////////////////////// + // for initialize + /////////////////////////////////////////////////////////////////////////// public Cocos2dxGLSurfaceView(Context context) { super(context); initView(); @@ -27,8 +155,86 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { mRenderer = new Cocos2dxRenderer(); setFocusableInTouchMode(true); setRenderer(mRenderer); + mainView = this; } + /////////////////////////////////////////////////////////////////////////// + // for text input + /////////////////////////////////////////////////////////////////////////// + + 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, InputMethodManager.SHOW_IMPLICIT); + } + + public static void closeIMEKeyboard() { + if (null != mainView) { + Log.d("Cocos2dxGLSurfaceView", "closeIMEKeyboard"); + } + InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) { + return; + } + imm.hideSoftInputFromWindow(mainView.getWindowToken(), 0); + } + + @Override + public boolean onCheckIsTextEditor() { + if (null == mainView) + { + return false; + } + return true; + } + + private Cocos2dxInputConnection ic; + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + if (onCheckIsTextEditor()) { + + outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT; + outAttrs.imeOptions = EditorInfo.IME_NULL; + outAttrs.initialSelStart = -1; + outAttrs.initialSelEnd = -1; + outAttrs.initialCapsMode = 0; + + if (null == ic) + { + ic = new Cocos2dxInputConnection(); + ic.setGLSurfaceView(this); + } + return ic; + } + return null; + } + + public void insertText(final String text) { + queueEvent(new Runnable() { + @Override + public void run() { + mRenderer.handleInsertText(text); + } + }); + } + + public void deleteBackward() { + queueEvent(new Runnable() { + @Override + public void run() { + mRenderer.handleDeleteBackward(); + } + }); + } + /////////////////////////////////////////////////////////////////////////// + // for touch event + /////////////////////////////////////////////////////////////////////////// + public boolean onTouchEvent(final MotionEvent event) { // these data are used in ACTION_MOVE and ACTION_CANCEL final int pointerNumber = event.getPointerCount(); diff --git a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java index 4a80d59ac6..90f280614b 100644 --- a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java +++ b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxRenderer.java @@ -67,12 +67,26 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer { public static void setAnimationInterval(double interval){ animationInterval = (long)(interval * NANOSECONDSPERSECOND); } - private static native void nativeTouchesBegin(int id, float x, float y); private static native void nativeTouchesEnd(int id, float x, float y); private static native void nativeTouchesMove(int[] id, float[] x, float[] y); private static native void nativeTouchesCancel(int[] id, float[] x, float[] y); -private static native boolean nativeKeyDown(int keyCode); + private static native boolean nativeKeyDown(int keyCode); private static native void nativeRender(); private static native void nativeInit(int w, int h); + + ///////////////////////////////////////////////////////////////////////////////// + // handle input method edit message + ///////////////////////////////////////////////////////////////////////////////// + + public void handleInsertText(final String text) { + nativeInsertText(text); + } + + public void handleDeleteBackward() { + nativeDeleteBackward(); + } + + private static native void nativeInsertText(String text); + private static native void nativeDeleteBackward(); } From 9b08f4add69674b380dc8700e977c7c2196fda0c Mon Sep 17 00:00:00 2001 From: yangws Date: Tue, 26 Apr 2011 16:33:20 +0800 Subject: [PATCH 4/5] keyboard notification message on ios and TextFieldTTF test code OK. --- cocos2dx/include/CCIMEDelegate.h | 38 ++++-- cocos2dx/include/CCIMEDispatcher.h | 13 +- cocos2dx/include/CCTextFieldTTF.h | 12 +- cocos2dx/platform/ios/EAGLView.mm | 124 +++++++++++++++++- cocos2dx/text_input_node/CCIMEDispatcher.cpp | 80 +++++++---- cocos2dx/text_input_node/CCTextFieldTTF.cpp | 26 ++-- .../project.pbxproj.REMOVED.git-id | 2 +- tests/test.win32/test.win32.vcproj | 12 ++ tests/tests/controller.cpp | 4 +- tests/tests/tests.h | 5 +- 10 files changed, 249 insertions(+), 67 deletions(-) diff --git a/cocos2dx/include/CCIMEDelegate.h b/cocos2dx/include/CCIMEDelegate.h index f2044b8f5d..be9ad903d1 100644 --- a/cocos2dx/include/CCIMEDelegate.h +++ b/cocos2dx/include/CCIMEDelegate.h @@ -25,19 +25,27 @@ THE SOFTWARE. #ifndef __CC_IME_DELEGATE_H__ #define __CC_IME_DELEGATE_H__ -#include "CCCommon.h" +#include "CCGeometry.h" NS_CC_BEGIN; +typedef struct +{ + CCRect begin; // the soft keyboard rectangle when animatin begin + CCRect end; // the soft keyboard rectangle when animatin end + float duration; // the soft keyboard animation duration +} CCIMEKeyboardNotificationInfo; + /** -@brief Input method editor protocol. +@brief Input method editor delegate. */ class CC_DLL CCIMEDelegate { public: virtual ~CCIMEDelegate(); - bool attachWithIME(); + virtual bool attachWithIME(); + virtual bool detachWithIME(); protected: friend class CCIMEDispatcher; @@ -47,35 +55,39 @@ protected: Called by CCIMEDispatcher. */ - virtual bool canAttachWithIME() = 0; + virtual bool canAttachWithIME() { return false; } + /** + @brief When the delegate detach with IME, this method call by CCIMEDispatcher. + */ + virtual void didAttachWithIME() {} /** @brief Decide the delegate instance can stop receive ime message or not. */ - virtual bool canDetatchWithIME() = 0; + virtual bool canDetachWithIME() { return false; } /** - @brief Input end and release keyboard. + @brief When the delegate detach with IME, this method call by CCIMEDispatcher. */ - virtual void detatchWithIME() = 0; + virtual void didDetachWithIME() {} /** @brief Called by CCIMEDispatcher when some text input from IME. */ - virtual void insertText(const char * text, int len) = 0; + virtual void insertText(const char * text, int len) {} /** @brief Called by CCIMEDispatcher when user clicked the backward key. */ - virtual void deleteBackward() = 0; + virtual void deleteBackward() {} ////////////////////////////////////////////////////////////////////////// // keyboard show/hide notification ////////////////////////////////////////////////////////////////////////// - virtual void keyboardWillShow(CCRect& begin, CCRect& end) {} - virtual void keyboardDidShow(CCRect& begin, CCRect& end) {} - virtual void keyboardWillHide(CCRect& begin, CCRect& end) {} - virtual void keyboardDidHide(CCRect& begin, CCRect& end) {} + virtual void keyboardWillShow(CCIMEKeyboardNotificationInfo& info) {} + virtual void keyboardDidShow(CCIMEKeyboardNotificationInfo& info) {} + virtual void keyboardWillHide(CCIMEKeyboardNotificationInfo& info) {} + virtual void keyboardDidHide(CCIMEKeyboardNotificationInfo& info) {} protected: CCIMEDelegate(); diff --git a/cocos2dx/include/CCIMEDispatcher.h b/cocos2dx/include/CCIMEDispatcher.h index a1c28c0ebc..515c02677a 100644 --- a/cocos2dx/include/CCIMEDispatcher.h +++ b/cocos2dx/include/CCIMEDispatcher.h @@ -25,12 +25,10 @@ THE SOFTWARE. #ifndef __CC_IME_DISPATCHER_H__ #define __CC_IME_DISPATCHER_H__ -#include "CCGeometry.h" +#include "CCIMEDelegate.h" NS_CC_BEGIN; -class CCIMEDelegate; - /** @brief Input Method Edit Message Dispatcher. */ @@ -62,10 +60,10 @@ public: ////////////////////////////////////////////////////////////////////////// // dispatch keyboard notification ////////////////////////////////////////////////////////////////////////// - void dispatchKeyboardWillShow(CCRect& begin, CCRect& end); - void dispatchKeyboardDidShow(CCRect& begin, CCRect& end); - void dispatchKeyboardWillHide(CCRect& begin, CCRect& end); - void dispatchKeyboardDidHide(CCRect& begin, CCRect& end); + void dispatchKeyboardWillShow(CCIMEKeyboardNotificationInfo& info); + void dispatchKeyboardDidShow(CCIMEKeyboardNotificationInfo& info); + void dispatchKeyboardWillHide(CCIMEKeyboardNotificationInfo& info); + void dispatchKeyboardDidHide(CCIMEKeyboardNotificationInfo& info); protected: friend class CCIMEDelegate; @@ -81,6 +79,7 @@ protected: can attach with ime, return true, otherwise return false. */ bool attachDelegateWithIME(CCIMEDelegate * pDelegate); + bool detachDelegateWithIME(CCIMEDelegate * pDelegate); /** @brief remove the delegate from the delegates who concern ime msg diff --git a/cocos2dx/include/CCTextFieldTTF.h b/cocos2dx/include/CCTextFieldTTF.h index d7a6e34ba2..bcf0a73959 100644 --- a/cocos2dx/include/CCTextFieldTTF.h +++ b/cocos2dx/include/CCTextFieldTTF.h @@ -53,9 +53,14 @@ public: bool initWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize); /** - @brief Get keyboard ready and waiting for input. + @brief Open keyboard and receive input text. */ - bool attachWithIME(); + virtual bool attachWithIME(); + + /** + @brief End text input and close keyboard. + */ + virtual bool detachWithIME(); ////////////////////////////////////////////////////////////////////////// // properties @@ -83,8 +88,7 @@ protected: ////////////////////////////////////////////////////////////////////////// virtual bool canAttachWithIME(); - virtual bool canDetatchWithIME(); - virtual void detatchWithIME(); + virtual bool canDetachWithIME(); virtual void insertText(const char * text, int len); virtual void deleteBackward(); diff --git a/cocos2dx/platform/ios/EAGLView.mm b/cocos2dx/platform/ios/EAGLView.mm index 83b14653f0..4945aeccde 100755 --- a/cocos2dx/platform/ios/EAGLView.mm +++ b/cocos2dx/platform/ios/EAGLView.mm @@ -177,6 +177,25 @@ static cocos2d::CCTouch *s_pTouches[MAX_TOUCHES]; return self; } +- (void)didMoveToWindow; +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onUIKeyboardNotification:) + name:UIKeyboardWillShowNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onUIKeyboardNotification:) + name:UIKeyboardDidShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onUIKeyboardNotification:) + name:UIKeyboardWillHideNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onUIKeyboardNotification:) + name:UIKeyboardDidHideNotification object:nil]; + +} + -(int) getWidth { CGSize bound = [self bounds].size; @@ -502,7 +521,7 @@ static cocos2d::CCTouch *s_pTouches[MAX_TOUCHES]; } #pragma mark - -#pragma mark EAGLView - UIKeyInput +#pragma mark UIKeyInput protocol - (BOOL)hasText { @@ -520,6 +539,14 @@ static cocos2d::CCTouch *s_pTouches[MAX_TOUCHES]; cocos2d::CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); } +#pragma mark - +#pragma mark UITextInputTrait protocol + +-(UITextAutocapitalizationType) autocapitalizationType +{ + return UITextAutocapitalizationTypeNone; +} + #pragma mark - #pragma mark UITextInput protocol @@ -691,4 +718,99 @@ static cocos2d::CCTouch *s_pTouches[MAX_TOUCHES]; return nil; } +#pragma mark - +#pragma mark UIKeyboard notification + +- (void)onUIKeyboardNotification:(NSNotification *)notif; +{ + NSString * type = notif.name; + + NSDictionary* info = [notif userInfo]; + CGRect begin = [self convertRect: + [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] + fromView:self]; + CGRect end = [self convertRect: + [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] + fromView:self]; + double aniDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + + CGSize viewSize = self.frame.size; + CGFloat tmp; + + switch ([[UIApplication sharedApplication] statusBarOrientation]) + { + case UIInterfaceOrientationPortrait: + begin.origin.y = viewSize.height - begin.origin.y - begin.size.height; + end.origin.y = viewSize.height - end.origin.y - end.size.height; + break; + + case UIInterfaceOrientationPortraitUpsideDown: + begin.origin.x = viewSize.width - (begin.origin.x + begin.size.width); + end.origin.x = viewSize.width - (end.origin.x + end.size.width); + break; + + case UIInterfaceOrientationLandscapeLeft: + tmp = begin.size.width; + begin.size.width = begin.size.height; + begin.size.height = tmp; + tmp = end.size.width; + end.size.width = end.size.height; + end.size.height = tmp; + + tmp = begin.origin.x; + begin.origin.x = begin.origin.y; + begin.origin.y = viewSize.width - tmp - begin.size.height; + tmp = end.origin.x; + end.origin.x = end.origin.y; + end.origin.y = viewSize.width - tmp - end.size.height; + break; + + case UIInterfaceOrientationLandscapeRight: + tmp = begin.size.width; + begin.size.width = begin.size.height; + begin.size.height = tmp; + tmp = end.size.width; + end.size.width = end.size.height; + end.size.height = tmp; + + tmp = begin.origin.x; + begin.origin.x = begin.origin.y; + begin.origin.y = tmp; + tmp = end.origin.x; + end.origin.x = end.origin.y; + end.origin.y = tmp; + break; + + default: + break; + } + cocos2d::CCIMEKeyboardNotificationInfo notiInfo; + notiInfo.begin = cocos2d::CCRect(begin.origin.x, + begin.origin.y, + begin.size.width, + begin.size.height); + notiInfo.end = cocos2d::CCRect(end.origin.x, + end.origin.y, + end.size.width, + end.size.height); + notiInfo.duration = (float)aniDuration; + cocos2d::CCIMEDispatcher* dispatcher = cocos2d::CCIMEDispatcher::sharedDispatcher(); + if (UIKeyboardWillShowNotification == type) + { + dispatcher->dispatchKeyboardWillShow(notiInfo); + } + else if (UIKeyboardDidShowNotification == type) + { + dispatcher->dispatchKeyboardDidShow(notiInfo); + } + else if (UIKeyboardWillHideNotification == type) + { + dispatcher->dispatchKeyboardWillHide(notiInfo); + } + else if (UIKeyboardDidHideNotification == type) + { + dispatcher->dispatchKeyboardDidHide(notiInfo); + } +} + @end diff --git a/cocos2dx/text_input_node/CCIMEDispatcher.cpp b/cocos2dx/text_input_node/CCIMEDispatcher.cpp index 46981ecd2d..1e21b4dad4 100644 --- a/cocos2dx/text_input_node/CCIMEDispatcher.cpp +++ b/cocos2dx/text_input_node/CCIMEDispatcher.cpp @@ -26,8 +26,6 @@ THE SOFTWARE. #include -#include "CCIMEDelegate.h" - NS_CC_BEGIN; ////////////////////////////////////////////////////////////////////////// @@ -49,6 +47,11 @@ bool CCIMEDelegate::attachWithIME() return CCIMEDispatcher::sharedDispatcher()->attachDelegateWithIME(this); } +bool CCIMEDelegate::detachWithIME() +{ + return CCIMEDispatcher::sharedDispatcher()->detachDelegateWithIME(this); +} + ////////////////////////////////////////////////////////////////////////// typedef std::list< CCIMEDelegate * > DelegateList; @@ -72,7 +75,7 @@ public: void init() { - m_DelegateWithIme = m_DelegateList.end(); + m_DelegateWithIme = 0; } DelegateIter findDelegate(CCIMEDelegate* pDelegate) @@ -88,8 +91,8 @@ public: return end; } - DelegateList m_DelegateList; - DelegateIter m_DelegateWithIme; + DelegateList m_DelegateList; + CCIMEDelegate* m_DelegateWithIme; }; ////////////////////////////////////////////////////////////////////////// @@ -138,20 +141,40 @@ bool CCIMEDispatcher::attachDelegateWithIME(CCIMEDelegate * pDelegate) // if pDelegate is not in delegate list, return CC_BREAK_IF(end == iter); - if (m_pImpl->m_DelegateWithIme != end) + if (m_pImpl->m_DelegateWithIme) { - // if old delegate canDetatchWithIME return false + // if old delegate canDetachWithIME return false // or pDelegate canAttachWithIME return false, // do nothing. - CC_BREAK_IF(! (*(m_pImpl->m_DelegateWithIme))->canDetatchWithIME() + CC_BREAK_IF(! m_pImpl->m_DelegateWithIme->canDetachWithIME() || ! pDelegate->canAttachWithIME()); // detach first - CCIMEDelegate * pOldDelegate = *(m_pImpl->m_DelegateWithIme); - m_pImpl->m_DelegateWithIme = end; - pOldDelegate->detatchWithIME(); + CCIMEDelegate * pOldDelegate = m_pImpl->m_DelegateWithIme; + m_pImpl->m_DelegateWithIme = 0; + pOldDelegate->didDetachWithIME(); } - m_pImpl->m_DelegateWithIme = iter; + m_pImpl->m_DelegateWithIme = *iter; + pDelegate->didAttachWithIME(); + bRet = true; + } while (0); + return bRet; +} + +bool CCIMEDispatcher::detachDelegateWithIME(CCIMEDelegate * pDelegate) +{ + bool bRet = false; + do + { + CC_BREAK_IF(! m_pImpl || ! pDelegate); + + // if pDelegate is not the current delegate attached with ime, return + CC_BREAK_IF(m_pImpl->m_DelegateWithIme != pDelegate); + + CC_BREAK_IF(! pDelegate->canDetachWithIME()); + + m_pImpl->m_DelegateWithIme = 0; + pDelegate->didDetachWithIME(); bRet = true; } while (0); return bRet; @@ -167,10 +190,11 @@ void CCIMEDispatcher::removeDelegate(CCIMEDelegate* pDelegate) DelegateIter end = m_pImpl->m_DelegateList.end(); CC_BREAK_IF(end == iter); - if (m_pImpl->m_DelegateWithIme != end - &&*iter == *(m_pImpl->m_DelegateWithIme)) + if (m_pImpl->m_DelegateWithIme) + + if (*iter == m_pImpl->m_DelegateWithIme) { - m_pImpl->m_DelegateWithIme == end; + m_pImpl->m_DelegateWithIme = 0; } m_pImpl->m_DelegateList.erase(iter); } while (0); @@ -187,10 +211,9 @@ void CCIMEDispatcher::dispatchInsertText(const char * pText, int nLen) CC_BREAK_IF(! m_pImpl || ! pText || nLen <= 0); // there is no delegate attach with ime - CC_BREAK_IF(m_pImpl->m_DelegateWithIme == m_pImpl->m_DelegateList.end()); + CC_BREAK_IF(! m_pImpl->m_DelegateWithIme); - CCIMEDelegate * pDelegate = *(m_pImpl->m_DelegateWithIme); - pDelegate->insertText(pText, nLen); + m_pImpl->m_DelegateWithIme->insertText(pText, nLen); } while (0); } @@ -201,10 +224,9 @@ void CCIMEDispatcher::dispatchDeleteBackward() CC_BREAK_IF(! m_pImpl); // there is no delegate attach with ime - CC_BREAK_IF(m_pImpl->m_DelegateWithIme == m_pImpl->m_DelegateList.end()); + CC_BREAK_IF(! m_pImpl->m_DelegateWithIme); - CCIMEDelegate * pDelegate = *(m_pImpl->m_DelegateWithIme); - pDelegate->deleteBackward(); + m_pImpl->m_DelegateWithIme->deleteBackward(); } while (0); } @@ -212,7 +234,7 @@ void CCIMEDispatcher::dispatchDeleteBackward() // dispatch keyboard message ////////////////////////////////////////////////////////////////////////// -void CCIMEDispatcher::dispatchKeyboardWillShow(CCRect& begin, CCRect& end) +void CCIMEDispatcher::dispatchKeyboardWillShow(CCIMEKeyboardNotificationInfo& info) { if (m_pImpl) { @@ -223,13 +245,13 @@ void CCIMEDispatcher::dispatchKeyboardWillShow(CCRect& begin, CCRect& end) pDelegate = *(first); if (pDelegate) { - pDelegate->keyboardWillShow(begin, end); + pDelegate->keyboardWillShow(info); } } } } -void CCIMEDispatcher::dispatchKeyboardDidShow(CCRect& begin, CCRect& end) +void CCIMEDispatcher::dispatchKeyboardDidShow(CCIMEKeyboardNotificationInfo& info) { if (m_pImpl) { @@ -240,13 +262,13 @@ void CCIMEDispatcher::dispatchKeyboardDidShow(CCRect& begin, CCRect& end) pDelegate = *(first); if (pDelegate) { - pDelegate->keyboardDidShow(begin, end); + pDelegate->keyboardDidShow(info); } } } } -void CCIMEDispatcher::dispatchKeyboardWillHide(CCRect& begin, CCRect& end) +void CCIMEDispatcher::dispatchKeyboardWillHide(CCIMEKeyboardNotificationInfo& info) { if (m_pImpl) { @@ -257,13 +279,13 @@ void CCIMEDispatcher::dispatchKeyboardWillHide(CCRect& begin, CCRect& end) pDelegate = *(first); if (pDelegate) { - pDelegate->keyboardWillHide(begin, end); + pDelegate->keyboardWillHide(info); } } } } -void CCIMEDispatcher::dispatchKeyboardDidHide(CCRect& begin, CCRect& end) +void CCIMEDispatcher::dispatchKeyboardDidHide(CCIMEKeyboardNotificationInfo& info) { if (m_pImpl) { @@ -274,7 +296,7 @@ void CCIMEDispatcher::dispatchKeyboardDidHide(CCRect& begin, CCRect& end) pDelegate = *(first); if (pDelegate) { - pDelegate->keyboardDidHide(begin, end); + pDelegate->keyboardDidHide(info); } } } diff --git a/cocos2dx/text_input_node/CCTextFieldTTF.cpp b/cocos2dx/text_input_node/CCTextFieldTTF.cpp index 5b170b4edd..6e36d7cfb2 100644 --- a/cocos2dx/text_input_node/CCTextFieldTTF.cpp +++ b/cocos2dx/text_input_node/CCTextFieldTTF.cpp @@ -134,25 +134,31 @@ bool CCTextFieldTTF::attachWithIME() return bRet; } +bool CCTextFieldTTF::detachWithIME() +{ + bool bRet = CCIMEDelegate::detachWithIME(); + if (bRet) + { + // close keyboard + CCEGLView * pGlView = CCDirector::sharedDirector()->getOpenGLView(); + if (pGlView) + { + pGlView->setIMEKeyboardState(false); + } + } + return bRet; +} + bool CCTextFieldTTF::canAttachWithIME() { return true; } -bool CCTextFieldTTF::canDetatchWithIME() +bool CCTextFieldTTF::canDetachWithIME() { return true; } -void CCTextFieldTTF::detatchWithIME() -{ - CCEGLView * pGlView = CCDirector::sharedDirector()->getOpenGLView(); - if (pGlView) - { - pGlView->setIMEKeyboardState(false); - } -} - void CCTextFieldTTF::insertText(const char * text, int len) { std::string sInsert(text, len); diff --git a/tests/test.ios/test.xcodeproj/project.pbxproj.REMOVED.git-id b/tests/test.ios/test.xcodeproj/project.pbxproj.REMOVED.git-id index 59f8b8c6fd..1ce1e46c65 100644 --- a/tests/test.ios/test.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/tests/test.ios/test.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -38bdb35f5d331e4f326831460ce303bfed7e29bd \ No newline at end of file +1684c4f675e0f74eb4b6b0dfb3b990900632d290 \ No newline at end of file diff --git a/tests/test.win32/test.win32.vcproj b/tests/test.win32/test.win32.vcproj index 09b357254d..42bb2bb879 100644 --- a/tests/test.win32/test.win32.vcproj +++ b/tests/test.win32/test.win32.vcproj @@ -923,6 +923,18 @@ > + + + + + + diff --git a/tests/tests/controller.cpp b/tests/tests/controller.cpp index a93dd7bd4b..2cefce8aba 100644 --- a/tests/tests/controller.cpp +++ b/tests/tests/controller.cpp @@ -62,8 +62,10 @@ static TestScene* CreateTestScene(int nIdx) #endif #endif #endif - case TEST_ATLAS: + case TEST_LABEL: pScene = new AtlasTestScene(); break; + case TEST_TEXT_INPUT: + pScene = new TextInputTestScene(); break; case TEST_SPRITE: pScene = new SpriteTestScene(); break; case TEST_SCHEDULER: diff --git a/tests/tests/tests.h b/tests/tests/tests.h index ea9a5853a8..502b142a6d 100644 --- a/tests/tests/tests.h +++ b/tests/tests/tests.h @@ -21,6 +21,7 @@ #include "TileMapTest/TileMapTest.h" #include "IntervalTest/IntervalTest.h" #include "LabelTest/LabelTest.h" +#include "TextInputTest/TextInputTest.h" #include "SpriteTest/SpriteTest.h" #include "SchedulerTest/SchedulerTest.h" #include "RenderTextureTest/RenderTextureTest.h" @@ -66,7 +67,8 @@ enum TEST_TILE_MAP, TEST_INTERVAL, TEST_CHIPMUNK, - TEST_ATLAS, + TEST_LABEL, + TEST_TEXT_INPUT, TEST_SPRITE, TEST_SCHEDULER, TEST_RENDERTEXTURE, @@ -105,6 +107,7 @@ const std::string g_aTestNames[TESTS_COUNT] = { "IntervalTest", "ChipmunkTest", "LabelTest", + "TextInputTest", "SpriteTest", "SchdulerTest", "RenderTextureTest", From a73ccaf0e3552c78580f843499da2cc32ac4bbe3 Mon Sep 17 00:00:00 2001 From: yangws Date: Tue, 26 Apr 2011 16:40:49 +0800 Subject: [PATCH 5/5] Cocos2dxGLSurfaceView little modify. --- .../src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java | 7 ++++--- .../src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java index 1a975de2d6..4c91853316 100644 --- a/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java +++ b/HelloWorld/android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java @@ -7,6 +7,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.ViewGroup.LayoutParams; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; @@ -170,12 +171,12 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { if (imm == null) { return; } - imm.showSoftInput(mainView, InputMethodManager.SHOW_IMPLICIT); + imm.showSoftInput(mainView, 0); } public static void closeIMEKeyboard() { - if (null != mainView) { - Log.d("Cocos2dxGLSurfaceView", "closeIMEKeyboard"); + if (null == mainView) { + return; } InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (imm == null) { diff --git a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java index 1a975de2d6..749e28a3c0 100644 --- a/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java +++ b/tests/test.android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java @@ -174,8 +174,8 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView { } public static void closeIMEKeyboard() { - if (null != mainView) { - Log.d("Cocos2dxGLSurfaceView", "closeIMEKeyboard"); + if (null == mainView) { + return; } InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (imm == null) {