X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d68a2a24d1d25542974045f0bff3f035c192e5bb..7c60222510bc5e197b12f153c4bf05db66cb0f4a:/src/osx/cocoa/textctrl.mm?ds=inline diff --git a/src/osx/cocoa/textctrl.mm b/src/osx/cocoa/textctrl.mm index 0eb4afc84e..14f3a176e1 100644 --- a/src/osx/cocoa/textctrl.mm +++ b/src/osx/cocoa/textctrl.mm @@ -111,6 +111,7 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; @interface wxMaximumLengthFormatter : NSFormatter { int maxLength; + wxTextEntry* field; } @end @@ -148,12 +149,17 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; int len = [*partialStringPtr length]; if ( maxLength > 0 && len > maxLength ) { - // TODO wxEVT_COMMAND_TEXT_MAXLEN + field->SendMaxLenEvent(); return NO; } return YES; } +- (void) setTextEntry:(wxTextEntry*) tf +{ + field = tf; +} + @end @implementation wxNSSecureTextField @@ -182,7 +188,11 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); if ( impl ) { - impl->DoNotifyFocusEvent( false, NULL ); + NSResponder * responder = wxNonOwnedWindowCocoaImpl::GetNextFirstResponder(); + NSView* otherView = wxOSXGetViewFromResponder(responder); + + wxWidgetImpl* otherWindow = impl->FindBestFromWXWidget(otherView); + impl->DoNotifyFocusEvent( false, otherWindow ); } } @@ -206,7 +216,7 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton); if ( def && def->IsEnabled() ) { - wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() ); + wxCommandEvent event(wxEVT_BUTTON, def->GetId() ); event.SetEventObject(def); def->Command(event); handled = YES; @@ -336,7 +346,11 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); if ( impl ) { - impl->DoNotifyFocusEvent( false, NULL ); + NSResponder * responder = wxNonOwnedWindowCocoaImpl::GetNextFirstResponder(); + NSView* otherView = wxOSXGetViewFromResponder(responder); + + wxWidgetImpl* otherWindow = impl->FindBestFromWXWidget(otherView); + impl->DoNotifyFocusEvent( false, otherWindow ); } } @@ -499,7 +513,18 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); if ( impl ) { - impl->DoNotifyFocusEvent( false, NULL ); + wxNSTextFieldControl* timpl = dynamic_cast(impl); + if ( fieldEditor ) + { + NSRange range = [fieldEditor selectedRange]; + timpl->SetInternalSelection(range.location, range.location + range.length); + } + + NSResponder * responder = wxNonOwnedWindowCocoaImpl::GetNextFirstResponder(); + NSView* otherView = wxOSXGetViewFromResponder(responder); + + wxWidgetImpl* otherWindow = impl->FindBestFromWXWidget(otherView); + impl->DoNotifyFocusEvent( false, otherWindow ); } } @end @@ -515,7 +540,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, @@ -688,24 +714,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]; } } @@ -774,6 +811,7 @@ void wxNSTextFieldControl::SetMaxLength(unsigned long len) { wxMaximumLengthFormatter* formatter = [[[wxMaximumLengthFormatter alloc] init] autorelease]; [formatter setMaxLength:len]; + [formatter setTextEntry:GetTextEntry()]; [m_textField setFormatter:formatter]; } @@ -852,11 +890,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) @@ -867,7 +905,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 { @@ -888,13 +931,59 @@ void wxNSTextFieldControl::controlAction(WXWidget WXUNUSED(slf), wxWindow* wxpeer = (wxWindow*) GetWXPeer(); if ( wxpeer && (wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER) ) { - wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId()); + wxCommandEvent event(wxEVT_TEXT_ENTER, wxpeer->GetId()); event.SetEventObject( wxpeer ); event.SetString( GetTextEntry()->GetValue() ); wxpeer->HandleWindowEvent( event ); } } +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); @@ -918,11 +1007,12 @@ wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer, NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ; wxWidgetCocoaImpl* c = NULL; - if ( style & wxTE_MULTILINE || style & wxTE_RICH || style & wxTE_RICH2 ) + if ( style & wxTE_MULTILINE ) { wxNSTextScrollView* v = nil; v = [[wxNSTextScrollView alloc] initWithFrame:r]; c = new wxNSTextViewControl( wxpeer, v ); + c->SetNeedsFocusRect( true ); } else { @@ -940,25 +1030,31 @@ wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer, { [v setAlignment:NSCenterTextAlignment]; } - - if ( style & wxNO_BORDER ) - { - // FIXME: How can we remove the native control's border? - // setBordered is separate from the text ctrl's border. - } - + 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; }