mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1303 lines
41 KiB
1303 lines
41 KiB
/* The file is the modified version of window_cocoa.mm from opencv-cocoa project by Andre Cohen */ |
|
|
|
/*M/////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. |
|
// |
|
// By downloading, copying, installing or using the software you agree to this license. |
|
// If you do not agree to this license, do not download, install, |
|
// copy or use the software. |
|
// |
|
// |
|
// License Agreement |
|
// For Open Source Computer Vision Library |
|
// |
|
// Copyright (C) 2010, Willow Garage Inc., all rights reserved. |
|
// Third party copyrights are property of their respective owners. |
|
// |
|
// Redistribution and use in source and binary forms, with or without modification, |
|
// are permitted provided that the following conditions are met: |
|
// |
|
// * Redistribution's of source code must retain the above copyright notice, |
|
// this list of conditions and the following disclaimer. |
|
// |
|
// * Redistribution's in binary form must reproduce the above copyright notice, |
|
// this list of conditions and the following disclaimer in the documentation |
|
// and/or other materials provided with the distribution. |
|
// |
|
// * The name of Intel Corporation may not be used to endorse or promote products |
|
// derived from this software without specific prior written permission. |
|
// |
|
// This software is provided by the copyright holders and contributors "as is" and |
|
// any express or implied warranties, including, but not limited to, the implied |
|
// warranties of merchantability and fitness for a particular purpose are disclaimed. |
|
// In no event shall the Intel Corporation or contributors be liable for any direct, |
|
// indirect, incidental, special, exemplary, or consequential damages |
|
// (including, but not limited to, procurement of substitute goods or services; |
|
// loss of use, data, or profits; or business interruption) however caused |
|
// and on any theory of liability, whether in contract, strict liability, |
|
// or tort (including negligence or otherwise) arising in any way out of |
|
// the use of this software, even if advised of the possibility of such damage. |
|
// |
|
//M*/ |
|
#include "precomp.hpp" |
|
#include "opencv2/imgproc.hpp" |
|
|
|
#import <TargetConditionals.h> |
|
|
|
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR |
|
/*** begin IPhone OS Stubs ***/ |
|
// When highgui functions are referred to on iPhone OS, they will fail silently. |
|
CV_IMPL int cvInitSystem( int argc, char** argv) { return 0;} |
|
CV_IMPL int cvStartWindowThread(){ return 0; } |
|
CV_IMPL void cvDestroyWindow( const char* name) {} |
|
CV_IMPL void cvDestroyAllWindows( void ) {} |
|
CV_IMPL void cvShowImage( const char* name, const CvArr* arr) {} |
|
CV_IMPL void cvResizeWindow( const char* name, int width, int height) {} |
|
CV_IMPL void cvMoveWindow( const char* name, int x, int y){} |
|
CV_IMPL int cvCreateTrackbar (const char* trackbar_name,const char* window_name, |
|
int* val, int count, CvTrackbarCallback on_notify) {return 0;} |
|
CV_IMPL int cvCreateTrackbar2(const char* trackbar_name,const char* window_name, |
|
int* val, int count, CvTrackbarCallback2 on_notify2, void* userdata) {return 0;} |
|
CV_IMPL void cvSetMouseCallback( const char* name, CvMouseCallback function, void* info) {} |
|
CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name ) {return 0;} |
|
CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos) {} |
|
CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval) {} |
|
CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) {} |
|
CV_IMPL void* cvGetWindowHandle( const char* name ) {return NULL;} |
|
CV_IMPL const char* cvGetWindowName( void* window_handle ) {return NULL;} |
|
CV_IMPL int cvNamedWindow( const char* name, int flags ) {return 0; } |
|
CV_IMPL int cvWaitKey (int maxWait) {return 0;} |
|
//*** end IphoneOS Stubs ***/ |
|
#else |
|
|
|
#import <Cocoa/Cocoa.h> |
|
|
|
#include <iostream> |
|
|
|
const int MIN_SLIDER_WIDTH=200; |
|
|
|
static NSApplication *application = nil; |
|
static NSAutoreleasePool *pool = nil; |
|
static NSMutableDictionary *windows = nil; |
|
static bool wasInitialized = false; |
|
|
|
@interface CVView : NSView |
|
@property(retain) NSView *imageView; |
|
@property(retain) NSImage *image; |
|
@property int sliderHeight; |
|
- (void)setImageData:(CvArr *)arr; |
|
@end |
|
|
|
@interface CVSlider : NSView { |
|
NSSlider *slider; |
|
NSTextField *name; |
|
NSString *initialName; |
|
int *value; |
|
void *userData; |
|
CvTrackbarCallback callback; |
|
CvTrackbarCallback2 callback2; |
|
} |
|
@property(retain) NSSlider *slider; |
|
@property(retain) NSTextField *name; |
|
@property(retain) NSString *initialName; |
|
@property(assign) int *value; |
|
@property(assign) void *userData; |
|
@property(assign) CvTrackbarCallback callback; |
|
@property(assign) CvTrackbarCallback2 callback2; |
|
@end |
|
|
|
@interface CVWindow : NSWindow { |
|
NSMutableDictionary *sliders; |
|
NSMutableArray *slidersKeys; |
|
CvMouseCallback mouseCallback; |
|
void *mouseParam; |
|
BOOL autosize; |
|
BOOL firstContent; |
|
int status; |
|
int x0, y0; |
|
} |
|
@property(assign) CvMouseCallback mouseCallback; |
|
@property(assign) void *mouseParam; |
|
@property(assign) BOOL autosize; |
|
@property(assign) BOOL firstContent; |
|
@property(assign) int x0; |
|
@property(assign) int y0; |
|
@property(retain) NSMutableDictionary *sliders; |
|
@property(retain) NSMutableArray *slidersKeys; |
|
@property(readwrite) int status; |
|
- (CVView *)contentView; |
|
- (void)cvSendMouseEvent:(NSEvent *)event type:(int)type flags:(int)flags; |
|
- (void)cvMouseEvent:(NSEvent *)event; |
|
- (void)createSliderWithName:(const char *)name maxValue:(int)max value:(int *)value callback:(CvTrackbarCallback)callback; |
|
@end |
|
|
|
/*static void icvCocoaCleanup(void) |
|
{ |
|
//cout << "icvCocoaCleanup" << endl; |
|
if( application ) |
|
{ |
|
cvDestroyAllWindows(); |
|
//[application terminate:nil]; |
|
application = 0; |
|
[pool release]; |
|
} |
|
}*/ |
|
|
|
CV_IMPL int cvInitSystem( int , char** ) |
|
{ |
|
//cout << "cvInitSystem" << endl; |
|
wasInitialized = true; |
|
|
|
pool = [[NSAutoreleasePool alloc] init]; |
|
application = [NSApplication sharedApplication]; |
|
windows = [[NSMutableDictionary alloc] init]; |
|
|
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 |
|
|
|
#ifndef NSAppKitVersionNumber10_5 |
|
#define NSAppKitVersionNumber10_5 949 |
|
#endif |
|
if( floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5 ) |
|
[application setActivationPolicy:NSApplicationActivationPolicyRegular]; |
|
#endif |
|
//[application finishLaunching]; |
|
//atexit(icvCocoaCleanup); |
|
|
|
setlocale(LC_NUMERIC,"C"); |
|
|
|
return 0; |
|
} |
|
|
|
static CVWindow *cvGetWindow(const char *name) { |
|
//cout << "cvGetWindow" << endl; |
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
NSString *cvname = [NSString stringWithFormat:@"%s", name]; |
|
CVWindow* retval = (CVWindow*) [windows valueForKey:cvname] ; |
|
//cout << "retain count: " << [retval retainCount] << endl; |
|
//retval = [retval retain]; |
|
//cout << "retain count: " << [retval retainCount] << endl; |
|
[localpool drain]; |
|
//cout << "retain count: " << [retval retainCount] << endl; |
|
return retval; |
|
} |
|
|
|
CV_IMPL int cvStartWindowThread() |
|
{ |
|
//cout << "cvStartWindowThread" << endl; |
|
return 0; |
|
} |
|
|
|
CV_IMPL void cvDestroyWindow( const char* name) |
|
{ |
|
|
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
//cout << "cvDestroyWindow" << endl; |
|
CVWindow *window = cvGetWindow(name); |
|
if(window) { |
|
if ([window styleMask] & NSFullScreenWindowMask) { |
|
[window toggleFullScreen:nil]; |
|
} |
|
[window close]; |
|
[windows removeObjectForKey:[NSString stringWithFormat:@"%s", name]]; |
|
} |
|
[localpool drain]; |
|
} |
|
|
|
|
|
CV_IMPL void cvDestroyAllWindows( void ) |
|
{ |
|
//cout << "cvDestroyAllWindows" << endl; |
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
NSDictionary* list = [NSDictionary dictionaryWithDictionary:windows]; |
|
for(NSString *key in list) { |
|
cvDestroyWindow([key cStringUsingEncoding:NSASCIIStringEncoding]); |
|
} |
|
[localpool drain]; |
|
} |
|
|
|
|
|
CV_IMPL void cvShowImage( const char* name, const CvArr* arr) |
|
{ |
|
//cout << "cvShowImage" << endl; |
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
CVWindow *window = cvGetWindow(name); |
|
if(!window) |
|
{ |
|
cvNamedWindow(name, CV_WINDOW_AUTOSIZE); |
|
window = cvGetWindow(name); |
|
} |
|
|
|
if(window) |
|
{ |
|
bool empty = [[window contentView] image] == nil; |
|
NSRect vrectOld = [[window contentView] frame]; |
|
NSSize oldImageSize = [[[window contentView] image] size]; |
|
[[window contentView] setImageData:(CvArr *)arr]; |
|
if([window autosize] || [window firstContent] || empty) |
|
{ |
|
NSSize imageSize = [[[window contentView] image] size]; |
|
// Only adjust the image size if the new image is a different size from the previous |
|
if (oldImageSize.height != imageSize.height || oldImageSize.width != imageSize.width) |
|
{ |
|
//Set new view size considering sliders (reserve height and min width) |
|
NSSize scaledImageSize = imageSize; |
|
if ([[window contentView] respondsToSelector:@selector(convertSizeFromBacking:)]) |
|
{ |
|
// Only resize for retina displays if the image is bigger than the screen |
|
NSSize screenSize = NSScreen.mainScreen.visibleFrame.size; |
|
CGFloat titleBarHeight = window.frame.size.height - [window contentRectForFrameRect:window.frame].size.height; |
|
screenSize.height -= titleBarHeight; |
|
if (imageSize.width > screenSize.width || imageSize.height > screenSize.height) |
|
{ |
|
CGFloat fx = screenSize.width/std::max(imageSize.width, (CGFloat)1.f); |
|
CGFloat fy = screenSize.height/std::max(imageSize.height, (CGFloat)1.f); |
|
CGFloat min_f = std::min(fx, fy); |
|
scaledImageSize = [[window contentView] convertSizeFromBacking:imageSize]; |
|
scaledImageSize.width = std::min(scaledImageSize.width, min_f*imageSize.width); |
|
scaledImageSize.height = std::min(scaledImageSize.height, min_f*imageSize.height); |
|
} |
|
} |
|
NSSize contentSize = vrectOld.size; |
|
contentSize.height = scaledImageSize.height + [window contentView].sliderHeight; |
|
contentSize.width = std::max<int>(scaledImageSize.width, MIN_SLIDER_WIDTH); |
|
[window setContentSize:contentSize]; //adjust sliders to fit new window size |
|
if([window firstContent]) |
|
{ |
|
int x = [window x0]; |
|
int y = [window y0]; |
|
if(x >= 0 && y >= 0) |
|
{ |
|
y = [[window screen] visibleFrame].size.height - y; |
|
[window setFrameTopLeftPoint:NSMakePoint(x, y)]; |
|
} |
|
} |
|
} |
|
} |
|
[window setFirstContent:NO]; |
|
} |
|
[localpool drain]; |
|
} |
|
|
|
CV_IMPL void cvResizeWindow( const char* name, int width, int height) |
|
{ |
|
|
|
//cout << "cvResizeWindow" << endl; |
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
CVWindow *window = cvGetWindow(name); |
|
if(window && ![window autosize]) { |
|
height += [window contentView].sliderHeight; |
|
NSSize size = { (CGFloat)width, (CGFloat)height }; |
|
[window setContentSize:size]; |
|
} |
|
[localpool drain]; |
|
} |
|
|
|
CV_IMPL void cvMoveWindow( const char* name, int x, int y) |
|
{ |
|
CV_FUNCNAME("cvMoveWindow"); |
|
__BEGIN__; |
|
|
|
NSAutoreleasePool* localpool1 = [[NSAutoreleasePool alloc] init]; |
|
CVWindow *window = nil; |
|
|
|
if(name == NULL) |
|
CV_ERROR( CV_StsNullPtr, "NULL window name" ); |
|
//cout << "cvMoveWindow"<< endl; |
|
window = cvGetWindow(name); |
|
if(window) { |
|
if([window firstContent]) { |
|
[window setX0:x]; |
|
[window setY0:y]; |
|
} |
|
else { |
|
y = [[window screen] visibleFrame].size.height - y; |
|
[window setFrameTopLeftPoint:NSMakePoint(x, y)]; |
|
} |
|
} |
|
[localpool1 drain]; |
|
|
|
__END__; |
|
} |
|
|
|
CV_IMPL int cvCreateTrackbar (const char* trackbar_name, |
|
const char* window_name, |
|
int* val, int count, |
|
CvTrackbarCallback on_notify) |
|
{ |
|
CV_FUNCNAME("cvCreateTrackbar"); |
|
|
|
|
|
int result = 0; |
|
CVWindow *window = nil; |
|
NSAutoreleasePool* localpool2 = nil; |
|
|
|
__BEGIN__; |
|
if (localpool2 != nil) [localpool2 drain]; |
|
localpool2 = [[NSAutoreleasePool alloc] init]; |
|
|
|
if(window_name == NULL) |
|
CV_ERROR( CV_StsNullPtr, "NULL window name" ); |
|
|
|
//cout << "cvCreateTrackbar" << endl ; |
|
window = cvGetWindow(window_name); |
|
if(window) { |
|
[window createSliderWithName:trackbar_name |
|
maxValue:count |
|
value:val |
|
callback:on_notify]; |
|
result = 1; |
|
} |
|
[localpool2 drain]; |
|
__END__; |
|
return result; |
|
} |
|
|
|
|
|
CV_IMPL int cvCreateTrackbar2(const char* trackbar_name, |
|
const char* window_name, |
|
int* val, int count, |
|
CvTrackbarCallback2 on_notify2, |
|
void* userdata) |
|
{ |
|
//cout <<"cvCreateTrackbar2" << endl; |
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
int res = cvCreateTrackbar(trackbar_name, window_name, val, count, NULL); |
|
if(res) { |
|
CVWindow *window = cvGetWindow(window_name); |
|
if (window && [window respondsToSelector:@selector(sliders)]) { |
|
CVSlider *slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; |
|
[slider setCallback2:on_notify2]; |
|
[slider setUserData:userdata]; |
|
} |
|
} |
|
[localpool drain]; |
|
return res; |
|
} |
|
|
|
|
|
CV_IMPL void |
|
cvSetMouseCallback( const char* name, CvMouseCallback function, void* info) |
|
{ |
|
CV_FUNCNAME("cvSetMouseCallback"); |
|
|
|
CVWindow *window = nil; |
|
NSAutoreleasePool* localpool3 = nil; |
|
__BEGIN__; |
|
//cout << "cvSetMouseCallback" << endl; |
|
|
|
if (localpool3 != nil) [localpool3 drain]; |
|
localpool3 = [[NSAutoreleasePool alloc] init]; |
|
|
|
if(name == NULL) |
|
CV_ERROR( CV_StsNullPtr, "NULL window name" ); |
|
|
|
window = cvGetWindow(name); |
|
if(window) { |
|
[window setMouseCallback:function]; |
|
[window setMouseParam:info]; |
|
} |
|
[localpool3 drain]; |
|
|
|
__END__; |
|
} |
|
|
|
CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name ) |
|
{ |
|
CV_FUNCNAME("cvGetTrackbarPos"); |
|
|
|
CVWindow *window = nil; |
|
int pos = -1; |
|
NSAutoreleasePool* localpool4 = nil; |
|
__BEGIN__; |
|
|
|
//cout << "cvGetTrackbarPos" << endl; |
|
if(trackbar_name == NULL || window_name == NULL) |
|
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" ); |
|
|
|
if (localpool4 != nil) [localpool4 drain]; |
|
localpool4 = [[NSAutoreleasePool alloc] init]; |
|
|
|
window = cvGetWindow(window_name); |
|
if(window && [window respondsToSelector:@selector(sliders)]) { |
|
CVSlider *slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; |
|
if(slider) { |
|
pos = [[slider slider] intValue]; |
|
} |
|
} |
|
[localpool4 drain]; |
|
__END__; |
|
return pos; |
|
} |
|
|
|
CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos) |
|
{ |
|
CV_FUNCNAME("cvSetTrackbarPos"); |
|
|
|
CVWindow *window = nil; |
|
CVSlider *slider = nil; |
|
NSAutoreleasePool* localpool5 = nil; |
|
|
|
__BEGIN__; |
|
//cout << "cvSetTrackbarPos" << endl; |
|
if(trackbar_name == NULL || window_name == NULL) |
|
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" ); |
|
|
|
if(pos < 0) |
|
CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" ); |
|
|
|
if (localpool5 != nil) [localpool5 drain]; |
|
localpool5 = [[NSAutoreleasePool alloc] init]; |
|
|
|
window = cvGetWindow(window_name); |
|
if(window && [window respondsToSelector:@selector(sliders)]) { |
|
slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; |
|
if(slider) { |
|
[[slider slider] setIntValue:pos]; |
|
if([slider respondsToSelector:@selector(handleSlider)]) { |
|
[slider performSelector:@selector(handleSlider)]; |
|
} |
|
} |
|
} |
|
[localpool5 drain]; |
|
|
|
__END__; |
|
} |
|
|
|
CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval) |
|
{ |
|
CV_FUNCNAME("cvSetTrackbarMax"); |
|
|
|
CVWindow *window = nil; |
|
CVSlider *slider = nil; |
|
NSAutoreleasePool* localpool5 = nil; |
|
|
|
__BEGIN__; |
|
//cout << "cvSetTrackbarPos" << endl; |
|
if(trackbar_name == NULL || window_name == NULL) |
|
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" ); |
|
|
|
if (localpool5 != nil) [localpool5 drain]; |
|
localpool5 = [[NSAutoreleasePool alloc] init]; |
|
|
|
window = cvGetWindow(window_name); |
|
if(window && [window respondsToSelector:@selector(sliders)]) { |
|
slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; |
|
if(slider) { |
|
if(maxval >= 0) { |
|
int minval = [[slider slider] minValue]; |
|
maxval = (minval>maxval)?minval:maxval; |
|
[[slider slider] setMaxValue:maxval]; |
|
} |
|
} |
|
} |
|
[localpool5 drain]; |
|
|
|
__END__; |
|
} |
|
|
|
CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) |
|
{ |
|
CV_FUNCNAME("cvSetTrackbarMin"); |
|
|
|
CVWindow *window = nil; |
|
CVSlider *slider = nil; |
|
NSAutoreleasePool* localpool5 = nil; |
|
|
|
__BEGIN__; |
|
if(trackbar_name == NULL || window_name == NULL) |
|
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" ); |
|
|
|
if (localpool5 != nil) [localpool5 drain]; |
|
localpool5 = [[NSAutoreleasePool alloc] init]; |
|
|
|
window = cvGetWindow(window_name); |
|
if(window && [window respondsToSelector:@selector(sliders)]) { |
|
slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; |
|
if(slider) { |
|
if(minval >= 0) { |
|
int maxval = [[slider slider] maxValue]; |
|
minval = (minval<maxval)?minval:maxval; |
|
[[slider slider] setMinValue:minval]; |
|
} |
|
} |
|
} |
|
[localpool5 drain]; |
|
|
|
__END__; |
|
} |
|
|
|
CV_IMPL void* cvGetWindowHandle( const char* name ) |
|
{ |
|
//cout << "cvGetWindowHandle" << endl; |
|
return cvGetWindow(name); |
|
} |
|
|
|
|
|
CV_IMPL const char* cvGetWindowName( void* window_handle ) |
|
{ |
|
//cout << "cvGetWindowName" << endl; |
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
for(NSString *key in windows) { |
|
if([windows valueForKey:key] == window_handle) { |
|
[localpool drain]; |
|
return [key UTF8String]; |
|
} |
|
} |
|
[localpool drain]; |
|
return 0; |
|
} |
|
|
|
CV_IMPL int cvNamedWindow( const char* name, int flags ) |
|
{ |
|
if( !wasInitialized ) |
|
cvInitSystem(0, 0); |
|
|
|
//cout << "cvNamedWindow" << endl; |
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
CVWindow *window = cvGetWindow(name); |
|
if( window ) |
|
{ |
|
[window setAutosize:(flags == CV_WINDOW_AUTOSIZE)]; |
|
[localpool drain]; |
|
return 0; |
|
} |
|
|
|
NSScreen* mainDisplay = [NSScreen mainScreen]; |
|
|
|
NSString *windowName = [NSString stringWithFormat:@"%s", name]; |
|
NSUInteger showResize = NSResizableWindowMask; |
|
NSUInteger styleMask = NSTitledWindowMask|NSMiniaturizableWindowMask|showResize; |
|
CGFloat windowWidth = [NSWindow minFrameWidthWithTitle:windowName styleMask:styleMask]; |
|
NSRect initContentRect = NSMakeRect(0, 0, windowWidth, 0); |
|
if (mainDisplay) { |
|
NSRect dispFrame = [mainDisplay visibleFrame]; |
|
initContentRect.origin.y = dispFrame.size.height-20; |
|
} |
|
|
|
|
|
window = [[CVWindow alloc] initWithContentRect:initContentRect |
|
styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|showResize |
|
backing:NSBackingStoreBuffered |
|
defer:YES |
|
screen:mainDisplay]; |
|
|
|
[window setFrameTopLeftPoint:initContentRect.origin]; |
|
|
|
[window setFirstContent:YES]; |
|
[window setX0:-1]; |
|
[window setY0:-1]; |
|
|
|
[window setContentView:[[CVView alloc] init]]; |
|
|
|
[NSApp activateIgnoringOtherApps:YES]; |
|
|
|
[window setHasShadow:YES]; |
|
[window setAcceptsMouseMovedEvents:YES]; |
|
[window useOptimizedDrawing:YES]; |
|
[window setTitle:windowName]; |
|
[window makeKeyAndOrderFront:nil]; |
|
|
|
[window setAutosize:(flags == CV_WINDOW_AUTOSIZE)]; |
|
|
|
[windows setValue:window forKey:windowName]; |
|
|
|
[localpool drain]; |
|
return [windows count]-1; |
|
} |
|
|
|
CV_IMPL int cvWaitKey (int maxWait) |
|
{ |
|
//cout << "cvWaitKey" << endl; |
|
int returnCode = -1; |
|
NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init]; |
|
double start = [[NSDate date] timeIntervalSince1970]; |
|
|
|
while(true) { |
|
if(([[NSDate date] timeIntervalSince1970] - start) * 1000 >= maxWait && maxWait>0) |
|
break; |
|
|
|
//event = [application currentEvent]; |
|
[localpool drain]; |
|
localpool = [[NSAutoreleasePool alloc] init]; |
|
|
|
NSEvent *event = |
|
[application |
|
nextEventMatchingMask:NSAnyEventMask |
|
untilDate://[NSDate dateWithTimeIntervalSinceNow: 1./100] |
|
[NSDate distantPast] |
|
inMode:NSDefaultRunLoopMode |
|
dequeue:YES]; |
|
|
|
if([event type] == NSKeyDown && [[event characters] length]) { |
|
returnCode = [[event characters] characterAtIndex:0]; |
|
break; |
|
} |
|
|
|
[application sendEvent:event]; |
|
[application updateWindows]; |
|
|
|
[NSThread sleepForTimeInterval:1/100.]; |
|
} |
|
[localpool drain]; |
|
|
|
return returnCode; |
|
} |
|
|
|
CvRect cvGetWindowRect_COCOA( const char* name ) |
|
{ |
|
CvRect result = cvRect(-1, -1, -1, -1); |
|
CVWindow *window = nil; |
|
|
|
CV_FUNCNAME( "cvGetWindowRect_COCOA" ); |
|
|
|
__BEGIN__; |
|
if( name == NULL ) |
|
{ |
|
CV_ERROR( CV_StsNullPtr, "NULL name string" ); |
|
} |
|
|
|
window = cvGetWindow( name ); |
|
if ( window == NULL ) |
|
{ |
|
CV_ERROR( CV_StsNullPtr, "NULL window" ); |
|
} else { |
|
NSRect rect = [window frame]; |
|
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6 |
|
NSPoint pt = [window convertRectToScreen:rect].origin; |
|
#else |
|
NSPoint pt = [window convertBaseToScreen:rect.origin]; |
|
#endif |
|
NSSize sz = [[[window contentView] image] size]; |
|
result = cvRect(pt.x, pt.y, sz.width, sz.height); |
|
} |
|
|
|
__END__; |
|
return result; |
|
} |
|
|
|
double cvGetModeWindow_COCOA( const char* name ) |
|
{ |
|
double result = -1; |
|
CVWindow *window = nil; |
|
|
|
CV_FUNCNAME( "cvGetModeWindow_COCOA" ); |
|
|
|
__BEGIN__; |
|
if( name == NULL ) |
|
{ |
|
CV_ERROR( CV_StsNullPtr, "NULL name string" ); |
|
} |
|
|
|
window = cvGetWindow( name ); |
|
if ( window == NULL ) |
|
{ |
|
CV_ERROR( CV_StsNullPtr, "NULL window" ); |
|
} |
|
|
|
result = window.status; |
|
|
|
__END__; |
|
return result; |
|
} |
|
|
|
void cvSetModeWindow_COCOA( const char* name, double prop_value ) |
|
{ |
|
CVWindow *window = nil; |
|
|
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 |
|
NSDictionary *fullscreenOptions = nil; |
|
#endif |
|
|
|
NSAutoreleasePool* localpool = nil; |
|
|
|
CV_FUNCNAME( "cvSetModeWindow_COCOA" ); |
|
|
|
__BEGIN__; |
|
if( name == NULL ) |
|
{ |
|
CV_ERROR( CV_StsNullPtr, "NULL name string" ); |
|
} |
|
|
|
window = cvGetWindow(name); |
|
if ( window == NULL ) |
|
{ |
|
CV_ERROR( CV_StsNullPtr, "NULL window" ); |
|
} |
|
|
|
if ( [window autosize] ) |
|
{ |
|
return; |
|
} |
|
|
|
localpool = [[NSAutoreleasePool alloc] init]; |
|
|
|
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6 |
|
if ( ([window styleMask] & NSFullScreenWindowMask) && prop_value==CV_WINDOW_NORMAL ) |
|
{ |
|
[window toggleFullScreen:nil]; |
|
|
|
window.status=CV_WINDOW_NORMAL; |
|
} |
|
else if( !([window styleMask] & NSFullScreenWindowMask) && prop_value==CV_WINDOW_FULLSCREEN ) |
|
{ |
|
[window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; |
|
|
|
NSScreen* screen = [window screen]; |
|
|
|
NSRect frame = [screen frame]; |
|
[window setFrame:frame display:YES]; |
|
|
|
[window setContentSize:frame.size]; |
|
|
|
[window toggleFullScreen:nil]; |
|
|
|
[window setFrameTopLeftPoint: frame.origin]; |
|
|
|
window.status=CV_WINDOW_FULLSCREEN; |
|
} |
|
#else |
|
fullscreenOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:NSFullScreenModeSetting]; |
|
if ( [[window contentView] isInFullScreenMode] && prop_value==CV_WINDOW_NORMAL ) |
|
{ |
|
[[window contentView] exitFullScreenModeWithOptions:fullscreenOptions]; |
|
window.status=CV_WINDOW_NORMAL; |
|
} |
|
else if( ![[window contentView] isInFullScreenMode] && prop_value==CV_WINDOW_FULLSCREEN ) |
|
{ |
|
[[window contentView] enterFullScreenMode:[NSScreen mainScreen] withOptions:fullscreenOptions]; |
|
window.status=CV_WINDOW_FULLSCREEN; |
|
} |
|
#endif |
|
[localpool drain]; |
|
|
|
__END__; |
|
} |
|
|
|
double cvGetPropVisible_COCOA(const char* name) |
|
{ |
|
double result = -1; |
|
CVWindow* window = nil; |
|
|
|
CV_FUNCNAME("cvGetPropVisible_COCOA"); |
|
|
|
__BEGIN__; |
|
if (name == NULL) |
|
{ |
|
CV_ERROR(CV_StsNullPtr, "NULL name string"); |
|
} |
|
|
|
window = cvGetWindow(name); |
|
if (window == NULL) |
|
{ |
|
CV_ERROR(CV_StsNullPtr, "NULL window"); |
|
} |
|
|
|
result = window.isVisible ? 1 : 0; |
|
|
|
__END__; |
|
return result; |
|
} |
|
|
|
double cvGetPropTopmost_COCOA(const char* name) |
|
{ |
|
double result = -1; |
|
CVWindow* window = nil; |
|
|
|
CV_FUNCNAME("cvGetPropTopmost_COCOA"); |
|
|
|
__BEGIN__; |
|
if (name == NULL) |
|
{ |
|
CV_ERROR(CV_StsNullPtr, "NULL name string"); |
|
} |
|
|
|
window = cvGetWindow(name); |
|
if (window == NULL) |
|
{ |
|
CV_ERROR(CV_StsNullPtr, "NULL window"); |
|
} |
|
|
|
result = (window.level == NSStatusWindowLevel) ? 1 : 0; |
|
|
|
__END__; |
|
return result; |
|
} |
|
|
|
void cvSetPropTopmost_COCOA( const char* name, const bool topmost ) |
|
{ |
|
CVWindow *window = nil; |
|
NSAutoreleasePool* localpool = nil; |
|
CV_FUNCNAME( "cvSetPropTopmost_COCOA" ); |
|
|
|
__BEGIN__; |
|
if( name == NULL ) |
|
{ |
|
CV_ERROR( CV_StsNullPtr, "NULL name string" ); |
|
} |
|
|
|
window = cvGetWindow(name); |
|
if ( window == NULL ) |
|
{ |
|
CV_ERROR( CV_StsNullPtr, "NULL window" ); |
|
} |
|
|
|
if (([window styleMask] & NSFullScreenWindowMask)) |
|
{ |
|
EXIT; |
|
} |
|
|
|
localpool = [[NSAutoreleasePool alloc] init]; |
|
if (topmost) |
|
{ |
|
[window makeKeyAndOrderFront:window.self]; |
|
[window setLevel:CGWindowLevelForKey(kCGMaximumWindowLevelKey)]; |
|
} |
|
else |
|
{ |
|
[window makeKeyAndOrderFront:nil]; |
|
} |
|
[localpool drain]; |
|
__END__; |
|
} |
|
|
|
void setWindowTitle_COCOA(const cv::String& winname, const cv::String& title) |
|
{ |
|
CVWindow *window = cvGetWindow(winname.c_str()); |
|
|
|
if (window == NULL) |
|
{ |
|
cv::namedWindow(winname); |
|
window = cvGetWindow(winname.c_str()); |
|
} |
|
|
|
if (window == NULL) |
|
CV_Error(cv::Error::StsNullPtr, "NULL window"); |
|
|
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
|
|
NSString *windowTitle = [NSString stringWithFormat:@"%s", title.c_str()]; |
|
[window setTitle:windowTitle]; |
|
|
|
[localpool drain]; |
|
} |
|
|
|
static NSSize constrainAspectRatio(NSSize base, NSSize constraint) { |
|
CGFloat heightDiff = (base.height / constraint.height); |
|
CGFloat widthDiff = (base.width / constraint.width); |
|
if (heightDiff == 0) heightDiff = widthDiff; |
|
if (widthDiff == heightDiff) { |
|
return base; |
|
} |
|
else if (widthDiff > heightDiff) { |
|
NSSize out = { constraint.width / constraint.height * base.height, base.height }; |
|
return out; |
|
} |
|
else { |
|
NSSize out = { base.width, constraint.height / constraint.width * base.width }; |
|
return out; |
|
} |
|
} |
|
|
|
@implementation CVWindow |
|
|
|
@synthesize mouseCallback; |
|
@synthesize mouseParam; |
|
@synthesize autosize; |
|
@synthesize firstContent; |
|
@synthesize x0; |
|
@synthesize y0; |
|
@synthesize sliders; |
|
@synthesize slidersKeys; |
|
@synthesize status; |
|
|
|
- (void)cvSendMouseEvent:(NSEvent *)event type:(int)type flags:(int)flags { |
|
(void)event; |
|
//cout << "cvSendMouseEvent" << endl; |
|
NSPoint mp = [NSEvent mouseLocation]; |
|
//NSRect visible = [[self contentView] frame]; |
|
mp = [self convertScreenToBase: mp]; |
|
CVView *contentView = [self contentView]; |
|
NSSize viewSize = contentView.frame.size; |
|
if (contentView.imageView) { |
|
viewSize = contentView.imageView.frame.size; |
|
} |
|
else { |
|
viewSize.height -= contentView.sliderHeight; |
|
} |
|
mp.y = viewSize.height - mp.y; |
|
|
|
NSSize imageSize = contentView.image.size; |
|
mp.y *= (imageSize.height / std::max(viewSize.height, 1.)); |
|
mp.x *= (imageSize.width / std::max(viewSize.width, 1.)); |
|
|
|
if( [event type] == NSEventTypeScrollWheel ) { |
|
if( event.hasPreciseScrollingDeltas ) { |
|
mp.x = int(event.scrollingDeltaX); |
|
mp.y = int(event.scrollingDeltaY); |
|
} else { |
|
mp.x = int(event.scrollingDeltaX / 0.100006); |
|
mp.y = int(event.scrollingDeltaY / 0.100006); |
|
} |
|
if( mp.x && !mp.y && CV_EVENT_MOUSEWHEEL == type ) { |
|
type = CV_EVENT_MOUSEHWHEEL; |
|
} |
|
mouseCallback(type, mp.x, mp.y, flags, mouseParam); |
|
} else if( mp.x >= 0 && mp.y >= 0 && mp.x < imageSize.width && mp.y < imageSize.height ) { |
|
mouseCallback(type, mp.x, mp.y, flags, mouseParam); |
|
} |
|
|
|
} |
|
|
|
- (void)cvMouseEvent:(NSEvent *)event { |
|
//cout << "cvMouseEvent" << endl; |
|
if(!mouseCallback) |
|
return; |
|
|
|
int flags = 0; |
|
if([event modifierFlags] & NSShiftKeyMask) flags |= CV_EVENT_FLAG_SHIFTKEY; |
|
if([event modifierFlags] & NSControlKeyMask) flags |= CV_EVENT_FLAG_CTRLKEY; |
|
if([event modifierFlags] & NSAlternateKeyMask) flags |= CV_EVENT_FLAG_ALTKEY; |
|
|
|
if([event type] == NSLeftMouseDown) {[self cvSendMouseEvent:event type:CV_EVENT_LBUTTONDOWN flags:flags | CV_EVENT_FLAG_LBUTTON];} |
|
if([event type] == NSLeftMouseUp) {[self cvSendMouseEvent:event type:CV_EVENT_LBUTTONUP flags:flags | CV_EVENT_FLAG_LBUTTON];} |
|
if([event type] == NSRightMouseDown){[self cvSendMouseEvent:event type:CV_EVENT_RBUTTONDOWN flags:flags | CV_EVENT_FLAG_RBUTTON];} |
|
if([event type] == NSRightMouseUp) {[self cvSendMouseEvent:event type:CV_EVENT_RBUTTONUP flags:flags | CV_EVENT_FLAG_RBUTTON];} |
|
if([event type] == NSOtherMouseDown){[self cvSendMouseEvent:event type:CV_EVENT_MBUTTONDOWN flags:flags];} |
|
if([event type] == NSOtherMouseUp) {[self cvSendMouseEvent:event type:CV_EVENT_MBUTTONUP flags:flags];} |
|
if([event type] == NSMouseMoved) {[self cvSendMouseEvent:event type:CV_EVENT_MOUSEMOVE flags:flags];} |
|
if([event type] == NSLeftMouseDragged) {[self cvSendMouseEvent:event type:CV_EVENT_MOUSEMOVE flags:flags | CV_EVENT_FLAG_LBUTTON];} |
|
if([event type] == NSRightMouseDragged) {[self cvSendMouseEvent:event type:CV_EVENT_MOUSEMOVE flags:flags | CV_EVENT_FLAG_RBUTTON];} |
|
if([event type] == NSOtherMouseDragged) {[self cvSendMouseEvent:event type:CV_EVENT_MOUSEMOVE flags:flags | CV_EVENT_FLAG_MBUTTON];} |
|
if([event type] == NSEventTypeScrollWheel) {[self cvSendMouseEvent:event type:CV_EVENT_MOUSEWHEEL flags:flags ];} |
|
} |
|
|
|
-(void)scrollWheel:(NSEvent *)theEvent { |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)keyDown:(NSEvent *)theEvent { |
|
//cout << "keyDown" << endl; |
|
[super keyDown:theEvent]; |
|
} |
|
- (void)rightMouseDragged:(NSEvent *)theEvent { |
|
//cout << "rightMouseDragged" << endl ; |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)rightMouseUp:(NSEvent *)theEvent { |
|
//cout << "rightMouseUp" << endl; |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)rightMouseDown:(NSEvent *)theEvent { |
|
// Does not seem to work? |
|
//cout << "rightMouseDown" << endl; |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)mouseMoved:(NSEvent *)theEvent { |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)otherMouseDragged:(NSEvent *)theEvent { |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)otherMouseUp:(NSEvent *)theEvent { |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)otherMouseDown:(NSEvent *)theEvent { |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)mouseDragged:(NSEvent *)theEvent { |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)mouseUp:(NSEvent *)theEvent { |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
- (void)mouseDown:(NSEvent *)theEvent { |
|
[self cvMouseEvent:theEvent]; |
|
} |
|
|
|
- (void)createSliderWithName:(const char *)name maxValue:(int)max value:(int *)value callback:(CvTrackbarCallback)callback { |
|
//cout << "createSliderWithName" << endl; |
|
if(sliders == nil) |
|
sliders = [[NSMutableDictionary alloc] init]; |
|
|
|
if(slidersKeys == nil) |
|
slidersKeys = [[NSMutableArray alloc] init]; |
|
|
|
NSString *cvname = [NSString stringWithFormat:@"%s", name]; |
|
|
|
// Avoid overwriting slider |
|
if([sliders valueForKey:cvname]!=nil) |
|
return; |
|
|
|
// Create slider |
|
CVSlider *slider = [[CVSlider alloc] init]; |
|
[[slider name] setStringValue:cvname]; |
|
slider.initialName = [NSString stringWithFormat:@"%s", name]; |
|
[[slider slider] setMaxValue:max]; |
|
[[slider slider] setMinValue:0]; |
|
if(value) |
|
{ |
|
[[slider slider] setIntValue:*value]; |
|
[slider setValue:value]; |
|
NSString *temp = [slider initialName]; |
|
NSString *text = [NSString stringWithFormat:@"%@ %d", temp, *value]; |
|
[[slider name] setStringValue: text]; |
|
} |
|
if(callback) |
|
[slider setCallback:callback]; |
|
|
|
// Save slider |
|
[sliders setValue:slider forKey:cvname]; |
|
[slidersKeys addObject:cvname]; |
|
[[self contentView] addSubview:slider]; |
|
|
|
|
|
//update contentView size to contain sliders |
|
NSSize viewSize=[[self contentView] frame].size, |
|
sliderSize=[slider frame].size; |
|
viewSize.height += sliderSize.height; |
|
viewSize.width = std::max<int>(viewSize.width, MIN_SLIDER_WIDTH); |
|
|
|
// Update slider sizes |
|
[self contentView].sliderHeight += sliderSize.height; |
|
|
|
if ([[self contentView] image] && ![[self contentView] imageView]) { |
|
[[self contentView] setNeedsDisplay:YES]; |
|
} |
|
|
|
//update window size to contain sliders |
|
[self setContentSize: viewSize]; |
|
} |
|
|
|
- (CVView *)contentView { |
|
return (CVView*)[super contentView]; |
|
} |
|
|
|
@end |
|
|
|
@implementation CVView |
|
|
|
@synthesize image; |
|
|
|
- (id)init { |
|
//cout << "CVView init" << endl; |
|
[super init]; |
|
return self; |
|
} |
|
|
|
- (void)setImageData:(CvArr *)arr { |
|
//cout << "setImageData" << endl; |
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
|
|
cv::Mat arrMat = cv::cvarrToMat(arr); |
|
/*CGColorSpaceRef colorspace = NULL; |
|
CGDataProviderRef provider = NULL; |
|
int width = cvimage->width; |
|
int height = cvimage->height; |
|
|
|
colorspace = CGColorSpaceCreateDeviceRGB(); |
|
|
|
int size = 8; |
|
int nbChannels = 3; |
|
|
|
provider = CGDataProviderCreateWithData(NULL, cvimage->data.ptr, width * height , NULL ); |
|
|
|
CGImageRef imageRef = CGImageCreate(width, height, size , size*nbChannels , cvimage->step, colorspace, kCGImageAlphaNone , provider, NULL, true, kCGRenderingIntentDefault); |
|
|
|
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:imageRef]; |
|
if(image) { |
|
[image release]; |
|
}*/ |
|
|
|
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL |
|
pixelsWide:arrMat.cols |
|
pixelsHigh:arrMat.rows |
|
bitsPerSample:8 |
|
samplesPerPixel:3 |
|
hasAlpha:NO |
|
isPlanar:NO |
|
colorSpaceName:NSDeviceRGBColorSpace |
|
bitmapFormat: kCGImageAlphaNone |
|
bytesPerRow:((arrMat.cols * 3 + 3) & -4) |
|
bitsPerPixel:24]; |
|
|
|
if (bitmap) { |
|
cv::Mat dst(arrMat.rows, arrMat.cols, CV_8UC3, [bitmap bitmapData], [bitmap bytesPerRow]); |
|
convertToShow(arrMat, dst); |
|
} |
|
else { |
|
// It's not guaranteed to like the bitsPerPixel:24, but this is a lot slower so we'd rather not do it |
|
bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL |
|
pixelsWide:arrMat.cols |
|
pixelsHigh:arrMat.rows |
|
bitsPerSample:8 |
|
samplesPerPixel:3 |
|
hasAlpha:NO |
|
isPlanar:NO |
|
colorSpaceName:NSDeviceRGBColorSpace |
|
bytesPerRow:(arrMat.cols * 4) |
|
bitsPerPixel:32]; |
|
cv::Mat dst(arrMat.rows, arrMat.cols, CV_8UC4, [bitmap bitmapData], [bitmap bytesPerRow]); |
|
convertToShow(arrMat, dst); |
|
} |
|
|
|
if( image ) { |
|
[image release]; |
|
} |
|
|
|
image = [[NSImage alloc] init]; |
|
[image addRepresentation:bitmap]; |
|
[bitmap release]; |
|
|
|
// This isn't supported on older versions of macOS |
|
// The performance issues this solves are mainly on newer versions of macOS, so that's fine |
|
if( floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5 ) { |
|
if (![self imageView]) { |
|
[self setImageView:[[NSView alloc] init]]; |
|
[[self imageView] setWantsLayer:true]; |
|
[self addSubview:[self imageView]]; |
|
} |
|
|
|
[[[self imageView] layer] setContents:image]; |
|
|
|
NSRect imageViewFrame = [self frame]; |
|
imageViewFrame.size.height -= [self sliderHeight]; |
|
NSRect constrainedFrame = { imageViewFrame.origin, constrainAspectRatio(imageViewFrame.size, [image size]) }; |
|
[[self imageView] setFrame:constrainedFrame]; |
|
} |
|
else { |
|
NSRect redisplayRect = [self frame]; |
|
redisplayRect.size.height -= [self sliderHeight]; |
|
[self setNeedsDisplayInRect:redisplayRect]; |
|
} |
|
|
|
/*CGColorSpaceRelease(colorspace); |
|
CGDataProviderRelease(provider); |
|
CGImageRelease(imageRef);*/ |
|
|
|
[localpool drain]; |
|
} |
|
|
|
- (void)setFrameSize:(NSSize)size { |
|
//cout << "setFrameSize" << endl; |
|
[super setFrameSize:size]; |
|
|
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
int height = size.height; |
|
|
|
CVWindow *cvwindow = (CVWindow *)[self window]; |
|
if ([cvwindow respondsToSelector:@selector(sliders)]) { |
|
for(NSString *key in [cvwindow slidersKeys]) { |
|
CVSlider *slider = [[cvwindow sliders] valueForKey:key]; |
|
NSRect r = [slider frame]; |
|
r.origin.y = height - r.size.height; |
|
r.size.width = [[cvwindow contentView] frame].size.width; |
|
|
|
CGRect sliderRect = slider.slider.frame; |
|
CGFloat targetWidth = r.size.width - (sliderRect.origin.x + 10); |
|
sliderRect.size.width = targetWidth < 0 ? 0 : targetWidth; |
|
slider.slider.frame = sliderRect; |
|
|
|
[slider setFrame:r]; |
|
height -= r.size.height; |
|
} |
|
} |
|
NSRect frame = self.frame; |
|
if (frame.size.height < self.sliderHeight) { |
|
frame.size.height = self.sliderHeight; |
|
self.frame = frame; |
|
} |
|
if ([self imageView]) { |
|
NSRect imageViewFrame = frame; |
|
imageViewFrame.size.height -= [self sliderHeight]; |
|
NSRect constrainedFrame = { imageViewFrame.origin, constrainAspectRatio(imageViewFrame.size, [image size]) }; |
|
[[self imageView] setFrame:constrainedFrame]; |
|
} |
|
[localpool drain]; |
|
} |
|
|
|
- (void)drawRect:(NSRect)rect { |
|
//cout << "drawRect" << endl; |
|
[super drawRect:rect]; |
|
// If imageView exists, all drawing will be done by it and nothing needs to happen here |
|
if ([self image] && ![self imageView]) { |
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init]; |
|
|
|
if(image != nil) { |
|
[image drawInRect: [self frame] |
|
fromRect: NSZeroRect |
|
operation: NSCompositeSourceOver |
|
fraction: 1.0]; |
|
} |
|
[localpool release]; |
|
} |
|
} |
|
|
|
@end |
|
|
|
@implementation CVSlider |
|
|
|
@synthesize slider; |
|
@synthesize name; |
|
@synthesize initialName; |
|
@synthesize value; |
|
@synthesize userData; |
|
@synthesize callback; |
|
@synthesize callback2; |
|
|
|
- (id)init { |
|
[super init]; |
|
|
|
callback = NULL; |
|
value = NULL; |
|
userData = NULL; |
|
|
|
[self setFrame:NSMakeRect(0,0,200,30)]; |
|
|
|
name = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 0,110, 25)]; |
|
[name setEditable:NO]; |
|
[name setSelectable:NO]; |
|
[name setBezeled:NO]; |
|
[name setBordered:NO]; |
|
[name setDrawsBackground:NO]; |
|
[[name cell] setLineBreakMode:NSLineBreakByTruncatingTail]; |
|
[self addSubview:name]; |
|
|
|
slider = [[NSSlider alloc] initWithFrame:NSMakeRect(120, 0, 70, 25)]; |
|
[slider setAutoresizingMask:NSViewWidthSizable]; |
|
[slider setMinValue:0]; |
|
[slider setMaxValue:100]; |
|
[slider setContinuous:YES]; |
|
[slider setTarget:self]; |
|
[slider setAction:@selector(handleSliderNotification:)]; |
|
[self addSubview:slider]; |
|
|
|
[self setAutoresizingMask:NSViewWidthSizable]; |
|
|
|
//[self setFrame:NSMakeRect(12, 0, 100, 30)]; |
|
|
|
return self; |
|
} |
|
|
|
- (void)handleSliderNotification:(NSNotification *)notification { |
|
(void)notification; |
|
[self handleSlider]; |
|
} |
|
|
|
- (void)handleSlider { |
|
int pos = [slider intValue]; |
|
NSString *temp = [self initialName]; |
|
NSString *text = [NSString stringWithFormat:@"%@ %d", temp, pos]; |
|
[name setStringValue: text]; |
|
if(value) |
|
*value = pos; |
|
if(callback) |
|
callback(pos); |
|
if(callback2) |
|
callback2(pos, userData); |
|
} |
|
|
|
@end |
|
|
|
#endif |
|
|
|
/* End of file. */
|
|
|