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