]> git.saurik.com Git - wxWidgets.git/blob - src/osx/iphone/textctrl.mm
iphone implementations
[wxWidgets.git] / src / osx / iphone / textctrl.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/cocoa/textctrl.mm
3 // Purpose: wxTextCtrl
4 // Author: Stefan Csomor
5 // Modified by: Ryan Norton (MLTE GetLineLength and GetLineText)
6 // Created: 1998-01-01
7 // RCS-ID: $Id: textctrl.cpp 54820 2008-07-29 20:04:11Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #if wxUSE_TEXTCTRL
15
16 #include "wx/textctrl.h"
17
18 #ifndef WX_PRECOMP
19 #include "wx/intl.h"
20 #include "wx/app.h"
21 #include "wx/utils.h"
22 #include "wx/dc.h"
23 #include "wx/button.h"
24 #include "wx/menu.h"
25 #include "wx/settings.h"
26 #include "wx/msgdlg.h"
27 #include "wx/toplevel.h"
28 #endif
29
30 #ifdef __DARWIN__
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #else
34 #include <stat.h>
35 #endif
36
37 #if wxUSE_STD_IOSTREAM
38 #if wxUSE_IOSTREAMH
39 #include <fstream.h>
40 #else
41 #include <fstream>
42 #endif
43 #endif
44
45 #include "wx/filefn.h"
46 #include "wx/sysopt.h"
47 #include "wx/thread.h"
48
49 #include "wx/osx/private.h"
50 #include "wx/osx/iphone/private/textimpl.h"
51
52 // currently for some reasong the UITextField leads to a recursion when the keyboard should be shown, so let's leave the code
53 // in case this gets resolved...
54
55 #define wxOSX_IPHONE_USE_TEXTFIELD 0
56
57 class wxMacEditHelper
58 {
59 public :
60 wxMacEditHelper( UITextView* textView )
61 {
62 m_textView = textView;
63 m_formerState = YES;
64 if ( textView )
65 {
66 m_formerState = [textView isEditable];
67 [textView setEditable:YES];
68 }
69 }
70
71 ~wxMacEditHelper()
72 {
73 if ( m_textView )
74 [m_textView setEditable:m_formerState];
75 }
76
77 protected :
78 BOOL m_formerState ;
79 UITextView* m_textView;
80 } ;
81
82 #if wxOSX_IPHONE_USE_TEXTFIELD
83
84 @interface wxUITextField : UITextField<UITextFieldDelegate>
85 {
86 }
87
88 @end
89
90 @implementation wxNSSecureTextField
91
92 + (void)initialize
93 {
94 static BOOL initialized = NO;
95 if (!initialized)
96 {
97 initialized = YES;
98 wxOSXIPhoneClassAddWXMethods( self );
99 }
100 }
101
102 - (void)controlTextDidChange:(NSNotification *)aNotification
103 {
104 wxUnusedVar(aNotification);
105 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
106 if ( impl )
107 impl->controlTextDidChange();
108 }
109
110 - (void)controlTextDidEndEditing:(NSNotification *)aNotification
111 {
112 wxUnusedVar(aNotification);
113 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
114 if ( impl )
115 {
116 impl->DoNotifyFocusEvent( false, NULL );
117 }
118 }
119
120 @end
121
122 @implementation wxUITextFieldEditor
123
124 - (void) keyDown:(NSEvent*) event
125 {
126 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
127 lastKeyDownEvent = event;
128 if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
129 [super keyDown:event];
130 lastKeyDownEvent = nil;
131 }
132
133 - (void) keyUp:(NSEvent*) event
134 {
135 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
136 if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
137 [super keyUp:event];
138 }
139
140 - (void) flagsChanged:(NSEvent*) event
141 {
142 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
143 if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
144 [super flagsChanged:event];
145 }
146
147 - (BOOL) performKeyEquivalent:(NSEvent*) event
148 {
149 BOOL retval = [super performKeyEquivalent:event];
150 return retval;
151 }
152
153 - (void) insertText:(id) str
154 {
155 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
156 if ( impl == NULL || lastKeyDownEvent==nil || !impl->DoHandleCharEvent(lastKeyDownEvent, str) )
157 {
158 [super insertText:str];
159 }
160 }
161
162 @end
163
164 @implementation wxUITextField
165
166 + (void)initialize
167 {
168 static BOOL initialized = NO;
169 if (!initialized)
170 {
171 initialized = YES;
172 wxOSXIPhoneClassAddWXMethods( self );
173 }
174 }
175
176 #if 0
177 - (void)controlTextDidChange:(NSNotification *)aNotification
178 {
179 wxUnusedVar(aNotification);
180 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
181 if ( impl )
182 impl->controlTextDidChange();
183 }
184 #endif
185
186 - (BOOL)textFieldShouldReturn:(UITextField *)textField
187 {
188 wxUnusedVar(textField);
189
190 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
191 if ( impl )
192 {
193 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
194 if ( wxpeer && wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER )
195 {
196 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
197 event.SetEventObject( wxpeer );
198 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
199 wxpeer->HandleWindowEvent( event );
200 }
201 }
202
203 return NO;
204 }
205
206 - (void)controlTextDidEndEditing:(NSNotification *)aNotification
207 {
208 wxUnusedVar(aNotification);
209 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
210 if ( impl )
211 {
212 impl->DoNotifyFocusEvent( false, NULL );
213 }
214 }
215 @end
216
217 #endif
218
219 @interface wxUITextViewDelegate : NSObject<UITextViewDelegate>
220 {
221 }
222
223 - (void)textViewDidChange:(UITextView *)textView;
224 - (void)textViewDidBeginEditing:(UITextView *)textView;
225 - (void)textViewDidEndEditing:(UITextView *)textView;
226 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
227
228 @end
229
230 @implementation wxUITextViewDelegate
231
232 - (void)textViewDidChange:(UITextView *)textView
233 {
234 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( textView );
235 if ( impl )
236 impl->controlTextDidChange();
237 }
238
239 - (void)textViewDidBeginEditing:(UITextView *)textView
240 {
241 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( textView );
242 if ( impl )
243 impl->DoNotifyFocusEvent(true, NULL);
244 }
245
246 - (void)textViewDidEndEditing:(UITextView *)textView
247 {
248 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( textView );
249 if ( impl )
250 impl->DoNotifyFocusEvent(false, NULL);
251 }
252
253 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
254 {
255 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( textView );
256 if ( impl )
257 {
258 if ( !impl->GetWXPeer()->HasFlag(wxTE_MULTILINE) && [text isEqualToString:@"\n"])
259 {
260 [textView resignFirstResponder];
261 return NO;
262 }
263 }
264 return YES;
265 }
266
267
268 @end
269
270 //
271 // wxUITextViewControl
272 //
273
274 wxUITextViewControl::wxUITextViewControl( wxTextCtrl *wxPeer, UITextView* v) : wxWidgetIPhoneImpl(wxPeer, v)
275 {
276 m_textView = v;
277 wxUITextViewDelegate* d = [[wxUITextViewDelegate alloc] init];
278
279 [m_textView setDelegate:d];
280 }
281
282 wxUITextViewControl::~wxUITextViewControl()
283 {
284 if (m_textView)
285 {
286 wxUITextViewDelegate* d = [m_textView delegate];
287 [m_textView setDelegate: nil];
288 [d release];
289 }
290 }
291
292 bool wxUITextViewControl::CanFocus() const
293 {
294 return true;
295 }
296
297 wxString wxUITextViewControl::GetStringValue() const
298 {
299 if (m_textView)
300 {
301 wxString result = wxCFStringRef::AsString([m_textView text], m_wxPeer->GetFont().GetEncoding());
302 wxMacConvertNewlines13To10( &result ) ;
303 return result;
304 }
305 return wxEmptyString;
306 }
307
308 void wxUITextViewControl::SetStringValue( const wxString &str)
309 {
310 wxString st = str;
311 wxMacConvertNewlines10To13( &st );
312 wxMacEditHelper helper(m_textView);
313
314 if (m_textView)
315 [m_textView setText: wxCFStringRef( st , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
316 }
317
318 void wxUITextViewControl::Copy()
319 {
320 if (m_textView)
321 [m_textView copy:nil];
322
323 }
324
325 void wxUITextViewControl::Cut()
326 {
327 if (m_textView)
328 [m_textView cut:nil];
329 }
330
331 void wxUITextViewControl::Paste()
332 {
333 if (m_textView)
334 [m_textView paste:nil];
335 }
336
337 bool wxUITextViewControl::CanPaste() const
338 {
339 return true;
340 }
341
342 void wxUITextViewControl::SetEditable(bool editable)
343 {
344 if (m_textView)
345 [m_textView setEditable: editable];
346 }
347
348 void wxUITextViewControl::GetSelection( long* from, long* to) const
349 {
350 if (m_textView)
351 {
352 NSRange range = [m_textView selectedRange];
353 *from = range.location;
354 *to = range.location + range.length;
355 }
356 }
357
358 void wxUITextViewControl::SetSelection( long from , long to )
359 {
360 long textLength = [[m_textView text] length];
361 if ((from == -1) && (to == -1))
362 {
363 from = 0 ;
364 to = textLength ;
365 }
366 else
367 {
368 from = wxMin(textLength,wxMax(from,0)) ;
369 if ( to == -1 )
370 to = textLength;
371 else
372 to = wxMax(0,wxMin(textLength,to)) ;
373 }
374
375 NSRange selrange = NSMakeRange(from, to-from);
376 [m_textView setSelectedRange:selrange];
377 [m_textView scrollRangeToVisible:selrange];
378 }
379
380 void wxUITextViewControl::WriteText(const wxString& str)
381 {
382 wxString st = str;
383 wxMacConvertNewlines10To13( &st );
384 wxMacEditHelper helper(m_textView);
385
386 wxCFStringRef insert( st , m_wxPeer->GetFont().GetEncoding() );
387 NSMutableString* subst = [NSMutableString stringWithString:[m_textView text]];
388 [subst replaceCharactersInRange:[m_textView selectedRange] withString:insert.AsNSString()];
389
390 [m_textView setText:subst];
391 }
392
393 void wxUITextViewControl::SetFont( const wxFont & font , const wxColour& WXUNUSED(foreground) , long WXUNUSED(windowStyle), bool WXUNUSED(ignoreBlack) )
394 {
395 if ([m_textView respondsToSelector:@selector(setFont:)])
396 [m_textView setFont: font.OSXGetUIFont()];
397 }
398
399 bool wxUITextViewControl::GetStyle(long position, wxTextAttr& style)
400 {
401 if (m_textView && position >=0)
402 {
403 UIFont* font = NULL;
404 NSColor* bgcolor = NULL;
405 NSColor* fgcolor = NULL;
406 // NOTE: It appears that other platforms accept GetStyle with the position == length
407 // but that UITextStorage does not accept length as a valid position.
408 // Therefore we return the default control style in that case.
409 /*
410 if (position < [[m_textView string] length])
411 {
412 UITextStorage* storage = [m_textView textStorage];
413 font = [[storage attribute:NSFontAttributeName atIndex:position effectiveRange:NULL] autorelease];
414 bgcolor = [[storage attribute:NSBackgroundColorAttributeName atIndex:position effectiveRange:NULL] autorelease];
415 fgcolor = [[storage attribute:NSForegroundColorAttributeName atIndex:position effectiveRange:NULL] autorelease];
416 }
417 else
418 {
419 NSDictionary* attrs = [m_textView typingAttributes];
420 font = [[attrs objectForKey:NSFontAttributeName] autorelease];
421 bgcolor = [[attrs objectForKey:NSBackgroundColorAttributeName] autorelease];
422 fgcolor = [[attrs objectForKey:NSForegroundColorAttributeName] autorelease];
423 }
424 */
425 /*
426 if (font)
427 style.SetFont(wxFont(font));
428
429 if (bgcolor)
430 style.SetBackgroundColour(wxColour(bgcolor));
431
432 if (fgcolor)
433 style.SetTextColour(wxColour(fgcolor));
434 */
435 return true;
436 }
437
438 return false;
439 }
440
441 void wxUITextViewControl::SetStyle(long start,
442 long end,
443 const wxTextAttr& style)
444 {
445 if (m_textView) {
446 NSRange range = NSMakeRange(start, end-start);
447 if (start == -1 && end == -1)
448 range = [m_textView selectedRange];
449 /*
450 UITextStorage* storage = [m_textView textStorage];
451
452 wxFont font = style.GetFont();
453 if (style.HasFont() && font.IsOk())
454 [storage addAttribute:NSFontAttributeName value:font.OSXGetNSFont() range:range];
455
456 wxColour bgcolor = style.GetBackgroundColour();
457 if (style.HasBackgroundColour() && bgcolor.IsOk())
458 [storage addAttribute:NSBackgroundColorAttributeName value:bgcolor.OSXGetNSColor() range:range];
459
460 wxColour fgcolor = style.GetTextColour();
461 if (style.HasTextColour() && fgcolor.IsOk())
462 [storage addAttribute:NSForegroundColorAttributeName value:fgcolor.OSXGetNSColor() range:range];
463 */
464 }
465 }
466
467 void wxUITextViewControl::CheckSpelling(bool check)
468 {
469 }
470
471 wxSize wxUITextViewControl::GetBestSize() const
472 {
473 wxRect r;
474
475 GetBestRect(&r);
476
477 /*
478 if (m_textView && [m_textView layoutManager])
479 {
480 NSRect rect = [[m_textView layoutManager] usedRectForTextContainer: [m_textView textContainer]];
481 wxSize size = wxSize(rect.size.width, rect.size.height);
482 size.x += [m_textView textContainerInset].width;
483 size.y += [m_textView textContainerInset].height;
484 return size;
485 }
486 return wxSize(0,0);
487 */
488 return r.GetSize();
489 }
490
491 #if wxOSX_IPHONE_USE_TEXTFIELD
492
493 //
494 // wxUITextFieldControl
495 //
496
497 wxUITextFieldControl::wxUITextFieldControl( wxWindow *wxPeer, UITextField* w ) : wxWidgetIPhoneImpl(wxPeer, w)
498 {
499 UITextField wxOSX_10_6_AND_LATER(<UITextFieldDelegate>) *tf = (UITextField*) w;
500 m_textField = tf;
501 [m_textField setDelegate: tf];
502 m_selStart = m_selEnd = 0;
503 }
504
505 wxUITextFieldControl::~wxUITextFieldControl()
506 {
507 if (m_textField)
508 [m_textField setDelegate: nil];
509 }
510
511 wxString wxUITextFieldControl::GetStringValue() const
512 {
513 return wxCFStringRef::AsString([m_textField text], m_wxPeer->GetFont().GetEncoding());
514 }
515
516 void wxUITextFieldControl::SetStringValue( const wxString &str)
517 {
518 // wxMacEditHelper helper(m_textField);
519 [m_textField setText: wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
520 }
521
522 void wxUITextFieldControl::Copy()
523 {
524 [m_textField copy:nil];
525 }
526
527 void wxUITextFieldControl::Cut()
528 {
529 [m_textField cut:nil];
530 }
531
532 void wxUITextFieldControl::Paste()
533 {
534 [m_textField paste:nil];
535 }
536
537 bool wxUITextFieldControl::CanPaste() const
538 {
539 return true;
540 }
541
542 void wxUITextFieldControl::SetEditable(bool editable)
543 {
544 }
545
546 void wxUITextFieldControl::GetSelection( long* from, long* to) const
547 {
548 *from = m_selStart;
549 *to = m_selEnd;
550 }
551
552 void wxUITextFieldControl::SetSelection( long from , long to )
553 {
554 long textLength = [[m_textField text] length];
555 if ((from == -1) && (to == -1))
556 {
557 from = 0 ;
558 to = textLength ;
559 }
560 else
561 {
562 from = wxMin(textLength,wxMax(from,0)) ;
563 if ( to == -1 )
564 to = textLength;
565 else
566 to = wxMax(0,wxMin(textLength,to)) ;
567 }
568
569 m_selStart = from;
570 m_selEnd = to;
571 }
572
573 void wxUITextFieldControl::WriteText(const wxString& str)
574 {
575 #if 0
576 NSEvent* formerEvent = m_lastKeyDownEvent;
577 UIText* editor = [m_textField currentEditor];
578 if ( editor )
579 {
580 wxMacEditHelper helper(m_textField);
581 [editor insertText:wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
582 }
583 else
584 #endif
585 {
586 wxString val = GetStringValue() ;
587 long start , end ;
588 GetSelection( &start , &end ) ;
589 val.Remove( start , end - start ) ;
590 val.insert( start , str ) ;
591 SetStringValue( val ) ;
592 SetSelection( start + str.length() , start + str.length() ) ;
593 }
594 #if 0
595 m_lastKeyDownEvent = formerEvent;
596 #endif
597 }
598
599 void wxUITextFieldControl::controlAction(WXWidget WXUNUSED(slf),
600 void* WXUNUSED(_cmd), void *WXUNUSED(sender))
601 {
602 wxWindow* wxpeer = (wxWindow*) GetWXPeer();
603 if ( wxpeer && (wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER) )
604 {
605 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
606 event.SetEventObject( wxpeer );
607 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
608 wxpeer->HandleWindowEvent( event );
609 }
610 }
611
612 #endif
613
614 //
615 //
616 //
617
618 wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer,
619 wxWindowMac* WXUNUSED(parent),
620 wxWindowID WXUNUSED(id),
621 const wxString& str,
622 const wxPoint& pos,
623 const wxSize& size,
624 long style,
625 long WXUNUSED(extraStyle))
626 {
627 CGRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
628 wxWidgetIPhoneImpl* c = NULL;
629 wxTextWidgetImpl* t = NULL;
630 id<UITextInputTraits> tv = nil;
631
632 #if wxOSX_IPHONE_USE_TEXTFIELD
633 if ( style & wxTE_MULTILINE || style & wxTE_RICH || style & wxTE_RICH2 )
634 #endif
635 {
636 UITextView * v = nil;
637 v = [[UITextView alloc] initWithFrame:r];
638 tv = v;
639
640 wxUITextViewControl* tc = new wxUITextViewControl( wxpeer, v );
641 c = tc;
642 t = tc;
643 }
644 #if wxOSX_IPHONE_USE_TEXTFIELD
645 else
646 {
647 UITextField* v = [[UITextField alloc] initWithFrame:r];
648 tv = v;
649
650 v.textColor = [UIColor blackColor];
651 v.font = [UIFont systemFontOfSize:17.0];
652 v.placeholder = @"<enter text>";
653 v.backgroundColor = [UIColor whiteColor];
654
655 v.clearButtonMode = UITextFieldViewModeWhileEditing; // has a clear 'x' button to the right
656
657 v.delegate = v; // let us be the delegate so we know when the keyboard's "Done" button is pressed
658
659 [v setBorderStyle:UITextBorderStyleBezel];
660 if ( style & wxNO_BORDER )
661 v.borderStyle = UITextBorderStyleNone;
662
663 wxUITextFieldControl* tc = new wxUITextFieldControl( wxpeer, v );
664 c = tc;
665 t = tc;
666 }
667 #endif
668
669 if ( style & wxTE_PASSWORD )
670 [tv setSecureTextEntry:YES];
671
672 if ( !(style & wxTE_MULTILINE) )
673 {
674 [tv setAutocorrectionType:UITextAutocorrectionTypeNo];
675 [tv setReturnKeyType:UIReturnKeyDone];
676 }
677 [tv setKeyboardType:UIKeyboardTypeDefault];
678
679 t->SetStringValue(str);
680
681 return c;
682 }
683
684
685 #endif // wxUSE_TEXTCTRL