6aca4d39 |
1 | // Created on: 2012-11-12 |
4fe56619 |
2 | // Created by: Kirill GAVRILOV |
6aca4d39 |
3 | // Copyright (c) 2012-2014 OPEN CASCADE SAS |
4fe56619 |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
4fe56619 |
6 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
4fe56619 |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
4fe56619 |
15 | |
a2e4f780 |
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 |
4fe56619 |
23 | |
24 | #include <Cocoa_Window.hxx> |
25 | |
26 | #include <Cocoa_LocalPool.hxx> |
27 | |
28 | #include <Image_AlienPixMap.hxx> |
29 | #include <Aspect_Convert.hxx> |
4fe56619 |
30 | #include <Aspect_WindowDefinitionError.hxx> |
31 | |
f5f4ebd0 |
32 | IMPLEMENT_STANDARD_RTTIEXT(Cocoa_Window,Aspect_Window) |
33 | |
a2e4f780 |
34 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE |
35 | // |
36 | #else |
e2b4dea2 |
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 | |
4fe56619 |
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 | } |
a2e4f780 |
67 | #endif |
4fe56619 |
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) |
dc3fe572 |
78 | : Aspect_Window (), |
a2e4f780 |
79 | #if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) |
4fe56619 |
80 | myHWindow (NULL), |
a2e4f780 |
81 | #endif |
4fe56619 |
82 | myHView (NULL), |
83 | myXLeft (thePxLeft), |
84 | myYTop (thePxTop), |
85 | myXRight (thePxLeft + thePxWidth), |
86 | myYBottom (thePxTop + thePxHeight) |
87 | { |
a2e4f780 |
88 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE |
89 | // |
90 | #else |
4fe56619 |
91 | if (thePxWidth <= 0 || thePxHeight <= 0) |
92 | { |
9775fa61 |
93 | throw Aspect_WindowDefinitionError("Coordinate(s) out of range"); |
4fe56619 |
94 | } |
95 | else if (NSApp == NULL) |
96 | { |
9775fa61 |
97 | throw Aspect_WindowDefinitionError("Cocoa application should be instantiated before window"); |
4fe56619 |
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; |
e2b4dea2 |
106 | NSUInteger aWinStyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable; |
4fe56619 |
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 | { |
9775fa61 |
114 | throw Aspect_WindowDefinitionError("Unable to create window"); |
4fe56619 |
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]; |
a2e4f780 |
124 | #endif |
4fe56619 |
125 | } |
126 | |
127 | // ======================================================================= |
128 | // function : Cocoa_Window |
129 | // purpose : |
130 | // ======================================================================= |
a2e4f780 |
131 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE |
132 | Cocoa_Window::Cocoa_Window (UIView* theViewNS) |
133 | : Aspect_Window(), |
134 | #else |
4fe56619 |
135 | Cocoa_Window::Cocoa_Window (NSView* theViewNS) |
a2e4f780 |
136 | : Aspect_Window(), |
4fe56619 |
137 | myHWindow (NULL), |
a2e4f780 |
138 | #endif |
139 | myHView (NULL), |
4fe56619 |
140 | myXLeft (0), |
141 | myYTop (0), |
142 | myXRight (512), |
143 | myYBottom (512) |
144 | { |
a2e4f780 |
145 | #if defined(HAVE_OBJC_ARC) |
146 | myHView = theViewNS; |
147 | #else |
148 | myHView = [theViewNS retain]; |
149 | #endif |
4fe56619 |
150 | DoResize(); |
151 | } |
152 | |
153 | // ======================================================================= |
e6f550da |
154 | // function : ~Cocoa_Window |
4fe56619 |
155 | // purpose : |
156 | // ======================================================================= |
e6f550da |
157 | Cocoa_Window::~Cocoa_Window() |
4fe56619 |
158 | { |
a2e4f780 |
159 | #if !defined(HAVE_OBJC_ARC) |
4fe56619 |
160 | Cocoa_LocalPool aLocalPool; |
a2e4f780 |
161 | #endif |
162 | #if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) |
4fe56619 |
163 | if (myHWindow != NULL) |
164 | { |
a2e4f780 |
165 | #if !defined(HAVE_OBJC_ARC) |
4fe56619 |
166 | //[myHWindow close]; |
167 | [myHWindow release]; |
a2e4f780 |
168 | #endif |
4fe56619 |
169 | myHWindow = NULL; |
170 | } |
a2e4f780 |
171 | #endif |
4fe56619 |
172 | if (myHView != NULL) |
173 | { |
a2e4f780 |
174 | #if !defined(HAVE_OBJC_ARC) |
4fe56619 |
175 | [myHView release]; |
a2e4f780 |
176 | #endif |
4fe56619 |
177 | myHView = NULL; |
178 | } |
179 | } |
180 | |
4fe56619 |
181 | // ======================================================================= |
182 | // function : SetHView |
183 | // purpose : |
184 | // ======================================================================= |
a2e4f780 |
185 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE |
186 | void Cocoa_Window::SetHView (UIView* theView) |
187 | { |
188 | #else |
4fe56619 |
189 | void Cocoa_Window::SetHView (NSView* theView) |
190 | { |
191 | if (myHWindow != NULL) |
192 | { |
193 | [myHWindow setContentView: theView]; |
194 | } |
a2e4f780 |
195 | #endif |
196 | |
197 | #if defined(HAVE_OBJC_ARC) |
198 | myHView = theView; |
199 | #else |
4fe56619 |
200 | if (myHView != NULL) |
201 | { |
202 | [myHView release]; |
203 | myHView = NULL; |
204 | } |
205 | myHView = [theView retain]; |
a2e4f780 |
206 | #endif |
4fe56619 |
207 | } |
208 | |
4fe56619 |
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 | |
a2e4f780 |
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 |
4fe56619 |
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 | { |
a2e4f780 |
241 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE |
242 | // |
243 | #else |
4fe56619 |
244 | [[myHView window] orderFront: NULL]; |
a2e4f780 |
245 | #endif |
4fe56619 |
246 | } |
247 | } |
248 | |
249 | // ======================================================================= |
250 | // function : Unmap |
251 | // purpose : |
252 | // ======================================================================= |
253 | void Cocoa_Window::Unmap() const |
254 | { |
255 | if (myHView != NULL) |
256 | { |
a2e4f780 |
257 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE |
258 | // |
259 | #else |
4fe56619 |
260 | [[myHView window] orderOut: NULL]; |
a2e4f780 |
261 | #endif |
4fe56619 |
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 | |
a2e4f780 |
276 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE |
277 | CGRect aBounds = [myHView bounds]; |
278 | #else |
4fe56619 |
279 | NSRect aBounds = [myHView bounds]; |
a2e4f780 |
280 | #endif |
4fe56619 |
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 | |
4fe56619 |
318 | // ======================================================================= |
319 | // function : Ratio |
320 | // purpose : |
321 | // ======================================================================= |
ee2be2a8 |
322 | Standard_Real Cocoa_Window::Ratio() const |
4fe56619 |
323 | { |
324 | if (myHView == NULL) |
325 | { |
326 | return 1.0; |
327 | } |
328 | |
a2e4f780 |
329 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE |
330 | CGRect aBounds = [myHView bounds]; |
331 | #else |
4fe56619 |
332 | NSRect aBounds = [myHView bounds]; |
a2e4f780 |
333 | #endif |
ee2be2a8 |
334 | return Standard_Real (aBounds.size.width / aBounds.size.height); |
4fe56619 |
335 | } |
336 | |
4fe56619 |
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 | { |
a2e4f780 |
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 |
18d715bd |
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; |
a2e4f780 |
357 | #endif |
4fe56619 |
358 | } |
359 | |
4fe56619 |
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 | |
a2e4f780 |
372 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE |
373 | CGRect aBounds = [myHView bounds]; |
374 | #else |
4fe56619 |
375 | NSRect aBounds = [myHView bounds]; |
a2e4f780 |
376 | #endif |
4fe56619 |
377 | theWidth = (Standard_Integer )aBounds.size.width; |
378 | theHeight = (Standard_Integer )aBounds.size.height; |
379 | } |