+- (void)controlTextDidChange:(NSNotification *)aNotification
+{
+ wxUnusedVar(aNotification);
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if ( impl )
+ impl->controlTextDidChange();
+}
+
+- (void)controlTextDidEndEditing:(NSNotification *)aNotification
+{
+ wxUnusedVar(aNotification);
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if ( impl )
+ {
+ NSResponder * responder = wxNonOwnedWindowCocoaImpl::GetNextFirstResponder();
+ NSView* otherView = wxOSXGetViewFromResponder(responder);
+
+ wxWidgetImpl* otherWindow = impl->FindBestFromWXWidget(otherView);
+ impl->DoNotifyFocusEvent( false, otherWindow );
+ }
+}
+
+- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector
+{
+ wxUnusedVar(textView);
+
+ BOOL handled = NO;
+
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( control );
+ if ( impl )
+ {
+ wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
+ if ( wxpeer )
+ {
+ if (commandSelector == @selector(insertNewline:))
+ {
+ wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(wxpeer), wxTopLevelWindow);
+ if ( tlw && tlw->GetDefaultItem() )
+ {
+ wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
+ if ( def && def->IsEnabled() )
+ {
+ wxCommandEvent event(wxEVT_BUTTON, def->GetId() );
+ event.SetEventObject(def);
+ def->Command(event);
+ handled = YES;
+ }
+ }
+ }
+ }
+ }
+
+ return handled;
+}
+
+@end
+
+@interface wxNSTextScrollView : NSScrollView
+{
+}
+@end
+
+@implementation wxNSTextScrollView
+
++ (void)initialize
+{
+ static BOOL initialized = NO;
+ if (!initialized)
+ {
+ initialized = YES;
+ wxOSXCocoaClassAddWXMethods( self );
+ }
+}
+
+@end
+
+@implementation wxNSTextFieldEditor
+
+- (void) keyDown:(NSEvent*) event
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
+ lastKeyDownEvent = event;
+ if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
+ [super keyDown:event];
+ lastKeyDownEvent = nil;
+}
+
+- (void) keyUp:(NSEvent*) event
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
+ if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
+ [super keyUp:event];
+}
+
+- (void) flagsChanged:(NSEvent*) event
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
+ if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
+ [super flagsChanged:event];
+}
+
+- (BOOL) performKeyEquivalent:(NSEvent*) event
+{
+ BOOL retval = [super performKeyEquivalent:event];
+ return retval;
+}
+
+- (void) insertText:(id) str
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
+ if ( impl == NULL || lastKeyDownEvent==nil || !impl->DoHandleCharEvent(lastKeyDownEvent, str) )
+ {
+ [super insertText:str];
+ }
+}
+
+@end
+
+@implementation wxNSTextView
+
++ (void)initialize
+{
+ static BOOL initialized = NO;
+ if (!initialized)
+ {
+ initialized = YES;
+ wxOSXCocoaClassAddWXMethods( self );
+ }
+}
+
+- (void)textDidChange:(NSNotification *)aNotification
+{
+ wxUnusedVar(aNotification);
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if ( impl )
+ impl->controlTextDidChange();
+}
+
+- (void) setEnabled:(BOOL) flag
+{
+ // from Technical Q&A QA1461
+ if (flag) {
+ [self setTextColor: [NSColor controlTextColor]];
+
+ } else {
+ [self setTextColor: [NSColor disabledControlTextColor]];
+ }
+
+ [self setSelectable: flag];
+ [self setEditable: flag];
+}
+
+- (BOOL) isEnabled
+{
+ return [self isEditable];
+}
+
+- (void)textDidEndEditing:(NSNotification *)aNotification
+{
+ wxUnusedVar(aNotification);
+
+ if ( self == wxMacEditHelper::GetCurrentlyEditedView() )
+ {
+ // This notification is generated as the result of calling our own
+ // wxTextCtrl method (e.g. WriteText()) and doesn't correspond to any
+ // real focus loss event so skip generating it.
+ return;
+ }
+
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if ( impl )
+ {
+ NSResponder * responder = wxNonOwnedWindowCocoaImpl::GetNextFirstResponder();
+ NSView* otherView = wxOSXGetViewFromResponder(responder);
+
+ wxWidgetImpl* otherWindow = impl->FindBestFromWXWidget(otherView);
+ impl->DoNotifyFocusEvent( false, otherWindow );
+ }
+}
+
+@end
+
+@implementation wxNSTextField
+
++ (void)initialize
+{
+ static BOOL initialized = NO;
+ if (!initialized)
+ {
+ initialized = YES;
+ wxOSXCocoaClassAddWXMethods( self );
+ }
+}
+
+- (id) initWithFrame:(NSRect) frame
+{
+ self = [super initWithFrame:frame];
+ fieldEditor = nil;
+ return self;
+}
+
+- (void) dealloc
+{
+ [fieldEditor release];
+ [super dealloc];
+}
+
+- (void) setFieldEditor:(wxNSTextFieldEditor*) editor
+{
+ if ( editor != fieldEditor )
+ {
+ [editor retain];
+ [fieldEditor release];
+ fieldEditor = editor;
+ }
+}
+
+- (wxNSTextFieldEditor*) fieldEditor
+{
+ return fieldEditor;
+}
+
+- (void) setEnabled:(BOOL) flag
+{
+ [super setEnabled: flag];
+
+ if (![self drawsBackground]) {
+ // Static text is drawn incorrectly when disabled.
+ // For an explanation, see
+ // http://www.cocoabuilder.com/archive/message/cocoa/2006/7/21/168028
+ if (flag) {
+ [self setTextColor: [NSColor controlTextColor]];
+ } else {
+ [self setTextColor: [NSColor secondarySelectedControlColor]];
+ }
+ }
+}
+
+- (void)controlTextDidChange:(NSNotification *)aNotification
+{
+ wxUnusedVar(aNotification);
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if ( impl )
+ impl->controlTextDidChange();
+}
+
+- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words
+ forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger*)index
+{
+ NSMutableArray* matches = NULL;
+
+ wxTextWidgetImpl* impl = (wxNSTextFieldControl * ) wxWidgetImpl::FindFromWXWidget( self );
+ wxTextEntry * const entry = impl->GetTextEntry();
+ wxTextCompleter * const completer = entry->OSXGetCompleter();
+ if ( completer )
+ {
+ const wxString prefix = entry->GetValue();
+ if ( completer->Start(prefix) )
+ {
+ const wxString
+ wordStart = wxCFStringRef::AsString(
+ [[textView string] substringWithRange:charRange]
+ );
+
+ matches = [NSMutableArray array];
+ for ( ;; )
+ {
+ const wxString s = completer->GetNext();
+ if ( s.empty() )
+ break;
+
+ // Normally the completer should return only the strings
+ // starting with the prefix, but there could be exceptions
+ // and, for compatibility with MSW which simply ignores all
+ // entries that don't match the current text control contents,
+ // we ignore them as well. Besides, our own wxTextCompleterFixed
+ // doesn't respect this rule and, moreover, we need to extract
+ // just the rest of the string anyhow.
+ wxString completion;
+ if ( s.StartsWith(prefix, &completion) )
+ {
+ // We discarded the entire prefix above but actually we
+ // should include the part of it that consists of the
+ // beginning of the current word, otherwise it would be
+ // lost when completion is accepted as OS X supposes that
+ // our matches do start with the "partial word range"
+ // passed to us.
+ const wxCFStringRef fullWord(wordStart + completion);
+ [matches addObject: fullWord.AsNSString()];
+ }
+ }
+ }
+ }
+
+ return matches;
+}
+
+- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector
+{
+ wxUnusedVar(textView);
+ wxUnusedVar(control);
+
+ BOOL handled = NO;
+
+ // send back key events wx' common code knows how to handle
+
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if ( impl )
+ {
+ wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
+ if ( wxpeer )
+ {
+ if (commandSelector == @selector(insertNewline:))
+ {
+ [textView insertNewlineIgnoringFieldEditor:self];
+ handled = YES;
+ }
+ else if ( commandSelector == @selector(insertTab:))
+ {
+ [textView insertTabIgnoringFieldEditor:self];
+ handled = YES;
+ }
+ else if ( commandSelector == @selector(insertBacktab:))
+ {
+ [textView insertTabIgnoringFieldEditor:self];
+ handled = YES;
+ }
+ }
+ }
+
+ return handled;
+}
+
+- (void)controlTextDidEndEditing:(NSNotification *)aNotification