1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/cocoa/textctrl.mm
4 // Author: Stefan Csomor
5 // Modified by: Ryan Norton (MLTE GetLineLength and GetLineText)
7 // RCS-ID: $Id: textctrl.cpp 54820 2008-07-29 20:04:11Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
16 #include "wx/textctrl.h"
23 #include "wx/button.h"
25 #include "wx/settings.h"
26 #include "wx/msgdlg.h"
27 #include "wx/toplevel.h"
31 #include <sys/types.h>
37 #if wxUSE_STD_IOSTREAM
45 #include "wx/filefn.h"
46 #include "wx/sysopt.h"
47 #include "wx/thread.h"
49 #include "wx/osx/private.h"
50 #include "wx/osx/cocoa/private/textimpl.h"
52 @interface wxNSSecureTextField : NSSecureTextField
57 @implementation wxNSSecureTextField
61 static BOOL initialized = NO;
65 wxOSXCocoaClassAddWXMethods( self );
69 - (void)controlTextDidChange:(NSNotification *)aNotification
71 wxUnusedVar(aNotification);
72 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
75 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
77 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId());
78 event.SetEventObject( wxpeer );
79 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
80 wxpeer->HandleWindowEvent( event );
85 - (void)controlTextDidEndEditing:(NSNotification *)aNotification
87 wxUnusedVar(aNotification);
88 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
91 impl->DoNotifyFocusEvent( false, NULL );
97 @interface wxNSTextView : NSScrollView
103 @implementation wxNSTextView
107 static BOOL initialized = NO;
111 wxOSXCocoaClassAddWXMethods( self );
115 - (void)textDidChange:(NSNotification *)aNotification
117 wxUnusedVar(aNotification);
118 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
121 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
123 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId());
124 event.SetEventObject( wxpeer );
125 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
126 wxpeer->HandleWindowEvent( event );
131 - (BOOL)textView:(NSTextView *)aTextView doCommandBySelector:(SEL)commandSelector
133 wxUnusedVar(aTextView);
134 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
137 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
138 if (commandSelector == @selector(insertNewline:))
140 if ( wxpeer && wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER )
142 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
143 event.SetEventObject( wxpeer );
144 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
145 wxpeer->HandleWindowEvent( event );
154 @implementation wxNSTextField
158 static BOOL initialized = NO;
162 wxOSXCocoaClassAddWXMethods( self );
166 - (void) setEnabled:(BOOL) flag
168 [super setEnabled: flag];
170 if (![self drawsBackground]) {
171 // Static text is drawn incorrectly when disabled.
172 // For an explanation, see
173 // http://www.cocoabuilder.com/archive/message/cocoa/2006/7/21/168028
175 [self setTextColor: [NSColor controlTextColor]];
177 [self setTextColor: [NSColor secondarySelectedControlColor]];
182 - (void)controlTextDidChange:(NSNotification *)aNotification
184 wxUnusedVar(aNotification);
185 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
188 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
190 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId());
191 event.SetEventObject( wxpeer );
192 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
193 wxpeer->HandleWindowEvent( event );
198 typedef BOOL (*wxOSX_insertNewlineHandlerPtr)(NSView* self, SEL _cmd, NSControl *control, NSTextView* textView, SEL commandSelector);
200 - (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector
202 wxUnusedVar(textView);
203 wxUnusedVar(control);
204 if (commandSelector == @selector(insertNewline:))
206 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
209 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
210 if ( wxpeer && wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER )
212 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
213 event.SetEventObject( wxpeer );
214 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
215 wxpeer->HandleWindowEvent( event );
223 - (void)controlTextDidEndEditing:(NSNotification *)aNotification
225 wxUnusedVar(aNotification);
226 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
229 impl->DoNotifyFocusEvent( false, NULL );
234 // wxNSTextViewControl
236 wxNSTextViewControl::wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w ) : wxWidgetCocoaImpl(wxPeer, w)
238 m_scrollView = (NSScrollView*) w;
240 [m_scrollView setHasVerticalScroller:YES];
241 [m_scrollView setHasHorizontalScroller:NO];
242 [m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
243 NSSize contentSize = [m_scrollView contentSize];
245 m_textView = [[NSTextView alloc] initWithFrame: NSMakeRect(0, 0,
246 contentSize.width, contentSize.height)];
247 [m_textView setVerticallyResizable:YES];
248 [m_textView setHorizontallyResizable:NO];
249 [m_textView setAutoresizingMask:NSViewWidthSizable];
251 [m_scrollView setDocumentView: m_textView];
253 [m_textView setDelegate: w];
256 wxNSTextViewControl::~wxNSTextViewControl()
259 [m_textView setDelegate: nil];
262 wxString wxNSTextViewControl::GetStringValue() const
266 wxCFStringRef cf( (CFStringRef) [[m_textView string] retain] );
267 return cf.AsString(m_wxPeer->GetFont().GetEncoding());
269 return wxEmptyString;
271 void wxNSTextViewControl::SetStringValue( const wxString &str)
274 [m_textView setString: wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
276 void wxNSTextViewControl::Copy()
279 [m_textView copy:nil];
283 void wxNSTextViewControl::Cut()
286 [m_textView cut:nil];
289 void wxNSTextViewControl::Paste()
292 [m_textView paste:nil];
295 bool wxNSTextViewControl::CanPaste() const
300 void wxNSTextViewControl::SetEditable(bool editable)
303 [m_textView setEditable: editable];
306 void wxNSTextViewControl::GetSelection( long* from, long* to) const
310 NSRange range = [m_textView selectedRange];
311 *from = range.location;
312 *to = range.location + range.length;
316 void wxNSTextViewControl::SetSelection( long from , long to )
318 NSRange selrange = NSMakeRange(from, to-from);
319 [m_textView setSelectedRange:selrange];
320 [m_textView scrollRangeToVisible:selrange];
323 void wxNSTextViewControl::WriteText(const wxString& str)
325 // temp hack to get logging working early
326 wxString former = GetStringValue();
327 SetStringValue( former + str );
328 SetSelection(GetStringValue().length(), GetStringValue().length());
331 // wxNSTextFieldControl
333 wxNSTextFieldControl::wxNSTextFieldControl( wxTextCtrl *wxPeer, WXWidget w ) : wxWidgetCocoaImpl(wxPeer, w)
335 m_textField = (NSTextField*) w;
336 [m_textField setDelegate: w];
339 wxNSTextFieldControl::~wxNSTextFieldControl()
342 [m_textField setDelegate: nil];
345 wxString wxNSTextFieldControl::GetStringValue() const
347 wxCFStringRef cf( (CFStringRef) [[m_textField stringValue] retain] );
348 return cf.AsString(m_wxPeer->GetFont().GetEncoding());
350 void wxNSTextFieldControl::SetStringValue( const wxString &str)
352 [m_textField setStringValue: wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
354 void wxNSTextFieldControl::Copy()
356 NSText* editor = [m_textField currentEditor];
363 void wxNSTextFieldControl::Cut()
365 NSText* editor = [m_textField currentEditor];
372 void wxNSTextFieldControl::Paste()
374 NSText* editor = [m_textField currentEditor];
381 bool wxNSTextFieldControl::CanPaste() const
386 void wxNSTextFieldControl::SetEditable(bool editable)
388 [m_textField setEditable:editable];
391 void wxNSTextFieldControl::GetSelection( long* from, long* to) const
393 NSText* editor = [m_textField currentEditor];
396 NSRange range = [editor selectedRange];
397 *from = range.location;
398 *to = range.location + range.length;
402 void wxNSTextFieldControl::SetSelection( long from , long to )
404 NSText* editor = [m_textField currentEditor];
407 [editor setSelectedRange:NSMakeRange(from, to-from)];
411 void wxNSTextFieldControl::WriteText(const wxString& str)
413 // temp hack to get logging working early
414 wxString former = GetStringValue();
415 SetStringValue( former + str );
416 SetSelection(GetStringValue().length(), GetStringValue().length());
419 void wxNSTextFieldControl::controlAction(WXWidget WXUNUSED(slf),
420 void* WXUNUSED(_cmd), void *WXUNUSED(sender))
422 wxWindow* wxpeer = (wxWindow*) GetWXPeer();
423 if ( wxpeer && (wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER) )
425 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
426 event.SetEventObject( wxpeer );
427 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
428 wxpeer->HandleWindowEvent( event );
436 wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer,
437 wxWindowMac* WXUNUSED(parent),
438 wxWindowID WXUNUSED(id),
443 long WXUNUSED(extraStyle))
445 NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
446 wxWidgetCocoaImpl* c = NULL;
448 if ( style & wxTE_MULTILINE || style & wxTE_RICH || style & wxTE_RICH2 )
450 wxNSTextView* v = nil;
451 v = [[wxNSTextView alloc] initWithFrame:r];
452 c = new wxNSTextViewControl( wxpeer, v );
453 static_cast<wxNSTextViewControl*>(c)->SetStringValue(str);
457 NSTextField* v = nil;
458 if ( style & wxTE_PASSWORD )
459 v = [[wxNSSecureTextField alloc] initWithFrame:r];
461 v = [[wxNSTextField alloc] initWithFrame:r];
463 if ( style & wxNO_BORDER )
465 // FIXME: How can we remove the native control's border?
466 // setBordered is separate from the text ctrl's border.
472 c = new wxNSTextFieldControl( wxpeer, v );
473 static_cast<wxNSTextFieldControl*>(c)->SetStringValue(str);
480 #endif // wxUSE_TEXTCTRL