X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c16b215350e25bf65a36323d5ba0d9ecdeffa03c..ae0e22dd7af3fa44819a08c21c9b478688e9d172:/src/osx/iphone/window.mm?ds=sidebyside diff --git a/src/osx/iphone/window.mm b/src/osx/iphone/window.mm index c5a78eb7c7..15e4029b84 100644 --- a/src/osx/iphone/window.mm +++ b/src/osx/iphone/window.mm @@ -13,15 +13,58 @@ #include "wx/osx/private.h" -#include "wx/event.h" -#include "wx/nonownedwnd.h" -#include "wx/frame.h" +#ifndef WX_PRECOMP + #include "wx/nonownedwnd.h" + #include "wx/frame.h" + #include "wx/event.h" + #include "wx/log.h" +#endif + +#include + +WXWidget wxWidgetImpl::FindFocus() +{ + UIView* focusedView = nil; + UIWindow* keyWindow = [[UIApplication sharedApplication] keyWindow]; + if ( keyWindow != nil ) + { + /* + NSResponder* responder = [keyWindow firstResponder]; + if ( [responder isKindOfClass:[NSTextView class]] && + [keyWindow fieldEditor:NO forObject:nil] != nil ) + { + focusedView = [(NSTextView*)responder delegate]; + } + else + { + if ( [responder isKindOfClass:[NSView class]] ) + focusedView = (NSView*) responder; + } + */ + } + return focusedView; +} + +CGRect 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); + UIView* sv = (window->GetParent()->GetHandle() ); + + return wxToNSRect( sv, bounds ); +} @interface wxUIView : UIView { - wxWidgetImpl* m_impl; } +@end // wxUIView + +@interface wxUIView(PossibleMethods) +- (void)setTitle:(NSString *)title forState:(UIControlState)state; + - (void)drawRect: (CGRect) rect; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; @@ -29,13 +72,9 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; - (void)handleTouchEvent:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)setImplementation: (wxWidgetImpl *) theImplementation; -- (wxWidgetImpl*) implementation; -- (BOOL) isFlipped; - (BOOL) becomeFirstResponder; - (BOOL) resignFirstResponder; - -@end // wxUIView +@end @interface wxUIContentView : wxUIView { @@ -59,7 +98,7 @@ void SetupMouseEvent( wxMouseEvent &wxevent , NSSet* touches, UIEvent * nsEvent UITouch *touch = [touches anyObject]; // these parameters are not given for all events - UInt32 button = 0; // no secondary button + UInt32 button = 0; // no secondary button UInt32 clickCount = [touch tapCount]; UInt32 mouseChord = 0; // TODO does this exist for cocoa @@ -154,71 +193,65 @@ void SetupMouseEvent( wxMouseEvent &wxevent , NSSet* touches, UIEvent * nsEvent @implementation wxUIView -- (id) initWithFrame: (CGRect) frame ++ (void)initialize { - if ( self = [super initWithFrame:frame]) + static BOOL initialized = NO; + if (!initialized) { - // additional inits + initialized = YES; + wxOSXIPhoneClassAddWXMethods( self ); } - return self; } -- (void) dealloc -{ - // additional deallocs - [super dealloc]; -} +@end // wxUIView +/* - (void)drawRect: (CGRect) rect { - if ( m_impl ) + wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + if ( impl ) { CGContextRef context = (CGContextRef) UIGraphicsGetCurrentContext(); CGContextSaveGState( context ); // draw background - - CGContextSetFillColorWithColor( context, m_impl->GetWXPeer()->GetBackgroundColour().GetCGColor()); - CGContextFillRect(context, rect ); - if ( [ self isFlipped ] == NO ) - { - CGContextTranslateCTM( context, 0, [self bounds].size.height ); - CGContextScaleCTM( context, 1, -1 ); - } + CGContextSetFillColorWithColor( context, impl->GetWXPeer()->GetBackgroundColour().GetCGColor()); + CGContextFillRect(context, rect ); - m_impl->GetWXPeer()->MacSetCGContextRef( context ); + impl->GetWXPeer()->MacSetCGContextRef( context ); - m_impl->GetWXPeer()->GetUpdateRegion() = + impl->GetWXPeer()->GetUpdateRegion() = wxRegion(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height) ; wxPaintEvent event; event.SetTimestamp(0); // todo - event.SetEventObject(m_impl->GetWXPeer()); - m_impl->GetWXPeer()->HandleWindowEvent(event); + event.SetEventObject(impl->GetWXPeer()); + impl->GetWXPeer()->HandleWindowEvent(event); CGContextRestoreGState( context ); } } -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self handleTouchEvent:touches withEvent:event]; } -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [self handleTouchEvent:touches withEvent:event]; } -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [self handleTouchEvent:touches withEvent:event]; } --(void)handleTouchEvent:(NSSet *)touches withEvent:(UIEvent *)event -{ - CGPoint clickLocation; +-(void)handleTouchEvent:(NSSet *)touches withEvent:(UIEvent *)event +{ + wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + CGPoint clickLocation; UITouch *touch = [touches anyObject]; clickLocation = [touch locationInView:self]; @@ -226,46 +259,59 @@ void SetupMouseEvent( wxMouseEvent &wxevent , NSSet* touches, UIEvent * nsEvent SetupMouseEvent( wxevent , touches, event ) ; wxevent.m_x = clickLocation.x; wxevent.m_y = clickLocation.y; - wxevent.SetEventObject( m_impl->GetWXPeer() ) ; - wxevent.SetId( m_impl->GetWXPeer()->GetId() ) ; - m_impl->GetWXPeer()->HandleWindowEvent(wxevent); + wxevent.SetEventObject( impl->GetWXPeer() ) ; + wxevent.SetId( impl->GetWXPeer()->GetId() ) ; + impl->GetWXPeer()->HandleWindowEvent(wxevent); } -- (void)setImplementation: (wxWidgetImpl *) theImplementation -{ - m_impl = theImplementation; -} +*/ -- (wxWidgetImpl*) implementation +void wxOSX_touchEvent(UIView* self, SEL _cmd, NSSet* touches, UIEvent *event ) { - return m_impl; + wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + if (impl == NULL) + return; + + impl->touchEvent(touches, event, self, _cmd); } -- (BOOL) isFlipped +BOOL wxOSX_becomeFirstResponder(UIView* self, SEL _cmd) { - return YES; + wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + if (impl == NULL) + return NO; + + return impl->becomeFirstResponder(self, _cmd); } -- (BOOL) becomeFirstResponder +BOOL wxOSX_resignFirstResponder(UIView* self, SEL _cmd) { - BOOL r = [super becomeFirstResponder]; - if ( r ) - { - } - return r; + wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + if (impl == NULL) + return NO; + + return impl->resignFirstResponder(self, _cmd); } -- (BOOL) resignFirstResponder +void wxOSX_drawRect(UIView* self, SEL _cmd, CGRect rect) { - BOOL r = [super resignFirstResponder]; - if ( r ) - { - } - return r; + wxWidgetIPhoneImpl* impl = (wxWidgetIPhoneImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + if (impl == NULL) + return; + + return impl->drawRect(&rect, self, _cmd); } -@end // wxUIView +void wxOSXIPhoneClassAddWXMethods(Class c) +{ + class_addMethod(c, @selector(touchesBegan:withEvent:), (IMP) wxOSX_touchEvent, "v@:@@"); + class_addMethod(c, @selector(touchesMoved:withEvent:), (IMP) wxOSX_touchEvent, "v@:@@"); + class_addMethod(c, @selector(touchesEnded:withEvent:), (IMP) wxOSX_touchEvent, "v@:@@"); + class_addMethod(c, @selector(becomeFirstResponder), (IMP) wxOSX_becomeFirstResponder, "c@:" ); + class_addMethod(c, @selector(resignFirstResponder), (IMP) wxOSX_resignFirstResponder, "c@:" ); + class_addMethod(c, @selector(drawRect:), (IMP) wxOSX_drawRect, "v@:{_CGRect={_CGPoint=ff}{_CGSize=ff}}" ); +} @implementation wxUIContentView @@ -298,7 +344,7 @@ wxWidgetIPhoneImpl::wxWidgetIPhoneImpl( wxWindowMac* peer , WXWidget w, bool isR { } -wxWidgetIPhoneImpl::wxWidgetIPhoneImpl() +wxWidgetIPhoneImpl::wxWidgetIPhoneImpl() { } @@ -309,14 +355,25 @@ void wxWidgetIPhoneImpl::Init() wxWidgetIPhoneImpl::~wxWidgetIPhoneImpl() { - [m_osxView setImplementation:NULL]; + RemoveAssociations( this ); + + if ( !IsRootControl() ) + { + UIView *sv = [m_osxView superview]; + if ( sv != nil ) + [m_osxView removeFromSuperview]; + } [m_osxView release]; } - -bool wxWidgetIPhoneImpl::IsVisible() const + +bool wxWidgetIPhoneImpl::IsVisible() const { - // TODO Superviews - return [m_osxView isHidden] == NO; + UIView* view = m_osxView; + while ( view != nil && [view isHidden] == NO ) + { + view = [view superview]; + } + return view == nil; } void wxWidgetIPhoneImpl::SetVisibility( bool visible ) @@ -328,7 +385,7 @@ void wxWidgetIPhoneImpl::Raise() { [[m_osxView superview] bringSubviewToFront:m_osxView]; } - + void wxWidgetIPhoneImpl::Lower() { [[m_osxView superview] sendSubviewToBack:m_osxView]; @@ -336,6 +393,7 @@ void wxWidgetIPhoneImpl::Lower() void wxWidgetIPhoneImpl::ScrollRect( const wxRect *rect, int dx, int dy ) { + SetNeedsDisplay() ; } void wxWidgetIPhoneImpl::Move(int x, int y, int width, int height) @@ -392,7 +450,7 @@ bool wxWidgetIPhoneImpl::HasFocus() const return [m_osxView isFirstResponder] == YES; } -bool wxWidgetIPhoneImpl::SetFocus() +bool wxWidgetIPhoneImpl::SetFocus() { // [m_osxView makeKeyWindow] ; // TODO @@ -415,7 +473,7 @@ void wxWidgetIPhoneImpl::Embed( wxWidgetImpl *parent ) void wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to ) { CGPoint p = CGPointMake( pt->x , pt->y ); - p = [from->GetWXWidget() convertPoint:p toView:to->GetWXWidget() ]; + p = [from->GetWXWidget() convertPoint:p toView:to->GetWXWidget() ]; pt->x = (int)p.x; pt->y = (int)p.y; } @@ -425,29 +483,288 @@ void wxWidgetIPhoneImpl::SetBackgroundColour( const wxColour &col ) // m_osxView.backgroundColor = [[UIColor alloc] initWithCGColor:col.GetCGColor()]; } +void wxWidgetIPhoneImpl::SetLabel(const wxString& title, wxFontEncoding encoding) +{ + if ( [m_osxView respondsToSelector:@selector(setTitle:forState:) ] ) + { + wxCFStringRef cf( title , encoding ); + [m_osxView setTitle:cf.AsNSString() forState:UIControlStateNormal ]; + } + else if ( [m_osxView respondsToSelector:@selector(setStringValue:) ] ) + { + wxCFStringRef cf( title , encoding ); + [m_osxView setStringValue:cf.AsNSString()]; + } +} + + +void wxWidgetIPhoneImpl::SetCursor( const wxCursor & cursor ) +{ +} + +void wxWidgetIPhoneImpl::CaptureMouse() +{ +} + +void wxWidgetIPhoneImpl::ReleaseMouse() +{ +} + +wxInt32 wxWidgetIPhoneImpl::GetValue() const +{ +} + +void wxWidgetIPhoneImpl::SetValue( wxInt32 v ) +{ +} + +void wxWidgetIPhoneImpl::SetBitmap( const wxBitmap& bitmap ) +{ +} + +wxBitmap wxWidgetIPhoneImpl::GetBitmap() const +{ + wxBitmap bmp; + return bmp; +} + +void wxWidgetIPhoneImpl::SetBitmapPosition( wxDirection dir ) +{ +} + +void wxWidgetIPhoneImpl::SetupTabs( const wxNotebook ¬ebook ) +{ +} + +void wxWidgetIPhoneImpl::GetBestRect( wxRect *r ) const +{ + r->x = r->y = r->width = r->height = 0; + + if ( [m_osxView respondsToSelector:@selector(sizeToFit)] ) + { + CGRect former = [m_osxView frame]; + [m_osxView sizeToFit]; + CGRect best = [m_osxView frame]; + [m_osxView setFrame:former]; + r->width = best.size.width; + r->height = best.size.height; + } +} + +bool wxWidgetIPhoneImpl::IsEnabled() const +{ +} + +void wxWidgetIPhoneImpl::Enable( bool enable ) +{ +} + +void wxWidgetIPhoneImpl::SetMinimum( wxInt32 v ) +{ +} + +void wxWidgetIPhoneImpl::SetMaximum( wxInt32 v ) +{ +} + +wxInt32 wxWidgetIPhoneImpl::GetMinimum() const +{ +} + +wxInt32 wxWidgetIPhoneImpl::GetMaximum() const +{ +} + +void wxWidgetIPhoneImpl::PulseGauge() +{ +} + +void wxWidgetIPhoneImpl::SetScrollThumb( wxInt32 value, wxInt32 thumbSize ) +{ +} + +void wxWidgetIPhoneImpl::SetControlSize( wxWindowVariant variant ) +{ +} + +void wxWidgetIPhoneImpl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle, bool ignoreBlack ) +{ +} + +void wxWidgetIPhoneImpl::InstallEventHandler( WXWidget control ) +{ + WXWidget c = control ? control : (WXWidget) m_osxView; + wxWidgetImpl::Associate( c, this ) ; + + if ([c isKindOfClass:[UIControl class] ]) + { + UIControl* cc = (UIControl*) c; + /* + [cc addTarget:self action:@selector(touchUpInsideAction:event:) forControlEvents:UIControlEventTouchUpInside]; + */ + } +} + +void wxWidgetIPhoneImpl::DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* otherWindow) +{ + wxWindow* thisWindow = GetWXPeer(); + if ( thisWindow->MacGetTopLevelWindow() && NeedsFocusRect() ) + { + thisWindow->MacInvalidateBorders(); + } + + if ( receivedFocus ) + { + wxLogTrace(wxT("Focus"), wxT("focus set(%p)"), static_cast(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); + if (otherWindow) + event.SetWindow(otherWindow->GetWXPeer()); + thisWindow->HandleWindowEvent(event) ; + } + else // !receivedFocuss + { +#if wxUSE_CARET + if ( thisWindow->GetCaret() ) + thisWindow->GetCaret()->OnKillFocus(); +#endif + + wxLogTrace(wxT("Focus"), wxT("focus lost(%p)"), static_cast(thisWindow)); + + wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId()); + event.SetEventObject(thisWindow); + if (otherWindow) + event.SetWindow(otherWindow->GetWXPeer()); + thisWindow->HandleWindowEvent(event) ; + } +} + +typedef void (*wxOSX_DrawRectHandlerPtr)(UIView* self, SEL _cmd, CGRect rect); +typedef BOOL (*wxOSX_FocusHandlerPtr)(UIView* self, SEL _cmd); + +bool wxWidgetIPhoneImpl::becomeFirstResponder(WXWidget slf, void *_cmd) +{ + wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd]; + // get the current focus before running becomeFirstResponder + UIView* otherView = FindFocus(); + wxWidgetImpl* otherWindow = FindFromWXWidget(otherView); + BOOL r = superimpl(slf, (SEL)_cmd); + if ( r ) + { + DoNotifyFocusEvent( true, otherWindow ); + } + return r; +} + +bool wxWidgetIPhoneImpl::resignFirstResponder(WXWidget slf, void *_cmd) +{ + wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd]; + BOOL r = superimpl(slf, (SEL)_cmd); + // get the current focus after running resignFirstResponder + UIView* otherView = FindFocus(); + wxWidgetImpl* otherWindow = FindFromWXWidget(otherView); + // NSTextViews have an editor as true responder, therefore the might get the + // resign notification if their editor takes over, don't trigger any event hen + if ( r && otherWindow != this) + { + DoNotifyFocusEvent( false, otherWindow ); + } + return r; +} + +void wxWidgetIPhoneImpl::drawRect(CGRect* rect, WXWidget slf, void *WXUNUSED(_cmd)) +{ + CGContextRef context = (CGContextRef) UIGraphicsGetCurrentContext(); + CGContextSaveGState( context ); + // draw background + + CGContextSetFillColorWithColor( context, GetWXPeer()->GetBackgroundColour().GetCGColor()); + CGContextFillRect(context, *rect ); + + GetWXPeer()->MacSetCGContextRef( context ); + + GetWXPeer()->GetUpdateRegion() = + wxRegion(rect->origin.x,rect->origin.y,rect->size.width,rect->size.height) ; + + wxRegion updateRgn( wxFromNSRect( slf, *rect ) ); + + wxWindow* wxpeer = GetWXPeer(); + wxpeer->GetUpdateRegion() = updateRgn; + wxpeer->MacSetCGContextRef( context ); + + bool handled = wxpeer->MacDoRedraw( 0 ); + + CGContextRestoreGState( context ); + + CGContextSaveGState( context ); + if ( !handled ) + { + // call super + SEL _cmd = @selector(drawRect:); + wxOSX_DrawRectHandlerPtr superimpl = (wxOSX_DrawRectHandlerPtr) [[slf superclass] instanceMethodForSelector:_cmd]; + if ( superimpl != wxOSX_drawRect ) + { + superimpl(slf, _cmd, *rect); + CGContextRestoreGState( context ); + CGContextSaveGState( context ); + } + } + wxpeer->MacPaintChildrenBorders(); + wxpeer->MacSetCGContextRef( NULL ); + + CGContextRestoreGState( context ); +} + +void wxWidgetIPhoneImpl::touchEvent(NSSet* touches, UIEvent *event, WXWidget slf, void *WXUNUSED(_cmd)) +{ + CGPoint clickLocation; + UITouch *touch = [touches anyObject]; + clickLocation = [touch locationInView:slf]; + wxPoint pt = wxFromNSPoint( m_osxView, clickLocation ); + + wxMouseEvent wxevent(wxEVT_LEFT_DOWN); + SetupMouseEvent( wxevent , touches, event ) ; + wxevent.m_x = pt.x; + wxevent.m_y = pt.y; + wxevent.SetEventObject( GetWXPeer() ) ; + //?wxevent.SetId( GetWXPeer()->GetId() ) ; + + GetWXPeer()->HandleWindowEvent(wxevent); +} + +void wxWidgetIPhoneImpl::touchUpInsideAction(void* sender, WX_UIEvent evt, WXWidget slf, void* _cmd) +{ +} + // // 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* WXUNUSED(parent), + wxWindowID WXUNUSED(id), const wxPoint& pos, const wxSize& size, + long WXUNUSED(style), long WXUNUSED(extraStyle)) { UIView* sv = (wxpeer->GetParent()->GetHandle() ); - + CGRect r = CGRectMake( pos.x, pos.y, size.x, size.y) ; // Rect bounds = wxMacGetBoundsForControl( wxpeer, pos , size ) ; wxUIView* v = [[wxUIView alloc] initWithFrame:r]; sv.clipsToBounds = YES; sv.contentMode = UIViewContentModeRedraw; sv.clearsContextBeforeDrawing = NO; - // sv.backgroundColor = [[UIColor alloc] initWithCGColor:wxpeer->GetBackgroundColour().GetCGColor()]; - [sv addSubview:v]; wxWidgetIPhoneImpl* c = new wxWidgetIPhoneImpl( wxpeer, v ); - [v setImplementation:c]; return c; } -wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now ) +wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now ) { UIWindow* toplevelwindow = now->GetWXWindow(); @@ -458,25 +775,25 @@ wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now ) /* UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; // left orientation not yet implemented ! - if (orientation == UIInterfaceOrientationLandscapeRight ) + if (orientation == UIInterfaceOrientationLandscapeRight ) { CGAffineTransform transform = v.transform; - + // Use the status bar frame to determine the center point of the window's content area. CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame]; CGRect bounds = CGRectMake(0, 0, statusBarFrame.size.height, statusBarFrame.origin.x); CGPoint center = CGPointMake(bounds.size.height / 2.0, bounds.size.width / 2.0); - + // Set the center point of the view to the center point of the window's content area. v.center = center; - + // Rotate the view 90 degrees around its new center point. transform = CGAffineTransformRotate(transform, ( M_PI / 2.0)); v.transform = transform; } */ wxWidgetIPhoneImpl* impl = new wxWidgetIPhoneImpl( now, contentview, true ); - [contentview setImplementation:impl]; + impl->InstallEventHandler(); [toplevelwindow addSubview:contentview]; return impl; }