X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9c71750d8097c4ef7a8918645b242bd122a4fab5..4ca0bca0f31652f0b27209e97eecac0fb99c2adf:/src/osx/cocoa/textctrl.mm diff --git a/src/osx/cocoa/textctrl.mm b/src/osx/cocoa/textctrl.mm index 96a35ede64..5b7fc73310 100644 --- a/src/osx/cocoa/textctrl.mm +++ b/src/osx/cocoa/textctrl.mm @@ -119,7 +119,7 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; - (id)init { - [super init]; + self = [super init]; maxLength = 0; return self; } @@ -186,6 +186,39 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; } } +- (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 @@ -466,6 +499,13 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); if ( impl ) { + wxNSTextFieldControl* timpl = dynamic_cast(impl); + if ( fieldEditor ) + { + NSRange range = [fieldEditor selectedRange]; + timpl->SetInternalSelection(range.location, range.location + range.length); + } + impl->DoNotifyFocusEvent( false, NULL ); } } @@ -482,7 +522,8 @@ wxNSTextViewControl::wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w ) [m_scrollView setHasVerticalScroller:YES]; [m_scrollView setHasHorizontalScroller:NO]; - [m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + // TODO Remove if no regression, this was causing automatic resizes of multi-line textfields when the tlw changed + // [m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; NSSize contentSize = [m_scrollView contentSize]; wxNSTextView* tv = [[wxNSTextView alloc] initWithFrame: NSMakeRect(0, 0, @@ -655,24 +696,35 @@ void wxNSTextViewControl::SetStyle(long start, long end, const wxTextAttr& style) { - if (m_textView) { + if ( !m_textView ) + return; + + if ( start == -1 && end == -1 ) + { + NSMutableDictionary* const + attrs = [NSMutableDictionary dictionaryWithCapacity:3]; + if ( style.HasFont() ) + [attrs setValue:style.GetFont().OSXGetNSFont() forKey:NSFontAttributeName]; + if ( style.HasBackgroundColour() ) + [attrs setValue:style.GetBackgroundColour().OSXGetNSColor() forKey:NSBackgroundColorAttributeName]; + if ( style.HasTextColour() ) + [attrs setValue:style.GetTextColour().OSXGetNSColor() forKey:NSForegroundColorAttributeName]; + + [m_textView setTypingAttributes:attrs]; + } + else // Set the attributes just for this range. + { 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]; + if ( style.HasFont() ) + [storage addAttribute:NSFontAttributeName value:style.GetFont().OSXGetNSFont() range:range]; + + if ( style.HasBackgroundColour() ) + [storage addAttribute:NSBackgroundColorAttributeName value:style.GetBackgroundColour().OSXGetNSColor() range:range]; + + if ( style.HasTextColour() ) + [storage addAttribute:NSForegroundColorAttributeName value:style.GetTextColour().OSXGetNSColor() range:range]; } } @@ -819,11 +871,11 @@ void wxNSTextFieldControl::SetSelection( long from , long to ) { [editor setSelectedRange:NSMakeRange(from, to-from)]; } - else - { - m_selStart = from; - m_selEnd = to; - } + + // the editor might still be in existence, but we might be already passed our 'focus lost' storage + // of the selection, so make sure we copy this + m_selStart = from; + m_selEnd = to; } void wxNSTextFieldControl::WriteText(const wxString& str) @@ -834,7 +886,12 @@ void wxNSTextFieldControl::WriteText(const wxString& str) if ( editor ) { wxMacEditHelper helper(m_textField); + BOOL hasUndo = [editor respondsToSelector:@selector(setAllowsUndo:)]; + if ( hasUndo ) + [(NSTextView*)editor setAllowsUndo:NO]; [editor insertText:wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()]; + if ( hasUndo ) + [(NSTextView*)editor setAllowsUndo:YES]; } else { @@ -862,6 +919,52 @@ void wxNSTextFieldControl::controlAction(WXWidget WXUNUSED(slf), } } +void wxNSTextFieldControl::SetInternalSelection( long from , long to ) +{ + m_selStart = from; + m_selEnd = to; +} + +// as becoming first responder on a window - triggers a resign on the same control, we have to avoid +// the resign notification writing back native selection values before we can set our own + +static WXWidget s_widgetBecomingFirstResponder = nil; + +bool wxNSTextFieldControl::becomeFirstResponder(WXWidget slf, void *_cmd) +{ + s_widgetBecomingFirstResponder = slf; + bool retval = wxWidgetCocoaImpl::becomeFirstResponder(slf, _cmd); + s_widgetBecomingFirstResponder = nil; + if ( retval ) + { + NSText* editor = [m_textField currentEditor]; + if ( editor ) + { + long textLength = [[m_textField stringValue] length]; + m_selStart = wxMin(textLength,wxMax(m_selStart,0)) ; + m_selEnd = wxMax(0,wxMin(textLength,m_selEnd)) ; + + [editor setSelectedRange:NSMakeRange(m_selStart, m_selEnd-m_selStart)]; + } + } + return retval; +} + +bool wxNSTextFieldControl::resignFirstResponder(WXWidget slf, void *_cmd) +{ + if ( slf != s_widgetBecomingFirstResponder ) + { + NSText* editor = [m_textField currentEditor]; + if ( editor ) + { + NSRange range = [editor selectedRange]; + m_selStart = range.location; + m_selEnd = range.location + range.length; + } + } + return wxWidgetCocoaImpl::resignFirstResponder(slf, _cmd); +} + bool wxNSTextFieldControl::SetHint(const wxString& hint) { wxCFStringRef hintstring(hint); @@ -890,6 +993,7 @@ wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer, wxNSTextScrollView* v = nil; v = [[wxNSTextScrollView alloc] initWithFrame:r]; c = new wxNSTextViewControl( wxpeer, v ); + c->SetNeedsFocusRect( true ); } else { @@ -899,24 +1003,39 @@ wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer, 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]; - [v setBezeled:NO]; - [v setBordered:NO]; - c = new wxNSTextFieldControl( wxpeer, wxpeer, v ); + + 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); + } } - c->SetNeedsFocusRect( true ); return c; }