X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f66ecdc4fbfa14f18f95331ba859a85baee36ae6..a51e79e87db3512823258d487849bb7e7947b700:/src/osx/cocoa/textctrl.mm diff --git a/src/osx/cocoa/textctrl.mm b/src/osx/cocoa/textctrl.mm index 77a6ba4d02..b1364c509c 100644 --- a/src/osx/cocoa/textctrl.mm +++ b/src/osx/cocoa/textctrl.mm @@ -4,7 +4,7 @@ // Author: Stefan Csomor // Modified by: Ryan Norton (MLTE GetLineLength and GetLineText) // Created: 1998-01-01 -// RCS-ID: $Id: textctrl.cpp 54820 2008-07-29 20:04:11Z SC $ +// RCS-ID: $Id$ // Copyright: (c) Stefan Csomor // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -45,24 +45,36 @@ #include "wx/filefn.h" #include "wx/sysopt.h" #include "wx/thread.h" +#include "wx/textcompleter.h" #include "wx/osx/private.h" #include "wx/osx/cocoa/private/textimpl.h" -@interface NSView(EditableView) +@interface NSView(EditableView) - (BOOL)isEditable; - (void)setEditable:(BOOL)flag; +- (BOOL)isSelectable; +- (void)setSelectable:(BOOL)flag; @end +// An object of this class is created before the text is modified +// programmatically and destroyed as soon as this is done. It does several +// things, like ensuring that the control is editable to allow setting its text +// at all and eating any unwanted focus loss events from textDidEndEditing: +// which don't really correspond to focus change. class wxMacEditHelper { public : wxMacEditHelper( NSView* textView ) { - m_textView = textView ; + m_viewPreviouslyEdited = ms_viewCurrentlyEdited; + ms_viewCurrentlyEdited = + m_textView = textView; + m_formerEditable = YES; if ( textView ) { - m_formerState = [textView isEditable]; + m_formerEditable = [textView isEditable]; + m_formerSelectable = [textView isSelectable]; [textView setEditable:YES]; } } @@ -70,20 +82,86 @@ public : ~wxMacEditHelper() { if ( m_textView ) - [m_textView setEditable:m_formerState]; + { + [m_textView setEditable:m_formerEditable]; + [m_textView setSelectable:m_formerSelectable]; + } + + ms_viewCurrentlyEdited = m_viewPreviouslyEdited; } + // Returns the last view we were instantiated for or NULL. + static NSView *GetCurrentlyEditedView() { return ms_viewCurrentlyEdited; } + protected : - BOOL m_formerState ; + BOOL m_formerEditable ; + BOOL m_formerSelectable; NSView* m_textView; + + // The original value of ms_viewCurrentlyEdited when this object was + // created. + NSView* m_viewPreviouslyEdited; + + static NSView* ms_viewCurrentlyEdited; } ; -@implementation wxNSSecureTextField +NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; + +// a minimal NSFormatter that just avoids getting too long entries +@interface wxMaximumLengthFormatter : NSFormatter +{ + int maxLength; +} + +@end + +@implementation wxMaximumLengthFormatter + +- (id)init +{ + self = [super init]; + maxLength = 0; + return self; +} + +- (void) setMaxLength:(int) maxlen +{ + maxLength = maxlen; +} + +- (NSString *)stringForObjectValue:(id)anObject +{ + if(![anObject isKindOfClass:[NSString class]]) + return nil; + return [NSString stringWithString:anObject]; +} + +- (BOOL)getObjectValue:(id *)obj forString:(NSString *)string errorDescription:(NSString **)error +{ + *obj = [NSString stringWithString:string]; + return YES; +} + +- (BOOL)isPartialStringValid:(NSString **)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr + originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString **)error +{ + int len = [*partialStringPtr length]; + if ( maxLength > 0 && len > maxLength ) + { + // TODO wxEVT_COMMAND_TEXT_MAXLEN + return NO; + } + return YES; +} + +@end + +@implementation wxNSSecureTextField + (void)initialize { static BOOL initialized = NO; - if (!initialized) + if (!initialized) { initialized = YES; wxOSXCocoaClassAddWXMethods( self ); @@ -95,15 +173,7 @@ protected : wxUnusedVar(aNotification); wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); if ( impl ) - { - wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer(); - if ( wxpeer ) { - wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId()); - event.SetEventObject( wxpeer ); - event.SetString( static_cast(wxpeer)->GetValue() ); - wxpeer->HandleWindowEvent( event ); - } - } + impl->controlTextDidChange(); } - (void)controlTextDidEndEditing:(NSNotification *)aNotification @@ -116,6 +186,39 @@ protected : } } +- (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_COMMAND_BUTTON_CLICKED, def->GetId() ); + event.SetEventObject(def); + def->Command(event); + handled = YES; + } + } + } + } + } + + return handled; +} + @end @interface wxNSTextScrollView : NSScrollView @@ -128,8 +231,8 @@ protected : + (void)initialize { static BOOL initialized = NO; - if (!initialized) - { + if (!initialized) + { initialized = YES; wxOSXCocoaClassAddWXMethods( self ); } @@ -184,13 +287,59 @@ protected : + (void)initialize { static BOOL initialized = NO; - if (!initialized) + 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 ) + { + impl->DoNotifyFocusEvent( false, NULL ); + } +} + @end @implementation wxNSTextField @@ -198,7 +347,7 @@ protected : + (void)initialize { static BOOL initialized = NO; - if (!initialized) + if (!initialized) { initialized = YES; wxOSXCocoaClassAddWXMethods( self ); @@ -220,7 +369,12 @@ protected : - (void) setFieldEditor:(wxNSTextFieldEditor*) editor { - fieldEditor = editor; + if ( editor != fieldEditor ) + { + [editor retain]; + [fieldEditor release]; + fieldEditor = editor; + } } - (wxNSTextFieldEditor*) fieldEditor @@ -228,7 +382,6 @@ protected : return fieldEditor; } - - (void) setEnabled:(BOOL) flag { [super setEnabled: flag]; @@ -250,40 +403,94 @@ protected : 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 ) { - wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer(); - if ( wxpeer ) { - wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId()); - event.SetEventObject( wxpeer ); - event.SetString( static_cast(wxpeer)->GetValue() ); - wxpeer->HandleWindowEvent( event ); + 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()]; + } + } } } -} -typedef BOOL (*wxOSX_insertNewlineHandlerPtr)(NSView* self, SEL _cmd, NSControl *control, NSTextView* textView, SEL commandSelector); + return matches; +} - (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector { wxUnusedVar(textView); wxUnusedVar(control); - if (commandSelector == @selector(insertNewline:)) + + BOOL handled = NO; + + // send back key events wx' common code knows how to handle + + wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + if ( impl ) { - wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); - if ( impl ) + wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer(); + if ( wxpeer ) { - wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer(); - if ( wxpeer && wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER ) + if (commandSelector == @selector(insertNewline:)) + { + [textView insertNewlineIgnoringFieldEditor:self]; + handled = YES; + } + else if ( commandSelector == @selector(insertTab:)) { - wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId()); - event.SetEventObject( wxpeer ); - event.SetString( static_cast(wxpeer)->GetValue() ); - wxpeer->HandleWindowEvent( event ); + [textView insertTabIgnoringFieldEditor:self]; + handled = YES; + } + else if ( commandSelector == @selector(insertBacktab:)) + { + [textView insertTabIgnoringFieldEditor:self]; + handled = YES; } } } - return NO; + return handled; } - (void)controlTextDidEndEditing:(NSNotification *)aNotification @@ -299,28 +506,30 @@ typedef BOOL (*wxOSX_insertNewlineHandlerPtr)(NSView* self, SEL _cmd, NSControl // wxNSTextViewControl -wxNSTextViewControl::wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w ) : wxWidgetCocoaImpl(wxPeer, w) +wxNSTextViewControl::wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w ) + : wxWidgetCocoaImpl(wxPeer, w), + wxTextWidgetImpl(wxPeer) { wxNSTextScrollView* sv = (wxNSTextScrollView*) w; m_scrollView = sv; - + [m_scrollView setHasVerticalScroller:YES]; [m_scrollView setHasHorizontalScroller:NO]; [m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; NSSize contentSize = [m_scrollView contentSize]; - + wxNSTextView* tv = [[wxNSTextView alloc] initWithFrame: NSMakeRect(0, 0, contentSize.width, contentSize.height)]; m_textView = tv; [tv setVerticallyResizable:YES]; [tv setHorizontallyResizable:NO]; [tv setAutoresizingMask:NSViewWidthSizable]; - + [m_scrollView setDocumentView: tv]; - [tv setDelegate: w]; - - InstallEventHandler(tv); + [tv setDelegate: tv]; + + InstallEventHandler(tv); } wxNSTextViewControl::~wxNSTextViewControl() @@ -329,9 +538,17 @@ wxNSTextViewControl::~wxNSTextViewControl() [m_textView setDelegate: nil]; } -wxString wxNSTextViewControl::GetStringValue() const +bool wxNSTextViewControl::CanFocus() const +{ + // since this doesn't work (return false), we hardcode + // if (m_textView) + // return [m_textView canBecomeKeyView]; + return true; +} + +wxString wxNSTextViewControl::GetStringValue() const { - if (m_textView) + if (m_textView) { wxString result = wxCFStringRef::AsString([m_textView string], m_wxPeer->GetFont().GetEncoding()); wxMacConvertNewlines13To10( &result ) ; @@ -339,7 +556,7 @@ wxString wxNSTextViewControl::GetStringValue() const } return wxEmptyString; } -void wxNSTextViewControl::SetStringValue( const wxString &str) +void wxNSTextViewControl::SetStringValue( const wxString &str) { wxString st = str; wxMacConvertNewlines10To13( &st ); @@ -349,37 +566,37 @@ void wxNSTextViewControl::SetStringValue( const wxString &str) [m_textView setString: wxCFStringRef( st , m_wxPeer->GetFont().GetEncoding() ).AsNSString()]; } -void wxNSTextViewControl::Copy() +void wxNSTextViewControl::Copy() { if (m_textView) [m_textView copy:nil]; } -void wxNSTextViewControl::Cut() +void wxNSTextViewControl::Cut() { if (m_textView) [m_textView cut:nil]; } -void wxNSTextViewControl::Paste() +void wxNSTextViewControl::Paste() { if (m_textView) [m_textView paste:nil]; } -bool wxNSTextViewControl::CanPaste() const -{ +bool wxNSTextViewControl::CanPaste() const +{ return true; } -void wxNSTextViewControl::SetEditable(bool editable) +void wxNSTextViewControl::SetEditable(bool editable) { if (m_textView) [m_textView setEditable: editable]; } -void wxNSTextViewControl::GetSelection( long* from, long* to) const +void wxNSTextViewControl::GetSelection( long* from, long* to) const { if (m_textView) { @@ -411,28 +628,127 @@ void wxNSTextViewControl::SetSelection( long from , long to ) [m_textView scrollRangeToVisible:selrange]; } -void wxNSTextViewControl::WriteText(const wxString& str) +void wxNSTextViewControl::WriteText(const wxString& str) { wxString st = str; wxMacConvertNewlines10To13( &st ); wxMacEditHelper helper(m_textView); - + NSEvent* formerEvent = m_lastKeyDownEvent; + m_lastKeyDownEvent = nil; [m_textView insertText:wxCFStringRef( st , m_wxPeer->GetFont().GetEncoding() ).AsNSString()]; + m_lastKeyDownEvent = formerEvent; } -void wxNSTextViewControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle, bool ignoreBlack ) +void wxNSTextViewControl::SetFont( const wxFont & font , const wxColour& WXUNUSED(foreground) , long WXUNUSED(windowStyle), bool WXUNUSED(ignoreBlack) ) { if ([m_textView respondsToSelector:@selector(setFont:)]) [m_textView setFont: font.OSXGetNSFont()]; } +bool wxNSTextViewControl::GetStyle(long position, wxTextAttr& style) +{ + if (m_textView && position >=0) + { + NSFont* font = NULL; + NSColor* bgcolor = NULL; + NSColor* fgcolor = NULL; + // NOTE: It appears that other platforms accept GetStyle with the position == length + // but that NSTextStorage does not accept length as a valid position. + // Therefore we return the default control style in that case. + if (position < (long) [[m_textView string] length]) + { + NSTextStorage* storage = [m_textView textStorage]; + font = [[storage attribute:NSFontAttributeName atIndex:position effectiveRange:NULL] autorelease]; + bgcolor = [[storage attribute:NSBackgroundColorAttributeName atIndex:position effectiveRange:NULL] autorelease]; + fgcolor = [[storage attribute:NSForegroundColorAttributeName atIndex:position effectiveRange:NULL] autorelease]; + } + else + { + NSDictionary* attrs = [m_textView typingAttributes]; + font = [[attrs objectForKey:NSFontAttributeName] autorelease]; + bgcolor = [[attrs objectForKey:NSBackgroundColorAttributeName] autorelease]; + fgcolor = [[attrs objectForKey:NSForegroundColorAttributeName] autorelease]; + } + + if (font) + style.SetFont(wxFont(font)); + + if (bgcolor) + style.SetBackgroundColour(wxColour(bgcolor)); + + if (fgcolor) + style.SetTextColour(wxColour(fgcolor)); + return true; + } + + return false; +} + +void wxNSTextViewControl::SetStyle(long start, + long end, + const wxTextAttr& style) +{ + if (m_textView) { + NSRange range = NSMakeRange(start, end-start); + if (start == -1 && end == -1) + range = [m_textView selectedRange]; + + NSTextStorage* storage = [m_textView textStorage]; + + wxFont font = style.GetFont(); + if (style.HasFont() && font.IsOk()) + [storage addAttribute:NSFontAttributeName value:font.OSXGetNSFont() range:range]; + + wxColour bgcolor = style.GetBackgroundColour(); + if (style.HasBackgroundColour() && bgcolor.IsOk()) + [storage addAttribute:NSBackgroundColorAttributeName value:bgcolor.OSXGetNSColor() range:range]; + + wxColour fgcolor = style.GetTextColour(); + if (style.HasTextColour() && fgcolor.IsOk()) + [storage addAttribute:NSForegroundColorAttributeName value:fgcolor.OSXGetNSColor() range:range]; + } +} + +void wxNSTextViewControl::CheckSpelling(bool check) +{ + if (m_textView) + [m_textView setContinuousSpellCheckingEnabled: check]; +} + +wxSize wxNSTextViewControl::GetBestSize() const +{ + if (m_textView && [m_textView layoutManager]) + { + NSRect rect = [[m_textView layoutManager] usedRectForTextContainer: [m_textView textContainer]]; + return wxSize((int)(rect.size.width + [m_textView textContainerInset].width), + (int)(rect.size.height + [m_textView textContainerInset].height)); + } + return wxSize(0,0); +} // wxNSTextFieldControl -wxNSTextFieldControl::wxNSTextFieldControl( wxTextCtrl *wxPeer, WXWidget w ) : wxWidgetCocoaImpl(wxPeer, w) +wxNSTextFieldControl::wxNSTextFieldControl( wxTextCtrl *text, WXWidget w ) + : wxWidgetCocoaImpl(text, w), + wxTextWidgetImpl(text) { - m_textField = (NSTextField*) w; - [m_textField setDelegate: w]; + Init(w); +} + +wxNSTextFieldControl::wxNSTextFieldControl(wxWindow *wxPeer, + wxTextEntry *entry, + WXWidget w) + : wxWidgetCocoaImpl(wxPeer, w), + wxTextWidgetImpl(entry) +{ + Init(w); +} + +void wxNSTextFieldControl::Init(WXWidget w) +{ + NSTextField wxOSX_10_6_AND_LATER() *tf = (NSTextField wxOSX_10_6_AND_LATER()*) w; + m_textField = tf; + [m_textField setDelegate: tf]; m_selStart = m_selEnd = 0; m_hasEditor = [w isKindOfClass:[NSTextField class]]; } @@ -443,18 +759,25 @@ wxNSTextFieldControl::~wxNSTextFieldControl() [m_textField setDelegate: nil]; } -wxString wxNSTextFieldControl::GetStringValue() const +wxString wxNSTextFieldControl::GetStringValue() const { return wxCFStringRef::AsString([m_textField stringValue], m_wxPeer->GetFont().GetEncoding()); } -void wxNSTextFieldControl::SetStringValue( const wxString &str) +void wxNSTextFieldControl::SetStringValue( const wxString &str) { wxMacEditHelper helper(m_textField); [m_textField setStringValue: wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()]; } -void wxNSTextFieldControl::Copy() +void wxNSTextFieldControl::SetMaxLength(unsigned long len) +{ + wxMaximumLengthFormatter* formatter = [[[wxMaximumLengthFormatter alloc] init] autorelease]; + [formatter setMaxLength:len]; + [m_textField setFormatter:formatter]; +} + +void wxNSTextFieldControl::Copy() { NSText* editor = [m_textField currentEditor]; if ( editor ) @@ -463,7 +786,7 @@ void wxNSTextFieldControl::Copy() } } -void wxNSTextFieldControl::Cut() +void wxNSTextFieldControl::Cut() { NSText* editor = [m_textField currentEditor]; if ( editor ) @@ -472,7 +795,7 @@ void wxNSTextFieldControl::Cut() } } -void wxNSTextFieldControl::Paste() +void wxNSTextFieldControl::Paste() { NSText* editor = [m_textField currentEditor]; if ( editor ) @@ -481,17 +804,17 @@ void wxNSTextFieldControl::Paste() } } -bool wxNSTextFieldControl::CanPaste() const -{ +bool wxNSTextFieldControl::CanPaste() const +{ return true; } -void wxNSTextFieldControl::SetEditable(bool editable) +void wxNSTextFieldControl::SetEditable(bool editable) { [m_textField setEditable:editable]; } -void wxNSTextFieldControl::GetSelection( long* from, long* to) const +void wxNSTextFieldControl::GetSelection( long* from, long* to) const { NSText* editor = [m_textField currentEditor]; if ( editor ) @@ -536,13 +859,20 @@ void wxNSTextFieldControl::SetSelection( long from , long to ) } } -void wxNSTextFieldControl::WriteText(const wxString& str) +void wxNSTextFieldControl::WriteText(const wxString& str) { + NSEvent* formerEvent = m_lastKeyDownEvent; + m_lastKeyDownEvent = nil; NSText* editor = [m_textField currentEditor]; if ( editor ) { wxMacEditHelper helper(m_textField); + BOOL hasUndo = [editor respondsToSelector:@selector(setAllowsUndo:)]; + if ( hasUndo ) + [editor setAllowsUndo:NO]; [editor insertText:wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()]; + if ( hasUndo ) + [editor setAllowsUndo:YES]; } else { @@ -554,65 +884,94 @@ void wxNSTextFieldControl::WriteText(const wxString& str) SetStringValue( val ) ; SetSelection( start + str.length() , start + str.length() ) ; } + m_lastKeyDownEvent = formerEvent; } -void wxNSTextFieldControl::controlAction(WXWidget WXUNUSED(slf), +void wxNSTextFieldControl::controlAction(WXWidget WXUNUSED(slf), void* WXUNUSED(_cmd), void *WXUNUSED(sender)) { wxWindow* wxpeer = (wxWindow*) GetWXPeer(); - if ( wxpeer && (wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER) ) + if ( wxpeer && (wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER) ) { wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId()); event.SetEventObject( wxpeer ); - event.SetString( static_cast(wxpeer)->GetValue() ); + event.SetString( GetTextEntry()->GetValue() ); wxpeer->HandleWindowEvent( event ); } } +bool wxNSTextFieldControl::SetHint(const wxString& hint) +{ + wxCFStringRef hintstring(hint); + [[m_textField cell] setPlaceholderString:hintstring.AsNSString()]; + return true; +} + // // // -wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer, - wxWindowMac* WXUNUSED(parent), - wxWindowID WXUNUSED(id), - const wxString& str, - const wxPoint& pos, +wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer, + wxWindowMac* WXUNUSED(parent), + wxWindowID WXUNUSED(id), + const wxString& WXUNUSED(str), + const wxPoint& pos, const wxSize& size, - long style, + long style, long WXUNUSED(extraStyle)) { NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ; wxWidgetCocoaImpl* c = NULL; - + if ( style & wxTE_MULTILINE || style & wxTE_RICH || style & wxTE_RICH2 ) { wxNSTextScrollView* v = nil; v = [[wxNSTextScrollView alloc] initWithFrame:r]; c = new wxNSTextViewControl( wxpeer, v ); - static_cast(c)->SetStringValue(str); + c->SetNeedsFocusRect( true ); } - else + else { NSTextField* v = nil; if ( style & wxTE_PASSWORD ) v = [[wxNSSecureTextField alloc] initWithFrame:r]; else v = [[wxNSTextField alloc] initWithFrame:r]; - - if ( style & wxNO_BORDER ) + + if ( style & wxTE_RIGHT) { - // FIXME: How can we remove the native control's border? - // setBordered is separate from the text ctrl's border. + [v setAlignment:NSRightTextAlignment]; } + else if ( style & wxTE_CENTRE) + { + [v setAlignment:NSCenterTextAlignment]; + } + + NSTextFieldCell* cell = [v cell]; + [cell setScrollable:YES]; + // TODO: Remove if we definitely are sure, it's not needed + // as setting scrolling to yes, should turn off any wrapping + // [cell setLineBreakMode:NSLineBreakByClipping]; + + c = new wxNSTextFieldControl( wxpeer, wxpeer, v ); - [v setBezeled:NO]; - [v setBordered:NO]; - - c = new wxNSTextFieldControl( wxpeer, v ); - static_cast(c)->SetStringValue(str); + if ( (style & wxNO_BORDER) || (style & wxSIMPLE_BORDER) ) + { + // under 10.7 the textcontrol can draw its own focus + // even if no border is shown, on previous systems + // we have to emulate this + [v setBezeled:NO]; + [v setBordered:NO]; + if ( UMAGetSystemVersion() < 0x1070 ) + c->SetNeedsFocusRect( true ); + } + else + { + // use native border + c->SetNeedsFrame(false); + } } - + return c; }