]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/textctrl.mm
Don't exit on errors in the pre-commit svn hook.
[wxWidgets.git] / src / osx / cocoa / textctrl.mm
CommitLineData
dbeddfb9
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/cocoa/textctrl.mm
3// Purpose: wxTextCtrl
4// Author: Stefan Csomor
5// Modified by: Ryan Norton (MLTE GetLineLength and GetLineText)
6// Created: 1998-01-01
7// RCS-ID: $Id: textctrl.cpp 54820 2008-07-29 20:04:11Z SC $
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
14#if wxUSE_TEXTCTRL
15
16#include "wx/textctrl.h"
17
18#ifndef WX_PRECOMP
19 #include "wx/intl.h"
20 #include "wx/app.h"
21 #include "wx/utils.h"
22 #include "wx/dc.h"
23 #include "wx/button.h"
24 #include "wx/menu.h"
25 #include "wx/settings.h"
26 #include "wx/msgdlg.h"
27 #include "wx/toplevel.h"
28#endif
29
30#ifdef __DARWIN__
31 #include <sys/types.h>
32 #include <sys/stat.h>
33#else
34 #include <stat.h>
35#endif
36
37#if wxUSE_STD_IOSTREAM
38 #if wxUSE_IOSTREAMH
39 #include <fstream.h>
40 #else
41 #include <fstream>
42 #endif
43#endif
44
45#include "wx/filefn.h"
46#include "wx/sysopt.h"
47#include "wx/thread.h"
48
49#include "wx/osx/private.h"
1e181c7a 50#include "wx/osx/cocoa/private/textimpl.h"
dbeddfb9 51
03647350 52@interface NSView(EditableView)
5f65ba36
SC
53- (BOOL)isEditable;
54- (void)setEditable:(BOOL)flag;
55@end
56
57class wxMacEditHelper
58{
59public :
60 wxMacEditHelper( NSView* textView )
61 {
62 m_textView = textView ;
63 if ( textView )
64 {
65 m_formerState = [textView isEditable];
66 [textView setEditable:YES];
67 }
68 }
69
70 ~wxMacEditHelper()
71 {
72 if ( m_textView )
73 [m_textView setEditable:m_formerState];
74 }
75
76protected :
77 BOOL m_formerState ;
78 NSView* m_textView;
79} ;
80
03647350 81@implementation wxNSSecureTextField
dbeddfb9 82
4dd9fdf8
SC
83+ (void)initialize
84{
85 static BOOL initialized = NO;
03647350 86 if (!initialized)
4dd9fdf8
SC
87 {
88 initialized = YES;
89 wxOSXCocoaClassAddWXMethods( self );
90 }
91}
dbeddfb9 92
4d23a0d3
KO
93- (void)controlTextDidChange:(NSNotification *)aNotification
94{
6331c8c0
SC
95 wxUnusedVar(aNotification);
96 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
4d23a0d3
KO
97 if ( impl )
98 {
99 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
100 if ( wxpeer ) {
101 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId());
102 event.SetEventObject( wxpeer );
103 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
104 wxpeer->HandleWindowEvent( event );
105 }
106 }
107}
108
6d109846
SC
109- (void)controlTextDidEndEditing:(NSNotification *)aNotification
110{
111 wxUnusedVar(aNotification);
112 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
113 if ( impl )
114 {
115 impl->DoNotifyFocusEvent( false, NULL );
116 }
117}
118
e32090ba
SC
119@end
120
1087c6c1 121@interface wxNSTextScrollView : NSScrollView
4d23a0d3 122{
4d23a0d3 123}
1087c6c1
SC
124@end
125
1087c6c1 126@implementation wxNSTextScrollView
c824c165
KO
127
128+ (void)initialize
129{
130 static BOOL initialized = NO;
03647350
VZ
131 if (!initialized)
132 {
c824c165
KO
133 initialized = YES;
134 wxOSXCocoaClassAddWXMethods( self );
135 }
136}
137
7cb2a241
SC
138@end
139
140@implementation wxNSTextFieldEditor
141
142- (void) keyDown:(NSEvent*) event
4d23a0d3 143{
9e55f38d 144 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
7cb2a241
SC
145 lastKeyDownEvent = event;
146 if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
147 [super keyDown:event];
148 lastKeyDownEvent = nil;
4d23a0d3 149}
533e2ae1 150
7cb2a241 151- (void) keyUp:(NSEvent*) event
533e2ae1 152{
9e55f38d 153 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
7cb2a241
SC
154 if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
155 [super keyUp:event];
533e2ae1 156}
1087c6c1 157
7cb2a241 158- (void) flagsChanged:(NSEvent*) event
1087c6c1 159{
9e55f38d 160 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
7cb2a241
SC
161 if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
162 [super flagsChanged:event];
1087c6c1 163}
1087c6c1 164
7cb2a241
SC
165- (BOOL) performKeyEquivalent:(NSEvent*) event
166{
167 BOOL retval = [super performKeyEquivalent:event];
168 return retval;
169}
1087c6c1 170
7cb2a241 171- (void) insertText:(id) str
1087c6c1 172{
9e55f38d 173 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
7cb2a241 174 if ( impl == NULL || lastKeyDownEvent==nil || !impl->DoHandleCharEvent(lastKeyDownEvent, str) )
1087c6c1 175 {
7cb2a241 176 [super insertText:str];
1087c6c1 177 }
1087c6c1
SC
178}
179
7cb2a241
SC
180@end
181
182@implementation wxNSTextView
1087c6c1 183
7cb2a241 184+ (void)initialize
1087c6c1 185{
7cb2a241 186 static BOOL initialized = NO;
03647350 187 if (!initialized)
7cb2a241
SC
188 {
189 initialized = YES;
190 wxOSXCocoaClassAddWXMethods( self );
191 }
1087c6c1
SC
192}
193
c824c165
KO
194@end
195
e32090ba 196@implementation wxNSTextField
ffad7b0d 197
e32090ba 198+ (void)initialize
dbeddfb9 199{
e32090ba 200 static BOOL initialized = NO;
03647350 201 if (!initialized)
e32090ba
SC
202 {
203 initialized = YES;
204 wxOSXCocoaClassAddWXMethods( self );
205 }
dbeddfb9 206}
e32090ba 207
7cb2a241
SC
208- (id) initWithFrame:(NSRect) frame
209{
210 self = [super initWithFrame:frame];
211 fieldEditor = nil;
212 return self;
213}
214
af665c2d
SC
215- (void) dealloc
216{
217 [fieldEditor release];
218 [super dealloc];
219}
220
7cb2a241
SC
221- (void) setFieldEditor:(wxNSTextFieldEditor*) editor
222{
223 fieldEditor = editor;
224}
225
226- (wxNSTextFieldEditor*) fieldEditor
227{
228 return fieldEditor;
229}
230
231
c3e433b1
SC
232- (void) setEnabled:(BOOL) flag
233{
234 [super setEnabled: flag];
235
236 if (![self drawsBackground]) {
237 // Static text is drawn incorrectly when disabled.
238 // For an explanation, see
239 // http://www.cocoabuilder.com/archive/message/cocoa/2006/7/21/168028
240 if (flag) {
241 [self setTextColor: [NSColor controlTextColor]];
242 } else {
243 [self setTextColor: [NSColor secondarySelectedControlColor]];
244 }
245 }
246}
4d23a0d3 247
ffad7b0d
SC
248- (void)controlTextDidChange:(NSNotification *)aNotification
249{
6331c8c0
SC
250 wxUnusedVar(aNotification);
251 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
ffad7b0d
SC
252 if ( impl )
253 {
254 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
255 if ( wxpeer ) {
256 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId());
257 event.SetEventObject( wxpeer );
258 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
259 wxpeer->HandleWindowEvent( event );
260 }
261 }
262}
dbeddfb9 263
2d6aa919
KO
264typedef BOOL (*wxOSX_insertNewlineHandlerPtr)(NSView* self, SEL _cmd, NSControl *control, NSTextView* textView, SEL commandSelector);
265
266- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector
267{
6331c8c0
SC
268 wxUnusedVar(textView);
269 wxUnusedVar(control);
2d6aa919
KO
270 if (commandSelector == @selector(insertNewline:))
271 {
6331c8c0 272 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
2d6aa919
KO
273 if ( impl )
274 {
275 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
03647350 276 if ( wxpeer && wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER )
2d6aa919
KO
277 {
278 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
279 event.SetEventObject( wxpeer );
280 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
281 wxpeer->HandleWindowEvent( event );
282 }
283 }
284 }
03647350 285
2d6aa919
KO
286 return NO;
287}
6d109846 288
ffad7b0d
SC
289- (void)controlTextDidEndEditing:(NSNotification *)aNotification
290{
6d109846
SC
291 wxUnusedVar(aNotification);
292 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
ffad7b0d
SC
293 if ( impl )
294 {
6d109846 295 impl->DoNotifyFocusEvent( false, NULL );
ffad7b0d
SC
296 }
297}
dbeddfb9
SC
298@end
299
c824c165
KO
300// wxNSTextViewControl
301
302wxNSTextViewControl::wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w ) : wxWidgetCocoaImpl(wxPeer, w)
303{
1087c6c1
SC
304 wxNSTextScrollView* sv = (wxNSTextScrollView*) w;
305 m_scrollView = sv;
03647350 306
c824c165
KO
307 [m_scrollView setHasVerticalScroller:YES];
308 [m_scrollView setHasHorizontalScroller:NO];
309 [m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
310 NSSize contentSize = [m_scrollView contentSize];
03647350 311
1087c6c1 312 wxNSTextView* tv = [[wxNSTextView alloc] initWithFrame: NSMakeRect(0, 0,
c824c165 313 contentSize.width, contentSize.height)];
1087c6c1
SC
314 m_textView = tv;
315 [tv setVerticallyResizable:YES];
316 [tv setHorizontallyResizable:NO];
317 [tv setAutoresizingMask:NSViewWidthSizable];
03647350 318
1087c6c1 319 [m_scrollView setDocumentView: tv];
c824c165 320
1087c6c1 321 [tv setDelegate: w];
03647350
VZ
322
323 InstallEventHandler(tv);
c824c165
KO
324}
325
326wxNSTextViewControl::~wxNSTextViewControl()
327{
328 if (m_textView)
329 [m_textView setDelegate: nil];
330}
331
03647350 332wxString wxNSTextViewControl::GetStringValue() const
c824c165 333{
03647350 334 if (m_textView)
c824c165 335 {
f66ecdc4 336 wxString result = wxCFStringRef::AsString([m_textView string], m_wxPeer->GetFont().GetEncoding());
50b5e38d
SC
337 wxMacConvertNewlines13To10( &result ) ;
338 return result;
c824c165
KO
339 }
340 return wxEmptyString;
341}
03647350 342void wxNSTextViewControl::SetStringValue( const wxString &str)
c824c165 343{
50b5e38d
SC
344 wxString st = str;
345 wxMacConvertNewlines10To13( &st );
5f65ba36 346 wxMacEditHelper helper(m_textView);
50b5e38d 347
c824c165 348 if (m_textView)
50b5e38d 349 [m_textView setString: wxCFStringRef( st , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
c824c165 350}
7cb2a241 351
03647350 352void wxNSTextViewControl::Copy()
c824c165
KO
353{
354 if (m_textView)
355 [m_textView copy:nil];
356
357}
358
03647350 359void wxNSTextViewControl::Cut()
c824c165
KO
360{
361 if (m_textView)
362 [m_textView cut:nil];
363}
364
03647350 365void wxNSTextViewControl::Paste()
c824c165
KO
366{
367 if (m_textView)
368 [m_textView paste:nil];
369}
370
03647350
VZ
371bool wxNSTextViewControl::CanPaste() const
372{
c824c165
KO
373 return true;
374}
375
03647350 376void wxNSTextViewControl::SetEditable(bool editable)
c824c165
KO
377{
378 if (m_textView)
379 [m_textView setEditable: editable];
380}
381
03647350 382void wxNSTextViewControl::GetSelection( long* from, long* to) const
c824c165
KO
383{
384 if (m_textView)
385 {
386 NSRange range = [m_textView selectedRange];
387 *from = range.location;
388 *to = range.location + range.length;
389 }
390}
391
392void wxNSTextViewControl::SetSelection( long from , long to )
393{
50b5e38d
SC
394 long textLength = [[m_textView string] length];
395 if ((from == -1) && (to == -1))
396 {
397 from = 0 ;
398 to = textLength ;
399 }
400 else
401 {
402 from = wxMin(textLength,wxMax(from,0)) ;
403 if ( to == -1 )
404 to = textLength;
405 else
406 to = wxMax(0,wxMin(textLength,to)) ;
407 }
408
2d6aa919
KO
409 NSRange selrange = NSMakeRange(from, to-from);
410 [m_textView setSelectedRange:selrange];
411 [m_textView scrollRangeToVisible:selrange];
c824c165
KO
412}
413
03647350 414void wxNSTextViewControl::WriteText(const wxString& str)
c824c165 415{
50b5e38d
SC
416 wxString st = str;
417 wxMacConvertNewlines10To13( &st );
5f65ba36 418 wxMacEditHelper helper(m_textView);
715824d5
SC
419 NSEvent* formerEvent = m_lastKeyDownEvent;
420 m_lastKeyDownEvent = nil;
50b5e38d 421 [m_textView insertText:wxCFStringRef( st , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
715824d5 422 m_lastKeyDownEvent = formerEvent;
c824c165
KO
423}
424
f95dd972
SC
425void wxNSTextViewControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle, bool ignoreBlack )
426{
427 if ([m_textView respondsToSelector:@selector(setFont:)])
428 [m_textView setFont: font.OSXGetNSFont()];
429}
430
431
c824c165
KO
432// wxNSTextFieldControl
433
1e181c7a
SC
434wxNSTextFieldControl::wxNSTextFieldControl( wxTextCtrl *wxPeer, WXWidget w ) : wxWidgetCocoaImpl(wxPeer, w)
435{
e32090ba
SC
436 m_textField = (NSTextField*) w;
437 [m_textField setDelegate: w];
50b5e38d 438 m_selStart = m_selEnd = 0;
7cb2a241 439 m_hasEditor = [w isKindOfClass:[NSTextField class]];
1e181c7a
SC
440}
441
442wxNSTextFieldControl::~wxNSTextFieldControl()
443{
c824c165
KO
444 if (m_textField)
445 [m_textField setDelegate: nil];
1e181c7a
SC
446}
447
03647350 448wxString wxNSTextFieldControl::GetStringValue() const
1e181c7a 449{
f66ecdc4 450 return wxCFStringRef::AsString([m_textField stringValue], m_wxPeer->GetFont().GetEncoding());
1e181c7a 451}
50b5e38d 452
03647350 453void wxNSTextFieldControl::SetStringValue( const wxString &str)
1e181c7a 454{
5f65ba36 455 wxMacEditHelper helper(m_textField);
e32090ba 456 [m_textField setStringValue: wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
1e181c7a 457}
50b5e38d 458
03647350 459void wxNSTextFieldControl::Copy()
1e181c7a 460{
e32090ba
SC
461 NSText* editor = [m_textField currentEditor];
462 if ( editor )
463 {
464 [editor copy:nil];
465 }
1e181c7a
SC
466}
467
03647350 468void wxNSTextFieldControl::Cut()
1e181c7a 469{
e32090ba
SC
470 NSText* editor = [m_textField currentEditor];
471 if ( editor )
472 {
473 [editor cut:nil];
474 }
1e181c7a
SC
475}
476
03647350 477void wxNSTextFieldControl::Paste()
1e181c7a 478{
e32090ba
SC
479 NSText* editor = [m_textField currentEditor];
480 if ( editor )
481 {
482 [editor paste:nil];
483 }
1e181c7a
SC
484}
485
03647350
VZ
486bool wxNSTextFieldControl::CanPaste() const
487{
e32090ba 488 return true;
1e181c7a
SC
489}
490
03647350 491void wxNSTextFieldControl::SetEditable(bool editable)
1e181c7a 492{
e32090ba 493 [m_textField setEditable:editable];
1e181c7a
SC
494}
495
03647350 496void wxNSTextFieldControl::GetSelection( long* from, long* to) const
1e181c7a 497{
e32090ba
SC
498 NSText* editor = [m_textField currentEditor];
499 if ( editor )
500 {
501 NSRange range = [editor selectedRange];
502 *from = range.location;
503 *to = range.location + range.length;
504 }
50b5e38d
SC
505 else
506 {
507 *from = m_selStart;
508 *to = m_selEnd;
509 }
1e181c7a
SC
510}
511
512void wxNSTextFieldControl::SetSelection( long from , long to )
513{
50b5e38d
SC
514 long textLength = [[m_textField stringValue] length];
515 if ((from == -1) && (to == -1))
516 {
517 from = 0 ;
518 to = textLength ;
519 }
520 else
521 {
522 from = wxMin(textLength,wxMax(from,0)) ;
523 if ( to == -1 )
524 to = textLength;
525 else
526 to = wxMax(0,wxMin(textLength,to)) ;
527 }
528
e32090ba
SC
529 NSText* editor = [m_textField currentEditor];
530 if ( editor )
531 {
532 [editor setSelectedRange:NSMakeRange(from, to-from)];
533 }
50b5e38d
SC
534 else
535 {
536 m_selStart = from;
537 m_selEnd = to;
538 }
1e181c7a
SC
539}
540
03647350 541void wxNSTextFieldControl::WriteText(const wxString& str)
1e181c7a 542{
715824d5
SC
543 NSEvent* formerEvent = m_lastKeyDownEvent;
544 m_lastKeyDownEvent = nil;
50b5e38d
SC
545 NSText* editor = [m_textField currentEditor];
546 if ( editor )
547 {
5f65ba36 548 wxMacEditHelper helper(m_textField);
50b5e38d
SC
549 [editor insertText:wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
550 }
551 else
552 {
553 wxString val = GetStringValue() ;
554 long start , end ;
555 GetSelection( &start , &end ) ;
556 val.Remove( start , end - start ) ;
557 val.insert( start , str ) ;
558 SetStringValue( val ) ;
559 SetSelection( start + str.length() , start + str.length() ) ;
560 }
715824d5 561 m_lastKeyDownEvent = formerEvent;
1e181c7a 562}
dbeddfb9 563
03647350 564void wxNSTextFieldControl::controlAction(WXWidget WXUNUSED(slf),
6331c8c0 565 void* WXUNUSED(_cmd), void *WXUNUSED(sender))
e32090ba
SC
566{
567 wxWindow* wxpeer = (wxWindow*) GetWXPeer();
03647350 568 if ( wxpeer && (wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER) )
e32090ba
SC
569 {
570 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
571 event.SetEventObject( wxpeer );
572 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
573 wxpeer->HandleWindowEvent( event );
574 }
575}
576
577//
578//
579//
580
03647350
VZ
581wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer,
582 wxWindowMac* WXUNUSED(parent),
583 wxWindowID WXUNUSED(id),
dbeddfb9 584 const wxString& str,
03647350 585 const wxPoint& pos,
dbeddfb9 586 const wxSize& size,
03647350 587 long style,
6331c8c0 588 long WXUNUSED(extraStyle))
dbeddfb9 589{
dbeddfb9 590 NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
c824c165 591 wxWidgetCocoaImpl* c = NULL;
03647350 592
c824c165 593 if ( style & wxTE_MULTILINE || style & wxTE_RICH || style & wxTE_RICH2 )
b15f9375 594 {
1087c6c1
SC
595 wxNSTextScrollView* v = nil;
596 v = [[wxNSTextScrollView alloc] initWithFrame:r];
c824c165
KO
597 c = new wxNSTextViewControl( wxpeer, v );
598 static_cast<wxNSTextViewControl*>(c)->SetStringValue(str);
599 }
03647350 600 else
c824c165 601 {
6331c8c0 602 NSTextField* v = nil;
c824c165
KO
603 if ( style & wxTE_PASSWORD )
604 v = [[wxNSSecureTextField alloc] initWithFrame:r];
605 else
606 v = [[wxNSTextField alloc] initWithFrame:r];
03647350 607
c824c165
KO
608 if ( style & wxNO_BORDER )
609 {
610 // FIXME: How can we remove the native control's border?
611 // setBordered is separate from the text ctrl's border.
612 }
03647350 613
b15f9375
SC
614 [v setBezeled:NO];
615 [v setBordered:NO];
03647350 616
c824c165
KO
617 c = new wxNSTextFieldControl( wxpeer, v );
618 static_cast<wxNSTextFieldControl*>(c)->SetStringValue(str);
b15f9375 619 }
03647350 620
dbeddfb9
SC
621 return c;
622}
623
624
625#endif // wxUSE_TEXTCTRL