0030694: Data Exchange - support non-standard GB2312-encoded STEP files
[occt.git] / src / Cocoa / Cocoa_Window.mm
CommitLineData
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 32IMPLEMENT_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 45static 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
8693dfd0 69//! Extension for Cocoa_Window::InvalidateContent().
70#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
71 @interface UIView (UIViewOcctAdditions)
72 - (void )invalidateContentOcct: (id )theSender;
73 @end
74 @implementation UIView (UIViewOcctAdditions)
75 - (void )invalidateContentOcct: (id )theSender
76 {
77 (void )theSender;
78 [self setNeedsDisplay];
79 }
80 @end
81#else
82 @interface NSView (NSViewOcctAdditions)
83 - (void )invalidateContentOcct: (id )theSender;
84 @end
85 @implementation NSView (NSViewOcctAdditions)
86 - (void )invalidateContentOcct: (id )theSender
87 {
88 (void )theSender;
89 [self setNeedsDisplay: YES];
90 }
91 @end
92#endif
93
4fe56619 94// =======================================================================
95// function : Cocoa_Window
96// purpose :
97// =======================================================================
98Cocoa_Window::Cocoa_Window (const Standard_CString theTitle,
99 const Standard_Integer thePxLeft,
100 const Standard_Integer thePxTop,
101 const Standard_Integer thePxWidth,
102 const Standard_Integer thePxHeight)
dc3fe572 103: Aspect_Window (),
a2e4f780 104#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
4fe56619 105 myHWindow (NULL),
a2e4f780 106#endif
4fe56619 107 myHView (NULL),
108 myXLeft (thePxLeft),
109 myYTop (thePxTop),
110 myXRight (thePxLeft + thePxWidth),
111 myYBottom (thePxTop + thePxHeight)
112{
a2e4f780 113#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
114 //
115#else
4fe56619 116 if (thePxWidth <= 0 || thePxHeight <= 0)
117 {
9775fa61 118 throw Aspect_WindowDefinitionError("Coordinate(s) out of range");
4fe56619 119 }
120 else if (NSApp == NULL)
121 {
9775fa61 122 throw Aspect_WindowDefinitionError("Cocoa application should be instantiated before window");
4fe56619 123 return;
124 }
125
126 // convert top-bottom coordinates to bottom-top (Cocoa)
127 myYTop = getScreenBottom() - myYBottom;
128 myYBottom = myYTop + thePxHeight;
129
130 Cocoa_LocalPool aLocalPool;
e2b4dea2 131 NSUInteger aWinStyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
4fe56619 132 NSRect aRectNs = NSMakeRect (float(myXLeft), float(myYTop), float(thePxWidth), float(thePxHeight));
133 myHWindow = [[NSWindow alloc] initWithContentRect: aRectNs
134 styleMask: aWinStyle
135 backing: NSBackingStoreBuffered
136 defer: NO];
137 if (myHWindow == NULL)
138 {
9775fa61 139 throw Aspect_WindowDefinitionError("Unable to create window");
4fe56619 140 }
141 myHView = [[myHWindow contentView] retain];
142
143 NSString* aTitleNs = [[NSString alloc] initWithUTF8String: theTitle];
144 [myHWindow setTitle: aTitleNs];
145 [aTitleNs release];
146
147 // do not destroy NSWindow on close - we didn't handle it!
148 [myHWindow setReleasedWhenClosed: NO];
a2e4f780 149#endif
4fe56619 150}
151
152// =======================================================================
153// function : Cocoa_Window
154// purpose :
155// =======================================================================
a2e4f780 156#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
157Cocoa_Window::Cocoa_Window (UIView* theViewNS)
158: Aspect_Window(),
159#else
4fe56619 160Cocoa_Window::Cocoa_Window (NSView* theViewNS)
a2e4f780 161: Aspect_Window(),
4fe56619 162 myHWindow (NULL),
a2e4f780 163#endif
164 myHView (NULL),
4fe56619 165 myXLeft (0),
166 myYTop (0),
167 myXRight (512),
168 myYBottom (512)
169{
a2e4f780 170#if defined(HAVE_OBJC_ARC)
171 myHView = theViewNS;
172#else
173 myHView = [theViewNS retain];
174#endif
4fe56619 175 DoResize();
176}
177
178// =======================================================================
e6f550da 179// function : ~Cocoa_Window
4fe56619 180// purpose :
181// =======================================================================
e6f550da 182Cocoa_Window::~Cocoa_Window()
4fe56619 183{
a2e4f780 184#if !defined(HAVE_OBJC_ARC)
4fe56619 185 Cocoa_LocalPool aLocalPool;
a2e4f780 186#endif
187#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
4fe56619 188 if (myHWindow != NULL)
189 {
a2e4f780 190 #if !defined(HAVE_OBJC_ARC)
4fe56619 191 //[myHWindow close];
192 [myHWindow release];
a2e4f780 193 #endif
4fe56619 194 myHWindow = NULL;
195 }
a2e4f780 196#endif
4fe56619 197 if (myHView != NULL)
198 {
a2e4f780 199 #if !defined(HAVE_OBJC_ARC)
4fe56619 200 [myHView release];
a2e4f780 201 #endif
4fe56619 202 myHView = NULL;
203 }
204}
205
206// =======================================================================
4fe56619 207// function : SetHView
208// purpose :
209// =======================================================================
a2e4f780 210#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
211void Cocoa_Window::SetHView (UIView* theView)
212{
213#else
4fe56619 214void Cocoa_Window::SetHView (NSView* theView)
215{
216 if (myHWindow != NULL)
217 {
218 [myHWindow setContentView: theView];
219 }
a2e4f780 220#endif
221
222#if defined(HAVE_OBJC_ARC)
223 myHView = theView;
224#else
4fe56619 225 if (myHView != NULL)
226 {
227 [myHView release];
228 myHView = NULL;
229 }
230 myHView = [theView retain];
a2e4f780 231#endif
4fe56619 232}
233
234// =======================================================================
4fe56619 235// function : IsMapped
236// purpose :
237// =======================================================================
238Standard_Boolean Cocoa_Window::IsMapped() const
239{
240 if (IsVirtual())
241 {
242 return Standard_True;
243 }
244
a2e4f780 245#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
246 return myHView != NULL;
247#else
248 return myHView != NULL
249 && [[myHView window] isVisible];
250#endif
4fe56619 251}
252
253// =======================================================================
254// function : Map
255// purpose :
256// =======================================================================
257void Cocoa_Window::Map() const
258{
259 if (IsVirtual())
260 {
261 return;
262 }
263
264 if (myHView != NULL)
265 {
a2e4f780 266 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
267 //
268 #else
4fe56619 269 [[myHView window] orderFront: NULL];
a2e4f780 270 #endif
4fe56619 271 }
272}
273
274// =======================================================================
275// function : Unmap
276// purpose :
277// =======================================================================
278void Cocoa_Window::Unmap() const
279{
280 if (myHView != NULL)
281 {
a2e4f780 282 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
283 //
284 #else
4fe56619 285 [[myHView window] orderOut: NULL];
a2e4f780 286 #endif
4fe56619 287 }
288}
289
290// =======================================================================
291// function : DoResize
292// purpose :
293// =======================================================================
294Aspect_TypeOfResize Cocoa_Window::DoResize() const
295{
296 if (myHView == NULL)
297 {
298 return Aspect_TOR_UNKNOWN;
299 }
300
a2e4f780 301#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
302 CGRect aBounds = [myHView bounds];
303#else
4fe56619 304 NSRect aBounds = [myHView bounds];
a2e4f780 305#endif
4fe56619 306 Standard_Integer aMask = 0;
307 Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN;
308
309 if (Abs ((Standard_Integer )aBounds.origin.x - myXLeft ) > 2) aMask |= 1;
310 if (Abs ((Standard_Integer )(aBounds.origin.x + aBounds.size.width) - myXRight ) > 2) aMask |= 2;
311 if (Abs ((Standard_Integer )aBounds.origin.y - myYTop ) > 2) aMask |= 4;
312 if (Abs ((Standard_Integer )(aBounds.origin.y + aBounds.size.height) - myYBottom) > 2) aMask |= 8;
313 switch (aMask)
314 {
315 case 0: aMode = Aspect_TOR_NO_BORDER; break;
316 case 1: aMode = Aspect_TOR_LEFT_BORDER; break;
317 case 2: aMode = Aspect_TOR_RIGHT_BORDER; break;
318 case 4: aMode = Aspect_TOR_TOP_BORDER; break;
319 case 5: aMode = Aspect_TOR_LEFT_AND_TOP_BORDER; break;
320 case 6: aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER; break;
321 case 8: aMode = Aspect_TOR_BOTTOM_BORDER; break;
322 case 9: aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER; break;
323 case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break;
324 default: break;
325 }
326
327 *((Standard_Integer* )&myXLeft ) = (Standard_Integer )aBounds.origin.x;
328 *((Standard_Integer* )&myXRight ) = (Standard_Integer )(aBounds.origin.x + aBounds.size.width);
329 *((Standard_Integer* )&myYTop ) = (Standard_Integer )aBounds.origin.y;
330 *((Standard_Integer* )&myYBottom ) = (Standard_Integer )(aBounds.origin.y + aBounds.size.height);
331 return aMode;
332}
333
334// =======================================================================
335// function : DoMapping
336// purpose :
337// =======================================================================
338Standard_Boolean Cocoa_Window::DoMapping() const
339{
340 return Standard_True;
341}
342
343// =======================================================================
4fe56619 344// function : Ratio
345// purpose :
346// =======================================================================
ee2be2a8 347Standard_Real Cocoa_Window::Ratio() const
4fe56619 348{
349 if (myHView == NULL)
350 {
351 return 1.0;
352 }
353
a2e4f780 354#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
355 CGRect aBounds = [myHView bounds];
356#else
4fe56619 357 NSRect aBounds = [myHView bounds];
a2e4f780 358#endif
ee2be2a8 359 return Standard_Real (aBounds.size.width / aBounds.size.height);
4fe56619 360}
361
362// =======================================================================
363// function : Position
364// purpose :
365// =======================================================================
4fe56619 366void Cocoa_Window::Position (Standard_Integer& X1, Standard_Integer& Y1,
367 Standard_Integer& X2, Standard_Integer& Y2) const
368{
a2e4f780 369#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
370 CGRect aBounds = [myHView bounds];
371 X1 = 0;
372 Y1 = 0;
373 X2 = (Standard_Integer )aBounds.size.width;
374 Y2 = (Standard_Integer )aBounds.size.height;
375#else
18d715bd 376 NSWindow* aWindow = [myHView window];
377 NSRect aWindowRect = [aWindow frame];
378 X1 = (Standard_Integer) aWindowRect.origin.x;
379 Y1 = getScreenBottom() - (Standard_Integer) aWindowRect.origin.y - (Standard_Integer) aWindowRect.size.height;
380 X2 = X1 + (Standard_Integer) aWindowRect.size.width;
381 Y2 = Y1 + (Standard_Integer) aWindowRect.size.height;
a2e4f780 382#endif
4fe56619 383}
384
385// =======================================================================
386// function : Size
387// purpose :
388// =======================================================================
4fe56619 389void Cocoa_Window::Size (Standard_Integer& theWidth,
390 Standard_Integer& theHeight) const
391{
392 if (myHView == NULL)
393 {
394 return;
395 }
396
a2e4f780 397#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
398 CGRect aBounds = [myHView bounds];
399#else
4fe56619 400 NSRect aBounds = [myHView bounds];
a2e4f780 401#endif
4fe56619 402 theWidth = (Standard_Integer )aBounds.size.width;
403 theHeight = (Standard_Integer )aBounds.size.height;
404}
8693dfd0 405
406// =======================================================================
407// function : InvalidateContent
408// purpose :
409// =======================================================================
410void Cocoa_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& )
411{
412 if (myHView == NULL)
413 {
414 return;
415 }
416
417 if ([NSThread isMainThread])
418 {
419 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
420 [myHView setNeedsDisplay];
421 #else
422 [myHView setNeedsDisplay: YES];
423 #endif
424 }
425 else
426 {
427 [myHView performSelectorOnMainThread: @selector(invalidateContentOcct:)
428 withObject: NULL
429 waitUntilDone: NO];
430 }
431}