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