reworked font handling for osx
[wxWidgets.git] / src / osx / cocoa / window.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/cocoa/window.mm
3 // Purpose:     widgets (non tlw) for cocoa
4 // Author:      Stefan Csomor
5 // Modified by:
6 // Created:     2008-06-20
7 // RCS-ID:      $Id: window.mm 48805 2007-09-19 14:52:25Z SC $
8 // Copyright:   (c) Stefan Csomor
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #ifndef WX_PRECOMP
15     #include "wx/dcclient.h"
16     #include "wx/nonownedwnd.h"
17     #include "wx/log.h"
18 #endif
19
20 #ifdef __WXMAC__
21     #include "wx/osx/private.h"
22 #endif
23
24 #if wxUSE_CARET
25     #include "wx/caret.h"
26 #endif
27
28 #if wxUSE_DRAG_AND_DROP
29     #include "wx/dnd.h"
30 #endif
31
32 #include <objc/objc-runtime.h>
33
34 NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
35 {
36     int x, y, w, h ;
37
38     window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
39     wxRect bounds(x,y,w,h);
40     NSView* sv = (window->GetParent()->GetHandle() );
41
42     return wxToNSRect( sv, bounds );
43 }
44
45 @interface wxNSView : NSView
46 {
47     NSTrackingRectTag rectTag;
48 }
49
50 - (BOOL) canBecomeKeyView;
51 // the tracking tag is needed to track mouse enter / exit events 
52 - (void) setTrackingTag: (NSTrackingRectTag)tag;
53 - (NSTrackingRectTag) trackingTag;
54 @end // wxNSView
55
56 @interface NSView(PossibleMethods) 
57 - (void)setTitle:(NSString *)aString;
58 - (void)setStringValue:(NSString *)aString;
59 - (void)setIntValue:(int)anInt;
60 - (void)setFloatValue:(float)aFloat;
61 - (void)setDoubleValue:(double)aDouble;
62
63 - (double)minValue;
64 - (double)maxValue;
65 - (void)setMinValue:(double)aDouble;
66 - (void)setMaxValue:(double)aDouble;
67
68 - (void)sizeToFit;
69
70 - (BOOL)isEnabled;
71 - (void)setEnabled:(BOOL)flag;
72
73 - (void)setImage:(NSImage *)image;
74 - (void)setControlSize:(NSControlSize)size;
75
76 - (void)setFont:(NSFont *)fontObject;
77
78 - (id)contentView;
79
80 - (void)setTarget:(id)anObject;
81 - (void)setAction:(SEL)aSelector;
82 - (void)setDoubleAction:(SEL)aSelector;
83 @end 
84
85 long wxOSXTranslateCocoaKey( NSEvent* event )
86 {
87     long retval = 0;
88
89     if ([event type] != NSFlagsChanged)
90     {    
91         NSString* s = [event charactersIgnoringModifiers];
92         // backspace char reports as delete w/modifiers for some reason
93         if ([s length] == 1)
94         {
95             switch ( [s characterAtIndex:0] )
96             {
97                 // backspace key
98                 case 0x7F :
99                 case 8 : 
100                     retval = WXK_BACK;
101                     break;
102                 case NSUpArrowFunctionKey :
103                     retval = WXK_UP;
104                     break;
105                 case NSDownArrowFunctionKey :
106                     retval = WXK_DOWN;
107                     break;
108                 case NSLeftArrowFunctionKey :
109                     retval = WXK_LEFT;
110                     break;
111                 case NSRightArrowFunctionKey :
112                     retval = WXK_RIGHT;
113                     break;
114                 case NSInsertFunctionKey  :
115                     retval = WXK_INSERT;
116                     break;
117                 case NSDeleteFunctionKey  :
118                     retval = WXK_DELETE;
119                     break;
120                 case NSHomeFunctionKey  :
121                     retval = WXK_HOME;
122                     break;
123         //        case NSBeginFunctionKey  :
124         //            retval = WXK_BEGIN;
125         //            break;
126                 case NSEndFunctionKey  :
127                     retval = WXK_END;
128                     break;
129                 case NSPageUpFunctionKey  :
130                     retval = WXK_PAGEUP;
131                     break;
132                case NSPageDownFunctionKey  :
133                     retval = WXK_PAGEDOWN;
134                     break;
135                case NSHelpFunctionKey  :
136                     retval = WXK_HELP;
137                     break;
138                 default:
139                     int intchar = [s characterAtIndex: 0];
140                     if ( intchar >= NSF1FunctionKey && intchar <= NSF24FunctionKey )
141                         retval = WXK_F1 + (intchar - NSF1FunctionKey );
142                     break;
143             }
144         }
145     }
146     
147     // Some keys don't seem to have constants. The code mimics the approach
148     // taken by WebKit. See:
149     // http://trac.webkit.org/browser/trunk/WebCore/platform/mac/KeyEventMac.mm
150     switch( [event keyCode] )
151     {
152         // command key
153         case 54:
154         case 55:
155             retval = WXK_COMMAND;
156             break;
157         // caps locks key
158         case 57: // Capslock
159             retval = WXK_CAPITAL;
160             break;
161         // shift key
162         case 56: // Left Shift
163         case 60: // Right Shift
164             retval = WXK_SHIFT;
165             break;
166         // alt key
167         case 58: // Left Alt
168         case 61: // Right Alt
169             retval = WXK_ALT;
170             break;
171         // ctrl key
172         case 59: // Left Ctrl
173         case 62: // Right Ctrl
174             retval = WXK_CONTROL;
175             break;
176         // clear key
177         case 71: 
178             retval = WXK_CLEAR;
179             break;
180         // tab key
181         case 48: 
182             retval = WXK_TAB;
183             break;
184
185         default :
186             break;
187     }
188     return retval;
189 }
190
191 void SetupKeyEvent( wxKeyEvent &wxevent , NSEvent * nsEvent, NSString* charString = NULL )
192 {
193     UInt32 modifiers = [nsEvent modifierFlags] ;
194     int eventType = [nsEvent type];
195
196     wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
197     wxevent.m_controlDown = modifiers & NSControlKeyMask;
198     wxevent.m_altDown = modifiers & NSAlternateKeyMask;
199     wxevent.m_metaDown = modifiers & NSCommandKeyMask;
200     
201     wxevent.m_rawCode = [nsEvent keyCode];
202     wxevent.m_rawFlags = modifiers;
203     
204     wxevent.SetTimestamp( [nsEvent timestamp] * 1000.0 ) ;
205     switch (eventType)
206     {
207         case NSKeyDown :
208             wxevent.SetEventType( wxEVT_KEY_DOWN )  ;
209             break;
210         case NSKeyUp :
211             wxevent.SetEventType( wxEVT_KEY_UP )  ;
212             break;
213         case NSFlagsChanged :
214             // setup common code here
215             break;
216         default :
217             break ;
218     }
219
220     wxString chars;
221     if ( eventType != NSFlagsChanged )
222     {
223         NSString* nschars = [nsEvent characters];
224         if ( charString )
225         {
226             // if charString is set, it did not come from key up / key down
227             wxevent.SetEventType( wxEVT_CHAR );
228             wxCFStringRef cfchars((CFStringRef)[charString retain]);
229             chars = cfchars.AsString();
230         }
231         else if ( nschars )
232         {
233             wxCFStringRef cfchars((CFStringRef)[nschars retain]);
234             chars = cfchars.AsString();
235         }
236     }
237     
238     int aunichar = chars.Length() > 0 ? chars[0] : 0;
239     long keyval = 0;
240     
241     if (wxevent.GetEventType() != wxEVT_CHAR)
242         keyval = wxOSXTranslateCocoaKey(nsEvent) ;
243
244     if ( !keyval )
245     {
246         if ( wxevent.GetEventType() == wxEVT_KEY_UP || wxevent.GetEventType() == wxEVT_KEY_DOWN )
247             keyval = wxToupper( aunichar ) ;
248         else
249             keyval = aunichar;
250     }
251     
252 #if wxUSE_UNICODE
253     wxevent.m_uniChar = aunichar;
254 #endif
255     wxevent.m_keyCode = keyval;
256 }
257
258 UInt32 g_lastButton = 0 ;
259 bool g_lastButtonWasFakeRight = false ;
260
261 void SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
262 {
263     int eventType = [nsEvent type];
264     UInt32 modifiers = [nsEvent modifierFlags] ;
265     wxPoint screenMouseLocation = wxFromNSPoint( NULL, [nsEvent locationInWindow]);
266
267     // these parameters are not given for all events
268     UInt32 button = [nsEvent buttonNumber];
269     UInt32 clickCount = 0;
270
271     wxevent.m_x = screenMouseLocation.x;
272     wxevent.m_y = screenMouseLocation.y;
273     wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
274     wxevent.m_controlDown = modifiers & NSControlKeyMask;
275     wxevent.m_altDown = modifiers & NSAlternateKeyMask;
276     wxevent.m_metaDown = modifiers & NSCommandKeyMask;
277     wxevent.SetTimestamp( [nsEvent timestamp] * 1000.0 ) ;
278
279     UInt32 mouseChord = 0; 
280
281     switch (eventType)
282     {
283         case NSLeftMouseDown :
284         case NSLeftMouseDragged :
285             mouseChord = 1U;
286             break;
287         case NSRightMouseDown :
288         case NSRightMouseDragged :
289             mouseChord = 2U;
290             break;
291         case NSOtherMouseDown :
292         case NSOtherMouseDragged :
293             mouseChord = 4U;
294             break;
295     }
296
297     // a control click is interpreted as a right click
298     bool thisButtonIsFakeRight = false ;
299     if ( button == 0 && (modifiers & NSControlKeyMask) )
300     {
301         button = 1 ;
302         thisButtonIsFakeRight = true ;
303     }
304
305     // otherwise we report double clicks by connecting a left click with a ctrl-left click
306     if ( clickCount > 1 && button != g_lastButton )
307         clickCount = 1 ;
308
309     // we must make sure that our synthetic 'right' button corresponds in
310     // mouse down, moved and mouse up, and does not deliver a right down and left up
311     switch (eventType)
312     {
313         case NSLeftMouseDown :
314         case NSRightMouseDown :
315         case NSOtherMouseDown :
316             g_lastButton = button ;
317             g_lastButtonWasFakeRight = thisButtonIsFakeRight ;
318             break;
319      }
320
321     if ( button == 0 )
322     {
323         g_lastButton = 0 ;
324         g_lastButtonWasFakeRight = false ;
325     }
326     else if ( g_lastButton == 1 && g_lastButtonWasFakeRight )
327         button = g_lastButton ;
328
329     // Adjust the chord mask to remove the primary button and add the
330     // secondary button.  It is possible that the secondary button is
331     // already pressed, e.g. on a mouse connected to a laptop, but this
332     // possibility is ignored here:
333     if( thisButtonIsFakeRight && ( mouseChord & 1U ) )
334         mouseChord = ((mouseChord & ~1U) | 2U);
335
336     if(mouseChord & 1U)
337                 wxevent.m_leftDown = true ;
338     if(mouseChord & 2U)
339                 wxevent.m_rightDown = true ;
340     if(mouseChord & 4U)
341                 wxevent.m_middleDown = true ;
342
343     // translate into wx types
344     switch (eventType)
345     {
346         case NSLeftMouseDown :
347         case NSRightMouseDown :
348         case NSOtherMouseDown :
349             clickCount = [nsEvent clickCount];
350             switch ( button )
351             {
352                 case 0 :
353                     wxevent.SetEventType( clickCount > 1 ? wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN )  ;
354                     break ;
355
356                 case 1 :
357                     wxevent.SetEventType( clickCount > 1 ? wxEVT_RIGHT_DCLICK : wxEVT_RIGHT_DOWN ) ;
358                     break ;
359
360                 case 2 :
361                     wxevent.SetEventType( clickCount > 1 ? wxEVT_MIDDLE_DCLICK : wxEVT_MIDDLE_DOWN ) ;
362                     break ;
363
364                 default:
365                     break ;
366             }
367             break ;
368
369         case NSLeftMouseUp :
370         case NSRightMouseUp :
371         case NSOtherMouseUp :
372             clickCount = [nsEvent clickCount];
373             switch ( button )
374             {
375                 case 0 :
376                     wxevent.SetEventType( wxEVT_LEFT_UP )  ;
377                     break ;
378
379                 case 1 :
380                     wxevent.SetEventType( wxEVT_RIGHT_UP ) ;
381                     break ;
382
383                 case 2 :
384                     wxevent.SetEventType( wxEVT_MIDDLE_UP ) ;
385                     break ;
386
387                 default:
388                     break ;
389             }
390             break ;
391
392      case NSScrollWheel :
393         {
394             wxevent.SetEventType( wxEVT_MOUSEWHEEL ) ;
395             wxevent.m_wheelDelta = 10;
396             wxevent.m_linesPerAction = 1;
397             NSLog(@"deltaX %f, deltaY %f",[nsEvent deltaX], [nsEvent deltaY]);
398             if ( abs([nsEvent deltaX]) > abs([nsEvent deltaY]) )
399             {
400                 wxevent.m_wheelAxis = 1;
401                 wxevent.m_wheelRotation = [nsEvent deltaX] * 10.0;
402             }
403             else
404             {
405                 wxevent.m_wheelRotation = [nsEvent deltaY] * 10.0;
406             }
407         }
408         break ;
409
410         case NSMouseEntered :
411             wxevent.SetEventType( wxEVT_ENTER_WINDOW ) ;
412             break;
413         case NSMouseExited :
414             wxevent.SetEventType( wxEVT_LEAVE_WINDOW ) ;
415             break;
416         case NSLeftMouseDragged :
417         case NSRightMouseDragged :
418         case NSOtherMouseDragged :
419         case NSMouseMoved :
420             wxevent.SetEventType( wxEVT_MOTION ) ;
421             break;
422         default :
423             break ;
424     }
425     
426     wxevent.m_clickCount = clickCount;
427     
428 }
429
430 @implementation wxNSView
431
432 + (void)initialize
433 {
434     static BOOL initialized = NO;
435     if (!initialized) 
436     {
437         initialized = YES;
438         wxOSXCocoaClassAddWXMethods( self );
439     }
440 }
441
442 - (BOOL) canBecomeKeyView
443 {
444     return YES;
445 }
446
447 - (void) setTrackingTag: (NSTrackingRectTag)tag
448 {
449     rectTag = tag;
450 }
451
452 - (NSTrackingRectTag) trackingTag
453 {
454     return rectTag;
455 }
456
457 @end // wxNSView
458
459 //
460 // event handlers
461 //
462
463 #if wxUSE_DRAG_AND_DROP
464
465 // see http://lists.apple.com/archives/Cocoa-dev/2005/Jul/msg01244.html
466 // for details on the NSPasteboard -> PasteboardRef conversion
467
468 NSDragOperation wxOSX_draggingEntered( id self, SEL _cmd, id <NSDraggingInfo>sender )
469 {
470     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
471     if (impl == NULL)
472         return NSDragOperationNone;
473         
474     return impl->draggingEntered(sender, self, _cmd);
475 }
476
477 void wxOSX_draggingExited( id self, SEL _cmd, id <NSDraggingInfo> sender )
478 {
479     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
480     if (impl == NULL)
481         return ;
482         
483     return impl->draggingExited(sender, self, _cmd);
484 }
485
486 NSDragOperation wxOSX_draggingUpdated( id self, SEL _cmd, id <NSDraggingInfo>sender )
487 {
488     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
489     if (impl == NULL)
490         return NSDragOperationNone;
491         
492     return impl->draggingUpdated(sender, self, _cmd);
493 }
494
495 BOOL wxOSX_performDragOperation( id self, SEL _cmd, id <NSDraggingInfo> sender )
496 {
497     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
498     if (impl == NULL)
499         return NSDragOperationNone;
500         
501     return impl->performDragOperation(sender, self, _cmd) ? YES:NO ;
502 }
503
504 void wxOSX_mouseEvent(NSView* self, SEL _cmd, NSEvent *event) 
505 {
506     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
507     if (impl == NULL)
508         return;
509         
510     impl->mouseEvent(event, self, _cmd);
511 }
512
513 void wxOSX_keyEvent(NSView* self, SEL _cmd, NSEvent *event) 
514 {
515     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
516     if (impl == NULL)
517         return;
518         
519     impl->keyEvent(event, self, _cmd);
520 }
521
522 void wxOSX_insertText(NSView* self, SEL _cmd, NSString* text) 
523 {
524     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
525     if (impl == NULL)
526         return;
527         
528     impl->insertText(text, self, _cmd);
529 }
530
531 BOOL wxOSX_performKeyEquivalent(NSView* self, SEL _cmd, NSEvent *event) 
532 {
533     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
534     if (impl == NULL)
535         return NO;
536         
537     return impl->performKeyEquivalent(event, self, _cmd);
538 }
539
540 BOOL wxOSX_acceptsFirstResponder(NSView* self, SEL _cmd)
541 {
542     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
543     if (impl == NULL)
544         return NO;
545         
546     return impl->acceptsFirstResponder(self, _cmd);
547 }
548
549 BOOL wxOSX_becomeFirstResponder(NSView* self, SEL _cmd)
550 {
551     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
552     if (impl == NULL)
553         return NO;
554         
555     return impl->becomeFirstResponder(self, _cmd);
556 }
557
558 BOOL wxOSX_resignFirstResponder(NSView* self, SEL _cmd)
559 {
560     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
561     if (impl == NULL)
562         return NO;
563         
564     return impl->resignFirstResponder(self, _cmd);
565 }
566
567 void wxOSX_resetCursorRects(NSView* self, SEL _cmd)
568 {
569     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
570     if (impl == NULL)
571         return;
572         
573     impl->resetCursorRects(self, _cmd);
574 }
575
576 BOOL wxOSX_isFlipped(NSView* self, SEL _cmd)
577 {
578     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
579     if (impl == NULL)
580         return NO;
581         
582     return impl->isFlipped(self, _cmd) ? YES:NO;
583 }
584
585 void wxOSX_drawRect(NSView* self, SEL _cmd, NSRect rect)
586 {
587     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
588     if (impl == NULL)
589         return;
590         
591     return impl->drawRect(&rect, self, _cmd);
592 }
593
594 void wxOSX_controlAction(NSView* self, SEL _cmd, id sender)
595 {
596     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
597     if (impl == NULL)
598         return;
599         
600     impl->controlAction(self, _cmd, sender);
601 }
602
603 void wxOSX_controlDoubleAction(NSView* self, SEL _cmd, id sender)
604 {
605     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
606     if (impl == NULL)
607         return;
608         
609     impl->controlDoubleAction(self, _cmd, sender);
610 }
611
612 unsigned int wxWidgetCocoaImpl::draggingEntered(void* s, WXWidget slf, void *_cmd)
613 {
614     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
615     NSPasteboard *pboard = [sender draggingPasteboard];
616     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
617     
618     wxWindow* wxpeer = GetWXPeer();
619     if ( wxpeer == NULL )
620         return NSDragOperationNone;
621         
622     wxDropTarget* target = wxpeer->GetDropTarget();
623     if ( target == NULL )
624         return NSDragOperationNone;
625
626     wxDragResult result = wxDragNone;
627     wxPoint pt = wxFromNSPoint( m_osxView, [sender draggingLocation] );
628
629     if ( sourceDragMask & NSDragOperationLink )
630         result = wxDragLink;
631     else if ( sourceDragMask & NSDragOperationCopy )
632         result = wxDragCopy;
633     else if ( sourceDragMask & NSDragOperationMove )
634         result = wxDragMove;
635
636     PasteboardRef pboardRef;    
637     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
638     target->SetCurrentDragPasteboard(pboardRef);
639     result = target->OnEnter(pt.x, pt.y, result);
640     CFRelease(pboardRef);
641      
642     NSDragOperation nsresult = NSDragOperationNone;
643     switch (result )
644     {
645         case wxDragLink:
646             nsresult = NSDragOperationLink;
647         case wxDragMove:
648             nsresult = NSDragOperationMove;
649         case wxDragCopy:
650             nsresult = NSDragOperationCopy;
651         default :
652             break;
653     }
654     return nsresult;
655 }
656
657 void wxWidgetCocoaImpl::draggingExited(void* s, WXWidget slf, void *_cmd)
658 {
659     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
660     NSPasteboard *pboard = [sender draggingPasteboard];
661     
662     wxWindow* wxpeer = GetWXPeer();
663     if ( wxpeer == NULL )
664         return;
665         
666     wxDropTarget* target = wxpeer->GetDropTarget();
667     if ( target == NULL )
668         return;
669         
670     PasteboardRef pboardRef;    
671     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
672     target->SetCurrentDragPasteboard(pboardRef);
673     target->OnLeave();
674     CFRelease(pboardRef);
675  }
676
677 unsigned int wxWidgetCocoaImpl::draggingUpdated(void* s, WXWidget slf, void *_cmd)
678 {
679     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
680     NSPasteboard *pboard = [sender draggingPasteboard];
681     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
682         
683     wxWindow* wxpeer = GetWXPeer();
684     if ( wxpeer == NULL )
685         return NSDragOperationNone;
686         
687     wxDropTarget* target = wxpeer->GetDropTarget();
688     if ( target == NULL )
689         return NSDragOperationNone;
690
691     wxDragResult result = wxDragNone;
692     wxPoint pt = wxFromNSPoint( m_osxView, [sender draggingLocation] );
693
694     if ( sourceDragMask & NSDragOperationLink )
695         result = wxDragLink;
696     else if ( sourceDragMask & NSDragOperationCopy )
697         result = wxDragCopy;
698     else if ( sourceDragMask & NSDragOperationMove )
699         result = wxDragMove;
700
701     PasteboardRef pboardRef;    
702     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
703     target->SetCurrentDragPasteboard(pboardRef);
704     result = target->OnDragOver(pt.x, pt.y, result);
705     CFRelease(pboardRef);
706      
707     NSDragOperation nsresult = NSDragOperationNone;
708     switch (result )
709     {
710         case wxDragLink:
711             nsresult = NSDragOperationLink;
712         case wxDragMove:
713             nsresult = NSDragOperationMove;
714         case wxDragCopy:
715             nsresult = NSDragOperationCopy;
716         default :
717             break;
718     }
719     return nsresult;
720 }
721
722 bool wxWidgetCocoaImpl::performDragOperation(void* s, WXWidget slf, void *_cmd)
723 {
724     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
725
726     NSPasteboard *pboard = [sender draggingPasteboard];
727     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
728     
729     wxWindow* wxpeer = GetWXPeer();
730     wxDropTarget* target = wxpeer->GetDropTarget();
731     wxDragResult result = wxDragNone;
732     wxPoint pt = wxFromNSPoint( m_osxView, [sender draggingLocation] );
733
734     if ( sourceDragMask & NSDragOperationLink )
735         result = wxDragLink;
736     else if ( sourceDragMask & NSDragOperationCopy )
737         result = wxDragCopy;
738     else if ( sourceDragMask & NSDragOperationMove )
739         result = wxDragMove;
740
741     PasteboardRef pboardRef;    
742     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
743     target->SetCurrentDragPasteboard(pboardRef);
744     result = target->OnData(pt.x, pt.y, result);
745     CFRelease(pboardRef);
746      
747     return result != wxDragNone;
748 }
749
750 #endif
751
752 typedef void (*wxOSX_TextEventHandlerPtr)(NSView* self, SEL _cmd, NSString *event);
753 typedef void (*wxOSX_EventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
754 typedef BOOL (*wxOSX_PerformKeyEventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
755 typedef BOOL (*wxOSX_FocusHandlerPtr)(NSView* self, SEL _cmd);
756 typedef BOOL (*wxOSX_ResetCursorRectsHandlerPtr)(NSView* self, SEL _cmd);
757 typedef BOOL (*wxOSX_DrawRectHandlerPtr)(NSView* self, SEL _cmd, NSRect rect);
758
759 void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
760 {
761     if ( !DoHandleMouseEvent(event) )
762     {
763         wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
764         superimpl(slf, (SEL)_cmd, event);
765     }
766 }
767
768 void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
769 {
770     if ( [[slf window] firstResponder] != slf || !DoHandleKeyEvent(event) )
771     {
772         wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
773         superimpl(slf, (SEL)_cmd, event);
774     }
775 }
776
777 void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
778 {
779     if (m_lastKeyDownEvent && !DoHandleCharEvent(m_lastKeyDownEvent, text) )
780     {
781             wxOSX_TextEventHandlerPtr superimpl = (wxOSX_TextEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
782             superimpl(slf, (SEL)_cmd, text);
783     }
784     m_lastKeyDownEvent = NULL;
785 }
786
787
788 bool wxWidgetCocoaImpl::performKeyEquivalent(WX_NSEvent event, WXWidget slf, void *_cmd)
789 {
790     wxOSX_PerformKeyEventHandlerPtr superimpl = (wxOSX_PerformKeyEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
791     return superimpl(slf, (SEL)_cmd, event);
792 }
793
794 bool wxWidgetCocoaImpl::acceptsFirstResponder(WXWidget slf, void *_cmd)
795 {
796     // FIXME: We need to find a way to query AcceptsFocus here, but when we do it
797     // it calls native APIs which lead us back here and into a loop.
798     wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
799     return superimpl(slf, (SEL)_cmd);
800 }
801
802 bool wxWidgetCocoaImpl::becomeFirstResponder(WXWidget slf, void *_cmd)
803 {
804     wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
805     // get the current focus before running becomeFirstResponder
806     NSResponder* currentResponder = [[NSApp keyWindow] firstResponder]; 
807     NSView* otherView = (currentResponder != nil && [currentResponder isKindOfClass:[NSView class]]) ? (NSView*) currentResponder : NULL; 
808     wxWidgetImpl* otherWindow = FindFromWXWidget(otherView);
809     BOOL r = superimpl(slf, (SEL)_cmd);
810     if ( r )
811         DoNotifyFocusEvent( true, otherWindow );
812     return r;
813 }
814
815 bool wxWidgetCocoaImpl::resignFirstResponder(WXWidget slf, void *_cmd)
816 {
817     wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
818     BOOL r = superimpl(slf, (SEL)_cmd);
819     // get the current focus after running resignFirstResponder
820     NSResponder* currentResponder = [[NSApp keyWindow] firstResponder]; 
821     NSView* otherView = (currentResponder != nil && [currentResponder isKindOfClass:[NSView class]]) ? (NSView*) currentResponder : NULL; 
822     wxWidgetImpl* otherWindow = FindFromWXWidget(otherView);
823     if ( r )
824         DoNotifyFocusEvent( false, otherWindow );
825     return r;
826 }
827
828 void wxWidgetCocoaImpl::resetCursorRects(WXWidget slf, void *_cmd)
829 {
830     wxWindow* wxpeer = GetWXPeer();
831     if ( wxpeer )
832     {
833         NSCursor *cursor = (NSCursor*)wxpeer->GetCursor().GetHCURSOR();
834         if (cursor == NULL)
835         {
836             wxOSX_ResetCursorRectsHandlerPtr superimpl = (wxOSX_ResetCursorRectsHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
837             superimpl(slf, (SEL)_cmd);
838         }
839         else
840         {
841             [slf addCursorRect: [slf bounds]
842                 cursor: cursor];
843         }
844     }
845 }
846   
847 bool wxWidgetCocoaImpl::isFlipped(WXWidget slf, void *_cmd)
848 {
849     return m_isFlipped;
850 }
851
852
853 #define OSX_DEBUG_DRAWING 0
854
855 void wxWidgetCocoaImpl::drawRect(void* rect, WXWidget slf, void *_cmd)
856 {
857     CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
858     CGContextSaveGState( context );
859     
860 #if OSX_DEBUG_DRAWING
861     CGContextBeginPath( context );
862     CGContextMoveToPoint(context, 0, 0);
863     NSRect bounds = [self bounds];
864     CGContextAddLineToPoint(context, 10, 0);
865     CGContextMoveToPoint(context, 0, 0);
866     CGContextAddLineToPoint(context, 0, 10);
867     CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
868     CGContextAddLineToPoint(context, bounds.size.width, bounds.size.height-10);
869     CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
870     CGContextAddLineToPoint(context, bounds.size.width-10, bounds.size.height);
871     CGContextClosePath( context );
872     CGContextStrokePath(context);
873 #endif
874
875     if ( !m_isFlipped )
876     {
877         CGContextTranslateCTM( context, 0,  [m_osxView bounds].size.height );
878         CGContextScaleCTM( context, 1, -1 );
879     }
880     
881     wxRegion updateRgn;
882     const NSRect *rects;
883     NSInteger count;
884
885     [slf getRectsBeingDrawn:&rects count:&count];
886     for ( int i = 0 ; i < count ; ++i )
887     {
888         updateRgn.Union(wxFromNSRect(slf, rects[i]) );
889     }
890
891     wxWindow* wxpeer = GetWXPeer();
892     wxpeer->GetUpdateRegion() = updateRgn;
893     wxpeer->MacSetCGContextRef( context );
894     
895     bool handled = wxpeer->MacDoRedraw( 0 );
896             
897     CGContextRestoreGState( context );
898
899     CGContextSaveGState( context );
900     if ( !handled )
901     {
902         // call super
903         SEL _cmd = @selector(drawRect:);
904         wxOSX_DrawRectHandlerPtr superimpl = (wxOSX_DrawRectHandlerPtr) [[slf superclass] instanceMethodForSelector:_cmd];
905         superimpl(slf, _cmd, *(NSRect*)rect);
906         CGContextRestoreGState( context );
907         CGContextSaveGState( context );
908     }
909     wxpeer->MacPaintChildrenBorders();
910     wxpeer->MacSetCGContextRef( NULL );
911     CGContextRestoreGState( context );
912 }
913
914 void wxWidgetCocoaImpl::controlAction( WXWidget slf, void *_cmd, void *sender)
915 {
916     wxWindow* wxpeer = (wxWindow*) GetWXPeer();
917     if ( wxpeer )
918         wxpeer->OSXHandleClicked(0);
919 }
920
921 void wxWidgetCocoaImpl::controlDoubleAction( WXWidget slf, void *_cmd, void *sender)
922 {
923 }
924
925 // 
926
927 #if OBJC_API_VERSION >= 2
928
929 #define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
930     class_addMethod(c, s, i, t );
931
932 #else
933
934 #define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
935     { s, t, i },
936
937 #endif
938
939 void wxOSXCocoaClassAddWXMethods(Class c)
940 {
941
942 #if OBJC_API_VERSION < 2
943     static objc_method wxmethods[] =
944     {
945 #endif
946
947     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
948     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
949     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
950
951     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
952     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
953     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
954
955     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseMoved:), (IMP) wxOSX_mouseEvent, "v@:@" )
956
957     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
958     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
959     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
960
961     wxOSX_CLASS_ADD_METHOD(c, @selector(scrollWheel:), (IMP) wxOSX_mouseEvent, "v@:@" )
962     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (IMP) wxOSX_mouseEvent, "v@:@" )
963     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseExited:), (IMP) wxOSX_mouseEvent, "v@:@" )
964     
965     wxOSX_CLASS_ADD_METHOD(c, @selector(keyDown:), (IMP) wxOSX_keyEvent, "v@:@" )
966     wxOSX_CLASS_ADD_METHOD(c, @selector(keyUp:), (IMP) wxOSX_keyEvent, "v@:@" )
967     wxOSX_CLASS_ADD_METHOD(c, @selector(flagsChanged:), (IMP) wxOSX_keyEvent, "v@:@" )
968     
969     wxOSX_CLASS_ADD_METHOD(c, @selector(insertText:), (IMP) wxOSX_insertText, "v@:@" )
970
971     wxOSX_CLASS_ADD_METHOD(c, @selector(performKeyEquivalent:), (IMP) wxOSX_performKeyEquivalent, "v@:@" )
972
973     wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstResponder), (IMP) wxOSX_acceptsFirstResponder, "c@:" )
974     wxOSX_CLASS_ADD_METHOD(c, @selector(becomeFirstResponder), (IMP) wxOSX_becomeFirstResponder, "c@:" )
975     wxOSX_CLASS_ADD_METHOD(c, @selector(resignFirstResponder), (IMP) wxOSX_resignFirstResponder, "c@:" )
976     wxOSX_CLASS_ADD_METHOD(c, @selector(resetCursorRects), (IMP) wxOSX_resetCursorRects, "v@:" )
977
978     wxOSX_CLASS_ADD_METHOD(c, @selector(isFlipped), (IMP) wxOSX_isFlipped, "c@:" )
979     wxOSX_CLASS_ADD_METHOD(c, @selector(drawRect:), (IMP) wxOSX_drawRect, "v@:{_NSRect={_NSPoint=ff}{_NSSize=ff}}" )
980
981     wxOSX_CLASS_ADD_METHOD(c, @selector(controlAction:), (IMP) wxOSX_controlAction, "v@:@" )
982     wxOSX_CLASS_ADD_METHOD(c, @selector(controlDoubleAction:), (IMP) wxOSX_controlDoubleAction, "v@:@" )
983
984 #if wxUSE_DRAG_AND_DROP
985     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingEntered:), (IMP) wxOSX_draggingEntered, "I@:@" )
986     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingUpdated:), (IMP) wxOSX_draggingUpdated, "I@:@" )
987     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingExited:), (IMP) wxOSX_draggingExited, "v@:@" )
988     wxOSX_CLASS_ADD_METHOD(c, @selector(performDragOperation:), (IMP) wxOSX_performDragOperation, "c@:@" )
989 #endif     
990         
991 #if OBJC_API_VERSION < 2
992     } ;
993     static int method_count = WXSIZEOF( wxmethods );
994     static objc_method_list *wxmethodlist = NULL;
995     if ( wxmethodlist == NULL )
996     {
997         wxmethodlist = (objc_method_list*) malloc(sizeof(objc_method_list) + sizeof(wxmethods) );
998         memcpy( &wxmethodlist->method_list[0], &wxmethods[0], sizeof(wxmethods) );
999         wxmethodlist->method_count = method_count;
1000         wxmethodlist->obsolete = 0;
1001     }
1002     class_addMethods( c, wxmethodlist );
1003 #endif
1004 }
1005
1006 //
1007 // C++ implementation class
1008 //
1009
1010 IMPLEMENT_DYNAMIC_CLASS( wxWidgetCocoaImpl , wxWidgetImpl )
1011
1012 wxWidgetCocoaImpl::wxWidgetCocoaImpl( wxWindowMac* peer , WXWidget w, bool isRootControl ) :
1013     wxWidgetImpl( peer, isRootControl )
1014 {
1015     Init();
1016     m_osxView = w;
1017 }
1018
1019 wxWidgetCocoaImpl::wxWidgetCocoaImpl() 
1020 {
1021     Init();
1022 }
1023
1024 void wxWidgetCocoaImpl::Init()
1025 {
1026     m_osxView = NULL;
1027     m_isFlipped = true;
1028     m_lastKeyDownEvent = NULL;
1029 }
1030
1031 wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
1032 {
1033     RemoveAssociations( this );
1034
1035     if ( !IsRootControl() )
1036     {
1037         NSView *sv = [m_osxView superview];
1038         if ( sv != nil )
1039             [m_osxView removeFromSuperview];
1040     }
1041     [m_osxView release];
1042 }
1043     
1044 bool wxWidgetCocoaImpl::IsVisible() const 
1045 {
1046     return [m_osxView isHiddenOrHasHiddenAncestor] == NO;
1047 }
1048
1049 void wxWidgetCocoaImpl::SetVisibility( bool visible )
1050 {
1051     [m_osxView setHidden:(visible ? NO:YES)];
1052 }
1053
1054 void wxWidgetCocoaImpl::Raise()
1055 {
1056 }
1057     
1058 void wxWidgetCocoaImpl::Lower()
1059 {
1060 }
1061
1062 void wxWidgetCocoaImpl::ScrollRect( const wxRect *rect, int dx, int dy )
1063 {
1064 #if 1
1065     SetNeedsDisplay() ;
1066 #else
1067     // We should do something like this, but it wasn't working in 10.4.
1068     if (GetNeedsDisplay() )
1069     {
1070         SetNeedsDisplay() ;
1071     }
1072     NSRect r = wxToNSRect( [m_osxView superview], *rect );
1073     NSSize offset = NSMakeSize((float)dx, (float)dy);
1074     [m_osxView scrollRect:r by:offset];
1075 #endif
1076 }
1077
1078 void wxWidgetCocoaImpl::Move(int x, int y, int width, int height)
1079 {
1080     wxWindowMac* parent = GetWXPeer()->GetParent();
1081     // under Cocoa we might have a contentView in the wxParent to which we have to 
1082     // adjust the coordinates
1083     if (parent)
1084     {
1085         int cx = 0,cy = 0,cw = 0,ch = 0;
1086         if ( parent->GetPeer() )
1087         {
1088             parent->GetPeer()->GetContentArea(cx, cy, cw, ch);
1089             x -= cx;
1090             y -= cy;
1091         }
1092     }
1093     [[m_osxView superview] setNeedsDisplayInRect:[m_osxView frame]];
1094     NSRect r = wxToNSRect( [m_osxView superview], wxRect(x,y,width, height) );
1095     [m_osxView setFrame:r];
1096     [[m_osxView superview] setNeedsDisplayInRect:r]; 
1097     
1098     if ([m_osxView respondsToSelector:@selector(trackingTag)] )
1099     {
1100         if ( [(wxNSView*)m_osxView trackingTag] )
1101             [m_osxView removeTrackingRect: [(wxNSView*)m_osxView trackingTag]];
1102         
1103         [(wxNSView*)m_osxView setTrackingTag: [m_osxView addTrackingRect: [m_osxView bounds] owner: m_osxView userData: nil assumeInside: NO]];
1104     }
1105 }
1106
1107 void wxWidgetCocoaImpl::GetPosition( int &x, int &y ) const
1108 {
1109     wxRect r = wxFromNSRect( [m_osxView superview], [m_osxView frame] );
1110     x = r.GetLeft();
1111     y = r.GetTop();
1112 }
1113
1114 void wxWidgetCocoaImpl::GetSize( int &width, int &height ) const
1115 {
1116     NSRect rect = [m_osxView frame];
1117     width = rect.size.width;
1118     height = rect.size.height;
1119 }
1120
1121 void wxWidgetCocoaImpl::GetContentArea( int&left, int &top, int &width, int &height ) const
1122 {
1123     if ( [m_osxView respondsToSelector:@selector(contentView) ] )
1124     {
1125         NSView* cv = [m_osxView contentView];
1126      
1127         NSRect bounds = [m_osxView bounds];
1128         NSRect rect = [cv frame];
1129         
1130         int y = rect.origin.y;
1131         int x = rect.origin.x;
1132         if ( ![ m_osxView isFlipped ] )
1133             y = bounds.size.height - (rect.origin.y + rect.size.height);
1134         left = x;
1135         top = y;
1136         width = rect.size.width;
1137         height = rect.size.height;
1138     }
1139     else
1140     {
1141         left = top = 0;
1142         GetSize( width, height );
1143     }
1144 }
1145
1146 void wxWidgetCocoaImpl::SetNeedsDisplay( const wxRect* where )
1147 {
1148     if ( where )
1149         [m_osxView setNeedsDisplayInRect:wxToNSRect(m_osxView, *where )];
1150     else
1151         [m_osxView setNeedsDisplay:YES];
1152 }
1153
1154 bool wxWidgetCocoaImpl::GetNeedsDisplay() const
1155 {
1156     return [m_osxView needsDisplay];
1157 }
1158
1159 bool wxWidgetCocoaImpl::CanFocus() const
1160 {
1161     return [m_osxView canBecomeKeyView] == YES;
1162 }
1163
1164 bool wxWidgetCocoaImpl::HasFocus() const
1165 {
1166     return ( [[m_osxView window] firstResponder] == m_osxView );
1167 }
1168
1169 bool wxWidgetCocoaImpl::SetFocus() 
1170 {
1171     if ( [m_osxView canBecomeKeyView] == NO )
1172         return false;
1173         
1174     [[m_osxView window] makeFirstResponder: m_osxView] ;
1175     return true;
1176 }
1177
1178
1179 void wxWidgetCocoaImpl::RemoveFromParent()
1180 {
1181     [m_osxView removeFromSuperview];
1182 }
1183
1184 void wxWidgetCocoaImpl::Embed( wxWidgetImpl *parent )
1185 {
1186     NSView* container = parent->GetWXWidget() ;
1187     wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
1188     [container addSubview:m_osxView];
1189 }
1190
1191 void wxWidgetCocoaImpl::SetBackgroundColour( const wxColour &WXUNUSED(col) )
1192 {
1193     // m_osxView.backgroundColor = [[UIColor alloc] initWithCGColor:col.GetCGColor()];
1194 }
1195
1196 void wxWidgetCocoaImpl::SetLabel( const wxString& title, wxFontEncoding encoding )
1197 {
1198     if ( [m_osxView respondsToSelector:@selector(setTitle:) ] )
1199     {
1200         wxCFStringRef cf( title , m_wxPeer->GetFont().GetEncoding() );
1201         [m_osxView setTitle:cf.AsNSString()];
1202     }
1203     else if ( [m_osxView respondsToSelector:@selector(setStringValue:) ] )
1204     {
1205         wxCFStringRef cf( title , m_wxPeer->GetFont().GetEncoding() );
1206         [m_osxView setStringValue:cf.AsNSString()];
1207     }
1208 }
1209     
1210
1211 void  wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
1212 {
1213     NSPoint p = wxToNSPoint( from->GetWXWidget(), *pt );
1214     p = [from->GetWXWidget() convertPoint:p toView:to->GetWXWidget() ]; 
1215     *pt = wxFromNSPoint( to->GetWXWidget(), p );
1216 }
1217
1218 wxInt32 wxWidgetCocoaImpl::GetValue() const 
1219 {
1220     return [(NSControl*)m_osxView intValue];
1221 }
1222
1223 void wxWidgetCocoaImpl::SetValue( wxInt32 v ) 
1224 {
1225     if (  [m_osxView respondsToSelector:@selector(setIntValue:)] )
1226     {
1227         [m_osxView setIntValue:v];
1228     }
1229     else if (  [m_osxView respondsToSelector:@selector(setFloatValue:)] )
1230     {
1231         [m_osxView setFloatValue:(double)v];
1232     }
1233     else if (  [m_osxView respondsToSelector:@selector(setDoubleValue:)] )
1234     {
1235         [m_osxView setDoubleValue:(double)v];
1236     }
1237 }
1238
1239 void wxWidgetCocoaImpl::SetMinimum( wxInt32 v ) 
1240 {
1241     if (  [m_osxView respondsToSelector:@selector(setMinValue:)] )
1242     {
1243         [m_osxView setMinValue:(double)v];
1244     }
1245 }
1246
1247 void wxWidgetCocoaImpl::SetMaximum( wxInt32 v ) 
1248 {
1249     if (  [m_osxView respondsToSelector:@selector(setMaxValue:)] )
1250     {
1251         [m_osxView setMaxValue:(double)v];
1252     }
1253 }
1254
1255 wxInt32 wxWidgetCocoaImpl::GetMinimum() const 
1256 {
1257     if (  [m_osxView respondsToSelector:@selector(getMinValue:)] )
1258     {
1259         return [m_osxView minValue];
1260     }
1261     return 0;
1262 }
1263
1264 wxInt32 wxWidgetCocoaImpl::GetMaximum() const 
1265 {
1266     if (  [m_osxView respondsToSelector:@selector(getMaxValue:)] )
1267     {
1268         return [m_osxView maxValue];
1269     }
1270     return 0;
1271 }
1272
1273 void wxWidgetCocoaImpl::SetBitmap( const wxBitmap& bitmap )
1274 {
1275     if (  [m_osxView respondsToSelector:@selector(setImage:)] )
1276     {
1277         [m_osxView setImage:bitmap.GetNSImage()];
1278     }
1279 }
1280
1281 void wxWidgetCocoaImpl::SetupTabs( const wxNotebook& notebook)
1282 {
1283     // implementation in subclass
1284 }
1285
1286 void wxWidgetCocoaImpl::GetBestRect( wxRect *r ) const
1287 {
1288     r->x = r->y = r->width = r->height = 0;
1289
1290     if (  [m_osxView respondsToSelector:@selector(sizeToFit)] )
1291     {
1292         NSRect former = [m_osxView frame];
1293         [m_osxView sizeToFit];
1294         NSRect best = [m_osxView frame];
1295         [m_osxView setFrame:former];
1296         r->width = best.size.width;
1297         r->height = best.size.height;
1298     }
1299 }
1300
1301 bool wxWidgetCocoaImpl::IsEnabled() const
1302 {
1303     if ( [m_osxView respondsToSelector:@selector(isEnabled) ] )
1304         return [m_osxView isEnabled];
1305     return true;
1306 }
1307
1308 void wxWidgetCocoaImpl::Enable( bool enable )
1309 {
1310     if ( [m_osxView respondsToSelector:@selector(setEnabled:) ] )
1311         [m_osxView setEnabled:enable];
1312 }
1313
1314 void wxWidgetCocoaImpl::PulseGauge()
1315 {
1316 }
1317
1318 void wxWidgetCocoaImpl::SetScrollThumb( wxInt32 val, wxInt32 view )
1319 {
1320 }
1321
1322 void wxWidgetCocoaImpl::SetControlSize( wxWindowVariant variant ) 
1323 {
1324     NSControlSize size = NSRegularControlSize;
1325     
1326     switch ( variant )
1327     {
1328         case wxWINDOW_VARIANT_NORMAL :
1329             size = NSRegularControlSize;
1330             break ;
1331
1332         case wxWINDOW_VARIANT_SMALL :
1333             size = NSSmallControlSize;
1334             break ;
1335
1336         case wxWINDOW_VARIANT_MINI :
1337             size = NSMiniControlSize;
1338             break ;
1339
1340         case wxWINDOW_VARIANT_LARGE :
1341             size = NSRegularControlSize;
1342             break ;
1343
1344         default:
1345             wxFAIL_MSG(_T("unexpected window variant"));
1346             break ;
1347     }
1348     if ( [m_osxView respondsToSelector:@selector(setControlSize:)] )
1349         [m_osxView setControlSize:size];
1350 }
1351
1352 void wxWidgetCocoaImpl::SetFont(wxFont const& font, wxColour const&, long, bool)
1353 {
1354     if ([m_osxView respondsToSelector:@selector(setFont:)])
1355         [m_osxView setFont: font.GetNSFont()];
1356 }
1357
1358 void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control )
1359 {
1360     WXWidget c =  control ? control : (WXWidget) m_osxView;
1361     wxWidgetImpl::Associate( c, this ) ;
1362     if ([c respondsToSelector:@selector(setAction:)])
1363     {
1364         [c setTarget: c];
1365         [c setAction: @selector(controlAction:)];
1366         if ([c respondsToSelector:@selector(setDoubleAction:)])
1367         {
1368             [c setDoubleAction: @selector(controlDoubleAction:)];
1369         }
1370         
1371     }
1372 }
1373
1374 bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text)
1375 {
1376     wxKeyEvent wxevent(wxEVT_KEY_DOWN);
1377     SetupKeyEvent( wxevent, event, text );
1378     wxevent.SetEventObject(GetWXPeer());  
1379
1380     return GetWXPeer()->OSXHandleKeyEvent(wxevent);
1381 }
1382
1383 bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event)
1384 {
1385     wxKeyEvent wxevent(wxEVT_KEY_DOWN);
1386     SetupKeyEvent( wxevent, event );
1387     wxevent.SetEventObject(GetWXPeer());    
1388     bool result = GetWXPeer()->OSXHandleKeyEvent(wxevent);
1389
1390     // this will fire higher level events, like insertText, to help
1391     // us handle EVT_CHAR, etc.
1392     if ([event type] == NSKeyDown)
1393     {
1394         m_lastKeyDownEvent = event;
1395         [m_osxView interpretKeyEvents:[NSArray arrayWithObject:event]];
1396     }
1397     return result;
1398 }
1399
1400 bool wxWidgetCocoaImpl::DoHandleMouseEvent(NSEvent *event)
1401 {
1402     NSPoint clickLocation; 
1403     clickLocation = [m_osxView convertPoint:[event locationInWindow] fromView:nil]; 
1404     wxPoint pt = wxFromNSPoint( m_osxView, clickLocation );
1405     wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
1406     SetupMouseEvent( wxevent , event ) ;
1407     wxevent.SetEventObject(GetWXPeer());
1408     wxevent.m_x = pt.x;
1409     wxevent.m_y = pt.y;
1410
1411     return GetWXPeer()->HandleWindowEvent(wxevent);
1412 }
1413
1414 void wxWidgetCocoaImpl::DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* otherWindow)
1415 {
1416     wxWindow* thisWindow = GetWXPeer();
1417     if ( thisWindow->MacGetTopLevelWindow() && NeedsFocusRect() )
1418     {
1419         thisWindow->MacInvalidateBorders();
1420     }
1421
1422     if ( receivedFocus )
1423     {
1424         wxLogTrace(_T("Focus"), _T("focus set(%p)"), static_cast<void*>(thisWindow));
1425         wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
1426         thisWindow->HandleWindowEvent(eventFocus);
1427
1428 #if wxUSE_CARET
1429         if ( thisWindow->GetCaret() )
1430             thisWindow->GetCaret()->OnSetFocus();
1431 #endif
1432
1433         wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
1434         event.SetEventObject(thisWindow);
1435         if (otherWindow)
1436             event.SetWindow(otherWindow->GetWXPeer());
1437         thisWindow->HandleWindowEvent(event) ;
1438     }
1439     else // !receivedFocuss
1440     {
1441 #if wxUSE_CARET
1442         if ( thisWindow->GetCaret() )
1443             thisWindow->GetCaret()->OnKillFocus();
1444 #endif
1445
1446         wxLogTrace(_T("Focus"), _T("focus lost(%p)"), static_cast<void*>(thisWindow));
1447                     
1448         wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
1449         event.SetEventObject(thisWindow);
1450         if (otherWindow)
1451             event.SetWindow(otherWindow->GetWXPeer());
1452         thisWindow->HandleWindowEvent(event) ;
1453     }
1454 }
1455
1456 void wxWidgetCocoaImpl::SetCursor(const wxCursor& cursor)
1457 {
1458     NSPoint location = [NSEvent mouseLocation];
1459     location = [[m_osxView window] convertScreenToBase:location];
1460     NSPoint locationInView = [m_osxView convertPoint:location fromView:nil];
1461
1462     if( NSMouseInRect(locationInView, [m_osxView bounds], YES) )
1463     {
1464         [(NSCursor*)cursor.GetHCURSOR() set];
1465     }
1466     [[m_osxView window] invalidateCursorRectsForView:m_osxView];
1467 }
1468
1469 void wxWidgetCocoaImpl::CaptureMouse()
1470 {
1471     [[m_osxView window] disableCursorRects];
1472 }
1473
1474 void wxWidgetCocoaImpl::ReleaseMouse()
1475 {
1476     [[m_osxView window] enableCursorRects];
1477 }
1478
1479 void wxWidgetCocoaImpl::SetFlipped(bool flipped)
1480 {
1481     m_isFlipped = flipped;
1482 }
1483
1484 //
1485 // Factory methods
1486 //
1487
1488 wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, wxWindowMac* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
1489                             long style, long extraStyle)
1490 {
1491     NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
1492     wxNSView* v = [[wxNSView alloc] initWithFrame:r];
1493
1494     // temporary hook for dnd
1495     [v registerForDraggedTypes:[NSArray arrayWithObjects:
1496         NSStringPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPICTPboardType, NSPDFPboardType, nil]];
1497         
1498     wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( wxpeer, v );
1499     return c;
1500 }
1501
1502 wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now ) 
1503 {
1504     NSWindow* tlw = now->GetWXWindow();
1505     wxNSView* v = [[wxNSView alloc] initWithFrame:[[tlw contentView] frame]];
1506     wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( now, v, true );
1507     c->InstallEventHandler();
1508     [tlw setContentView:v];
1509     return c;
1510 }