1 // Copyright (c) 2013-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
16 #import <Cocoa/Cocoa.h>
18 #include <Draw_Window.hxx>
19 #include <Cocoa_LocalPool.hxx>
21 @interface Draw_CocoaView : NSView
26 - (void )setImage: (NSImage* )theImage;
30 @implementation Draw_CocoaView
32 - (void )setImage: (NSImage* )theImage
41 return YES; // for drawing image from left-top corner
46 [self setNeedsDisplay: YES];
49 - (void )drawRect: (NSRect )theRect
52 NSRect aBounds = NSMakeRect (0.0, 0.0, myImage.size.width, myImage.size.height);
54 [myImage drawInRect: aBounds
56 operation: NSCompositeSourceOver
69 static Standard_Integer getScreenBottom()
71 NSRect aRect = [[[NSScreen screens] objectAtIndex:0] frame];
72 Standard_Integer aScreenBottom = Standard_Integer(aRect.size.height + aRect.origin.y);
76 extern Standard_Boolean Draw_VirtualWindows;
77 static Standard_Boolean Draw_IsInZoomingMode = Standard_False;
79 Standard_Real Draw_RGBColorsArray[MAXCOLOR][3] = {{1.0, 1.0, 1.0},
95 //=======================================================================
96 //function : Draw_Window
98 //=======================================================================
99 Draw_Window::Draw_Window() :
102 myImageBuffer (NULL),
103 myUseBuffer (Standard_False),
104 nextWindow (firstWindow),
105 previousWindow (NULL)
107 if (firstWindow != NULL) firstWindow->previousWindow = this;
111 //=======================================================================
112 //function : Draw_Window
114 //=======================================================================
115 Draw_Window::Draw_Window (Standard_CString theTitle,
116 const Standard_Integer& theXLeft, const Standard_Integer& theYTop,
117 const Standard_Integer& theWidth, const Standard_Integer& theHeight):
120 myImageBuffer (NULL),
121 myUseBuffer (Standard_False),
122 nextWindow (firstWindow),
123 previousWindow (NULL)
125 if (firstWindow != NULL) firstWindow->previousWindow = this;
127 Init (theXLeft, theYTop, theWidth, theHeight);
131 Draw_Window::Draw_Window (NSWindow* theWindow, Standard_CString theTitle,
132 const Standard_Integer& theXLeft, const Standard_Integer& theYTop,
133 const Standard_Integer& theWidth, const Standard_Integer& theHeight):
136 myImageBuffer (NULL),
137 myUseBuffer (Standard_False),
138 nextWindow (firstWindow),
139 previousWindow (NULL)
141 myWindow = [theWindow retain];
142 if (firstWindow != NULL) firstWindow->previousWindow = this;
144 Init (theXLeft, theYTop, theWidth, theHeight);
148 //=======================================================================
149 //function : ~Draw_Window
151 //=======================================================================
152 Draw_Window::~Draw_Window()
154 if (previousWindow != NULL)
156 previousWindow->nextWindow = nextWindow;
160 firstWindow = nextWindow;
163 if (nextWindow != NULL)
165 nextWindow->previousWindow = previousWindow;
168 if (myWindow != NULL)
180 if (myImageBuffer != NULL)
182 [myImageBuffer release];
183 myImageBuffer = NULL;
187 //=======================================================================
190 //=======================================================================
191 void Draw_Window::Init (const Standard_Integer& theXLeft, const Standard_Integer& theYTop,
192 const Standard_Integer& theWidth, const Standard_Integer& theHeight)
194 Cocoa_LocalPool aLocalPool;
196 // converting left-bottom coordinate to left-top coordinate
197 Standard_Integer anYTop = getScreenBottom() - theYTop - theHeight;
199 if (myWindow == NULL)
201 NSRect aRectNs = NSMakeRect (theXLeft, anYTop, theWidth, theHeight);
202 NSUInteger aWinStyle = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
204 myWindow = [[NSWindow alloc] initWithContentRect: aRectNs
206 backing: NSBackingStoreBuffered
212 NSRect aBounds = [[myWindow contentView] bounds];
214 myView = [[Draw_CocoaView alloc] initWithFrame: aBounds];
215 [myWindow setContentView: myView];
218 if (myImageBuffer == NULL)
220 NSRect aRectNs = [myView bounds];
221 myImageBuffer = [[NSImage alloc] initWithSize: aRectNs.size];
224 [myView setImage: myImageBuffer];
226 myUseBuffer = Draw_VirtualWindows;
230 [myWindow setBackgroundColor: NSColor.blackColor];
231 [myWindow setReleasedWhenClosed: NO];
234 //=======================================================================
235 //function : InitBuffer
237 //=======================================================================
238 void Draw_Window::InitBuffer()
243 //=======================================================================
244 //function : SetPosition
246 //=======================================================================
247 void Draw_Window::SetPosition (const Standard_Integer& theNewXpos,
248 const Standard_Integer& theNewYpos)
250 NSPoint aNewPosition = NSMakePoint (theNewXpos, theNewYpos);
251 [myWindow setFrameTopLeftPoint: aNewPosition];
254 //=======================================================================
255 //function : SetDimension
257 //=======================================================================
258 void Draw_Window::SetDimension (const Standard_Integer& theNewWidth,
259 const Standard_Integer& theNewHeight)
261 NSRect aWindowRect = [myWindow frame];
262 Standard_Integer aNewY = aWindowRect.origin.y + aWindowRect.size.height - theNewHeight;
263 NSRect aNewContentRect = NSMakeRect (aWindowRect.origin.x, aNewY,
264 theNewWidth, theNewHeight);
265 [myWindow setFrame: aNewContentRect display: YES];
268 //=======================================================================
269 //function : GetPosition
271 //=======================================================================
272 void Draw_Window::GetPosition (Standard_Integer &thePosX,
273 Standard_Integer &thePosY)
275 NSRect aWindowRect = [myWindow frame];
276 thePosX = aWindowRect.origin.x;
277 thePosY = getScreenBottom() - aWindowRect.origin.y - aWindowRect.size.height;
280 //=======================================================================
281 //function : HeightWin
283 //=======================================================================
284 Standard_Integer Draw_Window::HeightWin() const
286 NSRect aViewBounds = [myView bounds];
287 return aViewBounds.size.height;
290 //=======================================================================
291 //function : WidthWin
293 //=======================================================================
294 Standard_Integer Draw_Window::WidthWin() const
296 NSRect aViewBounds = [myView bounds];
297 return aViewBounds.size.width;
300 //=======================================================================
301 //function : SetTitle
303 //=======================================================================
304 void Draw_Window::SetTitle (Standard_CString theTitle)
306 NSString* aTitleNs = [[NSString alloc] initWithUTF8String: theTitle];
307 [myWindow setTitle: aTitleNs];
311 //=======================================================================
312 //function : GetTitle
314 //=======================================================================
315 Standard_CString Draw_Window::GetTitle()
317 Standard_CString aTitle = [[myWindow title] UTF8String];
321 //=======================================================================
322 //function :DefineColor
324 //=======================================================================
325 Standard_Boolean Draw_Window::DefineColor (const Standard_Integer&, Standard_CString)
327 return Standard_True; // unused
330 //=======================================================================
331 //function : DisplayWindow
333 //=======================================================================
334 void Draw_Window::DisplayWindow()
336 if (Draw_VirtualWindows)
341 if (myWindow != NULL)
343 [myWindow orderFront: NULL];
347 //=======================================================================
350 //=======================================================================
351 void Draw_Window::Hide()
353 if (myWindow != NULL)
355 [myWindow orderOut: NULL];
359 //=======================================================================
362 //=======================================================================
363 void Draw_Window::Destroy()
365 if (myWindow != NULL)
377 if (myImageBuffer != NULL)
379 [myImageBuffer release];
380 myImageBuffer = NULL;
384 //=======================================================================
387 //=======================================================================
388 void Draw_Window::Clear()
390 [myImageBuffer lockFocus];
391 [[NSColor blackColor] set];
392 NSRect anImageBounds = NSMakeRect (0.0, 0.0, myImageBuffer.size.width, myImageBuffer.size.height);
393 NSRectFill (anImageBounds);
394 [myImageBuffer unlockFocus];
402 //=======================================================================
405 //=======================================================================
406 void Draw_Window::Flush()
411 //=======================================================================
412 //function : DrawString
414 //=======================================================================
415 void Draw_Window::DrawString (const Standard_Integer& theXLeft, const Standard_Integer& theYTop, char* theText)
417 Cocoa_LocalPool aLocalPool;
419 NSString* aTextNs = [[[NSString alloc] initWithUTF8String: theText] autorelease];
420 NSColor* aColor = [NSColor colorWithDeviceRed: Draw_RGBColorsArray[myCurrentColor][0]
421 green: Draw_RGBColorsArray[myCurrentColor][1]
422 blue: Draw_RGBColorsArray[myCurrentColor][2]
424 NSDictionary* anAttributes = [[[NSDictionary alloc] initWithObjectsAndKeys: aColor, NSForegroundColorAttributeName, nil] autorelease];
426 [myImageBuffer lockFocus];
427 [aTextNs drawAtPoint: NSMakePoint (theXLeft, myImageBuffer.size.height - theYTop) withAttributes: anAttributes];
428 [myImageBuffer unlockFocus];
436 //=======================================================================
437 //function : DrawSegments
439 //=======================================================================
440 void Draw_Window::DrawSegments (Segment *theSegment, const Standard_Integer& theNumberOfElements)
442 Cocoa_LocalPool aLocalPool;
444 NSBezierPath* aPath = [[[NSBezierPath alloc] init] autorelease];
447 Standard_Integer anIter = 0;
449 if (Draw_IsInZoomingMode)
451 // workaround for rectangle drawing when zooming
452 anImage = [[myImageBuffer copy] autorelease];
457 anImage = myImageBuffer;
461 for (; anIter < theNumberOfElements; anIter++)
463 NSPoint aPoint = NSMakePoint (theSegment[anIter].myXStart, myImageBuffer.size.height - theSegment[anIter].myYStart);
464 [aPath moveToPoint: aPoint];
465 aPoint = NSMakePoint (theSegment[anIter].myXEnd, myImageBuffer.size.height - theSegment[anIter].myYEnd);
466 [aPath lineToPoint: aPoint];
470 NSColor* aColor = [NSColor colorWithDeviceRed: Draw_RGBColorsArray[myCurrentColor][0]
471 green: Draw_RGBColorsArray[myCurrentColor][1]
472 blue: Draw_RGBColorsArray[myCurrentColor][2]
476 [anImage unlockFocus];
480 [myView setImage: anImage];
484 Draw_IsInZoomingMode = Standard_False;
487 //=======================================================================
490 //=======================================================================
491 void Draw_Window::Redraw()
499 //=======================================================================
500 //function : SetColor
502 //=======================================================================
503 void Draw_Window::SetColor (const Standard_Integer& theColor)
505 myCurrentColor = theColor;
508 //=======================================================================
511 //=======================================================================
512 void Draw_Window::SetMode (const Standard_Integer& theMode)
518 //=======================================================================
521 //=======================================================================
522 Standard_Boolean Draw_Window::Save (Standard_CString theFileName) const
524 Cocoa_LocalPool aLocalPool;
526 NSString* aFileName = [[[NSString alloc] initWithUTF8String: theFileName] autorelease];
527 NSString* aFileExtension = [[aFileName pathExtension] lowercaseString];
529 NSDictionary* aFileTypeDict = [NSDictionary dictionaryWithObjectsAndKeys:
530 [NSNumber numberWithInt: NSPNGFileType], @"png",
531 [NSNumber numberWithInt: NSBMPFileType], @"bmp",
532 [NSNumber numberWithInt: NSJPEGFileType], @"jpg",
533 [NSNumber numberWithInt: NSGIFFileType], @"gif",
535 if ([aFileTypeDict valueForKey: aFileExtension] == NULL)
537 return Standard_False; // unsupported image extension
540 NSBitmapImageFileType aFileType = (NSBitmapImageFileType )[[aFileTypeDict valueForKey: aFileExtension] intValue];
541 NSBitmapImageRep* anImageRep = [NSBitmapImageRep imageRepWithData: [myImageBuffer TIFFRepresentation]];
543 NSDictionary* anImgProps = [NSDictionary dictionaryWithObject: [NSNumber numberWithFloat: 0.8]
544 forKey: NSImageCompressionFactor];
546 NSData* aData = [anImageRep representationUsingType: aFileType
547 properties: anImgProps];
549 Standard_Boolean isSuccess = [aData writeToFile: aFileName
555 Standard_Boolean Draw_Window::IsEqualWindows (const Standard_Integer& theWindowNumber)
557 return ([myWindow windowNumber] == theWindowNumber);
560 void GetNextEvent (Standard_Boolean theWait,
561 Standard_Integer& theWindowNumber,
562 Standard_Integer& theX,
563 Standard_Integer& theY,
564 Standard_Integer& theButton)
566 Cocoa_LocalPool aLocalPool;
568 unsigned int anEventMatchMask = NSLeftMouseDownMask | NSRightMouseDownMask;
572 anEventMatchMask = anEventMatchMask | NSMouseMovedMask | NSLeftMouseDraggedMask;
573 Draw_IsInZoomingMode = Standard_True;
576 NSEvent* anEvent = [NSApp nextEventMatchingMask: anEventMatchMask
577 untilDate: [NSDate distantFuture]
578 inMode: NSEventTrackingRunLoopMode
581 NSWindow* aWindow = [anEvent window];
582 NSView* aView = [aWindow contentView];
583 theWindowNumber = [aWindow windowNumber];
585 NSPoint aMouseLoc = [aView convertPoint: [anEvent locationInWindow] fromView: nil];
587 theX = Standard_Integer (aMouseLoc.x);
588 theY = Standard_Integer (aMouseLoc.y);
590 NSEventType anEventType = [anEvent type];
592 if (anEventType == NSLeftMouseDown)
596 else if (anEventType == NSRightMouseDown)
600 else if ((anEventType == NSMouseMoved || anEventType == NSLeftMouseDragged) && !theWait)