1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/iphone/window.mm
3 // Purpose: widgets (non tlw) for iphone
4 // Author: Stefan Csomor
7 // RCS-ID: $Id: window.mm 48805 2007-09-19 14:52:25Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
14 #include "wx/osx/private.h"
17 #include "wx/nonownedwnd.h"
20 @interface wxUIView : UIView
25 - (void)drawRect: (CGRect) rect;
27 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
28 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
29 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
30 - (void)handleTouchEvent:(NSSet *)touches withEvent:(UIEvent *)event;
32 - (void)setImplementation: (wxWidgetImpl *) theImplementation;
33 - (wxWidgetImpl*) implementation;
35 - (BOOL) becomeFirstResponder;
36 - (BOOL) resignFirstResponder;
40 @interface wxUIContentView : wxUIView
46 @interface wxUIContentViewController : UIViewController
56 void SetupMouseEvent( wxMouseEvent &wxevent , NSSet* touches, UIEvent * nsEvent )
58 UInt32 modifiers = 0 ;
59 UITouch *touch = [touches anyObject];
61 // these parameters are not given for all events
62 UInt32 button = 0; // no secondary button
63 UInt32 clickCount = [touch tapCount];
64 UInt32 mouseChord = 0; // TODO does this exist for cocoa
69 wxevent.m_shiftDown = 0;
70 wxevent.m_controlDown = 0;
71 wxevent.m_altDown = 0;
72 wxevent.m_metaDown = 0;
73 wxevent.m_clickCount = clickCount;
74 wxevent.SetTimestamp( [touch timestamp] ) ;
76 // a control click is interpreted as a right click
77 bool thisButtonIsFakeRight = false ;
78 if ( button == kEventMouseButtonPrimary && (modifiers & controlKey) )
80 button = kEventMouseButtonSecondary ;
81 thisButtonIsFakeRight = true ;
84 // otherwise we report double clicks by connecting a left click with a ctrl-left click
85 if ( clickCount > 1 && button != g_lastButton )
87 // we must make sure that our synthetic 'right' button corresponds in
88 // mouse down, moved and mouse up, and does not deliver a right down and left up
90 if ( cEvent.GetKind() == kEventMouseDown )
92 g_lastButton = button ;
93 g_lastButtonWasFakeRight = thisButtonIsFakeRight ;
99 g_lastButtonWasFakeRight = false ;
101 else if ( g_lastButton == kEventMouseButtonSecondary && g_lastButtonWasFakeRight )
102 button = g_lastButton ;
104 // Adjust the chord mask to remove the primary button and add the
105 // secondary button. It is possible that the secondary button is
106 // already pressed, e.g. on a mouse connected to a laptop, but this
107 // possibility is ignored here:
108 if( thisButtonIsFakeRight && ( mouseChord & 1U ) )
109 mouseChord = ((mouseChord & ~1U) | 2U);
112 wxevent.m_leftDown = true ;
114 wxevent.m_rightDown = true ;
116 wxevent.m_middleDown = true ;
119 // translate into wx types
120 int eventType = [touch phase];
123 case UITouchPhaseBegan :
127 wxevent.SetEventType( clickCount > 1 ? wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN ) ;
135 case UITouchPhaseEnded :
139 wxevent.SetEventType( wxEVT_LEFT_UP ) ;
147 case UITouchPhaseMoved :
148 wxevent.SetEventType( wxEVT_MOTION ) ;
155 @implementation wxUIView
157 - (id) initWithFrame: (CGRect) frame
159 if ( self = [super initWithFrame:frame])
168 // additional deallocs
172 - (void)drawRect: (CGRect) rect
176 CGContextRef context = (CGContextRef) UIGraphicsGetCurrentContext();
177 CGContextSaveGState( context );
180 CGContextSetFillColorWithColor( context, ->GetWXPeer()->GetBackgroundColour().GetCGColor());
181 CGContextFillRect(context, rect );
183 if ( [ self isFlipped ] == NO )
185 CGContextTranslateCTM( context, 0, [self bounds].size.height );
186 CGContextScaleCTM( context, 1, -1 );
189 ->GetWXPeer()->MacSetCGContextRef( context );
191 ->GetWXPeer()->GetUpdateRegion() =
192 wxRegion(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height) ;
195 event.SetTimestamp(0); // todo
196 event.SetEventObject(->GetWXPeer());
197 ->GetWXPeer()->HandleWindowEvent(event);
199 CGContextRestoreGState( context );
204 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
206 [self handleTouchEvent:touches withEvent:event];
209 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
211 [self handleTouchEvent:touches withEvent:event];
214 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
216 [self handleTouchEvent:touches withEvent:event];
219 -(void)handleTouchEvent:(NSSet *)touches withEvent:(UIEvent *)event
221 CGPoint clickLocation;
222 UITouch *touch = [touches anyObject];
223 clickLocation = [touch locationInView:self];
225 wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
226 SetupMouseEvent( wxevent , touches, event ) ;
227 wxevent.m_x = clickLocation.x;
228 wxevent.m_y = clickLocation.y;
229 wxevent.SetEventObject( ->GetWXPeer() ) ;
230 wxevent.SetId( ->GetWXPeer()->GetId() ) ;
231 ->GetWXPeer()->HandleWindowEvent(wxevent);
234 - (void)setImplementation: (wxWidgetImpl *) theImplementation
239 - (wxWidgetImpl*) implementation
249 - (BOOL) becomeFirstResponder
251 BOOL r = [super becomeFirstResponder];
258 - (BOOL) resignFirstResponder
260 BOOL r = [super resignFirstResponder];
270 @implementation wxUIContentView
274 @implementation wxUIContentViewController
276 - (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation
281 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
283 CGRect fr = [self.view frame];
284 // CGRect cv = [[self.view superview] frame];
285 // CGRect bounds = CGRectMake( 0,0,fr.size.width, fr.size.height);
286 // [[self.view superview] setFrame: fr ];
287 // [self.view setFrame: bounds];
288 // [self.view setNeedsDisplayInRect:bounds];
294 IMPLEMENT_DYNAMIC_CLASS( wxWidgetIPhoneImpl , wxWidgetImpl )
296 wxWidgetIPhoneImpl::wxWidgetIPhoneImpl( wxWindowMac* peer , WXWidget w, bool isRootControl ) :
297 wxWidgetImpl( peer, isRootControl ), m_osxView(w)
301 wxWidgetIPhoneImpl::wxWidgetIPhoneImpl()
305 void wxWidgetIPhoneImpl::Init()
310 wxWidgetIPhoneImpl::~wxWidgetIPhoneImpl()
312 [m_osxView setImplementation:NULL];
316 bool wxWidgetIPhoneImpl::IsVisible() const
319 return [m_osxView isHidden] == NO;
322 void wxWidgetIPhoneImpl::SetVisibility( bool visible )
324 [m_osxView setHidden:(visible ? NO:YES)];
327 void wxWidgetIPhoneImpl::Raise()
329 [[m_osxView superview] bringSubviewToFront:m_osxView];
332 void wxWidgetIPhoneImpl::Lower()
334 [[m_osxView superview] sendSubviewToBack:m_osxView];
337 void wxWidgetIPhoneImpl::ScrollRect( const wxRect *rect, int dx, int dy )
341 void wxWidgetIPhoneImpl::Move(int x, int y, int width, int height)
343 CGRect r = CGRectMake( x, y, width, height) ;
344 [m_osxView setFrame:r];
347 void wxWidgetIPhoneImpl::GetPosition( int &x, int &y ) const
349 CGRect r = [m_osxView frame];
354 void wxWidgetIPhoneImpl::GetSize( int &width, int &height ) const
356 CGRect rect = [m_osxView frame];
357 width = rect.size.width;
358 height = rect.size.height;
361 void wxWidgetIPhoneImpl::GetContentArea( int&left, int &top, int &width, int &height ) const
364 GetSize( width, height );
367 void wxWidgetIPhoneImpl::SetNeedsDisplay( const wxRect* where )
371 CGRect r = CGRectMake( where->x, where->y, where->width, where->height) ;
372 [m_osxView setNeedsDisplayInRect:r];
375 [m_osxView setNeedsDisplay];
378 bool wxWidgetIPhoneImpl::GetNeedsDisplay() const
381 // return [m_osxView needsDisplay];
384 bool wxWidgetIPhoneImpl::CanFocus() const
386 return [m_osxView canBecomeFirstResponder] == YES;
387 // ? return [m_osxView isUserInteractionEnabled] == YES;
390 bool wxWidgetIPhoneImpl::HasFocus() const
392 return [m_osxView isFirstResponder] == YES;
395 bool wxWidgetIPhoneImpl::SetFocus()
397 // [m_osxView makeKeyWindow] ;
403 void wxWidgetIPhoneImpl::RemoveFromParent()
405 [m_osxView removeFromSuperview];
408 void wxWidgetIPhoneImpl::Embed( wxWidgetImpl *parent )
410 UIView* container = parent->GetWXWidget() ;
411 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
412 [container addSubview:m_osxView];
415 void wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
417 CGPoint p = CGPointMake( pt->x , pt->y );
418 p = [from->GetWXWidget() convertPoint:p toView:to->GetWXWidget() ];
423 void wxWidgetIPhoneImpl::SetBackgroundColour( const wxColour &col )
425 // m_osxView.backgroundColor = [[UIColor alloc] initWithCGColor:col.GetCGColor()];
432 wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, const wxPoint& pos, const wxSize& size,
433 long style, long extraStyle)
435 UIView* sv = (wxpeer->GetParent()->GetHandle() );
437 CGRect r = CGRectMake( pos.x, pos.y, size.x, size.y) ;
438 // Rect bounds = wxMacGetBoundsForControl( wxpeer, pos , size ) ;
439 wxUIView* v = [[wxUIView alloc] initWithFrame:r];
440 sv.clipsToBounds = YES;
441 sv.contentMode = UIViewContentModeRedraw;
442 sv.clearsContextBeforeDrawing = NO;
443 // sv.backgroundColor = [[UIColor alloc] initWithCGColor:wxpeer->GetBackgroundColour().GetCGColor()];
445 wxWidgetIPhoneImpl* c = new wxWidgetIPhoneImpl( wxpeer, v );
446 [v setImplementation:c];
450 wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now )
452 UIWindow* toplevelwindow = now->GetWXWindow();
454 wxUIContentView* contentview = [[wxUIContentView alloc] initWithFrame:[toplevelwindow bounds]];
455 contentview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
456 wxUIContentViewController* controller = [[wxUIContentViewController alloc] init];
457 controller.view = contentview;
459 UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
460 // left orientation not yet implemented !
461 if (orientation == UIInterfaceOrientationLandscapeRight )
463 CGAffineTransform transform = v.transform;
465 // Use the status bar frame to determine the center point of the window's content area.
466 CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
467 CGRect bounds = CGRectMake(0, 0, statusBarFrame.size.height, statusBarFrame.origin.x);
468 CGPoint center = CGPointMake(bounds.size.height / 2.0, bounds.size.width / 2.0);
470 // Set the center point of the view to the center point of the window's content area.
473 // Rotate the view 90 degrees around its new center point.
474 transform = CGAffineTransformRotate(transform, ( M_PI / 2.0));
475 v.transform = transform;
478 wxWidgetIPhoneImpl* impl = new wxWidgetIPhoneImpl( now, contentview, true );
479 [contentview setImplementation:impl];
480 [toplevelwindow addSubview:contentview];