d5f74e42 |
1 | // Copyright (c) 2013-2014 OPEN CASCADE SAS |
67d97f0e |
2 | // |
973c2be1 |
3 | // This file is part of Open CASCADE Technology software library. |
67d97f0e |
4 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
67d97f0e |
10 | // |
973c2be1 |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
67d97f0e |
13 | |
14 | #if defined(__APPLE__) && !defined(MACOSX_USE_GLX) |
15 | |
16 | #import <Cocoa/Cocoa.h> |
17 | |
18 | #include <Draw_Window.hxx> |
19 | #include <Cocoa_LocalPool.hxx> |
20 | |
21 | @interface Draw_CocoaView : NSView |
22 | { |
23 | NSImage* myImage; |
24 | } |
25 | |
26 | - (void )setImage: (NSImage* )theImage; |
27 | - (void )redraw; |
28 | @end |
29 | |
30 | @implementation Draw_CocoaView |
31 | |
32 | - (void )setImage: (NSImage* )theImage |
33 | { |
34 | [theImage retain]; |
35 | [myImage release]; |
36 | myImage = theImage; |
37 | } |
38 | |
39 | - (BOOL )isFlipped |
40 | { |
41 | return YES; // for drawing image from left-top corner |
42 | } |
43 | |
44 | - (void )redraw |
45 | { |
46 | [self setNeedsDisplay: YES]; |
47 | } |
48 | |
49 | - (void )drawRect: (NSRect )theRect |
50 | { |
5ef127d0 |
51 | (void )theRect; |
67d97f0e |
52 | NSRect aBounds = NSMakeRect (0.0, 0.0, myImage.size.width, myImage.size.height); |
53 | |
54 | [myImage drawInRect: aBounds |
55 | fromRect: NSZeroRect |
56 | operation: NSCompositeSourceOver |
57 | fraction: 1 |
58 | respectFlipped: YES |
59 | hints: nil]; |
60 | } |
61 | |
62 | - (void )dealloc |
63 | { |
64 | [myImage release]; |
65 | [super dealloc]; |
66 | } |
67 | @end |
68 | |
69 | static Standard_Integer getScreenBottom() |
70 | { |
71 | NSRect aRect = [[[NSScreen screens] objectAtIndex:0] frame]; |
72 | Standard_Integer aScreenBottom = Standard_Integer(aRect.size.height + aRect.origin.y); |
73 | return aScreenBottom; |
74 | } |
75 | |
76 | extern Standard_Boolean Draw_VirtualWindows; |
77 | static Standard_Boolean Draw_IsInZoomingMode = Standard_False; |
78 | |
79 | Standard_Real Draw_RGBColorsArray[MAXCOLOR][3] = {{1.0, 1.0, 1.0}, |
80 | {1.0, 0.0, 0.0}, |
81 | {0.0, 1.0, 0.0}, |
82 | {0.0, 0.0, 1.0}, |
83 | {0.0, 1.0, 1.0}, |
84 | {1.0, 0.84, 0.0}, |
85 | {1.0, 0.0, 1.0}, |
86 | {1.0, 0.2, 0.7}, |
87 | {1.0, 0.65, 0.0}, |
88 | {1.0, 0.89, 0.88}, |
89 | {1.0, 0.63, 0.48}, |
90 | {0.78, 0.08, 0.52}, |
91 | {1.0, 1.0, 0.0}, |
92 | {0.94, 0.9, 0.55}, |
93 | {1.0, 0.5, 0.31}}; |
94 | |
95 | //======================================================================= |
96 | //function : Draw_Window |
97 | //purpose : |
98 | //======================================================================= |
99 | Draw_Window::Draw_Window() : |
100 | myWindow (NULL), |
101 | myView (NULL), |
102 | myImageBuffer (NULL), |
103 | myUseBuffer (Standard_False), |
104 | nextWindow (firstWindow), |
105 | previousWindow (NULL) |
106 | { |
107 | if (firstWindow != NULL) firstWindow->previousWindow = this; |
108 | firstWindow = this; |
109 | } |
110 | |
111 | //======================================================================= |
112 | //function : Draw_Window |
113 | //purpose : |
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): |
118 | myWindow (NULL), |
119 | myView (NULL), |
120 | myImageBuffer (NULL), |
121 | myUseBuffer (Standard_False), |
122 | nextWindow (firstWindow), |
123 | previousWindow (NULL) |
124 | { |
125 | if (firstWindow != NULL) firstWindow->previousWindow = this; |
126 | firstWindow = this; |
127 | Init (theXLeft, theYTop, theWidth, theHeight); |
128 | SetTitle (theTitle); |
129 | } |
130 | |
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): |
134 | myWindow (NULL), |
135 | myView (NULL), |
136 | myImageBuffer (NULL), |
137 | myUseBuffer (Standard_False), |
138 | nextWindow (firstWindow), |
139 | previousWindow (NULL) |
140 | { |
141 | myWindow = [theWindow retain]; |
142 | if (firstWindow != NULL) firstWindow->previousWindow = this; |
143 | firstWindow = this; |
144 | Init (theXLeft, theYTop, theWidth, theHeight); |
145 | SetTitle (theTitle); |
146 | } |
147 | |
148 | //======================================================================= |
149 | //function : ~Draw_Window |
150 | //purpose : |
151 | //======================================================================= |
152 | Draw_Window::~Draw_Window() |
153 | { |
154 | if (previousWindow != NULL) |
155 | { |
156 | previousWindow->nextWindow = nextWindow; |
157 | } |
158 | else |
159 | { |
160 | firstWindow = nextWindow; |
161 | } |
162 | |
163 | if (nextWindow != NULL) |
164 | { |
165 | nextWindow->previousWindow = previousWindow; |
166 | } |
167 | |
168 | if (myWindow != NULL) |
169 | { |
170 | [myWindow release]; |
171 | myWindow = NULL; |
172 | } |
173 | |
174 | if (myView != NULL) |
175 | { |
176 | [myView release]; |
177 | myView = NULL; |
178 | } |
179 | |
180 | if (myImageBuffer != NULL) |
181 | { |
182 | [myImageBuffer release]; |
183 | myImageBuffer = NULL; |
184 | } |
185 | } |
186 | |
187 | //======================================================================= |
188 | //function : Init |
189 | //purpose : |
190 | //======================================================================= |
191 | void Draw_Window::Init (const Standard_Integer& theXLeft, const Standard_Integer& theYTop, |
192 | const Standard_Integer& theWidth, const Standard_Integer& theHeight) |
193 | { |
194 | Cocoa_LocalPool aLocalPool; |
195 | |
196 | // converting left-bottom coordinate to left-top coordinate |
197 | Standard_Integer anYTop = getScreenBottom() - theYTop - theHeight; |
198 | |
199 | if (myWindow == NULL) |
200 | { |
201 | NSRect aRectNs = NSMakeRect (theXLeft, anYTop, theWidth, theHeight); |
202 | NSUInteger aWinStyle = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask; |
203 | |
204 | myWindow = [[NSWindow alloc] initWithContentRect: aRectNs |
205 | styleMask: aWinStyle |
206 | backing: NSBackingStoreBuffered |
207 | defer: NO]; |
208 | } |
209 | |
210 | if (myView == NULL) |
211 | { |
212 | NSRect aBounds = [[myWindow contentView] bounds]; |
213 | |
214 | myView = [[Draw_CocoaView alloc] initWithFrame: aBounds]; |
215 | [myWindow setContentView: myView]; |
216 | } |
217 | |
218 | if (myImageBuffer == NULL) |
219 | { |
220 | NSRect aRectNs = [myView bounds]; |
221 | myImageBuffer = [[NSImage alloc] initWithSize: aRectNs.size]; |
222 | } |
223 | |
224 | [myView setImage: myImageBuffer]; |
225 | |
226 | myUseBuffer = Draw_VirtualWindows; |
227 | |
228 | myCurrentColor = 3; |
229 | |
230 | [myWindow setBackgroundColor: NSColor.blackColor]; |
231 | [myWindow setReleasedWhenClosed: NO]; |
232 | } |
233 | |
234 | //======================================================================= |
235 | //function : InitBuffer |
236 | //purpose : |
237 | //======================================================================= |
238 | void Draw_Window::InitBuffer() |
239 | { |
240 | // |
241 | } |
242 | |
243 | //======================================================================= |
244 | //function : SetPosition |
245 | //purpose : |
246 | //======================================================================= |
247 | void Draw_Window::SetPosition (const Standard_Integer& theNewXpos, |
248 | const Standard_Integer& theNewYpos) |
249 | { |
250 | NSPoint aNewPosition = NSMakePoint (theNewXpos, theNewYpos); |
251 | [myWindow setFrameTopLeftPoint: aNewPosition]; |
252 | } |
253 | |
254 | //======================================================================= |
255 | //function : SetDimension |
256 | //purpose : |
257 | //======================================================================= |
258 | void Draw_Window::SetDimension (const Standard_Integer& theNewWidth, |
259 | const Standard_Integer& theNewHeight) |
260 | { |
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]; |
266 | } |
267 | |
268 | //======================================================================= |
269 | //function : GetPosition |
270 | //purpose : |
271 | //======================================================================= |
272 | void Draw_Window::GetPosition (Standard_Integer &thePosX, |
273 | Standard_Integer &thePosY) |
274 | { |
275 | NSRect aWindowRect = [myWindow frame]; |
276 | thePosX = aWindowRect.origin.x; |
277 | thePosY = getScreenBottom() - aWindowRect.origin.y - aWindowRect.size.height; |
278 | } |
279 | |
280 | //======================================================================= |
281 | //function : HeightWin |
282 | //purpose : |
283 | //======================================================================= |
284 | Standard_Integer Draw_Window::HeightWin() const |
285 | { |
286 | NSRect aViewBounds = [myView bounds]; |
287 | return aViewBounds.size.height; |
288 | } |
289 | |
290 | //======================================================================= |
291 | //function : WidthWin |
292 | //purpose : |
293 | //======================================================================= |
294 | Standard_Integer Draw_Window::WidthWin() const |
295 | { |
296 | NSRect aViewBounds = [myView bounds]; |
297 | return aViewBounds.size.width; |
298 | } |
299 | |
300 | //======================================================================= |
301 | //function : SetTitle |
302 | //purpose : |
303 | //======================================================================= |
304 | void Draw_Window::SetTitle (Standard_CString theTitle) |
305 | { |
306 | NSString* aTitleNs = [[NSString alloc] initWithUTF8String: theTitle]; |
307 | [myWindow setTitle: aTitleNs]; |
308 | [aTitleNs release]; |
309 | } |
310 | |
311 | //======================================================================= |
312 | //function : GetTitle |
313 | //purpose : |
314 | //======================================================================= |
315 | Standard_CString Draw_Window::GetTitle() |
316 | { |
317 | Standard_CString aTitle = [[myWindow title] UTF8String]; |
318 | return aTitle; |
319 | } |
320 | |
321 | //======================================================================= |
322 | //function :DefineColor |
323 | //purpose : |
324 | //======================================================================= |
325 | Standard_Boolean Draw_Window::DefineColor (const Standard_Integer&, Standard_CString) |
326 | { |
327 | return Standard_True; // unused |
328 | } |
329 | |
330 | //======================================================================= |
331 | //function : DisplayWindow |
332 | //purpose : |
333 | //======================================================================= |
334 | void Draw_Window::DisplayWindow() |
335 | { |
336 | if (Draw_VirtualWindows) |
337 | { |
338 | return; |
339 | } |
340 | |
341 | if (myWindow != NULL) |
342 | { |
343 | [myWindow orderFront: NULL]; |
344 | } |
345 | } |
346 | |
347 | //======================================================================= |
348 | //function : Hide |
349 | //purpose : |
350 | //======================================================================= |
351 | void Draw_Window::Hide() |
352 | { |
353 | if (myWindow != NULL) |
354 | { |
355 | [myWindow orderOut: NULL]; |
356 | } |
357 | } |
358 | |
359 | //======================================================================= |
360 | //function : Destroy |
361 | //purpose : |
362 | //======================================================================= |
363 | void Draw_Window::Destroy() |
364 | { |
365 | if (myWindow != NULL) |
366 | { |
367 | [myWindow release]; |
368 | myWindow = NULL; |
369 | } |
370 | |
371 | if (myView != NULL) |
372 | { |
373 | [myView release]; |
374 | myView = NULL; |
375 | } |
376 | |
377 | if (myImageBuffer != NULL) |
378 | { |
379 | [myImageBuffer release]; |
380 | myImageBuffer = NULL; |
381 | } |
382 | } |
383 | |
384 | //======================================================================= |
385 | //function : Clear |
386 | //purpose : |
387 | //======================================================================= |
388 | void Draw_Window::Clear() |
389 | { |
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]; |
395 | |
396 | if (!myUseBuffer) |
397 | { |
398 | [myView redraw]; |
399 | } |
400 | } |
401 | |
402 | //======================================================================= |
403 | //function : Flush |
404 | //purpose : |
405 | //======================================================================= |
406 | void Draw_Window::Flush() |
407 | { |
408 | // |
409 | } |
410 | |
411 | //======================================================================= |
412 | //function : DrawString |
413 | //purpose : |
414 | //======================================================================= |
415 | void Draw_Window::DrawString (const Standard_Integer& theXLeft, const Standard_Integer& theYTop, char* theText) |
416 | { |
417 | Cocoa_LocalPool aLocalPool; |
418 | |
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] |
423 | alpha: 1.0f]; |
424 | NSDictionary* anAttributes = [[[NSDictionary alloc] initWithObjectsAndKeys: aColor, NSForegroundColorAttributeName, nil] autorelease]; |
425 | |
426 | [myImageBuffer lockFocus]; |
427 | [aTextNs drawAtPoint: NSMakePoint (theXLeft, myImageBuffer.size.height - theYTop) withAttributes: anAttributes]; |
428 | [myImageBuffer unlockFocus]; |
429 | |
430 | if (!myUseBuffer) |
431 | { |
432 | [myView redraw]; |
433 | } |
434 | } |
435 | |
436 | //======================================================================= |
437 | //function : DrawSegments |
438 | //purpose : |
439 | //======================================================================= |
440 | void Draw_Window::DrawSegments (Segment *theSegment, const Standard_Integer& theNumberOfElements) |
441 | { |
442 | Cocoa_LocalPool aLocalPool; |
443 | |
444 | NSBezierPath* aPath = [[[NSBezierPath alloc] init] autorelease]; |
445 | |
446 | NSImage* anImage; |
447 | Standard_Integer anIter = 0; |
448 | |
449 | if (Draw_IsInZoomingMode) |
450 | { |
451 | // workaround for rectangle drawing when zooming |
452 | anImage = [[myImageBuffer copy] autorelease]; |
453 | anIter = 4; |
454 | } |
455 | else |
456 | { |
457 | anImage = myImageBuffer; |
458 | } |
459 | |
460 | |
461 | for (; anIter < theNumberOfElements; anIter++) |
462 | { |
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]; |
467 | } |
468 | |
469 | [anImage lockFocus]; |
470 | NSColor* aColor = [NSColor colorWithDeviceRed: Draw_RGBColorsArray[myCurrentColor][0] |
471 | green: Draw_RGBColorsArray[myCurrentColor][1] |
472 | blue: Draw_RGBColorsArray[myCurrentColor][2] |
473 | alpha: 1.0f]; |
474 | [aColor set]; |
475 | [aPath stroke]; |
476 | [anImage unlockFocus]; |
477 | |
478 | if (!myUseBuffer) |
479 | { |
480 | [myView setImage: anImage]; |
481 | [myView redraw]; |
482 | } |
483 | |
484 | Draw_IsInZoomingMode = Standard_False; |
485 | } |
486 | |
487 | //======================================================================= |
488 | //function : Redraw |
489 | //purpose : |
490 | //======================================================================= |
491 | void Draw_Window::Redraw() |
492 | { |
493 | if (myUseBuffer) |
494 | { |
495 | [myView redraw]; |
496 | } |
497 | } |
498 | |
499 | //======================================================================= |
500 | //function : SetColor |
501 | //purpose : |
502 | //======================================================================= |
503 | void Draw_Window::SetColor (const Standard_Integer& theColor) |
504 | { |
505 | myCurrentColor = theColor; |
506 | } |
507 | |
508 | //======================================================================= |
509 | //function : SetMode |
510 | //purpose : |
511 | //======================================================================= |
512 | void Draw_Window::SetMode (const Standard_Integer& theMode) |
513 | { |
5ef127d0 |
514 | // unsupported |
515 | (void )theMode; |
67d97f0e |
516 | } |
517 | |
518 | //======================================================================= |
519 | //function : Save |
520 | //purpose : |
521 | //======================================================================= |
522 | Standard_Boolean Draw_Window::Save (Standard_CString theFileName) const |
523 | { |
524 | Cocoa_LocalPool aLocalPool; |
525 | |
526 | NSString* aFileName = [[[NSString alloc] initWithUTF8String: theFileName] autorelease]; |
527 | NSString* aFileExtension = [[aFileName pathExtension] lowercaseString]; |
528 | |
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", |
534 | nil]; |
52f7e0d0 |
535 | if ([aFileTypeDict valueForKey: aFileExtension] == NULL) |
67d97f0e |
536 | { |
537 | return Standard_False; // unsupported image extension |
538 | } |
539 | |
52f7e0d0 |
540 | NSBitmapImageFileType aFileType = (NSBitmapImageFileType )[[aFileTypeDict valueForKey: aFileExtension] intValue]; |
67d97f0e |
541 | NSBitmapImageRep* anImageRep = [NSBitmapImageRep imageRepWithData: [myImageBuffer TIFFRepresentation]]; |
542 | |
5ef127d0 |
543 | NSDictionary* anImgProps = [NSDictionary dictionaryWithObject: [NSNumber numberWithFloat: 0.8] |
544 | forKey: NSImageCompressionFactor]; |
545 | |
67d97f0e |
546 | NSData* aData = [anImageRep representationUsingType: aFileType |
5ef127d0 |
547 | properties: anImgProps]; |
67d97f0e |
548 | |
549 | Standard_Boolean isSuccess = [aData writeToFile: aFileName |
550 | atomically: NO]; |
551 | |
552 | return isSuccess; |
553 | } |
554 | |
555 | Standard_Boolean Draw_Window::IsEqualWindows (const Standard_Integer& theWindowNumber) |
556 | { |
557 | return ([myWindow windowNumber] == theWindowNumber); |
558 | } |
559 | |
560 | void GetNextEvent (Standard_Boolean theWait, |
561 | Standard_Integer& theWindowNumber, |
562 | Standard_Integer& theX, |
563 | Standard_Integer& theY, |
564 | Standard_Integer& theButton) |
565 | { |
566 | Cocoa_LocalPool aLocalPool; |
567 | |
568 | unsigned int anEventMatchMask = NSLeftMouseDownMask | NSRightMouseDownMask; |
569 | |
570 | if (!theWait) |
571 | { |
572 | anEventMatchMask = anEventMatchMask | NSMouseMovedMask | NSLeftMouseDraggedMask; |
573 | Draw_IsInZoomingMode = Standard_True; |
574 | } |
575 | |
576 | NSEvent* anEvent = [NSApp nextEventMatchingMask: anEventMatchMask |
577 | untilDate: [NSDate distantFuture] |
578 | inMode: NSEventTrackingRunLoopMode |
579 | dequeue: YES]; |
580 | |
581 | NSWindow* aWindow = [anEvent window]; |
582 | NSView* aView = [aWindow contentView]; |
583 | theWindowNumber = [aWindow windowNumber]; |
584 | |
585 | NSPoint aMouseLoc = [aView convertPoint: [anEvent locationInWindow] fromView: nil]; |
67d97f0e |
586 | |
587 | theX = Standard_Integer (aMouseLoc.x); |
588 | theY = Standard_Integer (aMouseLoc.y); |
589 | |
590 | NSEventType anEventType = [anEvent type]; |
591 | |
592 | if (anEventType == NSLeftMouseDown) |
593 | { |
594 | theButton = 1; |
595 | } |
596 | else if (anEventType == NSRightMouseDown) |
597 | { |
598 | theButton = 3; |
599 | } |
600 | else if ((anEventType == NSMouseMoved || anEventType == NSLeftMouseDragged) && !theWait) |
601 | { |
602 | theButton = 0; |
603 | } |
604 | } |
605 | #endif // __APPLE__ |