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