]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/osx/iphone/textctrl.mm
Merge in from trunk r67662 to r64801
[wxWidgets.git] / src / osx / iphone / textctrl.mm
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/iphone/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$
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 1
56
57class wxMacEditHelper
58{
59public :
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
77protected :
78 BOOL m_formerState ;
79 UITextView* m_textView;
80} ;
81
82#if wxOSX_IPHONE_USE_TEXTFIELD
83
84@interface wxUITextFieldDelegate : NSObject<UITextFieldDelegate>
85{
86}
87
88@end
89
90
91@interface wxUITextField : UITextField
92{
93}
94
95@end
96
97@interface wxNSSecureTextField : UITextField<UITextFieldDelegate>
98{
99}
100
101@end
102
103@implementation wxNSSecureTextField
104
105+ (void)initialize
106{
107 static BOOL initialized = NO;
108 if (!initialized)
109 {
110 initialized = YES;
111 wxOSXIPhoneClassAddWXMethods( self );
112 }
113}
114
115- (void)controlTextDidChange:(NSNotification *)aNotification
116{
117 wxUnusedVar(aNotification);
118 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
119 if ( impl )
120 impl->controlTextDidChange();
121}
122
123- (void)controlTextDidEndEditing:(NSNotification *)aNotification
124{
125 wxUnusedVar(aNotification);
126 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
127 if ( impl )
128 {
129 impl->DoNotifyFocusEvent( false, NULL );
130 }
131}
132
133@end
134
135#if 0
136@implementation wxUITextFieldEditor
137
138- (void) keyDown:(NSEvent*) event
139{
140 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
141 lastKeyDownEvent = event;
142 if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
143 [super keyDown:event];
144 lastKeyDownEvent = nil;
145}
146
147- (void) keyUp:(NSEvent*) event
148{
149 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
150 if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
151 [super keyUp:event];
152}
153
154- (void) flagsChanged:(NSEvent*) event
155{
156 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
157 if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
158 [super flagsChanged:event];
159}
160
161- (BOOL) performKeyEquivalent:(NSEvent*) event
162{
163 BOOL retval = [super performKeyEquivalent:event];
164 return retval;
165}
166
167- (void) insertText:(id) str
168{
169 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
170 if ( impl == NULL || lastKeyDownEvent==nil || !impl->DoHandleCharEvent(lastKeyDownEvent, str) )
171 {
172 [super insertText:str];
173 }
174}
175
176@end
177
178#endif
179
180
181@implementation wxUITextFieldDelegate
182
183- (BOOL)textFieldShouldReturn:(UITextField *)textField
184{
185 // the user pressed the "Done" button, so dismiss the keyboard
186 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( textField );
187 if ( impl )
188 {
189 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
190 if ( wxpeer && wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER )
191 {
192 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
193 event.SetEventObject( wxpeer );
194 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
195 wxpeer->HandleWindowEvent( event );
196 }
197 }
198
199 [textField resignFirstResponder];
200 return YES;
201}
202
203/*
204- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField; // return NO to disallow editing.
205- (void)textFieldDidBeginEditing:(UITextField *)textField; // became first responder
206- (BOOL)textFieldShouldEndEditing:(UITextField *)textField; // return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end
207- (void)textFieldDidEndEditing:(UITextField *)textField; // may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called
208
209- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; // return NO to not change text
210
211- (BOOL)textFieldShouldClear:(UITextField *)textField; // called when clear button pressed. return NO to ignore (no notifications)
212*/
213
214@end
215
216
217@implementation wxUITextField
218
219+ (void)initialize
220{
221 static BOOL initialized = NO;
222 if (!initialized)
223 {
224 initialized = YES;
225 wxOSXIPhoneClassAddWXMethods( self );
226 }
227}
228
229#if 0
230- (void)controlTextDidChange:(NSNotification *)aNotification
231{
232 wxUnusedVar(aNotification);
233 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
234 if ( impl )
235 impl->controlTextDidChange();
236}
237#endif
238
239- (BOOL)textFieldShouldReturn:(UITextField *)textField
240{
241 wxUnusedVar(textField);
242
243
244 return NO;
245}
246
247- (void)controlTextDidEndEditing:(NSNotification *)aNotification
248{
249 wxUnusedVar(aNotification);
250 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self );
251 if ( impl )
252 {
253 impl->DoNotifyFocusEvent( false, NULL );
254 }
255}
256@end
257
258#endif
259
260@interface wxUITextViewDelegate : NSObject<UITextViewDelegate>
261{
262}
263
264- (void)textViewDidChange:(UITextView *)textView;
265- (void)textViewDidBeginEditing:(UITextView *)textView;
266- (void)textViewDidEndEditing:(UITextView *)textView;
267- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
268
269@end
270
271@implementation wxUITextViewDelegate
272
273- (void)textViewDidChange:(UITextView *)textView
274{
275 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( textView );
276 if ( impl )
277 impl->controlTextDidChange();
278}
279
280- (void)textViewDidBeginEditing:(UITextView *)textView
281{
282 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( textView );
283 if ( impl )
284 impl->DoNotifyFocusEvent(true, NULL);
285}
286
287- (void)textViewDidEndEditing:(UITextView *)textView
288{
289 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( textView );
290 if ( impl )
291 impl->DoNotifyFocusEvent(false, NULL);
292}
293
294- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
295{
296 wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( textView );
297 if ( impl )
298 {
299 if ( !impl->GetWXPeer()->HasFlag(wxTE_MULTILINE) && [text isEqualToString:@"\n"])
300 {
301 [textView resignFirstResponder];
302 return NO;
303 }
304 }
305 return YES;
306}
307
308
309@end
310
311//
312// wxUITextViewControl
313//
314
315wxUITextViewControl::wxUITextViewControl( wxTextCtrl *wxPeer, UITextView* v) :
316 wxWidgetIPhoneImpl(wxPeer, v),
317 wxTextWidgetImpl(wxPeer)
318{
319 m_textView = v;
320 m_delegate= [[wxUITextViewDelegate alloc] init];
321
322 [m_textView setDelegate:m_delegate];
323}
324
325wxUITextViewControl::~wxUITextViewControl()
326{
327 if (m_textView)
328 {
329 [m_textView setDelegate: nil];
330 }
331 [m_delegate release];
332}
333
334bool wxUITextViewControl::CanFocus() const
335{
336 return true;
337}
338
339wxString wxUITextViewControl::GetStringValue() const
340{
341 if (m_textView)
342 {
343 wxString result = wxCFStringRef::AsString([m_textView text], m_wxPeer->GetFont().GetEncoding());
344 wxMacConvertNewlines13To10( &result ) ;
345 return result;
346 }
347 return wxEmptyString;
348}
349
350void wxUITextViewControl::SetStringValue( const wxString &str)
351{
352 wxString st = str;
353 wxMacConvertNewlines10To13( &st );
354 wxMacEditHelper helper(m_textView);
355
356 if (m_textView)
357 [m_textView setText: wxCFStringRef( st , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
358}
359
360void wxUITextViewControl::Copy()
361{
362 if (m_textView)
363 [m_textView copy:nil];
364
365}
366
367void wxUITextViewControl::Cut()
368{
369 if (m_textView)
370 [m_textView cut:nil];
371}
372
373void wxUITextViewControl::Paste()
374{
375 if (m_textView)
376 [m_textView paste:nil];
377}
378
379bool wxUITextViewControl::CanPaste() const
380{
381 return true;
382}
383
384void wxUITextViewControl::SetEditable(bool editable)
385{
386 if (m_textView)
387 [m_textView setEditable: editable];
388}
389
390void wxUITextViewControl::GetSelection( long* from, long* to) const
391{
392 if (m_textView)
393 {
394 NSRange range = [m_textView selectedRange];
395 *from = range.location;
396 *to = range.location + range.length;
397 }
398}
399
400void wxUITextViewControl::SetSelection( long from , long to )
401{
402 long textLength = [[m_textView text] length];
403 if ((from == -1) && (to == -1))
404 {
405 from = 0 ;
406 to = textLength ;
407 }
408 else
409 {
410 from = wxMin(textLength,wxMax(from,0)) ;
411 if ( to == -1 )
412 to = textLength;
413 else
414 to = wxMax(0,wxMin(textLength,to)) ;
415 }
416
417 NSRange selrange = NSMakeRange(from, to-from);
418 [m_textView setSelectedRange:selrange];
419 [m_textView scrollRangeToVisible:selrange];
420}
421
422void wxUITextViewControl::WriteText(const wxString& str)
423{
424 wxString st = str;
425 wxMacConvertNewlines10To13( &st );
426 wxMacEditHelper helper(m_textView);
427
428 wxCFStringRef insert( st , m_wxPeer->GetFont().GetEncoding() );
429 NSMutableString* subst = [NSMutableString stringWithString:[m_textView text]];
430 [subst replaceCharactersInRange:[m_textView selectedRange] withString:insert.AsNSString()];
431
432 [m_textView setText:subst];
433}
434
435void wxUITextViewControl::SetFont( const wxFont & font , const wxColour& WXUNUSED(foreground) , long WXUNUSED(windowStyle), bool WXUNUSED(ignoreBlack) )
436{
437 if ([m_textView respondsToSelector:@selector(setFont:)])
438 [m_textView setFont: font.OSXGetUIFont()];
439}
440
441bool wxUITextViewControl::GetStyle(long position, wxTextAttr& style)
442{
443 if (m_textView && position >=0)
444 {
445 // UIFont* font = NULL;
446 // NSColor* bgcolor = NULL;
447 // NSColor* fgcolor = NULL;
448 // NOTE: It appears that other platforms accept GetStyle with the position == length
449 // but that UITextStorage does not accept length as a valid position.
450 // Therefore we return the default control style in that case.
451 /*
452 if (position < [[m_textView string] length])
453 {
454 UITextStorage* storage = [m_textView textStorage];
455 font = [[storage attribute:NSFontAttributeName atIndex:position effectiveRange:NULL] autorelease];
456 bgcolor = [[storage attribute:NSBackgroundColorAttributeName atIndex:position effectiveRange:NULL] autorelease];
457 fgcolor = [[storage attribute:NSForegroundColorAttributeName atIndex:position effectiveRange:NULL] autorelease];
458 }
459 else
460 {
461 NSDictionary* attrs = [m_textView typingAttributes];
462 font = [[attrs objectForKey:NSFontAttributeName] autorelease];
463 bgcolor = [[attrs objectForKey:NSBackgroundColorAttributeName] autorelease];
464 fgcolor = [[attrs objectForKey:NSForegroundColorAttributeName] autorelease];
465 }
466 */
467 /*
468 if (font)
469 style.SetFont(wxFont(font));
470
471 if (bgcolor)
472 style.SetBackgroundColour(wxColour(bgcolor));
473
474 if (fgcolor)
475 style.SetTextColour(wxColour(fgcolor));
476 */
477 return true;
478 }
479
480 return false;
481}
482
483void wxUITextViewControl::SetStyle(long start,
484 long end,
485 const wxTextAttr& style)
486{
487 if (m_textView) {
488 NSRange range = NSMakeRange(start, end-start);
489 if (start == -1 && end == -1)
490 range = [m_textView selectedRange];
491/*
492 UITextStorage* storage = [m_textView textStorage];
493
494 wxFont font = style.GetFont();
495 if (style.HasFont() && font.IsOk())
496 [storage addAttribute:NSFontAttributeName value:font.OSXGetNSFont() range:range];
497
498 wxColour bgcolor = style.GetBackgroundColour();
499 if (style.HasBackgroundColour() && bgcolor.IsOk())
500 [storage addAttribute:NSBackgroundColorAttributeName value:bgcolor.OSXGetNSColor() range:range];
501
502 wxColour fgcolor = style.GetTextColour();
503 if (style.HasTextColour() && fgcolor.IsOk())
504 [storage addAttribute:NSForegroundColorAttributeName value:fgcolor.OSXGetNSColor() range:range];
505*/
506 }
507}
508
509void wxUITextViewControl::CheckSpelling(bool check)
510{
511}
512
513wxSize wxUITextViewControl::GetBestSize() const
514{
515 wxRect r;
516
517 GetBestRect(&r);
518
519 /*
520 if (m_textView && [m_textView layoutManager])
521 {
522 NSRect rect = [[m_textView layoutManager] usedRectForTextContainer: [m_textView textContainer]];
523 wxSize size = wxSize(rect.size.width, rect.size.height);
524 size.x += [m_textView textContainerInset].width;
525 size.y += [m_textView textContainerInset].height;
526 return size;
527 }
528 return wxSize(0,0);
529 */
530
531 wxSize sz = r.GetSize();
532 if ( sz.y < 31 )
533 sz.y = 31;
534
535 return sz;
536}
537
538#if wxOSX_IPHONE_USE_TEXTFIELD
539
540//
541// wxUITextFieldControl
542//
543
544wxUITextFieldControl::wxUITextFieldControl( wxTextCtrl *wxPeer, UITextField* w ) :
545 wxWidgetIPhoneImpl(wxPeer, w),
546 wxTextWidgetImpl(wxPeer)
547{
548 m_textField = w;
549 m_delegate = [[wxUITextFieldDelegate alloc] init];
550 [m_textField setDelegate: m_delegate];
551 m_selStart = m_selEnd = 0;
552}
553
554wxUITextFieldControl::~wxUITextFieldControl()
555{
556 if (m_textField)
557 [m_textField setDelegate: nil];
558 [m_delegate release];
559}
560
561wxString wxUITextFieldControl::GetStringValue() const
562{
563 return wxCFStringRef::AsString([m_textField text], m_wxPeer->GetFont().GetEncoding());
564}
565
566void wxUITextFieldControl::SetStringValue( const wxString &str)
567{
568// wxMacEditHelper helper(m_textField);
569 [m_textField setText: wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
570}
571
572wxSize wxUITextFieldControl::GetBestSize() const
573{
574 wxRect r;
575
576 GetBestRect(&r);
577 wxSize sz = r.GetSize();
578 if ( sz.y < 31 )
579 sz.y = 31;
580 return sz;
581}
582
583void wxUITextFieldControl::Copy()
584{
585 [m_textField copy:nil];
586}
587
588void wxUITextFieldControl::Cut()
589{
590 [m_textField cut:nil];
591}
592
593void wxUITextFieldControl::Paste()
594{
595 [m_textField paste:nil];
596}
597
598bool wxUITextFieldControl::CanPaste() const
599{
600 return true;
601}
602
603void wxUITextFieldControl::SetEditable(bool editable)
604{
605}
606
607void wxUITextFieldControl::GetSelection( long* from, long* to) const
608{
609 *from = m_selStart;
610 *to = m_selEnd;
611}
612
613void wxUITextFieldControl::SetSelection( long from , long to )
614{
615 long textLength = [[m_textField text] length];
616 if ((from == -1) && (to == -1))
617 {
618 from = 0 ;
619 to = textLength ;
620 }
621 else
622 {
623 from = wxMin(textLength,wxMax(from,0)) ;
624 if ( to == -1 )
625 to = textLength;
626 else
627 to = wxMax(0,wxMin(textLength,to)) ;
628 }
629
630 m_selStart = from;
631 m_selEnd = to;
632}
633
634void wxUITextFieldControl::WriteText(const wxString& str)
635{
636#if 0
637 NSEvent* formerEvent = m_lastKeyDownEvent;
638 UIText* editor = [m_textField currentEditor];
639 if ( editor )
640 {
641 wxMacEditHelper helper(m_textField);
642 [editor insertText:wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
643 }
644 else
645#endif
646 {
647 wxString val = GetStringValue() ;
648 long start , end ;
649 GetSelection( &start , &end ) ;
650 val.Remove( start , end - start ) ;
651 val.insert( start , str ) ;
652 SetStringValue( val ) ;
653 SetSelection( start + str.length() , start + str.length() ) ;
654 }
655#if 0
656 m_lastKeyDownEvent = formerEvent;
657#endif
658}
659
660void wxUITextFieldControl::controlAction(WXWidget WXUNUSED(slf),
661 void* WXUNUSED(_cmd), void *WXUNUSED(sender))
662{
663 wxWindow* wxpeer = (wxWindow*) GetWXPeer();
664 if ( wxpeer && (wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER) )
665 {
666 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
667 event.SetEventObject( wxpeer );
668 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
669 wxpeer->HandleWindowEvent( event );
670 }
671}
672
673bool wxUITextFieldControl::SetHint(const wxString& hint)
674{
675 wxCFStringRef hintstring(hint);
676 [m_textField setPlaceholder:hintstring.AsNSString()];
677}
678
679#endif
680
681//
682//
683//
684
685wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer,
686 wxWindowMac* WXUNUSED(parent),
687 wxWindowID WXUNUSED(id),
688 const wxString& str,
689 const wxPoint& pos,
690 const wxSize& size,
691 long style,
692 long WXUNUSED(extraStyle))
693{
694 CGRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
695 wxWidgetIPhoneImpl* c = NULL;
696 wxTextWidgetImpl* t = NULL;
697 id<UITextInputTraits> tv = nil;
698
699#if wxOSX_IPHONE_USE_TEXTFIELD
700 if ( style & wxTE_MULTILINE || style & wxTE_RICH || style & wxTE_RICH2 )
701#endif
702 {
703 UITextView * v = nil;
704 v = [[UITextView alloc] initWithFrame:r];
705 tv = v;
706
707 wxUITextViewControl* tc = new wxUITextViewControl( wxpeer, v );
708 c = tc;
709 t = tc;
710 }
711#if wxOSX_IPHONE_USE_TEXTFIELD
712 else
713 {
714 wxUITextField* v = [[wxUITextField alloc] initWithFrame:r];
715 tv = v;
716
717 v.textColor = [UIColor blackColor];
718 v.font = [UIFont systemFontOfSize:17.0];
719 v.backgroundColor = [UIColor whiteColor];
720
721 v.clearButtonMode = UITextFieldViewModeNever;
722
723 [v setBorderStyle:UITextBorderStyleBezel];
724 if ( style & wxNO_BORDER )
725 v.borderStyle = UITextBorderStyleNone;
726
727 wxUITextFieldControl* tc = new wxUITextFieldControl( wxpeer, v );
728 c = tc;
729 t = tc;
730 }
731#endif
732
733 if ( style & wxTE_PASSWORD )
734 [tv setSecureTextEntry:YES];
735
736 if ( !(style & wxTE_MULTILINE) )
737 {
738 [tv setAutocorrectionType:UITextAutocorrectionTypeNo];
739 [tv setReturnKeyType:UIReturnKeyDone];
740 }
741 [tv setKeyboardType:UIKeyboardTypeDefault];
742
743 t->SetStringValue(str);
744
745 return c;
746}
747
748
749#endif // wxUSE_TEXTCTRL