Home | History | Annotate | Download | only in src
      1 /* The file is the modified version of window_cocoa.mm from opencv-cocoa project by Andre Cohen */
      2 
      3 /*M///////////////////////////////////////////////////////////////////////////////////////
      4 //
      5 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      6 //
      7 //  By downloading, copying, installing or using the software you agree to this license.
      8 //  If you do not agree to this license, do not download, install,
      9 //  copy or use the software.
     10 //
     11 //
     12 //                         License Agreement
     13 //                For Open Source Computer Vision Library
     14 //
     15 // Copyright (C) 2010, Willow Garage Inc., all rights reserved.
     16 // Third party copyrights are property of their respective owners.
     17 //
     18 // Redistribution and use in source and binary forms, with or without modification,
     19 // are permitted provided that the following conditions are met:
     20 //
     21 //   * Redistribution's of source code must retain the above copyright notice,
     22 //     this list of conditions and the following disclaimer.
     23 //
     24 //   * Redistribution's in binary form must reproduce the above copyright notice,
     25 //     this list of conditions and the following disclaimer in the documentation
     26 //     and/or other materials provided with the distribution.
     27 //
     28 //   * The name of Intel Corporation may not be used to endorse or promote products
     29 //     derived from this software without specific prior written permission.
     30 //
     31 // This software is provided by the copyright holders and contributors "as is" and
     32 // any express or implied warranties, including, but not limited to, the implied
     33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     34 // In no event shall the Intel Corporation or contributors be liable for any direct,
     35 // indirect, incidental, special, exemplary, or consequential damages
     36 // (including, but not limited to, procurement of substitute goods or services;
     37 // loss of use, data, or profits; or business interruption) however caused
     38 // and on any theory of liability, whether in contract, strict liability,
     39 // or tort (including negligence or otherwise) arising in any way out of
     40 // the use of this software, even if advised of the possibility of such damage.
     41 //
     42 //M*/
     43 #include "precomp.hpp"
     44 
     45 #import <TargetConditionals.h>
     46 
     47 #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
     48 /*** begin IPhone OS Stubs ***/
     49 // When highgui functions are referred to on iPhone OS, they will fail silently.
     50 CV_IMPL int cvInitSystem( int argc, char** argv) { return 0;}
     51 CV_IMPL int cvStartWindowThread(){ return 0; }
     52 CV_IMPL void cvDestroyWindow( const char* name) {}
     53 CV_IMPL void cvDestroyAllWindows( void ) {}
     54 CV_IMPL void cvShowImage( const char* name, const CvArr* arr) {}
     55 CV_IMPL void cvResizeWindow( const char* name, int width, int height) {}
     56 CV_IMPL void cvMoveWindow( const char* name, int x, int y){}
     57 CV_IMPL int cvCreateTrackbar (const char* trackbar_name,const char* window_name,
     58                               int* val, int count, CvTrackbarCallback on_notify) {return  0;}
     59 CV_IMPL int cvCreateTrackbar2(const char* trackbar_name,const char* window_name,
     60                               int* val, int count, CvTrackbarCallback2 on_notify2, void* userdata) {return 0;}
     61 CV_IMPL void cvSetMouseCallback( const char* name, CvMouseCallback function, void* info) {}
     62 CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name ) {return 0;}
     63 CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos) {}
     64 CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval) {}
     65 CV_IMPL void* cvGetWindowHandle( const char* name ) {return NULL;}
     66 CV_IMPL const char* cvGetWindowName( void* window_handle ) {return NULL;}
     67 CV_IMPL int cvNamedWindow( const char* name, int flags ) {return 0; }
     68 CV_IMPL int cvWaitKey (int maxWait) {return 0;}
     69 //*** end IphoneOS Stubs ***/
     70 #else
     71 
     72 #import <Cocoa/Cocoa.h>
     73 
     74 #include <iostream>
     75 
     76 const int TOP_BORDER  = 7;
     77 const int MIN_SLIDER_WIDTH=200;
     78 
     79 static NSApplication *application = nil;
     80 static NSAutoreleasePool *pool = nil;
     81 static NSMutableDictionary *windows = nil;
     82 static bool wasInitialized = false;
     83 
     84 @interface CVView : NSView {
     85     NSImage *image;
     86 }
     87 @property(retain) NSImage *image;
     88 - (void)setImageData:(CvArr *)arr;
     89 @end
     90 
     91 @interface CVSlider : NSView {
     92     NSSlider *slider;
     93     NSTextField *name;
     94     int *value;
     95     void *userData;
     96     CvTrackbarCallback callback;
     97     CvTrackbarCallback2 callback2;
     98 }
     99 @property(retain) NSSlider *slider;
    100 @property(retain) NSTextField *name;
    101 @property(assign) int *value;
    102 @property(assign) void *userData;
    103 @property(assign) CvTrackbarCallback callback;
    104 @property(assign) CvTrackbarCallback2 callback2;
    105 @end
    106 
    107 @interface CVWindow : NSWindow {
    108     NSMutableDictionary *sliders;
    109     CvMouseCallback mouseCallback;
    110     void *mouseParam;
    111     BOOL autosize;
    112     BOOL firstContent;
    113     int status;
    114 }
    115 @property(assign) CvMouseCallback mouseCallback;
    116 @property(assign) void *mouseParam;
    117 @property(assign) BOOL autosize;
    118 @property(assign) BOOL firstContent;
    119 @property(retain) NSMutableDictionary *sliders;
    120 @property(readwrite) int status;
    121 - (CVView *)contentView;
    122 - (void)cvSendMouseEvent:(NSEvent *)event type:(int)type flags:(int)flags;
    123 - (void)cvMouseEvent:(NSEvent *)event;
    124 - (void)createSliderWithName:(const char *)name maxValue:(int)max value:(int *)value callback:(CvTrackbarCallback)callback;
    125 @end
    126 
    127 /*static void icvCocoaCleanup(void)
    128 {
    129     //cout << "icvCocoaCleanup" << endl;
    130     if( application )
    131     {
    132         cvDestroyAllWindows();
    133         //[application terminate:nil];
    134         application = 0;
    135         [pool release];
    136     }
    137 }*/
    138 
    139 CV_IMPL int cvInitSystem( int , char** )
    140 {
    141     //cout << "cvInitSystem" << endl;
    142     wasInitialized = true;
    143 
    144     pool = [[NSAutoreleasePool alloc] init];
    145     application = [NSApplication sharedApplication];
    146     windows = [[NSMutableDictionary alloc] init];
    147 
    148 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
    149 
    150 #ifndef NSAppKitVersionNumber10_5
    151 #define NSAppKitVersionNumber10_5 949
    152 #endif
    153     if( floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5 )
    154         [application setActivationPolicy:NSApplicationActivationPolicyRegular];
    155 #endif
    156     //[application finishLaunching];
    157     //atexit(icvCocoaCleanup);
    158 
    159     setlocale(LC_NUMERIC,"C");
    160 
    161     return 0;
    162 }
    163 
    164 static CVWindow *cvGetWindow(const char *name) {
    165     //cout << "cvGetWindow" << endl;
    166     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    167     NSString *cvname = [NSString stringWithFormat:@"%s", name];
    168     CVWindow* retval = (CVWindow*) [windows valueForKey:cvname] ;
    169     //cout << "retain count: " << [retval retainCount] << endl;
    170     //retval = [retval retain];
    171     //cout << "retain count: " << [retval retainCount] << endl;
    172     [localpool drain];
    173     //cout << "retain count: " << [retval retainCount] << endl;
    174     return retval;
    175 }
    176 
    177 CV_IMPL int cvStartWindowThread()
    178 {
    179     //cout << "cvStartWindowThread" << endl;
    180     return 0;
    181 }
    182 
    183 CV_IMPL void cvDestroyWindow( const char* name)
    184 {
    185 
    186     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    187     //cout << "cvDestroyWindow" << endl;
    188     CVWindow *window = cvGetWindow(name);
    189     if(window) {
    190         [window close];
    191         [windows removeObjectForKey:[NSString stringWithFormat:@"%s", name]];
    192     }
    193     [localpool drain];
    194 }
    195 
    196 
    197 CV_IMPL void cvDestroyAllWindows( void )
    198 {
    199     //cout << "cvDestroyAllWindows" << endl;
    200     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    201     NSDictionary* list = [NSDictionary dictionaryWithDictionary:windows];
    202     for(NSString *key in list) {
    203         cvDestroyWindow([key cStringUsingEncoding:NSASCIIStringEncoding]);
    204     }
    205     [localpool drain];
    206 }
    207 
    208 
    209 CV_IMPL void cvShowImage( const char* name, const CvArr* arr)
    210 {
    211     //cout << "cvShowImage" << endl;
    212     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    213     CVWindow *window = cvGetWindow(name);
    214     if(!window)
    215     {
    216         cvNamedWindow(name, CV_WINDOW_AUTOSIZE);
    217         window = cvGetWindow(name);
    218     }
    219 
    220     if(window)
    221     {
    222         bool empty = [[window contentView] image] == nil;
    223         NSRect rect = [window frame];
    224         NSRect vrectOld = [[window contentView] frame];
    225 
    226         [[window contentView] setImageData:(CvArr *)arr];
    227         if([window autosize] || [window firstContent] || empty)
    228         {
    229             //Set new view size considering sliders (reserve height and min width)
    230             NSRect vrectNew = vrectOld;
    231             int slider_height = 0;
    232             for(NSString *key in [window sliders]) {
    233                 slider_height += [[[window sliders] valueForKey:key] frame].size.height;
    234             }
    235             vrectNew.size.height = [[[window contentView] image] size].height + slider_height;
    236             vrectNew.size.width = std::max<int>([[[window contentView] image] size].width, MIN_SLIDER_WIDTH);
    237             [[window contentView]  setFrameSize:vrectNew.size]; //adjust sliders to fit new window size
    238 
    239             rect.size.width += vrectNew.size.width - vrectOld.size.width;
    240             rect.size.height += vrectNew.size.height - vrectOld.size.height;
    241             rect.origin.y -= vrectNew.size.height - vrectOld.size.height;
    242 
    243             [window setFrame:rect display:YES];
    244         }
    245         else
    246             [window display];
    247         [window setFirstContent:NO];
    248     }
    249     [localpool drain];
    250 }
    251 
    252 CV_IMPL void cvResizeWindow( const char* name, int width, int height)
    253 {
    254 
    255     //cout << "cvResizeWindow" << endl;
    256     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    257     CVWindow *window = cvGetWindow(name);
    258     if(window && ![window autosize]) {
    259         NSRect frame = [window frame];
    260         frame.size.width = width;
    261         frame.size.height = height;
    262         [window setFrame:frame display:YES];
    263     }
    264     [localpool drain];
    265 }
    266 
    267 CV_IMPL void cvMoveWindow( const char* name, int x, int y)
    268 {
    269 
    270     CV_FUNCNAME("cvMoveWindow");
    271     __BEGIN__;
    272 
    273     NSAutoreleasePool* localpool1 = [[NSAutoreleasePool alloc] init];
    274     CVWindow *window = nil;
    275 
    276     if(name == NULL)
    277         CV_ERROR( CV_StsNullPtr, "NULL window name" );
    278     //cout << "cvMoveWindow"<< endl;
    279     window = cvGetWindow(name);
    280     if(window) {
    281         y = [[window screen] frame].size.height - y;
    282         [window setFrameTopLeftPoint:NSMakePoint(x, y)];
    283     }
    284     [localpool1 drain];
    285 
    286     __END__;
    287 }
    288 
    289 CV_IMPL int cvCreateTrackbar (const char* trackbar_name,
    290                               const char* window_name,
    291                               int* val, int count,
    292                               CvTrackbarCallback on_notify)
    293 {
    294     CV_FUNCNAME("cvCreateTrackbar");
    295 
    296 
    297     int result = 0;
    298     CVWindow *window = nil;
    299     NSAutoreleasePool* localpool2 = nil;
    300 
    301     __BEGIN__;
    302     if (localpool2 != nil) [localpool2 drain];
    303     localpool2 = [[NSAutoreleasePool alloc] init];
    304 
    305     if(window_name == NULL)
    306         CV_ERROR( CV_StsNullPtr, "NULL window name" );
    307 
    308     //cout << "cvCreateTrackbar" << endl ;
    309     window = cvGetWindow(window_name);
    310     if(window) {
    311         [window createSliderWithName:trackbar_name
    312                             maxValue:count
    313                                value:val
    314                             callback:on_notify];
    315         result = 1;
    316     }
    317     [localpool2 drain];
    318     __END__;
    319     return result;
    320 }
    321 
    322 
    323 CV_IMPL int cvCreateTrackbar2(const char* trackbar_name,
    324                               const char* window_name,
    325                               int* val, int count,
    326                               CvTrackbarCallback2 on_notify2,
    327                               void* userdata)
    328 {
    329     //cout <<"cvCreateTrackbar2" << endl;
    330     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    331     int res = cvCreateTrackbar(trackbar_name, window_name, val, count, NULL);
    332     if(res) {
    333         CVSlider *slider = [[cvGetWindow(window_name) sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]];
    334         [slider setCallback2:on_notify2];
    335         [slider setUserData:userdata];
    336     }
    337     [localpool drain];
    338     return res;
    339 }
    340 
    341 
    342 CV_IMPL void
    343 cvSetMouseCallback( const char* name, CvMouseCallback function, void* info)
    344 {
    345     CV_FUNCNAME("cvSetMouseCallback");
    346 
    347     CVWindow *window = nil;
    348     NSAutoreleasePool* localpool3 = nil;
    349     __BEGIN__;
    350     //cout << "cvSetMouseCallback" << endl;
    351 
    352     if (localpool3 != nil) [localpool3 drain];
    353     localpool3 = [[NSAutoreleasePool alloc] init];
    354 
    355     if(name == NULL)
    356         CV_ERROR( CV_StsNullPtr, "NULL window name" );
    357 
    358     window = cvGetWindow(name);
    359     if(window) {
    360         [window setMouseCallback:function];
    361         [window setMouseParam:info];
    362     }
    363     [localpool3 drain];
    364 
    365     __END__;
    366 }
    367 
    368  CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
    369 {
    370     CV_FUNCNAME("cvGetTrackbarPos");
    371 
    372     CVWindow *window = nil;
    373     int pos = -1;
    374     NSAutoreleasePool* localpool4 = nil;
    375     __BEGIN__;
    376 
    377     //cout << "cvGetTrackbarPos" << endl;
    378     if(trackbar_name == NULL || window_name == NULL)
    379         CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
    380 
    381     if (localpool4 != nil) [localpool4 drain];
    382     localpool4 = [[NSAutoreleasePool alloc] init];
    383 
    384     window = cvGetWindow(window_name);
    385     if(window) {
    386         CVSlider *slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]];
    387         if(slider) {
    388             pos = [[slider slider] intValue];
    389         }
    390     }
    391     [localpool4 drain];
    392     __END__;
    393     return pos;
    394 }
    395 
    396 CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos)
    397 {
    398     CV_FUNCNAME("cvSetTrackbarPos");
    399 
    400     CVWindow *window = nil;
    401     CVSlider *slider = nil;
    402     NSAutoreleasePool* localpool5 = nil;
    403 
    404     __BEGIN__;
    405     //cout << "cvSetTrackbarPos" << endl;
    406     if(trackbar_name == NULL || window_name == NULL)
    407         CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
    408 
    409     if(pos < 0)
    410         CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
    411 
    412     if (localpool5 != nil) [localpool5 drain];
    413     localpool5 = [[NSAutoreleasePool alloc] init];
    414 
    415     window = cvGetWindow(window_name);
    416     if(window) {
    417         slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]];
    418         if(slider) {
    419             [[slider slider] setIntValue:pos];
    420         }
    421     }
    422     [localpool5 drain];
    423 
    424     __END__;
    425 }
    426 
    427 CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval)
    428 {
    429     CV_FUNCNAME("cvSetTrackbarPos");
    430 
    431     CVWindow *window = nil;
    432     CVSlider *slider = nil;
    433     NSAutoreleasePool* localpool5 = nil;
    434 
    435     __BEGIN__;
    436     //cout << "cvSetTrackbarPos" << endl;
    437     if(trackbar_name == NULL || window_name == NULL)
    438         CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
    439 
    440     if (localpool5 != nil) [localpool5 drain];
    441     localpool5 = [[NSAutoreleasePool alloc] init];
    442 
    443     window = cvGetWindow(window_name);
    444     if(window) {
    445         slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]];
    446         if(slider) {
    447             if(maxval >= 0) {
    448                 [[slider slider] setMaxValue:maxval];
    449             }
    450         }
    451     }
    452     [localpool5 drain];
    453 
    454     __END__;
    455 }
    456 
    457 CV_IMPL void* cvGetWindowHandle( const char* name )
    458 {
    459     //cout << "cvGetWindowHandle" << endl;
    460     return cvGetWindow(name);
    461 }
    462 
    463 
    464 CV_IMPL const char* cvGetWindowName( void* window_handle )
    465 {
    466     //cout << "cvGetWindowName" << endl;
    467     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    468     for(NSString *key in windows) {
    469         if([windows valueForKey:key] == window_handle) {
    470             [localpool drain];
    471             return [key UTF8String];
    472         }
    473     }
    474     [localpool drain];
    475     return 0;
    476 }
    477 
    478 CV_IMPL int cvNamedWindow( const char* name, int flags )
    479 {
    480     if( !wasInitialized )
    481         cvInitSystem(0, 0);
    482 
    483     //cout << "cvNamedWindow" << endl;
    484     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    485     CVWindow *window = cvGetWindow(name);
    486     if( window )
    487     {
    488         [window setAutosize:(flags == CV_WINDOW_AUTOSIZE)];
    489         [localpool drain];
    490         return 0;
    491     }
    492 
    493     NSScreen* mainDisplay = [NSScreen mainScreen];
    494 
    495     NSString *windowName = [NSString stringWithFormat:@"%s", name];
    496     NSUInteger showResize = (flags == CV_WINDOW_AUTOSIZE) ? 0: NSResizableWindowMask ;
    497     NSUInteger styleMask = NSTitledWindowMask|NSMiniaturizableWindowMask|showResize;
    498     CGFloat windowWidth = [NSWindow minFrameWidthWithTitle:windowName styleMask:styleMask];
    499     NSRect initContentRect = NSMakeRect(0, 0, windowWidth, 0);
    500     if (mainDisplay) {
    501         NSRect dispFrame = [mainDisplay visibleFrame];
    502         initContentRect.origin.y = dispFrame.size.height-20;
    503     }
    504 
    505 
    506     window = [[CVWindow alloc] initWithContentRect:initContentRect
    507                                          styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|showResize
    508                                            backing:NSBackingStoreBuffered
    509                                              defer:YES
    510                                             screen:mainDisplay];
    511 
    512     [window setFrameTopLeftPoint:initContentRect.origin];
    513 
    514     [window setFirstContent:YES];
    515 
    516     [window setContentView:[[CVView alloc] init]];
    517 
    518     [window setHasShadow:YES];
    519     [window setAcceptsMouseMovedEvents:YES];
    520     [window useOptimizedDrawing:YES];
    521     [window setTitle:windowName];
    522     [window makeKeyAndOrderFront:nil];
    523 
    524     [window setAutosize:(flags == CV_WINDOW_AUTOSIZE)];
    525 
    526     [windows setValue:window forKey:windowName];
    527 
    528     [localpool drain];
    529     return [windows count]-1;
    530 }
    531 
    532 CV_IMPL int cvWaitKey (int maxWait)
    533 {
    534     //cout << "cvWaitKey" << endl;
    535     int returnCode = -1;
    536     NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init];
    537     double start = [[NSDate date] timeIntervalSince1970];
    538 
    539     while(true) {
    540         if(([[NSDate date] timeIntervalSince1970] - start) * 1000 >= maxWait && maxWait>0)
    541             break;
    542 
    543         //event = [application currentEvent];
    544         [localpool drain];
    545         localpool = [[NSAutoreleasePool alloc] init];
    546 
    547         NSEvent *event =
    548         [application
    549          nextEventMatchingMask:NSAnyEventMask
    550          untilDate://[NSDate dateWithTimeIntervalSinceNow: 1./100]
    551          [NSDate distantPast]
    552          inMode:NSDefaultRunLoopMode
    553          dequeue:YES];
    554 
    555         if([event type] == NSKeyDown) {
    556             returnCode = [[event characters] characterAtIndex:0];
    557             break;
    558         }
    559 
    560         [application sendEvent:event];
    561         [application updateWindows];
    562 
    563         [NSThread sleepForTimeInterval:1/100.];
    564     }
    565     [localpool drain];
    566 
    567     return returnCode;
    568 }
    569 
    570 double cvGetModeWindow_COCOA( const char* name )
    571 {
    572     double result = -1;
    573     CVWindow *window = nil;
    574 
    575     CV_FUNCNAME( "cvGetModeWindow_COCOA" );
    576 
    577     __BEGIN__;
    578     if( name == NULL )
    579     {
    580         CV_ERROR( CV_StsNullPtr, "NULL name string" );
    581     }
    582 
    583     window = cvGetWindow( name );
    584     if ( window == NULL )
    585     {
    586         CV_ERROR( CV_StsNullPtr, "NULL window" );
    587     }
    588 
    589     result = window.status;
    590 
    591     __END__;
    592     return result;
    593 }
    594 
    595 void cvSetModeWindow_COCOA( const char* name, double prop_value )
    596 {
    597     CVWindow *window = nil;
    598     NSDictionary *fullscreenOptions = nil;
    599     NSAutoreleasePool* localpool = nil;
    600 
    601     CV_FUNCNAME( "cvSetModeWindow_COCOA" );
    602 
    603     __BEGIN__;
    604     if( name == NULL )
    605     {
    606         CV_ERROR( CV_StsNullPtr, "NULL name string" );
    607     }
    608 
    609     window = cvGetWindow(name);
    610     if ( window == NULL )
    611     {
    612         CV_ERROR( CV_StsNullPtr, "NULL window" );
    613     }
    614 
    615     if ( [window autosize] )
    616     {
    617         return;
    618     }
    619 
    620     localpool = [[NSAutoreleasePool alloc] init];
    621 
    622     fullscreenOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:NSFullScreenModeSetting];
    623     if ( [[window contentView] isInFullScreenMode] && prop_value==CV_WINDOW_NORMAL )
    624     {
    625         [[window contentView] exitFullScreenModeWithOptions:fullscreenOptions];
    626         window.status=CV_WINDOW_NORMAL;
    627     }
    628     else if( ![[window contentView] isInFullScreenMode] && prop_value==CV_WINDOW_FULLSCREEN )
    629     {
    630         [[window contentView] enterFullScreenMode:[NSScreen mainScreen] withOptions:fullscreenOptions];
    631         window.status=CV_WINDOW_FULLSCREEN;
    632     }
    633 
    634     [localpool drain];
    635 
    636     __END__;
    637 }
    638 
    639 void cv::setWindowTitle(const String& winname, const String& title)
    640 {
    641     CVWindow *window = cvGetWindow(winname.c_str());
    642 
    643     if (window == NULL)
    644     {
    645         namedWindow(winname);
    646         window = cvGetWindow(winname.c_str());
    647     }
    648 
    649     if (window == NULL)
    650         CV_Error(Error::StsNullPtr, "NULL window");
    651 
    652     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    653 
    654     NSString *windowTitle = [NSString stringWithFormat:@"%s", title.c_str()];
    655     [window setTitle:windowTitle];
    656 
    657     [localpool drain];
    658 }
    659 
    660 @implementation CVWindow
    661 
    662 @synthesize mouseCallback;
    663 @synthesize mouseParam;
    664 @synthesize autosize;
    665 @synthesize firstContent;
    666 @synthesize sliders;
    667 @synthesize status;
    668 
    669 - (void)cvSendMouseEvent:(NSEvent *)event type:(int)type flags:(int)flags {
    670     (void)event;
    671     //cout << "cvSendMouseEvent" << endl;
    672     NSPoint mp = [NSEvent mouseLocation];
    673     //NSRect visible = [[self contentView] frame];
    674     mp = [self convertScreenToBase: mp];
    675     double viewHeight = [self contentView].frame.size.height;
    676     double viewWidth = [self contentView].frame.size.width;
    677     CVWindow *window = (CVWindow *)[[self contentView] window];
    678     for(NSString *key in [window sliders]) {
    679         NSSlider *slider = [[window sliders] valueForKey:key];
    680         viewHeight = std::min(viewHeight, (double)([slider frame].origin.y));
    681     }
    682     viewHeight -= TOP_BORDER;
    683     mp.y = viewHeight - mp.y;
    684 
    685     NSImage* image = ((CVView*)[self contentView]).image;
    686     NSSize imageSize = [image size];
    687     mp.x = mp.x * imageSize.width / std::max(viewWidth, 1.);
    688     mp.y = mp.y * imageSize.height / std::max(viewHeight, 1.);
    689 
    690     if( mp.x >= 0 && mp.y >= 0 && mp.x < imageSize.width && mp.y < imageSize.height )
    691         mouseCallback(type, mp.x, mp.y, flags, mouseParam);
    692 }
    693 
    694 - (void)cvMouseEvent:(NSEvent *)event {
    695     //cout << "cvMouseEvent" << endl;
    696     if(!mouseCallback)
    697         return;
    698 
    699     int flags = 0;
    700     if([event modifierFlags] & NSShiftKeyMask)		flags |= CV_EVENT_FLAG_SHIFTKEY;
    701     if([event modifierFlags] & NSControlKeyMask)	flags |= CV_EVENT_FLAG_CTRLKEY;
    702     if([event modifierFlags] & NSAlternateKeyMask)	flags |= CV_EVENT_FLAG_ALTKEY;
    703 
    704     if([event type] == NSLeftMouseDown)	{[self cvSendMouseEvent:event type:CV_EVENT_LBUTTONDOWN flags:flags | CV_EVENT_FLAG_LBUTTON];}
    705     if([event type] == NSLeftMouseUp)	{[self cvSendMouseEvent:event type:CV_EVENT_LBUTTONUP   flags:flags | CV_EVENT_FLAG_LBUTTON];}
    706     if([event type] == NSRightMouseDown){[self cvSendMouseEvent:event type:CV_EVENT_RBUTTONDOWN flags:flags | CV_EVENT_FLAG_RBUTTON];}
    707     if([event type] == NSRightMouseUp)	{[self cvSendMouseEvent:event type:CV_EVENT_RBUTTONUP   flags:flags | CV_EVENT_FLAG_RBUTTON];}
    708     if([event type] == NSOtherMouseDown){[self cvSendMouseEvent:event type:CV_EVENT_MBUTTONDOWN flags:flags];}
    709     if([event type] == NSOtherMouseUp)	{[self cvSendMouseEvent:event type:CV_EVENT_MBUTTONUP   flags:flags];}
    710     if([event type] == NSMouseMoved)	{[self cvSendMouseEvent:event type:CV_EVENT_MOUSEMOVE   flags:flags];}
    711     if([event type] == NSLeftMouseDragged) {[self cvSendMouseEvent:event type:CV_EVENT_MOUSEMOVE   flags:flags | CV_EVENT_FLAG_LBUTTON];}
    712     if([event type] == NSRightMouseDragged)	{[self cvSendMouseEvent:event type:CV_EVENT_MOUSEMOVE   flags:flags | CV_EVENT_FLAG_RBUTTON];}
    713     if([event type] == NSOtherMouseDragged)	{[self cvSendMouseEvent:event type:CV_EVENT_MOUSEMOVE   flags:flags | CV_EVENT_FLAG_MBUTTON];}
    714 }
    715 - (void)keyDown:(NSEvent *)theEvent {
    716     //cout << "keyDown" << endl;
    717     [super keyDown:theEvent];
    718 }
    719 - (void)rightMouseDragged:(NSEvent *)theEvent {
    720     //cout << "rightMouseDragged" << endl ;
    721     [self cvMouseEvent:theEvent];
    722 }
    723 - (void)rightMouseUp:(NSEvent *)theEvent {
    724     //cout << "rightMouseUp" << endl;
    725     [self cvMouseEvent:theEvent];
    726 }
    727 - (void)rightMouseDown:(NSEvent *)theEvent {
    728     // Does not seem to work?
    729     //cout << "rightMouseDown" << endl;
    730     [self cvMouseEvent:theEvent];
    731 }
    732 - (void)mouseMoved:(NSEvent *)theEvent {
    733     [self cvMouseEvent:theEvent];
    734 }
    735 - (void)otherMouseDragged:(NSEvent *)theEvent {
    736     [self cvMouseEvent:theEvent];
    737 }
    738 - (void)otherMouseUp:(NSEvent *)theEvent {
    739     [self cvMouseEvent:theEvent];
    740 }
    741 - (void)otherMouseDown:(NSEvent *)theEvent {
    742     [self cvMouseEvent:theEvent];
    743 }
    744 - (void)mouseDragged:(NSEvent *)theEvent {
    745     [self cvMouseEvent:theEvent];
    746 }
    747 - (void)mouseUp:(NSEvent *)theEvent {
    748     [self cvMouseEvent:theEvent];
    749 }
    750 - (void)mouseDown:(NSEvent *)theEvent {
    751     [self cvMouseEvent:theEvent];
    752 }
    753 
    754 - (void)createSliderWithName:(const char *)name maxValue:(int)max value:(int *)value callback:(CvTrackbarCallback)callback {
    755     //cout << "createSliderWithName" << endl;
    756     if(sliders == nil)
    757         sliders = [[NSMutableDictionary alloc] init];
    758 
    759     NSString *cvname = [NSString stringWithFormat:@"%s", name];
    760 
    761     // Avoid overwriting slider
    762     if([sliders valueForKey:cvname]!=nil)
    763         return;
    764 
    765     // Create slider
    766     CVSlider *slider = [[CVSlider alloc] init];
    767     [[slider name] setStringValue:cvname];
    768     [[slider slider] setMaxValue:max];
    769     [[slider slider] setMinValue:0];
    770     [[slider slider] setNumberOfTickMarks:(max+1)];
    771     [[slider slider] setAllowsTickMarkValuesOnly:YES];
    772     if(value)
    773     {
    774         [[slider slider] setIntValue:*value];
    775         [slider setValue:value];
    776     }
    777     if(callback)
    778         [slider setCallback:callback];
    779 
    780     // Save slider
    781     [sliders setValue:slider forKey:cvname];
    782     [[self contentView] addSubview:slider];
    783 
    784 
    785     //update contentView size to contain sliders
    786     NSSize viewSize=[[self contentView] frame].size,
    787            sliderSize=[slider frame].size;
    788     viewSize.height += sliderSize.height;
    789     viewSize.width = std::max<int>(viewSize.width, MIN_SLIDER_WIDTH);
    790 
    791     // Update slider sizes
    792     [[self contentView] setFrameSize:viewSize];
    793     [[self contentView] setNeedsDisplay:YES];
    794 
    795     //update window size to contain sliders
    796     NSRect rect = [self frame];
    797     rect.size.height += [slider frame].size.height;
    798     rect.size.width = std::max<int>(rect.size.width, MIN_SLIDER_WIDTH);
    799     [self setFrame:rect display:YES];
    800 
    801 
    802 
    803 }
    804 
    805 - (CVView *)contentView {
    806     return (CVView*)[super contentView];
    807 }
    808 
    809 @end
    810 
    811 @implementation CVView
    812 
    813 @synthesize image;
    814 
    815 - (id)init {
    816     //cout << "CVView init" << endl;
    817     [super init];
    818     image = [[NSImage alloc] init];
    819     return self;
    820 }
    821 
    822 - (void)setImageData:(CvArr *)arr {
    823     //cout << "setImageData" << endl;
    824     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    825     CvMat *arrMat, *cvimage, stub;
    826 
    827     arrMat = cvGetMat(arr, &stub);
    828 
    829     cvimage = cvCreateMat(arrMat->rows, arrMat->cols, CV_8UC3);
    830     cvConvertImage(arrMat, cvimage, CV_CVTIMG_SWAP_RB);
    831 
    832     /*CGColorSpaceRef colorspace = NULL;
    833     CGDataProviderRef provider = NULL;
    834     int width = cvimage->width;
    835     int height = cvimage->height;
    836 
    837     colorspace = CGColorSpaceCreateDeviceRGB();
    838 
    839     int size = 8;
    840     int nbChannels = 3;
    841 
    842     provider = CGDataProviderCreateWithData(NULL, cvimage->data.ptr, width * height , NULL );
    843 
    844     CGImageRef imageRef = CGImageCreate(width, height, size , size*nbChannels , cvimage->step, colorspace,  kCGImageAlphaNone , provider, NULL, true, kCGRenderingIntentDefault);
    845 
    846     NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:imageRef];
    847     if(image) {
    848         [image release];
    849     }*/
    850 
    851     NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
    852                 pixelsWide:cvimage->width
    853                 pixelsHigh:cvimage->height
    854                 bitsPerSample:8
    855                 samplesPerPixel:3
    856                 hasAlpha:NO
    857                 isPlanar:NO
    858                 colorSpaceName:NSDeviceRGBColorSpace
    859                 bytesPerRow:(cvimage->width * 4)
    860                 bitsPerPixel:32];
    861 
    862     int	pixelCount = cvimage->width * cvimage->height;
    863     unsigned char *src = cvimage->data.ptr;
    864     unsigned char *dst = [bitmap bitmapData];
    865 
    866     for( int i = 0; i < pixelCount; i++ )
    867     {
    868         dst[i * 4 + 0] = src[i * 3 + 0];
    869         dst[i * 4 + 1] = src[i * 3 + 1];
    870         dst[i * 4 + 2] = src[i * 3 + 2];
    871     }
    872 
    873     if( image )
    874         [image release];
    875 
    876     image = [[NSImage alloc] init];
    877     [image addRepresentation:bitmap];
    878     [bitmap release];
    879 
    880     /*CGColorSpaceRelease(colorspace);
    881     CGDataProviderRelease(provider);
    882     CGImageRelease(imageRef);*/
    883     cvReleaseMat(&cvimage);
    884     [localpool drain];
    885 
    886     [self setNeedsDisplay:YES];
    887 
    888 }
    889 
    890 - (void)setFrameSize:(NSSize)size {
    891     //cout << "setFrameSize" << endl;
    892     [super setFrameSize:size];
    893 
    894     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    895     int height = size.height;
    896 
    897     CVWindow *cvwindow = (CVWindow *)[self window];
    898     for(NSString *key in [cvwindow sliders]) {
    899         NSSlider *slider = [[cvwindow sliders] valueForKey:key];
    900         NSRect r = [slider frame];
    901         r.origin.y = height - r.size.height;
    902         r.size.width = [[cvwindow contentView] frame].size.width;
    903         [slider setFrame:r];
    904         height -= r.size.height;
    905     }
    906     [localpool drain];
    907 }
    908 
    909 - (void)drawRect:(NSRect)rect {
    910     //cout << "drawRect" << endl;
    911     [super drawRect:rect];
    912 
    913     NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
    914     CVWindow *cvwindow = (CVWindow *)[self window];
    915     int height = 0;
    916     if ([cvwindow respondsToSelector:@selector(sliders)]) {
    917         for(NSString *key in [cvwindow sliders]) {
    918             height += [[[cvwindow sliders] valueForKey:key] frame].size.height;
    919         }
    920     }
    921 
    922 
    923     NSRect imageRect = {{0,0}, {[image size].width, [image size].height}};
    924 
    925     if(image != nil) {
    926         [image drawInRect: imageRect
    927                               fromRect: NSZeroRect
    928                              operation: NSCompositeSourceOver
    929                               fraction: 1.0];
    930     }
    931     [localpool release];
    932 
    933 }
    934 
    935 @end
    936 
    937 @implementation CVSlider
    938 
    939 @synthesize slider;
    940 @synthesize name;
    941 @synthesize value;
    942 @synthesize userData;
    943 @synthesize callback;
    944 @synthesize callback2;
    945 
    946 - (id)init {
    947     [super init];
    948 
    949     callback = NULL;
    950     value = NULL;
    951     userData = NULL;
    952 
    953     [self setFrame:NSMakeRect(0,0,200,30)];
    954 
    955     name = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 0,110, 25)];
    956     [name setEditable:NO];
    957     [name setSelectable:NO];
    958     [name setBezeled:NO];
    959     [name setBordered:NO];
    960     [name setDrawsBackground:NO];
    961     [[name cell] setLineBreakMode:NSLineBreakByTruncatingTail];
    962     [self addSubview:name];
    963 
    964     slider = [[NSSlider alloc] initWithFrame:NSMakeRect(120, 0, 70, 25)];
    965     [slider setAutoresizingMask:NSViewWidthSizable];
    966     [slider setMinValue:0];
    967     [slider setMaxValue:100];
    968     [slider setContinuous:YES];
    969     [slider setTarget:self];
    970     [slider setAction:@selector(sliderChanged:)];
    971     [self addSubview:slider];
    972 
    973     [self setAutoresizingMask:NSViewWidthSizable];
    974 
    975     //[self setFrame:NSMakeRect(12, 0, 100, 30)];
    976 
    977     return self;
    978 }
    979 
    980 - (void)sliderChanged:(NSNotification *)notification {
    981     (void)notification;
    982     int pos = [slider intValue];
    983     if(value)
    984         *value = pos;
    985     if(callback)
    986         callback(pos);
    987     if(callback2)
    988         callback2(pos, userData);
    989 }
    990 
    991 @end
    992 
    993 #endif
    994 
    995 /* End of file. */
    996