]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/textctrl.mm
adding support for focus events to multiline textctrl
[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
e32090ba 52@interface wxNSSecureTextField : NSSecureTextField
4d23a0d3 53{
4d23a0d3 54}
e32090ba
SC
55@end
56
57@implementation wxNSSecureTextField
dbeddfb9 58
4dd9fdf8
SC
59+ (void)initialize
60{
61 static BOOL initialized = NO;
62 if (!initialized)
63 {
64 initialized = YES;
65 wxOSXCocoaClassAddWXMethods( self );
66 }
67}
dbeddfb9 68
4d23a0d3
KO
69- (void)controlTextDidChange:(NSNotification *)aNotification
70{
6331c8c0
SC
71 wxUnusedVar(aNotification);
72 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
4d23a0d3
KO
73 if ( impl )
74 {
75 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
76 if ( wxpeer ) {
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 );
81 }
82 }
83}
84
6d109846
SC
85- (void)controlTextDidEndEditing:(NSNotification *)aNotification
86{
87 wxUnusedVar(aNotification);
88 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
89 if ( impl )
90 {
91 impl->DoNotifyFocusEvent( false, NULL );
92 }
93}
94
e32090ba
SC
95@end
96
1087c6c1 97@interface wxNSTextScrollView : NSScrollView
4d23a0d3 98{
4d23a0d3 99}
1087c6c1
SC
100@end
101
102@interface wxNSTextView : NSTextView
103{
104 wxNSTextScrollView* scrollView;
105}
106
107- (void)setScrollView: (wxNSTextScrollView *) sv;
108- (wxNSTextScrollView*) scrollView;
c824c165
KO
109
110@end
111
1087c6c1 112@implementation wxNSTextScrollView
c824c165
KO
113
114+ (void)initialize
115{
116 static BOOL initialized = NO;
117 if (!initialized)
118 {
119 initialized = YES;
120 wxOSXCocoaClassAddWXMethods( self );
121 }
122}
123
533e2ae1 124- (void)textDidChange:(NSNotification *)aNotification
4d23a0d3 125{
6331c8c0
SC
126 wxUnusedVar(aNotification);
127 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
4d23a0d3
KO
128 if ( impl )
129 {
130 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
131 if ( wxpeer ) {
132 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId());
133 event.SetEventObject( wxpeer );
134 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
135 wxpeer->HandleWindowEvent( event );
136 }
137 }
138}
533e2ae1
KO
139
140- (BOOL)textView:(NSTextView *)aTextView doCommandBySelector:(SEL)commandSelector
141{
6331c8c0
SC
142 wxUnusedVar(aTextView);
143 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
533e2ae1
KO
144 if ( impl )
145 {
146 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
147 if (commandSelector == @selector(insertNewline:))
148 {
149 if ( wxpeer && wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER )
150 {
151 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
152 event.SetEventObject( wxpeer );
153 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
154 wxpeer->HandleWindowEvent( event );
155 }
156 }
157 }
158
159 return NO;
160}
1087c6c1
SC
161
162- (void)textDidEndEditing:(NSNotification *)aNotification
163{
164 wxUnusedVar(aNotification);
165 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
166 if ( impl )
167 {
168 impl->DoNotifyFocusEvent( false, NULL );
169 }
170}
171@end
172
173@implementation wxNSTextView
174
175- (BOOL) becomeFirstResponder
176{
177 BOOL val = [super becomeFirstResponder];
178
179 if ( val )
180 {
181 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( scrollView );
182 if (impl )
183 impl->DoNotifyFocusEvent( true, NULL );
184
185 }
186 return val;
187}
188
189- (void)setScrollView: (wxNSTextScrollView *) sv
190{
191 scrollView = sv;
192}
193
194- (wxNSTextScrollView*) scrollView
195{
196 return scrollView;
197}
198
c824c165
KO
199@end
200
e32090ba 201@implementation wxNSTextField
ffad7b0d 202
e32090ba 203+ (void)initialize
dbeddfb9 204{
e32090ba
SC
205 static BOOL initialized = NO;
206 if (!initialized)
207 {
208 initialized = YES;
209 wxOSXCocoaClassAddWXMethods( self );
210 }
dbeddfb9 211}
e32090ba 212
c3e433b1
SC
213- (void) setEnabled:(BOOL) flag
214{
215 [super setEnabled: flag];
216
217 if (![self drawsBackground]) {
218 // Static text is drawn incorrectly when disabled.
219 // For an explanation, see
220 // http://www.cocoabuilder.com/archive/message/cocoa/2006/7/21/168028
221 if (flag) {
222 [self setTextColor: [NSColor controlTextColor]];
223 } else {
224 [self setTextColor: [NSColor secondarySelectedControlColor]];
225 }
226 }
227}
4d23a0d3 228
ffad7b0d
SC
229- (void)controlTextDidChange:(NSNotification *)aNotification
230{
6331c8c0
SC
231 wxUnusedVar(aNotification);
232 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
ffad7b0d
SC
233 if ( impl )
234 {
235 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
236 if ( wxpeer ) {
237 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId());
238 event.SetEventObject( wxpeer );
239 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
240 wxpeer->HandleWindowEvent( event );
241 }
242 }
243}
dbeddfb9 244
2d6aa919
KO
245typedef BOOL (*wxOSX_insertNewlineHandlerPtr)(NSView* self, SEL _cmd, NSControl *control, NSTextView* textView, SEL commandSelector);
246
247- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector
248{
6331c8c0
SC
249 wxUnusedVar(textView);
250 wxUnusedVar(control);
2d6aa919
KO
251 if (commandSelector == @selector(insertNewline:))
252 {
6331c8c0 253 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
2d6aa919
KO
254 if ( impl )
255 {
256 wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
257 if ( wxpeer && wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER )
258 {
259 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
260 event.SetEventObject( wxpeer );
261 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
262 wxpeer->HandleWindowEvent( event );
263 }
264 }
265 }
266
267 return NO;
268}
6d109846 269
ffad7b0d
SC
270- (void)controlTextDidEndEditing:(NSNotification *)aNotification
271{
6d109846
SC
272 wxUnusedVar(aNotification);
273 wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
ffad7b0d
SC
274 if ( impl )
275 {
6d109846 276 impl->DoNotifyFocusEvent( false, NULL );
ffad7b0d
SC
277 }
278}
dbeddfb9
SC
279@end
280
c824c165
KO
281// wxNSTextViewControl
282
283wxNSTextViewControl::wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w ) : wxWidgetCocoaImpl(wxPeer, w)
284{
1087c6c1
SC
285 wxNSTextScrollView* sv = (wxNSTextScrollView*) w;
286 m_scrollView = sv;
c824c165
KO
287
288 [m_scrollView setHasVerticalScroller:YES];
289 [m_scrollView setHasHorizontalScroller:NO];
290 [m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
291 NSSize contentSize = [m_scrollView contentSize];
292
1087c6c1 293 wxNSTextView* tv = [[wxNSTextView alloc] initWithFrame: NSMakeRect(0, 0,
c824c165 294 contentSize.width, contentSize.height)];
1087c6c1
SC
295 m_textView = tv;
296 [tv setVerticallyResizable:YES];
297 [tv setHorizontallyResizable:NO];
298 [tv setAutoresizingMask:NSViewWidthSizable];
c824c165 299
1087c6c1 300 [m_scrollView setDocumentView: tv];
c824c165 301
1087c6c1
SC
302 [tv setDelegate: w];
303 [tv setScrollView:sv];
c824c165
KO
304}
305
306wxNSTextViewControl::~wxNSTextViewControl()
307{
308 if (m_textView)
309 [m_textView setDelegate: nil];
310}
311
312wxString wxNSTextViewControl::GetStringValue() const
313{
314 if (m_textView)
315 {
316 wxCFStringRef cf( (CFStringRef) [[m_textView string] retain] );
317 return cf.AsString(m_wxPeer->GetFont().GetEncoding());
318 }
319 return wxEmptyString;
320}
321void wxNSTextViewControl::SetStringValue( const wxString &str)
322{
323 if (m_textView)
324 [m_textView setString: wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
325}
326void wxNSTextViewControl::Copy()
327{
328 if (m_textView)
329 [m_textView copy:nil];
330
331}
332
333void wxNSTextViewControl::Cut()
334{
335 if (m_textView)
336 [m_textView cut:nil];
337}
338
339void wxNSTextViewControl::Paste()
340{
341 if (m_textView)
342 [m_textView paste:nil];
343}
344
345bool wxNSTextViewControl::CanPaste() const
346{
347 return true;
348}
349
350void wxNSTextViewControl::SetEditable(bool editable)
351{
352 if (m_textView)
353 [m_textView setEditable: editable];
354}
355
356void wxNSTextViewControl::GetSelection( long* from, long* to) const
357{
358 if (m_textView)
359 {
360 NSRange range = [m_textView selectedRange];
361 *from = range.location;
362 *to = range.location + range.length;
363 }
364}
365
366void wxNSTextViewControl::SetSelection( long from , long to )
367{
2d6aa919
KO
368 NSRange selrange = NSMakeRange(from, to-from);
369 [m_textView setSelectedRange:selrange];
370 [m_textView scrollRangeToVisible:selrange];
c824c165
KO
371}
372
373void wxNSTextViewControl::WriteText(const wxString& str)
374{
375 // temp hack to get logging working early
376 wxString former = GetStringValue();
377 SetStringValue( former + str );
2d6aa919 378 SetSelection(GetStringValue().length(), GetStringValue().length());
c824c165
KO
379}
380
381// wxNSTextFieldControl
382
1e181c7a
SC
383wxNSTextFieldControl::wxNSTextFieldControl( wxTextCtrl *wxPeer, WXWidget w ) : wxWidgetCocoaImpl(wxPeer, w)
384{
e32090ba
SC
385 m_textField = (NSTextField*) w;
386 [m_textField setDelegate: w];
1e181c7a
SC
387}
388
389wxNSTextFieldControl::~wxNSTextFieldControl()
390{
c824c165
KO
391 if (m_textField)
392 [m_textField setDelegate: nil];
1e181c7a
SC
393}
394
395wxString wxNSTextFieldControl::GetStringValue() const
396{
e32090ba 397 wxCFStringRef cf( (CFStringRef) [[m_textField stringValue] retain] );
1e181c7a
SC
398 return cf.AsString(m_wxPeer->GetFont().GetEncoding());
399}
400void wxNSTextFieldControl::SetStringValue( const wxString &str)
401{
e32090ba 402 [m_textField setStringValue: wxCFStringRef( str , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
1e181c7a
SC
403}
404void wxNSTextFieldControl::Copy()
405{
e32090ba
SC
406 NSText* editor = [m_textField currentEditor];
407 if ( editor )
408 {
409 [editor copy:nil];
410 }
1e181c7a
SC
411}
412
413void wxNSTextFieldControl::Cut()
414{
e32090ba
SC
415 NSText* editor = [m_textField currentEditor];
416 if ( editor )
417 {
418 [editor cut:nil];
419 }
1e181c7a
SC
420}
421
422void wxNSTextFieldControl::Paste()
423{
e32090ba
SC
424 NSText* editor = [m_textField currentEditor];
425 if ( editor )
426 {
427 [editor paste:nil];
428 }
1e181c7a
SC
429}
430
431bool wxNSTextFieldControl::CanPaste() const
432{
e32090ba 433 return true;
1e181c7a
SC
434}
435
436void wxNSTextFieldControl::SetEditable(bool editable)
437{
e32090ba 438 [m_textField setEditable:editable];
1e181c7a
SC
439}
440
441void wxNSTextFieldControl::GetSelection( long* from, long* to) const
442{
e32090ba
SC
443 NSText* editor = [m_textField currentEditor];
444 if ( editor )
445 {
446 NSRange range = [editor selectedRange];
447 *from = range.location;
448 *to = range.location + range.length;
449 }
1e181c7a
SC
450}
451
452void wxNSTextFieldControl::SetSelection( long from , long to )
453{
e32090ba
SC
454 NSText* editor = [m_textField currentEditor];
455 if ( editor )
456 {
457 [editor setSelectedRange:NSMakeRange(from, to-from)];
458 }
1e181c7a
SC
459}
460
461void wxNSTextFieldControl::WriteText(const wxString& str)
462{
463 // temp hack to get logging working early
464 wxString former = GetStringValue();
465 SetStringValue( former + str );
2d6aa919 466 SetSelection(GetStringValue().length(), GetStringValue().length());
1e181c7a 467}
dbeddfb9 468
6331c8c0
SC
469void wxNSTextFieldControl::controlAction(WXWidget WXUNUSED(slf),
470 void* WXUNUSED(_cmd), void *WXUNUSED(sender))
e32090ba
SC
471{
472 wxWindow* wxpeer = (wxWindow*) GetWXPeer();
473 if ( wxpeer && (wxpeer->GetWindowStyle() & wxTE_PROCESS_ENTER) )
474 {
475 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, wxpeer->GetId());
476 event.SetEventObject( wxpeer );
477 event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
478 wxpeer->HandleWindowEvent( event );
479 }
480}
481
482//
483//
484//
485
dbeddfb9 486wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer,
6331c8c0
SC
487 wxWindowMac* WXUNUSED(parent),
488 wxWindowID WXUNUSED(id),
dbeddfb9
SC
489 const wxString& str,
490 const wxPoint& pos,
491 const wxSize& size,
492 long style,
6331c8c0 493 long WXUNUSED(extraStyle))
dbeddfb9 494{
dbeddfb9 495 NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
c824c165 496 wxWidgetCocoaImpl* c = NULL;
e32090ba 497
c824c165 498 if ( style & wxTE_MULTILINE || style & wxTE_RICH || style & wxTE_RICH2 )
b15f9375 499 {
1087c6c1
SC
500 wxNSTextScrollView* v = nil;
501 v = [[wxNSTextScrollView alloc] initWithFrame:r];
c824c165
KO
502 c = new wxNSTextViewControl( wxpeer, v );
503 static_cast<wxNSTextViewControl*>(c)->SetStringValue(str);
504 }
505 else
506 {
6331c8c0 507 NSTextField* v = nil;
c824c165
KO
508 if ( style & wxTE_PASSWORD )
509 v = [[wxNSSecureTextField alloc] initWithFrame:r];
510 else
511 v = [[wxNSTextField alloc] initWithFrame:r];
512
513 if ( style & wxNO_BORDER )
514 {
515 // FIXME: How can we remove the native control's border?
516 // setBordered is separate from the text ctrl's border.
517 }
518
b15f9375
SC
519 [v setBezeled:NO];
520 [v setBordered:NO];
c824c165
KO
521
522 c = new wxNSTextFieldControl( wxpeer, v );
523 static_cast<wxNSTextFieldControl*>(c)->SetStringValue(str);
b15f9375 524 }
dbeddfb9 525
dbeddfb9
SC
526 return c;
527}
528
529
530#endif // wxUSE_TEXTCTRL