CCUIEditBoxMac.mm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /****************************************************************************
  2. Copyright (c) 2010-2012 cocos2d-x.org
  3. Copyright (c) 2013-2016 zilongshanren
  4. http://www.cocos2d-x.org
  5. Permission is hereby granted, free of charge, to any person obtaining a copy
  6. of this software and associated documentation files (the "Software"), to deal
  7. in the Software without restriction, including without limitation the rights
  8. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the Software is
  10. furnished to do so, subject to the following conditions:
  11. The above copyright notice and this permission notice shall be included in
  12. all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. THE SOFTWARE.
  20. ****************************************************************************/
  21. #import "ui/UIEditBox/Mac/CCUIEditBoxMac.h"
  22. #include "base/CCDirector.h"
  23. #include "ui/UIEditBox/Mac/CCUISingleLineTextField.h"
  24. #include "ui/UIEditBox/Mac/CCUIPasswordTextField.h"
  25. #include "ui/UIEditBox/Mac/CCUIMultilineTextField.h"
  26. #define getEditBoxImplMac() ((cocos2d::ui::EditBoxImplMac *)_editBox)
  27. @implementation UIEditBoxImplMac
  28. - (instancetype)initWithFrame:(NSRect)frameRect editBox:(void *)editBox
  29. {
  30. self = [super init];
  31. if (self) {
  32. _editState = NO;
  33. self.frameRect = frameRect;
  34. self.editBox = editBox;
  35. self.dataInputMode = cocos2d::ui::EditBox::InputFlag::LOWERCASE_ALL_CHARACTERS;
  36. self.keyboardReturnType = cocos2d::ui::EditBox::KeyboardReturnType::DEFAULT;
  37. [self createMultiLineTextField];
  38. }
  39. return self;
  40. }
  41. - (void)createSingleLineTextField
  42. {
  43. CCUISingleLineTextField *textField = [[[CCUISingleLineTextField alloc] initWithFrame:self.frameRect] autorelease];
  44. self.textInput = textField;
  45. }
  46. - (void)createMultiLineTextField
  47. {
  48. CCUIMultilineTextField *textView = [[[CCUIMultilineTextField alloc] initWithFrame:self.frameRect] autorelease];
  49. [textView setVerticallyResizable:NO];
  50. self.textInput = textView;
  51. }
  52. - (void)createPasswordTextField
  53. {
  54. CCUIPasswordTextField *textField = [[[CCUIPasswordTextField alloc] initWithFrame:self.frameRect] autorelease];
  55. self.textInput = textField;
  56. }
  57. - (void)setTextInput:(NSView<CCUITextInput> *)textInput
  58. {
  59. if (_textInput == textInput) {
  60. return;
  61. }
  62. // Migrate properties
  63. textInput.ccui_textColor = _textInput.ccui_textColor ?: [NSColor whiteColor];
  64. textInput.ccui_text = _textInput.ccui_text ?: @"";
  65. textInput.ccui_placeholder = _textInput.ccui_placeholder ?: @"";
  66. textInput.ccui_font = _textInput.ccui_font ?: [NSFont systemFontOfSize:self.frameRect.size.height*3/2];
  67. textInput.ccui_maxLength = getEditBoxImplMac()->getMaxLength();
  68. textInput.ccui_alignment = _textInput.ccui_alignment;
  69. [_textInput removeFromSuperview];
  70. [_textInput release];
  71. _textInput = [textInput retain];
  72. [_textInput performSelector:@selector(setTextColor:) withObject:_textInput.ccui_textColor];
  73. [_textInput performSelector:@selector(setBackgroundColor:) withObject:[NSColor clearColor]];
  74. if (![_textInput isKindOfClass:[NSTextView class]]) {
  75. [_textInput performSelector:@selector(setBordered:) withObject:nil];
  76. }
  77. _textInput.hidden = NO;
  78. _textInput.wantsLayer = YES;
  79. [_textInput ccui_setDelegate:self];
  80. [self setInputFlag:self.dataInputMode];
  81. [self setReturnType:self.keyboardReturnType];
  82. }
  83. - (void)updateFrame:(CGRect)rect
  84. {
  85. NSRect frame = self.textInput.frame;
  86. frame.origin.x = rect.origin.x;
  87. frame.origin.y = rect.origin.y;
  88. frame.size.height = rect.size.height;
  89. frame.size.width = rect.size.width;
  90. self.textInput.frame = frame;
  91. }
  92. - (void)dealloc
  93. {
  94. self.textInput = nil;
  95. [super dealloc];
  96. }
  97. - (NSWindow *)window
  98. {
  99. auto glview = cocos2d::Director::getInstance()->getOpenGLView();
  100. return glview->getCocoaWindow();
  101. }
  102. - (void)openKeyboard
  103. {
  104. [self.window.contentView addSubview:self.textInput];
  105. if (![self.textInput isKindOfClass:[NSTextView class]]) {
  106. [self.textInput becomeFirstResponder];
  107. }else {
  108. [self.window makeFirstResponder:self.textInput];
  109. }
  110. auto editbox = getEditBoxImplMac()->getEditBox();
  111. auto oldPos = editbox->getPosition();
  112. editbox->setPosition(oldPos + cocos2d::Vec2(10,20));
  113. editbox->setPosition(oldPos);
  114. }
  115. - (void)closeKeyboard
  116. {
  117. if (![self.textInput isKindOfClass:[NSTextView class]]) {
  118. [self.textInput resignFirstResponder];
  119. }
  120. [self.textInput removeFromSuperview];
  121. }
  122. - (const char*) getText
  123. {
  124. return [self.textInput.ccui_text UTF8String];
  125. }
  126. - (void)controlTextDidBeginEditing:(NSNotification *)notification
  127. {
  128. _editState = YES;
  129. getEditBoxImplMac()->editBoxEditingDidBegin();
  130. }
  131. - (void)controlTextDidEndEditing:(NSNotification *)notification
  132. {
  133. _editState = NO;
  134. getEditBoxImplMac()->editBoxEditingDidEnd([self getText], [self getEndAction:notification]);
  135. }
  136. - (void)setMaxLength:(int)length
  137. {
  138. self.textInput.ccui_maxLength = length;
  139. }
  140. /**
  141. * Called each time when the text field's text has changed.
  142. */
  143. - (void)controlTextDidChange:(NSNotification *)notification
  144. {
  145. getEditBoxImplMac()->editBoxEditingChanged([self getText]);
  146. }
  147. - (NSString *)getDefaultFontName
  148. {
  149. return self.textInput.ccui_font.fontName ?: @"";
  150. }
  151. - (void)setInputMode:(cocos2d::ui::EditBox::InputMode)inputMode
  152. {
  153. //multiline input
  154. if (inputMode == cocos2d::ui::EditBox::InputMode::ANY) {
  155. if (![self.textInput isKindOfClass:[NSTextView class]]) {
  156. [self createMultiLineTextField];
  157. }
  158. }
  159. else {
  160. if (self.dataInputMode != cocos2d::ui::EditBox::InputFlag::PASSWORD) {
  161. if (![self.textInput isKindOfClass:[NSTextField class]]) {
  162. [self createSingleLineTextField];
  163. }
  164. }
  165. }
  166. }
  167. - (void)setInputFlag:(cocos2d::ui::EditBox::InputFlag)inputFlag
  168. {
  169. if (self.dataInputMode == inputFlag) {
  170. return;
  171. }
  172. if (self.dataInputMode == cocos2d::ui::EditBox::InputFlag::PASSWORD
  173. && inputFlag != cocos2d::ui::EditBox::InputFlag::PASSWORD) {
  174. [self createSingleLineTextField];
  175. }
  176. if (self.dataInputMode != cocos2d::ui::EditBox::InputFlag::PASSWORD
  177. && inputFlag == cocos2d::ui::EditBox::InputFlag::PASSWORD) {
  178. [self createPasswordTextField];
  179. }
  180. switch (inputFlag)
  181. {
  182. case cocos2d::ui::EditBox::InputFlag::PASSWORD:
  183. self.dataInputMode = inputFlag;
  184. break;
  185. case cocos2d::ui::EditBox::InputFlag::INITIAL_CAPS_WORD:
  186. CCLOG("INITIAL_CAPS_WORD not implemented");
  187. break;
  188. case cocos2d::ui::EditBox::InputFlag::INITIAL_CAPS_SENTENCE:
  189. CCLOG("INITIAL_CAPS_SENTENCE not implemented");
  190. break;
  191. case cocos2d::ui::EditBox::InputFlag::INITIAL_CAPS_ALL_CHARACTERS:
  192. CCLOG("INITIAL_CAPS_ALL_CHARACTERS not implemented");
  193. break;
  194. case cocos2d::ui::EditBox::InputFlag::SENSITIVE:
  195. CCLOG("SENSITIVE not implemented");
  196. break;
  197. case cocos2d::ui::EditBox::InputFlag::LOWERCASE_ALL_CHARACTERS:
  198. CCLOG("LOWERCASE_ALL_CHARACTERS not implemented");
  199. break;
  200. default:
  201. break;
  202. }
  203. }
  204. - (void)setReturnType:(cocos2d::ui::EditBox::KeyboardReturnType)returnType
  205. {
  206. CCLOG("setReturnType not implemented");
  207. }
  208. - (void)setTextHorizontalAlignment:(cocos2d::TextHAlignment)alignment
  209. {
  210. // swizzle center & right, for some reason they're backwards on !TARGET_OS_IPHONE
  211. if (alignment == cocos2d::TextHAlignment::CENTER) alignment = cocos2d::TextHAlignment::RIGHT;
  212. else if (alignment == cocos2d::TextHAlignment::RIGHT) alignment = cocos2d::TextHAlignment::CENTER;
  213. self.textInput.ccui_alignment = static_cast<NSTextAlignment>(alignment);
  214. }
  215. - (void)setPlaceHolder:(const char *)text
  216. {
  217. self.textInput.ccui_placeholder = [NSString stringWithUTF8String:text];
  218. }
  219. - (void)setVisible:(BOOL)visible
  220. {
  221. self.textInput.hidden = !visible;
  222. }
  223. - (void)setTextColor:(NSColor*)color
  224. {
  225. self.textInput.ccui_textColor = color;
  226. }
  227. - (void)setFont:(NSFont *)font
  228. {
  229. if (font != nil) {
  230. self.textInput.ccui_font = font;
  231. }
  232. }
  233. - (void)setPlaceholderFontColor:(NSColor *)color
  234. {
  235. self.textInput.ccui_placeholderColor = color;
  236. }
  237. - (void)setPlaceholderFont:(NSFont*)font
  238. {
  239. self.textInput.ccui_placeholderFont = font;
  240. }
  241. - (void)setText:(NSString *)text
  242. {
  243. self.textInput.ccui_text = text;
  244. }
  245. - (BOOL)textShouldBeginEditing:(NSText *)textObject // YES means do it
  246. {
  247. _editState = YES;
  248. getEditBoxImplMac()->editBoxEditingDidBegin();
  249. return YES;
  250. }
  251. - (void)textDidEndEditing:(NSNotification *)notification
  252. {
  253. _editState = NO;
  254. getEditBoxImplMac()->editBoxEditingDidEnd([self getText], [self getEndAction:notification]);
  255. }
  256. - (cocos2d::ui::EditBoxDelegate::EditBoxEndAction)getEndAction:(NSNotification *)notification
  257. {
  258. auto type = cocos2d::ui::EditBoxDelegate::EditBoxEndAction::UNKNOWN;
  259. NSUInteger reasonForEnding = [[[notification userInfo] objectForKey:@"NSTextMovement"] unsignedIntValue];
  260. if (reasonForEnding == NSTabTextMovement) {
  261. type = cocos2d::ui::EditBoxDelegate::EditBoxEndAction::TAB_TO_NEXT;
  262. } else if (reasonForEnding == NSBacktabTextMovement) {
  263. type = cocos2d::ui::EditBoxDelegate::EditBoxEndAction::TAB_TO_PREVIOUS;
  264. } else if (reasonForEnding == NSReturnTextMovement) {
  265. type = cocos2d::ui::EditBoxDelegate::EditBoxEndAction::RETURN;
  266. }
  267. return type;
  268. }
  269. - (void)textDidChange:(NSNotification *)notification
  270. {
  271. NSTextView* textView = notification.object;
  272. const char* inputText = [textView.string UTF8String];
  273. getEditBoxImplMac()->editBoxEditingChanged(inputText);
  274. }
  275. - (BOOL)textView:(NSTextView *)textView shouldChangeTextInRange:(NSRange)affectedCharRange replacementString:(NSString *)replacementString
  276. {
  277. int maxLength = getEditBoxImplMac()->getMaxLength();
  278. if (maxLength < 0)
  279. {
  280. return YES;
  281. }
  282. if (affectedCharRange.length + affectedCharRange.location > textView.string.length) {
  283. return NO;
  284. }
  285. NSUInteger oldLength = textView.string.length;
  286. NSUInteger replacementLength = replacementString.length;
  287. NSUInteger rangeLength = affectedCharRange.length;
  288. NSUInteger newLength = oldLength - rangeLength + replacementLength;
  289. return newLength <= maxLength;
  290. }
  291. @end