#include "wx/wxprec.h"
-#include <Cocoa/Cocoa.h>
+#ifndef WX_PRECOMP
+ #include "wx/nonownedwnd.h"
+ #include "wx/log.h"
+#endif
#ifdef __WXMAC__
#include "wx/osx/private.h"
#endif
-#if wxOSX_USE_COCOA
+#if wxUSE_CARET
+ #include "wx/caret.h"
+#endif
+
+NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
+{
+ int x, y, w, h ;
+
+ window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
+ wxRect bounds(x,y,w,h);
+ NSView* sv = (window->GetParent()->GetHandle() );
+
+ return wxToNSRect( sv, bounds );
+}
@interface wxNSView : NSView
{
- wxWidgetImpl* m_impl;
+ WXCOCOAIMPL_COMMON_MEMBERS
}
- (void)drawRect: (NSRect) rect;
--(void)mouseDown:(NSEvent *)event ;
--(void)rightMouseDown:(NSEvent *)event ;
--(void)otherMouseDown:(NSEvent *)event ;
--(void)mouseUp:(NSEvent *)event ;
--(void)rightMouseUp:(NSEvent *)event ;
--(void)otherMouseUp:(NSEvent *)event ;
--(void)handleMouseEvent:(NSEvent *)event;
+WXCOCOAIMPL_COMMON_INTERFACE
-- (void)setImplementation: (wxWidgetImpl *) theImplementation;
-- (wxWidgetImpl*) implementation;
-- (BOOL) isFlipped;
-- (BOOL) becomeFirstResponder;
-- (BOOL) resignFirstResponder;
+- (BOOL) canBecomeKeyView;
@end // wxNSView
+@interface NSView(PossibleMethods)
+- (void)setImplementation:(wxWidgetCocoaImpl *)theImplementation;
+- (void)setTitle:(NSString *)aString;
+- (void)setStringValue:(NSString *)aString;
+- (void)setIntValue:(int)anInt;
+- (void)setFloatValue:(float)aFloat;
+- (void)setDoubleValue:(double)aDouble;
+
+- (void)setMinValue:(double)aDouble;
+- (void)setMaxValue:(double)aDouble;
+
+- (void)sizeToFit;
+
+- (BOOL)isEnabled;
+- (void)setEnabled:(BOOL)flag;
+
+- (void)setImage:(NSImage *)image;
+- (void)setControlSize:(NSControlSize)size;
+
+- (id)contentView;
+@end
+
+long wxOSXTranslateCocoaKey(unsigned short code, int unichar )
+{
+ long retval = code;
+ switch( unichar )
+ {
+ case NSUpArrowFunctionKey :
+ retval = WXK_UP;
+ break;
+ case NSDownArrowFunctionKey :
+ retval = WXK_DOWN;
+ break;
+ case NSLeftArrowFunctionKey :
+ retval = WXK_LEFT;
+ break;
+ case NSRightArrowFunctionKey :
+ retval = WXK_RIGHT;
+ break;
+ case NSInsertFunctionKey :
+ retval = WXK_INSERT;
+ break;
+ case NSDeleteFunctionKey :
+ retval = WXK_DELETE;
+ break;
+ case NSHomeFunctionKey :
+ retval = WXK_HOME;
+ break;
+// case NSBeginFunctionKey :
+// retval = WXK_BEGIN;
+// break;
+ case NSEndFunctionKey :
+ retval = WXK_END;
+ break;
+ case NSPageUpFunctionKey :
+ retval = WXK_PAGEUP;
+ break;
+ case NSPageDownFunctionKey :
+ retval = WXK_PAGEDOWN;
+ break;
+ case NSHelpFunctionKey :
+ retval = WXK_HELP;
+ break;
+
+ default :
+ if ( unichar >= NSF1FunctionKey && unichar >= NSF24FunctionKey )
+ retval = WXK_F1 + (unichar - NSF1FunctionKey );
+ break;
+ }
+ return retval;
+}
+
+void SetupKeyEvent( wxKeyEvent &wxevent , NSEvent * nsEvent )
+{
+ UInt32 modifiers = [nsEvent modifierFlags] ;
+ int eventType = [nsEvent type];
+
+ wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
+ wxevent.m_controlDown = modifiers & NSControlKeyMask;
+ wxevent.m_altDown = modifiers & NSAlternateKeyMask;
+ wxevent.m_metaDown = modifiers & NSCommandKeyMask;
+
+ wxString chars;
+ if ( eventType != NSFlagsChanged )
+ {
+ NSString* nschars = [nsEvent characters];
+ if ( nschars )
+ {
+ wxCFStringRef cfchars((CFStringRef)[nschars retain]);
+ chars = cfchars.AsString();
+ }
+ }
+
+ int unichar = chars.Length() > 0 ? chars[0] : 0;
+
+#if wxUSE_UNICODE
+ wxevent.m_uniChar = unichar;
+#endif
+ wxevent.m_keyCode = wxOSXTranslateCocoaKey( [nsEvent keyCode], unichar ) ;
+// wxevent.m_rawCode = keymessage;
+ wxevent.m_rawFlags = modifiers;
+
+ wxevent.SetTimestamp( [nsEvent timestamp] * 1000.0 ) ;
+ switch (eventType)
+ {
+ case NSKeyDown :
+ wxevent.SetEventType( wxEVT_KEY_DOWN ) ;
+ break;
+ case NSKeyUp :
+ wxevent.SetEventType( wxEVT_KEY_UP ) ;
+ break;
+ case NSFlagsChanged :
+ // setup common code here
+ break;
+ default :
+ break ;
+ }
+}
+
void SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
{
UInt32 modifiers = [nsEvent modifierFlags] ;
// these parameters are not given for all events
UInt32 button = [nsEvent buttonNumber];
UInt32 clickCount = [nsEvent clickCount];
- UInt32 mouseChord = 0; // TODO does this exist for cocoa
wxevent.m_x = screenMouseLocation.x;
wxevent.m_y = screenMouseLocation.y;
wxevent.m_altDown = modifiers & NSAlternateKeyMask;
wxevent.m_metaDown = modifiers & NSCommandKeyMask;
wxevent.m_clickCount = clickCount;
- wxevent.SetTimestamp( [nsEvent timestamp] ) ;
+ wxevent.SetTimestamp( [nsEvent timestamp] * 1000.0 ) ;
/*
+ UInt32 mouseChord = 0; // TODO does this exist for cocoa
// a control click is interpreted as a right click
bool thisButtonIsFakeRight = false ;
if ( button == kEventMouseButtonPrimary && (modifiers & controlKey) )
@implementation wxNSView
+#define OSX_DEBUG_DRAWING 0
+
- (void)drawRect: (NSRect) rect
{
- if ( m_impl )
+ if ( impl )
{
CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
CGContextSaveGState( context );
+#if OSX_DEBUG_DRAWING
CGContextBeginPath( context );
CGContextMoveToPoint(context, 0, 0);
NSRect bounds = [self bounds];
CGContextAddLineToPoint(context, bounds.size.width-10, bounds.size.height);
CGContextClosePath( context );
CGContextStrokePath(context);
+#endif
if ( [ self isFlipped ] == NO )
{
CGContextTranslateCTM( context, 0, [self bounds].size.height );
CGContextScaleCTM( context, 1, -1 );
}
- m_impl->GetWXPeer()->MacSetCGContextRef( context );
+
+ wxRegion updateRgn;
+ const NSRect *rects;
+ NSInteger count;
+
+ [self getRectsBeingDrawn:&rects count:&count];
+ for ( int i = 0 ; i < count ; ++i )
+ {
+ updateRgn.Union(wxFromNSRect(self, rects[i]) );
+ }
+ wxWindow* wxpeer = impl->GetWXPeer();
+ wxpeer->GetUpdateRegion() = updateRgn;
+ wxpeer->MacSetCGContextRef( context );
+
wxPaintEvent event;
event.SetTimestamp(0); // todo
- event.SetEventObject(m_impl->GetWXPeer());
- m_impl->GetWXPeer()->HandleWindowEvent(event);
-
+ event.SetEventObject(wxpeer);
+ wxpeer->HandleWindowEvent(event);
+
CGContextRestoreGState( context );
}
}
--(void)mouseDown:(NSEvent *)event
-{
- [self handleMouseEvent:event];
-}
-
--(void)rightMouseDown:(NSEvent *)event
-{
- [self handleMouseEvent:event];
-}
-
--(void)otherMouseDown:(NSEvent *)event
-{
- [self handleMouseEvent:event];
-}
-
--(void)mouseUp:(NSEvent *)event
-{
- [self handleMouseEvent:event];
-}
-
--(void)rightMouseUp:(NSEvent *)event
-{
- [self handleMouseEvent:event];
-}
-
--(void)otherMouseUp:(NSEvent *)event
-{
- [self handleMouseEvent:event];
-}
-
--(void)handleMouseEvent:(NSEvent *)event
-{
- NSPoint clickLocation;
- clickLocation = [self convertPoint:[event locationInWindow] fromView:nil];
- wxPoint pt = wxFromNSPoint( self, clickLocation );
- wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
- SetupMouseEvent( wxevent , event ) ;
- wxevent.m_x = pt.x;
- wxevent.m_y = pt.y;
- m_impl->GetWXPeer()->HandleWindowEvent(wxevent);
-}
-
-- (void)setImplementation: (wxWidgetImpl *) theImplementation
-{
- m_impl = theImplementation;
-}
+WXCOCOAIMPL_COMMON_IMPLEMENTATION
-- (wxWidgetImpl*) implementation
-{
- return m_impl;
-}
-
-- (BOOL) isFlipped
+- (BOOL) canBecomeKeyView
{
return YES;
}
-- (BOOL) becomeFirstResponder
-{
- BOOL r = [super becomeFirstResponder];
- if ( r )
- {
- }
- return r;
-}
-
-- (BOOL) resignFirstResponder
-{
- BOOL r = [super resignFirstResponder];
- if ( r )
- {
- }
- return r;
-}
-
-
@end // wxNSView
IMPLEMENT_DYNAMIC_CLASS( wxWidgetCocoaImpl , wxWidgetImpl )
wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
{
- [m_osxView setImplementation:NULL];
+ if ( [m_osxView respondsToSelector:@selector(setImplementation:) ] )
+ [m_osxView setImplementation:NULL];
+ if ( !IsRootControl() )
+ {
+ NSView *sv = [m_osxView superview];
+ if ( sv != nil )
+ [m_osxView removeFromSuperview];
+ }
[m_osxView release];
}
return [m_osxView isHiddenOrHasHiddenAncestor] == NO;
}
+void wxWidgetCocoaImpl::SetVisibility( bool visible )
+{
+ [m_osxView setHidden:(visible ? NO:YES)];
+}
+
void wxWidgetCocoaImpl::Raise()
{
}
void wxWidgetCocoaImpl::Move(int x, int y, int width, int height)
{
+ wxWindowMac* parent = GetWXPeer()->GetParent();
+ // under Cocoa we might have a contentView in the wxParent to which we have to
+ // adjust the coordinates
+ if (parent)
+ {
+ wxPoint pt(parent->GetClientAreaOrigin());
+ x -= pt.x;
+ y -= pt.y;
+ }
NSRect r = wxToNSRect( [m_osxView superview], wxRect(x,y,width, height) );
[m_osxView setFrame:r];
}
height = rect.size.height;
}
-void wxWidgetCocoaImpl::GetContentArea( int&left, int &top, int &width, int &height )
+void wxWidgetCocoaImpl::GetContentArea( int&left, int &top, int &width, int &height ) const
{
- left = top = 0;
- GetSize( width, height );
+ if ( [m_osxView respondsToSelector:@selector(contentView) ] )
+ {
+ NSView* cv = [m_osxView contentView];
+
+ NSRect bounds = [m_osxView bounds];
+ NSRect rect = [cv frame];
+
+ int y = rect.origin.y;
+ int x = rect.origin.x;
+ if ( ![ m_osxView isFlipped ] )
+ y = bounds.size.height - (rect.origin.y + rect.size.height);
+ left = x;
+ top = y;
+ width = rect.size.width;
+ height = rect.size.height;
+ }
+ else
+ {
+ left = top = 0;
+ GetSize( width, height );
+ }
}
void wxWidgetCocoaImpl::SetNeedsDisplay( const wxRect* where )
return [m_osxView needsDisplay];
}
-void wxWidgetCocoaImpl::CanFocus() const
+bool wxWidgetCocoaImpl::CanFocus() const
{
- return [m_osxView acceptsFirstResponder] == YES;
+ return [m_osxView canBecomeKeyView] == YES;
}
bool wxWidgetCocoaImpl::HasFocus() const
{
- return [m_osxView isFirstResponder] == YES;
+ return ( [[m_osxView window] firstResponder] == m_osxView );
}
bool wxWidgetCocoaImpl::SetFocus()
{
- [m_osxView makeKeyWindow] ;
+ if ( [m_osxView canBecomeKeyView] == NO )
+ return false;
+
+ [[m_osxView window] makeFirstResponder: m_osxView] ;
+ return true;
}
[container addSubview:m_osxView];
}
+void wxWidgetCocoaImpl::SetBackgroundColour( const wxColour &WXUNUSED(col) )
+{
+ // m_osxView.backgroundColor = [[UIColor alloc] initWithCGColor:col.GetCGColor()];
+}
+
+void wxWidgetCocoaImpl::SetLabel( const wxString& title, wxFontEncoding encoding )
+{
+ if ( [m_osxView respondsToSelector:@selector(setTitle:) ] )
+ {
+ wxCFStringRef cf( title , m_wxPeer->GetFont().GetEncoding() );
+ [m_osxView setTitle:cf.AsNSString()];
+ }
+}
+
+
+void wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
+{
+ NSPoint p = wxToNSPoint( from->GetWXWidget(), *pt );
+ p = [from->GetWXWidget() convertPoint:p toView:to->GetWXWidget() ];
+ *pt = wxFromNSPoint( to->GetWXWidget(), p );
+}
+
+wxInt32 wxWidgetCocoaImpl::GetValue() const
+{
+ return [(NSControl*)m_osxView intValue];
+}
+
+void wxWidgetCocoaImpl::SetValue( wxInt32 v )
+{
+ if ( [m_osxView respondsToSelector:@selector(setIntValue:)] )
+ {
+ [m_osxView setIntValue:v];
+ }
+ else if ( [m_osxView respondsToSelector:@selector(setFloatValue:)] )
+ {
+ [m_osxView setFloatValue:(double)v];
+ }
+ else if ( [m_osxView respondsToSelector:@selector(setDoubleValue:)] )
+ {
+ [m_osxView setDoubleValue:(double)v];
+ }
+}
+
+void wxWidgetCocoaImpl::SetMinimum( wxInt32 v )
+{
+ if ( [m_osxView respondsToSelector:@selector(setMinValue:)] )
+ {
+ [m_osxView setMinValue:(double)v];
+ }
+}
+
+void wxWidgetCocoaImpl::SetMaximum( wxInt32 v )
+{
+ if ( [m_osxView respondsToSelector:@selector(setMaxValue:)] )
+ {
+ [m_osxView setMaxValue:(double)v];
+ }
+}
+
+void wxWidgetCocoaImpl::SetBitmap( const wxBitmap& bitmap )
+{
+ if ( [m_osxView respondsToSelector:@selector(setImage:)] )
+ {
+ [m_osxView setImage:bitmap.GetNSImage()];
+ }
+}
+
+void wxWidgetCocoaImpl::SetupTabs( const wxNotebook& notebook)
+{
+ // implementation in subclass
+}
+
+void wxWidgetCocoaImpl::GetBestRect( wxRect *r ) const
+{
+ r->x = r->y = r->width = r->height = 0;
+// if ( [m_osxView isKindOfClass:[NSControl class]] )
+ if ( [m_osxView respondsToSelector:@selector(sizeToFit)] )
+ {
+ NSRect former = [m_osxView frame];
+ [m_osxView sizeToFit];
+ NSRect best = [m_osxView frame];
+ [m_osxView setFrame:former];
+ r->width = best.size.width;
+ r->height = best.size.height;
+ }
+}
+
+bool wxWidgetCocoaImpl::IsEnabled() const
+{
+ if ( [m_osxView respondsToSelector:@selector(isEnabled) ] )
+ return [m_osxView isEnabled];
+ return true;
+}
+
+void wxWidgetCocoaImpl::Enable( bool enable )
+{
+ if ( [m_osxView respondsToSelector:@selector(setEnabled:) ] )
+ [m_osxView setEnabled:enable];
+}
+
+void wxWidgetCocoaImpl::PulseGauge()
+{
+}
+
+void wxWidgetCocoaImpl::SetScrollThumb( wxInt32 val, wxInt32 view )
+{
+}
+
+void wxWidgetCocoaImpl::SetControlSize( wxWindowVariant variant )
+{
+ NSControlSize size = NSRegularControlSize;
+
+ switch ( variant )
+ {
+ case wxWINDOW_VARIANT_NORMAL :
+ size = NSRegularControlSize;
+ break ;
+
+ case wxWINDOW_VARIANT_SMALL :
+ size = NSSmallControlSize;
+ break ;
+
+ case wxWINDOW_VARIANT_MINI :
+ size = NSMiniControlSize;
+ break ;
+
+ case wxWINDOW_VARIANT_LARGE :
+ size = NSRegularControlSize;
+ break ;
+
+ default:
+ wxFAIL_MSG(_T("unexpected window variant"));
+ break ;
+ }
+ if ( [m_osxView respondsToSelector:@selector(setControlSize:)] )
+ [m_osxView setControlSize:size];
+}
+
+void wxWidgetCocoaImpl::SetFont(wxFont const&, wxColour const&, long, bool)
+{
+ // TODO
+}
+
+void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control )
+{
+}
+
+bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event)
+{
+ wxKeyEvent wxevent(wxEVT_KEY_DOWN);
+ SetupKeyEvent( wxevent, event );
+ return GetWXPeer()->HandleWindowEvent(wxevent);
+}
+
+bool wxWidgetCocoaImpl::DoHandleMouseEvent(NSEvent *event)
+{
+ NSPoint clickLocation;
+ clickLocation = [m_osxView convertPoint:[event locationInWindow] fromView:nil];
+ wxPoint pt = wxFromNSPoint( m_osxView, clickLocation );
+ wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
+ SetupMouseEvent( wxevent , event ) ;
+ wxevent.m_x = pt.x;
+ wxevent.m_y = pt.y;
+
+ return GetWXPeer()->HandleWindowEvent(wxevent);
+}
+
+void wxWidgetCocoaImpl::DoNotifyFocusEvent(bool receivedFocus)
+{
+ wxWindow* thisWindow = GetWXPeer();
+ if ( thisWindow->MacGetTopLevelWindow() && NeedsFocusRect() )
+ {
+ thisWindow->MacInvalidateBorders();
+ }
+
+ if ( receivedFocus )
+ {
+ wxLogTrace(_T("Focus"), _T("focus set(%p)"), static_cast<void*>(thisWindow));
+ wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
+ thisWindow->HandleWindowEvent(eventFocus);
+
+#if wxUSE_CARET
+ if ( thisWindow->GetCaret() )
+ thisWindow->GetCaret()->OnSetFocus();
+#endif
+
+ wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
+ event.SetEventObject(thisWindow);
+ // TODO how to find out the targetFocusWindow ?
+ // event.SetWindow(targetFocusWindow);
+ thisWindow->HandleWindowEvent(event) ;
+ }
+ else // !receivedFocuss
+ {
+#if wxUSE_CARET
+ if ( thisWindow->GetCaret() )
+ thisWindow->GetCaret()->OnKillFocus();
+#endif
+
+ wxLogTrace(_T("Focus"), _T("focus lost(%p)"), static_cast<void*>(thisWindow));
+
+ wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
+ event.SetEventObject(thisWindow);
+ // TODO how to find out the targetFocusWindow ?
+ // event.SetWindow(targetFocusWindow);
+ thisWindow->HandleWindowEvent(event) ;
+ }
+}
+
//
// Factory methods
//
-wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, const wxPoint& pos, const wxSize& size,
- long style, long extraStyle, const wxString& name)
+wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, wxWindowMac* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
+ long style, long extraStyle)
{
NSView* sv = (wxpeer->GetParent()->GetHandle() );
- NSRect r = wxToNSRect( sv, wxRect( pos, size) );
- // Rect bounds = wxMacGetBoundsForControl( wxpeer, pos , size ) ;
+ NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
wxNSView* v = [[wxNSView alloc] initWithFrame:r];
[sv addSubview:v];
wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( wxpeer, v );
[tlw setContentView:v];
return c;
}
-
-
-#endif