0029156: Coding Rules - eliminate deprecation compiler warnings when targeting macOS...
[occt.git] / src / Cocoa / Cocoa_Window.mm
1 // Created on: 2012-11-12
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #import <TargetConditionals.h>
17
18 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
19   #import <UIKit/UIKit.h>
20 #else
21   #import <Cocoa/Cocoa.h>
22 #endif
23
24 #include <Cocoa_Window.hxx>
25
26 #include <Cocoa_LocalPool.hxx>
27
28 #include <Image_AlienPixMap.hxx>
29 #include <Aspect_Convert.hxx>
30 #include <Aspect_WindowDefinitionError.hxx>
31
32 IMPLEMENT_STANDARD_RTTIEXT(Cocoa_Window,Aspect_Window)
33
34 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
35   //
36 #else
37
38 #if !defined(MAC_OS_X_VERSION_10_12) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12)
39   // replacements for macOS versions before 10.12
40   #define NSWindowStyleMaskResizable NSResizableWindowMask
41   #define NSWindowStyleMaskClosable  NSClosableWindowMask
42   #define NSWindowStyleMaskTitled    NSTitledWindowMask
43 #endif
44
45 static Standard_Integer getScreenBottom()
46 {
47   Cocoa_LocalPool aLocalPool;
48   NSArray* aScreens = [NSScreen screens];
49   if (aScreens == NULL || [aScreens count] == 0)
50   {
51     return 0;
52   }
53
54   NSScreen* aScreen = (NSScreen* )[aScreens objectAtIndex: 0];
55   NSDictionary* aDict = [aScreen deviceDescription];
56   NSNumber* aNumber = [aDict objectForKey: @"NSScreenNumber"];
57   if (aNumber == NULL
58   || [aNumber isKindOfClass: [NSNumber class]] == NO)
59   {
60     return 0;
61   }
62
63   CGDirectDisplayID aDispId = [aNumber unsignedIntValue];
64   CGRect aRect = CGDisplayBounds(aDispId);
65   return Standard_Integer(aRect.origin.y + aRect.size.height);
66 }
67 #endif
68
69 // =======================================================================
70 // function : Cocoa_Window
71 // purpose  :
72 // =======================================================================
73 Cocoa_Window::Cocoa_Window (const Standard_CString theTitle,
74                             const Standard_Integer thePxLeft,
75                             const Standard_Integer thePxTop,
76                             const Standard_Integer thePxWidth,
77                             const Standard_Integer thePxHeight)
78 : Aspect_Window (),
79 #if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
80   myHWindow (NULL),
81 #endif
82   myHView   (NULL),
83   myXLeft   (thePxLeft),
84   myYTop    (thePxTop),
85   myXRight  (thePxLeft + thePxWidth),
86   myYBottom (thePxTop + thePxHeight)
87 {
88 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
89   //
90 #else
91   if (thePxWidth <= 0 || thePxHeight <= 0)
92   {
93     throw Aspect_WindowDefinitionError("Coordinate(s) out of range");
94   }
95   else if (NSApp == NULL)
96   {
97     throw Aspect_WindowDefinitionError("Cocoa application should be instantiated before window");
98     return;
99   }
100
101   // convert top-bottom coordinates to bottom-top (Cocoa)
102   myYTop    = getScreenBottom() - myYBottom;
103   myYBottom = myYTop + thePxHeight;
104
105   Cocoa_LocalPool aLocalPool;
106   NSUInteger aWinStyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
107   NSRect aRectNs = NSMakeRect (float(myXLeft), float(myYTop), float(thePxWidth), float(thePxHeight));
108   myHWindow = [[NSWindow alloc] initWithContentRect: aRectNs
109                                           styleMask: aWinStyle
110                                             backing: NSBackingStoreBuffered
111                                               defer: NO];
112   if (myHWindow == NULL)
113   {
114     throw Aspect_WindowDefinitionError("Unable to create window");
115   }
116   myHView = [[myHWindow contentView] retain];
117
118   NSString* aTitleNs = [[NSString alloc] initWithUTF8String: theTitle];
119   [myHWindow setTitle: aTitleNs];
120   [aTitleNs release];
121
122   // do not destroy NSWindow on close - we didn't handle it!
123   [myHWindow setReleasedWhenClosed: NO];
124 #endif
125 }
126
127 // =======================================================================
128 // function : Cocoa_Window
129 // purpose  :
130 // =======================================================================
131 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
132 Cocoa_Window::Cocoa_Window (UIView* theViewNS)
133 : Aspect_Window(),
134 #else
135 Cocoa_Window::Cocoa_Window (NSView* theViewNS)
136 : Aspect_Window(),
137   myHWindow (NULL),
138 #endif
139   myHView   (NULL),
140   myXLeft   (0),
141   myYTop    (0),
142   myXRight  (512),
143   myYBottom (512)
144 {
145 #if defined(HAVE_OBJC_ARC)
146   myHView = theViewNS;
147 #else
148   myHView = [theViewNS retain];
149 #endif
150   DoResize();
151 }
152
153 // =======================================================================
154 // function : ~Cocoa_Window
155 // purpose  :
156 // =======================================================================
157 Cocoa_Window::~Cocoa_Window()
158 {
159 #if !defined(HAVE_OBJC_ARC)
160   Cocoa_LocalPool aLocalPool;
161 #endif
162 #if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
163   if (myHWindow != NULL)
164   {
165   #if !defined(HAVE_OBJC_ARC)
166     //[myHWindow close];
167     [myHWindow release];
168   #endif
169     myHWindow = NULL;
170   }
171 #endif
172   if (myHView != NULL)
173   {
174   #if !defined(HAVE_OBJC_ARC)
175     [myHView release];
176   #endif
177     myHView = NULL;
178   }
179 }
180
181 // =======================================================================
182 // function : SetHView
183 // purpose  :
184 // =======================================================================
185 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
186 void Cocoa_Window::SetHView (UIView* theView)
187 {
188 #else
189 void Cocoa_Window::SetHView (NSView* theView)
190 {
191   if (myHWindow != NULL)
192   {
193     [myHWindow setContentView: theView];
194   }
195 #endif
196
197 #if defined(HAVE_OBJC_ARC)
198   myHView = theView;
199 #else
200   if (myHView != NULL)
201   {
202     [myHView release];
203     myHView = NULL;
204   }
205   myHView = [theView retain];
206 #endif
207 }
208
209 // =======================================================================
210 // function : IsMapped
211 // purpose  :
212 // =======================================================================
213 Standard_Boolean Cocoa_Window::IsMapped() const
214 {
215   if (IsVirtual())
216   {
217     return Standard_True;
218   }
219
220 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
221   return myHView != NULL;
222 #else
223   return myHView != NULL
224    &&  [[myHView window] isVisible];
225 #endif
226 }
227
228 // =======================================================================
229 // function : Map
230 // purpose  :
231 // =======================================================================
232 void Cocoa_Window::Map() const
233 {
234   if (IsVirtual())
235   {
236     return;
237   }
238
239   if (myHView != NULL)
240   {
241   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
242     //
243   #else
244     [[myHView window] orderFront: NULL];
245   #endif
246   }
247 }
248
249 // =======================================================================
250 // function : Unmap
251 // purpose  :
252 // =======================================================================
253 void Cocoa_Window::Unmap() const
254 {
255   if (myHView != NULL)
256   {
257   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
258     //
259   #else
260     [[myHView window] orderOut: NULL];
261   #endif
262   }
263 }
264
265 // =======================================================================
266 // function : DoResize
267 // purpose  :
268 // =======================================================================
269 Aspect_TypeOfResize Cocoa_Window::DoResize() const
270 {
271   if (myHView == NULL)
272   {
273     return Aspect_TOR_UNKNOWN;
274   }
275
276 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
277   CGRect aBounds = [myHView bounds];
278 #else
279   NSRect aBounds = [myHView bounds];
280 #endif
281   Standard_Integer aMask = 0;
282   Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN;
283
284   if (Abs ((Standard_Integer )aBounds.origin.x                         - myXLeft  ) > 2) aMask |= 1;
285   if (Abs ((Standard_Integer )(aBounds.origin.x + aBounds.size.width)  - myXRight ) > 2) aMask |= 2;
286   if (Abs ((Standard_Integer )aBounds.origin.y                         - myYTop   ) > 2) aMask |= 4;
287   if (Abs ((Standard_Integer )(aBounds.origin.y + aBounds.size.height) - myYBottom) > 2) aMask |= 8;
288   switch (aMask)
289   {
290     case 0:  aMode = Aspect_TOR_NO_BORDER;               break;
291     case 1:  aMode = Aspect_TOR_LEFT_BORDER;             break;
292     case 2:  aMode = Aspect_TOR_RIGHT_BORDER;            break;
293     case 4:  aMode = Aspect_TOR_TOP_BORDER;              break;
294     case 5:  aMode = Aspect_TOR_LEFT_AND_TOP_BORDER;     break;
295     case 6:  aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER;    break;
296     case 8:  aMode = Aspect_TOR_BOTTOM_BORDER;           break;
297     case 9:  aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER;  break;
298     case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break;
299     default: break;
300   }
301
302   *((Standard_Integer* )&myXLeft   ) = (Standard_Integer )aBounds.origin.x;
303   *((Standard_Integer* )&myXRight  ) = (Standard_Integer )(aBounds.origin.x + aBounds.size.width);
304   *((Standard_Integer* )&myYTop    ) = (Standard_Integer )aBounds.origin.y;
305   *((Standard_Integer* )&myYBottom ) = (Standard_Integer )(aBounds.origin.y + aBounds.size.height);
306   return aMode;
307 }
308
309 // =======================================================================
310 // function : DoMapping
311 // purpose  :
312 // =======================================================================
313 Standard_Boolean Cocoa_Window::DoMapping() const
314 {
315   return Standard_True;
316 }
317
318 // =======================================================================
319 // function : Ratio
320 // purpose  :
321 // =======================================================================
322 Standard_Real Cocoa_Window::Ratio() const
323 {
324   if (myHView == NULL)
325   {
326     return 1.0;
327   }
328
329 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
330   CGRect aBounds = [myHView bounds];
331 #else
332   NSRect aBounds = [myHView bounds];
333 #endif
334   return Standard_Real (aBounds.size.width / aBounds.size.height);
335 }
336
337 // =======================================================================
338 // function : Position
339 // purpose  :
340 // =======================================================================
341 void Cocoa_Window::Position (Standard_Integer& X1, Standard_Integer& Y1,
342                              Standard_Integer& X2, Standard_Integer& Y2) const
343 {
344 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
345   CGRect aBounds = [myHView bounds];
346   X1 = 0;
347   Y1 = 0;
348   X2 = (Standard_Integer )aBounds.size.width;
349   Y2 = (Standard_Integer )aBounds.size.height;
350 #else
351   NSWindow* aWindow = [myHView window];
352   NSRect aWindowRect = [aWindow frame];
353   X1 = (Standard_Integer) aWindowRect.origin.x;
354   Y1 = getScreenBottom() - (Standard_Integer) aWindowRect.origin.y - (Standard_Integer) aWindowRect.size.height;
355   X2 = X1 + (Standard_Integer) aWindowRect.size.width;
356   Y2 = Y1 + (Standard_Integer) aWindowRect.size.height;
357 #endif
358 }
359
360 // =======================================================================
361 // function : Size
362 // purpose  :
363 // =======================================================================
364 void Cocoa_Window::Size (Standard_Integer& theWidth,
365                          Standard_Integer& theHeight) const
366 {
367   if (myHView == NULL)
368   {
369     return;
370   }
371
372 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
373   CGRect aBounds = [myHView bounds];
374 #else
375   NSRect aBounds = [myHView bounds];
376 #endif
377   theWidth  = (Standard_Integer )aBounds.size.width;
378   theHeight = (Standard_Integer )aBounds.size.height;
379 }