• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
50CV_IMPL int cvInitSystem( int argc, char** argv) { return 0;}
51CV_IMPL int cvStartWindowThread(){ return 0; }
52CV_IMPL void cvDestroyWindow( const char* name) {}
53CV_IMPL void cvDestroyAllWindows( void ) {}
54CV_IMPL void cvShowImage( const char* name, const CvArr* arr) {}
55CV_IMPL void cvResizeWindow( const char* name, int width, int height) {}
56CV_IMPL void cvMoveWindow( const char* name, int x, int y){}
57CV_IMPL int cvCreateTrackbar (const char* trackbar_name,const char* window_name,
58                              int* val, int count, CvTrackbarCallback on_notify) {return  0;}
59CV_IMPL int cvCreateTrackbar2(const char* trackbar_name,const char* window_name,
60                              int* val, int count, CvTrackbarCallback2 on_notify2, void* userdata) {return 0;}
61CV_IMPL void cvSetMouseCallback( const char* name, CvMouseCallback function, void* info) {}
62CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name ) {return 0;}
63CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos) {}
64CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval) {}
65CV_IMPL void* cvGetWindowHandle( const char* name ) {return NULL;}
66CV_IMPL const char* cvGetWindowName( void* window_handle ) {return NULL;}
67CV_IMPL int cvNamedWindow( const char* name, int flags ) {return 0; }
68CV_IMPL int cvWaitKey (int maxWait) {return 0;}
69//*** end IphoneOS Stubs ***/
70#else
71
72#import <Cocoa/Cocoa.h>
73
74#include <iostream>
75
76const int TOP_BORDER  = 7;
77const int MIN_SLIDER_WIDTH=200;
78
79static NSApplication *application = nil;
80static NSAutoreleasePool *pool = nil;
81static NSMutableDictionary *windows = nil;
82static 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
139CV_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
164static 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
177CV_IMPL int cvStartWindowThread()
178{
179    //cout << "cvStartWindowThread" << endl;
180    return 0;
181}
182
183CV_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
197CV_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
209CV_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
252CV_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
267CV_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
289CV_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
323CV_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
342CV_IMPL void
343cvSetMouseCallback( 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
396CV_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
427CV_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
457CV_IMPL void* cvGetWindowHandle( const char* name )
458{
459    //cout << "cvGetWindowHandle" << endl;
460    return cvGetWindow(name);
461}
462
463
464CV_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
478CV_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
532CV_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
570double 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
595void 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
639void 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