paint event handling fixes and wxClientDC implementation for osx-cocoa
[wxWidgets.git] / src / osx / carbon / utilscocoa.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/carbon/utils.mm
3 // Purpose:     various cocoa mixin utility functions
4 // Author:      Stefan Csomor
5 // Modified by:
6 // Created:     1998-01-01
7 // RCS-ID:      $Id: utilscocoa.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 #if wxOSX_USE_COCOA_OR_CARBON
15 #include <Cocoa/Cocoa.h>
16 #else
17 #import <UIKit/UIKit.h>
18 #endif
19
20 #ifdef __WXMAC__
21 #include "wx/osx/private.h"
22 #endif
23
24 #ifdef __WXMAC__
25
26 #if wxOSX_USE_CARBON
27 bool wxMacInitCocoa()
28 {
29     bool cocoaLoaded = NSApplicationLoad();
30     wxASSERT_MSG(cocoaLoaded,wxT("Couldn't load Cocoa in Carbon Environment")) ;
31     return cocoaLoaded;
32 }
33 #endif
34
35 wxMacAutoreleasePool::wxMacAutoreleasePool()
36 {
37     m_pool = [[NSAutoreleasePool alloc] init];
38 }
39
40 wxMacAutoreleasePool::~wxMacAutoreleasePool()
41 {
42     [(NSAutoreleasePool*)m_pool release];
43 }
44
45 #endif
46
47 #if wxOSX_USE_COCOA_OR_IPHONE
48
49 CGContextRef wxOSXGetContextFromCurrentNSContext()
50 {
51     CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext]
52                                           graphicsPort];
53     return context;
54 }
55
56 void wxOSXLockFocus( WXWidget view) 
57 {
58     [view lockFocus];
59 }
60
61 void wxOSXUnlockFocus( WXWidget view) 
62 {
63     [view unlockFocus];
64 }
65
66 #endif
67
68 // ----------------------------------------------------------------------------
69 // NSObject Utils
70 // ----------------------------------------------------------------------------
71
72 void wxMacCocoaRelease( void* obj )
73 {
74     [(NSObject*)obj release];
75 }
76
77 void wxMacCocoaAutorelease( void* obj )
78 {
79     [(NSObject*)obj autorelease];
80 }
81
82 void wxMacCocoaRetain( void* obj )
83 {
84     [(NSObject*)obj retain];
85 }
86
87 #if wxOSX_USE_COCOA
88
89 // ----------------------------------------------------------------------------
90 // NSImage Utils
91 // ----------------------------------------------------------------------------
92
93 //  From "Cocoa Drawing Guide:Working with Images"
94 WX_NSImage  wxOSXCreateNSImageFromCGImage( CGImageRef image )
95 {
96     NSRect      imageRect    = NSMakeRect(0.0, 0.0, 0.0, 0.0);
97     
98     // Get the image dimensions.
99     imageRect.size.height = CGImageGetHeight(image);
100     imageRect.size.width = CGImageGetWidth(image);
101     
102     // Create a new image to receive the Quartz image data.
103     NSImage  *newImage = [[NSImage alloc] initWithSize:imageRect.size]; 
104     [newImage lockFocus];
105     
106     // Get the Quartz context and draw.
107     CGContextRef  imageContext = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
108     CGContextDrawImage( imageContext, *(CGRect*)&imageRect, image );
109     [newImage unlockFocus];
110     
111     /*
112         // Create a bitmap rep from the image...
113         NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
114         // Create an NSImage and add the bitmap rep to it...
115         NSImage *image = [[NSImage alloc] init];
116         [image addRepresentation:bitmapRep];
117         [bitmapRep release];
118     */
119     [newImage autorelease];
120     return( newImage );
121 }
122
123 // ----------------------------------------------------------------------------
124 // NSCursor Utils
125 // ----------------------------------------------------------------------------
126
127 // copied from cursor.mm
128
129 static NSCursor* wxGetStockCursor( short sIndex )
130 {
131     ClassicCursor* pCursor = &gMacCursors[sIndex];
132
133     //Classic mac cursors are 1bps 16x16 black and white with a
134     //identical mask that is 1 for on and 0 for off
135     NSImage *theImage = [[NSImage alloc] initWithSize:NSMakeSize(16.0,16.0)];
136
137     //NSCursor takes an NSImage takes a number of Representations - here
138     //we need only one for the raw data
139     NSBitmapImageRep *theRep =
140     [[NSBitmapImageRep alloc]
141       initWithBitmapDataPlanes:nil  // Allocate the buffer for us :)
142       pixelsWide:16
143       pixelsHigh:16
144       bitsPerSample:1
145       samplesPerPixel:2
146       hasAlpha:YES                  // Well, more like a mask...
147       isPlanar:NO
148       colorSpaceName:NSCalibratedWhiteColorSpace // Normal B/W - 0 black 1 white
149       bytesPerRow:0     // I don't care - figure it out for me :)
150       bitsPerPixel:2];  // bitsPerSample * samplesPerPixel
151
152     //unsigned int is better to put data in then a void*
153     //note that working with bitfields would be a lot better here -
154     //but since it breaks some compilers...
155     wxUint32 *data = (wxUint32 *)[theRep bitmapData];
156
157     //traverse through the bitmap data
158     for (int i = 0; i < 16; ++i)
159     {
160         //bit alpha bit alpha ... :D
161
162         //Notice the = instead of |= -
163         //this is to avoid doing a memset earlier
164         data[i] = 0;
165
166         //do the rest of those bits and alphas :)
167         for (int shift = 0; shift < 32; ++shift)
168         {
169             const int bit = 1 << (shift >> 1);
170             data[i] |= ( !!( (pCursor->mask[i] & bit) ) ) << shift;
171             data[i] |= ( !( (pCursor->bits[i] & bit) ) ) << ++shift;
172         }
173     }
174
175     //add the representation (data) to the image
176     [theImage addRepresentation:theRep];
177
178     //create the new cursor
179     NSCursor* theCursor =  [[NSCursor alloc]  initWithImage:theImage
180                                     hotSpot:NSMakePoint(pCursor->hotspot[1], pCursor->hotspot[0])
181                             ];
182
183     //do the usual cleanups
184     [theRep release];
185     [theImage release];
186
187     //return the new cursor
188     return theCursor;
189 }
190
191 WX_NSCursor wxMacCocoaCreateStockCursor( int cursor_type )
192 {
193     WX_NSCursor cursor = nil;
194     switch (cursor_type)
195     {
196     case wxCURSOR_COPY_ARROW:
197         cursor = [[NSCursor arrowCursor] retain];
198         break;
199
200     case wxCURSOR_WATCH:
201     case wxCURSOR_WAIT:
202         // should be displayed by the system when things are running
203         cursor = [[NSCursor arrowCursor] retain];
204         break;
205
206     case wxCURSOR_IBEAM:
207         cursor = [[NSCursor IBeamCursor] retain];
208         break;
209
210     case wxCURSOR_CROSS:
211         cursor = [[NSCursor crosshairCursor] retain];
212         break;
213
214     case wxCURSOR_SIZENWSE:
215         cursor = wxGetStockCursor(kwxCursorSizeNWSE);
216         break;
217
218     case wxCURSOR_SIZENESW:
219         cursor = wxGetStockCursor(kwxCursorSizeNESW);
220         break;
221
222     case wxCURSOR_SIZEWE:
223         cursor = [[NSCursor resizeLeftRightCursor] retain];
224         break;
225
226     case wxCURSOR_SIZENS:
227         cursor = [[NSCursor resizeUpDownCursor] retain];
228         break;
229
230     case wxCURSOR_SIZING:
231         cursor = wxGetStockCursor(kwxCursorSize);
232         break;
233
234     case wxCURSOR_HAND:
235         cursor = [[NSCursor pointingHandCursor] retain];
236         break;
237         
238     case wxCURSOR_BULLSEYE:
239         cursor = wxGetStockCursor(kwxCursorBullseye);
240         break;
241
242     case wxCURSOR_PENCIL:
243         cursor = wxGetStockCursor(kwxCursorPencil);
244         break;
245
246     case wxCURSOR_MAGNIFIER:
247         cursor = wxGetStockCursor(kwxCursorMagnifier);
248         break;
249
250     case wxCURSOR_NO_ENTRY:
251         cursor = wxGetStockCursor(kwxCursorNoEntry);
252         break;
253
254     case wxCURSOR_PAINT_BRUSH:
255         cursor = wxGetStockCursor(kwxCursorPaintBrush);
256         break;
257
258     case wxCURSOR_POINT_LEFT:
259         cursor = wxGetStockCursor(kwxCursorPointLeft);
260         break;
261
262     case wxCURSOR_POINT_RIGHT:
263         cursor = wxGetStockCursor(kwxCursorPointRight);
264         break;
265
266     case wxCURSOR_QUESTION_ARROW:
267         cursor = wxGetStockCursor(kwxCursorQuestionArrow);
268         break;
269
270     case wxCURSOR_BLANK:
271         cursor = wxGetStockCursor(kwxCursorBlank);
272         break;
273
274     case wxCURSOR_RIGHT_ARROW:
275         cursor = wxGetStockCursor(kwxCursorRightArrow);
276         break;
277
278     case wxCURSOR_SPRAYCAN:
279         cursor = wxGetStockCursor(kwxCursorRoller);
280         break;
281
282     case wxCURSOR_OPEN_HAND:
283         cursor = [[NSCursor openHandCursor] retain];
284         break;
285
286     case wxCURSOR_CLOSED_HAND:
287         cursor = [[NSCursor closedHandCursor] retain];
288         break;
289
290     case wxCURSOR_CHAR:
291     case wxCURSOR_ARROW:
292     case wxCURSOR_LEFT_BUTTON:
293     case wxCURSOR_RIGHT_BUTTON:
294     case wxCURSOR_MIDDLE_BUTTON:
295     default:
296         cursor = [[NSCursor arrowCursor] retain];
297         break;
298     }
299     return cursor;
300 }
301
302 //  C-based style wrapper routines around NSCursor
303 WX_NSCursor  wxMacCocoaCreateCursorFromCGImage( CGImageRef cgImageRef, float hotSpotX, float hotSpotY )
304 {
305     static BOOL    firstTime  = YES;
306     
307     if ( firstTime )
308     {
309         //  Must first call [[[NSWindow alloc] init] release] to get the NSWindow machinery set up so that NSCursor can use a window to cache the cursor image
310         [[[NSWindow alloc] init] release];
311         firstTime = NO;
312     }
313     
314     NSImage    *nsImage  = wxOSXCreateNSImageFromCGImage( cgImageRef );
315     NSCursor  *cursor    = [[NSCursor alloc] initWithImage:nsImage hotSpot:NSMakePoint( hotSpotX, hotSpotY )];
316     
317     [nsImage release];
318     
319     return cursor;
320 }
321
322 void  wxMacCocoaSetCursor( WX_NSCursor cursor )
323 {
324     [cursor set];
325 }
326
327 void  wxMacCocoaHideCursor()
328 {
329     [NSCursor hide];
330 }
331
332 void  wxMacCocoaShowCursor()
333 {
334     [NSCursor unhide];
335 }
336
337 #endif
338