adapting to autorelease of factory method
[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 #include "wx/fontutil.h"
25
26 #ifdef __WXMAC__
27
28 #if wxOSX_USE_CARBON
29 bool wxMacInitCocoa()
30 {
31     bool cocoaLoaded = NSApplicationLoad();
32     wxASSERT_MSG(cocoaLoaded,wxT("Couldn't load Cocoa in Carbon Environment")) ;
33     return cocoaLoaded;
34 }
35 #endif
36
37 wxMacAutoreleasePool::wxMacAutoreleasePool()
38 {
39     m_pool = [[NSAutoreleasePool alloc] init];
40 }
41
42 wxMacAutoreleasePool::~wxMacAutoreleasePool()
43 {
44     [(NSAutoreleasePool*)m_pool release];
45 }
46
47 #endif
48
49 #if wxOSX_USE_COCOA_OR_IPHONE
50
51 CGContextRef wxOSXGetContextFromCurrentNSContext()
52 {
53     CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext]
54                                           graphicsPort];
55     return context;
56 }
57
58 bool wxOSXLockFocus( WXWidget view) 
59 {
60     return [view lockFocusIfCanDraw];
61 }
62
63 void wxOSXUnlockFocus( WXWidget view) 
64 {
65     [view unlockFocus];
66 }
67
68 #endif
69
70 // ----------------------------------------------------------------------------
71 // NSObject Utils
72 // ----------------------------------------------------------------------------
73
74 void wxMacCocoaRelease( void* obj )
75 {
76     [(NSObject*)obj release];
77 }
78
79 void wxMacCocoaAutorelease( void* obj )
80 {
81     [(NSObject*)obj autorelease];
82 }
83
84 void* wxMacCocoaRetain( void* obj )
85 {
86     [(NSObject*)obj retain];
87     return obj;
88 }
89
90 // ----------------------------------------------------------------------------
91 // NSFont Utils
92 // ----------------------------------------------------------------------------
93
94 #if wxOSX_USE_COCOA
95
96 WX_NSFont wxFont::CreateNSFont(wxOSXSystemFont font, wxNativeFontInfo* info)
97 {
98     NSFont* nsfont;
99     switch( font )
100     {
101         case wxOSX_SYSTEM_FONT_NORMAL:
102             nsfont = [NSFont systemFontOfSize:[NSFont systemFontSize]];
103             break;
104         case wxOSX_SYSTEM_FONT_BOLD:
105             nsfont = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]];
106             break;
107         case wxOSX_SYSTEM_FONT_SMALL:
108             nsfont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
109             break;
110         case wxOSX_SYSTEM_FONT_SMALL_BOLD:
111             nsfont = [NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]];
112             break;
113         case wxOSX_SYSTEM_FONT_MINI:
114             nsfont = [NSFont systemFontOfSize:[NSFont systemFontSize]];
115             break;
116        case wxOSX_SYSTEM_FONT_MINI_BOLD:
117             nsfont = [NSFont boldSystemFontOfSize:
118                 [NSFont systemFontSizeForControlSize:NSMiniControlSize]];
119             break;
120         case wxOSX_SYSTEM_FONT_LABELS:
121             nsfont = [NSFont labelFontOfSize:
122                 [NSFont systemFontSizeForControlSize:NSMiniControlSize]];
123             break;
124        case wxOSX_SYSTEM_FONT_VIEWS:
125             nsfont = [NSFont controlContentFontOfSize:0];
126             break;
127         default:
128             break;
129     }
130     [nsfont retain];
131     NSFontDescriptor*desc = [[nsfont fontDescriptor] retain];
132     if ( info->m_faceName.empty())
133     {
134         wxFontStyle fontstyle = wxFONTSTYLE_NORMAL;
135         wxFontWeight fontweight = wxFONTWEIGHT_NORMAL;
136         bool underlined = false;
137         
138         int size = (int) ([desc pointSize]+0.5);
139         NSFontSymbolicTraits traits = [desc symbolicTraits];
140             
141         if ( traits & NSFontBoldTrait )
142             fontweight = wxFONTWEIGHT_BOLD ;
143         else
144             fontweight = wxFONTWEIGHT_NORMAL ;
145         if ( traits & NSFontItalicTrait )
146             fontstyle = wxFONTSTYLE_ITALIC ;
147              
148         wxCFStringRef fontname( [desc postscriptName] );
149         info->Init(size,wxFONTFAMILY_DEFAULT,fontstyle,fontweight,underlined,
150             fontname.AsString(), wxFONTENCODING_DEFAULT);
151         
152     }
153     info->m_nsFontDescriptor = desc;
154     return nsfont;
155 }
156
157 void wxNativeFontInfo::ValidateNSFontDescriptor()
158 {
159     NSFontDescriptor* desc  = [NSFontDescriptor fontDescriptorWithName:wxCFStringRef(m_faceName).AsNSString() size:m_pointSize];
160     NSFontSymbolicTraits traits = 0;
161
162     if (m_weight == wxFONTWEIGHT_BOLD)
163         traits |= NSFontBoldTrait;
164     if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
165         traits |= NSFontItalicTrait;
166
167     if ( traits != 0 )
168     {
169         desc = [desc fontDescriptorWithSymbolicTraits:traits];
170     }
171     else
172     {
173         wxMacCocoaRetain(desc);
174     }
175     m_nsFontDescriptor = desc;
176 }
177
178 WX_NSFont wxFont::CreateNSFont(const wxNativeFontInfo* info)
179 {
180     NSFont* nsFont;
181     nsFont = [NSFont fontWithDescriptor:info->m_nsFontDescriptor size:info->m_pointSize];
182     
183     return nsFont;
184 }
185
186 #endif
187
188 // ----------------------------------------------------------------------------
189 // NSImage Utils
190 // ----------------------------------------------------------------------------
191
192 #if wxOSX_USE_COCOA
193
194 //  From "Cocoa Drawing Guide:Working with Images"
195 WX_NSImage  wxOSXCreateNSImageFromCGImage( CGImageRef image )
196 {
197     NSRect      imageRect    = NSMakeRect(0.0, 0.0, 0.0, 0.0);
198     
199     // Get the image dimensions.
200     imageRect.size.height = CGImageGetHeight(image);
201     imageRect.size.width = CGImageGetWidth(image);
202     
203     // Create a new image to receive the Quartz image data.
204     NSImage  *newImage = [[NSImage alloc] initWithSize:imageRect.size]; 
205     [newImage lockFocus];
206     
207     // Get the Quartz context and draw.
208     CGContextRef  imageContext = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
209     CGContextDrawImage( imageContext, *(CGRect*)&imageRect, image );
210     [newImage unlockFocus];
211     
212     /*
213         // Create a bitmap rep from the image...
214         NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
215         // Create an NSImage and add the bitmap rep to it...
216         NSImage *image = [[NSImage alloc] init];
217         [image addRepresentation:bitmapRep];
218         [bitmapRep release];
219     */
220     [newImage autorelease];
221     return( newImage );
222 }
223
224 // ----------------------------------------------------------------------------
225 // NSCursor Utils
226 // ----------------------------------------------------------------------------
227
228 // copied from cursor.mm
229
230 static NSCursor* wxGetStockCursor( short sIndex )
231 {
232     ClassicCursor* pCursor = &gMacCursors[sIndex];
233
234     //Classic mac cursors are 1bps 16x16 black and white with a
235     //identical mask that is 1 for on and 0 for off
236     NSImage *theImage = [[NSImage alloc] initWithSize:NSMakeSize(16.0,16.0)];
237
238     //NSCursor takes an NSImage takes a number of Representations - here
239     //we need only one for the raw data
240     NSBitmapImageRep *theRep =
241     [[NSBitmapImageRep alloc]
242       initWithBitmapDataPlanes:nil  // Allocate the buffer for us :)
243       pixelsWide:16
244       pixelsHigh:16
245       bitsPerSample:1
246       samplesPerPixel:2
247       hasAlpha:YES                  // Well, more like a mask...
248       isPlanar:NO
249       colorSpaceName:NSCalibratedWhiteColorSpace // Normal B/W - 0 black 1 white
250       bytesPerRow:0     // I don't care - figure it out for me :)
251       bitsPerPixel:2];  // bitsPerSample * samplesPerPixel
252
253     //unsigned int is better to put data in then a void*
254     //note that working with bitfields would be a lot better here -
255     //but since it breaks some compilers...
256     wxUint32 *data = (wxUint32 *)[theRep bitmapData];
257
258     //traverse through the bitmap data
259     for (int i = 0; i < 16; ++i)
260     {
261         //bit alpha bit alpha ... :D
262
263         //Notice the = instead of |= -
264         //this is to avoid doing a memset earlier
265         data[i] = 0;
266
267         //do the rest of those bits and alphas :)
268         for (int shift = 0; shift < 32; ++shift)
269         {
270             const int bit = 1 << (shift >> 1);
271             data[i] |= ( !!( (pCursor->mask[i] & bit) ) ) << shift;
272             data[i] |= ( !( (pCursor->bits[i] & bit) ) ) << ++shift;
273         }
274     }
275
276     //add the representation (data) to the image
277     [theImage addRepresentation:theRep];
278
279     //create the new cursor
280     NSCursor* theCursor =  [[NSCursor alloc]  initWithImage:theImage
281                                     hotSpot:NSMakePoint(pCursor->hotspot[1], pCursor->hotspot[0])
282                             ];
283
284     //do the usual cleanups
285     [theRep release];
286     [theImage release];
287
288     //return the new cursor
289     return theCursor;
290 }
291
292 WX_NSCursor wxMacCocoaCreateStockCursor( int cursor_type )
293 {
294     WX_NSCursor cursor = nil;
295     switch (cursor_type)
296     {
297     case wxCURSOR_COPY_ARROW:
298         cursor = [[NSCursor arrowCursor] retain];
299         break;
300
301     case wxCURSOR_WATCH:
302     case wxCURSOR_WAIT:
303         // should be displayed by the system when things are running
304         cursor = [[NSCursor arrowCursor] retain];
305         break;
306
307     case wxCURSOR_IBEAM:
308         cursor = [[NSCursor IBeamCursor] retain];
309         break;
310
311     case wxCURSOR_CROSS:
312         cursor = [[NSCursor crosshairCursor] retain];
313         break;
314
315     case wxCURSOR_SIZENWSE:
316         cursor = wxGetStockCursor(kwxCursorSizeNWSE);
317         break;
318
319     case wxCURSOR_SIZENESW:
320         cursor = wxGetStockCursor(kwxCursorSizeNESW);
321         break;
322
323     case wxCURSOR_SIZEWE:
324         cursor = [[NSCursor resizeLeftRightCursor] retain];
325         break;
326
327     case wxCURSOR_SIZENS:
328         cursor = [[NSCursor resizeUpDownCursor] retain];
329         break;
330
331     case wxCURSOR_SIZING:
332         cursor = wxGetStockCursor(kwxCursorSize);
333         break;
334
335     case wxCURSOR_HAND:
336         cursor = [[NSCursor pointingHandCursor] retain];
337         break;
338         
339     case wxCURSOR_BULLSEYE:
340         cursor = wxGetStockCursor(kwxCursorBullseye);
341         break;
342
343     case wxCURSOR_PENCIL:
344         cursor = wxGetStockCursor(kwxCursorPencil);
345         break;
346
347     case wxCURSOR_MAGNIFIER:
348         cursor = wxGetStockCursor(kwxCursorMagnifier);
349         break;
350
351     case wxCURSOR_NO_ENTRY:
352         cursor = wxGetStockCursor(kwxCursorNoEntry);
353         break;
354
355     case wxCURSOR_PAINT_BRUSH:
356         cursor = wxGetStockCursor(kwxCursorPaintBrush);
357         break;
358
359     case wxCURSOR_POINT_LEFT:
360         cursor = wxGetStockCursor(kwxCursorPointLeft);
361         break;
362
363     case wxCURSOR_POINT_RIGHT:
364         cursor = wxGetStockCursor(kwxCursorPointRight);
365         break;
366
367     case wxCURSOR_QUESTION_ARROW:
368         cursor = wxGetStockCursor(kwxCursorQuestionArrow);
369         break;
370
371     case wxCURSOR_BLANK:
372         cursor = wxGetStockCursor(kwxCursorBlank);
373         break;
374
375     case wxCURSOR_RIGHT_ARROW:
376         cursor = wxGetStockCursor(kwxCursorRightArrow);
377         break;
378
379     case wxCURSOR_SPRAYCAN:
380         cursor = wxGetStockCursor(kwxCursorRoller);
381         break;
382
383     case wxCURSOR_OPEN_HAND:
384         cursor = [[NSCursor openHandCursor] retain];
385         break;
386
387     case wxCURSOR_CLOSED_HAND:
388         cursor = [[NSCursor closedHandCursor] retain];
389         break;
390
391     case wxCURSOR_CHAR:
392     case wxCURSOR_ARROW:
393     case wxCURSOR_LEFT_BUTTON:
394     case wxCURSOR_RIGHT_BUTTON:
395     case wxCURSOR_MIDDLE_BUTTON:
396     default:
397         cursor = [[NSCursor arrowCursor] retain];
398         break;
399     }
400     return cursor;
401 }
402
403 //  C-based style wrapper routines around NSCursor
404 WX_NSCursor  wxMacCocoaCreateCursorFromCGImage( CGImageRef cgImageRef, float hotSpotX, float hotSpotY )
405 {
406     static BOOL    firstTime  = YES;
407     
408     if ( firstTime )
409     {
410         //  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
411         [[[NSWindow alloc] init] release];
412         firstTime = NO;
413     }
414     
415     NSImage    *nsImage  = wxOSXCreateNSImageFromCGImage( cgImageRef );
416     NSCursor  *cursor    = [[NSCursor alloc] initWithImage:nsImage hotSpot:NSMakePoint( hotSpotX, hotSpotY )];
417     
418     [nsImage release];
419     
420     return cursor;
421 }
422
423 void  wxMacCocoaSetCursor( WX_NSCursor cursor )
424 {
425     [cursor set];
426 }
427
428 void  wxMacCocoaHideCursor()
429 {
430     [NSCursor hide];
431 }
432
433 void  wxMacCocoaShowCursor()
434 {
435     [NSCursor unhide];
436 }
437
438 #endif
439