Merge pull request #6574 from andyque/focus3861

issue #3861, add focus functionality to ui framework
This commit is contained in:
minggo 2014-05-08 13:44:01 +08:00
commit e9caee282f
33 changed files with 2585 additions and 207 deletions

View File

@ -1093,6 +1093,14 @@
2905FA8D18CF08D100240AA3 /* UIWidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2905FA1318CF08D100240AA3 /* UIWidget.cpp */; };
2905FA8E18CF08D100240AA3 /* UIWidget.h in Headers */ = {isa = PBXBuildFile; fileRef = 2905FA1418CF08D100240AA3 /* UIWidget.h */; };
2905FA8F18CF08D100240AA3 /* UIWidget.h in Headers */ = {isa = PBXBuildFile; fileRef = 2905FA1418CF08D100240AA3 /* UIWidget.h */; };
296CAD221915EC8000C64FBF /* CCEventFocus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 296CAD201915EC8000C64FBF /* CCEventFocus.cpp */; };
296CAD231915EC8000C64FBF /* CCEventFocus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 296CAD201915EC8000C64FBF /* CCEventFocus.cpp */; };
296CAD241915EC8000C64FBF /* CCEventFocus.h in Headers */ = {isa = PBXBuildFile; fileRef = 296CAD211915EC8000C64FBF /* CCEventFocus.h */; };
296CAD251915EC8000C64FBF /* CCEventFocus.h in Headers */ = {isa = PBXBuildFile; fileRef = 296CAD211915EC8000C64FBF /* CCEventFocus.h */; };
296CAD281915EC9900C64FBF /* CCEventListenerFocus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 296CAD261915EC9900C64FBF /* CCEventListenerFocus.cpp */; };
296CAD291915EC9900C64FBF /* CCEventListenerFocus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 296CAD261915EC9900C64FBF /* CCEventListenerFocus.cpp */; };
296CAD2A1915EC9900C64FBF /* CCEventListenerFocus.h in Headers */ = {isa = PBXBuildFile; fileRef = 296CAD271915EC9900C64FBF /* CCEventListenerFocus.h */; };
296CAD2B1915EC9900C64FBF /* CCEventListenerFocus.h in Headers */ = {isa = PBXBuildFile; fileRef = 296CAD271915EC9900C64FBF /* CCEventListenerFocus.h */; };
2986667F18B1B246000E39CA /* CCTweenFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2986667818B1B079000E39CA /* CCTweenFunction.cpp */; };
2AC795DB1862870F005EC8E1 /* SkeletonBounds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AC795D918628689005EC8E1 /* SkeletonBounds.cpp */; };
2AC795DC1862870F005EC8E1 /* Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AC795D51862867D005EC8E1 /* Event.cpp */; };
@ -2279,6 +2287,10 @@
2905FA1218CF08D100240AA3 /* UITextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UITextField.h; sourceTree = "<group>"; };
2905FA1318CF08D100240AA3 /* UIWidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UIWidget.cpp; sourceTree = "<group>"; };
2905FA1418CF08D100240AA3 /* UIWidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIWidget.h; sourceTree = "<group>"; };
296CAD201915EC8000C64FBF /* CCEventFocus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CCEventFocus.cpp; path = ../base/CCEventFocus.cpp; sourceTree = "<group>"; };
296CAD211915EC8000C64FBF /* CCEventFocus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCEventFocus.h; path = ../base/CCEventFocus.h; sourceTree = "<group>"; };
296CAD261915EC9900C64FBF /* CCEventListenerFocus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CCEventListenerFocus.cpp; path = ../base/CCEventListenerFocus.cpp; sourceTree = "<group>"; };
296CAD271915EC9900C64FBF /* CCEventListenerFocus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCEventListenerFocus.h; path = ../base/CCEventListenerFocus.h; sourceTree = "<group>"; };
2986667818B1B079000E39CA /* CCTweenFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCTweenFunction.cpp; sourceTree = "<group>"; };
2986667918B1B079000E39CA /* CCTweenFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTweenFunction.h; sourceTree = "<group>"; };
2AC795D318628672005EC8E1 /* BoundingBoxAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BoundingBoxAttachment.cpp; sourceTree = "<group>"; };
@ -3098,6 +3110,10 @@
500DC92719106300007B91BF /* s3tc.h */,
500DC92819106300007B91BF /* ZipUtils.cpp */,
500DC92919106300007B91BF /* ZipUtils.h */,
296CAD201915EC8000C64FBF /* CCEventFocus.cpp */,
296CAD211915EC8000C64FBF /* CCEventFocus.h */,
296CAD261915EC9900C64FBF /* CCEventListenerFocus.cpp */,
296CAD271915EC9900C64FBF /* CCEventListenerFocus.h */,
);
name = base;
path = ../cocos/2d;
@ -4928,6 +4944,7 @@
500DC94E19106300007B91BF /* CCEvent.h in Headers */,
1A57007F180BC5A10088DEC7 /* CCActionInterval.h in Headers */,
1A01C69A18F57BE800EFE3A6 /* CCSet.h in Headers */,
296CAD2A1915EC9900C64FBF /* CCEventListenerFocus.h in Headers */,
A023FA36185198C800E10CD1 /* ccShader_PositionTextureColor_noMVP_vert.h in Headers */,
1A570083180BC5A10088DEC7 /* CCActionManager.h in Headers */,
1A570087180BC5A10088DEC7 /* CCActionPageTurn3D.h in Headers */,
@ -5078,6 +5095,7 @@
1A570356180BD0B00088DEC7 /* ioapi.h in Headers */,
500DC99619106300007B91BF /* CCScheduler.h in Headers */,
1A57035A180BD0B00088DEC7 /* unzip.h in Headers */,
296CAD241915EC8000C64FBF /* CCEventFocus.h in Headers */,
1A570535180BD9500088DEC7 /* CCGLProgram.h in Headers */,
1AA95FE018EBB8EF00AE7485 /* ccShader_Label_frag_df.h in Headers */,
500DC98819106300007B91BF /* CCNS.h in Headers */,
@ -5463,6 +5481,7 @@
2905FA7B18CF08D100240AA3 /* UISlider.h in Headers */,
1AA95FE318EBB8EF00AE7485 /* ccShader_Label_frag_normal.h in Headers */,
1A5701CE180BCB5A0088DEC7 /* CCLabelTTF.h in Headers */,
296CAD251915EC8000C64FBF /* CCEventFocus.h in Headers */,
50FCEBCA18C72017004AD434 /* WidgetReader.h in Headers */,
1A5701E1180BCB8C0088DEC7 /* CCLayer.h in Headers */,
1A5701E5180BCB8C0088DEC7 /* CCScene.h in Headers */,
@ -5647,6 +5666,7 @@
1A9DCA3C180E6955007A3AD4 /* firePngData.h in Headers */,
1AA95FDF18EBB8EF00AE7485 /* ccShader_Label_frag_df_glow.h in Headers */,
1A01C69F18F57BE800EFE3A6 /* CCString.h in Headers */,
296CAD2B1915EC9900C64FBF /* CCEventListenerFocus.h in Headers */,
1A01C69118F57BE800EFE3A6 /* CCDictionary.h in Headers */,
500DC99B19106300007B91BF /* ccTypes.h in Headers */,
1A8C598E180E930E00EF57C3 /* CCActionFrame.h in Headers */,
@ -6110,6 +6130,7 @@
1A570081180BC5A10088DEC7 /* CCActionManager.cpp in Sources */,
1A570085180BC5A10088DEC7 /* CCActionPageTurn3D.cpp in Sources */,
1A570089180BC5A10088DEC7 /* CCActionProgressTimer.cpp in Sources */,
296CAD281915EC9900C64FBF /* CCEventListenerFocus.cpp in Sources */,
1A57008D180BC5A10088DEC7 /* CCActionTiledGrid.cpp in Sources */,
1A570091180BC5A10088DEC7 /* CCActionTween.cpp in Sources */,
B2AF2F9918EBAEAE00C5807C /* Matrix.cpp in Sources */,
@ -6278,6 +6299,7 @@
1AD71ECD180E26E600808F54 /* Skeleton.cpp in Sources */,
1AD71ED1180E26E600808F54 /* SkeletonData.cpp in Sources */,
1AD71ED5180E26E600808F54 /* SkeletonJson.cpp in Sources */,
296CAD221915EC8000C64FBF /* CCEventFocus.cpp in Sources */,
1AD71ED9180E26E600808F54 /* Skin.cpp in Sources */,
1AD71EDD180E26E600808F54 /* Slot.cpp in Sources */,
1AD71EE1180E26E600808F54 /* SlotData.cpp in Sources */,
@ -6484,6 +6506,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
296CAD291915EC9900C64FBF /* CCEventListenerFocus.cpp in Sources */,
1A01C69918F57BE800EFE3A6 /* CCSet.cpp in Sources */,
1A01C69D18F57BE800EFE3A6 /* CCString.cpp in Sources */,
2986667F18B1B246000E39CA /* CCTweenFunction.cpp in Sources */,
@ -6631,6 +6654,7 @@
1A570306180BCED90088DEC7 /* ccUtils.cpp in Sources */,
1A57030D180BCF190088DEC7 /* CCComponent.cpp in Sources */,
1A570311180BCF190088DEC7 /* CCComponentContainer.cpp in Sources */,
296CAD231915EC8000C64FBF /* CCEventFocus.cpp in Sources */,
1A57031A180BCF430088DEC7 /* ccCArray.cpp in Sources */,
B375107C1823ACA100B3BA6A /* CCPhysicsBodyInfo_chipmunk.cpp in Sources */,
50FCEBB418C72017004AD434 /* SliderReader.cpp in Sources */,

View File

@ -806,6 +806,8 @@
1AF152DA18FD252A00A52F3D /* PerformanceCallbackTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AF152D718FD252A00A52F3D /* PerformanceCallbackTest.cpp */; };
1F33634F18E37E840074764D /* RefPtrTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1F33634D18E37E840074764D /* RefPtrTest.cpp */; };
1F33635018E37E840074764D /* RefPtrTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1F33634D18E37E840074764D /* RefPtrTest.cpp */; };
296CAD4D1917936900C64FBF /* UIFocusTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 296CAD4B1917936900C64FBF /* UIFocusTest.cpp */; };
296CAD4E1917936900C64FBF /* UIFocusTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 296CAD4B1917936900C64FBF /* UIFocusTest.cpp */; };
A05FCACA177C124500BE600E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15C64822165F391E007D4F18 /* Cocoa.framework */; };
A07A521E1783A1D20073F6A7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15C6482E165F399D007D4F18 /* libz.dylib */; };
A07A521F1783A1D20073F6A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15C64832165F3AFD007D4F18 /* Foundation.framework */; };
@ -1834,6 +1836,8 @@
1D6058910D05DD3D006BFB54 /* cpp-tests Mac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cpp-tests Mac.app"; sourceTree = BUILT_PRODUCTS_DIR; };
1F33634D18E37E840074764D /* RefPtrTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RefPtrTest.cpp; sourceTree = "<group>"; };
1F33634E18E37E840074764D /* RefPtrTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefPtrTest.h; sourceTree = "<group>"; };
296CAD4B1917936900C64FBF /* UIFocusTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UIFocusTest.cpp; sourceTree = "<group>"; };
296CAD4C1917936900C64FBF /* UIFocusTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIFocusTest.h; sourceTree = "<group>"; };
46A15F9C1807A4F8005B8026 /* cocos2d_libs.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = cocos2d_libs.xcodeproj; sourceTree = "<group>"; };
A035A71117822E9E00987F6C /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
A07A52291783A1D20073F6A7 /* cpp-tests iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cpp-tests iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -2693,6 +2697,7 @@
1AC359EC18CECF0B00F37B72 /* CocoStudioGUITest */ = {
isa = PBXGroup;
children = (
296CAD4A1917936900C64FBF /* UIFocusTest */,
1AC359ED18CECF0B00F37B72 /* CocosGUIScene.cpp */,
1AC359EE18CECF0B00F37B72 /* CocosGUIScene.h */,
1AC359EF18CECF0B00F37B72 /* CocoStudioGUITest.cpp */,
@ -3686,6 +3691,15 @@
name = tests;
sourceTree = "<group>";
};
296CAD4A1917936900C64FBF /* UIFocusTest */ = {
isa = PBXGroup;
children = (
296CAD4B1917936900C64FBF /* UIFocusTest.cpp */,
296CAD4C1917936900C64FBF /* UIFocusTest.h */,
);
path = UIFocusTest;
sourceTree = "<group>";
};
29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
isa = PBXGroup;
children = (
@ -4633,6 +4647,7 @@
1AC35B6518CECF0C00F37B72 /* EffectsTest.cpp in Sources */,
1AC35B7118CECF0C00F37B72 /* TestHeaderLayer.cpp in Sources */,
1AC35B2118CECF0C00F37B72 /* ActionManagerTest.cpp in Sources */,
296CAD4D1917936900C64FBF /* UIFocusTest.cpp in Sources */,
1AC35BA318CECF0C00F37B72 /* UIImageViewTest_Editor.cpp in Sources */,
1AC35BCF18CECF0C00F37B72 /* UITextFieldTest.cpp in Sources */,
1AC35B9B18CECF0C00F37B72 /* UIButtonTest_Editor.cpp in Sources */,
@ -4804,6 +4819,7 @@
1AC35BDE18CECF0C00F37B72 /* acts.cpp in Sources */,
1AC35B7618CECF0C00F37B72 /* ArmatureScene.cpp in Sources */,
1AC35B8E18CECF0C00F37B72 /* CustomImageView.cpp in Sources */,
296CAD4E1917936900C64FBF /* UIFocusTest.cpp in Sources */,
1AC35B8218CECF0C00F37B72 /* SceneController.cpp in Sources */,
1AC35B3418CECF0C00F37B72 /* Test.cpp in Sources */,
1AC35C2418CECF0C00F37B72 /* ParticleTest.cpp in Sources */,

View File

@ -181,10 +181,12 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou
<ClCompile Include="..\base\CCEventAcceleration.cpp" />
<ClCompile Include="..\base\CCEventCustom.cpp" />
<ClCompile Include="..\base\CCEventDispatcher.cpp" />
<ClCompile Include="..\base\CCEventFocus.cpp" />
<ClCompile Include="..\base\CCEventKeyboard.cpp" />
<ClCompile Include="..\base\CCEventListener.cpp" />
<ClCompile Include="..\base\CCEventListenerAcceleration.cpp" />
<ClCompile Include="..\base\CCEventListenerCustom.cpp" />
<ClCompile Include="..\base\CCEventListenerFocus.cpp" />
<ClCompile Include="..\base\CCEventListenerKeyboard.cpp" />
<ClCompile Include="..\base\CCEventListenerMouse.cpp" />
<ClCompile Include="..\base\CCEventListenerTouch.cpp" />
@ -341,10 +343,12 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou
<ClInclude Include="..\base\CCEventAcceleration.h" />
<ClInclude Include="..\base\CCEventCustom.h" />
<ClInclude Include="..\base\CCEventDispatcher.h" />
<ClInclude Include="..\base\CCEventFocus.h" />
<ClInclude Include="..\base\CCEventKeyboard.h" />
<ClInclude Include="..\base\CCEventListener.h" />
<ClInclude Include="..\base\CCEventListenerAcceleration.h" />
<ClInclude Include="..\base\CCEventListenerCustom.h" />
<ClInclude Include="..\base\CCEventListenerFocus.h" />
<ClInclude Include="..\base\CCEventListenerKeyboard.h" />
<ClInclude Include="..\base\CCEventListenerMouse.h" />
<ClInclude Include="..\base\CCEventListenerTouch.h" />

View File

@ -570,6 +570,12 @@
<ClCompile Include="..\renderer\CCRenderer.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\base\CCEventFocus.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\base\CCEventListenerFocus.cpp">
<Filter>base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\physics\CCPhysicsBody.h">
@ -1154,6 +1160,12 @@
<ClInclude Include="..\renderer\CCRenderer.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\base\CCEventFocus.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\base\CCEventListenerFocus.h">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="..\math\CMakeLists.txt">

View File

@ -293,6 +293,13 @@ public class Cocos2dxGLSurfaceView extends GLSurfaceView {
switch (pKeyCode) {
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MENU:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_DPAD_CENTER:
this.queueEvent(new Runnable() {
@Override
public void run() {

View File

@ -65,28 +65,41 @@ extern "C" {
cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesCancel(size, id, x, y);
}
#define KEYCODE_BACK 0x04
#define KEYCODE_MENU 0x52
#define KEYCODE_BACK 0x04
#define KEYCODE_MENU 0x52
#define KEYCODE_DPAD_UP 0x13
#define KEYCODE_DPAD_DOWN 0x14
#define KEYCODE_DPAD_LEFT 0x15
#define KEYCODE_DPAD_RIGHT 0x16
#define KEYCODE_ENTER 0x42
#define KEYCODE_PLAY 0x7e
#define KEYCODE_DPAD_CENTER 0x17
static std::unordered_map<int, cocos2d::EventKeyboard::KeyCode> g_keyCodeMap = {
{ KEYCODE_BACK , cocos2d::EventKeyboard::KeyCode::KEY_ESCAPE},
{ KEYCODE_MENU , cocos2d::EventKeyboard::KeyCode::KEY_MENU},
{ KEYCODE_DPAD_UP , cocos2d::EventKeyboard::KeyCode::KEY_DPAD_UP },
{ KEYCODE_DPAD_DOWN , cocos2d::EventKeyboard::KeyCode::KEY_DPAD_DOWN },
{ KEYCODE_DPAD_LEFT , cocos2d::EventKeyboard::KeyCode::KEY_DPAD_LEFT },
{ KEYCODE_DPAD_RIGHT , cocos2d::EventKeyboard::KeyCode::KEY_DPAD_RIGHT },
{ KEYCODE_ENTER , cocos2d::EventKeyboard::KeyCode::KEY_ENTER},
{ KEYCODE_PLAY , cocos2d::EventKeyboard::KeyCode::KEY_PLAY},
{ KEYCODE_DPAD_CENTER , cocos2d::EventKeyboard::KeyCode::KEY_DPAD_CENTER},
};
JNIEXPORT jboolean JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeKeyDown(JNIEnv * env, jobject thiz, jint keyCode) {
Director* pDirector = Director::getInstance();
switch (keyCode) {
case KEYCODE_BACK:
{
cocos2d::EventKeyboard event(cocos2d::EventKeyboard::KeyCode::KEY_BACKSPACE, false);
cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);
return JNI_TRUE;
}
case KEYCODE_MENU:
{
cocos2d::EventKeyboard event(cocos2d::EventKeyboard::KeyCode::KEY_MENU, false);
cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);
return JNI_TRUE;
}
default:
return JNI_FALSE;
auto iterKeyCode = g_keyCodeMap.find(keyCode);
if (iterKeyCode == g_keyCodeMap.end()) {
return JNI_FALSE;
}
return JNI_FALSE;
}
}
cocos2d::EventKeyboard::KeyCode cocos2dKey = g_keyCodeMap.at(keyCode);
cocos2d::EventKeyboard event(cocos2dKey, false);
cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);
return JNI_TRUE;
}}

View File

@ -121,6 +121,8 @@ base/CCEventListenerMouse.cpp \
base/CCEventListenerTouch.cpp \
base/CCEventMouse.cpp \
base/CCEventTouch.cpp \
base/CCEventFocus.cpp \
base/CCEventListenerFocus.cpp \
base/CCNS.cpp \
base/CCProfiling.cpp \
base/CCRef.cpp \

View File

@ -48,6 +48,7 @@ public:
KEYBOARD,
ACCELERATION,
MOUSE,
FOCUS,
CUSTOM
};

View File

@ -30,6 +30,7 @@
#include "base/CCEventListenerMouse.h"
#include "base/CCEventListenerKeyboard.h"
#include "base/CCEventListenerCustom.h"
#include "base/CCEventListenerFocus.h"
#include "2d/CCScene.h"
#include "base/CCDirector.h"
@ -85,6 +86,9 @@ static EventListener::ListenerID __getListenerID(Event* event)
case Event::Type::MOUSE:
ret = EventListenerMouse::LISTENER_ID;
break;
case Event::Type::FOCUS:
ret = EventListenerFocus::LISTENER_ID;
break;
case Event::Type::TOUCH:
// Touch listener is very special, it contains two kinds of listeners, EventListenerTouchOneByOne and EventListenerTouchAllAtOnce.
// return UNKNOWN instead.

View File

@ -0,0 +1,42 @@
/****************************************************************************
Copyright (c) 2014 cocos2d-x.org
Copyright (c) 2014 Chukong Technologies Inc.
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 "CCEventFocus.h"
NS_CC_BEGIN
EventFocus::EventFocus(ui::Widget *widgetLoseFocus, ui::Widget* widgetGetFocus)
:Event(Type::FOCUS),
_widgetLoseFocus(widgetLoseFocus),
_widgetGetFocus(widgetGetFocus)
{
}
NS_CC_END

53
cocos/base/CCEventFocus.h Normal file
View File

@ -0,0 +1,53 @@
/****************************************************************************
Copyright (c) 2014 cocos2d-x.org
Copyright (c) 2014 Chukong Technologies Inc.
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 __cocos2d_libs__CCEventFocus__
#define __cocos2d_libs__CCEventFocus__
#include "CCEvent.h"
NS_CC_BEGIN
namespace ui {
class Widget;
}
class EventFocus : public Event
{
public:
EventFocus(ui::Widget* widgetLoseFocus, ui::Widget* widgetGetFocus);
private:
ui::Widget *_widgetGetFocus;
ui::Widget *_widgetLoseFocus;
friend class EventListenerFocus;
};
NS_CC_END
#endif /* defined(__cocos2d_libs__CCEventFocus__) */

View File

@ -38,162 +38,169 @@ public:
*/
enum class KeyCode
{
KEY_NONE = 0,
KEY_PAUSE = 0x0013,
KEY_SCROLL_LOCK = 0x1014,
KEY_PRINT = 0x1061,
KEY_SYSREQ = 0x106A,
KEY_BREAK = 0x106B,
KEY_ESCAPE = 0x001B,
KEY_BACKSPACE = 0x0008,
KEY_TAB = 0x0009,
KEY_BACK_TAB = 0x0089,
KEY_RETURN = 0x000D,
KEY_CAPS_LOCK = 0x00E5,
KEY_SHIFT = 0x00E1,
KEY_CTRL = 0x00E3,
KEY_ALT = 0x00E9,
KEY_MENU = 0x1067,
KEY_HYPER = 0x10ED,
KEY_INSERT = 0x1063,
KEY_HOME = 0x1050,
KEY_PG_UP = 0x1055,
KEY_DELETE = 0x10FF,
KEY_END = 0x1057,
KEY_PG_DOWN = 0x1056,
KEY_LEFT_ARROW = 0x1051,
KEY_RIGHT_ARROW = 0x1053,
KEY_UP_ARROW = 0x1052,
KEY_DOWN_ARROW = 0x1054,
KEY_NUM_LOCK = 0x107F,
KEY_KP_PLUS = 0x10AB,
KEY_KP_MINUS = 0x10AD,
KEY_KP_MULTIPLY = 0x10AA,
KEY_KP_DIVIDE = 0x10AF,
KEY_KP_ENTER = 0x108D,
KEY_KP_HOME = 0x10B7,
KEY_KP_UP = 0x10B8,
KEY_KP_PG_UP = 0x10B9,
KEY_KP_LEFT = 0x10B4,
KEY_KP_FIVE = 0x10B5,
KEY_KP_RIGHT = 0x10B6,
KEY_KP_END = 0x10B1,
KEY_KP_DOWN = 0x10B2,
KEY_KP_PG_DOWN = 0x10B3,
KEY_KP_INSERT = 0x10B0,
KEY_KP_DELETE = 0x10AE,
KEY_F1 = 0x00BE,
KEY_F2 = 0x00BF,
KEY_F3 = 0x00C0,
KEY_F4 = 0x00C1,
KEY_F5 = 0x00C2,
KEY_F6 = 0x00C3,
KEY_F7 = 0x00C4,
KEY_F8 = 0x00C5,
KEY_F9 = 0x00C6,
KEY_F10 = 0x00C7,
KEY_F11 = 0x00C8,
KEY_F12 = 0x00C9,
KEY_SPACE = ' ',
KEY_EXCLAM = '!',
KEY_QUOTE = '"',
KEY_NUMBER = '#',
KEY_DOLLAR = '$',
KEY_PERCENT = '%',
KEY_CIRCUMFLEX = '^',
KEY_AMPERSAND = '&',
KEY_APOSTROPHE = '\'',
KEY_LEFT_PARENTHESIS = '(',
KEY_RIGHT_PARENTHESIS = ')',
KEY_ASTERISK = '*',
KEY_PLUS = '+',
KEY_COMMA = ',',
KEY_MINUS = '-',
KEY_PERIOD = '.',
KEY_SLASH = '/',
KEY_0 = '0',
KEY_1 = '1',
KEY_2 = '2',
KEY_3 = '3',
KEY_4 = '4',
KEY_5 = '5',
KEY_6 = '6',
KEY_7 = '7',
KEY_8 = '8',
KEY_9 = '9',
KEY_COLON = ':',
KEY_SEMICOLON = ';',
KEY_LESS_THAN = '<',
KEY_EQUAL = '=',
KEY_GREATER_THAN = '>',
KEY_QUESTION = '?',
KEY_AT = '@',
KEY_CAPITAL_A = 'A',
KEY_CAPITAL_B = 'B',
KEY_CAPITAL_C = 'C',
KEY_CAPITAL_D = 'D',
KEY_CAPITAL_E = 'E',
KEY_CAPITAL_F = 'F',
KEY_CAPITAL_G = 'G',
KEY_CAPITAL_H = 'H',
KEY_CAPITAL_I = 'I',
KEY_CAPITAL_J = 'J',
KEY_CAPITAL_K = 'K',
KEY_CAPITAL_L = 'L',
KEY_CAPITAL_M = 'M',
KEY_CAPITAL_N = 'N',
KEY_CAPITAL_O = 'O',
KEY_CAPITAL_P = 'P',
KEY_CAPITAL_Q = 'Q',
KEY_CAPITAL_R = 'R',
KEY_CAPITAL_S = 'S',
KEY_CAPITAL_T = 'T',
KEY_CAPITAL_U = 'U',
KEY_CAPITAL_V = 'V',
KEY_CAPITAL_W = 'W',
KEY_CAPITAL_X = 'X',
KEY_CAPITAL_Y = 'Y',
KEY_CAPITAL_Z = 'Z',
KEY_LEFT_BRACKET = '[',
KEY_BACK_SLASH = '\\',
KEY_RIGHT_BRACKET = ']',
KEY_UNDERSCORE = '_',
KEY_GRAVE = '`',
KEY_A = 'a',
KEY_B = 'b',
KEY_C = 'c',
KEY_D = 'd',
KEY_E = 'e',
KEY_F = 'f',
KEY_G = 'g',
KEY_H = 'h',
KEY_I = 'i',
KEY_J = 'j',
KEY_K = 'k',
KEY_L = 'l',
KEY_M = 'm',
KEY_N = 'n',
KEY_O = 'o',
KEY_P = 'p',
KEY_Q = 'q',
KEY_R = 'r',
KEY_S = 's',
KEY_T = 't',
KEY_U = 'u',
KEY_V = 'v',
KEY_W = 'w',
KEY_X = 'x',
KEY_Y = 'y',
KEY_Z = 'z',
KEY_LEFT_BRACE = '{',
KEY_BAR = '|',
KEY_RIGHT_BRACE = '}',
KEY_TILDE = '~',
KEY_EURO = 0x20AC,
KEY_POUND = 0x00A3,
KEY_YEN = 0x00A5,
KEY_MIDDLE_DOT = 0x0095,
KEY_SEARCH = 0xFFAA
KEY_NONE,
KEY_PAUSE,
KEY_SCROLL_LOCK,
KEY_PRINT,
KEY_SYSREQ,
KEY_BREAK,
KEY_ESCAPE,
KEY_BACKSPACE,
KEY_TAB,
KEY_BACK_TAB,
KEY_RETURN,
KEY_CAPS_LOCK,
KEY_SHIFT,
KEY_CTRL,
KEY_ALT,
KEY_MENU,
KEY_HYPER,
KEY_INSERT,
KEY_HOME,
KEY_PG_UP,
KEY_DELETE,
KEY_END,
KEY_PG_DOWN,
KEY_LEFT_ARROW,
KEY_RIGHT_ARROW,
KEY_UP_ARROW,
KEY_DOWN_ARROW,
KEY_NUM_LOCK,
KEY_KP_PLUS,
KEY_KP_MINUS,
KEY_KP_MULTIPLY,
KEY_KP_DIVIDE,
KEY_KP_ENTER,
KEY_KP_HOME,
KEY_KP_UP,
KEY_KP_PG_UP,
KEY_KP_LEFT,
KEY_KP_FIVE,
KEY_KP_RIGHT,
KEY_KP_END,
KEY_KP_DOWN,
KEY_KP_PG_DOWN,
KEY_KP_INSERT,
KEY_KP_DELETE,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEY_SPACE,
KEY_EXCLAM,
KEY_QUOTE,
KEY_NUMBER,
KEY_DOLLAR,
KEY_PERCENT,
KEY_CIRCUMFLEX,
KEY_AMPERSAND,
KEY_APOSTROPHE,
KEY_LEFT_PARENTHESIS,
KEY_RIGHT_PARENTHESIS,
KEY_ASTERISK,
KEY_PLUS,
KEY_COMMA,
KEY_MINUS,
KEY_PERIOD,
KEY_SLASH,
KEY_0,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_COLON,
KEY_SEMICOLON,
KEY_LESS_THAN,
KEY_EQUAL,
KEY_GREATER_THAN,
KEY_QUESTION,
KEY_AT,
KEY_CAPITAL_A,
KEY_CAPITAL_B,
KEY_CAPITAL_C,
KEY_CAPITAL_D,
KEY_CAPITAL_E,
KEY_CAPITAL_F,
KEY_CAPITAL_G,
KEY_CAPITAL_H,
KEY_CAPITAL_I,
KEY_CAPITAL_J,
KEY_CAPITAL_K,
KEY_CAPITAL_L,
KEY_CAPITAL_M,
KEY_CAPITAL_N,
KEY_CAPITAL_O,
KEY_CAPITAL_P,
KEY_CAPITAL_Q,
KEY_CAPITAL_R,
KEY_CAPITAL_S,
KEY_CAPITAL_T,
KEY_CAPITAL_U,
KEY_CAPITAL_V,
KEY_CAPITAL_W,
KEY_CAPITAL_X,
KEY_CAPITAL_Y,
KEY_CAPITAL_Z,
KEY_LEFT_BRACKET,
KEY_BACK_SLASH,
KEY_RIGHT_BRACKET,
KEY_UNDERSCORE,
KEY_GRAVE,
KEY_A,
KEY_B,
KEY_C,
KEY_D,
KEY_E,
KEY_F,
KEY_G,
KEY_H,
KEY_I,
KEY_J,
KEY_K,
KEY_L,
KEY_M,
KEY_N,
KEY_O,
KEY_P,
KEY_Q,
KEY_R,
KEY_S,
KEY_T,
KEY_U,
KEY_V,
KEY_W,
KEY_X,
KEY_Y,
KEY_Z,
KEY_LEFT_BRACE,
KEY_BAR,
KEY_RIGHT_BRACE,
KEY_TILDE,
KEY_EURO,
KEY_POUND,
KEY_YEN,
KEY_MIDDLE_DOT,
KEY_SEARCH,
KEY_DPAD_LEFT,
KEY_DPAD_RIGHT,
KEY_DPAD_UP,
KEY_DPAD_DOWN,
KEY_DPAD_CENTER,
KEY_ENTER,
KEY_PLAY,
};
EventKeyboard(KeyCode keyCode, bool isPressed);

View File

@ -54,6 +54,7 @@ public:
KEYBOARD,
MOUSE,
ACCELERATION,
FOCUS,
CUSTOM
};

View File

@ -0,0 +1,98 @@
/****************************************************************************
Copyright (c) 2014 cocos2d-x.org
Copyright (c) 2014 Chukong Technologies Inc.
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 "CCEventListenerFocus.h"
#include "CCEventFocus.h"
#include "ccMacros.h"
NS_CC_BEGIN
const std::string EventListenerFocus::LISTENER_ID = "__cc_focus_event";
EventListenerFocus::EventListenerFocus()
:onFocusChanged(nullptr)
{
}
EventListenerFocus::~EventListenerFocus()
{
CCLOGINFO("In the destructor of EventListenerFocus, %p", this);
}
EventListenerFocus* EventListenerFocus::create()
{
EventListenerFocus* ret = new EventListenerFocus;
if (ret && ret->init()) {
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
EventListenerFocus* EventListenerFocus::clone()
{
EventListenerFocus* ret = new EventListenerFocus;
if (ret && ret->init()) {
ret->autorelease();
ret->onFocusChanged = onFocusChanged;
}
else
{
CC_SAFE_DELETE(ret);
}
return ret;
}
bool EventListenerFocus::init()
{
auto listener = [this](Event* event){
auto focusEvent = static_cast<EventFocus*>(event);
onFocusChanged(focusEvent->_widgetLoseFocus, focusEvent->_widgetGetFocus);
};
if (EventListener::init(Type::FOCUS, LISTENER_ID, listener)) {
return true;
}
return false;
}
bool EventListenerFocus::checkAvailable()
{
if (onFocusChanged == nullptr)
{
CCASSERT(false, "Invalid EventListenerFocus!");
return false;
}
return true;
}
NS_CC_END

View File

@ -0,0 +1,65 @@
/****************************************************************************
Copyright (c) 2014 cocos2d-x.org
Copyright (c) 2014 Chukong Technologies Inc.
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 __cocos2d_libs__CCEventListenerFocus__
#define __cocos2d_libs__CCEventListenerFocus__
#include "CCEventListener.h"
NS_CC_BEGIN
namespace ui {
class Widget;
}
class EventListenerFocus : public EventListener
{
public:
static const std::string LISTENER_ID;
static EventListenerFocus* create();
virtual ~EventListenerFocus();
/// Overrides
virtual EventListenerFocus* clone() override;
virtual bool checkAvailable() override;
//
public:
std::function<void(ui::Widget*, ui::Widget*)> onFocusChanged;
private:
EventListenerFocus();
bool init();
friend class EventDispatcher;
};
NS_CC_END
#endif /* defined(__cocos2d_libs__CCEventListenerFocus__) */

View File

@ -20,6 +20,8 @@ set(COCOS_BASE_SRC
base/CCEventListenerTouch.cpp
base/CCEventMouse.cpp
base/CCEventTouch.cpp
base/CCEventFocus.cpp
base/CCEventListenerFocus.cpp
base/CCNS.cpp
base/CCProfiling.cpp
base/CCRef.cpp

View File

@ -69,6 +69,8 @@ THE SOFTWARE.
#include "base/CCEventListenerAcceleration.h"
#include "base/CCEventCustom.h"
#include "base/CCEventListenerCustom.h"
#include "base/CCEventFocus.h"
#include "base/CCEventListenerFocus.h"
// math
#include "math/CCAffineTransform.h"

View File

@ -293,7 +293,7 @@ void CheckBox::loadTextureFrontCrossDisabled(const std::string& frontCrossDisabl
void CheckBox::onTouchEnded(Touch *touch, Event *unusedEvent)
{
_touchEndPos = touch->getLocation();
if (_focus)
if (_highlight)
{
releaseUpEvent();
if (_isSelected){
@ -306,7 +306,7 @@ void CheckBox::onTouchEnded(Touch *touch, Event *unusedEvent)
selectedEvent();
}
}
setFocused(false);
setHighlighted(false);
Widget* widgetParent = getWidgetParent();
if (widgetParent)
{

View File

@ -604,9 +604,12 @@ _currentAlphaTestFunc(GL_ALWAYS),
_currentAlphaTestRef(1),
_backGroundImageColor(Color3B::WHITE),
_backGroundImageOpacity(255),
_curLayoutExecutant(nullptr)
_curLayoutExecutant(nullptr),
_passFocusToChild(true),
_loopFocus(false)
{
_widgetType = WidgetTypeContainer;
onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
}
Layout::~Layout()
@ -1514,5 +1517,911 @@ void Layout::copySpecialProperties(Widget *widget)
setClippingType(layout->_clippingType);
}
}
void Layout::setLoopFocus(bool loop)
{
_loopFocus = loop;
}
bool Layout::isLoopFocus()
{
return _loopFocus;
}
void Layout::setPassFocusToChild(bool pass)
{
_passFocusToChild = pass;
}
bool Layout::isPassFocusToChild()
{
return _passFocusToChild;
}
Size Layout::getLayoutContentSize()const
{
const auto& children = this->getChildren();
Size layoutSize = Size::ZERO;
int widgetCount =0;
for(const auto& widget : children)
{
Layout *layout = dynamic_cast<Layout*>(widget);
if (nullptr != layout)
{
layoutSize = layoutSize + layout->getLayoutContentSize();
}
else
{
Widget *w = dynamic_cast<Widget*>(widget);
if (w)
{
widgetCount++;
Margin m = w->getLayoutParameter(LAYOUT_PARAMETER_LINEAR)->getMargin();
layoutSize = layoutSize + w->getSize() + Size(m.right + m.left, m.top + m.bottom) * 0.5;
}
}
}
//substract extra size
LayoutType type = this->getLayoutType();
if (type == LAYOUT_LINEAR_HORIZONTAL)
{
layoutSize = layoutSize - Size(0, layoutSize.height/widgetCount * (widgetCount-1));
}
if (type == LAYOUT_LINEAR_VERTICAL)
{
layoutSize = layoutSize - Size(layoutSize.width/widgetCount * (widgetCount-1), 0);
}
return layoutSize;
}
Vector2 Layout::getWorldCenterPoint(Widget* widget)
{
Layout *layout = dynamic_cast<Layout*>(widget);
//FIXEDME: we don't need to calculate the content size of layout anymore
Size widgetSize = layout ? layout->getLayoutContentSize() : widget->getSize();
// CCLOG("contnet size : width = %f, height = %f", widgetSize.width, widgetSize.height);
return widget->convertToWorldSpace(Vector2(widgetSize.width/2, widgetSize.height/2));
}
float Layout::caculateNearestDistance(Widget* baseWidget)
{
float distance = FLT_MAX;
Vector2 widgetPosition = this->getWorldCenterPoint(baseWidget);
for (Node* node : _children) {
Layout *layout = dynamic_cast<Layout*>(node);
int length;
if (layout) {
length = layout->caculateNearestDistance(baseWidget);
}
else
{
Widget* w = dynamic_cast<Widget*>(node);
if (w && w->isFocusEnabled()) {
Vector2 wPosition = this->getWorldCenterPoint(w);
length = (wPosition - widgetPosition).length();
}
else {
continue;
}
}
if (length < distance) {
distance = length;
}
}
return distance;
}
float Layout::caculateFarestDistance(cocos2d::ui::Widget *baseWidget)
{
float distance = -FLT_MAX;
Vector2 widgetPosition = this->getWorldCenterPoint(baseWidget);
for (Node* node : _children) {
Layout *layout = dynamic_cast<Layout*>(node);
int length;
if (layout) {
length = layout->caculateFarestDistance(baseWidget);
}
else
{
Widget* w = dynamic_cast<Widget*>(node);
if (w && w->isFocusEnabled()) {
Vector2 wPosition = this->getWorldCenterPoint(w);
length = (wPosition - widgetPosition).length();
}
else {
continue;
}
}
if (length > distance) {
distance = length;
}
}
return distance;
}
int Layout::findFirstFocusEnabledWidgetIndex()
{
ssize_t index = 0;
ssize_t count = this->getChildren().size();
while (index < count) {
Widget* w = dynamic_cast<Widget*>(_children.at(index));
if (w && w->isFocusEnabled()) {
return (int)index;
}
index++;
}
CCASSERT(0, "invalide operation");
return 0;
}
int Layout::findNearestChildWidgetIndex(FocusDirection direction, Widget* baseWidget)
{
if (baseWidget == nullptr || baseWidget == this)
{
return this->findFirstFocusEnabledWidgetIndex();
}
int index = 0;
ssize_t count = this->getChildren().size();
float distance = FLT_MAX;
int found = 0;
if (direction == FocusDirection::FocusDirection_Left || direction == FocusDirection::FocusDirection_Right)
{
Vector2 widgetPosition = this->getWorldCenterPoint(baseWidget);
while (index < count)
{
Widget *w = dynamic_cast<Widget*>(this->getChildren().at(index));
if (w && w->isFocusEnabled())
{
Vector2 wPosition = this->getWorldCenterPoint(w);
float length;
Layout *layout = dynamic_cast<Layout*>(w);
if (layout)
{
length = layout->caculateNearestDistance(baseWidget);
}
else
{
length = (wPosition - widgetPosition).getLength();
}
if (length < distance)
{
found = index;
distance = length;
}
}
index++;
}
return found;
}
index = 0;
found = 0;
distance = FLT_MAX;
if (direction == FocusDirection::FocusDirection_Down || direction == FocusDirection::FocusDirection_Up) {
Vector2 widgetPosition = this->getWorldCenterPoint(baseWidget);
while (index < count)
{
Widget *w = dynamic_cast<Widget*>(this->getChildren().at(index));
if (w && w->isFocusEnabled())
{
Vector2 wPosition = this->getWorldCenterPoint(w);
float length;
Layout *layout = dynamic_cast<Layout*>(w);
if (layout)
{
length = layout->caculateNearestDistance(baseWidget);
}
else
{
length = (wPosition - widgetPosition).getLength();
}
if (length < distance)
{
found = index;
distance = length;
}
}
index++;
}
return found;
}
CCASSERT(0, "invalid focus direction!!!");
return 0;
}
int Layout::findFarestChildWidgetIndex(cocos2d::ui::FocusDirection direction, cocos2d::ui::Widget *baseWidget)
{
if (baseWidget == nullptr || baseWidget == this)
{
return this->findFirstFocusEnabledWidgetIndex();
}
int index = 0;
ssize_t count = this->getChildren().size();
float distance = -FLT_MAX;
int found = 0;
if (direction == FocusDirection::FocusDirection_Left || direction == FocusDirection::FocusDirection_Right)
{
Vector2 widgetPosition = this->getWorldCenterPoint(baseWidget);
while (index < count)
{
Widget *w = dynamic_cast<Widget*>(this->getChildren().at(index));
if (w && w->isFocusEnabled())
{
Vector2 wPosition = this->getWorldCenterPoint(w);
float length;
Layout *layout = dynamic_cast<Layout*>(w);
if (layout)
{
length = layout->caculateFarestDistance(baseWidget);
}
else
{
length = (wPosition - widgetPosition).getLength();
}
if (length > distance)
{
found = index;
distance = length;
}
}
index++;
}
return found;
}
index = 0;
found = 0;
distance = -FLT_MAX;
if (direction == FocusDirection::FocusDirection_Down || direction == FocusDirection::FocusDirection_Up) {
Vector2 widgetPosition = this->getWorldCenterPoint(baseWidget);
while (index < count)
{
Widget *w = dynamic_cast<Widget*>(this->getChildren().at(index));
if (w && w->isFocusEnabled())
{
Vector2 wPosition = this->getWorldCenterPoint(w);
float length;
Layout *layout = dynamic_cast<Layout*>(w);
if (layout)
{
length = layout->caculateFarestDistance(baseWidget);
}
else
{
length = (wPosition - widgetPosition).getLength();
}
if (length > distance)
{
found = index;
distance = length;
}
}
index++;
}
return found;
}
CCASSERT(0, "invalid focus direction!!!");
return 0;
}
Widget* Layout::findFocusEnabledChildWidgetByIndex(ssize_t index)
{
Widget *widget = this->getChildWidgetByIndex(index);
if (widget)
{
if (widget->isFocusEnabled())
{
return widget;
}
index = index + 1;
return this->findFocusEnabledChildWidgetByIndex(index);
}
return nullptr;
}
Widget *Layout::findFirstNonLayoutWidget()
{
Widget* widget = nullptr;
for(Node *node : _children)
{
Layout* layout = dynamic_cast<Layout*>(node);
if (layout) {
widget = layout->findFirstNonLayoutWidget();
}
else{
Widget *w = dynamic_cast<Widget*>(node);
if (w) {
widget = w;
break;
}
}
}
return widget;
}
void Layout::findProperSearchingFunctor(FocusDirection dir, Widget* baseWidget)
{
if (baseWidget == nullptr) {
return;
}
Vector2 previousWidgetPosition = this->getWorldCenterPoint(baseWidget);
Vector2 layoutPosition = this->getWorldCenterPoint(this->findFirstNonLayoutWidget());
if (dir == FocusDirection::FocusDirection_Left) {
if (previousWidgetPosition.x > layoutPosition.x) {
onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
}
else{
onPassFocusToChild = CC_CALLBACK_2(Layout::findFarestChildWidgetIndex, this);
}
}else if(dir == FocusDirection::FocusDirection_Right){
if (previousWidgetPosition.x > layoutPosition.x) {
onPassFocusToChild = CC_CALLBACK_2(Layout::findFarestChildWidgetIndex, this);
}
else{
onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
}
}else if(dir == FocusDirection::FocusDirection_Down){
if (previousWidgetPosition.y > layoutPosition.y) {
onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
}else{
onPassFocusToChild = CC_CALLBACK_2(Layout::findFarestChildWidgetIndex, this);
}
}else if(dir == FocusDirection::FocusDirection_Up){
if (previousWidgetPosition.y < layoutPosition.y) {
onPassFocusToChild = CC_CALLBACK_2(Layout::findNearestChildWidgetIndex, this);
}else{
onPassFocusToChild = CC_CALLBACK_2(Layout::findFarestChildWidgetIndex, this);
}
}else{
CCASSERT(0, "invalid direction!");
}
}
Widget* Layout::passFocusToChild(cocos2d::ui::FocusDirection dir, cocos2d::ui::Widget *current)
{
if (checkFocusEnabledChild())
{
Widget* previousWidget = this->getCurrentFocusedWidget(true);
this->findProperSearchingFunctor(dir, previousWidget);
int index = onPassFocusToChild(dir, previousWidget);
Widget *widget = this->getChildWidgetByIndex(index);
this->dispatchFocusEvent(current, widget);
Layout *layout = dynamic_cast<Layout*>(widget);
if (layout)
{
return layout->findNextFocusedWidget(dir, layout);
}
else
{
return widget;
}
}
else
{
return this;
}
}
bool Layout::checkFocusEnabledChild()
{
bool ret = false;
for(Node* node : _children)
{
Widget* widget = dynamic_cast<Widget*>(node);
if (widget && widget->isFocusEnabled())
{
ret = true;
break;
}
}
return ret;
}
Widget* Layout::getChildWidgetByIndex(ssize_t index)
{
ssize_t size = _children.size();
int count = 0;
ssize_t oldIndex = index;
Widget *widget = nullptr;
while (index < size)
{
Widget* firstChild = dynamic_cast<Widget*>(_children.at(index));
if (firstChild)
{
widget = firstChild;
break;
}
count++;
index++;
}
if (nullptr == widget)
{
int begin = 0;
while (begin < oldIndex)
{
Widget* firstChild = dynamic_cast<Widget*>(_children.at(begin));
if (firstChild)
{
widget = firstChild;
break;
}
count++;
begin++;
}
}
return widget;
}
Widget* Layout::getPreviousFocusedWidget(FocusDirection direction, Widget *current)
{
Widget *nextWidget = nullptr;
ssize_t previousWidgetPos = _children.getIndex(current);
previousWidgetPos = previousWidgetPos - 1;
if (previousWidgetPos >= 0)
{
nextWidget = this->getChildWidgetByIndex(previousWidgetPos);
if (nextWidget->isFocusEnabled())
{
this->dispatchFocusEvent(current, nextWidget);
Layout* layout = dynamic_cast<Layout*>(nextWidget);
if (layout)
{
return layout->findNextFocusedWidget(direction, layout);
}
return nextWidget;
}
else
{
//handling the disabled widget, there is no actual focus lose or get, so we don't need any envet
return this->getPreviousFocusedWidget(direction, nextWidget);
}
}else
{
if (_loopFocus)
{
if (checkFocusEnabledChild())
{
previousWidgetPos = _children.size()-1;
nextWidget = this->getChildWidgetByIndex(previousWidgetPos);
if (nextWidget->isFocusEnabled())
{
this->dispatchFocusEvent(current, nextWidget);
Layout* layout = dynamic_cast<Layout*>(nextWidget);
if (layout)
{
return layout->findNextFocusedWidget(direction, layout);
}
else
{
return nextWidget;
}
}
else
{
return this->getPreviousFocusedWidget(direction, nextWidget);
}
}
else
{
if (dynamic_cast<Layout*>(current)) {
return current;
}
else
{
return _focusedWidget;
}
}
}
else
{
if (isLastWidgetInContainer(current, direction))
{
if (isWidgetAncestorSupportLoopFocus(this, direction))
{
this->dispatchFocusEvent(current, this);
return Widget::findNextFocusedWidget(direction, this);
}
if (dynamic_cast<Layout*>(current)) {
return current;
}
else
{
return _focusedWidget;
}
}
else
{
//call parent method to get its parent's next focus enabled widget
this->dispatchFocusEvent(current,this);
return Widget::findNextFocusedWidget(direction, this);
}
}
}
}
Widget* Layout::getNextFocusedWidget(FocusDirection direction, Widget *current)
{
Widget *nextWidget = nullptr;
ssize_t previousWidgetPos = _children.getIndex(current);
previousWidgetPos = previousWidgetPos + 1;
if (previousWidgetPos < _children.size())
{
nextWidget = this->getChildWidgetByIndex(previousWidgetPos);
//handle widget
if (nextWidget)
{
if (nextWidget->isFocusEnabled())
{
this->dispatchFocusEvent(current, nextWidget);
Layout* layout = dynamic_cast<Layout*>(nextWidget);
if (layout)
{
return layout->findNextFocusedWidget(direction, layout);
}
else
{
return nextWidget;
}
}
else
{
return this->getNextFocusedWidget(direction, nextWidget);
}
}
else
{
return current;
}
}else
{
if (_loopFocus)
{
if (checkFocusEnabledChild())
{
previousWidgetPos = 0;
nextWidget = this->getChildWidgetByIndex(previousWidgetPos);
if (nextWidget->isFocusEnabled())
{
this->dispatchFocusEvent(current, nextWidget);
Layout* layout = dynamic_cast<Layout*>(nextWidget);
if (layout)
{
return layout->findNextFocusedWidget(direction, layout);
}else
{
return nextWidget;
}
}
else
{
return this->getNextFocusedWidget(direction, nextWidget);
}
}
else
{
if (dynamic_cast<Layout*>(current)) {
return current;
}
else
{
return _focusedWidget;
}
}
}
else{
if (isLastWidgetInContainer(current, direction))
{
if (isWidgetAncestorSupportLoopFocus(this, direction))
{
this->dispatchFocusEvent(current, this);
return Widget::findNextFocusedWidget(direction, this);
}
if (dynamic_cast<Layout*>(current)) {
return current;
}
else
{
return _focusedWidget;
}
}
else
{
//call parent method to get its parent's next focus enabled widget
this->dispatchFocusEvent(current,this);
return Widget::findNextFocusedWidget(direction, this);
}
}
}
}
bool Layout::isLastWidgetInContainer(Widget* widget, FocusDirection direction)
{
Layout* parent = dynamic_cast<Layout*>(widget->getParent());
if (parent == nullptr)
{
return true;
}
auto container = parent->getChildren();
ssize_t index = container.getIndex(widget);
if (parent->getLayoutType() == LAYOUT_LINEAR_HORIZONTAL)
{
if (direction == FocusDirection::FocusDirection_Left) {
if (index == 0)
{
return true * isLastWidgetInContainer(parent, direction);
}
else
{
return false;
}
}
if (direction == FocusDirection::FocusDirection_Right) {
if (index == container.size()-1)
{
return true * isLastWidgetInContainer(parent, direction);
}
else
{
return false;
}
}
if (direction == FocusDirection::FocusDirection_Down)
{
return isLastWidgetInContainer(parent, direction);
}
if (direction == FocusDirection::FocusDirection_Up)
{
return isLastWidgetInContainer(parent, direction);
}
}
else if(parent->getLayoutType() == LAYOUT_LINEAR_VERTICAL)
{
if (direction == FocusDirection::FocusDirection_Up)
{
if (index == 0)
{
return true * isLastWidgetInContainer(parent, direction);
}
else
{
return false;
}
}
if (direction == FocusDirection::FocusDirection_Down)
{
if (index == container.size() - 1)
{
return true * isLastWidgetInContainer(parent, direction);
}
else
{
return false;
}
}
if (direction == FocusDirection::FocusDirection_Left)
{
return isLastWidgetInContainer(parent, direction);
}
if (direction == FocusDirection::FocusDirection_Right)
{
return isLastWidgetInContainer(parent, direction);
}
}
else
{
CCASSERT(0, "invalid layout Type");
return false;
}
return false;
}
bool Layout::isWidgetAncestorSupportLoopFocus(Widget* widget, FocusDirection direction)
{
Layout* parent = dynamic_cast<Layout*>(widget->getParent());
if (parent == nullptr)
{
return false;
}
if (parent->isLoopFocus())
{
auto layoutType = parent->getLayoutType();
if (layoutType == LAYOUT_LINEAR_HORIZONTAL)
{
if (direction == FocusDirection::FocusDirection_Left || direction == FocusDirection::FocusDirection_Right)
{
return true;
}
else
{
return isWidgetAncestorSupportLoopFocus(parent, direction);
}
}
if (layoutType == LAYOUT_LINEAR_VERTICAL)
{
if (direction == FocusDirection::FocusDirection_Down || direction == FocusDirection::FocusDirection_Up)
{
return true;
}
else
{
return isWidgetAncestorSupportLoopFocus(parent, direction);
}
}
else
{
CCASSERT(0, "invalid layout type");
}
}
else
{
return isWidgetAncestorSupportLoopFocus(parent, direction);
}
}
Widget* Layout::findNextFocusedWidget(FocusDirection direction, Widget* current)
{
if (this->isFocused())
{
Layout* parent = dynamic_cast<Layout*>(this->getParent());
if (_passFocusToChild)
{
Widget * w = this->passFocusToChild(direction, current);
if (dynamic_cast<Layout*>(w)) {
if (parent) {
return parent->findNextFocusedWidget(direction, this);
}
}
return w;
}
if (nullptr == parent) {
return this;
}
return parent->findNextFocusedWidget(direction, this);
}
else if(current->isFocused() || !current->isFocusEnabled())
{
if (_layoutType == LAYOUT_LINEAR_HORIZONTAL)
{
switch (direction)
{
case FocusDirection::FocusDirection_Left:
{
return this->getPreviousFocusedWidget(direction, current);
}break;
case FocusDirection::FocusDirection_Right:
{
return this->getNextFocusedWidget(direction, current);
}break;
case FocusDirection::FocusDirection_Down:
case FocusDirection::FocusDirection_Up:
{
if (isLastWidgetInContainer(this, direction))
{
if (isWidgetAncestorSupportLoopFocus(current, direction))
{
this->dispatchFocusEvent(current, this);
return Widget::findNextFocusedWidget(direction, this);
}
return current;
}
else{
this->dispatchFocusEvent(current, this);
return Widget::findNextFocusedWidget(direction, this);
}
}break;
default:
{
CCASSERT(0, "Invalid Focus Direction");
return current;
}
break;
}
}
else if (_layoutType == LAYOUT_LINEAR_VERTICAL)
{
switch (direction)
{
case FocusDirection::FocusDirection_Left:
case FocusDirection::FocusDirection_Right:
{
if (isLastWidgetInContainer(this, direction))
{
if (isWidgetAncestorSupportLoopFocus(current, direction))
{
this->dispatchFocusEvent(current, this);
return Widget::findNextFocusedWidget(direction, this);
}
return current;
}
else
{
this->dispatchFocusEvent(current, this);
return Widget::findNextFocusedWidget(direction, this);
}
} break;
case FocusDirection::FocusDirection_Down:
{
return getNextFocusedWidget(direction, current);
}
break;
case FocusDirection::FocusDirection_Up:
{
return getPreviousFocusedWidget(direction, current);
}
break;
default:
{
CCASSERT(0, "Invalid Focus Direction");
return current;
}
break;
}
}
else
{
CCASSERT(0, "Un Supported Layout type, please use VBox and HBox instead!!!");
return current;
}
}
else
{
return current;
}
}
}
NS_CC_END

View File

@ -265,6 +265,44 @@ public:
virtual void onEnter() override;
virtual void onExit() override;
/**
* If a layout is loop focused which means that the focus movement will be inside the layout
*@param loop pass true to let the focus movement loop inside the layout
*/
void setLoopFocus(bool loop);
/**
*@return If focus loop is enabled, then it will return true, otherwise it returns false. The default value is false.
*/
bool isLoopFocus();
/**
*@param pass To specify whether the layout pass its focus to its child
*/
void setPassFocusToChild(bool pass);
/**
* @return To query whether the layout will pass the focus to its children or not. The default value is true
*/
bool isPassFocusToChild();
/**
* When a widget is in a layout, you could call this method to get the next focused widget within a specified direction.
* If the widget is not in a layout, it will return itself
*@param dir the direction to look for the next focused widget in a layout
*@param current the current focused widget
*@return the next focused widget in a layout
*/
virtual Widget* findNextFocusedWidget(FocusDirection direction, Widget* current) override;
/**
* To specify a user-defined functor to decide which child widget of the layout should get focused
* @param FocusDirection the finding direction
* @param this previous focused widget
* @return return the index of widget in the layout
*/
std::function<int(FocusDirection, Widget*)> onPassFocusToChild;
CC_CONSTRUCTOR_ACCESS:
//override "init" method of widget.
@ -300,6 +338,110 @@ protected:
void updateBackGroundImageOpacity();
void updateBackGroundImageRGBA();
LayoutExecutant* createCurrentLayoutExecutant();
/**
*get the content size of the layout, it will accumulate all its children's content size
*/
Size getLayoutContentSize() const;
/**
* When the layout get focused, it the layout pass the focus to its child, it will use this method to determine which child
* will get the focus. The current algorithm to determine which child will get focus is nearest-distance-priority algorithm
*@param dir next focused widget direction
*@return The index of child widget in the container
*/
int findNearestChildWidgetIndex(FocusDirection direction, Widget* baseWidget);
/**
* When the layout get focused, it the layout pass the focus to its child, it will use this method to determine which child
* will get the focus. The current algorithm to determine which child will get focus is farest-distance-priority algorithm
*@param dir next focused widget direction
*@return The index of child widget in the container
*/
int findFarestChildWidgetIndex(FocusDirection direction, Widget* baseWidget);
/**
* caculate the nearest distance between the baseWidget and the children of the layout
*@param the base widget which will be used to caculate the distance between the layout's children and itself
*@return return the nearest distance between the baseWidget and the layout's children
*/
float caculateNearestDistance(Widget* baseWidget);
/**
* caculate the farest distance between the baseWidget and the children of the layout
*@param the base widget which will be used to caculate the distance between the layout's children and itself
*@return return the farest distance between the baseWidget and the layout's children
*/
float caculateFarestDistance(Widget* baseWidget);
/**
* when a layout pass the focus to it's child, use this method to determine which algorithm to use, nearest or farest distance algorithm or not
*/
void findProperSearchingFunctor(FocusDirection dir, Widget* baseWidget);
/**
* find the first non-layout widget in this layout
*/
Widget *findFirstNonLayoutWidget();
/**
* find the fisrt focus enabled widget index in the layout, it will recusive searching the child widget
*/
int findFirstFocusEnabledWidgetIndex();
/**
* find a focus enabled child Widget in the layout by index
*/
Widget* findFocusEnabledChildWidgetByIndex(ssize_t index);
/**
* get the center point of a widget in world space
*/
Vector2 getWorldCenterPoint(Widget* node);
/**
* this method is called internally by nextFocusedWidget. When the dir is Right/Down, then this method will be called
*@param dir the direction.
*@param current the current focused widget
*@return the next focused widget
*/
Widget* getNextFocusedWidget(FocusDirection direction,Widget *current);
/**
* this method is called internally by nextFocusedWidget. When the dir is Left/Up, then this method will be called
*@param dir the direction.
*@param current the current focused widget
*@return the next focused widget
*/
Widget* getPreviousFocusedWidget(FocusDirection direction, Widget *current);
/**
* find the nth elment in the _children array. Only the Widget descendant object will be returned
*@param index The index of a element in the _children array
*/
Widget* getChildWidgetByIndex(ssize_t index);
/**
* whether it is the last element according to all their parents
*/
bool isLastWidgetInContainer(Widget* widget, FocusDirection direction);
/**Lookup any parent widget with a layout type as the direction,
* if the layout is loop focused, then return true, otherwise
* It returns false
*/
bool isWidgetAncestorSupportLoopFocus(Widget* widget, FocusDirection direction);
/**
* pass the focus to the layout's next focus enabled child
*/
Widget* passFocusToChild(FocusDirection direction, Widget* current);
/**
* If there are no focus enabled child in the layout, it will return false, otherwise it returns true
*/
bool checkFocusEnabledChild();
protected:
bool _clippingEnabled;
@ -356,6 +498,9 @@ protected:
CustomCommand _afterVisitCmdStencil;
CustomCommand _beforeVisitCmdScissor;
CustomCommand _afterVisitCmdScissor;
bool _loopFocus; //whether enable loop focus or not
bool _passFocusToChild; //on default, it will pass the focus to the next nearest widget
};
}

View File

@ -550,7 +550,7 @@ void PageView::interceptTouchEvent(int handleState, Widget *sender, const Vector
offset = fabs(sender->getTouchStartPos().x - touchPoint.x);
if (offset > _childFocusCancelOffset)
{
sender->setFocused(false);
sender->setHighlighted(false);
handleMoveLogic(touchPoint);
}
}

View File

@ -1528,7 +1528,7 @@ void ScrollView::interceptTouchEvent(int handleState, Widget *sender, const Vect
float offset = (sender->getTouchStartPos() - touchPoint).getLength();
if (offset > _childFocusCancelOffset)
{
sender->setFocused(false);
sender->setHighlighted(false);
handleMoveLogic(touchPoint);
}
}

View File

@ -30,12 +30,15 @@ NS_CC_BEGIN
namespace ui {
Widget* Widget::_focusedWidget = nullptr;
Widget* Widget::_realFocusedWidget = nullptr;
Widget::Widget():
_enabled(true),
_bright(true),
_touchEnabled(false),
_touchPassedEnabled(false),
_focus(false),
_highlight(false),
_brightStyle(BRIGHT_NONE),
_touchStartPos(Vector2::ZERO),
_touchMovePos(Vector2::ZERO),
@ -59,9 +62,12 @@ _touchListener(nullptr),
_color(Color3B::WHITE),
_opacity(255),
_flippedX(false),
_flippedY(false)
_flippedY(false),
_focused(false),
_focusEnabled(true)
{
onFocusChanged = CC_CALLBACK_2(Widget::onFocusChange,this);
onNextFocusedWidget = nullptr;
}
Widget::~Widget()
@ -69,6 +75,12 @@ Widget::~Widget()
_touchEventListener = nullptr;
_touchEventSelector = nullptr;
setTouchEnabled(false);
if (_focusedWidget == this) {
_focusedWidget = nullptr;
}
if (_realFocusedWidget == this) {
_realFocusedWidget = nullptr;
}
}
Widget* Widget::create()
@ -445,21 +457,21 @@ bool Widget::isTouchEnabled() const
return _touchEnabled;
}
bool Widget::isFocused() const
bool Widget::isHighlighted() const
{
return _focus;
return _highlight;
}
void Widget::setFocused(bool fucos)
void Widget::setHighlighted(bool hilight)
{
if (fucos == _focus)
if (hilight == _highlight)
{
return;
}
_focus = fucos;
_highlight = hilight;
if (_bright)
{
if (_focus)
if (_highlight)
{
setBrightStyle(BRIGHT_HIGHLIGHT);
}
@ -543,7 +555,7 @@ bool Widget::onTouchBegan(Touch *touch, Event *unusedEvent)
{
return false;
}
setFocused(true);
setHighlighted(true);
Widget* widgetParent = getWidgetParent();
if (widgetParent)
{
@ -556,7 +568,7 @@ bool Widget::onTouchBegan(Touch *touch, Event *unusedEvent)
void Widget::onTouchMoved(Touch *touch, Event *unusedEvent)
{
_touchMovePos = touch->getLocation();
setFocused(hitTest(_touchMovePos));
setHighlighted(hitTest(_touchMovePos));
Widget* widgetParent = getWidgetParent();
if (widgetParent)
{
@ -568,14 +580,14 @@ void Widget::onTouchMoved(Touch *touch, Event *unusedEvent)
void Widget::onTouchEnded(Touch *touch, Event *unusedEvent)
{
_touchEndPos = touch->getLocation();
bool focus = _focus;
setFocused(false);
bool highlight = _highlight;
setHighlighted(false);
Widget* widgetParent = getWidgetParent();
if (widgetParent)
{
widgetParent->checkChildInfo(2,this,_touchEndPos);
}
if (focus)
if (highlight)
{
releaseUpEvent();
}
@ -587,7 +599,7 @@ void Widget::onTouchEnded(Touch *touch, Event *unusedEvent)
void Widget::onTouchCancelled(Touch *touch, Event *unusedEvent)
{
setFocused(false);
setHighlighted(false);
cancelUpEvent();
}
@ -942,6 +954,132 @@ int Widget::getActionTag()
{
return _actionTag;
}
void Widget::setFocused(bool focus)
{
_focused = focus;
//make sure there is only one focusedWidget
if (focus) {
_focusedWidget = this;
if (!dynamic_cast<Layout*>(this)) {
_realFocusedWidget = this;
}
}
}
bool Widget::isFocused()
{
return _focused;
}
void Widget::setFocusEnabled(bool enable)
{
_focusEnabled = enable;
}
bool Widget::isFocusEnabled()
{
return _focusEnabled;
}
Widget* Widget::findNextFocusedWidget(cocos2d::ui::FocusDirection direction, Widget* current)
{
if (nullptr == onNextFocusedWidget || nullptr == onNextFocusedWidget(direction) ) {
if (this->isFocused() || !current->isFocusEnabled())
{
Node* parent = this->getParent();
Layout* layout = dynamic_cast<Layout*>(parent);
if (nullptr == layout)
{
//the outer layout's default behaviour is : loop focus
if (dynamic_cast<Layout*>(current))
{
return current->findNextFocusedWidget(direction, current);
}
return current;
}
else
{
Widget *nextWidget = layout->findNextFocusedWidget(direction, current);
return nextWidget;
}
}
else
{
return current;
}
}
else
{
Widget *getFocusWidget = onNextFocusedWidget(direction);
this->dispatchFocusEvent(this, getFocusWidget);
return getFocusWidget;
}
}
void Widget::dispatchFocusEvent(cocos2d::ui::Widget *widgetLoseFocus, cocos2d::ui::Widget *widgetGetFocus)
{
//if the widgetLoseFocus doesn't get focus, it will use the previous focused widget instead
if (widgetLoseFocus && !widgetLoseFocus->isFocused())
{
widgetLoseFocus = _focusedWidget;
}
if (widgetGetFocus != widgetLoseFocus)
{
if (widgetGetFocus)
{
widgetGetFocus->onFocusChanged(widgetLoseFocus, widgetGetFocus);
}
if (widgetLoseFocus)
{
widgetLoseFocus->onFocusChanged(widgetLoseFocus, widgetGetFocus);
}
EventFocus event(widgetLoseFocus, widgetGetFocus);
auto dispatcher = cocos2d::Director::getInstance()->getEventDispatcher();
dispatcher->dispatchEvent(&event);
}
}
void Widget::requestFocus()
{
if (this == _focusedWidget)
{
return;
}
this->dispatchFocusEvent(_focusedWidget, this);
}
void Widget::onFocusChange(Widget* widgetLostFocus, Widget* widgetGetFocus)
{
//only change focus when there is indeed a get&lose happens
if (widgetLostFocus)
{
widgetLostFocus->setFocused(false);
}
if (widgetGetFocus)
{
widgetGetFocus->setFocused(true);
}
}
Widget* Widget::getCurrentFocusedWidget(bool isWidget)
{
if (isWidget) {
return _realFocusedWidget;
}
return _focusedWidget;
}
}

View File

@ -72,6 +72,15 @@ typedef enum
POSITION_ABSOLUTE,
POSITION_PERCENT
}PositionType;
enum class FocusDirection
{
FocusDirection_Left,
FocusDirection_Right,
FocusDirection_Up,
FocusDirection_Down
};
typedef void (Ref::*SEL_TouchEvent)(Ref*,TouchEventType);
#define toucheventselector(_SELECTOR) (SEL_TouchEvent)(&_SELECTOR)
@ -156,20 +165,20 @@ public:
bool isTouchEnabled() const;
/**
* Determines if the widget is on focused
* Determines if the widget is highlighted
*
* @return true if the widget is on focused, false if the widget is not on focused.
* @return true if the widget is highlighted, false if the widget is not hignlighted .
*/
bool isFocused() const;
bool isHighlighted() const;
/**
* Sets whether the widget is on focused
* Sets whether the widget is hilighted
*
* The default value is false, a widget is default to not on focused
* The default value is false, a widget is default to not hilighted
*
* @param fucosed true if the widget is on focused, false if the widget is not on focused.
* @param hilight true if the widget is hilighted, false if the widget is not hilighted.
*/
void setFocused(bool fucosed);
void setHighlighted(bool hilight);
/**
* Gets the left boundary position of this widget.
@ -529,10 +538,63 @@ public:
void setActionTag(int tag);
int getActionTag();
/**
*@return whether the widget is focused or not
*/
bool isFocused();
/**
*@param focus pass true to let the widget get focus or pass false to let the widget lose focus
*@return void
*/
void setFocused(bool focus);
/**
*@return true represent the widget could accept focus, false represent the widget couldn't accept focus
*/
bool isFocusEnabled();
/**
*@param enable pass true/false to enable/disable the focus ability of a widget
*@return void
*/
void setFocusEnabled(bool enable);
/**
* When a widget is in a layout, you could call this method to get the next focused widget within a specified direction.
* If the widget is not in a layout, it will return itself
*@param dir the direction to look for the next focused widget in a layout
*@param current the current focused widget
*@return the next focused widget in a layout
*/
virtual Widget* findNextFocusedWidget(FocusDirection direction, Widget* current);
/**
* when a widget calls this method, it will get focus immediately.
*/
void requestFocus();
CC_CONSTRUCTOR_ACCESS:
//initializes state of widget.
virtual bool init() override;
/**
* This method is called when a focus change event happens
*@param widgetLostFocus The widget which lose its focus
*@param widgetGetFocus The widget whihc get its focus
*@return void
*/
void onFocusChange(Widget* widgetLostFocus, Widget* widgetGetFocus);
/**
* Dispatch a EventFocus through a EventDispatcher
*@param widgetLoseFocus The widget which lose its focus
*@param widgetGetFocus he widget whihc get its focus
*@return void
*/
void dispatchFocusEvent(Widget* widgetLoseFocus, Widget* widgetGetFocus);
protected:
//call back function called when size changed.
virtual void onSizeChanged();
@ -572,7 +634,7 @@ protected:
bool _bright; ///< is this widget bright
bool _touchEnabled; ///< is this widget touch endabled
bool _touchPassedEnabled; ///< is the touch event should be passed
bool _focus; ///< is the widget on focus
bool _highlight; ///< is the widget on focus
BrightStyle _brightStyle; ///< bright style
Vector2 _touchStartPos; ///< touch began point
Vector2 _touchMovePos; ///< touch moved point
@ -598,7 +660,25 @@ protected:
bool _flippedX;
bool _flippedY;
Map<int, LayoutParameter*> _layoutParameterDictionary;
bool _focused;
bool _focusEnabled;
/**
* store the only one focued widget
*/
static Widget *_focusedWidget; //both layout & widget will be stored in this variable
static Widget *_realFocusedWidget; //only the widget class will be stored in this variable
public:
/**
* no matter what widget object you call this method on , it will return you the exact one focused widget
* @param isWidget if your set isWidget to true, it will return the _realFocusedWidget which is always a widget
* otherwise, it will return a widget or a layout
*/
Widget* getCurrentFocusedWidget(bool isWidget);
std::function<void(Widget*,Widget*)> onFocusChanged;
std::function<Widget*(FocusDirection)> onNextFocusedWidget;
};
}

View File

@ -67,6 +67,7 @@ Classes/ExtensionsTest/CocoStudioGUITest/CustomGUIScene.cpp \
Classes/ExtensionsTest/CocoStudioGUITest/UIScene.cpp \
Classes/ExtensionsTest/CocoStudioGUITest/UISceneManager.cpp \
Classes/ExtensionsTest/CocoStudioGUITest/UIButtonTest/UIButtonTest.cpp \
Classes/ExtensionsTest/CocoStudioGUITest/UIFocusTest/UIFocusTest.cpp \
Classes/ExtensionsTest/CocoStudioGUITest/UICheckBoxTest/UICheckBoxTest.cpp \
Classes/ExtensionsTest/CocoStudioGUITest/UIImageViewTest/UIImageViewTest.cpp \
Classes/ExtensionsTest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp \

View File

@ -81,6 +81,7 @@ set(SAMPLE_SRC
Classes/ExtensionsTest/CocoStudioGUITest/UIScene.cpp
Classes/ExtensionsTest/CocoStudioGUITest/UISceneManager.cpp
Classes/ExtensionsTest/CocoStudioGUITest/UIButtonTest/UIButtonTest.cpp
Classes/ExtensionsTest/CocoStudioGUITest/UIFocusTest/UIFocusTest.cpp
Classes/ExtensionsTest/CocoStudioGUITest/UICheckBoxTest/UICheckBoxTest.cpp
Classes/ExtensionsTest/CocoStudioGUITest/UIImageViewTest/UIImageViewTest.cpp
Classes/ExtensionsTest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp

View File

@ -17,7 +17,20 @@ static struct
}
g_guisTests[] =
{
{
"gui focus test",
[](Ref* sender)
{
UISceneManager* pManager = UISceneManager::sharedUISceneManager();
pManager->setCurrentUISceneId(KUIFocusTest_HBox);
pManager->setMinUISceneId(KUIFocusTest_HBox);
pManager->setMaxUISceneId(KUIFocusTest_NestedLayout3);
Scene* pScene = pManager->currentUIScene();
Director::getInstance()->replaceScene(pScene);
}
},
{
"gui ButtonTest",
[](Ref* sender)
{
@ -267,6 +280,7 @@ g_guisTests[] =
Director::getInstance()->replaceScene(pScene);
}
},
};
static const int g_maxTests = sizeof(g_guisTests) / sizeof(g_guisTests[0]);

View File

@ -0,0 +1,589 @@
//
// UIFocusTest.cpp
// cocos2d_tests
//
// Created by guanghui on 5/4/14.
//
//
#include "UIFocusTest.h"
UIFocusTestBase::UIFocusTestBase()
{
}
UIFocusTestBase::~UIFocusTestBase()
{
_eventDispatcher->removeEventListener(_eventListener);
}
bool UIFocusTestBase::init()
{
if (UIScene::init()) {
Layout* root = static_cast<Layout*>(_uiLayer->getChildByTag(81));
Layout* background = dynamic_cast<Layout*>(root->getChildByName("background_Panel"));
background->removeFromParentAndCleanup(true);
_dpadMenu = Menu::create();
auto winSize = Director::getInstance()->getVisibleSize();
auto leftItem = MenuItemFont::create("Left", CC_CALLBACK_0(UIFocusTestBase::onLeftKeyPressed, this));
leftItem->setPosition(Vector2(winSize.width - 100, winSize.height/2));
_dpadMenu->addChild(leftItem);
auto rightItem = MenuItemFont::create("Right", CC_CALLBACK_0(UIFocusTestBase::onRightKeyPressed, this));
rightItem->setPosition(Vector2(winSize.width - 30, winSize.height/2));
_dpadMenu->addChild(rightItem);
auto upItem = MenuItemFont::create("Up", CC_CALLBACK_0(UIFocusTestBase::onUpKeyPressed, this));
upItem->setPosition(Vector2(winSize.width - 60, winSize.height/2 + 50));
_dpadMenu->addChild(upItem);
auto downItem = MenuItemFont::create("Down", CC_CALLBACK_0(UIFocusTestBase::onDownKeyPressed, this));
downItem->setPosition(Vector2(winSize.width - 60, winSize.height/2 - 50));
_dpadMenu->addChild(downItem);
_dpadMenu->setPosition(Vector2::ZERO);
_uiLayer->addChild(_dpadMenu);
_eventListener = EventListenerFocus::create();
_eventListener->onFocusChanged = CC_CALLBACK_2(UIFocusTestBase::onFocusChanged, this);
_eventDispatcher->addEventListenerWithFixedPriority(_eventListener, 1);
return true;
}
return false;
}
void UIFocusTestBase::onImageViewClicked(cocos2d::Ref *ref, TouchEventType touchType)
{
if (touchType == TouchEventType::TOUCH_EVENT_ENDED) {
Widget *w = (Widget*)ref;
if (w->isFocusEnabled()) {
w->setFocusEnabled(false);
w->setColor(Color3B::YELLOW);
}else{
w->setFocusEnabled(true);
w->setColor(Color3B::WHITE);
}
}
}
void UIFocusTestBase::onLeftKeyPressed()
{
if (_firstFocusedWidget) {
if (!_firstFocusedWidget->isFocused()) {
_firstFocusedWidget = _firstFocusedWidget->getCurrentFocusedWidget(false);
}
_firstFocusedWidget = _firstFocusedWidget->findNextFocusedWidget(FocusDirection::FocusDirection_Left, _firstFocusedWidget);
}
}
void UIFocusTestBase::onRightKeyPressed()
{
if (_firstFocusedWidget) {
if (!_firstFocusedWidget->isFocused()) {
_firstFocusedWidget = _firstFocusedWidget->getCurrentFocusedWidget(false);
}
_firstFocusedWidget = _firstFocusedWidget->findNextFocusedWidget(FocusDirection::FocusDirection_Right, _firstFocusedWidget);
}
}
void UIFocusTestBase::onUpKeyPressed()
{
if (_firstFocusedWidget) {
if (!_firstFocusedWidget->isFocused()) {
_firstFocusedWidget = _firstFocusedWidget->getCurrentFocusedWidget(false);
}
_firstFocusedWidget = _firstFocusedWidget->findNextFocusedWidget(FocusDirection::FocusDirection_Up, _firstFocusedWidget);
}
}
void UIFocusTestBase::onDownKeyPressed()
{
if (_firstFocusedWidget) {
if (!_firstFocusedWidget->isFocused()) {
_firstFocusedWidget = _firstFocusedWidget->getCurrentFocusedWidget(false);
}
_firstFocusedWidget = _firstFocusedWidget->findNextFocusedWidget(FocusDirection::FocusDirection_Down, _firstFocusedWidget);
}
}
void UIFocusTestBase::onFocusChanged(cocos2d::ui::Widget *widgetLostFocus, cocos2d::ui::Widget *widgetGetFocus)
{
//only change the widgets' state
Layout *getLayout = dynamic_cast<Layout*>(widgetGetFocus);
if (!getLayout && widgetGetFocus && widgetGetFocus->isFocusEnabled()) {
widgetGetFocus->setColor(Color3B::RED);
}
Layout *loseLayout = dynamic_cast<Layout*>(widgetLostFocus);
if (!loseLayout && widgetLostFocus && widgetLostFocus->isFocusEnabled()) {
widgetLostFocus->setColor(Color3B::WHITE);
}
if (widgetLostFocus && widgetGetFocus) {
CCLOG("on focus change, %d widget get focus, %d widget lose focus", widgetGetFocus->getTag(), widgetLostFocus->getTag());
}
}
//UIFocusTestHorizontal
UIFocusTestHorizontal::UIFocusTestHorizontal()
{
}
UIFocusTestHorizontal::~UIFocusTestHorizontal()
{
}
bool UIFocusTestHorizontal::init()
{
if (UIFocusTestBase::init()) {
Size winSize = Director::getInstance()->getVisibleSize();
_horizontalLayout = HBox::create();
_horizontalLayout->setPosition(Vector2(20, winSize.height/2 + 40));
_uiLayer->addChild(_horizontalLayout);
_horizontalLayout->setFocused(true);
_horizontalLayout->setLoopFocus(true);
_horizontalLayout->setTag(100);
_firstFocusedWidget = _horizontalLayout;
int count = 3;
for (int i=0; i<count; ++i) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setTouchEnabled(true);
w->setTag(i);
w->addTouchEventListener(this, toucheventselector(UIFocusTestHorizontal::onImageViewClicked));
_horizontalLayout->addChild(w);
}
_loopText = Text::create("loop enabled", "Airal", 20);
_loopText->setPosition(Vector2(winSize.width/2, winSize.height - 50));
_loopText->setColor(Color3B::GREEN);
this->addChild(_loopText);
auto btn = Button::create("cocosui/switch-mask.png");
btn->setTitleText("Toggle Loop");
btn->setPosition(Vector2(60, winSize.height - 50));
btn->setTitleColor(Color3B::RED);
btn->addTouchEventListener(this, toucheventselector(UIFocusTestHorizontal::toggleFocusLoop));
this->addChild(btn);
return true;
}
return false;
}
void UIFocusTestHorizontal::toggleFocusLoop(cocos2d::Ref * pObjc, TouchEventType type)
{
if (type == TouchEventType::TOUCH_EVENT_ENDED) {
_horizontalLayout->setLoopFocus(!_horizontalLayout->isLoopFocus());
if (_horizontalLayout->isLoopFocus()) {
_loopText->setText("loop enabled");
}else{
_loopText->setText("loop disabled");
}
}
}
//UIFocusTestVertical
UIFocusTestVertical::UIFocusTestVertical()
{
}
UIFocusTestVertical::~UIFocusTestVertical()
{
}
bool UIFocusTestVertical::init()
{
if (UIFocusTestBase::init()) {
Size winSize = Director::getInstance()->getVisibleSize();
_verticalLayout = VBox::create();
_verticalLayout->setPosition(Vector2(winSize.width/2 - 100, winSize.height - 70));
_uiLayer->addChild(_verticalLayout);
_verticalLayout->setTag(100);
_verticalLayout->setScale(0.8);
_verticalLayout->setFocused(true);
_verticalLayout->setLoopFocus(true);
_firstFocusedWidget = _verticalLayout;
int count = 3;
for (int i=0; i<count; ++i) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setTouchEnabled(true);
w->setTag(i);
w->addTouchEventListener(this, toucheventselector(UIFocusTestVertical::onImageViewClicked));
_verticalLayout->addChild(w);
if (i == 2) {
w->requestFocus();
}
}
_loopText = Text::create("loop enabled", "Airal", 20);
_loopText->setPosition(Vector2(winSize.width/2, winSize.height - 50));
_loopText->setColor(Color3B::GREEN);
this->addChild(_loopText);
auto btn = Button::create("cocosui/switch-mask.png");
btn->setTitleText("Toggle Loop");
btn->setPosition(Vector2(60, winSize.height - 50));
btn->setTitleColor(Color3B::RED);
btn->addTouchEventListener(this, toucheventselector(UIFocusTestHorizontal::toggleFocusLoop));
this->addChild(btn);
return true;
}
return false;
}
void UIFocusTestVertical::toggleFocusLoop(cocos2d::Ref * pObjc, TouchEventType type)
{
if (type == TouchEventType::TOUCH_EVENT_ENDED) {
_verticalLayout->setLoopFocus(!_verticalLayout->isLoopFocus());
if (_verticalLayout->isLoopFocus()) {
_loopText->setText("loop enabled");
}else{
_loopText->setText("loop disabled");
}
}
}
//UIFocusTestNestedLayout1
UIFocusTestNestedLayout1::UIFocusTestNestedLayout1()
{
}
UIFocusTestNestedLayout1::~UIFocusTestNestedLayout1()
{
}
bool UIFocusTestNestedLayout1::init()
{
if (UIFocusTestBase::init()) {
Size winSize = Director::getInstance()->getVisibleSize();
_verticalLayout = VBox::create();
_verticalLayout->setPosition(Vector2(winSize.width/2 - 100, winSize.height - 70));
_uiLayer->addChild(_verticalLayout);
_verticalLayout->setScale(0.8);
_verticalLayout->setFocused(true);
_verticalLayout->setLoopFocus(true);
_verticalLayout->setTag(100);
_firstFocusedWidget = _verticalLayout;
int count1 = 1;
for (int i=0; i<count1; ++i) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setAnchorPoint(Vector2::ZERO);
w->setTouchEnabled(true);
w->setScaleX(2.5);
w->setTag(i+count1);
w->addTouchEventListener(this, toucheventselector(UIFocusTestVertical::onImageViewClicked));
_verticalLayout->addChild(w);
}
//add HBox into VBox
HBox *hbox = HBox::create();
hbox->setScale(0.8);
hbox->setTag(101);
_verticalLayout->addChild(hbox);
int count2 = 2;
for (int i=0; i < count2; ++i) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setAnchorPoint(Vector2(0,1));
w->setScaleY(2.0);
w->setTouchEnabled(true);
w->setTag(i+count1+count2);
w->addTouchEventListener(this, toucheventselector(UIFocusTestVertical::onImageViewClicked));
hbox->addChild(w);
}
VBox *innerVBox = VBox::create();
hbox->addChild(innerVBox);
innerVBox->setTag(102);
// innerVBox->setPassFocusToChild(false);
// innerVBox->setFocusEnabled(false);
int count3 = 2;
for (int i=0; i<count3; ++i) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setTouchEnabled(true);
w->setTag(i+count1+count2+count3);
w->addTouchEventListener(this, toucheventselector(UIFocusTestVertical::onImageViewClicked));
innerVBox->addChild(w);
}
_loopText = Text::create("loop enabled", "Airal", 20);
_loopText->setPosition(Vector2(winSize.width/2, winSize.height - 50));
_loopText->setColor(Color3B::GREEN);
this->addChild(_loopText);
auto btn = Button::create("cocosui/switch-mask.png");
btn->setTitleText("Toggle Loop");
btn->setPosition(Vector2(60, winSize.height - 50));
btn->setTitleColor(Color3B::RED);
btn->addTouchEventListener(this, toucheventselector(UIFocusTestHorizontal::toggleFocusLoop));
this->addChild(btn);
return true;
}
return false;
}
void UIFocusTestNestedLayout1::toggleFocusLoop(cocos2d::Ref * pObjc, TouchEventType type)
{
if (type == TouchEventType::TOUCH_EVENT_ENDED) {
_verticalLayout->setLoopFocus(!_verticalLayout->isLoopFocus());
if (_verticalLayout->isLoopFocus()) {
_loopText->setText("loop enabled");
}else{
_loopText->setText("loop disabled");
}
}
}
//UIFocusTestNestedLayout2
UIFocusTestNestedLayout2::UIFocusTestNestedLayout2()
{
}
UIFocusTestNestedLayout2::~UIFocusTestNestedLayout2()
{
}
bool UIFocusTestNestedLayout2::init()
{
if (UIFocusTestBase::init()) {
Size winSize = Director::getInstance()->getVisibleSize();
_horizontalLayout = HBox::create();
_horizontalLayout->setPosition(Vector2(winSize.width/2 - 200, winSize.height - 70));
_uiLayer->addChild(_horizontalLayout);
_horizontalLayout->setScale(0.8);
_horizontalLayout->setFocused(true);
_horizontalLayout->setLoopFocus(true);
_horizontalLayout->setTag(100);
_firstFocusedWidget = _horizontalLayout;
int count1 = 2;
for (int i=0; i<count1; ++i) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setAnchorPoint(Vector2(0,1));
w->setTouchEnabled(true);
w->setTag(i+count1);
w->setScaleY(2.4);
w->addTouchEventListener(this, toucheventselector(UIFocusTestVertical::onImageViewClicked));
_horizontalLayout->addChild(w);
}
//add HBox into VBox
VBox *vbox = VBox::create();
vbox->setScale(0.8);
vbox->setTag(101);
_horizontalLayout->addChild(vbox);
int count2 = 2;
for (int i=0; i < count2; ++i) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setAnchorPoint(Vector2(0,1));
w->setScaleX(2.0);
w->setTouchEnabled(true);
w->setTag(i+count1+count2);
w->addTouchEventListener(this, toucheventselector(UIFocusTestVertical::onImageViewClicked));
vbox->addChild(w);
}
HBox *innerHBox = HBox::create();
vbox->addChild(innerHBox);
innerHBox->setTag(102);
// innerVBox->setPassFocusToChild(false);
// innerVBox->setFocusEnabled(false);
int count3 = 2;
for (int i=0; i<count3; ++i) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setTouchEnabled(true);
w->setTag(i+count1+count2+count3);
w->addTouchEventListener(this, toucheventselector(UIFocusTestVertical::onImageViewClicked));
innerHBox->addChild(w);
}
_loopText = Text::create("loop enabled", "Airal", 20);
_loopText->setPosition(Vector2(winSize.width/2, winSize.height - 50));
_loopText->setColor(Color3B::GREEN);
this->addChild(_loopText);
auto btn = Button::create("cocosui/switch-mask.png");
btn->setTitleText("Toggle Loop");
btn->setPosition(Vector2(60, winSize.height - 50));
btn->setTitleColor(Color3B::RED);
btn->addTouchEventListener(this, toucheventselector(UIFocusTestHorizontal::toggleFocusLoop));
this->addChild(btn);
return true;
}
return false;
}
void UIFocusTestNestedLayout2::toggleFocusLoop(cocos2d::Ref * pObjc, TouchEventType type)
{
if (type == TouchEventType::TOUCH_EVENT_ENDED) {
_horizontalLayout->setLoopFocus(!_horizontalLayout->isLoopFocus());
if (_horizontalLayout->isLoopFocus()) {
_loopText->setText("loop enabled");
}else{
_loopText->setText("loop disabled");
}
}
}
//UIFocusTestNestedLayout3
UIFocusTestNestedLayout3::UIFocusTestNestedLayout3()
{
}
UIFocusTestNestedLayout3::~UIFocusTestNestedLayout3()
{
}
bool UIFocusTestNestedLayout3::init()
{
if (UIFocusTestBase::init()) {
Size winSize = Director::getInstance()->getVisibleSize();
_verticalLayout = VBox::create();
_verticalLayout->setPosition(Vector2(40, winSize.height - 70));
_uiLayer->addChild(_verticalLayout);
_verticalLayout->setScale(0.8);
_verticalLayout->setFocused(true);
_verticalLayout->setLoopFocus(true);
_verticalLayout->setTag(-1000);
_firstFocusedWidget = _verticalLayout;
HBox *upperHBox = HBox::create();
upperHBox->setTag(-200);
_verticalLayout->addChild(upperHBox);
LinearLayoutParameter *params = LinearLayoutParameter::create();
params->setMargin(Margin(0,0,50,0));
LinearLayoutParameter *vparams = LinearLayoutParameter::create();
vparams->setMargin(Margin(10, 0, 0, 140));
upperHBox->setLayoutParameter(vparams);
int count = 3;
for (int i=0; i<count; ++i) {
VBox *firstVbox = VBox::create();
firstVbox->setScale(0.5);
firstVbox->setLayoutParameter(params);
firstVbox->setTag((i+1) * 100);
int count1 = 3;
for (int j=0; j<count1; ++j) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setTouchEnabled(true);
w->setTag(j+firstVbox->getTag()+1);
w->addTouchEventListener(this, toucheventselector(UIFocusTestVertical::onImageViewClicked));
firstVbox->addChild(w);
}
upperHBox->addChild(firstVbox);
}
HBox *bottomHBox = HBox::create();
bottomHBox->setScale(0.5);
bottomHBox->setTag(600);
bottomHBox->setLayoutParameter(vparams);
count = 3;
LinearLayoutParameter *bottomParams = LinearLayoutParameter::create();
bottomParams->setMargin(Margin(0, 0, 8, 0));
for (int i=0; i < count; ++i) {
ImageView *w = ImageView::create("cocosui/scrollviewbg.png");
w->setLayoutParameter(bottomParams);
w->setTouchEnabled(true);
w->setTag(i+601);
w->addTouchEventListener(this, toucheventselector(UIFocusTestVertical::onImageViewClicked));
bottomHBox->addChild(w);
}
_verticalLayout->addChild(bottomHBox);
_loopText = Text::create("loop enabled", "Airal", 20);
_loopText->setPosition(Vector2(winSize.width/2, winSize.height - 50));
_loopText->setColor(Color3B::GREEN);
this->addChild(_loopText);
auto btn = Button::create("cocosui/switch-mask.png");
btn->setTitleText("Toggle Loop");
btn->setPosition(Vector2(60, winSize.height - 50));
btn->setTitleColor(Color3B::RED);
btn->addTouchEventListener(this, toucheventselector(UIFocusTestHorizontal::toggleFocusLoop));
this->addChild(btn);
return true;
}
return false;
}
void UIFocusTestNestedLayout3::toggleFocusLoop(cocos2d::Ref * pObjc, TouchEventType type)
{
if (type == TouchEventType::TOUCH_EVENT_ENDED) {
_verticalLayout->setLoopFocus(!_verticalLayout->isLoopFocus());
if (_verticalLayout->isLoopFocus()) {
_loopText->setText("loop enabled");
}else{
_loopText->setText("loop disabled");
}
}
}

View File

@ -0,0 +1,115 @@
//
// UIFocusTest.h
// cocos2d_tests
//
// Created by guanghui on 5/4/14.
//
//
#ifndef __cocos2d_tests__UIFocusTest__
#define __cocos2d_tests__UIFocusTest__
#include "../UIScene.h"
class UIFocusTestBase : public UIScene
{
public:
UIFocusTestBase();
virtual ~UIFocusTestBase();
bool init();
virtual void onLeftKeyPressed();
virtual void onRightKeyPressed();
virtual void onUpKeyPressed();
virtual void onDownKeyPressed();
virtual void onFocusChanged(Widget* widgetLostFocus, Widget* widgetGetFocus);
void onImageViewClicked(Ref* ref, TouchEventType touchType);
protected:
Menu *_dpadMenu;
Widget *_firstFocusedWidget;
EventListenerFocus *_eventListener;
};
class UIFocusTestHorizontal : public UIFocusTestBase
{
public:
UIFocusTestHorizontal();
virtual ~UIFocusTestHorizontal();
bool init();
void toggleFocusLoop(Ref*,TouchEventType);
protected:
UI_SCENE_CREATE_FUNC(UIFocusTestHorizontal);
Layout *_horizontalLayout;
Text *_loopText;
};
class UIFocusTestVertical : public UIFocusTestBase
{
public:
UIFocusTestVertical();
virtual ~UIFocusTestVertical();
bool init();
void toggleFocusLoop(Ref*,TouchEventType);
protected:
UI_SCENE_CREATE_FUNC(UIFocusTestVertical);
Layout *_verticalLayout;
Text *_loopText;
};
class UIFocusTestNestedLayout1 : public UIFocusTestBase
{
public:
UIFocusTestNestedLayout1();
virtual ~UIFocusTestNestedLayout1();
bool init();
void toggleFocusLoop(Ref*,TouchEventType);
protected:
UI_SCENE_CREATE_FUNC(UIFocusTestNestedLayout1);
Layout *_verticalLayout;
Text *_loopText;
};
class UIFocusTestNestedLayout2 : public UIFocusTestBase
{
public:
UIFocusTestNestedLayout2();
virtual ~UIFocusTestNestedLayout2();
bool init();
void toggleFocusLoop(Ref*,TouchEventType);
protected:
UI_SCENE_CREATE_FUNC(UIFocusTestNestedLayout2);
Layout *_horizontalLayout;
Text *_loopText;
};
class UIFocusTestNestedLayout3 : public UIFocusTestBase
{
public:
UIFocusTestNestedLayout3();
virtual ~UIFocusTestNestedLayout3();
bool init();
void toggleFocusLoop(Ref*,TouchEventType);
protected:
UI_SCENE_CREATE_FUNC(UIFocusTestNestedLayout3);
Layout *_verticalLayout;
Text *_loopText;
};
#endif /* defined(__cocos2d_tests__UIFocusTest__) */

View File

@ -17,6 +17,7 @@
#include "UIListViewTest/UIListViewTest.h"
#include "UIWidgetAddNodeTest/UIWidgetAddNodeTest.h"
#include "UIRichTextTest/UIRichTextTest.h"
#include "UIFocusTest/UIFocusTest.h"
/*
#include "UISwitchTest/UISwitchTest.h"
*/
@ -109,6 +110,11 @@ static const char* s_testArray[] =
*/
"UIWidgetAddNodeTest",
"UIRichTextTest",
"UIFocusTest-HBox",
"UIFocusTest-VBox",
"UIFocusTest-NestedLayout1",
"UIFocusTest-NestedLayout2",
"UIFocusTest-NestedLayout3"
};
static UISceneManager *sharedInstance = NULL;
@ -359,6 +365,17 @@ Scene *UISceneManager::currentUIScene()
case kUIRichTextTest:
return UIRichTextTest::sceneWithTitle(s_testArray[_currentUISceneId]);
case KUIFocusTest_HBox:
return UIFocusTestHorizontal::sceneWithTitle(s_testArray[_currentUISceneId]);
case KUIFocusTest_VBox:
return UIFocusTestVertical::sceneWithTitle(s_testArray[_currentUISceneId]);
case KUIFocusTest_NestedLayout1:
return UIFocusTestNestedLayout1::sceneWithTitle(s_testArray[_currentUISceneId]);
case KUIFocusTest_NestedLayout2:
return UIFocusTestNestedLayout2::sceneWithTitle(s_testArray[_currentUISceneId]);
case KUIFocusTest_NestedLayout3:
return UIFocusTestNestedLayout3::sceneWithTitle(s_testArray[_currentUISceneId]);
}
return NULL;
}

View File

@ -101,6 +101,11 @@ enum
*/
kUIWidgetAddNodeTest,
kUIRichTextTest,
KUIFocusTest_HBox,
KUIFocusTest_VBox,
KUIFocusTest_NestedLayout1,
KUIFocusTest_NestedLayout2,
KUIFocusTest_NestedLayout3,
kUITestMax
};

View File

@ -166,6 +166,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\external\websockets\prebuilt\win32\*.*" "$(Ou
<ClCompile Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIButtonTest\UIButtonTest_Editor.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UICheckBoxTest\UICheckBoxTest.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UICheckBoxTest\UICheckBoxTest_Editor.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIFocusTest\UIFocusTest.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIImageViewTest\UIImageViewTest.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIImageViewTest\UIImageViewTest_Editor.cpp" />
<ClCompile Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UILayoutTest\UILayoutTest.cpp" />
@ -345,6 +346,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\external\websockets\prebuilt\win32\*.*" "$(Ou
<ClInclude Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIButtonTest\UIButtonTest_Editor.h" />
<ClInclude Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UICheckBoxTest\UICheckBoxTest.h" />
<ClInclude Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UICheckBoxTest\UICheckBoxTest_Editor.h" />
<ClInclude Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIFocusTest\UIFocusTest.h" />
<ClInclude Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIImageViewTest\UIImageViewTest.h" />
<ClInclude Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIImageViewTest\UIImageViewTest_Editor.h" />
<ClInclude Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UILayoutTest\UILayoutTest.h" />

View File

@ -325,6 +325,9 @@
<Filter Include="Classes\ExtensionsTest\CocoStudioGUITest\CustomTest\CustomParticleWidgetTest">
<UniqueIdentifier>{f2e15a07-0d4e-407f-b4dc-d7692afe64a4}</UniqueIdentifier>
</Filter>
<Filter Include="Classes\ExtensionsTest\CocoStudioGUITest\UIFocusTest">
<UniqueIdentifier>{f78b81ee-c6ab-43ea-b7bb-0e4ee1fa375f}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
@ -837,6 +840,9 @@
<ClCompile Include="..\Classes\UnitTest\RefPtrTest.cpp">
<Filter>Classes\UnitTest</Filter>
</ClCompile>
<ClCompile Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIFocusTest\UIFocusTest.cpp">
<Filter>Classes\ExtensionsTest\CocoStudioGUITest\UIFocusTest</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h">
@ -1547,5 +1553,8 @@
<ClInclude Include="..\Classes\UnitTest\RefPtrTest.h">
<Filter>Classes\UnitTest</Filter>
</ClInclude>
<ClInclude Include="..\Classes\ExtensionsTest\CocoStudioGUITest\UIFocusTest\UIFocusTest.h">
<Filter>Classes\ExtensionsTest\CocoStudioGUITest\UIFocusTest</Filter>
</ClInclude>
</ItemGroup>
</Project>