0024002: Overall code and build procedure refactoring -- automatic
[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_HANDLE (Cocoa_Window, Aspect_Window)
33 IMPLEMENT_STANDARD_RTTIEXT(Cocoa_Window, Aspect_Window)
34
35 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
36   //
37 #else
38 static Standard_Integer getScreenBottom()
39 {
40   Cocoa_LocalPool aLocalPool;
41   NSArray* aScreens = [NSScreen screens];
42   if (aScreens == NULL || [aScreens count] == 0)
43   {
44     return 0;
45   }
46
47   NSScreen* aScreen = (NSScreen* )[aScreens objectAtIndex: 0];
48   NSDictionary* aDict = [aScreen deviceDescription];
49   NSNumber* aNumber = [aDict objectForKey: @"NSScreenNumber"];
50   if (aNumber == NULL
51   || [aNumber isKindOfClass: [NSNumber class]] == NO)
52   {
53     return 0;
54   }
55
56   CGDirectDisplayID aDispId = [aNumber unsignedIntValue];
57   CGRect aRect = CGDisplayBounds(aDispId);
58   return Standard_Integer(aRect.origin.y + aRect.size.height);
59 }
60 #endif
61
62 // =======================================================================
63 // function : Cocoa_Window
64 // purpose  :
65 // =======================================================================
66 Cocoa_Window::Cocoa_Window (const Standard_CString theTitle,
67                             const Standard_Integer thePxLeft,
68                             const Standard_Integer thePxTop,
69                             const Standard_Integer thePxWidth,
70                             const Standard_Integer thePxHeight)
71 : Aspect_Window (),
72 #if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
73   myHWindow (NULL),
74 #endif
75   myHView   (NULL),
76   myXLeft   (thePxLeft),
77   myYTop    (thePxTop),
78   myXRight  (thePxLeft + thePxWidth),
79   myYBottom (thePxTop + thePxHeight)
80 {
81 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
82   //
83 #else
84   if (thePxWidth <= 0 || thePxHeight <= 0)
85   {
86     Aspect_WindowDefinitionError::Raise ("Coordinate(s) out of range");
87   }
88   else if (NSApp == NULL)
89   {
90     Aspect_WindowDefinitionError::Raise ("Cocoa application should be instantiated before window");
91     return;
92   }
93
94   // convert top-bottom coordinates to bottom-top (Cocoa)
95   myYTop    = getScreenBottom() - myYBottom;
96   myYBottom = myYTop + thePxHeight;
97
98   Cocoa_LocalPool aLocalPool;
99   NSUInteger aWinStyle = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
100   NSRect aRectNs = NSMakeRect (float(myXLeft), float(myYTop), float(thePxWidth), float(thePxHeight));
101   myHWindow = [[NSWindow alloc] initWithContentRect: aRectNs
102                                           styleMask: aWinStyle
103                                             backing: NSBackingStoreBuffered
104                                               defer: NO];
105   if (myHWindow == NULL)
106   {
107     Aspect_WindowDefinitionError::Raise ("Unable to create window");
108   }
109   myHView = [[myHWindow contentView] retain];
110
111   NSString* aTitleNs = [[NSString alloc] initWithUTF8String: theTitle];
112   [myHWindow setTitle: aTitleNs];
113   [aTitleNs release];
114
115   // do not destroy NSWindow on close - we didn't handle it!
116   [myHWindow setReleasedWhenClosed: NO];
117 #endif
118 }
119
120 // =======================================================================
121 // function : Cocoa_Window
122 // purpose  :
123 // =======================================================================
124 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
125 Cocoa_Window::Cocoa_Window (UIView* theViewNS)
126 : Aspect_Window(),
127 #else
128 Cocoa_Window::Cocoa_Window (NSView* theViewNS)
129 : Aspect_Window(),
130   myHWindow (NULL),
131 #endif
132   myHView   (NULL),
133   myXLeft   (0),
134   myYTop    (0),
135   myXRight  (512),
136   myYBottom (512)
137 {
138 #if defined(HAVE_OBJC_ARC)
139   myHView = theViewNS;
140 #else
141   myHView = [theViewNS retain];
142 #endif
143   DoResize();
144 }
145
146 // =======================================================================
147 // function : Destroy
148 // purpose  :
149 // =======================================================================
150 void Cocoa_Window::Destroy()
151 {
152 #if !defined(HAVE_OBJC_ARC)
153   Cocoa_LocalPool aLocalPool;
154 #endif
155 #if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
156   if (myHWindow != NULL)
157   {
158   #if !defined(HAVE_OBJC_ARC)
159     //[myHWindow close];
160     [myHWindow release];
161   #endif
162     myHWindow = NULL;
163   }
164 #endif
165   if (myHView != NULL)
166   {
167   #if !defined(HAVE_OBJC_ARC)
168     [myHView release];
169   #endif
170     myHView = NULL;
171   }
172 }
173
174 // =======================================================================
175 // function : SetHView
176 // purpose  :
177 // =======================================================================
178 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
179 void Cocoa_Window::SetHView (UIView* theView)
180 {
181 #else
182 void Cocoa_Window::SetHView (NSView* theView)
183 {
184   if (myHWindow != NULL)
185   {
186     [myHWindow setContentView: theView];
187   }
188 #endif
189
190 #if defined(HAVE_OBJC_ARC)
191   myHView = theView;
192 #else
193   if (myHView != NULL)
194   {
195     [myHView release];
196     myHView = NULL;
197   }
198   myHView = [theView retain];
199 #endif
200 }
201
202 // =======================================================================
203 // function : IsMapped
204 // purpose  :
205 // =======================================================================
206 Standard_Boolean Cocoa_Window::IsMapped() const
207 {
208   if (IsVirtual())
209   {
210     return Standard_True;
211   }
212
213 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
214   return myHView != NULL;
215 #else
216   return myHView != NULL
217    &&  [[myHView window] isVisible];
218 #endif
219 }
220
221 // =======================================================================
222 // function : Map
223 // purpose  :
224 // =======================================================================
225 void Cocoa_Window::Map() const
226 {
227   if (IsVirtual())
228   {
229     return;
230   }
231
232   if (myHView != NULL)
233   {
234   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
235     //
236   #else
237     [[myHView window] orderFront: NULL];
238   #endif
239   }
240 }
241
242 // =======================================================================
243 // function : Unmap
244 // purpose  :
245 // =======================================================================
246 void Cocoa_Window::Unmap() const
247 {
248   if (myHView != NULL)
249   {
250   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
251     //
252   #else
253     [[myHView window] orderOut: NULL];
254   #endif
255   }
256 }
257
258 // =======================================================================
259 // function : DoResize
260 // purpose  :
261 // =======================================================================
262 Aspect_TypeOfResize Cocoa_Window::DoResize() const
263 {
264   if (myHView == NULL)
265   {
266     return Aspect_TOR_UNKNOWN;
267   }
268
269 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
270   CGRect aBounds = [myHView bounds];
271 #else
272   NSRect aBounds = [myHView bounds];
273 #endif
274   Standard_Integer aMask = 0;
275   Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN;
276
277   if (Abs ((Standard_Integer )aBounds.origin.x                         - myXLeft  ) > 2) aMask |= 1;
278   if (Abs ((Standard_Integer )(aBounds.origin.x + aBounds.size.width)  - myXRight ) > 2) aMask |= 2;
279   if (Abs ((Standard_Integer )aBounds.origin.y                         - myYTop   ) > 2) aMask |= 4;
280   if (Abs ((Standard_Integer )(aBounds.origin.y + aBounds.size.height) - myYBottom) > 2) aMask |= 8;
281   switch (aMask)
282   {
283     case 0:  aMode = Aspect_TOR_NO_BORDER;               break;
284     case 1:  aMode = Aspect_TOR_LEFT_BORDER;             break;
285     case 2:  aMode = Aspect_TOR_RIGHT_BORDER;            break;
286     case 4:  aMode = Aspect_TOR_TOP_BORDER;              break;
287     case 5:  aMode = Aspect_TOR_LEFT_AND_TOP_BORDER;     break;
288     case 6:  aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER;    break;
289     case 8:  aMode = Aspect_TOR_BOTTOM_BORDER;           break;
290     case 9:  aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER;  break;
291     case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break;
292     default: break;
293   }
294
295   *((Standard_Integer* )&myXLeft   ) = (Standard_Integer )aBounds.origin.x;
296   *((Standard_Integer* )&myXRight  ) = (Standard_Integer )(aBounds.origin.x + aBounds.size.width);
297   *((Standard_Integer* )&myYTop    ) = (Standard_Integer )aBounds.origin.y;
298   *((Standard_Integer* )&myYBottom ) = (Standard_Integer )(aBounds.origin.y + aBounds.size.height);
299   return aMode;
300 }
301
302 // =======================================================================
303 // function : DoMapping
304 // purpose  :
305 // =======================================================================
306 Standard_Boolean Cocoa_Window::DoMapping() const
307 {
308   return Standard_True;
309 }
310
311 // =======================================================================
312 // function : Ratio
313 // purpose  :
314 // =======================================================================
315 Quantity_Ratio Cocoa_Window::Ratio() const
316 {
317   if (myHView == NULL)
318   {
319     return 1.0;
320   }
321
322 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
323   CGRect aBounds = [myHView bounds];
324 #else
325   NSRect aBounds = [myHView bounds];
326 #endif
327   return Quantity_Ratio (aBounds.size.width / aBounds.size.height);
328 }
329
330 // =======================================================================
331 // function : Position
332 // purpose  :
333 // =======================================================================
334 void Cocoa_Window::Position (Standard_Integer& X1, Standard_Integer& Y1,
335                              Standard_Integer& X2, Standard_Integer& Y2) const
336 {
337 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
338   CGRect aBounds = [myHView bounds];
339   X1 = 0;
340   Y1 = 0;
341   X2 = (Standard_Integer )aBounds.size.width;
342   Y2 = (Standard_Integer )aBounds.size.height;
343 #else
344   NSWindow* aWindow = [myHView window];
345   NSRect aWindowRect = [aWindow frame];
346   X1 = (Standard_Integer) aWindowRect.origin.x;
347   Y1 = getScreenBottom() - (Standard_Integer) aWindowRect.origin.y - (Standard_Integer) aWindowRect.size.height;
348   X2 = X1 + (Standard_Integer) aWindowRect.size.width;
349   Y2 = Y1 + (Standard_Integer) aWindowRect.size.height;
350 #endif
351 }
352
353 // =======================================================================
354 // function : Size
355 // purpose  :
356 // =======================================================================
357 void Cocoa_Window::Size (Standard_Integer& theWidth,
358                          Standard_Integer& theHeight) const
359 {
360   if (myHView == NULL)
361   {
362     return;
363   }
364
365 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
366   CGRect aBounds = [myHView bounds];
367 #else
368   NSRect aBounds = [myHView bounds];
369 #endif
370   theWidth  = (Standard_Integer )aBounds.size.width;
371   theHeight = (Standard_Integer )aBounds.size.height;
372 }