1 /* The file is the modified version of window_cocoa.mm from opencv-cocoa project by Andre Cohen */
3 /*M///////////////////////////////////////////////////////////////////////////////////////
5 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
13 // For Open Source Computer Vision Library
15 // Copyright (C) 2010, Willow Garage Inc., all rights reserved.
16 // Third party copyrights are property of their respective owners.
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
21 // * Redistribution's of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
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.
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.
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.
43 #include "precomp.hpp"
45 #import <TargetConditionals.h>
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 ***/
72 #import <Cocoa/Cocoa.h>
76 const int TOP_BORDER = 7;
77 const int MIN_SLIDER_WIDTH=200;
79 static NSApplication *application = nil;
80 static NSAutoreleasePool *pool = nil;
81 static NSMutableDictionary *windows = nil;
82 static bool wasInitialized = false;
84 @interface CVView : NSView {
87 @property(retain) NSImage *image;
88 - (void)setImageData:(CvArr *)arr;
91 @interface CVSlider : NSView {
96 CvTrackbarCallback callback;
97 CvTrackbarCallback2 callback2;
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;
107 @interface CVWindow : NSWindow {
108 NSMutableDictionary *sliders;
109 CvMouseCallback mouseCallback;
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;
127 /*static void icvCocoaCleanup(void)
129 //cout << "icvCocoaCleanup" << endl;
132 cvDestroyAllWindows();
133 //[application terminate:nil];
139 CV_IMPL int cvInitSystem( int , char** )
141 //cout << "cvInitSystem" << endl;
142 wasInitialized = true;
144 pool = [[NSAutoreleasePool alloc] init];
145 application = [NSApplication sharedApplication];
146 windows = [[NSMutableDictionary alloc] init];
148 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
150 #ifndef NSAppKitVersionNumber10_5
151 #define NSAppKitVersionNumber10_5 949
153 if( floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5 )
154 [application setActivationPolicy:NSApplicationActivationPolicyRegular];
156 //[application finishLaunching];
157 //atexit(icvCocoaCleanup);
159 setlocale(LC_NUMERIC,"C");
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;
173 //cout << "retain count: " << [retval retainCount] << endl;
177 CV_IMPL int cvStartWindowThread()
179 //cout << "cvStartWindowThread" << endl;
183 CV_IMPL void cvDestroyWindow( const char* name)
186 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
187 //cout << "cvDestroyWindow" << endl;
188 CVWindow *window = cvGetWindow(name);
191 [windows removeObjectForKey:[NSString stringWithFormat:@"%s", name]];
197 CV_IMPL void cvDestroyAllWindows( void )
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]);
209 CV_IMPL void cvShowImage( const char* name, const CvArr* arr)
211 //cout << "cvShowImage" << endl;
212 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
213 CVWindow *window = cvGetWindow(name);
216 cvNamedWindow(name, CV_WINDOW_AUTOSIZE);
217 window = cvGetWindow(name);
222 bool empty = [[window contentView] image] == nil;
223 NSRect rect = [window frame];
224 NSRect vrectOld = [[window contentView] frame];
226 [[window contentView] setImageData:(CvArr *)arr];
227 if([window autosize] || [window firstContent] || empty)
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;
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
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;
243 [window setFrame:rect display:YES];
247 [window setFirstContent:NO];
252 CV_IMPL void cvResizeWindow( const char* name, int width, int height)
255 //cout << "cvResizeWindow" << endl;
256 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
257 CVWindow *window = cvGetWindow(name);
259 NSRect frame = [window frame];
260 frame.size.width = width;
261 frame.size.height = height;
262 [window setFrame:frame display:YES];
267 CV_IMPL void cvMoveWindow( const char* name, int x, int y)
270 CV_FUNCNAME("cvMoveWindow");
273 NSAutoreleasePool* localpool1 = [[NSAutoreleasePool alloc] init];
274 CVWindow *window = nil;
277 CV_ERROR( CV_StsNullPtr, "NULL window name" );
278 //cout << "cvMoveWindow"<< endl;
279 window = cvGetWindow(name);
281 y = [[window screen] frame].size.height - y;
282 [window setFrameTopLeftPoint:NSMakePoint(x, y)];
289 CV_IMPL int cvCreateTrackbar (const char* trackbar_name,
290 const char* window_name,
292 CvTrackbarCallback on_notify)
294 CV_FUNCNAME("cvCreateTrackbar");
298 CVWindow *window = nil;
299 NSAutoreleasePool* localpool2 = nil;
302 if (localpool2 != nil) [localpool2 drain];
303 localpool2 = [[NSAutoreleasePool alloc] init];
305 if(window_name == NULL)
306 CV_ERROR( CV_StsNullPtr, "NULL window name" );
308 //cout << "cvCreateTrackbar" << endl ;
309 window = cvGetWindow(window_name);
311 [window createSliderWithName:trackbar_name
323 CV_IMPL int cvCreateTrackbar2(const char* trackbar_name,
324 const char* window_name,
326 CvTrackbarCallback2 on_notify2,
329 //cout <<"cvCreateTrackbar2" << endl;
330 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
331 int res = cvCreateTrackbar(trackbar_name, window_name, val, count, NULL);
333 CVSlider *slider = [[cvGetWindow(window_name) sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]];
334 [slider setCallback2:on_notify2];
335 [slider setUserData:userdata];
343 cvSetMouseCallback( const char* name, CvMouseCallback function, void* info)
345 CV_FUNCNAME("cvSetMouseCallback");
347 CVWindow *window = nil;
348 NSAutoreleasePool* localpool3 = nil;
350 //cout << "cvSetMouseCallback" << endl;
352 if (localpool3 != nil) [localpool3 drain];
353 localpool3 = [[NSAutoreleasePool alloc] init];
356 CV_ERROR( CV_StsNullPtr, "NULL window name" );
358 window = cvGetWindow(name);
360 [window setMouseCallback:function];
361 [window setMouseParam:info];
368 CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
370 CV_FUNCNAME("cvGetTrackbarPos");
372 CVWindow *window = nil;
374 NSAutoreleasePool* localpool4 = nil;
377 //cout << "cvGetTrackbarPos" << endl;
378 if(trackbar_name == NULL || window_name == NULL)
379 CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
381 if (localpool4 != nil) [localpool4 drain];
382 localpool4 = [[NSAutoreleasePool alloc] init];
384 window = cvGetWindow(window_name);
386 CVSlider *slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]];
388 pos = [[slider slider] intValue];
396 CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos)
398 CV_FUNCNAME("cvSetTrackbarPos");
400 CVWindow *window = nil;
401 CVSlider *slider = nil;
402 NSAutoreleasePool* localpool5 = nil;
405 //cout << "cvSetTrackbarPos" << endl;
406 if(trackbar_name == NULL || window_name == NULL)
407 CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
410 CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
412 if (localpool5 != nil) [localpool5 drain];
413 localpool5 = [[NSAutoreleasePool alloc] init];
415 window = cvGetWindow(window_name);
417 slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]];
419 [[slider slider] setIntValue:pos];
427 CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval)
429 CV_FUNCNAME("cvSetTrackbarPos");
431 CVWindow *window = nil;
432 CVSlider *slider = nil;
433 NSAutoreleasePool* localpool5 = nil;
436 //cout << "cvSetTrackbarPos" << endl;
437 if(trackbar_name == NULL || window_name == NULL)
438 CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
440 if (localpool5 != nil) [localpool5 drain];
441 localpool5 = [[NSAutoreleasePool alloc] init];
443 window = cvGetWindow(window_name);
445 slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]];
448 [[slider slider] setMaxValue:maxval];
457 CV_IMPL void* cvGetWindowHandle( const char* name )
459 //cout << "cvGetWindowHandle" << endl;
460 return cvGetWindow(name);
464 CV_IMPL const char* cvGetWindowName( void* window_handle )
466 //cout << "cvGetWindowName" << endl;
467 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
468 for(NSString *key in windows) {
469 if([windows valueForKey:key] == window_handle) {
471 return [key UTF8String];
478 CV_IMPL int cvNamedWindow( const char* name, int flags )
480 if( !wasInitialized )
483 //cout << "cvNamedWindow" << endl;
484 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
485 CVWindow *window = cvGetWindow(name);
488 [window setAutosize:(flags == CV_WINDOW_AUTOSIZE)];
493 NSScreen* mainDisplay = [NSScreen mainScreen];
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);
501 NSRect dispFrame = [mainDisplay visibleFrame];
502 initContentRect.origin.y = dispFrame.size.height-20;
506 window = [[CVWindow alloc] initWithContentRect:initContentRect
507 styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|showResize
508 backing:NSBackingStoreBuffered
512 [window setFrameTopLeftPoint:initContentRect.origin];
514 [window setFirstContent:YES];
516 [window setContentView:[[CVView alloc] init]];
518 [window setHasShadow:YES];
519 [window setAcceptsMouseMovedEvents:YES];
520 [window useOptimizedDrawing:YES];
521 [window setTitle:windowName];
522 [window makeKeyAndOrderFront:nil];
524 [window setAutosize:(flags == CV_WINDOW_AUTOSIZE)];
526 [windows setValue:window forKey:windowName];
529 return [windows count]-1;
532 CV_IMPL int cvWaitKey (int maxWait)
534 //cout << "cvWaitKey" << endl;
536 NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init];
537 double start = [[NSDate date] timeIntervalSince1970];
540 if(([[NSDate date] timeIntervalSince1970] - start) * 1000 >= maxWait && maxWait>0)
543 //event = [application currentEvent];
545 localpool = [[NSAutoreleasePool alloc] init];
549 nextEventMatchingMask:NSAnyEventMask
550 untilDate://[NSDate dateWithTimeIntervalSinceNow: 1./100]
552 inMode:NSDefaultRunLoopMode
555 if([event type] == NSKeyDown) {
556 returnCode = [[event characters] characterAtIndex:0];
560 [application sendEvent:event];
561 [application updateWindows];
563 [NSThread sleepForTimeInterval:1/100.];
570 double cvGetModeWindow_COCOA( const char* name )
573 CVWindow *window = nil;
575 CV_FUNCNAME( "cvGetModeWindow_COCOA" );
580 CV_ERROR( CV_StsNullPtr, "NULL name string" );
583 window = cvGetWindow( name );
584 if ( window == NULL )
586 CV_ERROR( CV_StsNullPtr, "NULL window" );
589 result = window.status;
595 void cvSetModeWindow_COCOA( const char* name, double prop_value )
597 CVWindow *window = nil;
598 NSDictionary *fullscreenOptions = nil;
599 NSAutoreleasePool* localpool = nil;
601 CV_FUNCNAME( "cvSetModeWindow_COCOA" );
606 CV_ERROR( CV_StsNullPtr, "NULL name string" );
609 window = cvGetWindow(name);
610 if ( window == NULL )
612 CV_ERROR( CV_StsNullPtr, "NULL window" );
615 if ( [window autosize] )
620 localpool = [[NSAutoreleasePool alloc] init];
622 fullscreenOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:NSFullScreenModeSetting];
623 if ( [[window contentView] isInFullScreenMode] && prop_value==CV_WINDOW_NORMAL )
625 [[window contentView] exitFullScreenModeWithOptions:fullscreenOptions];
626 window.status=CV_WINDOW_NORMAL;
628 else if( ![[window contentView] isInFullScreenMode] && prop_value==CV_WINDOW_FULLSCREEN )
630 [[window contentView] enterFullScreenMode:[NSScreen mainScreen] withOptions:fullscreenOptions];
631 window.status=CV_WINDOW_FULLSCREEN;
639 void cv::setWindowTitle(const String& winname, const String& title)
641 CVWindow *window = cvGetWindow(winname.c_str());
645 namedWindow(winname);
646 window = cvGetWindow(winname.c_str());
650 CV_Error(Error::StsNullPtr, "NULL window");
652 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
654 NSString *windowTitle = [NSString stringWithFormat:@"%s", title.c_str()];
655 [window setTitle:windowTitle];
660 @implementation CVWindow
662 @synthesize mouseCallback;
663 @synthesize mouseParam;
664 @synthesize autosize;
665 @synthesize firstContent;
669 - (void)cvSendMouseEvent:(NSEvent *)event type:(int)type flags:(int)flags {
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));
682 viewHeight -= TOP_BORDER;
683 mp.y = viewHeight - mp.y;
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.);
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);
694 - (void)cvMouseEvent:(NSEvent *)event {
695 //cout << "cvMouseEvent" << endl;
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;
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];}
715 - (void)keyDown:(NSEvent *)theEvent {
716 //cout << "keyDown" << endl;
717 [super keyDown:theEvent];
719 - (void)rightMouseDragged:(NSEvent *)theEvent {
720 //cout << "rightMouseDragged" << endl ;
721 [self cvMouseEvent:theEvent];
723 - (void)rightMouseUp:(NSEvent *)theEvent {
724 //cout << "rightMouseUp" << endl;
725 [self cvMouseEvent:theEvent];
727 - (void)rightMouseDown:(NSEvent *)theEvent {
728 // Does not seem to work?
729 //cout << "rightMouseDown" << endl;
730 [self cvMouseEvent:theEvent];
732 - (void)mouseMoved:(NSEvent *)theEvent {
733 [self cvMouseEvent:theEvent];
735 - (void)otherMouseDragged:(NSEvent *)theEvent {
736 [self cvMouseEvent:theEvent];
738 - (void)otherMouseUp:(NSEvent *)theEvent {
739 [self cvMouseEvent:theEvent];
741 - (void)otherMouseDown:(NSEvent *)theEvent {
742 [self cvMouseEvent:theEvent];
744 - (void)mouseDragged:(NSEvent *)theEvent {
745 [self cvMouseEvent:theEvent];
747 - (void)mouseUp:(NSEvent *)theEvent {
748 [self cvMouseEvent:theEvent];
750 - (void)mouseDown:(NSEvent *)theEvent {
751 [self cvMouseEvent:theEvent];
754 - (void)createSliderWithName:(const char *)name maxValue:(int)max value:(int *)value callback:(CvTrackbarCallback)callback {
755 //cout << "createSliderWithName" << endl;
757 sliders = [[NSMutableDictionary alloc] init];
759 NSString *cvname = [NSString stringWithFormat:@"%s", name];
761 // Avoid overwriting slider
762 if([sliders valueForKey:cvname]!=nil)
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];
774 [[slider slider] setIntValue:*value];
775 [slider setValue:value];
778 [slider setCallback:callback];
781 [sliders setValue:slider forKey:cvname];
782 [[self contentView] addSubview:slider];
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);
791 // Update slider sizes
792 [[self contentView] setFrameSize:viewSize];
793 [[self contentView] setNeedsDisplay:YES];
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];
805 - (CVView *)contentView {
806 return (CVView*)[super contentView];
811 @implementation CVView
816 //cout << "CVView init" << endl;
818 image = [[NSImage alloc] init];
822 - (void)setImageData:(CvArr *)arr {
823 //cout << "setImageData" << endl;
824 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
825 CvMat *arrMat, *cvimage, stub;
827 arrMat = cvGetMat(arr, &stub);
829 cvimage = cvCreateMat(arrMat->rows, arrMat->cols, CV_8UC3);
830 cvConvertImage(arrMat, cvimage, CV_CVTIMG_SWAP_RB);
832 /*CGColorSpaceRef colorspace = NULL;
833 CGDataProviderRef provider = NULL;
834 int width = cvimage->width;
835 int height = cvimage->height;
837 colorspace = CGColorSpaceCreateDeviceRGB();
842 provider = CGDataProviderCreateWithData(NULL, cvimage->data.ptr, width * height , NULL );
844 CGImageRef imageRef = CGImageCreate(width, height, size , size*nbChannels , cvimage->step, colorspace, kCGImageAlphaNone , provider, NULL, true, kCGRenderingIntentDefault);
846 NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:imageRef];
851 NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
852 pixelsWide:cvimage->width
853 pixelsHigh:cvimage->height
858 colorSpaceName:NSDeviceRGBColorSpace
859 bytesPerRow:(cvimage->width * 4)
862 int pixelCount = cvimage->width * cvimage->height;
863 unsigned char *src = cvimage->data.ptr;
864 unsigned char *dst = [bitmap bitmapData];
866 for( int i = 0; i < pixelCount; i++ )
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];
876 image = [[NSImage alloc] init];
877 [image addRepresentation:bitmap];
880 /*CGColorSpaceRelease(colorspace);
881 CGDataProviderRelease(provider);
882 CGImageRelease(imageRef);*/
883 cvReleaseMat(&cvimage);
886 [self setNeedsDisplay:YES];
890 - (void)setFrameSize:(NSSize)size {
891 //cout << "setFrameSize" << endl;
892 [super setFrameSize:size];
894 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
895 int height = size.height;
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;
904 height -= r.size.height;
909 - (void)drawRect:(NSRect)rect {
910 //cout << "drawRect" << endl;
911 [super drawRect:rect];
913 NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
914 CVWindow *cvwindow = (CVWindow *)[self window];
916 if ([cvwindow respondsToSelector:@selector(sliders)]) {
917 for(NSString *key in [cvwindow sliders]) {
918 height += [[[cvwindow sliders] valueForKey:key] frame].size.height;
923 NSRect imageRect = {{0,0}, {[image size].width, [image size].height}};
926 [image drawInRect: imageRect
928 operation: NSCompositeSourceOver
937 @implementation CVSlider
942 @synthesize userData;
943 @synthesize callback;
944 @synthesize callback2;
953 [self setFrame:NSMakeRect(0,0,200,30)];
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];
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];
973 [self setAutoresizingMask:NSViewWidthSizable];
975 //[self setFrame:NSMakeRect(12, 0, 100, 30)];
980 - (void)sliderChanged:(NSNotification *)notification {
982 int pos = [slider intValue];
988 callback2(pos, userData);